pencil-0.4.4b/0000755000175000017500000000000011154200535013637 5ustar khashayarkhashayarpencil-0.4.4b/README0000644000175000017500000000261310641754634014537 0ustar khashayarkhashayarPencil 0.4.3b - Source Code - July 1st, 2007 Source code has been unified for Mac, Windows and Linux. Now available on sourceforge SVN repository. Lots of improvements, and lots of things to do still (see TODO) See notes for Mac and Windows. Pascal http://www.les-stooges.org/pascal/pencil/ --------- Pencil 0.4b - Source Code - January 4th, 2007 Added many things, notably vector graphics. PLEASE NOTE: There is still a bug which prevents the Windows release version to work well with optimization flags. So for the moment, one should compile in debug mode or change the optimization flags in the release makefile. Pascal http://www.les-stooges.org/pascal/pencil/ --------- Pencil 0.2b - Source Code PLEASE NOTE: This source code is optimized for compiling on Mac OSX. This means that the movie export functions refer to a local application called assembler2 (also included source). The Windows version replaces the movie export function to use a different application, quite easy really, so it's not included. The source code is very, hum, quick and dirty. I'm not a programmer at all and it's quite a miracle I was able to piece the software together. If you actually improve something, I'd like you to let me know. To compile on Linux, remove the Mac OSX headers (you'll find them), and re-implement the movie export with mencoder or ffmpeg. All the best, Patrick http://www.saltmountain.org/pencil/ pencil-0.4.4b/cpmac0000755000175000017500000000765210745152004014664 0ustar khashayarkhashayar#make clean #qmake -config release #make pencil="build/Release/Pencil.app" echo $pencil #qtlib="/usr/local/Trolltech/Qt-4.2.2/lib/" qtlib="/Library/Frameworks" #qtlib="" echo $qtlib cp Resources/assembler2 $pencil/Contents/Resources/ cp Resources/qt.conf $pencil/Contents/Resources mkdir $pencil/Contents/Frameworks mkdir $pencil/Contents/plugins mkdir $pencil/Contents/plugins/imageformats cp -R $qtlib/QtCore.framework $pencil/Contents/Frameworks/ cp -R $qtlib/QtGui.framework $pencil/Contents/Frameworks/ cp -R $qtlib/QtXml.framework $pencil/Contents/Frameworks/ cp -R $qtlib/QtOpenGL.framework $pencil/Contents/Frameworks/ cp -R /Developer/Applications/Qt/plugins/imageformats/libqjpeg.dylib $pencil/Contents/plugins/imageformats/ rm $pencil/Contents/Frameworks/QtCore.framework/QtCore_debug rm $pencil/Contents/Frameworks/QtCore.framework/QtCore_debug.prl rm $pencil/Contents/Frameworks/QtCore.framework/Versions/4/QtCore_debug rm $pencil/Contents/Frameworks/QtGui.framework/QtGui_debug rm $pencil/Contents/Frameworks/QtGui.framework/QtGui_debug.prl rm $pencil/Contents/Frameworks/QtGui.framework/Versions/4/QtGui_debug rm $pencil/Contents/Frameworks/QtXml.framework/QtXml_debug rm $pencil/Contents/Frameworks/QtXml.framework/QtXml_debug.prl rm $pencil/Contents/Frameworks/QtXml.framework/Versions/4/QtXml_debug rm $pencil/Contents/Frameworks/QtOpenGL.framework/QtOpenGL_debug rm $pencil/Contents/Frameworks/QtOpenGL.framework/QtOpenGL_debug.plr rm $pencil/Contents/Frameworks/QtOpenGL.framework/Versions/4/QtOpenGL_debug #install_name_tool -id @executable_path/../Frameworks/QtCore.framework/Versions/4/QtCore $pencil/Contents/Frameworks/QtCore.framework/Versions/4/QtCore #install_name_tool -id @executable_path/../Frameworks/QtGui.framework/Versions/4/QtGui $pencil/Contents/Frameworks/QtGui.framework/Versions/4/QtGui #install_name_tool -id @executable_path/../Frameworks/QtXml.framework/Versions/4/QtXml $pencil/Contents/Frameworks/QtXml.framework/Versions/4/QtXml #install_name_tool -id @executable_path/../Frameworks/QtOpenGL.framework/Versions/4/QtOpenGL $pencil/Contents/Frameworks/QtOpenGL.framework/Versions/4/QtOpenGL #install_name_tool -change $qtlib"QtCore.framework/Versions/4/QtCore" @executable_path/../Frameworks/QtCore.framework/Versions/4/QtCore $pencil/Contents/MacOs/pencil #install_name_tool -change $qtlib"QtGui.framework/Versions/4/QtGui" @executable_path/../Frameworks/QtGui.framework/Versions/4/QtGui $pencil/Contents/MacOS/pencil #install_name_tool -change $qtlib"QtXml.framework/Versions/4/QtXml" @executable_path/../Frameworks/QtXml.framework/Versions/4/QtXml $pencil/Contents/MacOS/pencil #install_name_tool -change $qtlib"QtOpenGL.framework/Versions/4/QtOpenGL" @executable_path/../Frameworks/QtOpenGL.framework/Versions/4/QtOpenGL $pencil/Contents/MacOS/pencil #install_name_tool -change $qtlib"QtCore.framework/Versions/4/QtCore" @executable_path/../Frameworks/QtCore.framework/Versions/4/QtCore $pencil/Contents/Frameworks/QtGui.framework/Versions/4/QtGui #install_name_tool -change $qtlib"QtCore.framework/Versions/4/QtCore" @executable_path/../Frameworks/QtCore.framework/Versions/4/QtCore $pencil/Contents/Frameworks/QtXml.framework/Versions/4/QtXml #install_name_tool -change $qtlib"QtCore.framework/Versions/4/QtCore" @executable_path/../Frameworks/QtCore.framework/Versions/4/QtCore $pencil/Contents/Frameworks/QtOpenGL.framework/Versions/4/QtOpenGL #install_name_tool -change $qtlib"QtGui.framework/Versions/4/QtGui" @executable_path/../Frameworks/QtGui.framework/Versions/4/QtGui $pencil/Contents/Frameworks/QtOpenGL.framework/Versions/4/QtOpenGL #install_name_tool -change $qtlib"QtCore.framework/Versions/4/QtCore" @executable_path/../Frameworks/QtCore.framework/Versions/4/QtCore $pencil/Contents/plugins/imageformats/libqjpeg.dylib #install_name_tool -change $qtlib"QtGui.framework/Versions/4/QtGui" @executable_path/../Frameworks/QtGui.framework/Versions/4/QtGui $pencil/Contents/plugins/imageformats/libqjpeg.dylib echo ok pencil-0.4.4b/Resources/0000755000175000017500000000000010757714700015625 5ustar khashayarkhashayarpencil-0.4.4b/pencil.ico0000644000175000017500000020407610652240437015625 0ustar khashayarkhashayar ((               !! ! !   !"#$%%&&&&&'$$#"!!   #$&''())*+*,-,+)(&&&$#!  !$%()+,-.//01101201/.-,+*('%""  "%((+,/012357676777663110/.-*'&$#   !$')+-013579;======><;:9865410-,+('%#!   !$')+/03689;>@BBCDECBCA@?>=<:85422.,*(%$"    #&)+/248:<=@BDFHHHIHIIHGECBB@>=;9733/-,)&$"   "%(*/147;>@BEGHJMNOONOONMKIHGFDCA?=;9532/,*'%#   $&)-056:>ACFILNPRRTTTUTTTRPONLJIGFEB?<:853/-*'$"   $(*.159=@CGKLNQSUWWXYZYZXXUUTRRPNLLIFC@>;853.+)&#  &*(!"&).26:>ADIMPSTWYZ\\]^`_^]\\[YYWTSRQNKGDB><:51/,($!  q]F;0+05;@CGKOQUWZ[^`aabccbba``^_]ZYXWSPMKHDA>;730,(%#  iaPD9;AHMQTWZ\^bbcefgffeffeddba`^]ZWSQNJGDA=952/*'%"  ~hYMGMSX[]_cdfghiijjhiihigfeda`]YVTPMIGC?=74/,)'# +n^SV[`cegijklmmmmllmkjjigeb_[YVSOMIDB=941.+'# '~k]^chjlmmoooopppooomkjgda_[XURNJGC>:630,'$! kbhloppqrstrrsrrpomjheb_\YVRNKEA>963.*'#   Lvfknrtuvvuvuuuspmlkhda_\XSPJGD?<92/+'$  , lptwvwyxwwutronljfca\XVPLIEA=84/,)$   1//dzmM_k'05sruyyyxwvutqomjhea]ZVQNJGC=961-(%! X C@@YVV.--򉧽w^s6CK yvwyyxxwurpnkieb_[VROLGB>:41,($! 4+**gee644ߊ~e{>LVxxyxwusrpnjge_[XTQMHC?;71.)&" :77ROO-**GVaኧrJ[f#)zyvutrolkhd`]YURMHEA<830,'#  `/..Ƽ866EAAy{Rer'/5 }ztromjhd`^YVRNKFB=83/+($" ;~~`]]433:99 䁠^s4?G rqmkhfb`\WSPMGB?:50,)%! b__WUUOLL*))$""Sgt醤bx6DM% qonljfd`\XUQLGC>:61.*'" h=::][[\ZZ 񆣷Z-]"/opomjgd`\YUQMGC?:630+%# B%%%º}zzPMM Xnx䍭nC3s)8nrolkhda^ZVRMHC@;63/+'$  ! qkkjgg977---$)捯Bvc3~-Hopomkgdb^ZVRMID@<84.*($  v"!!_[[jffXUUPNN.--OLL.,, |Mz*l(0Nmqonkieb^ZVQNIE@<83/+(#  BEAAuppPLLjhhGDE  wp4w>%,Onrpnljgd`\WTOKFB>940-(% ,++kffqmmLKK q{*l1|M6. Inqpnljgc`[XTOLGC>:53.)$! 977yyĽ}}DAA ꀢ}-m"qR9; Nprqnljfc_]XUQMHD?;63.(%" t755yydaa$-1ډElMI;/ Uqqpoljfca\YVRNHD?;73-)&! 4%##NLLSQQ521  #oFj@ID9&"*`rqqomihd`]ZVRMIEB<82-+&# %(]w}ӕVf;CO@<+/fuqpnmkieb^[XSOKFB=740+(#  v^yކa&s-|EEDD7z*$Sy xqoonlifca\VROLGC<850,)%  1yj1x!r=w,F>I1r/!S yrrpmmifda[WTOKFB=94/,($! FX^s;z,6u&|0KIC#}4%_|rpponkhe`]ZVQLFB>:62-)&! xiCz(y=FR;"}&0&d }qrqpmkhda^ZVPKGC>;72-)%! .b=r&wD@.)B;D*.-'&j %qsrpnkheb^YTQMHB>;62,(%  I]cO|I!r69?2HCE3}3$,)p +ptqpnkieb]ZURLHD?;61,($  FuXl3D>+-OEA897"}'*w *psrpnlieb^ZVQMID@<62.(%! 3舯wCyRs%T92%8U'09G/x-2w(osqpnkifb^[VQNJEB=61,)%  CY^QC=;'zFE5.AF)!~1?-"{168Qmtrpnligca]XTOKGB<62-)&" zI;<_A7J=*,7[7 ~-7)|'(+9Sntrpnligda]XTOKFA;72.*&" '[g_5~BeM;9-<@O>(*m{+2-Ciossqonkhda]XUOJE@;72.($! ~IYlk]1{FLM537DEW5~ #"|~*,#Elqttrpnlhda]YSNID@<52,'$  +W @agik\-u.dK9+:DGHG$~&"r,z-0Ktttsqnlheb^XSNIEA:61+(% Pdkv&AELQ[diU-s1jC15;JAA<!*)|2{' $5Owvtrqokheb\WRMIE>:60+(" }#$+9KT\fikjiR4~0r2~:44D9@-++,#%-2Lxvtsqnkie`[WRMIC>94.+&! .21TSLLUZeijiR:.tA7*5@=6,-!'/z'. (zvtsqolhc_[VSMGB>82.)% _v|I3SMTW^ZNMW^eifR;RA,;161%/'$"w,}.,H{tttqokhd_[WRLGB<72.)# 1;=\M]ghjieif`SRY]]IKY4,3,;011$&%|#El $//.{svspnkgc^ZUPLGA;71,&" 3''m#3D]`beghhjlmjbVVU@E=8-(38%!'9-*.*kXXW<<<{surqmjfc_ZTPJE@;61,'"  bz~u"5GZ]Z]]]_^cfgcgigbQ5+93/+%! 6 !p(';WkklljhhffbZVX^agg`TQM[gkkiA2zHR B>0<4(.,qIHMPXXXRRRmmmrrr\\\ppnkgca[WRMHA<62.)$ H[`h.EX_bhlllllkkheaaZUZ`bfcUS[bliI;OA&C332)-4zHHLP]\\OOOddddddxxxFFF}mnmifc^ZUPKD?:6/,'" q"1;+ )ktgaWVY]_ckkkkkkjieb`YW_bfcQP\bE>P38>,;+4/%xC7;50+&!   M`bggjkkkkkkkkgW[ad\\b`XRUahklY8D+?;/;"wH &!! !!!AAA___333BBBQQQZZZLLL  tlifc_ZVRMHB=82.(#  { fRIM^cggiklkkkje_YS\]V[`UX\]hgH.y9FRE4q D~"&"""777QQQ<<82-'$ hlmmndYTY_`b\RbeiklmkdZMQSXNJ@"x1N]ZO3F'()!!!555111NNN======fffeeeKKK(N0{,F jed`\XSOID?850*%" wafilnnml`TX][VYafjlmmleXSNKJ<({4TW 9d"/<'((---HHH)))AAA(((...YYYiiiLLL110 G,qS3*Beba]YUQKGA;71+'$  rXZ_adgjmlf`YRVWUV^dimlmmbSJIM2LE *I$*0''(<<>>ZZZLLLCCC =%aQ2P1&=a_^YVRLIC=82-)%! u^\_NLRX\`ajmjfbZYWTUdffjmmilcN6J..-...)))TTT;;;'''@@@%%%555555JJJCCCLLL *BO0}Q2Q22Na][VRNJE?:50+'# w}qjaYMW[[QVVZ_inkgb_dadhcbhloP#1/.666:::BBBWWWFFF>>>***@@@:::HHH======/N0{Q2Q2O1~/JZZVSOKF@<61,)$   x jqmkehd[^cccYSUY_inlijjhcX\o2b}PPPEEERRR___TTTCCCccc999333MMM???IIIAAA+++"#!!L/yQ2Q2R2N1|+DTVSOKFA=73-*%!  y ~_bhlkea[]ihedbYUSRahmmkfgb(3643xxxccctttwwwuuuuuu\\\666EEE^^^AAALLLFFF'''/..K/wQ2Q2Q2R2J.u/`VSOJFB>84/+&"  xZGQV[^__``gllhfe^XMNXfmq6innn~}}焁yyyxxxQQQ<<<^^^kkkEEEUUUHHH(((DED K.vQ2Q2Q2Q2R3<%_ QSOKFB>84/+'#  ujgc_[WQHPWYaillkigd[NTR+7|vuzzzxxxYYYaaaxxxmmmPPPbbbGGG,,,KKK J.vQ2Q2Q2Q2R3I-t/QPNKGB=94/,'#  q||'`]adghe`\PKMOJZ_bcge^!OnAAC턅}|||}}qqqkkkoooFFF222LLL J.vQ2Q2Q2Q2Q2R3/L`LMJFA=930+'# i tt(i]YQKZ[^chiib^YUMDOC &|{{~~~~~~mmmHHHLLLRRQ K.vQ2Q2Q2Q2Q2T4;%^oILIEA=930+&" c&thjhe\WVTW\Y`dgil_F^ojh{{{qqqooogggK.wQ2Q2Q2Q2Q2S3B(h ~FJGC?<82/+&" [ (e__`ffdcec[VOPYW'Wr!}}}~~~mml$L/xQ2Q2Q2Q2Q2S3I-s DGE@=:51-)%"  +jY[[Z]Z_]_bddb5e~yyyWWV -L/yQ2Q2Q2Q2Q2R3N0|#JCA=;840-($! y7XZ]dbc_\[__V2b"}}}554$8N0|Q2Q2Q2Q2Q2Q2S4+O?>;853-*&#  r~~<^VYQVV`dnd0^v|{{󀀀1MP1~Q2Q2Q2Q2Q2Q2U5 3S:;8530+'$! o}}7ZU][^_d_+Ul䍌hhhA(gR2Q2Q2Q2Q2Q2Q2U4&<V57530-)%" AMM ^^bfjH&2;64½⏏01/#K.wQ2Q2Q2Q2Q2Q2Q2T4*CV030/,)&#  >KKalh5gRMK~~.KP1~Q2Q2Q2Q2Q2Q2Q2T4,ET,/-+(&$! ;JJxuI2A zutXWW C)jR3Q2Q2Q2Q2Q2Q2Q2T4,EP(+*'&$! 9FFo󁦻'>J GCC00+!7M0zQ2Q2Q2Q2Q2Q2Q2Q2T4+CK$'&$#  6BBcm 4P%3?_ZY#!*S>V6N/|P1Q2Q2Q2Q2Q2Q2U4'=D $#! 1**xxNN$$))FNN[[UYN~~|bY;Q2Q2Q2Q2Q2Q2U4#6;  5      '33EOOuvvHETnz[=Q2Q2Q2Q2Q2T4.1 &$""]]Zi]wX9Q2Q2Q2R2Q2'$ <99MHhxpS3Q2Q2R3L/x v 200SRTqcu[O0|Q2S3F+o ] (,++kjhC=e~T5Q2S3?'e H !$##}}{=8RqkOO0}S45!T+  >;Mqcz`N/|L/x"6   IGTn`iO/}?'c K  |}xxYTntlG)o/  {|ww~}zlf{f2N_ yyuukjgwpjT  uvqqVURRQT{0#M, rnjjljh11.YUmqak lRRRffc676>7]zlz ___x[\[TSUa]olax*%Ed+++JJJ[[^hgkpptwvzwvzttxnmrZYcTNki_=4b4]F'f $95.UG>t]Rqbzi|kyiqbdVSGC:k7/W+%E/ s.Dh &,.,'  vU<%4BGIHB8, ????????????pencil-0.4.4b/linkmac0000755000175000017500000000604110745152004015206 0ustar khashayarkhashayar#make clean #qmake -config release #make pencil="build/Release/Pencil.app" echo $pencil #qtlib="/usr/local/Trolltech/Qt-4.2.2/lib/" #qtlib="/Library/Frameworks" qtlib="" echo $qtlib #mkdir $pencil/Contents/Frameworks #mkdir $pencil/Contents/plugins #mkdir $pencil/Contents/plugins/imageformats #cp -R $qtlib/QtCore.framework $pencil/Contents/Frameworks/ #cp -R $qtlib/QtGui.framework $pencil/Contents/Frameworks/ #cp -R $qtlib/QtXml.framework $pencil/Contents/Frameworks/ #cp -R $qtlib/QtOpenGL.framework $pencil/Contents/Frameworks/ #cp -R /Developer/Applications/Qt/plugins/imageformats/libqjpeg.dylib $pencil/Contents/plugins/imageformats/ install_name_tool -id @executable_path/../Frameworks/QtCore.framework/Versions/4/QtCore $pencil/Contents/Frameworks/QtCore.framework/Versions/4/QtCore install_name_tool -id @executable_path/../Frameworks/QtGui.framework/Versions/4/QtGui $pencil/Contents/Frameworks/QtGui.framework/Versions/4/QtGui install_name_tool -id @executable_path/../Frameworks/QtXml.framework/Versions/4/QtXml $pencil/Contents/Frameworks/QtXml.framework/Versions/4/QtXml install_name_tool -id @executable_path/../Frameworks/QtOpenGL.framework/Versions/4/QtOpenGL $pencil/Contents/Frameworks/QtOpenGL.framework/Versions/4/QtOpenGL install_name_tool -change $qtlib"QtCore.framework/Versions/4/QtCore" @executable_path/../Frameworks/QtCore.framework/Versions/4/QtCore $pencil/Contents/MacOs/pencil install_name_tool -change $qtlib"QtGui.framework/Versions/4/QtGui" @executable_path/../Frameworks/QtGui.framework/Versions/4/QtGui $pencil/Contents/MacOS/pencil install_name_tool -change $qtlib"QtXml.framework/Versions/4/QtXml" @executable_path/../Frameworks/QtXml.framework/Versions/4/QtXml $pencil/Contents/MacOS/pencil install_name_tool -change $qtlib"QtOpenGL.framework/Versions/4/QtOpenGL" @executable_path/../Frameworks/QtOpenGL.framework/Versions/4/QtOpenGL $pencil/Contents/MacOS/pencil install_name_tool -change $qtlib"QtCore.framework/Versions/4/QtCore" @executable_path/../Frameworks/QtCore.framework/Versions/4/QtCore $pencil/Contents/Frameworks/QtGui.framework/Versions/4/QtGui install_name_tool -change $qtlib"QtCore.framework/Versions/4/QtCore" @executable_path/../Frameworks/QtCore.framework/Versions/4/QtCore $pencil/Contents/Frameworks/QtXml.framework/Versions/4/QtXml install_name_tool -change $qtlib"QtCore.framework/Versions/4/QtCore" @executable_path/../Frameworks/QtCore.framework/Versions/4/QtCore $pencil/Contents/Frameworks/QtOpenGL.framework/Versions/4/QtOpenGL install_name_tool -change $qtlib"QtGui.framework/Versions/4/QtGui" @executable_path/../Frameworks/QtGui.framework/Versions/4/QtGui $pencil/Contents/Frameworks/QtOpenGL.framework/Versions/4/QtOpenGL install_name_tool -change $qtlib"QtCore.framework/Versions/4/QtCore" @executable_path/../Frameworks/QtCore.framework/Versions/4/QtCore $pencil/Contents/plugins/imageformats/libqjpeg.dylib install_name_tool -change $qtlib"QtGui.framework/Versions/4/QtGui" @executable_path/../Frameworks/QtGui.framework/Versions/4/QtGui $pencil/Contents/plugins/imageformats/libqjpeg.dylib echo ok pencil-0.4.4b/notes-linux.txt0000755000175000017500000000151010704272754016701 0ustar khashayarkhashayarThese are some notes/memo about compiling Pencil on Linux Last edited: 2007-10-12 Pascal Naidon 1) Install Qt if you haven't done it 2) Install Ming 3) Open a terminal, go to the directory where pencil.pro is located, and type "qmake" 4) Type "make" The Debian directory has been created by Paul Wise for Debian distribution. ==================================================================== Qt on Linux -> The Qt framework is needed to create the graphical interface of Pencil Use the installer from Trolltech www.trolltech.com ==================================================================== Ming (Flash/SWF library) on Linux -> The Ming library enables Pencil to export animation to the Flash/SWF format www.libming.org ======================== Deploying Pencil on Linux systems ???? No one has made a package for Linux yet.pencil-0.4.4b/pencil.qrc0000644000175000017500000000265110713434142015627 0ustar khashayarkhashayar icons/arrow.png icons/clear.png icons/remove.png icons/add.png icons/eraser.png icons/pencil2.png icons/house.png icons/select.png icons/move.png icons/pen.png icons/brush.png icons/polyline.png icons/eraser2.png icons/hand.png icons/bucket.png icons/bucketTool.png icons/eyedropper.png icons/thinlines5.png icons/outlines5.png icons/mirror.png icons/magnify.png icons/smudge.png icons/onionPrev.png icons/onionNext.png icons/layer-vector.png icons/layer-bitmap.png icons/layer-sound.png icons/layer-camera.png icons/controls/play.png icons/controls/loop.png icons/controls/sound.png icons/controls/separator.png icons/prefspencil.png icons/prefstimeline.png icons/prefs-files.png background/weave.jpg background/dots.png icons/logo.png icons/icon.png icons/aqua.png pencil-0.4.4b/.DS_Store0000644000175000017500000001400410757714707015344 0ustar khashayarkhashayarBud1 ground backgroundIlocblobPcpmacIlocblobdebianIlocblobiconsIlocblob0 libmacosxIlocblobPplibwin32Ilocblobp LICENSE.TXTIlocblobplinkmacIlocblob0pnotes-linux.txtIlocblobPnotes-macosx.txtIlocblobnotes-win32.txtIlocblob pencil.icnsIlocblob0 pencil.icoIlocblobP pencil.proIlocblob pencil.qrcIlocblob pencil.rcIlocblob0READMEIlocblobPf ResourcesIlocblobfsrcIlocblobfTODOIlocblob0f  @ @ @ @ E DSDB ` @ @ @pencil-0.4.4b/pencil.pro0000644000175000017500000000573610744607202015654 0ustar khashayarkhashayar###################################################################### # Automatically generated by qmake (2.01a) sam. janv. 13 17:20:35 2007 ###################################################################### CONFIG += qt release TEMPLATE = app TARGET = Pencil DEPENDPATH += . src INCLUDEPATH += . src \ src/external/flash \ src/external/linux \ src/external/macosx \ src/external/win32 \ src/graphics \ src/graphics/bitmap \ src/graphics/vector \ src/interface \ src/structure # Input HEADERS += src/interfaces.h \ src/external/flash/flash.h \ src/graphics/bitmap/bitmapimage.h \ src/graphics/vector/bezierarea.h \ src/graphics/vector/beziercurve.h \ src/graphics/vector/colourref.h \ src/graphics/vector/gradient.h \ src/graphics/vector/vectorimage.h \ src/graphics/vector/vertexref.h \ src/structure/layer.h \ src/structure/layerbitmap.h \ src/structure/layercamera.h \ src/structure/layerimage.h \ src/structure/layersound.h \ src/structure/layervector.h \ src/structure/object.h \ src/interface/editor.h \ src/interface/mainwindow.h \ src/interface/palette.h \ src/interface/preferences.h \ src/interface/scribblearea.h \ src/interface/timeline.h \ src/interface/timecontrols.h \ src/interface/toolset.h SOURCES += src/external/flash/flash.cpp \ src/graphics/bitmap/blur.cpp \ src/graphics/bitmap/bitmapimage.cpp \ src/graphics/vector/bezierarea.cpp \ src/graphics/vector/beziercurve.cpp \ src/graphics/vector/colourref.cpp \ src/graphics/vector/gradient.cpp \ src/graphics/vector/vectorimage.cpp \ src/graphics/vector/vertexref.cpp \ src/structure/layer.cpp \ src/structure/layerbitmap.cpp \ src/structure/layercamera.cpp \ src/structure/layerimage.cpp \ src/structure/layersound.cpp \ src/structure/layervector.cpp \ src/structure/object.cpp \ src/interface/editor.cpp \ src/interface/mainwindow.cpp \ src/interface/palette.cpp \ src/interface/preferences.cpp \ src/interface/scribblearea.cpp \ src/interface/timeline.cpp \ src/interface/timecontrols.cpp \ src/interface/toolset.cpp \ src/main.cpp win32 { INCLUDEPATH += . libwin32 SOURCES += src/external/win32/win32.cpp LIBS += -Llibwin32 -lming -lpng RC_FILE = pencil.rc } macx { INCLUDEPATH += . libmacosx HEADERS += src/external/macosx/style.h SOURCES += src/external/macosx/macosx.cpp \ src/external/macosx/style.cpp LIBS += -Llibmacosx -lming RC_FILE = pencil.icns } linux-g++ { INCLUDEPATH += . liblinux SOURCES += src/external/linux/linux.cpp LIBS += -Lliblinux -lming -lpng } RESOURCES += pencil.qrc QT += xml opengl pencil-0.4.4b/background/0000755000175000017500000000000010757714670016000 5ustar khashayarkhashayarpencil-0.4.4b/background/dots.png0000644000175000017500000000025410641754634017454 0ustar khashayarkhashayarPNG  IHDRzgAMAOX2tEXtSoftwareAdobe ImageReadyqe< PLTEM2)IDATxb`& e @P6@A#@ [}YIENDB`pencil-0.4.4b/background/weave.jpg0000644000175000017500000001040010641754634017600 0ustar khashayarkhashayarJFIFHHC  !"$"$C"C!1Q"Aq#a23s4BS$RTrCDct ?ZR3@Al`\tb틹O)epKH2[4fx>qn[ރG cLFmR ,Ć<*,o-Tg%$BB`&7+  v4gbse*S#eea.1c TbF :ke\5-cb(h5cP0: t9cȰ޺NbthѬōm@ش2ʅ`]tlHI 8HG UY3u/ oY$։&6kZ Z/?>TV F1&Tcuh\4MRpLIxFD# eUhPU^᝔F )\58Q7 "0.<;p 4# mvRPR7 )f{6ۭNAcD7[," )8sWN$%]n6UwxrQ ':8dv5jJDVv`72Uܐh?ցBAͤGϞU2F6XػcI. .ZئqA V9$H,n,~4%RX-}nU1H f,-FԂ#c7oAHԤF& nDũ7օYudB$'%k[XB"y W3A3-TF _jVɂFvTl/pXP cݑ}.4_:+NL,\XV]T W%*.Oƚ،;~E#\cK{ohj$Me2}UZRI21vQ˯¨nƜj%k 6=O1SDqJ(-ܫ6ya\C-#jys ~n$ 4{b@nѸ+Y)_RMg ʧAn0*)ˑq#ʳLD%'Zc;wVx {㕪Hssö;؍ +cxVQbMZ/{e4 ]Qv&oNp" J4n "İޙr&gS^~zP#"T02Z۝%&@xXR̨ƮL%Xz*):{ꑢeE ]wPJ xU܏0UdEVW]m&%b3&=7wHفFDcWc$-\u1ŏ4,p T*KbCf0˟uME$rƒf\hD=GΊ Xfl,PE1qYa[} @DV[n8uTPj,2A!썭N$-+YA#qqQe]H7؃׺,#MA{!X)J{i2MV\u;η &=mHui@\}(["`"]M!VSj ,m5/>E4# N$ Ln6?SeF+ϥu)8.${ꚲ& KiܤvIPVz PWf `2AuRJkN*ʧ91v+~uTYEu#AMX^frDj@yAEy#C*3HԹ6> CqLHb;6邏9 ѶKFT $۰c%:\ [Ϻ7i^Uuhi~u;e.oRlWd Sck΃m`{jóryp5ATn$q("XEoJT$BX"P4vs~ *#J轓Q.S$,>bQГtZ;z˧ɠrc3iiT6ڸ!JHH wehʹ "o;qciО@ I`]$ĕHo2e |GF[M~@#HMhl0&e&J 5ƻe쥊XwfFhu#^BBȿ1H3YԦp#A%m@(pD+*nß6*Jkٯp+k/ ~ȭ4G # ߕb;85)c$dbN.S~},d $+ȩ),;r+ v 2g54lA#ǂΆ6X R _VȶhAMd8*nT*dDᘗ XomWud;\qj(M:|CڗP11PA)"Hi!lHuƢ%1SmM<@vȆR$eAAXb #include #include #include // requires the Ming Library #include "layer.h" #include "layervector.h" #include "layerbitmap.h" #include "vectorimage.h" class Object; class Flash { public: static void exportFlash(Object* object, int startFrame, int endFrame, QMatrix view, QSize exportSize, QString filePath, int fps, int compression); static void convertToSWFSprite( BitmapImage* image, Object* object, QMatrix view, SWFSprite* sprite ); static void convertToSWFSprite( VectorImage* vectorImage, Object* object, QMatrix view, SWFSprite* sprite ); static void addShape( SWFSprite* sprite, QPainterPath path, QColor fillColour, QColor borderColour, qreal width, bool fill ); }; #endif pencil-0.4.4b/src/external/flash/flash.cpp0000644000175000017500000002115010704272754021161 0ustar khashayarkhashayar/* Pencil - Traditional Animation Software Copyright (C) 2005-2007 Patrick Corrieri & Pascal Naidon This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #include #include #include #include "flash.h" #include "object.h" #include "beziercurve.h" #include "colourref.h" void Flash::exportFlash(Object* object, int startFrame, int endFrame, QMatrix view, QSize exportSize, QString filePath, int fps, int compression) { qDebug() << "------Flash------" << compression; // ************* Requires the MING Library *************** Ming_init(); SWFMovie *movie = new SWFMovie(); movie->setDimension(exportSize.width(), exportSize.height()); movie->setRate(fps); // 12 frames per seconds //SWFShape *shape = new SWFShape(); SWFSprite *objectSprite = new SWFSprite(); for(int i=0; i < object->getLayerCount(); i++) { Layer* layer = object->getLayer(i); if(layer->visible) { // paints the bitmap images if(layer->type == Layer::BITMAP) { LayerBitmap* layerBitmap = (LayerBitmap*)layer; SWFSprite *layerSprite = new SWFSprite(); SWFDisplayItem *previousItem = NULL; for(int frameNumber = startFrame; frameNumber <= endFrame; frameNumber++) { BitmapImage* bitmapImage = layerBitmap->getBitmapImageAtFrame(frameNumber); if(bitmapImage != NULL) { if(previousItem != NULL) layerSprite->remove( previousItem ); SWFSprite *imageSprite = new SWFSprite(); convertToSWFSprite( bitmapImage, object, view, imageSprite); previousItem = layerSprite->add( imageSprite ); } layerSprite->nextFrame(); } //layerSprite->add( new SWFAction("stop();") ); //layerSprite->nextFrame(); objectSprite->add(layerSprite); } // paints the vector images if(layer->type == Layer::VECTOR) { LayerVector* layerVector = (LayerVector*)layer; SWFSprite *layerSprite = new SWFSprite(); SWFDisplayItem *previousItem = NULL; for(int frameNumber = startFrame; frameNumber <= endFrame; frameNumber++) { VectorImage* vectorImage = layerVector->getVectorImageAtFrame(frameNumber); if(vectorImage != NULL) { if(previousItem != NULL) layerSprite->remove( previousItem ); SWFSprite *sprite = new SWFSprite(); convertToSWFSprite( vectorImage, object, view, sprite); previousItem = layerSprite->add( sprite ); } layerSprite->nextFrame(); } //layerSprite->add( new SWFAction("stop();") ); //layerSprite->nextFrame(); objectSprite->add(layerSprite); } } } objectSprite->nextFrame(); //objectSprite->add( new SWFAction("stop();") ); //objectSprite->nextFrame(); movie->add(objectSprite); movie->nextFrame(); movie->add( new SWFAction("gotoFrame(0);") ); movie->nextFrame(); QByteArray byteArray(filePath.toLatin1()); // is there any problem with accented characters? movie->save(byteArray.data(), compression); qDebug() << "done."; } void Flash::convertToSWFSprite( BitmapImage* bitmapImage, Object* object, QMatrix view, SWFSprite* sprite ) { QString tempPath = QDir::tempPath()+"penciltemp.png"; QByteArray tempPath2( tempPath.toLatin1()); bitmapImage->image->save( tempPath , "PNG"); SWFShape *shape = new SWFShape(); SWFFill* fill = shape->addBitmapFill( new SWFBitmap( tempPath2.data() ) ); fill->moveTo(static_cast(bitmapImage->topLeft().x()), static_cast(bitmapImage->topLeft().y())); shape->setRightFill(fill); shape->movePenTo(bitmapImage->left(), bitmapImage->top()); shape->drawLineTo(bitmapImage->right(), bitmapImage->top()); shape->drawLineTo(bitmapImage->right(), bitmapImage->bottom()); shape->drawLineTo(bitmapImage->left(), bitmapImage->bottom()); shape->drawLineTo(bitmapImage->left(), bitmapImage->top()); SWFDisplayItem *item = sprite->add( shape ); //item->setMatrix( view.m11(), view.m12(), view.m21(), view.m22(), view.dx(), view.dy() ); // this C++ method is not defined in mingpp.h version 0.3 SWFDisplayItem_setMatrix( item->item, view.m11(), view.m12(), view.m21(), view.m22(), view.dx(), view.dy() ); // we use the C function instead sprite->nextFrame(); } void Flash::convertToSWFSprite( VectorImage* vectorImage, Object* object, QMatrix view, SWFSprite* sprite ) { // add filled areas for(int i=0; i< vectorImage->area.size(); i++) { QColor colour = object->getColour(vectorImage->area[i].getColourNumber()).colour; QPainterPath path = view.map( vectorImage->area[i].path ); addShape(sprite, path, colour, colour, 0, true); } // add curves for(int i=0; i< vectorImage->curve.size(); i++) { if(!vectorImage->curve[i].isInvisible()) { QColor colour = object->getColour(vectorImage->curve[i].getColourNumber()).colour; if(vectorImage->curve[i].getVariableWidth()) { QPainterPath path = view.map( vectorImage->curve[i].getStrokedPath() ); addShape(sprite, path, colour, colour, 0, true); } else { QPainterPath path = view.map( vectorImage->curve[i].getSimplePath() ); qreal width = vectorImage->curve[i].getWidth(); addShape(sprite, path, colour, colour, width, false); } } } sprite->nextFrame(); } void Flash::addShape( SWFSprite* sprite, QPainterPath path, QColor fillColour, QColor borderColour, qreal width, bool fill ) { SWFShape* shape = new SWFShape(); //float widthf = static_cast< float >(width); if(width == 0.0) { shape->setLine( static_cast(width), borderColour.red(), borderColour.green(), borderColour.blue(), 0); } else { shape->setLine(static_cast(width), borderColour.red(), borderColour.green(), borderColour.blue() ); } if(fill) { SWFFill* fill = shape->addSolidFill( fillColour.red(), fillColour.green(), fillColour.blue() ); shape->setRightFill(fill); } qreal memoP0x = 0.0; qreal memoP0y = 0.0; qreal memoP1x = 0.0; qreal memoP1y = 0.0; qreal memoP2x = 0.0; qreal memoP2y = 0.0; qreal memoP3x = 0.0; qreal memoP3y = 0.0; qreal memo = 0.0; for(int i=0; i < path.elementCount() ; i++) { QPainterPath::Element element = path.elementAt(i); if( element.type == QPainterPath::CurveToDataElement ) { memo++; if(memo == 1) { memoP2x = element.x; memoP2y = element.y; } if(memo == 2) { memoP3x = element.x; memoP3y = element.y; } } if( (element.type != QPainterPath::CurveToDataElement) || ((element.type == QPainterPath::CurveToDataElement) && (i==path.elementCount()-1)) ) { if(memo == 1) { shape->drawCurveTo( static_cast(memoP1x), static_cast(memoP1y), static_cast(memoP2x), static_cast(memoP2y) ); //--- memo = 0; memoP0x = memoP2x; memoP0y = memoP2y; } if(memo == 2) { // now we need to approximate a cubic Bezier curve by 4 quadratic Bezier curves (Flash API uses only quadratic Bezier curves) // we use the fixed midpoint method // Excellent explanations here: http://timotheegroleau.com/Flash/articles/cubic_bezier_in_flash.htm QPointF P0(memoP0x, memoP0y); QPointF P1(memoP1x, memoP1y); QPointF P2(memoP2x, memoP2y); QPointF P3(memoP3x, memoP3y); QPointF M2 = (P0+3*P1+3*P2+P3)/8; QPointF C1 = (5*P0+3*P1)/8; QPointF C4 = (5*P3+3*P2)/8; QPointF C2 = (3*(P0+2*P1+P2)/4+M2)/4; QPointF C3 = (3*(P1+2*P2+P3)/4+M2)/4; QPointF M1 = 0.5*(C1+C2); QPointF M3 = 0.5*(C3+C4); shape->drawCurveTo( static_cast(C1.x()), static_cast(C1.y()), static_cast(M1.x()), static_cast(M1.y()) ); shape->drawCurveTo( static_cast(C2.x()), static_cast(C2.y()), static_cast(M2.x()), static_cast(M2.y()) ); shape->drawCurveTo( static_cast(C3.x()), static_cast(C3.y()), static_cast(M3.x()), static_cast(M3.y()) ); shape->drawCurveTo( static_cast(C4.x()), static_cast(C4.y()), static_cast(P3.x()), static_cast(P3.y()) ); //--- memo = 0; memoP0x = memoP3x; memoP0y = memoP3y; } } if( element.type == QPainterPath::MoveToElement ) { shape->movePenTo( static_cast(element.x), static_cast(element.y) ); memoP0x = element.x; memoP0y = element.y; } if( element.type == QPainterPath::LineToElement ) { shape->drawLineTo( static_cast(element.x), static_cast(element.y) ); memoP0x = element.x; memoP0y = element.y; } if( element.type == QPainterPath::CurveToElement ) { memoP1x = element.x; memoP1y = element.y; } } sprite->add( shape ); } pencil-0.4.4b/src/external/win32/0000755000175000017500000000000010757714676017242 5ustar khashayarkhashayarpencil-0.4.4b/src/external/win32/win32.cpp0000644000175000017500000000153010650474602020667 0ustar khashayarkhashayar/* Pencil - Traditional Animation Software Copyright (C) 2005-2007 Patrick Corrieri & Pascal Naidon This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #include "object.h" void initialise() { // nothing, for now } void Object::exportMovie(int startFrame, int endFrame, QMatrix view, Layer* currentLayer, QSize exportSize, QString filePath, int fps) { QMessageBox assembling("Export",tr("Not supported yet on this platform..."),QMessageBox::Information,0,0,0); assembling.show(); // nothing } pencil-0.4.4b/src/external/macosx/0000755000175000017500000000000010757714676017572 5ustar khashayarkhashayarpencil-0.4.4b/src/external/macosx/macosx.cpp0000644000175000017500000000530110745152004021541 0ustar khashayarkhashayar/* Pencil - Traditional Animation Software Copyright (C) 2005-2007 Patrick Corrieri & Pascal Naidon This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #include #include #include #include #include #include "object.h" #include "mainwindow.h" #include "style.h" #include void initialise() { qApp->setStyle(new AquaStyle()); } void Object::exportMovie(int startFrame, int endFrame, QMatrix view, Layer* currentLayer, QSize exportSize, QString filePath, int fps) { if(!filePath.endsWith(".mov", Qt::CaseInsensitive)) { filePath = filePath + ".mov"; } qDebug() << "-------QuickTime------" << filePath << QDir::temp().absolutePath(); // --------- Export all the temporary frames ---------- QDir::temp().mkdir("pencil"); QString tempPath = QDir::tempPath()+"pencil/"; QProgressDialog progress("Exporting movie...", "Abort", 0, 100, NULL); progress.setWindowModality(Qt::WindowModal); progress.show(); exportFrames(startFrame, endFrame, view, currentLayer, exportSize, tempPath+"tmp", "jpg", 100, true, true, 2); qDebug() << "frames exported in temp directory"; // --------- Quicktime assemble call ---------- // --- locate the assembler --- CFURLRef pluginRef = CFBundleCopyBundleURL(CFBundleGetMainBundle()); CFStringRef macPath = CFURLCopyFileSystemPath(pluginRef, kCFURLPOSIXPathStyle); const char *pathPtr = CFStringGetCStringPtr(macPath, CFStringGetSystemEncoding()); CFRelease(pluginRef); CFRelease(macPath); QString appPath = pathPtr; // --- run the assembler --- QProcess assemble; QStringList args; args << QString::number(endFrame+1) << tempPath+"tmp%03d.jpg" << QString::number(fps) << filePath; assemble.start(appPath+"/Contents/Resources/assembler2",args); assemble.waitForStarted(); assemble.waitForFinished(); qDebug() << "exit status " << assemble.exitStatus(); qDebug() << assemble.readAllStandardOutput(); qDebug() << assemble.readAllStandardError(); progress.setValue(100); qDebug() << "QuickTime export done"; // --------- Clean up temp directory --------- QDir dir(tempPath); QStringList filtername("*.*"); QStringList entries = dir.entryList(filtername,QDir::Files,QDir::Type); for(int i=0;i #include class AquaStyle : public QMacStyle { Q_OBJECT public: AquaStyle() {} //void polish(QPalette &palette); //void polish(QWidget *widget); //void unpolish(QWidget *widget); int pixelMetric(PixelMetric metric, const QStyleOption *option, const QWidget *widget) const; //int styleHint(StyleHint hint, const QStyleOption *option, // const QWidget *widget, QStyleHintReturn *returnData) const; void drawPrimitive(PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const; void drawControl(ControlElement control, const QStyleOption *option, QPainter *painter, const QWidget *widget) const; void drawComplexControl ( ComplexControl control, const QStyleOptionComplex * option, QPainter * painter, const QWidget * widget = 0 ) const; QRect subControlRect ( ComplexControl control, const QStyleOptionComplex * option, SubControl subControl, const QWidget * widget = 0 ) const; QPixmap standardPixmap ( StandardPixmap standardPixmap, const QStyleOption * option = 0, const QWidget * widget = 0 ) const; private: //static void setTexture(QPalette &palette, QPalette::ColorRole role, // const QPixmap &pixmap); //static QPainterPath roundRectPath(const QRect &rect); }; #endifpencil-0.4.4b/src/external/macosx/style.cpp0000644000175000017500000003034510650474602021423 0ustar khashayarkhashayar/* Pencil - Traditional Animation Software Copyright (C) 2005-2007 Patrick Corrieri & Pascal Naidon This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #include #include "style.h" int AquaStyle::pixelMetric(PixelMetric metric, const QStyleOption *option, const QWidget *widget) const { switch (metric) { case QStyle::PM_DockWidgetSeparatorExtent: return 3; case QStyle::PM_DockWidgetTitleBarButtonMargin: return 1; default: return QMacStyle::pixelMetric(metric, option, widget); } } void AquaStyle::drawPrimitive(PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const { /*const QDockWidget *truc = qobject_cast(widget); if (truc) { qDebug() << "DOCK! -- element" << element; }*/ /*const QStyleOptionDockWidget *dockWidgetOption = qstyleoption_cast(option); if(dockWidgetOption) { qDebug() << "DOCK!" << element << PE_FrameDockWidget; }*/ switch (element) { case PE_FrameDockWidget: { int x, y, width, height; option->rect.getRect(&x, &y, &width, &height); //painter->setBrush( Qt::red ); //painter->drawRect( QRect(0,0, width, height) ); //if(dockWidgetOption->isFloating) { painter->setBrush( Qt::NoBrush ); painter->setPen( QColor(142,142,142) ); painter->drawRect( QRect( QPoint(0,0), QSize(width-1, height-1) ) ); //} } break; /*case PE_PanelButtonCommand: { int delta = (option->state & State_MouseOver) ? 64 : 0; QColor slightlyOpaqueBlack(0, 0, 0, 63); QColor semiTransparentWhite(255, 255, 255, 127 + delta); QColor semiTransparentBlack(0, 0, 0, 127 - delta); int x, y, width, height; option->rect.getRect(&x, &y, &width, &height); QPainterPath roundRect = roundRectPath(option->rect); int radius = qMin(width, height) / 2; QBrush brush; bool darker; const QStyleOptionButton *buttonOption = qstyleoption_cast(option); if (buttonOption && (buttonOption->features & QStyleOptionButton::Flat)) { brush = option->palette.background(); darker = (option->state & (State_Sunken | State_On)); } else { if (option->state & (State_Sunken | State_On)) { brush = option->palette.mid(); darker = !(option->state & State_Sunken); } else { brush = option->palette.button(); darker = false; } } painter->save(); painter->setRenderHint(QPainter::Antialiasing, true); painter->fillPath(roundRect, brush); if (darker) painter->fillPath(roundRect, slightlyOpaqueBlack); int penWidth; if (radius < 10) penWidth = 3; else if (radius < 20) penWidth = 5; else penWidth = 7; QPen topPen(semiTransparentWhite, penWidth); QPen bottomPen(semiTransparentBlack, penWidth); if (option->state & (State_Sunken | State_On)) qSwap(topPen, bottomPen); int x1 = x; int x2 = x + radius; int x3 = x + width - radius; int x4 = x + width; if (option->direction == Qt::RightToLeft) { qSwap(x1, x4); qSwap(x2, x3); } QPolygon topHalf; topHalf << QPoint(x1, y) << QPoint(x4, y) << QPoint(x3, y + radius) << QPoint(x2, y + height - radius) << QPoint(x1, y + height); painter->setClipPath(roundRect); painter->setClipRegion(topHalf, Qt::IntersectClip); painter->setPen(topPen); painter->drawPath(roundRect); QPolygon bottomHalf = topHalf; bottomHalf[0] = QPoint(x4, y + height); painter->setClipPath(roundRect); painter->setClipRegion(bottomHalf, Qt::IntersectClip); painter->setPen(bottomPen); painter->drawPath(roundRect); painter->setPen(option->palette.foreground().color()); painter->setClipping(false); painter->drawPath(roundRect); painter->restore(); } break;*/ default: QMacStyle::drawPrimitive(element, option, painter, widget); } } void AquaStyle::drawComplexControl ( ComplexControl control, const QStyleOptionComplex * option, QPainter * painter, const QWidget * widget ) const { //const QStyleOptionTitleBar *titleBarOption = qstyleoption_cast(option); //if(titleBarOption) { // qDebug() << "DOCK2!" << control; //} //qDebug() << "control" << control; if(control == CC_TitleBar) { //qDebug() << "coucou"; } else { QMacStyle::drawComplexControl(control, option, painter, widget); } } void AquaStyle::drawControl(ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const { //const QStyleOptionDockWidget *dockWidgetOption = qstyleoption_cast(option); //if(dockWidgetOption) { // qDebug() << "DOCK!" << element << CE_DockWidgetTitle; //} switch (element) { case CE_DockWidgetTitle: { /*QStyleOptionButton option; option.initFrom(this); option.state = isDown() ? QStyle::State_Sunken : QStyle::State_Raised; if (isDefault()) option.features |= QStyleOptionButton::DefaultButton; option.text = text(); option.icon = icon();*/ int x, y, width, height; option->rect.getRect(&x, &y, &width, &height); width = width+6; height = height - 1; const QStyleOptionDockWidget *dockWidgetOption = qstyleoption_cast(option); painter->setPen( QColor(142,142,142) ); QLinearGradient gradient(0,1,0,height); QSettings settings("Pencil","Pencil"); QString style = settings.value("style").toString(); if(style=="") style = "default"; if(style=="default") { gradient.setColorAt(0, QColor(247,247,247)); gradient.setColorAt(0.0625, QColor(235,235,235)); gradient.setColorAt(1, QColor(207,207,207)); painter->setBrush( gradient ); } if(style=="aqua") { gradient.setColorAt(0, QColor(208,226,245)); gradient.setColorAt(0.25, QColor(142,187,232)); gradient.setColorAt(0.5, QColor(134,186,237)); gradient.setColorAt(0.51, QColor(104,169,234)); gradient.setColorAt(0.76, QColor(104,169,234)); gradient.setColorAt(0.90, QColor(145,210,240)); gradient.setColorAt(1, QColor(187,252,255)); /*gradient.setColorAt(0, QColor(238,239,241)); gradient.setColorAt(0.25, QColor(200,205,210)); gradient.setColorAt(0.5, QColor(194,200,206)); gradient.setColorAt(0.51, QColor(180,188,195)); gradient.setColorAt(1, QColor(240,247,255));*/ painter->setBrush( QPixmap(":icons/aqua.png") ); } painter->drawRect( QRect( QPoint(-1,0), QSize(width+1, height) ) ); if(style=="aqua") { painter->setPen( QColor(0,78,193) ); painter->drawLine( QPoint(0,0), QPoint(width,0) ); painter->setPen( QColor(102,147,192) ); painter->drawLine( QPoint(0,height), QPoint(width, height) ); /*painter->setPen( QColor(93,109,124) ); painter->drawLine( QPoint(0,0), QPoint(width,0) ); painter->setPen( QColor(153,159,166) ); painter->drawLine( QPoint(0,16), QPoint(width,16) );*/ painter->setPen( QColor(0,78,193,128) ); painter->drawLine( QPoint(0,0), QPoint(0,height) ); painter->drawLine( QPoint(width-1,0), QPoint(width-1, height) ); painter->setPen( QColor(0,0,0,160) ); for(int i=0; idrawPoint(4,3+2*i); painter->drawPoint(7,3+2*i); } painter->setPen( QColor(255,255,255,240) ); for(int i=0; idrawPoint(5,4+2*i); painter->drawPoint(8,4+2*i); } } if(style=="default") { painter->setPen( QColor(100,100,100,128) ); painter->drawLine( QPoint(0,0), QPoint(0, height) ); painter->drawLine( QPoint(width-1,0), QPoint(width-1, height) ); } painter->setPen( QColor(0,0,0) ); painter->setFont( QFont("Helvetica", 12) ); if(style == "aqua") { painter->drawText(QPoint(13,14), dockWidgetOption->title); } if(style == "default") { painter->drawText(QPoint(6,14), dockWidgetOption->title); } //QStyleOptionButton option; //option.initFrom(this); //option.backgroundColor = palette().color(QPalette::Background); //QMacStyle::drawControl(QStyle::CE_PushButton, option, painter, widget); /*QStyleOptionButton myButtonOption; const QStyleOptionButton *buttonOption = qstyleoption_cast(option); if (buttonOption) { myButtonOption = *buttonOption; if (myButtonOption.palette.currentColorGroup() != QPalette::Disabled) { if (myButtonOption.state & (State_Sunken | State_On)) { myButtonOption.palette.setBrush(QPalette::ButtonText, myButtonOption.palette.brightText()); } } } QMotifStyle::drawControl(element, &myButtonOption, painter, widget);*/ } break; default: QMacStyle::drawControl(element, option, painter, widget); } } QRect AquaStyle::subControlRect ( ComplexControl control, const QStyleOptionComplex * option, SubControl subControl, const QWidget * widget ) const { //qDebug() << "ComplexControl" << control << "subControl" << subControl << QMacStyle::subControlRect(control, option, subControl, widget); if(control == CC_ToolButton){ if(subControl == SC_TitleBarNormalButton) { qDebug() << "ComplexControl" << control << "subControl" << subControl; } //return QRect(30,5,20,20); } // else { //return QRect(2,2,32,32); return QMacStyle::subControlRect(control, option, subControl, widget); //} } QPixmap AquaStyle::standardPixmap ( StandardPixmap standardPixmap, const QStyleOption * option, const QWidget * widget ) const { return QMacStyle::standardPixmap(standardPixmap, option, widget); /* //qDebug() << "standardPixmap" << standardPixmap; //if(option) qDebug() << "option" << *option; switch (standardPixmap) { case SP_TitleBarNormalButton: { QPixmap pixmap(":icons/titleBar/floatButton.png"); return pixmap; //qDebug() << "SP_TitleBarNormalButton" << QMacStyle::standardPixmap(standardPixmap, option, widget).size(); //return QMacStyle::standardPixmap(standardPixmap, option, widget); } break; case SP_TitleBarCloseButton: { QPixmap pixmap(":icons/titleBar/closeButton.png"); return pixmap; //qDebug() << "SP_TitleBarCloseButton" << QMacStyle::standardPixmap(standardPixmap, option, widget).size(); //return QMacStyle::standardPixmap(standardPixmap, option, widget); } break; default: return QMacStyle::standardPixmap(standardPixmap, option, widget); } */ } pencil-0.4.4b/src/interfaces.h0000644000175000017500000000601610744607202016733 0ustar khashayarkhashayar/**************************************************************************** ** ** Copyright (C) 2005-2007 Trolltech ASA. All rights reserved. ** ** This file is part of the example classes of the Qt Toolkit. ** ** This file may be used under the terms of the GNU General Public ** License version 2.0 as published by the Free Software Foundation ** and appearing in the file LICENSE.GPL included in the packaging of ** this file. Please review the following information to ensure GNU ** General Public Licensing requirements will be met: ** http://www.trolltech.com/products/qt/opensource.html ** ** If you are unsure which license is appropriate for your use, please ** review the following information: ** http://www.trolltech.com/products/qt/licensing.html or contact the ** sales department at sales@trolltech.com. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ****************************************************************************/ #ifndef INTERFACES_H #define INTERFACES_H #include class QImage; class QPainter; class QWidget; class QPainterPath; class QPoint; class QRect; class QStringList; class QMatrix; class QSize; class QString; class Object; class BrushInterface { public: virtual ~BrushInterface() {} virtual QStringList brushes() const = 0; virtual QRect mousePress(const QString &brush, QPainter &painter, const QPoint &pos) = 0; virtual QRect mouseMove(const QString &brush, QPainter &painter, const QPoint &oldPos, const QPoint &newPos) = 0; virtual QRect mouseRelease(const QString &brush, QPainter &painter, const QPoint &pos) = 0; }; class ShapeInterface { public: virtual ~ShapeInterface() {} virtual QStringList shapes() const = 0; virtual QPainterPath generateShape(const QString &shape, QWidget *parent) = 0; }; class FilterInterface { public: virtual ~FilterInterface() {} virtual QStringList filters() const = 0; virtual QImage filterImage(const QString &filter, const QImage &image, QWidget *parent) = 0; }; class ExportInterface { public: virtual ~ExportInterface() {} virtual QString name() const = 0; virtual bool exportFile(Object* object, int startFrame, int endFrame, QMatrix view, QSize exportSize, QString filePath, int fps, int compression) const = 0; /*virtual QImage filterImage(const QString &filter, const QImage &image, QWidget *parent) = 0;*/ }; Q_DECLARE_INTERFACE(BrushInterface, "com.trolltech.PlugAndPaint.BrushInterface/1.0") Q_DECLARE_INTERFACE(ShapeInterface, "com.trolltech.PlugAndPaint.ShapeInterface/1.0") Q_DECLARE_INTERFACE(FilterInterface, "com.trolltech.PlugAndPaint.FilterInterface/1.0") Q_DECLARE_INTERFACE(ExportInterface, "org.pencil.plugins.ExportInterface/1.0") #endif pencil-0.4.4b/src/plugins/0000755000175000017500000000000010757714676016137 5ustar khashayarkhashayarpencil-0.4.4b/src/graphics/0000755000175000017500000000000010757714675016255 5ustar khashayarkhashayarpencil-0.4.4b/src/graphics/bitmap/0000755000175000017500000000000010757714675017531 5ustar khashayarkhashayarpencil-0.4.4b/src/graphics/bitmap/bitmapimage.h0000644000175000017500000000720210745152004022135 0ustar khashayarkhashayar/* Pencil - Traditional Animation Software Copyright (C) 2005-2007 Patrick Corrieri & Pascal Naidon This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #ifndef BITMAP_IMAGE_H #define BITMAP_IMAGE_H #include #include class Object; // forward declaration class BitmapImage { //Q_OBJECT public: BitmapImage(); BitmapImage(const BitmapImage &); BitmapImage(Object* parent); BitmapImage(Object* parent, QRect boundaries, QColor colour); BitmapImage(Object* parent, QRect boundaries, QImage image); //BitmapImage(Object* parent, QImage image, QPoint topLeft); BitmapImage(Object* parent, QString path, QPoint topLeft); ~BitmapImage(); BitmapImage &operator=(const BitmapImage &a); QDomElement createDomElement(QDomDocument &doc); void loadDomElement(QDomElement element, QString filePath); void modification(); bool isModified(); void setModified(bool); void paintImage(QPainter &painter); void outputImage(QImage* image, QSize size, QMatrix myView); BitmapImage copy(); BitmapImage copy(QRect rectangle); void paste(BitmapImage*); void paste(BitmapImage*, QPainter::CompositionMode cm); void add(BitmapImage*); void moveTopLeft(QPoint point); void moveTopLeft(QPointF point) { moveTopLeft(point.toPoint()); } void transform(QRect rectangle, bool smoothTransform); void transform(QRectF rectangle, bool smoothTransform) { transform(rectangle.toRect(), smoothTransform); } BitmapImage transformed(QRect rectangle, bool smoothTransform); BitmapImage transformed(QRectF rectangle, bool smoothTransform) { return transformed(rectangle.toRect(), smoothTransform); } bool contains(QPoint P) { return boundaries.contains(P); } bool contains(QPointF P) { return contains(P.toPoint()); } void extend(QPoint P); void extend(QRect rectangle); QRgb pixel(int x, int y); QRgb pixel(QPoint P); void setPixel(int x, int y, QRgb colour); void setPixel(QPoint P, QRgb colour); void clear(); void clear(QRect rectangle); void clear(QRectF rectangle) { clear(rectangle.toRect()); } static int sqr(int); static int rgbDistance(QRgb rgba1, QRgb rgba2); static void floodFill(BitmapImage* targetImage, BitmapImage* fillImage, QPoint point, QRgb targetColour, QRgb replacementColour, int tolerance, bool extendFillImage); void drawLine(QPointF P1, QPointF P2, QPen pen, QPainter::CompositionMode cm, bool antialiasing); void drawRect( QRectF rectangle, QPen pen, QBrush brush, QPainter::CompositionMode cm, bool antialiasing); void drawEllipse( QRectF rectangle, QPen pen, QBrush brush, QPainter::CompositionMode cm, bool antialiasing); void drawPath( QPainterPath path, QPen pen, QBrush brush, QPainter::CompositionMode cm, bool antialiasing); void blur(qreal radius); void blur2(qreal radius); QPoint topLeft() { return boundaries.topLeft(); } QPoint topRight() { return boundaries.topRight(); } QPoint bottomLeft() { return boundaries.bottomLeft(); } QPoint bottomRight() { return boundaries.bottomRight(); } int left() { return boundaries.left(); } int right() { return boundaries.right(); } int top() { return boundaries.top(); } int bottom() { return boundaries.bottom(); } int width() { return boundaries.width(); } int height() { return boundaries.height(); } public: QImage* image; QRect boundaries; bool extendable; protected: Object* myParent; }; #endif pencil-0.4.4b/src/graphics/bitmap/bitmapimage.cpp0000644000175000017500000004327010745152004022475 0ustar khashayarkhashayar/* Pencil - Traditional Animation Software Copyright (C) 2005-2007 Patrick Corrieri & Pascal Naidon This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #include #include "bitmapimage.h" #include "blur.h" #include "object.h" #include BitmapImage::BitmapImage() { // nothing image = NULL; extendable = true; } BitmapImage::BitmapImage(Object *parent) { myParent = parent; image = new QImage(0, 0, QImage::Format_ARGB32_Premultiplied); boundaries = QRect(0,0,0,0); extendable = true; } BitmapImage::BitmapImage(Object *parent, QRect rectangle, QColor colour) { myParent = parent; boundaries = rectangle; image = new QImage( boundaries.size(), QImage::Format_ARGB32_Premultiplied); image->fill(colour.rgba()); extendable = true; } BitmapImage::BitmapImage(Object *parent, QRect rectangle, QImage image) { myParent = parent; boundaries = rectangle.normalized(); extendable = true; this->image = new QImage(image); if(this->image->width() != rectangle.width() || this->image->height() != rectangle.height()) qDebug() << "Error instancing bitmapImage."; } /*BitmapImage::BitmapImage(Object *parent, QImage image, QPoint topLeft) { myParent = parent; this->image = new QImage(image); boundaries = QRect( topLeft, image.size() ); }*/ BitmapImage::BitmapImage(const BitmapImage &a) { myParent=a.myParent; boundaries=a.boundaries; image=new QImage(*a.image); extendable = true; } BitmapImage::BitmapImage(Object *parent, QString path, QPoint topLeft) { myParent = parent; image = new QImage(path); boundaries = QRect( topLeft, image->size() ); extendable = true; } BitmapImage::~BitmapImage() { if(image) delete image; } BitmapImage &BitmapImage::operator=(const BitmapImage &a) { myParent=a.myParent; boundaries=a.boundaries; image=new QImage(*a.image); return *this; } QDomElement BitmapImage::createDomElement(QDomDocument &doc) { return QDomElement(); // empty } void BitmapImage::loadDomElement(QDomElement imageElement, QString filePath) { QString path = filePath +".data/" + imageElement.attribute("src"); // the file is supposed to be in the data irectory QFileInfo fi(path); if(!fi.exists()) path = imageElement.attribute("src"); int x = imageElement.attribute("topLeftX").toInt(); int y = imageElement.attribute("topLeftY").toInt(); //loadImageAtFrame( path, position ); image = new QImage(path); if( !image->isNull() ) { boundaries = QRect( QPoint(x, y), image->size() ); } } void BitmapImage::modification() { } bool BitmapImage::isModified() { return false; } void BitmapImage::setModified(bool) { } void BitmapImage::paintImage(QPainter &painter) { painter.drawImage(topLeft(), *image); } void outputImage(QImage* image, QSize size, QMatrix myView) { } BitmapImage BitmapImage::copy() { return BitmapImage(myParent, boundaries, QImage(*image)); } BitmapImage BitmapImage::copy(QRect rectangle) { //QRect intersection = boundaries.intersected( rectangle ); QRect intersection2 = rectangle.translated( -topLeft() ); BitmapImage result = BitmapImage(myParent, rectangle, image->copy(intersection2)); return result; } void BitmapImage::paste(BitmapImage* bitmapImage) { paste(bitmapImage, QPainter::CompositionMode_SourceOver); } void BitmapImage::paste(BitmapImage* bitmapImage, QPainter::CompositionMode cm) { QImage* image2 = bitmapImage->image; QRect newBoundaries; if( image->width() == 0 || image->height() == 0 ) { newBoundaries = bitmapImage->boundaries; } else { newBoundaries = boundaries.united( bitmapImage->boundaries ); } extend( newBoundaries ); QPainter painter(image); painter.setCompositionMode(cm); painter.drawImage( bitmapImage->boundaries.topLeft() - boundaries.topLeft(), *image2); painter.end(); } void BitmapImage::add(BitmapImage* bitmapImage) { QImage* image2 = bitmapImage->image; QRect newBoundaries; if( image->width() == 0 || image->height() == 0 ) { newBoundaries = bitmapImage->boundaries; } else { newBoundaries = boundaries.united( bitmapImage->boundaries ); } extend( newBoundaries ); QPoint offset = bitmapImage->boundaries.topLeft() - boundaries.topLeft(); for(int y=0; yheight(); y++) { for(int x=0; xwidth(); x++) { /*QRgb p2 = image2->pixel(x,y); int r2 = qRed(p2); int g2 = qGreen(p2); int b2 = qBlue(p2); int a2 = qAlpha(p2); int r, g, b, a; r=0; g=0; b=0; a=0; for(int u=0; u<1; u++) { for(int v=0; v<1;v++) { if(boundaries.contains( bitmapImage->boundaries.topLeft() + QPoint(x+u,y+v) )) { QRgb p1 = image->pixel(offset.x()+x+u,offset.y()+y+v); int r1 = qRed(p1); int g1 = qGreen(p1); int b1 = qBlue(p1); int a1 = qAlpha(p1); r = r + r1; g = g + g1; b = b + b1; a = a + a1; } } } r = r/1; g = g/1; b = b/1; a = a/1; //r = 255; //g = 0; //b = 0; a = 255; QRgb p1 = image->pixel(offset.x()+x,offset.y()+y); int r1 = qRed(p1); int g1 = qGreen(p1); int b1 = qBlue(p1); int a1 = qAlpha(p1); r = (r1*(255-r2) + r2*r)/255; g = (g1*(255-g2) + g2*g)/255; b = (b1*(255-b2) + b2*b)/255; a = (a1*(255-a2) + a2*a)/255;*/ QRgb p1 = image->pixel(offset.x()+x,offset.y()+y); QRgb p2 = image2->pixel(x,y); int a1 = qAlpha(p1); int a2 = qAlpha(p2); int r1 = qRed(p1); int r2 = qRed(p2); // remember that the bitmap format is RGB32 Premultiplied int g1 = qGreen(p1); int g2 = qGreen(p2); int b1 = qBlue(p1); int b2 = qBlue(p2); /*qreal a1 = qAlpha(p1); qreal a2 = qAlpha(p2); qreal r1 = qRed(p1); qreal r2 = qRed(p2); // remember that the bitmap format is RGB32 Premultiplied qreal g1 = qGreen(p1); qreal g2 = qGreen(p2); qreal b1 = qBlue(p1); qreal b2 = qBlue(p2);*/ // unite int a = qMax(a1, a2); int r = qMax(r1, r2); int g = qMax(g1, g2); int b = qMax(b1, b2); // blend /*int a = a2 + a1*(255-a2)/255; int r = r2 + r1*(255-a2)/255; int g = g2 + g1*(255-a2)/255; int b = b2 + b1*(255-a2)/255;*/ // source /*int a = a2; int r = r2; int g = g2; int b = b2;*/ /*int a = qRound(a1+a2); int r = qRound((a1+a2)*((r1+0.)/a1+(r2+0.)/a2)/1); int g = qRound((a1+a2)*((g1+0.)/a1+(g2+0.)/a2)/1); int b = qRound((a1+a2)*((b1+0.)/a1+(b2+0.)/a2)/1);*/ // add /*int a = qMin(255, qRound(1.0*(a1+a2))); int r = qMin(255, qRound(0.5*(r1+r2))); int g = qMin(255, qRound(0.5*(g1+g2))); int b = qMin(255, qRound(0.5*(b1+b2)));*/ /*int a = qMin(255, qRound((1.0*a1+0.32*a2))); int r = qMin(255, qRound((1.0*r1+0.32*r2))); int g = qMin(255, qRound((1.0*g1+0.32*g2))); int b = qMin(255, qRound((1.0*b1+0.32*b2)));*/ QRgb mix = qRgba(r, g, b, a); /*qDebug() << "------"; qDebug() << r1 << g1 << b1 << a1; qDebug() << r2 << g2 << b2 << a2; qDebug() << r << g << b << a; qDebug() << qRed(mix) << qGreen(mix) << qBlue(mix) << qAlpha(mix);*/ //QRgb mix = qRgba(r2, g2, b2, a); if(a2 != 0) image->setPixel(offset.x()+x,offset.y()+y, mix); } } } void BitmapImage::moveTopLeft(QPoint point) { boundaries.moveTopLeft(point); } void BitmapImage::transform(QRect newBoundaries, bool smoothTransform) { if(boundaries != newBoundaries) { boundaries = newBoundaries; newBoundaries.moveTopLeft( QPoint(0,0) ); QImage* newImage = new QImage( boundaries.size(), QImage::Format_ARGB32_Premultiplied); //newImage->fill(QColor(255,255,255).rgb()); QPainter painter(newImage); painter.setRenderHint(QPainter::SmoothPixmapTransform, smoothTransform); painter.setCompositionMode(QPainter::CompositionMode_Source); painter.fillRect( newImage->rect(), QColor(0,0,0,0) ); painter.setCompositionMode(QPainter::CompositionMode_SourceOver); painter.drawImage(newBoundaries, *image ); painter.end(); //if(image != NULL) delete image; image = newImage; } } BitmapImage BitmapImage::transformed(QRect newBoundaries, bool smoothTransform) { BitmapImage transformedImage(NULL, newBoundaries, QColor(0,0,0,0)); QPainter painter(transformedImage.image); painter.setRenderHint(QPainter::SmoothPixmapTransform, smoothTransform); newBoundaries.moveTopLeft( QPoint(0,0) ); painter.drawImage(newBoundaries, *image ); painter.end(); return transformedImage; } void BitmapImage::extend(QPoint P) { if(boundaries.contains( P )) { // nothing } else { extend( QRect(P, QSize(0,0)) ); // can we set QSize(0,0) ? } } void BitmapImage::extend(QRect rectangle) { if(!extendable) return; if(rectangle.width() <= 0) rectangle.setWidth(1); if(rectangle.height() <= 0) rectangle.setHeight(1); if(boundaries.contains( rectangle )) { // nothing } else { QRect newBoundaries = boundaries.united(rectangle).normalized(); QImage* newImage = new QImage( newBoundaries.size(), QImage::Format_ARGB32_Premultiplied); newImage->fill(qRgba(0,0,0,0)); if(!newImage->isNull()) { QPainter painter(newImage); painter.drawImage(boundaries.topLeft() - newBoundaries.topLeft(), *image); painter.end(); } if(image != NULL) delete image; image = newImage; boundaries = newBoundaries; } } QRgb BitmapImage::pixel(int x, int y) { return pixel( QPoint(x,y) ); } QRgb BitmapImage::pixel(QPoint P) { QRgb result = qRgba(0,0,0,0); // black if( boundaries.contains( P ) ) result = image->pixel(P - topLeft()); return result; } void BitmapImage::setPixel(int x, int y, QRgb colour) { setPixel( QPoint(x,y), colour); } void BitmapImage::setPixel(QPoint P, QRgb colour) { extend( P ); if( boundaries.contains(P) ) image->setPixel(P-topLeft(), colour); //drawLine( QPointF(P), QPointF(P), QPen(QColor(colour)), QPainter::CompositionMode_SourceOver, false); } void BitmapImage::drawLine( QPointF P1, QPointF P2, QPen pen, QPainter::CompositionMode cm, bool antialiasing) { int width = pen.width(); extend( QRect(P1.toPoint(), P2.toPoint()).normalized().adjusted(-width,-width,width,width) ); if(image != NULL && !image->isNull() ) { QPainter painter(image); painter.setCompositionMode(cm); painter.setRenderHint(QPainter::Antialiasing, antialiasing); painter.setPen(pen); painter.drawLine( P1-topLeft(), P2-topLeft()); painter.end(); } } void BitmapImage::drawRect( QRectF rectangle, QPen pen, QBrush brush, QPainter::CompositionMode cm, bool antialiasing) { int width = pen.width(); extend( rectangle.adjusted(-width,-width,width,width).toRect() ); if(brush.style() == Qt::RadialGradientPattern) { QRadialGradient* gradient = (QRadialGradient*)brush.gradient(); gradient->setCenter( gradient->center() - topLeft() ); gradient->setFocalPoint( gradient->focalPoint() - topLeft() ); } if(image != NULL && !image->isNull() ) { QPainter painter(image); painter.setCompositionMode(cm); painter.setRenderHint(QPainter::Antialiasing, antialiasing); painter.setPen(pen); painter.setBrush(brush); //painter.fillRect( rectangle.translated(-topLeft()), brush ); //painter.fillRect( rectangle.translated(-topLeft()), QColor(255,0,0) ); painter.drawRect( rectangle.translated(-topLeft()) ); painter.end(); } } void BitmapImage::drawEllipse( QRectF rectangle, QPen pen, QBrush brush, QPainter::CompositionMode cm, bool antialiasing) { int width = pen.width(); extend( rectangle.adjusted(-width,-width,width,width).toRect() ); if(image != NULL && !image->isNull() ) { QPainter painter(image); painter.setCompositionMode(cm); painter.setRenderHint(QPainter::Antialiasing, antialiasing); painter.setPen(pen); painter.setBrush(brush); //if(brush == Qt::NoBrush) painter.drawEllipse( rectangle.translated(-topLeft()) ); painter.end(); } } void BitmapImage::drawPath( QPainterPath path, QPen pen, QBrush brush, QPainter::CompositionMode cm, bool antialiasing) { int width = pen.width(); extend( path.controlPointRect().adjusted(-width,-width,width,width).toRect() ); if(image != NULL && !image->isNull() ) { QPainter painter(image); painter.setCompositionMode(cm); painter.setRenderHint(QPainter::Antialiasing, antialiasing); painter.setPen(pen); painter.setBrush(brush); painter.setWorldMatrix(QMatrix().translate(-topLeft().x(), -topLeft().y())); painter.setMatrixEnabled(true); painter.drawPath( path ); painter.end(); } } void BitmapImage::blur(qreal radius) { if(image == NULL) return; int rad = qRound(0.5*radius); extend( boundaries.adjusted(-rad, -rad, rad, rad) ); Blur::fastbluralpha(*image, rad); } void BitmapImage::blur2(qreal radius) { if(image == NULL) return; int rad = qRound(0.5*radius); extend( boundaries.adjusted(-rad, -rad, rad, rad) ); Blur::expblur(*image, rad, 16, 7); } void BitmapImage::clear() { if(image != NULL) delete image; image = new QImage(0, 0, QImage::Format_ARGB32_Premultiplied); boundaries = QRect(0,0,0,0); } void BitmapImage::clear(QRect rectangle) { QRect clearRectangle = boundaries.intersected( rectangle ); clearRectangle.moveTopLeft( rectangle.topLeft() - topLeft() ); QPainter painter(image); painter.setCompositionMode(QPainter::CompositionMode_Clear); painter.fillRect( clearRectangle, QColor(0,0,0,0) ); painter.end(); } int BitmapImage::sqr(int n) { // square of a number return n*n; } int BitmapImage::rgbDistance(QRgb rgba1, QRgb rgba2) { int result = sqr(qRed(rgba1)-qRed(rgba2)) + sqr(qGreen(rgba1)-qGreen(rgba2)) + sqr(qBlue(rgba1)-qBlue(rgba2)) + sqr(qAlpha(rgba1)-qAlpha(rgba2)); return result; } void BitmapImage::floodFill(BitmapImage* targetImage, BitmapImage* fillImage, QPoint point, QRgb targetColour, QRgb replacementColour, int tolerance, bool extendFillImage) { QList queue; // queue all the pixels of the filled area (as they are found) int j, k; bool condition; BitmapImage* replaceImage; if(extendFillImage) { replaceImage = new BitmapImage(NULL, targetImage->boundaries.united(fillImage->boundaries), QColor(0,0,0,0)); } else { targetImage->extend(fillImage->boundaries); // not necessary - here just to prevent some bug when we draw outside the targetImage - to be fixed replaceImage = new BitmapImage(NULL, fillImage->boundaries, QColor(0,0,0,0)); replaceImage->extendable = false; } //QPainter painter1(replaceImage->image); //QPainter painter2(fillImage->image); //painter1.setPen( QColor(replacementColour) ); QPen myPen; myPen = QPen( QColor(replacementColour) , 1.0, Qt::SolidLine, Qt::RoundCap,Qt::RoundJoin); targetColour = targetImage->pixel(point.x(), point.y()); //if( rgbDistance(targetImage->pixel(point.x(), point.y()), targetColour) > tolerance ) return; queue.append( point ); // ----- flood fill // ----- from the standard flood fill algorithm // ----- http://en.wikipedia.org/wiki/Flood_fill j = -1; k = 1; for(int i=0; i< queue.size(); i++ ) { point = queue.at(i); if( replaceImage->pixel(point.x(), point.y()) != replacementColour && rgbDistance(targetImage->pixel(point.x(), point.y()), targetColour) < tolerance ) { j = -1; condition = (point.x() + j > targetImage->left()); if(!extendFillImage) condition = condition && (point.x() + j > replaceImage->left()); while( replaceImage->pixel(point.x()+j, point.y()) != replacementColour && rgbDistance(targetImage->pixel( point.x()+j, point.y() ), targetColour) < tolerance && condition) { j = j - 1; condition = (point.x() + j > targetImage->left()); if(!extendFillImage) condition = condition && (point.x() + j > replaceImage->left()); } k = 1; condition = ( point.x() + k < targetImage->right()-1); if(!extendFillImage) condition = condition && (point.x() + k < replaceImage->right()-1); while( replaceImage->pixel(point.x()+k, point.y()) != replacementColour && rgbDistance(targetImage->pixel( point.x()+k, point.y() ), targetColour) < tolerance && condition) { k = k + 1; condition = ( point.x() + k < targetImage->right()-1); if(!extendFillImage) condition = condition && (point.x() + k < replaceImage->right()-1); } //painter1.drawLine( point.x()+j, point.y(), point.x()+k+1, point.y() ); replaceImage->drawLine( QPointF(point.x()+j, point.y()), QPointF(point.x()+k, point.y()), myPen, QPainter::CompositionMode_SourceOver, false); //for(int l=0; l<=k-j+1 ; l++) { // replaceImage->setPixel( point.x()+j, point.y(), replacementColour ); //} for(int x = j+1; x < k; x++) { //replaceImage->setPixel( point.x()+x, point.y(), replacementColour); condition = point.y() - 1 > targetImage->top(); if(!extendFillImage) condition = condition && (point.y() - 1 > replaceImage->top()); if( condition && queue.size() < targetImage->height() * targetImage->width() ) { if( replaceImage->pixel(point.x()+x, point.y()-1) != replacementColour) { if(rgbDistance(targetImage->pixel( point.x()+x, point.y() - 1), targetColour) < tolerance) { queue.append( point + QPoint(x,-1) ); } else { replaceImage->setPixel( point.x()+x, point.y()-1, replacementColour); } } } condition = point.y() + 1 < targetImage->bottom(); if(!extendFillImage) condition = condition && (point.y() + 1 < replaceImage->bottom()); if( condition && queue.size() < targetImage->height() * targetImage->width() ) { if( replaceImage->pixel(point.x()+x, point.y()+1) != replacementColour) { if(rgbDistance(targetImage->pixel( point.x()+x, point.y() + 1), targetColour) < tolerance) { queue.append( point + QPoint(x, 1) ); } else { replaceImage->setPixel( point.x()+x, point.y()+1, replacementColour); } } } } } } //painter2.drawImage( QPoint(0,0), *replaceImage ); //bool memo = fillImage->extendable; //fillImage->extendable = false; fillImage->paste(replaceImage); //fillImage->extendable = memo; //replaceImage->fill(qRgba(0,0,0,0)); //painter1.end(); //painter2.end(); delete replaceImage; //update(); } pencil-0.4.4b/src/graphics/bitmap/blur.cpp0000644000175000017500000002201610716110271021153 0ustar khashayarkhashayar/* Pencil - Traditional Animation Software Copyright (C) 2005-2007 Patrick Corrieri & Pascal Naidon This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #include #include #include "blur.h" Blur::Blur() { // nothing } // Exponential blur, Jani Huhtanen, 2006 // static inline void blurinner(unsigned char *bptr, int &zR, int &zG, int &zB, int &zA, int alpha, int aprec, int zprec); static inline void blurrow( QImage & im, int line, int alpha, int aprec, int zprec); static inline void blurcol( QImage & im, int col, int alpha, int aprec, int zprec); /* * expblur(QImage &img, int radius) * * In-place blur of image 'img' with kernel * of approximate radius 'radius'. * * Blurs with two sided exponential impulse * response. * * aprec = precision of alpha parameter * in fixed-point format 0.aprec * * zprec = precision of state parameters * zR,zG,zB and zA in fp format 8.zprec */ void Blur::expblur( QImage &img, int radius, int aprec,int zprec ) { if(radius<1) return; /* Calculate the alpha such that 90% of the kernel is within the radius. (Kernel extends to infinity) */ int alpha = (int)((1<>aprec; zG += (alpha * ((G<>aprec; zB += (alpha * ((B<>aprec; zA += (alpha * ((A<>aprec; *bptr = zR>>zprec; *(bptr+1) = zG>>zprec; *(bptr+2) = zB>>zprec; *(bptr+3) = zA>>zprec; } static inline void blurrow( QImage & im, int line, int alpha, int aprec, int zprec) { int zR,zG,zB,zA; QRgb *ptr = (QRgb *)im.scanLine(line); zR = *((unsigned char *)ptr )<=0; index--) { blurinner((unsigned char *)&ptr[index],zR,zG,zB,zA,alpha,aprec,zprec); } } static inline void blurcol( QImage & im, int col, int alpha, int aprec, int zprec) { int zR,zG,zB,zA; QRgb *ptr = (QRgb *)im.bits(); ptr+=col; zR = *((unsigned char *)ptr )<=0; index-=im.width()) { blurinner((unsigned char *)&ptr[index],zR,zG,zB,zA,alpha,aprec,zprec); } } // Stack Blur Algorithm by Mario Klingemann void Blur::fastbluralpha(QImage &img, int radius) { if (radius < 1) { return; } QRgb *pix = (QRgb*)img.bits(); int w = img.width(); int h = img.height(); int wm = w-1; int hm = h-1; int wh = w*h; int div = radius+radius+1; int *r = new int[wh]; int *g = new int[wh]; int *b = new int[wh]; int *a = new int[wh]; int rsum, gsum, bsum, asum, x, y, i, yp, yi, yw; QRgb p; int *vmin = new int[qMax(w,h)]; int divsum = (div+1)>>1; divsum *= divsum; int *dv = new int[256*divsum]; for (i=0; i < 256*divsum; ++i) { dv[i] = (i/divsum); } yw = yi = 0; int **stack = new int*[div]; for(int i = 0; i < div; ++i) { stack[i] = new int[4]; } int stackpointer; int stackstart; int *sir; int rbs; int r1 = radius+1; int routsum, goutsum, boutsum, aoutsum; int rinsum, ginsum, binsum, ainsum; for (y = 0; y < h; ++y){ rinsum = ginsum = binsum = ainsum = routsum = goutsum = boutsum = aoutsum = rsum = gsum = bsum = asum = 0; for(i =- radius; i <= radius; ++i) { p = pix[yi+qMin(wm,qMax(i,0))]; sir = stack[i+radius]; sir[0] = qRed(p); sir[1] = qGreen(p); sir[2] = qBlue(p); sir[3] = qAlpha(p); rbs = r1-abs(i); rsum += sir[0]*rbs; gsum += sir[1]*rbs; bsum += sir[2]*rbs; asum += sir[3]*rbs; if (i > 0){ rinsum += sir[0]; ginsum += sir[1]; binsum += sir[2]; ainsum += sir[3]; } else { routsum += sir[0]; goutsum += sir[1]; boutsum += sir[2]; aoutsum += sir[3]; } } stackpointer = radius; for (x=0; x < w; ++x) { r[yi] = dv[rsum]; g[yi] = dv[gsum]; b[yi] = dv[bsum]; a[yi] = dv[asum]; rsum -= routsum; gsum -= goutsum; bsum -= boutsum; asum -= aoutsum; stackstart = stackpointer-radius+div; sir = stack[stackstart%div]; routsum -= sir[0]; goutsum -= sir[1]; boutsum -= sir[2]; aoutsum -= sir[3]; if (y == 0) { vmin[x] = qMin(x+radius+1,wm); } p = pix[yw+vmin[x]]; sir[0] = qRed(p); sir[1] = qGreen(p); sir[2] = qBlue(p); sir[3] = qAlpha(p); rinsum += sir[0]; ginsum += sir[1]; binsum += sir[2]; ainsum += sir[3]; rsum += rinsum; gsum += ginsum; bsum += binsum; asum += ainsum; stackpointer = (stackpointer+1)%div; sir = stack[(stackpointer)%div]; routsum += sir[0]; goutsum += sir[1]; boutsum += sir[2]; aoutsum += sir[3]; rinsum -= sir[0]; ginsum -= sir[1]; binsum -= sir[2]; ainsum -= sir[3]; ++yi; } yw += w; } for (x=0; x < w; ++x){ rinsum = ginsum = binsum = ainsum = routsum = goutsum = boutsum = aoutsum = rsum = gsum = bsum = asum = 0; yp =- radius * w; for(i=-radius; i <= radius; ++i) { yi=qMax(0,yp)+x; sir = stack[i+radius]; sir[0] = r[yi]; sir[1] = g[yi]; sir[2] = b[yi]; sir[3] = a[yi]; rbs = r1-abs(i); rsum += r[yi]*rbs; gsum += g[yi]*rbs; bsum += b[yi]*rbs; asum += a[yi]*rbs; if (i > 0) { rinsum += sir[0]; ginsum += sir[1]; binsum += sir[2]; ainsum += sir[3]; } else { routsum += sir[0]; goutsum += sir[1]; boutsum += sir[2]; aoutsum += sir[3]; } if (i < hm){ yp += w; } } yi = x; stackpointer = radius; for (y=0; y < h; ++y){ pix[yi] = qRgba(dv[rsum], dv[gsum], dv[bsum], dv[asum]); rsum -= routsum; gsum -= goutsum; bsum -= boutsum; asum -= aoutsum; stackstart = stackpointer-radius+div; sir = stack[stackstart%div]; routsum -= sir[0]; goutsum -= sir[1]; boutsum -= sir[2]; aoutsum -= sir[3]; if (x==0){ vmin[y] = qMin(y+r1,hm)*w; } p = x+vmin[y]; sir[0] = r[p]; sir[1] = g[p]; sir[2] = b[p]; sir[3] = a[p]; rinsum += sir[0]; ginsum += sir[1]; binsum += sir[2]; ainsum += sir[3]; rsum += rinsum; gsum += ginsum; bsum += binsum; asum += ainsum; stackpointer = (stackpointer+1)%div; sir = stack[stackpointer]; routsum += sir[0]; goutsum += sir[1]; boutsum += sir[2]; aoutsum += sir[3]; rinsum -= sir[0]; ginsum -= sir[1]; binsum -= sir[2]; ainsum -= sir[3]; yi += w; } } delete [] r; delete [] g; delete [] b; delete [] a; delete [] vmin; delete [] dv; } pencil-0.4.4b/src/graphics/bitmap/blur.h0000644000175000017500000000133110716110271020615 0ustar khashayarkhashayar/* Pencil - Traditional Animation Software Copyright (C) 2005-2007 Patrick Corrieri & Pascal Naidon This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #ifndef BLUR_H #define BLUR_H #include class Blur { public: Blur(); static void expblur(QImage &img, int radius, int aprec, int zprec); static void fastbluralpha(QImage &img, int radius); }; #endif pencil-0.4.4b/src/graphics/vector/0000755000175000017500000000000010757714675017557 5ustar khashayarkhashayarpencil-0.4.4b/src/graphics/vector/gradient.cpp0000644000175000017500000015615310716110271022044 0ustar khashayarkhashayar/* Pencil - Traditional Animation Software Copyright (C) 2005-2007 Patrick Corrieri & Pascal Naidon This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #include #include #include "gradient.h" #include "vectorimage.h" #include "bitmapimage.h" #include "bezierarea.h" #include "beziercurve.h" #include "vertexref.h" Gradient::Gradient() { // nothing } void Gradient::paint1(QPainter &painter, VectorImage* v, int i, int gradients) { QMatrix painterMatrix = painter.worldMatrix(); //qreal scale = qAbs(painterMatrix.m11()) + qAbs(painterMatrix.m12()); // quick overestimation of sqrt( m11*m22 - m12*m21 ) QColor colour = v->getColour(v->area[i].colourNumber); //bool buffer = false; //bool subBuffer = true; //QPainter painter2; QMatrix painter2Matrix; QImage* bufferImage; QRect rect; //QPainter painter3; QMatrix painter3Matrix; QImage* subBufferImage; QRect subRect; qreal gradientWidth = 0.0; for( int j=0; jarea[i].vertex.size(); j++) { qreal width = v->curve[ v->area[i].getVertexRef(j).curveNumber ].getFeather(); if( width > gradientWidth) gradientWidth = width; } QPainterPath path; VertexRef P1Ref, P2Ref; QPointF P1, P2, C1, C2; for( int j=1; jarea[i].vertex.size(); j++) { P1Ref = v->area[i].vertex[j-1]; P2Ref = v->area[i].vertex[j]; P1 = v->getVertex( P1Ref ); P2 = v->getVertex( P2Ref ); bool P1invisible = v->curve[ P1Ref.curveNumber ].isInvisible(); bool P2invisible = v->curve[ P2Ref.curveNumber ].isInvisible(); if( P1invisible || P2invisible ) { if(P1Ref.vertexNumber < P2Ref.vertexNumber ) { // the points follow the curve progression C1 = v->getC1( P2Ref ); C2 = v->getC2( P2Ref ); } else { C2 = v->getC1( P1Ref ); C1 = v->getC2( P1Ref ); } if( j==1 || !P1invisible) path.moveTo(P1); path.cubicTo(C1,C2,P2); } } painter.setBrush(Qt::NoBrush); qreal nsteps = gradientWidth; for(int incr=0; incr < nsteps; incr++) { QColor colour2 = colour; colour2.setAlphaF( (1.0*incr)/(2*nsteps) ); QPen pen = QPen(colour2); pen.setWidth( (gradientWidth*(nsteps-incr))/nsteps ); painter.setPen( pen ); painter.drawPath(path); } } void Gradient::paint2(QPainter &painter, VectorImage* v, int i, int gradients) { QMatrix painterMatrix = painter.worldMatrix(); qreal scale = qAbs(painterMatrix.m11()) + qAbs(painterMatrix.m12()); // quick overestimation of sqrt( m11*m22 - m12*m21 ) QColor colour = v->getColour(v->area[i].colourNumber); bool buffer = false; bool subBuffer = true; QPainter painter2; QMatrix painter2Matrix; QImage* bufferImage; QRect rect; QPainter painter3; QMatrix painter3Matrix; QImage* subBufferImage; QRect subRect; qreal gradientWidth = 0.0; for( int j=0; jarea[i].vertex.size(); j++) { qreal width = v->curve[ v->area[i].getVertexRef(j).curveNumber ].getFeather(); if( width > gradientWidth) gradientWidth = width; } QLinearGradient linearGrad(QPointF(0,0), QPointF(0,1)); QRadialGradient radialGrad(QPointF(0,0), gradientWidth, QPointF(0,0)); QColor colour2 = v->getColour(v->area[i].colourNumber); colour2.setAlpha(255); linearGrad.setColorAt(0, colour2 ); radialGrad.setColorAt(0, colour2 ); colour2.setAlpha(217); linearGrad.setColorAt(0.2, colour2 ); radialGrad.setColorAt(0.2, colour2 ); colour2.setAlpha(134); linearGrad.setColorAt(0.4, colour2 ); radialGrad.setColorAt(0.4, colour2 ); colour2.setAlpha(94); linearGrad.setColorAt(0.5, colour2 ); radialGrad.setColorAt(0.5, colour2 ); colour2.setAlpha(60); linearGrad.setColorAt(0.6, colour2 ); radialGrad.setColorAt(0.6, colour2 ); colour2.setAlpha(36); linearGrad.setColorAt(0.7, colour2 ); radialGrad.setColorAt(0.7, colour2 ); colour2.setAlpha(20); linearGrad.setColorAt(0.8, colour2 ); radialGrad.setColorAt(0.8, colour2 ); colour2.setAlpha(10); linearGrad.setColorAt(0.9, colour2 ); radialGrad.setColorAt(0.9, colour2 ); colour2.setAlpha(0); linearGrad.setColorAt(1, colour2 ); radialGrad.setColorAt(1, colour2 ); QBrush gradientBrush; painter.setRenderHint(QPainter::Antialiasing, false); VertexRef P1Ref, P2Ref; QPointF P1, P2, C1, C2; for( int j=1; j<=v->area[i].vertex.size(); j++) { P1Ref = v->area[i].getVertexRef(j-1); P2Ref = v->area[i].getVertexRef(j); P1 = v->getVertex( P1Ref ); P2 = v->getVertex( P2Ref ); bool P1invisible = v->curve[ P1Ref.curveNumber ].isInvisible(); bool P2invisible = v->curve[ P2Ref.curveNumber ].isInvisible(); qreal width1 = v->curve[ P1Ref.curveNumber ].getFeather(); qreal width2 = v->curve[ P2Ref.curveNumber ].getFeather(); gradientWidth = qMax(width1, width2); if(P1Ref.vertexNumber < P2Ref.vertexNumber ) { // the points follow the curve progression C1 = v->getC1( P2Ref ); C2 = v->getC2( P2Ref ); } else { C2 = v->getC1( P1Ref ); C1 = v->getC2( P1Ref ); } // ------------------------------------------------------------------------------------------------- if( (P1invisible || P2invisible) && gradientWidth != 0.0 ) { //if( QLineF(P1,P2).length() <= 0.5) if( (P1Ref.curveNumber != P2Ref.curveNumber) || (j==v->area[i].vertex.size()) ) { QPointF prevPoint, nextPoint, prevC1, prevC2, nextC1, nextC2; if(true) { // j > 1 && j < v->area[i].vertex.size()-1 if( P1Ref.curveNumber != v->area[i].getVertexRef(j-2).curveNumber) { // just to be sure VertexRef swap = P1Ref; P1Ref = P2Ref; P2Ref = swap; } int prevIndex = -1; do { prevIndex++; prevPoint = v->getVertex( v->area[i].getVertexRef(j-2-prevIndex) ); } while( prevPoint == P1); int nextIndex = -1; do { nextIndex++; nextPoint = v->getVertex( v->area[i].getVertexRef(j+1+nextIndex) ); } while( nextPoint == P2); //qDebug() << "indices =" << prevIndex << nextIndex; if(v->area[i].getVertexRef(j-2).vertexNumber < P1Ref.vertexNumber ) { // the points follow the curve progression prevC2 = v->getC2( v->area[i].getVertexRef(j-1-prevIndex) ); prevC1 = v->getC1( v->area[i].getVertexRef(j-1-prevIndex) ); if(prevC2 == P1) prevC2 = prevC1; } else { prevC2 = v->getC1( v->area[i].getVertexRef(j-2-prevIndex) ); prevC1 = v->getC2( v->area[i].getVertexRef(j-2-prevIndex) ); if(prevC2 == P1) prevC2 = prevC1; } if(P2Ref.vertexNumber < v->area[i].getVertexRef(j+1).vertexNumber ) { // the points follow the curve progression nextC1 = v->getC1( v->area[i].getVertexRef(j+1+nextIndex) ); nextC2 = v->getC2( v->area[i].getVertexRef(j+1+nextIndex) ); if(nextC1 == P2) nextC1 = nextC2; } else { nextC1 = v->getC2( v->area[i].getVertexRef(j+nextIndex) ); nextC2 = v->getC1( v->area[i].getVertexRef(j+nextIndex) ); if(nextC1 == P2) nextC1 = nextC2; } QLineF tangent1, tangent2, normal1, normal2; tangent1 = QLineF(prevC2, P1).unitVector(); QPointF tangentVec1 = (tangent1.p2() - tangent1.p1()); tangent2 = QLineF(P2, nextC1).unitVector(); QPointF tangentVec2 = (tangent2.p2() - tangent2.p1()); normal1 = tangent1.normalVector(); QPointF normalVec1 = (normal1.p2() - normal1.p1()); normal2 = tangent2.normalVector(); QPointF normalVec2 = (normal2.p2() - normal2.p1()); qreal t1 = 0.2; QPointF prevClosePoint = P1*(1-t1)*(1-t1)*(1-t1) + 3*prevC2*(1-t1)*(1-t1)*t1 + 3*prevC1*(1-t1)*t1*t1 + t1*t1*t1*prevPoint; if( v->area[i].path.contains( prevClosePoint + 0.01*normalVec1 ) ) { // we make sure the normal vector points outwards normalVec1 = -normalVec1; } QPointF nextClosePoint = P2*(1-t1)*(1-t1)*(1-t1) + 3*nextC1*(1-t1)*(1-t1)*t1 + 3*nextC2*(1-t1)*t1*t1 + t1*t1*t1*nextPoint; if( v->area[i].path.contains( nextClosePoint + 0.01*normalVec2 ) ) { // we make sure the normal vector points outwards normalVec2 = -normalVec2; } QPointF midPoint = 0.5*(P1+P2); //QLineF midLine = QLineF( midPoint, midPoint + vec1+vec2 ).unitVector(); //QPointF midVector = midLine.p2() - midLine.p1(); QPointF vec1, vec2, midVector; if(P1invisible && P2invisible) { vec1 = normalVec1; vec2 = normalVec2; midVector = normalVec1 + normalVec2; } if(P1invisible && !P2invisible) { vec1 = normalVec1; vec2 = -tangentVec2; midVector = -tangentVec1 - tangentVec2; } if(!P1invisible && P2invisible) { vec1 = tangentVec1; vec2 = normalVec2; midVector = tangentVec1 + tangentVec2; } //qDebug() << "----->" << midVector << tangentVec1 << prevC2 << P1 << prevPoint << nextPoint << (prevC2 == P1); QPainterPath extension; extension.moveTo( P1 ); extension.lineTo( P1 + gradientWidth*vec1); extension.lineTo( 0.5*(P1+P2) + 0.7*gradientWidth*(vec1+vec2) ); extension.lineTo( P2 + gradientWidth*vec2); extension.lineTo( P2); extension.closeSubpath(); radialGrad.setCenter(P1); radialGrad.setFocalPoint(P1); radialGrad.setRadius(gradientWidth); if(buffer) { // -- mask -- //int areaNumber = -1; //int areaNumber = getAreaNumber(P1 + 0.1*(-tangentVec1 + 0.1*normalVec1) ); //int areaNumber = getAreaNumber(prevClosePoint + 0.01*normalVec1 ); //if( areaNumber == -1 || areaNumber == i) areaNumber = getAreaNumber(nextClosePoint + 0.01*normalVec2 ); int areaNumber = v->getFirstAreaNumber(midPoint + 0.01*midVector); QPainterPath maskPath; if( areaNumber != -1 && areaNumber != i) { maskPath = painterMatrix.map( v->area[areaNumber].path ); } // ---------- subRect = painterMatrix.mapRect( extension.controlPointRect() ).toRect(); subRect = subRect.intersected( rect ); subBufferImage = new QImage(subRect.size(), QImage::Format_ARGB32_Premultiplied ); if(!subBufferImage->isNull()) { subBufferImage->fill(qRgba(0,0,0,0)); painter3.begin(subBufferImage); painter3.setCompositionMode(QPainter::CompositionMode_Source); painter3.setRenderHint(QPainter::Antialiasing, false); painter3Matrix = painterMatrix; painter3.setWorldMatrix( painter3Matrix.translate( -subRect.left()/scale, -subRect.top()/scale ) ); painter3.fillPath( extension, QBrush(radialGrad) ); //painter3.strokePath( extension, QPen(Qt::black) ); painter3.end(); for(int x=0; x < subRect.width(); x++ ) { for(int y=0; y < subRect.height(); y++ ) { int newX = subRect.left()-rect.left()+x; int newY = subRect.top()-rect.top()+y; if( newX >= 0 && newX < bufferImage->width() && newY >=0 && newY < bufferImage->height()) { if( qAlpha(subBufferImage->pixel(x,y)) > qAlpha(bufferImage->pixel(newX,newY)) ) { if(areaNumber == -1 || areaNumber == i) { bufferImage->setPixel( newX, newY, subBufferImage->pixel(x,y) ); } else { if( maskPath.contains(subRect.topLeft() + QPointF(x,y)) ) { bufferImage->setPixel( newX, newY, subBufferImage->pixel(x,y) ); } } } } else { //qDebug() << x << y << subRect << newX << newY << rect << bufferImage->width() << bufferImage->height(); } } } } delete subBufferImage; } else { //painter.fillPath( extension, QBrush(radialGrad) ); painter.strokePath( extension, QPen(Qt::gray) ); } /*qDebug() << "coucou---"; qDebug() << "coucou" << midPoint << midVector; painter.setBrush( QBrush(Qt::gray) ); painter.setPen( Qt::green ); painter.drawRect( QRectF( midPoint + 0.01*midVector , QSizeF(5/scale, 5/scale))); painter.drawLine( midPoint, midPoint + 0.01*midVector ); //painter.drawRect( QRectF( prevClosePoint + 0.01*normalVec1 , QSizeF(5/scale, 5/scale))); //painter.drawLine( prevClosePoint, prevClosePoint + 0.01*normalVec1 ); //painter.setPen( Qt::blue ); //painter.drawRect( QRectF( nextClosePoint + 0.01*normalVec2 , QSizeF(5/scale, 5/scale))); //painter.drawLine( nextClosePoint, nextClosePoint + 0.01*normalVec2 ); painter.setFont( QFont("Helvetica", 12) ); painter.setMatrixEnabled(false); //painter.drawText( painterMatrix.map(prevClosePoint + 0.01*normalVec1) + QPointF(5,5), QString::number(i)+">"+QString::number(getAreaNumber(prevClosePoint + 0.01*normalVec1)) ); //painter.drawText( painterMatrix.map(nextClosePoint + 0.01*normalVec2) + QPointF(5,5), QString::number(i)+">"+QString::number(getAreaNumber(nextClosePoint + 0.01*normalVec2)) ); //painter.drawText( painterMatrix.map(midPoint + 0.01*midVector) + QPointF(5,5), QString::number(i)+">"+QString::number(getAreaNumber(midPoint + 0.01*midVector)) ); painter.setMatrixEnabled(true);*/ } } // ------------------------------------------------------------------------------------------------- if( (P1Ref.curveNumber == P2Ref.curveNumber) && (j!=v->area[i].vertex.size()) && (P1 != P2)) { // therefore both P1 and P2 are invisible QLineF normal = QLineF(P1, P2).normalVector().unitVector(); QPointF normalVec = normal.p2() - normal.p1(); QPointF midPoint = 0.125*(P1 + 3*C1 + 3*C2 + P2); int sign = 1; if( v->area[i].path.contains( midPoint - 0.01*normalVec ) ) { // the path of the area (probably) has a negative orientation sign = -1; } // -- mask -- //int areaNumber = -1; int areaNumber = v->getFirstAreaNumber(midPoint - 0.01*sign*normalVec); QPainterPath maskPath; if( areaNumber != -1 ) { maskPath = painterMatrix.map( v->area[areaNumber].path ); } // ---------- int subdivisions = 1; if(gradients == 1) subdivisions = 4; for(int incr = 0; incr < subdivisions; incr++) { qreal t1 = (incr-0.0001/scale)/subdivisions; qreal t2 = (incr+1+0.0001/scale)/subdivisions; if(buffer) { t1 = (incr-0.03/scale)/subdivisions; t2 = (incr+1+0.03/scale)/subdivisions; } QPointF Q1 = P1*(1-t1)*(1-t1)*(1-t1) + 3*C1*(1-t1)*(1-t1)*t1 + 3*C2*(1-t1)*t1*t1 + t1*t1*t1*P2; QPointF Q2 = P1*(1-t2)*(1-t2)*(1-t2) + 3*C1*(1-t2)*(1-t2)*t2 + 3*C2*(1-t2)*t2*t2 + t2*t2*t2*P2; QPointF dQ1 = P1*(t1-1)*(1-t1) + C1*(1-t1)*(1-3*t1) + C2*t1*(2-3*t1) + P2*t1*t1; QPointF dQ2 = P1*(t2-1)*(1-t2) + C1*(1-t2)*(1-3*t2) + C2*t2*(2-3*t2) + P2*t2*t2; QLineF normal1 = QLineF(Q1, Q1+dQ1).normalVector().unitVector(); QPointF normalVec1 = sign*(normal1.p2() - normal1.p1()); QLineF normal2 = QLineF(Q2, Q2+dQ2).normalVector().unitVector(); QPointF normalVec2 = sign*(normal2.p2() - normal2.p1()); QLineF normal3 = QLineF(Q1, Q2).normalVector().unitVector(); QPointF normalVec3 = sign*(normal3.p2() - normal3.p1()); normal1 = QLineF(Q1, Q1 - gradientWidth*normalVec1); normal2 = QLineF(Q2, Q2 - gradientWidth*normalVec2); QPointF* intersectionPoint = new QPointF(); QPainterPath extension; extension.moveTo(Q1 + 4.0*normalVec1/subdivisions); if( normal1.intersect(normal2, intersectionPoint) == QLineF::BoundedIntersection) { extension.lineTo( *intersectionPoint ); } else { extension.lineTo(Q1 - gradientWidth*normalVec1); extension.lineTo(Q2 - gradientWidth*normalVec2); } extension.lineTo(Q2 + 4.0*normalVec2/subdivisions); //extension.cubicTo(C2+0.5*normalVec, C1+0.5*normalVec, prevPoint+0.5*normalVec); extension.closeSubpath(); linearGrad.setStart(Q1); linearGrad.setFinalStop(Q1 - gradientWidth*normalVec3); if(buffer) { if(subBuffer) { subRect = painterMatrix.mapRect( extension.controlPointRect() ).toRect().adjusted(-1,-1,1,1); subRect = subRect.intersected( rect ); subBufferImage = new QImage(subRect.size(), QImage::Format_ARGB32_Premultiplied ); if(!subBufferImage->isNull()) { subBufferImage->fill(qRgba(0,0,0,0)); painter3.begin(subBufferImage); painter3.setCompositionMode(QPainter::CompositionMode_Source); painter3.setRenderHint(QPainter::Antialiasing, false); painter3Matrix = painterMatrix; painter3.setWorldMatrix( painter3Matrix.translate( -subRect.left()/scale, -subRect.top()/scale ) ); painter3.fillPath( extension, QBrush(linearGrad) ); //painter3.strokePath( extension, QPen(Qt::gray) ); painter3.end(); for(int x=0; x < subRect.width(); x++ ) { for(int y=0; y < subRect.height(); y++ ) { int newX = subRect.left()-rect.left()+x; int newY = subRect.top()-rect.top()+y; if( newX >= 0 && newX < bufferImage->width() && newY >=0 && newY < bufferImage->height()) { if( qAlpha(subBufferImage->pixel(x,y)) > qAlpha(bufferImage->pixel(newX,newY)) ) { //bufferImage->setPixel( newX, newY, subBufferImage->pixel(x,y) ); if(areaNumber == -1) { bufferImage->setPixel( newX, newY, subBufferImage->pixel(x,y) ); } else { if( maskPath.contains(subRect.topLeft() + QPointF(x,y)) ) { bufferImage->setPixel( newX, newY, subBufferImage->pixel(x,y) ); } } } } else { //qDebug() << x << y << subRect << newX << newY << rect << bufferImage->width() << bufferImage->height(); } } } } delete subBufferImage; } else { painter2.fillPath( extension, QBrush(linearGrad)); } } else { //painter.strokePath( extension, QPen(Qt::gray) ); painter.fillPath( extension, QBrush(linearGrad) ); } painter.setPen( colour ); painter.drawLine( Q1, Q2 ); //painter.setPen( Qt::black ); //painter.setBrush( QBrush(linearGrad) ); //painter.strokePath( extension, QPen(Qt::black) ); //painter.setPen( Qt::blue ); //painter.drawRect( QRectF(midPoint - 0.01*sign*normalVec, QSizeF(5/scale, 5/scale))); } } //P1 = P2; //P1Ref.curveNumber = i; //P1Ref.vertexNumber = j; } } if(buffer && !bufferImage->isNull()) { painter2.end(); painter.setWorldMatrixEnabled(false); painter.drawImage( rect.topLeft(), *bufferImage); delete bufferImage; painter.setWorldMatrixEnabled(true); } } void Gradient::paint3(QPainter &painter, VectorImage* v, int i, int gradients) { QMatrix painterMatrix = painter.worldMatrix(); qreal scale = qAbs(painterMatrix.m11()) + qAbs(painterMatrix.m12()); // quick overestimation of sqrt( m11*m22 - m12*m21 ) QColor colour = v->getColour(v->area[i].colourNumber); painter.fillPath( v->area[i].path, colour ); BitmapImage* buffer = NULL; //BitmapImage* buffer = new BitmapImage(NULL); //bool subBuffer = true; //QPainter painter2; QMatrix painter2Matrix; QImage* bufferImage; QRect rect; //QPainter painter3; QMatrix painter3Matrix; QImage* subBufferImage; QRect subRect; qreal gradientWidth = 0.0; for( int j=0; jarea[i].vertex.size(); j++) { if( v->curve[ v->area[i].getVertexRef(j).curveNumber ].isInvisible() ) { qreal width = v->curve[ v->area[i].getVertexRef(j).curveNumber ].getFeather(); if( width > gradientWidth) gradientWidth = width; } } if(gradientWidth == 0.0) return; // ---- linear and radial gradient of exponentially decaying colour --- QLinearGradient linearGrad(QPointF(0,0), QPointF(0,1)); QRadialGradient radialGrad(QPointF(0,0), gradientWidth, QPointF(0,0)); QColor colour2 = v->getColour(v->area[i].colourNumber); colour2.setAlpha(qRound(255*colour.alphaF())); linearGrad.setColorAt(0, colour2 ); radialGrad.setColorAt(0, colour2 ); colour2.setAlpha(qRound(217*colour.alphaF())); linearGrad.setColorAt(0.2, colour2 ); radialGrad.setColorAt(0.2, colour2 ); colour2.setAlpha(qRound(134*colour.alphaF())); linearGrad.setColorAt(0.4, colour2 ); radialGrad.setColorAt(0.4, colour2 ); colour2.setAlpha(qRound(94*colour.alphaF())); linearGrad.setColorAt(0.5, colour2 ); radialGrad.setColorAt(0.5, colour2 ); colour2.setAlpha(qRound(60*colour.alphaF())); linearGrad.setColorAt(0.6, colour2 ); radialGrad.setColorAt(0.6, colour2 ); colour2.setAlpha(qRound(36*colour.alphaF())); linearGrad.setColorAt(0.7, colour2 ); radialGrad.setColorAt(0.7, colour2 ); colour2.setAlpha(qRound(20*colour.alphaF())); linearGrad.setColorAt(0.8, colour2 ); radialGrad.setColorAt(0.8, colour2 ); colour2.setAlpha(qRound(10*colour.alphaF())); linearGrad.setColorAt(0.9, colour2 ); radialGrad.setColorAt(0.9, colour2 ); colour2.setAlpha(0); linearGrad.setColorAt(1, colour2 ); radialGrad.setColorAt(1, colour2 ); QBrush gradientBrush; painter.setRenderHint(QPainter::Antialiasing, false); // ---- loop over all the points of the contour --- VertexRef P1Ref, P2Ref; QPointF P1, P2, C1, C2; for( int j=1; j<=v->area[i].vertex.size(); j++) { P1Ref = v->area[i].getVertexRef(j-1); P2Ref = v->area[i].getVertexRef(j); P1 = v->getVertex( P1Ref ); P2 = v->getVertex( P2Ref ); bool P1invisible = v->curve[ P1Ref.curveNumber ].isInvisible(); bool P2invisible = v->curve[ P2Ref.curveNumber ].isInvisible(); qreal width1 = v->curve[ P1Ref.curveNumber ].getFeather(); qreal width2 = v->curve[ P2Ref.curveNumber ].getFeather(); gradientWidth = qMax(width1, width2); if(P1Ref.vertexNumber < P2Ref.vertexNumber ) { // the points follow the curve progression C1 = v->getC1( P2Ref ); C2 = v->getC2( P2Ref ); } else { C2 = v->getC1( P1Ref ); C1 = v->getC2( P1Ref ); } // -------------------------- one of the two points is invisible ------------------------------------ if( (P1invisible || P2invisible) && gradientWidth != 0.0 ) { //if( QLineF(P1,P2).length() <= 0.5) // ----------------------- junction between two curves ("angular point") ----------------------------- if( (P1Ref.curveNumber != P2Ref.curveNumber) || (j==v->area[i].vertex.size()) ) { QPointF prevPoint, nextPoint, prevC1, prevC2, nextC1, nextC2; if(true) { // j > 1 && j < v->area[i].vertex.size()-1 if( P1Ref.curveNumber != v->area[i].getVertexRef(j-2).curveNumber) { // just to be sure VertexRef swap = P1Ref; P1Ref = P2Ref; P2Ref = swap; } int prevIndex = -1; do { prevIndex++; prevPoint = v->getVertex( v->area[i].getVertexRef(j-2-prevIndex) ); } while( prevPoint == P1); int nextIndex = -1; do { nextIndex++; nextPoint = v->getVertex( v->area[i].getVertexRef(j+1+nextIndex) ); } while( nextPoint == P2); //qDebug() << "indices =" << prevIndex << nextIndex; if(v->area[i].getVertexRef(j-2).vertexNumber < P1Ref.vertexNumber ) { // the points follow the curve progression prevC2 = v->getC2( v->area[i].getVertexRef(j-1-prevIndex) ); prevC1 = v->getC1( v->area[i].getVertexRef(j-1-prevIndex) ); if(prevC2 == P1) prevC2 = prevC1; } else { prevC2 = v->getC1( v->area[i].getVertexRef(j-2-prevIndex) ); prevC1 = v->getC2( v->area[i].getVertexRef(j-2-prevIndex) ); if(prevC2 == P1) prevC2 = prevC1; } if(P2Ref.vertexNumber < v->area[i].getVertexRef(j+1).vertexNumber ) { // the points follow the curve progression nextC1 = v->getC1( v->area[i].getVertexRef(j+1+nextIndex) ); nextC2 = v->getC2( v->area[i].getVertexRef(j+1+nextIndex) ); if(nextC1 == P2) nextC1 = nextC2; } else { nextC1 = v->getC2( v->area[i].getVertexRef(j+nextIndex) ); nextC2 = v->getC1( v->area[i].getVertexRef(j+nextIndex) ); if(nextC1 == P2) nextC1 = nextC2; } QLineF tangent1, tangent2, normal1, normal2; tangent1 = QLineF(prevC2, P1).unitVector(); QPointF tangentVec1 = (tangent1.p2() - tangent1.p1()); tangent2 = QLineF(P2, nextC1).unitVector(); QPointF tangentVec2 = (tangent2.p2() - tangent2.p1()); normal1 = tangent1.normalVector(); QPointF normalVec1 = (normal1.p2() - normal1.p1()); normal2 = tangent2.normalVector(); QPointF normalVec2 = (normal2.p2() - normal2.p1()); qreal t1 = 0.2; QPointF prevClosePoint = P1*(1-t1)*(1-t1)*(1-t1) + 3*prevC2*(1-t1)*(1-t1)*t1 + 3*prevC1*(1-t1)*t1*t1 + t1*t1*t1*prevPoint; if( v->area[i].path.contains( prevClosePoint + 0.01*normalVec1 ) ) { // we make sure the normal vector points outwards normalVec1 = -normalVec1; } QPointF nextClosePoint = P2*(1-t1)*(1-t1)*(1-t1) + 3*nextC1*(1-t1)*(1-t1)*t1 + 3*nextC2*(1-t1)*t1*t1 + t1*t1*t1*nextPoint; if( v->area[i].path.contains( nextClosePoint + 0.01*normalVec2 ) ) { // we make sure the normal vector points outwards normalVec2 = -normalVec2; } QPointF midPoint = 0.5*(P1+P2); //QLineF midLine = QLineF( midPoint, midPoint + vec1+vec2 ).unitVector(); //QPointF midVector = midLine.p2() - midLine.p1(); QPointF vec1, vec2, midVector; if(P1invisible && P2invisible) { vec1 = normalVec1; vec2 = normalVec2; midVector = normalVec1 + normalVec2; } if(P1invisible && !P2invisible) { vec1 = normalVec1; vec2 = -tangentVec2; midVector = -tangentVec1 - tangentVec2; } if(!P1invisible && P2invisible) { vec1 = tangentVec1; vec2 = normalVec2; midVector = tangentVec1 + tangentVec2; } //qDebug() << "----->" << midVector << tangentVec1 << prevC2 << P1 << prevPoint << nextPoint << (prevC2 == P1); QPainterPath extension; extension.moveTo( P1 ); extension.lineTo( P1 + gradientWidth*vec1); extension.lineTo( 0.5*(P1+P2) + 0.7*gradientWidth*(vec1+vec2) ); extension.lineTo( P2 + gradientWidth*vec2); extension.lineTo( P2); extension.closeSubpath(); radialGrad.setCenter(P1); radialGrad.setFocalPoint(P1); radialGrad.setRadius(gradientWidth); int areaNumber = v->getFirstAreaNumber(midPoint + 1.01*(vec1+vec2) ); if(areaNumber != -1) { painter.setClipping(true); painter.setClipPath( v->area[areaNumber].path ); //painter.fillPath( extension, QBrush(radialGrad) ); //painter.setClipPath( v->area[i].path, Qt::UniteClip ); painter.fillPath( extension, QBrush(radialGrad) ); painter.setClipping(false); //if(niceGradients) painter.strokePath( extension, QPen(Qt::gray) ); } //painter.strokePath( extension, QPen(Qt::gray) ); //if(areaNumber!=-1) painter.fillRect( QRectF(midPoint + 1.01*(vec1+vec2), QSizeF(0.2,0.2) ), Qt::red ); //if(areaNumber==-1) painter.fillRect( QRectF(midPoint + 1.01*(vec1+vec2), QSizeF(0.2,0.2) ), Qt::blue ); } } // -------------------- the two points are separated and on the same curve ------------------------------ if( (P1Ref.curveNumber == P2Ref.curveNumber) && (j!=v->area[i].vertex.size()) && (P1 != P2)) { // therefore both P1 and P2 are invisible QLineF normal = QLineF(P1, P2).normalVector().unitVector(); QPointF normalVec = normal.p2() - normal.p1(); QPointF midPoint = 0.125*(P1 + 3*C1 + 3*C2 + P2); int sign = 1; if( v->area[i].path.contains( midPoint - 0.01*normalVec ) ) { // the path of the area (probably) has a negative orientation sign = -1; } //sign = -sign; // -- mask -- //int areaNumber = -1; int areaNumber = v->getFirstAreaNumber(midPoint - 0.01*sign*normalVec); //QPainterPath maskPath; /*if( areaNumber != -1 ) { //maskPath = painterMatrix.map( v->area[areaNumber].path ); painter.setClipping(true); painter.setClipPath( v->area[areaNumber].path ); } else { painter.setClipping(false); }*/ //painter.setClipping(true); //painter.setClipPath( v->area[i].path ); // ---------- int subdivisions = 1; if(gradients == 1) subdivisions = 4; for(int incr = 0; incr < subdivisions; incr++) { qreal t1 = (incr-0.0001/scale)/subdivisions; qreal t2 = (incr+1+0.0001/scale)/subdivisions; //if(buffer) { // t1 = (incr-0.03/scale)/subdivisions; // t2 = (incr+1+0.03/scale)/subdivisions; //} QPointF Q1 = P1*(1-t1)*(1-t1)*(1-t1) + 3*C1*(1-t1)*(1-t1)*t1 + 3*C2*(1-t1)*t1*t1 + t1*t1*t1*P2; QPointF Q2 = P1*(1-t2)*(1-t2)*(1-t2) + 3*C1*(1-t2)*(1-t2)*t2 + 3*C2*(1-t2)*t2*t2 + t2*t2*t2*P2; QPointF dQ1 = P1*(t1-1)*(1-t1) + C1*(1-t1)*(1-3*t1) + C2*t1*(2-3*t1) + P2*t1*t1; QPointF dQ2 = P1*(t2-1)*(1-t2) + C1*(1-t2)*(1-3*t2) + C2*t2*(2-3*t2) + P2*t2*t2; QLineF normal1 = QLineF(Q1, Q1+dQ1).normalVector().unitVector(); QPointF normalVec1 = sign*(normal1.p2() - normal1.p1()); QLineF normal2 = QLineF(Q2, Q2+dQ2).normalVector().unitVector(); QPointF normalVec2 = sign*(normal2.p2() - normal2.p1()); QLineF normal3 = QLineF(Q1, Q2).normalVector().unitVector(); QPointF normalVec3 = sign*(normal3.p2() - normal3.p1()); normal1 = QLineF(Q1, Q1 - gradientWidth*normalVec1); normal2 = QLineF(Q2, Q2 - gradientWidth*normalVec2); QPointF* intersectionPoint = new QPointF(); QPainterPath extension; extension.moveTo(Q1 + 4.0*normalVec1/subdivisions); if( normal1.intersect(normal2, intersectionPoint) == QLineF::BoundedIntersection) { extension.lineTo( *intersectionPoint ); } else { extension.lineTo(Q1 - gradientWidth*normalVec1); extension.lineTo(Q2 - gradientWidth*normalVec2); } extension.lineTo(Q2 + 4.0*normalVec2/subdivisions); //extension.cubicTo(C2+0.5*normalVec, C1+0.5*normalVec, prevPoint+0.5*normalVec); extension.closeSubpath(); linearGrad.setStart(Q1); linearGrad.setFinalStop(Q1 - gradientWidth*normalVec3); if(buffer) { /*if(subBuffer) { subRect = painterMatrix.mapRect( extension.controlPointRect() ).toRect().adjusted(-1,-1,1,1); subRect = subRect.intersected( rect ); subBufferImage = new QImage(subRect.size(), QImage::Format_ARGB32_Premultiplied ); if(!subBufferImage->isNull()) { subBufferImage->fill(qRgba(0,0,0,0)); painter3.begin(subBufferImage); painter3.setCompositionMode(QPainter::CompositionMode_Source); painter3.setRenderHint(QPainter::Antialiasing, false); painter3Matrix = painterMatrix; painter3.setWorldMatrix( painter3Matrix.translate( -subRect.left()/scale, -subRect.top()/scale ) ); painter3.fillPath( extension, QBrush(linearGrad) ); //painter3.strokePath( extension, QPen(Qt::gray) ); painter3.end(); for(int x=0; x < subRect.width(); x++ ) { for(int y=0; y < subRect.height(); y++ ) { int newX = subRect.left()-rect.left()+x; int newY = subRect.top()-rect.top()+y; if( newX >= 0 && newX < bufferImage->width() && newY >=0 && newY < bufferImage->height()) { if( qAlpha(subBufferImage->pixel(x,y)) > qAlpha(bufferImage->pixel(newX,newY)) ) { //bufferImage->setPixel( newX, newY, subBufferImage->pixel(x,y) ); if(areaNumber == -1) { bufferImage->setPixel( newX, newY, subBufferImage->pixel(x,y) ); } else { if( maskPath.contains(subRect.topLeft() + QPointF(x,y)) ) { bufferImage->setPixel( newX, newY, subBufferImage->pixel(x,y) ); } } } } else { //qDebug() << x << y << subRect << newX << newY << rect << bufferImage->width() << bufferImage->height(); } } } } delete subBufferImage; } else { painter2.fillPath( extension, QBrush(linearGrad)); }*/ } else { if( areaNumber != -1 ) { painter.setClipping(true); painter.setClipPath( v->area[areaNumber].path ); painter.fillPath( extension, QBrush(linearGrad) ); painter.setClipPath( v->area[i].path ); painter.fillPath( extension, QBrush(linearGrad) ); painter.setClipping(false); } else { //painter.fillPath( extension, QBrush(linearGrad) ); } //if(niceGradients) painter.strokePath( extension, QPen(Qt::gray) ); } painter.setPen( colour ); painter.drawLine( Q1, Q2 ); //painter.setPen( Qt::black ); //painter.setBrush( QBrush(linearGrad) ); //painter.strokePath( extension, QPen(Qt::black) ); //painter.setPen( Qt::blue ); //painter.drawRect( QRectF(midPoint - 0.01*sign*normalVec, QSizeF(5/scale, 5/scale))); } } //P1 = P2; //P1Ref.curveNumber = i; //P1Ref.vertexNumber = j; } } /*if(buffer && !bufferImage->isNull()) { painter2.end(); painter.setWorldMatrixEnabled(false); painter.drawImage( rect.topLeft(), *bufferImage); delete bufferImage; painter.setWorldMatrixEnabled(true); }*/ } void Gradient::paint4(QPainter &painter, VectorImage* v, int i, int gradients) { //QMatrix painterMatrix = painter.worldMatrix(); //qreal scale = qAbs(painterMatrix.m11()) + qAbs(painterMatrix.m12()); // quick overestimation of sqrt( m11*m22 - m12*m21 ) QColor colour = v->getColour(v->area[i].colourNumber); BitmapImage* buffer = new BitmapImage(NULL); //BitmapImage* buffer = NULL; painter.fillPath( v->area[i].path, colour ); // ---- find the gradient width qreal gradientWidth = 0.0; for( int j=0; jarea[i].vertex.size(); j++) { if( v->curve[ v->area[i].getVertexRef(j).curveNumber ].isInvisible() ) { qreal width = v->curve[ v->area[i].getVertexRef(j).curveNumber ].getFeather(); if( width > gradientWidth) gradientWidth = width; } } if(gradientWidth == 0.0) { return; } // ---- find the area just below that area VertexRef P1Ref, P2Ref; QPointF midPoint; bool pointInside = false; int j=1; while(!pointInside && j<=v->area[i].vertex.size()) { P1Ref = v->area[i].getVertexRef(0); P2Ref = v->area[i].getVertexRef(j); midPoint = 0.5*( v->getVertex( P1Ref ) + v->getVertex( P2Ref ) ); pointInside = v->area[i].path.contains( midPoint ); j++; } if(!pointInside) return; int areaNumber = v->getFirstAreaNumber(midPoint); if(areaNumber != -1) { painter.setClipping(true); painter.setClipPath( v->area[areaNumber].path ); } else { //painter.setClipping(false); return; } /*qreal gradientWidth = 0.0; for( int j=0; jarea[i].vertex.size(); j++) { if( v->curve[ v->area[i].getVertexRef(j).curveNumber ].isInvisible() ) { qreal width = v->curve[ v->area[i].getVertexRef(j).curveNumber ].getFeather(); if( width > gradientWidth) gradientWidth = width; } } if(gradientWidth == 0.0) return;*/ // ---- radial gradient with gaussian decaying --- QRadialGradient radialGrad(QPointF(0,0), gradientWidth, QPointF(0,0)); QColor colour2 = v->getColour(v->area[i].colourNumber); //colour2 = Qt::black; colour2.setAlpha(255); radialGrad.setColorAt(0, colour2 ); colour2.setAlpha(217); radialGrad.setColorAt(0.2, colour2 ); colour2.setAlpha(134); radialGrad.setColorAt(0.4, colour2 ); colour2.setAlpha(94); radialGrad.setColorAt(0.5, colour2 ); colour2.setAlpha(60); radialGrad.setColorAt(0.6, colour2 ); colour2.setAlpha(36); radialGrad.setColorAt(0.7, colour2 ); colour2.setAlpha(20); radialGrad.setColorAt(0.8, colour2 ); colour2.setAlpha(10); radialGrad.setColorAt(0.9, colour2 ); colour2.setAlpha(0); radialGrad.setColorAt(1, colour2 ); /*colour2.setAlpha(255); radialGrad.setColorAt(0, colour2 ); colour2.setAlpha(212); radialGrad.setColorAt(0.2, colour2 ); colour2.setAlpha(142); radialGrad.setColorAt(0.4, colour2 ); colour2.setAlpha(107); radialGrad.setColorAt(0.5, colour2 ); colour2.setAlpha(77); radialGrad.setColorAt(0.6, colour2 ); colour2.setAlpha(32); radialGrad.setColorAt(0.7, colour2 ); colour2.setAlpha(16); radialGrad.setColorAt(0.8, colour2 ); colour2.setAlpha(3); radialGrad.setColorAt(0.9, colour2 ); colour2.setAlpha(0); radialGrad.setColorAt(1, colour2 );*/ /*colour2.setAlpha(255); radialGrad.setColorAt(0, colour2 ); colour2.setAlpha(204); radialGrad.setColorAt(0.2, colour2 ); colour2.setAlpha(153); radialGrad.setColorAt(0.4, colour2 ); colour2.setAlpha(127); radialGrad.setColorAt(0.5, colour2 ); colour2.setAlpha(102); radialGrad.setColorAt(0.6, colour2 ); colour2.setAlpha(76); radialGrad.setColorAt(0.7, colour2 ); colour2.setAlpha(51); radialGrad.setColorAt(0.8, colour2 ); colour2.setAlpha(25); radialGrad.setColorAt(0.9, colour2 ); colour2.setAlpha(0); radialGrad.setColorAt(1, colour2 );*/ // gradient for 1/2 spacings blended /*colour2.setAlpha(255); radialGrad.setColorAt(0, colour2 ); colour2.setAlpha(234); radialGrad.setColorAt(0.1, colour2 ); colour2.setAlpha(190); radialGrad.setColorAt(0.2, colour2 ); colour2.setAlpha(92); radialGrad.setColorAt(0.4, colour2 ); colour2.setAlpha(58); radialGrad.setColorAt(0.5, colour2 ); colour2.setAlpha(36); radialGrad.setColorAt(0.6, colour2 ); colour2.setAlpha(23); radialGrad.setColorAt(0.7, colour2 ); colour2.setAlpha(14); radialGrad.setColorAt(0.8, colour2 ); colour2.setAlpha(7); radialGrad.setColorAt(0.9, colour2 ); colour2.setAlpha(0); radialGrad.setColorAt(1, colour2 );*/ // gradient for 1/3 spacings blended /*colour2.setAlpha(255); radialGrad.setColorAt(0, colour2 ); colour2.setAlpha(213); radialGrad.setColorAt(0.1, colour2 ); colour2.setAlpha(168); radialGrad.setColorAt(0.2, colour2 ); colour2.setAlpha(75); radialGrad.setColorAt(0.4, colour2 ); colour2.setAlpha(44); radialGrad.setColorAt(0.5, colour2 ); colour2.setAlpha(25); radialGrad.setColorAt(0.6, colour2 ); colour2.setAlpha(14); radialGrad.setColorAt(0.7, colour2 ); colour2.setAlpha(8); radialGrad.setColorAt(0.8, colour2 ); colour2.setAlpha(3); radialGrad.setColorAt(0.9, colour2 ); colour2.setAlpha(0); radialGrad.setColorAt(1, colour2 );*/ // gradient for 1/2 spacings added /*colour2.setAlpha(147); radialGrad.setColorAt(0, colour2 ); colour2.setAlpha(142); radialGrad.setColorAt(0.1, colour2 ); colour2.setAlpha(125); radialGrad.setColorAt(0.2, colour2 ); colour2.setAlpha(76); radialGrad.setColorAt(0.4, colour2 ); colour2.setAlpha(52); radialGrad.setColorAt(0.5, colour2 ); colour2.setAlpha(34); radialGrad.setColorAt(0.6, colour2 ); colour2.setAlpha(20); radialGrad.setColorAt(0.7, colour2 ); colour2.setAlpha(11); radialGrad.setColorAt(0.8, colour2 ); colour2.setAlpha(5); radialGrad.setColorAt(0.9, colour2 ); colour2.setAlpha(0); radialGrad.setColorAt(1, colour2 );*/ painter.setRenderHint(QPainter::Antialiasing, false); // ---- loop over all the points of the contour --- //VertexRef P1Ref, P2Ref; QPointF P1, P2, C1, C2; QPointF lastPoint; bool lastPointExists = false; for( int j=1; j<=v->area[i].vertex.size(); j++) { P1Ref = v->area[i].getVertexRef(j-1); P2Ref = v->area[i].getVertexRef(j); P1 = v->getVertex( P1Ref ); P2 = v->getVertex( P2Ref ); bool P1invisible = v->curve[ P1Ref.curveNumber ].isInvisible(); bool P2invisible = v->curve[ P2Ref.curveNumber ].isInvisible(); qreal width1 = v->curve[ P1Ref.curveNumber ].getFeather(); qreal width2 = v->curve[ P2Ref.curveNumber ].getFeather(); gradientWidth = qMax(width1, width2); // ------------------------------------------------------------------------------------------------- //if( (P1invisible || P2invisible) && gradientWidth != 0.0 ) { //if( QLineF(P1,P2).length() <= 0.5) if(gradientWidth != 0.0) { if(!lastPointExists) { lastPoint = P1; } QPointF midPoint; if(P1Ref.curveNumber == P1Ref.curveNumber) { if(P1Ref.vertexNumber < P2Ref.vertexNumber ) { // the points follow the curve progression C1 = v->getC1( P2Ref ); C2 = v->getC2( P2Ref ); } else { C2 = v->getC1( P1Ref ); C1 = v->getC2( P1Ref ); } midPoint = 0.125*(P1 + 3*C1 + 3*C2 + P2); } else { midPoint = 0.5*(P1+P2); } /*QLineF normal = QLineF(P1, P2).normalVector().unitVector(); QPointF normalVec = normal.p2() - normal.p1(); if( v->area[i].path.contains( midPoint + 0.1*normalVec ) ) { normalVec = -normalVec; } int areaNumber = v->getAreaNumber(midPoint + 0.1*normalVec); if(areaNumber != -1 && areaNumber != i) { painter.setClipping(true); painter.setClipPath( v->area[areaNumber].path ); } else { painter.setClipping(false); }*/ qreal distance = 4.0*QLineF(P2, lastPoint).length(); int steps = qRound( distance /gradientWidth ); for(int i=0; i0 || !lastPointExists) { if(true) { //QPointF thePoint = lastPoint + (i)*(gradientWidth)*(P2 -lastPoint)/distance; qreal t1 = i*gradientWidth/distance; QPointF thePoint = P1*(1-t1)*(1-t1)*(1-t1) + 3*C1*(1-t1)*(1-t1)*t1 + 3*C2*(1-t1)*t1*t1 + t1*t1*t1*P2; //QPointF thePoint2 = thePoint - 0.00*gradientWidth*normalVec; QPointF thePoint2 = thePoint; radialGrad.setCenter( thePoint2 ); radialGrad.setFocalPoint( thePoint2 ); radialGrad.setRadius( gradientWidth ); QRectF rectangle(thePoint2.x()-gradientWidth, thePoint2.y()-gradientWidth, 2*gradientWidth, 2*gradientWidth); if(buffer) { BitmapImage* subBuffer = new BitmapImage(NULL); subBuffer->drawRect( rectangle, Qt::NoPen, radialGrad, QPainter::CompositionMode_SourceOver, false); buffer->add(subBuffer); delete subBuffer; } else { painter.fillRect( rectangle, radialGrad ); } //painter.setPen( Qt::black ); //painter.drawEllipse( rectangle ); //painter.setPen( Qt::red ); //painter.drawRect( QRectF(thePoint, QSizeF(2,2)) ); if(i==steps-1) lastPoint = thePoint; } } if(!lastPointExists) { lastPointExists = true; } } else { //lastPointExists = false; } } if(buffer) { if(buffer->image) painter.drawImage(buffer->topLeft(), *(buffer->image)); delete buffer; } } void Gradient::paint5(QPainter &painter, VectorImage* v, int i, int gradients) { //BitmapImage* buffer = new BitmapImage(NULL); //BitmapImage* buffer = NULL; QColor colour = v->getColour(v->area[i].colourNumber); // ---- find the gradient width qreal gradientWidth = 0.0; for( int j=0; jarea[i].vertex.size(); j++) { if( v->curve[ v->area[i].getVertexRef(j).curveNumber ].isInvisible() ) { qreal width = v->curve[ v->area[i].getVertexRef(j).curveNumber ].getFeather(); if( width > gradientWidth) gradientWidth = width; } } if(gradientWidth == 0.0) { painter.fillPath( v->area[i].path, colour ); return; } gradientWidth = gradientWidth * sqrt(painter.worldMatrix().det()); // ---- find the area just below that area VertexRef P1Ref, P2Ref; QPointF midPoint; bool pointInside = false; int j=1; while(!pointInside && j<=v->area[i].vertex.size()) { P1Ref = v->area[i].getVertexRef(0); P2Ref = v->area[i].getVertexRef(j); midPoint = 0.5*( v->getVertex( P1Ref ) + v->getVertex( P2Ref ) ); pointInside = v->area[i].path.contains( midPoint ); j++; } if(!pointInside) return; int areaNumber = v->getFirstAreaNumber(midPoint); if(areaNumber != -1) { painter.setClipping(true); painter.setClipPath( v->area[areaNumber].path ); } else { //painter.setClipping(false); return; } // ---- blur the area QMatrix painterMatrix = painter.worldMatrix(); QPainterPath path = painterMatrix.map( v->area[i].path ); BitmapImage* buffer = new BitmapImage(NULL); //buffer->drawPath( path, Qt::NoPen, colour, QPainter::CompositionMode_SourceOver, false); buffer->drawPath( path, QPen(colour, gradientWidth), colour, QPainter::CompositionMode_SourceOver, false); if(gradients == 3) buffer->blur2(0.9*gradientWidth); if(gradients == 4) buffer->blur(0.9*gradientWidth); /*QPointF P1, P2, C1, C2; int localGradientWidth; for( int j=1; jarea[i].vertex.size(); j++) { P1Ref = painterMatrix.map( v->area[i].getVertexRef(j-1) ); P2Ref = painterMatrix.map( v->area[i].getVertexRef(j) ); P1 = v->getVertex( P1Ref ); P2 = v->getVertex( P2Ref ); bool P1invisible = v->curve[ P1Ref.curveNumber ].isInvisible(); bool P2invisible = v->curve[ P2Ref.curveNumber ].isInvisible(); qreal width1 = v->curve[ P1Ref.curveNumber ].getFeather(); qreal width2 = v->curve[ P2Ref.curveNumber ].getFeather(); localGradientWidth = qMax(width1, width2); if(localGradientWidth == 0.0) localGradientWidth = gradientWidth; // ------------------------------------------------------------------------------------------------- if( (P1invisible || P2invisible) && gradientWidth != 0.0 ) { //if( QLineF(P1,P2).length() <= 0.5) //if(localGradientWidth != 0.0) { //if(!lastPointExists) { // lastPoint = P1; // lastPointExists = true; //} if(P1Ref.curveNumber == P1Ref.curveNumber) { if(P1Ref.vertexNumber < P2Ref.vertexNumber ) { // the points follow the curve progression C1 = v->getC1( P2Ref ); C2 = v->getC2( P2Ref ); } else { C2 = v->getC1( P1Ref ); C1 = v->getC2( P1Ref ); } } qreal distance = 2.0*QLineF(P2, lastPoint).length(); int steps = qRound( distance /localGradientWidth ); for(int i=0; i=0) { QPointF thePoint = P1 + (i)*(localGradientWidth)*(P2 -P1)/distance; QPointF thePoint2 = thePoint; radialGrad.setCenter( thePoint2 ); radialGrad.setFocalPoint( thePoint2 ); radialGrad.setRadius( localGradientWidth ); QRectF rectangle(thePoint2.x()-localGradientWidth, thePoint2.y()-localGradientWidth, 2*localGradientWidth, 2*localGradientWidth); if(buffer) { BitmapImage* subBuffer = new BitmapImage(NULL); subBuffer->drawRect( rectangle, Qt::NoPen, radialGrad, QPainter::CompositionMode_Source, false); buffer->add(subBuffer); delete subBuffer; } else { painter.fillRect( rectangle, radialGrad ); } //painter.setPen( Qt::black ); //painter.drawEllipse( rectangle ); if(i==steps-1) lastPoint = thePoint; } } //if(!lastPointExists) { // lastPointExists = true; //} } //} else { // lastPointExists = false; //} }*/ painter.setWorldMatrixEnabled(false); if(buffer->image) painter.drawImage(buffer->topLeft(), *(buffer->image)); painter.setWorldMatrixEnabled(true); delete buffer; /* // ---- radial gradient with gaussian decaying --- QRadialGradient radialGrad(QPointF(0,0), gradientWidth, QPointF(0,0)); QColor colour2 = v->getColour(v->area[i].colourNumber); //colour2 = Qt::black; colour2.setAlpha(255); radialGrad.setColorAt(0, colour2 ); colour2.setAlpha(217); radialGrad.setColorAt(0.2, colour2 ); colour2.setAlpha(134); radialGrad.setColorAt(0.4, colour2 ); colour2.setAlpha(94); radialGrad.setColorAt(0.5, colour2 ); colour2.setAlpha(60); radialGrad.setColorAt(0.6, colour2 ); colour2.setAlpha(36); radialGrad.setColorAt(0.7, colour2 ); colour2.setAlpha(20); radialGrad.setColorAt(0.8, colour2 ); colour2.setAlpha(10); radialGrad.setColorAt(0.9, colour2 ); colour2.setAlpha(0); radialGrad.setColorAt(1, colour2 ); colour2.setAlpha(255); radialGrad.setColorAt(0, colour2 ); colour2.setAlpha(212); radialGrad.setColorAt(0.2, colour2 ); colour2.setAlpha(142); radialGrad.setColorAt(0.4, colour2 ); colour2.setAlpha(107); radialGrad.setColorAt(0.5, colour2 ); colour2.setAlpha(77); radialGrad.setColorAt(0.6, colour2 ); colour2.setAlpha(32); radialGrad.setColorAt(0.7, colour2 ); colour2.setAlpha(16); radialGrad.setColorAt(0.8, colour2 ); colour2.setAlpha(3); radialGrad.setColorAt(0.9, colour2 ); colour2.setAlpha(0); radialGrad.setColorAt(1, colour2 ); colour2.setAlpha(255); radialGrad.setColorAt(0, colour2 ); colour2.setAlpha(204); radialGrad.setColorAt(0.2, colour2 ); colour2.setAlpha(153); radialGrad.setColorAt(0.4, colour2 ); colour2.setAlpha(127); radialGrad.setColorAt(0.5, colour2 ); colour2.setAlpha(102); radialGrad.setColorAt(0.6, colour2 ); colour2.setAlpha(76); radialGrad.setColorAt(0.7, colour2 ); colour2.setAlpha(51); radialGrad.setColorAt(0.8, colour2 ); colour2.setAlpha(25); radialGrad.setColorAt(0.9, colour2 ); colour2.setAlpha(0); radialGrad.setColorAt(1, colour2 ); // gradient for 1/2 spacings blended colour2.setAlpha(255); radialGrad.setColorAt(0, colour2 ); colour2.setAlpha(234); radialGrad.setColorAt(0.1, colour2 ); colour2.setAlpha(190); radialGrad.setColorAt(0.2, colour2 ); colour2.setAlpha(92); radialGrad.setColorAt(0.4, colour2 ); colour2.setAlpha(58); radialGrad.setColorAt(0.5, colour2 ); colour2.setAlpha(36); radialGrad.setColorAt(0.6, colour2 ); colour2.setAlpha(23); radialGrad.setColorAt(0.7, colour2 ); colour2.setAlpha(14); radialGrad.setColorAt(0.8, colour2 ); colour2.setAlpha(7); radialGrad.setColorAt(0.9, colour2 ); colour2.setAlpha(0); radialGrad.setColorAt(1, colour2 ); // gradient for 1/3 spacings blended colour2.setAlpha(255); radialGrad.setColorAt(0, colour2 ); colour2.setAlpha(213); radialGrad.setColorAt(0.1, colour2 ); colour2.setAlpha(168); radialGrad.setColorAt(0.2, colour2 ); colour2.setAlpha(75); radialGrad.setColorAt(0.4, colour2 ); colour2.setAlpha(44); radialGrad.setColorAt(0.5, colour2 ); colour2.setAlpha(25); radialGrad.setColorAt(0.6, colour2 ); colour2.setAlpha(14); radialGrad.setColorAt(0.7, colour2 ); colour2.setAlpha(8); radialGrad.setColorAt(0.8, colour2 ); colour2.setAlpha(3); radialGrad.setColorAt(0.9, colour2 ); colour2.setAlpha(0); radialGrad.setColorAt(1, colour2 ); // gradient for 1/2 spacings added colour2.setAlpha(147); radialGrad.setColorAt(0, colour2 ); colour2.setAlpha(142); radialGrad.setColorAt(0.1, colour2 ); colour2.setAlpha(125); radialGrad.setColorAt(0.2, colour2 ); colour2.setAlpha(76); radialGrad.setColorAt(0.4, colour2 ); colour2.setAlpha(52); radialGrad.setColorAt(0.5, colour2 ); colour2.setAlpha(34); radialGrad.setColorAt(0.6, colour2 ); colour2.setAlpha(20); radialGrad.setColorAt(0.7, colour2 ); colour2.setAlpha(11); radialGrad.setColorAt(0.8, colour2 ); colour2.setAlpha(5); radialGrad.setColorAt(0.9, colour2 ); colour2.setAlpha(0); radialGrad.setColorAt(1, colour2 ); painter.setRenderHint(QPainter::Antialiasing, false); // ---- loop over all the points of the contour --- QPointF lastPoint; bool lastPointExists = false; QPointF P1, P2, C1, C2; int localGradientWidth; for( int j=1; jarea[i].vertex.size(); j++) { P1Ref = v->area[i].getVertexRef(j-1); P2Ref = v->area[i].getVertexRef(j); P1 = v->getVertex( P1Ref ); P2 = v->getVertex( P2Ref ); //bool P1invisible = v->curve[ P1Ref.curveNumber ].isInvisible(); //bool P2invisible = v->curve[ P2Ref.curveNumber ].isInvisible(); qreal width1 = v->curve[ P1Ref.curveNumber ].getFeather(); qreal width2 = v->curve[ P2Ref.curveNumber ].getFeather(); localGradientWidth = qMax(width1, width2); if(localGradientWidth == 0.0) localGradientWidth = gradientWidth; // ------------------------------------------------------------------------------------------------- //if( (P1invisible || P2invisible) && gradientWidth != 0.0 ) { //if( QLineF(P1,P2).length() <= 0.5) if(localGradientWidth != 0.0) { if(!lastPointExists) { lastPoint = P1; lastPointExists = true; } if(P1Ref.curveNumber == P1Ref.curveNumber) { if(P1Ref.vertexNumber < P2Ref.vertexNumber ) { // the points follow the curve progression C1 = v->getC1( P2Ref ); C2 = v->getC2( P2Ref ); } else { C2 = v->getC1( P1Ref ); C1 = v->getC2( P1Ref ); } } qreal distance = 2.0*QLineF(P2, lastPoint).length(); int steps = qRound( distance /localGradientWidth ); for(int i=0; i=0) { QPointF thePoint = lastPoint + (i)*(localGradientWidth)*(P2 -lastPoint)/distance; QPointF thePoint2 = thePoint; radialGrad.setCenter( thePoint2 ); radialGrad.setFocalPoint( thePoint2 ); radialGrad.setRadius( localGradientWidth ); QRectF rectangle(thePoint2.x()-localGradientWidth, thePoint2.y()-localGradientWidth, 2*localGradientWidth, 2*localGradientWidth); if(buffer) { BitmapImage* subBuffer = new BitmapImage(NULL); subBuffer->drawRect( rectangle, Qt::NoPen, radialGrad, QPainter::CompositionMode_Source, false); buffer->add(subBuffer); delete subBuffer; } else { painter.fillRect( rectangle, radialGrad ); } //painter.setPen( Qt::black ); //painter.drawEllipse( rectangle ); if(i==steps-1) lastPoint = thePoint; } } //if(!lastPointExists) { // lastPointExists = true; //} } //} else { // lastPointExists = false; //} } if(buffer) { if(buffer->image) painter.drawImage(buffer->topLeft(), *(buffer->image)); delete buffer; }*/ }pencil-0.4.4b/src/graphics/vector/colourref.h0000644000175000017500000000150210641754634021715 0ustar khashayarkhashayar/* Pencil - Traditional Animation Software Copyright (C) 2005-2007 Patrick Corrieri & Pascal Naidon This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #ifndef COLOURREF_H #define COLOURREF_H #include #include class ColourRef { public: ColourRef(); ColourRef(QColor theColour, QString theName); bool operator==(ColourRef colourRef1); bool operator!=(ColourRef colourRef1); QColor colour; QString name; }; #endif pencil-0.4.4b/src/graphics/vector/colourref.cpp0000644000175000017500000000207010641754634022251 0ustar khashayarkhashayar/* Pencil - Traditional Animation Software Copyright (C) 2005-2007 Patrick Corrieri & Pascal Naidon This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #include "colourref.h" ColourRef::ColourRef() { colour = Qt::green; name = QString("Green"); } ColourRef::ColourRef(QColor theColour, QString theName) { colour = theColour; name = theName; } bool ColourRef::operator==(ColourRef colourRef1) { if( (colour == colourRef1.colour) && (name == colourRef1.name) ) { return true; } else { return false; } } bool ColourRef::operator!=(ColourRef colourRef1) { if( (colour != colourRef1.colour) || (name != colourRef1.name) ) { return true; } else { return false; } } pencil-0.4.4b/src/graphics/vector/vertexref.cpp0000644000175000017500000000235110641754634022265 0ustar khashayarkhashayar/* Pencil - Traditional Animation Software Copyright (C) 2005-2007 Patrick Corrieri & Pascal Naidon This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #include "vertexref.h" VertexRef::VertexRef() { curveNumber = -1; vertexNumber = -1; } VertexRef::VertexRef(int curveN, int vertexN) { curveNumber = curveN; vertexNumber = vertexN; } VertexRef VertexRef::nextVertex() { return VertexRef(curveNumber, vertexNumber+1); } VertexRef VertexRef::prevVertex() { return VertexRef(curveNumber, vertexNumber-1); } bool VertexRef::operator==(VertexRef vertexRef1) { if( (curveNumber == vertexRef1.curveNumber) && (vertexNumber == vertexRef1.vertexNumber)) { return true; } else { return false; } } bool VertexRef::operator!=(VertexRef vertexRef1) { if( (curveNumber != vertexRef1.curveNumber) || (vertexNumber != vertexRef1.vertexNumber)) { return true; } else { return false; } } pencil-0.4.4b/src/graphics/vector/beziercurve.cpp0000644000175000017500000006300510646223355022577 0ustar khashayarkhashayar/* Pencil - Traditional Animation Software Copyright (C) 2005-2007 Patrick Corrieri & Pascal Naidon This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #include #include #include "beziercurve.h" #include "object.h" BezierCurve::BezierCurve() { // nothing; } BezierCurve::BezierCurve(QList pointList) { QList pressureList; for(int i=0; i< pointList.size(); i++) { pressureList << 0.5; // default pressure } createCurve(pointList, pressureList); } BezierCurve::BezierCurve(QList pointList, QList pressureList, double tol) { int n = pointList.size(); // Simplify path QList markList; for(int i=0; i simplifiedPointList; QList simplifiedPressureList; for(int i=0; i i) { simplifiedPressureList.append(pressureList.at(i)); } else { simplifiedPressureList.append(0.5); // default pressure } } } //pointList = simplifiedPointList; //pressureList = simplifiedPressureList; //n = pointList.size(); // Create curve from the simplified path createCurve(simplifiedPointList, simplifiedPressureList); //createCurve(pointList, pressureList); } QDomElement BezierCurve::createDomElement(QDomDocument &doc) { QDomElement curveTag = doc.createElement("curve"); curveTag.setAttribute("width", width); curveTag.setAttribute("variableWidth", variableWidth); if(feather>0) curveTag.setAttribute("feather", feather); curveTag.setAttribute("invisible", invisible); curveTag.setAttribute("colourNumber", colourNumber); curveTag.setAttribute("originX", origin.x()); curveTag.setAttribute("originY", origin.y()); curveTag.setAttribute("originPressure", pressure.at(0)); for(int i=0; i < c1.size() ; i++) { QDomElement segementTag = doc.createElement("segment"); segementTag.setAttribute("c1x", c1.at(i).x()); segementTag.setAttribute("c1y", c1.at(i).y()); segementTag.setAttribute("c2x", c2.at(i).x()); segementTag.setAttribute("c2y", c2.at(i).y()); segementTag.setAttribute("vx", vertex.at(i).x()); segementTag.setAttribute("vy", vertex.at(i).y()); segementTag.setAttribute("pressure", pressure.at(i+1)); curveTag.appendChild(segementTag); } return curveTag; } void BezierCurve::loadDomElement(QDomElement element) { width = element.attribute("width").toDouble(); variableWidth = (element.attribute("variableWidth") == "1"); feather = element.attribute("feather").toDouble(); invisible = (element.attribute("invisible") == "1"); if(width == 0) invisible = true; colourNumber = element.attribute("colourNumber").toInt(); origin = QPointF( element.attribute("originX").toFloat(), element.attribute("originY").toFloat() ); pressure.append( element.attribute("originPressure").toFloat() ); selected.append(false); QDomNode segmentTag = element.firstChild(); while(!segmentTag.isNull()) { QDomElement segmentElement = segmentTag.toElement(); if(!segmentElement.isNull()) { if(segmentElement.tagName() == "segment") { QPointF c1Point = QPointF(segmentElement.attribute("c1x").toFloat(), segmentElement.attribute("c1y").toFloat()); QPointF c2Point = QPointF(segmentElement.attribute("c2x").toFloat(), segmentElement.attribute("c2y").toFloat()); QPointF vertexPoint = QPointF(segmentElement.attribute("vx").toFloat(), segmentElement.attribute("vy").toFloat()); qreal pressureValue = segmentElement.attribute("pressure").toFloat(); appendCubic(c1Point, c2Point, vertexPoint, pressureValue); } } segmentTag = segmentTag.nextSibling(); } } void BezierCurve::setOrigin(const QPointF &point) { origin = point; } void BezierCurve::setOrigin(const QPointF &point, const qreal &pressureValue, const bool &trueOrFalse) { origin = point; pressure[0] = pressureValue; selected[0] = trueOrFalse; } void BezierCurve::setC1(int i, const QPointF &point) { if( i >= 0 || i < c1.size() ) { c1[i] = point; } else { qDebug() << "BezierCurve::setC1! index out of bounds:" << i; } } void BezierCurve::setC2(int i, const QPointF &point) { if( i >= 0 || i < c2.size() ) { c2[i] = point; } else { qDebug() << "BezierCurve::setC2! index out of bounds:" << i; } } void BezierCurve::setVertex(int i, const QPointF &point) { if(i==-1) { origin = point; } else { if( i >= 0 || i < vertex.size() ) { vertex[i] = point; } else { qDebug() << "BezierCurve::setVertex! index out of bounds:" << i; } } } void BezierCurve::setLastVertex(const QPointF &point) { if(vertex.size()>0) { vertex[vertex.size()-1] = point; } else { qDebug() << "BezierCurve::setLastVertex! curve has less than 2 vertices"; } } void BezierCurve::setWidth(qreal desiredWidth) { width = desiredWidth; } void BezierCurve::setFeather(qreal desiredFeather) { feather = desiredFeather; } void BezierCurve::setVariableWidth(bool YesOrNo) { variableWidth = YesOrNo; } void BezierCurve::setInvisibility(bool YesOrNo) { invisible = YesOrNo; } void BezierCurve::setSelected(int i, bool YesOrNo) { selected[i+1] = YesOrNo; } BezierCurve BezierCurve::transformed(QMatrix transformation) { BezierCurve transformedCurve = *this; // copy the curve if(isSelected(-1)) { transformedCurve.setOrigin(transformation.map(origin)); } for(int i=0; i< vertex.size(); i++) { if(isSelected(i-1)) { transformedCurve.setC1(i, transformation.map(c1.at(i))); } if(isSelected(i)) { transformedCurve.setC2(i, transformation.map(c2.at(i))); transformedCurve.setVertex(i, transformation.map(vertex.at(i))); } } //transformedCurve.smoothCurve(); /*QPointF newOrigin = origin; if(isSelected(-1)) { newOrigin = transformation.map(newOrigin); } transformedCurve.setOrigin( newOrigin ); for(int i=0; i< vertex.size(); i++) { QPointF newC1 = c1.at(i); QPointF newC2 = c2.at(i); QPointF newVertex = vertex.at(i); if(isSelected(i-1)) { newC1 = transformation.map(newC1); } if(isSelected(i)) { newC2 = transformation.map(newC2); newVertex = transformation.map(newVertex); } transformedCurve.appendCubic( newC1, newC2, newVertex, pressure.at(i) ); if(isSelected(i)) { transformedCurve.setSelected(i, true); } } transformedCurve.setWidth( width); transformedCurve.setVariableWidth( variableWidth ); //transformedCurve.setSelected(true); // or select only the selected elements of the orginal curve? */ return transformedCurve; } void BezierCurve::transform(QMatrix transformation) { if(isSelected(-1)) setOrigin( transformation.map(origin) ); for(int i=0; i< vertex.size(); i++) { if(isSelected(i-1)) c1[i] = transformation.map(c1.at(i)); if(isSelected(i)) { c2[i] = transformation.map(c2.at(i)); vertex[i] = transformation.map(vertex.at(i)); } } //smoothCurve(); } void BezierCurve::appendCubic(const QPointF &c1Point, const QPointF &c2Point, const QPointF &vertexPoint, qreal pressureValue) { c1.append(c1Point); c2.append(c2Point); vertex.append(vertexPoint); pressure.append(pressureValue); selected.append(false); } void BezierCurve::addPoint(int position, const QPointF point) { if( position > -1 && position < getVertexSize() ) { QPointF v1 = getVertex(position-1); QPointF v2 = getVertex(position); QPointF c1o = getC1(position); QPointF c2o = getC2(position); c1[position] = point + 0.2*(v2-v1); c2[position] = v2 + (c2o-v2)*(0.5); c1.insert(position, v1 + (c1o-v1)*(0.5) ); c2.insert(position, point - 0.2*(v2-v1)); vertex.insert(position, point); pressure.insert(position, getPressure(position)); selected.insert(position, isSelected(position) && isSelected(position-1)); //smoothCurve(); } else { qDebug() << "Error BezierCurve::addPoint(int, QPointF)"; } } void BezierCurve::addPoint(int position, const qreal t) { // t is the fraction where to split the bezier curve (ex: t=0.5) // de Casteljau's method is used // http://en.wikipedia.org/wiki/De_Casteljau%27s_algorithm // http://www.damtp.cam.ac.uk/user/na/PartIII/cagd2002/halve.ps if( position > -1 && position < getVertexSize() ) { QPointF vA = getVertex(position-1); QPointF vB = getVertex(position); QPointF c1o = getC1(position); QPointF c2o = getC2(position); QPointF c12 = (1-t)*c1o + t*c2o; QPointF cA1 = (1-t)*vA + t*c1o; QPointF cB2 = (1-t)*c2o + t*vB; QPointF cA2 = (1-t)*cA1 + t*c12; QPointF cB1 = (1-t)*c12 + t*cB2; QPointF vM = (1-t)*cA2 + t*cB1; setC1(position, cB1); setC2(position, cB2); c1.insert(position, cA1); c2.insert(position, cA2); vertex.insert(position, vM); pressure.insert(position, getPressure(position)); selected.insert(position, isSelected(position) && isSelected(position-1)); //smoothCurve(); } else { qDebug() << "Error BezierCurve::addPoint(int, qreal)"; } } void BezierCurve::removeVertex(int i) { int n = vertex.size(); if(i>-2 && i< n) { if(i== -1) { origin = vertex.at(0); vertex.removeAt(0); c1.removeAt(0); c2.removeAt(0); pressure.removeAt(0); selected.removeAt(0); } else { vertex.removeAt(i); c2.removeAt(i); pressure.removeAt(i+1); selected.removeAt(i+1); if( i != n-1 ) { c1.removeAt(i+1); } else { c1.removeAt(i); } } } } void BezierCurve::drawPath(QPainter &painter, Object* object, QMatrix transformation, bool simplified, bool showThinLines, qreal opacity) { if(!simplified) painter.setOpacity(opacity); QColor colour = object->getColour(colourNumber).colour; //simplified = true; //if(selected) { painter.setMatrix(transformation); } else { painter.setMatrix(QMatrix()); } //QColor colour = object->getColour(colourNumber).colour; if(!simplified) painter.setOpacity(opacity); BezierCurve myCurve; if(isPartlySelected()) { myCurve = (transformed(transformation)); } else { myCurve = *this; } //if(variableWidth && !simplified && width != 0) { if( variableWidth && !simplified && !invisible) { painter.setPen(QPen(QBrush(colour), 1, Qt::NoPen, Qt::RoundCap,Qt::RoundJoin)); painter.setBrush(colour); painter.drawPath(myCurve.getStrokedPath()); /*QPen pen; pen.setColor(colour); QPointF P1 = origin; QPointF P2 = origin; for(int i=0; i-1) { normale = (myCurve.getVertex(i)-myCurve.getC2(i)); } else { normale = (myCurve.getC1(i+1)-myCurve.getVertex(i)); } normale = QPointF(-normale.y(), normale.x()); normale = 8.0*normale/eLength(normale)/painter.matrix().m11(); painter.drawLine(myCurve.getVertex(i), myCurve.getVertex(i)+normale); painter.drawText(myCurve.getVertex(i)+2*normale, QString::number(i));*/ } } } } QPainterPath BezierCurve::getSimplePath() { QPainterPath path; path.moveTo(origin); for(int i=0; i-1; i--) { normalVec2_1 = QPointF((vertex.at(i) - c1.at(i+1)).y(), -(vertex.at(i) - c1.at(i+1)).x()); normalise(normalVec2_1); normalVec2_2 = QPointF((c2.at(i) - vertex.at(i)).y(), -(c2.at(i) - vertex.at(i)).x()); normalise(normalVec2_2); normalVec2 = normalVec2_1 + normalVec2_2; normalise(normalVec2); if(usePressure) width2 = width * 0.5 * pressure.at(i); if(n==1 && width2 == 0.0) width2 = 0.15 * width; path.cubicTo(c2.at(i+1) - width2*normalVec, c1.at(i+1) - width2*normalVec2, vertex.at(i) - width2*normalVec2); normalVec = normalVec2; } normalVec2 = QPointF((origin - c1.at(0)).y(), -(origin - c1.at(0)).x()); normalise(normalVec2); if(usePressure) width2 = width * 0.5 * pressure.at(0); if(n==1 && width2 == 0.0) width2 = 0.15 * width; path.cubicTo(c2.at(0) - width2*normalVec, c1.at(0) - width2*normalVec2, origin - width2*normalVec2); path.closeSubpath(); return path; } QRectF BezierCurve::getBoundingRect() { return getSimplePath().boundingRect(); } void BezierCurve::createCurve(QList &pointList, QList &pressureList ) { int p = 0; int n = pointList.size(); // generate the Bezier (cubic) curve from the simplified path and mouse pressure // first, empty everything while(c1.size()>0) c1.removeAt(0); while(c2.size()>0) c2.removeAt(0); while(vertex.size()>0) vertex.removeAt(0); while(selected.size()>0) selected.removeAt(0); while(pressure.size()>0) pressure.removeAt(0); setOrigin( pointList.at(0) ); selected.append(false); pressure.append(pressureList.at(0)); for(p=1; pc1[p] = c2old; this->c2[p] = c1; //appendCubic(c2old, c1, D, pressureList->at(p)); c2old = c2; } if(n>2) { this->c1[n-1] = c2old; this->c2[n-1] = 0.5*(c2old+vertex.at(n-1)); } } /* --- old code --- void BezierCurve::createCurve(QList *pointList, QList *pressureList ) { int p = 0; int n = pointList->size(); QPointF c1, c2, c2old, tangentVec, normalVec; // generate the Bezier (cubic) curve from the simplified path and mouse pressure setOrigin( pointList->at(0) ); while(selected.size()>0) selected.removeAt(0); selected.append(false); c2old = QPointF(-100,-100); // bogus point for(p=1; pat(p); QPointF Dprev = pointList->at(p-1); QPointF Dnext = pointList->at(p+1); qreal L1 = mLength(D-Dprev); qreal L2 = mLength(D-Dnext); //if(L1 == 0) L1 = 1; //if(L2 == 0) L2 = 1; //painter.setPen(QPen(QBrush(Qt::black), 2, Qt::SolidLine, Qt::RoundCap,Qt::RoundJoin)); //painter.drawRect(D.x()-1, D.y()-1, 1, 1); tangentVec = 0.4*(Dnext - Dprev); normalVec = QPointF(-tangentVec.y(), tangentVec.x())/eLength(tangentVec); if( ((D-Dprev).x()*(D-Dnext).x()+(D-Dprev).y()*(D-Dnext).y())/(1.0*L1*L2) < 0 ) { // smooth point c1 = D - tangentVec*(L1+0.0)/(L1+L2); c2 = D + tangentVec*(L2+0.0)/(L1+L2); } else { // sharp point c1 = 0.6*D + 0.4*Dprev; c2 = 0.6*D + 0.4*Dnext; } //painter.setPen(QPen(QBrush(Qt::green), 2, Qt::SolidLine, Qt::RoundCap,Qt::RoundJoin)); //painter.drawRect(c1.x()-1, c1.y()-1 ,2,2 ); //painter.drawRect(c2.x()-1, c2.y()-1, 2,2 ); //painter.drawLine(c1, c2); if(p==1) c2old = 0.5*(pointList->at(0)+c1); //path.cubicTo( c2old, c1, D); appendCubic(c2old, c1, D, pressureList->at(p)); c2old = c2; } if(n > 2) { //path.cubicTo( c2old, 0.5*(c2old+mousePath.at(n-1)), mousePath.at(n-1)); appendCubic( c2old, 0.5*(c2old+pointList->at(n-1)), pointList->at(n-1), pressureList->at(n-1)); } else { //path.cubicTo( 0.5*(mousePath.at(0)+mousePath.at(n-1)), 0.5*(mousePath.at(0)+mousePath.at(n-1)), mousePath.at(n-1)); appendCubic( 0.75*pointList->at(0)+0.25*pointList->at(n-1), 0.25*pointList->at(0)+0.75*pointList->at(n-1), pointList->at(n-1), pressureList->at(n-1)); } } */ void BezierCurve::simplify(double tol, QList &inputList, int j, int k, QList &markList) { // -- Douglas-Peucker simplification algorithm // from http://geometryalgorithms.com/Archive/algorithm_0205/ if (k <= j+1) { //there is nothing to simplify // return immediately } else { // test distance of intermediate vertices from segment Vj to Vk double maxd = 0.0; //is the distance of farthest vertex from segment jk int maxi = j; //is the index of the vertex farthest from segement jk for(int i=j+1; i &intersections) { //finds the intersection between two cubic sections bool result = false; //qDebug() << "---- INTER CUBIC CUBIC" << i1 << i2; QPointF P1, Q1, P2, Q2; QLineF L1, L2; QRectF R1; QRectF R2; P1 = curve1.getVertex(i1-1); Q1 = curve1.getVertex(i1); P2 = curve2.getVertex(i2-1); Q2 = curve2.getVertex(i2); L1 = QLineF(P1, Q1); L2 = QLineF(P2, Q2); //qDebug() << "-------------------- "; R1.setTopLeft(P1); R1.setBottomRight(Q1); R2.setTopLeft(P2); R2.setBottomRight(Q2); //QPointF intersectionPoint = QPointF(50.0, 50.0); // bogus point //QPointF* intersection = &intersectionPoint; QPointF* cubicIntersection = &QPointF(50.0, 50.0); // bogus point if( R1.intersects(R2) || L2.intersect(L1, cubicIntersection) == QLineF::BoundedIntersection ) { //if(L2.intersect(L1, intersection) == QLineF::BoundedIntersection) { //qDebug() << " FOUND rectangle intersection "; //if(intersectionPoint != curve1.getVertex(i1-1) && intersectionPoint != curve1.getVertex(i1)) { // qDebug() << " it's not one of the points "; // find the cubic intersection int nSteps = 24; P1 = curve1.getVertex(i1-1); for(int i=1; i<=nSteps;i++) { qreal s = (i+0.0)/nSteps; Q1 = curve1.getPointOnCubic(i1, s); P2 = curve2.getVertex(i2-1); for(int j=1; j<=nSteps;j++) { qreal t = (j+0.0)/nSteps; Q2 = curve2.getPointOnCubic(i2, t); L1 = QLineF(P1, Q1); L2 = QLineF(P2, Q2); if(L2.intersect(L1, cubicIntersection) == QLineF::BoundedIntersection) { QPointF intersectionPoint = *cubicIntersection; if(intersectionPoint != curve1.getVertex(i1-1) && intersectionPoint != curve1.getVertex(i1)) { qreal fraction1 = eLength(intersectionPoint-Q1)/(0.0+eLength(Q1-P1)); qreal fraction2 = eLength(intersectionPoint-Q2)/(0.0+eLength(Q2-P2)); qreal t1 = (i - fraction1)/nSteps; qreal t2 = (j - fraction2)/nSteps; Intersection intersection; intersection.point = intersectionPoint; intersection.t1 = t1; intersection.t2 = t2; intersections.append( intersection ); result = true; //qDebug() << "FOUND cubic interesection " << intersectionPoint << i << j; } } P2 = Q2; } P1 = Q1; } } else { //return false; // approximation to speed up the calculation } //qDebug() << "------"; return result; } pencil-0.4.4b/src/graphics/vector/vertexref.h0000644000175000017500000000150710641754634021734 0ustar khashayarkhashayar/* Pencil - Traditional Animation Software Copyright (C) 2005-2007 Patrick Corrieri & Pascal Naidon This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #ifndef VERTEXREF_H #define VERTEXREF_H class VertexRef { public: VertexRef(); VertexRef(int curveN, int vertexN); VertexRef nextVertex(); VertexRef prevVertex(); bool operator==(VertexRef vertexRef1); bool operator!=(VertexRef vertexRef1); int curveNumber; int vertexNumber; }; #endif pencil-0.4.4b/src/graphics/vector/vectorimage.h0000644000175000017500000001157510702435104022217 0ustar khashayarkhashayar/* Pencil - Traditional Animation Software Copyright (C) 2005-2007 Patrick Corrieri & Pascal Naidon This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #ifndef VECTORIMAGE_H #define VECTORIMAGE_H #include #include #include "bezierarea.h" #include "beziercurve.h" #include "vertexref.h" class Object; // forward declaration //class VectorImage : public QObject class VectorImage { //Q_OBJECT public: VectorImage(); VectorImage(Object* parent); //VectorImage(QSize size, QImage::Format format, Object* parent); //VectorImage(QImage newImage, Object* parent); bool read(QString filePath); bool write(QString filePath, QString format); QDomElement createDomElement(QDomDocument &doc); void loadDomElement(QDomElement element); //void setView(QMatrix newView); void addPoint(int curveNumber, int vertexNumber, qreal t); void addCurve(BezierCurve &newCurve, qreal factor); void removeCurveAt(int i); void select(QRectF rectangle); void setSelected(int curveNumber, bool YesOrNo); void setSelected(int curveNumber, int vertexNumber, bool YesOrNo); void setSelected(VertexRef vertexRef, bool YesOrNo); void setSelected(QList curveList, bool YesOrNo); void setSelected(QList vertexList, bool YesOrNo); bool isSelected(int curveNumber); bool isSelected(int curveNumber, int vertexNumber); bool isSelected(VertexRef vertexRef); bool isSelected(QList curveList); bool isSelected(QList vertexList); void setAreaSelected(int areaNumber, bool YesOrNo); bool isAreaSelected(int areaNumber); int getFirstSelectedCurve(); int getFirstSelectedArea(); void selectAll(); void deselectAll(); QRectF getSelectionRect() { return selectionRect; } void setSelectionRect(QRectF rectange); void calculateSelectionRect(); void deleteSelection(); void deleteSelectedPoints(); void removeVertex(int i, int m); void paste(VectorImage); bool isModified(); void setModified(bool); QColor getColour(int i); int getColourNumber(QPointF point); bool usesColour(int index); void removeColour(int index); void paintImage(QPainter &painter, bool simplified, bool showThinCurves, qreal curveOpacity, bool antialiasing, int gradients); void outputImage(QImage* image, QSize size, QMatrix myView, bool simplified, bool showThinCurves, qreal curveOpacity, bool antialiasing, int gradients); // uses paintImage void clear(); void clean(); void setSelectionTransformation(QMatrix transform); void applySelectionTransformation(); void applySelectionTransformation(QMatrix transform); void applyColourToSelection(int colourNumber); void applyWidthToSelection(qreal width); void applyFeatherToSelection(qreal feather); void applyOpacityToSelection(qreal opacity); void applyInvisibilityToSelection(bool YesOrNo); void applyVariableWidthToSelection(bool YesOrNo); void colour(QList mousePath, int colour); void addArea(BezierArea bezierArea); int getFirstAreaNumber(QPointF point); int getLastAreaNumber(QPointF point); int getLastAreaNumber(QPointF point, int maxAreaNumber); void removeArea(QPointF point); void updateArea(BezierArea &bezierArea); QList getCurvesCloseTo(QPointF thisPoint, qreal maxDistance); VertexRef getClosestVertexTo(QPointF thisPoint, qreal maxDistance); QList getVerticesCloseTo(QPointF thisPoint, qreal maxDistance); QList getVerticesCloseTo(QPointF thisPoint, qreal maxDistance, QList *listOfPoints); QList getVerticesCloseTo(VertexRef thisPointRef, qreal maxDistance); QList getVerticesCloseTo(VertexRef thisPointRef, qreal maxDistance, QList *listOfPoints); QList getAndRemoveVerticesCloseTo(QPointF thisPoint, qreal maxDistance, QList *listOfPoints); QList getAndRemoveVerticesCloseTo(VertexRef thisPointRef, qreal maxDistance, QList *listOfPoints); QPointF getVertex(int curveNumber, int vertexNumber); QPointF getVertex(VertexRef vertexRef); QPointF getC1(int curveNumber, int vertexNumber); QPointF getC1(VertexRef vertexRef); QPointF getC2(int curveNumber, int vertexNumber); QPointF getC2(VertexRef vertexRef); QList getAllVertices(); int getCurveSize(int curveNumber); QList curve; QList area; qreal getDistance(VertexRef r1, VertexRef r2); private: void modification(); bool modified; Object* myParent; QRectF selectionRect; //, transformedSelection; QMatrix selectionTransformation; }; #endif pencil-0.4.4b/src/graphics/vector/bezierarea.h0000644000175000017500000000245110641754634022032 0ustar khashayarkhashayar/* Pencil - Traditional Animation Software Copyright (C) 2005-2007 Patrick Corrieri & Pascal Naidon This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #ifndef BEZIERAREA_H #define BEZIERAREA_H #include #include #include "vertexref.h" //class BezierArea : public QObject class BezierArea { //Q_OBJECT public: BezierArea(); //BezierArea(QList > pointList, VectorImage* vectorImage); BezierArea(QList vertexList, int colour); QDomElement createDomElement(QDomDocument &doc); void loadDomElement(QDomElement element); VertexRef getVertexRef(int i); int getColourNumber() { return colourNumber; } void decreaseColourNumber() { colourNumber--; } void setSelected(bool YesOrNo); bool isSelected() const { return selected; } void setColourNumber(int cn) { colourNumber = cn; } QList vertex; QPainterPath path; int colourNumber; private: //VectorImage* picture; bool selected; }; #endif pencil-0.4.4b/src/graphics/vector/vectorimage.cpp0000644000175000017500000011364310744607202022557 0ustar khashayarkhashayar/* Pencil - Traditional Animation Software Copyright (C) 2005-2007 Patrick Corrieri & Pascal Naidon This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #include #include #include "vectorimage.h" #include "object.h" #include "gradient.h" //#include "beziercurve.h" VectorImage::VectorImage() { // nothing } VectorImage::VectorImage(Object *parent) { myParent = parent; deselectAll(); } bool VectorImage::read(QString filePath) { QFileInfo fileInfo(filePath); if( fileInfo.isDir() ) return false; QFile* file = new QFile(filePath); if (!file->open(QFile::ReadOnly)) { //QMessageBox::warning(this, "Warning", "Cannot read file"); return false; } QDomDocument doc; if (!doc.setContent(file)) return false; // this is not a XML file QDomDocumentType type = doc.doctype(); if(type.name() != "PencilVectorImage") return false; // this is not a Pencil document int layerNumber = -1; QDomElement element = doc.documentElement(); if(element.tagName() == "image") { // --- vector image --- if(element.attribute("type") == "vector") { loadDomElement( element ); } } return true; } bool VectorImage::write(QString filePath, QString format) { QFile* file = new QFile(filePath); //if (!file->open(QIODevice::WriteOnly | QIODevice::Text)) { //bool result = file->open(QIODevice::WriteOnly | QIODevice::Text); bool result = file->open(QIODevice::WriteOnly); if (!result) { //QMessageBox::warning(this, "Warning", "Cannot write file"); qDebug() << "VectorImage - Cannot write file" << filePath << file->error(); return false; } QTextStream out(file); if(format == "VEC") { QDomDocument doc("PencilVectorImage"); //QDomElement root = doc.createElement("vectorImage"); //doc.appendChild(root); QDomElement imageTag = createDomElement(doc); doc.appendChild(imageTag); int IndentSize = 2; qDebug() << "--- Starting to write XML file..."; doc.save(out, IndentSize); qDebug() << "--- Writing XML file done."; file->close(); return true; } else { file->close(); qDebug() << "--- Not the VEC format!"; return false; } } QDomElement VectorImage::createDomElement(QDomDocument &doc) { QDomElement imageTag = doc.createElement("image"); imageTag.setAttribute("type", "vector"); for(int i=0; i < curve.size() ; i++) { QDomElement curveTag = curve[i].createDomElement(doc); imageTag.appendChild(curveTag); } for(int i=0; i < area.size() ; i++) { QDomElement areaTag = area[i].createDomElement(doc); imageTag.appendChild(areaTag); } return imageTag; } void VectorImage::loadDomElement(QDomElement element) { QDomNode atomTag = element.firstChild(); // an atom in a vector picture is a curve or an area while(!atomTag.isNull()) { QDomElement atomElement = atomTag.toElement(); if(!atomElement.isNull()) { if(atomElement.tagName() == "curve") { BezierCurve newCurve = BezierCurve(); newCurve.loadDomElement(atomElement); curve.append(newCurve); } if(atomElement.tagName() == "area") { BezierArea newArea = BezierArea(); newArea.loadDomElement(atomElement); addArea(newArea); } } atomTag = atomTag.nextSibling(); } clean(); modification(); } /*void VectorImage::setView(QMatrix newView) { myView = newView; modification(); }*/ void VectorImage::addPoint(int curveNumber, int vertexNumber, qreal t) { //curve[curveNumber].addPoint(vertexNumber, point); curve[curveNumber].addPoint(vertexNumber, t); // updates the bezierAreas for(int j=0; j < area.size(); j++) { // shift the references of all the points beyond the new point for(int k=0; k< area.at(j).vertex.size();k++) { if(area[j].getVertexRef(k).curveNumber == curveNumber) { if(area[j].getVertexRef(k).vertexNumber >= vertexNumber) { area[j].vertex[k].vertexNumber++; } } } // insert the new point in the area if necessary for(int k=1; k< area.at(j).vertex.size();k++) { if( VertexRef(curveNumber, vertexNumber+1) == area.at(j).vertex.at(k) ) { // area[j].vertex[k] == VertexRef(curveNumber, vertexNumber+1) if( VertexRef(curveNumber, vertexNumber-1) == area.at(j).vertex.at(k-1) ) { area[j].vertex.insert(k, VertexRef(curveNumber, vertexNumber) ); } } if( VertexRef(curveNumber, vertexNumber-1) == area.at(j).vertex.at(k) ) { if( VertexRef(curveNumber, vertexNumber+1) == area.at(j).vertex.at(k-1) ) { area[j].vertex.insert(k, VertexRef(curveNumber, vertexNumber) ); } } } } } void VectorImage::removeCurveAt(int i) { // first change the curve numbers in the areas for(int j=0; j < area.size(); j++) { for(int k=0; k< area.at(j).vertex.size();k++) { if(area.at(j).vertex[k].curveNumber > i) { area[j].vertex[k].curveNumber--; } } } // then remove curve curve.removeAt(i); } void VectorImage::addCurve(BezierCurve &newCurve, qreal factor) { if(newCurve.getVertexSize() < 1) return; // security - a new curve should have a least 2 vertices qreal tol = qMax(newCurve.getWidth() / factor, 3.0 / factor); // tolerance for taking the intersection as an existing vertex on a curve //qDebug() << "tolerance" << tol; // finds if the new curve interesects itself for(int k=0; k < newCurve.getVertexSize(); k++) { // for each cubic section of the new curve for(int j=k+1; j < newCurve.getVertexSize(); j++) { // for each other cubic section of the new curve QList intersections; bool intersection = BezierCurve::findIntersection(newCurve, k, newCurve, j, intersections); if(intersection) { //qDebug() << "INTERSECTION" << intersectionPoint << t1 << t2; //newCurve.addPoint(k, intersectionPoint); newCurve.addPoint(k, intersections[0].t1); //qDebug() << "--a " << newCurve.getVertex(k) << newCurve.getVertex(k+1); k++; j++; //newCurve.addPoint(j, intersectionPoint); newCurve.addPoint(j, intersections[0].t2); //qDebug() << "--a " << newCurve.getVertex(j) << newCurve.getVertex(j+1); j++; } } } // finds if the new curve is closed QPointF P = newCurve.getVertex(-1); QPointF Q = newCurve.getVertex(newCurve.getVertexSize()-1); if( BezierCurve::eLength(P-Q) < tol) { newCurve.setVertex(newCurve.getVertexSize()-1, P); } // finds if the first or last point of the new curve is close to other curves for(int i=0; i < curve.size(); i++) { // for each other curve for(int j=0; j < curve.at(i).getVertexSize(); j++) { // for each cubic section of the other curve QPointF P = newCurve.getVertex(-1); QPointF Q = newCurve.getVertex(newCurve.getVertexSize()-1); QPointF P1 = curve.at(i).getVertex(j-1); QPointF P2 = curve.at(i).getVertex(j); qreal tol3 = 2.0*sqrt( 0.25*((P1-P2).x()*(P1-P2).x() + (P1-P2).y()*(P1-P2).y()) + tol*tol ); qreal dist1 = BezierCurve::eLength(P-P1); qreal dist2 = BezierCurve::eLength(P-P2); if(dist1 <= 0.2*tol) { newCurve.setVertex(-1, P1); //qDebug() << "--b " << P1; } else { if(dist2 <= 0.2*tol) { newCurve.setVertex(-1, P2); //qDebug() << "--c " << P2; } else { if( dist1+dist2 <= 3*tol3 ) { // preselection, to speed up QPointF nearestPoint = P; qreal t = -1.0; qreal distance = BezierCurve::findDistance(curve[i], j, P, nearestPoint, t); if(distance < tol) { newCurve.setOrigin(nearestPoint); //qDebug() << "--d " << nearestPoint; addPoint(i, j, t); //j++; } } } //qDebug() << "Modif first"; } dist1 = BezierCurve::eLength(Q-P1); dist2 = BezierCurve::eLength(Q-P2); if(dist1 <= 0.2*tol) { newCurve.setLastVertex(P1); //qDebug() << "--e " << P1; } else { if(dist2 <= 0.2*tol) { newCurve.setLastVertex(P2); //qDebug() << "--f " << P2; } else { if( dist1+dist2 <= 3*tol3 ) { // preselection, to speed up QPointF nearestPoint = Q; qreal t = -1.0;; qreal distance = BezierCurve::findDistance(curve[i], j, Q, nearestPoint, t); if(distance < tol) { newCurve.setLastVertex(nearestPoint); //qDebug() << "--g " << nearestPoint; addPoint(i, j, t); //j++; } } } //qDebug() << "Modif last"; } } } // finds if the new curve interesects other curves for(int k=0; k < newCurve.getVertexSize(); k++) { // for each cubic section of the new curve //if(k==0) L1 = QLineF(P1 + 1.5*tol*(P1-Q1)/BezierCurve::eLength(P1-Q1), Q1); // we extend slightly the line for the near point //if(k==newCurve.getVertexSize()-1) L1 = QLineF(P1, Q1- 1.5*tol*(P1-Q1)/BezierCurve::eLength(P1-Q1)); // we extend slightly the line for the last point //QPointF extension1 = 1.5*tol*(P1-Q1)/BezierCurve::eLength(P1-Q1); //L1 = QLineF(P1 + extension1, Q1 - extension1); for(int i=0; i < curve.size(); i++) { // for each other curve // TO DO: should only loop on "nearby" curves instead of all //BezierCurve otherCurve; //if(i==-1) { otherCurve = newCurve; } else { otherCurve = curve.at(i); } // ---- finds if the first or last point of the other curve is close to the current cubic section of the new curve QPointF P = curve.at(i).getVertex(-1); QPointF Q = curve.at(i).getVertex(curve.at(i).getVertexSize()-1); QPointF P1 = newCurve.getVertex(k-1); QPointF P2 = newCurve.getVertex(k); qreal tol3 = 2.0*sqrt( 0.25*((P1-P2).x()*(P1-P2).x() + (P1-P2).y()*(P1-P2).y()) + tol*tol ); qreal dist1 = BezierCurve::eLength(P-P1); qreal dist2 = BezierCurve::eLength(P-P2); if(dist1 < 0.2*tol) { curve[i].setVertex(-1, P1); // memo: curve.at(i) is just a copy which can be read, curve[i] is a reference which can be modified } else { if(dist2 < 0.2*tol) { curve[i].setVertex(-1, P2); } else { if( dist1+dist2 < 3*tol3 ) { // TO DO: find a better intersection point QPointF nearestPoint = P; qreal t = -1.0; qreal distance = BezierCurve::findDistance(newCurve, k, P, nearestPoint, t); //qDebug() << "OK1" << t; if(distance < tol) { P = nearestPoint; curve[i].setOrigin(P); newCurve.addPoint(k, P); //qDebug() << "--i " << P; } } } //qDebug() << "Modif first"; } dist1 = BezierCurve::eLength(Q-P1); dist2 = BezierCurve::eLength(Q-P2); if(dist1 < 0.2*tol) { curve[i].setVertex(curve.at(i).getVertexSize()-1, P1); } else { if(dist2 < 0.2*tol) { curve[i].setVertex(curve.at(i).getVertexSize()-1, P2); } else { if( dist1+dist2 < 3*tol3 ) { // TO DO: find a better intersection point QPointF nearestPoint = Q; qreal t = -1.0;; qreal distance = BezierCurve::findDistance(newCurve, k, Q, nearestPoint, t); //qDebug() << "OK2" << t; if(distance < tol) { Q = nearestPoint; curve[i].setLastVertex(Q); newCurve.addPoint(k, Q); //qDebug() << "--j " << Q; } } } //qDebug() << "Modif first"; } // ---- finds if any cubic section of the other curve intersects the current cubic section of the new curve for(int j=0; j < curve.at(i).getVertexSize(); j++) { // for each cubic section of the other curve QList intersections; bool intersection = BezierCurve::findIntersection(newCurve, k, curve.at(i), j, intersections); if(intersection) { //qDebug() << "Found " << intersections.size() << " intersections"; QPointF intersectionPoint = intersections[0].point; qreal t1 = intersections[0].t1; qreal t2 = intersections[0].t2; if( BezierCurve::eLength(intersectionPoint - newCurve.getVertex(k-1)) <= 0.1*tol ) { // the first point is close to the intersection newCurve.setVertex(k-1, intersectionPoint); //qDebug() << "--k " << intersectionPoint; //qDebug() << "--------- recal " << k-1 << intersectionPoint; } else { if( BezierCurve::eLength(intersectionPoint - newCurve.getVertex(k)) <= 0.1*tol ) { // the second point is close to the intersection newCurve.setVertex(k, intersectionPoint); //qDebug() << "--l " << intersectionPoint; //qDebug() << "-------- recal " << k << intersectionPoint; } else { // none of the point is close to the intersection -> we add a new point //newCurve.addPoint(k, intersectionPoint); newCurve.addPoint(k, t1); //qDebug() << "--m " << newCurve.getVertex(k); //qDebug() << "----- add " << k << newCurve.getVertex(k); //k++; } } if( BezierCurve::eLength(intersectionPoint - curve.at(i).getVertex(j-1)) <= 0.1*tol ) { // the first point is close to the intersection curve[i].setVertex(j-1, intersectionPoint); //qDebug() << "--n " << intersectionPoint; //qDebug() << "-------- recal2 " << j-1 << intersectionPoint; } else { if( BezierCurve::eLength(intersectionPoint - curve.at(i).getVertex(j)) <= 0.1*tol ) { // the second point is close to the intersection curve[i].setVertex(j, intersectionPoint); //qDebug() << "--o " << intersectionPoint; //qDebug() << "-------- recal2 " << j << intersectionPoint; } else { // none of the point is close to the intersection -> we add a new point addPoint(i, j, t2); //qDebug() << "----- add2 " << j << curve[i].getVertex(j); //j++; } } } } } } curve.append(newCurve); modification(); //QPainter painter(&image); //painter.setRenderHint(QPainter::Antialiasing, true); //newCurve.drawPath(&painter); } void VectorImage::select(QRectF rectangle) { for(int i=0; i< curve.size(); i++) { if( curve[i].intersects(rectangle) ) { setSelected(i, true); } else { setSelected(i, false); } } for(int i=0; i< area.size(); i++) { if( rectangle.contains(area[i].path.boundingRect()) ) { setAreaSelected(i, true); } else { setAreaSelected(i, false); } } modification(); } void VectorImage::setSelected(int curveNumber, bool YesOrNo) { curve[curveNumber].setSelected(YesOrNo); if(YesOrNo) selectionRect |= curve[curveNumber].getBoundingRect(); modification(); } void VectorImage::setSelected(int curveNumber, int vertexNumber, bool YesOrNo) { curve[curveNumber].setSelected(vertexNumber, YesOrNo); QPointF vertex = getVertex(curveNumber, vertexNumber); if(YesOrNo) selectionRect |= QRectF(vertex.x(), vertex.y(), 0.0, 0.0); modification(); } void VectorImage::setSelected(VertexRef vertexRef, bool YesOrNo) { setSelected(vertexRef.curveNumber, vertexRef.vertexNumber, YesOrNo); } void VectorImage::setSelected(QList curveList, bool YesOrNo) { for(int i=0; i vertexList, bool YesOrNo) { for(int i=0; i curveList) { bool result = true; for(int i=0; i vertexList) { bool result = true; for(int i=0; i i) { area[j].vertex[k].curveNumber = area[j].vertex[k].curveNumber - 1; } } if(toBeDeleted) { area.removeAt(j); j--; } } curve.removeAt(i); i--; } else { /*for(int j=-1; j i) { area[j].vertex[k].curveNumber = area[j].vertex[k].curveNumber - 1; } } if(toBeDeleted) { area.removeAt(j); j--; } } // then eliminates the point if(curve[i].getVertexSize() > 1) { // first possibility: we just remove the point in the curve /* curve[i].removeVertex(m); m--;*/ // second possibility: we split the curve into two parts: if( m == -1 || m == getCurveSize(i) - 1 ) { // we just remove the first or last point curve[i].removeVertex(m); m--; // we also need to update the areas for(int j=0; j < area.size(); j++) { for(int k=0; k< area.at(j).vertex.size();k++) { if(area.at(j).vertex[k].curveNumber == i && area.at(j).vertex[k].vertexNumber > m) { area[j].vertex[k].vertexNumber--; } } } } else { int n = getCurveSize(i); BezierCurve newCurve = curve.at(i); // duplicate curve for(int p = m; p < n; p++) { // removes the end of of the curve i (after m, included) -> left part curve[i].removeVertex( getCurveSize(i)-1 ); } for(int p=-1; p <= m; p++) { // removes the beginning of the new curve (before m, included) -> right part newCurve.removeVertex(-1); } //if(newCurve.getVertexSize() > 0) curve.insert(i+1, newCurve); if(newCurve.getVertexSize() > 0) curve.append( newCurve); // insert the right part if it has more than one point // we also need to update the areas for(int j=0; j < area.size(); j++) { for(int k=0; k< area.at(j).vertex.size();k++) { if(area.at(j).vertex[k].curveNumber == i && area.at(j).vertex[k].vertexNumber > m) { area[j].vertex[k].curveNumber = curve.size()-1; area[j].vertex[k].vertexNumber = area[j].vertex[k].vertexNumber-m-1; } } } if( getCurveSize(i) < 1) { // the left part has less than two points so we remove it //curve.removeAt(i); removeCurveAt(i); i--; } } } else { // there are just two points left, so we remove the whole curve //curve.removeAt(i); removeCurveAt(i); i--; } } void VectorImage::deleteSelectedPoints() { for(int i=0; i< curve.size(); i++) { for(int m=-1; m < getCurveSize(i); m++) { if(curve.at(i).isSelected(m)) { // point m of curve i is selected removeVertex(i, m); } } } modification(); } void VectorImage::paste(VectorImage vectorImage) { selectionRect = QRect(0,0,0,0); int n = curve.size(); QList selectedCurves; for(int i=0; i < vectorImage.curve.size() ; i++) { if( vectorImage.curve.at(i).isSelected() ) { curve.append( vectorImage.curve.at(i) ); selectedCurves << i; selectionRect |= vectorImage.curve[i].getBoundingRect(); } } for(int i=0; i < vectorImage.area.size() ; i++) { BezierArea newArea = vectorImage.area.at(i); bool ok = true; for(int j=0; j < newArea.vertex.size(); j++) { int curveNumber = newArea.vertex.at(j).curveNumber; int vertexNumber = newArea.vertex.at(j).vertexNumber; if( vectorImage.curve.at(curveNumber).isSelected() ) { newArea.vertex[j] = VertexRef( selectedCurves.indexOf(curveNumber) + n, vertexNumber ); } else { ok = false; } } if(ok) area.append( newArea ); } modification(); } void VectorImage::modification() { setModified(true); } bool VectorImage::isModified() { return modified; } void VectorImage::setModified(bool trueOrFalse) { modified = trueOrFalse; } QColor VectorImage::getColour(int colourNumber) { return myParent->getColour(colourNumber).colour; //return Qt::blue; } int VectorImage::getColourNumber(QPointF point) { int result = -1; int areaNumber = getLastAreaNumber(point); if(areaNumber != -1) { result = area[areaNumber].colourNumber; } return result; } bool VectorImage::usesColour(int index) { for(int i=0; i< area.size(); i++) { if(area[i].colourNumber == index) return true; } for(int i=0; i< curve.size(); i++) { if(curve[i].getColourNumber() == index) return true; } return false; } void VectorImage::removeColour(int index) { for(int i=0; i< area.size(); i++) { if(area[i].getColourNumber() > index) area[i].decreaseColourNumber(); } for(int i=0; i< curve.size(); i++) { if(curve[i].getColourNumber() > index) curve[i].decreaseColourNumber(); } } void VectorImage::paintImage(QPainter &painter, bool simplified, bool showThinCurves, qreal curveOpacity, bool antialiasing, int gradients) { painter.setRenderHint(QPainter::Antialiasing, antialiasing); painter.setClipping(false); painter.setOpacity(1.0); QMatrix painterMatrix = painter.worldMatrix(); qreal scale = qAbs(painterMatrix.m11()) + qAbs(painterMatrix.m12()); // quick overestimation of sqrt( m11*m22 - m12*m21 ) QRect mappedViewRect = QRect(0,0, painter.device()->width(), painter.device()->height() ); QRectF viewRect = painterMatrix.inverted().mapRect( mappedViewRect ); // --- draw filled areas ---- if(!simplified) { for(int i=0; i< area.size(); i++) { updateArea( area[i] ); // to do: if selected // --- fill areas ---- // /*buffer = false; if(buffer) { rect = painterMatrix.mapRect( area[i].path.controlPointRect().adjusted(-gradientWidth,-gradientWidth,gradientWidth,gradientWidth) ).toRect(); rect = rect.intersected( mappedViewRect ); bufferImage = new QImage(rect.size(), QImage::Format_ARGB32_Premultiplied ); if(!bufferImage->isNull()) { bufferImage->fill(qRgba(0,0,0,0)); painter2.begin(bufferImage); painter2.setCompositionMode(QPainter::CompositionMode_Source); painter2.setRenderHint(QPainter::Antialiasing, false); painter2Matrix = painterMatrix; painter2.setWorldMatrix( painter2Matrix.translate( -rect.left()/scale, -rect.top()/scale ) ); } }*/ QColor colour = getColour(area[i].colourNumber); //if(buffer) painter2.fillPath( area[i].path, colour ); //else // ---- smooth edge ---- // //int method = 0; //if(method == 1) Gradient::paint1(painter, this, i, gradients); //if(method == 2) Gradient::paint2(painter, this, i, gradients); if(gradients == 2) Gradient::paint3(painter, this, i, gradients); if(gradients >= 3) Gradient::paint5(painter, this, i, gradients); if(gradients <= 1) { painter.setClipRect( viewRect ); painter.setClipping(true); painter.fillPath( area[i].path, colour ); } if(area[i].isSelected()) { //QBrush brush = painter.brush(); painter.save(); painter.setWorldMatrixEnabled(false); painter.setBrush( QBrush( QColor(255-colour.red(),255-colour.green(),255-colour.blue()), Qt::Dense6Pattern) ); //painter.setCompositionMode( QPainter::CompositionMode_Screen ); painter.drawPath( painter.worldMatrix().map( area[i].path ) ); //painter.setBrush( brush ); painter.restore(); painter.setWorldMatrixEnabled(true); } // -- painter.setRenderHint(QPainter::Antialiasing, antialiasing); painter.setClipping(false); } } // ---- draw curves ---- //simplified = true; painter.setClipRect( viewRect ); painter.setClipping(true); for(int i=0; i< curve.size(); i++) { curve[i].drawPath(painter, myParent, selectionTransformation, simplified, showThinCurves, curveOpacity); } //painter.resetMatrix(); ????? painter.setClipping(false); } void VectorImage::outputImage(QImage* image, QSize size, QMatrix myView, bool simplified, bool showThinCurves, qreal curveOpacity, bool antialiasing, int gradients) { //if( image->size() != size) { // delete image; // image = new QImage(size, QImage::Format_ARGB32_Premultiplied); //} image->fill(qRgba(0,0,0,0)); QPainter painter(image); painter.setWorldMatrix(myView); //painter.setClipRegion( QRegion( myView.inverted().mapToPolygon( QRect(40, 40, size.width()-80, size.height()-80) ) ) ); paintImage(painter, simplified, showThinCurves, curveOpacity, antialiasing, gradients); } void VectorImage::clear() { //image.fill(qRgba(0,0,0,0)); while(curve.size() > 0) { curve.removeAt(0); } while(area.size() > 0) { area.removeAt(0); } modification(); } void VectorImage::clean() { for(int i=0; i VectorImage::getCurvesCloseTo(QPointF P1, qreal maxDistance) { QList result; for(int j=0; j VectorImage::getVerticesCloseTo(QPointF P1, qreal maxDistance) { QList result; for(int j=0; j VectorImage::getVerticesCloseTo(QPointF P1, qreal maxDistance, QList *listOfPoints) { QList result; for(int j=0; jsize(); j++) { QPointF P2 = getVertex(listOfPoints->at(j)); qreal distance = (P1.x()-P2.x())*(P1.x()-P2.x()) + (P1.y()-P2.y())*(P1.y()-P2.y()); if( distance < maxDistance*maxDistance ) { result.append(listOfPoints->at(j)); //listOfPoints->removeAt(j); } } return result; } QList VectorImage::getVerticesCloseTo(VertexRef P1ref, qreal maxDistance) { return getVerticesCloseTo( getVertex(P1ref), maxDistance); } QList VectorImage::getVerticesCloseTo(VertexRef P1ref, qreal maxDistance, QList *listOfPoints) { return getVerticesCloseTo( getVertex(P1ref), maxDistance, listOfPoints); } QList VectorImage::getAndRemoveVerticesCloseTo(QPointF P1, qreal maxDistance, QList *listOfPoints) { QList result; //qreal distance = image.width()*image.width(); // initial big value for(int j=0; jsize(); j++) { QPointF P2 = getVertex(listOfPoints->at(j)); qreal distance = (P1.x()-P2.x())*(P1.x()-P2.x()) + (P1.y()-P2.y())*(P1.y()-P2.y()); if( distance < maxDistance*maxDistance ) { result.append(listOfPoints->at(j)); listOfPoints->removeAt(j); } } return result; } QList VectorImage::getAndRemoveVerticesCloseTo(VertexRef P1Ref, qreal maxDistance, QList *listOfPoints) { return getAndRemoveVerticesCloseTo(getVertex(P1Ref), maxDistance, listOfPoints); } QPointF VectorImage::getVertex(int curveNumber, int vertexNumber) { QPointF result = QPointF(11.11, 11.11); // bogus point if(curveNumber > -1 && curveNumber < curve.size()) { BezierCurve myCurve = curve.at(curveNumber); if( myCurve.isPartlySelected() ) myCurve = myCurve.transformed(selectionTransformation); if( vertexNumber > -2 && vertexNumber < myCurve.getVertexSize()) { result = myCurve.getVertex(vertexNumber); } } return result; } QPointF VectorImage::getVertex(VertexRef vertexRef) { return getVertex(vertexRef.curveNumber, vertexRef.vertexNumber); } QPointF VectorImage::getC1(int curveNumber, int vertexNumber) { QPointF result = QPointF(11.11, 11.11); // bogus point if(curveNumber > -1 && curveNumber < curve.size()) { BezierCurve myCurve = curve.at(curveNumber); if( myCurve.isPartlySelected() ) myCurve = myCurve.transformed(selectionTransformation); if( vertexNumber > -1 && vertexNumber < myCurve.getVertexSize()) { result = myCurve.getC1(vertexNumber); } } return result; } QPointF VectorImage::getC1(VertexRef vertexRef) { return getC1(vertexRef.curveNumber, vertexRef.vertexNumber); } QPointF VectorImage::getC2(int curveNumber, int vertexNumber) { QPointF result = QPointF(11.11, 11.11); // bogus point if(curveNumber > -1 && curveNumber < curve.size()) { BezierCurve myCurve = curve.at(curveNumber); if( myCurve.isPartlySelected() ) myCurve = myCurve.transformed(selectionTransformation); if( vertexNumber > -1 && vertexNumber < myCurve.getVertexSize()) { result = myCurve.getC2(vertexNumber); } } return result; } QPointF VectorImage::getC2(VertexRef vertexRef) { return getC2(vertexRef.curveNumber, vertexRef.vertexNumber); } QList VectorImage::getAllVertices() { QList result; for(int j=0; j -1 && curveNumber < curve.size()) { return curve.at(curveNumber).getVertexSize(); } else { return -1; } } void VectorImage::colour(QList mousePath, int colour) { QList path; VertexRef vertex, lastVertex; int incr = 0; int n = 0; for(int i=0; i < mousePath.size(); i++) { vertex = getClosestVertexTo(mousePath.at(i), 10.0); if( vertex.curveNumber != -1 && !path.contains(vertex) ) { // we found a point on a curve if( path.size() == 0) { path.append(vertex); } else { if( vertex != lastVertex ) { // unnecessary precaution if(vertex.curveNumber == lastVertex.curveNumber) { // the two vertices are on the same curve int j1 = lastVertex.vertexNumber; int j2 = vertex.vertexNumber; if(incr == 0) { // this is the beginning of a new curve n = curve.at(vertex.curveNumber).getVertexSize(); incr = 1; if( j2 < j1 ) { incr = -1; } } if(incr == 1) { if(j1 < j2) { // normal case for(int j=j1; j " << j2; VertexRef newVertex = VertexRef(vertex.curveNumber, j+1); path.append(newVertex); } } else { // special case: we join the tips of the curves //qDebug() << "Special case +1 " << " : " << j1 << " -> " << j2; for(int j=j1; j newVertex; newVertex << vertex[0] << (j+1); path.append(newVertex); VertexRef newVertex = VertexRef(vertex.curveNumber, j+1); path.append(newVertex); } for(int j=-2; j newVertex; newVertex << vertex[0] << (j+1); path.append(newVertex); VertexRef newVertex = VertexRef(vertex.curveNumber, j+1); path.append(newVertex); } } } if(incr == -1) { if(j2 < j1) { // normal case for(int j=j1; j>j2;j--) { //qDebug() << "[-1] " << (j-1) << " : " << j1 << " -> " << j2; //QList newVertex; newVertex << vertex[0] << (j-1); path.append(newVertex); VertexRef newVertex = VertexRef(vertex.curveNumber, j-1); path.append(newVertex); } } else { // special case: we join the tips of the curves //qDebug() << "Special case -1 " << " : " << j1 << " -> " << j2; for(int j=j1; j>-1;j--) { //qDebug() << "[-1] " << (j-1) << " : " << j1 << " -> " << j2; //QList newVertex; newVertex << vertex[0] << (j-1); path.append(newVertex); VertexRef newVertex = VertexRef(vertex.curveNumber, j+1); path.append(newVertex); } for(int j=n; j>j2;j--) { //qDebug() << "[-1] " << (j-1) << " : " << j1 << " -> " << j2; //QList newVertex; newVertex << vertex[0] << (j-1); path.append(newVertex); VertexRef newVertex = VertexRef(vertex.curveNumber, j+1); path.append(newVertex); } } } } else { // the two vertices are not on the same curve incr = 0; path.append(vertex); } } } lastVertex = vertex; } } BezierArea bezierArea(path, colour); addArea( bezierArea ); modification(); //qDebug() << path; //return path; } void VectorImage::addArea(BezierArea bezierArea) { updateArea(bezierArea); area.append( bezierArea ); modification(); } int VectorImage::getFirstAreaNumber(QPointF point) { int result = -1; for(int i=0; i-1 && result==-1; i--) { if( area[i].path.controlPointRect().contains( point ) ) { if( area[i].path.contains( point ) ) { result = i; } } } return result; } void VectorImage::removeArea(QPointF point) { int areaNumber = getLastAreaNumber(point); if( areaNumber != -1) { area.removeAt(areaNumber); } modification(); } void VectorImage::updateArea(BezierArea &bezierArea) { QPainterPath newPath; for(int i=0; i #include class Object; struct Intersection { QPointF point; qreal t1, t2; }; //class BezierCurve : public QObject class BezierCurve { //Q_OBJECT public: BezierCurve(); BezierCurve(QList pointList); BezierCurve(QList pointList, QList pressureList, double tol); QDomElement createDomElement(QDomDocument &doc); void loadDomElement(QDomElement element); qreal getWidth() const { return width; } qreal getFeather() const { return feather; } bool getVariableWidth() const { return variableWidth; } int getColourNumber() const { return colourNumber; } void decreaseColourNumber() { colourNumber--; } int getVertexSize() const { return vertex.size(); } QPointF getOrigin() const { return origin; } QPointF getVertex(int i) const { if(i==-1) { return origin; } else { return vertex.at(i);} } QPointF getC1(int i) const { return c1.at(i); } QPointF getC2(int i) const { return c2.at(i); } qreal getPressure(int i) const { return pressure.at(i); } bool isSelected(int i) const { return selected.at(i+1); } bool isSelected() const { bool result=true; for(int i=0;icolourNumber = colourNumber; } void setSelected(bool YesOrNo) { for(int i=0;i &pointList, QList &pressureList ); void smoothCurve(); static void simplify(double tol, QList &inputList, int j, int k, QList &markList); // general useful functions -> to be placed elsewhere? static qreal eLength(const QPointF point); // returns the Euclidean length of a point (seen as a vector) static qreal mLength(const QPointF point); // returns the Manhattan length of a point (seen as a vector) static void normalise(QPointF &point); // normalises a point (seen as a vector); static qreal findDistance(BezierCurve curve, int i, QPointF P, QPointF &nearestPoint, qreal &t); //finds the distance between a cubic section and a point static bool findIntersection(BezierCurve curve1, int i1, BezierCurve curve2, int i2, QList &intersections); //finds the intersection between two cubic sections private: QPointF origin; QList c1; QList c2; QList vertex; QList pressure; // this list has one more element than the other list (the first element is for the origin) int colourNumber; qreal width; qreal feather; bool variableWidth; //bool selected; bool invisible; QList selected; // this list has one more element than the other list (the first element is for the origin) }; #endif pencil-0.4.4b/src/graphics/vector/bezierarea.cpp0000644000175000017500000000403410641754634022364 0ustar khashayarkhashayar/* Pencil - Traditional Animation Software Copyright (C) 2005-2007 Patrick Corrieri & Pascal Naidon This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #include //#include #include "bezierarea.h" BezierArea::BezierArea() { selected = false; // nothing; } //BezierArea::BezierArea(QList > pointList, VectorImage* vectorImage) { BezierArea::BezierArea(QList vertexList, int colour) { vertex = vertexList; colourNumber = colour; selected = false; //picture = vectorImage; } VertexRef BezierArea::getVertexRef(int i) { while(i >= vertex.size() ) { i = i - vertex.size(); } while(i < 0 ) { i = i + vertex.size(); } return vertex[i]; } void BezierArea::setSelected(bool YesOrNo) { selected = YesOrNo; } QDomElement BezierArea::createDomElement(QDomDocument &doc) { QDomElement areaTag = doc.createElement("area"); areaTag.setAttribute("colourNumber", colourNumber); for(int i=0; i < vertex.size() ; i++) { QDomElement vertexTag = doc.createElement("vertex"); vertexTag.setAttribute("curve", vertex.at(i).curveNumber); vertexTag.setAttribute("vertex", vertex.at(i).vertexNumber); areaTag.appendChild(vertexTag); } return areaTag; } void BezierArea::loadDomElement(QDomElement element) { colourNumber = element.attribute("colourNumber").toInt(); QDomNode vertexTag = element.firstChild(); while(!vertexTag.isNull()) { QDomElement vertexElement = vertexTag.toElement(); if(!vertexElement.isNull()) { if(vertexElement.tagName() == "vertex") { vertex.append( VertexRef(vertexElement.attribute("curve").toInt() , vertexElement.attribute("vertex").toInt() ) ); } } vertexTag = vertexTag.nextSibling(); } } pencil-0.4.4b/src/graphics/vector/gradient.h0000644000175000017500000000223210641754634021513 0ustar khashayarkhashayar/* Pencil - Traditional Animation Software Copyright (C) 2005-2007 Patrick Corrieri & Pascal Naidon This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #ifndef GRADIENT_H #define GRADIENT_H #include //#include "vectorimage.h" class VectorImage; // forward declaration class Gradient { public: Gradient(); static void paint1(QPainter &painter, VectorImage *vectorImage, int areaNumber, int gradients); static void paint2(QPainter &painter, VectorImage *vectorImage, int areaNumber, int gradients); static void paint3(QPainter &painter, VectorImage *vectorImage, int areaNumber, int gradients); static void paint4(QPainter &painter, VectorImage *vectorImage, int areaNumber, int gradients); static void paint5(QPainter &painter, VectorImage *vectorImage, int areaNumber, int gradients); }; #endif pencil-0.4.4b/src/structure/0000755000175000017500000000000010757714676016516 5ustar khashayarkhashayarpencil-0.4.4b/src/structure/object.h0000644000175000017500000000620410744607202020115 0ustar khashayarkhashayar/* Pencil - Traditional Animation Software Copyright (C) 2005-2007 Patrick Corrieri & Pascal Naidon This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #ifndef OBJECT_H #define OBJECT_H #include #include #include #include "layer.h" #include "layerbitmap.h" #include "layervector.h" #include "colourref.h" #include "flash.h" class Object : public QObject { Q_OBJECT public slots: void modification() { modified = true; } void toggleMirror() { mirror = !mirror; } void resetMirror() { mirror = false; } void imageCheck(int); signals: void imageAdded(int); void imageAdded(int,int); void imageRemoved(int); public: Object(); virtual ~Object(); QDomElement createDomElement(QDomDocument &doc); bool loadDomElement(QDomElement element, QString filePath); bool read(QString filePath); bool write(QString filePath); QString name; bool modified; bool mirror; // if true, the returned image is flipped horizontally QList layer; QList myPalette; //void paintImage(QPainter &painter, int frameNumber, const QRectF &source, const QRectF &target, bool background, qreal curveOpacity, bool antialiasing, bool niceGradients); void paintImage(QPainter &painter, int frameNumber, bool background, qreal curveOpacity, bool antialiasing, int gradients); ColourRef getColour(int i); void setColour(int index, QColor newColour) { myPalette[index].colour = newColour; } void addColour(QColor); void addColour(ColourRef newColour) { myPalette.append(newColour); } bool removeColour(int index); void renameColour(int i, QString text); int getColourCount() { return myPalette.size();} bool importPalette(QString filePath); bool exportPalette(QString filePath); bool savePalette(QString filePath); bool loadPalette(QString filePath); void loadDefaultPalette(); void addNewBitmapLayer(); void addNewVectorLayer(); void addNewSoundLayer(); void addNewCameraLayer(); Layer* getLayer(int i); int getLayerCount() { return layer.size(); } int getMaxID(); void moveLayer(int i, int j); void deleteLayer(int i); void playSoundIfAny(int frame); void stopSoundIfAny(); void defaultInitialisation(); void exportFrames(int frameStart, int frameEnd, QMatrix view, Layer* currentLayer, QSize exportSize, QString filePath, const char* format, int quality, bool background, bool antialiasing, int gradients); void exportMovie(int startFrame, int endFrame, QMatrix view, Layer* currentLayer, QSize exportSize, QString filePath, int fps); void exportX(int frameStart, int frameEnd, QMatrix view, QSize exportSize, QString filePath, bool antialiasing, int gradients); void exportFlash(int startFrame, int endFrame, QMatrix view, QSize exportSize, QString filePath, int fps, int compression); }; #endif pencil-0.4.4b/src/structure/layercamera.cpp0000644000175000017500000002253210744607202021471 0ustar khashayarkhashayar/* Pencil - Traditional Animation Software Copyright (C) 2005-2007 Patrick Corrieri & Pascal Naidon This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #include "layercamera.h" #include Camera::Camera() { view = QMatrix(); } Camera::~Camera() { } // ------ CameraPropertiesDialog::CameraPropertiesDialog(QString name, int width, int height) : QDialog() { QLabel* nameLabel = new QLabel(tr("Camera name:")); nameBox = new QLineEdit(); nameBox->setText(name); QHBoxLayout* nameLayout = new QHBoxLayout(); nameLayout->addWidget(nameLabel); nameLayout->addWidget(nameBox); QLabel* sizeLabel = new QLabel(tr("Camera size:")); widthBox = new QSpinBox(); heightBox = new QSpinBox(); widthBox->setValue(width); heightBox->setValue(height); widthBox->setMaximum(10000); heightBox->setMaximum(10000); widthBox->setMinimum(1); heightBox->setMinimum(1); QHBoxLayout* sizeLayout = new QHBoxLayout(); sizeLayout->addWidget(sizeLabel); sizeLayout->addWidget(widthBox); sizeLayout->addWidget(heightBox); QPushButton* okButton = new QPushButton(tr("Ok")); QPushButton* cancelButton = new QPushButton(tr("Cancel")); QHBoxLayout* buttonLayout = new QHBoxLayout(); buttonLayout->addWidget(okButton); buttonLayout->addWidget(cancelButton); QGridLayout* layout = new QGridLayout(); layout->addLayout(nameLayout, 0, 0); layout->addLayout(sizeLayout, 1, 0); layout->addLayout(buttonLayout, 2, 0); setLayout(layout); connect(okButton, SIGNAL(pressed()), this, SLOT(accept())); connect(cancelButton, SIGNAL(pressed()), this, SLOT(reject())); } CameraPropertiesDialog::~CameraPropertiesDialog() { } QString CameraPropertiesDialog::getName() { return nameBox->text(); } void CameraPropertiesDialog::setName(QString name) { nameBox->setText(name); } int CameraPropertiesDialog::getWidth() { return widthBox->value(); } void CameraPropertiesDialog::setWidth(int width) { widthBox->setValue(width); } int CameraPropertiesDialog::getHeight() { return heightBox->value(); } void CameraPropertiesDialog::setHeight(int height) { heightBox->setValue(height); } // ------ LayerCamera::LayerCamera(Object* object) : LayerImage(object) { type = Layer::CAMERA; name = QString("Camera Layer"); viewRect = QRect( QPoint(-320,-240), QSize(640,480) ); dialog = NULL; addImageAtFrame(1); } LayerCamera::~LayerCamera() { while(!framesCamera.empty()) delete framesCamera.takeFirst(); } // ------ Camera* LayerCamera::getCameraAtIndex(int index) { if( index < 0 || index >= framesCamera.size() ) { return NULL; } else { return framesCamera.at(index); } } Camera* LayerCamera::getCameraAtFrame(int frameNumber) { int index = getIndexAtFrame(frameNumber); return getCameraAtIndex(index); } Camera* LayerCamera::getLastCameraAtFrame(int frameNumber, int increment) { int index = getLastIndexAtFrame(frameNumber); return getCameraAtIndex(index + increment); } QMatrix LayerCamera::getViewAtFrame(int frameNumber) { //qDebug() << ">> " << frameNumber; int index = getLastIndexAtFrame(frameNumber); int frame1 = -1; int frame2 = -1; Camera* camera1 = getCameraAtIndex(index); if(camera1) frame1 = framesPosition.at(index); Camera* camera2 = getCameraAtIndex(index+1); if(camera2) frame2 = framesPosition.at(index+1); if(camera1 == NULL && camera2 == NULL) { return QMatrix(); } if(camera1 == NULL && camera2 != NULL) { return camera2->view; } if(camera2 == NULL && camera1 != NULL) { return camera1->view; } if(camera1 != NULL && camera2 != NULL) { // linear interpolation qreal c2 = (frameNumber-frame1+0.0)/(frame2-frame1); qreal c1 = 1.0 - c2; //qDebug() << ">> -- " << c1 << c2; return QMatrix( c1*camera1->view.m11() + c2*camera2->view.m11(), c1*camera1->view.m12() + c2*camera2->view.m12(), c1*camera1->view.m21() + c2*camera2->view.m21(), c1*camera1->view.m22() + c2*camera2->view.m22(), c1*camera1->view.dx() + c2*camera2->view.dx(), c1*camera1->view.dy() + c2*camera2->view.dy() ); } } QRect LayerCamera::getViewRect() { return viewRect; } // ----- QImage* LayerCamera::getImageAtIndex(int index) { /*if( index < 0 || index >= framesImage.size() ) { return NULL; } else { return framesImage.at(index); }*/ return NULL; } bool LayerCamera::addImageAtFrame(int frameNumber) { int index = getIndexAtFrame(frameNumber); if(index == -1) { //framesImage.append(new QImage(imageSize, QImage::Format_ARGB32_Premultiplied)); Camera* camera = new Camera(); camera->view = getViewAtFrame(frameNumber); framesCamera.append(camera); framesPosition.append(frameNumber); framesSelected.append(false); framesFilename.append(""); framesModified.append(false); bubbleSort(); int frameNumber1 = frameNumber; int frameNumber2 = frameNumber; if(index>0) frameNumber1 = framesPosition.at(index-1); if(indexview = view; emit imageAdded(frameNumber); } void LayerCamera::swap(int i, int j) { LayerImage::swap(i, j); framesCamera.swap(i,j); } bool LayerCamera::saveImage(int index, QString path, int layerNumber) { QString layerNumberString = QString::number(layerNumber); QString frameNumberString = QString::number(framesPosition.at(index)); while( layerNumberString.length() < 3) layerNumberString.prepend("0"); while( frameNumberString.length() < 3) frameNumberString.prepend("0"); //framesFilename[index] = path+"/"+layerNumberString+"."+frameNumberString+".png"; framesFilename[index] = layerNumberString+"."+frameNumberString+".png"; //qDebug() << "Write " << framesFilename.at(index); //framesCamera[index]->image->save(path +"/"+ framesFilename.at(index),"PNG"); framesModified[index] = false; } void LayerCamera::editProperties() { bool ok; if(dialog == NULL) dialog = new CameraPropertiesDialog(name, viewRect.width(), viewRect.height()); dialog->setName(name); dialog->setWidth(viewRect.width()); dialog->setHeight(viewRect.height()); int result = dialog->exec(); if(result == QDialog::Accepted) { name = dialog->getName(); viewRect = QRect(-dialog->getWidth()/2, -dialog->getHeight()/2, dialog->getWidth(), dialog->getHeight()); } } QDomElement LayerCamera::createDomElement(QDomDocument &doc) { QDomElement layerTag = doc.createElement("layer"); layerTag.setAttribute("name", name); layerTag.setAttribute("visibility", visible); layerTag.setAttribute("type", type); layerTag.setAttribute("width", viewRect.width()); layerTag.setAttribute("height", viewRect.height()); for(int index=0; index < framesPosition.size() ; index++) { QDomElement keyTag = doc.createElement("camera"); keyTag.setAttribute("frame", framesPosition.at(index)); keyTag.setAttribute("m11", framesCamera[index]->view.m11()); keyTag.setAttribute("m12", framesCamera[index]->view.m12()); keyTag.setAttribute("m21", framesCamera[index]->view.m21()); keyTag.setAttribute("m22", framesCamera[index]->view.m22()); keyTag.setAttribute("dx", framesCamera[index]->view.dx()); keyTag.setAttribute("dy", framesCamera[index]->view.dy()); layerTag.appendChild(keyTag); } return layerTag; } void LayerCamera::loadDomElement(QDomElement element, QString filePath) { name = element.attribute("name"); //visible = (element.attribute("visibility") == "1"); visible = true; type = element.attribute("type").toInt(); int width = element.attribute("width").toInt(); int height = element.attribute("height").toInt(); viewRect = QRect(-width/2,-height/2,width,height); QDomNode imageTag = element.firstChild(); while(!imageTag.isNull()) { QDomElement imageElement = imageTag.toElement(); if(!imageElement.isNull()) { if(imageElement.tagName() == "camera") { int frame = imageElement.attribute("frame").toInt(); qreal m11 = imageElement.attribute("m11").toDouble(); qreal m12 = imageElement.attribute("m12").toDouble(); qreal m21 = imageElement.attribute("m21").toDouble(); qreal m22 = imageElement.attribute("m22").toDouble(); qreal dx = imageElement.attribute("dx").toDouble(); qreal dy = imageElement.attribute("dy").toDouble(); loadImageAtFrame(frame, QMatrix(m11,m12,m21,m22,dx,dy) ); } /*if(imageElement.tagName() == "image") { int frame = imageElement.attribute("frame").toInt(); addImageAtFrame( frame ); getBitmapImageAtFrame( frame )->loadDomElement(imageElement, filePath); }*/ } imageTag = imageTag.nextSibling(); } } pencil-0.4.4b/src/structure/layervector.h0000644000175000017500000000430210744607202021203 0ustar khashayarkhashayar/* Pencil - Traditional Animation Software Copyright (C) 2005-2007 Patrick Corrieri & Pascal Naidon This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #ifndef LAYERVECTOR_H #define LAYERVECTOR_H #include #include #include #include #include #include "layerimage.h" #include "vectorimage.h" class LayerVector : public LayerImage { Q_OBJECT public: LayerVector(Object* object); ~LayerVector(); // method from layerImage //QImage* getImageAtFrame(int frameNumber); //QImage* getLastImageAtFrame(int frameNumber); bool addImageAtFrame(int frameNumber); void removeImageAtFrame(int frameNumber); void loadImageAtFrame(QString, int); //void loadImageAtFrame(VectorImage, int); QImage* getImageAtIndex(int, QSize, bool, bool, qreal, bool, int); QImage* getImageAtFrame(int, QSize, bool, bool, qreal, bool, int); QImage* getLastImageAtFrame(int, int, QSize, bool, bool, qreal, bool, int); bool saveImage(int, QString, int); void setView(QMatrix view); QString fileName(int index, int layerNumber); void setModified(bool trueOrFalse); void setModified(int frameNumber, bool trueOrFalse); QDomElement createDomElement(QDomDocument &doc); void loadDomElement(QDomElement element, QString filePath); // graphic representation -- could be put in another class //void paint(QPainter &painter, int verticalPosition, int layerHeight, int frameSize, int timeLineWidth); VectorImage* getVectorImageAtIndex(int index); VectorImage* getVectorImageAtFrame(int frameNumber); VectorImage* getLastVectorImageAtFrame(int frameNumber, int increment); bool usesColour(int index); void removeColour(int index); protected: QList framesVector; QList framesImage; // bitmap output of the vector pictures void swap(int i, int j); QMatrix myView; }; #endif pencil-0.4.4b/src/structure/layer.h0000644000175000017500000000435210702435104017757 0ustar khashayarkhashayar/* Pencil - Traditional Animation Software Copyright (C) 2005-2007 Patrick Corrieri & Pascal Naidon This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #ifndef LAYER_H #define LAYER_H #include #include #include #include #include class Object; class TimeLineCells; class Layer : public QObject { Q_OBJECT public: Layer(Object* object); virtual ~Layer(); //Layer(QColor theColour, QString theName); //bool operator==(ColourRef colourRef1); //bool operator!=(ColourRef colourRef1); //virtual QImage* getImageAtFrame(int frameNumber); //virtual QImage* getLastImageAtFrame(int frameNumber); //virtual void addImageAtFrame(int frameNumber); Object* object; int type; bool visible; int id; QString name; void switchVisibility() { visible = !visible;} virtual int getMaxFrame() { return -1;} virtual QDomElement createDomElement(QDomDocument &doc); // constructs an dom/xml representation of the layer for the document doc virtual void loadDomElement(QDomElement element); // construct a layer from a dom/xml representation // graphic representation -- could be put in another class virtual void paintTrack(QPainter &painter, TimeLineCells *cells, int x, int y, int height, int width, bool selected, int frameSize); virtual void paintLabel(QPainter &painter, TimeLineCells *cells, int x, int y, int height, int width, bool selected, int allLayers); virtual void paintSelection(QPainter &painter, int x, int y, int height, int width); virtual void mousePress(QMouseEvent *event, int frameNumber); virtual void mouseMove(QMouseEvent *event, int frameNumber); virtual void mouseRelease(QMouseEvent *event, int frameNumber); virtual void mouseDoubleClick(QMouseEvent *event, int frameNumber); virtual void editProperties(); public: enum types { UNDEFINED, BITMAP, VECTOR, MOVIE, SOUND, CAMERA }; }; #endif pencil-0.4.4b/src/structure/layerbitmap.h0000644000175000017500000000276010744607202021163 0ustar khashayarkhashayar/* Pencil - Traditional Animation Software Copyright (C) 2005-2007 Patrick Corrieri & Pascal Naidon This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #ifndef LAYERBITMAP_H #define LAYERBITMAP_H #include #include #include #include #include #include "layerimage.h" #include "bitmapimage.h" class LayerBitmap : public LayerImage { Q_OBJECT public: LayerBitmap(Object* object); ~LayerBitmap(); // method from layerImage QImage* getImageAtIndex(int index); bool addImageAtFrame(int frameNumber); void removeImageAtFrame(int frameNumber); void loadImageAtFrame(QString, QPoint, int); bool saveImage(int, QString, int); QString fileName(int index, int layerNumber); QDomElement createDomElement(QDomDocument &doc); void loadDomElement(QDomElement element, QString filePath); // graphic representation -- could be put in another class BitmapImage* getBitmapImageAtIndex(int index); BitmapImage* getBitmapImageAtFrame(int frameNumber); BitmapImage* getLastBitmapImageAtFrame(int frameNumber, int increment); protected: QList framesBitmap; void swap(int i, int j); }; #endif pencil-0.4.4b/src/structure/layerimage.h0000644000175000017500000000473310744607202020773 0ustar khashayarkhashayar/* Pencil - Traditional Animation Software Copyright (C) 2005-2007 Patrick Corrieri & Pascal Naidon This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #ifndef LAYERIMAGE_H #define LAYERIMAGE_H #include #include #include #include #include #include "layer.h" class TimeLineCells; class LayerImage : public Layer { Q_OBJECT public: LayerImage(Object* object); ~LayerImage(); int getMaxFrame() { return framesPosition.last(); } int getIndexAtFrame(int frameNumber); int getLastIndexAtFrame(int frameNumber); virtual QImage* getImageAtIndex(int index); QImage* getImageAtFrame(int frameNumber); QImage* getLastImageAtFrame(int frameNumber, int increment); virtual bool addImageAtFrame(int frameNumber); virtual void removeImageAtFrame(int frameNumber); virtual void setModified(int frameNumber, bool trueOrFalse); void deselectAllFrames(); bool saveImages(QString path, int layerNumber); virtual bool saveImage(int index, QString path, int layerNumber); virtual QString fileName(int index, int layerNumber); // graphic representation -- could be put in another class void paintTrack(QPainter &painter, TimeLineCells *cells, int x, int y, int width, int height, bool selected, int frameSize); virtual void paintImages(QPainter &painter, TimeLineCells *cells, int x, int y, int width, int height, bool selected, int frameSize); void mousePress(QMouseEvent *event, int frameNumber); void mouseMove(QMouseEvent *event, int frameNumber); void mouseRelease(QMouseEvent *event, int frameNumber); void mouseDoubleClick(QMouseEvent *event, int frameNumber); signals: void imageAdded(int); void imageAdded(int,int); void imageRemoved(int); protected: //QSize imageSize; //QList framesImage; //QList framesAlpha; QList framesPosition; QList framesOriginalPosition; QList framesFilename; QList framesModified; // graphic representation -- could be put in another class QList framesSelected; int frameClicked; int frameOffset; void bubbleSort(); virtual void swap(int i, int j); }; #endif pencil-0.4.4b/src/structure/layercamera.h0000644000175000017500000000370010744607202021132 0ustar khashayarkhashayar/* Pencil - Traditional Animation Software Copyright (C) 2005-2007 Patrick Corrieri & Pascal Naidon This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #ifndef LAYERCAMERA_H #define LAYERCAMERA_H #include #include #include #include #include #include "layerimage.h" #include "bitmapimage.h" class Camera { public: Camera(); ~Camera(); QMatrix view; }; class CameraPropertiesDialog : public QDialog { Q_OBJECT public: CameraPropertiesDialog(QString name, int width, int height); ~CameraPropertiesDialog(); QString getName(); void setName(QString); int getWidth(); void setWidth(int); int getHeight(); void setHeight(int); protected: QLineEdit* nameBox; QSpinBox *widthBox, *heightBox; }; class LayerCamera : public LayerImage { Q_OBJECT public: // constructor LayerCamera(Object* object); ~LayerCamera(); // method from layerImage QImage* getImageAtIndex(int index); bool addImageAtFrame(int frameNumber); void removeImageAtFrame(int frameNumber); void loadImageAtFrame(int, QMatrix); bool saveImage(int, QString, int); void editProperties(); QDomElement createDomElement(QDomDocument &doc); void loadDomElement(QDomElement element, QString filePath); Camera* getCameraAtIndex(int index); Camera* getCameraAtFrame(int frameNumber); Camera* getLastCameraAtFrame(int frameNumber, int increment); QMatrix getViewAtFrame(int frameNumber); QRect getViewRect(); protected: QRect viewRect; CameraPropertiesDialog* dialog; QList framesCamera; void swap(int i, int j); }; #endif pencil-0.4.4b/src/structure/layerimage.cpp0000644000175000017500000002640510744607202021326 0ustar khashayarkhashayar/* Pencil - Traditional Animation Software Copyright (C) 2005-2007 Patrick Corrieri & Pascal Naidon This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #include #include "layerimage.h" #include "object.h" #include "timeline.h" LayerImage::LayerImage(Object* object) : Layer(object) { //imageSize = desiredSize; //addImageAtFrame(1); frameClicked = -1; frameOffset = 0; } LayerImage::~LayerImage() { } int LayerImage::getIndexAtFrame(int frameNumber) { int index = -1; for(int i=0; i< framesPosition.size(); i++) { if(framesPosition.at(i) == frameNumber) index = i; } return index; } int LayerImage::getLastIndexAtFrame(int frameNumber) { int position = -1; int index = -1; for(int i=0; i < framesPosition.size(); i++) { if(framesPosition.at(i) > position && framesPosition.at(i) <= frameNumber) { position = framesPosition.at(i); index = i; } } return index; } QImage* LayerImage::getImageAtIndex(int index) { return NULL; // no image -> implemented in subclasses } QImage* LayerImage::getImageAtFrame(int frameNumber) { int index = getIndexAtFrame(frameNumber); if(index == -1) { return NULL; } else { return getImageAtIndex(index); } } QImage* LayerImage::getLastImageAtFrame(int frameNumber, int increment) { int index = getLastIndexAtFrame(frameNumber); if(index == -1) { return NULL; } else { return getImageAtIndex(index + increment); } } void LayerImage::paintTrack(QPainter &painter, TimeLineCells *cells, int x, int y, int width, int height, bool selected, int frameSize) { painter.setFont(QFont("helvetica", height/2)); if(visible) { QColor col; if(type == BITMAP) col = QColor(130,130,245); if(type == VECTOR) col = QColor(100,205,150); if(type == SOUND) col = QColor(245,130,130); if(type == CAMERA) col = QColor(100,128,140); if(!selected) col = QColor( (1*col.red() + 2*200)/3, (1*col.green()+2*200)/3, (1*col.blue()+2*200)/3 ); //QColor lcol = QColor( (col.red() + 2*255)/3, (col.green()+2*255)/3, (col.blue()+2*255)/3 ); //QColor mcol = QColor( (3*col.red() + 200)/4, (3*col.green()+200)/4, (3*col.blue()+200)/4 ); painter.setBrush( col ); painter.setPen(QPen(QBrush(QColor(100,100,100)), 1, Qt::SolidLine, Qt::RoundCap,Qt::RoundJoin)); painter.drawRect(x, y-1, width, height); //painter.setFont(QFont("helvetica", height/2)); paintImages(painter, cells, x, y, width, height, selected, frameSize); //painter.drawText(QPoint(10, y+(2*height)/3), name); // changes the apparence if selected if(selected) { paintSelection(painter, x, y, width, height); /*QLinearGradient linearGrad(QPointF(0, y), QPointF(0, y + height)); linearGrad.setColorAt(0, QColor(255,255,255,128) ); linearGrad.setColorAt(0.40, QColor(255,255,255,0) ); linearGrad.setColorAt(0.60, QColor(0,0,0,0) ); linearGrad.setColorAt(1, QColor(0,0,0,64) ); painter.setBrush( linearGrad ); painter.setPen(QPen(QBrush(QColor(70,70,70)), 1, Qt::SolidLine, Qt::RoundCap,Qt::RoundJoin)); painter.drawRect(x, y-1, width, height);*/ /*for(int i=0; i< 4; i++) { //painter.setBrush(QColor(0,0,0,(80*(8-i))/8)); painter.setPen(QColor(255, 255, 255, (255*(4-i))/4)); painter.drawLine(0, y+i, width, y+i); painter.setPen(QColor(0, 0, 0, (80*(4-i))/4)); painter.drawLine(0, y+height-2-i, width, y+height-2-i); }*/ //painter.drawRect(0, y, width, height); } } else { painter.setBrush(Qt::gray); painter.setPen(QPen(QBrush(QColor(100,100,100)), 1, Qt::SolidLine, Qt::RoundCap,Qt::RoundJoin)); painter.drawRect(x, y-1, width, height); // empty rectangle by default //painter.setFont(QFont("helvetica", height/2)); //painter.drawText(QPoint(10, y+(2*height)/3), name+" (hidden)"); } //painter.drawText(QPoint(10, y+(2*height)/3),"Undefined Layer"); } void LayerImage::paintImages(QPainter &painter, TimeLineCells *cells, int x, int y, int width, int height, bool selected, int frameSize) { painter.setPen(QPen(QBrush(QColor(40,40,40)), 1, Qt::SolidLine, Qt::RoundCap,Qt::RoundJoin)); if(visible) { for(int i=0; i < framesPosition.size(); i++) { if(framesSelected.at(i)) { painter.setBrush(QColor(60,60,60)); //painter.drawRect(x+(framesPosition.at(i)+frameOffset-1)*frameSize+2, y+1, frameSize-2, height-4); painter.drawRect( cells->getFrameX(framesPosition.at(i)+frameOffset)-frameSize+2, y+1, frameSize-2, height-4); } else { if(selected) painter.setBrush(QColor(125,125,125)); else painter.setBrush(QColor(125,125,125,125)); if(framesModified.at(i)) painter.setBrush(QColor(255,125,125,125)); painter.drawRect( cells->getFrameX(framesPosition.at(i))-frameSize+2, y+1, frameSize-2, height-4 ); //painter.drawRect(x+(framesPosition.at(i)-1)*frameSize+2, y+1, frameSize-2, height-4); //painter.drawText(QPoint( (framesPosition.at(i)-1)*frameSize+5, y+(2*height)/3), QString::number(i) ); } } } } void LayerImage::mousePress(QMouseEvent *event, int frameNumber) { frameClicked = frameNumber; int index = getIndexAtFrame(frameNumber); if(index == -1) { deselectAllFrames(); } else { if( (event->modifiers() != Qt::ShiftModifier) && (!framesSelected.at(index)) && (event->buttons() != Qt::RightButton) ) { deselectAllFrames(); } framesSelected[index] = true; } if(event->modifiers() == Qt::AltModifier) { for(int i=index; i < framesPosition.size(); i++) { framesSelected[i] = true; } } } void LayerImage::mouseDoubleClick(QMouseEvent *event, int frameNumber) { int index = getIndexAtFrame(frameNumber); if(index != -1) { for(int i=index; i < framesPosition.size(); i++) { framesSelected[i] = true; } } } void LayerImage::mouseMove(QMouseEvent *event, int frameNumber) { frameOffset = frameNumber - frameClicked; bool ok = true; for(int i=0; i < framesPosition.size(); i++) { if(framesSelected.at(i)) { if(framesPosition.at(i) + frameOffset < 1) ok = false; for(int j=0; j < framesPosition.size(); j++) { if(!framesSelected.at(j)) { if(framesPosition.at(i) + frameOffset == framesPosition.at(j)) { ok = false; } } } } } if(ok == false) frameOffset = 0; } void LayerImage::mouseRelease(QMouseEvent *event, int frameNumber) { for(int i=0; i < framesPosition.size(); i++) { if(framesSelected.at(i) && frameOffset != 0) { int originalFrame = framesPosition[i]; framesPosition[i] = originalFrame + frameOffset; //framesModified[i] = true; emit imageRemoved(originalFrame); // this is to indicate to the cache that an image have been removed here emit imageAdded(originalFrame + frameOffset); // this is to indicate to the cache that an image have been added here object->modification(); } } bubbleSort(); frameOffset = 0; } bool LayerImage::addImageAtFrame(int frameNumber) { int index = getIndexAtFrame(frameNumber); if(index == -1) { framesPosition.append(frameNumber); framesOriginalPosition.append(frameNumber); framesSelected.append(false); framesFilename.append(""); framesModified.append(false); bubbleSort(); emit imageAdded(frameNumber); return true; } else { return false; } } void LayerImage::removeImageAtFrame(int frameNumber) { int index = getIndexAtFrame(frameNumber); if(index != -1) { framesPosition.removeAt(index); framesOriginalPosition.removeAt(index); framesSelected.removeAt(index); framesFilename.removeAt(index); framesModified.removeAt(index); emit imageRemoved(frameNumber); } bubbleSort(); } void LayerImage::bubbleSort() { // from http://fr.wikipedia.org/wiki/Tri_a_bulles int i = 0; /* Indice de repetition du tri */ int j = 0; /* Variable de boucle */ int MAX = framesPosition.size(); /* taille du tableau */ /* Booleen marquant l'arret du tri si le tableau est ordonne */ bool en_desordre = true; /* Boucle de repetition du tri et le test qui arrete le tri des que le tableau est ordonne */ for(i = 0 ; (i < MAX ) && en_desordre; i++) { /* Supposons le tableau ordonne */ en_desordre = false; /* Verification des elements des places j et j-1 */ for(j = 1 ; j < MAX - i ; j++) { /* Si les 2 elements sont mal tries */ if(framesPosition[j] < framesPosition[j-1]) { /* Inversion des 2 elements */ swap(j-1,j); /* Le tableau n'est toujours pas trie */ en_desordre = true; } } } } void LayerImage::swap(int i, int j) { framesPosition.swap(i,j); framesOriginalPosition.swap(i,j); framesSelected.swap(i,j); framesFilename.swap(i,j); framesModified.swap(i,j); } void LayerImage::setModified(int frameNumber, bool trueOrFalse) { int index = getLastIndexAtFrame(frameNumber); if(index != -1) { framesModified[index] = trueOrFalse; object->modification(); } } void LayerImage::deselectAllFrames() { for(int i=0; i < framesPosition.size(); i++) { framesSelected[i] = false; } } bool LayerImage::saveImages(QString path, int layerNumber) { qDebug() << "Save images... "; QDir dir(path); //qDebug() << dir.exists() << dir.path(); //qDebug() << framesPosition; //qDebug() << framesOriginalPosition; // --- we test if all the files already exists for(int i=0; i < framesPosition.size(); i++) { QString fileName = framesFilename.at(i); qDebug() << "Testing if (" << i << ") " << fileName << " exists"; bool test = dir.exists(fileName); if(!test) { qDebug() << "--- The file does not seem to exist."; framesModified[i] = true; } } // --- we rename the files for the images which have been moved (if such files exist) // --- we do that in two steps, with temporary names in the first step, in order to avoid conflicting names for(int i=0; i < framesPosition.size(); i++) { int frame1 = framesPosition.at(i); int frame0 = framesOriginalPosition.at(i); if(frame1 != frame0 && framesFilename.at(i) != "") { QString fileName0 = fileName(frame0,layerNumber); QString fileName1 = fileName(frame1,layerNumber); //qDebug() << fileName0 << fileName1; bool rename = dir.rename( fileName0, "tmp"+fileName0 ); if(rename) { } } } for(int i=0; i < framesPosition.size(); i++) { int frame1 = framesPosition.at(i); int frame0 = framesOriginalPosition.at(i); if(frame1 != frame0 && framesFilename.at(i) != "") { QString fileName0 = fileName(frame0,layerNumber); QString fileName1 = fileName(frame1,layerNumber); bool rename = dir.rename( "tmp"+fileName0, fileName1 ); if(rename) { framesOriginalPosition[i] = frame1; framesFilename[i] = fileName1; qDebug() << "Rename to " << framesFilename.at(i); } else { // the file doesn't exist, we probably need to create it qDebug() << "Could not rename to " << framesFilename.at(i); framesFilename[i] = ""; framesModified[i] = true; } } } // --- we now save the files for the images which have been modified for(int i=0; i < framesPosition.size(); i++) { if(framesModified.at(i)) { qDebug() << "Trying to save " << framesFilename.at(i); saveImage(i, path, layerNumber); } } qDebug() << "done"; } bool LayerImage::saveImage(int index, QString path, int layerNumber) { // implemented in subclasses } QString LayerImage::fileName(int index, int layerNumber) { // implemented in subclasses return ""; } pencil-0.4.4b/src/structure/layersound.cpp0000644000175000017500000001315210744607202021367 0ustar khashayarkhashayar/* Pencil - Traditional Animation Software Copyright (C) 2005-2007 Patrick Corrieri & Pascal Naidon This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #include #include "layersound.h" #include "object.h" LayerSound::LayerSound(Object* object) : LayerImage(object) { type = Layer::SOUND; //modified = false; name = QString("Sound Layer"); } LayerSound::~LayerSound() { while(!sound.empty()) delete sound.takeFirst(); } void LayerSound::paintImages(QPainter &painter, TimeLineCells *cells, int x, int y, int width, int height, bool selected, int frameSize) { for(int i=0; i < sound.size(); i++) { qreal h = x + (framesPosition.at(i)-1)*frameSize+2; if(framesSelected.at(i)) { painter.setBrush(QColor(60,60,60)); h = h + frameOffset*frameSize; // painter.drawRect((framesPosition.at(i)+frameOffset-1)*frameSize+2, verticalPosition+1, frameSize-2, layerHeight-4); } else { // if(framesModified.at(i)) // painter.setBrush(QColor(255,125,125)); // else //painter.setPen(QPen(QBrush(QColor(40,40,40)), 1, Qt::SolidLine, Qt::RoundCap,Qt::RoundJoin)); painter.setBrush(QColor(125,125,125)); } QPointF points[3] = { QPointF(h, y+4), QPointF(h, y+height-4), QPointF(h+15, y+0.5*height) }; painter.drawPolygon( points, 3 ); //painter.drawRect((startingFrame.at(i)-1)*frameSize+2, verticalPosition+1, frameSize-2, layerHeight-4); painter.drawText(QPoint( h + 20, y+(2*height)/3), framesFilename.at(i) ); //} } } bool LayerSound::addImageAtFrame(int frameNumber) { int index = getIndexAtFrame(frameNumber); if(index == -1) { sound.append(NULL); soundFilepath.append(""); framesPosition.append(frameNumber); framesSelected.append(false); framesFilename.append(""); framesModified.append(false); bubbleSort(); return true; } else { return false; } } void LayerSound::removeImageAtFrame(int frameNumber) { int index = getIndexAtFrame(frameNumber); if(index != -1 && framesPosition.size() != 1) { delete sound.at(index); soundFilepath.removeAt(index); framesPosition.removeAt(index); framesSelected.removeAt(index); framesFilename.removeAt(index); framesModified.removeAt(index); bubbleSort(); } } void LayerSound::loadSoundAtFrame(QString filePathString, int frameNumber) { if(getIndexAtFrame(frameNumber) == -1) addImageAtFrame(frameNumber); int index = getIndexAtFrame(frameNumber); QFileInfo fi(filePathString); if(fi.exists()) { sound[index] = new QSound(filePathString, NULL); soundFilepath[index] = filePathString; framesFilename[index] = fi.fileName(); } else { sound[index] = NULL; soundFilepath[index] = "Wrong file"; framesFilename[index] = "Wrong file" + filePathString; } } void LayerSound::swap(int i, int j) { LayerImage::swap(i, j); sound.swap(i,j); soundFilepath.swap(i,j); } bool LayerSound::saveImage(int index, QString path, int layerNumber) { /*QString layerNumberString = QString::number(layerNumber); QString frameNumberString = QString::number(framesPosition.at(index)); while( layerNumberString.length() < 3) layerNumberString.prepend("0"); while( frameNumberString.length() < 3) frameNumberString.prepend("0");*/ //framesFilename[index] = path+"/"+layerNumberString+"."+frameNumberString+".png"; //framesFilename[index] = layerNumberString+"."+frameNumberString+".png"; //framesFilename[index] = layerNumberString+"."+frameNumberString+".png"; //qDebug() << "Write " << framesFilename.at(index); //framesImage[index]->save(framesFilename.at(index),"PNG"); QFile originalFile( soundFilepath.at(index) ); originalFile.copy( path + "/" + framesFilename.at(index) ); framesModified[index] = false; } void LayerSound::playSound(int frame) { for(int i=0; i < sound.size(); i++) { if(frame == framesPosition.at(i)) { if(sound.at(i) != NULL && visible) sound[i]->play(); } } } void LayerSound::stopSound() { for(int i=0; i < sound.size(); i++) { if(sound.at(i) != NULL) sound[i]->stop(); } } QDomElement LayerSound::createDomElement(QDomDocument &doc) { QDomElement layerTag = doc.createElement("layer"); layerTag.setAttribute("id",id); layerTag.setAttribute("name", name); layerTag.setAttribute("visibility", visible); layerTag.setAttribute("type", type); for(int index=0; index < framesPosition.size() ; index++) { QDomElement soundTag = doc.createElement("sound"); soundTag.setAttribute("position", framesPosition.at(index)); soundTag.setAttribute("src", framesFilename.at(index)); layerTag.appendChild(soundTag); } return layerTag; } void LayerSound::loadDomElement(QDomElement element, QString filePath) { if(!element.attribute("id").isNull()) id = element.attribute("id").toInt(); name = element.attribute("name"); visible = (element.attribute("visibility") == "1"); type = element.attribute("type").toInt(); QDomNode soundTag = element.firstChild(); while(!soundTag.isNull()) { QDomElement soundElement = soundTag.toElement(); if(!soundElement.isNull()) { if(soundElement.tagName() == "sound") { QString path = filePath + ".data/" + soundElement.attribute("src"); // the file is supposed to be in the data irectory QFileInfo fi(path); if(!fi.exists()) path = soundElement.attribute("src"); int position = soundElement.attribute("position").toInt(); loadSoundAtFrame( path, position ); } } soundTag = soundTag.nextSibling(); } } pencil-0.4.4b/src/structure/layervector.cpp0000644000175000017500000002171010744607202021540 0ustar khashayarkhashayar/* Pencil - Traditional Animation Software Copyright (C) 2005-2007 Patrick Corrieri & Pascal Naidon This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #include "layervector.h" #include LayerVector::LayerVector(Object* object) : LayerImage(object) { type = Layer::VECTOR; name = QString("Vector Layer"); addImageAtFrame(1); //framesVector.append(new VectorImage(imageSize, QImage::Format_ARGB32_Premultiplied, object)); } LayerVector::~LayerVector() { while (!framesVector.empty()) delete framesVector.takeFirst(); while (!framesImage.empty()) delete framesImage.takeFirst(); } // ------ QImage* LayerVector::getImageAtIndex(int index, QSize size, bool simplified, bool showThinLines, qreal curveOpacity, bool antialiasing, int gradients) { if( index < 0 || index >= framesImage.size() ) { return NULL; } else { VectorImage* vectorImage = getVectorImageAtIndex(index); QImage* image = framesImage.at(index); if(vectorImage->isModified() || size != image->size() ) { if( image->size() != size) { delete image; framesImage[index] = image = new QImage(size, QImage::Format_ARGB32_Premultiplied); } vectorImage->outputImage(image, size, myView, simplified, showThinLines, curveOpacity, antialiasing, gradients); vectorImage->setModified(false); } return image; } } QImage* LayerVector::getImageAtFrame(int frameNumber, QSize size, bool simplified, bool showThinLines, qreal curveOpacity, bool antialiasing, int gradients) { int index = getIndexAtFrame(frameNumber); if(index == -1) { return NULL; } else { return getImageAtIndex(index, size, simplified, showThinLines, curveOpacity, antialiasing, gradients); } } QImage* LayerVector::getLastImageAtFrame(int frameNumber, int increment, QSize size, bool simplified, bool showThinLines, qreal curveOpacity, bool antialiasing, int gradients) { int index = getLastIndexAtFrame(frameNumber); if(index == -1) { return NULL; } else { return getImageAtIndex(index + increment, size, simplified, showThinLines, curveOpacity, antialiasing, gradients); } } // ------ VectorImage* LayerVector::getVectorImageAtIndex(int index) { if( index < 0 || index >= framesVector.size() ) { return NULL; } else { return framesVector.at(index); } } VectorImage* LayerVector::getVectorImageAtFrame(int frameNumber) { int index = getIndexAtFrame(frameNumber); return getVectorImageAtIndex(index); } VectorImage* LayerVector::getLastVectorImageAtFrame(int frameNumber, int increment) { int index = getLastIndexAtFrame(frameNumber); return getVectorImageAtIndex(index + increment); } void LayerVector::setView(QMatrix view) { myView = view; setModified(true); } void LayerVector::setModified(bool trueOrFalse) { for(int i=0; i < framesVector.size(); i++) { framesVector[i]->setModified(trueOrFalse); } } void LayerVector::setModified(int frameNumber, bool trueOrFalse) { LayerImage::setModified(frameNumber, trueOrFalse); getLastVectorImageAtFrame(frameNumber, 0)->setModified(trueOrFalse); } // ----- bool LayerVector::usesColour(int index) { for(int i=0; i < framesVector.size(); i++) { if( framesVector[i]->usesColour(index) ) return true; } return false; } void LayerVector::removeColour(int index) { for(int i=0; i < framesVector.size(); i++) { framesVector[i]->removeColour(index); } } /*void LayerBitmap::paint(QPainter &painter, int verticalPosition, int layerHeight, int frameSize, int timeLineWidth) { painter.setBrush(QColor(128,128,255)); painter.setPen(QPen(QBrush(Qt::black), 1, Qt::SolidLine, Qt::RoundCap,Qt::RoundJoin)); painter.drawRect(0, verticalPosition, timeLineWidth, layerHeight); for(int i=0; i < framesPosition.size(); i++) { if(framesSelected.at(i)) { painter.setBrush(QColor(10,10,10)); painter.drawRect((framesPosition.at(i)+frameOffset-1)*frameSize, verticalPosition, frameSize, layerHeight); } else { painter.setBrush(QColor(75,75,75)); painter.drawRect((framesPosition.at(i)-1)*frameSize, verticalPosition, frameSize, layerHeight); } } //painter.setFont(QFont("helvetica", layerHeight/2)); //painter.drawText(QPoint(10, verticalPosition+(2*layerHeight)/3),"Undefined Layer"); } void LayerBitmap::mousePress(int frameNumber) { frameClicked = frameNumber; int index = getIndexAtFrame(frameNumber); if(index == -1) { // deselect all for(int i=0; i < framesPosition.size(); i++) { framesSelected[i] = false; } } else { framesSelected[index] = true; } }*/ bool LayerVector::addImageAtFrame(int frameNumber) { int index = getIndexAtFrame(frameNumber); if(index == -1) { //framesVector.append(new VectorImage(imageSize, QImage::Format_ARGB32_Premultiplied, object)); framesVector.append(new VectorImage(object)); framesImage.append(new QImage( QSize(2,2), QImage::Format_ARGB32_Premultiplied)); // very small image to begin with framesPosition.append(frameNumber); framesOriginalPosition.append(frameNumber); framesSelected.append(false); framesFilename.append(""); framesModified.append(false); bubbleSort(); emit imageAdded(frameNumber); return true; } else { return false; } } void LayerVector::removeImageAtFrame(int frameNumber) { int index = getIndexAtFrame(frameNumber); if(index != -1 && framesPosition.size() != 1) { delete framesVector.at(index); framesVector.removeAt(index); delete framesImage.at(index); framesImage.removeAt(index); framesPosition.removeAt(index); framesOriginalPosition.removeAt(index); framesSelected.removeAt(index); framesFilename.removeAt(index); framesModified.removeAt(index); bubbleSort(); emit imageRemoved(frameNumber); } } void LayerVector::loadImageAtFrame(QString path, int frameNumber) { if(getIndexAtFrame(frameNumber) == -1) addImageAtFrame(frameNumber); int index = getIndexAtFrame(frameNumber); framesVector[index]->read(path); QFileInfo fi(path); framesFilename[index] = fi.fileName(); } /*void LayerVector::loadImageAtFrame(VectorImage* picture, int frameNumber) { if(getIndexAtFrame(frameNumber) == -1) addImageAtFrame(frameNumber); int index = getIndexAtFrame(frameNumber); //image.convertToFormat(QImage::Format_ARGB32_Premultiplied); framesVector[index] = picture; }*/ void LayerVector::swap(int i, int j) { LayerImage::swap(i, j); framesVector.swap(i,j); framesImage.swap(i,j); } bool LayerVector::saveImage(int index, QString path, int layerNumber) { int theFrame = framesPosition.at(index); QString theFileName = fileName(theFrame, id); framesFilename[index] = theFileName; //qDebug() << "Write " << theFileName; framesVector[index]->write(path +"/"+ theFileName,"VEC"); framesModified[index] = false; } QString LayerVector::fileName(int frame, int layerID) { QString layerNumberString = QString::number(layerID); QString frameNumberString = QString::number(frame); while( layerNumberString.length() < 3) layerNumberString.prepend("0"); while( frameNumberString.length() < 3) frameNumberString.prepend("0"); return layerNumberString+"."+frameNumberString+".vec"; } QDomElement LayerVector::createDomElement(QDomDocument &doc) { QDomElement layerTag = doc.createElement("layer"); layerTag.setAttribute("id", id); layerTag.setAttribute("name", name); layerTag.setAttribute("visibility", visible); layerTag.setAttribute("type", type); for(int index=0; index < framesPosition.size() ; index++) { //QDomElement imageTag = framesVector[index]->createDomElement(doc); // if we want to embed the data QDomElement imageTag = doc.createElement("image"); imageTag.setAttribute("frame", framesPosition.at(index)); imageTag.setAttribute("src", framesFilename.at(index)); // if we want to link the data to an external file layerTag.appendChild(imageTag); } return layerTag; } void LayerVector::loadDomElement(QDomElement element, QString filePath) { if(!element.attribute("id").isNull()) id = element.attribute("id").toInt(); name = element.attribute("name"); visible = (element.attribute("visibility") == "1"); type = element.attribute("type").toInt(); QDomNode imageTag = element.firstChild(); while(!imageTag.isNull()) { QDomElement imageElement = imageTag.toElement(); if(!imageElement.isNull()) { if(imageElement.tagName() == "image") { if(!imageElement.attribute("src").isNull()) { QString path = filePath +".data/" + imageElement.attribute("src"); // the file is supposed to be in the data irectory QFileInfo fi(path); if(!fi.exists()) path = imageElement.attribute("src"); int position = imageElement.attribute("frame").toInt(); loadImageAtFrame( path, position ); } else { int frame = imageElement.attribute("frame").toInt(); addImageAtFrame( frame ); getVectorImageAtFrame( frame )->loadDomElement(imageElement); } } } imageTag = imageTag.nextSibling(); } } pencil-0.4.4b/src/structure/layer.cpp0000644000175000017500000001602110702435104020306 0ustar khashayarkhashayar/* Pencil - Traditional Animation Software Copyright (C) 2005-2007 Patrick Corrieri & Pascal Naidon This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #include #include #include "layer.h" #include "object.h" #include "timeline.h" Layer::Layer(Object* object) : QObject(0) { this->object = object; type = Layer::UNDEFINED; id = 0; name = QString("Undefined Layer"); visible = true; } Layer::~Layer() {} //QImage* Layer::getImageAtFrame(int frameNumber) { // qDebug() << "get image from undefined layer!"; // return NULL; // null by default //} //QImage* Layer::getLastImageAtFrame(int frameNumber) { // qDebug() << "get last image from undefined layer!"; // return NULL; // null by default //} QDomElement Layer::createDomElement(QDomDocument &doc) { QDomElement layerTag = doc.createElement("layer"); layerTag.setAttribute("name", name); layerTag.setAttribute("visibility", visible); layerTag.setAttribute("type", type); return layerTag; } void Layer::loadDomElement(QDomElement element) { name = element.attribute("name"); visible = (element.attribute("visibility") == "1"); type = element.attribute("type").toInt(); } void Layer::paintTrack(QPainter &painter, TimeLineCells *cells, int x, int y, int width, int height, bool selected, int frameSize) { painter.setBrush(Qt::lightGray); painter.setPen(QPen(QBrush(QColor(100,100,100)), 1, Qt::SolidLine, Qt::RoundCap,Qt::RoundJoin)); painter.drawRect(x, y, width, height); // empty rectangle by default //painter.setFont(QFont("helvetica", height/2)); //painter.drawText(QPoint(10, y+(2*height)/3), name); //if(selected) { // painter.setBrush(QColor(0,0,0,80)); // painter.drawRect(x, y-1, width, height); //} if(selected) { QLinearGradient linearGrad(QPointF(0, y), QPointF(0, y + height)); linearGrad.setColorAt(0, QColor(255,255,255,128) ); linearGrad.setColorAt(0.40, QColor(255,255,255,0) ); linearGrad.setColorAt(0.60, QColor(0,0,0,0) ); linearGrad.setColorAt(1, QColor(0,0,0,64) ); painter.setBrush( linearGrad ); painter.setPen(QPen(QBrush(QColor(70,70,70)), 1, Qt::SolidLine, Qt::RoundCap,Qt::RoundJoin)); painter.drawRect(x, y-1, width, height); } } void Layer::paintLabel(QPainter &painter, TimeLineCells *cells, int x, int y, int width, int height, bool selected, int allLayers) { painter.setBrush(Qt::lightGray); painter.setPen(QPen(QBrush(QColor(100,100,100)), 1, Qt::SolidLine, Qt::RoundCap,Qt::RoundJoin)); painter.drawRect(x, y-1, width, height); // empty rectangle by default if(visible) { if(allLayers==0) painter.setBrush(Qt::NoBrush); if(allLayers==1) painter.setBrush(Qt::darkGray); if((allLayers==2) || selected) painter.setBrush(Qt::black); } else { painter.setBrush(Qt::NoBrush); } painter.setPen(Qt::black); painter.setRenderHint(QPainter::Antialiasing, true); painter.drawEllipse(x+6, y+4, 9, 9); painter.setRenderHint(QPainter::Antialiasing, false); /*if(selected) { painter.setPen(Qt::NoPen); painter.setBrush(QColor(0,0,0,80)); painter.drawRect(x, y-1, width, height); }*/ if(selected) { paintSelection(painter, x, y, width, height); } if(type == BITMAP) painter.drawPixmap( QPoint(20, y+2), QPixmap(":/icons/layer-bitmap.png") ); if(type == VECTOR) painter.drawPixmap( QPoint(20, y+2), QPixmap(":/icons/layer-vector.png") ); if(type == SOUND) painter.drawPixmap( QPoint(21, y+2), QPixmap(":/icons/layer-sound.png") ); if(type == CAMERA) painter.drawPixmap( QPoint(21, y+2), QPixmap(":/icons/layer-camera.png") ); painter.setFont(QFont("helvetica", height/2)); painter.setPen(Qt::black); painter.drawText(QPoint(45, y+(2*height)/3), name); } void Layer::paintSelection(QPainter &painter, int x, int y, int width, int height) { QLinearGradient linearGrad(QPointF(0, y), QPointF(0, y + height)); QSettings settings("Pencil","Pencil"); QString style = settings.value("style").toString(); if(style == "aqua") { linearGrad.setColorAt(0, QColor(225,225,255,100) ); linearGrad.setColorAt(0.10, QColor(225,225,255,80) ); linearGrad.setColorAt(0.20, QColor(225,225,255,64) ); linearGrad.setColorAt(0.35, QColor(225,225,255,20) ); linearGrad.setColorAt(0.351, QColor(0,0,0,32) ); linearGrad.setColorAt(0.66, QColor(245,255,235,32) ); linearGrad.setColorAt(1, QColor(245,255,235,128) ); } else { linearGrad.setColorAt(0, QColor(255,255,255,128) ); linearGrad.setColorAt(0.49, QColor(255,255,255,0) ); linearGrad.setColorAt(0.50, QColor(0,0,0,0) ); linearGrad.setColorAt(1, QColor(0,0,0,48) ); /*linearGrad.setColorAt(0, QColor(255,255,255,128) ); linearGrad.setColorAt(0.10, QColor(255,255,255,64) ); linearGrad.setColorAt(0.49, QColor(0,0,0,32) ); linearGrad.setColorAt(0.50, QColor(0,0,0,32) ); linearGrad.setColorAt(0.70, QColor(245,255,245,32) ); linearGrad.setColorAt(1, QColor(245,255,245,128) );*/ /*linearGrad.setColorAt(0, QColor(255,255,255,128) ); linearGrad.setColorAt(0.10, QColor(255,255,255,64) ); linearGrad.setColorAt(0.20, QColor(0,0,0,32) ); linearGrad.setColorAt(0.40, QColor(0,0,0,0) ); linearGrad.setColorAt(0.41, QColor(255,255,255,0) ); linearGrad.setColorAt(1, QColor(255,255,255,128) );*/ } painter.setBrush( linearGrad ); painter.setPen( Qt::NoPen ); painter.drawRect(x, y, width, height-1); //painter.setBrush( Qt::NoBrush ); //painter.setPen(QPen(QBrush(QColor(0,0,0,100)), 1, Qt::SolidLine, Qt::RoundCap,Qt::RoundJoin)); //painter.drawRect(x, y-1, width, height); /*if(style == "aqua") { QColor col; if(type == BITMAP) col = QColor(65,65,122); if(type == VECTOR) col = QColor(50,102,75); if(type == SOUND) col = QColor(122,65,65); painter.setPen(col); painter.drawLine(x,y-1, x+width, y-1); }*/ } void Layer::mousePress(QMouseEvent *event, int frameNumber) { } void Layer::mouseDoubleClick(QMouseEvent *event, int frameNumber) { } void Layer::mouseMove(QMouseEvent *event, int frameNumber) { } void Layer::mouseRelease(QMouseEvent *event, int frameNumber) { } void Layer::editProperties() { bool ok; QString text = QInputDialog::getText(NULL, tr("Layer Properties"), tr("Layer name:"), QLineEdit::Normal, name, &ok); if (ok && !text.isEmpty()) { name = text; //palette->updateList(); } } //void Layer::addImageAtFrame(int frameNumber) { // nothing by default //} /*Layer::Layer(QColor theColour, QString theName) { colour = theColour; name = theName; }*/ /*bool Layer::operator==(Layer colourRef1) { if( (colour == colourRef1.colour) && (name == colourRef1.name) ) { return true; } else { return false; } } bool Layer::operator!=(Layer colourRef1) { if( (colour != colourRef1.colour) || (name != colourRef1.name) ) { return true; } else { return false; } }*/ pencil-0.4.4b/src/structure/object.cpp0000644000175000017500000004043410744607202020453 0ustar khashayarkhashayar/* Pencil - Traditional Animation Software Copyright (C) 2005-2007 Patrick Corrieri & Pascal Naidon This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #include #include #include #include #include "object.h" #include "layer.h" #include "layerbitmap.h" #include "layervector.h" #include "layersound.h" #include "layercamera.h" #include "editor.h" #include "bitmapimage.h" // ******* Mac-specific: ******** (please comment (or reimplement) the lines below to compile on Windows or Linux //#include // ****************************** Object::Object() : QObject(0) { // default name name = "Object"; modified = false; mirror = false; } Object::~Object() { while(!layer.empty()) { delete layer.takeLast(); } } QDomElement Object::createDomElement(QDomDocument &doc) { QDomElement tag = doc.createElement("object"); for(int i=0; i < getLayerCount(); i++) { Layer* layer = getLayer(i); QDomElement layerTag = layer->createDomElement(doc); tag.appendChild(layerTag); } return tag; } bool Object::loadDomElement(QDomElement docElem, QString filePath) { if(docElem.isNull()) return false; int layerNumber = -1; QDomNode tag = docElem.firstChild(); bool someRelevantData = false; while(!tag.isNull()) { QDomElement element = tag.toElement(); // try to convert the node to an element. if(!element.isNull()) { if(element.tagName() == "layer") { someRelevantData = true; // --- bitmap layer --- if(element.attribute("type").toInt() == Layer::BITMAP) { addNewBitmapLayer(); layerNumber++; ((LayerBitmap*)(getLayer(layerNumber)))->loadDomElement( element, filePath ); } // --- vector layer --- if(element.attribute("type").toInt() == Layer::VECTOR) { addNewVectorLayer(); layerNumber++; ((LayerVector*)(getLayer(layerNumber)))->loadDomElement( element, filePath ); } // --- sound layer --- if(element.attribute("type").toInt() == Layer::SOUND) { addNewSoundLayer(); layerNumber++; ((LayerSound*)(getLayer(layerNumber)))->loadDomElement( element, filePath ); } // --- camera layer --- if(element.attribute("type").toInt() == Layer::CAMERA) { addNewCameraLayer(); layerNumber++; ((LayerCamera*)(getLayer(layerNumber)))->loadDomElement( element, filePath ); } } } tag = tag.nextSibling(); } return someRelevantData; } bool Object::read(QString filePath) { QFileInfo fileInfo(filePath); if( fileInfo.isDir() ) return false; QFile* file = new QFile(filePath); if (!file->open(QFile::ReadOnly)) return false; QDomDocument doc; doc.setContent(file); QDomElement docElem = doc.documentElement(); loadDomElement(docElem, filePath); /* // old code: list all the files beginning with the same name QStringList list = name.split("."); QStringList filtername(list.at(0)+"*.*"); QDir dir(fileInfo.absolutePath()); QStringList entries = dir.entryList(filtername,QDir::Files,QDir::Type); */ return true; } bool Object::write(QString filePath) { QFile* file = new QFile(filePath); if (!file->open(QFile::WriteOnly | QFile::Text)) { //QMessageBox::warning(this, "Warning", "Cannot write file"); qDebug() << "Object - Cannot write file" << filePath; return false; } QTextStream out(file); QDomDocument doc("PencilDocument"); QDomElement root = createDomElement(doc); doc.appendChild(root); int IndentSize = 2; qDebug() << "--- Starting to write XML file..."; doc.save(out, IndentSize); file->close(); qDebug() << "--- Writing XML file done."; return true; } void Object::addNewBitmapLayer() { LayerBitmap* layerBitmap = new LayerBitmap(this); layerBitmap->id = 1+getMaxID(); layer.append( layerBitmap ); connect( layerBitmap, SIGNAL(imageAdded(int)), this, SIGNAL(imageAdded(int)) ); connect( layerBitmap, SIGNAL(imageRemoved(int)), this, SLOT(imageCheck(int)) ); } void Object::addNewVectorLayer() { LayerVector* layerVector = new LayerVector(this); layerVector->id = 1+getMaxID(); layer.append( layerVector ); connect( layerVector, SIGNAL(imageAdded(int)), this, SIGNAL(imageAdded(int)) ); connect( layerVector, SIGNAL(imageRemoved(int)), this, SLOT(imageCheck(int)) ); } void Object::addNewSoundLayer() { LayerSound* layerSound = new LayerSound(this); layerSound->id = 1+getMaxID(); layer.append( layerSound ); } void Object::addNewCameraLayer() { LayerCamera* layerCamera = new LayerCamera(this); layerCamera->id = 1+getMaxID(); layer.append( layerCamera ); connect( layerCamera, SIGNAL(imageAdded(int,int)), this, SIGNAL(imageAdded(int,int)) ); connect( layerCamera, SIGNAL(imageRemoved(int)), this, SLOT(imageCheck(int)) ); } int Object::getMaxID() { int result = 0; for(int i=0; i< getLayerCount(); i++) { Layer* layeri = getLayer(i); if(layeri->id > result) result = layeri->id; } return result; } Layer* Object::getLayer(int i) { if(i > -1 && i < getLayerCount()) { return layer.at(i); } else { return NULL; } } void Object::moveLayer(int i, int j) { if(i != j) { layer.insert(j, layer.at(i)); if(i>j) { layer.removeAt(i+1); } else { layer.removeAt(i); } } } void Object::deleteLayer(int i) { if(i > -1 && i < layer.size()) { //layer.removeAt(i); disconnect( layer[i], 0, this, 0); // disconnect the layer from this object delete layer.takeAt(i); } } void Object::playSoundIfAny(int frame) { for(int i=0; i < getLayerCount(); i++) { Layer* layer = getLayer(i); if( layer->type == Layer::SOUND) { ((LayerSound*)layer)->playSound(frame); } } } void Object::stopSoundIfAny() { for(int i=0; i < getLayerCount(); i++) { Layer* layer = getLayer(i); if( layer->type == Layer::SOUND) { ((LayerSound*)layer)->stopSound(); } } } ColourRef Object::getColour(int i) { ColourRef result(Qt::white, "error"); if( i > -1 && i < myPalette.size() ) { result = myPalette.at(i); } return result; } void Object::addColour(QColor colour) { addColour( ColourRef(colour, "Colour "+QString::number(myPalette.size()) ) ); } bool Object::removeColour(int index) { for(int i=0; i< getLayerCount(); i++) { Layer* layer = getLayer(i); if( layer->type == Layer::VECTOR) { LayerVector *layerVector = ((LayerVector*)layer); if(layerVector->usesColour(index)) return false; } } for(int i=0; i< getLayerCount(); i++) { Layer* layer = getLayer(i); if( layer->type == Layer::VECTOR) { LayerVector *layerVector = ((LayerVector*)layer); layerVector->removeColour(index); } } myPalette.removeAt(index); return true; // update the vector pictures using that colour ! } void Object::renameColour(int i, QString text) { myPalette[i].name = text; } bool Object::savePalette(QString filePath) { return exportPalette(filePath+"/palette.xml"); } bool Object::exportPalette(QString filePath) { //qDebug() << "coucou" << filePath; QFile* file = new QFile(filePath); if (!file->open(QFile::WriteOnly | QFile::Text)) { //QMessageBox::warning(this, "Warning", "Cannot write file"); return false; } QTextStream out(file); QDomDocument doc("PencilPalette"); QDomElement root = doc.createElement("palette"); doc.appendChild(root); for(int i=0; i < myPalette.size(); i++) { QDomElement tag = doc.createElement("Colour"); tag.setAttribute("name", myPalette.at(i).name); tag.setAttribute("red", myPalette.at(i).colour.red()); tag.setAttribute("green", myPalette.at(i).colour.green()); tag.setAttribute("blue", myPalette.at(i).colour.blue()); root.appendChild(tag); //QDomText t = doc.createTextNode( myPalette.at(i).name ); //tag.appendChild(t); } //QString xml = doc.toString(); int IndentSize = 2; doc.save(out, IndentSize); return true; } bool Object::loadPalette(QString filePath) { return importPalette(filePath+"/palette.xml"); } bool Object::importPalette(QString filePath) { QFile* file = new QFile(filePath); if (!file->open(QFile::ReadOnly)) { //QMessageBox::warning(this, "Warning", "Cannot read file"); return false; } QDomDocument doc; doc.setContent(file); myPalette.clear(); QDomElement docElem = doc.documentElement(); QDomNode tag = docElem.firstChild(); while(!tag.isNull()) { QDomElement e = tag.toElement(); // try to convert the node to an element. if(!e.isNull()) { QString name = e.attribute("name"); int r = e.attribute("red").toInt(); int g = e.attribute("green").toInt(); int b = e.attribute("blue").toInt(); myPalette.append( ColourRef( QColor(r, g, b), name) ); //qDebug() << name << r << g << b << endl; // the node really is an element. } tag = tag.nextSibling(); } return true; } void Object::defaultInitialisation() { // default layers addNewBitmapLayer(); addNewVectorLayer(); // default palette loadDefaultPalette(); } void Object::loadDefaultPalette() { myPalette.clear(); addColour( ColourRef(QColor(Qt::black), QString("Black")) ); addColour( ColourRef(QColor(Qt::red), QString("Red")) ); addColour( ColourRef(QColor(Qt::darkRed), QString("Dark Red")) ); addColour( ColourRef(QColor(255,128,0), QString("Orange")) ); addColour( ColourRef(QColor(128,64,0), QString("Dark Orange")) ); addColour( ColourRef(QColor(Qt::yellow), QString("Yellow")) ); addColour( ColourRef(QColor(Qt::darkYellow), QString("Dark Yellow")) ); addColour( ColourRef(QColor(Qt::green), QString("Green")) ); addColour( ColourRef(QColor(Qt::darkGreen), QString("Dark Green")) ); addColour( ColourRef(QColor(Qt::cyan), QString("Cyan")) ); addColour( ColourRef(QColor(Qt::darkCyan), QString("Dark Cyan")) ); addColour( ColourRef(QColor(Qt::blue), QString("Blue")) ); addColour( ColourRef(QColor(Qt::darkBlue), QString("Dark Blue")) ); addColour( ColourRef(QColor(255,255,255), QString("White")) ); addColour( ColourRef(QColor(220,220,229), QString("Very Light Grey")) ); addColour( ColourRef(QColor(Qt::lightGray), QString("Light Grey")) ); addColour( ColourRef(QColor(Qt::gray), QString("Grey")) ); addColour( ColourRef(QColor(Qt::darkGray), QString("Dark Grey")) ); addColour( ColourRef(QColor(255,227,187), QString("Light Skin")) ); addColour( ColourRef(QColor(221,196,161), QString("Light Skin - shade")) ); addColour( ColourRef(QColor(255,214,156), QString("Skin")) ); addColour( ColourRef(QColor(207,174,127), QString("Skin - shade")) ); addColour( ColourRef(QColor(255,198,116), QString("Dark Skin")) ); addColour( ColourRef(QColor(227,177,105), QString("Dark Skin - shade")) ); } //void Object::paintImage(QPainter &painter, int frameNumber, const QRectF &source, const QRectF &target, bool background, qreal curveOpacity, bool antialiasing, bool niceGradients) { void Object::paintImage(QPainter &painter, int frameNumber, bool background, qreal curveOpacity, bool antialiasing, int gradients) { painter.setRenderHint(QPainter::Antialiasing, true); painter.setRenderHint(QPainter::SmoothPixmapTransform, true); //painter.setWorldMatrix(matrix); painter.setCompositionMode(QPainter::CompositionMode_SourceOver); // paints the background if(background) { painter.setPen(Qt::NoPen); painter.setBrush(Qt::white); painter.setWorldMatrixEnabled(false); painter.drawRect( QRect(0,0, painter.device()->width(), painter.device()->height() ) ); painter.setWorldMatrixEnabled(true); } for(int i=0; i < getLayerCount(); i++) { Layer* layer = getLayer(i); if(layer->visible) { painter.setOpacity(1.0); // paints the bitmap images if(layer->type == Layer::BITMAP) { LayerBitmap* layerBitmap = (LayerBitmap*)layer; /*BitmapImage* bitmapImage = layerBitmap->getLastBitmapImageAtFrame(frameNumber, 0); // TO BE FIXED if(bitmapImage != NULL) { if( mirror) { painter.drawImage(target, (*(bitmapImage->image)).mirrored(true, false), source); } else { painter.drawImage(target, *(bitmapImage->image), source); } }*/ layerBitmap->getLastBitmapImageAtFrame(frameNumber, 0)->paintImage(painter); } // paints the vector images if(layer->type == Layer::VECTOR) { LayerVector* layerVector = (LayerVector*)layer; layerVector->getLastVectorImageAtFrame(frameNumber, 0)->paintImage(painter, false, false, curveOpacity, antialiasing, gradients); } } } } void Object::exportFrames(int frameStart, int frameEnd, QMatrix view, Layer* currentLayer, QSize exportSize, QString filePath, const char* format, int quality, bool background, bool antialiasing, int gradients) { QSettings settings("Pencil","Pencil"); qreal curveOpacity = (100-settings.value("curveOpacity").toInt())/100.0; // default value is 1.0 QString extension = ""; QString formatStr = format; if( formatStr == "PNG" || formatStr == "png") { format = "PNG"; extension = ".png"; } if( formatStr == "JPG" || formatStr == "jpg" || formatStr == "JPEG") { format = "JPG"; extension = ".jpg"; background = true; // JPG doesn't support transparency so we have to include the background } if(filePath.endsWith(extension, Qt::CaseInsensitive)) { filePath = filePath.remove(extension, Qt::CaseInsensitive); } //qDebug() << "format =" << format << "extension = " << extension; qDebug() << "Exporting frames from " << frameStart << "to" << frameEnd << "at size " << exportSize; for(int currentFrame = frameStart; currentFrame <= frameEnd ; currentFrame++) { QImage tempImage(exportSize, QImage::Format_ARGB32_Premultiplied); QPainter painter(&tempImage); if(currentLayer->type == Layer::CAMERA) { QRect viewRect = ((LayerCamera*)currentLayer)->getViewRect(); QMatrix mapView = Editor::map( viewRect, QRectF(QPointF(0,0), exportSize) ); mapView = ((LayerCamera*)currentLayer)->getViewAtFrame(currentFrame) * mapView; painter.setWorldMatrix(mapView); } else { painter.setWorldMatrix(view); } paintImage(painter, currentFrame, background, curveOpacity, antialiasing, gradients); QString frameNumberString = QString::number(currentFrame); while( frameNumberString.length() < 3) frameNumberString.prepend("0"); tempImage.save(filePath+frameNumberString+extension, format, quality); } } void Object::exportX(int frameStart, int frameEnd, QMatrix view, QSize exportSize, QString filePath, bool antialiasing, int gradients) { QSettings settings("Pencil","Pencil"); qreal curveOpacity = (100-settings.value("curveOpacity").toInt())/100.0; // default value is 1.0 int page; page=0; for(int j = frameStart; j <= frameEnd; j=j+15) { QImage xImg(QSize(2300,3400), QImage::Format_ARGB32_Premultiplied); QPainter xPainter(&xImg); xPainter.fillRect(0,0,2300,3400,Qt::white); int y = j-1; for(int i=j;i<15+page*15 && i<=frameEnd;i++) { QRect source = QRect( QPoint(0,0) , exportSize ); QRect target = QRect ( QPoint((y%3)*800+30, (y/3)*680+50-page*3400) , QSize(640,480) ); QMatrix thumbView = view * Editor::map(source, target); xPainter.setWorldMatrix( thumbView ); xPainter.setClipRegion( thumbView.inverted().map( QRegion(target) ) ); paintImage(xPainter, i, false, curveOpacity, antialiasing, gradients); xPainter.resetMatrix(); xPainter.setClipping(false); xPainter.setPen( Qt::black ); xPainter.setFont(QFont("helvetica",50)); xPainter.drawRect( target ); xPainter.drawText(QPoint((y%3)*800+35, (y/3)*680+65-page*3400), QString::number(i)); y++; } if(filePath.endsWith(".jpg", Qt::CaseInsensitive)) { filePath = filePath.remove(".jpg", Qt::CaseInsensitive); } xImg.save(filePath+QString::number(page)+".jpg", "JPG", 60); page++; } } void Object::exportFlash(int startFrame, int endFrame, QMatrix view, QSize exportSize, QString filePath, int fps, int compression) { if(!filePath.endsWith(".swf", Qt::CaseInsensitive)) { filePath = filePath + ".swf"; } // ************* Requires the MING Library *************** Flash::exportFlash(this, startFrame, endFrame, view, exportSize, filePath, fps, compression); // ********************************************** } void Object::imageCheck(int frameNumber) { bool noImage = true; for(int i=0; i< layer.size() && noImage; i++) { if(layer[i]->type == Layer::BITMAP || layer[i]->type == Layer::VECTOR) { if( ((LayerImage*)layer[i])->getIndexAtFrame( frameNumber ) != -1) noImage = false; } } if(noImage) emit imageRemoved(frameNumber); } pencil-0.4.4b/src/structure/layerbitmap.cpp0000644000175000017500000001271710744607202021521 0ustar khashayarkhashayar/* Pencil - Traditional Animation Software Copyright (C) 2005-2007 Patrick Corrieri & Pascal Naidon This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #include "layerbitmap.h" #include LayerBitmap::LayerBitmap(Object* object) : LayerImage(object) { type = Layer::BITMAP; name = QString("Bitmap Layer"); addImageAtFrame(1); //imageSize = desiredSize; //frameClicked = -1; //frameOffset = 0; } LayerBitmap::~LayerBitmap() { while(!framesBitmap.empty()) delete framesBitmap.takeFirst(); } // ------ BitmapImage* LayerBitmap::getBitmapImageAtIndex(int index) { if( index < 0 || index >= framesBitmap.size() ) { return NULL; } else { return framesBitmap.at(index); } } BitmapImage* LayerBitmap::getBitmapImageAtFrame(int frameNumber) { int index = getIndexAtFrame(frameNumber); return getBitmapImageAtIndex(index); } BitmapImage* LayerBitmap::getLastBitmapImageAtFrame(int frameNumber, int increment) { int index = getLastIndexAtFrame(frameNumber); return getBitmapImageAtIndex(index + increment); } // ----- QImage* LayerBitmap::getImageAtIndex(int index) { /*if( index < 0 || index >= framesImage.size() ) { return NULL; } else { return framesImage.at(index); }*/ return NULL; } bool LayerBitmap::addImageAtFrame(int frameNumber) { int index = getIndexAtFrame(frameNumber); if(index == -1) { //framesImage.append(new QImage(imageSize, QImage::Format_ARGB32_Premultiplied)); framesBitmap.append(new BitmapImage(object)); framesPosition.append(frameNumber); framesOriginalPosition.append(frameNumber); framesSelected.append(false); framesFilename.append(""); framesModified.append(false); bubbleSort(); emit imageAdded(frameNumber); return true; } else { return false; } } void LayerBitmap::removeImageAtFrame(int frameNumber) { int index = getIndexAtFrame(frameNumber); if(index != -1 && framesPosition.size() != 1) { delete framesBitmap.at(index); framesBitmap.removeAt(index); framesPosition.removeAt(index); framesOriginalPosition.removeAt(index); framesSelected.removeAt(index); framesFilename.removeAt(index); framesModified.removeAt(index); bubbleSort(); emit imageRemoved(frameNumber); } } void LayerBitmap::loadImageAtFrame(QString path, QPoint topLeft, int frameNumber) { //qDebug() << path; if(getIndexAtFrame(frameNumber) == -1) addImageAtFrame(frameNumber); int index = getIndexAtFrame(frameNumber); framesBitmap[index] = new BitmapImage(object, path, topLeft); QFileInfo fi(path); framesFilename[index] = fi.fileName(); } void LayerBitmap::swap(int i, int j) { LayerImage::swap(i, j); framesBitmap.swap(i,j); } bool LayerBitmap::saveImage(int index, QString path, int layerNumber) { int theFrame = framesPosition.at(index); QString theFileName = fileName(theFrame, id); framesFilename[index] = theFileName; //qDebug() << "Write " << theFileName; framesBitmap[index]->image->save(path +"/"+ theFileName,"PNG"); framesModified[index] = false; } QString LayerBitmap::fileName(int frame, int layerID) { QString layerNumberString = QString::number(layerID); QString frameNumberString = QString::number(frame); while( layerNumberString.length() < 3) layerNumberString.prepend("0"); while( frameNumberString.length() < 3) frameNumberString.prepend("0"); return layerNumberString+"."+frameNumberString+".png"; } QDomElement LayerBitmap::createDomElement(QDomDocument &doc) { QDomElement layerTag = doc.createElement("layer"); layerTag.setAttribute("id", id); layerTag.setAttribute("name", name); layerTag.setAttribute("visibility", visible); layerTag.setAttribute("type", type); for(int index=0; index < framesPosition.size() ; index++) { QDomElement imageTag = doc.createElement("image"); imageTag.setAttribute("frame", framesPosition.at(index)); imageTag.setAttribute("src", framesFilename.at(index)); imageTag.setAttribute("topLeftX", framesBitmap[index]->topLeft().x()); imageTag.setAttribute("topLeftY", framesBitmap[index]->topLeft().y()); layerTag.appendChild(imageTag); } return layerTag; } void LayerBitmap::loadDomElement(QDomElement element, QString filePath) { if(!element.attribute("id").isNull()) id = element.attribute("id").toInt(); name = element.attribute("name"); visible = (element.attribute("visibility") == "1"); type = element.attribute("type").toInt(); QDomNode imageTag = element.firstChild(); while(!imageTag.isNull()) { QDomElement imageElement = imageTag.toElement(); if(!imageElement.isNull()) { if(imageElement.tagName() == "image") { QString path = filePath +".data/" + imageElement.attribute("src"); // the file is supposed to be in the data irectory QFileInfo fi(path); if(!fi.exists()) path = imageElement.attribute("src"); int position = imageElement.attribute("frame").toInt(); int x = imageElement.attribute("topLeftX").toInt(); int y = imageElement.attribute("topLeftY").toInt(); loadImageAtFrame( path, QPoint(x,y), position ); } /*if(imageElement.tagName() == "image") { int frame = imageElement.attribute("frame").toInt(); addImageAtFrame( frame ); getBitmapImageAtFrame( frame )->loadDomElement(imageElement, filePath); }*/ } imageTag = imageTag.nextSibling(); } } pencil-0.4.4b/src/structure/layersound.h0000644000175000017500000000353110744607202021034 0ustar khashayarkhashayar/* Pencil - Traditional Animation Software Copyright (C) 2005-2007 Patrick Corrieri & Pascal Naidon This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #ifndef LAYERSOUND_H #define LAYERSOUND_H #include #include #include #include #include #include "layerimage.h" class LayerSound : public LayerImage { Q_OBJECT public: LayerSound(Object* object); ~LayerSound(); QDomElement createDomElement(QDomDocument &doc); void loadDomElement(QDomElement element, QString filePath); bool addImageAtFrame(int frameNumber); void removeImageAtFrame(int frameNumber); //void setModified(bool trueOrFalse) { modified = trueOrFalse; } void loadSoundAtFrame( QString filePathString, int frame ); bool saveImage(int index, QString path, int layerNumber); void playSound(int frame); void stopSound(); // graphic representation -- could be put in another class void paintImages(QPainter &painter, TimeLineCells *cells, int x, int y, int width, int height, bool selected, int frameSize); //void mousePress(QMouseEvent *event, int frameNumber); //void mouseMove(QMouseEvent *event, int frameNumber); //void mouseRelease(QMouseEvent *event, int frameNumber); protected: //bool modified; //QList startingFrame; //QList filePath; QList soundFilepath; QList sound; // graphic representation -- could be put in another class void swap(int i, int j); }; #endif pencil-0.4.4b/src/main.cpp0000644000175000017500000000205710744607202016070 0ustar khashayarkhashayar/* Pencil - Traditional Animation Software Copyright (C) 2005-2007 Patrick Corrieri & Pascal Naidon This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #include #include #include "mainwindow.h" void initialise(); int main(int argc, char *argv[]) { QApplication app(argc, argv); #ifndef Q_WS_MAC app.setWindowIcon(QIcon(":/icons/icon.png")); #endif initialise(); /*QDir dir(QApplication::applicationDirPath()); dir.cdUp(); if(dir.cd("plugins")) { QApplication::setLibraryPaths(QStringList(dir.absolutePath())); }*/ MainWindow mainWindow; mainWindow.show(); qDebug() << "MainWindow thread" << mainWindow.thread(); qDebug() << "App thread" << app.thread(); return app.exec(); } pencil-0.4.4b/src/interface/0000755000175000017500000000000010757714675016415 5ustar khashayarkhashayarpencil-0.4.4b/src/interface/preferences.h0000644000175000017500000000323710716110271021045 0ustar khashayarkhashayar/* Pencil - Traditional Animation Software Copyright (C) 2005-2007 Patrick Corrieri & Pascal Naidon This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #include class QListWidget; class QListWidgetItem; class QStackedWidget; class Preferences : public QDialog { Q_OBJECT public: Preferences(); public slots: void changePage(QListWidgetItem *current, QListWidgetItem *previous); signals: void windowOpacityChange(int); void curveOpacityChange(int); void curveSmoothingChange(int); void highResPositionChange(int); void antialiasingChange(int); void gradientsChange(int); void backgroundChange(int); void shadowsChange(int); void toolCursorsChange(int); void styleChange(int); void autosaveChange(int); void autosaveNumberChange(int); void lengthSizeChange(QString); void fontSizeChange(int); void frameSizeChange(int); void labelChange(int); void scrubChange(int); private: void createIcons(); QListWidget *contentsWidget; QStackedWidget *pagesWidget; }; class GeneralPage : public QWidget { Q_OBJECT public: GeneralPage(QWidget *parent = 0); }; class TimelinePage : public QWidget { Q_OBJECT public: TimelinePage(QWidget *parent = 0); }; class FilesPage : public QWidget { Q_OBJECT public: FilesPage(QWidget *parent = 0); };pencil-0.4.4b/src/interface/timeline.cpp0000644000175000017500000006075510757712552020734 0ustar khashayarkhashayar/* Pencil - Traditional Animation Software Copyright (C) 2005-2007 Patrick Corrieri & Pascal Naidon This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #include #include "timeline.h" #include "editor.h" #include "toolset.h" #include "timecontrols.h" TimeLine::TimeLine(QWidget *parent, Editor *editor) : QDockWidget(parent, Qt::Tool) // DockPalette("") { QWidget* timeLineContent = new QWidget(this); list = new TimeLineCells(this, editor, "layers"); cells = new TimeLineCells(this, editor, "tracks"); connect(list, SIGNAL(mouseMovedY(int)), list, SLOT(setMouseMoveY(int))); connect(list, SIGNAL(mouseMovedY(int)), cells, SLOT(setMouseMoveY(int))); numberOfLayers = 0; hScrollBar = new QScrollBar(Qt::Horizontal); vScrollBar = new QScrollBar(Qt::Vertical); vScrollBar->setMinimum(0); vScrollBar->setMaximum(1); vScrollBar->setPageStep(1); QWidget* leftWidget = new QWidget(); leftWidget->setMinimumWidth(120); QWidget* rightWidget = new QWidget(); QWidget* leftToolBar = new QWidget(); leftToolBar->setFixedHeight(31); QWidget* rightToolBar = new QWidget(); rightToolBar->setFixedHeight(31); // --- left widget --- // --------- layer buttons --------- //QFrame* layerButtons = new QFrame(this); QToolBar* layerButtons = new QToolBar(this); //QHBoxLayout* layerButtonLayout = new QHBoxLayout(); QLabel* layerLabel = new QLabel(tr("Layers:")); layerLabel->setIndent(5); layerLabel->setFont( QFont("Helvetica", 10) ); QToolButton* addLayerButton = new QToolButton(this); addLayerButton->setIcon(QIcon(":icons/add.png")); addLayerButton->setToolTip("Add Layer"); addLayerButton->setFixedSize(24,24); QToolButton* removeLayerButton = new QToolButton(this); removeLayerButton->setIcon(QIcon(":icons/remove.png")); removeLayerButton->setToolTip("Remove Layer"); removeLayerButton->setFixedSize(24,24); /*layerButtonLayout->addWidget(layerLabel); layerButtonLayout->addWidget(addLayerButton); layerButtonLayout->addWidget(removeLayerButton); layerButtonLayout->setMargin(0); layerButtonLayout->setSpacing(5); layerButtons->setLayout(layerButtonLayout);*/ layerButtons->addWidget(layerLabel); layerButtons->addWidget(addLayerButton); layerButtons->addWidget(removeLayerButton); QHBoxLayout* leftToolBarLayout = new QHBoxLayout(); leftToolBarLayout->setAlignment(Qt::AlignLeft); leftToolBarLayout->setMargin(0); leftToolBarLayout->addWidget(layerButtons); leftToolBar->setLayout(leftToolBarLayout); QAction* newBitmapLayerAct = new QAction(QIcon(":icons/layer-bitmap.png"), tr("New Bitmap Layer"), this); QAction* newVectorLayerAct = new QAction(QIcon(":icons/layer-vector.png"), tr("New Vector Layer"), this); QAction* newSoundLayerAct = new QAction(QIcon(":icons/layer-sound.png"), tr("New Sound Layer"), this); QAction* newCameraLayerAct = new QAction(QIcon(":icons/layer-camera.png"), tr("New Camera Layer"), this); QMenu* layerMenu = new QMenu(tr("&Layer"), this); layerMenu->addAction(newBitmapLayerAct); layerMenu->addAction(newVectorLayerAct); layerMenu->addAction(newSoundLayerAct); layerMenu->addAction(newCameraLayerAct); addLayerButton->setMenu(layerMenu); addLayerButton->setPopupMode(QToolButton::InstantPopup); QGridLayout *leftLayout = new QGridLayout(); leftLayout->addWidget(leftToolBar,0,0); leftLayout->addWidget(list,1,0); leftLayout->setMargin(0); leftLayout->setSpacing(0); leftWidget->setLayout(leftLayout); // --- right widget --- // --------- key buttons --------- //QFrame* keyButtons = new QFrame(this); QToolBar* keyButtons = new QToolBar(this); //keyButtons->setFixedWidth(90); //QHBoxLayout* keyButtonsLayout = new QHBoxLayout(); QLabel* keyLabel = new QLabel(tr("Keys:")); keyLabel->setFont( QFont("Helvetica", 10) ); keyLabel->setIndent(5); QToolButton* addKeyButton = new QToolButton(this); addKeyButton->setIcon(QIcon(":icons/add.png")); addKeyButton->setToolTip("Add Key"); addKeyButton->setFixedSize(24,24); QToolButton* removeKeyButton = new QToolButton(this); removeKeyButton->setIcon(QIcon(":icons/remove.png")); removeKeyButton->setToolTip("Remove Key"); removeKeyButton->setFixedSize(24,24); /*keyButtonsLayout->addWidget(keyLabel); keyButtonsLayout->addWidget(addKeyButton); keyButtonsLayout->addWidget(removeKeyButton); keyButtonsLayout->setMargin(0); keyButtonsLayout->setSpacing(0); //keyButtonLayout->setSizeConstraint(QLayout::SetMinimumSize); keyButtons->setLayout(keyButtonsLayout);*/ keyButtons->addWidget(keyLabel); keyButtons->addWidget(addKeyButton); keyButtons->addWidget(removeKeyButton); // --------- Onion skin buttons --------- //QFrame* onionButtons = new QFrame(this); QToolBar* onionButtons = new QToolBar(this); //onionButtons->setFixedWidth(90); //QHBoxLayout* onionButtonsLayout = new QHBoxLayout(); QLabel* onionLabel = new QLabel(tr("Onion skin:")); onionLabel->setFont( QFont("Helvetica", 10) ); onionLabel->setIndent(5); QToolButton* onionPrevButton = new QToolButton(this); onionPrevButton->setIcon(QIcon(":icons/onionPrev.png")); onionPrevButton->setToolTip("Show previous frame"); onionPrevButton->setFixedSize(24,24); onionPrevButton->setCheckable(true); onionPrevButton->setChecked(true); QToolButton* onionNextButton = new QToolButton(this); onionNextButton->setIcon(QIcon(":icons/onionNext.png")); onionNextButton->setToolTip("Show next frame"); onionNextButton->setFixedSize(24,24); onionNextButton->setCheckable(true); /*onionButtonsLayout->addWidget(onionLabel); onionButtonsLayout->addWidget(onionPrevButton); onionButtonsLayout->addWidget(onionNextButton); onionButtonsLayout->setMargin(0); onionButtonsLayout->setSpacing(0); //keyButtonLayout->setSizeConstraint(QLayout::SetMinimumSize); onionButtons->setLayout(onionButtonsLayout);*/ onionButtons->addSeparator(); onionButtons->addWidget(onionLabel); onionButtons->addWidget(onionPrevButton); onionButtons->addWidget(onionNextButton); // --------- Time controls --------- TimeControls* timeControls = new TimeControls(this); QHBoxLayout* rightToolBarLayout = new QHBoxLayout(); //rightToolBarLayout->setAlignment(Qt::AlignLeft); rightToolBarLayout->addWidget(keyButtons); rightToolBarLayout->addWidget(onionButtons); rightToolBarLayout->addStretch(1); rightToolBarLayout->addWidget(timeControls); rightToolBarLayout->setMargin(0); rightToolBarLayout->setSpacing(0); rightToolBar->setLayout(rightToolBarLayout); QGridLayout *rightLayout = new QGridLayout(); rightLayout->addWidget(rightToolBar,0,0); rightLayout->addWidget(cells,1,0); rightLayout->setMargin(0); rightLayout->setSpacing(0); rightWidget->setLayout(rightLayout); // --- Splitter --- QSplitter *splitter = new QSplitter(parent); splitter->addWidget(leftWidget); splitter->addWidget(rightWidget); splitter->setSizes( QList() << 100 << 600 ); //splitter->addWidget(cells); QGridLayout *lay = new QGridLayout(); //lay->addWidget(cells,0,0); //lay->addWidget(toolBar,0,0); lay->addWidget(splitter,0,0); lay->addWidget(vScrollBar,0,1); lay->addWidget(hScrollBar,1,0); //lay->addWidget(vScrollBar,1,1); lay->setMargin(0); lay->setSpacing(0); timeLineContent->setLayout(lay); //timeLineContent->setBackgroundRole(QPalette::Dark); //timeLineContent->setForegroundRole(QPalette::Dark); setWidget(timeLineContent); setWindowFlags(Qt::WindowStaysOnTopHint); setWindowTitle("Time Line"); //setWindowFlags(Qt::SubWindow); setFloating(true); //setMinimumSize(100, 300); //setGeometry(10,60,100, 300); connect(this,SIGNAL(lengthChange(QString)), cells, SLOT(lengthChange(QString))); connect(this,SIGNAL(fontSizeChange(int)), cells, SLOT(fontSizeChange(int))); connect(this,SIGNAL(frameSizeChange(int)), cells, SLOT(frameSizeChange(int))); connect(this,SIGNAL(labelChange(int)), cells, SLOT(labelChange(int))); connect(this,SIGNAL(scrubChange(int)), cells, SLOT(scrubChange(int))); connect(hScrollBar,SIGNAL(valueChanged(int)), cells, SLOT(hScrollChange(int))); connect(vScrollBar,SIGNAL(valueChanged(int)), cells, SLOT(vScrollChange(int))); connect(vScrollBar,SIGNAL(valueChanged(int)), list, SLOT(vScrollChange(int))); connect(addKeyButton, SIGNAL(clicked()), this, SIGNAL(addKeyClick())); connect(removeKeyButton, SIGNAL(clicked()), this, SIGNAL(removeKeyClick())); connect(onionPrevButton, SIGNAL(clicked()), this, SIGNAL(onionPrevClick())); connect(onionNextButton, SIGNAL(clicked()), this, SIGNAL(onionNextClick())); connect(timeControls, SIGNAL(playClick()), this, SIGNAL(playClick())); connect(timeControls, SIGNAL(loopClick()), this, SIGNAL(loopClick())); connect(timeControls, SIGNAL(soundClick()), this, SIGNAL(soundClick())); connect(timeControls, SIGNAL(fpsClick(int)), this, SIGNAL(fpsClick(int))); //connect(this, SIGNAL(topLevelChanged(bool)), timeControls, SLOT(updateButtons(bool))); // when the windows is docked or made floatable connect(newBitmapLayerAct, SIGNAL(triggered()), this, SIGNAL(newBitmapLayer())); connect(newVectorLayerAct, SIGNAL(triggered()), this, SIGNAL(newVectorLayer())); connect(newSoundLayerAct, SIGNAL(triggered()), this, SIGNAL(newSoundLayer())); connect(newCameraLayerAct, SIGNAL(triggered()), this, SIGNAL(newCameraLayer())); connect(removeLayerButton, SIGNAL(clicked()), this, SIGNAL(deleteCurrentLayer())); scrubbing = false; //QSettings settings("Pencil","Pencil"); //layerHeight = (settings.value("layerHeight").toInt()); //if(layerHeight==0) { layerHeight=20; settings.setValue("layerHeight", layerHeight); } //startY = 0; //endY = 0; //startLayerNumber = -1; //offsetY = 15; } void TimeLine::resizeEvent(QResizeEvent *event) { //QWidget::resizeEvent(event); updateLayerView(); //event->accept(); } void TimeLine::updateFrame(int frameNumber) { if(cells) cells->updateFrame(frameNumber); } void TimeLine::updateLayerView() { vScrollBar->setPageStep( (height()-cells->getOffsetY()-hScrollBar->height())/cells->getLayerHeight() -2 ); vScrollBar->setMinimum( 0 ); vScrollBar->setMaximum( qMax(0, numberOfLayers - vScrollBar->pageStep()) ); update(); updateContent(); } void TimeLine::updateLayerNumber(int numberOfLayers) { this->numberOfLayers = numberOfLayers; updateLayerView(); } void TimeLine::updateLength(int frameLength) { hScrollBar->setMaximum( frameLength ); } void TimeLine::updateContent() { list->updateContent(); cells->updateContent(); update(); } /*void TimeLine::mousePressEvent(QMouseEvent *event) { //int frameNumber = getFrameNumber(event->pos().x()); int layerNumber = getLayerNumber(event->pos().y()); startY = event->pos().y(); startLayerNumber = layerNumber; endY = event->pos().y(); //if(frameNumber == editor->currentFrame) { // scrubbing = true; //} else { if( (layerNumber != -1) && layerNumber < editor->object->getLayerCount()) { //editor->object->getLayer(layerNumber)->mousePress(event, frameNumber); editor->setCurrentLayer(layerNumber); //} else { //editor->scrubTo(frameNumber); //scrubbing = true; } //} } void TimeLine::mouseMoveEvent(QMouseEvent *event) { endY = event->pos().y(); //int frameNumber = getFrameNumber(event->pos().x()); int layerNumber = getLayerNumber(event->pos().y()); //if(scrubbing) { // editor->scrubTo(frameNumber); //} else { //if(layerNumber != -1 && layerNumber < editor->object->getLayerCount()) { // editor->object->getLayer(layerNumber)->mouseMove(event, frameNumber); //} //} update(); } void TimeLine::mouseReleaseEvent(QMouseEvent *event) { endY = startY; //scrubbing = false; //int frameNumber = getFrameNumber(event->pos().x()); int layerNumber = getLayerNumber(event->pos().y()); //if(layerNumber != -1 && layerNumber < editor->object->getLayerCount() ) { // editor->object->getLayer(layerNumber)->mouseRelease(event, frameNumber); //} if(layerNumber != startLayerNumber && startLayerNumber != -1 && layerNumber != -1) { editor->moveLayer(startLayerNumber, layerNumber); } update(); } void TimeLine::mouseDoubleClickEvent(QMouseEvent *event) { int layerNumber = getLayerNumber(event->pos().y()); if(layerNumber != -1 && layerNumber < editor->object->getLayerCount() ) { editor->switchVisibilityOfLayer(layerNumber); } }*/ TimeLineCells::TimeLineCells(TimeLine *parent, Editor *editor, QString type) : QWidget(parent) { this->timeLine = parent; this->editor = editor; this->type = type; cache = NULL; QSettings settings("Pencil","Pencil"); frameLength = settings.value("length").toInt(); if (frameLength==0) { frameLength=240; settings.setValue("length", frameLength); } shortScrub = settings.value("shortScrub").toBool(); fps = editor->fps; //playing = false; //scrubbing = false; startY = 0; endY = 0; mouseMoveY = 0; startLayerNumber = -1; offsetX = 0; offsetY = 20; frameOffset = 0; layerOffset = 0; frameSize = (settings.value("frameSize").toInt()); if (frameSize==0) { frameSize=12; settings.setValue("frameSize", frameSize); } fontSize = (settings.value("labelFontSize").toInt()); if (fontSize==0) { fontSize=12; settings.setValue("labelFontSize", fontSize); } layerHeight = (settings.value("layerHeight").toInt()); if(layerHeight==0) { layerHeight=20; settings.setValue("layerHeight", layerHeight); } //setMinimumSize(frameLength*frameSize, 3*layerHeight); //setMinimumWidth(500); setMinimumSize(500, 4*layerHeight); setSizePolicy( QSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding) ); setAttribute(Qt::WA_OpaquePaintEvent, false); } int TimeLineCells::getFrameNumber(int x) { int frameNumber = frameOffset+1+(x-offsetX)/frameSize; return frameNumber; } int TimeLineCells::getFrameX(int frameNumber) { int x = offsetX + (frameNumber-frameOffset)*frameSize; return x; } int TimeLineCells::getLayerNumber(int y) { int layerNumber = layerOffset + (y-offsetY)/layerHeight; if (y < offsetY) layerNumber = -1; if (layerNumber >= editor->object->getLayerCount()) layerNumber = editor->object->getLayerCount(); return layerNumber; } int TimeLineCells::getLayerY(int layerNumber) { return offsetY + (layerNumber-layerOffset)*layerHeight; } void TimeLineCells::updateFrame(int frameNumber) { int x = getFrameX(frameNumber); update(x-frameSize,0,frameSize+1,height()); } void TimeLineCells::updateContent() { drawContent(); update(); } void TimeLineCells::drawContent() { //qDebug() << "draw content" << QDateTime::currentDateTime() << timeLine->scrubbing; if(cache == NULL) { cache = new QPixmap(size()); } if(cache->isNull()) return; QPainter painter( cache ); Object* object = editor->object; if(object == NULL) return; Layer* layer = object->getLayer(editor->currentLayer); if(layer == NULL) return; // grey background of the view painter.setPen(Qt::NoPen); painter.setBrush(Qt::lightGray); painter.drawRect(QRect(0,0, width(), height())); // --- updates the offsetX /*painter.setPen(Qt::black); painter.setFont(QFont("helvetica", getLayerHeight()/2)); for(int i=0; i< object->getLayerCount(); i++) { Layer* layeri = object->getLayer(i); if(layeri != NULL) { int rightmost = 20 + painter.boundingRect(QRect(0,0,300,100), Qt::AlignLeft, layeri->name).width() + 5; if( rightmost > offsetX) offsetX = rightmost; } }*/ // --- draw layers of the current object for(int i=0; i< object->getLayerCount(); i++) { if(i != editor->currentLayer) { Layer* layeri = object->getLayer(i); if(layeri != NULL) { if(type == "tracks") layeri->paintTrack(painter, this, offsetX, getLayerY(i), width()-offsetX, getLayerHeight(), false, frameSize); if(type == "layers") layeri->paintLabel(painter, this, 0, getLayerY(i), width()-1, getLayerHeight(), false, editor->allLayers()); } } } //if(timeLine->scrubbing == false && abs(getMouseMoveY()) > 5) { if( abs(getMouseMoveY()) > 5 ) { if(type == "tracks") layer->paintTrack(painter, this, offsetX, getLayerY(editor->currentLayer)+getMouseMoveY(), width()-offsetX, getLayerHeight(), true, frameSize); if(type == "layers") layer->paintLabel(painter, this, 0, getLayerY(editor->currentLayer)+getMouseMoveY(), width()-1, getLayerHeight(), true, editor->allLayers()); painter.setPen( Qt::black ); painter.drawRect(0, getLayerY( getLayerNumber(endY) ) -1, width(), 2); } else { if(type == "tracks") layer->paintTrack(painter, this, offsetX, getLayerY(editor->currentLayer), width()-offsetX, getLayerHeight(), true, frameSize); if(type == "layers") layer->paintLabel(painter, this, 0, getLayerY(editor->currentLayer), width()-1, getLayerHeight(), true, editor->allLayers()); } // --- draw top painter.setPen(Qt::NoPen); painter.setBrush(QColor(220,220,220)); painter.drawRect(QRect(0,0, width()-1, offsetY-1)); painter.setPen( Qt::gray ); painter.drawLine(0,0, width()-1, 0); painter.drawLine(0,offsetY-2, width()-1, offsetY-2); painter.setPen( Qt::lightGray ); painter.drawLine(0,offsetY-3, width()-1, offsetY-3); painter.drawLine(0,0, 0, offsetY-3); if(type == "layers") { // --- draw circle painter.setPen(Qt::black); if(editor->allLayers() == 0) { painter.setBrush(Qt::NoBrush); } if(editor->allLayers() == 1) { painter.setBrush(Qt::darkGray); } if(editor->allLayers() == 2) { painter.setBrush(Qt::black); } painter.setRenderHint(QPainter::Antialiasing, true); painter.drawEllipse(6, 4, 9, 9); painter.setRenderHint(QPainter::Antialiasing, false); // --- draw right border line //painter.setPen( Qt::lightGray ); //painter.drawLine(width()/2-1,0, width()/2-1, height()); } if(type == "tracks") { // --- draw ticks painter.setPen( QColor(70,70,70,255) ); painter.setBrush(Qt::darkGray); painter.setFont(QFont("helvetica", 10)); int incr = 0; for(int i=frameOffset; i frameList = editor->frameList; for(int i=0; i frameOffset ) { painter.drawLine( getFrameX(j-1-frameOffset), 1, getFrameX(j-frameOffset), 1); } }*/ // --- draw left border line painter.setPen( Qt::darkGray ); painter.drawLine(0,0, 0, height()); } } void TimeLineCells::paintEvent(QPaintEvent *event) { Object* object = editor->object; if(object == NULL) return; Layer* layer = object->getLayer(editor->currentLayer); if(layer == NULL) return; QPainter painter( this ); if( (!editor->playing && !timeLine->scrubbing) || cache == NULL) drawContent(); if(cache) painter.drawPixmap(QPoint(0,0), *cache); if(type == "tracks") { // --- draw the position of the current frame if(editor->currentFrame > frameOffset) { painter.setBrush(QColor(255,0,0,128)); painter.setPen(Qt::NoPen); painter.setFont(QFont("helvetica", 10)); //painter.setCompositionMode(QPainter::CompositionMode_Source); // this causes the message: QPainter::setCompositionMode: PorterDuff modes not supported on device QRect scrubRect; scrubRect.setTopLeft(QPoint( getFrameX(editor->currentFrame-1), 0)); scrubRect.setBottomRight(QPoint( getFrameX(editor->currentFrame), height())); if(shortScrub) scrubRect.setBottomRight(QPoint( getFrameX(editor->currentFrame), 19)); painter.drawRect(scrubRect); painter.setPen( QColor(70,70,70,255) ); int incr = 0; if(editor->currentFrame < 10) { incr = 4; } else { incr = 0; } painter.drawText(QPoint(getFrameX(editor->currentFrame-1)+incr, 15), QString::number(editor->currentFrame)); } } //event->accept(); } void TimeLineCells::resizeEvent(QResizeEvent *event) { //QWidget::resizeEvent(event); if(cache) delete cache; cache = new QPixmap(size()); updateContent(); event->accept(); } void TimeLineCells::mousePressEvent(QMouseEvent *event) { int frameNumber = getFrameNumber(event->pos().x()); int layerNumber = getLayerNumber(event->pos().y()); startY = event->pos().y(); startLayerNumber = layerNumber; endY = event->pos().y(); if(type == "layers") { if(layerNumber != -1 && layerNumber < editor->object->getLayerCount() ) { if(event->pos().x() < 15) { editor->switchVisibilityOfLayer(layerNumber); } else { editor->setCurrentLayer(layerNumber); update(); } } if(layerNumber == -1) { if(event->pos().x() < 15) { editor->toggleShowAllLayers(); } } } if(type == "tracks") { if(frameNumber == editor->currentFrame && (!shortScrub || (shortScrub && startY < 20)) ) { timeLine->scrubbing = true; } else { if( (layerNumber != -1) && layerNumber < editor->object->getLayerCount()) { editor->object->getLayer(layerNumber)->mousePress(event, frameNumber); //if(event->pos().x() > 15) editor->setCurrentLayer(layerNumber); editor->setCurrentLayer(layerNumber); update(); } else { if(frameNumber > 0) { editor->scrubTo(frameNumber); timeLine->scrubbing = true; } } } } } void TimeLineCells::mouseMoveEvent(QMouseEvent *event) { //if(event->pos().x() < offsetX) endY = event->pos().y(); if(type == "layers") { endY = event->pos().y(); emit mouseMovedY(endY-startY); } int frameNumber = getFrameNumber(event->pos().x()); int layerNumber = getLayerNumber(event->pos().y()); if(timeLine->scrubbing && type == "tracks") { editor->scrubTo(frameNumber); } else { if(layerNumber != -1 && layerNumber < editor->object->getLayerCount()) { editor->object->getLayer(layerNumber)->mouseMove(event, frameNumber); } } timeLine->update(); } void TimeLineCells::mouseReleaseEvent(QMouseEvent *event) { endY = startY; emit mouseMovedY(0); timeLine->scrubbing = false; int frameNumber = getFrameNumber(event->pos().x()); if(frameNumber < 1) frameNumber = -1; int layerNumber = getLayerNumber(event->pos().y()); if(type == "tracks" && layerNumber != -1 && layerNumber < editor->object->getLayerCount() ) { editor->object->getLayer(layerNumber)->mouseRelease(event, frameNumber); } //if(event->pos().x() < offsetX && layerNumber != startLayerNumber && startLayerNumber != -1 && layerNumber != -1) { if(type == "layers" && layerNumber != startLayerNumber && startLayerNumber != -1 && layerNumber != -1) { editor->moveLayer(startLayerNumber, layerNumber); } update(); } void TimeLineCells::mouseDoubleClickEvent(QMouseEvent *event) { int frameNumber = getFrameNumber(event->pos().x()); int layerNumber = getLayerNumber(event->pos().y()); // -- short scrub -- if(event->pos().y() < 20) { if(shortScrub) scrubChange(0); else scrubChange(1); } // -- layer -- Layer* layer = editor->object->getLayer( layerNumber ); //if(layerNumber != -1 && layerNumber < editor->object->getLayerCount() ) { if(layer) { if(type == "tracks" && (layerNumber != -1) && (frameNumber > 0) && layerNumber < editor->object->getLayerCount()) { editor->object->getLayer(layerNumber)->mouseDoubleClick(event, frameNumber); } if(type == "layers") { layer->editProperties(); } } } // --- changes --- void TimeLineCells::fontSizeChange(int x) { fontSize=x; QSettings settings("Pencil","Pencil"); settings.setValue("labelFontSize", x); updateContent(); } void TimeLineCells::frameSizeChange(int x) { //int old; //old=frameSize; frameSize = x; QSettings settings("Pencil","Pencil"); settings.setValue("frameSize", x); /*int i; for(i=0;iupdateLength(frameLength); //setMinimumSize(dec*frameSize,40); //setFixedWidth(dec*frameSize); updateContent(); QSettings settings("Pencil","Pencil"); settings.setValue("length", dec); } void TimeLineCells::hScrollChange(int x) { frameOffset = x; update(); } void TimeLineCells::vScrollChange(int x) { layerOffset = x; update(); } pencil-0.4.4b/src/interface/timecontrols.cpp0000644000175000017500000000775710644055565021652 0ustar khashayarkhashayar/* Pencil - Traditional Animation Software Copyright (C) 2005-2007 Patrick Corrieri & Pascal Naidon This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #include #include "timecontrols.h" TimeControls::TimeControls(QWidget* parent) : QToolBar(parent) { QSettings settings("Pencil","Pencil"); //QFrame* frame = new QFrame(); QSpinBox* fpsBox = new QSpinBox(); //fpsBox->setFixedWidth(50); fpsBox->setFont( QFont("Helvetica", 10) ); fpsBox->setFixedHeight(22); fpsBox->setValue(settings.value("fps").toInt()); fpsBox->setMinimum(1); fpsBox->setMaximum(50); fpsBox->setToolTip("Frames per second"); fpsBox->setFocusPolicy(Qt::NoFocus); QPushButton* playButton = new QPushButton(); loopButton = new QPushButton(); soundButton = new QPushButton(); QLabel* separator = new QLabel(); separator->setPixmap(QPixmap(":icons/controls/separator.png")); separator->setFixedSize(QSize(37,31)); QLabel* spacingLabel = new QLabel(""); spacingLabel->setIndent(6); QLabel* fpsLabel = new QLabel(tr("Fps: ")); fpsLabel->setIndent(6); QIcon playIcon(":icons/controls/play.png"); QIcon loopIcon(":icons/controls/loop.png"); QIcon soundIcon(":icons/controls/sound.png"); #ifdef Q_WS_MAC /*loopButton->setFixedSize( QSize(35,30) ); loopButton->setIconSize( QSize(35,30) ); loopIcon.addFile (":icons/controls/loopOn.png", QSize(35,20), QIcon::Normal, QIcon::On ); loopIcon.addFile (":icons/controls/loopOff.png", QSize(35,20), QIcon::Normal, QIcon::Off); loopIcon.addFile (":icons/controls/loopOn.png", QSize(35,20), QIcon::Disabled, QIcon::On ); loopIcon.addFile (":icons/controls/loopOff.png", QSize(35,20), QIcon::Disabled, QIcon::Off); loopIcon.addFile (":icons/controls/loopOn.png", QSize(35,20), QIcon::Active, QIcon::On ); loopIcon.addFile (":icons/controls/loopOff.png", QSize(35,20), QIcon::Active, QIcon::Off);*/ #endif playButton->setIcon(playIcon); loopButton->setIcon(loopIcon); soundButton->setIcon(soundIcon); playButton->setToolTip(tr("Play")); loopButton->setToolTip(tr("Loop")); soundButton->setToolTip(tr("Sound on/off")); loopButton->setCheckable(true); soundButton->setCheckable(true); soundButton->setChecked(true); addWidget(separator); addWidget(playButton); addWidget(loopButton); addWidget(soundButton); addWidget(fpsLabel); addWidget(fpsBox); /*QHBoxLayout* frameLayout = new QHBoxLayout(); frameLayout->setMargin(0); frameLayout->setSpacing(0); frameLayout->addWidget(separator); frameLayout->addWidget(playButton); frameLayout->addWidget(loopButton); frameLayout->addWidget(soundButton); frameLayout->addWidget(fpsLabel); frameLayout->addWidget(fpsBox); frameLayout->addWidget(spacingLabel); setLayout(frameLayout); setFixedSize(300,32);*/ //QHBoxLayout* layout = new QHBoxLayout(); //layout->setAlignment(Qt::AlignRight); //layout->addWidget(frame); //layout->setMargin(0); //layout->setSizeConstraint(QLayout::SetNoConstraint); //setLayout(frameLayout); connect(playButton, SIGNAL(clicked()), this, SIGNAL(playClick())); connect(loopButton, SIGNAL(clicked()), this, SIGNAL(loopClick())); connect(soundButton, SIGNAL(clicked()), this, SIGNAL(soundClick())); connect(fpsBox,SIGNAL(valueChanged(int)), this, SIGNAL(fpsClick(int))); //updateButtons(false); } void TimeControls::updateButtons(bool floating) { /*if(floating) { loopButton->setFixedSize(QSize(45,22)); soundButton->setFixedSize(QSize(45,22)); } else { loopButton->setFixedSize(QSize(26,17)); soundButton->setFixedSize(QSize(26,17)); }*/ } /*void TimeControls::updateLoopButton(bool checked) { if(checked) { loopButton->setIcon(QIcon(":icons/controls/loopOn.png")); } else { loopButton->setIcon(QIcon(":icons/controls/loopOff.png")); } }*/ pencil-0.4.4b/src/interface/toolset.h0000644000175000017500000000741110745152004020235 0ustar khashayarkhashayar/* Pencil - Traditional Animation Software Copyright (C) 2005-2007 Patrick Corrieri & Pascal Naidon This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #ifndef TOOLSET_H #define TOOLSET_H #include class SpinSlider : public QWidget { Q_OBJECT public: SpinSlider(QString text, QString type, QString dataType, qreal min, qreal max, QWidget *parent = 0); public slots: void changeValue(qreal); void changeValue(int); void setValue(qreal); void sliderReleased(); void sliderMoved(int); signals: void valueChanged(qreal); private: QLabel* valueLabel; QSlider* slider; qreal value, min, max; QString type, dataType; }; class ToolSet : public QWidget { Q_OBJECT public: ToolSet(); QDockWidget *drawPalette; QDockWidget *optionPalette; QDockWidget *displayPalette; QDockWidget *keyPalette; QDockWidget *onionPalette; QDockWidget *timePalette; public slots: void setCounter(int); void setWidth(qreal); void setFeather(qreal); void setOpacity(qreal); void setInvisibility(int); void setPressure(int); void setPreserveAlpha(int); void setFollowContour(int); void setColour(QColor); //void playStart(); void changePencilButton(); void changeEraserButton(); void changeSelectButton(); void changeMoveButton(); void changeHandButton(); void changePenButton(); void changePolylineButton(); void changeBucketButton(); void changeEyedropperButton(); void changeColouringButton(); void changeThinLinesButton(bool); void changeOutlinesButton(bool); void changeSmudgeButton(); void resetMirror(); void pressureClick(bool); void invisibleClick(bool); void preserveAlphaClick(bool); void followContourClick(bool); signals: void rmClick(); void playClick(); void addClick(); void pencilClick(); void eraserClick(); void selectClick(); void moveClick(); void handClick(); void penClick(); void pressureClick(int); void invisibleClick(int); void preserveAlphaClick(int); void followContourClick(int); void polylineClick(); void bucketClick(); void eyedropperClick(); void colouringClick(); void smudgeClick(); void lengthClick(QString); void fpsClick(int); void clearClick(); void thinLinesClick(); void outlinesClick(); void mirrorClick(); void prevClick(); void nextClick(); void widthClick(qreal); void featherClick(qreal); void opacityClick(qreal); void colourClick(); void loopClick(); void soundClick(); private: void newToolButton(QToolButton* &toolButton); QToolButton *choseColour; QPixmap *colourSwatch; QToolButton *pencilButton; QToolButton *selectButton; QToolButton *moveButton; QToolButton *handButton; QToolButton *eraserButton; QToolButton *penButton; QToolButton *polylineButton; QToolButton *bucketButton; QToolButton *colouringButton; QToolButton *eyedropperButton; QToolButton *magnifyButton; QToolButton *smudgeButton; QToolButton *thinLinesButton; QToolButton *outlinesButton; QToolButton *mirrorButton; QToolButton *clearButton; QToolButton *add; QToolButton *rm; QSpinBox *fpsBox; //QDoubleSpinBox *sizeSlider; SpinSlider *sizeSlider; SpinSlider *featherSlider; SpinSlider *opacitySlider; //QSlider *featherSlider; QLabel *framecounter; QPushButton *play; QCheckBox *usePressureBox; QCheckBox *makeInvisibleBox; QCheckBox *preserveAlphaBox; QCheckBox *followContourBox; QCheckBox *onionPrevBox; QCheckBox *onionNextBox; QCheckBox *loopBox; QCheckBox *soundBox; int fps; void deselectAllTools(); }; #endif pencil-0.4.4b/src/interface/mainwindow.h0000644000175000017500000000406010744607202020721 0ustar khashayarkhashayar/* Pencil - Traditional Animation Software Copyright (C) 2005-2007 Patrick Corrieri & Pascal Naidon This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #include #include #include "editor.h" class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(); //void initialiseStyle(); void addRecentFile(QString filePath); public slots: void setOpacity(int opacity); private slots: void exportFile(); private: void arrangePalettes(); void createMenus(); void loadPlugins(); void populateMenus(QObject *plugin); void addToMenu(QObject *plugin, const QString text, QMenu *menu, const char *member, QActionGroup *actionGroup = 0); void closeEvent(QCloseEvent *); void keyPressEvent( QKeyEvent *e); void keyReleaseEvent( QKeyEvent *e); void readSettings(); void writeSettings(); Editor *editor; QMenu *fileMenu; QMenu *openRecentMenu; QMenu *importMenu; QMenu *exportMenu; QMenu *editMenu; QMenu *layerMenu; QMenu *helpMenu; QMenu *windowsMenu; QAction *newAct; QAction *openAct; QAction *saveAct; QAction *exitAct; QAction *helpMe; QAction *aboutAct; QAction *aboutQtAct; QAction *exportXAct; QAction *exportAct; QAction *exportMovAct; QAction *exportFlashAct; QAction *exportPaletteAct; QAction *importPaletteAct; QAction *savAct; QAction *importAct; QAction *undoAct; QAction *redoAct; QAction *copyAct; QAction *pasteAct; QAction *selectAllAct; QAction *importSndAct; QAction *preferencesAct; QAction *newBitmapLayerAct; QAction *newVectorLayerAct; QAction *newSoundLayerAct; QAction *newCameraLayerAct; QAction *deleteLayerAct; QAction *dockAllPalettesAct; QAction *detachAllPalettesAct; }; pencil-0.4.4b/src/interface/timeline.h0000644000175000017500000000662010650474602020361 0ustar khashayarkhashayar/* Pencil - Traditional Animation Software Copyright (C) 2005-2007 Patrick Corrieri & Pascal Naidon This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #ifndef TIMELINE_H #define TIMELINE_H #include #include #include #include #include #include #include #include "toolset.h" class Editor; class TimeLine; class TimeLineCells : public QWidget { Q_OBJECT public: TimeLineCells(TimeLine *parent = 0, Editor *editor = 0, QString type = ""); //int currentFrame; //int currentLayer; int getFps() { return fps; } int getLayerNumber(int y); int getLayerY(int layerNumber); int getFrameNumber(int x); int getFrameX(int frameNumber); int getMouseMoveY() { return mouseMoveY; } int getOffsetY() { return offsetY; } int getLayerHeight() { return layerHeight; } signals: void mouseMovedY(int); public slots: void updateContent(); void updateFrame(int frameNumber); void lengthChange(QString); void frameSizeChange(int); void fontSizeChange(int); void scrubChange(int); void labelChange(int); void hScrollChange(int); void vScrollChange(int); void setMouseMoveY(int x) { mouseMoveY = x;} protected: void drawContent(); void paintEvent(QPaintEvent *event); void resizeEvent(QResizeEvent *event); void mousePressEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event); void mouseDoubleClickEvent(QMouseEvent *event); private: TimeLine *timeLine; Editor* editor; // the editor for which this timeLine operates QString type; QPixmap* cache; bool drawFrameNumber; bool shortScrub; int frameLength; int frameSize; int fontSize; int fps; bool scrubbing; int layerHeight; int offsetX, offsetY; int startY, endY, startLayerNumber; int mouseMoveY; int frameOffset, layerOffset; }; class TimeLine : public QDockWidget //DockPalette { Q_OBJECT signals: void modification(); void lengthChange(QString); void frameSizeChange(int); void fontSizeChange(int); void labelChange(int); void scrubChange(int); void addKeyClick(); void removeKeyClick(); void newBitmapLayer(); void newVectorLayer(); void newSoundLayer(); void newCameraLayer(); void deleteCurrentLayer(); void playClick(); void loopClick(); void soundClick(); void fpsClick(int); void onionPrevClick(); void onionNextClick(); public slots: void updateFrame(int frameNumber); void updateLayerNumber(int number); void updateLayerView(); void updateLength(int frameLength); void updateContent(); public: TimeLine(QWidget *parent = 0, Editor *editor = 0); QScrollBar *hScrollBar, *vScrollBar; //int currentFrame; //int currentLayer; bool scrubbing; protected: void resizeEvent(QResizeEvent *event); //void mousePressEvent(QMouseEvent *event); //void mouseMoveEvent(QMouseEvent *event); //void mouseReleaseEvent(QMouseEvent *event); //void mouseDoubleClickEvent(QMouseEvent *event); private: Editor* editor; // the editor for which this timeLine operates //TimeLineCells* list; TimeLineCells* cells; TimeLineCells* list; int numberOfLayers; }; #endif pencil-0.4.4b/src/interface/palette.h0000644000175000017500000000314510716110271020200 0ustar khashayarkhashayar/* Pencil - Traditional Animation Software Copyright (C) 2005-2007 Patrick Corrieri & Pascal Naidon This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #ifndef PALETTE_H #define PALETTE_H //#include #include #include #include #include //#include #include "toolset.h" class Editor; class Palette : public QDockWidget { Q_OBJECT public: Palette(Editor*); int currentColour() { return listOfColours->currentRow(); } protected: //QSize sizeHint(); Editor* editor; QListWidget* listOfColours; QToolButton *addButton, *removeButton; QSlider *sliderRed, *sliderGreen, *sliderBlue, *sliderAlpha; QToolButton *colourSwatch; public slots: void updateList(); void updateSwatch(QColor); void selectColour(int i) { listOfColours->setCurrentRow(i); } void setColour(QColor); void setColour(int, int, int, int); private slots: void colourSwatchClicked(); void selectColour(QListWidgetItem*, QListWidgetItem*); void selectAndApplyColour(QListWidgetItem*); void updateColour(); void changeColour(); void changeColour(QListWidgetItem*); void changeColourName(QListWidgetItem*); void addClick(); void rmClick(); void closeIfDocked(bool); }; #endif pencil-0.4.4b/src/interface/scribblearea.cpp0000644000175000017500000031242010745152004021514 0ustar khashayarkhashayar/* Pencil - Traditional Animation Software Copyright (C) 2005-2007 Patrick Corrieri & Pascal Naidon This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #include #include #include "scribblearea.h" #include "beziercurve.h" #include "editor.h" #include "layerbitmap.h" #include "layervector.h" #include "layercamera.h" #include "bitmapimage.h" void VectorSelection::clear() { vertex.clear(); curve.clear(); } void VectorSelection::add(int curveNumber) { curve << curveNumber; } void VectorSelection::add(QList list) { if(list.size() > 0) add(list[0]); /*for(int i=0; i list) { if(list.size() > 0) add(list[0]); /*for(int i=0; ieditor = editor; QSettings settings("Pencil","Pencil"); pencil.width = settings.value("pencilWidth").toDouble(); if (pencil.width == 0) { pencil.width = 1; settings.setValue("pencilWidth", pencil.width); } pen.width = settings.value("penWidth").toDouble(); if (pen.width == 0) { pen.width = 2; settings.setValue("penWidth", pen.width); } brush.width = settings.value("brushWidth").toDouble(); if (brush.width == 0) { brush.width = 48; settings.setValue("brushWidth", brush.width); } eraser.width = settings.value("eraserWidth").toDouble(); if (eraser.width == 0) { eraser.width = 24; settings.setValue("eraserWidth", brush.width); } currentWidth = pencil.width; pencil.colour = Qt::black; pen.colour = Qt::black; brush.colour = Qt::blue; currentColour = pencil.colour; pencil.colourNumber = 0; pen.colourNumber = 0; brush.colourNumber = 1; pencil.feather = 0; pen.feather = 0; brush.feather = settings.value("brushFeather").toDouble(); if (brush.feather == 0) { brush.feather = 70; settings.setValue("brushFeather", brush.feather); } eraser.feather = 0; pencil.opacity = 0.8; pen.opacity = 1; brush.opacity = 0.5; eraser.opacity = 0.5; pencil.pressure = 1; pen.pressure = 1; brush.pressure = 1; eraser.pressure = 1; pencil.invisibility = 1; pen.invisibility = 0; brush.invisibility = -1; eraser.invisibility = -1; pencil.preserveAlpha = 0; pen.preserveAlpha = 0; brush.preserveAlpha = 0; eraser.preserveAlpha = 0; followContour = 0; curveOpacity = (100-settings.value("curveOpacity").toInt())/100.0; // default value is 1.0 int curveSmoothingLevel = settings.value("curveSmoothing").toInt(); if(curveSmoothingLevel == 0) { curveSmoothingLevel = 20; settings.setValue("curveSmoothing", curveSmoothingLevel); } // default curveSmoothing = curveSmoothingLevel/20.0; // default value is 1.0 highResPosition = false; // default is false (because it does not work on Windows) if( settings.value("highResPosition").toString() == "true") highResPosition = true; antialiasing = true; // default value is true (because it's prettier) if( settings.value("antialiasing").toString() == "false") antialiasing = false; shadows = false; // default value is false if( settings.value("shadows").toString() == "true") shadows = true; toolCursors = true; // default value is true if( settings.value("toolCursors").toString() == "false") toolCursors = false; gradients = 2; if( settings.value("gradients").toString() != "") gradients = settings.value("gradients").toInt();; toolMode = PENCIL; tabletEraserBackupToolMode=-1; tabletInUse=false; tabletPressure=1.0; setAttribute(Qt::WA_StaticContents); // ? modified = false; simplified = false; usePressure = true; makeInvisible = false; somethingSelected = false; setCursor(Qt::CrossCursor); onionPrev = true; onionNext = false; showThinLines = false; showAllLayers = 1; myView = QMatrix(); // identity matrix myTempView = QMatrix(); transMatrix = QMatrix(); centralView = QMatrix(); QString background = settings.value("background").toString(); if(background == "") background = "white"; setBackgroundBrush(background); bufferImg = new BitmapImage(NULL); eyedropperCursor = NULL; QRect newSelection(QPoint(0,0), QSize(0,0)); mySelection = newSelection; myTransformedSelection = newSelection; myTempTransformedSelection = newSelection; offset.setX(0); offset.setY(0); selectionTransformation.reset(); tol = 7.0; readCanvasFromCache = true; mouseInUse = false; setMouseTracking(true); // reacts to mouse move events, even if the button is not pressed debugRect = QRectF(0,0,0,0); setSizePolicy( QSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding) ); QPixmapCache::setCacheLimit(30*2*1024); //setAutoFillBackground (false); //setAttribute(Qt::WA_OpaquePaintEvent, false); //setAttribute(Qt::WA_NoSystemBackground, true); } void ScribbleArea::setColour(const int i) { if(toolMode == PENCIL) { pencil.colourNumber = i; pencil.colour = editor->object->getColour(i).colour; } if(toolMode == PEN || toolMode == POLYLINE) { pen.colourNumber = i; pen.colour = editor->object->getColour(i).colour; } if(toolMode == BUCKET || toolMode == COLOURING || toolMode == EYEDROPPER) { brush.colourNumber = i; brush.colour = editor->object->getColour(i).colour; } updateCursor(); updateFrame(); } void ScribbleArea::setColour(const QColor colour) { if(toolMode == PENCIL || toolMode == EYEDROPPER) { pencil.colour = colour; } if(toolMode == PEN || toolMode == EYEDROPPER) { pen.colour = colour; } if(toolMode == COLOURING || toolMode == BUCKET || toolMode == EYEDROPPER) { brush.colour = colour; } currentColour = colour; updateCursor(); } void ScribbleArea::resetColours() { pen.colourNumber = 0; pencil.colourNumber = 0; brush.colourNumber = 1; } void ScribbleArea::setWidth(const qreal newWidth) { QSettings settings("Pencil","Pencil"); if(toolMode == PENCIL) { pencil.width = newWidth; settings.setValue("pencilWidth", newWidth); } if(toolMode == ERASER) { eraser.width = newWidth; settings.setValue("eraserWidth", newWidth); } if(toolMode == PEN || toolMode == POLYLINE) { pen.width = newWidth; settings.setValue("penWidth", newWidth); } if(toolMode == COLOURING) { brush.width = newWidth; settings.setValue("brushWidth", newWidth); } currentWidth = newWidth; updateAllFrames(); updateCursor(); } void ScribbleArea::setFeather(const qreal newFeather) { QSettings settings("Pencil","Pencil"); if(toolMode == PENCIL) { pencil.feather = newFeather; settings.setValue("pencilOpacity", newFeather); } if(toolMode == PEN || toolMode == POLYLINE) { pen.feather = newFeather; settings.setValue("penOpacity", newFeather); } if(toolMode == COLOURING) { brush.feather = newFeather; settings.setValue("brushOpacity", newFeather); } //currentWidth = newWidth; updateAllFrames(); updateCursor(); } void ScribbleArea::setOpacity(const qreal newOpacity) { QSettings settings("Pencil","Pencil"); if(toolMode == PENCIL) { pencil.opacity = newOpacity; settings.setValue("pencilOpacity", newOpacity); } if(toolMode == PEN || toolMode == POLYLINE) { pen.opacity = newOpacity; settings.setValue("penOpacity", newOpacity); } if(toolMode == COLOURING) { brush.opacity = newOpacity; settings.setValue("brushOpacity", newOpacity); } //currentWidth = newWidth; updateAllFrames(); } void ScribbleArea::setInvisibility(const bool invisibility) { QSettings settings("Pencil","Pencil"); if(toolMode == PENCIL) { pencil.invisibility = invisibility; settings.setValue("pencilOpacity", invisibility); } if(toolMode == PEN || toolMode == POLYLINE) { pen.invisibility = invisibility; settings.setValue("penOpacity", invisibility); } makeInvisible = invisibility; updateAllFrames(); } void ScribbleArea::setPressure(const bool pressure) { QSettings settings("Pencil","Pencil"); if(toolMode == PENCIL) { pencil.pressure = pressure; settings.setValue("pencilOpacity", pressure); } if(toolMode == PEN || toolMode == POLYLINE) { pen.pressure = pressure; settings.setValue("penOpacity", pressure); } if(toolMode == COLOURING) { brush.pressure = pressure; settings.setValue("brushOpacity", pressure); } usePressure = pressure; updateAllFrames(); } void ScribbleArea::setPreserveAlpha(const bool preserveAlpha) { QSettings settings("Pencil","Pencil"); if(toolMode == PENCIL) { pencil.preserveAlpha = preserveAlpha; //settings.setValue("pencilCompositionMode", preserveAlpha); } if(toolMode == PEN || toolMode == POLYLINE) { pen.preserveAlpha = preserveAlpha; //settings.setValue("penCompositionMode", preserveAlpha); } if(toolMode == COLOURING) { brush.preserveAlpha = preserveAlpha; //settings.setValue("brushCompositionMode", preserveAlpha); } //this->preserveAlpha = preserveAlpha; //updateAllFrames(); } void ScribbleArea::setFollowContour(const bool followContour) { this->followContour = followContour; } void ScribbleArea::setCurveOpacity(int newOpacity) { curveOpacity = newOpacity/100.0; QSettings settings("Pencil","Pencil"); settings.setValue("curveOpacity", 100-newOpacity); updateAllVectorLayers(); } void ScribbleArea::setCurveSmoothing(int newSmoothingLevel) { curveSmoothing = newSmoothingLevel/20.0; QSettings settings("Pencil","Pencil"); settings.setValue("curveSmoothing", newSmoothingLevel); } void ScribbleArea::setHighResPosition(int x) { QSettings settings("Pencil","Pencil"); if (x==0) { highResPosition=false; settings.setValue("highResPosition","false"); } else { highResPosition=true; settings.setValue("highResPosition","true"); } } void ScribbleArea::setAntialiasing(int x) { QSettings settings("Pencil","Pencil"); if (x==0) { antialiasing=false; settings.setValue("antialiasing","false"); } else { antialiasing=true; settings.setValue("antialiasing","true"); } updateAllVectorLayers(); } void ScribbleArea::setGradients(int x) { //if(x==0) { gradients = x; } else { gradients = x; } QSettings settings("Pencil","Pencil"); if(x > 0) { gradients = x; settings.setValue("gradients", gradients); } else { gradients = 2; gradients = settings.value("gradients").toInt(); } //if (x==0) { antialiasing=false; settings.setValue("antialiasing","false"); } //else { antialiasing=true; settings.setValue("antialiasing","true"); } updateAllVectorLayers(); } void ScribbleArea::setShadows(int x) { QSettings settings("Pencil","Pencil"); if (x==0) { shadows=false; settings.setValue("shadows","false"); } else { shadows=true; settings.setValue("shadows","true"); } update(); } void ScribbleArea::setToolCursors(int x) { QSettings settings("Pencil","Pencil"); if (x==0) { toolCursors=false; settings.setValue("toolCursors","false"); } else { toolCursors=true; settings.setValue("toolCursors","true"); } } void ScribbleArea::setStyle(int x) { QSettings settings("Pencil","Pencil"); if (x==0) { settings.setValue("style","default"); } else { settings.setValue("style","aqua"); } update(); } void ScribbleArea::setBackground(int number) { if(number == 1) setBackgroundBrush("checkerboard"); if(number == 2) setBackgroundBrush("white"); if(number == 3) setBackgroundBrush("grey"); if(number == 4) setBackgroundBrush("dots"); if(number == 5) setBackgroundBrush("weave"); updateAllFrames(); } void ScribbleArea::setBackgroundBrush(QString brushName) { QSettings settings("Pencil","Pencil"); settings.setValue("background", brushName); backgroundBrush = getBackgroundBrush(brushName); } QBrush ScribbleArea::getBackgroundBrush(QString brushName) { QBrush brush = QBrush(Qt::white); if(brushName == "white") { brush = QBrush(Qt::white); } if(brushName == "grey") { brush = QBrush(Qt::lightGray); } if(brushName == "checkerboard") { QPixmap pattern(16,16); pattern.fill( QColor(255,255,255) ); QPainter painter(&pattern); painter.fillRect( QRect(0,0,8,8), QColor(220,220,220) ); painter.fillRect( QRect(8,8,8,8), QColor(220,220,220) ); painter.end(); brush.setTexture(pattern); } if(brushName == "dots") { QPixmap pattern(":background/dots.png"); brush.setTexture(pattern); } if(brushName == "weave") { QPixmap pattern(":background/weave.jpg"); brush.setTexture(pattern); } return brush; } void ScribbleArea::updateFrame() { updateFrame(editor->currentFrame); } void ScribbleArea::updateFrame(int frame) { //qDebug() << "updateFrame"; //paintCanvas(frame); setView(); int frameNumber = editor->getLastFrameAtFrame( frame ); QPixmapCache::remove("frame"+QString::number(frameNumber)); readCanvasFromCache = true; update(); } void ScribbleArea::updateAllFrames() { //qDebug() << "updateAllFrames"; //frameList.clear(); setView(); QPixmapCache::clear(); readCanvasFromCache = true; update(); } void ScribbleArea::updateAllVectorLayersAtCurrentFrame() { updateAllVectorLayersAt(editor->currentFrame); } void ScribbleArea::updateAllVectorLayersAt(int frameNumber) { for(int i=0; i< editor->object->getLayerCount(); i++) { Layer* layer = editor->object->getLayer(i); if(layer->type == Layer::VECTOR) ((LayerVector*)layer)->getLastVectorImageAtFrame(frameNumber, 0)->setModified(true); } updateFrame(editor->currentFrame); } void ScribbleArea::updateAllVectorLayers() { for(int i=0; i< editor->object->getLayerCount(); i++) { Layer* layer = editor->object->getLayer(i); if(layer->type == Layer::VECTOR) ((LayerVector*)layer)->setModified(true); } updateAllFrames(); } void ScribbleArea::setModified(int layerNumber, int frameNumber) { Layer* layer = editor->object->getLayer(layerNumber); //if(layer->type == Layer::VECTOR) ((LayerVector*)layer)->getLastVectorImageAtFrame(frameNumber, 0)->setModified(true); if(layer->type == Layer::VECTOR) ((LayerVector*)layer)->setModified(frameNumber, true); if(layer->type == Layer::BITMAP) ((LayerImage*)layer)->setModified(frameNumber, true); emit modification(layerNumber); //updateFrame(frame); updateAllFrames(); } void ScribbleArea::escape() { deselectAll(); } void ScribbleArea::keyPressEvent( QKeyEvent *event ) { switch (event->key()) { case Qt::Key_Right: if(somethingSelected) { myTempTransformedSelection.translate(1,0); myTransformedSelection = myTempTransformedSelection; calculateSelectionTransformation(); update(); } else { editor->scrubForward(); event->ignore(); } break; case Qt::Key_Left: if(somethingSelected) { myTempTransformedSelection.translate(-1,0); myTransformedSelection = myTempTransformedSelection; calculateSelectionTransformation(); update(); } else { editor->scrubBackward(); event->ignore(); } break; case Qt::Key_Up: if(somethingSelected) { myTempTransformedSelection.translate(0,-1); myTransformedSelection = myTempTransformedSelection; calculateSelectionTransformation(); update(); } else { editor->previousLayer(); event->ignore(); } break; case Qt::Key_Down: if(somethingSelected) { myTempTransformedSelection.translate(0,1); myTransformedSelection = myTempTransformedSelection; calculateSelectionTransformation(); update(); } else { editor->nextLayer(); event->ignore(); } break; case Qt::Key_Return: if(somethingSelected) { paintTransformedSelection(); deselectAll(); } else { if(toolMode == POLYLINE) { endPolyline(); } else { event->ignore(); } } break; case Qt::Key_Escape: if(somethingSelected || toolMode == POLYLINE) { escape(); } break; case Qt::Key_Backspace: if(somethingSelected) deleteSelection(); break; case Qt::Key_F1: simplified = true; emit outlinesChanged(simplified); gradients = 0; updateAllVectorLayersAtCurrentFrame(); break; case Qt::Key_F2: gradients = 1; updateAllVectorLayersAtCurrentFrame(); break; case Qt::Key_F3: gradients = 2; updateAllVectorLayersAtCurrentFrame(); break; default: event->ignore(); //QWidget::keyPressEvent(e); } } void ScribbleArea::keyReleaseEvent( QKeyEvent *event ) { switch (event->key()) { case Qt::Key_F1: simplified = false; emit outlinesChanged(simplified); setGradients(-1); updateAllVectorLayersAtCurrentFrame(); break; case Qt::Key_F2: setGradients(-1); updateAllVectorLayersAtCurrentFrame(); break; case Qt::Key_F3: setGradients(-1); updateAllVectorLayersAtCurrentFrame(); break; default: event->ignore(); //QWidget::keyPressEvent(e); } } void ScribbleArea::tabletEvent(QTabletEvent *event) { //qDebug() << "Device" << event->device() << "Pointer type" << event->pointerType(); tabletInUse = true; tabletPosition = event->hiResGlobalPos(); tabletPressure = event->pressure(); if(event->pointerType() == QTabletEvent::Cursor) tabletPressure = 0.5*tabletPressure; // "normal" pressure is chosen to be 0.5 instead of 1.0 mousePressure.append(tabletPressure); if(toolMode==ScribbleArea::ERASER) { //myPenWidth = static_cast(10.0*tabletPressure); currentWidth = (eraser.width*tabletPressure); } if(toolMode==ScribbleArea::PENCIL) { currentColour = pencil.colour; if(usePressure) {currentColour.setAlphaF(pencil.colour.alphaF()*tabletPressure); } else { currentColour.setAlphaF(pencil.colour.alphaF()); } currentWidth = pencil.width; } if(toolMode==ScribbleArea::PEN) { currentColour = pen.colour; currentColour.setAlphaF(pen.colour.alphaF()); if(usePressure) { currentWidth = 2.0*pen.width*tabletPressure; } else { currentWidth = pen.width; } } if(event->pointerType() == QTabletEvent::Eraser) { //if(tabletEraser == false) eraserOn(); //tabletEraser = true; if(tabletEraserBackupToolMode == -1) { tabletEraserBackupToolMode = toolMode; // memorise which tool was being used before switching to the eraser eraserOn(); } } else { //if(tabletEraser == true) pencilOn(); //tabletEraser = false; if(tabletEraserBackupToolMode != -1) { // restore the tool in use switch(tabletEraserBackupToolMode) { case ScribbleArea::PENCIL: pencilOn(); break; case ScribbleArea::PEN: penOn(); break; default: pencilOn(); } tabletEraserBackupToolMode = -1; } } event->ignore(); // indicates that the tablet event is not accepted yet, so that it is propagated as a mouse event) } void ScribbleArea::mousePressEvent(QMouseEvent *event) { mouseInUse = true; Layer* layer = editor->getCurrentLayer(); // ---- checks ------ if(layer==NULL) return; if(!layer->visible && toolMode != HAND && (event->button() != Qt::RightButton)) { QMessageBox::warning(this, tr("Warning"), tr("You are drawing on a hidden layer! Please select another layer (or make the current layer visible)."), QMessageBox::Ok, QMessageBox::Ok); mouseInUse = false; return; } if(layer->type == Layer::VECTOR) { VectorImage* vectorImage = ((LayerVector*)layer)->getLastVectorImageAtFrame(editor->currentFrame, 0); if (vectorImage == NULL) return; if(toolMode == ScribbleArea::PENCIL) editor->selectColour(pencil.colourNumber); if(toolMode == ScribbleArea::PEN) editor->selectColour(pen.colourNumber); if(toolMode == ScribbleArea::COLOURING || toolMode == ScribbleArea::BUCKET) editor->selectColour(brush.colourNumber); } if(layer->type == Layer::BITMAP) { BitmapImage* bitmapImage = ((LayerBitmap*)layer)->getLastBitmapImageAtFrame(editor->currentFrame, 0); if (bitmapImage == NULL) return; } // --- end checks ---- while(!mousePath.isEmpty()) mousePath.removeAt(0); // empty the mousePath while(!mousePressure.isEmpty()) mousePressure.removeAt(0); // empty the mousePressure if (event->button() == Qt::LeftButton || event->button() == Qt::RightButton) { // if the user is pressing the left or right button if(tabletInUse && highResPosition) { lastPixel = QPointF(event->pos()) + tabletPosition - QPointF(event->globalPos()); } else { lastPixel = QPointF(event->pos()); } bool invertible = true; lastPoint = myTempView.inverted(&invertible).map(QPointF(lastPixel)); lastBrushPoint = lastPoint; } if (event->button() == Qt::LeftButton) { if(toolMode == ScribbleArea::PENCIL || toolMode == ScribbleArea::ERASER || toolMode == ScribbleArea::PEN || toolMode == ScribbleArea::BUCKET || toolMode == ScribbleArea::COLOURING) { editor->backup(); if(layer->type == Layer::VECTOR) { if(toolMode == ScribbleArea::PENCIL && !showThinLines) toggleThinLines(); } mousePath.append(lastPoint); } // ---------------------------------------------------------------------- if(toolMode == COLOURING) { if(layer->type == Layer::BITMAP) { qreal opacity = 1.0; qreal brushWidth = brush.width + 0.5*brush.feather; qreal offset = qMax(0.0,brush.width-0.5*brush.feather)/brushWidth; if(tabletInUse) opacity = tabletPressure; if(usePressure) brushWidth = brushWidth*tabletPressure; drawBrush( lastPoint, brushWidth, offset, brush.colour, opacity); int rad = qRound(brushWidth / 2) + 3; update(myTempView.mapRect(QRect(lastPoint.toPoint(), lastPoint.toPoint()).normalized().adjusted(-rad, -rad, +rad, +rad))); } } // ---------------------------------------------------------------------- if(toolMode == POLYLINE && (layer->type == Layer::BITMAP || layer->type == Layer::VECTOR) ) { if(mousePoints.size() == 0) editor->backup(); if(layer->type == Layer::VECTOR) { ((LayerVector*)layer)->getLastVectorImageAtFrame(editor->currentFrame, 0)->deselectAll(); if(makeInvisible && !showThinLines) toggleThinLines(); } mousePoints << lastPoint; //qDebug() << "--------- " << mousePoints; } // ---------------------------------------------------------------------- if(toolMode == ScribbleArea::SELECT && (layer->type == Layer::BITMAP || layer->type == Layer::VECTOR)) { if(layer->type == Layer::VECTOR) { ((LayerVector*)layer)->getLastVectorImageAtFrame(editor->currentFrame, 0)->deselectAll(); } moveMode = ScribbleArea::MIDDLE; if( somethingSelected ) { // there is something selected if( BezierCurve::mLength(lastPoint - myTransformedSelection.topLeft()) < 6) moveMode = ScribbleArea::TOPLEFT; if( BezierCurve::mLength(lastPoint - myTransformedSelection.topRight()) < 6) moveMode = ScribbleArea::TOPRIGHT; if( BezierCurve::mLength(lastPoint - myTransformedSelection.bottomLeft()) < 6) moveMode = ScribbleArea::BOTTOMLEFT; if( BezierCurve::mLength(lastPoint - myTransformedSelection.bottomRight()) < 6) moveMode = ScribbleArea::BOTTOMRIGHT; if( moveMode == ScribbleArea::MIDDLE ) { paintTransformedSelection(); deselectAll(); } // the user did not click on one of the corners } else { // there is nothing selected mySelection.setTopLeft( lastPoint ); mySelection.setBottomRight( lastPoint ); setSelection(mySelection, true); } update(); } // ---------------------------------------------------------------------- if(toolMode == ScribbleArea::EDIT) { if(layer->type == Layer::VECTOR) { closestCurves = ((LayerVector*)layer)->getLastVectorImageAtFrame(editor->currentFrame, 0)->getCurvesCloseTo(currentPoint, tol/myTempView.m11()); closestVertices = ((LayerVector*)layer)->getLastVectorImageAtFrame(editor->currentFrame, 0)->getVerticesCloseTo(currentPoint, tol/myTempView.m11()); if( closestVertices.size() > 0 || closestCurves.size() > 0 ) { // the user clicks near a vertex or a curve editor->backup(); VectorImage* vectorImage = ((LayerVector*)layer)->getLastVectorImageAtFrame(editor->currentFrame, 0); if(event->modifiers() != Qt::ShiftModifier && !vectorImage->isSelected(closestVertices)) { paintTransformedSelection(); deselectAll(); } vectorImage->setSelected(closestVertices, true); vectorSelection.add(closestCurves); vectorSelection.add(closestVertices); /*calculateSelectionRect(); moveMode == ScribbleArea::MIDDLE; if( somethingSelected ) { // there is an area selection if( BezierCurve::mLength(lastPoint - myTransformedSelection.topLeft()) < 6) moveMode = ScribbleArea::TOPLEFT; if( BezierCurve::mLength(lastPoint - myTransformedSelection.topRight()) < 6) moveMode = ScribbleArea::TOPRIGHT; if( BezierCurve::mLength(lastPoint - myTransformedSelection.bottomLeft()) < 6) moveMode = ScribbleArea::BOTTOMLEFT; if( BezierCurve::mLength(lastPoint - myTransformedSelection.bottomRight()) < 6) moveMode = ScribbleArea::BOTTOMRIGHT; }*/ update(); } else { deselectAll(); } } } // ---------------------------------------------------------------------- if(toolMode == ScribbleArea::MOVE && (layer->type == Layer::BITMAP || layer->type == Layer::VECTOR)) { editor->backup(); moveMode = ScribbleArea::MIDDLE; if( somethingSelected ) { // there is an area selection if( BezierCurve::mLength(lastPoint - myTransformedSelection.topLeft()) < 6) moveMode = ScribbleArea::TOPLEFT; if( BezierCurve::mLength(lastPoint - myTransformedSelection.topRight()) < 6) moveMode = ScribbleArea::TOPRIGHT; if( BezierCurve::mLength(lastPoint - myTransformedSelection.bottomLeft()) < 6) moveMode = ScribbleArea::BOTTOMLEFT; if( BezierCurve::mLength(lastPoint - myTransformedSelection.bottomRight()) < 6) moveMode = ScribbleArea::BOTTOMRIGHT; } // --- if(moveMode == ScribbleArea::MIDDLE) { if(layer->type == Layer::BITMAP) { if(!(myTransformedSelection.contains(lastPoint))) { // click is outside the transformed selection with the MOVE tool paintTransformedSelection(); deselectAll(); } } if(layer->type == Layer::VECTOR) { VectorImage* vectorImage = ((LayerVector*)layer)->getLastVectorImageAtFrame(editor->currentFrame, 0); if(closestCurves.size() > 0) { // the user clicks near a curve // editor->backup(); if(!vectorImage->isSelected(closestCurves)) { paintTransformedSelection(); if(event->modifiers() != Qt::ShiftModifier) { deselectAll(); } vectorImage->setSelected(closestCurves, true); setSelection( vectorImage->getSelectionRect(), true ); update(); } } else { int areaNumber = vectorImage->getLastAreaNumber(lastPoint); if(areaNumber != -1) { // the user clicks on an area if(!vectorImage->isAreaSelected(areaNumber)) { if(event->modifiers() != Qt::ShiftModifier) { deselectAll(); } vectorImage->setAreaSelected(areaNumber, true); //setSelection( vectorImage->getSelectionRect() ); setSelection( QRectF(0,0,0,0), true ); update(); } } else { // the user doesn't click near a curve or an area if(!(myTransformedSelection.contains(lastPoint))) { // click is outside the transformed selection with the MOVE tool paintTransformedSelection(); deselectAll(); } } } } } // --- } } } void ScribbleArea::mouseMoveEvent(QMouseEvent *event) { Layer* layer = editor->getCurrentLayer(); // ---- checks ------ if(layer==NULL) return; if(layer->type == Layer::VECTOR) { VectorImage* vectorImage = ((LayerVector*)layer)->getLastVectorImageAtFrame(editor->currentFrame, 0); if (vectorImage == NULL) return; } if(layer->type == Layer::BITMAP) { BitmapImage* bitmapImage = ((LayerBitmap*)layer)->getLastBitmapImageAtFrame(editor->currentFrame, 0); if (bitmapImage == NULL) return; } // ---- end checks ------ if(tabletInUse && highResPosition) { currentPixel = QPointF(event->pos()) + tabletPosition - QPointF(event->globalPos()); } else { currentPixel = event->pos(); } bool invertible = true; currentPoint = myTempView.inverted(&invertible).map(QPointF(currentPixel)); if(event->buttons() & Qt::LeftButton || event->buttons() & Qt::RightButton) { // the user is also pressing the mouse (dragging) offset = currentPoint - lastPoint; mousePath.append(currentPoint); } // ---------------------------------------------------------------------- if(layer->type == Layer::BITMAP || layer->type == Layer::VECTOR) { if ((event->buttons() & Qt::LeftButton) && (toolMode == ScribbleArea::PENCIL || toolMode == ScribbleArea::ERASER || toolMode == ScribbleArea::PEN || toolMode == ScribbleArea::COLOURING)) drawLineTo(currentPixel, currentPoint); if(toolMode == ScribbleArea::POLYLINE) drawPolyline(); } // ---------------------------------------------------------------------- if (toolMode == ScribbleArea::SELECT && (event->buttons() & Qt::LeftButton) && somethingSelected && (layer->type == Layer::BITMAP || layer->type == Layer::VECTOR)) { if(moveMode == ScribbleArea::MIDDLE) mySelection.setBottomRight(currentPoint); if(moveMode == ScribbleArea::TOPLEFT) mySelection.setTopLeft(currentPoint); if(moveMode == ScribbleArea::TOPRIGHT) mySelection.setTopRight(currentPoint); if(moveMode == ScribbleArea::BOTTOMLEFT) mySelection.setBottomLeft(currentPoint); if(moveMode == ScribbleArea::BOTTOMRIGHT) mySelection.setBottomRight(currentPoint); myTransformedSelection = mySelection.adjusted(0,0,0,0); myTempTransformedSelection = mySelection.adjusted(0,0,0,0); if(layer->type == Layer::VECTOR) ((LayerVector*)layer)->getLastVectorImageAtFrame(editor->currentFrame, 0)->select(mySelection); update(); } // ---------------------------------------------------------------------- if (toolMode == ScribbleArea::ERASER && (layer->type == Layer::BITMAP || layer->type == Layer::VECTOR)) { if(event->buttons() & Qt::LeftButton) { // the user is also pressing the mouse (dragging) if(layer->type == Layer::VECTOR) { qreal radius = (eraser.width/2)/myTempView.m11(); QList nearbyVertices = ((LayerVector*)layer)->getLastVectorImageAtFrame(editor->currentFrame, 0)->getVerticesCloseTo(currentPoint, radius); for(int i=0; i< nearbyVertices.size(); i++) { ((LayerVector*)layer)->getLastVectorImageAtFrame(editor->currentFrame, 0)->setSelected(nearbyVertices.at(i), true); } //update(); } } } // ---------------------------------------------------------------------- if (toolMode == ScribbleArea::EDIT && (layer->type == Layer::BITMAP || layer->type == Layer::VECTOR)) { if(event->buttons() & Qt::LeftButton) { // the user is also pressing the mouse (dragging) { if( layer->type == Layer::VECTOR) { if( event->modifiers() != Qt::ShiftModifier) { // (and the user doesn't press shift) // transforms the selection selectionTransformation = QMatrix().translate(offset.x(), offset.y()); ((LayerVector*)layer)->getLastVectorImageAtFrame(editor->currentFrame, 0)->setSelectionTransformation(selectionTransformation); /*if(moveMode == ScribbleArea::MIDDLE) { if(QLineF(lastPixel,currentPixel).length()>4) myTempTransformedSelection = myTransformedSelection.translated(offset); } if(moveMode == ScribbleArea::TOPLEFT) myTempTransformedSelection = myTransformedSelection.adjusted(offset.x(), offset.y(), 0, 0); if(moveMode == ScribbleArea::TOPRIGHT) myTempTransformedSelection = myTransformedSelection.adjusted(0, offset.y(), offset.x(), 0); if(moveMode == ScribbleArea::BOTTOMLEFT) myTempTransformedSelection = myTransformedSelection.adjusted(offset.x(), 0, 0, offset.y()); if(moveMode == ScribbleArea::BOTTOMRIGHT) myTempTransformedSelection = myTransformedSelection.adjusted(0, 0, offset.x(), offset.y()); calculateSelectionTransformation();*/ //update(); } } } else { // the user is moving the mouse without pressing it if(layer->type == Layer::VECTOR) { closestVertices = ((LayerVector*)layer)->getLastVectorImageAtFrame(editor->currentFrame, 0)->getVerticesCloseTo(currentPoint, tol/myTempView.m11()); } //update(); } update(); } // ---------------------------------------------------------------------- if (toolMode == ScribbleArea::MOVE && (layer->type == Layer::BITMAP || layer->type == Layer::VECTOR)) { if(event->buttons() & Qt::LeftButton) { // the user is also pressing the mouse (dragging) if( somethingSelected) { // there is something selected if( event->modifiers() != Qt::ShiftModifier) { // (and the user doesn't press shift) // transforms the selection if(moveMode == ScribbleArea::MIDDLE) { if(QLineF(lastPixel,currentPixel).length()>4) myTempTransformedSelection = myTransformedSelection.translated(offset); } if(moveMode == ScribbleArea::TOPLEFT) myTempTransformedSelection = myTransformedSelection.adjusted(offset.x(), offset.y(), 0, 0); if(moveMode == ScribbleArea::TOPRIGHT) myTempTransformedSelection = myTransformedSelection.adjusted(0, offset.y(), offset.x(), 0); if(moveMode == ScribbleArea::BOTTOMLEFT) myTempTransformedSelection = myTransformedSelection.adjusted(offset.x(), 0, 0, offset.y()); if(moveMode == ScribbleArea::BOTTOMRIGHT) myTempTransformedSelection = myTransformedSelection.adjusted(0, 0, offset.x(), offset.y()); calculateSelectionTransformation(); update(); } } else { // there is nothing selected //selectionTransformation = selectionTransformation.translate(offset.x(), offset.y()); //if(layer->type == Layer::VECTOR) ((LayerVector*)layer)->getLastVectorImageAtFrame(editor->currentFrame, 0)->setSelectionTransformation(selectionTransformation); //VectorImage* vectorImage = ((LayerVector*)layer)->getLastVectorImageAtFrame(editor->currentFrame, 0); //setSelection( vectorImage->getSelectionRect() ); // we switch to the select tool editor->getToolSet()->changeSelectButton(); selectOn(); moveMode = ScribbleArea::MIDDLE; mySelection.setTopLeft( lastPoint ); mySelection.setBottomRight( lastPoint ); setSelection(mySelection, true); } } else { // the user is moving the mouse without pressing it if(layer->type == Layer::VECTOR) { closestCurves = ((LayerVector*)layer)->getLastVectorImageAtFrame(editor->currentFrame, 0)->getCurvesCloseTo(currentPoint, tol/myTempView.m11()); } update(); } } // ---------------------------------------------------------------------- if ( toolMode == ScribbleArea::HAND && (event->buttons() != Qt::NoButton || event->buttons() & Qt::RightButton) ) { if(event->modifiers() & Qt::ControlModifier || event->modifiers() & Qt::AltModifier || event->buttons() & Qt::RightButton) { QPoint centralPixel(width()/2, height()/2); if(lastPixel.x() != centralPixel.x()) { qreal scale = 1.0; qreal cosine = 1.0; qreal sine = 0.0; if( event->modifiers() & Qt::AltModifier) { // rotation QPointF V1 = lastPixel-centralPixel; QPointF V2 = currentPixel-centralPixel; cosine = ( V1.x()*V2.x() + V1.y()*V2.y() )/(BezierCurve::eLength(V1)*BezierCurve::eLength(V2)); sine = ( -V1.x()*V2.y() + V1.y()*V2.x() )/(BezierCurve::eLength(V1)*BezierCurve::eLength(V2)); } if( event->modifiers() & Qt::ControlModifier || event->buttons() & Qt::RightButton) { // scale scale = exp( 0.01*( currentPixel.y()-lastPixel.y() ) ); } transMatrix = QMatrix( scale*cosine, -scale*sine, scale*sine, scale*cosine, 0.0, 0.0 ); } } else { // translation transMatrix.setMatrix(1.0,0.0,0.0,1.0, currentPixel.x()-lastPixel.x(), currentPixel.y()-lastPixel.y()); } update(); } // ---------------------------------------------------------------------- if( toolMode == EYEDROPPER ) { if(layer->type == Layer::BITMAP) { BitmapImage* targetImage = ((LayerBitmap*)layer)->getLastBitmapImageAtFrame(editor->currentFrame, 0); if( targetImage->contains(currentPoint) ) { QColor pickedColour = targetImage->pixel(currentPoint.x(), currentPoint.y()); if(pickedColour.alpha() != 0) drawEyedropperPreview(pickedColour); } } if(layer->type == Layer::VECTOR) { VectorImage* vectorImage = ((LayerVector*)layer)->getLastVectorImageAtFrame(editor->currentFrame, 0); int colourNumber = vectorImage->getColourNumber(currentPoint); if( colourNumber != -1) { drawEyedropperPreview( editor->object->getColour(colourNumber).colour ); } } } } void ScribbleArea::mouseReleaseEvent(QMouseEvent *event) { mouseInUse = false; Layer* layer = editor->getCurrentLayer(); // ---- checks ------ if(layer==NULL) return; if(layer->type == Layer::VECTOR) { VectorImage* vectorImage = ((LayerVector*)layer)->getLastVectorImageAtFrame(editor->currentFrame, 0); if (vectorImage == NULL) return; } if(layer->type == Layer::BITMAP) { BitmapImage* bitmapImage = ((LayerBitmap*)layer)->getLastBitmapImageAtFrame(editor->currentFrame, 0); if (bitmapImage == NULL) return; } // ---- end checks ------ //currentWidth = myPenWidth; if(layer->type == Layer::BITMAP || layer->type == Layer::VECTOR) { if ((event->button() == Qt::LeftButton) && (toolMode == ScribbleArea::PENCIL || toolMode == ScribbleArea::ERASER || toolMode == ScribbleArea::PEN)) { drawLineTo(currentPixel, currentPoint); } } if(event->button() == Qt::LeftButton) { // ====================================================================== if(layer->type == Layer::BITMAP) { // ---------------------------------------------------------------------- if( toolMode == BUCKET) { BitmapImage* sourceImage = ((LayerBitmap*)layer)->getLastBitmapImageAtFrame(editor->currentFrame, 0); Layer* targetLayer = layer; // by default int layerNumber = editor->currentLayer; // by default if( editor->currentLayer > 0) { Layer* layer2 = editor->getCurrentLayer(-1); if(layer2->type == Layer::BITMAP) { targetLayer = layer2; layerNumber = layerNumber - 1; } } BitmapImage* targetImage = ((LayerBitmap*)targetLayer)->getLastBitmapImageAtFrame(editor->currentFrame, 0); BitmapImage::floodFill( sourceImage, targetImage, lastPoint.toPoint(), qRgba(0,0,0,0), brush.colour.rgba(), 10*10, true); setModified(layerNumber, editor->currentFrame); } // ---------------------------------------------------------------------- if( toolMode == EYEDROPPER) { BitmapImage* targetImage = ((LayerBitmap*)layer)->getLastBitmapImageAtFrame(editor->currentFrame, 0); QColor pickedColour = targetImage->pixel(lastPoint.x(), lastPoint.y()); if(pickedColour.alpha() != 0) editor->setColour( pickedColour ); } // ---------------------------------------------------------------------- if( toolMode == PENCIL || toolMode == PEN || toolMode == ERASER || toolMode == COLOURING ) { paintBitmapBuffer(); } } // ====================================================================== if(layer->type == Layer::VECTOR) { // ---------------------------------------------------------------------- if( toolMode == BUCKET) { VectorImage* vectorImage = ((LayerVector*)layer)->getLastVectorImageAtFrame(editor->currentFrame, 0); if(event->modifiers() == Qt::AltModifier) { vectorImage->removeArea(lastPoint); } else { floodFill(vectorImage, lastPixel.toPoint(), qRgba(0,0,0,0), qRgb(200,200,200), 100*100); } setModified(editor->currentLayer, editor->currentFrame); } // ---------------------------------------------------------------------- if( toolMode == EYEDROPPER) { VectorImage* vectorImage = ((LayerVector*)layer)->getLastVectorImageAtFrame(editor->currentFrame, 0); int colourNumber = vectorImage->getColourNumber(lastPoint); if( colourNumber != -1) { editor->selectColour( colourNumber ); } } // ---------------------------------------------------------------------- if( toolMode == COLOURING) { // Clear the temporary pixel path bufferImg->clear(); ((LayerVector*)layer)->getLastVectorImageAtFrame(editor->currentFrame, 0)->colour(mousePath, brush.colourNumber); //((LayerImage*)layer)->setModified(editor->currentFrame, true); //update(); setModified(editor->currentLayer, editor->currentFrame); } // ---------------------------------------------------------------------- if( (toolMode == ScribbleArea::PENCIL || toolMode == ScribbleArea::PEN) && mousePath.size() > -1 ) { // Clear the temporary pixel path bufferImg->clear(); qreal tol = curveSmoothing/qAbs( myView.m11() ); BezierCurve curve(mousePath, mousePressure, tol); if(toolMode == PEN) { curve.setWidth(pen.width); curve.setFeather(0); curve.setInvisibility(false); curve.setVariableWidth(usePressure); curve.setColourNumber(pen.colourNumber); } else { curve.setWidth(0); curve.setFeather(0); curve.setInvisibility(true); curve.setVariableWidth(false); curve.setColourNumber(pencil.colourNumber); } VectorImage* vectorImage = ((LayerVector*)layer)->getLastVectorImageAtFrame(editor->currentFrame, 0); //curve.setSelected(true); //qDebug() << "this curve has " << curve.getVertexSize() << "vertices"; vectorImage->addCurve(curve, qAbs(myView.m11()) ); //if(layer->type == Layer::BITMAP || layer->type == Layer::VECTOR) ((LayerImage*)layer)->setModified(editor->currentFrame, true); //update(); setModified(editor->currentLayer, editor->currentFrame); } // ---------------------------------------------------------------------- if( toolMode == ScribbleArea::ERASER ) { VectorImage* vectorImage = ((LayerVector*)layer)->getLastVectorImageAtFrame(editor->currentFrame, 0); // Clear the area containing the last point //vectorImage->removeArea(lastPoint); // Clear the temporary pixel path bufferImg->clear(); vectorImage->deleteSelectedPoints(); //update(); setModified(editor->currentLayer, editor->currentFrame); } } } // ====================== for all kinds of layers ======================= // ---------------------------------------------------------------------- if ((toolMode == ScribbleArea::EDIT) && (event->button() == Qt::LeftButton)) { if(layer->type == Layer::VECTOR) { VectorImage* vectorImage = ((LayerVector*)layer)->getLastVectorImageAtFrame(editor->currentFrame, 0); vectorImage->applySelectionTransformation(); selectionTransformation.reset(); for(int k=0; kcurve[curveNumber].smoothCurve(); } setModified(editor->currentLayer, editor->currentFrame); } } if ((toolMode == ScribbleArea::MOVE) && (event->button() == Qt::LeftButton) && (layer->type == Layer::BITMAP || layer->type == Layer::VECTOR)) { offset.setX(0); offset.setY(0); calculateSelectionTransformation(); //if(layer->type == Layer::VECTOR) { // closestCurves = ((LayerVector*)layer)->getLastVectorImageAtFrame(editor->currentFrame, 0)->getCurvesCloseTo(currentPoint, tol/myView.m11()); // closestVertices = ((LayerVector*)layer)->getLastVectorImageAtFrame(editor->currentFrame, 0)->getVerticesCloseTo(currentPoint, tol/myView.m11()); //} //if(somethingSelected && layer->type == Layer::VECTOR) { //editor->backup(); //((LayerVector*)layer)->getLastVectorImageAtFrame(editor->currentFrame, 0)->applySelectionTransformation(); //} //if( (mySelection.width() > 1) || (mySelection.height() > 1) ) { myTransformedSelection = myTempTransformedSelection; // update(); //} //if(layer->type == Layer::BITMAP || layer->type == Layer::VECTOR) ((LayerImage*)layer)->setModified(editor->currentFrame, true); if(layer->type == Layer::VECTOR) { if(somethingSelected) { //VectorImage* vectorImage = ((LayerVector*)layer)->getLastVectorImageAtFrame(editor->currentFrame, 0); //-- we should recalculate the intersections, once the curved are moved! //vectorImage->reinsertSelection(); } } setModified(editor->currentLayer, editor->currentFrame); } // ---------------------------------------------------------------------- if( toolMode == ScribbleArea::HAND || (event->button() == Qt::RightButton) ) { bufferImg->clear(); if(layer->type == Layer::CAMERA) { LayerCamera* layerCamera = (LayerCamera*)layer; QMatrix view = layerCamera->getViewAtFrame(editor->currentFrame); layerCamera->loadImageAtFrame(editor->currentFrame, view * transMatrix); //Camera* camera = ((LayerCamera*)layer)->getLastCameraAtFrame(editor->currentFrame, 0); //camera->view = camera->view * transMatrix; } else { myView = myView * transMatrix; } transMatrix.reset(); updateAllVectorLayers(); //update(); } // ---------------------------------------------------------------------- if( toolMode == ScribbleArea::SELECT && (event->button() == Qt::LeftButton) && (layer->type == Layer::BITMAP || layer->type == Layer::VECTOR)) { if(layer->type == Layer::VECTOR) { if(somethingSelected) { editor->getToolSet()->changeMoveButton(); moveOn(); VectorImage* vectorImage = ((LayerVector*)layer)->getLastVectorImageAtFrame(editor->currentFrame, 0); setSelection( vectorImage->getSelectionRect(), true ); if(mySelection.size() == QSizeF(0,0)) somethingSelected = false; } } updateFrame(); } // ---------------------------------------------------------------------- //update(); tabletInUse = false; } void ScribbleArea::mouseDoubleClickEvent(QMouseEvent *event) { if( toolMode == ScribbleArea::HAND || event->button() == Qt::RightButton ) { resetView(); } else { if( toolMode == ScribbleArea::POLYLINE && BezierCurve::eLength(lastPixel.toPoint() - event->pos()) < 2.0 ) { endPolyline(); } else { mousePressEvent(event); } } } void ScribbleArea::paintBitmapBuffer() { Layer* layer = editor->getCurrentLayer(); // ---- checks ------ if(layer==NULL) return; // Clear the temporary pixel path BitmapImage* targetImage = ((LayerBitmap*)layer)->getLastBitmapImageAtFrame(editor->currentFrame, 0); if(targetImage!=NULL) { QPainter::CompositionMode cm = QPainter::CompositionMode_SourceOver; switch(toolMode) { case ERASER: cm = QPainter::CompositionMode_DestinationOut; break; case COLOURING: if(brush.preserveAlpha) cm = QPainter::CompositionMode_SourceAtop; if(followContour) { // writes on the layer below if( editor->currentLayer > 0) { Layer* layer2 = editor->getCurrentLayer(-1); if(layer2->type == Layer::BITMAP) { targetImage = ((LayerBitmap*)layer2)->getLastBitmapImageAtFrame(editor->currentFrame, 0); } } } break; case PEN: if(pen.preserveAlpha) cm = QPainter::CompositionMode_SourceAtop; break; case PENCIL: if(pencil.preserveAlpha) cm = QPainter::CompositionMode_SourceAtop; break; } targetImage->paste(bufferImg, cm); } QRect rect = myTempView.mapRect(bufferImg->boundaries); // Clear the buffer bufferImg->clear(); //setModified(layer, editor->currentFrame); ((LayerImage*)layer)->setModified(editor->currentFrame, true); emit modification(); QPixmapCache::remove("frame"+QString::number(editor->currentFrame)); readCanvasFromCache = false; updateCanvas(editor->currentFrame, rect.adjusted(-1,-1,1,1) ); update(rect); } void ScribbleArea::paintEvent(QPaintEvent* event) { //qDebug() << "paint event!" << QDateTime::currentDateTime() << event->rect(); //readCanvasFromCache << mouseInUse << editor->currentFrame; QPainter painter(this); // draws the background (if necessary) if(mouseInUse && toolMode == HAND) { painter.setWorldMatrix(myTempView); painter.setWorldMatrixEnabled(true); painter.setPen(Qt::NoPen); painter.setBrush(backgroundBrush); painter.drawRect( (myTempView).inverted().mapRect( QRect(-2,-2, width()+3, height()+3) ) ); // this is necessary to have the background move with the view } // process the canvas (or not) if(!mouseInUse && readCanvasFromCache) { // --- we retrieve the canvas from the cache; we create it if it doesn't exist int frameNumber = editor->getLastFrameAtFrame( editor->currentFrame ); if(!QPixmapCache::find("frame"+QString::number(frameNumber), canvas)) { updateCanvas(editor->currentFrame, event->rect()); QPixmapCache::insert("frame"+QString::number(frameNumber), canvas); } } if(toolMode == MOVE) { Layer* layer = editor->getCurrentLayer(); if(layer->type == Layer::VECTOR) ((LayerVector*)layer)->getLastVectorImageAtFrame(editor->currentFrame, 0)->setModified(true); updateCanvas(editor->currentFrame, event->rect()); } // paints the canvas painter.setWorldMatrixEnabled(true); painter.setWorldMatrix( centralView.inverted() * transMatrix * centralView ); painter.drawPixmap( QPoint(0,0), canvas ); Layer* layer = editor->getCurrentLayer(); if(!layer) return; if(!editor->playing) { // we don't need to display the following when the animation is playing painter.setWorldMatrix(myTempView); if(layer->type == Layer::VECTOR) { VectorImage* vectorImage = ((LayerVector*)layer)->getLastVectorImageAtFrame(editor->currentFrame, 0); if(toolMode == EDIT || toolMode == HAND) { //bufferImg->clear(); painter.save(); painter.setWorldMatrixEnabled(false); painter.setRenderHint(QPainter::Antialiasing, false); // ----- paints the edited elements QPen pen2(Qt::black, 0.5, Qt::SolidLine, Qt::RoundCap,Qt::RoundJoin); painter.setPen( pen2 ); QColor colour; // ------------ vertices of the edited curves colour = QColor(200,200,200); painter.setBrush( colour ); for(int k=0; kcurve[curveNumber].getStrokedPath(); //bufferImg->drawPath( myTempView.map(path), pen2, colour, QPainter::CompositionMode_SourceOver, false); for(int vertexNumber=-1; vertexNumbergetCurveSize(curveNumber); vertexNumber++) { QPointF vertexPoint = vectorImage->getVertex(curveNumber, vertexNumber); QRectF rectangle = QRectF( (myView*transMatrix*centralView).map(vertexPoint)-QPointF(3.0,3.0), QSizeF(7,7) ); if(rect().contains( (myView*transMatrix*centralView).map(vertexPoint).toPoint())) { painter.drawRect( rectangle.toRect() ); //bufferImg->drawRect( rectangle.toRect(), pen2, colour, QPainter::CompositionMode_SourceOver, false); } } } // ------------ selected vertices of the edited curves colour = QColor(100,100,255); painter.setBrush( colour ); for(int k=0; kgetVertex(vertexRef); QRectF rectangle0 = QRectF( (myView*transMatrix*centralView).map(vertexPoint)-QPointF(3.0,3.0), QSizeF(7,7) ); painter.drawRect( rectangle0.toRect() ); //bufferImg->drawRect( rectangle0, pen2, colour, QPainter::CompositionMode_SourceOver, false); /* --- draws the control points -- maybe editable in a future version (although not recommended) QPointF c1Point = vectorImage->getC1(vertexRef.nextVertex()); QPointF c2Point = vectorImage->getC2(vertexRef); QRectF rectangle1 = QRectF( myTempView.map(c1Point)-QPointF(3.0,3.0), QSize(7,7) ); QRectF rectangle2 = QRectF( myTempView.map(c2Point)-QPointF(3.0,3.0), QSize(7,7) ); bufferImg->drawLine( myTempView.map(vertexPoint), myTempView.map(c1Point), colour, QPainter::CompositionMode_SourceOver, antialiasing); bufferImg->drawLine( myTempView.map(vertexPoint), myTempView.map(c2Point), colour, QPainter::CompositionMode_SourceOver, antialiasing); bufferImg->drawRect( rectangle0, pen2, colour, QPainter::CompositionMode_SourceOver, false); bufferImg->drawEllipse( rectangle1, pen2, Qt::white, QPainter::CompositionMode_SourceOver, false); bufferImg->drawEllipse( rectangle2, pen2, Qt::white, QPainter::CompositionMode_SourceOver, false);*/ } // ----- paints the closest vertices colour = QColor(255,0,0); painter.setBrush( colour ); if( vectorSelection.curve.size() > 0 ) { for(int k=0; kgetVertex(vertexRef); //if( vectorImage->isSelected(vertexRef) ) vertexPoint = selectionTransformation.map( vertexPoint ); QRectF rectangle = QRectF( (myView*transMatrix*centralView).map(vertexPoint)-QPointF(3.0,3.0), QSizeF(7,7) ); painter.drawRect( rectangle.toRect() ); //bufferImg->drawRect( rectangle.toRect(), pen2, colour, QPainter::CompositionMode_SourceOver, false); } } painter.restore(); } if(toolMode == MOVE) { // ----- paints the closest curves bufferImg->clear(); QPen pen2(Qt::black, 0.5, Qt::SolidLine, Qt::RoundCap,Qt::RoundJoin); QColor colour = QColor(100,100,255); for(int k=0; kcurve[closestCurves[k]]; if(myCurve.isPartlySelected()) myCurve.transform( selectionTransformation ); QPainterPath path = myCurve.getStrokedPath(1.2/scale, false); bufferImg->drawPath( (myView*transMatrix*centralView).map(path), pen2, colour, QPainter::CompositionMode_SourceOver, antialiasing); } } } // paints the buffer image if(editor->getCurrentLayer() != NULL) { painter.setOpacity(1.0); if(editor->getCurrentLayer()->type == Layer::BITMAP) painter.setWorldMatrixEnabled(true); if(editor->getCurrentLayer()->type == Layer::VECTOR) painter.setWorldMatrixEnabled(false); bufferImg->paintImage(painter); } // paints the selection outline if( somethingSelected && myTempTransformedSelection.isValid() ) { // outline of the transformed selection painter.setWorldMatrixEnabled(false); painter.setOpacity(1.0); QPolygon tempRect = (myView*transMatrix*centralView).mapToPolygon( myTempTransformedSelection.normalized().toRect() ); Layer* layer = editor->getCurrentLayer(); if(layer != NULL) { if(layer->type == Layer::BITMAP) { painter.setBrush(Qt::NoBrush); painter.setPen(Qt::DashLine); } if(layer->type == Layer::VECTOR) { painter.setBrush(QColor(0,0,0,20)); painter.setPen(Qt::gray); } painter.drawPolygon( tempRect ); if(layer->type != Layer::VECTOR || toolMode != SELECT) { painter.setPen(Qt::SolidLine); painter.setBrush(QBrush(Qt::gray)); painter.drawRect( tempRect.point(0).x()-3, tempRect.point(0).y()-3, 6, 6 ); painter.drawRect( tempRect.point(1).x()-3, tempRect.point(1).y()-3, 6, 6 ); painter.drawRect( tempRect.point(2).x()-3, tempRect.point(2).y()-3, 6, 6 ); painter.drawRect( tempRect.point(3).x()-3, tempRect.point(3).y()-3, 6, 6 ); } } } } // clips to the frame of the camera if(layer->type == Layer::CAMERA) { QRect rect = ((LayerCamera*)layer)->getViewRect(); rect.translate( width()/2, height()/2 ); painter.setWorldMatrixEnabled(false); painter.setPen(Qt::NoPen); painter.setBrush(QColor(0,0,0,160)); painter.drawRect( QRect(0, 0, width(), (height() - rect.height())/2) ); painter.drawRect( QRect(0, rect.bottom(), width(), (height() - rect.height())/2) ); painter.drawRect( QRect(0, rect.top(), (width() - rect.width())/2, rect.height()-1) ); painter.drawRect( QRect((width() + rect.width())/2, rect.top(), (width() - rect.width())/2, rect.height()-1) ); painter.setPen(Qt::black); painter.setBrush(Qt::NoBrush); painter.drawRect(rect); } // outlines the frame of the viewport painter.setWorldMatrixEnabled(false); painter.setPen( QPen(Qt::gray, 2) ); painter.setBrush(Qt::NoBrush); painter.drawRect(QRect(0,0, width(), height())); // shadow if(shadows && !editor->playing && (!mouseInUse || toolMode == HAND)) { int radius1 = 12; int radius2 = 8; QLinearGradient shadow = QLinearGradient( 0, 0, 0, radius1); setGaussianGradient(shadow, Qt::black, 0.15, 0.0); painter.setPen(Qt::NoPen); painter.setBrush(shadow); painter.drawRect(QRect(0,0, width(), radius1)); shadow.setFinalStop(radius1, 0); painter.setBrush(shadow); painter.drawRect(QRect(0,0, radius1, height())); shadow.setStart(0, height()); shadow.setFinalStop(0, height()-radius2); painter.setBrush(shadow); painter.drawRect(QRect(0,height()-radius2, width(), height())); shadow.setStart(width(), 0); shadow.setFinalStop(width()-radius2, 0); painter.setBrush(shadow); painter.drawRect(QRect(width()-radius2,0, width(), height())); } event->accept(); } void ScribbleArea::updateCanvas(int frame, QRect rect) { //qDebug() << "paint canvas!" << QDateTime::currentDateTime(); // merge the different layers into the ScribbleArea QPainter painter(&canvas); if(myTempView.det() == 1.0) { painter.setRenderHint(QPainter::SmoothPixmapTransform, false); } else { painter.setRenderHint(QPainter::SmoothPixmapTransform, antialiasing); } painter.setClipRect(rect); painter.setClipping(true); setView(); painter.setWorldMatrix(myTempView); painter.setWorldMatrixEnabled(true); // background painter.setPen(Qt::NoPen); painter.setBrush(backgroundBrush); painter.drawRect( myTempView.inverted().mapRect( QRect(-2,-2, width()+3, height()+3) ) ); // this is necessary to have the background move with the view // grid bool drawGrid = false; if(drawGrid) { painter.setOpacity(1.0); painter.setPen(Qt::gray); painter.setBrush(Qt::NoBrush); // What kind of grid do we want? //painter.drawRect(QRect(0,0, mySize.width(), mySize.height())); //painter.drawLine( QPoint(0,mySize.height()/2), QPoint(mySize.width(), mySize.height()/2) ); //painter.drawLine( QPoint(mySize.width()/3, 0), QPoint(mySize.width()/3, mySize.height()) ); //painter.drawLine( QPoint(mySize.width()*2/3, 0), QPoint(mySize.width()*2/3, mySize.height()) ); } Object* object = editor->object; qreal opacity; for(int i=0; i < object->getLayerCount(); i++) { opacity = 1.0; if(i != editor->currentLayer && (showAllLayers == 1)) { opacity = 0.4; } if(editor->getCurrentLayer()->type == Layer::CAMERA) opacity = 1.0; Layer* layer = (object->getLayer(i)); if(layer->visible && (showAllLayers>0 || i == editor->currentLayer)) { // paints the bitmap images if(layer->type == Layer::BITMAP) { LayerBitmap* layerBitmap = (LayerBitmap*)layer; BitmapImage* bitmapImage = layerBitmap->getLastBitmapImageAtFrame(frame, 0); if(bitmapImage != NULL) { painter.setWorldMatrixEnabled(true); // previous frame (onion skin) BitmapImage* previousImage = layerBitmap->getLastBitmapImageAtFrame(frame, -1); if(previousImage != NULL && onionPrev) { painter.setOpacity(opacity*0.5); previousImage->paintImage(painter); } //painter.drawImage(previousImage->topLeft(), *(previousImage->image) ); // next frame (onion skin) BitmapImage* nextImage = layerBitmap->getLastBitmapImageAtFrame(frame, 1); if(nextImage != NULL && onionNext) { painter.setOpacity(opacity*0.5); nextImage->paintImage(painter); } // current frame painter.setOpacity(opacity); if(i==editor->currentLayer && somethingSelected && (myTempTransformedSelection != mySelection) ) { // hole in the original selection -- might support arbitrary shapes in the future painter.setClipping(true); QRegion clip = QRegion(mySelection.toRect()); QRegion totalImage = QRegion( myTempView.inverted().mapRect( QRect(-2,-2, width()+3, height()+3) ) ); QRegion ImageWithHole = totalImage-=clip; painter.setClipRegion(ImageWithHole, Qt::ReplaceClip); //painter.drawImage(bitmapImage->topLeft(), *(bitmapImage->image) ); bitmapImage->paintImage(painter); painter.setClipping(false); // transforms the bitmap selection bool smoothTransform = false; if(myTempTransformedSelection.width() != mySelection.width() || myTempTransformedSelection.height() != mySelection.height() ) smoothTransform = true; BitmapImage selectionClip = bitmapImage->copy(mySelection.toRect()); selectionClip.transform(myTempTransformedSelection, smoothTransform); selectionClip.paintImage(painter); //painter.drawImage(selectionClip.topLeft(), *(selectionClip.image)); } else { //painter.drawImage(bitmapImage->topLeft(), *(bitmapImage->image) ); bitmapImage->paintImage(painter); } //painter.setPen(Qt::red); //painter.setBrush(Qt::NoBrush); //painter.drawRect(bitmapImage->boundaries); } } // paints the vector images if(layer->type == Layer::VECTOR) { LayerVector* layerVector = (LayerVector*)layer; VectorImage* vectorImage = layerVector->getLastVectorImageAtFrame(frame, 0); if( somethingSelected ) { // transforms the vector selection //calculateSelectionTransformation(); vectorImage->setSelectionTransformation(selectionTransformation); //vectorImage->setTransformedSelection(myTempTransformedSelection); } QImage* image = layerVector->getLastImageAtFrame(frame, 0, size(), simplified, showThinLines, curveOpacity, antialiasing, gradients); if(image != NULL) { painter.setWorldMatrixEnabled(false); // previous frame (onion skin) QImage* previousImage = layerVector->getLastImageAtFrame(frame, -1, size(), simplified, showThinLines, curveOpacity, antialiasing, gradients); if(previousImage != NULL && onionPrev) { painter.setOpacity(opacity*0.5); painter.drawImage(QPoint(0, 0), *previousImage ); } // next frame (onion skin) QImage* nextImage = layerVector->getLastImageAtFrame(frame, 1, size(), simplified, showThinLines, curveOpacity, antialiasing, gradients); if(nextImage != NULL && onionNext) { painter.setOpacity(opacity*0.5); painter.drawImage(QPoint(0, 0), *nextImage ); } // current frame painter.setOpacity(opacity); painter.drawImage(QPoint(0, 0), *image); } } } } painter.end(); } void ScribbleArea::setGaussianGradient(QGradient &gradient, QColor colour, qreal opacity, qreal offset) { int r = colour.red(); int g = colour.green(); int b = colour.blue(); qreal a = colour.alphaF(); gradient.setColorAt(0.0, QColor(r, g, b, qRound(a*255*opacity)) ); gradient.setColorAt(offset+0.0*(1.0-offset), QColor(r, g, b, qRound(a*255*opacity)) ); gradient.setColorAt(offset+0.1*(1.0-offset), QColor(r, g, b, qRound(a*245*opacity)) ); gradient.setColorAt(offset+0.2*(1.0-offset), QColor(r, g, b, qRound(a*217*opacity)) ); gradient.setColorAt(offset+0.3*(1.0-offset), QColor(r, g, b, qRound(a*178*opacity)) ); gradient.setColorAt(offset+0.4*(1.0-offset), QColor(r, g, b, qRound(a*134*opacity)) ); gradient.setColorAt(offset+0.5*(1.0-offset), QColor(r, g, b, qRound(a*94*opacity)) ); gradient.setColorAt(offset+0.6*(1.0-offset), QColor(r, g, b, qRound(a*60*opacity)) ); gradient.setColorAt(offset+0.7*(1.0-offset), QColor(r, g, b, qRound(a*36*opacity)) ); gradient.setColorAt(offset+0.8*(1.0-offset), QColor(r, g, b, qRound(a*20*opacity)) ); gradient.setColorAt(offset+0.9*(1.0-offset), QColor(r, g, b, qRound(a*10*opacity)) ); gradient.setColorAt(offset+1.0*(1.0-offset), QColor(r, g, b, 0) ); } void ScribbleArea::drawBrush(QPointF thePoint, qreal brushWidth, qreal offset, QColor fillColour, qreal opacity) { QRadialGradient radialGrad(thePoint, 0.5*brushWidth); setGaussianGradient(radialGrad, fillColour, opacity, offset); //radialGrad.setCenter( thePoint ); //radialGrad.setFocalPoint( thePoint ); QRectF rectangle(thePoint.x()-0.5*brushWidth, thePoint.y()-0.5*brushWidth, brushWidth, brushWidth); BitmapImage* tempBitmapImage = new BitmapImage(NULL); if(followContour) { tempBitmapImage = new BitmapImage(NULL, rectangle.toRect(), QColor(0,0,0,0)); //tempBitmapImage->drawRect( rectangle, Qt::NoPen, QColor(0,0,0,0), QPainter::CompositionMode_Source, antialiasing); Layer* layer = editor->getCurrentLayer(); if(layer == NULL) return; int index = ((LayerImage*)layer)->getLastIndexAtFrame(editor->currentFrame); if(index == -1) return; BitmapImage* bitmapImage = ((LayerBitmap*)layer)->getLastBitmapImageAtFrame(editor->currentFrame, 0); if(bitmapImage == NULL) { qDebug() << "NULL image pointer!" << editor->currentLayer << editor->currentFrame; return; } BitmapImage::floodFill(bitmapImage, tempBitmapImage, thePoint.toPoint(), qRgba(255,255,255,0), fillColour.rgb(), 20*20, false); tempBitmapImage->drawRect( rectangle.toRect(), Qt::NoPen, radialGrad, QPainter::CompositionMode_SourceIn, antialiasing); } else { tempBitmapImage = new BitmapImage(NULL); tempBitmapImage->drawRect( rectangle, Qt::NoPen, radialGrad, QPainter::CompositionMode_Source, antialiasing); } bufferImg->paste(tempBitmapImage); delete tempBitmapImage; } void ScribbleArea::drawLineTo(const QPointF &endPixel, const QPointF &endPoint) { Layer* layer = editor->getCurrentLayer(); if(layer == NULL) return; if(layer->type == Layer::BITMAP) { //int index = ((LayerImage*)layer)->getLastIndexAtFrame(editor->currentFrame); //if(index == -1) return; //BitmapImage* bitmapImage = ((LayerBitmap*)layer)->getLastBitmapImageAtFrame(editor->currentFrame, 0); //if(bitmapImage == NULL) { qDebug() << "NULL image pointer!" << editor->currentLayer << editor->currentFrame; return; } if (toolMode == ScribbleArea::ERASER) { QPen pen2 = QPen ( QBrush(QColor(255,255,255,255)), currentWidth, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin ); bufferImg->drawLine(lastPoint, endPoint, pen2, QPainter::CompositionMode_SourceOver, antialiasing); int rad = qRound(currentWidth / 2) + 2; update(myTempView.mapRect(QRect(lastPoint.toPoint(), endPoint.toPoint()).normalized().adjusted(-rad, -rad, +rad, +rad))); } if(toolMode == ScribbleArea::PENCIL) { QPen pen2 = QPen ( QBrush(currentColour), currentWidth, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin ); bufferImg->drawLine(lastPoint, endPoint, pen2, QPainter::CompositionMode_SourceOver, antialiasing); int rad = qRound(currentWidth / 2) + 3; update(myTempView.mapRect(QRect(lastPoint.toPoint(), endPoint.toPoint()).normalized().adjusted(-rad, -rad, +rad, +rad))); } if(toolMode == ScribbleArea::PEN) { QPen pen2 = QPen ( QBrush(pen.colour), currentWidth, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin ); bufferImg->drawLine(lastPoint, endPoint, pen2, QPainter::CompositionMode_SourceOver, antialiasing); int rad = qRound(currentWidth / 2) + 3; update(myTempView.mapRect(QRect(lastPoint.toPoint(), endPoint.toPoint()).normalized().adjusted(-rad, -rad, +rad, +rad))); } if(toolMode == ScribbleArea::COLOURING) { qreal opacity = 1.0; qreal brushWidth = brush.width + 0.5*brush.feather; qreal offset = qMax(0.0,brush.width-0.5*brush.feather)/brushWidth; if(tabletInUse) opacity = tabletPressure; if(usePressure) brushWidth = brushWidth*tabletPressure; qreal distance = 4*QLineF(endPoint, lastBrushPoint).length(); qreal brushStep = 0.5*brush.width + 0.5*brush.feather; if(usePressure) brushStep = brushStep*tabletPressure; brushStep = qMax(1.0, brushStep); int steps = qRound( distance)/brushStep ; for(int i=0; itype == Layer::VECTOR) { if (toolMode == ScribbleArea::ERASER) { bufferImg->drawLine(lastPixel, currentPixel, QPen(Qt::white, currentWidth, Qt::SolidLine, Qt::RoundCap,Qt::RoundJoin), QPainter::CompositionMode_SourceOver, antialiasing); int rad = qRound( (currentWidth/2 + 2)*qAbs( myTempView.m11() ) ); update(QRect(lastPixel.toPoint(), endPixel.toPoint()).normalized().adjusted(-rad, -rad, +rad, +rad)); } if(toolMode == ScribbleArea::PENCIL) { bufferImg->drawLine(lastPixel, currentPixel, QPen(currentColour, 1, Qt::DotLine, Qt::RoundCap,Qt::RoundJoin), QPainter::CompositionMode_SourceOver, antialiasing); int rad = qRound( ( currentWidth/2 + 2)*qAbs( myTempView.m11() ) ); update(QRect(lastPixel.toPoint(), endPixel.toPoint()).normalized().adjusted(-rad, -rad, +rad, +rad)); } if(toolMode == ScribbleArea::PEN) { bufferImg->drawLine(lastPixel, currentPixel, QPen(pen.colour, currentWidth*myTempView.m11(), Qt::SolidLine, Qt::RoundCap,Qt::RoundJoin), QPainter::CompositionMode_SourceOver, antialiasing); int rad = qRound( (currentWidth/2 + 2)* (qAbs(myTempView.m11())+qAbs(myTempView.m22())) ); update(QRect(lastPixel.toPoint(), endPixel.toPoint()).normalized().adjusted(-rad, -rad, +rad, +rad)); } if(toolMode == ScribbleArea::COLOURING) { bufferImg->drawLine(lastPixel, currentPixel, QPen(Qt::gray, 1, Qt::DashLine, Qt::RoundCap,Qt::RoundJoin), QPainter::CompositionMode_SourceOver, antialiasing); int rad = qRound( (currentWidth/2 + 2)*qAbs( myTempView.m11() ) ); update(QRect(lastPixel.toPoint(), endPixel.toPoint()).normalized().adjusted(-rad, -rad, +rad, +rad)); } } //emit modification(); lastPixel = endPixel; lastPoint = endPoint; } void ScribbleArea::drawEyedropperPreview(const QColor colour) { QPainter painter( eyedropperCursor ); painter.setPen(QPen(Qt::black, 1, Qt::SolidLine, Qt::RoundCap,Qt::RoundJoin)); painter.setBrush(colour); painter.drawRect( 10, 10, 20, 20); painter.end(); setCursor( QCursor(*eyedropperCursor, 5, 5) ); } void ScribbleArea::drawPolyline() { if(toolMode == POLYLINE) { if(mousePoints.size()>0) { QPen pen2(pen.colour, pen.width, Qt::SolidLine, Qt::RoundCap,Qt::RoundJoin); QPainterPath tempPath = BezierCurve(mousePoints).getSimplePath(); tempPath.lineTo(currentPoint); QRect updateRect = myTempView.mapRect(tempPath.boundingRect().toRect()).adjusted(-10,-10,10,10); if(editor->getCurrentLayer()->type == Layer::VECTOR) { tempPath = myTempView.map( tempPath ); if(makeInvisible) { pen2.setWidth(0); pen2.setStyle(Qt::DotLine);} else pen2.setWidth(pen.width*myTempView.m11()); } bufferImg->clear(); bufferImg->drawPath( tempPath, pen2, Qt::NoBrush, QPainter::CompositionMode_SourceOver, antialiasing); update( updateRect ); //update( QRect(lastPixel.toPoint(), currentPixel.toPoint()).normalized() ); //bufferImg->drawRect(tempPath.boundingRect().toRect()); //update( QRect(lastPixel.toPoint()-QPoint(10,10), lastPixel.toPoint()+QPoint(10,10)) ); //update(); } } } void ScribbleArea::endPolyline() { Layer* layer = editor->getCurrentLayer(); if(layer == NULL) return; if(layer->type == Layer::VECTOR) { BezierCurve curve = BezierCurve(mousePoints); if(makeInvisible) curve.setWidth(0); else curve.setWidth(pen.width); curve.setColourNumber( pen.colourNumber ); curve.setVariableWidth(false); curve.setInvisibility(makeInvisible); //curve.setSelected(true); ((LayerVector*)layer)->getLastVectorImageAtFrame(editor->currentFrame, 0)->addCurve(curve, qAbs(myTempView.m11()) ); } if(layer->type == Layer::BITMAP) { drawPolyline(); BitmapImage* bitmapImage = ((LayerBitmap*)layer)->getLastBitmapImageAtFrame(editor->currentFrame, 0); bitmapImage->paste(bufferImg); } bufferImg->clear(); while(!mousePoints.isEmpty()) mousePoints.removeAt(0); // empty the mousePoints setModified(editor->currentLayer, editor->currentFrame); } void ScribbleArea::resizeEvent(QResizeEvent *event) { //resize( size() ); QWidget::resizeEvent(event); canvas = QPixmap(size()); recentre(); updateAllFrames(); } void ScribbleArea::recentre() { centralView = QMatrix(1,0,0,1, 0.5*width(), 0.5*height()); setView(); QPixmapCache::clear(); update(); } void ScribbleArea::setMyView(QMatrix view) { myView = view; } QMatrix ScribbleArea::getMyView() { return myView; } void ScribbleArea::setView() { setView(getView()); } void ScribbleArea::setView(QMatrix view) { for(int i=0; i < editor->object->getLayerCount() ; i++) { Layer* layer = editor->object->getLayer(i); if(layer->type == Layer::VECTOR) { ((LayerVector*)layer)->setView(view * centralView); } } myTempView = view * centralView; } void ScribbleArea::resetView() { editor->resetMirror(); myView.reset(); myTempView = myView * centralView; recentre(); } QMatrix ScribbleArea::getView() { Layer* layer = editor->getCurrentLayer(); if(layer == NULL) return QMatrix(); // error if(layer->type == Layer::CAMERA) { return ((LayerCamera*)layer)->getViewAtFrame(editor->currentFrame); qDebug() << "viewCamera" << ((LayerCamera*)layer)->getViewAtFrame(editor->currentFrame); } else { return myView; } } QRectF ScribbleArea::getViewRect() { QRectF rect = QRectF( -width()/2, -height()/2, width(), height() ); Layer* layer = editor->getCurrentLayer(); if(layer == NULL) return rect; if(layer->type == Layer::CAMERA) { return ((LayerCamera*)layer)->getViewRect(); } else { return rect; } } QPointF ScribbleArea::getCentralPoint() { return myTempView.inverted().map( QPoint(width()/2, height()/2) ); } void ScribbleArea::calculateSelectionRect() { selectionTransformation.reset(); Layer* layer = editor->getCurrentLayer(); if(layer==NULL) return; if(layer->type == Layer::VECTOR) { VectorImage* vectorImage = ((LayerVector*)layer)->getLastVectorImageAtFrame(editor->currentFrame, 0); vectorImage->calculateSelectionRect(); setSelection( vectorImage->getSelectionRect(), true ); } } void ScribbleArea::calculateSelectionTransformation() { qreal c1x, c1y , c2x, c2y, scaleX, scaleY; c1x = 0.5*(myTempTransformedSelection.left()+myTempTransformedSelection.right()); c1y = 0.5*(myTempTransformedSelection.top()+myTempTransformedSelection.bottom()); c2x = 0.5*(mySelection.left()+mySelection.right()); c2y = 0.5*(mySelection.top()+mySelection.bottom()); if(mySelection.width() == 0) { scaleX = 1.0; } else { scaleX = myTempTransformedSelection.width()/mySelection.width(); } if(mySelection.height() == 0) { scaleY = 1.0; } else { scaleY = myTempTransformedSelection.height()/mySelection.height(); } selectionTransformation.reset(); selectionTransformation.translate(c1x,c1y); selectionTransformation.scale(scaleX, scaleY); selectionTransformation.translate(-c2x,-c2y); //modification(); } void ScribbleArea::paintTransformedSelection() { Layer* layer = editor->getCurrentLayer(); if(layer == NULL) return; if(somethingSelected) { // there is something selected if(layer->type == Layer::BITMAP && (myTransformedSelection != mySelection) ) { //backup(); BitmapImage* bitmapImage = ((LayerBitmap*)layer)->getLastBitmapImageAtFrame(editor->currentFrame, 0); if(bitmapImage == NULL) { qDebug() << "NULL image pointer!" << editor->currentLayer << editor->currentFrame; return; } bool smoothTransform = false; if(myTransformedSelection.width() != mySelection.width() || myTransformedSelection.height() != mySelection.height() ) smoothTransform = true; BitmapImage selectionClip = bitmapImage->copy(mySelection.toRect()); selectionClip.transform( myTransformedSelection, smoothTransform ); bitmapImage->clear(mySelection.toRect()); bitmapImage->paste(&selectionClip); } if(layer->type == Layer::VECTOR) { // vector transformation LayerVector* layerVector = (LayerVector*)layer; VectorImage* vectorImage = layerVector->getLastVectorImageAtFrame(editor->currentFrame, 0); vectorImage->applySelectionTransformation(); selectionTransformation.reset(); } //deselectAll(); //emit modification(); setModified(editor->currentLayer, editor->currentFrame); } } void ScribbleArea::setSelection(QRectF rect, bool trueOrFalse) { mySelection = rect; myTransformedSelection = rect; myTempTransformedSelection = rect; somethingSelected = trueOrFalse; displaySelectionProperties(); } void ScribbleArea::displaySelectionProperties() { Layer* layer = editor->getCurrentLayer(); if(layer == NULL) return; if(layer->type == Layer::VECTOR) { LayerVector* layerVector = (LayerVector*)layer; VectorImage* vectorImage = layerVector->getLastVectorImageAtFrame(editor->currentFrame, 0); //vectorImage->applySelectionTransformation(); if(toolMode == MOVE) { //if(closestCurves.size()>0) { int selectedCurve = vectorImage->getFirstSelectedCurve(); if(selectedCurve != -1) { editor->setWidth(vectorImage->curve[selectedCurve].getWidth()); editor->setFeather(vectorImage->curve[selectedCurve].getFeather()); editor->setOpacity(0); editor->setInvisibility(vectorImage->curve[selectedCurve].isInvisible()); editor->setPressure(vectorImage->curve[selectedCurve].getVariableWidth()); editor->selectColour(vectorImage->curve[selectedCurve].getColourNumber()); } int selectedArea = vectorImage->getFirstSelectedArea(); if(selectedArea != -1) { editor->selectColour(vectorImage->area[selectedArea].colourNumber); //editor->setFeather(vectorImage->area[selectedArea].getFeather()); } } } } void ScribbleArea::selectAll() { offset.setX(0); offset.setY(0); Layer* layer = editor->getCurrentLayer(); if(layer == NULL) return; if(layer->type == Layer::BITMAP) { setSelection( myTempView.inverted().mapRect( QRect(-2,-2, width()+3, height()+3) ), true ); // TO BE IMPROVED } if(layer->type == Layer::VECTOR) { VectorImage* vectorImage = ((LayerVector*)layer)->getLastVectorImageAtFrame(editor->currentFrame, 0); vectorImage->selectAll(); setSelection( vectorImage->getSelectionRect(), true ); } updateFrame(); } void ScribbleArea::deselectAll() { offset.setX(0); offset.setY(0); selectionTransformation.reset(); mySelection.setRect(10,10,20,20); myTransformedSelection.setRect(10,10,20,20); myTempTransformedSelection.setRect(10,10,20,20); Layer* layer = editor->getCurrentLayer(); if(layer == NULL) return; if(layer->type == Layer::VECTOR) { ((LayerVector*)layer)->getLastVectorImageAtFrame(editor->currentFrame, 0)->deselectAll(); if(toolMode == MOVE) { editor->setWidth(-1); editor->setOpacity(-1); editor->setInvisibility(-1); editor->setPressure(-1); } } somethingSelected = false; bufferImg->clear(); vectorSelection.clear(); while(!mousePoints.isEmpty()) mousePoints.removeAt(0); // empty the mousePoints updateFrame(); } void ScribbleArea::onionNextSlot() { onionNext = !onionNext; updateAllFrames(); } void ScribbleArea::onionPrevSlot() { onionPrev = !onionPrev; updateAllFrames(); } void ScribbleArea::floodFill(VectorImage* vectorImage, QPoint point, QRgb targetColour, QRgb replacementColour, int tolerance) { bool invertible; QPointF initialPoint = myTempView.inverted(&invertible).map(QPointF(point)); // Step 1: peforms a standard (pixel-based) flood fill, and finds the vertices on the contour of the filled area qreal tol = 8.0/qAbs(myTempView.m11()); // tolerance for finding vertices along the contour of the flood-filled area qreal tol2 = 1.5/qAbs(myTempView.m11()); // tolerance for connecting contour vertices from different curves // should be small as close points of different curves are supposed to coincide QList queue; // queue all the pixels of the filled area (as they are found) QList contourPixels; // list of the pixels near the contour of the filled area int j, k; bool condition; //vectorImage->update(true, showThinLines); // update the vector image with simplified curves (all width=1) QImage* targetImage = new QImage(size(), QImage::Format_ARGB32_Premultiplied); vectorImage->outputImage(targetImage, size(), myTempView, true, showThinLines, 1.0, true, false); // the target image is the vector image with simplified curves (all width=1) //QImage* replaceImage = &bufferImg; QImage* replaceImage = new QImage( size(), QImage::Format_ARGB32_Premultiplied); QList points = vectorImage->getAllVertices(); // refs of all the points QList boxPoints; // refs of points inside the bounding box QList contourPoints; // refs of points near the contour pixels QList vertices; if( BitmapImage::rgbDistance(targetImage->pixel(point.x(), point.y()), targetColour) > tolerance ) return; queue.append( point ); int boxLeft = point.x(); int boxRight = point.x(); int boxTop = point.y(); int boxBottom = point.y(); // ----- flood fill and remember the contour pixels -> contourPixels // ----- from the standard flood fill algorithm // ----- http://en.wikipedia.org/wiki/Flood_fill j = -1; k = 1; for(int i=0; i< queue.size(); i++ ) { point = queue.at(i); if( replaceImage->pixel(point.x(), point.y()) != replacementColour && BitmapImage::rgbDistance(targetImage->pixel(point.x(), point.y()), targetColour) < tolerance ) { //image.setPixel( point.x(), point.y(), replacementColour); j = -1; condition = (point.x() + j > 0); while( replaceImage->pixel(point.x()+j, point.y()) != replacementColour && BitmapImage::rgbDistance(targetImage->pixel( point.x()+j, point.y() ), targetColour) < tolerance && condition) { j = j - 1; condition = (point.x() + j > 0); } if(!condition) { floodFillError(1); return; } if( BitmapImage::rgbDistance(targetImage->pixel( point.x()+j, point.y() ), targetColour) >= tolerance ) { // bumps into the contour contourPixels.append( point+QPoint(j,0) ); } k = 1; condition = ( point.x() + k < targetImage->width()-1); while( replaceImage->pixel(point.x()+k, point.y()) != replacementColour && BitmapImage::rgbDistance(targetImage->pixel( point.x()+k, point.y() ), targetColour) < tolerance && condition) { k = k + 1; condition = ( point.x() + k < targetImage->width()-1); } if(!condition) { floodFillError(1); return; } if( BitmapImage::rgbDistance(targetImage->pixel( point.x()+k, point.y() ), targetColour) >= tolerance ) { // bumps into the contour contourPixels.append( point + QPoint(k,0) ); } if(point.x()+k > boxRight) boxRight = point.x()+k; if(point.x()+j < boxLeft) boxLeft = point.x()+j; for(int x = j+1; x < k; x++) { replaceImage->setPixel( point.x()+x, point.y(), replacementColour); if(point.y() - 1 > 0 && queue.size() < targetImage->height() * targetImage->width() ) { if( replaceImage->pixel(point.x()+x, point.y()-1) != replacementColour) { if(BitmapImage::rgbDistance(targetImage->pixel( point.x()+x, point.y() - 1), targetColour) < tolerance) { queue.append( point + QPoint(x,-1) ); if(point.y()-1< boxBottom) boxBottom = point.y()-1; } else { // bumps into the contour contourPixels.append(point+QPoint(x,-1)); } } } else { floodFillError(1); return; } if(point.y() + 1 < targetImage->height() && queue.size() < targetImage->height() * targetImage->width() ) { if( replaceImage->pixel(point.x()+x, point.y()+1) != replacementColour) { if(BitmapImage::rgbDistance(targetImage->pixel( point.x()+x, point.y() + 1), targetColour) < tolerance) { queue.append( point + QPoint(x, 1) ); if(point.y()+1> boxTop) boxTop = point.y()+1; } else { // bumps into the contour contourPixels.append(point+QPoint(x,1)); } } } else { floodFillError(1); return; } } } } // --- finds the bounding box of the filled area, and all the points contained inside (+ 1*tol) -> boxPoints QPointF mBoxTopRight = myTempView.inverted(&invertible).map( QPointF(qMax(boxLeft,boxRight)+1*tol, qMax(boxTop,boxBottom)+1*tol) ); QPointF mBoxBottomLeft = myTempView.inverted(&invertible).map( QPointF(qMin(boxLeft,boxRight)-1*tol, qMin(boxTop,boxBottom)-1*tol) ); QRectF boundingBox = QRectF( mBoxBottomLeft.x()-1, mBoxBottomLeft.y()-1, qAbs(mBoxBottomLeft.x()-mBoxTopRight.x())+2, qAbs(mBoxBottomLeft.y()-mBoxTopRight.y())+2 ); debugRect = QRectF(0,0,0,0); debugRect = boundingBox; for(int l=0; lgetVertex(points.at(l)); if( boundingBox.contains( mPoint ) ) { // ----- //vectorImage->setSelected(points.at(l), true); boxPoints.append( points.at(l) ); } } // ---- finds the points near the contourPixels -> contourPoints for(int i=0; i< contourPixels.size(); i++ ) { QPointF mPoint = myTempView.inverted(&invertible).map( QPointF( contourPixels.at(i) ) ); vertices = vectorImage->getAndRemoveVerticesCloseTo(mPoint, tol, &boxPoints); //contourPoints << vertices; for(int m=0; m we correct for that for(int i=0; i< contourPoints.size(); i++) { VertexRef theNextVertex = contourPoints[i].nextVertex(); if( ! contourPoints.contains(theNextVertex) ) { // if the next vertex is not in the list of contour points if( contourPoints.contains( theNextVertex.nextVertex() ) ) { // but the next-next vertex is... contourPoints.append( theNextVertex ); //qDebug() << "----- found SHARP point (type 1a) ------"; } QList closePoints = vectorImage->getVerticesCloseTo( theNextVertex, tol2 ); for( int j=0; j closePoints = vectorImage->getVerticesCloseTo( thePreviousVertex, tol2 ); for( int j=0; jsetSelected( contourPoints, true); update(); //replaceImage->fill(qRgba(0,0,0,0)); //QMessageBox::warning(this, tr("My Application"), tr("all the contour points"), QMessageBox::Ok, QMessageBox::Ok); //vectorImage->deselectAll(); //return; // 2 --- or continue // Step 2: finds closed paths among the selected vertices: we start from a vertex and build a tree of connected vertices //while(contourPoints.size() > 0) { QList tree; QList fatherNode; // given the index in tree (of a vertex), return the index (in tree) of its father vertex; this will define the tree structure QList leaves; // list of indices in tree which correspond to end of branches (leaves) // Step 2.1: build tree int rootIndex = -1; bool rootIndexFound = false; while(!rootIndexFound && rootIndex < contourPoints.size()-1) { rootIndex++; if( vectorImage->getVerticesCloseTo( vectorImage->getVertex(contourPoints.at(rootIndex)), tol2, &contourPoints).size() > 1) { // this point is connected! rootIndexFound = true; } } if(!rootIndexFound) { floodFillError(3); return; } tree << contourPoints.at(rootIndex); fatherNode.append(-1); //leaves << 0; contourPoints.removeAt(rootIndex); VertexRef vertex0 = tree.at(0); //qDebug() << "ROOT = " << vertex0.curveNumber << "," << vertex0.vertexNumber; j=0; bool success = false; int counter = 0; while(!success && j>-1 && counter<1000) { counter++; //qDebug() << "------"; VertexRef vertex = tree.at(j); //qDebug() << j << "/" << tree.size() << " " << vertex.curveNumber << "," << vertex.vertexNumber << "->" << fatherNode.at(j); int index1 = contourPoints.indexOf(vertex.nextVertex()); if( index1 != -1) { //qDebug() << "next vertex"; tree.append(vertex.nextVertex()); fatherNode.append(j); contourPoints.removeAt(index1); j = tree.size()-1; } else { int index2 = contourPoints.indexOf(vertex.prevVertex()); if( index2 != -1 ) { // qDebug() << "previous vertex"; tree.append(vertex.prevVertex()); fatherNode.append(j); contourPoints.removeAt(index2); j = tree.size()-1; } else { QList pointsNearby = vectorImage->getVerticesCloseTo( vectorImage->getVertex(vertex), tol2, &contourPoints); if(pointsNearby.size() > 0) { //qDebug() << "close vertex"; tree << pointsNearby.at(0); fatherNode.append(j); contourPoints.removeAt( contourPoints.indexOf(pointsNearby.at(0)) ); j = tree.size()-1; } else { qreal dist = vectorImage->getDistance(vertex, vertex0); //qDebug() << "is it a leave ? " << j << "dist = " << dist << "-" << tol2; if( ((vertex.curveNumber == vertex0.curveNumber) && (qAbs(vertex.vertexNumber-vertex0.vertexNumber)==1)) || (dist < tol2) ) { // we found a leaf close to the root of the tree - does the closed path contain the initial point? QList closedPath; int pathIndex = j; if(dist > 0) closedPath.prepend(vertex0); closedPath.prepend(tree.at(pathIndex)); while( (pathIndex = fatherNode.at(pathIndex)) != -1) { closedPath.prepend(tree.at(pathIndex)); } BezierArea newArea = BezierArea( closedPath, brush.colourNumber ); vectorImage->updateArea(newArea); if( newArea.path.contains(initialPoint) ) { vectorImage->addArea( newArea ); //qDebug() << "Yes!"; success = true; } else { //qDebug() << "No! almost"; j = fatherNode.at(j); } } else { //qDebug() << "No!"; leaves << j; j = fatherNode.at(j); } } } } // } if(!success) { floodFillError(2); return; } //qDebug() << "failure!" << contourPoints.size(); replaceImage->fill(qRgba(0,0,0,0)); deselectAll(); // -- debug --- (display tree) /*for(int indexm=0; indexm < tree.size(); indexm++) { qDebug() << indexm << ") " << tree.at(indexm).curveNumber << "," << tree.at(indexm).vertexNumber << " -> " << fatherNode.at(indexm); //if(leaves.contains(indexm)) vectorImage->setSelected( tree.at(indexm), true); vectorImage->setSelected( tree.at(indexm), true); update(); //sleep( 1 ); QMessageBox::warning(this, tr("My Application"), tr("all the tree points"), QMessageBox::Ok, QMessageBox::Ok); }*/ delete targetImage; update(); } void ScribbleArea::floodFillError(int errorType) { QString message, error; if(errorType == 1) message = "There is a gap in your drawing (or maybe you have zoomed too much)."; if(errorType == 2 || errorType == 3) message = "Sorry! This doesn't always work." "Please try again (zoom a bit, click at another location... )
" "if it doesn't work, zoom a bit and check that your paths are connected by pressing F1.)."; if(errorType == 1) error = "Out of bound."; if(errorType == 2) error = "Could not find a closed path."; if(errorType == 3) error = "Could not find the root index."; QMessageBox::warning(this, tr("Flood fill error"), message+"

Error: "+error, QMessageBox::Ok, QMessageBox::Ok); bufferImg->clear(); deselectAll(); } void ScribbleArea::switchTool() { if(toolMode == ScribbleArea::MOVE) { paintTransformedSelection(); deselectAll(); } if(toolMode == ScribbleArea::POLYLINE) escape(); } void ScribbleArea::updateCursor() { if(toolMode == PENCIL) { if(toolCursors) { QCursor cursor(QPixmap(":icons/pencil2.png"),0,16); setCursor(cursor); } else { setCursor(Qt::CrossCursor); } } if(toolMode == PEN) { if(toolCursors) { QCursor cursor(QPixmap(":icons/pen.png"),7,0); setCursor(cursor); } else { setCursor(Qt::CrossCursor); } } if(toolMode == ERASER) { QPixmap pixmap(eraser.width,eraser.width); pixmap.fill( QColor(255,255,255,0) ); QPainter painter(&pixmap); painter.setPen( QColor(0,0,0,190) ); painter.setBrush( QColor(255,255,255,100) ); painter.drawLine( QPointF(eraser.width/2-2,eraser.width/2), QPointF(eraser.width/2+2,eraser.width/2) ); painter.drawLine( QPointF(eraser.width/2,eraser.width/2-2), QPointF(eraser.width/2,eraser.width/2+2) ); painter.setRenderHints(QPainter::Antialiasing, true); painter.setPen( QColor(0,0,0,100) ); painter.drawEllipse( QRectF(1,1,eraser.width-2,eraser.width-2) ); painter.end(); setCursor(pixmap); //setCursor(Qt::CrossCursor); } if(toolMode == BUCKET) { if(toolCursors) { QPixmap pixmap(":icons/bucketTool.png"); QPainter painter(&pixmap); painter.setPen( brush.colour ); painter.drawLine( QPoint(5,16), QPoint(5,18) ); painter.end(); QCursor cursor(pixmap,4,20); setCursor(cursor); } else { setCursor(Qt::CrossCursor); } } if(toolMode == EYEDROPPER) { if(eyedropperCursor == NULL) { eyedropperCursor = new QPixmap(32,32); eyedropperCursor->fill(Qt::white); QPixmap* mask = new QPixmap(32,32); mask->fill(Qt::color0); QPainter painter(eyedropperCursor); painter.drawLine(5,0,5,10); painter.drawLine(0,5,10,5); painter.end(); painter.begin(mask); painter.setBrush(Qt::color1); painter.setPen(Qt::color1); painter.drawLine(5,0,5,10); painter.drawLine(0,5,10,5); painter.drawRect(10,10,20,20); painter.end(); eyedropperCursor->setMask(*mask); } setCursor( QCursor(*eyedropperCursor, 5, 5) ); } if(toolMode == SELECT) { Layer* layer = editor->getCurrentLayer(); if(layer->type == Layer::VECTOR) setCursor(Qt::ArrowCursor); if(layer->type == Layer::BITMAP) setCursor(Qt::CrossCursor); } if(toolMode == MOVE) { setCursor(Qt::ArrowCursor); } if(toolMode == HAND) { QPixmap pixmap(":icons/hand.png"); setCursor(pixmap); //setCursor(Qt::PointingHandCursor); } if(toolMode == POLYLINE) { setCursor(Qt::CrossCursor); } if(toolMode == COLOURING) { Layer* layer = editor->getCurrentLayer(); if(layer->type == Layer::VECTOR) { setCursor(Qt::CrossCursor); } if(layer->type == Layer::BITMAP) { //qreal width = brush.width*0.66; qreal width = brush.width + 0.5*brush.feather; QPixmap pixmap(width,width); if(!pixmap.isNull()) { pixmap.fill( QColor(255,255,255,0) ); QPainter painter(&pixmap); painter.setPen( QColor(0,0,0,190) ); painter.setBrush( Qt::NoBrush ); painter.drawLine( QPointF(width/2-2,width/2), QPointF(width/2+2,width/2) ); painter.drawLine( QPointF(width/2,width/2-2), QPointF(width/2,width/2+2) ); painter.setRenderHints(QPainter::Antialiasing, true); painter.setPen( QColor(0,0,0,100) ); painter.drawEllipse( QRectF(1+brush.feather/2,1+brush.feather/2,qMax(0.0,brush.width-brush.feather/2-2),qMax(0.0,brush.width-brush.feather/2-2)) ); painter.setPen( QColor(0,0,0,50) ); painter.drawEllipse( QRectF(1+brush.feather/8,1+brush.feather/8,qMax(0.0,width-brush.feather/4-2),qMax(0.0,width-brush.feather/4-2)) ); painter.end(); } setCursor(pixmap); } } if(toolMode == EDIT) { QCursor cursor(QPixmap(":icons/smudge.png"),3,16); setCursor(cursor); //setCursor(Qt::ArrowCursor); } } void ScribbleArea::pencilOn() { switchTool(); toolMode = ScribbleArea::PENCIL; // --- change properties --- Layer* layer = editor->getCurrentLayer(); if(layer == NULL) return; if(layer->type == Layer::VECTOR) editor->selectColour(pencil.colourNumber); if(layer->type == Layer::BITMAP) editor->setColour(pencil.colour); editor->setWidth(pencil.width); editor->setFeather(pencil.feather); editor->setFeather(-1); // by definition the pencil has no feather editor->setOpacity(pencil.opacity); editor->setPressure(pencil.pressure); editor->setInvisibility(pencil.invisibility); editor->setPreserveAlpha(pencil.preserveAlpha); editor->setFollowContour(-1); editor->setInvisibility(-1); // by definition the pencil is invisible in vector mode // --- change cursor --- updateCursor(); } void ScribbleArea::penOn() { switchTool(); toolMode = ScribbleArea::PEN; // --- change properties --- Layer* layer = editor->getCurrentLayer(); if(layer == NULL) return; if(layer->type == Layer::VECTOR) editor->selectColour(pen.colourNumber); if(layer->type == Layer::BITMAP) editor->setColour(pen.colour); if(pen.width<0) pen.width = 1.0; editor->setWidth(pen.width); if(pen.feather<0) pen.feather = 0.0; editor->setFeather(pen.feather); editor->setFeather(-1); if(pen.opacity<0) pen.opacity = 1.0; editor->setOpacity(pen.opacity); editor->setPressure(pen.pressure); editor->setInvisibility(pen.invisibility); editor->setPreserveAlpha(pen.preserveAlpha); editor->setFollowContour(-1); editor->setInvisibility(-1); // by definition the pen is visible in vector mode // --- change cursor --- updateCursor(); } void ScribbleArea::eraserOn() { switchTool(); toolMode = ScribbleArea::ERASER; // --- change properties --- editor->setWidth(eraser.width); editor->setFeather(eraser.feather); editor->setFeather(-1); editor->setOpacity(eraser.opacity); editor->setPressure(eraser.pressure); editor->setPreserveAlpha(0); editor->setPreserveAlpha(-1); editor->setFollowContour(-1); editor->setInvisibility(0); editor->setInvisibility(-1); // --- change cursor --- updateCursor(); } void ScribbleArea::selectOn() { switchTool(); toolMode = ScribbleArea::SELECT; // --- change properties --- Layer* layer = editor->getCurrentLayer(); if(layer == NULL) return; editor->setWidth(-1); editor->setFeather(-1); editor->setOpacity(-1); editor->setPressure(-1); editor->setInvisibility(-1); editor->setPreserveAlpha(-1); editor->setFollowContour(-1); // --- change cursor --- updateCursor(); } void ScribbleArea::moveOn() { toolMode = ScribbleArea::MOVE; // --- change properties --- editor->setWidth(-1); editor->setFeather(-1); editor->setOpacity(-1); editor->setPressure(-1); editor->setInvisibility(-1); editor->setPreserveAlpha(-1); editor->setFollowContour(-1); // --- change cursor --- updateCursor(); } void ScribbleArea::handOn() { if(toolMode == ScribbleArea::HAND) resetView(); toolMode = ScribbleArea::HAND; // --- change properties --- editor->setWidth(-1); editor->setFeather(-1); editor->setOpacity(-1); editor->setPressure(-1); editor->setInvisibility(-1); editor->setPreserveAlpha(-1); editor->setFollowContour(-1); // --- change cursor --- updateCursor(); } void ScribbleArea::polylineOn() { switchTool(); toolMode = ScribbleArea::POLYLINE; // --- change properties --- Layer* layer = editor->getCurrentLayer(); if(layer == NULL) return; if(layer->type == Layer::VECTOR) editor->selectColour(pen.colourNumber); if(layer->type == Layer::BITMAP) editor->setColour(pen.colour); editor->setWidth(pen.width); editor->setFeather(pen.feather); editor->setFeather(-1); editor->setOpacity(pen.opacity); editor->setPressure(pen.pressure); editor->setInvisibility(pen.invisibility); editor->setPreserveAlpha(pen.preserveAlpha); editor->setFollowContour(-1); // --- change cursor --- updateCursor(); } void ScribbleArea::bucketOn() { switchTool(); toolMode = ScribbleArea::BUCKET; // --- change properties --- Layer* layer = editor->getCurrentLayer(); if(layer == NULL) return; if(layer->type == Layer::VECTOR) editor->selectColour(brush.colourNumber); if(layer->type == Layer::BITMAP) editor->setColour(brush.colour); editor->setWidth(-1); editor->setFeather(brush.feather); editor->setFeather(-1); editor->setOpacity(1); // the bucket has full opacity (but one should be able to use it with translucent colours) editor->setOpacity(-1); // disable the button editor->setPressure(0); editor->setPressure(-1); // disable the button editor->setInvisibility(0); editor->setInvisibility(-1); // disable the button editor->setPreserveAlpha(0); editor->setPreserveAlpha(-1); // disable the button editor->setFollowContour(-1); // --- change cursor --- updateCursor(); } void ScribbleArea::eyedropperOn() { switchTool(); toolMode = ScribbleArea::EYEDROPPER; // --- change properties --- editor->setWidth(-1); editor->setFeather(-1); editor->setOpacity(-1); editor->setPressure(-1); editor->setInvisibility(0); editor->setInvisibility(-1); editor->setPreserveAlpha(0); editor->setPreserveAlpha(-1); editor->setFollowContour(-1); // --- change cursor --- updateCursor(); } void ScribbleArea::colouringOn() { switchTool(); toolMode = ScribbleArea::COLOURING; // --- change properties --- Layer* layer = editor->getCurrentLayer(); if(layer == NULL) return; if(layer->type == Layer::VECTOR) editor->selectColour(brush.colourNumber); if(layer->type == Layer::BITMAP) editor->setColour(brush.colour); editor->setWidth(brush.width); editor->setFeather(brush.feather); editor->setOpacity(brush.opacity); editor->setPressure(brush.pressure); editor->setPreserveAlpha(brush.preserveAlpha); editor->setFollowContour(followContour); editor->setInvisibility(0); editor->setInvisibility(-1); // --- change cursor --- updateCursor(); } void ScribbleArea::smudgeOn() { switchTool(); toolMode = EDIT; // --- change properties --- editor->setWidth(-1); editor->setFeather(-1); editor->setOpacity(-1); editor->setPressure(-1); editor->setInvisibility(0); editor->setInvisibility(-1); editor->setPreserveAlpha(0); editor->setPreserveAlpha(-1); editor->setFollowContour(-1); // --- change cursor --- updateCursor(); } void ScribbleArea::deleteSelection() { if( somethingSelected ) { // there is something selected editor->backup(); Layer* layer = editor->getCurrentLayer(); if(layer == NULL) return; closestCurves.clear(); if(layer->type == Layer::VECTOR) ((LayerVector*)layer)->getLastVectorImageAtFrame(editor->currentFrame, 0)->deleteSelection(); if(layer->type == Layer::BITMAP) ((LayerBitmap*)layer)->getLastBitmapImageAtFrame(editor->currentFrame, 0)->clear(mySelection); updateAllFrames(); } } void ScribbleArea::clearImage() { editor->backup(); Layer* layer = editor->getCurrentLayer(); if(layer == NULL) return; if(layer->type == Layer::VECTOR) ((LayerVector*)layer)->getLastVectorImageAtFrame(editor->currentFrame, 0)->clear(); if(layer->type == Layer::BITMAP) ((LayerBitmap*)layer)->getLastBitmapImageAtFrame(editor->currentFrame, 0)->clear(); //emit modification(); //update(); setModified(editor->currentLayer, editor->currentFrame); } void ScribbleArea::toggleThinLines() { showThinLines = !showThinLines; emit thinLinesChanged(showThinLines); setView(myView); updateAllFrames(); } void ScribbleArea::toggleOutlines() { simplified = !simplified; emit outlinesChanged(simplified); setView(myView); updateAllFrames(); } void ScribbleArea::toggleMirror() { myView = myView * QMatrix(-1, 0, 0, 1, 0, 0); myTempView = myView * centralView; setView(myView); updateAllFrames(); } void ScribbleArea::toggleShowAllLayers() { showAllLayers++; if(showAllLayers==3) showAllLayers = 0; //emit showAllLayersChanged(showAllLayers); setView(myView); updateAllFrames(); } pencil-0.4.4b/src/interface/editor.h0000644000175000017500000001545110745152004020035 0ustar khashayarkhashayar/* Pencil - Traditional Animation Software Copyright (C) 2005-2007 Patrick Corrieri & Pascal Naidon This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #ifndef EDITOR_H #define EDITOR_H #include #include #include #include #include "timeline.h" #include "scribblearea.h" #include "toolset.h" #include "preferences.h" #include "palette.h" #include "object.h" #include "vectorimage.h" #include "bitmapimage.h" class Editor; class BackupElement : public QObject { Q_OBJECT public: enum types { UNDEFINED, BITMAP_MODIF, VECTOR_MODIF }; //int type; //BackupElement() { type = UNDEFINED; } virtual int type() { return UNDEFINED; } virtual void restore(Editor*) { qDebug() << "Wrong"; }; }; class BackupBitmapElement : public BackupElement { Q_OBJECT public: int layer, frame; BitmapImage bitmapImage; //BackupBitmapElement() { type = BackupElement::BITMAP_MODIF; } int type() { return BackupElement::BITMAP_MODIF; } void restore(Editor*); }; class BackupVectorElement : public BackupElement { Q_OBJECT public: int layer, frame; VectorImage vectorImage; //BackupVectorElement() { type = BackupElement::VECTOR_MODIF; } int type() { return BackupElement::VECTOR_MODIF; } void restore(Editor*); }; class Editor : public QWidget { Q_OBJECT public: Editor(QMainWindow* parent); virtual ~Editor(); //Object* getObject() { return object; } //bool somethingSelected(); Object* object; // the object to be edited by the editor //int currentPenColour, currentFillColour; int currentLayer; // the current layer to be edited/displayed by the editor int currentFrame; // the current frame to be edited/displayed by the editor int maxFrame; // the number of the last frame for the current object QList frameList; // the frames that are to be cached -- should we use a QMap, or a QHash? int fps; // the number of frames per second used by the editor QTimer* timer; // the timer used for animation in the editor bool playing; bool looping; bool sound; Palette* getPalette() { return palette; } TimeLine* getTimeLine() { return timeLine; } ToolSet* getToolSet() { return toolSet; } Layer* getCurrentLayer(int incr) { if(object != NULL) { return object->getLayer(currentLayer+incr); } else { return NULL; } } Layer* getCurrentLayer() { return getCurrentLayer(0); } bool isModified() { return modified; } int allLayers() { return scribbleArea->allLayers(); } static QMatrix map(QRectF, QRectF); protected: void dragEnterEvent(QDragEnterEvent *event); void dropEvent(QDropEvent *event); signals: void selectAll(); public slots: void showCounter(int); bool maybeSave(); void importImage(); void importImage(QString filePath); void importSound(); void importSound(QString filePath); void importPalette(); void exportPalette(); void updateFrame(int frameNumber); void updateFrameAndVector(int frameNumber); void scrubTo(int frameNumber); void scrubForward(); void scrubBackward(); void play(); void startOrStop(); void playNextFrame(); void changeFps(int); int getFps(); void setLoop(); void setSound(); //void scrubKF(); //void scrubKB(); void previousLayer(); void nextLayer(); void addKey(); void addKey(int layerNumber, int &frameNumber); void removeKey(); void addFrame(int frameNumber); void addFrame(int frameNumber1, int frameNumber2); void removeFrame(int frameNumber); int getLastIndexAtFrame(int frameNumber); int getLastFrameAtFrame(int frameNumber); //void altPress(); //void altRelease(); void showPreferences(); void newObject(); void setObject(Object *object); void updateObject(); void setCurrentLayer(int layerNumber); void switchVisibilityOfLayer(int layerNumber); void moveLayer(int i, int j); void updateMaxFrame(); void setWidth(qreal); void applyWidth(qreal); void setFeather(qreal); void applyFeather(qreal); void setOpacity(qreal); void applyOpacity(qreal); void setInvisibility(int); void applyInvisibility(int); void setPressure(int); void applyPressure(int); void setPreserveAlpha(int); void applyPreserveAlpha(int); void setFollowContour(int); void applyFollowContour(int); void selectColour(int); void selectAndApplyColour(int); void setColour(QColor); void changeColour(int); void changeColourName(int); void changeColour(int,QColor); void updateColour(int, QColor); void addColour(); void removeColour(int); void changeAutosave(int); void changeAutosaveNumber(int); void modification(); void modification(int); void backup(); void backup(int layerNumber, int frameNumber); void undo(); void redo(); void copy(); void paste(); void clipboardChanged(); void newBitmapLayer(); void newVectorLayer(); void newSoundLayer(); void newCameraLayer(); void deleteCurrentLayer(); void toggleMirror(); void toggleShowAllLayers(); void resetMirror(); void openRecent(); void dockAllPalettes(); void detachAllPalettes(); void restorePalettesSettings(bool, bool, bool); private slots: void newDocument(); void openDocument(); bool saveDocument(); void saveForce(); bool exportX(); bool exportSeq(); bool exportMov(); bool exportFlash(); void showPalette(); void about(); void helpBox(); void saveLength(QString); private: bool openObject(QString); bool saveObject(QString); ScribbleArea *scribbleArea; TimeLine *timeLine; ToolSet *toolSet; Palette *palette; Preferences *preferences; QMainWindow *mainWindow; QString savedName; bool altpress; bool modified; int numberOfModifications; bool autosave; int autosaveNumber; // backup int backupIndex; QList backupList; void clearBackup(); int lastModifiedFrame, lastModifiedLayer; // clipboard bool clipboardBitmapOk, clipboardVectorOk; BitmapImage clipboardBitmapImage; VectorImage clipboardVectorImage; // dialogs void createExportFramesSizeBox(); void createExportMovieSizeBox(); void createExportFramesDialog(); void createExportMovieDialog(); void createExportFlashDialog(); void createNewDocumentDialog(); QDialog *newDocumentDialog; QDialog *exportFramesDialog; QDialog *exportMovieDialog; QDialog *exportFlashDialog; QSpinBox *exportFramesDialog_hBox; QSpinBox *exportFramesDialog_vBox; QSpinBox *exportMovieDialog_hBox; QSpinBox *exportMovieDialog_vBox; QComboBox *exportFramesDialog_format; QComboBox *exportMovieDialog_format; QSlider* exportFlashDialog_compression; // saving (XML) QDomElement createDomElement(QDomDocument &doc); bool loadDomElement(QDomElement element, QString filePath); }; #endif pencil-0.4.4b/src/interface/mainwindow.cpp0000644000175000017500000003723710744607202021270 0ustar khashayarkhashayar/* Pencil - Traditional Animation Software Copyright (C) 2005-2007 Patrick Corrieri & Pascal Naidon This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #include #include "editor.h" #include "mainwindow.h" #include "object.h" #include MainWindow::MainWindow() { editor = new Editor(this); //Object* object = new Object(); //object->defaultInitialisation(); //editor->setObject( object ); editor->newObject(); arrangePalettes(); //editor->getTimeLine()->close(); createMenus(); loadPlugins(); readSettings(); } void MainWindow::arrangePalettes() { setCentralWidget(editor); addDockWidget(Qt::RightDockWidgetArea, editor->getPalette()); //editor->getPalette()->close(); addDockWidget(Qt::LeftDockWidgetArea, editor->getToolSet()->drawPalette); addDockWidget(Qt::LeftDockWidgetArea, editor->getToolSet()->optionPalette); addDockWidget(Qt::LeftDockWidgetArea, editor->getToolSet()->displayPalette); //addDockWidget(Qt::LeftDockWidgetArea, editor->getToolSet()->onionPalette); //addDockWidget(Qt::LeftDockWidgetArea, editor->getToolSet()->keyPalette); //addDockWidget(Qt::BottomDockWidgetArea, editor->getToolSet()->timePalette); addDockWidget(Qt::BottomDockWidgetArea, editor->getTimeLine()); editor->getToolSet()->drawPalette->setFeatures(QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable); editor->getToolSet()->optionPalette->setFeatures(QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable); //editor->getToolSet()->keyPalette->setFeatures(QDockWidget::NoDockWidgetFeatures); //editor->getToolSet()->onionPalette->setFeatures(QDockWidget::NoDockWidgetFeatures); editor->getToolSet()->displayPalette->setFeatures(QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable); editor->getToolSet()->keyPalette->setFeatures(QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable); editor->getToolSet()->onionPalette->setFeatures(QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable); editor->getToolSet()->timePalette->setFeatures(QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable); editor->getTimeLine()->setFeatures(QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable); } void MainWindow::createMenus() { // ---------- Actions ------------- exitAct = new QAction(tr("E&xit"), this); exitAct->setShortcut(tr("Ctrl+Q")); connect(exitAct, SIGNAL(triggered()), editor, SLOT(close())); newAct = new QAction(tr("&New"), this); newAct->setShortcut(tr("Ctrl+N")); connect(newAct, SIGNAL(triggered()), editor, SLOT(newDocument())); openAct = new QAction(tr("&Open..."), this); openAct->setShortcut(tr("Ctrl+O")); connect(openAct, SIGNAL(triggered()), editor, SLOT(openDocument())); saveAct = new QAction(tr("Save &As..."), this); saveAct->setShortcut(tr("Ctrl+Shift+S")); connect(saveAct, SIGNAL(triggered()), editor, SLOT(saveDocument())); savAct = new QAction(tr("&Save"), this); savAct->setShortcut(tr("Ctrl+S")); connect(savAct, SIGNAL(triggered()), editor, SLOT(saveForce())); exportXAct = new QAction(tr("&X-Sheet..."), this); exportXAct->setShortcut(tr("Ctrl+Alt+X")); connect(exportXAct, SIGNAL(triggered()), editor, SLOT(exportX())); exportAct = new QAction(tr("&Image Sequence..."), this); exportAct->setShortcut(tr("Ctrl+Alt+S")); connect(exportAct, SIGNAL(triggered()), editor, SLOT(exportSeq())); exportMovAct = new QAction(tr("&Movie..."), this); exportMovAct->setShortcut(tr("Ctrl+Alt+M")); connect(exportMovAct, SIGNAL(triggered()), editor, SLOT(exportMov())); exportFlashAct = new QAction(tr("&Flash/SWF..."), this); exportFlashAct->setShortcut(tr("Ctrl+Alt+F")); connect(exportFlashAct, SIGNAL(triggered()), editor, SLOT(exportFlash())); exportFlashAct = new QAction(tr("&Flash/SWF..."), this); exportFlashAct->setShortcut(tr("Ctrl+Alt+F")); connect(exportFlashAct, SIGNAL(triggered()), editor, SLOT(exportFlash())); exportPaletteAct = new QAction(tr("Palette..."), this); connect(exportPaletteAct, SIGNAL(triggered()), editor, SLOT(exportPalette())); importPaletteAct = new QAction(tr("Palette..."), this); connect(importPaletteAct, SIGNAL(triggered()), editor, SLOT(importPalette())); importAct = new QAction(tr("&Import image..."), this); importAct->setShortcut(tr("Ctrl+I")); connect(importAct, SIGNAL(triggered()), editor, SLOT(importImage())); importSndAct = new QAction(tr("&Import sound..."), this); // importAct->setShortcut(tr("Ctrl+I")); connect(importSndAct, SIGNAL(triggered()), editor, SLOT(importSound())); aboutAct = new QAction(tr("&About"), this); connect(aboutAct, SIGNAL(triggered()), editor, SLOT(about())); helpMe = new QAction(tr("&Help"), this); helpMe->setShortcut(tr("Ctrl+?")); connect(helpMe, SIGNAL(triggered()), editor, SLOT(helpBox())); aboutQtAct = new QAction(tr("About &Qt"), this); connect(aboutQtAct, SIGNAL(triggered()), qApp, SLOT(aboutQt())); undoAct = new QAction(tr("Undo"), this); undoAct->setShortcut(tr("Ctrl+Z")); connect(undoAct, SIGNAL(triggered()), editor, SLOT(undo())); redoAct = new QAction(tr("Redo"), this); redoAct->setShortcut(tr("Ctrl+Shift+Z")); connect(redoAct, SIGNAL(triggered()), editor, SLOT(redo())); copyAct = new QAction(tr("Copy"), this); copyAct->setShortcut(tr("Ctrl+C")); connect(copyAct, SIGNAL(triggered()), editor, SLOT(copy())); pasteAct = new QAction(tr("Paste"), this); pasteAct->setShortcut(tr("Ctrl+V")); connect(pasteAct, SIGNAL(triggered()), editor, SLOT(paste())); selectAllAct = new QAction(tr("Select All"), this); selectAllAct->setShortcut(tr("Ctrl+A")); connect(selectAllAct, SIGNAL(triggered()), editor, SIGNAL(selectAll())); preferencesAct = new QAction(tr("Preferences"), this); connect(preferencesAct, SIGNAL(triggered()), editor, SLOT(showPreferences())); newBitmapLayerAct = new QAction(tr("New Bitmap Layer"), this); connect(newBitmapLayerAct, SIGNAL(triggered()), editor, SLOT(newBitmapLayer())); newVectorLayerAct = new QAction(tr("New Vector Layer"), this); connect(newVectorLayerAct, SIGNAL(triggered()), editor, SLOT(newVectorLayer())); newSoundLayerAct = new QAction(tr("New Sound Layer"), this); connect(newSoundLayerAct, SIGNAL(triggered()), editor, SLOT(newSoundLayer())); newCameraLayerAct = new QAction(tr("New Camera Layer"), this); connect(newCameraLayerAct, SIGNAL(triggered()), editor, SLOT(newCameraLayer())); deleteLayerAct = new QAction(tr("Delete Current Layer"), this); connect(deleteLayerAct, SIGNAL(triggered()), editor, SLOT(deleteCurrentLayer())); dockAllPalettesAct = new QAction(tr("Dock All Palettes"), this); connect(dockAllPalettesAct, SIGNAL(triggered()), editor, SLOT(dockAllPalettes())); detachAllPalettesAct = new QAction(tr("Detach All Palettes"), this); connect(detachAllPalettesAct, SIGNAL(triggered()), editor, SLOT(detachAllPalettes())); // --------------- Menus ------------------ importMenu = new QMenu(tr("Import"), this); importMenu->addAction(importPaletteAct); exportMenu = new QMenu(tr("Export"), this); exportMenu->addAction(exportXAct); exportMenu->addAction(exportAct); exportMenu->addAction(exportMovAct); exportMenu->addAction(exportFlashAct); exportMenu->addSeparator(); exportMenu->addAction(exportPaletteAct); openRecentMenu = new QMenu(tr("Open recent..."), this); fileMenu = new QMenu(tr("&File"), this); fileMenu->addAction(newAct); fileMenu->addAction(openAct); fileMenu->addMenu(openRecentMenu); fileMenu->addAction(savAct); fileMenu->addAction(saveAct); fileMenu->addSeparator(); fileMenu->addMenu(importMenu); fileMenu->addMenu(exportMenu); editMenu = new QMenu(tr("&Edit"), this); editMenu->addAction(undoAct); editMenu->addAction(redoAct); editMenu->addSeparator(); editMenu->addAction(copyAct); editMenu->addAction(pasteAct); editMenu->addSeparator(); editMenu->addAction(selectAllAct); editMenu->addSeparator(); editMenu->addAction(importAct); editMenu->addAction(importSndAct); editMenu->addSeparator(); editMenu->addAction(preferencesAct); layerMenu = new QMenu(tr("&Layer"), this); layerMenu->addAction(newBitmapLayerAct); layerMenu->addAction(newVectorLayerAct); layerMenu->addAction(newSoundLayerAct); layerMenu->addAction(newCameraLayerAct); layerMenu->addSeparator(); layerMenu->addAction(deleteLayerAct); helpMenu = new QMenu(tr("&Help"), this); helpMenu->addAction(helpMe); helpMenu->addAction(aboutAct); helpMenu->addAction(aboutQtAct); windowsMenu = new QMenu(tr("Windows"), this); windowsMenu->addAction(dockAllPalettesAct); windowsMenu->addAction(detachAllPalettesAct); menuBar()->addMenu(fileMenu); menuBar()->addMenu(editMenu); menuBar()->addMenu(layerMenu); menuBar()->addMenu(helpMenu); menuBar()->addMenu(windowsMenu); } void MainWindow::loadPlugins() { qDebug() << "MainWindow loadplugins" << this << this->thread(); // foreach (QObject *plugin, QPluginLoader::staticInstances()) populateMenus(plugin); // static plugins QDir pluginsDir = QDir(qApp->applicationDirPath()); #if defined(Q_OS_WIN) if (pluginsDir.dirName().toLower() == "debug" || pluginsDir.dirName().toLower() == "release") pluginsDir.cdUp(); #elif defined(Q_OS_MAC) if (pluginsDir.dirName() == "MacOS") { pluginsDir.cdUp(); } #endif pluginsDir.cd("plugins"); qDebug() << "Plugin dir = " << pluginsDir.dirName(); /*foreach (QString fileName, pluginsDir.entryList(QDir::Files)) { QPluginLoader loader(pluginsDir.absoluteFilePath(fileName)); QObject *plugin = loader.instance(); qDebug() << "loader " << loader.thread(); qDebug() << "plugin " << fileName << plugin << plugin->thread(); if (plugin) { plugin->moveToThread(this->thread()); populateMenus(plugin); //pluginFileNames += fileName; } }*/ //brushMenu->setEnabled(!brushActionGroup->actions().isEmpty()); //shapesMenu->setEnabled(!shapesMenu->actions().isEmpty()); //filterMenu->setEnabled(!filterMenu->actions().isEmpty()); } void MainWindow::populateMenus(QObject *plugin) { qDebug() << "MainWindow populateMenus" << this << this->thread(); qDebug() << "MainWindow populateMenus" << plugin << plugin->thread(); /*BrushInterface *iBrush = qobject_cast(plugin); if (iBrush) addToMenu(plugin, iBrush->brushes(), brushMenu, SLOT(changeBrush()), brushActionGroup); ShapeInterface *iShape = qobject_cast(plugin); if (iShape) addToMenu(plugin, iShape->shapes(), shapesMenu, SLOT(insertShape())); FilterInterface *iFilter = qobject_cast(plugin); if (iFilter) addToMenu(plugin, iFilter->filters(), filterMenu, SLOT(applyFilter()));*/ ExportInterface *exportPlugin = qobject_cast(plugin); if (exportPlugin) addToMenu(plugin, exportPlugin->name(), exportMenu, SLOT(exportFile())); } void MainWindow::addToMenu(QObject *plugin, const QString text, QMenu *menu, const char *member, QActionGroup *actionGroup) { qDebug() << "MainWindow populateMenus" << this << this->thread(); qDebug() << "MainWindow populateMenus" << plugin << plugin->thread(); qDebug() << "addToMenu 1"; QAction *action = new QAction(text, plugin); qDebug() << "addToMenu 2"; connect(action, SIGNAL(triggered()), this, member); menu->addAction(action); if (actionGroup) { action->setCheckable(true); actionGroup->addAction(action); } } void MainWindow::exportFile() { QAction *action = qobject_cast(sender()); ExportInterface *exportPlugin = qobject_cast(action->parent()); if(exportPlugin) { //exportPlugin->exportFile(); } else { qDebug() << "exportPlugin is null"; } //const QImage image = iFilter->filterImage(action->text(), paintArea->image(), this); //paintArea->setImage(image); } void MainWindow::setOpacity(int opacity) { QSettings settings("Pencil","Pencil"); settings.setValue("windowOpacity", 100-opacity); setWindowOpacity(opacity/100.0); } void MainWindow::closeEvent(QCloseEvent *event) { if (editor->maybeSave()) { writeSettings(); event->accept(); } else { event->ignore(); } } void MainWindow::keyPressEvent( QKeyEvent *e ) { switch (e->key()) { case Qt::Key_H: editor->switchVisibilityOfLayer(editor->currentLayer); break; case Qt::Key_D: editor->scrubForward(); break; case Qt::Key_Right: //editor->scrubForward(); break; case Qt::Key_S: editor->scrubBackward(); break; case Qt::Key_Left: //editor->scrubBackward(); break; case Qt::Key_Up: //editor->previousLayer(); break; case Qt::Key_Down: //editor->nextLayer(); break; case Qt::Key_Space: editor->play(); break; case Qt::Key_Alt: //editor->altPress(); break; case Qt::Key_Return: editor->addKey(); break; default: QWidget::keyPressEvent(e); } } void MainWindow::keyReleaseEvent( QKeyEvent *e ) { switch (e->key()) { case Qt::Key_Alt: //editor->altRelease(); break; default: QWidget::keyPressEvent(e); } } void MainWindow::readSettings() { QSettings settings("Pencil", "Pencil"); QRect desktopRect = QApplication::desktop()->screenGeometry(); desktopRect.adjust(80,80,-80,-80); //QPoint pos = settings.value("editorPosition", QPoint( qMax(0, (desktopRect.width()-800)/2), qMax(0, (desktopRect.height()-600)/2) )).toPoint(); QPoint pos = settings.value("editorPosition", desktopRect.topLeft() ).toPoint(); //QSize size = settings.value("editorSize", QSize(800, 600)).toSize(); QSize size = settings.value("editorSize", desktopRect.size() ).toSize(); move(pos); resize(size); editor->restorePalettesSettings(true, true, true); QString myPath = settings.value("lastFilePath", QVariant(QDir::homePath())).toString(); addRecentFile(myPath); setOpacity(100-settings.value("windowOpacity").toInt()); //initialiseStyle(); } void MainWindow::writeSettings() { QSettings settings("Pencil", "Pencil"); settings.setValue("editorPosition", pos()); settings.setValue("editorSize", size()); Palette* colourPalette = editor->getPalette(); if(colourPalette != NULL) { settings.setValue("colourPalettePosition", colourPalette->pos()); settings.setValue("colourPaletteSize", colourPalette->size()); settings.setValue("colourPaletteFloating", colourPalette->isFloating()); } TimeLine* timelinePalette = editor->getTimeLine(); if(timelinePalette != NULL) { settings.setValue("timelinePalettePosition", timelinePalette->pos()); settings.setValue("timelinePaletteSize", timelinePalette->size()); settings.setValue("timelinePaletteFloating", timelinePalette->isFloating()); } QDockWidget* drawPalette = editor->getToolSet()->drawPalette; if(drawPalette != NULL) { settings.setValue("drawPalettePosition", drawPalette->pos()); settings.setValue("drawPaletteSize", drawPalette->size()); settings.setValue("drawPaletteFloating", drawPalette->isFloating()); } QDockWidget* optionPalette = editor->getToolSet()->optionPalette; if(optionPalette != NULL) { settings.setValue("optionPalettePosition", optionPalette->pos()); settings.setValue("optionPaletteSize", optionPalette->size()); settings.setValue("optionPaletteFloating", optionPalette->isFloating()); } QDockWidget* displayPalette = editor->getToolSet()->displayPalette; if(optionPalette != NULL) { settings.setValue("displayPalettePosition", displayPalette->pos()); settings.setValue("displayPaletteSize", displayPalette->size()); settings.setValue("displayPaletteFloating", displayPalette->isFloating()); } } void MainWindow::addRecentFile(QString filePath) { QAction* openThisFileAct = new QAction(filePath, this); connect(openThisFileAct, SIGNAL(triggered()), editor, SLOT(openRecent())); openRecentMenu->addAction(openThisFileAct); } pencil-0.4.4b/src/interface/toolset.cpp0000644000175000017500000005402110745152004020567 0ustar khashayarkhashayar/* Pencil - Traditional Animation Software Copyright (C) 2005-2007 Patrick Corrieri & Pascal Naidon This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #include #include "toolset.h" #include SpinSlider::SpinSlider(QString text, QString type, QString dataType, qreal min, qreal max, QWidget* parent) : QWidget(parent) { value = 1.0; this->type = type; this->dataType = dataType; this->min = min; this->max = max; QLabel* label = new QLabel(text+": "); label->setFont( QFont("Helvetica", 10) ); valueLabel = new QLabel("--"); valueLabel->setFont( QFont("Helvetica", 10) ); //valueLabel->setFixedWidth(30); valueLabel->setAlignment(Qt::AlignRight|Qt::AlignVCenter); slider = new QSlider(Qt::Horizontal, this); slider->setMinimum(0); slider->setMaximum(100); //slider->setFixedHeight(16); QGridLayout *lay = new QGridLayout(); lay->setMargin(2); lay->setSpacing(2); //lay->setColumnStretch(0,1); lay->addWidget(label,0,0,1,1); lay->addWidget(valueLabel,0,1,1,1); lay->addWidget(slider,1,0,1,2); setLayout(lay); setSizePolicy(QSizePolicy::Preferred,QSizePolicy::Fixed); connect(slider, SIGNAL(valueChanged(int)), this, SLOT(changeValue(int))); connect(slider, SIGNAL(sliderReleased()), this, SLOT(sliderReleased())); connect(slider, SIGNAL(sliderMoved(int)), this, SLOT(sliderMoved(int))); } void SpinSlider::changeValue(qreal value) { this->value = value; if(dataType == "integer") { valueLabel->setText( QString::number(qRound(value)) ); } else { valueLabel->setText( QLocale::system().toString(value,'f',1) ); } } void SpinSlider::changeValue(int value) { qreal value2 = 0.0; if(type=="linear") value2 = min + value*(max-min)/100; if(type=="log") value2 = min*exp( value*log(max/min)/100 ); changeValue(value2); } void SpinSlider::setValue(qreal value) { qreal value2 = 0.0; if(type=="linear") value2 = qRound( 100*(value-min)/(max-min) ); if(type=="log") value2 = qRound( 100.0*log(value/0.2)/log(1000.0) ); slider->setSliderPosition(value2); changeValue(value); } void SpinSlider::sliderReleased() { //qDebug() << "sliderReleased"; emit valueChanged(this->value); } void SpinSlider::sliderMoved(int value) { changeValue(value); emit valueChanged(this->value); } // ---------------------------------------------------------------------------------- ToolSet::ToolSet() { drawPalette = new QDockWidget(tr("Tools")); optionPalette = new QDockWidget(tr("Options")); displayPalette = new QDockWidget(tr("Display")); keyPalette = new QDockWidget(tr("Keys")); onionPalette = new QDockWidget(tr("Onion skin")); timePalette = new QDockWidget(tr("Controls")); #ifdef Q_WS_MAC //drawPalette->setTitleBarWidget(new TitleBar(drawPalette)); #endif //drawPalette->setAutoFillBackground(false); //drawPalette->setAttribute(Qt::WA_NoSystemBackground, true); /*QPalette optionPalettePalette(optionPalette->palette()); optionPalettePalette.setColor(QPalette::Light, Qt::red); optionPalettePalette.setColor(QPalette::Midlight, Qt::red); optionPalettePalette.setColor(QPalette::Dark, Qt::red); optionPalettePalette.setColor(QPalette::Shadow, Qt::red); optionPalette->setPalette(optionPalettePalette);*/ //optionPalette->setWindowFlags(Qt::Tool); //optionPalette->setWindowIconText(tr("Coucou")); //optionPalette->setFont( QFont("Helvetica", 14, QFont::Bold) ); //QGroupBox *drawGroup = new QGroupBox(tr("Draw")); QFrame *drawGroup = new QFrame(); QFrame *optionGroup = new QFrame(); QFrame *displayGroup = new QFrame(); QFrame *keyGroup = new QFrame(); QFrame *onionGroup = new QFrame(); QFrame * timeGroup = new QFrame(); //QFrame *line = new QFrame(); //line->setFrameStyle(QFrame::HLine | QFrame::Raised); //drawGroup->setMaximumHeight( 100 ); //optionGroup->setFrameStyle(QFrame::Panel | QFrame::Raised); //keyGroup->setFrameStyle(QFrame::Panel | QFrame::Raised); //onionGroup->setFrameStyle(QFrame::Panel | QFrame::Raised); //timeGroup->setFrameStyle(QFrame::Panel | QFrame::Raised); //optionGroup->setLineWidth(2); //keyGroup->setLineWidth(2); //displayGroup->setLineWidth(2); //onionGroup->setLineWidth(2); //timeGroup->setLineWidth(2); drawPalette->setWidget(drawGroup); optionPalette->setWidget(optionGroup); displayPalette->setWidget(displayGroup); keyPalette->setWidget(keyGroup); onionPalette->setWidget(onionGroup); timePalette->setWidget(timeGroup); QVBoxLayout *framelay = new QVBoxLayout(); QGridLayout *drawLay = new QGridLayout(); QGridLayout *optionLay = new QGridLayout(); QGridLayout *displayLay = new QGridLayout(); QGridLayout *keyLay = new QGridLayout(); QGridLayout *onionLay = new QGridLayout(); QGridLayout *timeLay = new QGridLayout(); QVBoxLayout *butlay = new QVBoxLayout(); QSettings settings("Pencil","Pencil"); newToolButton(pencilButton); // = new QToolButton(this); newToolButton(selectButton); // = new QToolButton(this); newToolButton(moveButton); // = new QToolButton(this); newToolButton(handButton); // = new QToolButton(this); newToolButton(penButton); // = new QToolButton(this); newToolButton(eraserButton); // = new QToolButton(this); newToolButton(polylineButton); // = new QToolButton(this); newToolButton(bucketButton); // = new QToolButton(this); newToolButton(colouringButton); // = new QToolButton(this); newToolButton(eyedropperButton); // = new QToolButton(this); newToolButton(clearButton); // = new QToolButton(this); newToolButton(magnifyButton); newToolButton(smudgeButton); add = new QToolButton(this); rm = new QToolButton(this); thinLinesButton = new QToolButton(this); outlinesButton = new QToolButton(this); mirrorButton = new QToolButton(this); // = new QToolButton(this); choseColour = new QToolButton(this); play = new QPushButton(tr("Play"),this); play->setFixedWidth(80); pencilButton->setWhatsThis("Draw"); penButton->setWhatsThis("Pen"); polylineButton->setWhatsThis("Polyline"); bucketButton->setWhatsThis("Paint bucket"); colouringButton->setWhatsThis("Brush"); usePressureBox = new QCheckBox("Size with pressure"); usePressureBox->setFont( QFont("Helvetica", 10) ); usePressureBox->setChecked(true); makeInvisibleBox = new QCheckBox("Invisible"); makeInvisibleBox->setFont( QFont("Helvetica", 10) ); makeInvisibleBox->setChecked(false); preserveAlphaBox = new QCheckBox("Preserve Alpha"); preserveAlphaBox->setFont( QFont("Helvetica", 10) ); preserveAlphaBox->setChecked(false); followContourBox = new QCheckBox("Stop at contours"); followContourBox->setFont( QFont("Helvetica", 10) ); followContourBox->setChecked(false); onionPrevBox = new QCheckBox("Previous"); onionNextBox = new QCheckBox("Next"); onionPrevBox->setFont( QFont("Helvetica", 10) ); onionNextBox->setFont( QFont("Helvetica", 10) ); onionPrevBox->setChecked(true); /*sizeSlider = new QDoubleSpinBox(this); sizeSlider->setFocusPolicy(Qt::NoFocus); sizeSlider->setFont( QFont("Helvetica", 10) ); sizeSlider->setDecimals(1); sizeSlider->setMinimum(0); sizeSlider->setMaximum(200); sizeSlider->setValue(settings.value("width").toInt()); sizeSlider->setFixedWidth(50); sizeSlider->setFixedHeight(22);*/ sizeSlider = new SpinSlider("Size", "log", "real", 0.2, 200.0, this); sizeSlider->setValue(settings.value("pencilWidth").toDouble()); featherSlider = new SpinSlider("Feather", "log", "real", 0.2, 200.0, this); featherSlider->setValue(settings.value("pencilFeather").toDouble()); opacitySlider = new SpinSlider("Opacity", "linear", "real", 0.0, 1.0, this); opacitySlider->setValue(settings.value("pencilOpacity").toDouble()); /*featherSlider = new QSlider(Qt::Horizontal, this); featherSlider->setMinimum(0); featherSlider->setMaximum(100); featherSlider->setFixedHeight(22);*/ soundBox = new QCheckBox("Sound"); soundBox->setFont( QFont("Helvetica", 10) ); loopBox = new QCheckBox(tr("Loop"), this); loopBox->setFont( QFont("Helvetica", 10) ); fpsBox = new QSpinBox(this); //fpsBox->setFixedWidth(50); fpsBox->setFont( QFont("Helvetica", 10) ); fpsBox->setFixedHeight(22); fpsBox->setValue(settings.value("fps").toInt()); fpsBox->setMinimum(1); fpsBox->setMaximum(50); fpsBox->setToolTip("FPS"); fpsBox->setFocusPolicy(Qt::NoFocus); /*framecounter = new QLabel; framecounter->setText("1"); framecounter->setAlignment(Qt::AlignCenter); framecounter->setToolTip("Frame Counter!"); framecounter->setFont( QFont("Helvetica", 40, QFont::Bold) );*/ onionNextBox->setToolTip("Onion skin next frame"); onionPrevBox->setToolTip("Onion skin previous frame"); sizeSlider->setToolTip("Set Pen Width"); pencilButton->setIcon(QIcon(":icons/pencil2.png")); pencilButton->setToolTip("Sketch"); penButton->setIcon(QIcon(":icons/pen.png")); penButton->setToolTip("Draw"); polylineButton->setIcon(QIcon(":icons/polyline.png")); polylineButton->setToolTip("Polyline"); bucketButton->setIcon(QIcon(":icons/bucket.png")); bucketButton->setToolTip("Fill"); colouringButton->setIcon(QIcon(":icons/brush.png")); colouringButton->setToolTip("Colouring tool"); eyedropperButton->setIcon(QIcon(":icons/eyedropper.png")); eyedropperButton->setToolTip("Pick colour"); selectButton->setIcon(QIcon(":icons/select.png")); selectButton->setToolTip("Select"); moveButton->setIcon(QIcon(":icons/arrow.png")); moveButton->setToolTip("Select/Move object"); handButton->setIcon(QIcon(":icons/hand.png")); handButton->setToolTip("Move/Zoom canvas"); magnifyButton->setIcon(QIcon(":icons/magnify.png")); magnifyButton->setToolTip("Magnify canvas"); magnifyButton->setEnabled(false); smudgeButton->setIcon(QIcon(":icons/smudge.png")); smudgeButton->setToolTip("Modify curve"); smudgeButton->setEnabled(true); eraserButton->setIcon(QIcon(":icons/eraser.png")); eraserButton->setToolTip("Erase"); add->setIcon(QIcon(":icons/add.png")); add->setToolTip("Add Frame"); rm->setIcon(QIcon(":icons/remove.png")); rm->setToolTip("Remove Frame"); QPixmap colourSwatch(30,30); colourSwatch.fill(Qt::black); QLabel* colourLabel = new QLabel(); colourLabel->setText(tr("Colour:")); colourLabel->setFont( QFont("Helvetica", 10) ); choseColour->setIcon(colourSwatch); choseColour->setToolTip("Display Colours"); thinLinesButton->setIcon(QIcon(":icons/thinlines5.png")); thinLinesButton->setToolTip("Show invisible lines"); outlinesButton->setIcon(QIcon(":icons/outlines5.png")); outlinesButton->setToolTip("Show outlines only"); mirrorButton->setIcon(QIcon(":icons/mirror.png")); mirrorButton->setToolTip("Horizontal flip"); clearButton->setIcon(QIcon(":icons/clear.png")); clearButton->setToolTip("Clear"); thinLinesButton->setCheckable(true); thinLinesButton->setChecked(false); outlinesButton->setCheckable(true); outlinesButton->setChecked(false); mirrorButton->setCheckable(true); mirrorButton->setChecked(false); pencilButton->setCheckable(true); penButton->setCheckable(true); polylineButton->setCheckable(true); bucketButton->setCheckable(true); colouringButton->setCheckable(true); smudgeButton->setCheckable(true); eyedropperButton->setCheckable(true); selectButton->setCheckable(true); moveButton->setCheckable(true); handButton->setCheckable(true); eraserButton->setCheckable(true); pencilButton->setChecked(true); drawLay->setMargin(2); drawLay->setSpacing(0); drawLay->addWidget(pencilButton,0,0); drawLay->setAlignment(pencilButton, Qt::AlignRight); drawLay->addWidget(colouringButton,0,1); drawLay->setAlignment(colouringButton, Qt::AlignLeft); drawLay->addWidget(penButton,1,0); drawLay->setAlignment(penButton, Qt::AlignRight); drawLay->addWidget(polylineButton,1,1); drawLay->setAlignment(polylineButton, Qt::AlignLeft); drawLay->addWidget(eraserButton,2,0); drawLay->setAlignment(eraserButton, Qt::AlignRight); drawLay->addWidget(clearButton,2,1); drawLay->setAlignment(clearButton, Qt::AlignLeft); drawLay->addWidget(bucketButton,3,0); drawLay->setAlignment(bucketButton, Qt::AlignRight); drawLay->addWidget(eyedropperButton,3,1); drawLay->setAlignment(eyedropperButton, Qt::AlignLeft); drawLay->addWidget(selectButton,4,0); drawLay->setAlignment(selectButton, Qt::AlignRight); drawLay->addWidget(moveButton,4,1); drawLay->setAlignment(moveButton, Qt::AlignLeft); drawLay->addWidget(handButton,5,0); drawLay->setAlignment(handButton, Qt::AlignRight); drawLay->addWidget(smudgeButton,5,1); drawLay->setAlignment(smudgeButton, Qt::AlignLeft); //drawLay->addWidget(mirrorButton,5,1); drawLay->setAlignment(mirrorButton, Qt::AlignLeft); optionLay->setMargin(8); optionLay->setSpacing(8); optionLay->addWidget(colourLabel,6,0); optionLay->addWidget(choseColour,6,1); //optionLay->addWidget(thinLinesButton,6,2); //optionLay->addWidget(sizeSlider,7,0,1,2); /*QGroupBox* sizeBox = new QGroupBox("Size"); QHBoxLayout* sizeBoxLay = new QHBoxLayout(); sizeBoxLay->addWidget(sizeSlider2); sizeBoxLay->setMargin(0); sizeBoxLay->setSpacing(0); sizeBox->setLayout(sizeBoxLay);*/ optionLay->addWidget(sizeSlider,8,0,1,2); optionLay->addWidget(featherSlider,9,0,1,2); //optionLay->addWidget(opacitySlider,10,0,1,2); optionLay->addWidget(usePressureBox,11,0,1,2); optionLay->addWidget(preserveAlphaBox,12,0,1,2); optionLay->addWidget(followContourBox,13,0,1,2); optionLay->addWidget(makeInvisibleBox,14,0,1,2); optionLay->setRowStretch(15,1); displayLay->setMargin(4); displayLay->setSpacing(0); displayLay->addWidget(mirrorButton,0,0); displayLay->addWidget(thinLinesButton,0,1); displayLay->addWidget(outlinesButton,0,2); keyLay->setMargin(4); keyLay->setSpacing(0); keyLay->addWidget(add,0,0); keyLay->addWidget(rm,0,1); onionLay->setMargin(4); onionLay->setSpacing(0); onionLay->addWidget(onionPrevBox, 0,0); onionLay->addWidget(onionNextBox, 1,0); timeLay->setMargin(4); timeLay->setSpacing(0); timeLay->addWidget(play,0,0); timeLay->addWidget(fpsBox,1,0); timeLay->addWidget(loopBox,2,0,1,-1); timeLay->addWidget(soundBox,3,0,1,-1); drawGroup->setLayout(drawLay); optionGroup->setLayout(optionLay); displayGroup->setLayout(displayLay); keyGroup->setLayout(keyLay); onionGroup->setLayout(onionLay); timeGroup->setLayout(timeLay); //keyGroup->setFlat(true); //onionGroup->setFlat(true); //timeGroup->setFlat(true); //drawGroup->setMaximumSize( QSize(3*32,6*32+1) ); drawGroup->setMaximumHeight(6*32+1); drawPalette->setMaximumHeight(200); //drawPalette->setFeatures(drawPalette->features() | QDockWidget::DockWidgetVerticalTitleBar); //optionPalette->setMaximumHeight(300); //optionGroup->setMaximumHeight(160); displayPalette->setMaximumHeight(60); keyGroup->setMaximumHeight(60); onionGroup->setMaximumHeight(60); /*butlay->setMargin(0); butlay->setSpacing(2); butlay->addWidget(drawGroup); butlay->addWidget(optionGroup); butlay->addWidget(keyGroup); butlay->addWidget(onionGroup); butlay->addWidget(timeGroup); framelay->addLayout(butlay); //framelay->addWidget(framecounter); setLayout(framelay);*/ connect(add, SIGNAL(clicked()), this, SIGNAL(addClick())); connect(rm, SIGNAL(clicked()), this, SIGNAL(rmClick())); connect(pencilButton, SIGNAL(clicked()), this, SIGNAL(pencilClick())); connect(selectButton, SIGNAL(clicked()), this, SIGNAL(selectClick())); connect(moveButton, SIGNAL(clicked()), this, SIGNAL(moveClick())); connect(handButton, SIGNAL(clicked()), this, SIGNAL(handClick())); connect(eraserButton, SIGNAL(clicked()), this, SIGNAL(eraserClick())); connect(penButton, SIGNAL(clicked()), this, SIGNAL(penClick())); connect(polylineButton, SIGNAL(clicked()), this, SIGNAL(polylineClick())); connect(bucketButton, SIGNAL(clicked()), this, SIGNAL(bucketClick())); connect(eyedropperButton, SIGNAL(clicked()), this, SIGNAL(eyedropperClick())); connect(colouringButton, SIGNAL(clicked()), this, SIGNAL(colouringClick())); connect(smudgeButton, SIGNAL(clicked()), this, SIGNAL(smudgeClick())); connect(thinLinesButton, SIGNAL(clicked()), this, SIGNAL(thinLinesClick())); connect(outlinesButton, SIGNAL(clicked()), this, SIGNAL(outlinesClick())); //connect(outlinesButton, SIGNAL(pressed()), this, SIGNAL(outlinesPressed())); //connect(outlinesButton, SIGNAL(released()), this, SIGNAL(outlinesReleased())); connect(usePressureBox, SIGNAL(clicked(bool)), this, SLOT(pressureClick(bool))); connect(makeInvisibleBox, SIGNAL(clicked(bool)), this, SLOT(invisibleClick(bool))); connect(preserveAlphaBox, SIGNAL(clicked(bool)), this, SLOT(preserveAlphaClick(bool))); connect(followContourBox, SIGNAL(clicked(bool)), this, SLOT(followContourClick(bool))); connect(sizeSlider, SIGNAL(valueChanged(qreal)), this, SIGNAL(widthClick(qreal))); connect(featherSlider, SIGNAL(valueChanged(qreal)), this, SIGNAL(featherClick(qreal))); connect(opacitySlider, SIGNAL(valueChanged(qreal)), this, SIGNAL(opacityClick(qreal))); connect(onionPrevBox, SIGNAL(stateChanged(int)), this, SIGNAL(prevClick())); connect(onionNextBox, SIGNAL(stateChanged(int)), this, SIGNAL(nextClick())); connect(choseColour, SIGNAL(clicked()), this, SIGNAL(colourClick())); connect(clearButton, SIGNAL(clicked()), this, SIGNAL(clearClick())); connect(mirrorButton, SIGNAL(clicked()), this, SIGNAL(mirrorClick())); connect(play, SIGNAL(clicked()), this, SIGNAL(playClick())); connect(loopBox, SIGNAL(stateChanged(int)), this, SIGNAL(loopClick())); connect(soundBox, SIGNAL(stateChanged(int)), this, SIGNAL(soundClick())); connect(fpsBox,SIGNAL(valueChanged(int)), this, SIGNAL(fpsClick(int))); connect(pencilButton, SIGNAL(clicked()), this, SLOT(changePencilButton())); connect(selectButton, SIGNAL(clicked()), this, SLOT(changeSelectButton())); connect(moveButton, SIGNAL(clicked()), this, SLOT(changeMoveButton())); connect(handButton, SIGNAL(clicked()), this, SLOT(changeHandButton())); connect(eraserButton, SIGNAL(clicked()), this, SLOT(changeEraserButton())); connect(penButton, SIGNAL(clicked()), this, SLOT(changePenButton())); connect(polylineButton, SIGNAL(clicked()), this, SLOT(changePolylineButton())); connect(bucketButton, SIGNAL(clicked()), this, SLOT(changeBucketButton())); connect(eyedropperButton, SIGNAL(clicked()), this, SLOT(changeEyedropperButton())); connect(colouringButton, SIGNAL(clicked()), this, SLOT(changeColouringButton())); connect(smudgeButton, SIGNAL(clicked()), this, SLOT(changeSmudgeButton())); //connect(thinLinesButton, SIGNAL(clicked()), this, SLOT(changeThinLinesButton())); } void ToolSet::newToolButton(QToolButton* &toolButton) { toolButton = new QToolButton(this); toolButton->setAutoRaise(true); toolButton->setIconSize( QSize(24,24) ); toolButton->setFixedSize(32,32); } void ToolSet::setCounter(int x) { //framecounter->setText(QString::number(x)); } void ToolSet::setWidth(qreal x) { if(x < 0) { sizeSlider->setEnabled(false); } else { sizeSlider->setEnabled(true); sizeSlider->setValue(x); } } void ToolSet::setFeather(qreal x) { if(x < 0) { featherSlider->setEnabled(false); } else { featherSlider->setEnabled(true); featherSlider->setValue(x); } } void ToolSet::setOpacity(qreal x) { if(x < 0) { opacitySlider->setEnabled(false); } else { opacitySlider->setEnabled(true); opacitySlider->setValue(x); } } void ToolSet::setPressure(int x) { // x = -1, 0, 1 if(x<0) { usePressureBox->setEnabled(false); } else { usePressureBox->setEnabled(true); usePressureBox->setChecked(x>0); } } void ToolSet::pressureClick(bool x) { int y = 0; if(x) y = 1; emit pressureClick(y); } void ToolSet::setInvisibility(int x) { // x = -1, 0, 1 if(x<0) { makeInvisibleBox->setEnabled(false); } else { makeInvisibleBox->setEnabled(true); makeInvisibleBox->setChecked(x>0); } } void ToolSet::invisibleClick(bool x) { int y = 0; if(x) y = 1; emit invisibleClick(y); } void ToolSet::setPreserveAlpha(int x) { // x = -1, 0, 1 if(x<0) { preserveAlphaBox->setEnabled(false); } else { preserveAlphaBox->setEnabled(true); preserveAlphaBox->setChecked(x>0); } } void ToolSet::preserveAlphaClick(bool x) { int y = 0; if(x) y = 1; emit preserveAlphaClick(y); } void ToolSet::setFollowContour(int x) { // x = -1, 0, 1 if(x<0) { followContourBox->setEnabled(false); } else { followContourBox->setEnabled(true); followContourBox->setChecked(x>0); } } void ToolSet::followContourClick(bool x) { int y = 0; if(x) y = 1; emit followContourClick(y); } void ToolSet::setColour(QColor x) { QPixmap colourSwatch(30,30); colourSwatch.fill(x); choseColour->setIcon(colourSwatch); } void ToolSet::changePencilButton() { deselectAllTools(); pencilButton->setChecked(true); } void ToolSet::changeEraserButton() { deselectAllTools(); eraserButton->setChecked(true); } void ToolSet::changeSelectButton() { deselectAllTools(); selectButton->setChecked(true); } void ToolSet::changeMoveButton() { deselectAllTools(); moveButton->setChecked(true); } void ToolSet::changeHandButton() { deselectAllTools(); handButton->setChecked(true); } void ToolSet::changePenButton() { deselectAllTools(); penButton->setChecked(true); } void ToolSet::changePolylineButton() { deselectAllTools(); polylineButton->setChecked(true); } void ToolSet::changeBucketButton() { deselectAllTools(); bucketButton->setChecked(true); } void ToolSet::changeEyedropperButton() { deselectAllTools(); eyedropperButton->setChecked(true); } void ToolSet::changeColouringButton() { deselectAllTools(); colouringButton->setChecked(true); } void ToolSet::changeSmudgeButton() { deselectAllTools(); smudgeButton->setChecked(true); } void ToolSet::changeOutlinesButton(bool trueOrFalse) { outlinesButton->setChecked(trueOrFalse); } void ToolSet::changeThinLinesButton(bool trueOrFalse) { thinLinesButton->setChecked(trueOrFalse); } void ToolSet::resetMirror() { mirrorButton->setChecked(false); } void ToolSet::deselectAllTools() { pencilButton->setChecked(false); eraserButton->setChecked(false); selectButton->setChecked(false); moveButton->setChecked(false); handButton->setChecked(false); penButton->setChecked(false); polylineButton->setChecked(false); bucketButton->setChecked(false); eyedropperButton->setChecked(false); colouringButton->setChecked(false); smudgeButton->setChecked(false); } pencil-0.4.4b/src/interface/preferences.cpp0000644000175000017500000004144110716110271021377 0ustar khashayarkhashayar/* Pencil - Traditional Animation Software Copyright (C) 2005-2007 Patrick Corrieri & Pascal Naidon This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #include #include "preferences.h" #include "scribblearea.h"; Preferences::Preferences() { contentsWidget = new QListWidget; contentsWidget->setViewMode(QListView::IconMode); contentsWidget->setIconSize(QSize(96, 84)); contentsWidget->setMovement(QListView::Static); contentsWidget->setMaximumWidth(128); contentsWidget->setSpacing(12); pagesWidget = new QStackedWidget; pagesWidget->addWidget(new GeneralPage(this)); pagesWidget->addWidget(new FilesPage(this)); pagesWidget->addWidget(new TimelinePage(this)); //pagesWidget->addWidget(new QueryPage); QPushButton *closeButton = new QPushButton(tr("Close")); createIcons(); contentsWidget->setCurrentRow(0); connect(closeButton, SIGNAL(clicked()), this, SLOT(close())); QHBoxLayout *horizontalLayout = new QHBoxLayout; horizontalLayout->addWidget(contentsWidget); horizontalLayout->addWidget(pagesWidget, 1); QHBoxLayout *buttonsLayout = new QHBoxLayout; buttonsLayout->addStretch(1); buttonsLayout->addWidget(closeButton); QVBoxLayout *mainLayout = new QVBoxLayout; mainLayout->addLayout(horizontalLayout); mainLayout->addStretch(1); mainLayout->addSpacing(12); mainLayout->addLayout(buttonsLayout); setLayout(mainLayout); setWindowTitle(tr("Preferences")); } void Preferences::createIcons() { QListWidgetItem *generalButton = new QListWidgetItem(contentsWidget); generalButton->setIcon(QIcon(":icons/prefspencil.png")); generalButton->setText(tr("General")); generalButton->setTextAlignment(Qt::AlignHCenter); generalButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); QListWidgetItem *filesButton = new QListWidgetItem(contentsWidget); filesButton->setIcon(QIcon(":icons/prefs-files.png")); filesButton->setText(tr("Files")); filesButton->setTextAlignment(Qt::AlignHCenter); filesButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); QListWidgetItem *timelineButton = new QListWidgetItem(contentsWidget); timelineButton->setIcon(QIcon(":icons/prefstimeline.png")); timelineButton->setText(tr("Time Line")); timelineButton->setTextAlignment(Qt::AlignHCenter); timelineButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); /*QListWidgetItem *queryButton = new QListWidgetItem(contentsWidget); queryButton->setIcon(QIcon(":/images/query.png")); queryButton->setText(tr("Query")); queryButton->setTextAlignment(Qt::AlignHCenter); queryButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);*/ connect(contentsWidget, SIGNAL(currentItemChanged(QListWidgetItem *, QListWidgetItem *)), this, SLOT(changePage(QListWidgetItem *, QListWidgetItem*))); } void Preferences::changePage(QListWidgetItem *current, QListWidgetItem *previous) { if (!current) current = previous; pagesWidget->setCurrentIndex(contentsWidget->row(current)); } GeneralPage::GeneralPage(QWidget *parent) : QWidget(parent) { QSettings settings("Pencil","Pencil"); QVBoxLayout *lay = new QVBoxLayout(); QGroupBox* windowOpacityBox = new QGroupBox(tr("Window opacity")); QGroupBox* backgroundBox = new QGroupBox(tr("Background")); QGroupBox* appearanceBox = new QGroupBox(tr("Appearance")); QGroupBox* displayBox = new QGroupBox(tr("Rendering")); QGroupBox* editingBox = new QGroupBox(tr("Editing")); QLabel *windowOpacityLabel = new QLabel(tr("Opacity")); QSlider *windowOpacityLevel = new QSlider(Qt::Horizontal); windowOpacityLevel->setMinimum(30); windowOpacityLevel->setMaximum(100); int value = settings.value("windowOpacity").toInt(); windowOpacityLevel->setValue( 100 - value ); QButtonGroup* backgroundButtons = new QButtonGroup(); QRadioButton* checkerBackgroundButton = new QRadioButton(); QRadioButton* whiteBackgroundButton = new QRadioButton(); QRadioButton* greyBackgroundButton = new QRadioButton(); QRadioButton* dotsBackgroundButton = new QRadioButton(); QRadioButton* weaveBackgroundButton = new QRadioButton(); QPixmap previewCheckerboard(32,32); QPixmap previewWhite(32,32); QPixmap previewGrey(32,32); QPixmap previewDots(32,32); QPixmap previewWeave(32,32); QPainter painter(&previewCheckerboard); painter.fillRect( QRect(0,0,32,32), ScribbleArea::getBackgroundBrush("checkerboard") ); painter.end(); painter.begin(&previewDots); painter.fillRect( QRect(0,0,32,32), ScribbleArea::getBackgroundBrush("dots") ); painter.end(); painter.begin(&previewWeave); painter.fillRect( QRect(0,0,32,32), ScribbleArea::getBackgroundBrush("weave") ); painter.end(); previewWhite.fill( Qt::white ); previewGrey.fill( Qt:: lightGray ); checkerBackgroundButton->setIcon( previewCheckerboard ); whiteBackgroundButton->setIcon( previewWhite ); greyBackgroundButton->setIcon( previewGrey ); dotsBackgroundButton->setIcon( previewDots ); dotsBackgroundButton->setIcon( previewWeave ); backgroundButtons->addButton(checkerBackgroundButton); backgroundButtons->addButton(whiteBackgroundButton); backgroundButtons->addButton(greyBackgroundButton); backgroundButtons->addButton(dotsBackgroundButton); backgroundButtons->addButton(weaveBackgroundButton); backgroundButtons->setId(checkerBackgroundButton, 1); backgroundButtons->setId(whiteBackgroundButton, 2); backgroundButtons->setId(greyBackgroundButton, 3); backgroundButtons->setId(dotsBackgroundButton, 4); backgroundButtons->setId(weaveBackgroundButton, 5); QHBoxLayout *backgroundLayout = new QHBoxLayout(); backgroundBox->setLayout(backgroundLayout); backgroundLayout->addWidget(checkerBackgroundButton); backgroundLayout->addWidget(whiteBackgroundButton); backgroundLayout->addWidget(greyBackgroundButton); backgroundLayout->addWidget(dotsBackgroundButton); backgroundLayout->addWidget(weaveBackgroundButton); if( settings.value("background").toString() == "checkerboard" ) checkerBackgroundButton->setChecked(true); if( settings.value("background").toString() == "white" ) whiteBackgroundButton->setChecked(true); if( settings.value("background").toString() == "grey" ) greyBackgroundButton->setChecked(true); if( settings.value("background").toString() == "dots" ) dotsBackgroundButton->setChecked(true); if( settings.value("background").toString() == "weave" ) weaveBackgroundButton->setChecked(true); QCheckBox *shadowsBox = new QCheckBox(tr("Shadows")); shadowsBox->setChecked(false); // default if (settings.value("shadows").toString()=="true") shadowsBox->setChecked(true); QCheckBox *toolCursorsBox = new QCheckBox(tr("Tool Cursors")); toolCursorsBox->setChecked(true); // default if (settings.value("toolCursors").toString()=="false") toolCursorsBox->setChecked(false); QCheckBox *aquaBox = new QCheckBox(tr("Aqua Style")); aquaBox->setChecked(false); // default if (settings.value("style").toString()=="aqua") aquaBox->setChecked(true); QCheckBox *antialiasingBox = new QCheckBox(tr("Antialiasing")); antialiasingBox->setChecked(true); // default if (settings.value("antialiasing").toString()=="false") antialiasingBox->setChecked(false); QButtonGroup *gradientsButtons = new QButtonGroup(); QRadioButton* gradient1Button = new QRadioButton(tr("None")); QRadioButton* gradient2Button = new QRadioButton(tr("Quick")); QRadioButton* gradient3Button = new QRadioButton(tr("Gradient1")); QRadioButton* gradient4Button = new QRadioButton(tr("Gradient2")); gradientsButtons->addButton(gradient1Button); gradientsButtons->addButton(gradient2Button); gradientsButtons->addButton(gradient3Button); gradientsButtons->addButton(gradient4Button); gradientsButtons->setId(gradient1Button, 1); gradientsButtons->setId(gradient2Button, 2); gradientsButtons->setId(gradient3Button, 3); gradientsButtons->setId(gradient4Button, 4); QGroupBox* gradientsBox = new QGroupBox(tr("Gradients")); QHBoxLayout *gradientsLayout = new QHBoxLayout(); gradientsBox->setLayout(gradientsLayout); gradientsLayout->addWidget(gradient1Button); gradientsLayout->addWidget(gradient2Button); gradientsLayout->addWidget(gradient3Button); gradientsLayout->addWidget(gradient4Button); if( settings.value("gradients").toString() == "1" ) gradient1Button->setChecked(true); if( settings.value("gradients").toString() == "2" ) gradient2Button->setChecked(true); if( settings.value("gradients").toString() == "" ) gradient2Button->setChecked(true); // default if( settings.value("gradients").toString() == "3" ) gradient3Button->setChecked(true); if( settings.value("gradients").toString() == "4" ) gradient4Button->setChecked(true); /*QCheckBox *gradientsBox = new QCheckBox(tr("Gradients")); gradientsBox->setChecked(true); // default if (settings.value("gradients").toString()=="0") gradientsBox->setChecked(false);*/ QLabel *curveOpacityLabel = new QLabel(tr("Vector curve opacity")); QSlider *curveOpacityLevel = new QSlider(Qt::Horizontal); curveOpacityLevel->setMinimum(0); curveOpacityLevel->setMaximum(100); curveOpacityLevel->setValue( 100 - settings.value("curveOpacity").toInt() ); QGridLayout *windowOpacityLayout = new QGridLayout(); windowOpacityBox->setLayout(windowOpacityLayout); windowOpacityLayout->addWidget(windowOpacityLabel, 0, 0); windowOpacityLayout->addWidget(windowOpacityLevel, 0, 1); QVBoxLayout *appearanceLayout = new QVBoxLayout(); appearanceBox->setLayout(appearanceLayout); appearanceLayout->addWidget(shadowsBox); appearanceLayout->addWidget(toolCursorsBox); #ifdef Q_WS_MAC appearanceLayout->addWidget(aquaBox); #endif QGridLayout *displayLayout = new QGridLayout(); displayBox->setLayout(displayLayout); displayLayout->addWidget(antialiasingBox, 0, 0); displayLayout->addWidget(gradientsBox, 1, 0); displayLayout->addWidget(curveOpacityLabel, 2, 0); displayLayout->addWidget(curveOpacityLevel, 3, 0); QLabel *curveSmoothingLabel = new QLabel(tr("Vector curve smoothing")); QSlider *curveSmoothingLevel = new QSlider(Qt::Horizontal); curveSmoothingLevel->setMinimum(1); curveSmoothingLevel->setMaximum(100); value = settings.value("curveSmoothing").toInt(); curveSmoothingLevel->setValue( value ); QCheckBox *highResBox = new QCheckBox(tr("Tablet high-resolution position")); if (settings.value("highResPosition")=="true") highResBox->setChecked(true); else highResBox->setChecked(false); QGridLayout *editingLayout = new QGridLayout(); editingBox->setLayout(editingLayout); editingLayout->addWidget(curveSmoothingLabel, 0, 0); editingLayout->addWidget(curveSmoothingLevel, 1, 0); editingLayout->addWidget(highResBox, 2, 0); //QLabel *fontSizeLabel = new QLabel(tr("Labels font size")); //QDoubleSpinBox *fontSize = new QDoubleSpinBox(); /*fontSize->setMinimum(4); fontSize->setMaximum(20); frameSize->setMinimum(4); frameSize->setMaximum(20); fontSize->setFixedWidth(50); frameSize->setFixedWidth(50); lengthSize->setFixedWidth(50); if (settings.value("drawLabel")=="false") drawLabel->setChecked(false); else drawLabel->setChecked(true); fontSize->setValue(settings.value("labelFontSize").toInt()); frameSize->setValue(settings.value("frameSize").toInt()); if (settings.value("labelFontSize").toInt()==0) fontSize->setValue(12); if (settings.value("frameSize").toInt()==0) frameSize->setValue(6); lengthSize->setText(settings.value("length").toString()); if (settings.value("length").toInt()==0) lengthSize->setText("240"); connect(fontSize, SIGNAL(valueChanged(int)), this, SIGNAL(fontSizeChange(int))); connect(frameSize, SIGNAL(valueChanged(int)), this, SIGNAL(frameSizeChange(int))); connect(lengthSize, SIGNAL(textChanged(QString)), this, SIGNAL(lengthSizeChange(QString))); connect(drawLabel, SIGNAL(stateChanged(int)), this, SIGNAL(labelChange(int)));*/ lay->addWidget(windowOpacityBox); lay->addWidget(appearanceBox); lay->addWidget(backgroundBox); lay->addWidget(displayBox); lay->addWidget(editingBox); connect(windowOpacityLevel, SIGNAL(valueChanged(int)), parent, SIGNAL(windowOpacityChange(int))); connect(backgroundButtons, SIGNAL(buttonClicked(int)), parent, SIGNAL(backgroundChange(int))); connect(gradientsButtons, SIGNAL(buttonClicked(int)), parent, SIGNAL(gradientsChange(int))); connect(shadowsBox, SIGNAL(stateChanged(int)), parent, SIGNAL(shadowsChange(int))); connect(toolCursorsBox, SIGNAL(stateChanged(int)), parent, SIGNAL(toolCursorsChange(int))); connect(aquaBox, SIGNAL(stateChanged(int)), parent, SIGNAL(styleChange(int))); connect(antialiasingBox, SIGNAL(stateChanged(int)), parent, SIGNAL(antialiasingChange(int))); connect(curveOpacityLevel, SIGNAL(valueChanged(int)), parent, SIGNAL(curveOpacityChange(int))); connect(curveSmoothingLevel, SIGNAL(valueChanged(int)), parent, SIGNAL(curveSmoothingChange(int))); connect(highResBox, SIGNAL(stateChanged(int)), parent, SIGNAL(highResPositionChange(int))); /*lay->addWidget(fontSizeLabel); lay->addWidget(fontSize); lay->addWidget(frameSizeLabel); lay->addWidget(frameSize); lay->addWidget(lengthSizeLabel); lay->addWidget(lengthSize);*/ setLayout(lay); } TimelinePage::TimelinePage(QWidget *parent) : QWidget(parent) { QSettings settings("Pencil","Pencil"); QVBoxLayout *lay = new QVBoxLayout(); QGroupBox* timeLineBox = new QGroupBox(tr("Time Line")); QCheckBox *drawLabel = new QCheckBox(tr("Draw timeline labels")); QLabel *fontSizeLabel = new QLabel(tr("Labels font size")); QSpinBox *fontSize = new QSpinBox(); QLabel *frameSizeLabel = new QLabel(tr("Frame size in Pixels")); QSpinBox *frameSize = new QSpinBox(this); QLabel *lengthSizeLabel = new QLabel(tr("Timeline size in Frames")); QLineEdit *lengthSize = new QLineEdit(this); lengthSize->setInputMask("9999"); QCheckBox *scrubBox = new QCheckBox(tr("Short scrub")); scrubBox->setChecked(false); // default if (settings.value("shortScrub").toBool()) scrubBox->setChecked(true); fontSize->setMinimum(4); fontSize->setMaximum(20); frameSize->setMinimum(4); frameSize->setMaximum(20); fontSize->setFixedWidth(50); frameSize->setFixedWidth(50); lengthSize->setFixedWidth(50); if (settings.value("drawLabel")=="false") drawLabel->setChecked(false); else drawLabel->setChecked(true); fontSize->setValue(settings.value("labelFontSize").toInt()); frameSize->setValue(settings.value("frameSize").toInt()); if (settings.value("labelFontSize").toInt()==0) fontSize->setValue(12); if (settings.value("frameSize").toInt()==0) frameSize->setValue(6); lengthSize->setText(settings.value("length").toString()); if (settings.value("length").toInt()==0) lengthSize->setText("240"); connect(fontSize, SIGNAL(valueChanged(int)), parent, SIGNAL(fontSizeChange(int))); connect(frameSize, SIGNAL(valueChanged(int)), parent, SIGNAL(frameSizeChange(int))); connect(lengthSize, SIGNAL(textChanged(QString)), parent, SIGNAL(lengthSizeChange(QString))); connect(drawLabel, SIGNAL(stateChanged(int)), parent, SIGNAL(labelChange(int))); connect(scrubBox, SIGNAL(stateChanged(int)), parent, SIGNAL(scrubChange(int))); //lay->addWidget(drawLabel); //lay->addWidget(fontSizeLabel); //lay->addWidget(fontSize); lay->addWidget(frameSizeLabel); lay->addWidget(frameSize); lay->addWidget(lengthSizeLabel); lay->addWidget(lengthSize); lay->addWidget(scrubBox); timeLineBox->setLayout(lay); QVBoxLayout *lay2 = new QVBoxLayout(); lay2->addWidget(timeLineBox); lay2->addStretch(1); setLayout(lay2); } FilesPage::FilesPage(QWidget *parent) : QWidget(parent) { QSettings settings("Pencil","Pencil"); QVBoxLayout *lay = new QVBoxLayout(); QGroupBox* autosaveBox = new QGroupBox(tr("Autosave documents")); QCheckBox *autosaveCheckBox = new QCheckBox(tr("Enable autosave")); QLabel *autosaveNumberLabel = new QLabel(tr("Number of modifications before autosaving:")); QSpinBox *autosaveNumberBox = new QSpinBox(); autosaveNumberBox->setMinimum(5); autosaveNumberBox->setMaximum(200); autosaveNumberBox->setFixedWidth(50); autosaveCheckBox->setChecked(false); if (settings.value("autosave")=="true") autosaveCheckBox->setChecked(true); autosaveNumberBox->setValue(settings.value("autosaveNumber").toInt()); if (settings.value("autosaveNumber").toInt()==0) autosaveNumberBox->setValue(20); connect(autosaveNumberBox, SIGNAL(valueChanged(int)), parent, SIGNAL(autosaveNumberChange(int))); connect(autosaveCheckBox, SIGNAL(stateChanged(int)), parent, SIGNAL(autosaveChange(int))); lay->addWidget(autosaveCheckBox); lay->addWidget(autosaveNumberLabel); lay->addWidget(autosaveNumberBox); autosaveBox->setLayout(lay); QVBoxLayout *lay2 = new QVBoxLayout(); lay2->addWidget(autosaveBox); lay2->addStretch(1); setLayout(lay2); } pencil-0.4.4b/src/interface/palette.cpp0000644000175000017500000002032510716110271020532 0ustar khashayarkhashayar/* Pencil - Traditional Animation Software Copyright (C) 2005-2007 Patrick Corrieri & Pascal Naidon This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #include #include #include "palette.h" #include "colourref.h" #include "object.h" #include "editor.h" Palette::Palette(Editor* editor) : QDockWidget(editor, Qt::Tool) { this->editor = editor; QWidget* paletteContent = new QWidget(); //paletteContent->setWindowFlags(Qt::FramelessWindowHint); sliderRed = new QSlider(Qt::Horizontal); sliderGreen = new QSlider(Qt::Horizontal); sliderBlue = new QSlider(Qt::Horizontal); sliderAlpha = new QSlider(Qt::Horizontal); sliderRed->setRange(0,255); sliderGreen->setRange(0,255); sliderBlue->setRange(0,255); sliderAlpha->setRange(0,255); QLabel* labelRed = new QLabel(tr("Red")); QLabel* labelGreen = new QLabel(tr("Green")); QLabel* labelBlue = new QLabel(tr("Blue")); QLabel* labelAlpha = new QLabel(tr("Alpha")); labelRed->setFont( QFont("Helvetica", 10) ); labelGreen->setFont( QFont("Helvetica", 10) ); labelBlue->setFont( QFont("Helvetica", 10) ); labelAlpha->setFont( QFont("Helvetica", 10) ); QGridLayout* sliderLayout = new QGridLayout(); sliderLayout->setSpacing(3); sliderLayout->addWidget(labelRed, 0, 0); sliderLayout->addWidget(sliderRed, 0, 1); sliderLayout->addWidget(labelGreen, 1, 0); sliderLayout->addWidget(sliderGreen, 1, 1); sliderLayout->addWidget(labelBlue, 2, 0); sliderLayout->addWidget(sliderBlue, 2, 1); sliderLayout->addWidget(labelAlpha, 3, 0); sliderLayout->addWidget(sliderAlpha, 3, 1); sliderLayout->setMargin(10); sliderLayout->setSpacing(2); //QWidget* sliders = new QWidget(); //sliders->setLayout(sliderLayout); //sliders->setFixedHeight(60); listOfColours = new QListWidget(); QToolBar *buttons = new QToolBar(); addButton = new QToolButton(); removeButton = new QToolButton(); addButton->setIcon(QIcon(":icons/add.png")); addButton->setToolTip("Add Colour"); addButton->setFixedSize(30,30); removeButton->setIcon(QIcon(":icons/remove.png")); removeButton->setToolTip("Remove Colour"); removeButton->setFixedSize(30,30); QLabel* spacer = new QLabel(); spacer->setFixedWidth(10); colourSwatch = new QToolButton(); //QLabel(); colourSwatch->setFixedSize( 40, 40 ); QPixmap colourPixmap(30,30); colourPixmap.fill( Qt::black ); colourSwatch->setIcon(QIcon(colourPixmap)); //colourSwatch->setPixmap(colourPixmap); /*QFrame* colourSwatchFrame = new QFrame(); colourSwatchFrame->setFixedSize( 50, 50 ); //colourSwatchFrame->setFrameStyle(QFrame::Panel | QFrame::Sunken); QVBoxLayout *colourSwatchLayout = new QVBoxLayout(); colourSwatchLayout->addWidget(colourSwatch); colourSwatchFrame->setLayout(colourSwatchLayout);*/ //QGridLayout *buttonLayout = new QGridLayout(); buttons->addWidget(spacer); buttons->addWidget(colourSwatch); buttons->addWidget(addButton); buttons->addWidget(removeButton); //buttons->setFixedSize(100,34); //buttons->layout()->setMargin(0); //buttons->layout()->setSpacing(0); //buttonLayout->setMargin(0); //buttonLayout->setSpacing(0); //buttons->setLayout(buttonLayout); listOfColours->setFrameStyle(QFrame::Panel | QFrame::Sunken); listOfColours->setLineWidth(1); listOfColours->setFocusPolicy(Qt::NoFocus); //listOfColours->setMinimumWidth(100); QVBoxLayout *layout = new QVBoxLayout(); layout->addLayout(sliderLayout); layout->addWidget(buttons); layout->addWidget(listOfColours); layout->setMargin(0); paletteContent->setLayout(layout); setWidget(paletteContent); //setFrameStyle(QFrame::Panel); //setWindowFlags(Qt::Tool); setWindowFlags(Qt::WindowStaysOnTopHint); //setWindowFlags(Qt::SubWindow); setFloating(true); //setAllowedAreas(Qt::NoDockWidgetArea); //setMinimumSize(100, 300); paletteContent->setFixedWidth(150); /// otherwise the palette is naturally too wide. Someone please fix this. //setFloating(false); //setFixedWidth(130); //setGeometry(10,60,100, 300); //setFocusPolicy(Qt::NoFocus); //setWindowOpacity(0.7); setWindowTitle(tr("Colours")); connect(sliderRed, SIGNAL(sliderMoved(int)), this, SLOT(updateColour())); connect(sliderGreen, SIGNAL(sliderMoved(int)), this, SLOT(updateColour())); connect(sliderBlue, SIGNAL(sliderMoved(int)), this, SLOT(updateColour())); connect(sliderAlpha, SIGNAL(sliderMoved(int)), this, SLOT(updateColour())); connect(sliderRed, SIGNAL(sliderReleased()), this, SLOT(changeColour())); connect(sliderGreen, SIGNAL(sliderReleased()), this, SLOT(changeColour())); connect(sliderBlue, SIGNAL(sliderReleased()), this, SLOT(changeColour())); connect(sliderAlpha, SIGNAL(sliderReleased()), this, SLOT(changeColour())); connect(listOfColours, SIGNAL(currentItemChanged(QListWidgetItem *, QListWidgetItem *)), this, SLOT(selectColour(QListWidgetItem *, QListWidgetItem *))); connect(listOfColours, SIGNAL(itemClicked ( QListWidgetItem *)), this, SLOT(selectAndApplyColour( QListWidgetItem *))); //connect(listOfColours, SIGNAL(itemDoubleClicked ( QListWidgetItem *)), this, SLOT(changeColour( QListWidgetItem *))); connect(listOfColours, SIGNAL(itemDoubleClicked ( QListWidgetItem *)), this, SLOT(changeColourName( QListWidgetItem *))); connect(addButton, SIGNAL(clicked()), this, SLOT(addClick())); connect(removeButton, SIGNAL(clicked()), this, SLOT(rmClick())); connect(colourSwatch, SIGNAL(clicked()), this, SLOT(colourSwatchClicked())); connect(this, SIGNAL(topLevelChanged(bool)), this, SLOT(closeIfDocked(bool))); } /*QSize Palette::sizeHint() { return QSize(150,600); }*/ void Palette::updateList() { //listOfColours->clear(); // for some reason, this creates an bus error when one removes the last element while(listOfColours->count() > 0) listOfColours->takeItem(0); for(int i=0; i < editor->object->getColourCount(); i++) { ColourRef colourRef = editor->object->getColour(i); QListWidgetItem* colourItem = new QListWidgetItem(listOfColours); colourItem->setText( colourRef.name ); QPixmap colourSwatch(32,32); colourSwatch.fill( colourRef.colour ); QPainter painter(&colourSwatch); painter.setPen( QColor(0,0,0,128) ); painter.drawRect( QRect(0,-1,31,31) ); colourItem->setIcon( colourSwatch ); } update(); } void Palette::colourSwatchClicked() { editor->changeColour(currentColour()); } void Palette::selectColour(QListWidgetItem* current, QListWidgetItem* previous) { if (!current) current = previous; editor->selectColour(listOfColours->row(current)); } void Palette::selectAndApplyColour(QListWidgetItem* current) { editor->selectAndApplyColour(listOfColours->row(current)); } void Palette::changeColour() { QColor newColour = QColor( sliderRed->value(), sliderGreen->value(), sliderBlue->value(), sliderAlpha->value() ); editor->changeColour(currentColour(), newColour); } void Palette::updateColour() { QColor newColour = QColor( sliderRed->value(), sliderGreen->value(), sliderBlue->value(), sliderAlpha->value() ); editor->updateColour(currentColour(), newColour); } void Palette::updateSwatch(QColor colour) { QPixmap colourPixmap(30,30); colourPixmap.fill( colour ); if(colourSwatch != NULL) colourSwatch->setIcon(QIcon(colourPixmap)); //colourSwatch->setPixmap(colourPixmap); } void Palette::changeColour( QListWidgetItem * item ) { if(item != NULL) editor->changeColour(listOfColours->row(item)); } void Palette::changeColourName( QListWidgetItem * item ) { if(item != NULL) editor->changeColourName(listOfColours->row(item)); } void Palette::addClick() { editor->addColour(); } void Palette::rmClick() { editor->removeColour(listOfColours->currentRow()); } void Palette::closeIfDocked(bool floating) { //if(floating == false) close(); // we don't want to dock the palette in the mainwindow (or do we?) } void Palette::setColour(QColor colour) { setColour(colour.red(), colour.green(), colour.blue(), colour.alpha()); updateSwatch(colour); } void Palette::setColour(int r, int g, int b, int a) { sliderRed->setValue(r); sliderGreen->setValue(g); sliderBlue->setValue(b); sliderAlpha->setValue(a); } pencil-0.4.4b/src/interface/scribblearea.h0000644000175000017500000001533110745152004021162 0ustar khashayarkhashayar/* Pencil - Traditional Animation Software Copyright (C) 2005-2007 Patrick Corrieri & Pascal Naidon This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #ifndef SCRIBBLEAREA_H #define SCRIBBLEAREA_H #include #include #include #include #include #include #include "vectorimage.h" #include "bitmapimage.h" #include "colourref.h" class Editor; class Layer; class Properties { public: qreal width; qreal feather; qreal opacity; QColor colour; int colourNumber; bool pressure; bool invisibility; bool preserveAlpha; }; class VectorSelection { public: QList vertex; QList curve; //QList area; void clear(); void add(int curveNumber); void add(QList curveNumbers); void add(VertexRef point); void add(QList points); }; /*struct Buffer { QList points; QList colours; };*/ //class ScribbleArea : public QGLWidget class ScribbleArea : public QWidget { Q_OBJECT public: ScribbleArea(QWidget *parent = 0, Editor* editor = 0); void next(const int &i); void setColour(const int); void setColour(const QColor); void resetColours(); void deleteSelection(); void setSelection(QRectF rect, bool); void displaySelectionProperties(); QRectF getSelection() { return mySelection; } bool somethingSelected; bool readCanvasFromCache; bool isModified() const { return modified; } static QBrush getBackgroundBrush(QString); //QColor penColour() const { return myPenColour; } //double pencilWidth() const { return myPencilWidth; } //double penWidth() const { return myPenWidth; } //double brushWidth() const { return myBrushWidth; } bool thinLines() const { return showThinLines; } int allLayers() const { return showAllLayers; } QMatrix getView(); QRectF getViewRect(); QPointF getCentralPoint(); void updateFrame(); void updateFrame(int frame); void updateAllFrames(); void updateAllVectorLayersAtCurrentFrame(); void updateAllVectorLayersAt(int frame); void updateAllVectorLayers(); signals: void modification(); void modification(int); void thinLinesChanged(bool); void outlinesChanged(bool); //void showAllLayersChanged(bool); public slots: void clearImage(); void calculateSelectionRect(); void calculateSelectionTransformation(); void paintTransformedSelection(); void setModified(int layerNumber, int frameNumber); void selectAll(); void deselectAll(); void onionPrevSlot(); void onionNextSlot(); //void pressureSlot(int); //void invisibleSlot(int); void pencilOn(); void eraserOn(); void selectOn(); void moveOn(); void handOn(); void resetView(); void setMyView(QMatrix view); QMatrix getMyView(); void penOn(); void polylineOn(); void bucketOn(); void eyedropperOn(); void colouringOn(); void smudgeOn(); void setWidth(const qreal); void setFeather(const qreal); void setOpacity(const qreal); void setPressure(const bool); void setInvisibility(const bool); void setPreserveAlpha(const bool); void setFollowContour(const bool); void setCurveOpacity(int); void setCurveSmoothing(int); void setHighResPosition(int); void setAntialiasing(int); void setGradients(int); void setBackground(int); void setBackgroundBrush(QString); void setShadows(int); void setToolCursors(int); void setStyle(int); void toggleThinLines(); void toggleOutlines(); void toggleMirror(); void toggleShowAllLayers(); void escape(); //void undo(); //void redo(); //void copy(); //void paste(); protected: void tabletEvent(QTabletEvent *event); void mousePressEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event); void mouseDoubleClickEvent(QMouseEvent *event); void keyPressEvent(QKeyEvent *event); void keyReleaseEvent(QKeyEvent *event); void paintEvent(QPaintEvent *event); void resizeEvent(QResizeEvent *event); void recentre(); void setView(); void setView(QMatrix); private: void paintBitmapBuffer(); void updateCanvas(int frame, QRect rect); void setGaussianGradient(QGradient &gradient, QColor coulour, qreal opacity, qreal offset); void drawBrush(QPointF thePoint, qreal brushWidth, qreal offset, QColor fillColour, qreal opacity); void drawLineTo(const QPointF &endPixel, const QPointF &endPoint); void drawEyedropperPreview(const QColor colour); void drawPolyline(); void endPolyline(); void updateCursor(); void floodFill(VectorImage* vectorImage, QPoint point, QRgb targetColour, QRgb replacementColour, int tolerance); void floodFillError(int errorType); enum myToolModes { PENCIL, ERASER, SELECT, MOVE, EDIT, HAND, SMUDGE, PEN, POLYLINE, BUCKET, EYEDROPPER, COLOURING }; enum myMoveModes { MIDDLE, TOPLEFT, TOPRIGHT, BOTTOMLEFT, BOTTOMRIGHT }; myToolModes toolMode; myMoveModes moveMode; void switchTool(); Editor* editor; int tabletEraserBackupToolMode; bool modified; bool simplified; bool showThinLines; int showAllLayers; bool usePressure, makeInvisible; bool highResPosition; bool antialiasing; bool shadows; bool toolCursors; int gradients; qreal curveOpacity; qreal curveSmoothing; bool onionPrev, onionNext; Properties pencil; Properties pen; Properties brush; Properties eraser; qreal currentWidth; QColor currentColour; /*qreal myPencilWidth, currentPencilWidth; qreal myPenWidth, currentPenWidth; qreal myBrushWidth, currentBrushWidth;*/ //QColor myPenColour, myFillColour; //int penColourNumber, fillColourNumber; bool followContour; QBrush backgroundBrush; BitmapImage* bufferImg; // used to pre-draw vector modifications //Buffer buffer; // used to pre-draw bitmap modifications, such as lines, brushes, etc. QPixmap* eyedropperCursor; bool mouseInUse; QList mousePoints; // copy of points clicked using polyline tool QList mousePath; // copy of points drawn using pencil, pen, eraser, etc, tools QList mousePressure; QPointF lastPixel, currentPixel; QPointF lastPoint, currentPoint; QPointF lastBrushPoint; //QBrush brush; // the current brush qreal tol; QList closestCurves; QList closestVertices; QPointF offset; VectorSelection vectorSelection; //bool selectionChanged; QMatrix selectionTransformation; QRectF mySelection, myTransformedSelection, myTempTransformedSelection; bool tabletInUse; qreal tabletPressure; QPointF tabletPosition; QMatrix myView, myTempView, centralView, transMatrix; QPixmap canvas; // debug QRectF debugRect; }; #endif pencil-0.4.4b/src/interface/timecontrols.h0000644000175000017500000000176410644055565021307 0ustar khashayarkhashayar/* Pencil - Traditional Animation Software Copyright (C) 2005-2007 Patrick Corrieri & Pascal Naidon This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #ifndef TIMECONTROL_H #define TIMECONTROL_H #include #include #include #include class TimeControls : public QToolBar { Q_OBJECT public: TimeControls(QWidget *parent = 0); signals: void playClick(); void loopClick(); void soundClick(); void fpsClick(int); public slots: //void updateLoopButton(bool); void updateButtons(bool); protected: private: QPushButton* playButton; QPushButton* loopButton; QPushButton* soundButton; }; #endif pencil-0.4.4b/src/interface/editor.cpp0000644000175000017500000016311510745152004020371 0ustar khashayarkhashayar/* Pencil - Traditional Animation Software Copyright (C) 2005-2007 Patrick Corrieri & Pascal Naidon This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #include #include #include #include #include #include #include #include #include "editor.h" #include "layerbitmap.h" #include "layervector.h" #include "layersound.h" #include "layercamera.h" Editor::Editor(QMainWindow* parent) { mainWindow = parent; QSettings settings("Pencil","Pencil"); object = NULL; // the editor is initialized with no object savedName = ""; altpress=false; modified=false; numberOfModifications = 0; autosave=settings.value("autosave").toBool(); autosaveNumber=settings.value("autosaveNumber").toInt(); if (autosaveNumber==0) { autosaveNumber=20; settings.setValue("autosaveNumber", 20); } backupIndex = -1; clipboardBitmapOk = false; clipboardVectorOk = false; fps = settings.value("fps").toInt(); if (fps==0) { fps=12; settings.setValue("fps", 12); } maxFrame = 1; timer = new QTimer(this); timer->setInterval(1000/fps); connect(timer, SIGNAL(timeout()), this, SLOT(playNextFrame())); playing = false; looping = false; sound = true; frameList << 1; currentFrame = 1; currentLayer = 0; QHBoxLayout *lay = new QHBoxLayout(); QVBoxLayout *framelay = new QVBoxLayout(); scribbleArea = new ScribbleArea(this, this); timeLine = new TimeLine(this, this); toolSet = new ToolSet(); palette = new Palette(this); preferences = new Preferences(); exportFramesDialog = NULL; // will be created when needed exportMovieDialog = NULL; exportFlashDialog = NULL; newDocumentDialog = NULL; exportFramesDialog_hBox = NULL; exportFramesDialog_vBox = NULL; exportFramesDialog_format = NULL; exportMovieDialog_hBox = NULL; exportMovieDialog_vBox = NULL; exportMovieDialog_format = NULL; exportFlashDialog_compression = NULL; // FOCUS POLICY scribbleArea->setFocusPolicy(Qt::StrongFocus); timeLine->setFocusPolicy(Qt::NoFocus); toolSet->setFocusPolicy(Qt::NoFocus); palette->setFocusPolicy(Qt::NoFocus); // CONNECTIONS connect(toolSet, SIGNAL(addClick()), this, SLOT(addKey())); connect(toolSet, SIGNAL(rmClick()), this, SLOT(removeKey())); connect(toolSet, SIGNAL(playClick()), this, SLOT(play())); connect(toolSet, SIGNAL(fpsClick(int)), this, SLOT(changeFps(int))); connect(toolSet, SIGNAL(loopClick()), this, SLOT(setLoop())); connect(toolSet, SIGNAL(pencilClick()), scribbleArea, SLOT(pencilOn())); connect(toolSet, SIGNAL(eraserClick()), scribbleArea, SLOT(eraserOn())); connect(toolSet, SIGNAL(selectClick()), scribbleArea, SLOT(selectOn())); connect(toolSet, SIGNAL(moveClick()), scribbleArea, SLOT(moveOn())); connect(toolSet, SIGNAL(handClick()), scribbleArea, SLOT(handOn())); connect(toolSet, SIGNAL(penClick()), scribbleArea, SLOT(penOn())); connect(toolSet, SIGNAL(polylineClick()), scribbleArea, SLOT(polylineOn())); connect(toolSet, SIGNAL(bucketClick()), scribbleArea, SLOT(bucketOn())); connect(toolSet, SIGNAL(eyedropperClick()), scribbleArea, SLOT(eyedropperOn())); connect(toolSet, SIGNAL(colouringClick()), scribbleArea, SLOT(colouringOn())); connect(toolSet, SIGNAL(smudgeClick()), scribbleArea, SLOT(smudgeOn())); connect(toolSet, SIGNAL(pressureClick(int)), this, SLOT(applyPressure(int))); connect(toolSet, SIGNAL(invisibleClick(int)), this, SLOT(applyInvisibility(int))); connect(toolSet, SIGNAL(preserveAlphaClick(int)), this, SLOT(applyPreserveAlpha(int))); connect(toolSet, SIGNAL(followContourClick(int)), this, SLOT(applyFollowContour(int))); connect(toolSet, SIGNAL(widthClick(qreal)), this, SLOT(applyWidth(qreal))); connect(toolSet, SIGNAL(featherClick(qreal)), this, SLOT(applyFeather(qreal))); connect(toolSet, SIGNAL(opacityClick(qreal)), this, SLOT(applyOpacity(qreal))); connect(toolSet, SIGNAL(colourClick()), this, SLOT(showPalette())); connect(toolSet,SIGNAL(clearClick()), scribbleArea, SLOT(clearImage())); connect(toolSet, SIGNAL(thinLinesClick()), scribbleArea, SLOT(toggleThinLines())); connect(toolSet, SIGNAL(outlinesClick()), scribbleArea, SLOT(toggleOutlines())); connect(scribbleArea, SIGNAL(thinLinesChanged(bool)), toolSet, SLOT(changeThinLinesButton(bool))); connect(scribbleArea, SIGNAL(outlinesChanged(bool)), toolSet, SLOT(changeOutlinesButton(bool))); connect(toolSet, SIGNAL(mirrorClick()), this, SLOT(toggleMirror())); connect(toolSet, SIGNAL(prevClick()), scribbleArea, SLOT(onionPrevSlot())); connect(toolSet, SIGNAL(nextClick()), scribbleArea, SLOT(onionNextSlot())); connect(this, SIGNAL(selectAll()), scribbleArea, SLOT(selectAll())); connect(scribbleArea, SIGNAL(modification()), this, SLOT(modification())); connect(scribbleArea, SIGNAL(modification(int)), this, SLOT(modification(int))); connect(timeLine, SIGNAL(modification()), this, SLOT(modification())); connect(timeLine, SIGNAL(addKeyClick()), this, SLOT(addKey())); connect(timeLine, SIGNAL(removeKeyClick()), this, SLOT(removeKey())); connect(timeLine, SIGNAL(newBitmapLayer()), this, SLOT(newBitmapLayer())); connect(timeLine, SIGNAL(newVectorLayer()), this, SLOT(newVectorLayer())); connect(timeLine, SIGNAL(newSoundLayer()), this, SLOT(newSoundLayer())); connect(timeLine, SIGNAL(newCameraLayer()), this, SLOT(newCameraLayer())); connect(timeLine, SIGNAL(deleteCurrentLayer()), this, SLOT(deleteCurrentLayer())); connect(timeLine, SIGNAL(playClick()), this, SLOT(play())); connect(timeLine, SIGNAL(loopClick()), this, SLOT(setLoop())); connect(timeLine, SIGNAL(soundClick()), this, SLOT(setSound())); connect(timeLine, SIGNAL(fpsClick(int)), this, SLOT(changeFps(int))); connect(timeLine, SIGNAL(onionPrevClick()), scribbleArea, SLOT(onionPrevSlot())); connect(timeLine, SIGNAL(onionNextClick()), scribbleArea, SLOT(onionNextSlot())); connect(preferences, SIGNAL(windowOpacityChange(int)), mainWindow, SLOT(setOpacity(int))); connect(preferences, SIGNAL(curveOpacityChange(int)), scribbleArea, SLOT(setCurveOpacity(int))); connect(preferences, SIGNAL(curveSmoothingChange(int)), scribbleArea, SLOT(setCurveSmoothing(int))); connect(preferences, SIGNAL(highResPositionChange(int)), scribbleArea, SLOT(setHighResPosition(int))); connect(preferences, SIGNAL(antialiasingChange(int)), scribbleArea, SLOT(setAntialiasing(int))); connect(preferences, SIGNAL(gradientsChange(int)), scribbleArea, SLOT(setGradients(int))); connect(preferences, SIGNAL(backgroundChange(int)), scribbleArea, SLOT(setBackground(int))); connect(preferences, SIGNAL(shadowsChange(int)), scribbleArea, SLOT(setShadows(int))); connect(preferences, SIGNAL(toolCursorsChange(int)), scribbleArea, SLOT(setToolCursors(int))); connect(preferences, SIGNAL(styleChange(int)), scribbleArea, SLOT(setStyle(int))); connect(preferences, SIGNAL(autosaveChange(int)), this, SLOT(changeAutosave(int))); connect(preferences, SIGNAL(autosaveNumberChange(int)), this, SLOT(changeAutosaveNumber(int))); connect(preferences, SIGNAL(lengthSizeChange(QString)), timeLine, SIGNAL(lengthChange(QString))); connect(preferences, SIGNAL(fontSizeChange(int)), timeLine, SIGNAL(fontSizeChange(int))); connect(preferences, SIGNAL(frameSizeChange(int)), timeLine, SIGNAL(frameSizeChange(int))); connect(preferences, SIGNAL(labelChange(int)), timeLine, SIGNAL(labelChange(int))); connect(preferences, SIGNAL(scrubChange(int)), timeLine, SIGNAL(scrubChange(int))); connect(QApplication::clipboard(), SIGNAL(dataChanged()), this, SLOT(clipboardChanged()) ); framelay->addWidget(scribbleArea); lay->addWidget(toolSet); lay->addLayout(framelay); framelay->setMargin(0); framelay->setSpacing(0); lay->setMargin(0); lay->setSpacing(0); setLayout(lay); qDebug() << "Hello"; qDebug() << QLibraryInfo::location(QLibraryInfo::PluginsPath); qDebug() << QLibraryInfo::location(QLibraryInfo::BinariesPath); qDebug() << QLibraryInfo::location(QLibraryInfo::LibrariesPath); setAcceptDrops(true); } Editor::~Editor() { // a lot more probably needs to be cleaned here... if (object) delete object; clearBackup(); } void Editor::dragEnterEvent(QDragEnterEvent *event) { //if (event->mimeData()->hasFormat("text/plain")) event->acceptProposedAction(); } void Editor::dropEvent(QDropEvent *event) { if( event->mimeData()->hasUrls() ) { for(int i=0; i < event->mimeData()->urls().size(); i++) { if(i>0) scrubForward(); QUrl url = event->mimeData()->urls()[i]; QString filePath = url.toLocalFile(); if(filePath.endsWith(".png") || filePath.endsWith(".jpg") || filePath.endsWith(".jpeg")) importImage( filePath ); if(filePath.endsWith(".aif") || filePath.endsWith(".mp3") || filePath.endsWith(".wav")) importSound( filePath ); } } } void Editor::showCounter(int n) { toolSet->setCounter(n); } void Editor::newDocument() { if (maybeSave()) { //if (!exportFramesDialog) createNewDocumentDialog(); //newDocumentDialog->exec(); //if(newDocumentDialog->result() == QDialog::Rejected) return; //QSize documentSize = QSize(newDocumentDialog_hBox->value(), newDocumentDialog_vBox->value()); //newObject(documentSize); newObject(); // default size } } void Editor::openDocument() { if (maybeSave()) { QSettings settings("Pencil","Pencil"); QString myPath = settings.value("lastFilePath", QVariant(QDir::homePath())).toString(); QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"), myPath); if (!fileName.isEmpty()) { bool ok = openObject(fileName); if(!ok) { QMessageBox::warning(this, "Warning", "Pencil cannot read this file. If you want to import images, use the command import."); newObject(); } } } } void Editor::openRecent() { QSettings settings("Pencil","Pencil"); QString myPath = settings.value("lastFilePath", QVariant(QDir::homePath())).toString(); bool ok = openObject(myPath); if(!ok) { QMessageBox::warning(this, "Warning", "Pencil cannot read this file. If you want to import images, use the command import."); newObject(); } } bool Editor::saveDocument() { //QAction *action = qobject_cast(sender()); // ? old code from Patrick? //QByteArray fileFormat = action->data().toByteArray(); // ? old code from Patrick? QSettings settings("Pencil","Pencil"); QString myPath = settings.value("lastFilePath", QVariant(QDir::homePath())).toString(); QString fileName = QFileDialog::getSaveFileName(this, tr("Save As"), myPath); if (fileName.isEmpty()) { return false; } else { QSettings settings("Pencil","Pencil"); settings.setValue("lastFilePath", QVariant(fileName)); return saveObject(fileName); } } void Editor::setWidth(qreal width) { scribbleArea->setWidth(width); toolSet->setWidth(width); } void Editor::applyWidth(qreal width) { setWidth(width); Layer* layer = getCurrentLayer(); if(layer == NULL) return; if(layer->type == Layer::VECTOR) ((LayerVector*)layer)->getLastVectorImageAtFrame(currentFrame, 0)->applyWidthToSelection(width); } void Editor::setFeather(qreal feather) { scribbleArea->setFeather(feather); toolSet->setFeather(feather); } void Editor::applyFeather(qreal feather) { setFeather(feather); Layer* layer = getCurrentLayer(); if(layer == NULL) return; if(layer->type == Layer::VECTOR) ((LayerVector*)layer)->getLastVectorImageAtFrame(currentFrame, 0)->applyFeatherToSelection(feather); } void Editor::setOpacity(qreal opacity) { scribbleArea->setOpacity(opacity); toolSet->setOpacity(opacity); } void Editor::applyOpacity(qreal opacity) { setOpacity(opacity); Layer* layer = getCurrentLayer(); if(layer == NULL) return; if(layer->type == Layer::VECTOR) ((LayerVector*)layer)->getLastVectorImageAtFrame(currentFrame, 0)->applyOpacityToSelection(opacity); } void Editor::setInvisibility(int invisibility) { if(invisibility>=0) scribbleArea->setInvisibility(invisibility>0); toolSet->setInvisibility(invisibility); } void Editor::applyInvisibility(int invisibility) { setInvisibility(invisibility); Layer* layer = getCurrentLayer(); if(layer == NULL) return; if(layer->type == Layer::VECTOR) ((LayerVector*)layer)->getLastVectorImageAtFrame(currentFrame, 0)->applyInvisibilityToSelection(invisibility>0); } void Editor::setPreserveAlpha(int preserveAlpha) { if(preserveAlpha>=0) scribbleArea->setPreserveAlpha(preserveAlpha>0); toolSet->setPreserveAlpha(preserveAlpha); } void Editor::applyPreserveAlpha(int preserveAlpha) { setPreserveAlpha(preserveAlpha); } void Editor::setFollowContour(int followContour) { if(followContour>=0) scribbleArea->setFollowContour(followContour>0); toolSet->setFollowContour(followContour); } void Editor::applyFollowContour(int followContour) { setFollowContour(followContour); } void Editor::setPressure(int pressure) { if(pressure>=0) scribbleArea->setPressure(pressure>0); toolSet->setPressure(pressure); } void Editor::applyPressure(int pressure) { setPressure(pressure); Layer* layer = getCurrentLayer(); if(layer == NULL) return; if(layer->type == Layer::VECTOR) ((LayerVector*)layer)->getLastVectorImageAtFrame(currentFrame, 0)->applyVariableWidthToSelection(pressure>0); } void Editor::selectColour(int i) { if(i > -1) { scribbleArea->setColour(i); toolSet->setColour(object->getColour(i).colour); palette->selectColour(i); palette->setColour(object->getColour(i).colour); } } void Editor::selectAndApplyColour(int i) { selectColour(i); Layer* layer = getCurrentLayer(); if(layer == NULL) return; if(layer->type == Layer::VECTOR) ((LayerVector*)layer)->getLastVectorImageAtFrame(currentFrame, 0)->applyColourToSelection(i); } void Editor::setColour(QColor colour) { scribbleArea->setColour(colour); toolSet->setColour(colour); palette->setColour(colour); } void Editor::changeColour(int i) { //QColor newColour = QColorDialog::getColor(object->getColour(i).colour); if(i>-1) { bool *ok; ok = new bool; QRgb qrgba = QColorDialog::getRgba( object->getColour(i).colour.rgba(), ok, this ); if(*ok) { changeColour(i, QColor::fromRgba(qrgba) ); } delete ok; } } void Editor::changeColourName(int i) { if (i>-1) { bool ok; QString text = QInputDialog::getText(this, tr("Colour name"), tr("Colour name:"), QLineEdit::Normal, object->getColour(i).name, &ok); if (ok && !text.isEmpty()) { object->renameColour(i, text); palette->updateList(); } } } void Editor::changeColour(int i, QColor newColour) { if (newColour.isValid() && i>-1) { /*object->setColour(i, newColour); Layer* layer = object->getLayer(currentLayer); if(layer != NULL) { if(layer->type == Layer::VECTOR) scribbleArea->setModified(layer, currentFrame); }*/ updateColour(i, newColour); palette->updateList(); selectColour(i); } } void Editor::updateColour(int i, QColor newColour) { if( newColour.isValid() && i>-1) { object->setColour(i, newColour); Layer* layer = object->getLayer(currentLayer); if(layer != NULL) { if(layer->type == Layer::VECTOR) scribbleArea->setModified(currentLayer, currentFrame); } toolSet->setColour(object->getColour(i).colour); palette->updateSwatch(object->getColour(i).colour); scribbleArea->setColour(i); } } void Editor::addColour() { QColor initialColour = Qt::white; int currentColourIndex = palette->currentColour(); if( currentColourIndex > -1 ) { initialColour = object->getColour(currentColourIndex).colour; } bool *ok; ok = new bool; QRgb qrgba = QColorDialog::getRgba( initialColour.rgba(), ok, this ); if(*ok) { object->addColour( QColor::fromRgba(qrgba) ); palette->updateList(); selectColour(object->getColourCount()-1); } delete ok; /*QColor newColour = QColorDialog::getColor( initialColour ); if (newColour.isValid()) { object->addColour(newColour); palette->updateList(); //selectColour(object->getColourCount()); }*/ } void Editor::removeColour(int i) { if(object->removeColour(i)) { palette->updateList(); } else { QMessageBox::warning(this, tr("Warning"), tr("You cannot remove this colour because it is used!"), QMessageBox::Ok, QMessageBox::Ok); } } void Editor::changeAutosave(int x) { QSettings settings("Pencil","Pencil"); if (x==0) { autosave=false; settings.setValue("autosave","false"); } else { autosave=true; settings.setValue("autosave","true"); } } void Editor::changeAutosaveNumber(int number) { autosaveNumber = number; QSettings settings("Pencil","Pencil"); settings.setValue("autosaveNumber", number); } void Editor::modification() { modification(currentLayer); } void Editor::modification(int layerNumber) { modified = true; if(object != NULL) object->modification(); lastModifiedFrame = currentFrame; lastModifiedLayer = layerNumber; scribbleArea->update(); timeLine->updateContent(); numberOfModifications++; if(autosave && numberOfModifications > autosaveNumber) { numberOfModifications = 0; //saveForce(); if (savedName!="") saveObject(savedName); } } void Editor::backup() { if(lastModifiedLayer>-1 && lastModifiedFrame > 0) { backup(lastModifiedLayer, lastModifiedFrame); } if( lastModifiedLayer != currentLayer || lastModifiedFrame != currentFrame ) { backup(currentLayer, currentFrame); } } void Editor::backup(int backupLayer, int backupFrame) { while(backupList.size()-1 > backupIndex && backupList.size() > 0) { delete backupList.takeLast(); } while(backupList.size() > 19) { // we authorize only 20 levels of cancellation delete backupList.takeFirst(); backupIndex--; } Layer* layer = object->getLayer(backupLayer); if(layer != NULL) { if(layer->type == Layer::BITMAP) { BackupBitmapElement* element = new BackupBitmapElement(); element->layer = backupLayer; element->frame = backupFrame; BitmapImage* bitmapImage = ((LayerBitmap*)layer)->getLastBitmapImageAtFrame(backupFrame, 0); if(bitmapImage != NULL) { element->bitmapImage = bitmapImage->copy(); // copy the image backupList.append(element); backupIndex++; } } if(layer->type == Layer::VECTOR) { BackupVectorElement* element = new BackupVectorElement(); element->layer = backupLayer; element->frame = backupFrame; VectorImage* vectorImage = ((LayerVector*)layer)->getLastVectorImageAtFrame(backupFrame, 0); if(vectorImage != NULL) { element->vectorImage = *vectorImage; // copy the image (that works but I should also provide a copy() method) backupList.append(element); backupIndex++; } } } } void BackupBitmapElement::restore(Editor* editor) { Layer* layer = editor->object->getLayer(this->layer); if(layer != NULL) { if(layer->type == Layer::BITMAP) { *( ((LayerBitmap*)layer)->getLastBitmapImageAtFrame(this->frame, 0) ) = this->bitmapImage; // restore the image } } editor->updateFrame(this->frame); editor->scrubTo(this->frame); } void BackupVectorElement::restore(Editor* editor) { Layer* layer = editor->object->getLayer(this->layer); if(layer != NULL) { if(layer->type == Layer::VECTOR) { *( ((LayerVector*)layer)->getLastVectorImageAtFrame(this->frame, 0) ) = this->vectorImage; // restore the image //((LayerVector*)layer)->getLastVectorImageAtFrame(this->frame, 0)->setModified(true); // why? //editor->scribbleArea->setModified(layer, this->frame); } } editor->updateFrameAndVector(this->frame); editor->scrubTo(this->frame); } void Editor::undo() { if( backupList.size() > 0 && backupIndex > -1) { if(backupIndex == backupList.size()-1) { BackupElement* lastBackupElement = backupList[backupIndex]; if(lastBackupElement->type() == BackupElement::BITMAP_MODIF) { BackupBitmapElement* lastBackupBitmapElement = (BackupBitmapElement*)lastBackupElement; backup( lastBackupBitmapElement->layer, lastBackupBitmapElement->frame ); backupIndex--; } if(lastBackupElement->type() == BackupElement::VECTOR_MODIF) { BackupVectorElement* lastBackupVectorElement = (BackupVectorElement*)lastBackupElement; backup( lastBackupVectorElement->layer, lastBackupVectorElement->frame ); backupIndex--; } } // backupList[backupIndex]->restore(this); backupIndex--; scribbleArea->calculateSelectionRect(); // really ugly -- to improve } } void Editor::redo() { if( backupList.size() > 0 && backupIndex < backupList.size()-2) { backupIndex++; backupList[backupIndex+1]->restore(this); } } void Editor::clearBackup() { backupIndex = -1; while( !backupList.isEmpty() ) { delete backupList.takeLast(); } lastModifiedLayer = -1; lastModifiedFrame = -1; } void Editor::copy() { Layer* layer = object->getLayer(currentLayer); if(layer != NULL) { if(layer->type == Layer::BITMAP) { if(scribbleArea->somethingSelected) { clipboardBitmapImage = ((LayerBitmap*)layer)->getLastBitmapImageAtFrame(currentFrame, 0)->copy( scribbleArea->getSelection().toRect() ); // copy part of the image } else { clipboardBitmapImage = ((LayerBitmap*)layer)->getLastBitmapImageAtFrame(currentFrame, 0)->copy(); // copy the whole image } clipboardBitmapOk = true; if( clipboardBitmapImage.image != NULL ) QApplication::clipboard()->setImage( *(clipboardBitmapImage.image) ); } if(layer->type == Layer::VECTOR) { clipboardVectorOk = true; clipboardVectorImage = *( ((LayerVector*)layer)->getLastVectorImageAtFrame(currentFrame, 0) ); // copy the image (that works but I should also provide a copy() method) } } } void Editor::paste() { Layer* layer = object->getLayer(currentLayer); if(layer != NULL) { if(layer->type == Layer::BITMAP && clipboardBitmapImage.image != NULL) { // clipboardBitmapOk backup(); BitmapImage tobePasted = clipboardBitmapImage.copy(); qDebug() << "to be pasted --->" << tobePasted.image->size(); if(scribbleArea->somethingSelected) { QRectF selection = scribbleArea->getSelection(); if( clipboardBitmapImage.width() <= selection.width() && clipboardBitmapImage.height() <= selection.height() ) { tobePasted.moveTopLeft( selection.topLeft() ); } else { tobePasted.transform( selection, true ); } } ((LayerBitmap*)layer)->getLastBitmapImageAtFrame(currentFrame, 0)->paste( &tobePasted ); // paste the clipboard } if(layer->type == Layer::VECTOR && clipboardVectorOk) { backup(); scribbleArea->deselectAll(); VectorImage* vectorImage = ((LayerVector*)layer)->getLastVectorImageAtFrame(currentFrame, 0); vectorImage->paste( clipboardVectorImage ); // paste the clipboard scribbleArea->setSelection( vectorImage->getSelectionRect(), true ); //((LayerVector*)layer)->getLastVectorImageAtFrame(backupFrame, 0)->modification(); ???? } } scribbleArea->updateFrame(); } void Editor::clipboardChanged() { if(clipboardBitmapOk == false) { clipboardBitmapImage.image = new QImage( QApplication::clipboard()->image() ); clipboardBitmapImage.boundaries = QRect( clipboardBitmapImage.topLeft(), clipboardBitmapImage.image->size() ); qDebug() << "New clipboard image" << clipboardBitmapImage.image->size(); } else { clipboardBitmapOk = false; qDebug() << "The image has been saved in the clipboard"; } } void Editor::newBitmapLayer() { if(object != NULL) { object->addNewBitmapLayer(); timeLine->updateLayerNumber( object->getLayerCount() ); setCurrentLayer( object->getLayerCount()-1 ); } } void Editor::newVectorLayer() { if(object != NULL) { object->addNewVectorLayer(); timeLine->updateLayerNumber( object->getLayerCount() ); setCurrentLayer( object->getLayerCount()-1 ); } } void Editor::newSoundLayer() { if(object != NULL) { object->addNewSoundLayer(); timeLine->updateLayerNumber( object->getLayerCount() ); setCurrentLayer( object->getLayerCount()-1 ); } } void Editor::newCameraLayer() { if(object != NULL) { object->addNewCameraLayer(); timeLine->updateLayerNumber( object->getLayerCount() ); setCurrentLayer( object->getLayerCount()-1 ); } } void Editor::deleteCurrentLayer() { int ret = QMessageBox::warning(this, tr("Warning"), tr("Are yo sure you want to delete the selected layer?"), QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Ok); if(ret == QMessageBox::Ok) { object->deleteLayer(currentLayer); if(currentLayer == object->getLayerCount()) setCurrentLayer( currentLayer-1 ); timeLine->updateLayerNumber( object->getLayerCount() ); //timeLine->update(); scribbleArea->updateAllFrames(); } } void Editor::toggleMirror() { object->toggleMirror(); scribbleArea->toggleMirror(); } void Editor::toggleShowAllLayers() { scribbleArea->toggleShowAllLayers(); timeLine->updateContent(); } void Editor::resetMirror() { object->resetMirror(); toolSet->resetMirror(); } void Editor::showPalette() { if(palette->isVisible()) { palette->close(); } else { palette->show(); } } void Editor::saveLength(QString x) { bool ok; int dec = x.toInt(&ok, 10); QSettings settings("Pencil","Pencil"); settings.setValue("length", dec); } void Editor::about() { QMessageBox::about(this, tr("Pencil 0.4.4b"), tr("
" "
" "
" "Developed by: Pascal Naidon & Patrick Corrieri
" "Version: 0.4.4b (21st January, 2008)

" "Thanks to:
" "Trolltech for the Qt libraries
" "Roland for the Movie export functions
" "Axel for his help with Qt
" "Mark for his help with Qt and SVN

" "http://www.les-stooges.org/pascal/pencil/

" "Distributed under the GPL License." "
" "
")); } void Editor::helpBox() { QMessageBox::about(this, tr("Help"), tr("Some documentation is available online.

" "Please visit:
" "http://www.les-stooges.org/pascal/pencil/.")); } bool Editor::maybeSave() { if (object->modified) { int ret = QMessageBox::warning(this, tr("Warning"), tr("This animation has been modified.\n" "Do you want to save your changes?"), QMessageBox::Yes | QMessageBox::Default, QMessageBox::No, QMessageBox::Cancel | QMessageBox::Escape); if (ret == QMessageBox::Yes) { saveForce(); return true; } else if (ret == QMessageBox::Cancel) { return false; } } return true; } bool Editor::saveObject(QString filePath) { QFileInfo fileInfo(filePath); if(fileInfo.isDir()) return false; QFileInfo dataInfo(filePath+".data"); if(!dataInfo.exists()) { QDir dir(fileInfo.absolutePath()); // the directory where filePath is or will be saved dir.mkpath(filePath+".data"); // creates a directory with the same name +".data" } savedName=filePath; mainWindow->setWindowTitle(savedName); QProgressDialog progress("Saving document...", "Abort", 0, 100, mainWindow); progress.setWindowModality(Qt::WindowModal); progress.show(); int progressValue = 0; // save data int nLayers = object->getLayerCount(); for(int i=0; i < nLayers; i++) { qDebug() << "Saving Layer " << i; progressValue = (i*100)/nLayers; progress.setValue(progressValue); Layer* layer = object->getLayer(i); if(layer->type == Layer::BITMAP) ((LayerBitmap*)layer)->saveImages(filePath+".data", i); if(layer->type == Layer::VECTOR) ((LayerVector*)layer)->saveImages(filePath+".data", i); if(layer->type == Layer::SOUND) ((LayerSound*)layer)->saveImages(filePath+".data", i); } // save palette object->savePalette(filePath+".data"); // -------- save main XML file ----------- QFile* file = new QFile(filePath); if (!file->open(QFile::WriteOnly | QFile::Text)) { //QMessageBox::warning(this, "Warning", "Cannot write file"); return false; } QTextStream out(file); QDomDocument doc("PencilDocument"); QDomElement root = doc.createElement("document"); doc.appendChild(root); // save editor information QDomElement editorElement = createDomElement(doc); root.appendChild(editorElement); // save object QDomElement objectElement = object->createDomElement(doc); root.appendChild(objectElement); int IndentSize = 2; doc.save(out, IndentSize); // ----------------------------------- progress.setValue(100); object->modified = false; timeLine->updateContent(); return true; } void Editor::newObject() { //if(object != NULL) delete object; Object *newObject = new Object(); newObject->defaultInitialisation(); setObject(newObject); updateObject(); savedName = ""; mainWindow->setWindowTitle(tr("Pencil v0.4.4b")); } void Editor::setObject(Object *object) { if ((this->object)&&(object!=this->object)) { disconnect( this->object, 0, 0, 0); // disconnect the current object from everything delete this->object; } this->object = object; if(object) { connect( object, SIGNAL(imageAdded(int)), this, SLOT(addFrame(int)) ); connect( object, SIGNAL(imageAdded(int,int)), this, SLOT(addFrame(int,int)) ); connect( object, SIGNAL(imageRemoved(int)), this, SLOT(removeFrame(int)) ); //currentLayer = object->getLayerCount()-1; // the default selected layer is the last one currentLayer = 0; // the default selected layer is the first one currentFrame = 1; frameList.clear(); frameList << 1; } } void Editor::updateObject() { scribbleArea->resetColours(); palette->selectColour(0); //scribbleArea->resize(object->size); //scribbleArea->updateAllFrames(); //scribbleArea->resetView(); timeLine->updateLayerNumber(object->getLayerCount()); palette->updateList(); clearBackup(); scribbleArea->resetColours(); palette->selectColour(0); scribbleArea->updateAllFrames(); } bool Editor::openObject(QString filePath) { // ---- test before opening ---- QFileInfo fileInfo(filePath); if( fileInfo.isDir() ) return false; QFile* file = new QFile(filePath); if (!file->open(QFile::ReadOnly)) return false; QDomDocument doc; if (!doc.setContent(file)) return false; // this is not a XML file QDomDocumentType type = doc.doctype(); if(type.name() != "PencilDocument" && type.name() != "MyObject") return false; // this is not a Pencil document // ----------------------------- QProgressDialog progress("Opening document...", "Abort", 0, 100, mainWindow); progress.setWindowModality(Qt::WindowModal); progress.show(); savedName = filePath; QSettings settings("Pencil","Pencil"); settings.setValue("lastFilePath", QVariant(savedName) ); mainWindow->setWindowTitle(savedName); Object* newObject = new Object(); if(!newObject->loadPalette(savedName+".data")) newObject->loadDefaultPalette(); setObject(newObject); // ------- reads the XML file ------- bool ok = true; QDomElement docElem = doc.documentElement(); if(docElem.isNull()) return false; if(docElem.tagName() == "document") { QDomNode tag = docElem.firstChild(); while(!tag.isNull()) { QDomElement element = tag.toElement(); // try to convert the node to an element. if(!element.isNull()) { if(element.tagName() == "editor") { loadDomElement(element, filePath); } if(element.tagName() == "object") { ok = newObject->loadDomElement(element, filePath); } } tag = tag.nextSibling(); } } else { if(docElem.tagName() == "object" || docElem.tagName() == "MyOject") { // old Pencil format (<=0.4.3) ok = newObject->loadDomElement(docElem, filePath); } } // ------------------------------ if(ok) updateObject(); progress.setValue(100); return ok; } void Editor::saveForce() { if (savedName!="") saveObject(savedName); else saveDocument(); } void Editor::createNewDocumentDialog() { /*newDocumentDialog = new QDialog(this, Qt::Dialog); QGridLayout *mainLayout = new QGridLayout; QGroupBox *resolutionBox = new QGroupBox(tr("Resolution")); newDocumentDialog_hBox = new QSpinBox(this); newDocumentDialog_hBox->setMinimum(1); newDocumentDialog_hBox->setMaximum(10000); int defaultWidth = 720; int defaultHeight = 540; //if(object != NULL) { // defaultWidth = object->size.width(); defaultHeight = object->size.height(); //} newDocumentDialog_hBox->setValue(defaultWidth); newDocumentDialog_hBox->setFixedWidth(80); newDocumentDialog_vBox = new QSpinBox(this); newDocumentDialog_vBox->setMinimum(1); newDocumentDialog_vBox->setMaximum(10000); newDocumentDialog_vBox->setValue(defaultHeight); newDocumentDialog_vBox->setFixedWidth(80); QGridLayout *resolutionLayout = new QGridLayout; resolutionLayout->addWidget(newDocumentDialog_hBox,0,0); resolutionLayout->addWidget(newDocumentDialog_vBox,0,1); resolutionBox->setLayout(resolutionLayout); QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); connect(buttonBox, SIGNAL(accepted()), newDocumentDialog, SLOT(accept())); connect(buttonBox, SIGNAL(rejected()), newDocumentDialog, SLOT(reject())); mainLayout->addWidget(resolutionBox, 0, 0); mainLayout->addWidget(buttonBox, 1, 0); newDocumentDialog->setLayout(mainLayout); newDocumentDialog->setWindowTitle(tr("Options")); newDocumentDialog->setModal(true);*/ } void Editor::createExportFramesSizeBox() { int defaultWidth = 720; int defaultHeight = 540; exportFramesDialog_hBox = new QSpinBox(this); exportFramesDialog_hBox->setMinimum(1); exportFramesDialog_hBox->setMaximum(10000); exportFramesDialog_hBox->setValue(defaultWidth); exportFramesDialog_hBox->setFixedWidth(80); exportFramesDialog_vBox = new QSpinBox(this); exportFramesDialog_vBox->setMinimum(1); exportFramesDialog_vBox->setMaximum(10000); exportFramesDialog_vBox->setValue(defaultHeight); exportFramesDialog_vBox->setFixedWidth(80); } void Editor::createExportMovieSizeBox() { int defaultWidth = 720; int defaultHeight = 540; exportMovieDialog_hBox = new QSpinBox(this); exportMovieDialog_hBox->setMinimum(1); exportMovieDialog_hBox->setMaximum(10000); exportMovieDialog_hBox->setValue(defaultWidth); exportMovieDialog_hBox->setFixedWidth(80); exportMovieDialog_vBox = new QSpinBox(this); exportMovieDialog_vBox->setMinimum(1); exportMovieDialog_vBox->setMaximum(10000); exportMovieDialog_vBox->setValue(defaultHeight); exportMovieDialog_vBox->setFixedWidth(80); } void Editor::createExportFramesDialog() { exportFramesDialog = new QDialog(this, Qt::Dialog); QGridLayout *mainLayout = new QGridLayout; QGroupBox *resolutionBox = new QGroupBox(tr("Resolution")); if(exportFramesDialog_hBox == NULL || exportFramesDialog_vBox == NULL) { createExportFramesSizeBox(); } QGridLayout *resolutionLayout = new QGridLayout; resolutionLayout->addWidget(exportFramesDialog_hBox,0,0); resolutionLayout->addWidget(exportFramesDialog_vBox,0,1); resolutionBox->setLayout(resolutionLayout); QGroupBox *formatBox = new QGroupBox(tr("Format")); exportFramesDialog_format = new QComboBox(); exportFramesDialog_format->addItem("PNG"); exportFramesDialog_format->addItem("JPEG"); QGridLayout *formatLayout = new QGridLayout; formatLayout->addWidget(exportFramesDialog_format,0,0); formatBox->setLayout(formatLayout); QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); connect(buttonBox, SIGNAL(accepted()), exportFramesDialog, SLOT(accept())); connect(buttonBox, SIGNAL(rejected()), exportFramesDialog, SLOT(reject())); mainLayout->addWidget(resolutionBox, 0, 0); mainLayout->addWidget(formatBox, 1, 0); mainLayout->addWidget(buttonBox, 2, 0); exportFramesDialog->setLayout(mainLayout); exportFramesDialog->setWindowTitle(tr("Options")); exportFramesDialog->setModal(true); } void Editor::createExportMovieDialog() { exportMovieDialog = new QDialog(this, Qt::Dialog); QGridLayout *mainLayout = new QGridLayout; QGroupBox *resolutionBox = new QGroupBox(tr("Resolution")); if(!exportMovieDialog_hBox || !exportMovieDialog_vBox) { createExportMovieSizeBox(); } QGridLayout *resolutionLayout = new QGridLayout; resolutionLayout->addWidget(exportMovieDialog_hBox,0,0); resolutionLayout->addWidget(exportMovieDialog_vBox,0,1); resolutionBox->setLayout(resolutionLayout); QGroupBox *formatBox = new QGroupBox(tr("Format")); exportMovieDialog_format = new QComboBox(); exportMovieDialog_format->addItem("MOV"); //exportFramesDialog_format->addItem("JPEG"); QGridLayout *formatLayout = new QGridLayout; formatLayout->addWidget(exportMovieDialog_format,0,0); formatBox->setLayout(formatLayout); QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); connect(buttonBox, SIGNAL(accepted()), exportMovieDialog, SLOT(accept())); connect(buttonBox, SIGNAL(rejected()), exportMovieDialog, SLOT(reject())); mainLayout->addWidget(resolutionBox, 0, 0); mainLayout->addWidget(formatBox, 1, 0); mainLayout->addWidget(buttonBox, 2, 0); exportMovieDialog->setLayout(mainLayout); exportMovieDialog->setWindowTitle(tr("Options")); exportMovieDialog->setModal(true); } void Editor::createExportFlashDialog() { exportFlashDialog = new QDialog(this, Qt::Dialog); QGridLayout *mainLayout = new QGridLayout; QSettings settings("Pencil","Pencil"); exportFlashDialog_compression = new QSlider(Qt::Horizontal); exportFlashDialog_compression->setTickPosition(QSlider::TicksBelow); exportFlashDialog_compression->setMinimum(0); exportFlashDialog_compression->setMaximum(10); exportFlashDialog_compression->setValue( 10 - settings.value("flashCompressionLevel").toInt() ); QLabel* label1 = new QLabel("Large file"); QLabel* label2 = new QLabel("Small file"); QGroupBox *compressionBox = new QGroupBox(tr("Compression")); QGridLayout *compressionLayout = new QGridLayout; compressionLayout->addWidget(label1,0,0); compressionLayout->addWidget(exportFlashDialog_compression,0,1); compressionLayout->addWidget(label2,0,2); compressionBox->setLayout(compressionLayout); QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Cancel | QDialogButtonBox::Ok); connect(buttonBox, SIGNAL(accepted()), exportFlashDialog, SLOT(accept())); connect(buttonBox, SIGNAL(rejected()), exportFlashDialog, SLOT(reject())); mainLayout->addWidget(compressionBox, 0, 0); mainLayout->addWidget(buttonBox, 1, 0); exportFlashDialog->setLayout(mainLayout); exportFlashDialog->setWindowTitle(tr("Options")); exportFlashDialog->setModal(true); } QMatrix Editor::map(QRectF source, QRectF target) { // this method should be put somewhere else... qreal x1 = source.left(); qreal y1 = source.top(); qreal x2 = source.right(); qreal y2 = source.bottom(); qreal x1P = target.left(); qreal y1P = target.top(); qreal x2P = target.right(); qreal y2P = target.bottom(); QMatrix matrix; bool mirror = false; if( (x1 != x2) && (y1 != y2) ) { if( !mirror) { matrix = QMatrix ( (x2P-x1P)/(x2-x1), 0, 0, (y2P-y1P)/(y2-y1), (x1P*x2-x2P*x1)/(x2-x1), (y1P*y2-y2P*y1)/(y2-y1) ); } else { matrix = QMatrix ( (x2P-x1P)/(x1-x2), 0, 0, (y2P-y1P)/(y2-y1), (x1P*x1-x2P*x2)/(x1-x2), (y1P*y2-y2P*y1)/(y2-y1) ); } } else { matrix.reset(); } return matrix; } bool Editor::exportSeq() { QSettings settings("Pencil","Pencil"); QString initialPath = settings.value("lastExportPath", QVariant(QDir::homePath())).toString(); if(initialPath.isEmpty()) initialPath = QDir::homePath() + "/untitled"; QString filePath = QFileDialog::getSaveFileName(this, tr("Export As"),initialPath); if (filePath.isEmpty()) { return false; } else { settings.setValue("lastExportPath", QVariant(filePath)); if (!exportFramesDialog) createExportFramesDialog(); exportFramesDialog_hBox->setValue( scribbleArea->getViewRect().toRect().width() ); exportFramesDialog_vBox->setValue( scribbleArea->getViewRect().toRect().height() ); exportFramesDialog->exec(); if(exportFramesDialog->result() == QDialog::Rejected) return false; QSize exportSize = QSize(exportFramesDialog_hBox->value(), exportFramesDialog_vBox->value()); //QMatrix view = map( QRectF(QPointF(0,0), scribbleArea->size() ), QRectF(QPointF(0,0), exportSize) ); QMatrix view = map( scribbleArea->getViewRect(), QRectF(QPointF(0,0), exportSize) ); view = scribbleArea->getView() * view; QByteArray exportFormat(exportFramesDialog_format->currentText().toLatin1()); updateMaxFrame(); object->exportFrames(1, maxFrame, view, getCurrentLayer(), exportSize, filePath, exportFormat, -1, false, true, 2); return true; } } bool Editor::exportX() { QSettings settings("Pencil","Pencil"); QString initialPath = settings.value("lastExportPath", QVariant(QDir::homePath())).toString(); if(initialPath.isEmpty()) initialPath = QDir::homePath() + "/untitled"; QString filePath = QFileDialog::getSaveFileName(this, tr("Save As"),initialPath); if (filePath.isEmpty()) { qDebug() << "empty file"; return false; } else { settings.setValue("lastExportPath", QVariant(filePath)); QSize exportSize = scribbleArea->getViewRect().toRect().size(); QMatrix view = map( scribbleArea->getViewRect(), QRectF(QPointF(0,0), exportSize) ); view = scribbleArea->getView() * view; updateMaxFrame(); object->exportX(1, maxFrame, view, exportSize, filePath, true, 2); return true; } } bool Editor::exportMov() { QSettings settings("Pencil","Pencil"); QString initialPath = settings.value("lastExportPath", QVariant(QDir::homePath())).toString(); if(initialPath.isEmpty()) initialPath = QDir::homePath() + "/untitled"; QString filePath = QFileDialog::getSaveFileName(this, tr("Export As"),initialPath); if (filePath.isEmpty()) { return false; } else { settings.setValue("lastExportPath", QVariant(filePath)); if (!exportMovieDialog) createExportMovieDialog(); exportMovieDialog_hBox->setValue( scribbleArea->getViewRect().toRect().width() ); exportMovieDialog_vBox->setValue( scribbleArea->getViewRect().toRect().height() ); exportMovieDialog->exec(); if(exportMovieDialog->result() == QDialog::Rejected) return false; QSize exportSize = QSize(exportMovieDialog_hBox->value(), exportMovieDialog_vBox->value()); QMatrix view = map( scribbleArea->getViewRect(), QRectF(QPointF(0,0), exportSize) ); view = scribbleArea->getView() * view; updateMaxFrame(); object->exportMovie(1, maxFrame, view, getCurrentLayer(), exportSize, filePath, fps); return true; } } bool Editor::exportFlash() { QSettings settings("Pencil","Pencil"); QString initialPath = settings.value("lastExportPath", QVariant(QDir::homePath())).toString(); if(initialPath.isEmpty()) initialPath = QDir::homePath() + "/untitled"; QString filePath = QFileDialog::getSaveFileName(this, tr("Export As"),initialPath); if (filePath.isEmpty()) { return false; } else { settings.setValue("lastExportPath", QVariant(filePath)); if (!exportFlashDialog) createExportFlashDialog(); exportFlashDialog->exec(); if(exportFlashDialog->result() == QDialog::Rejected) return false; settings.setValue("flashCompressionLevel", 10-exportFlashDialog_compression->value() ); QSize exportSize = scribbleArea->getViewRect().toRect().size(); QMatrix view = map( scribbleArea->getViewRect(), QRectF(QPointF(0,0), exportSize) ); view = scribbleArea->getView() * view; updateMaxFrame(); object->exportFlash(1, maxFrame, view, exportSize, filePath, fps, exportFlashDialog_compression->value()); return true; } } void Editor::exportPalette() { QSettings settings("Pencil","Pencil"); QString initialPath = settings.value("lastFilePath", QVariant(QDir::homePath())).toString(); if(initialPath.isEmpty()) initialPath = QDir::homePath() + "/untitled.xml"; QString filePath = QFileDialog::getSaveFileName(this, tr("Export As"),initialPath); if (!filePath.isEmpty()) object->exportPalette(filePath); } void Editor::importPalette() { QSettings settings("Pencil","Pencil"); QString initialPath = settings.value("lastFilePath", QVariant(QDir::homePath())).toString(); if(initialPath.isEmpty()) initialPath = QDir::homePath() + "/untitled.xml"; QString filePath = QFileDialog::getOpenFileName(this, tr("Import"),initialPath); if (!filePath.isEmpty()) { object->importPalette(filePath); palette->updateList(); } } void Editor::importImage() { importImage("fromDialog"); } void Editor::importImage(QString filePath) { Layer* layer = object->getLayer(currentLayer); if(layer != NULL) { if( layer->type == Layer::BITMAP || layer->type == Layer::VECTOR ) { if(filePath == "fromDialog") { QSettings settings("Pencil","Pencil"); QString initialPath = settings.value("lastImportPath", QVariant(QDir::homePath())).toString(); if(initialPath.isEmpty()) initialPath = QDir::homePath() + "/untitled"; filePath = QFileDialog::getOpenFileName(this, tr("Import image..."),initialPath); if (!filePath.isEmpty()) settings.setValue("lastImportPath", QVariant(filePath)); } if (!filePath.isEmpty()) { backup(); // --- option 1 //((LayerBitmap*)layer)->loadImageAtFrame(filePath, currentFrame); // --- option 2 // TO BE IMPROVED if(layer->type == Layer::BITMAP) { BitmapImage* bitmapImage = ((LayerBitmap*)layer)->getBitmapImageAtFrame(currentFrame); if(bitmapImage == NULL) { addKey(); bitmapImage = ((LayerBitmap*)layer)->getBitmapImageAtFrame(currentFrame); } QImage* importedImage = new QImage(filePath); if(!importedImage->isNull()) { QRect boundaries = importedImage->rect(); //boundaries.moveTopLeft( scribbleArea->getView().inverted().map(QPoint(0,0)) ); boundaries.moveTopLeft( scribbleArea->getCentralPoint().toPoint() - QPoint(boundaries.width()/2, boundaries.height()/2) ); BitmapImage* importedBitmapImage = new BitmapImage(NULL, boundaries, *importedImage); if(scribbleArea->somethingSelected) { QRectF selection = scribbleArea->getSelection(); if( importedImage->width() <= selection.width() && importedImage->height() <= selection.height() ) { importedBitmapImage->boundaries.moveTopLeft( selection.topLeft().toPoint() ); } else { importedBitmapImage->transform( selection.toRect(), true ); } } bitmapImage->paste( importedBitmapImage ); } else { QMessageBox::warning(this, tr("Warning"), tr("This is not a bitmap image that Pencil can read."), QMessageBox::Ok, QMessageBox::Ok); } } if(layer->type == Layer::VECTOR) { VectorImage* vectorImage = ((LayerVector*)layer)->getVectorImageAtFrame(currentFrame); if(vectorImage == NULL) { addKey(); vectorImage = ((LayerVector*)layer)->getVectorImageAtFrame(currentFrame); } VectorImage* importedVectorImage = new VectorImage(NULL); bool ok = importedVectorImage->read(filePath); if(ok) { importedVectorImage->selectAll(); vectorImage->paste( *importedVectorImage ); } else { QMessageBox::warning(this, tr("Warning"), tr("This is not a vector image that Pencil can read."), QMessageBox::Ok, QMessageBox::Ok); } } scribbleArea->updateFrame(); timeLine->updateContent(); } } else { // create a new Bitmap layer ? QMessageBox::warning(this, tr("Warning"), tr("Please select a bitmap or vector layer in order to import images."), QMessageBox::Ok, QMessageBox::Ok); } } } void Editor::importSound() { importSound("fromDialog"); } void Editor::importSound(QString filePath) { Layer* layer = object->getLayer(currentLayer); if(layer != NULL) { if( layer->type == Layer::SOUND) { if(filePath == "fromDialog") { QSettings settings("Pencil","Pencil"); QString initialPath = settings.value("lastImportPath", QVariant(QDir::homePath())).toString(); if(initialPath.isEmpty()) initialPath = QDir::homePath() + "/untitled"; filePath = QFileDialog::getOpenFileName(this, tr("Import sound..."),initialPath); if (!filePath.isEmpty()) settings.setValue("lastImportPath", QVariant(filePath)); } if (!filePath.isEmpty()) { ((LayerSound*)layer)->loadSoundAtFrame(filePath, currentFrame); timeLine->updateContent(); } } else { // create a new Sound layer ? QMessageBox::warning(this, tr("Warning"), tr("Please select a sound layer in order to import sounds."), QMessageBox::Ok, QMessageBox::Ok); } } } void Editor::updateFrame(int frameNumber) { scribbleArea->updateFrame(frameNumber); } void Editor::updateFrameAndVector(int frameNumber) { scribbleArea->updateAllVectorLayersAt(frameNumber); } void Editor::scrubTo(int frameNumber) { int oldFrame = currentFrame; if(frameNumber < 1) frameNumber = 1; currentFrame = frameNumber; //toolSet->setCounter(frameNumber); //timeLine->setCurrentFrame(currentFrame); timeLine->updateFrame(oldFrame); timeLine->updateFrame(currentFrame); scribbleArea->readCanvasFromCache = true; scribbleArea->update(); } void Editor::scrubForward() { scrubTo(currentFrame+1); } void Editor::scrubBackward() { if(currentFrame > 1) scrubTo(currentFrame-1); } /*void Editor::scrubKF() { //timeLine->scrubKF(); } void Editor::scrubKB() { //timeLine->scrubKB(); }*/ void Editor::previousLayer() { currentLayer--; if(currentLayer<0) currentLayer = 0; timeLine->updateContent(); scribbleArea->updateAllFrames(); } void Editor::nextLayer() { currentLayer++; if(currentLayer == object->getLayerCount()) currentLayer = object->getLayerCount()-1; timeLine->updateContent(); scribbleArea->updateAllFrames(); } void Editor::addKey() { addKey(currentLayer, currentFrame); } void Editor::addKey(int layerNumber, int &frameNumber) { Layer* layer = object->getLayer(layerNumber); if(layer != NULL) { if(layer->type == Layer::BITMAP || layer->type == Layer::VECTOR || layer->type == Layer::CAMERA) { bool success = false; if(layer->type == Layer::BITMAP) success = ((LayerBitmap*)layer)->addImageAtFrame(frameNumber); if(layer->type == Layer::VECTOR) success = ((LayerVector*)layer)->addImageAtFrame(frameNumber); if(layer->type == Layer::CAMERA) success = ((LayerCamera*)layer)->addImageAtFrame(frameNumber); if(success) { timeLine->updateContent(); //scribbleArea->addFrame(frameNumber); } else { frameNumber++; addKey(); } } } } void Editor::removeKey() { Layer* layer = object->getLayer(currentLayer); if(layer != NULL) { if(layer->type == Layer::BITMAP) ((LayerBitmap*)layer)->removeImageAtFrame(currentFrame); if(layer->type == Layer::VECTOR) ((LayerVector*)layer)->removeImageAtFrame(currentFrame); if(layer->type == Layer::CAMERA) ((LayerCamera*)layer)->removeImageAtFrame(currentFrame); timeLine->updateContent(); scribbleArea->updateFrame(); } } void Editor::addFrame(int frameNumber) { // adding a frame to the cache frameList << frameNumber; qSort(frameList); scribbleArea->updateFrame(); timeLine->update(); } void Editor::addFrame(int frameNumber1, int frameNumber2) { // adding a range of frames to the cache for(int i=frameNumber1; i<=frameNumber2; i++) { frameList << i; } qSort(frameList); scribbleArea->updateFrame(); timeLine->update(); } void Editor::removeFrame(int frameNumber) { frameList.removeAt( getLastIndexAtFrame(frameNumber) ); scribbleArea->updateFrame(); timeLine->update(); } int Editor::getLastIndexAtFrame(int frameNumber) { int position = -1; int index = -1; for(int i=0; i < frameList.size(); i++) { if(frameList.at(i) > position && frameList.at(i) <= frameNumber) { position = frameList.at(i); index = i; } } return index; } int Editor::getLastFrameAtFrame(int frameNumber) { return frameList.at( getLastIndexAtFrame(frameNumber) ); } void Editor::showPreferences() { preferences->show(); } void Editor::play() { updateMaxFrame(); if(currentFrame > maxFrame) { scrubTo(maxFrame); } else { if(currentFrame == maxFrame) { if( !playing ) { scrubTo(0); } else { if( looping ) { scrubTo(0); } else { startOrStop(); } } } else { startOrStop(); } } } void Editor::startOrStop() { if(!playing) { playing = true; timer->start(); } else { playing = false; timer->stop(); object->stopSoundIfAny(); } } void Editor::playNextFrame() { if(currentFrame < maxFrame) { if(sound) object->playSoundIfAny(currentFrame); scrubForward(); } else { play(); } } void Editor::changeFps(int x) { fps=x; QSettings settings("Pencil","Pencil"); settings.setValue("fps", x); timer->setInterval(1000/fps); } int Editor::getFps() { return fps; } void Editor::setLoop() { if (looping) looping=false; else looping=true; } void Editor::setSound() { if(sound) sound = false; else sound = true; } void Editor::setCurrentLayer(int layerNumber) { currentLayer = layerNumber; timeLine->updateContent(); scribbleArea->updateAllFrames(); } void Editor::switchVisibilityOfLayer(int layerNumber) { Layer* layer = object->getLayer(layerNumber); if(layer != NULL) layer->switchVisibility(); scribbleArea->updateAllFrames(); timeLine->updateContent(); } void Editor::moveLayer(int i, int j) { object->moveLayer(i, j); if(jupdateContent(); scribbleArea->updateAllFrames(); } void Editor::updateMaxFrame() { maxFrame = -1; for(int i=0; i < object->getLayerCount(); i++) { int frameNumber = object->getLayer(i)->getMaxFrame(); if( frameNumber > maxFrame) maxFrame = frameNumber; } } void Editor::dockAllPalettes() { getToolSet()->drawPalette->setFloating(false); getToolSet()->optionPalette->setFloating(false); getToolSet()->displayPalette->setFloating(false); getToolSet()->onionPalette->setFloating(false); getTimeLine()->setFloating(false); getPalette()->setFloating(false); } void Editor::detachAllPalettes() { getToolSet()->drawPalette->setFloating(true); getToolSet()->optionPalette->setFloating(true); getToolSet()->displayPalette->setFloating(true); getToolSet()->onionPalette->setFloating(true); getTimeLine()->setFloating(true); getPalette()->setFloating(true); restorePalettesSettings(false, true, true); } void Editor::restorePalettesSettings(bool restoreFloating, bool restorePosition, bool restoreSize) { QSettings settings("Pencil", "Pencil"); Palette* colourPalette = getPalette(); if(colourPalette != NULL) { QPoint pos = settings.value("colourPalettePosition", QPoint(100, 100)).toPoint(); QSize size = settings.value("colourPaletteSize", QSize(400, 300)).toSize(); bool floating = settings.value("colourPaletteFloating", false).toBool(); if(restoreFloating) colourPalette->setFloating(floating); if(restorePosition) colourPalette->move(pos); if(restoreSize) colourPalette->resize(size); colourPalette->show(); } TimeLine* timelinePalette = getTimeLine(); if(timelinePalette != NULL) { QPoint pos = settings.value("timelinePalettePosition", QPoint(100, 100)).toPoint(); QSize size = settings.value("timelinePaletteSize", QSize(400, 300)).toSize(); bool floating = settings.value("timelinePaletteFloating", false).toBool(); if(restoreFloating) timelinePalette->setFloating(floating); if(restorePosition) timelinePalette->move(pos); if(restoreSize) timelinePalette->resize(size); timelinePalette->show(); } QDockWidget* drawPalette = getToolSet()->drawPalette; if(drawPalette != NULL) { QPoint pos = settings.value("drawPalettePosition", QPoint(100, 100)).toPoint(); QSize size = settings.value("drawPaletteSize", QSize(400, 300)).toSize(); bool floating = settings.value("drawPaletteFloating", false).toBool(); if(restoreFloating) drawPalette->setFloating(floating); if(restorePosition) drawPalette->move(pos); if(restoreSize) drawPalette->resize(size); drawPalette->show(); } QDockWidget* optionPalette = getToolSet()->optionPalette; if(optionPalette != NULL) { QPoint pos = settings.value("optionPalettePosition", QPoint(100, 100)).toPoint(); QSize size = settings.value("optionPaletteSize", QSize(400, 300)).toSize(); bool floating = settings.value("optionPaletteFloating", false).toBool(); if(restoreFloating) optionPalette->setFloating(floating); if(restorePosition) optionPalette->move(pos); if(restoreSize) optionPalette->resize(size); optionPalette->show(); } QDockWidget* displayPalette = getToolSet()->displayPalette; if(optionPalette != NULL) { QPoint pos = settings.value("displayPalettePosition", QPoint(100, 100)).toPoint(); QSize size = settings.value("displayPaletteSize", QSize(400, 300)).toSize(); bool floating = settings.value("displayPaletteFloating", false).toBool(); if(restoreFloating) displayPalette->setFloating(floating); if(restorePosition) displayPalette->move(pos); if(restoreSize) displayPalette->resize(size); displayPalette->show(); } } QDomElement Editor::createDomElement(QDomDocument &doc) { QDomElement tag = doc.createElement("editor"); QDomElement tag1 = doc.createElement("currentLayer"); tag1.setAttribute("value", currentLayer); tag.appendChild(tag1); QDomElement tag2 = doc.createElement("currentFrame"); tag2.setAttribute("value", currentFrame); tag.appendChild(tag2); QDomElement tag3 = doc.createElement("currentView"); QMatrix myView = scribbleArea->getMyView(); tag3.setAttribute("m11", myView.m11()); tag3.setAttribute("m12", myView.m12()); tag3.setAttribute("m21", myView.m21()); tag3.setAttribute("m22", myView.m22()); tag3.setAttribute("dx", myView.dx()); tag3.setAttribute("dy", myView.dy()); tag.appendChild(tag3); return tag; } bool Editor::loadDomElement(QDomElement docElem, QString filePath) { if(docElem.isNull()) return false; QDomNode tag = docElem.firstChild(); while(!tag.isNull()) { QDomElement element = tag.toElement(); // try to convert the node to an element. if(!element.isNull()) { if(element.tagName() == "currentLayer") { currentLayer = element.attribute("value").toInt(); } if(element.tagName() == "currentFrame") { currentFrame = element.attribute("value").toInt(); } if(element.tagName() == "currentView") { qreal m11 = element.attribute("m11").toDouble(); qreal m12 = element.attribute("m12").toDouble(); qreal m21 = element.attribute("m21").toDouble(); qreal m22 = element.attribute("m22").toDouble(); qreal dx = element.attribute("dx").toDouble(); qreal dy = element.attribute("dy").toDouble(); scribbleArea->setMyView( QMatrix(m11,m12,m21,m22,dx,dy) ); } } tag = tag.nextSibling(); } return true; } pencil-0.4.4b/icons/0000755000175000017500000000000010757714700014766 5ustar khashayarkhashayarpencil-0.4.4b/icons/pen.png0000644000175000017500000000130710641754634016261 0ustar khashayarkhashayarPNG  IHDR;mGgAMAOX2tEXtSoftwareAdobe ImageReadyqe<YIDATxb?cL@l dbvRȴą,@5C@3«cp s#ecgg 5,Hj+>b +{)1010ED1bኙ_g0 (0<r/s w㽵P$2<76]AGR,jeM8=ڻ\hG9@1 y~W;N>/R P1WXX 9~IkO3900@!$ĊZ/?{vW_y#:HT= @,HkcQ$fm=e S$@ar4Z:#\~ie8 CՁ3#,14L_c3W.@9O@ мyRBajG:CWA0!@( U H⏐3 8a.fH X s5UzÙ/]R`=IENDB`pencil-0.4.4b/icons/bucket1.png0000644000175000017500000000312010641754634017030 0ustar khashayarkhashayarPNG  IHDRw= pHYs  IDATH}UPu^16~l.QNK"h]i?,^ȫ,(u]?r.SK!`x߻|>#Gdu{gTUUEGsH&SOQEE;D0 pd@AjqKKd+eygfgtM8N\ə()-uǨaplfCyDD̮]qVT~iE4^]⻩磞/}Ruu! , EP|Bm1uZ!SO?lZl^ɣ/nn͑pOFeOEk4GҴTN{o_G/\> R)Q>}{HWZh{?5]H*C9T~j: awC@G8(@d2c"Z 1~Tܸr>B wIS3pVd/YkPw,f_ ͎gPx=r^ a~\p .]pwfΘm +g΢01i-Ake=8/6Z-Μ9#䲲休|Ip #fJD^ػb F/ -0`ckF4,܂9kσi#&4r!'cy Fjjt #FASz}" Bw;$=ei~YyphsI~M 7ym68(),WuLow.wu.(YQqx d*L?y\>7&'MRgm-h՗6UUU]I%Ec0^WNd]ͥly}Io=PM`av6|Q6iNhԣ27 GFDx,v VҶⷚf3q8јG }ư};fia #> .\D|VV#:Z u9)J Qaaa@9`"mWNCӒ驩<*iX Gm|;vwZwyحv8mNt6eXS.N:Z\ 32fBU %"P 2bD_~܂}>Fׇ^ jҟQf1[VV8v예)Zv-dTLH#>&JVDD V4 :z`sXafAm n-X ÿq /~wvY{4Q@ @)CBRAHSϦJ7IB~~~Wd2IL!YIENDB`pencil-0.4.4b/icons/TitleBarNormalButton1.png0000644000175000017500000000047610641754634021641 0ustar khashayarkhashayarPNG  IHDR٬gAMAOX2tEXtSoftwareAdobe ImageReadyqe<IDATxbc @,?&C@STBBMŋ\® ) bUc8[VVM@&//W a<|6"H4eőw܁UTT 4e64[na amX}@Xihh@~|2 1@F7 2Y XO6b LfJeIENDB`pencil-0.4.4b/icons/clear.png0000644000175000017500000000657510641754634016601 0ustar khashayarkhashayarPNG  IHDR(%0` pHYs  gAMA cHRMmsHw2tl IDATxڄ1 0 &=cg< t)`ozC̬c8ιABZZc)e1.IkM9{&v\nꇴ@4$,@ :'to/_{N( (n- ,,,^~߿/ A @u߁4@@rQQ{䮇RHvvY"4GLL47,.@t?|t!OT3Uu} JN=xr &1-B::C\; .7+8:^B.GjFteTua&PJi*S. ^E1$9R:rή:T}~avWB )IgR;6A%6 ;vf:illc2Xz3&S)ŅTTkUA] x&9&UJI3={x;i2/d CLp%P[r8&C$a" G*Q_S0Eu&M.^S0}@"d]KqlNJ~^N& aSkMc 3^k;_ ULnx}BHg5ciC; !@zBc-%Z-P>IL[wP)3C"*AÉ7n,_v|4 !/ƻ 5#4@!D7,fMMM;D!$`m{# w&Ld)="08062=[W @(hDtI-D_gQ*^V3̰d-+?( ajT ުjzdۃY+S T^@&@OhKgo6UM)Zh Y;_P+bt 3vNho@WĉЍ4}wr_pWU͚ ix~fzkGsq5^1'˰faf`-z>]s \:^[eQA@/uHI4^U/X>}o`  e&NFX ˩ G A>YL` ,t@9 !X:hy|?0NNN9@(D˴.-u/ og3+vü dǏ2RO\g(USQU@H=q@cO عw?# 60y=S$@$C[ZE P*VXLu ZeW:h9v P#̐b6T< 9 Xã: A0E!q Qccc`= <(#2(Į= PtUpug(6u5WQ] @ S([+oE8A?C~ލA6"Cx8ca#G0(>@Y=Ǧ,f(L|=;2)!|* A205I4 `ƻI  9}D:P[`G,9$ EXx@%A9,i W:P @(`(x'w]Ҽ(g&m3Ƚa|uvV0Gkn| ]k!423@S0P yc̸p-,ʣ.N :p8f%pׅ! @s0THLd 0{HűNV'M/e( H@%TTu=l3z\AlRY&N @s@\/pM2KK/7^y3Hڕ-rݐ% 4WNgUΚ*<.1;yIƍBbI'@G~b1PsPZTZ)aX( !Ѡt RdddQ a 9h7Pks@={0 = X; \FPP(@i (PT*uXcZ >5g@rV3m5(`$ ? @Hb :@ u;A۰(I?(t@E%cv5pPQQ4UW@}OVegPqh3iB洀 5"1( gX%Mvp ǁ<Jϟg}6 4=@r' `5?*ssL(d@%vPhB0PT)tx:{ ؁2:ԎĂTM}V5Wo %vP**@! s J_v(ASPRy  Jw `z~L.Gq؆>@`ЃF>/miō(hh*ZXNE'q B VCB-j09LBF  @_C jK5X:oaZRPHP8@xи Ь@uA<`9*:06~< F|ム!`-)}`8-2&he` g XFk`4_P0;hT hhp w?n#L] ĢP: ,!"*Lf<:2X.0@CbZf J4"=` ڊk o޼KX;!|f `@v...p PL`h mll2 P 3 ,3 X?B3# pʚ2IENDB`pencil-0.4.4b/icons/controls/0000755000175000017500000000000010757714700016631 5ustar khashayarkhashayarpencil-0.4.4b/icons/controls/sound.png0000644000175000017500000000040710642631117020461 0ustar khashayarkhashayarPNG  IHDR _ pHYs  gAMA cHRMmsHw2tl }IDATxb?63 &l0M @Lhdb &2@uDFdN dSH (b 8fb"&i0p]4!CIENDB`pencil-0.4.4b/icons/controls/play.png0000644000175000017500000000046010642631117020275 0ustar khashayarkhashayarPNG  IHDRa pHYs  gAMA cHRMmsHw2tl IDATxb?% )5 (6 0 HOO ̜9FF @X 1 @AD  f@1ud a^jD6c68)ř IENDB`pencil-0.4.4b/icons/controls/separator.png0000644000175000017500000000244110642631117021331 0ustar khashayarkhashayarPNG  IHDR%`gAMAOX2tEXtSoftwareAdobe ImageReadyqe<IDATxbd``hll0bee`dd?l;w bccLW{ٳLLL~ HKGpà43 ukʕq>}qB eq߿ߪpr @p?%$$&!@P?`~:uꦕ[JQ (vC?Tw@1cDRVRYY^ =Cׯf:  1!3`()޽>| SaĄG7C޽{gBBB[@5F`1B5G3`iݻ}vRCC XT8~q0LLLZQ@dD5ׯttt򖋊^G_| ,dRDBHr?~M@5iI0/ f238 l@Q`*@Є'O Y@v8qLHE )(J@VLã̑.\Ґ f 6Þ ,ˮ@0a;L;b N9?@[#Տ-  g"7 9^imm?; Bbf`ևLR*Vׁ+W$0VH19 @Gƞ0L޼y JK`J/uҥ rqq[DjA͛_6`tfI j9 VD~MA@v<%_L }~ωu@1Q!(+"b"(ԝR &*J9l۶mk%=lmhGHgD胧1`w7Xiii,͟MDIENDB`pencil-0.4.4b/icons/controls/loop.png0000644000175000017500000000022610642631117020301 0ustar khashayarkhashayarPNG  IHDR Vu\]IDAT(Q C[!s5o[hJC=(XLfTX(c8Ӂdm N~C}9߶?i!HDY"9A9aIENDB`pencil-0.4.4b/icons/outlines5.png0000644000175000017500000000072610641754634017432 0ustar khashayarkhashayarPNG  IHDRagAMAOX2tEXtSoftwareAdobe ImageReadyqe<hIDATxb7 m D-c uuW? U;g'T(C5 I!4@1j. @LX,C1f &ߺ|A ]N]rW.gꖞc<]@(?! 0e@1!kb8sF&&d %Uf@1h>r9,C# =!Ąl333cl/./c@}k8{W#eV >YY;ĨaOܚowP. _~+IENDB`pencil-0.4.4b/icons/thinlines5.png0000644000175000017500000000052510641754634017562 0ustar khashayarkhashayarPNG  IHDRh6gAMAOX2tEXtSoftwareAdobe ImageReadyqe<IDATxb<qէw &U{ &U$@@L$b"I5I kش~ I O^#e,BpL?GA iq9%EѣG>3q%5Ndec7BhiGqW%T@1Bp 1 ˙_޿%hV213iĮ _\11IENDB`pencil-0.4.4b/icons/bucketTool.png0000644000175000017500000000256510646454406017620 0ustar khashayarkhashayarPNG  IHDR gAMAOX2tEXtSoftwareAdobe ImageReadyqe<IDATxbܵk0222[g޽ʕ'zӧ `yfff޻w.wN,>>> <3˗^pȑdYYٿ &&[ N?vrrrFF,ޮe KKĶO6Ԍ}]މ'by6׹EEE `W2IHHboÇ _~eDh߿54?ҥ&i `Cà0ݍ5yy7+.]wq={8CBB<b ߿a 1PMAKCw׮=yĮw[ 􎬉3aAǏ o߾e}6'ّGEۨ6|`#**ʰi&&K~A|5KeS=z&))  @d(A `hPK0,\ ف˗ %%% yl 0':1qqCbRUU= L (#ԩS1spo۶ l@P$0/_20+ 3 @1'8555˗3ܸqΝ; ɁM`f߿30P-zCP())12lݺALLٳg@eO> Sa s/2'@x{{ $(m`jj f4 <0?ϟ`8x(/o{zx(eM{?`48@ d; Wop]|<~rFٳ ۷}m+WDDDm޼Ik@޻z;]r$ K/061 (A=,<|eˀ>3ffz0"'~yh(WC@Ĭv |z(&*zt^WTfvG޾y{HWG;YJJ 6( "D< r@1LFq׭2&qq^nn3dΝ;i۠d@07oXsƆxgG;7$@ - 0AAA΅ !}|_|b`ceee`] ňɺRBMIENDB`pencil-0.4.4b/icons/hand.png0000644000175000017500000000160610641754634016413 0ustar khashayarkhashayarPNG  IHDR;mG pHYs  gAMA cHRMmsHw2tl IDATxbd@ TuuF =?1ڵٮgϟ?䴡 `HǏϟ?//00ŋA  &)`ATTӧOp;^xW[3MMMπB ;'O߿`_[XXo޼occǎO> *IbA PΧOMdddd@0hÇ @(| fe k! L4Y[[ٿ˃@`( X N&h4o+/]"v7}@."3̄`f`rJ m@N ,..gfffPVVfr Ù3g,--A@ B l;g߻wիW:uu @arUJQQد@(vh@̠Ǘ Aׯ_^a k׮y R^yt20 X f0WČ={vPc8`hKfΜp%+@w-[Rp&66k4Ã^~̀ -#|Aùs 0@8p6`0/OƿwIENDB`pencil-0.4.4b/icons/eraser.png0000644000175000017500000000221010641754634016752 0ustar khashayarkhashayarPNG  IHDRٱ\gAMAOX2tEXtSoftwareAdobe ImageReadyqe<IDATxb``da 30 W`efqg`@ fF&@wx;7302 V @_AY sMa/_\KoZ@ BkN6TI19^=0X/098$%y3 R(ܼvvv>}ffϦ ҧN1 geꁺ kqq?_0|zU=bMGf&&D0ɓ @@W׮1תX*O ^^k׮{3  @̌Avco3xӽ{((#"#988$t ߿1 6e1<ܶ۷ gccwu9a&0۷;;5zd@FE_~e t!;08Dnd|{Sw^r @,׏Abde & իW` .!?^t6 /uu?Еǐ}@ݽg>??w_|Q/;;;O>1?ٳg`>~ǏEut>|D`˖-{{{o?y(ׯ_ĔZV23aJ5@'lMpIENDB`pencil-0.4.4b/icons/thinlines4.png0000644000175000017500000000052610641754634017562 0ustar khashayarkhashayarPNG  IHDRh6gAMAOX2tEXtSoftwareAdobe ImageReadyqe<IDATxb2q˗on &T߾ d $@@L$b"I5I kXvm) hxȿ.X t gN2VĪ cb<~F]J a;w럾}G5ԆM۶#ʊ?f ˲I|LP5NO$%JW8s柿T iz 7IENDB`pencil-0.4.4b/icons/move.png0000644000175000017500000000044610641754634016450 0ustar khashayarkhashayarPNG  IHDRFgAMAOX2tEXtSoftwareAdobe ImageReadyqe<IDATxb`*I> ‡C5o C57@1!x&[1p{8Sc Cd3 13 ^ d] ^ 6x`bA ġlDz @ \ A5_¥ d\ )0&*FIENDB`pencil-0.4.4b/icons/eraser1.png0000644000175000017500000000676610641754634017057 0ustar khashayarkhashayarPNG  IHDRu pHYs   OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3-gAMA|Q cHRMz%u0`:o_FIDATxL1 L m$-7Rff*6.bĪ޽{a`02b`x?6 dA0R ՀD``'aytⱟL2Kh-^Ss ޹؆[%dkd 0C5)34Y2@!NQ y| $4|1 Kh~Fp$#7Zrθ;I/? 15 iirWˆ( f xjPڳ12b8;{6̙,PajVRbX-(0Y&祡DAAAիW#9Di& [h 0D bQH+ɖ&ޮn Y{yՂ4oC~q~ 뀛)guokwm@44E3f\뜋<4:~RJ-(Qefz 73 1U[ +K^S_wVa) X %$B$ @HT#qאB @.oՇ7xf\uW7Мsq`s.R"L8"p=hK0*0yl, 9t6rH^'6ޯ=%W2+imQ"RH0wl/wH!D fOl9A c 0h J8( Vu@1Qy @Lhf @LhbD3%A 2yΝsqibĕtvu#P$NK &''Wuwϔ]92)ܼJMJ` ve޽w@BPKB!^^fblbض~Bf onW}"H[tڵ L1=kIENDB`pencil-0.4.4b/icons/layer-bitmap.png0000644000175000017500000000161010646534551020061 0ustar khashayarkhashayarPNG  IHDRDbgAMAOX2tEXtSoftwareAdobe ImageReadyqe<IDATxlʡ 0$EٌH@ HD3]d& by%;.oo߾1|ӧ =^^^ 333 fddׯ_]㳱]r$@Djw0|A  cf uuu`D\0} aP>{!,, }qqq>>>+V a|2.ݿaʔ)`4KHH0HII1˃-#@ 2 FFF BBB ׯv2&OOO?2<|AXXl_w1ݷחǏ`E W^QVVǪ*8VZwW]@`@il޽ FF \\ ~bXrennnpTPP`ؾ};07CBB (pH5 $ |DF1O- U̠]dy"3NN6 d1)CNNñc/_P[[ ?~Հٳ`,G,0H!#TzH % QQQpX*))1ʂ Y&A 0"=(\i*Pl ? x!3f0>&@I^k 4V̠t @ gH5IENDB`pencil-0.4.4b/icons/outlines3.png0000644000175000017500000000031410641754634017421 0ustar khashayarkhashayarPNG  IHDRagAMAOX2tEXtSoftwareAdobe ImageReadyqe<^IDATxbd @Q9 5ŚbDfX3@Q ( @k 5ŚbDfX3@1P 4]/)+IENDB`pencil-0.4.4b/icons/pencil3.png0000644000175000017500000000135610641754634017040 0ustar khashayarkhashayarPNG  IHDRVΎW pHYs  IDAT8]HSa{ TpXdZ1FB 0% kވtM""I7$VP^T A )1H}(yv.bJyS /P99,kIL ]]H &m732g; ^x`h䙋2]ZB|f09= Is7?qcYe`#3Ά{>/dDcn,Di+躎Y@Im,WHt j4Q#`ebBWUuRUUuRJv]m;᥏h $IA^pP#8Z@=qIB<.77wnF2ZׁhpRZW^U9BȠ`֝NHLt- 5 qFi6!,VJP^sS1g8͈ kjFu]4mH/fY!˥m?[y利!g.py84'j=-!ƥc/MhG0b8F{"@l6+0fռ&4+0S)))ǭDCPJc<gYve٘f\./$YRxRv%QDC:TIENDB`pencil-0.4.4b/icons/bucket.png0000644000175000017500000000356410641754634016763 0ustar khashayarkhashayarPNG  IHDR KgAMAOX2tEXtSoftwareAdobe ImageReadyqe<IDATxbܵk:`ddd޽{O+++O~ӧOxyy̼w]v}W]<Y|||p31!!`&&&wUY_|YаYFFf3;;;#'R߿ell'-+˰}򳃃r d@XZZbhӧ 555c8q"7o_~+(([TTĠ֣XRZ&!!q軥߾}c >W/_]m_6u ϟ/tr kzzzMRR~ KA4(`@ CahPI0,\ `]L /_d())aE,ȫlll `A| ?V'&.n@L QUU0yǏNL ϟ?Gضm E ,+00Ç߿48\\\`򂂂`@ d (H` p͟r \LSIIAWWa֭ bbbkeO> A_dxObc` +@,J޶u) J밌 \/>۞9r ")((hڼ<9ٙ@Ihh(8lA;(M p2{w~KP 7~v/r +@ A409mۺW32K9pɃ00{995v~k/0>|훷tu$ @L% @,`W  "-a?~l024>@a'K+AYy܏>ܼq/_9l,M4 ?}_?Y8$%$}nnp; 0zpd/_',,Ĵlv!`ؚ[=w/?1}w o>|Y/_>}fce".&zX\@4p5F % * "L f'|gxcx ã{7]>Π($谭 ]V^1 <<Y~ï?? XY9Xظٸtx N9 bzpi?K  0H2r1p2 & fdÏ_I'0~bx%Oؗ_޽yׇg_e9.;:;Oe,bb)#.7}Z5u &/WВˏgObaabbE0;Xdosn,L e ]|]7IENDB`pencil-0.4.4b/icons/eraser2.png0000644000175000017500000000114510641754634017042 0ustar khashayarkhashayarPNG  IHDR& pHYs  gAMA cHRMmsHw2tl IDATxb?-#+~3R@,qtZ>Gt&TzLl -c)!ٖi)^ɖa)Nі,}3/RSpAˑ-Ro߿_r &|0R fZ bȲUL H _ez, Pf)rEk@VEK>bb\!SdY0@}TYL!ͧ}j\_PP!JJJ wo}X n0ˉq={ծyʄRl5@, ;W( [ h8h9e)G$R x>'իWSR pXL0@ @AMmKa 0pPҕZ J9`e 6|o}NL`tP4IENDB`pencil-0.4.4b/icons/pen0.png0000644000175000017500000000112410641754634016336 0ustar khashayarkhashayarPNG  IHDR  VgAMAOX2tEXtSoftwareAdobe ImageReadyqe<IDATxb?:6 NM WE-Z] 0y} +nBb n/ vB1 PSO!,"a´(&\@V5Q`xaMpxӭ (&ed1tMX 7 ps2H ]L8CG-n#.FIUZjquG0&=d`me@ M_}ћ/M{0ژyz! g/^/k0w 7 A1BL >%# b(2+ L@&@(-$g7?ŜT;]s((9TUE8HM׉킹OV,"˲."$u]vXVNSPH*;ڞ+FG{?ZZTl5YQSa,sWA0cFRU~b% ~,!4 `1FAشX,?Mt8{b{ 3iCCPICC ProfilexgXCA@DAXwWK.[`-.KĆQcKT"`A)jl+b=bE 0K{˙yN9z;ϐoJ\|EQp+.{EDUpɊg|}lJ=hh" hh (`)DT_@5*:e3@UK TW'W0"@U\||dDE{?p ~g Cj,PA Z,{ ߕHzLU2@6p4%K/h|gi%@UOرzf:F榔 &--,llmlk]\]'M>??0 (pڴаHjdTTttLllq 񉉉g$Ϝ9kr`0 +55INO={?L@(DYYbMvvNvnn^^޻9ϛ7_f .\d?dҥ˖˗XrUG^O?fڵ֭[~Æ7ݴi-[~Ttm۶o/3*+;MwekWUUuo55mv޳g}I r;t?8~ѣǎ:~ĉf?<SO :ssZBZZΟom~_]xzW\zڵoݸq[oIsݿwmV[<|O?}?Ϟ=Ew˗==_yw(J*54FСꌣR MM053hnaniaemmcceunnSN8-888$844,,%<<""JFQcbbNOHHL0oR:`2Y,T҈ٳ389nP(Dbq87'GD~A9R'qBDK-:rUR'4׬YVƍp|Ί vUUU[TWňuuu '<8ć'Ohj̆3g={\KaC\jB߰E׀o߾{D I=@Ok>bh`d8x6c L-,,mlmm\\&Mr:mTwwOOO/oo/___?_SAA>GDD\Rc||g BRRtd>bRStFpՈLKP$z-gg'//?`NRy>/Ze> kKkė6:߆swܿ_Z]M8rCj@]҂ȋ?_ |K@:@5 @DBĻ6׆}?5B d YAP2F@]P`k~E<(Jb7ʄLЈ1ⵌ CXT涬L959G"M "m V;Q+Q(~E9@JU UUۨ׏٪9jhͪ>hj7ζގ0P3h1t1=glkcZ8Lݼrb4K=[mrmc5{868dNJr {(bN`EGUE7ǴJ=h feBkXfL#aKs:ot>P(fn5_bxyU?=\ІMT*MVveGdyk5<\P#w6y59\bbMWu(v[rw=}-~ᙸӹƞ޽^w?0?H'Cà Uh@ ` RB)cG2A!#%&c!'^,!(/W$"?N/Qʜ$~?#<@\[x7I\?@͠<:B3us-,N9|͌ʳӫû3^vmg+2:*9VONHN)"y?00ym`{bVK,R*a.>xك+W0\ֶ eWvDV ^[XPcC5;kuv7~c}IY +e!?>^uBp/oDsu؂o|qQs3e̸}cV2nfCM&$y=&U1xZ69SG?C , L1!g&{ܡ9"s4ŋ`R|x~)q֖{[['/往L6 IDATxy|\W}7=wII,ɖvlg'NBHHB-Ky K}^ oKKY(-KiBiB[ @BH!+8/mZgF39g̝,gu}?ϙ;wrt;I,tEElj(ϻOJӿؑ{gY۲-lkk,˲T*뺦iK} aqUx;ah^Z,Pl{E醁w-UZ' "B6رcn Y_ ݙVBHSNecy7u-[쥝K3cHpU~gvqp]]֟Sb08n rx3\ɦ_o{7Hb'.Yk7<~Owo{~~KE8maY[ڶm.`F>?)g˲f'v.Dȶ\A ko|Ǖk6ڧ"9MMy_?w~ɔ~61̮^ɵZV~lB~T.j%'"!{v[)ũ&:vO&^ N9PT/?t/~M[SY3񎷾>zRhώ'NEz] Ӱ kGXdZm'Z[[Nv- }[Us5MuN`]Fb彿~Wx*!DaSFϖM$w~^z wMqj,IT)쀫,ss9 펁;_LOOS]6Zg2uFɧ5M5OGۖ gH_M !"8wf"CXЖcǎ}cLGooHiH>eAyy~QEQTUTKK{gg9}>k !I|}φnmݬZͳMGżK4t:eFk[ s|s; S51:^J|, ڞ7_bŪۯVÒu]ML&JYeXi*0(Q\nX8O)#iUלy鶿xF) NwJH+Ϛ'n>}{~_筝M0 #i,;i1 4 -8ϋ{o9X%;xzM8μx0o`N۷cؒ%K?4 3dKK2I*B) 0A:#hiF2ٸ-W_Wj0AM3ݻzjjjJ-o4"x+uc°doүYid2-mmhkv4|Q8Bм@LK@q|6VTǫXa޳g5k#ZN۩mYQD((-!qJk*0!nXV"n-k.v?^#K;+h3yզ"a.K~\ [~՝*wO~S_~G?u$[Zl6Lڪz^AU~躾㸜1BEUU-HtlyͅÝN3m0g d/Pe2J]YGAVƇQq2y o*c$p aV >ë~+n{|˖m{~TTƠiB(e\EuT*A8☦˯ѽ9,Ax :Qqȑ bK r5+Qey>apZcEDX޲,ǩov `സ0/Dh^[b^U~O~uSSoL˗wy[^fZ2TUub2ߏӴ׮ݰ] 񃃏oA3-Vβ 7=@Bֱ^mrs]z-ۚyU{nwsѾ]䤿's~˓In(/{UU]޷nuSKm'hTK20D \B#s]~=[ W庭GlFx]Y&G,0 frE$fnO~_?[tͺ>샟#?_Yxm)qe)rT8rY"lUysM9oewl%n"tv~0b6҅?9 5͘q5 ϰ燽z.;_}[qT6=SS Ol^n~8>>JYɤ5E^ŃMXQ.4f|*OAQ7)/ժ;t=Ȧ :AȬui!uQD0c j0 җ>O ';::>"L<}ﹺyѧ~~ztd":22|x4es'F)=>o41æWzzE1M8Nlu խ%N*T4 Ps~׿>7LR¼ H^FF~7-7":9q9Ŧpܺ+|_woe˜2Ͱ>E##w#rhB@Cn3ZN|/?12r"-l9ax|Jk׎1Ӂh"1YrTF~h*UU(k^1["O1"n9% e~:6E8S&.!ri¶,e~ >! e޺4LtcKxEJ]qޯ'k1W| mB|TppJ=NLڰ[~(Çy{ PehhhtttzzXG4-b!>,+4N?!.fg˕ f?~Pݹ/-|>/Lz2i4T%k[,ſ?կk6>t=4@QqEzN܏@y  x4"p+p(T*;w>PJyر#˹aJD9McA6<&9zg*P8v3L5>H푗2"O\|1Y䊉+Ftc&cdu_W~;7$( tca'0 BPÆJ`$H(  draG?'>q=(>s'ۧ5MT*dQh&:.6 R*C-dJ-ρ+TCMmAJysWCU~m2txf|Q?essΈҾ=C ;@ũ^[աUFfZwjH]du) dCs;==o}sϞoAoEt?z?F@p><TՄi242QBk'Qw!??}K6H(R*4L nje.[R帎Sq )^_s`?PUa1_iœ#])sLOx9XFqmkrq\k& 6+_n/>9oCgbɷHr=َBqJ"ӁLR0 .& nLBQuKZ ÇB/0 EIӅBn@;P8y{Bxv.oGQuygBo&vYqVUe<2,]] pGccW-<ߨ*<暚^91MG DkmZr;J3+:x*Exg>ݻD,S ҊgnʼnGBI-Ab;`$hp1SDy ECm]0,&E)cȏ7O]uF9~\O&aAP.d:6ScOګ!IQ.iEޟ\|.Rw6KBVrLm ;I%}\ܱ#:oStJ)"<78)O"W.Nw ^Cw 4*̞WRoBmc(go53&[oرo_?={蹀䞀wvX) &Ai9!T B Ih1qpˠtCż2ַ-JDBr9Ƙat:LXBӴbn+ jdo{)*V ^mxS"P BP)FPUhmE00GwU B]3ÕXcSZj?!2==j*TU0|>#M w~g0iu‡=Ϸec(aisEeԋ1i6Ф|Uǝwdl*oObfJc: !Ƕm/8C=Eeshg<ԥunޑu)Skkˊ>mL:8{ǝ\|l.wWºz*w= *9XIE\RD Jj> T0̑xW,N.$įs?E )*pģPq,H IDATEmǦֻ\!IݺهODM784mR??6__UK@wv[*2 =eT|I>Yf YPuD.ӆFГ0Lu#Njm$4T&a)Kǘ ^Mjzzzjj<5{ߺ~z~\Fͅ˷6jEQ[5i16U eYv4h@-;vD6v,Fu;oɮLhuơis&U,sܷ&/o]Ϛm[Sqq*1YϿR2ct]ɝ(WUUPT(*fB(ȇBhD*8V%;I+EQH!4uu-I$ܩeO?=66vEmܸ% I5B6/ڮ/u9xXr@6cus\Owc2 4i-I@ӿb qcقEuQexĩLqW61ߌ٥Ӱ-ܒmo=­ĴTUKQ-E%4¢ *6#Pad0TT--3(@¯R&4Vt ?:%pwM n*SlRq(7n4 cǎ{ݺu֭[cT䂗TnpJ xvRw^%ήdz2a71"Bi"[~\qC+o/)EN\m,5q*$ E`C%g{3XRK{k g9mEy?m|庙Tڪnfhift=i7?̞*8STX)cagy8%F* '8,RL7O=x`R'X0(DQT0-zi2]דd2ݿ-[.B[QVV@Lg{'ډypI-iߴJ+ks^AlbI:nOoYr:"P@z{ rEL|~Xj5]+tjT8C8œrpv\ p8ؿytj醪ak:QuB4iD5PTˆdYo#ߥ{WSt^(!Mh|I'Tv 4SGG2dVC2^Hb2V'UuST6;֭[uVCN]mL>ձ0GQdv>_u᠟,7(I^ 4[݅c~O8g,oW{דd/2Ȁ3U lGS%ٕ / [XOX> GG(.-;e)JD?d?SqZZS w~`ǎ9Z芪+ *e  h!GF^κ/N<g!)CQᔠi\0m$SP h:@`%=c-mos6+"4Z-FiGGǑ#G~ӟ^r%g}6wp+)g)gl⼍0Q/,uA\c$ :=]ll̠kǡ>Ɵ_],mFveMKd?+oo}ڇa<ftOqd\<7 CVy{Mt{-nh ` 1AUT1%Qfl7)'P. EnÆV  ˆ>j2VrA9m0*EjWIj=~tOO=s饗nڴ" +120 0eB=>>|aLB*bII,Yq*+Yoʨ+Cg: F`^[bft\v-(URGU'Z=e-9:|12x?69>WFCU^5^{DVU-# *@( , EQTBtU"B|5d Qv+["ha4(aDǏt'xA3MXPHH}5*SaD;XXf=%={Mo:3TPa2 oyC6S5`<_"BR=χwr+)4Y|spj4 n=l k<,,;˫X091veͫzc7#2.iNW.ͫvb*ܶ]-2Z:܎#Zݻ^!*/XAª "ʨy)D#DeJ EQQ/} GHG7T~!,idQwȎBfɀ6*nL%rѣjbȴRd+XblUjTɲ7LI1_Y4PSy$u%OO񍛆J܍6:'hQ( X ! \ln,v@#sq*f94&/~Ng(')@/~B@ yeJC0 1FZj!8f'aXihF0w#IZ,tʃj|WSR0R)fjf||d"x[ߺj*M8'c?&KY[yHD⮄l6N+򄫣Rw<ս>9~!,+Q; Ec !:f_qHaB9于:.!IvGjOw ȴf@id0hetRyStM/]qŋQsZYynN) 9oՑwo8c{v[itnT>{9D]v u\gPb<4Nm7prnDq3=V_:9רmm3.!:qe!QDYDi@C7 eEaaaHzQщ&e1Q{: S- V:J*t ْ0t)L9LOM׷(I|Bx˽ArA,B}*͆Q6TXVܡ-T!Xe #шҐRE,) >V ؎ŊN@C$tJLZy mWMrm.5K1m,p%tE{ސ>![(/Ûbu]VV$<`| -z+!bV$zk")E\zYAm:}p-?;UT P/sh.ED"?A4)F! 0"PQ@ !aeh`v*%_NN`zEIbI4pj}o2 C0-[ePE ̂'aÌf_sCXƉmtϸg)ɍ` I~osu&k]rTdrDps 002QGӡW€QF>J#QUךRBJ#JYD0rR !HDNJ.FVRw''VbӣScS>umKOi}78{5M3M/&dV+ڪ*(f(و u 2TT'jmm^Pï?/u6gs4{fY]ޚQnE @|m'ej,wr9^c#MEG܌QPo `8FjdDD[<.bK<ӡq(tj2JiУA% *QE|W 0ADaza! 4[< ÈF4#1N eJ(<[Y{ǕpU)R:Zn9/d2z-zTQ˲t]'ضiY$,KUU^"V ÐYtGPs:eǦg2!\hH s!?K ]s(~[,Ny︳fx裏v^w^.+W]Y V$cverqi>/>ek5\JeMiFf[nKfy# o+_w~:esOD( (B? .`) iȏҐ, ȋ/0N~s0 )hDY!afR0"_p?Bm5V @4˲5MSUU4!k܂\ZŅiQZ1S1\n &fĐmir;Z%XHD'xTeoyvA^gCF:7,@(sCr~ھ\zpyj}KVo4 a8kuh7Xc||'|[.7XD 0pХg(4.4C?~! (b" h~^zQ2Ƴ(Tӕ$s?Jka^m[bᎴ ]t^̭BڶwڶD7WCE–7 -u3!u#Ϫc@ʖKP[yAH|~Oqhqv5ck9/j~83T!8gIxjSq̖5Zk۪K5y# \؊?uJBF`Fn4iRȥÕ0Y0 s}0 ,EEQh5ш )PkQɶlGv"HLBcM?=/袋8dOu۶yAM sE+ןz_|!lu Rfg|+tԍ-d31@d\LqJ1rƍI4VI}?v_+z|-:l|R3>5+ш*uk?\_&nC}bmwzb1~E-pq񭘛ӄASOxUo\_'У&& Q(ªn8_v|z^XU ox>'7{;/M('= #XzS=/F 1U)-&5EI ݨR7}拯9s9SHZiriiZ"a㟵Q<+q]7t[oQpAQsr3qɏ?X97sѢeUlXf͖K-;ku+ߞm®+f4Xoz Ꙃc eP++8Rq \r}}WNũ㭤f7 ͑+tLf3Jq>KKIDATl_{Wnxv&ӚH${zs+xiYWx1 }s=w0 C\T*D,P@U($FdzXyyە˗/o4Jqwضͥn"్DBb 43>¬C6ӌeqlnbq >}lt|F+W` Iŝfx7'|6]'6o<ε};dF k[S6oFjl\knC-":cxyƪ-#[Y9Nؿ_o">vNb\LahvBA:<G>w>4ر hb<TYs{3]7\=rC}v緅ahO}i:}QDX5Xs Jit8>sGyUoY+b˥\=!drʏ{c-o6yGW̼Jcc㍇cc?w0$t:4C\.Ey/Yc"\k CC|siYձk8.H^d#3qN5<[nawRi0p'=`< ÏL|ǣa@0Qh5ւ(PFZ>HQV [ϧ}]hQ,(V"V.+bɤ~]sHыGt"CHSv¾x%yOq+WW]ڄj3^ux~"wR1X#d+\DMGug\4%\.w}\0Çw~LNN& (c3 X-EEט#xnO7\{iWM~DZnLkU/䤂ų/p33K!v~\pˏ4Mé8yr߽MCy"oRq劾ֶ ^~p\ [d$0tN-/m='-o8p`llwեR{ڵk#<˲|v?sdHsZ׌jyѿ;*^}͛z{{2Z}dޖiB! =<\87NZS#-ڴy=rnoT7TO?۲~~aiԯ:xUsMw裏LO=o0={:ʠ*V6R"LEcCO=rpp̴߽.]ׅUHK}r<_ēh>mߟ˹'F`j<O?moOn_ H,;:xunCW^yU*yo3g;:xnykoM]{앯fdSr(*O 0ȕNqݻwBɱ9x #GG=?M氭:' ŝ{{ё*loO6eYv+d.|K([11=ο=U<7R]Xg'N(S:5eSq~׬Ys!oeyͶ LM䃝 a|Ztd42;,o!is(_4~馛ReYRoȖx`d\MK*qS j-yc}/{Kr+X5r$fQMAQm8, 8>AVZS[nivƍ>$u&RbKm<׋nڠ.4/d$A,ȥ rb& _~|; imuUOŨO-^pn /Eljj߷뺮ܽ{N/]<ɸ4ҘՑ(\p JKIh?w+Lj&UbMYm,̿ot[VqN9q&~FV:6ۆzZ`t_Mӥ͝[pTot]BX͛U< 3LU I 8J2:P"NA]cp{'˜Z$;^NlǒB;x# V:ADmzF-!?wԮoߎ### ӱRynLmx紒yäoyP/[h[6?IaƄU*8iyM$~Ғ:rk* -xQ!1Z5HV3[dk4IBUtཟfVSa휁x>jϟgϞ߹s'E"@ pttTU{tt,H\p fp$W>\IrTo=pj"<'B{N67};o DHb)ү[3K>^q,arV%!+E ut/ՒDp>a`{/8Sbd&~ 4<~-jnV[qIc9Bcz*د iW.:&.s`ViֽFGtaJe)M+.u4pEN"?inEo >Q_/KXǸ^JQMӞ}6PMssccppP)q!R2wX=\__V$$iY^%S2X=>>Ul\. ,)xje<nmoEBaoooVgQꈷ2Vׯqo)]\\\&i^5p={688]2\.ƍPȃH?y8NJ!И&JJv!E:ߺ_ o|=ꀊ֯"=4MQ :{2kkXDFӴIeR/KKtzuzKFkqa__GJZ,=VU5}姧p8K^*DY>qQqRL$KAD Q9 R ~&غY%CQc%'z@0Zux* ctr򎪪ҰBP[pMӬTl;!ߡ)/zS!E,NlmhRjiR"z $3(|~-krj* :?mJB޲I{)t]㧱qplK=_y(^{@*ʅF-͓0lԯW nQ?]e\RnP mUX,MV%ò1YCCAyz~u]"QHGA˲Nc@Ȇd^Kً8&4"Ek J6U\]"^%+W7o2B۶<MWJ>禦5`6d^?}Y"*10aHlinDDsy|).p8*8#vޡ 9g@t]s?d^C=C;25=ܷuMq!Z0nYS1޽KT cTJΡėTUHR\X095JjPϭ1>>J?6EKp8d16Db&zDb!U*&╊@/Jt!}1zlAƒ g@ݻՊ$@!z5C~2+>+^b*Uaoєώ|D n]tqq C]tw@]tq%ѥn]\ID.Y.? (k)IENDB`pencil-0.4.4b/icons/thinlines.png0000644000175000017500000000055210641754634017475 0ustar khashayarkhashayarPNG  IHDRh6gAMAOX2tEXtSoftwareAdobe ImageReadyqe<IDATxb|z)AÏ@@T$J?|) fUCB@7W^Ib"`j  &T@aѰjRd@@޼׻h@1"ã>Ȉ3ņ~qj  epeW-3HX7׷n0xjLp"h<Hן۶0lo: D_XsIENDB`pencil-0.4.4b/icons/aqua.png0000644000175000017500000000043610644055565016430 0ustar khashayarkhashayarPNG  IHDR8@; gAMAOX2tEXtSoftwareAdobe ImageReadyqe<IDATxb˿@,?fddby ˗b` 312A83 Xg @,7߲ ;@,p@p39ō Xx9ba@p  @1np5@1nn+@(*".7IENDB`pencil-0.4.4b/icons/pencil.png0000644000175000017500000000124210641754634016747 0ustar khashayarkhashayarPNG  IHDR szziIDATXѕ0 Eln-(%-L 0)!.!S(&CBVpx1)%>ƘمRJf'_a8*hv iXtmƘT5ιk.K "*3M$TxY@gP9"snV{I@1z=ubTukۖ5''ЪL~Hmqat7:eHdkTmFP_XG*%z?jQHK6 /Cpv螿1u=Eށi1O(]x(lv k=OMhI׫ aR-p9ִ. 9H]}Ti.4M3ϕɁM{dL' ύ8> S9>p |$ ۿ, I JI \mT3R~P}KAC?eϟ2$PvCU1ˬ G6sN5&}~"B~9 r[*x 9 ݓBF+pK.d@aD4߆{o p>N?T|KEuIENDB`pencil-0.4.4b/icons/brush.png0000644000175000017500000000134610641754634016625 0ustar khashayarkhashayarPNG  IHDR"LgAMAOX2tEXtSoftwareAdobe ImageReadyqe<xIDATxb?`ѢEXjg0aNVb"ՐŋA6{ QU"b-[4Ak{y  پ} /'!moXCg{'.] 4P5jߟ~?x@6ܝIENDB`pencil-0.4.4b/icons/onionNext.png0000644000175000017500000000123110644055565017454 0ustar khashayarkhashayarPNG  IHDR ndgAMAOX2tEXtSoftwareAdobe ImageReadyqe<+IDATxb`DBĤ<<<||@LbƦ_AVMkWDݟ_~3ƍk M=Zw̬y|Ѵi%z111) j!1YW y܀R1lj`QR]CC+)-h&o`|BյM?89,'b)m`x+ <ؚ.W`fr , X0gYtaCW[]8Έ0pr0G0'&3| @`@i+\DVa]1!!!Zd @ `i b#l)pCĂQ Rpà|b dV-XeJP@`\\\ݻ@*'7@Q& xIENDB`pencil-0.4.4b/icons/outlines4.png0000644000175000017500000000074410641754634017431 0ustar khashayarkhashayarPNG  IHDRagAMAOX2tEXtSoftwareAdobe ImageReadyqe<vIDATxb7  D-c uu Wxڝ *N!AbĄ$lA a5f &,O3 r~ʉ`\ @^CzS/?~2JZ{=>g W2v `IENDB`pencil-0.4.4b/icons/remove.png0000644000175000017500000000123410646223355016767 0ustar khashayarkhashayarPNG  IHDRagAMAOX2tEXtSoftwareAdobe ImageReadyqe<.IDATxb?2wceeugaabM&&&7nBV@0dddr888ҹx4 fff߿~Ǐ3}6ڵk@6'@u ~˗%@\{ kfddd^KQNN΍{ mG\t (@~iٌO3@jjy (A P 0`g d3Hׯ n݂y @hlc;Ɂ ["K4 IB y p0  P,\b !̓+Eٯ_A40c X@) \ϟ3|o2P(yRF g'@16(yœK! 5@37mڴ mP;!@H I___sI9Hp$/ AlLĈ݀H ? eַIENDB`pencil-0.4.4b/icons/layer-camera.png0000644000175000017500000000216110650474602020032 0ustar khashayarkhashayarPNG  IHDR&gAMAOX2tEXtSoftwareAdobe ImageReadyqe<IDATxbd@쳘777ϟ?G>|wa"@1"sXYYWWV[X0~!#..95=]ٙ ~`u+P q/_$d0@1zzz@+{{{3|߿ ?1ʿ}!,4OEEE7˗/`FF`2ppp0?-a!Z@w233˸3| &Ï?>4(.%%o˖- Ȱ1; %?gJ'{@W|͛~F. QQQ`˗/ Ǐ~ ˗>,i &fff"Krh$贩S}}|Ν;s[n rA`ymmmYgg_|Y X~B#dPڵk]vM89% Ƣ`2_lȥ Gf0-)!2Oha)@={@W8p@ G1}L`d!a0-acg@, ͢L &MC 'gccG$(QR Rt-a5 GGG C3 }{{ ߽{70O0p￿,ĬqpL22LLW`D11ܹlѷo޾} )) XʃA022Ob622 !Ed103=z 555pE`Ȇ 7nfx'bR>rIvSN12-aP^Ѡ8 >cy A++zb9AIIȑ#v/g /3ܹs@>%M@KW>e6!A@~ˍ7A40~enjjjLbbbిz*(^@,^z+w?|b8s ÷Ν_|yUPh2`\``c f`NRJ<mZYUDTk: ~ _#QAyEHHw GhbIrFPZP2r (Mfagetv &ƶFFFCMMcP*9ʊ` _,/DZG>{^7 D_AB\쏰`;0m`嗐gُf=(@p @, 3~%_~|s_~ *.k"b?cf|ϧ9ntS'y~~ߟ_\V([21p%* ,{! +?>} |g~7n1<{p X@ܜȲ\# Ee+;;? Tgft P 7+3'bvkv"--v/Tfb B@ss3c`-)/ >3~Ç_>@, ;4L-$'N#)%mp cd561սp߾fffbd6prbksJJ\xrw{~_,HE8@ѽtEIENDB`pencil-0.4.4b/icons/eyedropper.png0000644000175000017500000000110410641754634017650 0ustar khashayarkhashayarPNG  IHDRa pHYs  gAMA cHRMmsHw2tl IDATxbb H˨a H,)|>ÿ j_X/:_BJQB;30 jVR78P޳VW bվWSwY_U+/#gy ( Lإ5k3~}]7CdTCw{)P@5`?~ffiaF..0>>d MP @XqFtF%%%(6 d#fr4͛ d JH'=(~߁R%d@IENDB`pencil-0.4.4b/icons/brush0.png0000644000175000017500000000116210641754634016701 0ustar khashayarkhashayarPNG  IHDR"LgAMAOX2tEXtSoftwareAdobe ImageReadyqe<IDATxb?`ѢEXjg0aNVb"Րŋr=VbXe˖~/Mo_ZA={hCo? lHk|E֯ ٳ@7!qCf͚Y @ 69_@m3l;t!8E@1⊵3?g6V 3 V6A]}2ssIENDB`pencil-0.4.4b/icons/bucket0.png0000644000175000017500000000144610641754634017040 0ustar khashayarkhashayarPNG  IHDR;mG pHYs  gAMA cHRMmsHw2tl IDATxb?6`ddǏ ׮]cd  E @lB%XUU?NMM]hlh?6u0 @X ?.C) ˻۴7/^WRRj@a 1Ldgf`fbbg{.0,8@arIJ2aIIY a))FFDںe|Ab %% b R 22 La*.fWSV# *00'DdAĄl@OQ8 dxZZ߿Aͳg ^f*_f% yy  JJ (+{0qRKLj@Ud />`P60`ڎ̀7O29Զm 3֮e77 ۷EneIBQÀ{/3\>|u s0h.200 v0p@ iebeݻo=mlAAp.$  xq,MMYэY9 J ]bN8233 lf@؁ 'iii aYf*  ѵkIENDB`pencil-0.4.4b/icons/prefstimeline.png0000644000175000017500000000647010641754634020353 0ustar khashayarkhashayarPNG  IHDRK3?FgAMAOX2tEXtSoftwareAdobe ImageReadyqe< IDATxڤK 0 T(.D"V:Yn <|ZO"R@M-4PA 9eJoy#awq.ѭOvp 6Q3| ##gh`:j8aBv!BFh GR j/TOVA4 3#?@033jIpC 9 )@ _Fb@ {S?,u'_$ &$ )˜e *dRv#ZaKȁKU hĈP?4CKl-%2"4xj @u_eA 0fPFT \|- #` Xy# r X)!cV_Pec9R# -uH-p#a_TȌd&3@9rZL!+`Bs #R 899΂a@`o߾#,,^ȣ1p73#WR@ 'P(R5!zjV08J.g&pߺu+!15!8eee1L6 =' |`ѲO_@2 jYqNJXTLh0Հ 81ralp,p dՊ DB̲XȩQ>xUτ##8A#ۋ^ ;wZЖ:Ċ@, Pq>h[p IiB')uA$u,hEr/Rej RT h@1aiGjwE+c RS);gC&DŽ%azU~bBk`G XxRAUf4;99U?<}=b F, 'z}A J1 :$cR('o)DǒEc el!f ,8Z!% 䲛 g@1~! p=D 8jhbƈfE , )ű`i3 Zݠh*#$<~?.FFF2RTmH80?3!.F _,M |8FVAXR ''e1a3n6i VFs"&fE) Zjx 8ɬ {z8"?Rb`ZH,Hُ lXb &,#8K qJBXX13,8c 4jm1 dwcD)EA"1Xƹ jlB ؆jL̬%Y1+2|m#AHZ)D#ĂT!?, k`+3=oy X?~m"?cKh'1) d?"9WB;R'rRP`޽G5 Z1a) |-I< tFWm7Zc ήr)@Տ2/ǏgϞ&v8<RVDn'"WH374EЇm?b C. Y_e Ò%K3wbGI6F8<̀6ܱf@Je&NK@0Y`1 Vs,LZa-$ ul?46:66>فm(P @/sƉ0j;[l%NOl_c/w!>a2̌Ega@MF{5#Za2?mv3Z W XR_r}xP`amgſh]2E"ІІ -1!ua-}2= _C3lDi*gj 9`Jg@bEbDjGIĂ4Ȁ?5Lϴ:zHA 1֗{e)BĂV0 ghh1#) @Zډ he a!vF,F Ą(ՠgh#<>CJK<%,@o* i0RPf kXm&)-ĂO,c/ ـE_/mDmz'RVQR1@HLh3%4=LX0lˌXF (fAHm" a xHQւx81he?4?hY/I?h?@G^˄co?bf35e>C?HvR?bObEGcfR?&4O0Y bk\&SM䵥ȩy1裤 t`Bg2Ɍ6c&;#5Q~Z(n9e t94F,sa2 ̈#[K0`iXCo@,H1*B (6b2WGh=2!e/&=Glŀc lXX" R 2LMɌhe_,CH# h hqD2 X#s6lȎWȡbL8̰%o3ΈL&LEkw0̙3b yz\N1 5 pb"%i"&\oVo&Z fA PWˏ?'TB K a𷿿=s۟-q֙DGv(Rp1b噑a ?cs G2}d> 07 0!e\mvyZȀfֵk_,[N/a+b q޾$vh[khк1Y Hm=1 @,o޼6 ?F)z_ mJ5 Id``4;BxgIENDB`pencil-0.4.4b/icons/polyline.png0000644000175000017500000000065610641754634017340 0ustar khashayarkhashayarPNG  IHDRa pHYs  gAMA cHRMmsHw2tl $IDATxb```Hb+4B-@b-b ( ~ğG@\ 5qќլ `nzۡdf(@ @ K4A@i@|u 9@@+ bi4} d< @=B3PF#Ԁn K X K@| `$P?@$@ TR *G-@y f\j3DDDXIIENDB`pencil-0.4.4b/icons/mirror.png0000644000175000017500000000045710641754634017016 0ustar khashayarkhashayarPNG  IHDRagAMAOX2tEXtSoftwareAdobe ImageReadyqe<IDATxb?% (DD5p@g'X $ͻ;t; B?%2`;a@ Pdh~ 2@1B(p/W&@,(_O-q}m: PcMN{W: ?`ɷ4X@Nww`)h @3\IDATmA DQ_̃&+R@сZyIM K134T^XSFsc[9B-IENDB`pencil-0.4.4b/icons/icon.png0000644000175000017500000003774210643100406016423 0ustar khashayarkhashayarPNG  IHDR>a IDATxwdWy[kʝH3#F" !@ đc slck 88I& P@49ӹkսgOhP@쩮]SU]Z ^yA^yA^9<Ǥ.$`hXJӔ e= 88wMPZ;BDJQk[(:p$9U.W.W;^q`u=Tr<)U_gL\Tm3}m/K p co|柼J.9  TAk0Yy)Jh֙U.w8?l |)yN_޺y`y9sa O+DHkR6L/nv8|z~i\3By7_xFX\zA:`4GgRw>u_t<_,_~0^fZkøO$ѣT᪵y9[8Uxg$`!#con`;QWqsӅCs;&<}_|(~]޷]v5x8fbZZx0;HSExދk;`;?tuJׯwz{+ y|?֊0Yz5⍛Te 2]rf`S?b244Tz_ 6|tӦM  H)ict3nT+\5C)wQ}2!ĥ3;v?Lr:zB_ bꫯ/q<|tB)K yf\:~=;Eo,z ﺼbyo[ O^j[gHjO)?JP~uk^ַ|H.WP('G)y^X,* 9z{{ٸq‹ĥ^&4kn_#<Γ"׌zZ |*O)?*P~x;͇??!8Q((twwOOO7b|>GPP8i r+B\zɋ=nwJY y HD 8:3?y.8VWcaUQ0ޞlA¤8|#}sp88@Ju Erk_v-͠Ŗ1Zu1pw5T |dO?z׻{'*m1H)<)%BH $CJc$RQq9\{9~Wz܄lav4?d/ {n_aG.&)ANӍ ZҀC)68(K/c*wlجur uk fhtX-hמN#x0oxɷ8_l#}ssy ^oU|j ͐8VD" C@Xddd066Z?^N c_4\KSv>TUª|43O[7Q^WJSB\S(X{|!h6aShb(&cV'v8ۋ\{Gæutbm809) O5nc=CĪU;d΋ƍ?Ƶ׾r!,+nRe clqdER Hfp u+ ^D0GZR|qĎ$c YcΠAk㴁}|Qh4!JR ,te 44*(]79DH+.V`D)4 W_{o\~ wp]\[IP\[kVZ+(&"ZV+@)}ZJǥ\*"|Wܳq~ז(`a4xh;R?>\`1l܇5Q<N:\7sO}9?я{yAHh4YZH b`ܵ%{d풏X<^i3=]q qa2ؖ>t'] ؆Ґݝx,cg\Gଫ/[RJ((;*y]]]p͗K/} T*> Ė:~I+gG_//{7 F)Rރ4bCq v,)q`Z 9+#jtbݺ#%8x>C8ر[ym _.6mԼ-?#ϿbqG+ zʌ|⎻: =8886vlu|@w|SXwXQzIkKh9^ _ͅp٧7>-w/ݪ?yVnFu7pQr9b1Z1?tD_rǿ -z‘rn$9E@XYXO+V NL 湆>r_>`(55? s{Iۿ__C(KK~"@ʷ!;$֖ʗBp6Ǒ s`lK4237[X ~J\8#9.=g_-}A>Oe`wɠ'B|ߝA~qpmՙ92(;.ŮÞ+ oF')-਀3C9Oo7<|_s6Ùg|?u=w^P+v.28Br>á̌6滜~:x7'8"`a}`9T~ _p+>SnZ#z=zC㬳g(RI}ƨs'5/WW#$Sט)V;K8jk}}oFG৴!zqsFI8o0qMkQa junz|On~ggKu]&'?>Qn4_Ri68@F7Sڏtg=kG~ЇRy4A&3VV|&B.ɽU1> Uxj bz{_)G,<QJGy~ж ݫ#%2X <ҺKӾ 2*7exʟzyi/oc W/^Β Z (-ş|VU/BHi$`uzL,=Zk+$sݚ[gaU};$qrhspDz< y\~ΉȽaO{8ƿwj2 }C ` q@9`H4UϿdJ/{˄mKDqh6~pfl뺲=NGM5pPl;|P;s(ޟivl#~u?N]LiKڶ :E=3`8M-]H=IߞIrkT/-kKK?G/9_| Jٞ0Ur;=sڡ}CRbV"q|&{ NugKp_<>OQy;!{gXVQq P?M ҪA 92s7mltj"5jwh?|0|!8fll>ahV),M-Wk9W}Qټa@|҆ cCRA1 ""|gaaaY Rz<Jո=p>&'6~}_#@xϚ5oʏ1Bo @}IUhOɊ@*t, Q#x>z,(mƨP"3ᚳ_nkר/{<6lq("\ץZL 41?9sGbW4ܛOYgÌ9}||OR#kBh~{VM0@V*%޴ @[WRw%6VTdK6 YS@|ᶝ8hh4(lݺ1ưyDQD.# f=2gs؎Pc܆Y/z֭[Ç!":`!)  _4u(GF ŠWg>U?3O} nI~Ȇ$ߔcpGl8O$1 6o&ơp펫V:-q$ uc5_b".RfI8z(q!jAzzzXZZlőX_Ǒ}bF{ڲZ$$nhhOkO;0n5.Y{U (WZ; h+\ȕF|[U F *;vԇz^rnI|Smh6...R.)Jx]|}֮]Kww7KKKQrr8B򝉝7_Fp+TnrQ'(b«LJy?xӛEL.!_^6 6ǑUZ ]6u@h{be[I$[+I^w=kXjQw[ WEG~`<jy* qؘ*nK%NJN'k ' ?]ddԧoySww8?/x;]LlmWv^P*zRT<9{^kZVabB0`+Dl;4544P=W6 x9ks\݌7 " rZ p];WZh4XU5e L/t -D}jxz"@u? xҞpOE 5z-i+~$X@'"^a,!֓pBr%6s8[l5.8{#A-r5t|)5-9~PA[G\wVLMCTMP|rsy;tIڥ$JM~jsevf5Q/>qw\"!K=xG.X,288FÇ311a1ہoiVhp;N$F~)M.83.zt|8>!P2uLDVysY֟!'Iz~;l/\Y8|(JF}p K6y "Qط󐚙m,tw U rx2WK=Mwr%bݺu4 v͎;RصXA7__B %{,ŇL4}s}}niq?& X*[?NK (h*\N"ZUT _+ Yֈ(bxx)%w&ۀa=Փ칸|a5Wk{~k&qHC9y՞fAq4Z IDATQ G(@9!+.~K0$}"1H2X'hv#hԢpۣcš5C~6J`ċH/O޴  H2.%gdEbq(Jk.o2330YٔЉ8x@?yC嗣D9HMnXYJS(V4F;JR+AznD] _37Ytzt'!`[P8hX֬=tS4>TpzS1 Z,ܲ3K8:￟KZocIfF6ЋPy:Fe=%Y-"&Yyg6dxSǓO@xUc׵CȤKPnWObR!FGHZ`\[8cB +J#E]i VB|tO<3"ɗ007d{{k`D)3^>XbNm9?)ty\ʇ'7^s\R;E8&LJ0LLc Amb .4MB+Ecb*6(%F+C tiܾscG,-Ub@7戴 CʣT/yE&HKyO߽'5>s+sjeݩƿ}8J]Ś;tyG_O'?.3+ !]MDmz(V*F: ߒFvSc(""*" 4m4hb * כ?VͫZ^DEM5nyZ ]E)4%Eo"]-|މc:vBYTwYdT <ppkZ `D " *a FKmZ$5o$(Fi0"1 i2QDF@;=En*,.zsuEE4 kqpfQ|]MMs e\bױ4r~6A^'F(m0j^&)ј6 F8nUV!0&ZQ0였heam7`Dv0$K)e")8Q[Y4cD>$rk BF~Z`!?FrYẹ^v[z19?;iXx*ʾ'$7\* 1" 8k:B$h;IG:7vW@ۣ#ݐQi(!,R(e c +0;H_Rr[e<./ 4 QD"E{P;?̎c+s,p^uxDfC~v/Kx 7ZPQ`$ݕ7US 1¡=@l@ő6hmFJ6Xb#,yjbmHȠq1ZMmr/ux11)=*ce0K#47qL읨|Na>K b5oR@ߩ',nZۻiZ)-^S# B"dؼ/ҕbF(R )!aTa6 Q"a$8+v_)@x91RL,4 {vCQv=q<բqw`'l8g?;ѼYd ~pC׿{I㍽^cca<I0q`VDq|mNk(R۹Za@G8!B r HErIs=}|E_9*Z2a#{;B=,e}K6[A68Y*۶lUU~]<";%cIX TFzepHzNngr)4UzGF-擷j^,PkK{H3[U~6wb;y}ܓ<"Qj=yEl(B |mu#$iO7I-囀7Tdu6DJ,A++ btdkc[ɒ9I@u<sbQ*,6 e"1֬wӯ U9NzS~ ;bfݧwNskB;̜s衷+7zr(s9ΠÈ$ؒ.qF1:bE+؄R8T ʨ$ڈDzhv4G|`iǝ~ϙŹ#yl,.Zc>n ceV;91̧+ǧ iS>tIxrslpW_} AT_]?_ {tb>[4r*Aʮ(&"L,(* 8 HN-Lmh7ypr+E|բk/̀|io0שߜ.:,YK_Ӣ|8Doo)x[xok! ١|{{#C}y)n+Vġ]W_Ś(V8aG"Mi($lǰ`nɅJ,g %aW4źstI3 u=z܁mN,OG,ϒ>Y <>V`OOe7n_\5xlp6##À`ii;xx _~%֎!D*8&b Ҩ0N|1Q:2i0!F$I70v FZ8ūxJ] CeAcnⷾ8Q3۱4lhuR~6wjH+z5 =mށ:Hg{pph^_@WW d .N\ba~ť-ߺoi gT0BDaD)T)ڨPD"laLpB\b Dc'X8Bh4\$s2E]Ŵ-bVH<)=#AKBӮ|8T*]YT޵nYW\t%T*9~|q&''طo3 癞:N펇vXDaD_&!40"Y$hC>2i=Yt榫~0);}C8ٻ_[4vIn'w*V iw:y?iiyOtuuxqu322ְ8ǎٲvw]XŪ<_}氻RʩX0R| ehzzT8$ [4A9r0ݻ{9z6i-ԕ[C2)N3b%csȣV!qYa_u(y'O줰N]MhZUˏYJ{raLN3>>΁ٻw/JJ)N;?^Jd(/Ajm蘩Rb`XWnyd( +-dQy';v]eKN!T3|8qYX.p.v͚a:k#\ yd+=}1}4uQ*fiiq?W_KDC%=}K"@l!i?_e:#L=SsL<|`0nēӠMz$/[Ω1B`/hxlڴk!۶f{q]k'횕F+^+7N1H,?WWGJ\ס{(v]1WaXlX$O'׉=U9x+}% _7R(;ǁ}E T|ZE]} (.T&۶uwII(``˶=ܳe9D֠lMıvsQ#NZ9N::ϸaezR>qu###S.c#޽^n}V ij}QoB7.i^Vc S3vs8Vq&bw`7ڴl;;Sus|Nޟ6Rl3.6^P((KVwS}hr:Y&'ى2Z369}?]=7AmN,_d 7]ΥIYOAY>!a(K6h`xRjuYv1dii Aĭwn?[\`]t{{;311idzv_k}ϑ ֚82[wq[[ |?; G<դ;)'W5~'aNpb *`k~~QVժDQPk*[[ {{Wc‚XOpu-:yj\{')tNVٔө}y3eb^l46cVa72ޚvtIGNޟ Cg$æu-X>Ux`o@;gV8xSj:gռ; V QB}{J ۘ䁛[Փ#b%==[x[ ]Ϸ7[gQtӲVrV1tBԒ6d9in`rdCt'H66.ɝGiP?P{y6ԟnm߉܁NF퐜 YtzAk-hx)YO͆,KGaV. @z8nߤڊYY SdhI9?jk#N e a52ӹ `Pv%}cm&IA4`JwjjHfYwt)-ߖު'(;r9aFC$ ٩l1e:@b"2OشO,s״s~u&Sh9f_.I#=nOhn]z= 1z϶%j|iɼt4od`<>f1"CIILY3#]6Zs򧚔^:JEKX ZI -aK-%&µۢeF +cq3%=CcO=DG#'c%+#x!ݘ|i.W~1ȟnb$eJԦ}g{[ nLH/IqN0G:I!~XB6Id5U]{^bK{9i!`@:F_.ty-[bEƙd3C 4I1bWr~+=+v˺oR'#~:iq=(J>IENDB`pencil-0.4.4b/icons/add.png0000644000175000017500000000140310646223355016220 0ustar khashayarkhashayarPNG  IHDRagAMAOX2tEXtSoftwareAdobe ImageReadyqe<IDATxb?2wceeugaabM&&&7nBV@0dddr888ҹx4 fff߿~Ǐ3}6ڵk@6'@XYYABBݻw o߾ejO/_,ڋ/> ) A899xyy?~"b.{ Z@, ?li .. 7@4 Cnmm X@3H#ffBAc<@ 5@<@/ (A5?~d30-k+˗/aޱ  M ;(`?f@xx88@ZTTs&@1  2d;K b ׁ$(2w\/^6@z€,+hcP wY @L JaDTPg'@16(y/!`/iiӦ]6Q"Mai%04m^ I___rJ$>@C f-[3@1gg`t;(@A~9Y=@L.ġbIENDB`pencil-0.4.4b/icons/prefs-files.png0000644000175000017500000001034010713507377017713 0ustar khashayarkhashayarPNG  IHDR:6ySgAMAOX2tEXtSoftwareAdobe ImageReadyqe<rIDATxb``b&(M1fcg9Y Cy98(&r?  t?~Fg 1 y?0ߌ<<<7(2^ sqq񊊈bk <ay٣ gz,@< Dʁ<A g3B!`a`cc{ aaa>gΜPW,-|`s y2(Iˁ$`0.X`46?Z,@U72'al瑓:(fAa0 32$L͛ Ybs,s0>,F= ȓ ? V[ZZΝ;1 @,Ql YX >`U`fƁgϞ= þ"f5F$,`1X01P)YPdqP=M&ZL1ʈg)2@apԂ< 1:u$G4ENņ3ȣ  6ŀҢ6o^6v ޑ9_P='GԶ#< @,IG-<D5AA]'AMD<02R5 ڼ η 7Cwĕk}0G=oʣ`Cg `03/3FkaȣjN"O^&Wz?a1N`Xfh?珮E]Bj@,yR3('_ ňZ*aRPzT aV1$/3E[[Xr3(X^T,k?bֺ_9 D/~Ṭ GrELޭcխ`mh~[ZZMVFFZ@! B  @c:4VA@aQ=z.dP< +,r2T YY̙Oe-#_0ʘ,[Π|ٻٸ9G ƄyW/h(6#wֱu`13 e ]5F뻦x1F_?%Ia1j?,Ħ/{) ¿ĄHH^b'Q`ef06 [߼ưkWUГσJ3L0 `~;{z )Ff3 cK-+3_fv38D>%1|c`x_6"8}/O ~`7G0*BA`R&?s0">q1cϯ_}gf|􎃙{FP/0_=͜Co{1AcBv3@Lp Xܹs I`c_?|a×O޽ 0ge˰ULhy5AM؈tw& Z+vYAT10&1?1 LCJ 1s13LzUWϡ1P6rr-&MlwO`!3 ؀?ySW㽁 ~`:g9;>4 ,a|X+2 -puAb?~b֕>1̛; }n128낛xh͇O;7|]@#"yL_OOF,Gi܃F=zp =y. C5`W7[{[w,@Kׯм _o8 @,8ga\XwWX0iRF_ .`X*bfTgU`zth}F[('Rc1) XF(nq< ޳g㠶>??P3 }2hr<)?&e HxD=U L  h4Wl4`;RM @\S"3x 4{A>d AP 9G@WFrPL"eĖȠ%GrЂ PѰB$gyxx@oh%?2@_ bety>l6lhP`Fʋ r4Al9Z 8tҘ3ĂU)čoĂ ^xB 7ŰlRkgw{ X A?1߹uK@䖰gl_:ۛy X`!? zDd(h?!36Nd ,-q jll@YBZ. `3Vb`DgKB A 4X h!hTC4D;(f$8zM^K@kj 0 0c6P1@0[w@& 2FBIgtN[¢fO&y=0c p3>a ?4/,dA@ fQhIA"<,hTc@LgbXR2,̛ CU#@1`D54A&) IiYZҤT0A@0Ȥ@& 8s,x@&*E 3b@jp B gcc&5`sӴۀK^ Ҽ @ Q-iVەL@S0%!M.Hq6MFb@t*ˀ}L4)~p8o\̜@1 @\r̐6,8q@yqa "@1 R8`Mqh8rIBBtKgjs@1 2&89at7fxEPKPH r]m25šO^:mrqq1Po@  ]!Lf\hq)hf,aP }q: xˌGK<ɏM\Xs j3x:FΠ- +~f90gg@3)j\\MgϚL@C 3p)g:$Aք@0XHZaKfR1Gjz M4,8)̘@ \05iAL5ZW,f̃=Rylq<䙘 )N| ؒDMg7AM ~0-D'3ANHIeA% ` R$ BEs *x&d 4x K*x r:E_); o YZ!2J4j0ta@ :xC ht qDIfe.,T(  IL- 3Y)QPBieŁ\Yhi")!֠ IH0JN`:EJg3MgYN Oڞz{|GQ@ 6pŒ)ov) 0 D@& , C@^" ILTv"ŒْAU?@(wJ@ y@QAjULtƋf 6 *hBG>LT&k@v@+;h`˄3NX:cD< @ @cHHCL\@o{젪ey # fhCŒW^ .wZfpNr{6? y(A`fQ yexsP3b@~0eLiCRq .$($ⲲlDlBXa Ngt\j@(a攅?x8ʄԅ 2bڃf4̤ \6-$IAihE3 P81,h:՜A2&R:X2H} 96)k.`3Hh @a?AL܀@A ңŸ`iXs,FP߁WA"P6Jku lVoBŒsp3’7ɉ$̰&+$Q~^lGLr&B ,Ë<(lP@akŒ`@ @̘`mHT6X3pTbBQ, +:ptFDl@<Ԝ 3A9a9~~YAqA)f؞kP L8a!(,ـ:ni ![Aa&'DNta@yS΀nG 3pA' 7LܜRBAAVb ccR Q~DRIl4{yCPN %r~hI! t 0(ÈFH ,, ,% *ЀbRRg rJAfYor(9 &B!a& JSL@ q)hHr CJI6끣E :  _Yp:e$fd@aOgb@C G%`'B%$ 0 @Sa;@&,ICZIH⃽@^ {0CUb`n@qaoJC VqB;dCqx1@z64mSHBleE2R( fzr@8af@e9Alvf"ž@fJN\8,}az8Zu .YPp)bfVqpk*:Bgఁ;xqi <1 )iO03ș(oC!&3'h 3f:EOg0h2`Ag őCXXv\Ȍ΀50Y~ h@a&2t]" Ll@aP %pR"`' 84pB e*V0PZ( @ 0) /B % ;,s%ˬde!)`i`D @ i" 0IDQ RK1˱ :@ (HW."2y(|D8A E DpPp!UL' 3Pl(aZ:wEDDdED y 2m@ &B@HDNX DKL4_,Q&)l3X6X)RT @ t^ iqX8 H$3HNZރ24\E@SRA/YP#&p2f<3ve@0ϐŒM IPJHDZФe@cA`9prA3hq jf Ȇf2&%dr aHJ4)BYa$/f03D 3Bu4BÌwbGlW 3 #h #3\3mp,)?@3xt[< [64! EH&S99[`=~l%VH5@aʝ Ю $l.4(v!2L#OH K2k0-FZx" ]+3nZH1!daؠ+Ayd,r؎&AXY ÀjTa `b7J Y ]<8 Ra@q9|c7 )ہe Z2a#7A-VY Lx 3TH a&l]0u8<4,X7xa x9!& A\ H7&فoMJjp>gVs0CaP0KIp4)@ (` S: >yPi`B)JxP΃'hy34QD:QD:QD:QD:0#HnoN>PIENDB`pencil-0.4.4b/icons/prefspencil.png0000644000175000017500000001442110713434142017777 0ustar khashayarkhashayarPNG  IHDR@6w pHYs  gAMA cHRMmsHw2tl IDATx Ty$U48z~ ' 繁y*6? @@,Иy^la~B=* 4كb^xϙݛUfX/t!<+y-i%03ǧ | ߾`b01Ǐ d`kHq(| @);H e QVM=B'OCy퉅 t%PEUXm:uaf盱 Ѹm8] qC$D+eEZj (n%COe:JA;=,'6jYUĩkp?ћj1v4%x#iz;2sx @H Чش17HR%PN-8BH(S i x϶d/ ?A !ܮ'L䜃1wAURAQ51J͑kS!'=xRi{S75OPN{ ?[ E%.03q13(ȫ0pp0A20|A[[ T ×/_p3~ѿ I*e g&8,cٯ0? f&i+q`'0g󇙁'T&n1| [Fx]EēWpN,a@L&H~<$<0<*,10=#0 ._Zp!BݿH6[LTas s0,YAãU@1aԖ'.sw1ps* lǰf{ >;{g H'0K*1s2of0_%z_zn&0ˁ [6m3z{%""5I Q` & ,qun XrDAXH&&"@Fvw = *xAC[yOe@M^}cUPfU(xڥ g R YC>3\9ꝫ 2_ wn00HJ a , X~bXt! 0ֵPI 71詝g8!APVX)$;p. koC`P`(Ià#q- ;H^x `6A_π${@9c%pp*õg> ܼ ߿~ê P'7{+G`gçD%̀.?ÍFpfva e(oRvXE5xՅ o2<9O Ydz-+WO3m2bPg l\س1@W/gHȉ\`؊'; ҈MG iQ />g`y#+ F LU Cl2#çĕt.0\髗  _1r`N%y5ӗT%XXyN 0]0E3y=p^'/2Hj2򉁙?ãsG)nghfW6Az%dW`PA%ye#~Cl L27nx%(vb^~fPdxw!Se_AضffeA?z%N^nd{?}ex rߜc1 38w J: B>3ܽtw bKbp̡(XYѽ  j] M[3HJ2 2\vAZZ,}AACH7 bV ^G2h2ɠ @)`gv7xXX@(3}uuu`טؽc26&A/>bPUgbUfQ&3<Pd(5&8@oVKNAYY*)Taΰn!Omn\0}z`K+ؓ:7'?VqBQe vn`k`del'1| /UY%C-9x/'3ػĸ=ϰbs3LƠ %b&  _1< ZΠ(ưabW_qTcW @()շ b <" *" OA!P̀A}n't3%y>ư~v˧/3ZܹčƠO2ȏ" q%% (@n ABR!/Н7Ɨἁîo 6PRgȨ P "\ ffF *r  ::zd6JرGA +x!xf vo>)`@K^FVv <> 1<иh,Bi$#鳷o߂S(+퓓vZHt%$&00hk#7÷o?>{7iQiiwWk? .31 3>H6o[g,̌YYY؁%)RdGN }s _v10`xeۙw.1 #Ý7؀?,ɿex PReLMS߁ya0P0kr`F@U* _l ,L ?6_Zlk|a8{NM'o߾4!fB 6fH b |.;co޼c. @srbT T3۞<Q@.13 ߟU$ehn4A!#6a- 0oe$h>`cezPѿL w B  n^/0XZY%2\X-0ܸq:~{L M &`a?3 d a! 7+hВ={ U 7/Cow+{a#?Y0~ /?2 w R" ?g8o]30 ᅌ{A\V_* /CZZôSlU>{SLߙS |,]t*CL @puiI)p?pPP40p؀wE>cCwK%] ޿e`}zD@>? $09| a_a Ptʻ؀%%,9G;gyg[b`tX"bC@7j20Cn:pJe0ˏ B6.[lȠlT'o_2}` `'7`~W L_=3fx: 2c< P:F_?3ڹ2nx81?Iʼ 3u %v ʛp?^&_ "1paVfwəYٍ \a`0o`7Çpv\ # X.ZaO/Z .^=uK}&nW1Ȝ ie> e3ßXo]fPU C ^*h[8}d <ֿ L=psF6VXAAABoiMᒟB<  \cx+*0tC AOS/`x O`GAwb@2b!K`lFUIFojcK^Tt`>3|C d n`0˂72T{/ĐOxh'@>?󊁇X)*2hNoAVa UgXL5v]ΰ8Aԋ.)dP’*[ üh`='oY3÷O' g \oo0r2˙y3x`onvs2W@h0@@C4jh2`_*- ,Oq0"詞9-bM`G,|V/`Z_2|lm񏍁ؿbcfXsC9o:aZ( K3BؠДz~_/ӑG3Rc9ؿ3D1pKw?W~}`AlD}qA6O~g_7POh9 _Y+) a/$ϓ@)uf_bTpYxn03M߀;3,:G\χ6=4<Š>Gh*,xD Ѱ1Ba<7O}!}on| Z= <lB& @1Ыǯ@+4C?@ xe,%|a@ ؁gD ?A,!z .IENDB`pencil-0.4.4b/icons/smudge.png0000644000175000017500000000133110642077223016751 0ustar khashayarkhashayarPNG  IHDR igAMAOX2tEXtSoftwareAdobe ImageReadyqe<kIDATxb?@1ϟ? Q0 6iҤ~̀1X.Ǐr߿ _ pǏ/^7 4ϟ`2bF+V+>rX#P۷o _|a o߾ uvv20lذĄaΝ ޽cz lP_NNÇp}0 n???`CΜ9PPPv)K>jÇllljkk\\\XXX?~ ͛7.dbb+###\@a5 vbx W߼yv y)55aӦM ;v`wChh(޽Ϡ@, SVV{o `֭[ ӦMc022bX|9ܟĈ-oollX~~>fcc{d(IA @..>e::: ˖-c$# ۷z\\|Y '==?0`8q⿝ aB y̙HJy@, " IENDB`pencil-0.4.4b/icons/layer-sound.png0000644000175000017500000000156210646534551017743 0ustar khashayarkhashayarPNG  IHDRDbgAMAOX2tEXtSoftwareAdobe ImageReadyqe<IDATxb`XY?30H $)"*wD]]m׮] """0M@`ěXAoAČvvvEa}npY*>\deeVc``Uv?C,@P[TL!9c,7û.cʋc b v@ c>#)&~AєY\\g3me>7#$+ .O1I_f 0@[55 66 <@a~ ďу !%ͣ"ȒJ* Y /^f+ȫPiq .썟?2?++ZBbACC/PiP@`>ILB;]Ç{bpwwePPP`w'7 >l9@gee# MU e` P? `S;`%1@Rׯ#9_. ^ĮĂ_~T|jf]^`/,,3?~DRwA1([|4P>n^q|o߾= fv_L?󿟟uX ^ z0A"Aa Him +8V!IENDB`pencil-0.4.4b/icons/arrow.png0000644000175000017500000000074310641754634016634 0ustar khashayarkhashayarPNG  IHDRH-gAMAOX2tEXtSoftwareAdobe ImageReadyqe<uIDATxb??tb 8C[[?T b4翂 @L Pr2C|||#G60o߾\4\#333+++>|okǏc Pldggg߿ O<]#@5<|512C@,0###ׯXX Blll [6o~FbB|aΜ9N޲u/nnkfffv/!!!;vĞ:u*A 3#@`uu ͵?] pj2eFy<@O@A straight line or even nothing * bug selected point moved ---> * bug: strange long things protruding out * bug when variable width and zoom - FIXED * bug when adding point -> area shrinks - FIXED * bug : new file --> bus error (FIXED?) * bug : when deleting/adding layers - FIXED * bug : when drawing 2nd vec layer - FIXED * bug : when moving a bitmap selection with transparent colour (FIXED?) THINGS TO IMPLEMENT: * compress the Pencil files (XML + data (images)) into a single ZIP archive - similarly to Open Office Documents. implement a open and save function for these ZIP archives * improve movie export (get a QuickTime dialog, AVI on Windows, MPEG...) * fast gaussian blur for smooth shading SUGGESTIONS FROM USERS: - duplicate frames - rotate - DONE ---> but bug when drawing upside down and very slow - free selection tool - animate selection, and disable selection - save colour palettes - shortcuts in the menus - DONE - customise hotkeys - import a sequence of images - DONE (drag and drop only) OTHER IDEAS: * operate on several (selected?) images at a time * morphing/tweening...? * multiple documents THINGS TO IMPROVE: Flood fill: * problem if a corner is too sharp ---> increase tolerance? temporarily change width? - DONE (but for very sharp? DONE! (up to 3 points) ) * problem: sometimes the final leaves are not next to each other - OBSOLETE * reduce contour pixels to pixels which are in the rectangular area - DONE * improve intersections! * test if the initial point is contained in the area - DONE * update areas when adding a point - DONE * remove points * bug when remove colour - DONE * manage colours ----> "transparent" colour; for shade contour interactive change of colour * write/read vectorial data - DONE * better eraser vectorial * several layers - DONE * eraser tool for vectorial - DONE * separate bitmap / vectorial - DONE * improve timeline management - DONE * warn when using a tool on hidden layer - DONE * improve the "cancel" function - DONE * blur tool, spray * improve simplification/inerpolation of curves * copy/paste - DONE * import sound - DONE * reestablish export movie - DONE * mirror option - flip horizontal - DONE * double-click on hand to re-establish - DONE * implement paint bucket, polyline for bitmap - DONE * preferences - DONE * accelerate : when moving the mouse, cache the background and draw only the modified element - DONE (but memory leaks?) * change structure??? -> intersections re-calculated dynamically? * use the OS clipboard for pasting - DONE * CREATE a class "Image" --> BITMAP, VECTORIAL... - DONE * add attribute for thin lines - DONE * add attribute for transparency - DONE * implement eyedropper - DONE * improve selection of one curve * improve selection of frames in timeline - DONE * suppress areas - DONE ============= WIN XP ============ implement export movie implement export flash - DONE flash compression bug grey border - FIXED bug export jpeg - FIXED bug file extension - FIXED bug release - FIXED bug with tablet - CIRCUMVENTED with option bug - tablet doesn't work?? pencil-0.4.4b/LICENSE.TXT0000755000175000017500000004313310641754634015347 0ustar khashayarkhashayar GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. pencil-0.4.4b/pencil.icns0000644000175000017500000011461310641754634016013 0ustar khashayarkhashayaricnsics#H???~???~is32ح{s$լhd S<- w3PQYþKq>lн>l5Jjp\’\{͎P߲) a& ƫD5 ƲZ Լ~$HҰ0V̶}.q?a&`/T}kȢl`ԟhBF2wXte?-r`aL2; neaaT3<&ܣ[V7$3۽z=, J2wCMa N's8mkm҇2[\! ChU/_:#^?gZ<U6%ǢyO0$j`[S@& %30# ICN#????w????wil32"%uȡFjk ʲP ˭(aʄ?翡xvE rk?֖cf.сyW;cq X37>_)#%H=GUPZ*t #C9~0¶߷) `ׯ! 6t-ÿ b&$Ƿ{i,ʭT!3K:evvkV(G}9 ȝ{( ƍJ тK awb3עf)4 ȯq+5 Ű֖f03ɣyW>+,ǵE58<&òj%I6ķpEUKݷľj[*߹Oشx>пu"wüvĴs \Ǿo 6u+ųj b& \ i,yuK-CFt|c-MC ɢ0 ʕ\֋g#pwʆ}T' 3qoGT+ ?dPwrDU' >g[_NޙdET-e[_`bU{W=AG1d^_`ccT*78<<+gcf`_]Q<+&I9[k*hnegd\_X?6#DV<ټ`O_][_^C41&]*qм`Rbd^B3+)'"̻WV]?<*% .ʺSK9<$$ ]˸c597' ǽp3<' Qwi;& 8}'_" f'8n.c}_<$6l8mk;=%f~"1' / 4'  ;5,A=4# DC5# GWE1HbR>) j[H3fqaP:& rfU?* qhXC.bohYE2  lfXF2! keVC1  YhbTA/  g`P>, e^N;+Q֯eZJ8'ŠsjcVF5$ ͣnhjlg\O?/! WiD=HU^_]WOC6(  (6AHKHC=4+! (.22/*#     ich#H???????1p???????1pih32 AC,Uӥ[4`( ʲ ᰖ݂[ ́̚ ހя: ߁̕ƂP "wᬲȂ^)Ȃ|ށSwd/ЅހYcc6ֈ ޤpVY<ۊ ޵{rSH?ߌ ӟqjCF/A QnfJN4Dh Dg,@2<8RtF ܹ-.5O=TH I(CW)7 W@RJ h`ḱPf! Y? r ŀEҷٷ%~ޭƸAlݛ Vc nƊ!bÿލ 0ȹa5`JmſŧYx Cȿr@ g"b2?% "#-Zy~rX0 HW9N|}m γia 㵄, БsH ހԃvB ߁rc2 "wdb43%)ȁתj݁?*13'/Ё|ހY%33'6ւͿʊޤs*24"<ہƂ޵{u214?߁tӟqjF'24ÀʭMofJN7#4)DO-@2<;"-F%/5O; G0*CW# .ƀŽ9CRJ廪—MckťƢ|Dh!UɦŧgAåH  ܴǓsAȫqwôm»i=ɿ~g e{_T_ſX nƋ!\V0ȹa5WQJm=x ;f: g"W,7 '*5hf8 Ud6R} δtp 縈9 ԓa نa$ y|R3 5fs|RS<(xNHIQS?6Z@Z=SS>8̀W]bCr;RT79Ƌ[__\^={s?QT-.Z]_^WIۢqjE3RT%z\__ac`bfVEpfJN60VB+zZ]_`^^die`)0@2<:5I"z_be^_cd`YE=<05O<5|]deica]X[^=?5-CW% VosL beffg`\^a[E47-GRJe˶c@]hffb_[Ya`F:72$0fkɀ7WY\XW]cdN;312 8i!C؀ƅ8WaaffaJ:3..,CpڀʾvD^_``M>3.$)!ɺ`@\fE4<;#$%2Q\O@6H-'"^ĴDD?4>')%ĶS06;83#0ʺ`24A1!Oý`/A3OO{P=: tϓ$GH; 3e8D<Npll~ 0uR.  k$jG#-h8mk 6n~Z/=DTbe^j rz : X k!# r,+# k73) ^@8-" RF;/# MG;." _RF8+  hYPA3&  o_WJ<- td\PB4& |gbUG8+ ^|lfZL=/" {ni]PA3& zoj_RD6( Yxok`SF8+tojaUG:-" rmi`UI:.# Tpng^SG;.# ong]RF9-" lmf\QD8-" LkjdZOC7+! kjbXMA5) jjaVJ?3( Eih_UI=2' ໌if]SH;/%  հwmjdZPD9-" ;ĞurqojaWLB6+! ҩqjlqqpjd\SH=3)  ٫~`UW`gjihgc\TLB8.% _J0-9GQX\__][WSLD<2)  '1:AHNQQQMIE@:3,%  #*17*@:H==/{~JJ-.)T;'@%55JCL B}NI0(ZLCa=d<(-H)A(.YiL0qBF)!51N==feK({F Ƕf,.5BBFi\AOG ӵ~&"7QRbikibVG:/% 'Un ylX4Sw~\"+nzJ@{jD|, 6/124F ɦ> C0024Jю2uݍW )324KgMތ~124MЌ&6ދ⣏1.24}ؾɵU݉ʌh(24~ؿϽ^ވ{125ٻôb߆τ}5024ȾǾe݄ פyW/230W خ}~m/23-  ̶Fj݁ خ{qog.23( t¿ ߁ ա{~~mHLR .24%|/OAŅ|}qkoF2L .231¿+v˓zxYaxmPbG,K .23- ѽ!¾in}yxQ<^kEUH(E .23%2ľʹ(4xctwuu\6E^ALF'./2.3žƾbPER_TCc93M?IA+#/219ſѢ/6:BWF>*@:H==02219ø6..)T;'@%55JCL 022ǽþʁź**'ZLC %21ûˀƾ{9/(-H)A(.YiL1 ,39ƾƿxO3(!51N==feK08ýoj=).5BBFi\A  Ļڹʃ%ÿ¼ǛyqD""7QznͲl1YqvҰVR0y͇kwj | ͧ~l2}̶YG ÓInO?  Ċ>qzNL" $}=kOS5 , ҽkCTQS?2կSquOQSF <ҖMSQQRL$]iXQRQ 'Eu ߗH[QT F[Y|YQU# %_#SVNPQU' o'G0!MQT+xݶuI zXCRQT,alh5R.PQT, ^^bfjH;0KQT*7ZU][^_d_+эhARQU&<^VYQVV`dnd0|1PQU 7XZ]dbc_\[__V2"օ}5$NQS +jY[[Z]Z_]_bddb5 ߧyW LQRN (e__`ffdcec[VOPYW'! }~mLQSI&thjhe\WVTW\Y`dgil_o {qogKQSB (i]YQKZ[^chiib^YUMDOC ݤ|~~mHLR KQT;/'֘`]adghe`\PKMOJZ_bcge^!Ä́}|qkoF2L JQR//͛jgc_[WQHPWYaillkigd[NTR|ԗzxYaxmPbG,K JQRI0ZGQV[^__``gllhfe^XMNXfmq6n~yxQ<^kEUH(DKQR<1 ~_bhlkea[]ihedbYUSRahmmkfgb6xctwuu\6E^ALF'/KQRJ jʻqmkehd[^c'YSUY_inlijjhcX\o2PER_TCc93M?IA+"LQQRN+8}“qjaYMW[[QVVZ_inkgb_dadhcbhloP16:BWF>*@:H==NQQO/8΂^\_NLRX\`ajmjfbZYWTUdffjmmilcN..)T;'@%55JCL *OQQ28 ޱrXZ_adgjmlf`YRVWUV^dimlmmbSJIM2LE $'ZLC=QP&8wafilnnml`TX][VYafjlmmleXSNKJ<(4TW "'-H)A(.YiL1GS*8hʙlmmndYTY_`b\RbeiklmkdZMQSXNJ@"1N]Z'!51N==feKN,8oњk`\TWT\cegilgcjljc^XMON[\LT[[6"ERMO'.5BBFi\A 1- fΉRIM^cggiklk&je_YS\]V[`UX\]hgH.9FRE4 "7QP38>,;+4/%7GLyMYmc1Hƿh.EX_bhl)kkheaaZUZ`bfcUS[bliI;OA&C332)-4H]OddxFIp(';WkklljhhffbZVX^agg`TQM[gkkiA2HR B>0<4(.,HXRmr\..ОZ8+Qage`Z\X\[afgcZTMGJ\agjG&BN'*K-3433// FRZ[ S׀>˰W#$@Y\ZWZ`cb^RQMBNXbdgjhfdR.EW4 A4,6-35"&DMj\GƱa %K^VVSYSTTNT[cdgiihf]^Y7Qe7&0C*2.230&, GX|[3ځՀ4{/3=N^U^debbaaccffb^cfX;7_?!3;1'!(?#%=0$XyE"bu"5GZ]Z] _^cfgcgigbQ5+g_5BeM;9-<@O>(*+2- րĽ$[+-OEA897"'* :IúOI!69?2HCE33$,) 9ƽb=&D@.)B;D*.-'& 9úiC(=<'>FR;"&0& FÀ»s;,6&0KIC#4%!yj1!=,F>I1/!^ a&-EEDD7*$ ]'V;CO@<+/%NS5 oF@ID9&"*%7оd$ EMI;/ 9ʹD}-"R9; (,kqLq{*1M6.  EһuPjG w p4>%, "_ȖjXP.O.|M*( qj9-B3 % }P XnC3 =ɒ]\Z- bۘWO*$Sb6 Կ`4: ^4 /ƒ8Ey{R' :R-G rJ+g6 ~e> CY.w^6 1dmM't8mk@%4BGIHB8, Dh̰vU<'fs.">v} c%k=uL]Jd4 x l rk u, y {_ | K   !+ (H ] v &$ 51 1;  6D $#! 9K$'&$#  ;P(+*'&$! >T,/-+(&$! AV030/,)&#  oV57530-)%" rS:;8530+'$! yO?>;853-*&#  JCA=;840-($! [DGE@=:51-)%" c~FJGC?<82/+&" ioILIEA=930+&"  q`LMJFA=930+'#  uQPNKGB=94/,'#  xQSOKFB>84/+'#  y`VSOJFB>84/+&"  xTVSOKFA=73-*%! wZZVSOKF@<61,)$  ua][VRNJE?:50+'# a_^YVRLIC=82-)%! eba]YUQKGA;71+'$ jed`\XSOID?850*%" mfda_ZURMHA>82-'$  {rigda]YTOKE@;50*%!  tlifc_ZVRMHB=82.(# rwmkhd`]XTOID>;50+&! 4wmligb_[WRLGA=62-(# qӀmnkhe`\WTOID?94.*&! }mnmifc^ZUPKD?:6/,'" 6ǃppnkgca[WRMHA<62.)$ v}orpljfa]XTNHD>93/+%! цpsqmjgc_ZVQJD@:50+'! /Іqsqolid`[XRMHB=72.($ zqtrolifa]XSMIB=81,($   {qtrpmkfb^XTOID?:4-)%" 3{surqmjfc_ZTPJE@;61,'" {svspnkgc^ZUPLGA;71,&" {tttqokhd_[WRLGB<72.)# .zvtsqolhc_[VSMGB>82.)% }xvtsqnkie`[WRMIC>94.+&! wvtrqokheb\WRMIE>:60+(" +tttsqnlheb^XSNIEA:61+(% ~qttrpnlhda]YSNID@<52,'$  ossqonkhda]XUOJE@;72.($! 'psrqoljhdb]ZTPKF@<83.*%! zntrpnligda]XTOKFA;72.*&" mtrpnligca]XTOKGB<62-)&" 3̄osqpnkifb^[VQNJEB=61,)%  Ɂpsrpnlieb^ZVQMID@<62.(%! ǀptqpnkieb]ZURLHD?;61,($  .qsrpnkheb^YTQMHB>;62,(%  x}qrqpmkhda^ZVPKGC>;72-)%! |rpponkhe`]ZVQLFB>:62-)&! 1yrrpmmifda[WTOKFB=94/,($! vxqoonlifca\VROLGC<850,)%  uqpnmkieb^[XSOKFB=740+(#  4rqqomihd`]ZVRMIEB<82-+&# tqqpoljfca\YVRNHD?;73-)&! prqnljfc_]XUQMHD?;63.(%" nqpnljgc`[XTOLGC>:53.)$! Bnrpnljgd`\WTOKFB>940-(% vmqonkieb^ZVQNIE@<83/+(# !opomkgdb^ZVRMID@<84.*($ Bnrolkhda^ZVRMHC@;63/+'$  hopomjgd`\YUQMGC?:630+%# qonljfd`\XUQLGC>:61.*'" ;澖rqmkhfb`\WSPMGB?:50,)%! `⸋}ztromjhd`^YVRNKFB=83/+($" ԫzyvutrolkhd`]YURMHEA<830,'#  4ˣxxyxwusrpnjge_[XTQMHC?;71.)&" Xyvwyyxxwurpnkieb_[VROLGB>:41,($! ۰sruyyyxwvutqomjhea]ZVQNJGC=961-(%! ,̨lptwvwyxwwutronljfca\XVPLIEA=84/,)$   L׽vfknrtuvvuvuuuspmlkhda_\XSPJGD?<92/+'$  ˬkbhloppqrstrrsrrpomjheb_\YVRNKEA>963.*'#  'մ~k]^chjlmmoooopppooomkjgda_[XURNJGC>:630,'$! +뿜n^SV[`cegijklmmmmllmkjjigeb_[YVSOMIDB=941.+'#  է~hYMGMSX[]_cdfghiijjhiihigfeda`]YVTPMIGC?=74/,)'#  i칅aPD9;AHMQTWZ\^bbcefgffeffeddba`^]ZWSQNJGDA=952/*'%"  qě]F;0+05;@CGKOQUWZ[^`aabccbba``^_]ZYXWSPMKHDA>;730,(%#  &*(!"&).26:>ADIMPSTWYZ\\]^`_^]\\[YYWTSRQNKGDB><:51/,($!   $(*.159=@CGKLNQSUWWXYZYZXXUUTRRPNLLIFC@>;853.+)&#  $&)-056:>ACFILNPRRTTTUTTTRPONLJIGFEB?<:853/-*'$"  "%(*/147;>@BEGHJMNOONOONMKIHGFDCA?=;9532/,*'%#    #&)+/248:<=@BDFHHHIHIIHGECBB@>=;9733/-,)&$"   !$')+/03689;>@BBCDECBCA@?>=<:85422.,*(%$"   !$')+-013579;======><;:9865410-,+('%#!   "%((+,/012357676777663110/.-*'&$#   !$%()+,-.//01101201/.-,+*('%""   #$&''())*+*,-,+)(&&&$#!   !"#$%%&&&&&'$$#"!!  !! ! !            pencil-0.4.4b/notes-win32.txt0000755000175000017500000000660210704272754016513 0ustar khashayarkhashayarThese are some notes/memo about compiling Pencil on Windows Last edited: 2007-10-12 Pascal Naidon To compile Pencil for Windows "out of the box" 1) Install Qt from TrollTech if you haven't done it (the installer will propose to install MinGW if you don't have any C++ compiler) 2) From the Start menu (for example), launch the Qt Command Prompt (a kind of DOS Terminal) 4) (Using DOS commands like cd) go to the directory where you saved Pencil source, ie the directory where the file pencil.pro is located. Then type "qmake". This should generate a makefile from the pencil.pro file. 5) Then type "make". This should compile Pencil. ==================================================================== Qt on Windows -> The Qt framework is needed to create the graphical interface of Pencil Use the installer from Trolltech www.trolltech.com I've used Qt 4.2.2 Problems encountered if the following message appears: mingw32\bin\ld.exe: cannot find -lqtmaind You are building in debug mode and haven't built the debug libraries. -> needs to build qmake with the debug libraries, ie: --> go to the QT bin folder and execute "qtvars.bat compile_debug" ==================================================================== Ming (Flash/SWF library) on Windows -> The Ming library enables Pencil to export animation to the Flash/SWF format www.libming.org I've used Ming 0.3 This took me some time to work out As a convenience, I put the compiled library (0.3) for Windows in the libwin32 directory, so you can just use those. If you want to get the latest version and compile Ming yourself, here is how I did it I roughly followed the instructions from http://eratosthenes.wordpress.com/tag/ming The MinGW (GNU compiler for Windows) was already installed during the Qt install. Compiling ming (Flash/SWF library) requires a UNIX-like environment to execute the configure script, which is why one has to install Cygwin. (MinGW and cygwin were installed separately so they are separate environment : don't re-install mingw within cygwin. To check that you are running the correct gcc (=MinGW), launch cygwin and type: gcc -v it should say "mingw special" and not "cygwin special") Ming requires the zlib and libpng library. The point is to find these libraries for MinGW: http://tjaden.strangesoft.net/loadpng/mingw.html http://gnuwin32.sourceforge.net/downlinks/libpng.php http://gnuwin32.sourceforge.net/downlinks/zlib.php (these libraries may also be present withing cygwin (if you have chosen to install them) but we won't use those.) Within cygwin, make sure (in your .bash_profile) that the paths are set correctly to work with mingw: PATH ===> /cygdrive/c/MinGW/bin (LD_)LIBRARY_PATH ===> /cygdrive/c/MinGW/lib C_INCLUDE_PATH ====> /cygdrive/c/MinGW/include CPLUS_INCLUDE_PATH ===> /cygdrive/c/MinGW/include Then download the ming source from www.libming.org and go to the ming directory and type: autoconf (but I'm not sure it's necessary) ./configure mingw32-make static Then I put the libming.a, ming.h, ming_conf.h in the "libwin32" directory inside the pencil directory, as well as libpng12.a libpng12.dll.a and I added lib -Llibwin32 -lming -lpng in the pencil.pro file, for the INCLUDEPATH and LIBS respectively. That worked (compiled pencil.exe) Now, a copy of the dynamic library libpng12.dll should be present next to pencil.exe in order for pencil to run. This library was installed inside c://MinGW/bin That's it. pencil-0.4.4b/notes-macosx.txt0000755000175000017500000000360610704272754017044 0ustar khashayarkhashayarThese are some notes/memo about compiling Pencil on Mac OS X Last edited: 2007-10-12 Pascal Naidon To compile Pencil for OS X Power PC "out of the box" 0) Install XCode and Apple Developer Kit if you haven't done it 1) Install Qt from TrollTech if you haven't done it 2) open a terminal, and go to the folder where pencil.pro is located 3) type "qmake" 4) this generates a file called "pencil.xcodeproj" 5) open it with XCode and press the build button ==================================================================== Qt on Mac -> The Qt framework is needed to create the graphical interface of Pencil Use the installer from Trolltech www.trolltech.com I've used Qt 4.3.0 ==================================================================== Ming (Flash/SWF library) on Mac -> The Ming library enables Pencil to export animation to the Flash/SWF format www.libming.org I've used Ming 0.3 Because of some obscure library name conflict on the Mac, I couldn't use Ming as a dynamic library. (I think this is because Ming links against libpng which is also present in the System/Library/ApplicationServices as libPng. If anyone manages to use Ming (with PNG support) a dynamic library, please let me know.) Instead I had to use it a static library I put the compiled library (libming.a) and the header files (*.h) in the "libmacosx" directory, as a convenience, so that you don't need to compile it yourself (maybe you need on an Intel Mac, though). If needed, you can get the latest files from www.libming.org and compile them yourself. ======================== Deploying Pencil/Mac OS X I chose to ship the Qt libraries within the app. In order to link the pencil.app against these local Qt libraries, I made the script "linkmac" After Pencil is build, simply run ./linkmac (the very first time, please uncomment the first lines in the script in order to copy the Qt libraries from /usr/local to the pencil.app package.)pencil-0.4.4b/debian/0000755000175000017500000000000010757714675015110 5ustar khashayarkhashayarpencil-0.4.4b/pencil.rc0000644000175000017500000000006610641754634015457 0ustar khashayarkhashayarIDI_ICON1 ICON DISCARDABLE "pencil.ico"