podofo-0.9.3/0000775000175000017500000000000012356565167012701 5ustar dominikdominikpodofo-0.9.3/ChangeLog0000664000175000017500000001601311365057365014447 0ustar dominikdominikVersion 0.8 See SVN ChangeLog Version 0.7 Fixed PdfPainter::ArcTo Fixed crash in FlateDecode and LZWDecode predictor functions Fixed writing of unicode PdfStrings with brackets (will be escaped now) Fixed encoding of bytes in PdfName Added many new unit tests Added methods to free object memory of objects that are not needed anymore (These objects will be re-read from disk if they are needed again) Fixed a crash when appending PDFs Added unicode support on Win32 (wchar_t* constructors and methods where apropriate, e.g. file handling) Fixed a memory leak in PdfStream Small optimizations in various places Fixed DCTDecode filter for CMYK images PdfReference is now immutable, which allows for various optimizations Fixed PdfInputDevice::Read to return now the correct number of bytes read Fixed a memory leak in PdfImmediateWriter/PdfStreamedDocument Fixed several minor parsing issues Fixed adding text to existing pages Added Lua5.1 plan file support to podofoimpose Several fixes in creating XObjects from pages Fixed a possible crash in PdfNamesTree Added support for setting colors in PdfAnnotations Added advanced text drawing support to PdfPainter Fixed parsing of Type1 fonts Fixed deletion of PdfAnnations (fixes a memory leak) Version 0.6 Many many changes :) See SVN log Version 0.5 Added support for Embedded Files (annotations & named objects) Added support for ExtGStates when drawing initially only supports basic transparency Fixed reading values from nametrees Added support for named destinations Fixed a memory leak in PdfDestination::GetPage Pages do not know their page number inside of the document Fixed reading PdfActions from PDF files Moved filter implementations to PdfFiltersPrivate.h Added PdfFilter::CanEncode and PdfFilter::CanDecode Simpliefid PoDoFos handling of XRef tables Version 0.4 PdfImage now supports creating an image stream from a "raw bitmap" which can also be optionally Flate compressed Added some new Page-related methods to PdfDocument Append - append one document to another InsertPages - insert a range of pages from one document to another DeletePages - delete a range of pages Added new tool podofomerge for merging two PDFs together Added methods to get & set a document's PageMode Added methods to set a document's FullScreen mode Added methods to set all the various ViewerPreferences for a document Added methods to set the document's PageLayout Added Outline support modified podofoinfo to display them, if present Added a PdfDestination class Added PdfNamesTree class for handling the global named objects modified podofoinfo to display them, if present PdfPainter can draw bezier curves Added XCode project for building on Mac OS X fixed up conditionals in font code to enable building on MacOSX - but no font loading, YET Added support for writing linearized PDF Added support for garbage collection of unused objects Simplified PdfObject constructor Improved annotation support Added support to encode names and various name testcases Fixed ascent and descent of fonts Improved PdfImage API Added support for the creation of file identifiers which makes PoDoFo created PDF files work in more different PDF workflows PdfImage optionally takes ownership of buffers Fixed a major parser bug: The parser expected all objects in object streams to be of type dictionary. Version 0.3 TOTAL revamp of PdfObject & PdfVariant to enable clean/consistent object handling; Added new PdfDocument object - new high level object for reading & writing a PDF doc; TOTAL revamp of the PdfDocument, PdfWriter & PdfParser relationship PdfDocument is now hub for both reading and writing a document it holds the PdfVecObjects - the others just reference them. TOTAL revamp of PdfPainter now uses PDF coordinates - UserUnits from bottom/left added PdfPainterMM for mm-based coords supports user-specified float precision and writes out floats in an optimal manner supports "appending" mode for drawing on existing documents Improved handling of the /Info dict for both reading and writing PDFs; Added new test app - podofopdfinfo, which will be used to dump metadata, etc. from a PDF; Added PdfError::DebugMessage() as the official way to write out debugging info; updated all other debugging msgs to use this; Added PdfError::DebugEnabled() to enable/disable display of debug messages; Added tracking of file size in PdfParser; Minor tweak to Linearization handling - to enable getting the status from a doc; Added getting GetPdfVersionAsString() to PdfWriter; Added new info/object getting methods to PdfDocument; bool IsLinearized(); size_t FileSize(); PdfObject* GetStructTreeRoot(); PdfObject* GetMetadata(); PdfObject* GetOutlines(); PdfObject* GetAcroForm(); Updated pdfinfo & podofopdfinfo to call the new PdfDocument methods; Added PdfDictionary and PdfArray classes; Added new PdfPagesTree (inside of PdfDocument.cpp) for handling walking a /Pages tree; Added new GetPageCount() method to PdfDocument; Modifications to PdfPage to attach it to a PdfDocument & construct from a PdfObject; Added new Legal and A3 standard page sizes; Changed page coordinates to be PDF unit-based instead of 1/1000mm; Changed PdfRect to use PDF units and also use bottom instead of top; Added ability to go between PdfRect and PdfArray & also get string version of a PdfRect; Added support for PdfPage to return all the standard boxes (Media, Crop, etc); Added support for fetching inherited values from pages (eg. boxes, rotation, etc.) Added more methods to PdfPage; GetRotation(); GetNumAnnots(); Use Exceptions now instead of error codes; Removed Init from PdfOutputDevice; Removed Init from PdfParser; Added LZW Filter support; Added PdfElement as base class for PdfAction, PdfAnnotation and PdfPage; Fixed podofoimageextract, podofotxt2pdf and podofopdfinfo; Removed PdfSimpleWriter in favour of PdfDocument; Headers are now installed in includedir/podofo/; Added a new WatermarkTest demonstrates how to read an existing PDF and draw on each page Version 0.2 Improved Documentation; Added SetInformation for additional error information to PdfError; Fixed the underline color of text; Introduced PdfReference class; Fixed PdfStream::GetFilteredCopy; Improved handling of DecodeParms for filters; Fixed PDF files with more than one DecodeParms dictionary in one object; Added on demand loading of objects to the PdfParser; Ported to windows by Leonard Rosenthol; On demand loading of objects is now the default; Refactored PdfFilter interface so that filters are cached; Fixed multiple connected XRef tables through /Prev keys in the trailer; Fixed a number of compiler warnings; Replaced char*'s with std::strings in a number of classes; Added std::ostream support to PdfOutputDevice; Improvements to the ImageExtractor tool; Refactored PdfVariant so that it is easier to use; Version 0.1 (11 June 2006) Initial release; podofo-0.9.3/vcincludes/0000775000175000017500000000000012356565167015040 5ustar dominikdominikpodofo-0.9.3/vcincludes/unistd.h0000664000175000017500000000026310517073142016500 0ustar dominikdominik/* * This file exists solely to keep VC++ happy * because it doesn't provide a * and flex doesn't provide us with any way to * prevent the inclusion of it. */podofo-0.9.3/doc/0000775000175000017500000000000012356565167013446 5ustar dominikdominikpodofo-0.9.3/doc/html/0000775000175000017500000000000012356565167014412 5ustar dominikdominikpodofo-0.9.3/doc/podofo_architecture.png0000664000175000017500000004220011460071654020166 0ustar dominikdominikPNG  IHDRA5sRGBbKGD pHYs+tIME   IDATxwtUg{vPB RBDHQQTAOwPzIhRB =mz$dd7;sȴΝ;wߝ;3+ |.ˆYDDDDD*1Q%""""bJDDDDLT1Q%""""&DDDDDLT*U""""bJDDDDD*1Q%""""bJDDDDLT 8V+0xԈ 3nWBqEqiޕGx -zcʴ9^WZv덦2|*:Q1pL\{T"1Q%""""&DDDDDLT*U""""bJDDDDD*1Q%""""bJDDDDLTQi#eQQtHT+\+7@vвS;HDS,\e2^X |AWU)MB]eWT" mr"o φF(d$Ƅ"E+Gog]U"Ʈ $$DB๵صK ;ޭjiG';{ 涃:+[kI_uADd IP:x»U_@%!JPڗG) yAF ^+g]%U"*`;vXd0/IXʣbh5t *uZ#wX\W_݆)ئv2^G!"^Q%bB@,@$2qa~DZ . p2N_}")MhxBۈŽgn]\Gbwq Vk,71=1Q%!4ed4My~>5Zw^`}hղt!8Mgyb|ZF$E/ĘPe&8mˆ]̭ܔꩧogpG "&Dd/WƵUo:G~ÚD'5 +,&Hˡ\N;*}M]\w]Љ*YܼW4GL,?jhNhcO$f;/BwCF H(K|- S'k%D\Lj_豋2ur)S։jو(KJDV [+\ Q^);: $Ȫ+э 7v5D]Y+p%"Ѷ 2+DTl5l 22Xy # w^΅5ur4*Lq03}/81Q%I{'O&!E%N<X^ꚵ=Ax|qvk7HB}!lܔc,bD kC A{/e{d'"_m^_&#*!RP<,nHb3c FcfM^_A^;7x^"7zu ,Z!G|* NB0Luy*kM&_qPxa_40^sK vcܠB]uruy4M훈O¶\-xޅ2%l"*xE Q5|""&DdIj&҇CDdIj8?U""""D """"D1Q%""""&DDDDDLT*U"""""&DDDDD(ũ"p.ZdeHAimúq|PZ#1>mmyxZ7kXՉL\"iΝCbb"ǺqKTr$&&KZcOJ~ ;_A@tTT8`]8Q%""""&DDDDDLT*U""""bJDDDDD*1Q%""""bJDDDDLTU"""""&DDDDDLT*U""""bJDDDDD1Q%""""bJDDDDLTU"""""&DDDDDLT*QNHYDDDTR DiA/_".67_3^..4&DDDD%cfnh=Z8QѽW+>XaLT GvakgrzH$b1Q%"""*rtv9DHd7a&DDDDE"3Q%"""*29DH?U""""ejLT\3Q%"""9D"d?U"""":a&DDDD%uLT,J?')`if+$C=`"7B&1Q%""DK-WPyWVFuC$HǬYYӘY*7*UA4^EbJDDDDLTU""""VrsB%7Y%y߈ _OU DEE_=xP:w} {{{V1QunϟL} oaMXi+U"""Z86/?wXq n>|[Pvx A|\+Ǐ1zxWU+aʧcr[=FJ֍Y"**`@cb'QJEԪ1#'Oe~<5+GU}ѲQ=T-_uTĐo衬sx㺿!Vm{m۶Jj|֯~YWc@z"mږ Abmӟ<Kpa{v'}4GH}~*;G\o}xtʹj߾d;h9ygN@pw`?O&OM6dL7fZ~ 5,Z^Qeb| +aø4;ĝ۷2-yZޱ *`u~/?EFMp/.̴;wҶs!xT/bɢÜyM^tvvvdxzXw0~m;59vg*{ARa§վ9{W.nϿhep ADDDd tMLoҴyeSD=|響mvkzJ>LRNmɇcp!;rbXԪ]dllm: E[;;""*ަuq6:]$A,Cn P0Q Wö*~cPUU(kaESb d*G8zFЦ(Kyߜ|4MmW"۾ 0j([a\FMo3L.:/uق""*>A69gx7gCS d$Ƅ"E+GoiWOobѱaP^QP кmΟʹl5qU<~5]̎m{VRBnѹ[w?!D"߰腋aѡS byiQeʡMBB+[]|ݪHL& a{䏫¹pjn;HcT:m"C*/16(+tL!99W.㛩3-;t(!}&x x>6]~=dZ/㶧Cyn~Ap1"66GSR L&0hPTT`@8y_">.Oǀ>=pn*U !CٚȀH"ݾƸ,)B*Ҿ<@oOa; 5jDDCyTj[% xL6*+O8v.gu:pܼqk~_'|dvիlʖsLJ>vsN;ǎfFvWAUm {?n޸aϴL9Xz(U*f""2ɡ#9j7EĿm̡<*6VCRY\Ǭ5r|UKy%mimJa+fB%7}۸ot H$PN9 eZ8p4&~jxׂR +kzcgqi|*eK@,@$2qa~DZ . p2N_}")M?dxͅL 4/URBr|WۈO 1*O.mŎp?2%<߈EÉ#+h$E#E\X?ŋdub qBMB|S= 6K-J :gŊ z}mТuokkK07 sk\W,5kRwlWlWf~Qzl@22m&'DU$q3ˆ]2|e1<} M[}i+Zp?:+~vR(㪯cC_>`+{ ll4N}c>`JDDDAl\+\fy7iL@tq9[۰rrhb>EN;*}TA85Oڞ8qd ֍;ACm@ @;xq2Ë7sw lC}s;@Z^ۢFӬ2"O֯Dv\lUkIDD bR^@(3)9Wd˥=z Yu-@n7vuM^_].Ƴ(å˯ȪmLJ<+e[Q^hڮ v+DDDTd-y.)0%ru*(eTe/:=\@LƲVCX{6mz VvpPKF5m&`d HWOY< I!gUzxR*FLQZ~*Q)U cqEWr4?d}8JPэ 7v5J^EM CPM*ڝQ}b|/OT(௎٧Q٩صQ1OS""ҩakO՟A Nph68WۿW?\ܱ{9j;JKIVvǴ.θϴ}Ҧ5j bZg8~U"""χLX,OxIx~5=&9AX2V:}EQRRUS>˿ӋE{~^ gJ, ڃ^N5;̽\3{xs2lMv\}U56ǝ<5/kJmcoۯlqe5V_m"1} l,4%""*Lg6+p2tgþh6`mޖH, krnhw+ %va92%=PZS>|^uc8k3?} A-h44jXj~3{n/ZLoSZC~;k~(`W*6C }O8"#ܪπhSrL%""*G= 1fQi.O.S0u%zE͏po@b־cc|^Q7U"""ʗ$_ s9-)YeJDDT J&K282=DDDDdU"""""&DDDDD*7 V!U""",wC&DDDDDLT*Q^'T H?˧Z|Y]?bQVs9"&J]jڛ%{ϣqFLT,O&B.EY#eHLԡVyeITmdUfIǰVv7&DDD,/օIDGER>G,dwgj:XYY!**DdPCX D:QHaT&FAXX(!W(h5P(䈍EHH0ZJ%"" 1+<< ёQ&c 1!rhWt2K"@$%ˑдXΞFZz |P(,bP!8dL Ve,H L Zm4T&VExxX qq&VXXXaT*Muh44n$'%An"VppD"r"##ƒJLb ˑh2d6.e&bBd*D,1<2Ēe82RX) 'cL ._Bdt 6z% 0Ok?aN~"}RQϞFAf H+~"$ABQp9}R^ sI׮"11 59O'O\<jԭWH'LI11+sw}TPY[ 7=\]*U g JJDB- ++A"CG/|ς\.d20e L& 6vbT*N uRc mlPRd,T*(VYƲ2V݄`2w?, Ajի  IDATR)&TZ-XVJ MƒL.7snH$T*U֫'?vd&LLa2֖]{f-[eKeme:KK,ڶǒH++eʖn{d2[ 1K& ?d nee+MJ>|+1VX,S[ =%,c:w*~¬>)9퓊B>EO2p-S@ sIy'L!t%_I'2"h'LIv–]{W9'U(pppX, ""prvT&#:PTw@ll agg:C*@RA&AecGgXYY N.HNNNHJL4 c)UPXY%e,GgllLƲA,RvdprvƓǁYr@TdXFc9:@ae{lb֭X1KR9XNj4&c!99 VbB"raTdǁ Xb:3llİXbN 1+MJ>|+1VX,箓3"#Ԑ尲Re sI'r'm? EJ{(~"}'T9}R 3I]J\ai~¬>D~BTA&.S'LIPT* |.X(L6q! b{ ć*U""""bJDDDDD1Q%""""bJDDDDLTU"""""&DDDDD*U""""bJDDDDDQp`ܒc02Ѵy 郆 CʕKm]ݽs;m10 l` Clް֬bmc>c`:VkV1z,ʲJm7f6;fFeZ&vv9++%o݅ںUxXFv ؘ4U .UnHpԉlsvv!HXi%ت0{tݵ05hJokrm;t,I*89;if-۳[l\mw0kJ};]`Z t "(=f%_& ;uf%:tJJ,ë4cP(\}.P(R/.BY jn93gBKvBYd7a~2Q` sిe> K?DՂe5axd5a'//IN_~q/?sa??J'SBY:?? 5YUFLdZ:o-$8y_>ybOPy% py\\;IhC$A _U3@Ilȵ_Ns--&Ƿ|XX\b/.?F>,*X"߿zT&qU̝Lat҅qI4mڬHrŊ8r봀NkصײK|qi4iҤv== HMVX Rڎ-?~~&>2~"ίI^ϟ?3@sws+Yyph:pvr̔ڨxA?C$l8r$P2x#)) ӿ]<US @*Sre1c޼ysސ-D q:QhrD, hUŵ˜ ӧO=|0j V/bίR)1;u6 ˡ-it:+W||,U۷omoo;ĢQ<|0vmbEbBc2K&MT*n۶-+% cXqQT 1]V ٯ˗Ov|ڿ]A?_R%< ͚52@FSj޼9r9Yfiқԯ_?BI铜ZjB5k}62DKڐ*Lk׮+BT*4nؠ=5~ɩU*>ӮDHMPo -p؟R_ԋ ˗1Wv1XTJPM6y4o~~~Ĥm۶BIIN XX͚5T¸q8쟃#G",JرcYfĉBIi|MT*VD1fmm]bFI"" =PINrRU""""bJDDDDD1Q%""""&dH@lĶBDTHJm,e5=+7Ê? [̊?[ /FI]%J;SǾ0qV8o .BIm+A׏c۾qn "b!U-;A5J\tb nV#Vr8"&TWJ ө0u-JǶreqAx &ǽqHI/%:Q-/ jHeR01UipBqq>_-2b+t|w4zAYgԯp./sJt]U0^Iۊz)XLt*ǞJ_ݱ- |8c-" l؆7Jޜ+݅?ĽPغf@QNiLqZ>27GedNZz&׉ mŕ{O(VboZ3/cƝ|\=cڠl_kN[їn ,* {g| 3eY2D=Î@Eڹ<7!Q*2RWfsʝձ6:m0[_\m1oi&ö;qmDAajuwQoNVe\j4 rFذ1/s Ux`Hm29s{ont˷ %ܜ ԥ v[駽}n"$"5<+~f~kML.]Ã/B^׸)0wQzR\ K'}~7.f}Q!UXuQv^_O7틏Drz{7.ϱ/Qs2TSf>5ͩl{ӖDN@#0ꭶpwee]k/Nc>nB+9ug%sBzC=0c"r"AuZ3{ZYWq8z|ګAz:ٕqPrs4wj3@AƟ7~f{kۥ>mX{- ~(<=8Kprm v0Fm=2 t5vج\Wƍ[Kq4v4oտVXL[)ղ1[ d)ɾ_XS~UC]cOРjٴuNYMҿ3s͏0QhXrx{ uD,75<$s$խ~/fo1mj>k EǭD9>pgD񤑰dXG$Am/ȴCetԄM;$m;/$%I,= hm̯%[7Y9qNVFml\3ӢlJqlt_5~Ųƻ~HɊ¡#_' 됬tr22 B604nB4sVѵ F7;z[fmJVP3O1whkPv5k k}ݩę+E.5@)_ƴQ8$ro~-*[T[)z迻e:؍s>˺ek|]sFkh-m*^3A6TjY(Q`Eա_]܌?J8ͭˠ_U))ű  CfnRͿ,r{ćڧ"Tq; :(ldz-xo_ҋR}EUfjDq_FC]yȍHS3ͳ1zew.&X\Fj,RR/6|s&+ꔇ$bSfSc0PE&SvMTɎG>Ss ?џۖ5~~YcIt9}$5[XbRw fmIj/`t71j8W)+ό<ԕZCi<b1BuZ'kndQjquh/!\# $Yk AzK R":qc%$囷=kڠ/8oFILYx͐~^ˬ5sfa03X^`g$i#SMdwv$hwJ4jD{@?ztm{J"N0xطERթ 7#Iȼw!~yZǜͽ5O`kZfY~sܖ9+&L[x[ hO7,a8\:p_ݼDu#nMjWxK, )ҝ׌׎.mJ-лE&FL݌{/hxb UUŧ]^I=};>Fm2D]l4}|o" Ljd /\jht`IHbquXy8Ĉz[h5P? yQR{|0+ϱL*ÆJ,F( h~P1˵ ̥ ݏ(#>|J\{$M2߼:XS:is6]3W@ƑQ\9a@sܔ9Q}_ٌD>3#5At[^@PD,: Bkq] 19EA":NY XySu}ڴT¯ax Vp>l{Iм{; WAYTB"Vқ<=7 j+t-oBK<3 hSF/bIؔ2*_kՙmXWğ|Ò`+L;XDtt1,"4q?}݌w; Ib~_AU=2^vΘ o[ εozIKC0 Ɣ9r r`H$F~D[We1oHl9=sScsV"Z>e9JSmLuvlksb:khNa۽KQia@fؼߛodؒ5w_:Klѧ_lv aw/cn ~#)X~ryij+LTX0+7۹Ok*~T.~w"6Y D]nsy`qa(ʸ^ݷYzuظi.^ @DLWGAcѣ--iQ׆ta l._ uLl\Q^stSKkcԽ&6؏Iѭ":*siifs ƲE5m?t-!+lY6:}͗uuPwl˞s?e֘}~TnlpuRBGi#^oq <F |0콲|*>yVp* vE/*SCs x%4P9śMJVq&hU[)Wu%xF ofyrL6 œ@3Hi ?smclXeoݾHbnW,ǏQlDN  [3M.;G|QWQH:wG΅H$?7'OD`ȫs~رKa ?S,ΗuyMxvCbG6Y٫ϳ5Kz|-ӧQrf-_bi6'/vKR]Nmx]0|2|hPû b /Wo6h 6m@yrA0CQ&T*X|%j̙:_zoϜneK<$+gS̼lt<;(D$m2$DVWNiWU *ކbGP,BzuOKDPI:ѽγ>N8b {Cr)*O gIDATnuOt6 GvϝgOFaKaqP?@$cX)EOoM\Jf}N*1NCSUkkg`\th(yPU;KšסªQW/ag}}% igU1_RۢOmB2m%=7.\2&bf-ϡr;m!\L=oƀ&~OG ugTm]yEpuۜyӡޣZUCIg?8^R#I'3xCѴ=S~&}:z(bE֨3&O;j!'E%aӚ5MXa 5c7!Ky&.W爈FAA]U%Gr{Trև F~~Rm`-\"};X#GgLa>D%UOicCĬ""""bJDDDDD1Q%""""&DDDDDLTU""""_|,,ܾ}ZrWbʕT*,lwдE?r+R9d2$''}yf疥_%+ wI#00GaPY٫_Rx*ӧOQr ,AX AbY 6&bO>rE -R*`a'LI[~0t:Xԇ}M$É l:K+#W(X|X}Q`jXp>c3Ml2b-2Q%""""=DDDDD*1Q%""""bJDDDDLT1Q%""""&DDDDDLT*U""""bJDDDDD*1Q%""""bJDDDDLTU"""""&DDDDD? xiIENDB`podofo-0.9.3/doc/latex/0000775000175000017500000000000012356565167014563 5ustar dominikdominikpodofo-0.9.3/podofo_config.h.in0000664000175000017500000000352012347347566016273 0ustar dominikdominik/* Template filled out by CMake */ /* * *** THIS HEADER IS INCLUDED BY PdfCompilerCompat.h *** * *** DO NOT INCLUDE DIRECTLY *** */ #ifndef _PDF_COMPILERCOMPAT_H #error Please include PdfDefines.h instead #endif #define PODOFO_VERSION_MAJOR @PODOFO_VERSION_MAJOR@ #define PODOFO_VERSION_MINOR @PODOFO_VERSION_MINOR@ #define PODOFO_VERSION_PATCH @PODOFO_VERSION_PATCH@ /* PoDoFo configuration options */ #cmakedefine PODOFO_MULTI_THREAD /* somewhat platform-specific headers */ #cmakedefine PODOFO_HAVE_STRINGS_H 1 #cmakedefine PODOFO_HAVE_ARPA_INET_H 1 #cmakedefine PODOFO_HAVE_WINSOCK2_H 1 #cmakedefine PODOFO_HAVE_MEM_H 1 #cmakedefine PODOFO_HAVE_CTYPE_H 1 /* Integer types - headers */ #cmakedefine PODOFO_HAVE_STDINT_H 1 #cmakedefine PODOFO_HAVE_BASETSD_H 1 #cmakedefine PODOFO_HAVE_SYS_TYPES_H 1 /* Integer types - type names */ #cmakedefine PDF_INT8_TYPENAME @PDF_INT8_TYPENAME@ #cmakedefine PDF_INT16_TYPENAME @PDF_INT16_TYPENAME@ #cmakedefine PDF_INT32_TYPENAME @PDF_INT32_TYPENAME@ #cmakedefine PDF_INT64_TYPENAME @PDF_INT64_TYPENAME@ #cmakedefine PDF_UINT8_TYPENAME @PDF_UINT8_TYPENAME@ #cmakedefine PDF_UINT16_TYPENAME @PDF_UINT16_TYPENAME@ #cmakedefine PDF_UINT32_TYPENAME @PDF_UINT32_TYPENAME@ #cmakedefine PDF_UINT64_TYPENAME @PDF_UINT64_TYPENAME@ /* Sizes of int64 and long, to pick proper printf format */ #cmakedefine SZ_INT64 @SZ_INT64@ #cmakedefine SZ_LONG @SZ_LONG@ /* Endianness */ #cmakedefine TEST_BIG /* Features */ #cmakedefine PODOFO_NO_FONTMANAGER /* Libraries */ #cmakedefine PODOFO_HAVE_JPEG_LIB #cmakedefine PODOFO_HAVE_PNG_LIB #cmakedefine PODOFO_HAVE_TIFF_LIB #cmakedefine PODOFO_HAVE_FONTCONFIG #cmakedefine PODOFO_HAVE_LUA #cmakedefine PODOFO_HAVE_BOOST #cmakedefine PODOFO_HAVE_CPPUNIT #cmakedefine PODOFO_HAVE_OPENSSL #cmakedefine PODOFO_HAVE_LIBIDN /* Platform quirks */ #cmakedefine PODOFO_JPEG_RUNTIME_COMPATIBLE podofo-0.9.3/CODINGSTYLE.txt0000664000175000017500000003002511460071654015212 0ustar dominikdominikThis document tries to give an overview of the codingstyle used in PoDoFo. To keep the code consistent every commit should apply to this codingstyle. The codingstyle of PoDoFo is in no way perfect and is in parts not even the preferred codingstyle of the maintainers. But consistency is more important than personal preferences and most parts of the style can be applied through simple editor settings. 2006 Dominik Seichter 0. Overall Rule =============== Documentation is an important part of PoDoFo. Every class and method should include appropriate documentation in Doxygen format so that automatic API documentation can be generated and the code can be easily understand by everyone. The comments are most important in the header files, though additional information may also be included in the source itself if necessary. 1. Code formatting ================== 1.1 Indentation The code is indented by 4 spaces. No tabs and no discussion ;) 1.2 Brackets Brackets always start in a new line of their own. The only exception are class and struct declarations and try and catch blocks. Example: if( true ) { // do something } but class MyClass { }; If only one line follows after an if or while statement, no brackets are needed, however they may be used if the author feels that there is a possibility for future expansion in that area. 1.3 Inline functions Inline functions are declared in the class definition in the header file. They are implemented in the header file after the class definition. The author may choose to either implement them directly at the same location as the declaration or may place them at the end of the header file (preferred). 2. Naming ========= 2.1 Variables Someone started to use hungarian notation in PoDoFo. Well, the maintainer thinks this was one of the worst ideas he ever had... . Nontheless, the point is consistency and not personall preference. PoDoFo uses hungarian notation for the following types: enum typenames should start with an E enum variables should start with an e struture typesnames should start with a T struture variables should start with a t pointer should start with a p strings should start with a s c-strings should start with psz (pointer zero terminated) numbers should start with a n long's should start with a l bool's should start with a b references often start with a r Example: bool bDecision; long lValue; char* pszString; int nNumber; 2.2 Member variables Member variables in classes are additionally prefixed with "m_". Examples: class MyClass { private: bool m_bMemberVar; }; 2.3 Methods All methods start with an uppercase letter and every new word is capitalized again. MyClass::FunctionWithLongName( long lParameter ); Properties are set using a function with the prefix "Set", and retrieved with a "Get". Also, unless there is a good reason not to - all "Getters" should be marked as const. MyClass::SetProperty( long lValue ); long MyClass::GetProperty() const; Additionally, please use the prefixes "Has" and "Is" when appropriate. E.g. PdfDictionary::HasKey(); PdfDocument::IsLinearized(); Avoid the throw() qualifier (see 3.5). 2.4 NULL-Pointers NULL Pointers are initialized in the code with the constant NULL. Please do not use 0 or 0L but use NULL. 3. General Guidelines =================== 3.1 Casting C++ style casting is strongly preferred, and the use of C-style casts will generate warnings on gcc builds. Use, as appropriate, static_cast<> const_cast<> reinterpret_cast<> Dynamic casting and typeid are not presently used in PoDoFo. const_cast<> should be avoided unless it is absolutely required, especially for `const char *' variables that might ever take a string literal value. 3.2 Local variable declaration Local variables should always be declared closest to their point of use, and should be declared `const' wherever possible. For example: Thing f() { Thing ret; // blah blah blah ret = DoSomething(); // blah blah blah return ret; } would be better written as: Thing f() { // blah blah blah Thing ret ( DoSomething() ); // blah blah blah return ret; } Remember your const pointers: char * x; Pointer to char const char * x; Pointer to const char char * const x; Const pointer to char const char * const x; Const pointer to const char 3.3 Static arrays Static data should be declared as an array of const char rather than a pointer to const char whereever possible. This will help the compiler put it in the static read only data section of the compiled object, resulting in a smaller memory footprint, faster load times, and hardware protection against accidental writes to the data. const char myStaticData[] = "This is the right way". const char * myStaticData = "Avoid this way". Two dimensional arrays may be specified in a similar way - see s_szPdfVersions in PdfDefines.{cpp,h} . It's usually better to waste a few bytes by padding the array to the length of the longest member and get it into the readonly data section of the executable than it is to use an array of pointers to char and save a few bytes. Which is best is, however, dependent on what "a few bytes" is in a given situation. 3.4 Use of temporary objects Where possible, it can be better to use a temporary rather than storing a named object, eg: DoSomething( PdfName("blah") ); rather than PdfName n("blah"); DoSomething( n ); as this makes it easier for the compiler to optimise the call, may reduce the stack size of the function, etc. Don't forget to consider the lifetime of the temporary, however. 3.5 The `throw' qualifier Under no circumstances use exception specifiers, even the empty exception specifier `throw()'. C++ checked exceptions - when implemented according to the standard - are essentially useless and may actually be costly. If you want to tell the compiler a method will not throw (as an optimisation) use a macro for __declspec(nothrow) instead. podofoapi provides appropriate macros for use in podofo. (Note that VC++ treats throw() as __declspec(nothrow) in violation of the standard, but that's all the more reason to just use __declspec(nothrow)). see: http://msdn2.microsoft.com/en-us/library/49147z04.aspx http://gcc.gnu.org/onlinedocs/gcc-3.3.1/gcc/Function-Attributes.html 3.6 Exported API PoDoFo draws a distinction between exported and private API on some platforms (currently Windows DLL builds and gcc 4 with PODOFO_USE_VISIBILITY). To do this it uses some macros defined in podofoapi.h to tell the compiler what's public API that should appear in the DLL/shared library's symbol table. The rest is not exported. This may have several positive effects depending on the particular platform and compiler. It can result in a smaller binary, better link times, help the compiler optimise better, and ensure that API intended to be private to PoDoFo _cannot_ be called from outside it. If you add new classes to PoDoFo, annotate them with PODOFO_API as shown in podofoapi.h if they're intended as public API. If an outside user will ever need to reference those symbols directly (by constructing the class, calling its methods, etc) they're public. Note that classes that only inherit and implement an abstract interface (adding no other public methods intended for use outside PoDoFo) that're only constructed through a factory or through other PoDoFo classes need not be exported. If you have a class that needs to be exported as public API, but it has quite a few methods that do not need to be externally visible (private helper methods etc), you can annotate those with the PODOFO_LOCAL macro as shown in podofoapi.h . This omits just those methods from the symbol table. Note that if the methods are accessed via public or protected inline functions it is not safe to make them private. If in doubt, ask for help on podofo-users. It also helps to build PoDoFo as a DLL (Windows) or, on UNIX platforms, use gcc4 and enable visibility support. This will help catch cases where you forgot to export required API. 3.7 Memory allocations in inlined methods It's not safe to (directly) allocate or free heap memory in an inlined function, because it only works if the same runtime library is used in the shared library and the executable linking to the library. Using malloc and/or new in inlined methods will lead to crashes on MS Windows systems. It might be undetected on Linux systems (even though it is bad style on Linux, too), because most processes and libraries use the same runtime library on a Linux system. There's also no point inlining functions that call new / delete / malloc / free, because the memory allocation is dramatically more expensive than a mere function call is. Using STL classes that may perform allocations internally is fine since they tend to carry their own std::allocator instance (or reference, anyway) around with them. 3.8 Visibility of 3rd party headers If at all possible, it's desirable not to expose the use of 3rd party headers in the PoDoFo headers. Rather than including headers for required libraries, try to forward-declare required types and then include the header in the implementation (.cpp) files. If the header is widely used, you might want to put it in PdfDefinesPrivate.h . Widely used forward declarations can go in Pdf3rdPtyForwardDecl.h . Avoiding exposing used 3rd party headers means that users' build systems don't need to know how to find those headers, and means that users' programs don't get their namespaces polluted by unrelated symbols from libjpeg, zlib, libtiff, freetype, etc etc etc. As some headers (*cough*freetype*cough*) aren't trivial to reliably locate, this can really simplify the build of tools that use PoDoFo. This applies to some system headers too. for example is a difficult and quirky header. Its behaviour is strongly affected by a variety of preprocessor definitions and it scatters macros everywhere. We shouldn't be exposing it to library users, because it's quite likely they'll need to include it with different macro parameters, and theirs may conflict with ours or vice versa. If you need to include a 3rd party header to make something a direct member, consider making it a member by pointer instead, initializing it in the object's ctor and destroying it it the dtor. That way you don't need to include the 3rd party's header to get access to their type sizes in the PoDoFo headers, only in the .cpp files. See, for example, PdfMutex.h . 4. Structure ============ 4.1 Project structure The PoDoFo project is structure as follows. There are two libraries: podofo-base and podofo-doc. Podofo-base contains everythign needed to work with reading, writing and modifying PDF files and there objects. It should have a minimal set of dependencies. Podofo-doc provides a rich interface, which also allows to easily create PDF files using the PdfPainter and PdfFont infrastructure. Additionally, there are two more projects. The test/ subdirectory contains tests for both libraries. All new tests shall go to the test/unit/ sub-projects to provide unit-tests for PoDoFo. Utility programs that come with PoDoFo go into the tools/ subdirectory. These tools provide a direct benefit for end users who want to work with PDF files on the commandline and are also a nice way to showcase the features of the PoDoFo libraries to new developers. podofo-0.9.3/COPYING.exception0000664000175000017500000000152412205463144015714 0ustar dominikdominik In addition, as a special exception, the copyright holders give permission to link the code of portions of this program with the OpenSSL library under certain conditions as described in each individual source file, and distribute linked combinations including the two. You must obey the GNU General Public License in all respects for all of the code used other than OpenSSL. If you modify file(s) with this exception, you may extend this exception to your version of the file(s), but you are not obligated to do so. If you do not wish to do so, delete this exception statement from your version. If you delete this exception statement from all source files in the program, then also delete it here. podofo-0.9.3/CONTRIBUTIONS.txt0000664000175000017500000000624211336742344015477 0ustar dominikdominikThis document describes how to contribute code to PoDoFo. 2010 Dominik Seichter 0. Code quality =============== Before you submit or commit code to PoDoFo (assuming you made a modification), you should make sure that your code adheres to the codingstyle guidelines (see CODINGSTYLE.txt). Note that the codingstyle guidelines also include documenting every newly introduced method (Doxygen syntax). Additionally, your code should work on at least Linux and Windows operating systems. Portability is one main goal of PoDoFo, so it is important that the code is always buildable and runnable on all supported platforms. We usually test at least using GCC on Linux and using Visual Studio on Windows. Both 32bit and 64bit systems are target platforms. So if your code needs to work at bit and byte-levels, take this into account. Last but not least, all unit tests - especially test/unit/podofo-test - should run after your modification. 1. Submitting code ================== If you are contributing code for the first time, the usual procedure is to send a patch containing your modifications to the PoDoFo mailing list . We will check your code and commit it for you to the repository. A patch should always be created against latest SVN trunk. Such a patch can be created using the SVN command "svn diff" on the commandline. It is recommended that you also add a unit test for the modification you have made. If your modification is a bug fix, a unit test assures that no regression for this bug is introduced at a later point of time (as everyone runs the unit tests after every modification and before every commit). If you added a new feature, the unit test guarantees that the new code was at least tested once. Another very useful test is to run the test/ParserTest executable and see if is able to parse and write the PDFReference1*.pdf from Adobe correctly. 2. Getting a SVN account ======================== After we integrated some patches of yours successfully into SVN, you usually can also get a SVN account. Feel free to ask for it, or if we think of it we will offer an SVN account to you. Frequent submitters of patches are encouraged to ask for an SVN account, as it is easier for everyone if submitters of good quality patches can integrate these themselves. 3. Committing code ================== Using a SVN account you can commit your code yourself. If you are working on the main part of PoDoFo, you should announce or discuss your intended changes on the mailing lists. If you are maintaining a tool (under tools/) you can add features or make changes as you like. An important point is that every commit has to go with a commit log message that tells the other developers what your change does and why you made it. These changes can be tracked and discussed on the PoDoFo SVN mailinglist . Every commit is automatically send to this list. 4. Non-code contributions ========================= Besides to code, we are also interested in other contributions like documentation, feedback, examples, webpage, articles ... Ask on the mailinglist if you are interested in helping or joining the project. podofo-0.9.3/podofo/0000775000175000017500000000000012356565165014165 5ustar dominikdominikpodofo-0.9.3/podofo/podofo.h0000664000175000017500000000063510614711122015605 0ustar dominikdominik#ifndef PODOFO_WRAPPER_PODOFO_H #define PODOFO_WRAPPER_PODOFO_H /* * This is a simple wrapper include file that lets you include * when building against a podofo build directory * rather than an installed copy of podofo. You'll probably need * this if you're including your own (probably static) copy of podofo * using a mechanism like svn:externals . */ #include "../src/podofo.h" #endif podofo-0.9.3/podofo/compilercompat/0000775000175000017500000000000012356565165017203 5ustar dominikdominikpodofo-0.9.3/podofo/compilercompat/borland/0000775000175000017500000000000012356565165020624 5ustar dominikdominikpodofo-0.9.3/podofo/compilercompat/borland/ctime0000664000175000017500000000002211231022232021610 0ustar dominikdominik#include podofo-0.9.3/podofo/compilercompat/borland/cstdio0000664000175000017500000000002311231022232021775 0ustar dominikdominik#include podofo-0.9.3/podofo/base/0000775000175000017500000000000012356565165015077 5ustar dominikdominikpodofo-0.9.3/podofo/base/PdfDictionary.h0000664000175000017500000000070511535255326020002 0ustar dominikdominik #ifndef PODOFO_WRAPPER_PDFDICTIONARYH #define PODOFO_WRAPPER_PDFDICTIONARYH /* * This is a simple wrapper include file that lets you include * when building against a podofo build directory * rather than an installed copy of podofo. You'll probably need * this if you're including your own (probably static) copy of podofo * using a mechanism like svn:externals . */ #include "../../src/base/PdfDictionary.h" #endif podofo-0.9.3/podofo/base/PdfName.h0000664000175000017500000000065511535255326016561 0ustar dominikdominik #ifndef PODOFO_WRAPPER_PDFNAMEH #define PODOFO_WRAPPER_PDFNAMEH /* * This is a simple wrapper include file that lets you include * when building against a podofo build directory * rather than an installed copy of podofo. You'll probably need * this if you're including your own (probably static) copy of podofo * using a mechanism like svn:externals . */ #include "../../src/base/PdfName.h" #endif podofo-0.9.3/podofo/base/PdfXRefStream.h0000664000175000017500000000070511535255326017715 0ustar dominikdominik #ifndef PODOFO_WRAPPER_PDFXREFSTREAMH #define PODOFO_WRAPPER_PDFXREFSTREAMH /* * This is a simple wrapper include file that lets you include * when building against a podofo build directory * rather than an installed copy of podofo. You'll probably need * this if you're including your own (probably static) copy of podofo * using a mechanism like svn:externals . */ #include "../../src/base/PdfXRefStream.h" #endif podofo-0.9.3/podofo/base/create_forward_headers.sh0000775000175000017500000000217711535255326022120 0ustar dominikdominik#!/bin/bash function create_header { HEADER=$1 FILENAME=$(basename $HEADER) DEFINE=$(echo $FILENAME | tr '[:lower:]' '[:upper:]' | tr -d '[:punct:]' ) echo "Creating forward header $FILENAME" echo "" > $FILENAME echo "#ifndef PODOFO_WRAPPER_$DEFINE" >> $FILENAME echo "#define PODOFO_WRAPPER_$DEFINE" >> $FILENAME echo "/*" >> $FILENAME echo " * This is a simple wrapper include file that lets you include" >> $FILENAME echo " * when building against a podofo build directory" >> $FILENAME echo " * rather than an installed copy of podofo. You'll probably need" >> $FILENAME echo " * this if you're including your own (probably static) copy of podofo" >> $FILENAME echo " * using a mechanism like svn:externals ." >> $FILENAME echo " */" >> $FILENAME echo "#include \"$HEADER\"" >> $FILENAME echo "#endif" >> $FILENAME } HEADERS=$(find ../../src/base -name '*.h') for HEADER in $HEADERS; do create_header $HEADER done cd util UTIL_HEADERS=$(find ../../../src/base/util -name '*.h') for HEADER in $UTIL_HEADERS; do create_header $HEADER done cd .. podofo-0.9.3/podofo/base/PdfXRef.h0000664000175000017500000000065511535255326016545 0ustar dominikdominik #ifndef PODOFO_WRAPPER_PDFXREFH #define PODOFO_WRAPPER_PDFXREFH /* * This is a simple wrapper include file that lets you include * when building against a podofo build directory * rather than an installed copy of podofo. You'll probably need * this if you're including your own (probably static) copy of podofo * using a mechanism like svn:externals . */ #include "../../src/base/PdfXRef.h" #endif podofo-0.9.3/podofo/base/PdfInputStream.h0000664000175000017500000000071111535255326020145 0ustar dominikdominik #ifndef PODOFO_WRAPPER_PDFINPUTSTREAMH #define PODOFO_WRAPPER_PDFINPUTSTREAMH /* * This is a simple wrapper include file that lets you include * when building against a podofo build directory * rather than an installed copy of podofo. You'll probably need * this if you're including your own (probably static) copy of podofo * using a mechanism like svn:externals . */ #include "../../src/base/PdfInputStream.h" #endif podofo-0.9.3/podofo/base/PdfContentsTokenizer.h0000664000175000017500000000074111535255326021365 0ustar dominikdominik #ifndef PODOFO_WRAPPER_PDFCONTENTSTOKENIZERH #define PODOFO_WRAPPER_PDFCONTENTSTOKENIZERH /* * This is a simple wrapper include file that lets you include * when building against a podofo build directory * rather than an installed copy of podofo. You'll probably need * this if you're including your own (probably static) copy of podofo * using a mechanism like svn:externals . */ #include "../../src/base/PdfContentsTokenizer.h" #endif podofo-0.9.3/podofo/base/PdfDataType.h0000664000175000017500000000067511535255326017416 0ustar dominikdominik #ifndef PODOFO_WRAPPER_PDFDATATYPEH #define PODOFO_WRAPPER_PDFDATATYPEH /* * This is a simple wrapper include file that lets you include * when building against a podofo build directory * rather than an installed copy of podofo. You'll probably need * this if you're including your own (probably static) copy of podofo * using a mechanism like svn:externals . */ #include "../../src/base/PdfDataType.h" #endif podofo-0.9.3/podofo/base/PdfFileStream.h0000664000175000017500000000070511535255326017730 0ustar dominikdominik #ifndef PODOFO_WRAPPER_PDFFILESTREAMH #define PODOFO_WRAPPER_PDFFILESTREAMH /* * This is a simple wrapper include file that lets you include * when building against a podofo build directory * rather than an installed copy of podofo. You'll probably need * this if you're including your own (probably static) copy of podofo * using a mechanism like svn:externals . */ #include "../../src/base/PdfFileStream.h" #endif podofo-0.9.3/podofo/base/Pdf3rdPtyForwardDecl.h0000664000175000017500000000074111535255326021177 0ustar dominikdominik #ifndef PODOFO_WRAPPER_PDF3RDPTYFORWARDDECLH #define PODOFO_WRAPPER_PDF3RDPTYFORWARDDECLH /* * This is a simple wrapper include file that lets you include * when building against a podofo build directory * rather than an installed copy of podofo. You'll probably need * this if you're including your own (probably static) copy of podofo * using a mechanism like svn:externals . */ #include "../../src/base/Pdf3rdPtyForwardDecl.h" #endif podofo-0.9.3/podofo/base/PdfObject.h0000664000175000017500000000066511535255326017110 0ustar dominikdominik #ifndef PODOFO_WRAPPER_PDFOBJECTH #define PODOFO_WRAPPER_PDFOBJECTH /* * This is a simple wrapper include file that lets you include * when building against a podofo build directory * rather than an installed copy of podofo. You'll probably need * this if you're including your own (probably static) copy of podofo * using a mechanism like svn:externals . */ #include "../../src/base/PdfObject.h" #endif podofo-0.9.3/podofo/base/PdfTokenizer.h0000664000175000017500000000070111535255326017643 0ustar dominikdominik #ifndef PODOFO_WRAPPER_PDFTOKENIZERH #define PODOFO_WRAPPER_PDFTOKENIZERH /* * This is a simple wrapper include file that lets you include * when building against a podofo build directory * rather than an installed copy of podofo. You'll probably need * this if you're including your own (probably static) copy of podofo * using a mechanism like svn:externals . */ #include "../../src/base/PdfTokenizer.h" #endif podofo-0.9.3/podofo/base/PdfXRefStreamParserObject.h0000664000175000017500000000076511535255326022227 0ustar dominikdominik #ifndef PODOFO_WRAPPER_PDFXREFSTREAMPARSEROBJECTH #define PODOFO_WRAPPER_PDFXREFSTREAMPARSEROBJECTH /* * This is a simple wrapper include file that lets you include * when building against a podofo build directory * rather than an installed copy of podofo. You'll probably need * this if you're including your own (probably static) copy of podofo * using a mechanism like svn:externals . */ #include "../../src/base/PdfXRefStreamParserObject.h" #endif podofo-0.9.3/podofo/base/PdfRect.h0000664000175000017500000000065511535255326016576 0ustar dominikdominik #ifndef PODOFO_WRAPPER_PDFRECTH #define PODOFO_WRAPPER_PDFRECTH /* * This is a simple wrapper include file that lets you include * when building against a podofo build directory * rather than an installed copy of podofo. You'll probably need * this if you're including your own (probably static) copy of podofo * using a mechanism like svn:externals . */ #include "../../src/base/PdfRect.h" #endif podofo-0.9.3/podofo/base/PdfSigIncWriter.h0000664000175000017500000000071512320241702020231 0ustar dominikdominik #ifndef PODOFO_WRAPPER_PDFSIGINCWRITERH #define PODOFO_WRAPPER_PDFSIGINCWRITERH /* * This is a simple wrapper include file that lets you include * when building against a podofo build directory * rather than an installed copy of podofo. You'll probably need * this if you're including your own (probably static) copy of podofo * using a mechanism like svn:externals . */ #include "../../src/base/PdfSigIncWriter.h" #endif podofo-0.9.3/podofo/base/PdfVecObjects.h0000664000175000017500000000070511535255326017724 0ustar dominikdominik #ifndef PODOFO_WRAPPER_PDFVECOBJECTSH #define PODOFO_WRAPPER_PDFVECOBJECTSH /* * This is a simple wrapper include file that lets you include * when building against a podofo build directory * rather than an installed copy of podofo. You'll probably need * this if you're including your own (probably static) copy of podofo * using a mechanism like svn:externals . */ #include "../../src/base/PdfVecObjects.h" #endif podofo-0.9.3/podofo/base/PdfObjectStreamParserObject.h0000664000175000017500000000077511535255326022572 0ustar dominikdominik #ifndef PODOFO_WRAPPER_PDFOBJECTSTREAMPARSEROBJECTH #define PODOFO_WRAPPER_PDFOBJECTSTREAMPARSEROBJECTH /* * This is a simple wrapper include file that lets you include * when building against a podofo build directory * rather than an installed copy of podofo. You'll probably need * this if you're including your own (probably static) copy of podofo * using a mechanism like svn:externals . */ #include "../../src/base/PdfObjectStreamParserObject.h" #endif podofo-0.9.3/podofo/base/PdfOutputDevice.h0000664000175000017500000000071511535255326020316 0ustar dominikdominik #ifndef PODOFO_WRAPPER_PDFOUTPUTDEVICEH #define PODOFO_WRAPPER_PDFOUTPUTDEVICEH /* * This is a simple wrapper include file that lets you include * when building against a podofo build directory * rather than an installed copy of podofo. You'll probably need * this if you're including your own (probably static) copy of podofo * using a mechanism like svn:externals . */ #include "../../src/base/PdfOutputDevice.h" #endif podofo-0.9.3/podofo/base/podofoapi.h0000664000175000017500000000066511535255326017230 0ustar dominikdominik #ifndef PODOFO_WRAPPER_PODOFOAPIH #define PODOFO_WRAPPER_PODOFOAPIH /* * This is a simple wrapper include file that lets you include * when building against a podofo build directory * rather than an installed copy of podofo. You'll probably need * this if you're including your own (probably static) copy of podofo * using a mechanism like svn:externals . */ #include "../../src/base/podofoapi.h" #endif podofo-0.9.3/podofo/base/PdfInputDevice.h0000664000175000017500000000071111535255326020111 0ustar dominikdominik #ifndef PODOFO_WRAPPER_PDFINPUTDEVICEH #define PODOFO_WRAPPER_PDFINPUTDEVICEH /* * This is a simple wrapper include file that lets you include * when building against a podofo build directory * rather than an installed copy of podofo. You'll probably need * this if you're including your own (probably static) copy of podofo * using a mechanism like svn:externals . */ #include "../../src/base/PdfInputDevice.h" #endif podofo-0.9.3/podofo/base/PdfLocale.h0000664000175000017500000000066511535255326017101 0ustar dominikdominik #ifndef PODOFO_WRAPPER_PDFLOCALEH #define PODOFO_WRAPPER_PDFLOCALEH /* * This is a simple wrapper include file that lets you include * when building against a podofo build directory * rather than an installed copy of podofo. You'll probably need * this if you're including your own (probably static) copy of podofo * using a mechanism like svn:externals . */ #include "../../src/base/PdfLocale.h" #endif podofo-0.9.3/podofo/base/PdfVersion.h0000664000175000017500000000067111535255326017324 0ustar dominikdominik #ifndef PODOFO_WRAPPER_PDFVERSIONH #define PODOFO_WRAPPER_PDFVERSIONH /* * This is a simple wrapper include file that lets you include * when building against a podofo build directory * rather than an installed copy of podofo. You'll probably need * this if you're including your own (probably static) copy of podofo * using a mechanism like svn:externals . */ #include "../../src/base/PdfVersion.h" #endif podofo-0.9.3/podofo/base/PdfImmediateWriter.h0000664000175000017500000000073111535255326020767 0ustar dominikdominik #ifndef PODOFO_WRAPPER_PDFIMMEDIATEWRITERH #define PODOFO_WRAPPER_PDFIMMEDIATEWRITERH /* * This is a simple wrapper include file that lets you include * when building against a podofo build directory * rather than an installed copy of podofo. You'll probably need * this if you're including your own (probably static) copy of podofo * using a mechanism like svn:externals . */ #include "../../src/base/PdfImmediateWriter.h" #endif podofo-0.9.3/podofo/base/PdfRijndael.h0000664000175000017500000000067511535255326017433 0ustar dominikdominik #ifndef PODOFO_WRAPPER_PDFRIJNDAELH #define PODOFO_WRAPPER_PDFRIJNDAELH /* * This is a simple wrapper include file that lets you include * when building against a podofo build directory * rather than an installed copy of podofo. You'll probably need * this if you're including your own (probably static) copy of podofo * using a mechanism like svn:externals . */ #include "../../src/base/PdfRijndael.h" #endif podofo-0.9.3/podofo/base/PdfOutputStream.h0000664000175000017500000000071511535255326020352 0ustar dominikdominik #ifndef PODOFO_WRAPPER_PDFOUTPUTSTREAMH #define PODOFO_WRAPPER_PDFOUTPUTSTREAMH /* * This is a simple wrapper include file that lets you include * when building against a podofo build directory * rather than an installed copy of podofo. You'll probably need * this if you're including your own (probably static) copy of podofo * using a mechanism like svn:externals . */ #include "../../src/base/PdfOutputStream.h" #endif podofo-0.9.3/podofo/base/PdfParser.h0000664000175000017500000000066511535255326017136 0ustar dominikdominik #ifndef PODOFO_WRAPPER_PDFPARSERH #define PODOFO_WRAPPER_PDFPARSERH /* * This is a simple wrapper include file that lets you include * when building against a podofo build directory * rather than an installed copy of podofo. You'll probably need * this if you're including your own (probably static) copy of podofo * using a mechanism like svn:externals . */ #include "../../src/base/PdfParser.h" #endif podofo-0.9.3/podofo/base/PdfReference.h0000664000175000017500000000070111535255326017567 0ustar dominikdominik #ifndef PODOFO_WRAPPER_PDFREFERENCEH #define PODOFO_WRAPPER_PDFREFERENCEH /* * This is a simple wrapper include file that lets you include * when building against a podofo build directory * rather than an installed copy of podofo. You'll probably need * this if you're including your own (probably static) copy of podofo * using a mechanism like svn:externals . */ #include "../../src/base/PdfReference.h" #endif podofo-0.9.3/podofo/base/PdfCompilerCompatPrivate.h0000664000175000017500000000076111535255326022150 0ustar dominikdominik #ifndef PODOFO_WRAPPER_PDFCOMPILERCOMPATPRIVATEH #define PODOFO_WRAPPER_PDFCOMPILERCOMPATPRIVATEH /* * This is a simple wrapper include file that lets you include * when building against a podofo build directory * rather than an installed copy of podofo. You'll probably need * this if you're including your own (probably static) copy of podofo * using a mechanism like svn:externals . */ #include "../../src/base/PdfCompilerCompatPrivate.h" #endif podofo-0.9.3/podofo/base/PdfRefCountedBuffer.h0000664000175000017500000000073511535255326021070 0ustar dominikdominik #ifndef PODOFO_WRAPPER_PDFREFCOUNTEDBUFFERH #define PODOFO_WRAPPER_PDFREFCOUNTEDBUFFERH /* * This is a simple wrapper include file that lets you include * when building against a podofo build directory * rather than an installed copy of podofo. You'll probably need * this if you're including your own (probably static) copy of podofo * using a mechanism like svn:externals . */ #include "../../src/base/PdfRefCountedBuffer.h" #endif podofo-0.9.3/podofo/base/PdfEncrypt.h0000664000175000017500000000067111535255326017323 0ustar dominikdominik #ifndef PODOFO_WRAPPER_PDFENCRYPTH #define PODOFO_WRAPPER_PDFENCRYPTH /* * This is a simple wrapper include file that lets you include * when building against a podofo build directory * rather than an installed copy of podofo. You'll probably need * this if you're including your own (probably static) copy of podofo * using a mechanism like svn:externals . */ #include "../../src/base/PdfEncrypt.h" #endif podofo-0.9.3/podofo/base/PdfMutexImpl_pthread.h0000664000175000017500000000074411535255326021333 0ustar dominikdominik #ifndef PODOFO_WRAPPER_PDFMUTEXIMPLPTHREADH #define PODOFO_WRAPPER_PDFMUTEXIMPLPTHREADH /* * This is a simple wrapper include file that lets you include * when building against a podofo build directory * rather than an installed copy of podofo. You'll probably need * this if you're including your own (probably static) copy of podofo * using a mechanism like svn:externals . */ #include "../../src/base/util/PdfMutexImpl_pthread.h" #endif podofo-0.9.3/podofo/base/PdfMemoryManagement.h0000664000175000017500000000073511535255326021145 0ustar dominikdominik #ifndef PODOFO_WRAPPER_PDFMEMORYMANAGEMENTH #define PODOFO_WRAPPER_PDFMEMORYMANAGEMENTH /* * This is a simple wrapper include file that lets you include * when building against a podofo build directory * rather than an installed copy of podofo. You'll probably need * this if you're including your own (probably static) copy of podofo * using a mechanism like svn:externals . */ #include "../../src/base/PdfMemoryManagement.h" #endif podofo-0.9.3/podofo/base/PdfArray.h0000664000175000017500000000066111535255326016754 0ustar dominikdominik #ifndef PODOFO_WRAPPER_PDFARRAYH #define PODOFO_WRAPPER_PDFARRAYH /* * This is a simple wrapper include file that lets you include * when building against a podofo build directory * rather than an installed copy of podofo. You'll probably need * this if you're including your own (probably static) copy of podofo * using a mechanism like svn:externals . */ #include "../../src/base/PdfArray.h" #endif podofo-0.9.3/podofo/base/PdfEncodingFactory.h0000664000175000017500000000073111535255326020752 0ustar dominikdominik #ifndef PODOFO_WRAPPER_PDFENCODINGFACTORYH #define PODOFO_WRAPPER_PDFENCODINGFACTORYH /* * This is a simple wrapper include file that lets you include * when building against a podofo build directory * rather than an installed copy of podofo. You'll probably need * this if you're including your own (probably static) copy of podofo * using a mechanism like svn:externals . */ #include "../../src/base/PdfEncodingFactory.h" #endif podofo-0.9.3/podofo/base/PdfFilter.h0000664000175000017500000000066511535255326017127 0ustar dominikdominik #ifndef PODOFO_WRAPPER_PDFFILTERH #define PODOFO_WRAPPER_PDFFILTERH /* * This is a simple wrapper include file that lets you include * when building against a podofo build directory * rather than an installed copy of podofo. You'll probably need * this if you're including your own (probably static) copy of podofo * using a mechanism like svn:externals . */ #include "../../src/base/PdfFilter.h" #endif podofo-0.9.3/podofo/base/PdfExtension.h0000664000175000017500000000070112320241722017631 0ustar dominikdominik #ifndef PODOFO_WRAPPER_PDFEXTENSIONH #define PODOFO_WRAPPER_PDFEXTENSIONH /* * This is a simple wrapper include file that lets you include * when building against a podofo build directory * rather than an installed copy of podofo. You'll probably need * this if you're including your own (probably static) copy of podofo * using a mechanism like svn:externals . */ #include "../../src/base/PdfExtension.h" #endif podofo-0.9.3/podofo/base/PdfDefines.h0000664000175000017500000000067111535255326017254 0ustar dominikdominik #ifndef PODOFO_WRAPPER_PDFDEFINESH #define PODOFO_WRAPPER_PDFDEFINESH /* * This is a simple wrapper include file that lets you include * when building against a podofo build directory * rather than an installed copy of podofo. You'll probably need * this if you're including your own (probably static) copy of podofo * using a mechanism like svn:externals . */ #include "../../src/base/PdfDefines.h" #endif podofo-0.9.3/podofo/base/PdfData.h0000664000175000017500000000065511535255326016552 0ustar dominikdominik #ifndef PODOFO_WRAPPER_PDFDATAH #define PODOFO_WRAPPER_PDFDATAH /* * This is a simple wrapper include file that lets you include * when building against a podofo build directory * rather than an installed copy of podofo. You'll probably need * this if you're including your own (probably static) copy of podofo * using a mechanism like svn:externals . */ #include "../../src/base/PdfData.h" #endif podofo-0.9.3/podofo/base/util/0000775000175000017500000000000012356565165016054 5ustar dominikdominikpodofo-0.9.3/podofo/base/util/PdfMutexImpl_pthread.h0000664000175000017500000000074711535255326022313 0ustar dominikdominik #ifndef PODOFO_WRAPPER_PDFMUTEXIMPLPTHREADH #define PODOFO_WRAPPER_PDFMUTEXIMPLPTHREADH /* * This is a simple wrapper include file that lets you include * when building against a podofo build directory * rather than an installed copy of podofo. You'll probably need * this if you're including your own (probably static) copy of podofo * using a mechanism like svn:externals . */ #include "../../../src/base/util/PdfMutexImpl_pthread.h" #endif podofo-0.9.3/podofo/base/util/PdfMutex.h0000664000175000017500000000067111535255326017756 0ustar dominikdominik #ifndef PODOFO_WRAPPER_PDFMUTEXH #define PODOFO_WRAPPER_PDFMUTEXH /* * This is a simple wrapper include file that lets you include * when building against a podofo build directory * rather than an installed copy of podofo. You'll probably need * this if you're including your own (probably static) copy of podofo * using a mechanism like svn:externals . */ #include "../../../src/base/util/PdfMutex.h" #endif podofo-0.9.3/podofo/base/util/PdfMutexImpl_win32.h0000664000175000017500000000073711535255326021625 0ustar dominikdominik #ifndef PODOFO_WRAPPER_PDFMUTEXIMPLWIN32H #define PODOFO_WRAPPER_PDFMUTEXIMPLWIN32H /* * This is a simple wrapper include file that lets you include * when building against a podofo build directory * rather than an installed copy of podofo. You'll probably need * this if you're including your own (probably static) copy of podofo * using a mechanism like svn:externals . */ #include "../../../src/base/util/PdfMutexImpl_win32.h" #endif podofo-0.9.3/podofo/base/util/PdfMutexImpl_noop.h0000664000175000017500000000073311535255326021632 0ustar dominikdominik #ifndef PODOFO_WRAPPER_PDFMUTEXIMPLNOOPH #define PODOFO_WRAPPER_PDFMUTEXIMPLNOOPH /* * This is a simple wrapper include file that lets you include * when building against a podofo build directory * rather than an installed copy of podofo. You'll probably need * this if you're including your own (probably static) copy of podofo * using a mechanism like svn:externals . */ #include "../../../src/base/util/PdfMutexImpl_noop.h" #endif podofo-0.9.3/podofo/base/util/PdfMutexWrapper.h0000664000175000017500000000072511535255326021317 0ustar dominikdominik #ifndef PODOFO_WRAPPER_PDFMUTEXWRAPPERH #define PODOFO_WRAPPER_PDFMUTEXWRAPPERH /* * This is a simple wrapper include file that lets you include * when building against a podofo build directory * rather than an installed copy of podofo. You'll probably need * this if you're including your own (probably static) copy of podofo * using a mechanism like svn:externals . */ #include "../../../src/base/util/PdfMutexWrapper.h" #endif podofo-0.9.3/podofo/base/PdfFiltersPrivate.h0000664000175000017500000000072511535255326020642 0ustar dominikdominik #ifndef PODOFO_WRAPPER_PDFFILTERSPRIVATEH #define PODOFO_WRAPPER_PDFFILTERSPRIVATEH /* * This is a simple wrapper include file that lets you include * when building against a podofo build directory * rather than an installed copy of podofo. You'll probably need * this if you're including your own (probably static) copy of podofo * using a mechanism like svn:externals . */ #include "../../src/base/PdfFiltersPrivate.h" #endif podofo-0.9.3/podofo/base/PdfColor.h0000664000175000017500000000066111535255326016754 0ustar dominikdominik #ifndef PODOFO_WRAPPER_PDFCOLORH #define PODOFO_WRAPPER_PDFCOLORH /* * This is a simple wrapper include file that lets you include * when building against a podofo build directory * rather than an installed copy of podofo. You'll probably need * this if you're including your own (probably static) copy of podofo * using a mechanism like svn:externals . */ #include "../../src/base/PdfColor.h" #endif podofo-0.9.3/podofo/base/PdfParserObject.h0000664000175000017500000000071511535255326020261 0ustar dominikdominik #ifndef PODOFO_WRAPPER_PDFPARSEROBJECTH #define PODOFO_WRAPPER_PDFPARSEROBJECTH /* * This is a simple wrapper include file that lets you include * when building against a podofo build directory * rather than an installed copy of podofo. You'll probably need * this if you're including your own (probably static) copy of podofo * using a mechanism like svn:externals . */ #include "../../src/base/PdfParserObject.h" #endif podofo-0.9.3/podofo/base/PdfEncoding.h0000664000175000017500000000067511535255326017431 0ustar dominikdominik #ifndef PODOFO_WRAPPER_PDFENCODINGH #define PODOFO_WRAPPER_PDFENCODINGH /* * This is a simple wrapper include file that lets you include * when building against a podofo build directory * rather than an installed copy of podofo. You'll probably need * this if you're including your own (probably static) copy of podofo * using a mechanism like svn:externals . */ #include "../../src/base/PdfEncoding.h" #endif podofo-0.9.3/podofo/base/PdfCanvas.h0000664000175000017500000000066511535255326017115 0ustar dominikdominik #ifndef PODOFO_WRAPPER_PDFCANVASH #define PODOFO_WRAPPER_PDFCANVASH /* * This is a simple wrapper include file that lets you include * when building against a podofo build directory * rather than an installed copy of podofo. You'll probably need * this if you're including your own (probably static) copy of podofo * using a mechanism like svn:externals . */ #include "../../src/base/PdfCanvas.h" #endif podofo-0.9.3/podofo/base/PdfString.h0000664000175000017500000000066511535255326017150 0ustar dominikdominik #ifndef PODOFO_WRAPPER_PDFSTRINGH #define PODOFO_WRAPPER_PDFSTRINGH /* * This is a simple wrapper include file that lets you include * when building against a podofo build directory * rather than an installed copy of podofo. You'll probably need * this if you're including your own (probably static) copy of podofo * using a mechanism like svn:externals . */ #include "../../src/base/PdfString.h" #endif podofo-0.9.3/podofo/base/PdfCompilerCompat.h0000664000175000017500000000072511535255326020615 0ustar dominikdominik #ifndef PODOFO_WRAPPER_PDFCOMPILERCOMPATH #define PODOFO_WRAPPER_PDFCOMPILERCOMPATH /* * This is a simple wrapper include file that lets you include * when building against a podofo build directory * rather than an installed copy of podofo. You'll probably need * this if you're including your own (probably static) copy of podofo * using a mechanism like svn:externals . */ #include "../../src/base/PdfCompilerCompat.h" #endif podofo-0.9.3/podofo/base/PdfDate.h0000664000175000017500000000065511535255326016556 0ustar dominikdominik #ifndef PODOFO_WRAPPER_PDFDATEH #define PODOFO_WRAPPER_PDFDATEH /* * This is a simple wrapper include file that lets you include * when building against a podofo build directory * rather than an installed copy of podofo. You'll probably need * this if you're including your own (probably static) copy of podofo * using a mechanism like svn:externals . */ #include "../../src/base/PdfDate.h" #endif podofo-0.9.3/podofo/base/PdfVariant.h0000664000175000017500000000067111535255326017303 0ustar dominikdominik #ifndef PODOFO_WRAPPER_PDFVARIANTH #define PODOFO_WRAPPER_PDFVARIANTH /* * This is a simple wrapper include file that lets you include * when building against a podofo build directory * rather than an installed copy of podofo. You'll probably need * this if you're including your own (probably static) copy of podofo * using a mechanism like svn:externals . */ #include "../../src/base/PdfVariant.h" #endif podofo-0.9.3/podofo/base/PdfMutex.h0000664000175000017500000000066611535255326017005 0ustar dominikdominik #ifndef PODOFO_WRAPPER_PDFMUTEXH #define PODOFO_WRAPPER_PDFMUTEXH /* * This is a simple wrapper include file that lets you include * when building against a podofo build directory * rather than an installed copy of podofo. You'll probably need * this if you're including your own (probably static) copy of podofo * using a mechanism like svn:externals . */ #include "../../src/base/util/PdfMutex.h" #endif podofo-0.9.3/podofo/base/PdfMutexImpl_win32.h0000664000175000017500000000073411535255326020645 0ustar dominikdominik #ifndef PODOFO_WRAPPER_PDFMUTEXIMPLWIN32H #define PODOFO_WRAPPER_PDFMUTEXIMPLWIN32H /* * This is a simple wrapper include file that lets you include * when building against a podofo build directory * rather than an installed copy of podofo. You'll probably need * this if you're including your own (probably static) copy of podofo * using a mechanism like svn:externals . */ #include "../../src/base/util/PdfMutexImpl_win32.h" #endif podofo-0.9.3/podofo/base/PdfMutexImpl_noop.h0000664000175000017500000000073011535255326020652 0ustar dominikdominik #ifndef PODOFO_WRAPPER_PDFMUTEXIMPLNOOPH #define PODOFO_WRAPPER_PDFMUTEXIMPLNOOPH /* * This is a simple wrapper include file that lets you include * when building against a podofo build directory * rather than an installed copy of podofo. You'll probably need * this if you're including your own (probably static) copy of podofo * using a mechanism like svn:externals . */ #include "../../src/base/util/PdfMutexImpl_noop.h" #endif podofo-0.9.3/podofo/base/PdfStream.h0000664000175000017500000000066511535255326017135 0ustar dominikdominik #ifndef PODOFO_WRAPPER_PDFSTREAMH #define PODOFO_WRAPPER_PDFSTREAMH /* * This is a simple wrapper include file that lets you include * when building against a podofo build directory * rather than an installed copy of podofo. You'll probably need * this if you're including your own (probably static) copy of podofo * using a mechanism like svn:externals . */ #include "../../src/base/PdfStream.h" #endif podofo-0.9.3/podofo/base/PdfRefCountedInputDevice.h0000664000175000017500000000076111535255326022075 0ustar dominikdominik #ifndef PODOFO_WRAPPER_PDFREFCOUNTEDINPUTDEVICEH #define PODOFO_WRAPPER_PDFREFCOUNTEDINPUTDEVICEH /* * This is a simple wrapper include file that lets you include * when building against a podofo build directory * rather than an installed copy of podofo. You'll probably need * this if you're including your own (probably static) copy of podofo * using a mechanism like svn:externals . */ #include "../../src/base/PdfRefCountedInputDevice.h" #endif podofo-0.9.3/podofo/base/PdfMutexWrapper.h0000664000175000017500000000072211535255326020337 0ustar dominikdominik #ifndef PODOFO_WRAPPER_PDFMUTEXWRAPPERH #define PODOFO_WRAPPER_PDFMUTEXWRAPPERH /* * This is a simple wrapper include file that lets you include * when building against a podofo build directory * rather than an installed copy of podofo. You'll probably need * this if you're including your own (probably static) copy of podofo * using a mechanism like svn:externals . */ #include "../../src/base/util/PdfMutexWrapper.h" #endif podofo-0.9.3/podofo/base/PdfMemStream.h0000664000175000017500000000070111535255326017563 0ustar dominikdominik #ifndef PODOFO_WRAPPER_PDFMEMSTREAMH #define PODOFO_WRAPPER_PDFMEMSTREAMH /* * This is a simple wrapper include file that lets you include * when building against a podofo build directory * rather than an installed copy of podofo. You'll probably need * this if you're including your own (probably static) copy of podofo * using a mechanism like svn:externals . */ #include "../../src/base/PdfMemStream.h" #endif podofo-0.9.3/podofo/base/PdfError.h0000664000175000017500000000066111535255326016767 0ustar dominikdominik #ifndef PODOFO_WRAPPER_PDFERRORH #define PODOFO_WRAPPER_PDFERRORH /* * This is a simple wrapper include file that lets you include * when building against a podofo build directory * rather than an installed copy of podofo. You'll probably need * this if you're including your own (probably static) copy of podofo * using a mechanism like svn:externals . */ #include "../../src/base/PdfError.h" #endif podofo-0.9.3/podofo/base/PdfDefinesPrivate.h0000664000175000017500000000072511535255326020607 0ustar dominikdominik #ifndef PODOFO_WRAPPER_PDFDEFINESPRIVATEH #define PODOFO_WRAPPER_PDFDEFINESPRIVATEH /* * This is a simple wrapper include file that lets you include * when building against a podofo build directory * rather than an installed copy of podofo. You'll probably need * this if you're including your own (probably static) copy of podofo * using a mechanism like svn:externals . */ #include "../../src/base/PdfDefinesPrivate.h" #endif podofo-0.9.3/podofo/base/PdfWriter.h0000664000175000017500000000066511535255326017156 0ustar dominikdominik #ifndef PODOFO_WRAPPER_PDFWRITERH #define PODOFO_WRAPPER_PDFWRITERH /* * This is a simple wrapper include file that lets you include * when building against a podofo build directory * rather than an installed copy of podofo. You'll probably need * this if you're including your own (probably static) copy of podofo * using a mechanism like svn:externals . */ #include "../../src/base/PdfWriter.h" #endif podofo-0.9.3/COPYING.LIB0000664000175000017500000006133410432364310014324 0ustar dominikdominik GNU LIBRARY GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1991 Free Software Foundation, Inc. 59 Temple Place - Suite 330 Boston, MA 02111-1307, USA. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the library GPL. It is numbered 2 because it goes with version 2 of the ordinary GPL.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Library General Public License, applies to some specially designated Free Software Foundation software, and to any other libraries whose authors decide to use it. You can use it for your libraries, 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 library, or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link a program with the library, you must provide complete object files to the recipients so that they can relink them with the library, after making changes to the library and recompiling it. And you must show them these terms so they know their rights. Our method of protecting your rights has two steps: (1) copyright the library, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the library. Also, for each distributor's protection, we want to make certain that everyone understands that there is no warranty for this free library. If the library is modified by someone else and passed on, we want its recipients to know that what they have is not the original version, 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 companies distributing free software will individually obtain patent licenses, thus in effect transforming the program into proprietary software. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License, which was designed for utility programs. This license, the GNU Library General Public License, applies to certain designated libraries. This license is quite different from the ordinary one; be sure to read it in full, and don't assume that anything in it is the same as in the ordinary license. The reason we have a separate public license for some libraries is that they blur the distinction we usually make between modifying or adding to a program and simply using it. Linking a program with a library, without changing the library, is in some sense simply using the library, and is analogous to running a utility program or application program. However, in a textual and legal sense, the linked executable is a combined work, a derivative of the original library, and the ordinary General Public License treats it as such. Because of this blurred distinction, using the ordinary General Public License for libraries did not effectively promote software sharing, because most developers did not use the libraries. We concluded that weaker conditions might promote sharing better. However, unrestricted linking of non-free programs would deprive the users of those programs of all benefit from the free status of the libraries themselves. This Library General Public License is intended to permit developers of non-free programs to use free libraries, while preserving your freedom as a user of such programs to change the free libraries that are incorporated in them. (We have not seen how to achieve this as regards changes in header files, but we have achieved it as regards changes in the actual functions of the Library.) The hope is that this will lead to faster development of free libraries. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, while the latter only works together with the library. Note that it is possible for a library to be covered by the ordinary General Public License rather than by this special one. GNU LIBRARY GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Library General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, 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 library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete 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 distribute a copy of this License along with the Library. 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 Library or any portion of it, thus forming a work based on the Library, 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) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, 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 Library, 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 Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you 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. If distribution of 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 satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also compile or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. c) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. d) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. 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. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library 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. 9. 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 Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library 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. 11. 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 Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library 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 Library. 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. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library 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. 13. The Free Software Foundation may publish revised and/or new versions of the Library 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 Library 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 Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, 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 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "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 LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. 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 LIBRARY 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 LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), 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 Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. 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 library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! podofo-0.9.3/TODO0000664000175000017500000000330110715632607013355 0ustar dominikdominikPoDoFo 0.5 - Do not inherit from PdfTokenizer - Interactive forms support PoDoFo 0.6: - convert PdfDocument / PdfStreamedDocument such that: + PdfDocument becomes PdfMemDocument + Common code moves to new shared base PdfDocument + PdfStreamedDocument does not depend on PdfMemDocument for base implementation + Most output-oriented tasks can be performed on any PdfDocument without caring what kind it is. - PdfString supports now unicode strings and conversions + PdfDocEncoding to UTF16 + UTF8 to UTF16 + UTF16 to UTF8 - Simple content stream parsing was added - Support for reading & writing encrypted PDFs FUTURE: - More filters (read & write) - Support for attaching an ICC profile to an image or content stream - Some more drawing routines (tiles, save and rstore?) also finish cleanup the existing ones revamp color support to be more general & support more types - PNG predictor functions in filters - CMYK image handling for podofoimgextract, images in different colour spaces in general. - Semi-streamed writing mode using normal in-memory document and a PdfStream class that can read input from a file / PdfInputStream on ::write() calls. (like PdfFileStream, but with support for user-supplied input files). - Streamline core datatypes to reduce repeated initialization, copy-construction, etc. Focus on limiting memory allocation/deallocation and heap fragmentation. Known trouble areas: + Small strings on heap in PdfString. Use an in-object buffer for small PdfStrings/PdfRefCountedBuffers since these are the most common type. podofo-0.9.3/test/0000775000175000017500000000000012356565165013656 5ustar dominikdominikpodofo-0.9.3/test/ObjectParserTest/0000775000175000017500000000000012356565164017100 5ustar dominikdominikpodofo-0.9.3/test/ObjectParserTest/objects/0000775000175000017500000000000012356565164020531 5ustar dominikdominikpodofo-0.9.3/test/ObjectParserTest/objects/27_0_R.obj0000664000175000017500000002251110517701505022142 0ustar dominikdominik27 0 obj << /Length 6469 /Filter /LZWDecode >> stream €Š€ÐP¼¨1ˆ"¡š0 FB„P@-ˆD¡C1ˆ¸p8 ÆC1pÒ&T6ÃÄx!° ‘Êp³9Ì@E,A1IPՍFñb¡tN:›L§#IŒÂlžÏÁCQ„‚+E‚ÅÓ)ÐÐo‹Fc  È).• PA˜äiD£…cyÊ£@Dê÷ExËw G¨e𯀎n£iC½ÎŽØ®±r¿Ï ƒ‹~FäE8L'CI¼Ý€ƒ FШd8-Õ°¡¶xQ‡Í†õl-dQŒ‡A€ Ç¦9šL”»ÈoÄcx<û)ÞÑj‚ uX»–7r4Ší²}üµÆµÀml¦]K§éô ænoS‹~æðì·C‘·®µ ¨:&…¡¨#‚¢¨D¾­BÕÀphÞ2á@¸AÈÔ"¶<­ðð¬!‹À²ŽúÔ j;°S$ØÀi:ø:D­Ê ¡ÆAºØFÉиâC0TKmÇP{YPœ[ Ȳ{];ŠÔ?Äo¼M»qc6Âä_&Æ2<°B£Àñ Å2„͋à{*ÆAà ޮRi8JÈ i%O´1&ÃST:¹G*”Q@Æo 3OT[&QÒte)L´=3DÊÃ=-D „º¾Ëô|Å2O’®1ÈAHWJÎA›g2†˜m@SlU;ZJô]_T±¡­0U#Ìlí&ҔD(TÁ«1¨p­1ÓR=9IÓÖåA`ŲÝ8µÌä²£‚±¬³½“qZmsgB£<3ÛÐL‚¹5äԡȁ\¸ ÇÊs=?z»-[m70F%BÛp ӅÆ7ýQsÒ“‚²¥¥HTT-ÍOÝ Ýðó]—peSÞNÄÁˆ0-”[}QæP¡–+à“¬…pæùEMù7=ä¸t ÕЂ9>+C¸Ò¯9µ8àæº [K°,£"›®ºÈâã¨Ü2 #òæÞ+·ëoxçº: SRCk„éÒ8n…¶Ó¼›Hèü§"p²€m[ëFàÕË(÷ï÷t&YH9÷\ïwº ŠoœÐæ9©#HÝ}u Ñ¿^zLzWԝs]ò0—{ õ™>ŸßtƒÀ…cØ‚¶h¸÷‹‡ùZ‚ùžSùô% Bºž×¸A£f±Lº´º¬;«Š9êWÒâm¢ÅvÃ(Ò»,_‚ͱ2}ÏÈ¡©îgæƒôúÃxl…§¾D€Ó±Æ)áŒ:†ÃG¤ì}82\¾Ã(~Ë©þw&¥œÓÀHʅ ­ ‚5T¦Ò%£J]imS,w:ËL ¬2ì̆+ú \SÔL@Ò1 ‚òQ‘yyŠKÄfôX3ÆRÆÙF®)XÎà1|³9+4Ðà\9A½ „ÔµÒ9Á6`ÈÙ¡P°Œƒ Þ~—ÃüÏT‚Ö;‹ ¹ל¦XÚö°Zzƾ“gÂÔP`‚:OꌈM[%ð5M„Ô¤­0ċªç›=è ŸŠÎôdpK} ¤èReBâ,Ñ\D-§Y)ñ®2¨¶‡¯GªEÁÉ«B³^›$y´Ñ€QZ ´– ‚Š{,Öêr=3ɏ2i¥8Ô,åLž”Å£YÕ KouUP­v=I^ú¶¬“†¸.ClÓ]ÙbèVwWÓ7 )åjYiA=N’@'`+©¨Æ'*6®*Dⱖ!>ƒGÒ85¤,zƒØ¬[Ù%nVV9’@l…(ô›ΊgG’lȟFґ“ Öƒ iu ӕ¼ÒÒ™S3!ñ"М`h85l1 Ûô›q«Š-x fà¤p¨ ‰U'@önÙ¥ìp§•zB¡ ÖàmhÔ-Ö´Ì,…Ú–ŽÁћK±U…+ÖÕc~J34A”2;ÔÌM¿¶µ\¹xtÓ&=9Ó1‘GpPNK³“®nWœV¶Rà_ZÏX߉#K,¡Ž%YXóàA. ˺`ˆ¼èd³*Q?`Ëåò\Oh¶dud«|æp ̐c¢âèoYõ*:Rßìªö8uòØd‘g°0Ÿ“yoµÒñ³ÙRùü׏€Uc6Ù 0dDg‘¦~d1Y;#߄’ãóÍdLÇg|«¯ÁTެyìd©³P,%I €åƒ2…l˜E `(8¨ \UH±#—&ƒ0n ‹ ±„-b&ÉH A%…r‰ÂF· ¡(=t ÂHMÐ9PÊAHD‚]h‚‰-ÓddÂj-¨4¶§K„j‰é¬ACÞS4f¥0J¢Ÿ4¼ì AJö™²mérúH©ÜŒyœ3’|¡0ß´¤3úejNéoiUp3NCp.ó«úèk·ÍÕފé†ÛJNEæÓ%ÌVNŚç1ªèà5ªEð;ÃyœûË6ÛÍï¹9™æÅTë!›qÔW5JÓ21ð¾¼7‡KéLsaœ6bc Öšä«:õ›pi2‘K4˜²P©ŒÃ"Ò Âb,dI„U\ÕEÜÁ‰ÍàmÖï¿(¿.‰ne™{ž3 Ê©Éç0F)|ïv$.K·Ì{Ø»¾Žª×ù>ãÌc€Kå€ðNK¸X^æã{¯­y¯½®ù†ÜçXÂDŒ„ƒ(@¾s&`¬Þ>ìª=ø—&60™ 4î9š¬n!AGå Bé7§JžŸYÛ[R£9ª5T ¸‘êýc¬õ®¿× ÅëÍ}ó.ÁØ{c€­“²önÏÚ:Ëi‘ªEöº÷ÕO§ü>3¸7Üܒôٛ \¡Aø—È‹FoG—V´ÞÔÕïöFTìÏÏÎêÿOO^™ïà…jìMΧ”{‚øã‹øzø­Ï g'O²ŒÖî ’Ë¯H]0¯0 ±éØLÐ ÏÖ0 fµÆÒâø MÚËê8¯î&B‚ù,z¡.ÐQ‹ "D ‰ÏþQ ˆMPpHG ÀŠŠ¿Kð7b. … £RÎÏîcÏÒòj@œúíP2³§@̐zìp¸XP,ć 羞d[PVÏã`‰ –Ý"t PdáäV¸'B®XÍP–åðìÎ,ðßd>ßÌìà%ž¿ 6° ãEtÏPüËлL¤%Šƒ,à ïTp'BàOü2ê+@Ȇc  ÎhJÁj¾¯èP B›Éô#fVÈ¢3ç^ˆƒUÎp/ ÒìT, àn(\óÃä~Q„=` lD;oL ›Ì>CÜ4њˆ©ÃðsÂ鄉ЎÊBž4CIDq¦~£šÁèúw#jê´€Ê ñ  ˆãbÊ ‰]ƒŠ.€Ø‘ŒDt£lkL4‰ƒœ#H P£ø´¢ðò¬.”Ȩ’&â= BÔFÿilF0„B°ê*Q #D·DÆ1G@cÐö[‹ºanÄôd™\¯íú¸HrŒÌíI´6\ãPÑ E¼¾¬ø.@â0 4 pøn(RMFJF¨ø@PrˆÐÍ`%­žílú^ùoš×­~úMˆØÍÙM˜Mœ ¶ PB!ï¼Ô/Á,ãTÔã¶$χ ÂP'R~{îU‘¾¯hBªç'Jê›d*¯ð-ÚÿTïÊÐB¦ç.’R笠E×'Þl±Jì™Z¸“ JœE²öÍì /ÊHâotÎ Œ6Òç“0®æÃt5kìð±:ñ)¼©cmLcÊӃ¸Ÿ°NVS ŽÜ0*f³A C­ö,’cGHµZP³S,¤g+d.S;9Ê@®Å 0¤G4°xE³§Ó6ó[dds é…Ç¡+‘ 3©7D*ßÊØâ³ã ,¸›Ò:/“ÒÎЄ±âù<°T¦"Þ£¢ø¦«–p+‚Íâ I²NâF¼’>  l1D¤B´*S+±Cú·'•&H2l‘':g Í >ðf ÚB´ ðŠô§|îS´´&—D-šöç>ÛF.÷„¤<m)@A)Q)Ϗ*2¦× ~ùÒ²ØR¶ú¯¯+òÂÚ ¤ñc\ÚòŒÚôüt–d@]. Á8/ito8k›8Л4t9 9Ʋhµò/“² Ìà-³@'S½<Î/6ðg4å Np¦d0ÂsÒL'=ŠË=ÓÏsJ.õ MÆÂD’"©ù@Ðæ0ÿT4L¦òB£Œ /’J@4.PRRǒXÌ&{E ÿ&”—Òq@'•'“Q(„R‰H²Ó)*Õ­@- h#ÂDžÖT ùT§+©+O©+¯±,µK°KòÏL2Ô´MP5l˜¯ˆªMÁFõ gä[O ¼¢tö'Tûs·P"åPs\¯SbPÓf'SRîŸ tâйÃ9³2¯Ç+2 »ŒÅÎk=IÔìS1^‡ 6 :N&ik$âÅ©:4'T3Äz!Rà/• ììóÓ/8ôFM @îG ríªž[weÓÕ [^&X„;/u-Ž—jÓëÑYU˜øÒ ù2©*ÍwZ„OZÒ¸úÒ¼û2Å[”À"ÍF#CÒ" bÛe\âý<©QU3rp'þìöMQ+ðÜê7FPÿF’zÔÎл4$Ln%3éG¤¡6Öà72‚Ó…#«Ñ\¤9ÍN7lš-֗YԟiÔ¥*”©Z´­Zö­[4·,m75Ö¶÷–¼íNɶƬrã6PÇ<ŒÉV§ ¶;?e˜ tJËÓíe ½NÃ<ßdÍ]Ó©&¶|çOó¹/óE`PÿQ@ޖY6öú™y=µú.P75×Ò.Õw"u?Q4v8FQS0?lât°ßBs'v†BlãTy5Öyxomh/sl7r5Ì*—#Ydõi•¡r j_s6§sv«K6±K¹,Â5\4-·ö"uËl—VÜ7Ì*vÓ:ñ/m’ø½Ê‰Bvó=å vl¼®,… x³>ÿñeW¿yX>;0Äu*°– t–1RwªÂØ©Sç~3pÓG{ÓÁ?U6¦ã„É•Qfbå#kE¸¡%jTòFPµV ÕZJ5_Cde%¦U%ô-&8‘x5r§p½W…7WÖ5pՃXvˆ"ŒUÉ­XXù J8ZoŸ€ï§6¯[V³µ»Ï¿k¤\N)µ–«],É4wä£/'…•ë…Ïõ0xyu£m_ölW·o>·ÁaðÁŒ¹- ±AS%•2LBÝ2ä8s7NÚh­AFÖ7 p%"Ö@|´dx|— 5Të 44ÐDÄÚó×Օ¿Y¶ÜӁqî÷u‹hÂHɘíYxñr–›u¥s¤ú8Ksöµ[ö¸ÚãÒ$‚ß‘Í[’"u=0V¨ÃamJÜÌX=dŠ­„9:„CØ8¿tþÔVï†ÓVÈöûG%Óp…4Ôšïpƒïˆ7”Œ—Lõ“Žôœr¥œ²¯ùѐ9ÕsÕ·×E×H"c…Ž•›ž™!l®ÓÙuó{vP%8vq—qNWvïW|9+a)zöy3Fw4,oP¸KPðÃe-ÿ‹õz8É_tÕ—zóÕ{0s`iÉ7ƒ=7Åc Žh·ßŸ¶kNƒ\t¹«:-hWñï{iBM›â#¤8œ–ŸÔ«¥±KZW,€trӂ7$š°š™ë¦ÂåŸǟx9 ùÿpXAmùy©ôuÚxÏØR6Ù4MZ›PW“Pח†¹{=ýRLݕz»–³å”¹-{}™UeéòÂiöE’<75G‰ø¼Ÿ8­U"u‹ ©‹{áÔ‹õeŒK¹Œ‘9&„é&úٍRvá¸Ú*W(uǎ/{)&ªÉ¤DÑa5£¯ùͤ́;wA:›‘KxÕ¸)™Í½²ñ’uÛ.â/xl ú,S®+LD.¬Á¦ÖæóI¦!s¢|Â͕È52yc2¶)ƒ'}-‡6`1Zâ'Wë›A*8WUϼ•—¼ùůºG½ZK°4¯½ù › ©¥Û¦Qi;ñÂ-cÀÌn¬Â#’+MEEí²ôüÐ{5@ûW„µgÜ~… À;0-Œ À©<ÁQ,OÆÆ íÊۙÀN °†\͆ˆCy×aST½0[ª9™ˆ‰å­viÃĎýüCgøÝ~ÜK®Ä¤F˜è„#œV©uŸ\_rücs[s» ¼oˆd¡¾m¯ÐÍ>ɼ~Ûã}Àê»ÌŽLVY²œ—|«„\£‡䨘TÀZ˜Ç<¹Ô\¿Á\ÄáwÀÞæCÍ3¢Ù®ãgZ)Íû8âã|3‡eœ#Ÿ¸…]zß4{°NLĞYwÊî£T˜VE¸k,·šU†CC6t·P…C÷tºýǶ‚ ¹—`<ôUÑmÁř3oÜcÚ†4kÛ?ØרÚÞ¤[N{»H{¿ÄÂM\Ë¥Å[Íї+¯Ý!j;ÙjšSÒ¼mt3ÕÓRÏá"=ÓÕÍÈo:–÷M´Oݝ1Ú>¨tîþZ•ÊýgÀ‡+ÖÜÈÑzÂ.Z‰Õ3em\Ê,§QýüóÓl9­Û.=NËo˜uJYŠsB]Ë]×w°Ë™{šŸ4;Iu@.VSDg?”ø…ÝÅÖ ½âl(‹b= (¢6) zp]}EȝIæëÏÙ3Oí Ù¢uª†pÜç17vë¡UØæµgƒ^SðLãQ°¯à¹/£;Áq¨ ÛÉpô’PvYÑ»Óâ8 œûÛÒxÆ»ã­Ù¼½ò.(=4’0{õ«xI³vÎ3pgmBõ¢´Vvz:ߨÔZžÛÀ_ï ¥æLæŒMþäje¬5fEµÃÑÊ@Š]qÝ¢Gô,rɎ  J&–9ŽÕ ®VìݓRšÊNºæs(NI”feȌQÁ`È®©§Ö‹H¸ŠŒâi:"ѐÌa  '#9”åBaF“qÊx2œÅÑ(œ(¨h2Ç¢‚ƒ™ÀٍŠK¥BP4/* FBˆ€¨f˜ F#ÈÀ@9š•“ 0¤¨j˜L‡iÄè3ͨtPP ÕH¥Lfcjtæ`6ˆ'•YlQ0"Cy,6G·BŽgRàÀb61šL¦édºÂ0ˆ(K=¤Øy‰$§3i¾%%7Àí²Rà Ê.3Çe²úäÒ¿P ¸IÅXeM*ðæ¡ð§G 8_óÓ+Ά`1Íðµl.°h. qvó•Äe± Fó¬\ÊdâŒ'8—(Pf7› ™ ìÀn7¯ohÇ~µ&—3šÍì©àâÜ Aôôo=n™¸¨Ôôjº²ô3êóبm*Êúªìº´ô´"`¦¯"®Q=T,Eԫڃ4«ËT«\]]RÔü6ÅÑ> stream 8;T)[:bY^""(EJg"_2%r'LT#i/jg!MO=63+VIuj#CB,WCF1If'\b*cS$n]!]4b-F8 qG%(:$AMg^T"YOX7AZtgSh=:Jjo>@Es8PIc5D/l`2DCV(kR[]C"pTDsic=_Q$KM6s !3MJ]jo~> endstream endobj podofo-0.9.3/test/ObjectParserTest/objects/27_0_R.info0000664000175000017500000000012610517701505022321 0ustar dominikdominik- This sample object has an invalid LZW decode dictionary and produces bad results. podofo-0.9.3/test/ObjectParserTest/objects/27_0_R.exp0000664000175000017500000000000010517701505022151 0ustar dominikdominikpodofo-0.9.3/test/ObjectParserTest/CMakeLists.txt0000664000175000017500000000100310614703752021622 0ustar dominikdominikADD_EXECUTABLE(ObjectParserTest ObjectParserTest.cpp) TARGET_LINK_LIBRARIES(ObjectParserTest ${PODOFO_LIB} ${PODOFO_LIB_DEPENDS}) SET_TARGET_PROPERTIES(ObjectParserTest PROPERTIES COMPILE_FLAGS "${PODOFO_CFLAGS}") ADD_DEPENDENCIES(ObjectParserTest ${PODOFO_DEPEND_TARGET}) # Copy the test samples over to the build tree ADD_CUSTOM_COMMAND( TARGET ObjectParserTest POST_BUILD COMMAND "${CMAKE_COMMAND}" -E copy_directory "${CMAKE_CURRENT_SOURCE_DIR}/objects" "${CMAKE_CURRENT_BINARY_DIR}/objects" ) podofo-0.9.3/test/ObjectParserTest/ObjectParserTest.cpp0000664000175000017500000004231711460071654023025 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2005 by Dominik Seichter * * domseichter@web.de * * * * 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., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "../PdfTest.h" #ifdef _WIN32 // Get access to POSIX unlink() #include #define unlink _unlink #else #include #endif #include #include #include #include #include #include #define HEADER_LEN 15 #define BUFFER_SIZE 4096 using namespace PoDoFo; using namespace std; #ifdef _WIN32 static const string sTmp("%TEMP%"); #else static const string sTmp("/tmp/pdfobjectparsertest_"); #endif static const bool KeepTempFiles = true; // Undefine if you want to let the tests crash when an exception // is thrown, so you can see the full call path. #ifndef CATCH_EXCEPTIONS #define CATCH_EXCEPTIONS #endif #ifdef CATCH_EXCEPTIONS #define TRY try #else #define TRY #endif // Print out an object in a human readable form. void PrintObject( const std::string & objectData, ostream & s, bool escapeNewlines, bool wrap ) { int wrapCtr = 0, numNonprintables = 0; for (string::const_iterator it = objectData.begin(); it != objectData.end(); ++it) { ++wrapCtr; char ch = *it; if ( ch != '\\' && ( ( !escapeNewlines && (ch == '\r' || ch == '\n') ) || ch == ' ' || PdfTokenizer::IsPrintable(ch) ) ) s << ch; else if (ch == '\r') s << "\\r"; else if (ch == '\n') s << "\\n"; else { static const char hx[17] = "0123456789ABCDEF"; s << '\\' << 'x' << hx[ch / 16] << hx[ch % 16]; wrapCtr += 3; // If we're processing binary data, just print part of it. ++numNonprintables; if (numNonprintables > 72) { cerr << "... [snip]"; break; } } if (wrap && wrapCtr > 72) { wrapCtr = 0; s << endl; } } } string WriteTempFile( const string & sFilename, const string & sData, long lObjNo, long lGenNo ) { std::ostringstream ss; ss << sFilename << lObjNo << '_' << lGenNo << "_obj"; string sNewFileName = ss.str(); ofstream f; f.open( sNewFileName.c_str(), ios_base::out|ios_base::trunc|ios_base::binary ); f.write( sData.data(), sData.length() ); return sNewFileName; } string ReadFile( string sFilename ) { FILE * f = fopen(sFilename.c_str(), "r"); fseek(f, 0L, SEEK_END); size_t bytes = ftell(f); fseek(f, 0L, SEEK_SET); char* buf = new char[bytes]; size_t bytesRead = fread(buf, 1, bytes, f); if (bytesRead != bytes) { cerr << "Failed to read file " << sFilename < Object Number: " << obj.Reference().ObjectNumber() << " Generation Number: " << obj.Reference().GenerationNumber() << endl; if( lObjNo != obj.Reference().ObjectNumber() || lGenNo != obj.Reference().GenerationNumber() ) { PODOFO_RAISE_ERROR( ePdfError_TestFailed ); } if (bHasStream != obj.HasStream()) { cerr << "ERROR: This object should've had an associated stream, but none was loaded" << endl; PODOFO_RAISE_ERROR( ePdfError_TestFailed ); } if (bHasStream) { char* pBuffer; pdf_long lLen; cerr << " -> Has Stream, loading ... " << flush; PdfMemStream * const ps = dynamic_cast(obj.GetStream()); assert(ps); cerr << " ok, length: " << ps->GetLength() << endl; ps->GetFilteredCopy( &pBuffer, &lLen ); cerr << " got a filtered copy of length: " << lLen << endl; cerr << "Data:\n" << endl; cerr.write( pBuffer, lLen ); cerr << "\n====\n" << endl; } string str; obj.ToString( str ); { size_t objOff = sOrigData.find(" obj")+5; if (sOrigData[objOff] == '\r' || sOrigData[objOff] == '\n') objOff++; const size_t endobjOff = sOrigData.rfind(string("endobj")); const string sOrigData_Base(sOrigData, objOff, endobjOff-objOff-1); cerr << " -> Input object data ("; PrintObject(sOrigData_Base, cerr, true, false); cerr << ")\n"; } cerr << " -> Parsed Value in this object : ("; PrintObject(str, cerr, true, false); cerr << ')' << endl; // TODO: ensure comparison correct after nulls if (bTestExpected) { cerr << " -> Expected value of this object: ("; PrintObject(sExpectedData, cerr, true, false); cerr << ')' << endl; if( str != sExpectedData ) { PODOFO_RAISE_ERROR( ePdfError_TestFailed ); } } const unsigned long lObjLen = obj.GetObjectLength( ePdfWriteMode_Default ); cerr << " -> Object Length: " << lObjLen << endl; std::ostringstream os; PdfOutputDevice deviceTest( &os ); obj.WriteObject( &deviceTest, ePdfWriteMode_Default, NULL ); string sLen = os.str(); cerr << " -> Object String Length: " << sLen.length() << endl; if( lObjLen != sLen.length() ) { cerr << "Object length does not match! Object Length: " << lObjLen << " String Length: " << sLen.length() << endl; cerr << " -> Object String begins\n" << "----------- begin " << lObjNo << ' ' << lGenNo << " --------------" << endl; PrintObject(sLen, cerr, false, false); cerr << "------------ end " << lObjNo << ' ' << lGenNo << " ---------------\n\n" << flush; PODOFO_RAISE_ERROR( ePdfError_TestFailed ); } cerr << "\n\n"; } // Test an object passed as a string against the expected value, also a string. void TestObject_String( const string & sData, long lObjNo, long lGenNo, bool bTestExpected = false, const string & sExpectedData = string(), bool bHasStream = false) { string sTempFile = WriteTempFile(sTmp, sData.c_str(), lObjNo, lGenNo); TRY { TestObject(sTempFile, lObjNo, lGenNo, bTestExpected, sExpectedData, bHasStream); if (!KeepTempFiles) unlink(sTempFile.c_str()); #ifdef CATCH_EXCEPTIONS } catch (PdfError & e) { if (!KeepTempFiles) unlink(sTempFile.c_str()); e.AddToCallstack( __FILE__, __LINE__ ); throw e; #endif } } // overload of TestObject_String that takes a `const char*' expected data argument that may be null. // This may only be used for objects without associated streams. void TestObject_String( const string & sData, long lObjNo, long lGenNo, const char * expectedData ) { TestObject_String(sData, lObjNo, lGenNo, expectedData != NULL, string(expectedData), false); } // Test an object stored in a file against the expected value, also a file (if provided). // Also ensures an object has a stream if set. void TestObject_File( const string & sFilename, long lObjNo, long lGenNo, bool bTestExpected = false, const string & sExpectedFile = string(), bool bHasStream = false ) { string sExpectedData; if (bTestExpected) sExpectedData = ReadFile(sExpectedFile); TestObject(sFilename, lObjNo, lGenNo, bTestExpected, sExpectedData, bHasStream); } const char* pszSimpleObjectBoolean = "1 0 obj\ntrue\nendobj\n"; const char* pszSimpleObjectNumber = "2 1 obj\n23\nendobj\n"; const char* pszSimpleObjectReal = "3 0 obj\n3.14\nendobj\n"; const char* pszSimpleObjectString = "4 0 obj\n(Hallo Welt!)\nendobj\n"; const char* pszSimpleObjectString2 = "5 0 obj\n(Hallo \\(schne\\) Welt!)\nendobj\n"; const char* pszSimpleObjectHex = "6 0 obj\n<48656C6C6F20576F726C64>\nendobj\n"; // Hello World const char* pszSimpleObjectRef = "7 0 obj\n6 0 R\nendobj\n"; const char* pszSimpleObjectArray = "8 0 obj\n[100 200 300 400 500]\nendobj\n"; const char* pszSimpleObjectArray2 = "9 0 obj\n[100 (Hallo Welt) 3.14 400 500]\nendobj\n"; const char* pszSimpleObjectArray3 = "9 1 obj\n[100/Name(Hallo Welt)[1 2]3.14 400 500]\nendobj\n"; const char* pszSimpleObjectArray4 = "9 1 obj\n[100/Name(Hallo Welt)[1 2]3.14 400 500 /Dict << /A (Hallo) /B [21 22] >> /Wert /Farbe]\nendobj\n"; const char* pszSimpleObjectArray5 = "1 2 obj\n[123 0 R]\nendobj\n"; const char* pszObject = "10 0 obj\n" "<<\n" "/Type/Test\n" "/Key /Value\n" "/Hard>>\n" "endobj\n"; const char* pszObject2 = "11 0 obj\n" "<<\n" "/Type/Test2\n" "/Key /Value\n" "/Key2[100/Name(Hallo Welt)[1 2] 3.14 400 500]/Key2/Key4(Hallo \\(Welt!)\n" "/ID[<530464995927cef8aaf46eb953b93373><530464995927cef8aaf46eb953b93373>]\n" ">>\n" "endobj\n"; const char* pszObject3 = "12 0 obj\n" "<<\n" "/Type/Test3\n" "/Font<>\n" ">>\n" "endobj\n"; const char* pszObject4 = "271 0 obj\n" "<< /Type /Pattern /PatternType 1 /PaintType 1 /TilingType 1 /BBox [ 0 0 45 45 ] \n" "/Resources << /ProcSet [ /ImageI ] /XObject << /BGIm 7 0 R >> >> \n" "/XStep 45 /YStep 45 /Matrix [ 1 0 0 1 0 27 ] /Length 272 0 R >>\nendobj\n"; // PDF reference, Example 3.2 (LZW and ASCII85 encoded stream) const char* pszObject5 ="32 0 obj\n" " << /Length 534\n" " /Filter [/ASCII85Decode /LZWDecode]\n" " >>\n" "stream\n" "J..)6T`?p&c!Jnl@\n" "RM]WM;jjH6Gnc75idkL5]+cPZKEBPWdR>FF(kj1_R%W_d\n" "&/jS!;iuad7h?[L.F$+]]0A3Ck*$I0KZ?;<)CJtqi65Xb\n" "Vc3\\n5ua:Q/=0$W<#N3U;H,MQKqfg1?:lUpR;6oN[C2E4\n" "ZNr8Udn.'p+?#X+1>0Kuk$bCDF/(3fL5]Oq)^kJZ!C2H1\n" "'TO]Rl?Q:&'<5&iP!$Rq;BXRecDN[IJB`,)o8XJOSJ9sD\n" "S]hQ;Rj@!ND)bD_q&C\\g:inYC%)&u#:u,M6Bm%IY!Kb1+\n" "\":aAa'S`ViJglLb8iG1p&i;eVoK&juJHs9%;Xomop\"5KatWRT\"JQ#qYuL,\n" "JD?M$0QP)lKn06l1apKDC@\\qJ4B!!(5m+j.7F790m(Vj8\n" "8l8Q:_CZ(Gm1%X\\N1&u!FKHMB~>\n" "endstream\n" "endobj\n"; // PDF reference, Example 3.4 const char * pszObject6 = "33 0 obj\n" "<< /Length 568 >>\n" "stream\n" "2 J\n" "BT\n" "/F1 12 Tf\n" "0 Tc\n" "0 Tw\n" "72.5 712 TD\n" "[(Unencoded streams can be read easily) 65 (, )] TJ\n" "0 .14 TD\n" "[(b) 20 (ut generally tak ) 10 (e more space than \\311)] TJ\n" "T* (encoded streams.) Tj\n" "0 .28 TD\n" "[(Se) 25 (v) 15 (eral encoding methods are a) 20 (v) 25 (ailable in PDF ) 80 (.)] TJ\n" "0 .14 TD\n" "(Some are used for compression and others simply ) Tj\n" "T* [(to represent binary data in an ) 55 (ASCII format.)] TJ\n" "T* (Some of the compression encoding methods are \\\n" "suitable ) Tj\n" "T* (for both data and images, while others are \\\n" "suitable only ) Tj\n" "T* (for continuous.tone images.) Tj\n" "ET\n" "endstream\n" "endobj\n"; // Comment tokenizer test adapted from PDF Reference, section 3.1.2 . Should parse as [ /abc 123 ] . const char* pszCommentObject = "91 0 obj\n[/abc\% comment {/%) blah blah blah\n123]\nendobj\n"; // Use a FULL statement in this macro, it will not add any trailing // semicolons etc. #ifdef CATCH_EXCEPTIONS #define TRY_TEST(x) \ try {\ ++tests;\ x\ ++tests_ok;\ } \ catch (PdfError & e) \ {\ e.PrintErrorMsg();\ ++tests_error;\ } #else #define TRY_TEST(x) \ {\ ++tests;\ x\ ++tests_ok;\ } #endif int main() { int tests = 0, tests_error = 0, tests_ok=0; PdfError eCode; fprintf(stderr,"This test tests the PdfParserObject class.\n"); fprintf(stderr,"---\n"); TRY_TEST(TestObject_String( pszSimpleObjectBoolean, 1, 0, "true" );) TRY_TEST(TestObject_String( pszSimpleObjectNumber , 2, 1, "23" );) TRY_TEST(TestObject_String( pszSimpleObjectReal , 3, 0, "3.140000" );) TRY_TEST(TestObject_String( pszSimpleObjectString , 4, 0, "(Hallo Welt!)" );) TRY_TEST(TestObject_String( pszSimpleObjectString2, 5, 0, "(Hallo \\(schne\\) Welt!)" );) TRY_TEST(TestObject_String( pszSimpleObjectHex , 6, 0, "<48656C6C6F20576F726C64>" );) TRY_TEST(TestObject_String( pszSimpleObjectRef , 7, 0, "6 0 R" );) TRY_TEST(TestObject_String( pszSimpleObjectArray , 8, 0, "[ 100 200 300 400 500 ]" );) TRY_TEST(TestObject_String( pszSimpleObjectArray2 , 9, 0, "[ 100 (Hallo Welt) 3.140000 400 500 ]" );) TRY_TEST(TestObject_String( pszSimpleObjectArray3 , 9, 1, "[ 100 /Name (Hallo Welt) [ 1 2 ] 3.140000 400 500 ]" );) TRY_TEST(TestObject_String( pszSimpleObjectArray4 , 9, 1, "[ 100 /Name (Hallo Welt) [ 1 2 ] 3.140000 400 500 /Dict <<\n/A (Hallo)\n/B [ 21 22 ]\n>> /Wert\n/Farbe ]" );) TRY_TEST(TestObject_String( pszSimpleObjectArray5 , 1, 2, "[ 123 0 R ]" );) TRY_TEST(TestObject_String( pszCommentObject, 91, 0, "[ /abc 123 ]" );) fprintf(stderr,"---\n"); TRY_TEST(TestObject_String( pszObject, 10, 0 );) TRY_TEST(TestObject_String( pszObject2, 11, 0 );) TRY_TEST(TestObject_String( pszObject3, 12, 0 );) TRY_TEST(TestObject_String( pszObject4, 271, 0 );) // These ones have attached streams TRY_TEST(TestObject_String( pszObject5, 32, 0, false, string(), true);) TRY_TEST(TestObject_String( pszObject6, 33, 0, false, string(), true);) TRY_TEST(TestObject_File( "objects/27_0_R.obj", 27, 0, false, string(), true );) TRY_TEST(TestObject_File( "objects/613_0_R.obj", 613, 0, false, string(), true );) cerr << "---\n" << flush; if (!tests_error) cerr << "All " << tests << " tests succeeded!" << endl; else cerr << tests_error << " of " << tests << " tests failed, " << tests_ok << " succeeded" << endl; return tests_error; } podofo-0.9.3/test/TokenizerTest/0000775000175000017500000000000012356565165016470 5ustar dominikdominikpodofo-0.9.3/test/TokenizerTest/CMakeLists.txt0000664000175000017500000000076110673174162021225 0ustar dominikdominikADD_EXECUTABLE(TokenizerTest TokenizerTest.cpp) TARGET_LINK_LIBRARIES(TokenizerTest ${PODOFO_LIB} ${PODOFO_LIB_DEPENDS}) SET_TARGET_PROPERTIES(TokenizerTest PROPERTIES COMPILE_FLAGS "${PODOFO_CFLAGS}") ADD_DEPENDENCIES(TokenizerTest ${PODOFO_DEPEND_TARGET}) # Copy the test samples over to the build tree ADD_CUSTOM_COMMAND( TARGET TokenizerTest POST_BUILD COMMAND "${CMAKE_COMMAND}" -E copy_directory "${CMAKE_CURRENT_SOURCE_DIR}/objects" "${CMAKE_CURRENT_BINARY_DIR}/objects" ) podofo-0.9.3/test/TokenizerTest/TokenizerTest.cpp0000664000175000017500000000430011460071654021771 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2005 by Dominik Seichter * * domseichter@web.de * * * * 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., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "../PdfTest.h" #include #define BUFFER_SIZE 4096 using namespace PoDoFo; int main( int argc, char* argv[] ) { printf("Tokenizer Test\n"); printf("==============\n"); if( argc != 2 ) { printf("Usage: TokenizerTest [input_filename]\n"); return 0; } try { PdfRefCountedInputDevice device( argv[1], "rb" ); PdfRefCountedBuffer buffer( BUFFER_SIZE ); PdfTokenizer tokenizer( device, buffer ); const char* pszToken; while ( tokenizer.GetNextToken(pszToken) ) { printf("Got token: %s\n", pszToken ); } } catch( const PdfError & e ) { e.PrintErrorMsg(); return e.GetError(); } return 0; } podofo-0.9.3/test/pdfs/0000775000175000017500000000000012356565165014612 5ustar dominikdominikpodofo-0.9.3/test/pdfs/README.txt0000664000175000017500000000042411231233340016262 0ustar dominikdominikThis directory stores SMALL sample PDFs for use with unit tests and with PoDoFo's general test programs. PDFs used in examples may also go here. Any PDF added here must be freely redistributable under the same license as PoDoFo its self (See README.html in the source root). podofo-0.9.3/test/pdfs/inline-image.pdf0000664000175000017500000001120711231233340017616 0ustar dominikdominik%PDF-1.4 %쏢 5 0 obj <> stream x]T 4|weK&2kKCy1 4暼hJ$+FF%c)G06޽099s4 &vGp8@'H ȟ5_"0mpA03 Zr`EgySh$v;`{`4! #!f0|TH(gDd-uͬOl:`+ 2Ӓnb,j;V.cƒlw4@ɰU45psUϜXy`͙]K)hI.6w:tGڠiv"ˢ+81_G%|ׂ)R;XT_޽~o=0qrHTE=uh<2XRQ>nV]bhߕ DN8}^؄M3״&ӝwaA Iɣ1NV*9xak_=R=Ygt:,ƵZTXͳ]| vILz{I^zE$jDv=P\1Z4 *^kn%L2Ro*JdݧF~tVRnjVGų,Pբ]_8*XrvvvwhNUД"\VWS}RN=: >9Zg9Q53MoaSJ:=GP>Β)D®NC*Yރ k<̙A]L0 d@ij+ԏ~'O:ßЖ|,Q6-w*5Aq{}V.Ń8ԙ%[w1}ۢ\jW ΂G!%kఱPbQ̐wL n&~m@|1$ۖS MrP2xD51mRPg2zooﲀq x/i?׋*.9x3;XaBq Mpcat! Z1n>KYojBܗjZ<k!8@Vw_љ '|Z0n:}i~3$&ܥ)jpK ot6]u}oK4䐃[:w\}7}߸Id_?+Ht!N0]7Mٌo:R晹+>l%+h9ĊL(k!Ehcg vVP Mslh,6ԨR[;< 96B42oofjֵAuSP#ǚWOIioU4P~-?(FZF\Mrdq` zO'zM~|h`#Dӗϡ qZ'f!gG:,/1Lg'Y7MOF~endstream endobj 6 0 obj 2280 endobj 4 0 obj <> /Contents 5 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R ] /Count 1 /Rotate 0>> endobj 1 0 obj <> endobj 7 0 obj <>endobj 8 0 obj <> endobj 9 0 obj <>stream Adobe InDesign CS4 \(6.0.3\) Untitled-1tranngocthachs endstream endobj 2 0 obj <>endobj xref 0 10 0000000000 65535 f 0000002601 00000 n 0000004185 00000 n 0000002533 00000 n 0000002385 00000 n 0000000015 00000 n 0000002365 00000 n 0000002665 00000 n 0000002706 00000 n 0000002735 00000 n trailer << /Size 10 /Root 1 0 R /Info 2 0 R /ID [<78550EE016C4CCDE53835B0AED8D62D1><78550EE016C4CCDE53835B0AED8D62D1>] >> startxref 4390 %%EOF podofo-0.9.3/test/pdfs/inline-image.txt0000664000175000017500000000123411231233340017663 0ustar dominikdominikThis PDF contains an inline image, defined according to the PDF Spec (4.8.6 Inline Images). test/ContentParser/ContentParser -p test/pdfs/inline-image.pdf should parse it fine, with output including: 37 Keyword: BI 38 Variant: /CS 39 Variant: /CMYK 40 Variant: /W 41 Variant: 43 42 Variant: /H 43 Variant: 66 44 Variant: /BPC 45 Variant: 8 46 Variant: /F 47 Variant: /Fl 48 Variant: /DP 49 Variant: << /Colors 4 /Columns 43 /Predictor 15 >> 50 Keyword: ID Inline image data: 560 bytes 51 Keyword: EI podofo-0.9.3/test/DeviceTest/0000775000175000017500000000000012356565165015715 5ustar dominikdominikpodofo-0.9.3/test/DeviceTest/DeviceTest.cpp0000664000175000017500000001074011460071654020450 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2005 by Dominik Seichter * * domseichter@web.de * * * * 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., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "../PdfTest.h" #include #include #define BUFFER_SIZE 4096 using namespace PoDoFo; void RefCountedBufferTest() { const char* pszTestString = "Hello World Buffer!"; long lLen = strlen( pszTestString ); PdfRefCountedBuffer buffer1; PdfRefCountedBuffer buffer2; // test simple append printf("\t -> Appending\n"); PdfBufferOutputStream stream1( &buffer1 ); stream1.Write( pszTestString, lLen ); stream1.Close(); if( static_cast(buffer1.GetSize()) != lLen ) { fprintf( stderr, "Buffer size does not match! Size=%li should be %li\n", buffer1.GetSize(), lLen ); PODOFO_RAISE_ERROR( ePdfError_TestFailed ); } if( strcmp( buffer1.GetBuffer(), pszTestString ) != 0 ) { fprintf( stderr, "Buffer contents do not match!\n" ); PODOFO_RAISE_ERROR( ePdfError_TestFailed ); } // test assignment printf("\t -> Assignment\n"); buffer2 = buffer1; if( buffer1.GetSize() != buffer2.GetSize() ) { fprintf( stderr, "Buffer sizes does not match! Size1=%li Size2=%li\n", buffer1.GetSize(), buffer2.GetSize() ); PODOFO_RAISE_ERROR( ePdfError_TestFailed ); } if( strcmp( buffer1.GetBuffer(), buffer2.GetBuffer() ) != 0 ) { fprintf( stderr, "Buffer contents do not match after assignment!\n" ); PODOFO_RAISE_ERROR( ePdfError_TestFailed ); } // test detach printf("\t -> Detaching\n"); PdfBufferOutputStream stream( &buffer2 ); stream.Write( pszTestString, lLen ); stream.Close(); if( static_cast(buffer2.GetSize()) != lLen * 2 ) { fprintf( stderr, "Buffer size after detach does not match! Size=%li should be %li\n", buffer2.GetSize(), lLen * 2 ); PODOFO_RAISE_ERROR( ePdfError_TestFailed ); } if( static_cast(buffer1.GetSize()) != lLen ) { fprintf( stderr, "Buffer1 size seems to be modified\n"); PODOFO_RAISE_ERROR( ePdfError_TestFailed ); } if( strcmp( buffer1.GetBuffer(), pszTestString ) != 0 ) { fprintf( stderr, "Buffer1 contents seem to be modified!\n" ); PODOFO_RAISE_ERROR( ePdfError_TestFailed ); } // large appends PdfBufferOutputStream streamLarge( &buffer1 ); for( int i=0;i<100;i++ ) { streamLarge.Write( pszTestString, lLen ); } streamLarge.Close(); if( static_cast(buffer1.GetSize()) != (lLen * 100 + lLen) ) { fprintf( stderr, "Buffer1 size is wrong after 100 attaches: %li\n", buffer1.GetSize() ); PODOFO_RAISE_ERROR( ePdfError_TestFailed ); } } int main( int argc, char** ) { printf("Device Test\n"); printf("==============\n"); if( argc != 1 ) { printf("Usage: DeviceTest\n"); return 0; } try { printf("-> Testing PdfRefCountedBuffer...\n"); RefCountedBufferTest(); } catch( const PdfError & e ) { e.PrintErrorMsg(); return e.GetError(); } printf("All tests successfull!\n"); return 0; } podofo-0.9.3/test/DeviceTest/CMakeLists.txt0000664000175000017500000000073710673174162020455 0ustar dominikdominikADD_EXECUTABLE(DeviceTest DeviceTest.cpp) TARGET_LINK_LIBRARIES(DeviceTest ${PODOFO_LIB} ${PODOFO_LIB_DEPENDS}) SET_TARGET_PROPERTIES(DeviceTest PROPERTIES COMPILE_FLAGS "${PODOFO_CFLAGS}") ADD_DEPENDENCIES(DeviceTest ${PODOFO_DEPEND_TARGET}) # Copy the test samples over to the build tree ADD_CUSTOM_COMMAND( TARGET DeviceTest POST_BUILD COMMAND "${CMAKE_COMMAND}" -E copy_directory "${CMAKE_CURRENT_SOURCE_DIR}/objects" "${CMAKE_CURRENT_BINARY_DIR}/objects" ) podofo-0.9.3/test/ParserTest/0000775000175000017500000000000012356565164015751 5ustar dominikdominikpodofo-0.9.3/test/ParserTest/CMakeLists.txt0000664000175000017500000000036311534747027020510 0ustar dominikdominikADD_EXECUTABLE(ParserTest ParserTest.cpp) TARGET_LINK_LIBRARIES(ParserTest ${PODOFO_LIB} ${PODOFO_LIB_DEPEND} ) SET_TARGET_PROPERTIES(ParserTest PROPERTIES COMPILE_FLAGS "${PODOFO_CFLAGS}") ADD_DEPENDENCIES(ParserTest ${PODOFO_DEPEND_TARGET}) podofo-0.9.3/test/ParserTest/ParserTest.cpp0000664000175000017500000002144511534747027020554 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2005 by Dominik Seichter * * domseichter@web.de * * * * 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., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include #include using std::cerr; using std::cout; using std::cin; using std::flush; using std::endl; using std::string; using namespace PoDoFo; void print_help() { cerr << "Usage: ParserTest [-d] [-clean] [-compact] []\n" << " -d Enable demand loading of objects\n" << " -clean Write a clean PDF that is readable in a text editor\n" << " -compact Write the PDF as compact as possible\n" << flush; } void enc_test() { /* PdfString documentId; documentId.SetHexData( "BF37541A9083A51619AD5924ECF156DF", 32 ); PdfEncrypt enc( "user", "podofo", 0 ); enc.GenerateEncryptionKey( documentId ); printf("\n\nTrying authentication!\n"); PdfOutputDevice debug( &(std::cout) ); printf("Debug: "); documentId.Write( &debug ); printf("\n\n"); std::string documentIdStr( documentId.GetString(), documentId.GetLength() ); std::string password = "user"; std::string uValue( reinterpret_cast(enc.GetUValue()), 32 ); std::string oValue( reinterpret_cast(enc.GetOValue()), 32 ); if( enc.Authenticate(documentIdStr, password, uValue, oValue, enc.GetPValue(), 40, 2) ) { printf("Successfull\n"); } else printf("FAILED\n"); enc.SetCurrentReference( PdfReference( 7, 0 ) ); const char* pBuffer1 = "Somekind of drawing \001 buffer that possibly \003 could contain PDF drawing commands"; const char* pBuffer2 = " possibly could contain PDF drawing\003 commands"; long lLen = strlen( pBuffer1 ) + 2 * strlen( pBuffer2 ); char* pEncBuffer = static_cast(malloc( sizeof(char) * lLen )); memcpy( pEncBuffer, pBuffer1, strlen( pBuffer1 ) * sizeof(char) ); memcpy( pEncBuffer + strlen(pBuffer1), pBuffer2, strlen( pBuffer2 ) ); memcpy( pEncBuffer + strlen(pBuffer1) + strlen( pBuffer2 ), pBuffer2, strlen( pBuffer2 ) ); enc.Encrypt( reinterpret_cast(pEncBuffer), lLen ); PdfMemoryOutputStream mem( lLen ); PdfOutputStream* pStream = enc.CreateEncryptionOutputStream( &mem ); pStream->Write( pBuffer1, strlen( pBuffer1 ) ); pStream->Write( pBuffer2, strlen( pBuffer2 ) ); pStream->Write( pBuffer2, strlen( pBuffer2 ) ); pStream->Close(); printf("Result: %i \n", memcmp( pEncBuffer, mem.TakeBuffer(), lLen ) ); enc.Encrypt( reinterpret_cast(pEncBuffer), lLen ); printf("Decrypted buffer: %s\n", pEncBuffer ); */ } void write_back( PdfParser* pParser, const char* pszFilename, EPdfWriteMode eWriteMode ) { //enc_test(); PdfWriter writer( pParser ); writer.SetWriteMode( eWriteMode ); /* PdfEncrypt encrypt( "user", "podofo", 0, PdfEncrypt::ePdfEncryptAlgorithm_RC4V2, PdfEncrypt::ePdfKeyLength_128 ); */ //writer.SetUseXRefStream( true ); //writer.SetLinearized( true ); writer.SetPdfVersion( ePdfVersion_1_6 ); //writer.SetEncrypted( encrypt ); writer.Write( pszFilename ); } int main( int argc, char* argv[] ) { PdfError::EnableLogging(true); PdfError::EnableDebug(true); PdfVecObjects objects; PdfParser parser( &objects ); EPdfWriteMode eWriteMode = ePdfWriteMode_Default; objects.SetAutoDelete( true ); bool useDemandLoading = false; bool useStrictMode = false; const char* pszInput = NULL; const char* pszFilename = NULL; for( int i=1; i []\n" << " -d Enable demand loading of objects\n" << " -s Enable strict parsing mode\n" << " -clean Enable clean writing mode\n" << " -compact Enable compact writing mode\n" << flush; return 0; } cerr << "This test reads a PDF file from disk and writes it to a new pdf file." << endl; cerr << "The PDF file should look unmodified in any viewer" << endl; cerr << "---" << endl; cerr << "Number of incremental updates: " << parser.GetNumberOfIncrementalUpdates() << endl; try { cerr << "Parsing " << pszInput << " with demand loading " << (useDemandLoading ? "on" : "off") << " with strict parsing " << (useStrictMode ? "on" : "off") << " ..." << flush; bool bIncorrectPw = false; std::string pw; parser.SetStrictParsing( useStrictMode ); do { try { if( !bIncorrectPw ) parser.ParseFile( pszInput, useDemandLoading ); else parser.SetPassword( pw ); bIncorrectPw = false; } catch( const PdfError & e ) { if( e.GetError() == ePdfError_InvalidPassword ) { cout << endl << "Password :"; std::getline( cin, pw ); cout << endl; // try to continue with the new password bIncorrectPw = true; } else throw e; } } while( bIncorrectPw ); cerr << " done" << endl; cerr << "PdfVersion=" << parser.GetPdfVersion() << endl; cerr << "PdfVersionString=" << parser.GetPdfVersionString() << endl; /* cerr << "=============\n"); PdfObject* pCheat = objects.CreateObject( "Cheat" ); std::reverse( objects.begin(), objects.end() ); objects.RenumberObjects( const_cast(parser.GetTrailer()) ); pCheat = objects.CreateObject("LastObject"); cerr << "=============\n"); */ if (pszFilename) { cerr << "Writing..." << flush; write_back( &parser, pszFilename, eWriteMode ); cerr << " done" << endl; } } catch( PdfError & e ) { e.PrintErrorMsg(); return e.GetError(); } if (pszFilename) cerr << "Parsed and wrote successfully" << endl; else cerr << "Parsed successfully" << endl; /* cerr << "Now with PdfMemDocument" << endl; PdfMemDocument document; document.Load( pszInput ); document.Write( pszFilename ); cerr << "DONE: Now with PdfMemDocument" << endl; */ return 0; } podofo-0.9.3/test/ContentParser/0000775000175000017500000000000012356565164016444 5ustar dominikdominikpodofo-0.9.3/test/ContentParser/CMakeLists.txt0000664000175000017500000000037211460071654021175 0ustar dominikdominik ADD_EXECUTABLE(ContentParser main.cpp) TARGET_LINK_LIBRARIES(ContentParser ${PODOFO_LIB} ${PODOFO_LIB_DEPENDS}) SET_TARGET_PROPERTIES(ContentParser PROPERTIES COMPILE_FLAGS "${PODOFO_CFLAGS}") ADD_DEPENDENCIES(ContentParser ${PODOFO_DEPEND_TARGET}) podofo-0.9.3/test/ContentParser/main.cpp0000664000175000017500000001243211233743456020071 0ustar dominikdominik#include "podofo.h" #include "../PdfTest.h" #include #include #include #include #include #include using namespace std; using namespace PoDoFo; static bool print_output = false; void parse_contents( PdfContentsTokenizer* pTokenizer ) { const char* pszToken = NULL; PdfVariant var; EPdfContentsType eType; std::string str; int numKeywords = 0; int numVariants = 0; std::stack stack; while( pTokenizer->ReadNext( eType, pszToken, var ) ) { if( eType == ePdfContentsType_Keyword ) { ++numKeywords; if (print_output) std::cout << setw(12) << (numKeywords+numVariants) << " Keyword: " << pszToken << std::endl; // support 'l' and 'm' tokens if( strcmp( pszToken, "l" ) == 0 ) { double dPosY = stack.top().GetReal(); stack.pop(); double dPosX = stack.top().GetReal(); stack.pop(); if(print_output) std::cout << string(12,' ') << " LineTo: " << dPosX << " " << dPosY << std::endl; } else if( strcmp( pszToken, "m" ) == 0 ) { double dPosY = stack.top().GetReal(); stack.pop(); double dPosX = stack.top().GetReal(); stack.pop(); if(print_output) std::cout << string(12,' ') << " MoveTo: " << dPosX << " " << dPosY << std::endl; } } else if ( eType == ePdfContentsType_Variant ) { ++numVariants; var.ToString( str ); if(print_output) std::cout << setw(12) << (numKeywords+numVariants) << " Variant: " << str << std::endl; stack.push( var ); } else if (eType == ePdfContentsType_ImageData) { if (print_output) { std::string d ( var.GetRawData().data() ); std::cout << string(13, ' ') << "Inline image data: " << d.size() << " bytes. Hex follows." << std::hex << std::endl; std::cout << std::hex << std::setfill('0'); for ( std::string::iterator i = d.begin(); i != d.end(); i ++) { std::cout << std::setw(2) << (static_cast(*i) & 0x00FF); } std::cout << std::dec << std::setfill(' ') << std::endl; } } else { // Impossible; type must be keyword or variant PODOFO_RAISE_ERROR( ePdfError_InternalLogic ); } } cout << ' ' << setw(12) << numKeywords << " keywords, " << setw(12) << numVariants << " variants"; } void parse_page( PdfMemDocument*, PdfPage* pPage ) { PdfContentsTokenizer tokenizer( pPage ); parse_contents( &tokenizer ); } void usage() { printf("Usage: ContentParser [-g] [-a] [-p] input_filename\n"); printf(" -a Process all pages of input, not just first\n"); printf(" -p Print parsed content stream to stdout\n"); } int main( int argc, char* argv[] ) { bool all_pages = false; int firstPageNo = 0; string inputFileName; ++argv; --argc; while (argc) { if( argv[0][0] == '-' ) { // Single character flag switch( argv[0][1] ) { case 'a': // Process all pages, not just first page all_pages = true; break; case 'p': // Print output, rather than parsing & checking // silently. print_output = true; break; case 'n': // Page number request. Chars 2+ are page number int. Let's do // this the quick and dirty way... firstPageNo = atoi(argv[0]+2) - 1; cerr << "Will process page: " << (firstPageNo+1) << endl; break; default: usage(); return 1; } } else { // Input filename if (inputFileName.empty()) { inputFileName = argv[0]; } else { usage(); return 1; } } ++argv; --argc; } if (inputFileName.empty()) { usage(); return 1; } try { PdfMemDocument doc( inputFileName.c_str() ); if( !doc.GetPageCount() ) { std::cerr << "This document contains no page!" << std::endl; return 1; } int toPage = all_pages ? doc.GetPageCount() : firstPageNo + 1 ; for ( int i = firstPageNo; i < toPage; ++i ) { cout << "Processing page " << setw(6) << (i+1) << "..." << std::flush; PdfPage* page = doc.GetPage( i ); PODOFO_RAISE_LOGIC_IF( !page, "Got null page pointer within valid page range" ); parse_page( &doc, page ); cout << " - page ok" << endl; } } catch( const PdfError & e ) { e.PrintErrorMsg(); return e.GetError(); } cout << endl; return 0; } podofo-0.9.3/test/CMakeLists.txt0000664000175000017500000000026511536424150016404 0ustar dominikdominikSUBDIRS( ContentParser CreationTest DeviceTest FilterTest FormTest LargeTest ObjectParserTest ParserTest SignatureTest TokenizerTest VariantTest WatermarkTest unit ) podofo-0.9.3/test/system/0000775000175000017500000000000012356565164015201 5ustar dominikdominikpodofo-0.9.3/test/system/podofo-system.sh0000775000175000017500000000326011306524712020335 0ustar dominikdominik#!/bin/bash if [ $# -ne 1 ]; then echo "Usage:" echo "./podofo-system.sh PATH_TO_PARSER_TEST_EXECUTABLE" exit -1 fi BAVARIA_DOWNLOAD="http://www.pdflib.com/fileadmin/pdflib/Bavaria/2009-04-03-Bavaria-pdfa.zip" BAVARIA_NAME="2009-04-03-Bavaria-pdfa.zip" DATA_DIR=data OUTPUT_DIR=output/$(date +%Y%m%d-%H:%M) PREFIX_OUT="podofo_" SUFFIX_LOG=".log" PARSER_TEST=$1 FAILED_TESTS="" echo "Starting PoDoFo system test session." echo "" echo "Reading input data from: $DATA_DIR" echo "Writing output to : $OUTPUT_DIR" echo "Using parser test : $PARSER_TEST" echo "" if [ ! -e $DATA_DIR/$BAVARIA_NAME ]; then echo "Bavaria test suite missing, downloading ..." wget -O $DATA_DIR/$BAVARIA_NAME $BAVARIA_DOWNLOAD unzip -d $DATA_DIR $DATA_DIR/$BAVARIA_NAME echo "Download done." fi mkdir -p $OUTPUT_DIR count=0 errors=0 SAVED_IFS=$IFS # Make for loop work with filenames containing spaces IFS=$(echo -en "\n\b") FILES=$(find $DATA_DIR -name '*.pdf' -print) for file in $FILES do FILENAME=$(basename "$file") echo -n -e "Running system test for: $file " $PARSER_TEST "$file" "$OUTPUT_DIR/$PREFIX_OUT$FILENAME" &> "$OUTPUT_DIR/$PREFIX_OUT$FILENAME$SUFFIX_LOG" RET=$? export count=$(( $count + 1 )) if [ $RET -eq 0 ]; then echo -n -e "OK\n" else export errors=$(( $errors + 1)) echo -n -e "FAIL\n" FAILED_TESTS="$FAILED_TESTS\n$file" fi done echo "" echo "Number of files parsed : "$count echo "Number of files in error: "$errors echo "" IFS=$SAVED_IFS if [ $errors -eq 0 ]; then echo "SUCCESS" exit 0 else echo "List of failed tests:" echo -e $FAILED_TESTS echo "" echo "FAILED" exit -2 fi podofo-0.9.3/test/system/data/0000775000175000017500000000000012356565164016112 5ustar dominikdominikpodofo-0.9.3/test/LargeTest/0000775000175000017500000000000012356565164015547 5ustar dominikdominikpodofo-0.9.3/test/LargeTest/CMakeLists.txt0000664000175000017500000000055111057763005020277 0ustar dominikdominikIF(WANT_FONTCONFIG) # We don't build LargeTest on win32 since it depends on # fontconfig to operate ADD_EXECUTABLE(LargeTest LargeTest.cpp) TARGET_LINK_LIBRARIES(LargeTest ${PODOFO_LIB} ${PODOFO_LIB_DEPENDS}) SET_TARGET_PROPERTIES(LargeTest PROPERTIES COMPILE_FLAGS "${PODOFO_CFLAGS}") ADD_DEPENDENCIES(LargeTest ${PODOFO_DEPEND_TARGET}) ENDIF(WANT_FONTCONFIG) podofo-0.9.3/test/LargeTest/LargeTest.cpp0000664000175000017500000001466712347306415020153 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2006 by Dominik Seichter * * domseichter@web.de * * * * 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., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include #include using namespace PoDoFo; #define MIN_PAGES 100 bool writeImmediately = true; void AddPage( PdfDocument* pDoc, const char* pszFontName, const char* pszImagePath ) { PdfPainter painter; PdfPage* pPage; PdfFont* pFont; PdfFont* pArial; PdfImage* pImage; PdfRect rect; try { pFont = pDoc->CreateFont( pszFontName ); } catch ( const PdfError & e ) { e.PrintErrorMsg(); return; } pPage = pDoc->CreatePage( PdfPage::CreateStandardPageSize( ePdfPageSize_A4 ) ); pArial = pDoc->CreateFont( "Arial" ); pImage = new PdfImage( pDoc ); rect = pPage->GetMediaBox(); const char* pszText = "The red brown fox jumps over the lazy dog!"; double dX = rect.GetLeft() + 20.0; double dY = rect.GetBottom() + rect.GetHeight() - 20.0; double dW, dH; pFont->SetFontSize( 16.0 ); pArial->SetFontSize( 24.0 ); painter.SetPage( pPage ); painter.SetFont( pFont ); dW = pFont->GetFontMetrics()->StringWidth( pszText ); dH = -pFont->GetFontMetrics()->GetDescent(); // GetDescent is usually negative! pFont->SetFontSize( 24.0 ); dH += pFont->GetFontMetrics()->GetLineSpacing() * 2.0; painter.Rectangle( dX, dY, dW, dH ); painter.Stroke(); dY -= pFont->GetFontMetrics()->GetLineSpacing(); painter.DrawText( dX, dY, "Hello World!" ); dY -= pFont->GetFontMetrics()->GetLineSpacing(); pFont->SetFontSize( 16.0 ); painter.DrawText( dX, dY, pszText ); painter.SetFont( pArial ); dY -= pArial->GetFontMetrics()->GetLineSpacing(); painter.DrawText( dX, dY, "The font used in this example is:" ); dY -= pArial->GetFontMetrics()->GetLineSpacing(); painter.DrawText( dX, dY, pszFontName ); dY -= pArial->GetFontMetrics()->GetLineSpacing(); #if defined PODOFO_HAVE_JPEG_LIB || defined PODOFO_HAVE_TIFF_LIB try { pImage->LoadFromFile( pszImagePath ); } catch( const PdfError & e ) { e.PrintErrorMsg(); } dY -= (pImage->GetHeight() * 0.5); dX = ((rect.GetWidth() - (pImage->GetWidth()*0.5))/2.0); painter.DrawImage( dX, dY, pImage, 0.5, 0.5 ); delete pImage; // delete image right after drawing #endif painter.FinishPage(); } void CreateLargePdf( const char* pszFilename, const char* pszImagePath ) { PdfDocument* pDoc = NULL; FcObjectSet* pObjectSet; FcFontSet* pFontSet; FcPattern* pPattern; if( !FcInit() ) { fprintf( stderr, "Cannot load fontconfig!\n"); return; } pPattern = FcPatternCreate(); pObjectSet = FcObjectSetBuild( FC_FAMILY, FC_STYLE, NULL ); pFontSet = FcFontList( 0, pPattern, pObjectSet ); FcObjectSetDestroy( pObjectSet ); FcPatternDestroy( pPattern ); if( writeImmediately ) pDoc = new PdfStreamedDocument( pszFilename ); else pDoc = new PdfMemDocument(); if( pFontSet ) { for( int i=0; i< (pFontSet->nfont > MIN_PAGES ? MIN_PAGES : pFontSet->nfont );i++ ) { FcValue v; //FcPatternPrint( pFontSet->fonts[i] ); FcPatternGet( pFontSet->fonts[i], FC_FAMILY, 0, &v ); //font = FcNameUnparse( pFontSet->fonts[i] ); printf(" -> Drawing with font: %s\n", reinterpret_cast(v.u.s) ); AddPage( pDoc, reinterpret_cast(v.u.s), pszImagePath ); } FcFontSetDestroy( pFontSet ); } if( writeImmediately ) static_cast(pDoc)->Close(); else static_cast(pDoc)->Write( pszFilename ); delete pDoc; } void usage() { printf("Usage: LargetTest [-m] output_filename image_file\n" " output_filename: filename to write produced pdf to\n" " image_file: An image to embed in the PDF file\n" "Options:\n" " -m Build entire document in memory before writing\n" "\n" "Note that output should be the same with and without the -m option.\n"); } int main( int argc, char* argv[] ) { if( argc < 3 || argc > 4 ) { usage(); return 1; } else if ( argc == 4) { // Handle options // Is this argument an option? if (argv[1][0] != '-') { usage(); return 1; } // Is it a recognised option? if (argv[1][1] == 'm') { // User wants us to build the whole doc in RAM before writing it out. writeImmediately = false; ++argv; } else { printf("Unrecognised argument: %s", argv[1]); usage(); return 1; } } try { CreateLargePdf( argv[1], argv[2] ); printf("\nWrote the PDF file %s successfully\n", argv[1] ); } catch( PdfError & e ) { e.PrintErrorMsg(); return e.GetError(); } return 0; } podofo-0.9.3/test/VariantTest/0000775000175000017500000000000012356565165016122 5ustar dominikdominikpodofo-0.9.3/test/VariantTest/CMakeLists.txt0000664000175000017500000000037010614703752020651 0ustar dominikdominikADD_EXECUTABLE(VariantTest VariantTest.cpp) TARGET_LINK_LIBRARIES(VariantTest ${PODOFO_LIB} ${PODOFO_LIB_DEPENDS}) SET_TARGET_PROPERTIES(VariantTest PROPERTIES COMPILE_FLAGS "${PODOFO_CFLAGS}") ADD_DEPENDENCIES(VariantTest ${PODOFO_DEPEND_TARGET}) podofo-0.9.3/test/VariantTest/VariantTest.cpp0000664000175000017500000002617211460071654021070 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2005 by Dominik Seichter * * domseichter@web.de * * * * 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., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "../PdfTest.h" #include #include #include #include using namespace PoDoFo; // // Test encoding of names. // pszString : internal representation, ie unencoded name // pszExpectedEncoded: the encoded string PoDoFo should produce // void TestName( const char* pszString, const char* pszExpectedEncoded ) { printf("Testing name: %s\n", pszString ); PdfName name( pszString ); printf(" -> Expected Value: %s\n", pszExpectedEncoded ); printf(" -> Got Value: %s\n", name.GetEscapedName().c_str() ); printf(" -> Unescaped Value: %s\n", name.GetName().c_str() ); if( strcmp( pszExpectedEncoded, name.GetEscapedName().c_str() ) != 0 ) { PODOFO_RAISE_ERROR( ePdfError_TestFailed ); } // Ensure the encoded string compares equal to its unencoded // variant if( name != PdfName::FromEscaped(pszExpectedEncoded) ) { PODOFO_RAISE_ERROR( ePdfError_TestFailed ); } } void TestEncodedName( const char* pszString, const char* pszExpected ) { PdfName name( PdfName::FromEscaped(pszString) ); printf("Testing encoded name: %s\n", pszString ); printf(" -> Expected Value: %s\n", pszExpected ); printf(" -> Got Value: %s\n", name.GetName().c_str() ); printf(" -> Escaped Value: %s\n", name.GetEscapedName().c_str() ); if ( strcmp( pszExpected, name.GetName().c_str() ) != 0 ) { PODOFO_RAISE_ERROR( ePdfError_TestFailed ); } // Ensure the name compares equal with one constructed from the // expected unescaped form if ( ! (name == PdfName(pszExpected)) ) { PODOFO_RAISE_ERROR( ePdfError_TestFailed ); } } void TestNameEquality( const char * pszName1, const char* pszName2 ) { PdfName name1( PdfName::FromEscaped(pszName1) ); PdfName name2( PdfName::FromEscaped(pszName2) ); printf("Testing equality of encoded names '%s' and '%s'\n", pszName1, pszName2); printf(" -> Name1 Decoded Value: %s\n", name1.GetName().c_str()); printf(" -> Name2 Decoded Value: %s\n", name2.GetName().c_str()); if (name1 != name2) { PODOFO_RAISE_ERROR( ePdfError_TestFailed ); } } void Test( const char* pszString, EPdfDataType eDataType, const char* pszExpected = NULL ) { PdfVariant variant; std::string ret; if( !pszExpected ) pszExpected = pszString; printf("Testing with value: %s\n", pszString ); PdfTokenizer tokenizer( pszString, strlen( pszString ) ); tokenizer.GetNextVariant( variant, NULL ); printf(" -> Expected Datatype: %i\n", eDataType ); printf(" -> Got Datatype: %i\n", variant.GetDataType() ); if( variant.GetDataType() != eDataType ) { PODOFO_RAISE_ERROR( ePdfError_TestFailed ); } variant.ToString( ret ); printf(" -> Convert To String: %s\n", ret.c_str() ); if( strcmp( pszExpected, ret.c_str() ) != 0 ) { PODOFO_RAISE_ERROR( ePdfError_TestFailed ); } } int main() { PdfError eCode; printf("This test tests the PdfVariant class.\n"); printf("---\n"); std::auto_ptr pFilter = PdfFilterFactory::Create( ePdfFilter_ASCIIHexDecode ); // testing strings TEST_SAFE_OP( Test( "(Hallo Welt!)", ePdfDataType_String ) ); TEST_SAFE_OP( Test( "(Hallo \\(schne\\) Welt!)", ePdfDataType_String ) ); TEST_SAFE_OP( Test( "(Balanced () brackets are (ok ()) in PDF Strings)", ePdfDataType_String, "(Balanced \\(\\) brackets are \\(ok \\(\\)\\) in PDF Strings)" ) ); TEST_SAFE_OP( Test( "()", ePdfDataType_String ) ); TEST_SAFE_OP( Test( "(Test: \\064)", ePdfDataType_String, "(Test: \064)" ) ); TEST_SAFE_OP( Test( "(Test: \\0645)", ePdfDataType_String, "(Test: 45)" ) ); TEST_SAFE_OP( Test( "(Test: \\478)", ePdfDataType_String, "(Test: '8)" ) ); printf("---\n"); // testing HEX Strings TEST_SAFE_OP( Test( "", ePdfDataType_HexString ) ); TEST_SAFE_OP( Test( "", ePdfDataType_HexString, "" ) ); TEST_SAFE_OP( Test( "<>", ePdfDataType_HexString ) ); printf("---\n"); // testing bool TEST_SAFE_OP( Test( "false", ePdfDataType_Bool ) ); TEST_SAFE_OP( Test( "true", ePdfDataType_Bool ) ); printf("---\n"); // testing null TEST_SAFE_OP( Test( "null", ePdfDataType_Null ) ); printf("---\n"); // testing numbers TEST_SAFE_OP( Test( "145", ePdfDataType_Number ) ); TEST_SAFE_OP( Test( "-12", ePdfDataType_Number ) ); TEST_SAFE_OP( Test( "3.140000", ePdfDataType_Real ) ); TEST_SAFE_OP( Test( "-2.970000", ePdfDataType_Real ) ); TEST_SAFE_OP( Test( "0", ePdfDataType_Number ) ); TEST_SAFE_OP_IGNORE( Test( "4.", ePdfDataType_Real ) ); printf("---\n"); // testing references TEST_SAFE_OP( Test( "2 0 R", ePdfDataType_Reference ) ); TEST_SAFE_OP( Test( "3 0 R", ePdfDataType_Reference ) ); TEST_SAFE_OP( Test( "4 1 R", ePdfDataType_Reference ) ); printf("---\n"); // testing names TEST_SAFE_OP( Test( "/Type", ePdfDataType_Name ) ); TEST_SAFE_OP( Test( "/Length", ePdfDataType_Name ) ); TEST_SAFE_OP( Test( "/Adobe#20Green", ePdfDataType_Name ) ); TEST_SAFE_OP( Test( "/$$", ePdfDataType_Name ) ); TEST_SAFE_OP( Test( "/1.2", ePdfDataType_Name ) ); TEST_SAFE_OP( Test( "/.notdef", ePdfDataType_Name ) ); TEST_SAFE_OP( Test( "/@pattern", ePdfDataType_Name ) ); TEST_SAFE_OP( Test( "/A;Name_With-Various***Characters?", ePdfDataType_Name ) ); TEST_SAFE_OP( Test( "/", ePdfDataType_Name ) ); // empty names are legal, too! printf("---\n"); // testing arrays TEST_SAFE_OP_IGNORE( Test( "[]", ePdfDataType_Array ) ); // this test may fail as the formating is different TEST_SAFE_OP( Test( "[ ]", ePdfDataType_Array ) ); TEST_SAFE_OP( Test( "[ 1 2 3 4 ]", ePdfDataType_Array ) ); TEST_SAFE_OP_IGNORE( Test( "[1 2 3 4]", ePdfDataType_Array ) ); // this test may fail as the formating is different TEST_SAFE_OP( Test( "[ 2 (Hallo Welt!) 3.500000 /FMC ]", ePdfDataType_Array ) ); TEST_SAFE_OP( Test( "[ [ 1 2 ] (Hallo Welt!) 3.500000 /FMC ]", ePdfDataType_Array ) ); TEST_SAFE_OP_IGNORE( Test( "[/ImageA/ImageB/ImageC]", ePdfDataType_Array ) ); // this test may fail as the formating is different TEST_SAFE_OP_IGNORE( Test( "[<530464995927cef8aaf46eb953b93373><530464995927cef8aaf46eb953b93373>]", ePdfDataType_Array ) ); TEST_SAFE_OP_IGNORE( Test( "[ 2 0 R (Test Data) 4 << /Key /Data >> 5 0 R ]", ePdfDataType_Array ) ); TEST_SAFE_OP_IGNORE( Test( "[<>2 0 R]", ePdfDataType_Array ) ); printf("---\n"); // Test some names. The first argument is the unencoded representation, the second // is the expected encoded result. The result must not only be /a/ correct encoded // name for the unencoded form, but must be the exact one PoDoFo should produce. TEST_SAFE_OP( TestName( "Length With Spaces", "Length#20With#20Spaces" ) ); TEST_SAFE_OP( TestName( "Length\001\002\003Spaces\177", "Length#01#02#03Spaces#7F" ) ); TEST_SAFE_OP( TestName( "Length#01#02#03Spaces#7F", "Length#2301#2302#2303Spaces#237F" ) ); TEST_SAFE_OP( TestName( "Tab\tTest", "Tab#09Test" ) ); printf("---\n"); // Test some pre-encoded names. The first argument is the encoded name that'll be // read from the PDF; the second is the expected representation. TEST_SAFE_OP( TestEncodedName( "PANTONE#205757#20CV", "PANTONE 5757 CV") ); TEST_SAFE_OP( TestEncodedName( "paired#28#29parentheses", "paired()parentheses") ); TEST_SAFE_OP( TestEncodedName( "The_Key_of_F#23_Minor", "The_Key_of_F#_Minor") ); TEST_SAFE_OP( TestEncodedName( "A#42", "AB") ); printf("---\n"); // Make sure differently encoded names compare equal if their decoded values // are equal. TEST_SAFE_OP( TestNameEquality( "With Spaces", "With#20Spaces" ) ); TEST_SAFE_OP( TestNameEquality( "#57#69#74#68#20#53#70#61#63#65#73", "With#20Spaces" ) ); printf("---\n"); // TODO: Move to AlgorithmTest char* pszHex = static_cast(malloc( sizeof(char) * 256 )); memset(pszHex, 0, 256); strcpy( pszHex, "Hallo Du schoene Welt!" ); pdf_long lLen = strlen( pszHex ); char* pszResult = NULL; pdf_long lRes = -1; std::string out; TEST_SAFE_OP( pFilter->Encode( pszHex, lLen, &pszResult, &lRes ) ); free( pszHex ); pszHex = pszResult; lLen = lRes; out.assign(pszHex, lLen); std::cerr << "Encoded buffer: (" << out << ')' << std::endl; TEST_SAFE_OP( pFilter->Decode( pszHex, lLen, &pszResult, &lRes ) ); free( pszHex ); pszHex = pszResult; lLen = lRes; out.assign(pszHex, lLen); std::cerr << "Encoded buffer: (" << out << ')' << std::endl; TEST_SAFE_OP( pFilter->Encode( pszHex, lLen, &pszResult, &lRes ) ); free( pszHex ); pszHex = pszResult; lLen = lRes; out.assign(pszHex, lLen); std::cerr << "Encoded buffer: (" << out << ')' << std::endl; TEST_SAFE_OP( pFilter->Decode( pszHex, lLen, &pszResult, &lRes ) ); free( pszHex ); pszHex = pszResult; lLen = lRes; out.assign(pszHex, lLen); std::cerr << "Encoded buffer: (" << out << ')' << std::endl; free( pszHex ); // test a hex string containing a whitespace character pszHex = static_cast(malloc( sizeof(char) * 256 )); strcpy( pszHex, "48616C6C6F2044\n75207363686F656E652057656C7421"); lLen = strlen( pszHex ); TEST_SAFE_OP( pFilter->Decode( pszHex, lLen, &pszResult, &lRes ) ); free( pszHex ); pszHex = pszResult; lLen = lRes; out.assign(pszHex, lLen); std::cerr << "Encoded buffer: (" << out << ')' << std::endl; free( pszResult ); // TODO: test variant equality comparisons printf("Test completed with error code: %i\n", eCode.GetError() ); return eCode.GetError(); } podofo-0.9.3/test/SignatureTest/0000775000175000017500000000000012356565165016457 5ustar dominikdominikpodofo-0.9.3/test/SignatureTest/NSSSignatureGenerator.h0000664000175000017500000000236411536423656023026 0ustar dominikdominik/** NSS signature generator * * Mozilla has two APIs for generating signatures (older SEC_PKCS7) * and newer SMIME (CMS). We are using newer API. * * You have to have certificate (CERTCertificate * )which will be * used for signing. */ #ifndef _NSS_SIGNATURE_GENERATOR_H_ #define _NSS_SIGNATURE_GENERATOR_H_ #include #include #include #include #include "SignatureGenerator.h" namespace PoDoFo { class PdfData; }; class NSSSignatureGenerator : public SignatureGenerator { private: PoDoFo::PdfData *pSignature; CERTCertificate *pCert; NSSCMSMessage *cmsg; NSSCMSEncoderContext *enc; std::string signature; static void sm_write_stream(void *arg, const char *buf, unsigned long len); protected: // get digest algoritm for the signing algoritm static SECOidTag getDigestAlgor(CERTCertificate *pCert); // create message with signature static NSSCMSMessage *createSign(CERTCertificate *cert); public: NSSSignatureGenerator(CERTCertificate *pCert); virtual ~NSSSignatureGenerator(); virtual bool init(); virtual bool appendData(const char *pData, unsigned int dataSize); virtual bool finishData(); virtual const PoDoFo::PdfData *getSignature(); }; #endif // _NSS_SIGNATURE_GENERATOR_H_ podofo-0.9.3/test/SignatureTest/SimpleSignatureGenerator.h0000664000175000017500000000130312347347566023612 0ustar dominikdominik #ifndef _SIMPLE_SIGNATURE_GENERATOR_H_ #define _SIMPLE_SIGNATURE_GENERATOR_H_ #include "SignatureGenerator.h" #include /** Simple signature generator */ class SimpleSignatureGenerator :public SignatureGenerator { PoDoFo::PdfData *pSignature; public: SimpleSignatureGenerator() { pSignature = NULL; } virtual ~SimpleSignatureGenerator() { delete pSignature; } virtual bool appendData(const char * /*pData*/, unsigned int /*dataSize*/) { return true; } virtual bool finishData() { pSignature = new PoDoFo::PdfData("My-Test-Signature"); return true; } virtual const PoDoFo::PdfData *getSignature() { return pSignature; } }; #endif // _SIMPLE_SIGNATURE_GENERATOR_H_ podofo-0.9.3/test/SignatureTest/CMakeLists.txt0000664000175000017500000000101111536424150021173 0ustar dominikdominikSET(sign_srcs SignTest.cpp ) #IF(FALSE) # SET(sign_extra_libs -L/usr/lib -lssl3 -lsmime3 -lnss3 -lnssutil3) # SET(sign_srcs ${sign_srcs} NSSSignatureGenerator.cpp) # ADD_DEFINITIONS(-I/usr/include/nss -I/usr/include/nspr ) #ENDIF(FALSE) ADD_EXECUTABLE(SignatureTest ${sign_srcs}) TARGET_LINK_LIBRARIES(SignatureTest ${PODOFO_LIB} ${PODOFO_LIB_DEPENDS} ${sign_extra_libs} ) SET_TARGET_PROPERTIES(SignatureTest PROPERTIES COMPILE_FLAGS "${PODOFO_CFLAGS}") ADD_DEPENDENCIES(SignatureTest ${PODOFO_DEPEND_TARGET}) podofo-0.9.3/test/SignatureTest/SignTest.cpp0000664000175000017500000001231712262234754020720 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2011 by Dominik Seichter * * domseichter@web.de * * by Petr Pytelka * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "../../src/podofo.h" #include "../PdfTest.h" #include "SignatureGenerator.h" #include "SimpleSignatureGenerator.h" //#include "NSSSignatureGenerator.h" //#include //#include #include #include #include using namespace PoDoFo; #define CONVERSION_CONSTANT 0.002834645669291339 /* static CERTCertificate* read_cert() { CERTCertificate* pCert = NULL; SECStatus status; CERTCertDBHandle* pDbHandle; const char* pszDbName = "/home/dominik/Desktop/Documents"; / * status = CERT_InitCertDB( pDbHandle ); printf("Init database: %i\n", status ); status = CERT_OpenCertDBFilename( pDbHandle, strdup(pszDbName), 0 ); printf("Open database: %i\n", status ); */ /* pCert = CERT_FindCertByName ( pDbHandle, "domseichter@web.de" ); * / return pCert; } */ void CreateSimpleForm( PdfPage* pPage, PdfStreamedDocument* pDoc, const PdfData &signatureData ) { PdfPainter painter; PdfFont* pFont = pDoc->CreateFont( "Courier" ); painter.SetPage( pPage ); painter.SetFont( pFont ); painter.DrawText( 10000 * CONVERSION_CONSTANT, 280000 * CONVERSION_CONSTANT, "PoDoFo Sign Test" ); painter.FinishPage(); PdfSignatureField signField( pPage, PdfRect( 70000 * CONVERSION_CONSTANT, 10000 * CONVERSION_CONSTANT, 50000 * CONVERSION_CONSTANT, 50000 * CONVERSION_CONSTANT ), pDoc ); signField.SetFieldName("SignatureFieldName"); signField.SetSignature(signatureData); signField.SetSignatureReason("I agree"); // Set time of signing signField.SetSignatureDate( PdfDate() ); } int main( int argc, char* argv[] ) { PdfPage* pPage; if( argc != 2 ) { printf("Usage: SignTest [output_filename]\n"); printf(" - Create a PDF ready to be signed\n"); return 0; } PdfSignOutputDevice signer(argv[1]); // Reserve space for signature signer.SetSignatureSize(1024); PdfStreamedDocument writer( &signer, PoDoFo::ePdfVersion_1_5 ); // Disable default appearance writer.GetAcroForm(ePdfCreateObject, ePdfAcroFormDefaultAppearance_None); pPage = writer.CreatePage( PdfPage::CreateStandardPageSize( ePdfPageSize_A4 ) ); TEST_SAFE_OP( CreateSimpleForm( pPage, &writer, *signer.GetSignatureBeacon() ) ); TEST_SAFE_OP( writer.Close() ); // Check if position of signature was found if(signer.HasSignaturePosition()) { // Adjust ByteRange for signature signer.AdjustByteRange(); // Read data for signature and count it // We have to seek at the beginning of the file signer.Seek(0); // Generate digest and count signature // use NSS, MS Crypto API or OpenSSL // to generate signature in DER format // This is example of generation process // with dummy generator. Check example for // NSS generator /* SimpleSignatureGenerator sg; // Read data to be signed and send them to the // signature generator char buff[65536]; size_t len; while( (len = signer.ReadForSignature(buff, 65536))>0 ) { sg.appendData(buff, len); } sg.finishData(); // Paste signature to the file const PdfData *pSignature = sg.getSignature(); */ /* CERTCertificate* pCert = read_cert(); NSSSignatureGenerator ng(pCert); char buff[65536]; size_t len; while( (len = signer.ReadForSignature(buff, 65536))>0 ) { ng.appendData(buff, len); } ng.finishData(); // Paste signature to the file const PdfData *pSignature = ng.getSignature(); CERT_DestroyCertificate(pCert); if(pSignature!=NULL) { signer.SetSignature(*pSignature); } */ } signer.Flush(); return 0; } podofo-0.9.3/test/SignatureTest/NSSSignatureGenerator.cpp0000664000175000017500000001306511536423656023361 0ustar dominikdominik/** NSS signature generator * * Mozilla has two APIs for generating signatures (older SEC_PKCS7) * and newer SMIME (CMS). We are using newer API. * * You have to have certificate (CERTCertificate * )which will be * used for signing. */ #include "NSSSignatureGenerator.h" #include void NSSSignatureGenerator::sm_write_stream(void *arg, const char *buf, unsigned long len) { NSSSignatureGenerator* pThis = static_cast(arg); pThis->signature.append(buf, len); } SECOidTag NSSSignatureGenerator::getDigestAlgor(CERTCertificate *pCert) { SECAlgorithmID *algID = &pCert->signature; if(algID==NULL) return SEC_OID_MD5; SECOidTag algOIDTag = SECOID_FindOIDTag(&algID->algorithm); switch(algOIDTag) { case SEC_OID_MD5: case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION: case SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC: return SEC_OID_MD5; case SEC_OID_SHA1: case SEC_OID_ISO_SHA_WITH_RSA_SIGNATURE: case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION: case SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC: case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4: case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4: case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC: case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC: case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC: case SEC_OID_PKCS12_RSA_SIGNATURE_WITH_SHA1_DIGEST: case SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST: case SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST: case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4: case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4: case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC: case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC: case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC: case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC: case SEC_OID_HMAC_SHA1: return SEC_OID_SHA1; case SEC_OID_SHA256: case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION: case SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE: case SEC_OID_HMAC_SHA256: return SEC_OID_SHA256; case SEC_OID_SHA384: case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION: case SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE: case SEC_OID_HMAC_SHA384: return SEC_OID_SHA384; case SEC_OID_SHA512: case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION: case SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE: case SEC_OID_HMAC_SHA512: return SEC_OID_SHA512; } PODOFO_ASSERT(0); return SEC_OID_MD5; } // create message with signature NSSCMSMessage* NSSSignatureGenerator::createSign(CERTCertificate *cert) { NSSCMSSignedData *sigd = NULL; NSSCMSContentInfo *cinfo = NULL; NSSCMSSignerInfo *signerinfo = NULL; SECOidTag hash=getDigestAlgor(cert); NSSCMSMessage *cmsg = NSS_CMSMessage_Create(NULL); // create a message on its own pool if (cmsg == NULL) return NULL; if ((sigd = NSS_CMSSignedData_Create(cmsg)) == NULL) { NSS_CMSMessage_Destroy(cmsg); return NULL; } cinfo = NSS_CMSMessage_GetContentInfo(cmsg); if (NSS_CMSContentInfo_SetContent_SignedData(cmsg, cinfo, sigd) != SECSuccess) { NSS_CMSMessage_Destroy(cmsg); return NULL; } // if !detatched, the contentinfo will alloc a data item for us cinfo = NSS_CMSSignedData_GetContentInfo(sigd); if (NSS_CMSContentInfo_SetContent_Data(cmsg, cinfo, NULL, PR_TRUE ) != SECSuccess) { NSS_CMSMessage_Destroy(cmsg); return NULL; } signerinfo = NSS_CMSSignerInfo_Create(cmsg, cert, hash); if (signerinfo == NULL) { NSS_CMSMessage_Destroy(cmsg); return NULL; } // we want the cert chain included for this one if (NSS_CMSSignerInfo_IncludeCerts(signerinfo, NSSCMSCM_CertChainWithRoot, certUsageEmailSigner) != SECSuccess) { NSS_CMSMessage_Destroy(cmsg); return NULL; } // SMIME RFC says signing time should always be added if (NSS_CMSSignerInfo_AddSigningTime(signerinfo, PR_Now()) != SECSuccess) { NSS_CMSMessage_Destroy(cmsg); return NULL; } if (NSS_CMSSignedData_AddSignerInfo(sigd, signerinfo) != SECSuccess) { NSS_CMSMessage_Destroy(cmsg); return NULL; } return cmsg; } NSSSignatureGenerator::NSSSignatureGenerator(CERTCertificate *pCert) :pCert(pCert) { pSignature = NULL; } NSSSignatureGenerator::~NSSSignatureGenerator() { delete pSignature; if(enc!=NULL) NSS_CMSEncoder_Cancel(enc); if(cmsg!=NULL) NSS_CMSMessage_Destroy(cmsg); } bool NSSSignatureGenerator::init() { cmsg = createSign(pCert); if(cmsg==NULL) return false; // Prepare encoder enc = NSS_CMSEncoder_Start(cmsg, sm_write_stream, this, // DER output callback NULL, NULL, // destination storage NULL, NULL, // password callback NULL, NULL, // decrypt key callback NULL, NULL ); // detached digests } bool NSSSignatureGenerator::appendData(const char *pData, unsigned int dataSize) { if(enc == NULL) return false; if (NSS_CMSEncoder_Update(enc, pData, dataSize) != SECSuccess) { NSS_CMSEncoder_Cancel(enc); enc = NULL; return false; } return true; } bool NSSSignatureGenerator::finishData() { if(enc == NULL) return false; if (NSS_CMSEncoder_Finish(enc) != SECSuccess) { enc = NULL; return false; } enc = NULL; return true; } const PoDoFo::PdfData* NSSSignatureGenerator::getSignature() { if(pSignature==NULL) { pSignature = new PoDoFo::PdfData(signature.c_str(), signature.size()); } return pSignature; } podofo-0.9.3/test/SignatureTest/SignatureGenerator.h0000664000175000017500000000057211536423656022441 0ustar dominikdominik #ifndef _SIGNATURE_GENERATOR_H_ #define _SIGNATURE_GENERATOR_H_ namespace PoDoFo { class PdfData; }; /** Abstract class for signature generator */ class SignatureGenerator { public: virtual bool appendData(const char* pData, unsigned int dataSize)=0; virtual bool finishData()=0; virtual const PoDoFo::PdfData* getSignature()=0; }; #endif // _SIGNATURE_GENERATOR_H_ podofo-0.9.3/test/FormTest/0000775000175000017500000000000012356565165015421 5ustar dominikdominikpodofo-0.9.3/test/FormTest/CMakeLists.txt0000664000175000017500000000035110631070103020131 0ustar dominikdominikADD_EXECUTABLE(FormTest FormTest.cpp) TARGET_LINK_LIBRARIES(FormTest ${PODOFO_LIB} ${PODOFO_LIB_DEPENDS}) SET_TARGET_PROPERTIES(FormTest PROPERTIES COMPILE_FLAGS "${PODOFO_CFLAGS}") ADD_DEPENDENCIES(FormTest ${PODOFO_DEPEND_TARGET}) podofo-0.9.3/test/FormTest/FormTest.cpp0000664000175000017500000003303512347271543017666 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2007 by Dominik Seichter * * domseichter@web.de * * * * 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., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "../../src/podofo.h" #include "../PdfTest.h" #include #include using namespace PoDoFo; #define CONVERSION_CONSTANT 0.002834645669291339 void CreateComplexForm( PdfPage* pPage, PdfStreamedDocument* pDoc ) { PdfRect rect = pPage->GetPageSize(); PdfPainter painter; PdfFont* pFont = pDoc->CreateFont( "Courier" ); painter.SetPage( pPage ); painter.SetFont( pFont ); const char* pszTitle = "PoDoFo Sample Feedback Form"; pFont->SetFontSize( 18.0 ); double x = (rect.GetWidth() - pFont->GetFontMetrics()->StringWidth( pszTitle )) / 2.0; double y = rect.GetHeight() - (20000.0 * CONVERSION_CONSTANT); painter.DrawText( x, y, pszTitle ); pFont->SetFontSize( 10.0 ); y -= 10000.0 * CONVERSION_CONSTANT; x = 10000.0 * CONVERSION_CONSTANT; double h = 10000.0 * CONVERSION_CONSTANT; // Name y -= 10000.0 * CONVERSION_CONSTANT; painter.DrawText( x, y, "Your Name:" ); PdfTextField textName( pPage, PdfRect( 80000.0 * CONVERSION_CONSTANT, y - 2500.0 * CONVERSION_CONSTANT, 80000.0 * CONVERSION_CONSTANT, h ), pDoc ); textName.SetFieldName("field_name"); textName.SetBorderColor( 1.0 ); // E-Mail y -= 10000.0 * CONVERSION_CONSTANT; painter.DrawText( x, y, "E-Mail Address:" ); PdfTextField textMail( pPage, PdfRect( 80000.0 * CONVERSION_CONSTANT, y - 2500.0 * CONVERSION_CONSTANT, 80000.0 * CONVERSION_CONSTANT, h ), pDoc ); textMail.SetFieldName("field_mail"); textMail.SetBorderColor( 1.0 ); // Interest y -= 10000.0 * CONVERSION_CONSTANT; painter.DrawText( x, y, "Job:" ); PdfComboBox comboJob( pPage, PdfRect( 80000.0 * CONVERSION_CONSTANT, y - 2500.0 * CONVERSION_CONSTANT, 80000.0 * CONVERSION_CONSTANT, h ), pDoc ); comboJob.SetFieldName("field_combo"); comboJob.SetBorderColor( 1.0 ); comboJob.InsertItem( "Software Engineer" ); comboJob.InsertItem( "Student" ); comboJob.InsertItem( "Publisher" ); comboJob.InsertItem( "Other" ); // Open Source y -= 11000.0 * CONVERSION_CONSTANT; painter.DrawText( x, y, "I wan't to use PoDoFo in an Open Source application" ); PdfCheckBox checkOpenSource( pPage, PdfRect( 120000.0 * CONVERSION_CONSTANT, y - 2500.0 * CONVERSION_CONSTANT, h, h ), pDoc ); checkOpenSource.SetFieldName("field_check_oss"); // Commercial y -= 11000.0 * CONVERSION_CONSTANT; painter.DrawText( x, y, "I wan't to use PoDoFo in a commercial application" ); PdfCheckBox checkCom( pPage, PdfRect( 120000.0 * CONVERSION_CONSTANT, y - 2500.0 * CONVERSION_CONSTANT, h, h ), pDoc ); checkCom.SetFieldName("field_check_com"); y -= 10000.0 * CONVERSION_CONSTANT; painter.DrawText( x, y, "Some comments you want to send to the PoDoFo developers:" ); PdfTextField textComment( pPage, PdfRect( 20000.0 * CONVERSION_CONSTANT, y - 120000.0 * CONVERSION_CONSTANT, 160000.0 * CONVERSION_CONSTANT, 100000.0 * CONVERSION_CONSTANT ), pDoc ); textComment.SetFieldName("field_comment"); textComment.SetMultiLine( true ); textComment.SetRichText( true ); textComment.SetText( "

Here is some bold italic text

This text uses default text state parameters but changes the font size to 16.

"); PdfPushButton buttonSend( pPage, PdfRect( 10000 * CONVERSION_CONSTANT, 10000 * CONVERSION_CONSTANT, 25000 * CONVERSION_CONSTANT, 25000 * CONVERSION_CONSTANT ), pDoc ); buttonSend.SetFieldName("field_send"); buttonSend.SetCaption("Send"); buttonSend.SetBackgroundColor( 0.5 ); PdfPushButton buttonClear( pPage, PdfRect( 40000 * CONVERSION_CONSTANT, 10000 * CONVERSION_CONSTANT, 25000 * CONVERSION_CONSTANT, 25000 * CONVERSION_CONSTANT ), pDoc ); buttonClear.SetFieldName("field_clear"); buttonClear.SetCaption("Clear"); buttonClear.SetBackgroundColor( 0.5 ); PdfAction actionClear( ePdfAction_JavaScript, pDoc ); actionClear.SetScript( PdfString("this.getField(\"field_name\").value = \"\";" \ "this.getField(\"field_mail\").value = \"\";" \ "this.getField(\"field_combo\").value = \"\";" "this.getField(\"field_check_oss.\").checkThisBox( 0, false );" \ "this.getField(\"field_check_com.\").checkThisBox( 0, false );" \ "this.getField(\"field_comment\").value = \"\";" ) ); buttonClear.SetMouseDownAction( actionClear ); PdfAction actionSubmit( ePdfAction_SubmitForm, pDoc ); buttonSend.SetMouseDownAction( actionSubmit ); painter.FinishPage(); } void CreateSimpleForm( PdfPage* pPage, PdfStreamedDocument* pDoc ) { PdfPainter painter; PdfFont* pFont = pDoc->CreateFont( "Courier" ); painter.SetPage( pPage ); painter.SetFont( pFont ); painter.DrawText( 10000 * CONVERSION_CONSTANT, 280000 * CONVERSION_CONSTANT, "PoDoFo Interactive Form Fields Test" ); painter.FinishPage(); PdfPushButton button( pPage, PdfRect( 10000 * CONVERSION_CONSTANT, 10000 * CONVERSION_CONSTANT, 50000 * CONVERSION_CONSTANT, 50000 * CONVERSION_CONSTANT ), pDoc ); button.SetFieldName("ButtonFieldName"); button.SetAlternateName("ButtonAlternateName"); button.SetMappingName("ButtonMappingName"); button.SetCaption("Hallo Welt"); PdfAction action( ePdfAction_JavaScript, pDoc ); action.SetScript( PdfString("var str = this.getField(\"TextFieldName\").value;" \ "var j = 4*5;" \ "app.alert(\"Hello World! 4 * 5 = \" + j + \" Text Field: \" + str );") ); button.SetMouseDownAction( action ); PdfTextField text( pPage, PdfRect( 70000 * CONVERSION_CONSTANT, 10000 * CONVERSION_CONSTANT, 50000 * CONVERSION_CONSTANT, 50000 * CONVERSION_CONSTANT ), pDoc ); text.SetFieldName("TextFieldName"); text.SetMultiLine( true ); text.SetMultiLine( false ); text.SetFileField( true ); printf("Text IsMultiLine: %i\n", text.IsMultiLine() ); PdfComboBox combo( pPage, PdfRect( 10000 * CONVERSION_CONSTANT, 250000 * CONVERSION_CONSTANT, 50000 * CONVERSION_CONSTANT, 10000 * CONVERSION_CONSTANT ), pDoc ); combo.SetFieldName("ComboFieldName"); combo.InsertItem( "Value1" ); combo.InsertItem( "Value2" ); combo.InsertItem( "Value3" ); combo.InsertItem( "XXXX", "Displayed Text" ); combo.SetEditable( true ); combo.SetSelectedItem( 1 ); printf("IsComboBox: %i\n", combo.IsComboBox() ); printf("Count : %i\n", static_cast(combo.GetItemCount()) ); printf("Selected : %i\n", combo.GetSelectedItem() ); PdfListBox listBox( pPage, PdfRect( 70000 * CONVERSION_CONSTANT, 200000 * CONVERSION_CONSTANT, 50000 * CONVERSION_CONSTANT, 50000 * CONVERSION_CONSTANT ), pDoc ); listBox.SetFieldName("ListBoxFieldName"); listBox.InsertItem( "Value1", "Display 1" ); listBox.InsertItem( "Value2", "Display 2" ); listBox.InsertItem( "Value3", "Display 3" ); //listBox.InsertItem( "XXXX", "Displayed Text" ); listBox.SetMultiSelect( true ); listBox.SetSelectedItem( 2 ); } void FillTextField( PdfTextField & rField ) { const char* pszCur = rField.GetText().GetString(); std::cout << " Current value:" << (pszCur ? pszCur : "") << std::endl; std::string value; std::cout << " Enter new value (if empty value is unchanged):" << std::endl; #if defined(_MSC_VER) && _MSC_VER <= 1200 // Visual Studio 6 { char buff[10240]; if (gets(buff)) value = buff; } #else getline( std::cin, value ); #endif if( value.length() ) { rField.SetText( value ); } } void FillListField( PdfListField & rField ) { const char* pszCur = ( rField.GetSelectedItem() == -1 ? NULL : rField.GetItemDisplayText( rField.GetSelectedItem() ).GetString() ); std::cout << " Current value:" << (pszCur ? pszCur : "") << std::endl; std::cout << " Values:" << std::endl; for( int i=0;i(rField.GetItemCount());i++ ) { pszCur = rField.GetItemDisplayText( i ).GetString(); std::cout << " " << i << " " << (pszCur ? pszCur : "") << std::endl; } int nValue; std::cout << " Enter index of new value:" << std::endl; std::cin >> nValue; if( nValue >= 0 && nValue < static_cast(rField.GetItemCount()) ) rField.SetSelectedItem( nValue ); } void FillForm( const char* pszFilename, const char* pszOutput ) { PdfMemDocument doc( pszFilename ); PdfPage* pPage; int nPageCount = doc.GetPageCount(); int nFieldCount; for( int i=0;iGetNumFields(); std::cout << "Page " << i + 1 << " contains " << nFieldCount << " fields." << std::endl; for( int n=0;nGetField( n ); EPdfField eType = field.GetType(); std::cout << " Field: " << field.GetFieldName().GetString() << std::endl; std::cout << " Type : "; switch( eType ) { case ePdfField_PushButton: std::cout << "PushButton" << std::endl; break; case ePdfField_CheckBox: std::cout << "CheckBox" << std::endl; break; case ePdfField_RadioButton: std::cout << "RadioButton" << std::endl; break; case ePdfField_TextField: { std::cout << "TextField" << std::endl; PdfTextField text( field ); FillTextField( text ); break; } case ePdfField_ComboBox: { std::cout << "ComboBox" << std::endl; PdfListField lst( field ); FillListField( lst ); break; } case ePdfField_ListBox: { std::cout << "ListBox" << std::endl; PdfListField lst( field ); FillListField( lst ); break; } case ePdfField_Signature: std::cout << "Signature" << std::endl; break; case ePdfField_Unknown: default: std::cout << "Unknown" << std::endl; break; } std::cout << std::endl; } } doc.Write( pszOutput ); } int main( int argc, char* argv[] ) { PdfPage* pPage; if( argc != 2 && argc != 3 ) { printf("Usage: FormTest [output_filename]\n"); printf(" - Create a new example PDF form\n"); printf(" Formtest [input_filename] [output_filename]\n"); printf(" - Fill out an existing form and save it to a PDF file\n"); return 0; } if( argc == 3 ) { TEST_SAFE_OP( FillForm( argv[1], argv[2] ) ); } else { PdfStreamedDocument writer( argv[1] ); pPage = writer.CreatePage( PdfPage::CreateStandardPageSize( ePdfPageSize_A4 ) ); TEST_SAFE_OP( CreateComplexForm( pPage, &writer ) ); pPage = writer.CreatePage( PdfPage::CreateStandardPageSize( ePdfPageSize_A4 ) ); TEST_SAFE_OP( CreateSimpleForm( pPage, &writer ) ); TEST_SAFE_OP( writer.Close() ); } return 0; } podofo-0.9.3/test/SignTest/0000775000175000017500000000000012356565165015416 5ustar dominikdominikpodofo-0.9.3/test/SignTest/CMakeLists.txt0000664000175000017500000000035111520343546020142 0ustar dominikdominikADD_EXECUTABLE(SignTest SignTest.cpp) TARGET_LINK_LIBRARIES(SignTest ${PODOFO_LIB} ${PODOFO_LIB_DEPENDS}) SET_TARGET_PROPERTIES(SignTest PROPERTIES COMPILE_FLAGS "${PODOFO_CFLAGS}") ADD_DEPENDENCIES(SignTest ${PODOFO_DEPEND_TARGET}) podofo-0.9.3/test/SignTest/SignTest.cpp0000664000175000017500000000725211520343546017655 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2011 by Dominik Seichter * * domseichter@web.de * * by Petr Pytelka * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "../../src/podofo.h" #include "../PdfTest.h" #include #include #include using namespace PoDoFo; #define CONVERSION_CONSTANT 0.002834645669291339 void CreateSimpleForm( PdfPage* pPage, PdfStreamedDocument* pDoc, const PdfData &signatureData ) { PdfPainter painter; PdfFont* pFont = pDoc->CreateFont( "Courier" ); painter.SetPage( pPage ); painter.SetFont( pFont ); painter.DrawText( 10000 * CONVERSION_CONSTANT, 280000 * CONVERSION_CONSTANT, "PoDoFo Sign Test" ); painter.FinishPage(); PdfSignatureField signField( pPage, PdfRect( 70000 * CONVERSION_CONSTANT, 10000 * CONVERSION_CONSTANT, 50000 * CONVERSION_CONSTANT, 50000 * CONVERSION_CONSTANT ), pDoc ); signField.SetFieldName("SignatureFieldName"); signField.SetSignature(signatureData); signField.SetSignatureReason("I agree"); } int main( int argc, char* argv[] ) { PdfPage* pPage; if( argc != 2 ) { printf("Usage: SignTest [output_filename]\n"); printf(" - Create a PDF ready to be signed\n"); return 0; } PdfSignOutputDevice signer(argv[1]); // Reserve space for signature signer.SetSignatureSize(1024); PdfStreamedDocument writer( &signer, PoDoFo::ePdfVersion_1_5 ); // Disable default appearance writer.GetAcroForm(ePdfCreateObject, PdfAcroForm::ePdfAcroFormDefaultAppearance_None); pPage = writer.CreatePage( PdfPage::CreateStandardPageSize( ePdfPageSize_A4 ) ); TEST_SAFE_OP( CreateSimpleForm( pPage, &writer, *signer.GetSignatureBeacon() ) ); TEST_SAFE_OP( writer.Close() ); // Adjust ByteRange for signature if(signer.HasSignaturePosition()) { signer.AdjustByteRange(); // read data for signature and count it signer.Seek(0); // generate digest and count signature // use NSS, MS Crypto API or OpenSSL // to generate signature in DER format char buff[65536]; size_t len; while( (len = signer.ReadForSignature(buff, 65536))>0 ) { } // Paste signature to the file PdfData sigData("my-real-signature"); signer.SetSignature(sigData); } signer.Flush(); return 0; } podofo-0.9.3/test/CreationTest/0000775000175000017500000000000012356565165016262 5ustar dominikdominikpodofo-0.9.3/test/CreationTest/resources/0000775000175000017500000000000012356565165020274 5ustar dominikdominikpodofo-0.9.3/test/CreationTest/resources/lena.jpg0000664000175000017500000063702310714372313021713 0ustar dominikdominikJFIFHHCC"  = !"#12 A$3BQ4CR%&a 6bqrD =!"12A#BQa$3RqbCr%4SDc ?JH?=YpyZ|`μ*2R̒=Y%=zI *T:xvpǒ=>ʏj;jى+ryyAʷ(U^Z@FDXWf]xYPFB^n4OR>99S9㧿חQ֋n)Y΋rrY`1?JF.@Y1gJ8u)&B:-+{$V6 vj# "s,0Fhc*"0't7I5|qt 6ux;s>šn{ Q=KZƲbr!P>6O$ -J)>7W4ǒg@27?Sķ|,[ي'SJ;y,չG"(oI*@ڏD e;x'zm\EdʮTbOOK?ܳbr4U`\3, P(Rj݅(o#:KӇ df+& :oD`!5*+HZylE0 Փ_?FckEnrHtjŐ$p*{V 2 <襑qʷ ԥ2!=`0ԧazlMau-$fBh],OkDbU{ʈyVr)K{9 BS 4~ Y5%F(. PuH£UV~׉Kp:Hx@2L|Lzǎ0OTo7BWތ 1B @ee\,դo:Tp,ǯnUDDŽ1Ԕ,\w!Yy04㪬+AAe[!jA$R1*ӰBwOvAM,YIXZQ:/z*@)]vՊ楚 SՅG'+Ӷ" 1HR?ۃu #(u#q*ibP>ذ;Y[ 8<(k.Z3REIbȠ+(BQE&:}F)r~JK8'ۨD:vJ(Ư@ʬZ ÕU+ܷixE}vSjx!ȊpDVm`DŽPek5oa U5@×#PTST5,hp)7]u,lPfCӞ xcʀ#^Q^PYZH?[RN@#Ȩ(}&I3EJHA3޵T]UC-~#C23s?1 eYDl xVA~ӿ şJ!Xj#䐫ggਲRX2FJ䚷` TA T]d1qGt <{}7Lo&HSvc3O>K3L ~ ފ(Ư& Z!)5Pg죰S"oY([Wנնk(CJrhܵߏ#j(D(T5$lA*H~<v%:c¦Y`FO@ pHxV Ce 38 DkS~ ^v5IȺ'Z?ߒ*ǨfQUW%4q<)۟~rs'ܼjY&UZgpzPS>yßr*U  R? *bx21jdvP{|%ᩳi,]o\l<rh6LQ2H̪1rAbTӖ8{O,ԐI*]}'V^׃iMױʬ8 @KNYWyZ&}4]gdM-CEtF)t*8UUfrgq%Y:2) j>2@yWzKxot@@ZGIS\}NW.:Q<@ VG~}Y9`U:=up*9rU)|s~<(]Go x^4 zAj׆W$'#K3;L@ȫ:P(**>iN`g XP $ Q7#kFl͂=3N`t V|du%!ٚr{a7סPGeFgݼ F1_H 8^~ɕt3 St!HngD_4$ )d,}q{#.xY N{_"`ܭkڍHaTmT4[=lv` 38=VhHb)'NU@ϫ*|2UJXvzxk)6n (%.V<ߖPY$"/yMؑ FYe!Of*׷|$[u[A5,>H4p$(4ŲِUbDq,B5_202&(^8 ^ =pZ.9Eڇ!}֎Ů$)@@Mʆ!}pݦdriu/Ȁ GPikeEt 'EڅZV0/_('[؀I'찴9ljA@ ^_9B;@2VRA`5(ꥃup X/'3yN|ױ%I^ʃ܀St‡Nxfj'Ëx)u`h>+ۀÅ&Ac )(> BA!T sc@BF”X {a`n]Lzʼn0HNIޯޗot#^mP4||쑙,A&GT`l`ʾ:t̿OM#n#Luֳ^׫~6#:eCdX@Bꚶ\KUW*”Ȫd}UJHOtAo\lVE8VYHۏT,m?tbtٗS#6.ܬʋe*$ba/!w=Ldj g',ZM9$TBB+IQhmJQYGnb>Dz/~VU w91 _ Tur,@j(:y,lr48~B~u$ ΢x}T" nQ|` @" 4rTcRY%q݋*r%7*O1PG݂vvb6wJi!iFND( {LT[c54I8_;1 >WHIzLTC|3P/ ?L^֞8;!r̤Е@ØcW&ӢiqgDsArS~4vIX账ufW):hh2*NFk٩>g 1 T']VĖ =rA-LId+*Wgʞ^jtipK b}є"j"/ARr`f=8SQwWַyXfPyPp[,U#r|JI@֐ <aI 3¾8<@bJy1U @ϿJg_u ~*~Y-PȅK|zI+j0p~Bq2x* T'r/ sb:[Մ$'QdY&_#@ St 5 tMfCpg0$7ԎTde\p#95@: dYGQg"Bd ڬ^U2q~dSآ6F*5r*Ht7^՘䒠X3p+j?E6PŃ(lKeX. 6ح 27OJQ[1qBȾ13ٻ{+FIJX#x=xJ10BšX"ٸ2ȥyG UYBd2OZ*M|d-^̨L \!BfTj~5HCɍ[C4d4Io_Wk!ӢIVv'sUuCv JjEU a׿13Rѧn (4|CFa5^[tbX{,QʵRPv,* 'Xl1U_SUj$(WRuPSphA تŨXUy%gZ )ϟv}꽛tdPcwTu<C졽>9{;ubyNB.°Fwjͻ)QǐGxEӣuUY QWCͧ_GN 6Y+Ann+em~}K}z)D0!E|[Ze5iDjfDž%YfFTTrqES/3rrM(suҧnAVa3^ΨL9j[JHnnRZ 5r*°w#BEjYK4_Ѫ<4xLk ̬sG%B_xT󞜏vvEVz:'*P5qY;DMKEᔺuۄZ:7GP v}(|HLiJ6,Fe*lH5lU@HŷVP[A~&?$BcPF:#SࢂLUe^!Ʃ{)~T^TPF8b$,h4p@^yBQ[yynأ(߫ev❤  Pro:Cײ|`J |1T[S? , kȰ+,mbֶ̧\ ͮiDlcOQUBnU=n[F*@:s:t t_!V4hTR[~G~l), HBӂh -j?40Ok,1|u":wI-|B,WXy u/W3z@YVfe,C˚339tfDj) Jp?I>`VfWе[yR=F A`9@ j܊7:B|:5 ,6vY: )h#DdN )tqFے٨{B|&O劊#'E*fAx2U(<(R'ƃ&hkyOr"> ѽTsj@QJb(OVE8`҄]cYf2RU ڬLf6H"`#_hr;w9CʔEErhQT?v=A&Wg4?p,:ND**rU<3BUyEGZ+͙1Ybr]@%Րx? Iݟ Y͗G*@D%@!2 dF='"7~JEA6m7M6(׏+X:l&tuo W?m(p]b2/bʡ||rwTrÐOF0*:ꪷvQ>s•,yb:*!6VB8VAWf@TisE,%)j܆Rs>MeU@#7MG U Mhjb7_4lKPʒߏ%1flVUq~ʷi+8.2foْ"TSd~߇̓FV̠r~+?`fNGRX*3x,ú7 33 3vu.̮ >*K *j ؖ* a ,W$LgRkdh\~"LWVHrݙxxtwء.O ADJ `>, 5DK*{)v3-5(WHZ:^XY oRX7GR Hi|[-uFQe钽hX?C6N*AbWBۯamO/3qi%|l+Ł+:QY V?3%hu']I,ECQGӓ`d`ʣY@ߓu(6HcEԓ2t>_uW*A!tiީ-c JҒwE^s4BA4U`*#x}75/ZbYht8JY:adN<=7Ed"ՖX_UmdslI|7 9/*7Fvն6ƂS$8q;_Rd%4`Uܐ.S1yx_pLG֧ﶜ?[wOu4FSl?#ڔ3bb#$t,W\{2CERjAp&ʹ^ӡ`LCU yqDvΤ!EGUt22i\$4{Fjqzjو( P #"1J %d(8B̠2\|e˩HUCՈUCTU{t=\Ȥ׼W\MdgS5e`¶$#buڤ-1l `/  X -=W ݡTEj8$杦%3IxY$ځԫG^'HUf$8c:|YZ#_d" '6 Zzi ;3?{<:tvaFhЉ 0xxS|v$ua12c# vXeN,* !Ey&&65365ZD!( O=Hb[/>'콉{ָgeaɭ|EbZRwv%]mwy `I _'PYՕ!dT?owY>(OZu \}O yqogKH^Z\Zj_MݩiڞV;SVNC'\a?#Hѯ*EOAҺK_U|a"< plSX3ԧ.˭s3Y.n]9UKHNd[U?VF*0KpWg[2o ,ӂBJ%g,0펞^@' #ԬGjG ?axd(G2i3v,@e_zdZE.O-1B U _(l ZdPHUO(1ێiB@$JA$ǎJv[;Mqm!ײS݋T'jJզ3ٗK.zkQ"[*(>!r9b[5qEPUWH<2fRX5K@_­;aj.X.HV֤h$1Z^JHzC@2 3οׅY"a"EP`S$vpʞ_p*5ϥKQ(UH{uR[?ܢ+%S@J@D^CQH$|[kyU~ֽL_ 0dbTEOS6:;~(UcGds_h\ガAT:%,~]t^Ğ{>ZZȥބTC0>O2ttVjY=P'?, !O3fBzbp.c^"qQDѼG 8Y(4䴋+Ng=~Tymρ!lY#VՍmeLyTv:hU(*snU]X&$Qքk%Yt *q_#"\JPh'UÜBrُx~U)IӉxgԯj/ˏޅV( Cusә9$$KzRe5k;#j_.uD!oE c$$VkaJ|c(lCF"?M+*J2Mϳ PIVw)$-|%{`)U c%L۸OLȉZNov,F $BczjHPb 읦hf5l@k. GՖ%S  `TQTʽ8NU{ǰGϐ@C tuNrd9Dy #w(B4H9ő&"wAUȋp]jZ1I-`5vN0 vVj6(;˃hy wb2Y*,*2ASnV >xt;=m!̫^: K1V}J/:$ب 1(t4D4 {/\U!Z4P i0 EU*KI"taGiP 2y< /^+ؐW[dŕTڐ8\3Xm9KӤxPjވZ$ _ϏO&wPKPٕ|t@|do:%۔NCduGPZF@VNBfHR~Eʭ~Ǧaԏf~j_ro"%XBU3qMA$1atE~ QIf EH偪 / +&xwz/jR ՃT7Geq=hJ:N~h;ST?4>XӠx*J9$*AAh*wbłt 'F=y[>%Ҍ|NYS;4ɩf&&?]Yujr'KcM`v`Xy,*n2P#wXQ"ŲDE~@Wt2T7̺ y ˖כuN"9+|*-Ǻ;ҩ_ B+PF%RO@\.\w\lJyqp`N3A B Nhۅ, ( h"~Y*)3}A 6TbCjIT%T͆!T\;\_B|ɎP;t>lBo#P*nfV^;2 EiGLPRH)#(.HyVݜ2~X6㿼ۅP*U8Z2̔/=^Xא8/6I? Du,I[X(C,%M--7T`k5zu*$R&h9=q,Id+W~ ,C`rz2F|'~J2^"yU \X<zy3y9%z+ Vpبˆxm!P&jͯ&AR@QK_ #G[ ,Ȩ`'O,{̙E UjbW*G=Ey CguEF^qxVB\^yuᛐN@dWLʑQpkC:5 IW*:ԛnzhؑ^K:~Yq]^c e =}Bj+b% =VFkT6N>'/ĤUCb/n$bɣW2"l*TB&&i(^Ơ娨Xk}=t.Eae¶YbӿYu[0'?9%灙DŽW_:5Udv Șt׹\IϊX݋#Z:p߾pdJaωb&8U@J% X0~5\6b_ 6+#蘫FPY?_Uc0K?7fTRyӔX#¡E@2XN mJN'r (7?=تW*ctOgfzUd7ePP 3BKbyB-#JvNEÆ^ŸS9~Y ¹WB?\Ƞn:-FN{X?^i2e Q "j#r^Ȳf68!EOm~US$T|@]ئ< 4ғt[1g`>~|RhxN~?%x:2xBThҾ49ir)CjiT䏒1DTI0rV:/+zQʅI%JePNb唦GT !C;!TAoH!#T! AnWbjJqx:Pʬ\7v$\O- 3QG坃O3Y_Q$_"{jՂKycdx2bR UuBB73 yu켋T'RYjS6dP eUn(bf$wJɹZ PR9b~K  &odQR[6K -Wl_lfgBP'N[}puV _y `={vn(C6Dp@13VVE7Sv!!iF-5/#ɏɈpé= 1E`lI^:!$$<`nv/͞ fPYOuᜂ;#^?>3*9c]rv{|,P,XܲbegMMUGv j N=yv!eDSt>05w:RGyZҝڄI M&WRımcԻKy?^>7Uɠt|mhnh:+IKWF^n*r|]mÍc(RAx3z`AS7su[cgc_*Qח! }}Q϶&tL&ʙ>4 )+ݔP,`oqGTtNS6#PvE%!pMz0rʈ`֬ Zk懬Kt*gPQPG 2( fqk+)Uc4 )քHrA::?'u0i悤ŧQuzL<` VF^OLl~|zNky{0[+#0~5#[fE2DQո6Ɣy k>$hphKcڠH4A Xcږu?xңPR4Q\[x<Ʉ@sG ?+byw tY#+⺆>2ǯ퟊Sw=?~~qpn̝lyZ0Kٚlfu ⪆'3i2/JfS"/v%h7<03*uɎ JG QIG/+Nk!ʫ Ħ2ZVOpozkedYޕ^/oLA EجQ%Aɐ\#\تEI3b GfA% e*?d6/^\EV3vVI[p ݾw^<=jɎei1vkYƞb$5 ƟEzTMr}"zK nł@XREzqpq0mLt W(?qPrZ2(`,X ;2ӳ{22H g5n)bW%oٙF+:!S< Z`iaQ2L7YR 5JOȌihf`ur?|`n2zذիb|xVUmu ĊChPݪţԕ!Y!292aB( ಀ$N BRwJDdfD"2v/лcmBS*7-ײ$ח,++?<0JЌ]۩jeQ C3X[&fl2/U=j/36"OuqԿWFbִc`H\I =+NoN||iaLc('`$Qm۾@#YIf=5,TRghy(CO W+apsV*JUC=] ѝj/T䪨 !pwq|rHdk}hQ m)ooO^Sʰ/Fh8t(IQ$IhU6$:ˆ3lvK+RPGg^u- 3 ӜSrIsFkbڶE4?&W~,]h]QGTq6e 2LR; ՚QؚK,`upKM7G1Z+)$VnVrBh%8c6u1F uzv~H=T±Yh*~ > pT|)nl8-ôՕ0d4љB(!Y:d'Jr{Id*xB(vrݨ܀PP%ah Kjʒd?PV!6ڛE˻E֜\2{{3OABݘ2`$f#V/3%9o*uF1ź&UV*]l,姒jiPR^"۞;i>e9-ndn.ێM[)cŨйa+ .k\pPj&ԃLӷ >KWFIJ)D=&0졐0Psf\wX{),_إ%PfHtab'Ρ!TօV@X3jBQWIteS ( .>G|ıad@*|+Ce@(h[U uj $R{je {*rO_ ErUfi*YЩU$ϖF=Ick> 0ID/מ8 w> .>`Ɉw 4(:||RejMu섹`՚FZ ~ml <( ^DHUW[$l)kc5]x zKjB6p7PunB,3ȝ/WuQzv~(T`tNf23<Y;^~A#TxdI%YH5hS"^!jsd{Rf n0HbyETy8N(  M@#jC'GPE_'jT j)B[ߖvF;7YJ,ܹ'M;x9v%UpDtRTtV% N̥] R'N(Zh_TE㛍rE.@ =^?wo/˓?,R b&)b.9#ׂ> *)Qb]ۊy>w"HW` VNH"T`FmI)"l sMɍd7Pp>?=rmѢfiZlչ^yS YF)S -2oB h]gs9oI~XnE g[$`QC}в$JP$B*;o-#=&oٙYiB,LmA|L9@8|͊urɶ0eL/vF4gKRYo9IS@ul7秞}oůZv6c[vn><(`LlK;{,o@>C2=S\ͦ?3.wލ2%τPI_uٟ"7k;&@ې'",B=jXj}C8 FlhD,HVxe6ueCUj[#(oTK_ʣT-U|UKDUn#JfH(҃ΝD{MbI ~.MV^TH4~7(ahq-<AIN$z'?)5$uuc3ȑꑨT E~l|PU$k$Y[_vI^,\0+ޔtN#Dgo-|lwo$|Nѹ1)CA$jT" mCP) %Q3("ˆYY͙*<`G#vqi>Db'`+{qYWE]x0 O4*>,"4δu[$Bw^r4FɣEh7+W):ۘGJ&9P(řKNgp]O.zdeuyJuV\,.[.O/@ĵ`::yOjXϿPӚ4̼H~yqL.4ñ,yY9K$&l;1I5TC^ n tjMAϒehøpAHT7Qƥ;Y?'YiT8ŀdUA,*:NtUy܎Nb(>K +9g #ʍZEϻ7QG^ujSќunoQ 6(BKloQjlHYrlT~ڰ"7<!y ¢EtF!zpRs܁gVwBv!3d_ 3E<;ĪRA VE'd~27BW7_ &(ſZP@I1h$AbF2M!xVv@`rU܎&ZYVc,ډdNHVO!-.pȵ-SY,"lfdUn(ӥAn"(hL}- dL ;ըTi,uq sǘv5$dYN(zYHNz-lP(JuV& :Xb~JY24`'pxuԏZ>%G)$`)pfݟjP^<ʔ1ƊB,9zM{"*'0ӛbfWiII:2I2f^FJaPOܣ:qL;UjM9-EvlO~ō#D X0NJFfe6xQV9$1A~x5n9&5#zt1nH@AX4Ufxԩ3a*YO_WE;=}\xPΆ5N_߫8Rl?T)⡛<΂ ]&ːyVY4NJ:U$N`L!*- C/+UyHٔ^Djڑdl p *,-Y*F)PX4m yu*,ݲReuϪ' aIpє?ӬޮYHW RUx񈎇uશcNVJM-)%RD+EJ# Qh_i?w5,)(RK/ŭB.|87Fk6ufbd`Y";G ]f"U);6 `:^^ ;$|2k5ffE`oQ{3 r "b\3)=&iRu`9IցDj{,GIgI䴜^%gDj4 !V.sqcgf$AyZGB;RbinZUltɤ1&U<óLyB| :rw8ҵr#_ɫζhŘvVuΎ;@,K,ر**aEsƹ+ :p)aE; f&9<6UfN-ԡIUgBGњkX.ʹ~=?Xdoѐ>iIl%jUXK%n^(bo% iTc'2Q 8X'P2ȩ|44c0SBcU*xLj3~E|9YLGPj_7!a\z#GP+,QIRT{EHՀ[ڛuP] 9Y@(k[4LLQu\D#& Dnxu) ;*,yA%e2jڬS&ɚ.d&4{텁ډgj5sH)S ěcBd/'Qξ9'alVdnuUGoyyNdŹaO%RMOkc#DAa_1u.AI 5@13و3%fYVf6%!J髒]A.IO𧁤,DuEώ/($/bL\w=;U$_zT-Zb쁔T E vƽ%L0ֶ5-JlKP yvF4BZ=rOXlJe;x4&A3GrsJ)nт RcU}e]O#GVF~tU{e V>bps8OCg<3#CD'Kmȿ:ddK~~]ˏv' dX(lkLL+0䲙YxhV 0+$ ȯzuiO9Ǔ-ZH:ҩDPX 5"闩kXnh1A`& Vd5BhwXj$ W& UUjڤq,ӣjcҭnȲu K;[GfYQɓ$ך26~9D0^ё>1ͷmٵr2wNZ=rR8sDeqm2m@ohDҴ٧O>On̲KpfBnmgͣ+E׭%kn(nHE<uEV{dSŒU9%i"f%{+.4(D{_[ٹlL6'u_'rxE`ʱ3bSfȌwfqӒ0 D Yő"ſ&|g21@ʰaDwN yP3pW ޞ,ݺ};ٛgRPtx]"K r1{RV*fۻRw㾗@i ّ3Q66u4Nj9R+lyjc jX?#řM7?oɦ鯑y# U^dvb!fK) 22 5.HJ! QV88@*ST4DRElxDN7FV 6[PjˣPdX;Ʈ $@US"xGY-4 ò&;UޑXŨOR23QPv<Ğ+tyԂfBZs @^G`@cį)p̬*Y_1{&7igʬ _XT/[+~bee&Tu30ǯọ21@ @4y5MA>au(K uw@`G#&{P,*8QE?GӎB'PЎvUv城]D䲖1wf嘿,zufPVݝQz]YkGNCpjf:r@lMj5o2݈6[m T=X( HX& ^OE/W+7r}T )3w:'-u&||$p':r9V,f:Gd9섪=.X9 PܩTH I|"VPfX1$ŬyRUԆ!Speڈ 9 HeA66.Št|}|cDIDyh]8b[W՟ IY,qt e~>CTVB GCWn}uj8nB$2:!JN3w.| )>PQZ$7 珴U^3Ge!ISAPn`'hQzoXyi^c2RTgh"'{#/EoRCZv†*Q"ȫP ztͣ;Zɖ&l(d)RM L:sCSpY:FqዴiԊeu2ꪭPQ 1mOf\I阘H[4M3cǸ팩(ğ`f` 0t<U 4#e $QAU[}HoFmL'ҍd KfU5K | ~:O`ٿ $5 >GtPVAU~B2Q6H P&0׵T!$j֔I$W2B[s|,^41․y^M;otn.к&*bt-$M,IK)ifff<(U\|srVfUZXAH4P#X,$gmSS˳!CɚVD,k[t9I#%K2x+ʰjy4U4ߨccP] J;kA9#$FU*lp-nǍTOI(V&Q?MY1|kVunK6*9j* w4WR/O͎^cUU2,]~Bn:vW^ͮ&2|*[UKgM b cYjO#b,[}iz=0;:ת U㕾w  m*_ Jr$i)eRlWG1.&Xrn?lK*ywi8;w攭Q|z3ég* XZOV}r/bf7P ۅV]a'Mm@6VI<; n g̢ _#4] u5ig%+Q*Z[˃*uJ$?iљe O\KCќ4\ך8S)WPov*?obJO"3U]ݚI6*Cᒉ]NvSC4y:@5Ry)l^y (b GUD>znY{*J=K˫$úrÐ/Yxb8BfyW#vR҇jt~T*pB!舓 z3֋ѕ !}GNI=zhyۃ`̭b|bVP`(hjWj$*)CߨcQe$?&L*ctVQUU1+7TD .NSVUr X1>5e( e .Hs֒yNSnXELO5!%f}}t"uZGFAʽ !Q JQ3 8+D2C:9Wr)cŝLq籣Wu0cUpAP1 !Pjs -@&Է]dԋU+k׶+,:Q@T= ~X'< QaC&kha<'EMD{ LD*DԲb(FjʴbW@\T]"ac"ȋְ?`T(C4fJNPUA岊Ey>"k nuț%a5 _G'(EwHd8jqP̂Żp+*|U?a9xz/Z=J^jJT)V$3)mrHIR7ECR3j |l2h/܉t3;jR,!l|F M򔛭z.P;S:yɯn2ȷ!%iۨtV "pO9ZE V_#c@JRp; cRYM?Yvih`krXB; лhh4 '{;H \'Knw@G*)F7OLUhG~W])8ў$*V@0d6^\LNsY9%RhIQq$Q\Iۉ)aI|.hj֒E'E(%:myrjrzXO|tu)' i91{'ȬSHǤ !ZG*-= Kj@Sb.I4=!NegJ_["t nqǥh#2ztݣ>8ZT0B*3ȶA1tdUj[-$4ܔH:ٰHHB`/UD\V8juZ do `/vg!X,%ZI{HG4:;d1(lv>wŦD/2SE5!pV+GX5oep2昺6!k VfU+Ms=4^<؍ItIYTȊںsJd#UI11MN(V/ gzsnt-[:飶1t1䌂D3 8G5 JJdXRS⏛lPJURi`2?ptl5h)Pn+)R) OS#X8(GumO<*#3+phKԛJlj#J i2`T# O:SnGr<:nbh# ukixʍ,I4#6hu ?/7:cqQzhrf Z,ΓZ*l"2Y53- >*viSRoY琖 Dd7n7qԪ9Y.8@Z5YCٟI= \3b{f {=B$I) ϔ^2;FdZ#}̌hzcvqMFrUJ$>baf:@LS-Ϻj>ITC7Ve#Y[aJ- ~*’ݏ\ a1 ]UB8U*=WUOPOѐE3+aE ^V@BJ|FWp+DڸUvڂuF~=AW`uR1ha'Խ8Fv۸݅s,I5/ುI?Z,W+%['óP6R[cHӫjZJ"UrU/*-n[$GԐWj] H2JEvO^W\X]( e EC(F$ $hO4iiT4*cVՍ> ]ɗi:`"(U`K RYDWCˏ&o>K׏O4Sxz^hǵZ1YZ~gԧw?vy&ʹtbK;o42z\x2Q2 m`HyV+ !+V{]S1VLyEƌ9P)) c2z.hv%ό<^&fHvfK6N̞Un:5R\vj^KrJiPj 2XT(^IneEIoXi\%䩝(~ǯXH>GM_]ޙ8:IRB5  |$),΄Q@&vN_YONrRmNxQ'^3j8wumoٺNɓGY%r z:FR%ʠ(Mw^ 1O60.l b緺9et笘2Y~xI!hEAA_J8<ÅG=ʉ(T)e#Y 9Cp\U[wUwĈ=A[_R+זD K{^}k&.9#0BzXϪKPg %noR,T3L&4A?54>OŀI7^|~ǢhZm>QGwSJBUO>wiHJRhGJ)Th`B\sV=QH՝abG;(*,SUB۫вCY?PMZBUu%jxSj>KBT/c*U,5$ʠO t='ZhKD qr|E-o gOٕu ӱfeVf [Ȯ@U^xG~U#?Ҝ,z ~vMX%Z, e:OORQǏ J<0K YX|׌>;3I 1ҹ",őJ |z'} ̭9Ya[OR29~ FnS^ҥ2ڟtN,S¼Zn|{p7>NܚG&&]!%Ic78)9l\&JECϜii̸!jN~*P$p)Y^Omb;A!k哓"bBۋiN]wK^4 EG0Kglҳ(e;Ѩgzi\yǼ<pWD&kJ)?"LόŲ^E;8UIRź=(MrK)f 4yiעѨѝ$t KTa\bQBδ0z(D.*RlՋKȓ57*W4dTxZUնr%(#+ddjYĤzF Y}hتH%4xpzv6vLp'Pn HOnj S;x俋UAVTf@*$lX˻I؃&(VR(D_ȺLWa H꼒okz{nl1gl}>]qT+Gf(W$M#`c`hd1,|u(8V0_D<c%v?z}A?8Kӣ c2Bj Қa2y@ΊјL?>nŕ6e2DA [jJUzкL`D3 opQ uj5\tXdQݑBG~dDͥ#5ދepJUnĀU3Pp|q?##ʓEe3b)ʬjU4-~UgFed\bxBFyzu'A%~(B8걀T/_EZ%47zG U5st̹Ze¡ύ H|!gIi^x`q|cI:E #:UAoء(T;Qxv!jl+XUB̫ʱg ^^{Rث֜D3 pBF yZ'uxn` m` A nIh%LݑMsyZvفĕd+[?z+/)O.}) F ***JlA1 P3.8WQqqB:'ƯZ?x&Llu.] ݇O]id7w$^t k*ʨU^p(D%zTT,T$/ TJ:(#L<>RFAV5BTeyRc}0f&E ܁j֔_ tCJȥJP4BKp-Pj'#sf48|Io"= ěBzqόɣd2Qre*X~1l ^Ol <" AI5Ub 9" ( +tQEPzQi*rf*8=E <%l>8P 9%k7ؗ'`{mUWt>ADVV1gGuy$K3 Q=' +RN?RtCCL*# p{vEO*RYxjD%V~2 ǭƟNJddWJ+/TF&;& ;Y>v%O.7Xw6uU% A ZE*lFW\?{0$N*Z)SHu E'Uj'^g,fu^, )C,W$*`NB#!&f~=$m9DYWvf7`K|09E \섩U<#W`Ԗ-FڵFUm ٶT'fC$gK:1vSԓBŏW\Jl? B j(DI&9`{'i>$S'eM 6;J,U*|VGLK+n{%T3u%sFI:8l&'f@3fJ3ȡ~0$81\}>W$)1)N(w.scW&iїrNF91^]ͼ+[ʹ9m %PȍbiF fK v>Gf4h hVqk"`RJTjY=M _'JΕLiS!:'yJ3E%~b%U5ɼ#Vue8R1.K,~i8\W25I' ]R)H'4+q(;u72iˢV>@ZSc?s%6! A gRA<\l \z+1U,W+-4-7ȤW[-VjJZU_^*C j(yc2i">ˣ,|o#\"6&ձN[y2.,x*U)Tzf,J0xJ|wUFVJE&Fj9 /luo"D WD 7]*JTZ#dԒ2R†@5D.XBއIRQڕd܏F ؕfY,qHQ#QlyOgU"bq0ѵˋS1idT6lZizc.*$Qݘˉp~H_-|=g). n' P[s@Gr>Hjz6k222bxճҟ'ژo2i˒mʪcEU$ Wȭ|).] *fB8F׍x E(m?(6OEJ(V~T\fg2,; 3lcp2mNӨD\监a3jbe#~Ҽ+#Or 4(춣srqs1udfjPHrZ?!23fn$ JT_"co7V0Q&3cb ($g¬-";ͺA,y*<௕32$OؖQE]hₑTKlÈGt$r oec4-\w B=UZVG)S^{+}z!#;4UyJfnJM8c^fVqꟳ5.)eiyR+&{jIL{dF$x3_ʋSi\s&UV >S"X JUaTD2B!H)AuT%6xhHI Ȧ"5pņ2]T'0pOSrdMݘS&>rc/'QF8;݇rb1_/?ϴlaSȔ2dv}X8azYby$ kܪҭǪ0$*X* ;"0}j4OoAGI$}KI1 m?S_JE6tcV;.B<)ef$e'_$Z>fz:igEw^1vƅr)_"pBO}t\1)1̔7,O)ry^G=@a`CRæHbdcXei:JÙO B?r"6!Vv!@%\V(c=u>3$S 7,|T(G2prm-AAJ vi2ydxPEK$Ӵzky,QpPB{PYU}ڍz*d9j޻oOS%JmqGnDxjOPVL1*$}̈́nZs24V/U2˲FW-ӐWUP5?'M C(R1R)ں)atlpA?q`4RciCB<2b u,E+^v/V*^fYوea 6i%P# ~ɢyŨYJy';P*pᘩ=iј?d,@E`@%%`2  BͰ؏YkȂL(rM q'xƐQ"ѫ~C/n3SA*m2ua) ʗb}RycO閦pRu onBn %CwDwrW!֍ؕ$5u 'tU#7 vYBnvd^O ڐY1RizZ說ek,nr=FJ`o=w/H/㏛8cdB8}˪:&y 6x¢:#1 5ŞiQZ^?Wʩ!U%2̊JΊ<`ҭ%?IˎN"и((X4U EQ.ER~>1%^&eh$~ x5G9D #V`)~2¯H7rɍؼh)4g~lCؽuen,YQG@j&=Rz,ǣp S` +;7AgkY8 tH%<.IlGV<}OV&FYIflYA[2켱ߓ&0Ɲc7H,P<$[7TQ9Pđ"wZYc*l̩A Rz MB.TP%1ÐG0ǐ3{+r`2ЩzGd^GkTѱ7ۊjz4}.s4ho) 1&ZoX\+ A\+{>&oRFPd1H-h>A$F@FNՁ9Gܾ 6nܝAԛ{kI"-hzKigtyyҏ)ZͲ1AP)*>Lll)gV |&m2>TLuǝ*ZomӴƎNKH[L$$^ζL,9:M9GO f S^EĦlgEW}"gBz.U$ ^W1<0$H[P( {ju'a @kM9C!^[)ԫUM>/jPǟ'҂X-f&iyi1PkPDO&v3VYUB̘P1(h!$Xک\ 6@cc3g%COKja6rV`p~t=wX-[~+!)@)>!8UeJA֯|GʔFU3~~+)$yϞJqdYWo֢&UXyq@Yڲȥ6Udpij"<Ado>?i&<+n(v9Vd, s4/oZ>,>ljU=YA},=PZ}qKNS 'DF3 #UOvN?Oǂ NpgDE!P#522"_o^hld$iؙudZ;4ر%J:^|hSԢzic?cnU;,If!Uky|11qv_jG !,lmvp,]ّv=qg~ p&p0#3r&UJ)b#ǃ6%_僥iB^)T#@*O##cEPCiT).^QTAny@~`ըe` N8G9B8ٻ0G dP8BWo;Sv(`7u*WfTbB[ٚEJvb*=Cv<ڱYGKvPC7 UTY5"OӰ? Nu*;O,d AU;(4W(@>kk"6 Q*O$9ǟPz]*A^ W"+򥘀,W? \갞]][VB [eMTTnA.ZǓ[ 1@B\We*BzX]BI'4SY YZoG_/ycԞ{wpUhd?1TIG!ʯ G!x9了lr7Ӱ f:~,P#(c^):N(gF#Jj|3/u=xCF?FȖwz3{>Ĥ>h/?"4ФݨGy gNO> ^ж?Dѩ6_ n'u|0cT NDHi]l8+?36ўqt@&1Sӧ#81S:?F7/Я>?%lzMd{ԴU㘚;u'vӫa.qVlr(յ<Gz]45k jq]yyP FI2LPӎL lL{i3paӑfe nU3l2+\*k O@Uf'vTn@b̨plD) @J%ߋ737fZֹ%mW-XCsx)GbJ0ݏ%@ 2ȠS΃k}K3,rp#JúI-@껁# JIt4u65+cDɦRQȧSBJyWerW6:*1R-T J'9gۮ1uYQ3^TcQ@TNeiBXCggHډaF!F K*ϫ h4<6a+/={ahY3mb1^["O-bQQ!hCBF[^Spz-mT9zBDz&ٝӱMij[2SL64#-$Q$/Q8۬#٧  CE 'u5UWjRJF0i˨eK3Q8~hB5\,X*,FQʈr23Le1H"G⌟9FEkyj6muv* -7LJRfrLU-2Ī[fY,=Wtr\erqEiORrד"U4ʠsȰ-l ')j"R$45`zS.MSKsr;(瑎Qɢ] VX`Ahg;NNe> ^ 0F 좙U K{j4XeP$Z5ƓUR$M &KYdnFZ etN*Vx~ 4yYBO8x,Q_O_n/eX>$/ Fy.'LLb Z~?D׷,9#ͧhW͇0lEЫ]fy)NʷmYbNɳj䵴V1"alaL:T~( CU*ceD}ZG"@&]&G'طy.Fi|XEq6+sɸUce|r@PL86U]xNNF)ee~>h q'_`' G3&A•eerʬ ~C#g  6YhطU;"$ԃ">GMD}Hx-LW&q|ŗH O)3 f!@_ɍiՀ(z)i1JAgCUIRj7UW pp-0j߯eyryU+%oYJmT+ "c6c`¥8m<>s8}6ukF(^DQiXٱJragnV UNf[ P#%xyRRdL,w=O9LG!=INWة<Oi}i>\-ޯO+veJ$C;Ș~LD D=S[K,YPx[?F |WpjgGQzdN28M?dcčqyR :p)5Z1F T3!%Y Uh+Աe@iR/v:uBJ2ظ_q")4.ê1(W'C]CY+ԵAePoU-*#c~Lђ@?m! f_&]Q7 'VCP %HtpXTdz C)(gnp(0 ).P^6fڏIY1 nYS%'*~gWεafIdG:0 ZySeO]} nԃO1 [Aѵ` P3yu#@e`֣eYǬz;P^c4(WOb*;JY([ Y/%j+VV@#z _`z%ZSvIh? )DfJM'FGg켩Rےr~?D Vk*B3yܿ$CT< @h$ U5sT.ġ= ]d:ZG.F,|wőrH@F( Hۡ*ʿ}7x辰z=E;jo]Ŷb)YZq~%p7 :Tml\i~LȊ嚈G@-DcJ?OӼN?ǫv}i;OZ:K~2FF\dg$Wi5vr{-K~(!qs33([RRaˏf^$i tc**PUV:iԳ6R×+3r`IN.˓OHW6uRcɍ͍g嫿3ETz^- l=1<0 V HZ aP99r#$ 2湁HiqzNtw_*X]@uoY> '+VyY,BΧD(_ M)@E(gɾE٠fQ(c_ɧ.0U+cDVn䆂muj(*!Yd푓V/礞APϋNFAL?Pb e' "M e5.YhEf8y3P%YS^wdZ!^7Ir*=_eܕb<|X՞EP%a$걒 Hy;w "Uc1Vg)Zv`-@ckV{Sқ?.xN-&gRܕ<2*J h_ŷ0/M3f*f_(RsI?*_@Lf lxm:.!?|d*( =?&{܃x.y®C9GXbz1g_.iQO`j_R4U3R<)RY)>e7ichFJ<'5fOo]d(sXrS` .9/ 蠪.&8(>_f!Y3x'#9$GYfmv F Kܜ6>$-~[%]~x>iAª4??dqףIQI^B)QCwpP2S=3W輆_ZYW߲p&/+Pr f`SڇC*SuOr4iA0Q j%qPL1X}+9< |)}`pJTofrΈy\"Uب$>(qP$Mꠉӡ^}@T#;t콖4e ye)Ց&rpDIURJUWŠʥ@wǑ˲+IZ׋շ@OF.Ey? )J3۷`{FSq t%[IV Xo%(QxԳmKNOhjcrV~tvhQ8{p܅P;RyZIG]0Mkf)g(+!f&(=Q;$bMWUr5S$!1Hxr8U9y$h7;)V,@$X(@&rel߯Rx+YR,Tŗ&]㙓 &E"ej1XcVYzr1r#O2 U3$ ̬_O#ß#TvӮWH-+$aӫcX C2\ΖD02aj_ X@ywe3H ㏋#x "A=JL$,s ѢwQt'yub$f(Rġm@y:Kבdw|4YAHG-٦*'R;{ +kH*6T=bT*x;uF gaFZV5̦M8%E<ߖn?{d#Ȇ$-oop05{i8khј ) FoB7hSԖTH#x,R sjDܥ+! *39H[ cVtcI!;"k:U1tOwH׊;<܏!>#I$,Ϲ7d'3b] YhBʙaI-,WKF?P:btM#11Bʹ3zB3|3Ͱ5s/F\V-)U~esK2b`e]YV5HJYZW`Qd_P:|b1UX1H4gv{`?|Kx83M؜H+MJr KY2U'd`%W_asֿ)XV>zmZrG-En=IF>]}ǛDHH$Q*{QVf>܇^-Tqŀ; cV#LPGH"{=vRtc׹ Fe,<`pT)<C'fo#VsP#&DoBTd-Cr†̙)të"lOv+u@Roݖk  ոP@'O݉ g4L\ MAllm4_ Tf'T9cbF뮓G"dd6RYg/﷭nEmmSv&ETFࢅt~"E¢TH+5R\`%~[Z9 GSkH&㞭7KQU74/ԯU@J!ݗ~]Gj+#2OwZp4+un9fƱ}ImOtKi{5KYrG*ߖdFٲgAi |c-yZU%Vq):XM #-Sqecirgyr˳彲xzxJ2uˬ(P#WΡ8Svd||8i@Ewy>T4E#ϓ9=0w$amX,bTT" BV|]li^ yqD`g%U+7U*ǪkV,*TpS'o6NEe< q w'<8A/۞8P$6j;J/a>OI=ec#kcdIbJ(tTMՒIIk]U-ɪ@C`PMY?[o+nOA!kN"e4KY97i(k8Ozр:F^>1T(]nPϲ<|b{bJ*32 4 *TA?GKUAB~{:{ rZ`/{_p+fVn |\$CV\p93t+̡2勎J ;ېP `#VVP 4X,Mya5׀uB8"lpxVAvپ)NE3v?P8P~N(b駐z+RePR|!FI~,cj/rXUG4bL37O(6+7np:QPx⼵9jB/ {:˧l @ /$6x (&;k'Hix+;t3=fetŻ+!U˥ZfIxZݘJ5Q;7jU<@W,2*Tl ԛnΧ2nN~BқJ}UyG/ E⌗vyFRrMf=mK!F*[W oڱ6@S^!jyYjp g8n~8Tm-q#r0W)$XM@O#Mn=GN䷜)BrLfBRr.NŽ)KɅP<, Y]3*`@.˨k?4EpOA)#FEd+PE_'iEǐ,;OL5u^\B/E^fjaE( v-&r /}\7LhW@B\fPYJ BR=训6Zrf{玮T/1P̑[3,x61J#>lAٝt"K0Rˣ ի0EQFј]thv<Nůp]=yG$|PxuWjKns J LpZlj9%f\xT=t_ )o0W:woSD=1f6AqcJ');XG̒.Y=z*3-]B:A!1) e>Dks46:[MX!d{?d|-ؚC\wɾFE!$ -,1$uB~"tND才nռS_e`UbM9eh@ dWK@PNbm3>ǒv~Br(}Pyz(J±Q&>󲪱.1[.]H`MKn2:2qni4 Ke pXnMйb߿O=}n7^Aʂբ/DDƒѹIE[5 F`x sW^Qs!Dd Q/~Wz,ܠ3'U],HgZ)#).]C[uJ|4B=~Aq/*C F zJOk&/Lk^;"׿VG"Z$j(ݕܖh̑C0(./@UQ}<hF Ov=Uc RH;kE*ؕљ bO$NY6(5…$P#BGWf)%AjCU7Tϟe9;v ǕK::n]t-.1a懇?ʰ\l=I띝GuCecbdgcÅJNFDH'X*GMkD~ Ae$O){WmFjکG.PW1nnK4 R%nM/eղS"[/=]JMd$6Jb `EqQD"Y)NaFbk@s xYTI5ZL3H)ǀrdI%UCf ѠmU `## ?RYnh+C† G&VljjBY',4j9ִLcPsKI=U5zJ8G-@R 2ful,}?qyM鑛iD l_ǓQ7ؿG^=#bZNжP%:"1K>@ ߬:4Y.d%%2#RCmR\fZXݻf85؋y(8gWP[ܶ/e|OxrJVDrdҳ?>Ӥ\uEbs"A9ыJ\oȧJu*S&{)GJ0Rxz%½<5en5_:6Eƫ͚lQGy#?,aAlTFnQDQ@tqYAY Qc<̄,Hrq.܂;?nHg^mW;+(S銐pHUH֊z='GS"4lu>YeطjKX䯼{G'}V=Kn.Vݓе 5x3R IޏѫUݻ}֨8 @W.;qJUL&%l1(sId]6S&1qvC- yf&} ^k*[%[|wIq*kCem-{-Q YsW}P$BKFPޱ].Z]CJK;4P3F! Ǹf&ޮF3d2r1Nr YM4(HfjôpLugHfE(ʌRuƞEtH,VC҂MW4pJvn=g2Y3+uiC)6;Pl踓ϓ_H_hM`H)"Q u$2s8=Jm5y>)“Nә/.GTZOHbQFjGml9S,JHgW&2ıGlR9v u^tWLF ?'cӞVVN&Ddš++ȏ|ii`+ItsYB6~52e7ӫjfCy3H!c4ZM=d1B ȝi$jBE d~2&aQ.H: D>qqS[6[ԙ-4r?ӵ3p9/#n9:&۫ldf{i >fLMVuwta$Vb2fend[RiY-;]/{(hEX^2?D,eӴvYugT(,3c.|sP`5 )]Ti: = GT,i ^v#-)Xv=GbGG Bϭ#/~9,U(? le ^*&bŻ9 E_Y$`Ye=_=GU:>o/V h:·PQy?W5B Xr8V]T:@&At~~ETOM)k߿s^zt; 89]4 dɢu=8=C&A* b<  DWeI!~yvtn%sE(S/Sן_=[};OT5NZ~rn*I_*28 J;].I1Z%jFUlFVz-2c^ TWiS#Ny~+DԆ>!lLq=A#]9f sK0L Q Cuk,NP=C?:Q>L|}捍 4%4fIofqrnmÛcۇ?Xh^|GUmfEjtX#-]u>)6!{ جnyk~\z.;;"QIᝁ S򫕙$/2rSMDF>_i_ϊn,4kb qB)Fe,ڀGY$ND:E HU x'U*hUֹ"T )ߺHc.ĭ SPxik|̚Mϒ%O *1|4ҢNEȺH#<|mG)GW!CyN39uQGZ!ꊇy2wъ2ZGtlSHVFVӒnZFǔ)vf=&;Kr=蜴wOUZIFDF܃j,Q7ud"/Q$dE$&Ē(QVOyzMLjL8nmQH -vfB<m썭`q1T)ώSՂwr QXr(ToXSDyeʣ,P2y઄ވ!ֵU*(&8, 5[!޻ϩaᛐl*;>&VQ؆67_Mdgwb8" R܅,ũ1zd$/b&On(:,G׆$8dU+ꧯ ?bJqBZQ"TƄ{ʪOTUu{0粀.\R*@<p_2b)С ˀH(Gry( ֮Pđ]{P,@^Є^WY4d$5FnbhYy{d0g)Y'LJ1Wr{.h= ZE$Q$TrT}̼ >t,{SEX~6?&ڑプ,\G#;WP:OɀS dD;ԯ^K#rT8_֤,5e$+ȓ_8՛b!Ej ڔA1O!,|8ɧZ:Y4uĈބM"9=YȰGGbRBY~^'z$'n\]z;z5BH(ǰoTGӁ. aR;T1,R<``wW,,ī*:=,) @nYU?* РEh<~5)ú ꝕrq@T3r_ƃi[K@]xWV,vPuiч^]XQ vApJpWXfCE*ea %f* 4uGva$g3AB{ڮK:`ʃ0|`7($ 2lT߉#ƌŷdYjTs+&:JJP0}[o:Pg.Wd nj/UjZMJ9';Y?^HjlњYRbIO{yL*k1U *sWdT vfQ#g$ox9_#I'FėGQ@hS_/QOY)=!UhpDp€P5H);DfTW&iE̔`]DÚeV@NG >ٴou=Rڢ;Z n99:ȵnVr<ʮr1jHP~~}8ioWɃS51ͅ,(\eԒ Tvl@l;Dvi"DŽ8غ7C/Ҧ;Ek`i3:MELlBp8Ϙ3"e5*&َsmOU'_;I,:+j;SC]?k0gipg"賢OZPŁ w9vw4J3)iDac|8NJs^(#MnFt Et*~GY {/wɨR zǧWNȥzdD3vR!ꈙ!%ZpYˉ7= rl ftD%ZnЖ? yh}@`2l{T,Ջ/X-x7yiQ~n\  SXR2Xf}OK>Fd ۺg+3/-γx%A}5d0șT6&p;E<@gZ;g{qȞ]24,|#WSr2++ E26䕃ɏa:+jdг3)4A2m#ds꾢j:al|Jȉ}NGU9uJP)1c>f,m.Bxi~zEU;'VYt|٥ϗ,YK~6F6Z1\uVͩ*y*Va]c[P[Rx tlOdԀ*+ΞHFjkHiHc!UUH>r ,Fh㒩2ߜsD 35艭xض``eb53-kT2Ys9YNYгo_"MT$%J^dILF푤.96(,H^=',VMv68o7edX* RqdqGeHPʇ$UMn(0鵺ȪȥNcUןVa6c6QUF%)|jrpS' jiyQm|b:Sum1A(\9iӣߍmCQ?Ux}k^czǩ~M왴x>&]qqcP0<0z"/FeNjYgzG#?R=-v5n6gK+V,Fk !vF3:8TC{o jLi>|lSZGJDr!je^h}7ZY4Mu-S 2G | <Hc*2?nza ?YtwR:dI>ljҳECbYg/0h~<ȽO=KQI(.g62,SOK')3HTH@qSZ#hU^;L X\x.d ,yV8{54/B>c~ƙѴ&668ǙxaԊPOyT nY7=I!dEZS^A_ܽG!tl-? vJف>J/)=ۺēm2y 5pVfH9NuV}_ mKM5#3 o7-Pg"3/)'b11(C$.ua+7#yc Q !i"( YXB} NԖ^W?#?IH^VjB:yIv49*:Vq?DR3!n r:YSC?-fPiXO~\?tPI;25%H—FʆiC[( SZֶ-@pEmӚ6'4Q ;C'bB[ؗ'T(gaو=Oz(A `ī*0~yq"؃ױ*AE5, /~A)I39 k??_ȡiPܩ [|}u %IݺN#B!{vjPp>D#K|teQ#][v8gO<(Q+LV*[ƫZ1osvͮjsjzjekzYusu Pȣ ɡ*hjT[uhd?۱ߐNE<-On%*;h 3ugguncpldgN]\P$FSvѨ2") .ȶE0LP2[E!(S0_S/VZS2ܾ*7!d2U|l6=exud_cYLriʜNMP['.WVRʥsY We}uq جg.,)5PъToUwzkNр1P 7@x,GU 'fXrPt1T`6ګ( .N_0RgQ@vZbUY$T,ӏFk+$!?.iu,v<3vR75{m!q39QŬgKa15 %ѝePGoNdHJ[< OI{;(ЕSZJ}נ{zWE30~⡝XO z?l~1 YeP6VR]5Րɞ&"QIsgTVy/.LP \i/ZyƑ VAu+ .Ϳ?sP 4nGe(A,K=U 2SgB(KPx/˅px>T6f/+nv%ܒ +Ft,EožER~h8 -R]d,xL3rܷ?neI Re Wa5PYU'ʄ?ק@Cv~/+5ctU^,̌YhA%f7N `@'"b>i@*XDFTE 0rQK!^z(` tdR%X1[*(-Ԇ0U CS)G:Mg=sli!zbǸs’ϕT=I<ŽI4@IUyh5%x؏'P `8G6^I G ~΍5pcwyGfn;轼׎X+i1tQ&W*AF@q-Aثf<$sوRxof>C:ۖ)ݘvUOg~Xʣig@kJJzԚy䏵fV^MhX.CeFd wu$SRNO>*LtakLVnrB̋ȣRUViѨ' bRt2 nELx+ЫGkRP/F(Zm*2F^]|d%@^BFp <Ү_#N 28 ]@Y7R-m|Ϋ~LKajGaݜj(/5G7VqR ~g^iMpApDlS;Hb?%QYB/$S}#!^&y]AL۳UrfٿZ_G\7U&iZ}h\t x?YK/r Z5%iA VN6^jPG@-Mz(m/;tOr: (;j`;sNI|!̪.̬(J_ x:&AY]į)DT+:O$= V )Hc,\EPBR9KVsۊbX O,oPD.ȵ셀cS܅ '-e=Y!OS_rg ?z5TQx<5 i<*tVfZQJ @(_7~НW7`QӨ!ш(x̊X _*5*(>ZU P6~Q"A=An6+04k6$*㈷^hts٘\W @{ TQZ:$MXjck7 MTL Jv3Sq{wn%DJ&jmgUSy cJl>hTa y XI DuNXUf@1&ԝ" Y&ȇ6rw)݋T:2W/4G|UQ rrQ(ʆgeJsgՋS7yGtK+>2WJ/rUiG Cܖ`$c5_tU{U 3`$m7QbfЭ65$@(e@$_.(B# joiGcUՙK/럗:ʵ$J)$)C0椇3ɴ]%!k͑>qS -'\O#![ V3 ըMy*HykI<~kuI$f6U&=^>O/b}Jطv>nO=KVsaߊsf۰,'g^*{ARlj;_kO`S!R*Æ9:՝&5k5z7`]\+i>7G+3vogf.iuf1sƅ$Ui~6\/ ۬gBBfLi$=EmpQiqrĂޤviDD(r +ŧQ]N5j)|jcP8]Um#Ů޷htܐ/4cXԆNS:",BmY:\f`Q[hiq|gSQLK̆GyEsu׆mf9V-9"xhaz {j ?߮u!~Yt?R5Ms #'O9xzv͇ Cd6meR@vY$㢣LY\"TrK$efȞxƚ3叹$Pq2BQnk]>&X$Q -M{t>>&(FI,N~OlBGy7V_ aZ6>=/KNiIZ5zdU(ag)VnF5ͷth8S fd6 7Wil.lUѤ؉rQ'I#'36w!/(26?%Qaܲ۝Q"C=2xI`lݹ. 6d QNjnU L)YhYXP#*j2q<.JYLQiz<0+\=PNڅKR4dYk-ԩluᠯ@1*4&PVֹ`ެZd[tݏݲ[GG2srYqHg㧫=buFze ͍ZcI_62Q"'5}G#fk4!VgRJTN*cZp|BޛcelONM2:z6nxC)+O$Me EiO#[ jLB:ԍ#'(ffUTŐyF/c<_e}F>:<8iɎ1Y5(f@H]g>>.;#L+ΰ(wǀ㉙X]iXaVo̝#C-ҒSSH {ui6fqD|uTG5gX`UND yt>:lŝ#șc@HeGn,}Uv%>{u(& y#wcykmAd v5#S]scZV8^ c-%]@fx7SR:rxݖ%mt?qO#\l|GwtuS/ qڣ?cFS兛͇HѴ?G$8[q2052u g2ж>Jً2Vw/{_P..ݹxZ LǮAǭ " hxiG#ſrle7ќ.zlme41-#&2GG\ ;t#L}1جɒfUvV~ex RzW~}'KS~FFXɍ%9E)l{ڝqUqީkZƟ޺4kƬp6[fJ99ˇL#R"7̜<9DdG~(mL1WloA yJ"|HȆ0bQGM`ԂҾFQȄA{ S5NȞ4"c"9ِ||g;zdDʻ՞߱wۋtng{z;MuYf^}u)亞4MG:KH0{-~B=8>vYxPӱ2z|Z2q9&'i(ΏӇ_a:Fﺭl\LgiBӴ/D˔' ݸER}pB9nGLmʒ2Q#nRRu+I%1y͌h#d"VuEt`K1U._/tzen'mIrk%d,ȫJ ~Vuɷ6+l[xVY^ HQA~YyboC^zϥ'm/@pqY]etӑ:==DEtrRAW>!EWPyNr33aL$||@0@d!gW r$vPSH;.^A3~x+yP4TL䲈.59niSb>{c@ZP0 ^PёR3.X 3fzG$)yHbiz8C) ;NrV<1/U,W/!'P$'*?x=Va>р9(z'ʃR]q譝NjlA:`9)ld6YF%ٙRݘK,ŽB_YQO۞z*ؖ wɲ5@ !hs…$'Y?;NCu^+C$ǂ2v #f\55(9(?2@Hdmvۚ9,$\˭[P#x5YQP1>@:8*:óӞ?seԺt,"1DQvv=SSf3H|Aº A%>UnT[ll MlOU3QVpi[E՝™丐s,s8T:%6Hİ*,*,KވSǧ i~V%: @`z=5Q%j\nʃ Zy/G#័_7~ &Z:>3#hz=G.NWCbUoݯ˹'\j:NMMEU\z,4TOG܈`&e͒=+?+$ZE"Gq?& wV[,U)O W=z^6NrFt hzdcJT*ZK6ӯyB> :98_۾շ"&ikOFG՝feJdnRH=*}}{SҴ=jο^XF`;;Pϱ+_J5mf?æ^oRus,˩o"GDRY''%S~:[%X;K,Hqy1#!@O/\2dtlB8fK 嗷v%٣bPt }}z/F}-XzU5q7an VHLt<(hx")C3m+Nll8]aI6[PR+(cYs=3C4,2-bfZZD4[ΡۖyFsOW X0ǙjDPN,O_ƫ#SgZ}#a.0JLQ&FC3O%y[H wJ((b(˕H#j#YXnj#gT1f43/5D:lu6B ~sxJQia#ڏ/́'YV=^~5LK&f=<QȘ#b wZo"/(-com68k9cW%\Y*ّBUZ8ccOPT+;!FM4X *E4.+4I X/PMf1) zkPf(E 1^toZLXt;f>),J"fiB)ndzZo90KȦ+cfJYjJ\Nf_ePtF+9EUm9mnōRX+-(QT ɒ(EgwWu>`'΂Em(VJEYswJ%k<*7#}~ex5Gȼժ^Ԣ(%_%¡*BI!пxhdPtsF Ffag @E]NdgE×!z -xwz!dkvB 1'G^+C4͑BٮW('Uie3Y!H"y G +t7OE朕@vR;,ܳEIi)F8ŔUEU-nOu%u`[r}{yge~ #ɯ.xpll*g*(|j"ȻfYj@){q qÂp|bfnOa~WBS2L2xG~OPW!?_T!!L%WIQ[U7l(,|@ *Obqt`9A*A&AS >ɅD-U V~<D2׿RJ ^/C?rB $j9NάxE\d`3(< 9m ?j"%{`JjV/H}d6bkX*~EPh(Q=<ʇܕfnJ1\Aق٩I+5Ky 'hD7J2L3MhjV 2>mHϵ#ɍEذۄE:xPqъu# 6QH4VYKTY@rR|gه)I얠/fs@8Pz5z)Φ E:`Yh ;!ldREM \(( Fddu5V~eʣ̧ U䅍fǪ.J/ )~eI:0gqaVSW\Lie5WYay]_oܐN:NuQ J J՞:'g~u_Zf6 >mWk 8Dƫv%bJs="0G$3<,ӷa7NmS4hx(bƝhif޹-ٟ1hWuWvxŔN-{_VfgCi:lR,%1@mFB6Yr;ײg#"d Ft$Iv"0$oAѤ2͓}uۏӝ'X[3t醹yz"hߍV|\c5NC`mM =12銋³drz1W;Bkթ6=-7kYV_N&5e^Ee1#uS<~n^cSOb:LFQf*&K:b3`Ã/xdV|BY"+cm#wрi;Gp)'[W.e-CQZy]{6_+oghGWlۺtLGRTjsj@@Y6>SgIS d3E &``SЕTOTfljL1ɳc,0סfr4mgW͂G3PL2s,( 4J&JpdM 3n؞d(pMp4|L\̕V%_i4;%Ɯ|Ih[wh}_?#imTi!A j9xRYXttvN Q+$ UQZXdyn~u33W7 : ݿ&lgQMrtKף+ x V @Zzލ&Ɠ%ղ7nqag^q͌l||̴_#xv@Tzj:ޯzM3^tzdcjZ[$ s/3M|}G^4C&_Yʲ\jfd8$%6ˬ'NŬw؝8;p&^${rhecx #͛=!X8, q]ѫJu%V]3G@k>nK brm[;Y4-]2:|i5p{z3m 2ro oRUԱu|k eZM 0fY<}fadptG oLRdjڗr@tkbmI[\ԧz&?錬e`tqIUFCWR)`I!e+z oxĈ05 m+V6m6-lZYHIeX!vDbY/M?nd42X pERJy lw{>r9NlM'G9.4MI*.IeZ:gBD>?ӯ-QfӟQT#!뙐ON}ÞK3릿L-gնfu[6.$ٝ2u䚞(sIqVSwdW=9b*VC8cwbRD<@jѰF!H^o?^LMO'CĞ%l DռVC5Igʘ֓aAlNNUֽG԰ԏP4JȞ.Km TtDζoO.sWgueqfghԆu\[jdԱ\\\%i,J5j/y!R^>qqoԵHb:YK97K) 5"'m)bHMaEqU. 4x&ȏrdɐY%dS"dȷ~=Cg azmPEtqM\)12%\]=S]'ѯPYUlgfn/R/MdiwH>NI58OF^mUq3>쿷㸾v/ Aw߬w{ M56'8M ٚYi߷ ;Tk_kVY>}L݃k#F~9ٚtR uJZ'П@gB[gT p՞ &.0-ӭ}]A@Bv4%\A`wOaJx;?3gefK7PʖzUD6"jV ("PN6fd}wqۣtH[o-JPV8U@h`b ֵڸ"Xx@SW9!=tISKQ StPnD@FЯ<rE^xAgO`))%@B;r <4uc2XYIʳ 0*k6k jl+ҬjQe|c$ǃdܿaNx%d8d< vp)k0sאLfPQt TE:na,G'&A^i#,>!U KszImBNd`>( ~R~'Z DihZ($}_V8ͦP@Mef&C"5QY9B+p_qX)g(܎xQꀧfn<{:d,q- X"ٜԝ!UOoGc-npf6nM L%w1@<*@/i`,cҍ(fn C(@!! gbBa&LȽE?L~pjK}3Y>꯬*s1u+;н(M%[VΎzFfxcU˘Ħ>+'|oPO|pBepb;-2'LQG [l=MY-Nt5F76cKzvu-uc 9SXY]7ym nҷj~4ⵦ.F Wɫ <=:^>>n:tΒ8zR :AuXy%NYDzOK *'&IjU"6("Ev!~m0gnqBczڮlV![tM}'͉sKԯɥQW Ӕ#W- Isq`f`KRژ\ څKcdu]49VYHw4܏db@!rG V.YvU3:(WA>yhUH4u۸  - sٙ|DQ0!g."6V(X߭  1S MĻPD?_'qn\-iXG;Pxacblܜ֫(׻^CNx=H~67KzDE7:޵YӰCV鎪f` Ͽ]2u_L} -t]RVSF6>nƺ%;` E[g:߻L$Nr:H/6Bчd'/1)X"#hT:XvE 'YH9WWzDt-D?NS'?#/V}0.΍ꖿҼdQҪ+ 6bgv0&zFhExg0K@p(S[c~}6MgkbyZ!TǕ&"J %PhWjL;4Pʌǎvo: iw/>saVbb'oSUG Lt?J6*Ɉ*uZ( @Ӱcj 2Y9B/*fYuW}ٸ3 cUgDK<2#EzJJˋ(n Sxpk(VH0ʰ`xzɏQIfIݲe&e5zؿtV0QmR/+cUG tVf+l>M.SuQR;YxUnCsP3k}Y«W,)՟t O3Mn䨍p5u*)R!h#"unfA裐W@aO,xvn(S颓'35R w#+1\{q,WD! U*>ZNm6Cץ4v4).  -dUfu_!= !<) 17OyF::GdpNGuś7*]DվS׆I u-Zu>K1-By`ym1 #"a$jTQ•U!"|0<*I<̓<x p]}(2vevTD#RB8Og,,&xhP/7~ž~m¬׊|g53r"p D Ted <@y$ȰXysG+LkmX$86vSS_?ՍO9&I2y=I^ 1_Rir8Nh)`x/=BӫJujڍۚȬ\-@F`QwN|:Ҥ_ƜC;#qא_($*i*5ԀA޲-N9",,]5 ߧ$;U"vjfy 5'ӟreŚwj%Bi_'n{Re֐ >貰tW)"aWFp*XudB2B$ p#XCJ.%8g+܁Șr BY'4^ TPxxzyLJO4.A b;2͙MJy ?.(uȌ -@1f–Rpxa`\^dIc6 d\O,F9|JLʳdgϸ*?{#:*H ǎJgTFmߏVܯfVLGE~gfe|)4WUNRR|v`G/$t輆Vp]1>7:gȊFOqfcVcwBGPcBū($[$xc@OL^mVP̴bk`&Ăy~u$LF 鼭8*[5PUP9蜲(iщz5G,)3J1V ; jYJ C}aݹ g2r׻)5]讶{*ջFtP^wJ"]j\+9KwJ{:;1Ԟ~q읆:6 8 jvPf Ba#Qs,OyR!9?rT+ezᅇV2\7aiYjDo 2Y:dv|N!`RDRٙzY<gBvw1pJP7^Jfefn!G4iM_P"X ׃?'yU62'TFXPWY6*ʃX9yr@3وEU,@<DVf>m|[q >z4ܜ=>fq|^@ c]湜f |]W?!M m#E-?=/ 0EKƹ+v'gʦE˯Z9ֵ=Yh ""TAP>=omWȎ#!KȥёrbgKTגࠖn%g'?RŞb٫ QY )dW)~8 ӧ?"(q`oKکy<(%.f Y48 TTS BOu΋: -srڴeQ9OABS 7K8{G;ǫnG0d#}+)ir)?*٤r:~#3^tLn&/<2^ȳrpd ռףkOoW3+>oX\xWaEAIx̞XW)+m7񭏌Цے6E +3S&Xh&B/9e+&Żat| L`ZJ?哇|)G,ZIw\x-;,gIɣf_u{MA: 5+ 7鶽m0ryr;+*eIRsU1h5!1;Z^\XR b} ϑ4aVΆl0ԀAuՄ;kgVx6ZVzud.hʚDkIXkvn>fۛ9Ϧ$D յ=e2 C˦|1R(6>vflt}omgdͳq) Q|% ĩ_pkz˴7tknm_ rT5ʶBk|\`AʔP3$Yc$s#"T%먵/;z+dPʣrwcDIf 1Qp"jbc VFjD3Rɖ><]Q#<\l -_?(1&DǬ۵1ri.D#dUJ~ǥ?Eju|-GN[bdV9XO K6ʯE _Q#}M#shۿIZ4U93$;0-U_ Eup֓UIuW; ?Wl "_qRƔ xBw )VqɄgY^^gLGӾjM)Ez"nzK=ZEFm+zjOӡ~fՄϷr1e|VRs^~7n\ #lrwyi?$ =e g[ɕGgPE}"ƮL˼L,XC.fNu`()Z^$:I1Q|!;;c%T*0pW^MŞ#chЩzMeb.W @η6DSVVkZ;0e=;V٘^7N'mOZnd#x:di${~<ގd0;-ѷ7n]kϾckNP+18:SP4X̴8g dfJbRV ?ȑFM1Gux?,(V,!W7NR8ҙStW#Pȉ٣-KVʽT,Mt35BuUTܛ[4ҏu>Z1b6AxհCDKN׼`L1$9*%Ub&W,O:0v6}"eOO?'4 *n_ǔXbjk/34fn}{bl[Qڗ\[|8Cnr]DOUpz[uᑩn-ON^_r$ṵw˳__.zbzhmJ m9'L8⇘3ޡy.h%Sx~HLU ₕ-p<;%vKP6=l9,U9+woXrթ\Y;Q'-< LSRiEaFjG3(; kii^Y!KHee? $Rs SIB27?I`[@wʠ%&Y[ [epefo33N(̌ID`)Sx8纕TEf>Ui9<ȟ&^_(Q(4TcI^ K(`ZER.h%BiunnD O2/*v{jX$ր <G7j;2E 1p}~5՜9₽biQPTGer&G5y폓28$y|Օd kUH2j-i#+1`/&^ I;(f>ݐ;KV{`>@WU*B3lzDIPU #ODk $\D%QI=a|w`ֻzyذ 9p(} L,YA{w^ю7Tڤ8.pr+QO -骇"sC'Uk w.JY8Gt 3ïQ1B]VB) P?8vbV$MYFF|$@כZ>$F^GJ*/5艍)LFU՘tV'02b^Nӗ}.5TOV>F Ořxdb ۢ&)_­1ʖ G к+cUIiQPwWM{9uX)F+Y0v7S gUFfj3@*HՋͼ BD*v ě鮑uї ]W?U8zV54o2*4Q׭ |)gik?5#;*PTYY̟JlΆ1h`SI2 vE}".tVh~m7_ oeW"-$v +苸hM˩k:6IlxznBaJH'[ePV&NM&YI٦e%%~H:͏zC6&gG_+!'g Nho`)pN)l6-I-B?Z[OCM hePb&yL򵟹Hͱ'mjԤQk'a E@I &=v;٫eoVuz^U崽H3{4vŵޓj KFG:99mg'HI(e];y[VU4d_DG@Ķ3QG#YdՖd1VMb|Q"&Fs;3l:vl3oB֟5p!XֳxКE% ˥he6vvcS5]W$*Vh]UXv~^Vy1"qe)=ԅT:=K.F{3H⇜},0;A$c܇(Vy܅ w2HfRLk~W_&9"Ǘ%&eI&± 0 wTC*)+^4 Rq"ͶbDEIq8Uk͠D [VKJӰΙ6iDY3ja[\3RVfwuLe#kukOǥ,VOƋ)XԴ1jt͸=\&ѰpEIRkT~]Ҟ+iXxFKNY\W>ň222PmK6sEƁV*b4cei_[954uyll|F@Su%WVA1瞪`iMv: [._jm ?$z5J~ELgvlטS+y?gF%xFj-P SY"yC4u-t َ?y 5D6~ K>>m]+]Ԏfەr{=t䍨'&3q["NkEF|\+r7['um_#}KdkhZѳu$ȴ#Y(ZdaK!qRzGKm&952c<:lam,mʢ=eQoYIv3ifὲm}dҷv6&Ҵ]Y0f6%hd"k?7ќi5IF:Zb҆vtT87U/{/uXbe%ƴ(|MoF-cPqiy~,!Lg2dJfq˲cM7`w/jR6\^K" A7 9{34gTz+T{o'AF˞WY #\, 2JIc7}z>v>8{խV M' ؘӜBr]CȑrG>+?S͝f)c2d^d`cU.Xbi=rzPySÓ&{FÇ$M]s)Y#cZ/c5 y59'R5ϑt.\yʍ .bRv_>ٴ[)V6s;p/64ǒ! MzSibƟ3G3BLq',ŝvV-UV656Nt3Yц.1ofIEH Gp ؍ƦTD#Pv*\7ig@""x,?pcMp;=\ij3w!"m3$WYΦ,.e3fNo:K;’>!XĐk7LgBƋ)2( {rm& 3A۫E3w ܻVm*fhu8 yNIFQSc9 {eV e8Z(dva@ ;:TuIwT+|x,X}/EEIs݋5`(oZ4\zi-rGbRUX RT-dW>Q 6R^r(#"a n{@p쇲.r?$1${s~Zd eJ~Eo}?(OY>\A]VNYrk2p~%{Gwi'dSRv^N<&Ӡt2셉F9$wߖ$ɐql<(V a$|z~۳ &\$y9n"&,C_ ૖/~{ *"ER'ҾN9=%ٕBu0Mo'ײ35cFJVxO&Y%vT F8[w F XuԆ(5:e3"ھF[>ŸI.|K.Gn+;Z+RZ |k1å盦_Sō[,qjdkX (W+e4P=#^fUJjK#J54v$z>(wr\'+nM/]Ut]}o-+a6<7?:]sȞv ^h+7(`'/ i댨,bVEukd߿ x… eӳq}RKN6Tt榋\o87`j2 K4)An (eF L+Q, p¬,ߗȈ8.8T)Y lxױGlP]O=Xrc_^z^x?+eۤ UWfee:8b P~EI 2©N^5 C0BgQ=LrŢu ɱZ 4WOقrq[8֡(Qz.TLRڄa vXI?l[M&C-#r8#b&`X s OGoXpK 7 5%&.ՔY-V~HCGAO,UKoh.-'A@ X ZtcW'1`~=:O/u/Y\ )# 1>BY*Gɡ%I zKikRWgFeF`f,Z-.lyQU!N'x2R_ ۩X=*;P[zPDb]J>@Oa8% n^ГNO# (D F^@FrGÆ*\sk(l( v3 dOkG Ġr D\1^VkPĎ̥POQ5J8B${ܢ){yZtfSn"=:<亰n'V @ 7My `9+BOUA*y珗T+iPk'U76Ib`ؔRHHR#^(rqwFkwd8n@1bOR(gLy¬<,X0~gf=5ѝzG= Sanџ鵱'!kkf, dz pHPȷƄ,m} K^AOm<Q zJ0 k+7$ǐbцI^ 7<^1O *݂V{p`;:^w6t'BQ=2J !,|d7bzqo ӆC/bĽ[~+J<< DVWYO ccW/"Ϗ#,`e*ܐzʼn9]@Q2'E$ߔ_n8@_[{b䫯@є17nK/QU@ $JNx^S6 R>@Ckc.>@Ba#AMJP%h&2AzgY8vYѬRT+͝f(2H#'z8eUX"{bOffOdP ?.RXE*V|$e =Y3)gvQ`ݧ闌'tkƅhBCG~/SSċU={#LVe> SUq@ǎPi6Uu*I[wVB'lV"uxHʓPh5xA|x-jKfS|6@`h()"ԷTw g7\t}KYI^)YJ*+i6M>)5UP:u_q4MM+? 1eI.C OIؾ]m-jM$׵\F!dʐYϬ'Hݕ^LX [$Pd|LV–JCy^')ONfdME{aI k3n|و|Ly̳ Z^rĸ 7o iץEJJ{Y]O?>YϺ<)b@%~QwT(_xL"tbU{fyqێ4Lƚ^l 6)P WϗJk,.4r1TyrrU "aڀrJ]!|\Y,ܜiY| F\y,,R[Q TC6Wg^oh8v ]X5*WTԩDc`d+i][+"2Oz퉕瓸pĴL}Ŭ>V593{_&ws4)B~z{Oz&N-|X1h4Ր2deJzIۗc؛o Kuۺީ-eaȧ6@H'ivjRYٹV8ۯ덆be1C0H TI2K"e>ݢDŽ;ω `G{P3eCpQ,1sVC,i۫э; U^zdP"+lZ}y q&s2 L&omeߛFEJ4>.IWNufz鿵]ý6fq5}ô2)1ҧǶ>9eLJt_`hۣGѴ}.1d˩4dS+&lBƏ-*0Woh.ޙգcY 4<=?R\<':ejxtDY7cU95ز(dvRl‰%/>iQ -n`U( -Z%jٚԲul\Lh|dBxyEd.sYh O|;7ul 3/!68~~԰BѨ{ll ܫΨ떹8~6=5z^ô&ikJ}EbZLLD=.zǧ;_\[Eiڮc|XXƭEqA0;։W#F&!$؟}Zey.dFM y&,|sK I ?X9:?Kkڄ%iFu=LD TM^lÖHeT?3}ka_SɸңAn-m H`KNj٥lP!dTw6wikG//+c>i>hOyxKug8:2i(ʌ0+w?Cm_Kan=Brt%bdX,x=rS^KYgԲKp+,rȰL2`ȧBq Pܛ>V9RG*T2Lp>νG{h_UShy ➽LOvihX[/F2j7gkY6no4}G=. G+˭LoK4͹Nۺv4_D$F QluSMtl)@ԯvB<ڗ-jij2-`Fgu$`&%xCpsuN0yr ,azd +Rő!v%2,-[3tӁN|#/z熲 LL92m72]MǟSR`pe#UWs;-lH%)}T̬ 6yˢ8QcPqtdqi|B y@//N^zk0S/Vߺ_lK3j5S-U+j!|)Y'(ÇBi z>+U&(pT:K`·?Qj_Lh\ۈUFNƪ}ᱽ&ڏ7α-?Iul{=/OǣdyKK8<"gLFHO3oS7=;ԶWҮG]ˬHǬoR&z~-[6.FGC_]}CsztGP{;S:V@EK=2l;Үz; 5ym^ZNy 1qBb6BiF[W`WZ|Ej555a-lӎ>M&V3/i䱐9d-kCg%lW%' bEYa|r#k@JeC pΡɢ?>ӥ#hN}УL,Y<3r 7eXi90'ݸQAϐlygԚ\Ӭ.m\|=_K" nCJ<֮oj,X4ZvW,0 )P̱pÙfG ,ȯPW"ۃ`jW~+$L_G*UjEaLd lK5k6ƩiZ2Z ܏{S,y>p.Za2xx{}-798sj (UYCs_^Un[*r 2-t;^اr)4tQ'v-:A+?\@vwi(f2<Ŷf?h$u1=XaLӝSx10Nj"=ƥJKȏ8.?)0C0U͖|rOWtjx /!LVsy(6uGU,oPMqMf8yN.v?ibf$5P\ g0HRlXwNt4uϵc:Wy.)VJć'wCtԧ\H8<G!@X6n:&fFfe8LFb*xdMZKrbXafEG,QsBn6OZrmڻ wNspg`gbBSVjxӲnrY$u`ۃBŬg9x"6qAZqK"دU'Rv>eO$V[Ǵ(4|AD(̨)dv^fJ:Lle C! MGm/VBc/26|Q O0M_Mԙ8 FNuTU痛 5ga:cWJJB 8p>4';v2"2\t#L.YqSF}K RA(j:ldj3  14s'h˦V&*@}'": dJlMVzcEnjT:Owt?mZ9Q(`ۍNxb˜免ǴpTA[ؽ$+M래f0-9hQV+,|$bʓ <_7rlY'&plX5ڗb䴌”LN$KzY"$ŹU"6OQI <"/SV2pkVv+ b’N'|wj)y(,Z'$-Z'gcRhWSah|GJeYk>;K뛸8_8= t 9^Vbm&H 2pxE30䞢e\BC2b̌*~̳(9C6fLBNz0rj݃0ŸUf8!}~$XCK05|,3چ卦j7@x?nZ vU+ ި U.'eC 0w!ʮ 2SFuX]Uy ǔu%*0eRBY ӟuV"Òta4eDn>VJ)d  E>xA &<:蝀w 喜]^!G/ªU>2 ԣhNfNSpኃ(&K3Qn{aL9c2x ܂bz{vpC8Udod_Xꤱ4$5pM 1/ v\]?$ v W(gqP~Ʌ }Ա3?s3GB+w~OdGH*$"b}@Dvns6H ' 1fY/Ȃj2ªK0R]U_|]BHT ڨI[U>etIVC=:E@/g3jB;AO<1@fqjnB! 29^ȪIy)>9 ۉr.;+,cRӢ^Q~SHF&nXTʗQ_1P{+7͊@ō6;EWI%C mSc~N44ʎI ^҄L5JF 7M1b]v~Ef*ȟك{OL4*](+ KՇSWs'I^L H uf *[^l[^dXMCZa( ̤<xoRQRp F4i㤒Qo IJ3s#WR,v#;*i^AYh[U^Xxpff5ԡ5PA3wRG&~<>9D8&R`R5Z3S l^]A iX/<C30.OS CnͬD&Eo%J*i.*׳ITK2]E!( A17E*u xbS778J=hD^9*eFT,f rCNlO6Lc9Q2Th{O}Vʽ,%f -TC3 X#ɻeH )czH/ŚMN* ?AZ1)\*XG=AGRbzPU!E?B%EK:*^5 p{2ƞ?r|u/KfS)TjnV*v@3eSe ?5~5gր\[RB݂eUz;د E L559H+y# ZOEÍju3_Ki{>9T~"&l}Le6n M԰B'փsSC&N1 ԬBՔU$Ef},V?$AIcv&ʿ*ֲ:̭mA<$ʦID͚胡["v3 E$uc%Yt.4! VC8w@n"+"yRWxuoçun`\x]zvb?hcM "p G"#ո1i%|XOhc ?3,s4 /iJYU(;uILp_@ɛD(b8FKRIfR̪Y`kR@Y6*]h%la'kPv[OjiYwcJVr3eDF.V/l] bAiVt/jmô7(M'澥-WK"]^p^8^zO?pdj.m 3~>-By6Ԯ;y5xRY3^:YX;++#Bx$ % V1KXhؾYtn&.|FnC:x%8Yb1eWo UW'Kuɮ-%mGzs%%lCe]pi97Kqj_E/|;^it&vU*<8b©Ӏ؈Ebs)c#+#&מ!.Kv1BVg!Y$oOJJ;kk;[ԲpqA ZRJ,Ī5^F5f-QZz1ⶶF~c2]| <4rAun]'?Q\r㏷=7ha)LL8J>El<|MFB*Ho7(zbj[)ΖZ ~ɬd^I(̎#R#ݴZdUx͵<9RRaDf Zİ<*?>OXװ3} +qi .t VVFfOsj&^Y۾=id"ӡ6$Ȩr󽗭{mchZ|[xlQկV#?!j1csKۇmvF^%q7>gӰ2ogGG|U-YPLӅȥ 7<oAbV3 n$U1D0FS[N0B 7,=?ua dž]q l][LU&WO;*mwȃ6U♈͗ޡXkbf#,jn#j򱌰ej]/lLL,cFi -N&r6b%sa9cBǞ&xtuQHyCVW&TXjM HY}jDmW$3> &(Ϊ4};^*C0k@A/Yn1)}ԯj[썱6,&sB* 14]5df&4օ1|,GÍ'vwrCD:kfmmRRg=W*npz'Gƛ'YqeHm!,9PfȞSB:xvCl +L^n cmztݻ+B%o\c%2ɓyϨ;v[vkyܧ#?]3_L8$11!:.'\\I_W=5'ի[Wsur}cS2)OC7ӴbaL#޾~zoDC:)ֶ5TE{֥Yߤ)N3H9!$n1rȔ*D ̓`83{S':H빱Rp;i.;0,h_rflV _zسuK42LyF09= *+Vޞ #Kj6xAE͔hO^JÊNԶ,l/ތW}}chk}3Omd1ȏJ4G:}Tw.gzVMÝ*\,5fm-+Ҙ/xznf,rb`ŴUVxaguA HW}>pYʖI*i;+/wŨund#qAΛ灹ci2ɶ;fjcXY^Wֆp o\ ݡm_V%RioU;Բe 1#65rru (A{BQoW7pl$۸akIih8Yn$W ,gN<=:Խ؛y[kVqY?AH,4Z-:X ax6iL;>=[fd%I"W~W6⇨s1Vl0^> Ӑ5#U!†;-k~, >زԑќ9'ȝT[ NNn@xrZو?uo'r=Šͷ77)ޑ FCcvFˢ˙`Gg fe׽EF[ŗGǃ&r_ݎ C2oH$3C,8AޞNc@*`I~=)׸m4Ґ),`h}c?AڸzϤwֳ6EtAYX%TTDjפ8$Zz߸=kI#n mSt :Y6Gr r牦-29VAYCXМ<ڴZɒ*S:}ӺlQA32U\q:VFJrY6rQ{Q|ZįXc*̱1C$ed~,mzrZGۇv Ak=Ԩ(<|1:+rF}fNN&N5 Ur7=)`lI\yyG.bM$3u_gT.nyyۧ#ti5q䓟CEGvH9_&0P x $Iȳed"ŐjJBcjWSWo013pVLYׂnQQX>J\uӶ*V:~%dG4C8|6 &T,L_V2Kz[Kf=A~ƊI2#7ŭIxFcK%Nad(>2C˭V6vPnfYA;jjvKBhA!13+$#PGvX)QLkٿIY&` E4xOLULM>nҊ,ɒrY`:fgѳY-Ցe RxTʎR݁*'VZŷ1cї8pU@{Mz3TݪiQz\~c4tKmayrJ tbd}LH_ d'/F}O&J(^jRj^?'?Y$ˏb  QWєe'r M:1y`T^9wtTT!QjCŧ6tp'Np;F j !#K$HVfn@mA{om5uidxuc 2T,%IJqՁnz¡G >*}K&X*7A#LX#967Um4<`hŽPC UuJtLJsNUf/YGy0%<,iU6*=bp54/_"*4 `Q nؑUth,xNQ>>ݔ1DגCTq؟-;3p:+teu "f!Q"ܓ)v^Ķ9(;)RYJ25v K<T*rŊ2GeN|2Nd ]rp<#{ZF,lI5@1UB݇VG 亨vd f~>53⼺bY~_*TuG r3|H{S(Ȟ@90啫'"h4uep>aGB&_D0ܨ!i+gҎYJu hE,(%=JQʎd՘_#b>C_ H!J~~r}ۿ C'uBu U'0&}ȿ 2Un8 ؛uNh~kj) `qUnl Gjj&x=Z(Bry<Uݜ@AY QB˲-N[֫% Bb/;.xɪ膂< d+v )ؗ=( 1aT! f`YWV^`5xHdX;ajbIL|-<ꄒk\IPS`~9|iEAVکe4 ԑ2Go_U^!eNhʀ{udu꽃9:c3Jٕl̥|X/~xN Tm*ɸ>))*ɗƝwK$~>;)<^7DvI4q̤˶z*Cڀ8÷^Lk'hy&+7y>Q Կ%Зw!, fK5-i'fȑM@K=EOa@zUkb`uk"VzUO][+\vgi9H ~ePPqGH d[ѡ_l,+-B4͕ T,ƹ> [ץ|`CPT{iP/^>=-6_"q uW@v+UJ$P[ISRY_ mRM1`]9O=te]J2^=H TPN(hQS,~Q:+Y<~8U# !<)fɺ{`K͹`{v"v뛿pApb=$CR&]UTP 0{~*)Otۓ+vUnHbհO@?t K8Wb}J*bM ev|O1e~EM^I̟EM̋F(hZoQ{pt?;}v/H`@e}fvFVlT7A}k T*^FV( $  sj# R\Z!3)X.ĐZ%Dg8xt?u GVomjcjz~|k7+P.C+fb\ex: JoEqEuC-f>tzڀȶqc:!ʪ GŌ՛5 wڇ^sF•G5jx9ENiY,h1LYVNgMW8/4880<-3&TZp6<&LQ:$˓vJ0Fwg޻&$lȼ#^8#XfuFX_3[Эٷ8um+O]u5, t1bf+s|u5\ٲ}n?P6T7 c_7Ͼ[O]BOQ| lZ,F @w-ᕿtfT 8kI` 9="vʬbS7ݧ[E1u=iZf|Ea#53x/ԗ.p: q6OaOk)QkϑcF'N%_, mf~e9j[6X2dd1 ߖ&E6T5)>Zve&c?Hwֶ^z`ick3헕SdTҸU,؀{v>m.7wCsȞ>NE/StP-Q6Zt[?b_chmo/V6.t}'/R1C76h՛cWg2x}t[n>Vjs^9YllaBݟ4h_4s~!avc꺱N̟(.F4W1SbhۏcY?Uf׷Zet蚌}St~3V.6k}bc?R&I4Sf*פhUzWR;Z:Sdcc 2ϊV=c[[1!:.6>00rs6ͧMYiӎeż'+0픥])hYz}&p⧩N_ozͤ]^lLu8ɅhL Lzd#d!b}kmP+<4B˻Fx׿\nLJcBL%$ΧdJ/br7٭E.އ4#IZ|$NU6qڋ\ܹjf0o<ֵLVx{sO6GU4Mjn]g|02tjMpSOzBcXViNI'X&.n3ȓPYO7FH=]6j& 6f5R{JLj6m<ܝf!c|RblIkf3"vW [QH\uSI<=Q*GF<bbD1+B,YY 2.HD,u+jFs=.I-F|-(e;&Eblo8=cCAm5&̈&+@ޓrKo`B3=aCBXu_}%K+%c=/z =Ǖ[bOf,͈jʙZ3AjeeWm5suF(lzs> L5-9[,`kԝ'cBU4nKvb",R6%HD'M>=6;ԖY:f;z'σ1q#8]:#kjZ;xc2KSvڦ\虚}r(Q ? YeVUDI*3ѬM8x7Ou7S2Pq*y4뇧fko&FGļӑi 6=rO+6| Tޚ| 'sf9 =Olwc'+X kR߻U}wtKS*~64r4 \hh߱އ޵.pPw&Ӣm?otlVd6F;y2kM[p/fi+o̖3.F4q":]X TUnd·貞a3o>8R^ sӳLνҥ9mBSvtu`vUGed5 !W#Efg:ZD1tqKmhǠ}dmpZ7Ya mJ5:%KȮ2Ʈf 5*Ƹcr mDkg;QUVadR 9(UybzN4Ibq{,ǘJ {weZ3(;NѴ<̩#PQnƒ6|۬k G%nŃ0%){Ṟ͗#Ղ˪P|Xnccnؚl8kxժBr?"ێԯ}l7jN42\x*QkR ֮MXĒRj@N57'K˭\66,[(ةT>>Mu]#.XMh8Θߥ,]IcC:L\\csFj7U~$B-&F@ÂXdLi$YcݑcNÃWtNngN&2Cp H"CCNŘd[0sWQ+԰QxDEyTa JvUf0^_G^5qi,M_Rñ'!Sd͊+?'Pl.wZInRIsSiZKXc}޹Ml6J\R#Li\7c˳XݑJ]f3DRt8%̈́oA:"l_$.WY CZPOΪm?SF5{IU4kӬRLq2U|YKv݉_Q.)bO^W UU,ǽ4sfr2oHX.=xI~R^_!iΛ^fO'7N|G+&sy` eg1LyBCn6>ME0Í7hRvN]]8FeWSg޸hl|˶k(Z=Ֆ*I*ɝq4b 2f.v ,S0F[ y C*0Ā/^٧%o%@$wfOӟJ}(OecCވ0F9DU/!uaMBQaފ@AX۠@vÕƟñq1Ws0ًVvR.9l/ƪV*z2+z uyY d:36L#&\Dž*R"Ke^o$1¤셔l(jH@w :P*?Y?V#Vz5n jӧpݦ3# ʰ?hjEEiєE^uUEϐrx-IO!Ӫ1*w$riֿK1¤6`XB>"~~*H5GbӃ$*e y&0\"XWO+"/sEXeJ~fe[L7IY~2ocֽĿUJ3(;u>4 nzHn(`Z@v`C(WPYBA~eIBW%@+ a>'A~Z5Ӿ>B2*-ԀZP2QrT?͔tR ;8JSBΝ0+8; g,9n2(MA'ȅ.s  b@O!MYlav *_[Ƣ|jN J9#쨤"T;Ĕkʳ0_7X^u&_ R;QOrhP\W.NlOL#O}{s_> 5 v P7P(ytjn,o0DY%:d:Ϣ(QR{?ii$'*(N/HB^:x#@q{<'Gk檘8 l \EuP&$ŝ`P3;̩ž%Zx"U_ > B|_-dBy RZObB,}to4q $Ǝ:t5^?VF<QdL?T RX<H~*ץTxoFG 4r]UOnT&:=Uؙ"*K2 OP=p4nLH8k!X7@-t%ArQC?ZKH"(kCpoFb@aA7 GʳG9\y%CJ3",vfpUk=Ke#{v*T{HA&0~%ջ3Z%qXSJ" v5k㸵TϳD9-EV 6x46y]~)]rH @!G ȼ<@\c5idQKyegX*p@p谦nw*L^cLUjiٌ)AMZjc=a\%ȓS2 +l|[7~Jxax \5,!'ރiP GDS͸͎<{9gdhsM]Cxf/LsS%"+r>fL4j>h9{R8e`6_a+Oz_F隮ʶfmS@-ugʚڒe֘9R4LXƐ]mVF1l| `$6d E{f{Z S1#U cc Z8w}ҷ}U4_H1䙸Y[:)I-S+ݎ5nw6K;]s71ײO{_3q>h49jzm{kszj4߻\itҴkJ/z6Y핪\.XHk>ZifJ@dK3+ \ ='fPfU JcMۓ̜]Gxy?rY[sմX~Ff1FZ3^+b* a{|^ $F!e*;0Ѧn)2ZOx;]J,GvcrVNj 4Sx_BV_oVa̱e#kWm##_/L6JPx7mJLmFF}Oԝjk;Vײ-l^ntUc J8Ж<}$^ Mt׿t h{N%_&YM&hֲ3:-Yg>=*OozoЈui5kbX| 9tӗ`㍩e-nțĦ@2>VO~U7=|p&,mJRQ,0jatΥ %4c"8X)ŏ GHb0K{i6a͎d?0xZFqcѮT$S! :;ZDrԅ2BVC9T(w7OF}X7n3^ͮv!:cƞHDL4i@I!{/@e\q2ꟶed"l(k+4iQjEXX9βC<w.Ă$_KGVH ZdjR@0[u譽|lhv&sDqqt}'JJELtSg#'t뵟^-r6_OtALݣXY4,b,s{z‚Iq}gU6S;`b-b9fTc/*H-,}=sW\}ƫRt=XeJÕu\ߞ䏮u6 N%e!?B$JYe=Yrgw@|> 0,&82HJ豏M|:ٺ^7~dN8q4ifeeY/IrgNcc7t}neL+ݥzG-fp1Mo/⾽ZC;QG i69?euMgo-z躆>woB>[ȕqS%-^YZ^\~Rj13j(əYQ8֋B ;Vj/;ۓ:5LiGHqS:;KX\]S"d'lo gzPip[KA$*t_Crxb ?זbTcV qOrIǽS>#?fEN=* >$tE5kCǜ\|nUbiPGr̨_^!S^)LuJmP{JrݝAy[Yw<,JeTP@ ,fPž+Ƙ"m mR/F`m-\{&#^9SDcb0Oix(1,xaOǵJ5j R+_ [cH~ϐ9e;@a#h80f&.{,mh{ĭUz|nS.{)L92fG,80;NziҕbءKi]~ܬەi(Uk,*-inH2pJӢ%i\#sVK(SH^(5oC&6dmAU6((|# > "2@u/褓Y7o DvE+fVb~uD,JwfуRnTDyV`pݦ_fg4;;(RjNN w!|scƉEH-ƧA_р 7-CfF*[!v+ zS6Է&.!ˏ<阭h 3%j1kE]i/u4I3(Qj'0NFd8ƏJ3 $B33<-1\ɐ^g*+Tu?Uɖ90H,4%C)S5}߱u"@*6R"3c@eFkڪ$%\76v[B'/7`]_= PxquHSk1Bxpu-+KlD%l|ʏQb!Zp&va,]Nl SaUTYZ>C#HVCHǑm{OY0Ν5 Hg-L$${ \ +US"FRJo1Be$!bI;|pX 8V/*qtl5)ls3h,QKED31Fذ5ݑ琓,I~ܰiF`JgNGo"ɞ(:tuEQݸ.+C#ȏ/Cz=;$ruB±`y G U*U:U/P*혊Vf MHO,d5nm8kbKk"ʰ$xg$ cc8L,Y_GȚ= dÞ "؎8cu6uS':s$bĎ!K6Z0'r9'rdž~*%z҄rzB%fv~^[ȡ> 8 T9bybx*;홁ƍ \|XdT݊>>eupX|`?qTAʚc)d&ju&\2C0ȣ4I!3a'< iYtLi~a*PLWfe VbC1pE!dG$;Bc /078x;X~YHFf[$*YYu$y k*ݹtlZ/eB]Y5(WW ok- mjP{:pb?خjU`@H'}]ڒFN#bdTv"1, Q;x 3jn}6tOx89Yiiy1yYJVV 'j3:bI40 Y1,rv*Vl,q]$lɈ#ş,8̮Ncȏms#ʶrY7mkivDݻZqM'IG[%i#27e~Sg7zN24? KLcPsem?%1S؆DTn[nܫimVO|49*UzH9W\/u7;Y& |a] )9昙m6Q.fZ|11eu+OVjҶejZ-5zG"5|֋Y,\`2n%׫nY4Owj)X+ۻo!a=:666əΠ}j8țiē UޕS$Zu H11&P뿤k#.^5dK&8գ,GZڜ)Lze5j> >o, vlt3jS&$.T^3Hl9P7ֵۨѳ7dky/L@duM/Rs5 7:_2qi4 ,< V+x-^ӭ̘ў1)u; eH0gfVXdęџ&N %E!D@|SR[:g{K)=M?.:vؖo*,n?Tpƺ6tZfRՎUq"zW`|Aje6:[OYd}G]Թǂqe)y6Zh)4Z2GUl4='9J-|zv3al\Nf"TVv!B1H 脎xBDA٘<QfA*,tEزɋ$ʠ'g'h(L)13 6} چB4UXS;&PQw\hQǐߟD=%ۺ{"i깻oStkYӹ6f'dUo|dD#j=u]!%ir0B5I\gC8uRSnY>m=S{m;k}5ں.?*Ηmѯcꩠ"g3o bǒ15ZRSM${e#aԗ; *MÆ.LD*zzK}Hٙx{"{{j6TL|zkwʤ|neYߑ%~6^]XZ]2?}?#&9OWʓĈo+ۄF5ؾڻi7TԴƫYIiju5 yYT>&6 ,b{unϹ ?MvN,m׬ֳ6O %flER:ej;ngN/IuܻRZVmT[kQ1oW BM+]^.ۋ?9=+̋,ZBA~[0^T}-*YX"Q&tTcI&xҘv؝յ'[o7p:6.;/jbRQĒ2j̇KIռV77oNf8gh~mSxb7tgc+] e,V?m9[moJLal-F Myt8"\y:rOpֽxZf1t}8GI4>KLMzBgv},xa3r|fr\>oEra`AGQg(SX٥ 3(ꀴT7ROruKz)2TB "yYUvyqAheZS:;sԷgXumlOV5ddTS+#/*9Ki(-Nml, 2^ZɁŰ3 Z_# .Of2p~ϧ]D%/A6w{<뗍cHգ\W󜨸\iD>M[]O;zN$Lo+Y=,EkTMK 0cā!nT QF44:$6i F[3~ Ezsrgr>,H/pUn,mDUnY|ve %?Rx3+7Pm7I` "jFl! &Oݍ.xaݨ&}P3:/lŹUժH<(M"%Iԕ#VaN;w29>ECZ;qy' >z[3qas`U:YpS/.TSȦj h\:v|~ȍÿi8Z:jԡnN!0VyQK+?4 ~l: 6R|@Sr!jGeδ,%O1 x5l9~{($3i~e#4pFrbC7hvy:'ȕV>( FxyT fpxGb bX>F]qfךe>*x~;1$ӯʼn!["C_cmBA|؈؁u~6Kl1B3Rt1gveU x#+!+D”`뜌y8o*p`OY˩,̢k4L]C%֔*l4jJ1ߟ ԏ=wg|&JVk6V Ƿ?*`\W k-Hka(4 Rhh%SUz8%hN5PJ(&xnzGXrntbJvya=&ʨN!<Æsى=?^;{BljPh1Oȉ*Y߲W\aN^"Py-M˔Db9+5nN}`ˈFʀ$D,S$ %蠑L5"|d:Ov1UDup51ǛRo+8KഎV-Uy/2_rC`~ې2C*x F;Dn@uT{MrxniGcPz2|+xAJI#WGjv7=O@XXd X [Vc%l׍Xh I%wuGgyq@oQ4++%jhIVacY UfRUU 9_'PƅΙt|*d(K/ZRP|nޕ;-5v3(&= # ecPUtQ9m:]jfQMOݘUYL/ =J:S:[M|Ë npUq{8$diTl`6U[ɭF|H4DW?tY}EɃo`)Gڤ~,QFx?Bƒo?mv朸 |#]jyz^oTe# 4K8F@_PˀH ё“o߆Wecѱ53VF4|qW05T];;YZը)^v~s^.>*Qa]#XlQUZbVSP>adS8w&Ӥ82O˦N@|d_OԳZB5) I.4c؛h> M5l3Fb}P(r),6<] WQ<0PDLyb{JIHGw"!xRȲY*f U|ȲG I-!oP5mT),&k'+MYYذB J >ؽ8b!Ku{gˆy9%`U'%KP̚0c6ud{ib9=JsXP T)t촗Uo;QZp_ 8*_$ʫ*XbA̡  ^b,XcT ֖TUbȣ-i;ӻMЖ4S%5-/+3p ܲy DRoӉqNHKu¸(j#NUWfu`yk.5n&*;$&C dd@yp)tE` BK=Pu^$Thh=$2nxtIhC†^8'?$fu'y=@ه#{KnxoNÏ1+#r^&*+RH>z|CQ Px?x5IduH ,= G) G0W? `ſo, TǎfcۃKQ@A*~=t*O^{xoHoń"~|M( xNVk@ h7Y#*C]]". d- C_VءBT;h1$*UYZN,%B +V:5ZoK$8W彙@Vi |mJ8=$ idabxG8eF qt%:f$I;do!D`Sz,;S؀M^M!lt9Ac x4TO/ o@kޚS 5㨄R:X2CʹN("h䗧(`IAOe0Q lq9 E| @G(GN 7%Gu)`#ѥ˲/V?uvS!UpKa!cI XTՈz6FC9$H*,o2p+eNY3v\OjgmAYg չ#)7P((i౾QZ ȲtW ك+X?To׈2:I% 5YPEkϱfQ2J7tD "Xة#Ih6P @{&G f04+ bSA$1 LafߛE9ZvϮG"8Ԝ2Vsf%3e ,#b}'RԮ3u;gZUWɣyn8TJ|1Q_jMf%Yr,ⳣpFeķ+IPXϗq2w.*Uk#*P*-N>C6D?x2"  T.M}\q3¯p܇j,D@+MKPѶVYb.JcڛwoȚkDtɀK2=B= 4ib3\h&?/_Õ4HR,E% VL௓#&m͑Vm[?rnM7E S$114NzI+K8DV49ǽTԿArBy9ƣ͒ԮB4O*U&?ᤖ7La/p&@G%A4RBXɷ$P9=>ɦ2bH&I|~}o,ߍ],]vgCr=Euz]N`)zwǙ>.XP0'h&Bޗ;zv\q9t lakw/'PH֍VSp&`XwF?4&sloVND,VE맬든zIeGk~&zcery-)T 2t\OY+)TElx5* EԱG E!cKF]E4Ku`2k]?L:Vcn]̷ׇ Jajgl5j9PEYህ4dewx{c2yT)D6bĴP8R|mCE0º6|L{7R8oG+)I>DVSmi'pljI;{KӰrԡ3Zg|Idj1gO}1"S"<.W$;~(եO(MUύ8˜EE mv!+Me``.B}92\lǵ^oo5<+Cb_wu`]/E#tNY7w*X.& l=29S\ŇZbƭfi;w ;gM]g*:u,];_1'zy?7kB:PʟԺ{AX|jO4F4Dpw_1[,^L~2FNkxY@ر GCu]?*jxf cQ{g- i#c2Ixo+NԓޫnÝ믨n}kUȅolxP32]qUQWQZ|Rza5-߾r3-zjiKXceϰ66?Zs(Fx5_PwlFjWifEW\ᇭlqgU1[NkOT9XdZZt隿{x?G+%Ls@Ғ涚^+MY^3C li3#<΂8=Э/Y}#be޺.J1 ݞ\ )[''D/tO`ɥ5u | v~:4lmf"33*m;G 7[E XRFp#lQٌ#XбU\cJ>Q# Xq՜ah;7 ,ޔjJZ&gW標q1ʥD)BF*8fAILzQz]1['#6,JMϫ*nF;W#(V TDM) u*~ .MU8()˄|QPu$ً$ŏJnacX!,@%=%4Gu%V2 KM3{=W*x$~VnQ3+6CHdMjxj212=X'-QddU$#'NIjƪmmM9oISŻd5jM9?@*~S N1ZƱb%T)A-WVcR}CW*:`×(HP_}5Qg_I>5?6:^Gp:Nbf-jvz S5>qLTNeh6@ob-l'a :[ p|  7_ɲVk__EkjU Bӏu 6~/T':T@LL;ZEMEEj7%H_'RQj(8M|CsD%s"׭YA-1p&vdrIpf6n1l]x򽔛ڱ`V`xUEef+GW}3+BL/lZش*I]lʠR}m/S5/G$]OOl3fírX=T NqQv`5|YY 4и)*z|Y M*RP2"_& S:pu5KRbEsG,$P"7qLEX[lýwumnR9qIYGˏ!QU*JIi7j7>ZZZyC?o8k->J;_򨟝xK9AhKS {dJ7^Vdp^y+n lf%A$PI=)~oz›2ͻ*ibJ+uF%,E3dNˋkZ$,ot &>g8WguGn"jĀ6$*+AEr7{ԋ=e Hf 39TGr)TB'b:W::UrX>̬ݯY n#9Wc;;WjY9:)jS!½).{2?K}X+*qԁyEZfF<*?o,~cA ܚM X᭙/f]a_5y&'x6Xӆ$rA `>ՋNyٚ^fi2,VEyqPu:#^{kB˶*woS|FB G a:8p>b]e(kfMs131>-eDSEJidPV|utܙM?Ow vraV,/D3r&n?V)u lO1sŢ CJ _x$ Ts>Mc}\.5Ꙃn2YWg簨wVy^ޝM9pֲ马Y]F}+jșF^ R( [{"Z02<gY$I&(>M kdwdOE[KzFT楥]1 ;+c5qe G>]L%l rw N@.Ҍ}ksQJXτjO+'[O"imw+5<},8̕ *OEObXD-PR_=OiFF ќNʔb$# PQqq5 ^ ʪ(=@ =y! dlj#E#R+.H$EBV4 b6`KƤ$ !9u^WM:3PK )p<G$9S]^iO(U%=YjFDR,˒UJz:L򅐕it*ۿ~ŋ4@3rJ?+'E676SY_d%~A ٲT@ׯ ֡B,,}GW{%U9 M[D&7q&x癰Zuu(>ኯ/RWBIk`6QS! .L:Y"J$}BMrW|&hXHgE耇ȆlĪƣ+3IA>$KƼ1`T9[UZ^1f2݉Uiљhӣ(g")1^DO\uӡ`I OQxG =0A7阸 ;* vTyVu&]z9[2H0@v$՛=%a W<_s)4ķ#r?eQ؂Ag1BgzܫH1<*yBBpu,%Tu1x0E0 v`vH@$a/'B|qv cJfG,9 v<?I|h{{rY<;{)<_՝~Ga$*(5m UX'ke%b!E?"5M~.>hfTG ȯ&PkCQʪk.DF j-|hR(wFֲR}̔ïWz M8knx4(.=\* jMNw$l yoR'Z)8ĊUU ީ٘ϝTc"cɗI߫VnV$xfW3Uuc9jEQh:ӫ5!ftutzELUq9hu]HHk-gzeVg@R|RIpW޽m3c( xGV{p~aو$[E .'s0 nt茭,e)8ۊuuqE6&@aU^[U^QA e|H'PTsXQrS!P(1>Gk[|< :WI ~NJA^xH~_a:y)J :=+2|AbfGVyv,8 E(Ѩ5z~F*7rzx_nÆ Ό[ K*Ȱpƛѿi'P6AEV~A,hX`\GY8VoyC*UP4+Y8l'z_F5_*\W5"kFK!6f qyMk֘]\cY9Tq?.UAr@9!ZwGGkd#'ɗu,mW\/lBI)KfN]]/dp (b7V5#o- SU>n\èO2+t3 B +y6 :/ ѡnfٚCѬN%&sz54kpZIvu]/_<1u w'Yo~F%Xc^CJ@--z=$^OgcW՚\}ى;M3gnIb  ~mH;ptbf#GT8Zi8*Ok.t\VSYLJ:NIl;La$By.|&3S pW$7V[}]ݴ>78/K-MGq\?$Wg/h`ܘhYа!$F+P`>@ 7̏#Eyq%Q[#0Ձ셑ЛҀ4QCjo-:7#bz>na_E4U?'8i{r啁aSoo}+kmIܙ圁\ve]5ȝػe1a.ܽͲ5mDNZ=+!;9i3eG}qmw,9ԣ6&1냅i]2uɑ1ݾgA&\R c1ՆEwdRk;8خ^c L:_&6UPKwHoN=,03# Q\=SO>kunfRZJطVoѯhQk9~*븑ms"Qs@(zVM-3Ƿ (\hD[+X%HnH^MqwgW#nҲ, Gg.M;wT԰%a_Qt9"ݨZ)Y/p<}z%zM=M{zb?*}O&V>Q8'M ޾WkžᎫMst곸ҢgxLG+َ&'vs^&vmŹ>{{kxZa%19ޅ<^&"7M}Xx,9HZwa"W\"OqaX|8ul\={I{k6HP9#7?Þ[K )ebd%VDzrr Z3F bO:yuu2LnaL+jɑ cɥ@^I^PDɖwbZ31f)7+1JQ*YT}?Ȇd?5Zd(=OƲ[ɎiYm. T;tW%Tb]ڢecMf3lX%U `t R=MH J,^$Ft]qp=LKCQo"Z`܎lԃbWVyVhn*ڝ5z#oH'Y&[4Q5 +uj[zb Ί7yO^,LLZ@ϮĒ'ą\.,a@doY6ef*<7,J:ydG=J`LoF'M]*Zvn /0X3ʅY;"ZxXw a; @OzdMSxsq.ܢ BThyk @`y"MyyqbPSFm||U*በ:)7rIYIӎA28KWPw8cE$ bXTM4m];Lpq|P LEAsѹ"؁̲p$H?6Lf2M'I\"(V SX}z/UԗUg(9ȚpݑJ:0GR m)$qL6ց?AɚKȤ,`s*'ClPnxO7N^ ĕCr ')Ϸ [CS!)椉W12 1U }W£X F<P_`Y쟺ѐֵiEL*f(֘(?k^s*$-O|Mz"MI*z+%hP:eE=\M_ui:j:;;/bYX8yulPlbuzG>&TѴ#+.iFP@P?*e18uw 767NuKqee9M,I7dǖ#VRPh3zċ2?vRV4 maMtT10c;͔1Pdm|ʬ`x$>68fϚW(^VV2Dn_A!l|flbz-FI~\yivi%;2&vK.WVLYY 8c*N{~OȔRWN:? ) 4>2 ̂~6*?e[~ aI-"–.* NJCv3gaAqF Њtr֙>"Ǚռ!2{ٙafƪ=q~.ZE|'F5JmB_(V:^spiQ/4j̬%L!i>Gox`:,I#;Jv2Z^H1U`5jX7*;OIZ >F~R*$P"r?HN_V>tj>];PsL5S])vj Ӵ5ye_UXO̜㗨,J j g SaSIؓ?7]oQԲfh_UZI MmF)*;\~: <lhraV-u˯[1w2)$KTJIv+Sn`hO a^ayBmlW<MCoJ+ЬLY`Hpr2it6j9H^<" Be$yGI≊3DžFq9Rfe`Y!hJ Y}7m" @TQ7xZځX y I&Yzs`Μ*P#J+S?y*˼&Ȯ tIE Vn835=iOwvKt𷗅(P%9 6ZԖvojg׃>Ayeeɔ?^輑=.=-:Q<లZ)LjO:n@[sJ(Kc0•BT!zD wli8;t^W*u;ѝ\::^,O*4Tt^!j=u,_^u/T TQ#W S9P '! 6M `X._l*'Sai*5ɭk 1Q7JY27`X'Tgw_LfS)t1+!T{K(f H.7 ʧ~' +0Fo0{)T'H`(*LE'FfA_+ 7$a{BC{1pu(<4k磳mC~r:Rn=ZK+Aۘ4)y&JBQRO j9߶GsEP ~3 "${QC}mvE1`}K0%HB#OAX@}OZV+qbFX"(+UˏD*G,T_t9hxAԱTpC~d'[/=ջ`?Q} /`:%@+o, 4< A,/RK{(c_O.C;-+9gظPP,_`I#|Hy1^RQؚ':#Fdc$ ~5aʮ(qg%jZuՊ>.a3F0~ w-Xr9_)?j.lkt,f #^ρүP 7kȫk4 XFTB;21jN0``2@$ؒ<֞^WQ|1@կ@D}Vcso_q7c>g3H1&\9|MFKl3U382ja]vuѽ7cJ_U>é~c[:v̿T1+½Z w( 0}.n뎕M_Gv2߇=ͥ)ԜEcez=&&}L,hԂYHR7*( ,YqGnǶMrDTvJ+<;n]'Gմ٥IrW:[|0q8d| J1)5K~doU.hמM>sih1㓷1d/ ҫqGǤZ;u}nO5홦>ᕳDeNt6:C#MSqǼZwv1[fmM%%ֲ5OR|h,t=GTuCNc.ff*cc2a4]ΉcXApYd [EsV3J ;@l7=er|+Cx3A }fem4X>D"} DQzKizQE0\gy탗S'@5ಖпC|k*z[H[9t7PC)(8*@|zYEh(g5pulj]輳}[C Qꆓ}k' MSq&}:~lb\>$vNF 󰱒h͔W!Mg~ݙ靲"Ɩ)A$/h`,r6N4h^B6:0wLuVHc:V|c(e깍LJjNOM D1c TO-3lغM,mR*n@JbG`-l@son MCXIivCP;bخu0.z]'N#Y+U Fox=v]łp2U_HvTSiZǨ9XC77JRMVL;{}k}ݹw|ouY~\ i֌$!G*aOf|weOէ^ǴznOo9cN]ˉa;OS i0c,X71>Pv{$2F>ds8H.?}tlZk)E#+èMQ[yEnӒYi; >i u[{hې0$x!v IJu]FN%|֊;G9͊T byd 5$1 Dr99hkMM^nrML&Z N&f\JFO!f5nMp+$LT b#1y] I^cɑ]D)"/IR YH>,1j!hPlDμY8PPZVϏexhVrCRVVSD* qIA iN@brOGÙrZ[21tɝ2؜W.T/. U!2T}BGҕ`/Qm4I/gu10bԿN|8 }ySc[G"x_!T.->}8.gfuJ0#iI.Cx+6J2ãQ-FFw;+IjW\3,4QvP9˒,9TvR擖DlX Y|nW/4:_%~SB&PԠmyC B9,R- 4JvS LIMIj" yQr0ˁfrR*)aA#ny*O]="P ʀ!@"d^BߧA֎aXir]QX*FY? %I' ( `J('ŬxHx'i!)M5dA0erxuOxh.%YD Nȁ1GJtbCO$v^$WU8JPr U#N 05Ǻi ~Vc32V>LpOrV Vې߸1'E:QœFwRHhuԍR-"_F5\1hy&(&)NDU@G3<2oO5Ҷ@lJ dijY Fi9N!u=7 r'x$ $N3*iݝSUt#PQ/ 4]/Fp4+ӽ7ͻ+D v]vVpLݣB0!]HEbqH.FPh,'h`gP:'HcҞI dɔ$.FbH1<#D'W7^'XTC8PhC-lOb= 2#YG@ZSg[*s5X[cF@υP .it:.ǖ7˄>0"5̝l<8jUEY6?&xp ›IE5jEWO=m93Lۦ;U[ff'ϸ Lz4/5gy-"dL|,9 +*DE?p l"(T #){f*/b]xV۬Ju}} /RV8F*gL^nZUh=>9q6ӵ)" rQi]C"bƼu8dŕLYf85,ZSG2tfөARRLicNͪCpHF&SRqVYWV<4@_8O *J ykɏh zh׹l\39KRb܂-J$ Kgf",N&ʝ;IVMn-BwY#^5!]̀j..o:fv.kdpKUl;/ ϦҽSٗƜzbȷ||J&^?DQ9Zާd[I5(uMb"-2@pj߸\u~2 l L|ۛ@Xctrd;Y+ 28wQ_`3>NN8y0eB@݋s/=?=FG@A#3<'22$_Gx`d^?g2vpn|BCUb1Ŗvp |辠1,(? Aײ[/n(,|X`yE*4~7n@6o"Ji:FaI#r@`PM9绐"C)d"KM\r]=Ò_{A!/ F р#ϒdiGI}yprԆ >+4mhU-->ţtR$R;+5M(MI Pr_XMG@=1*6 8hjq+#9+pG)G)n0RHMؐMn6>|S=!ݜ,:?Kj=YneGT)!ۂOB '.7 ǧȓxWQ p缠/X"HR+`Vŵ >," #F~mI}0䂥:r1fnJ0I{{4Bh }r8ǐ@RÓ˿?򼀼7 qx8UvbyبAڬZ$N b@j[ܕ^ۖOPX|?3 @pxO x$̷,į 'rx^xq in{y uC>aHZs\ &.XwV7olNMoƜftHYu5dg3K,MD )nĩwU*Yr\ FfdBf.?S=x~K0$1jE-VBU$$c2 $2aXQXzؗ1FXVe:q iS#L>ٴ.l~EіQP5 QiE{t+NeX:V`@s37= gW۱c}i1iG7ENnlOC_~1i/:ygdY\ʤ&>%GZ(:"\9ɧnz[&rQ tbǭ]V@ O;1E'adQB}5kI.-]T`T::Q8Z'-^;RWXOdn_@T]G^jߥ3K7fH=(Aé`J%‚rvȄUec³Էe|Ctu*bB'ĆB WbʩOZUo p;RJu3 +GRx<ԕn Ÿ?ՀK,Әa!diuB% Iw Ʊ$NQ|aB@Lr]=P̍+(gf?w=`v</Rɡ(]*U?c/jjs"'e7 #z/iQ52kTM_!)>uy8Iӭ{dzrڍm[n۸9N +ղF2nWV(e]Nj?"t) #\." z"anT|kt6-[v|{p:FvK<{>f1Y!mYkК,k$Qn΢OtL *Y55#JP'?h.֓L02SU{['/޵gOʶI7b=Pq|=,i5lrXk:x1tR9G;w?XP:NVc-Z5(ћ? P3y((fu_W]".hcOoj -'+1^2xv"/+@6[*yU63eHcDZV +؝IIog#+$ buoQ5Xz-H3*V)G xT,J:\ɝ9K%f4I2-ln'[?|4t\Oר\I8*R1.]lGi&y9cZqݟdRbTp ..&Mo^Ael QǒG5d-wMԶ P+|wQ ~zޛR^vO#Pϖ:OPj' }?"9XJ/ILmݵݭnyeBźm/NwnDȖ-!”徂h7wmf W=MCUumeɑ:~b&=hZ;ݻvLչе|:6EOQ(<[#7 V'Jئ\qIPŬIkS!%yB` )9 =Due&Ԙjwu}3nbS ?XjJ 1!j j'e =V;S'v棦VNGQd;p#c9z;P+OxXv&+ԧVz<LRэBDe* _t ik:z>A5-I4ᛤ\%;"x޸:r$$j={zou|l?Irw*O:Z2(zn.ȳW2+Lt}z%uuzsްfkvGC|"O^)ZPU}R_M[H:}ߛ7`^険dq2vCmm*WU2p urℏ ޛzpɅeT9|(xcti8`e' >ԡbn7t잵V驼#,N,$B9bXc݇2x_s]G՝4WvI.0n&gI㤿(*8S0<5YGo3H!,d^dDIpqV=Ѭ^m[3>.돥iر.,|xcVYٮ[-m4 Ry[irCEFOL'pR(11LtJ)rJ ْEy \ÿXAZ*H5%MR htNFcdr,5h$ZFiG($n^T+.rLm—fIX̓Q_yf"V"m X%ryfLv0Y4q.XcUQ ۏ=">V\ L%EqJV=Ci 1H3mM_Xk%#dnތ UX6ur[uj/Œu@I^nh+qGA@i:s%Dr'Q-$qɐNU,]4ò)7iU'W|LV*[uJ*ERUt?MK7bI DE*UeH74JJ]nOkRE=jN7-ex+A$de :1&E|qQJXlO eI.Fn6dK3MFl悝3`;Af~Gue)ĚvZy0/'Wi䬹l_ºO& y,", fM^*.Ѽ`0Bsqd~@ӂmx/ўLQ"T:!Ԓ@7+&k6b=n =O4sEUI@T+F_F~f4E@AJ/~Ɏ$?w^X,]h>fi>^MburI=|z[}yZcbRSiE]sW^E#85˦ӼlvkƯUZJjhx*O2D@;l9قTWgo6nh8$8.E.Xǀ|@v>^NMJ%êԉ:4*̀Ug蝜*clIg{cIV;ZWr䫂=YX(i20+tf,8G@,v0$PAqfu'8'9!o6o0UjM}PYBR]S>_처CǢҳ ^|$ ; C/7ƒ Id G3Z"  EGb#p,I4;e~*z+jӎ3r[&15u d"oXC]RL p4 Ld6+xȠ!PMY{#wn1b2wnQJM%x\ϙ11پ6A{F|oD1iIs5PØr?}W­| ƌA@!gV6R/PUҷ9 SG7\lt5%jUx@ %DrsO]ϕ" sUF-Osuձ[#DK*У~ Q^ 'ʪW8J֔0}kqmmåͨ2l,'[#P{Vac"(J2">Hee'@R Y($ʕ9V Ur9niN*#y ͩ@Lu²W~>:J:N Rh(Qpx ~7VhUٕvM0UMGu)^L܇3 sZ%UOd֩˸P(9óv Dj̠E7tVr&CIA*(M.<ʠE^VF$-Х;2,v`2ǐx4$!,=p}("ʨ&@_ -dFtRBٸKpBƷڬ>D;g>1ܪXuu2( )G|M9tE/$U Okq0Elj^EJyE۽A%Sߩ!/Q2{{Pb }= F_kYʼn;** y249Z4mI$^BTXUmp lʺxI!~:`gEd5R$V>EaBMH RXvSAVSdUغ~{uOfY2ng} 7nS$&! {8DD!%8 b(50xk.u6ͩ$zf`'6 T6bv,i~9>?ҲsfJU#0y>~K)^u9gP7(e #+zq s¯r=^2hm 3`9uЙCS5ɛau&IEDQ㞝nOx7SC'ݦHQ;W[Jy͝bnrO,<忰'%W*0UzC{{_b?Oy_B} =>B?HOX˱c9$1?۳{O+Xљ8y۞,ITaǚ?+o;{xHzrzLWJI%_${ `Ov_Y*P}מ=bxFX^wrg<AR <}qՈ \#RE!HTHѵ,,0QwW5?O-*ݹq\aߖnUHW>6C9,V$rc z>-[Z$dG{dh vg{ؐCy~ϷJmNn雒mH e ~JXiNAd 'nHUM6Τ :Z pP6DDZR#_͂>\#eq9(Q| 행vDiciߜr 2$)"Grlj7ZH,Α_ ͳrL1qZRym̿r2k;-aJs:ӝ۰ ?7QS%ZwO0RX4$/_HUv*`R`,T QCbz Ԡ6 QZKBp#KB%f oƒ[9 }40(Pt_* OHBO, ` XD:#AQ5E@:T r%GWdtP T7p䂡M{!Z`nz@ +7#&fCAn0v6 7ȡnuvL٩J >n*@]HkL{!Ugne9Pu Y<*#V:Frd*:SzO$+vFR9?WVNdSV"c/N{r|1Do6{{7ɮ63vf']_q?zv'3uXUxtԓ2 c- 1!nj 1$iHTHT"N$e͋nl̙-BFUܤ1dHWWC>~q㜱i9S4MumCXqtd֒<=ꇧz֮ilF'ܺں֧Ɲ4\wyZP'IJŋG Nl}C&>V/$f6B:~kf`Jm9P5L95rVm30o{/[pz5}Xo۵vwX]Y=DuXV˛l~rL}/#$&&+"8F+ ȯ߸E3,cwl^ f(g(Y򥉋3>?Lyt [TiLf.F=rI+ټi_5ZT$]ҿOg0HPΥu$R<;r8R6Կ-$j?bծH2e7<g2y^+ ],d|ƴ|i+YY+i ōjG*Jwz5+dfRL8Y\Vx*TJ[}џ՟Je>G&35,J gIF>K~*<28WW[S}$_2x( Z̰[]|B+hْ7SU3>= ڛ S;me z^:~)\dp9i~9vn폦hYu4GQcTiմ)M -7KP;|R%+b.NXt_.oc L6b zX_^u]m-[ah5:ox9cqm$' \y/$5иXRma9NFJ19yh2D$ɦ.D@X,#AK=eЭӡg.mއjv>0϶L)K*,LLz"NK维]RY~6T2Ж6UQ`k>6AG[j:ua7gVF_S=޽~7W۟T>{uDYF>u{,)tko׏ALl趷6閹6=1-a:iۃmfGqo!oIJ7# ('B΋7 L StxA* hwbhXRJcn#98й8TEg,WȁLQ9&YG{;5$dijf{eY?)g+&zQ{r|981{STǽcuO1 {\VK#%Y:K7 1,ijBӟ"k)[Py*@`Е#H#2MLInLw{@#_Lr B>" ]/$5E3&դE\*I4!}utr*X'5w^αK RZa YHeWeVvP Nw59V<ڀԃ; 9clrIKPWp5䠐m4y-uLHHfxpǒAP!#(S L2zDiK5$N8UsJ0]C"ӯY!RX[m{"oE@PcT~ ?C_7j+)URv;o9ڑv S7)5#$JumCk gJՃɾFRZ*=tFZK7@LyD#)!'_QվNJ(7!+1Fp9+F 0,[ 1@2k 3UXȔVg=߅nBr0HP„?.#VYR&u8lgJ+,{MQ jHدޢki7qhD#J4Ȣ.į9}}e2oM]-kjSW04p@{Vfz;?ull uVVJu~O`G<`iA̟2D-,y@ 4͐O@!Pc}Պ&Fgyq‘6uT33co@Klm HS8/BW`""T^mx㲻-4dLtNCwK@}ė{#'Eȵ]V#t3e͛4ͧOSy-ݷalnr3j@ e7_o.h-†^@x;C+Zt%x=71i693Y1)K-:7Uu[DU )<5<ҭڔMOu/CstHVìc! ,+DZߨI:O4cPȘh&%F$pY>F?dMRF~ y&:鋸FTlj_3F=|5+bVQ#4j$nv)C^epd̒ Jxۃ HBĶ38چ*-i2H5:=IjVX%W-fz*FNڎXjPKOS٧A'Kh}=>m 7ͤ&Nf蒡`,|zqUƫYܖ=I]TOIKt (p{~@v V6q^o9ʭ5 5nLx7#8 ~L {:8'X㾯Y|FfLy4˰cD|Ő -'2ib %+Z ~F.uPG!oo o{H5b ?緸_wÎ9VA4eÎ;#/Gx)-,Ⓠ*y-bU܎{pI$lD?)p<]nluyUXmn%X '3=b'opDR>DyNA$=ӳF'ԂQc!U3UO)g >LQ^i'yRq—RI*)UR >\z:JVZmr`x#N,hVVO(Ud?E:sF.L\.cC*mQYK=..yA6TxyDʠqDkϿ_zwf5eFu1fȠYIU r(:F^GҰ&32j kP3Y߹pwAVtOaapbݚk7k*L* +Ye;I6>>Th#WEWPM|J݂.2'!{k`ƫXʠU`7ȫi-cgu=Vy%B0bD" P,@(ye&4zWebqVfQánӒ:+O# ғjWA"%gʨ8uKi釨:s7y%ׇ֯uU2I?/63WwY&:tܐG@zH% IqCN6_bAGK95`@ $Q+LUvnl_7ޢp&$a48kK(wW)+i&Iw.nݷ`oI̳5kM9ZY `KO//WSd|Trf%0NB9iȲj(k?9 ݧ$H neĢp0E ԩEtnw#wh%x]wE&03mȑUc c?y<}ut=?j!qωÖH({||vs) +0 {#UA?m_,Hk<2%eVR*wn#M8ߪ%T7 G{Ee*C*?vIjz{I34}3WB&, ȹ2Nj/GdZXmāLCnĬ<l)=FGm&OqyE1+ r;JZ%_D@;hv} tݚꦵ| 4cJ$;y:2PNO5=עzv>F7OqQZ05-~-FUZ9!Urmdm2Gn.dR 6yu6S)k[uoOK>fZWiv9vSƠ7|Mei6C*CrCuaRl}N'P~!Yq Ȳ $3!S @YuxoN7UO>ꎫ>b #SȖ|Wk˛jL"%_90朲.]ttN9h*xMd+?'z"0^C"Uv ]xfGLg2LLR9\G1ݞl-j[A?3͑ rN%[nM>Lόl{!H-OOC[ݛ{~p2wŬ1r2rwXYT_E^Sl}zcǪڪpDe[nn<\ .yx~04ci6_[]#T}Fڙϡc~FuJ>l\|tܕßn񔓢>Lc5gȞ>qI˷EvFrB69ᦼ:Ǣ:cRu3K³í⎶bTUy>&p+}z@ޅz'X+m6ٗ88{+vn Keu~qltaCZc }dcT 28aִ~lJ~taY8(9bYVnC7C`=)*HӰ_1MYU+ie\ਲnqf*أ;P $t,F୆Eu-@}F&f"0!F"gQv n>I6+ؤ_KGzpcLͱZ$Yddx^ wh'~q Iy ;Hˈy_kUd8cO7rQ&JYV]jTj.VY=/LmSJEo˒]{"p]#T"= E(n|Uqa5Rvf-dp-Ac+}*z̷a]J64XgMA{sh/!CxE+FEu\|̵\Y[ti˪ӵLf-ߢM5)LڜpulA%4T(j#j65_)~:^YͅS|'V!&E,L͛+w"66pN@>EGGOA IocfnKX?((Yֹzy_y)2+Z4]Zɐl~_-@:aUhaiAOU Isd÷W&0eۮjx]!Oʅ> xRYxHB U+,(ꑓrHR9j=ҭߣaM#!' &Q@;l VKSzfRrڈ xUQ ۆphݤ(>:^@㫥HBP²)-}GƑ-1R/I3(RVjPZNK; )ē%  Պ\w`d%:<04 IbŨSvA: (]i-܊RXYp]]hUSW3@QN\8BQHB(%ӧPgjUYBlKG~ڝ?)׆,OTf@:'db)]egZRuIV3%WTWEU䩑|Y]M33~|Loe#n,Q ) ѠEagpwnVEo[_kki*Q&C0@[պd`8(ַe66?r(Q;N̡TgBǰ f0BE@P)-!Fff]7eb6u`)&qfUN|ït,Pv BZ5EMx1dmP+o"u~/բ 2T 4ՔPFby<'[aZºrx#ak 5u~GvIYµx&dBaj*)VHVY ,h@>I{tG"=Y`W_Hu i#Qw*,Yx TH!ʆ te }r~täy1duT(Qx!8ہ:^c$5@@y^3 7}+^,QU%y0p=v2E9#F AY5"+/iuGVɰ a\A$_pwCwfFKY5U4uV-36:LN;Q]9غί6V}?rdbo 29RjuY?ZYO[0VWvZ XQ} ~`A'G?^az}0_{m`bzn1Ɔ=&VĂVvӢ0}Ԕpz$zEc$dPiV9 J{QMaf"5yi`O! KeZu}Bܠ撖C9~\:ޤZ @‚s_+ȕK2wj6/ /ds2׷ɊqZׂrܻ9ZW bj:>:dt盋$jDʰ Rd): t-8!SP|c md3#~u]+7TC>0vmd2HqeVoM5UjB.?*4oVǖn;yx&R%[onFN 0lŨ/Fi ;r^jg *ե &hާ5_g|n{2|*v6(\JYP;vR\yc!Jߴu }ڰf(.qJ;)eoh_ G-, q`JmZɠfh8Ν'W4πxݐ!n2^;Rܺ8~f'\tvD^ >6Thf;pOpVf,:n.:Tg؀RGf C3ϗP1d@қ$5b<]7"(MATe<7ovvt8-$FFX!?57:DYF}˵,'㹢 ,L{Dt2ԑTK韤̋L[7G4f=3/Ŗdu݈\бI0'aE&̴D s E(jbSȕ?CxBAuKcYв7K6+PLV>NfkU2ҏX̢;@TDȉӂ bmݷ Wc]rrl)X0:ѹ_B0#s6 tPyEgABEdUn?5_6LtS1U C/ΫB{)6=HbQb|;u 'R +boɏoOa?MtcX!\0%8Y !uzRlPTt/e*>,y幊 _VrnB{9!R TߓԱM.:bPxUPqϿ!^#$q% K>!=y_=O^~]B;v -$vFTհ޿6Aȟ'ZY4HbH Q:j Ci9Y¯<3!_eIϢ(':ՌtdJ= !6@5gktƏ^Eł'Rщ˨ " D IЗXw& yέ 쑧FP8,EG)9NJ4m+M|GgD9t&PhLIQg@⽕)FGW%;D&Rq[7TNcƶ"TF؞Q:t z,r @W xMAϿuqu,{LQo/h9#ًށя*R;}_8~,Z;"Qر:On>rbٕ.oR IZ*KUA{`H#` d YPdr'$pP#))ӣM-Un-_1/Gt[.*G8Z~|221ӡ'= L[i`_@p5E,C3m/QNOcL5)>Nur E`yz} d=^RP4lD-!\Ciϑ68ϭan}_=[vm3Y0Wntʾ>!QbC{{i(hej)@n5,b$]̨$F5u$  -]JwnيS0T&o=Oeͫ=2P L3*Ngv:mOu]s@˔nRl\"渒--=Sgznq] @ASN5j T9R< UHA3c +]6#JUR7RIwv6V]ݲqr-da:>.'%r|?kazަ f\kL}?hiyJ3e J<V~>;XpJj]31E<+Sb3-&W2P2kIwm*Sc42Z}`ͧS/7'q6-'34C<k(mA;&@JH Du< f$Ƕ`ighR<| (5rz^]'L;d&~6%˻r6iԆybc$3<3zz釮cm^۫WCҜİپ9:v c32KwK_Ҏjٲ둋]OqS˸NʭiY@SXR1e?`iymKm>~n[6k-O "x$Q.l֟- T[22fW:cy\.Iq $,SB=:\? xɝ24jzVEY2_@*jT+S-.Z6I+cljb *l6CDk@rCp(_ ^3( Vqg̟&n}@GG⤐e94^|:j:FBZYn0RF/UX8y-)U}CQdąyj:WYfP?LїOq|Y@% *T*:<{U?D1]{c7x"@$ )̤Vm>K /T6y\&>}"$"J)~<\$ @R&[ʟXpʘw..K*Tr{jYB?A;2 `&@Z kKqV6I,H#.@CF*iͭX45:u*PIZ_3F={k<չS85+U!EIkBmAfOVvY~̀@\Rh\b}"*hfoc@py(<Bzmx ]CE.> @r,L-gCٻ /P*u W?QÎDǂe5YbqFs|i^uCvز<I<'=OxUm"IgЎr8$x >q''< H'_؟~#<pP9A# 8?MV @:2*?U=qr֍#<.WUs-?O mny+j I6c+P(_%|mm)WPô>OK/9S-ΌRO s"YoKF7ōw׶Ne`~\zZ-WOC'VBW5Wt}GF|/Q4]):.fSbfc9ZDt_A3E^ DcI4m؟_e ;eK7Wl!2a8cc1\1HAKR$i1f Ɩ_޷ox7MYn BX+*; ZED۪ [\_*uQ9[*xA~ғ&`Y ˟ݧ}Ӕ?o;2#߲2f߀ܒų!]W\_/͙eQ+j1*h'h<>d- Zgj<]3Y*꼨 @MpHP0F`F!⎀ !jrhId#v(K3^y LϹ DPbF5l $ӟ hJR\wi֓WDs#,bO؅a aXaN9Q"Ė'EP2XI['+\Lm/ݼ`T,ARn }^H5[TeaV6FI3&O`бglaVfU_,dz( ZlTL~IH<nn~Ԓ|gl|nd`~t=7#Q16%uaM3"=v`I)O'-*~ %-9 ZZc/L(՝u mB?#XR}pmy5 ŶrTrJ_qB ێ(~VN6FBSՌ8YbnyUft^_?UuɆ$˚*lTE2/`ł̟ꔆ+X1vVWfA25=A?^Ǖ41OPa[l`J,iI=?F ?GyH8bT#SQ>i5(c铗C&iWA װeZ:rl9;_ME&u$MB1*!h:( Ve .7Pf0o~I8Nyor5ĝ(h=ff;<^@ C&wh!TqTX9a]&Əy}D,􂁑jޚaޛ2̽˟YM&i*xVv~Qg^AA8~&8- ZUi>;.|SQ_ҥ6e1.M*j=^Bʞ%o u$qy"UKmSަ>AK! {2 $E+<23Ro#@a:RbE!YZVSZo9h;O.O猈V (Y3D9=Yly# *NՌVC?0aJjq{]avQ*?y,bCv>j~hEm8Г<:d0gl#zP4ggRpu6X .dXRo\HVjfbC:v-Pb\%b 36>I2VUBgup덽G'D ά՞O..=(3NU'?Ztf}D\~-?n@yo{nz=a뵣*Εp\=(k+ʍGT</&t5kՍPoY 5ĘĪxeB^i>т[{M\ )5VpVEe/ rQWfe yDgU(GBJ:㎊ݓB^6_'PyfSh:M֪g W̳~Sكf0zBUr'rʥI¸- på΀eF1$cI,x6}U dX $2A 47eFj^Tq0n_/,mDs_ ~rydyYU/LpIMCt&0턒3M,%ֈ\'Ԁk@[bN624 T&\փ  *$iJ؁8(NB{bPdVfΘi[PF\Fv ;(ImZ +fa\15z?mWk}7M݃_ On&iV;BuL[K]H/kTMKUJwwƽ-,ik`bexCuz)>Kʳt=O6.I1rz]>%vh/Y&YǕeDϕǐٗH׷Nei>LSU2ccRj婦yrW])W\)U\:OpԱ{"(=S(A:#Gߙf@i1`(c@"$J=QFI]з 3 :ΚCM[ȕ&FΦ2&_3H}/Kvޞgbm0m:n5 _/XyT٣+;&1LLRW׼ް_X0Of`nͥVD|mH:ؔ+Oϱ/z~ܾ軛mͥm ׳ju;73@ײ2TDl:p$̪d͏ p)s]ey5eF!bژ[Cf"l/FRʐfԈ ^9M4lUj9aꧤ}vߟp^/sz\Fv֣Nr*660cj_&M'>sj͛Ӫq^.GkK& rV ZCo)yk^Pp{{5l#HM61h[/MO+? ۦ=;'5o2׵Z֮ 5i"ĚٝnҌȕFb.3U:{'+I'ۧWLɪh4L+3%1ƹ+2gZtċƏ9*YXTeT5 3 iIP+WvK &;FUr:cn9I#*𽪂*H38ϵ32e179<|WյX$ lZ +lٯlZdbKx-KRs5vd n>K[=@"x)* ƓmBKEc0ucQ=Y>?ĂbVo4E hb]XᵿJP;R@A|o+8D*J|O˃ā«Y]P?-@?poO YY\dwuE:2KdV؊ u 6T٬+Fd2ȼBiECg%juaeܷn/]M%mVNldRT5YgPR(uc֐kD4iP"r`_EFnU9o{f&tʪX*H1G(9,rJDnY(=:^[>H[ qٌ,O$EbR BC@jH7Dl?hDN93POhJͼ}zsR&wJ%l1JVyٔ0YvzK]2R(`H)IOl8po,jUׅ0aLWETjr$xGǕ,J(~RN`0CaJ=mfω6t*M)Vbת|<$ u :r](ݨM˂*N,9bΊ:JP>E==c2:-YZ]_V3vv/; $q>U~,I2 VUu=Vvբ ;IHV2&;p@14 EYF%(* U۟"\VǛAF!:(U=ZFso'pXS".6>@W*=BCRTܳ&Kj3+Lł% S/P|3*_%SJmD  uH|\2ٽ$) RMu7dR@ƴs !Ve h|px^HZ}VaY*.JHMpgvq$RIcDB/>bB$RՇ }r;rn:c0HJ+E}*N&^ :tʊ~1NFq(&yb}=/7D»LTI*83VğR䗧e<+: ( \ uXQTj ,Hhfgm]OmU~9kRF lz?g),};pX{!X9= Xح8C2B;9FG$AQߗR 3/V "{avzދ@yU8V?i !(μ|iqT4@,4KJ ^AMUVs6 Er'&PB/`9/StUNѹg@I0v /fy3D!;:. }XV8#}ͿWܔ,A ց? *\YH)6MsȲ. v#OŸ@;cS:臐Yxeo?zO>.7mAS(k.P4lmo5N^BJڊÁJ)J$Hfc#oR;П?O=Q!2[og{kT:C8)&>k͙wW^.JtdC;Q:dI25A vP?.g}Ôk7\Uf`I #݅cmTJtD=u6?HŲZ 8/ռP "z-6@z\/iZ BYnmev̥GTIR:U]\tn#ܞx܂X0Q8X r- _,Ct*7RH'beLEZ׏]O&8bv9y$FwwŜj /l|@ |>TDlxagI^[zܿ_n0 $(Y23GTP'RGY9 13VXȆTꝐ0b$̿,RgR2<]U$Q 6bz }e}Hp 9wf>Zǚ ʾìԀdgޥP*ad5V ߬nQz2gY_@czTl-,xww d N\lܕoP;fRfyQ UO֠vNn*"t-j GV\!%.0fs&D%f٤ĩUŐEhn,FI$2HB~$ QS{\Xt=/F{ef9ӇjnP_3xN jY,|LHʶGqjL`{mkqzFL?KjneVgV((HC+4aƎLq;IR;RZ`-e'&L$ 2nڀ P94 _kܨ`ʘFlB~b҃,Wl7N#chZ~FvYBJ+c?ijդh*a&BmoM7+OLL4#]Uȹo0pn CUtvL_"~=3'<Q\"O+Q).\S2 ~Cn-AURыU4QF$56傃͂jX`DP mvbSU٘p56؉w:jXVX\"2i O+ɚE T,>.QgsPfA-*lo\X/){;V\ kfLSIbd,y]Y2Y*.gfV=*I|.{)AvdbNŤj-ڨ4Y[2:o:)k[ZBr)2_qb2:&SK'U .JK^<,yHBǩ+Ev5\ Y4xXɞBLmZY5U;sR}[ӕ.]>nj\Hvhic䎁CXүrn#:]M(ɯ04cE9RZY0F>Yأ2{>+4CKFF-kֶ+Jw+FNDe X#QdMw: 2%5|\*iƹy&fGOi"y9\}oJdZ[i ~|6o$]8JюMئZ]3O(uTudӴ]㑪!j&1Y_m"zCKtg6ָИPS6cXBT]eYp ܍l'*M!3EV I ګh-Jpg;P @Xy[`jY15ZdcW[li[jܚ}wWl&Vܻgm]-FjtO>eg*NkQB9J4ṫ(20j]tooU~V&Vݚֵ5zQ2vǙ.'+rIU_?K8c)3VJ&Y_ڙ4W?cPZBE`c!H " drrH`~IRZȢu2rY%2VFHWx5ZvЃ† QPTVd-6'%동ᜇƥj2D̅$ىI 1{LD , I.̻0$)!UA88.uJyl(I3k+xpiF iZtugΠJa@(;N&n6M;*yf`YŽYjLt`X0Bf̎ĀYߐ T 'b:]vUylHj+ 'vjQZG(i@p& bj{rYIN<_nxՐ3H2I! adž\"Xxgwy$T吭:9&8<\L&d[h^ `7* 4)oo"[RƫE ,t%`&ʼDžN Y ") 8ZaXfVoBGWTW/*thdTn3Oe?)ފ(jݑO)՞]Q(RWWVt7)z=;nWBڂI?$؀j$$ ]I5#OTnLN줸gT_.&أv>NI!af1g$fqbА\p*Ȥզٓ *UvcÂ3uۯ#`۞/AK/΂RA?JulX6ňZ" $Q{y6ҥoTʳPSϿ!^YʩVW3BA{}>pe"ȫfDuP܂]( w/XQ]?Ye_!c@[3}ؖӲ͚&?RhPː@rawl(qbfp|WG*1:HgS־JrfPj7#J\v4XtRtEv [}DtFd$ޭa߫)Twi}cb35f* RMβ)Nfb5ug)T l&NʁfRYCuX/˫GV@E@ů> ۱cf17u,T>&LKlxX%K)&Ȯ!nkb&@G P;Y=̓y ۏ0si+(jDJ򈬈*Ψ0C>LJc_sX9e,|US kJtG+ Ȋ+IR\ƴ+Ѭ]IՕE rI*!䓹t)g˟Q N#犿>=A1t3ҌZ YZw||}J0 !Enႉ|K|zU9$i$к)<1GW+KPI֤rq?{`bt^$xѴIb@:A;yr,]Tt5"tD%A`UxR;|#=nJ:{\#("ڭ#+@9zy,~wk;㉑EpJ;1*OWPaff~1 f<]gߍ-ۉӣzQ"Kzlpdv^A퐿6!w4h =,7P8eb7dԄC:MARl%DVDdLܩN;K9w?:zDhqƒ< Y@7(oұi6'*BUc9N ٔ_'bb'Ѳ䊴F΂oGi)0@̬QcPm@H(5jj`+^_U,ˌnh]j%AZ;x3);$>&fn P)ڟ%t|Fǚ]âA䋎ΈHI:F=FO9t"pA\(}Yυ& +Gѩd߯V(֪tip2{Nj$fL`ŵA*ūZK_ 5.UZ:Un"kZ}yN[v)4EyLv ܰќ-NĎ@*|&\rkQliBʎ`R42IDW?U;+LËeL;"*IN\Unxf'}m Owi3 aufJ%أ$oqc.EVRf6J"zEE|n!YNJȍUP+Ml~I͎5POS`Xӯuu # OC=s jR=R l X׺L3+u+K/mtE'ȃ*I`T/GC فFC gTjM ǓvVFTE J_Vv 0!fL\+幟 !sN)0U1 Q *OP5 %nHG4=%WT@ ((^(XYEkZP*&UtYzm4?rGͅk_ rRŽ!ԎN{7ʼn&LY҃'P6;c$/W԰1뺻JY(F\\,4&ć'NXvj͆$*IY|`7EBuO ELJƞ25m_ $#PH[ rΝ_YZǥ'YƚFOE23ꫝ-HБ:SoڑtlÏ{|qi X%ld}7l) dˠPX_vuݛo ڂ1'HEt`Bق he7+ Jr GPnM⾷sl#鎡1¦;x폋kxmֳYyyQ)d$~q}o#}7Fӥo|Iݵ-MLom13a:hK,3t/TRY^*ֵ&Yw,X c6=%"69UdfǤZ~8Y8'Pib4W47meuevyNu8g h,(| 7òA"}_VDž n3>4f)NaF bтr G-ٍ{nͣkzE-@`>8M62r6Җ/d`bR(՝eL]7~;n-ێU9~s' $Li\qzFCzNN9ۘ=@cU&da`[6kS 8O)|c4my3{֖ &((yz /fyfDΤd8;CP Pn#f\QGDѺqƞc#R[~(*le$wH̓\0iu%A̛go|x-DIIm9!85PPԣ,bĺccBXS YO"glp;jEVC%+p}"fn"ƩɢڌFF>-ݤqhK&=f`Z mkf?s+_ $wG) p=͛XjGCfدmٴ%6u %xGS+RT"*Ȧ06w%n}+udZM +VNCjdYGyh)rⰕZE ͫ$BKp}yej͞IrfO:dX$`Dc͐1|o +-~lvDGx&$P~'Z%9Wg./C"mCDS0@p'Zgy1B4MF [UM4(1E8z[ PnP*۩^*{ rP9 GW̡ p8Z{{b^T?5H/՝$ŠAnM{KT$q\6HQ&Z@)p!@)#Zp\a՘:L?'>VfQ/óʈFN3SC|݇v@SAea>bSêoTӆe94 %3-7务>d0$q@Fܐ WMMP)OQ$|C#.!Ihybe<j eARAK)8!%_:y _gr=~BuyMFz`IR1mT iZ54Mͧ#`D{~ \ !P/nTrɵnVY7d^pqrVidWܙ f:0GԱD5Tc@92<9f=GnW ŸnX 6౺ 8 z=Z9#T@aalYmtj? sffbQ ~nGy1fLݹF#H$v)SYlz%J4O_Þ>*,8rGŇ\*nF@Zl(klőh;r&,+/)c[E SǸU<HUV`PuO+QW|i8ϒxӳgp2zj&u2,ős=AfDRV0-XŋQؕմ;cLљӥ8XPd  uH kC"XͭwIi7u,݈pg&p(^ Xy o\V-.ʠ#bġE oMǨ.n]kQ9JYB p7_}ԳERݲOfɓ[i r4d,6bilDBi[{}NY5"B:?Uf(nTs۞DM!Ȑ 6bbvXZD4yß11q WXZ1سc/nMN`|YVIQ;sܣ8fuDE[]y~8t(;.z͏A ~^' dZGmzS_5zfS@ 'yg~i˞Ēl'QT2͉H[&cgrAP11zs{ݿQ(gŊM@u\xGǂmNV-(~~NNg.C췢Cn,,re6$/4FjѾFlBێ9P?TÓfS4mEYv+ɯ9 H}R(%Oq.gN, _5Ǯ,CH iE RΉب`[~d0\l"XQxzfJ~}E[rRFơ>z64ucVb @orNkhRձr)$ʀ\}(E4 ї 2 nA)TyC` $Q&Ҩ$|Q5́da :RI mfARoWUft̞UsќGUybHNO3>cF>: pP-{"wlSv>?H]U4UDxKgtbInp͟_~Kujx!cLjJ(1չFjObE5:9" ]ħ <_q՛K<}GZ59WCZƐ`=չvV('j/s\BR.Ke ݼihRdUY^JԩaU$>5Qzg "Nĸ*fKlQg^ eY|œ[ ='9p]'5ȌqL| n {׏Rva M>)hO\F̊,iEF=fFy]H,@eU@Pj`_PK:|CZQQ`_4 ndk>h`łڹʛUaK6+GUHr;kzjq8 Z|iyhQ:|jhi(2E)]-o08g>nJ=dN ^̳62\Iq%8M 4N9rŎ(Y1e+uwSfO&.^gE`q3̢e%ȷN#uUՒRRWH,*ٙc=d՚5x ]& lީ;ozնfT-,\H#Mn# _ojXJ?VyLRz4)9K#(IV?!m6W{nax_1ȗLr&d1{%||"qquW\uB+%dP ENl,:/q籑*%p*ִ|Q lفY3"~4D]??L<8*VGUbt0 ld;U?CowQ2`dאlp[fRZIa&9`Uq׫(p:1):wrԅK(U!XX:UijD`Rgx_bʓTbTr? R):MJ@@r~=y*\יjpu?'kIoRjMpZ MX*e3UR؅,0$"*̋`ajsE+:ܽ?JߏʺbjEGO0 ??ʼO3+ ě1fB㲠>οչWPUjm7R5$-V`yV4ej(!YOnWy$UêӠWU{iF H‚T2ەԓJE-ߠX4ߒL 2~zJE^]ѐ1#%YPaאIqd O#Z,pA+Lo'Կ(b6r:&VMz]0j]I^U0O"( 2ܱf埂 {[%n>Djx]R*5.l_>aBX#Z< 4lioiJ>pP9 @^[dR }KP ;_])IVs"4*;N苃ciӭ/qvvr@aV n? YD!hmdEk~~8Dŀ#FBHU\ğ?ZL}?ԯJw$[V( aVbC#Cu3RHeHۣpEn(ny/7GF\L)i{x;Jh(;jS\}Kؕ$g~|#waѩ*+n6 ږt~G$Xп]H]=k41f * o6xum%e3i_=,օ(ǯ?e pթIT^)PB?j׉&|7#P` ZYEH۫j%0ddzԩb#J$<9, ZSdJ~[+JgR*; DyQoNfٙƤTK"kѦ)`ޢSDz(Q-=Zmݮ (-2 4<Av!D}6{Wݾ'fl|t!/vI ӺbI̬Hxhkdq2iYS!ݑ.H|uvdF?jV\8R,i'q\X*,L`ٻ~G4d7EhO+Evp\ ?evZe\4rDTyNC&̢&WOѷuf>[NdJL݉T e3&,Wo`&ha%m8fIv LU } z>fr ;v(:q'`Q(QEB{JD~R/(<,WKXଢ଼ B|w$N=%,qZԡ˓F+( Z(t?:U:1/Zɀέmg˜E7z5ʪQLl5vjCΣ%0ݥԟ$.ܻ%_OJd-rBhjw$ ;HMhc%vP)pG5gR~O߈iMXR 7ܢW,\lL\_2CѓI f]TOhnsBۚjȢsLrV̌gڨ|2P,Lh`VT+4R_")E 1/U=&fz{1n4Zv2k2֬IiZIѩ֧“vf6 S Uli y_&^T/6! *¾~b;xHdlPn3KzƑH_w*$)`x{..6O|vz/hp*pI ڈzp vzem,p mJ.Xy,><, sؿ7ލOkj?_ υ,cUv!r2ZxUKl LxVUї3ۦpw*MG.4\IS(_bƂ} 쬀<5<*:2]f|\S=WI)ßrU$R}I1bEEf4(xU=#KЀ$>%V)oWXTQb܀;)z힨oLs+"$iխY 8) D|>W9I)=Ln}iAMG+pƘzUjuO8 kdE9?P7({nYXu=<Ԓ;r˗\٘{9tB|ڊ̮wK Z~ GYb}M2Q^ĒIR¬RpMڸ*3 Yg}C?pڍ;K<XUd2 hV]͞V󮵏L-lX1F\A'&LGo&Hz~JKq/x;)fgR_n䀳BցTAg[z>Wc"!UrLRV9 AtbX:˝VFE"ɚ#JݜVD1pҰ-e2Y9?AȺ[’__ &Iő0E1yږ-. +|,ly˴GS1~䢰QjB'#&=$Ku gbVoJ4K c&eKmNrɦ4l LULlsU}8v W28wT)յ⑙y*HMo7]OOVUv&|]e'(>.EiƧe!DdmЏ,WsrqbLjmM9tղYſv bdN#)5f2vَŬ$1 lhXrV"DR4_''gstT';j.K&6FS;<S*. QӚb랲z4cْޫkS!4N4J/g n6}Y]u<-3.FZkxL:~lӂtRRlʹSNe+1vnn]\}>Qe#gʪHQ&E'2!Kj6݇ɧa2팘-[o덠k*ŧ4m|5-FU4Qk"H>\NwāYMzq^pyIʀ34DEb Q=ȿΑ4S7>FC; z񣕷u5`\dџ>Jx0n)zA=eܛ Uܾzm=bF>zڞ{l)cxk|VV=GHqzw2s6ƶ\麞4\;#Iyw&㺵JTʆת-L|J/Gͼ|iN%1פ6KC<ƎDBoߺngdԤ0vr)V"'6GG_4ߤjI6z{ ~V\\\<|kQ|14"fhg:S+"_T: eO~!,K7*3U8]F) ]cY! SD6 4rM`{9@HY^6dc6ijчyX*M.̑*!(zM^PP|3y;+2R2rQ6~~zf$q|%;6i*<6G^TnDǷJqTIjV"sA w6ݙ2Ë.!BÃvB T;xؐ$9dP*3B۱FA Eo6V5Vy6it|EB$^;ܔp4i%4ynʄęiePArtLsSx%['?NlyAmDQ<0gA:{^4TAsC6 P̯*$ 9~dK+䙺f>`̨ 3nH@o"b ARȺ,6Y#lH VV/y5fk:2t'U+JF(Qu4YƝly9.r0y%UnU4h\JpSZVT)D!r@* VYXB J{IDKnvn0Rj* SQiv G$ܕ[1ƦMJ`PR:E%4gyʏzZ<<۫!JnN>ĬlCӘVb'?!>N[4_/*ch%кwbë|#՝瓎O2B7 'M p,I0`:dZP tA-$5ýD[5{$)l[Rq#CǢRN[  [3W"epΫ>Rʤ"1yZ  Vl`t,yu%gU"x*V?* nW+UAD+rT(V a$ \* IVB"6[ؚAGX.Vn|h> @@iˬպ*p IB'^vN;@A{jv#^LJYɢxf#?,P炎DzNUPK=G_d+O#rJ0*t^REA)RVS;3>+'Bx0=ӭá~*8EO+ۯR(Ebr6^y<c`u+0f`~he6u8\P}r~ Nկv#CF=$*:ԐԐ؟p*Y8'ʣIP>@`Hj*ۖa@ c[ ȌG?د$nR<9f egœuxXQzx8>I>w> hؚ *$L úUB~7=۱Ꝋ#oL3 :frkRNdDM+ ~`2 !rIaبfH8< -N,hO^m[K{^B2=*H P\u~_}[pTk gH~aޜY!0)?Yƣ:$2MzifBIɅErqj t3,rG&j !G8ӤD4^yJh \dy;c e־iZ/,l̚a_U Ү;{~F ګHH&M[+/d ٟiM:RЇZBiќdy $f3u_`D-v<+/ɑ+jAn>ek`(g*2VHC!Z?=KLY؄ Wɧu{]_["J][.)A3-Ufb&PaXA]Y^4 ?ivSP.Q 7r(/C_Wgt uݴ;)^c ߹Fo`oQ4=v$h^؉Lp܀Fo+V$&{+2V YRHFEϲ~+G!s* hJ\ϕVnpQQ-3" ֶRM III]C*#&# (>ջmLiȐ*%γ=~\<8oݯhy:E=lgR==CQfȄ}ؙYMFX:Uwu/ucUcҴS8.I3G 8b=zF%yhϖ|1bv.mWS?#cD,Ě|ΑqбDjRĀJYbu+ڞ&!GԵ1X4a&̓ |Z򭓏,l! [M֓) -Ry &t)k?Rdy2y^f>4z1fJ+=89wvVSh3Պ(<8\edT~Ci݃P7 B9G,@BS0(VaVU#PPu-[eZRvDLK[಩i='d/ Ӂ[28u]Ct~&,Gd*>HCҳuLjUOpodofo-0.9.3/test/CreationTest/resources/Illust.pdf0000664000175000017500000063660610714372313022247 0ustar dominikdominik%PDF-1.4 % 1 0 obj <> endobj 34 0 obj <>stream application/pdf Illust Adobe Illustrator CS3 2007-09-05T11:52:56+02:00 2007-09-05T11:52:56+02:00 2007-09-05T11:52:56+02:00 200 256 JPEG /9j/4AAQSkZJRgABAgEASABIAAD/7QAsUGhvdG9zaG9wIDMuMAA4QklNA+0AAAAAABAASAAAAAEA AQBIAAAAAQAB/+4ADkFkb2JlAGTAAAAAAf/bAIQABgQEBAUEBgUFBgkGBQYJCwgGBggLDAoKCwoK DBAMDAwMDAwQDA4PEA8ODBMTFBQTExwbGxscHx8fHx8fHx8fHwEHBwcNDA0YEBAYGhURFRofHx8f Hx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8f/8AAEQgBAADIAwER AAIRAQMRAf/EAaIAAAAHAQEBAQEAAAAAAAAAAAQFAwIGAQAHCAkKCwEAAgIDAQEBAQEAAAAAAAAA AQACAwQFBgcICQoLEAACAQMDAgQCBgcDBAIGAnMBAgMRBAAFIRIxQVEGE2EicYEUMpGhBxWxQiPB UtHhMxZi8CRygvElQzRTkqKyY3PCNUQnk6OzNhdUZHTD0uIIJoMJChgZhJRFRqS0VtNVKBry4/PE 1OT0ZXWFlaW1xdXl9WZ2hpamtsbW5vY3R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo+Ck5SVlpeYmZ qbnJ2en5KjpKWmp6ipqqusra6voRAAICAQIDBQUEBQYECAMDbQEAAhEDBCESMUEFURNhIgZxgZEy obHwFMHR4SNCFVJicvEzJDRDghaSUyWiY7LCB3PSNeJEgxdUkwgJChgZJjZFGidkdFU38qOzwygp 0+PzhJSktMTU5PRldYWVpbXF1eX1RlZmdoaWprbG1ub2R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo +DlJWWl5iZmpucnZ6fkqOkpaanqKmqq6ytrq+v/aAAwDAQACEQMRAD8A9U4q7FXYq7FXYq7FXYq7 FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7F XYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FX Yq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXY q7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq 7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7 FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7F XYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FX Yq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXY q7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq 7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7 FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7F XYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FX Yq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXY q7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq 7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7 FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7F XYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FX Yq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXY q7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXkv/OT+oX9h+VstxY3 MtpP9dtl9aB2jehLVHJSDhCvj7/GfnD/AKvuof8ASVP/AM14Uu/xn5w/6vuof9JU/wDzXirv8Z+c P+r7qH/SVP8A814q+pP+cSNW1TUvKetyajeT3kiX6qj3EjylR6KmgLk0wFD1Hzh5V1rWpbW40jXp 9EubVJUBjEskMnqsn97Cs0KPREdQT8S8uSlWAOBWPXv5befJbLSIrTz7dWl5pcTRvei3klM5ITgZ YnuTFJxKb+ssjMCfirviqqfIX5kzPaSXn5gSytbXUV06xafHbJIqGUPEywzKSjJIgCuWWqcirE7K ss8sabr2naWLfXNYOuah6ju199XitBwY1RBFFVQEG1aknFU2xV2KuxV2KuxV2KuxV2KuxV2KuxV2 KuxV2KuxV2KvHf8AnK3/AMlNL/zHW362whXxdhS7FXYq+sv+cOP+UP17/toL/wAmFwFBfQOBXYq7 FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq82/5yC8oeYvNn5eSaR5ftPruoNdwSiD1 IovgQnkeUzRrtXxxCvmL/oWv86/+pc/6fbD/AKr4bS7/AKFr/Ov/AKlz/p9sP+q+Nq7/AKFr/Ov/ AKlz/p9sP+q+Nq+hf+cavIPm3yZ5b1az8y2H1C5urxZoI/Vhm5IIlWtYXkA3HfEoew4FdirsVdir sVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirs VdirsVdirsVdirsVdirsVdirsVdirBLv86/IlhPFZ6pPPp+p3EssNrp0sDyTymKeS2qv1f1owryw sF5OPemKpiv5oeRyvNtSVF4hwSjk8Wthd1IUMV/dN+1TeoG+Ksmt7iK5t4riFuUMyLJG1CKqwqDQ 0I2PfFVTFXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FVO5tra6t5La5 iSe3mUpNDIodHRhRlZWqCCOoOKr0RERURQqKAFUCgAHQAYq3irsVdirsVdirsVdirsVdirsVdirs VdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsV dirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVd irsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdir/9k= uuid:CBF2C183945BDC1192F7ABDCFD1A3597 uuid:875c03d0-1825-4840-951a-7b833c396f5e uuid:CAF2C183945BDC1192F7ABDCFD1A3597 uuid:C8F2C183945BDC1192F7ABDCFD1A3597 EmbedByReference T:\d904\d4\TEST1.PDF Print 1 False False 110.000004 100.000001 Millimeters Times-Roman Times Roman Type 1 002.000 False TIR_____.PFB; TIR_____.PFM PBAAAA+Courier PBAAAA+Courier Unknown Version 2.007;PS 002.000;Core 1.0.38;makeotf.lib1.7.9032 False MyriadPro-Regular.otf Cyan Magenta Yellow Black Standard-Farbfeldgruppe 0 Weiß CMYK PROCESS 0.000000 0.000000 0.000000 0.000000 Schwarz CMYK PROCESS 0.000000 0.000000 0.000000 100.000000 CMYK Rot CMYK PROCESS 0.000000 100.000000 100.000000 0.000000 CMYK Gelb CMYK PROCESS 0.000000 0.000000 100.000000 0.000000 CMYK Grün CMYK PROCESS 100.000000 0.000000 100.000000 0.000000 CMYK Cyan CMYK PROCESS 100.000000 0.000000 0.000000 0.000000 CMYK Blau CMYK PROCESS 100.000000 100.000000 0.000000 0.000000 CMYK Magenta CMYK PROCESS 0.000000 100.000000 0.000000 0.000000 C=15 M=100 Y=90 K=10 CMYK PROCESS 14.999998 100.000000 90.000004 10.000002 C=0 M=90 Y=85 K=0 CMYK PROCESS 0.000000 90.000004 84.999996 0.000000 C=0 M=80 Y=95 K=0 CMYK PROCESS 0.000000 80.000001 94.999999 0.000000 C=0 M=50 Y=100 K=0 CMYK PROCESS 0.000000 50.000000 100.000000 0.000000 C=0 M=35 Y=85 K=0 CMYK PROCESS 0.000000 35.000002 84.999996 0.000000 C=5 M=0 Y=90 K=0 CMYK PROCESS 5.000001 0.000000 90.000004 0.000000 C=20 M=0 Y=100 K=0 CMYK PROCESS 19.999999 0.000000 100.000000 0.000000 C=50 M=0 Y=100 K=0 CMYK PROCESS 50.000000 0.000000 100.000000 0.000000 C=75 M=0 Y=100 K=0 CMYK PROCESS 75.000000 0.000000 100.000000 0.000000 C=85 M=10 Y=100 K=10 CMYK PROCESS 84.999996 10.000002 100.000000 10.000002 C=90 M=30 Y=95 K=30 CMYK PROCESS 90.000004 30.000001 94.999999 30.000001 C=75 M=0 Y=75 K=0 CMYK PROCESS 75.000000 0.000000 75.000000 0.000000 C=80 M=10 Y=45 K=0 CMYK PROCESS 80.000001 10.000002 44.999999 0.000000 C=70 M=15 Y=0 K=0 CMYK PROCESS 69.999999 14.999998 0.000000 0.000000 C=85 M=50 Y=0 K=0 CMYK PROCESS 84.999996 50.000000 0.000000 0.000000 C=100 M=95 Y=5 K=0 CMYK PROCESS 100.000000 94.999999 5.000001 0.000000 C=100 M=100 Y=25 K=25 CMYK PROCESS 100.000000 100.000000 25.000000 25.000000 C=75 M=100 Y=0 K=0 CMYK PROCESS 75.000000 100.000000 0.000000 0.000000 C=50 M=100 Y=0 K=0 CMYK PROCESS 50.000000 100.000000 0.000000 0.000000 C=35 M=100 Y=35 K=10 CMYK PROCESS 35.000002 100.000000 35.000002 10.000002 C=10 M=100 Y=50 K=0 CMYK PROCESS 10.000002 100.000000 50.000000 0.000000 C=0 M=95 Y=20 K=0 CMYK PROCESS 0.000000 94.999999 19.999999 0.000000 C=25 M=25 Y=40 K=0 CMYK PROCESS 25.000000 25.000000 39.999998 0.000000 C=40 M=45 Y=50 K=5 CMYK PROCESS 39.999998 44.999999 50.000000 5.000001 C=50 M=50 Y=60 K=25 CMYK PROCESS 50.000000 50.000000 60.000002 25.000000 C=55 M=60 Y=65 K=40 CMYK PROCESS 55.000001 60.000002 64.999998 39.999998 C=25 M=40 Y=65 K=0 CMYK PROCESS 25.000000 39.999998 64.999998 0.000000 C=30 M=50 Y=75 K=10 CMYK PROCESS 30.000001 50.000000 75.000000 10.000002 C=35 M=60 Y=80 K=25 CMYK PROCESS 35.000002 60.000002 80.000001 25.000000 C=40 M=65 Y=90 K=35 CMYK PROCESS 39.999998 64.999998 90.000004 35.000002 C=40 M=70 Y=100 K=50 CMYK PROCESS 39.999998 69.999999 100.000000 50.000000 C=50 M=70 Y=80 K=70 CMYK PROCESS 50.000000 69.999999 80.000001 69.999999 Druckfarben 1 C=0 M=30 Y=70 K=0 CMYK PROCESS 0.000000 30.000001 69.999999 0.000000 C=5 M=70 Y=90 K=0 CMYK PROCESS 5.000001 69.999999 90.000004 0.000000 C=5 M=90 Y=75 K=0 CMYK PROCESS 5.000001 90.000004 75.000000 0.000000 C=30 M=0 Y=95 K=0 CMYK PROCESS 30.000001 0.000000 94.999999 0.000000 C=60 M=5 Y=95 K=0 CMYK PROCESS 60.000002 5.000001 94.999999 0.000000 C=30 M=0 Y=10 K=0 CMYK PROCESS 30.000001 0.000000 10.000002 0.000000 C=60 M=10 Y=5 K=0 CMYK PROCESS 60.000002 10.000002 5.000001 0.000000 C=80 M=5 Y=10 K=0 CMYK PROCESS 80.000001 5.000001 10.000002 0.000000 Graustufen 1 K=100 GRAY PROCESS 255 K=90 GRAY PROCESS 229 K=80 GRAY PROCESS 203 K=70 GRAY PROCESS 178 K=60 GRAY PROCESS 152 K=50 GRAY PROCESS 127 K=40 GRAY PROCESS 101 K=30 GRAY PROCESS 76 K=20 GRAY PROCESS 50 K=10 GRAY PROCESS 25 K=5 GRAY PROCESS 12 Adobe PDF library 8.00 endstream endobj 2 0 obj <> endobj 5 0 obj <>/ArtBox[0.0 37.5566 311.811 283.465]/MediaBox[0.0 0.0 311.811 283.465]/Thumb 33 0 R/TrimBox[0.0 0.0 311.811 283.465]/Resources<>/ProcSet[/PDF/Text]/Properties<>>>/ExtGState<>>>/Type/Page/LastModified(D:20070905115214+02'00')>> endobj 27 0 obj <>stream H\MK@ {~{lN3׮C]uŶ{g*."!iw_È_+tgkB )"Ԝ('1l=$j:bŷc=P~ G5I I!&CFJwU[U s1n~tID5-;מLmGQC Za:=bl[B endstream endobj 33 0 obj <>stream 8;Xp,Sc4.*)[TicNm'rog=k71E(m?92ulcQ)ic@)9*NFKPa\G.j>%(e)X;hR$jPE# UL4eo#64c/!.r#_l2~> endstream endobj 20 0 obj <> endobj 23 0 obj <> endobj 25 0 obj <> endobj 26 0 obj <> endobj 30 0 obj <>stream H4mLSgǟr{ [ZMz޻`+"4\`.BEq-mĠC(e)qEctK2e%3J\0 DGl, gb[H}F%&r%E )xk4ٱQ&;1ˀ: 9n (dx βCp!24|uE$x%gYO]5 c:+Sߦ>r( Aw spDMް'hoWg켕$4V7|'r/#'>1N?gcI*6P5?rk ~Xl \oz D^K0WvIƸA0[zn;wHAӉ{#tIZQc WJ$x#@S` %Yg`02 endstream endobj 24 0 obj <> endobj 29 0 obj <>stream HkPww 2]][ jLg0U嵔Hh^Iy (DAU"BKEұiuCÙsEE􃇒6r"urQCK'aq͔ghp/^ŧ$z-o_.QP8?- Dq?rb$5)P%2&3 +=KpJ MUm,(WҾQڎ}=Q(_m|'M};g -Awg黳)@@Ksu Kc]>Ք5pu9+;JUۅp!am76i%:3+[7s? n$xS X-Su3rSFBJd<:!t(ZncU=,֊='j[H[Heky4Mang8tYIc ~tfV4: jWRi:Rn[pB~7#]TyB'ӭ?`Ll#o y^1&9`69G?aD)6cSgxc'* /)UQaY!`} Xjnpu##(nmp}x Ba(3@#n+)_>KZ[F62&nJ69 ("lٰ7fM+ ;^' endstream endobj 31 0 obj [/Indexed/DeviceRGB 255 32 0 R] endobj 32 0 obj <>stream 8;X]O>EqN@%''O_@%e@?J;%+8(9e>X=MR6S?i^YgA3=].HDXF.R$lIL@"pJ+EP(%0 b]6ajmNZn*!='OQZeQ^Y*,=]?C.B+\Ulg9dhD*"iC[;*=3`oP1[!S^)?1)IZ4dup` E1r!/,*0[*9.aFIR2&b-C#soRZ7Dl%MLY\.?d>Mn 6%Q2oYfNRF$$+ON<+]RUJmC0InDZ4OTs0S!saG>GGKUlQ*Q?45:CI&4J'_2j$XKrcYp0n+Xl_nU*O( l[$6Nn+Z_Nq0]s7hs]`XX1nZ8&94a\~> endstream endobj 6 0 obj <> endobj 7 0 obj <> endobj 8 0 obj <>stream %!PS-Adobe-3.0 %%Creator: Adobe Illustrator(R) 13.0 %%AI8_CreatorVersion: 13.0.0 %%For: (rmi) () %%Title: (Illust.ai) %%CreationDate: 9/5/2007 11:51 AM %%BoundingBox: -70 37 543 830 %%HiResBoundingBox: -69.7129 37.5566 542.2871 829.5562 %%DocumentProcessColors: Cyan Magenta Yellow Black %%DocumentFiles:T:\d904\d4\TEST1.PDF %AI5_FileFormat 9.0 %AI12_BuildNumber: 409 %AI3_ColorUsage: Color %AI7_ImageSettings: 0 %%CMYKProcessColor: 1 1 1 1 ([Passermarken]) %AI3_TemplateBox: 156.5 140.9648 156.5 140.9648 %AI3_TileBox: -141.6948 -279.1377 453.3252 562.7227 %AI3_DocumentPreview: None %AI5_ArtSize: 311.811 283.4646 %AI5_RulerUnits: 1 %AI9_ColorModel: 2 %AI5_ArtFlags: 0 0 0 1 0 0 1 0 0 %AI5_TargetResolution: 800 %AI5_NumLayers: 1 %AI9_OpenToView: -49 283.4648 3.17 1321 917 18 0 0 44 93 0 0 1 1 1 0 1 %AI5_OpenViewLayers: 7 %%PageOrigin:0 0 %AI7_GridSettings: 72 8 72 8 1 0 0.8 0.8 0.8 0.9 0.9 0.9 %AI9_Flatten: 1 %AI12_CMSettings: 00.MS %%EndComments endstream endobj 18 0 obj <>stream HWV}?clM B{R$(IR߳a?@AGHVۜ5WnU$v " dYm q-dTTb ){/13I>zH]Tk+ ?cXG}c҉De;}`d/,z}X%xzQꮭk:~%5\ ]e[W U)#f5ٵa*J\ŊE O-@gl]j!622_zƳa!E(U)T MP36hq[,ldž{E8Tg_b:dP:lT¿F t|2s{:Sgj_\N+1%-Pb66-pJq玺roωD/or"l ԕ`68Xe;7gB5ΩaSYU#:] '# 7.%SKX뜀uzF!:8tDŮH-v95TvŊ sATDgc[4KSaeC. >R.)tf[mU.!CljB&.g6 fl!9>A!w@].wUf٦:n"'tCr}`߀6`$1Ǵʮ^q̚8^̖3у:SK@h9U>Զy"b@,8fmZ']]L/*,.~3Ej<^)]KKW +gҥͬ4e:`DAxY3aAŎ#0 CʼL;%~.50iOA~b~|w&p)էAecv ːna}ž5;ڿjp`]:NuxZ5+./.#ZN=4Ti?"L&Ѕ!AFauTc!]Fl]3;n{F3#ұ3$ٚLDm#~ VkԿ (1sjONwkaK&e>kxt;H֮bၘl6tTN@s琭pᙳ)p&g9`X1Ѹ%?I8+ґ{߉sטbN\CsY1Or7p׹5^[0`tq= q~ddd,?HCAV?S-qkb}j? `Nosǖ|/dnwcF[&Xh9bf'<dfP]_vJqT͸c[v=r,+W UT{9A7yEZa6#OۢjTG6 O/bCnlϛ|g7{I ن0ϑT/"aPSR _իVnIB#DkJkN%(S<4eA: Oou_v*pd ^Z.$r3KIlй\z{I9O  ڥn j\jڪTP;7lwP9W|OC߲%B,w^BwZUF;1AV2uj TܮoDo&|xp&&qDثzXnorKGQT,\4'3aVBs4TtXnCvegQQI o ED|,ݡdR !X$nI<~`h@TT:5m)E;rPr_|iٟ9L}o؆hK/q=mTZ?Y&bbI|^*L2:2iGl\wΖ=AE;v4Ӿ\WIp,RoדBäJ$Jyz'8Um iT-,bAQccH1f}=CYٺafw)i@Ku9EOhP5U3P^P߀R4%Lة|ZPKM&A J*vs'/kG$6F#Pw9tQҮ *|w(Þh-(zd\yI)k REi *ۋ1~/osȢF-.\Q7W.T ߲`wjM9zrVyD|Q@5hYDHmW$m}XRF Β۳?C'a#5 gzl!;H[~%Ŧ<>p~DAf5޹`ŧ6+TrI3܄*[hSj,KTx!VO2)ۂ^H;FA3sCYQ*+7;] ;Vr@5b(mVM)Jx6Am9@$;9,oZ (R "ҏ,P!jNKFhvG]>oukdCc퍝(Y:nO HAw"7ٻGcRܢtG!eĹ- lh]FmfCH(m]nzv6"}G+ ό9` v],\bA(2VW\GkPc Λ/a'* j9vx91blJ`GGaRÃ` O~=ű$WGׇۥ(:K z*/cjo/5|v>ۻ :Q.luUWum}nwMw_-jW1Ǧa}Vnosהpӄu$|E!mW^rߙ gɟ:JWsvX-ye'+u$ B/ 똹9OQ5/Ap+ǿܯ<”4q /9~ r^Ű|DG䞦H3_PN ?!$r:A lp71j[&@pŚ7TB6*MT\i*,UG'<}vݵ.dtULEг7Q=U0{)V_y}ġ PB~-9ތ-3O{\!}='hy5(yf{' 1}a ݰ-j7fBP2oa~Nb?Y02z|J9H=%N 0z5*2š!\O ƍjUS_q_+n{TK`&bE>7Ƣh:SW5֪5T"Z̶r%GsOt7ql}j@5ET}\'XAaDwGdxʥl8 Ǐ1Z SCN?l9-xsKFMAWy櫹N)ĔӵM+hC3'8A%g 2]seơj6@\@ok;Ԋ)OތHNNJu~ iUY!wGOlUS(%aF;&⢐VC"v_Y P8%49u(LAfP^^K Yߪ}Q,YhǜuTjk/4&tpbhקO-H[]]>GÔx|A6яb!1C=.Ch9x0!$x[6H@i/V0#EySG^Ȇ6l9lM0hCХz*݇U\o~i496|?/\8@cLȽMm9]?4 xWUf̴A(^!v]P4s@ du}-::oҤO=n ꈰM#3>ZYXi}l!ptgB|g?Ʊfw1z6aG7N"+foWUd7wL;DJn\&~cɏKgUP'Ҽh{.߄S3nyn<Ɏ%+:Lf t5S@7ѧ@f(?A E T6tҭih0pxp)7U{ey].>)#)ے ^WL!YhE틲y7(|t3999ҏ4+ ,39^Nѡah2-|?LϘPya`Vt\q9ŏvaf[A84t#ƇTW@LhTbv!@Svf0j ZOtce ]$֗ #>d|Zq??LyYB;dL6?]B7r@]6Ů"BCO<6*lB{hh9i̕pb ]x B9ڙy4_~!o2"S0րQ D淲FE+!L^L݈ /.LYvѿn6-7bm߷ EN:*Fy1Τz6\ M`c6Q>=@ ]){SL5+7.PLLڠXs1e ;u]?&5"hw 7#voP !z^Z Y❂qXZcxy*L2>pAL_W+CTbMMfH!}$4؛Znc˵i^Y2U`()#0hHn'bݠ!2I,=4ݣ@shO]:`sslj0G>TkBEg%~0!U:4͂OH`,!t{WHY qۀLY]xSD 6h@[iu&=\dE0tcMewlVao"RCZ^hIQEKW^~UrоyBre"t8,kl-sse~VηV`}4a9^Cؖ~%̩G1F'&x:STcN-sۉ̨ ]1:{T&vͲ)O"oTC[1"Y6 H9u]\Q:0}r_xn͙izXjN-J\oF#~ϜJ}-B3ʔZ-ďԂt=(ӌ/(.BxXŔ*K#0)?-|/ږ8DKAZ".X@Q_pVA.M[6QΙ̜9Fm$Q{*Tx7$p/:-yM.Y,qPU ^}; 6Jԇ#q`^uЕP SE]Lѿ<Ԧ7YtmW 7 VU2hh1yJNju!jaEOb \B 5S*\Qa'wy*iMΰRj1[d0 hrijQӻG@aPKB275N9aEA#`m4$go 4Lņ͇pNaI|,!B6p;]hsNOuNjl JLˠv4:,ҘԏXF ܗt\wᝎ|9M/(YIcRnϚQҕRIYm_)kJ+,NAHJ;˼[}#t<Ӈ_UBNyk3et4qNG+5:tQ5ir> SwzہK~[W;ILa}YHJXv5?RvvjD{tOIo9{Ltx'ڈNmX_LvZXMX˛xVE5\; +{$~S*Rr'7KIC;AZYe7$@3Cj_OX{%Z1e("{D ]71ꆨTGoЉ`f}>j2IsQmMj<\ ߛc j5P'0ijOmTJr8P 8jA]m 0dXsTq⁍ )TC$#EEXႹQHf !;W&>,{=xfB&ƑE^ &l)ȰlvSB+NrWe p%:F :͙CSa(Jpqm" aGp,ˢɁn qP`\U,`1S=d>HXLda)6=(ˢr|r~ s IeaT4 o!wÌp"lIaXAG{ 6nnKm4ov\7ɗ' ,|XSaެ`髾"4/U gzTm~R5 +_KRK RlN, do oQ=zJaf#qn{#Zok0dP ʴ .c'Kv*.|96bsꓮL;_!T934vWaJWuvcUڷr3ne X^֢ aT; m@h m#@6eW2RuƹU0.= "$7Q r)j;kqEy-0,uƺg)|~\ʝyEY_ޤP%Wi%ǔ^򤪎"5䕯KTL>wɝG"Zo r}rMOk ]z>PG]ǔQ{XM{!kЖWF}\(vXV5N7_v)TΎrտ5ֺ]Bs4T{Ũ^Z\b[ ';LͰN:A.a ^4=FF"[Y;x'Zu~+-@,0ip=6kg -/Z ά!%[hv`#"fןa1 QfZQ"nmߤ:?F XW7@yw˒f5^U~2G8ko3y 6×hh\ٹkbh/NivEj?.ͮy! Q֍h1`ma'}.5Z5bQ ^n 8k(4Fx{M\W ;E9RD⚶Raf0=J}+$zH`,@X+[=rK!;7)*'A/kvWRژbdV$.2ox(meg H z䡒\Ѹ*}Sb,eݙUK9!ͮxPA}Ӿj1* ~ DN>ϹD\ >"=\qo݇tƪ`?[@yO@T!|8[ kUyT1v-Yxs>h,CKfYڏAZj93}܅KLДrǂqGVBZ d09̤} SnX 61ov3W\*ݟ`a7sikJ"87v-a7=빶7 ;f_tn,ʐxٞ~ t>wUHͅlHOs`G?dagtM߃y=<pL:FdӔ0*xgV}Ƽs1V;,ɼdҎ|&LB{,Hrp`oO@KgQ*SԘ=vOI5p[۪Ue1tu5ۛ$M&+4l/yZU 1GM6‡i֫t+^> S*6P-" ('oJQO>gﺮmu6#$f#hhg_PO[}. >Sry[3syY7bKPjNRY|4Σ9^* X5=L߷i<Okݳ=ݞEg5zTδm,N3us7X'HqwwK4 z&*8 `&K=!qpj9rFiF/25PM|ֲjۑdDM?xm%墆γ? p=U ?I I4\T6|㡎;N 7n9o*;Su.vhwY @הLu;L3kܘۦk]̹ uhJNKhPg4 7}g4V*n UM &q=Q !N'Sq{tM}ӝRA!AQN`Ozn?*ډN!) OeZe< iQ!cHEIwK!YP{4bu0B9QV(^4~" p0,mp}cu&>ZҸAS[HŨգRR!V'{_**D{)Ӷ7HL]qC&W1F <\.Yա{gWQג 3s'RYhRcIVO}NB`%affD0 ĕ$8L? c9ٖcn'l&PTǧKǠɩ0rhR;2_'c2T*.ԭ瓄fj Eҭ.Z ݿύ3QFN | 5d4_>ashl-zjlSֆZIK4i%-gFyV~YQ<) 2wə>!TEۀceayB:==I<ŚXn^Z⣯Q{*Y&L;܂tqF:~n: 4S!!Uf_S 3X*d]TLu\x׵y4*mT!Rv\BipPZOnuKA擳gM*^dB[nGEP|6=GOh8hI h(. B:q[A3G5y0tb ۊ؃O9GIcDzZ4iJDJi^G-h 2̽O tIZ'>uZŨXG]Jޛ6fTHIJQɅVl(bs-юq$/ךPq)o`vZ&o[dԖ )0:H\a2[ m8-C̳Ue )/-4i)FOH ԏtZl63n6ߴdL63 Σ4׆LDVk'S'_Jx_% h^#j\x)*ɾqC P <_|xpXf)pt# M;ψ4S݅K|5c ޠ0a?uc .}ٚ"u轂ePΪ6)GqbB6?j5w `W )q{E'7NrcO+O6Tuk-pKw*'t)I2x''!OUWlxC`:0*ilh[M+ ilhJ@ٯݰq^j{6Ò6嫀 -V |ߨ3z" pKyC[I{JC3E wn %YP\E OunR1h1YҮđ([Xd}iml0=.J f`PTU*IUQ/U!~ Nx}۽WMr*@nq'^Z[kfV5;L"q/>ғֻ#4yнń5 q`BnbHBnF+is;MJIi×E0=uR4NZlW4s]H%nh6?gq؎9Q]e(筌թj)^r֔Ϫ9tWPMzHɚ({hR&Q)JdA{Ëbk'03N8y?!Z@>{(b((ZVxNoڷե5JcMY;Ɠм93-Ŀe'(o&҇83(OEj-6昁h޾ДՆ8 Bnًٟ%}N~?MFOu2BB [+.oS[Fᕔ 1acnMCӺ+\!5Fz2ҍm#9EKnWkro1'۝GdaScU݆E!j̣ϝ{5:<^)Or ˰vez+f-A.պ_ ^COWH#f|H6.{.,7ٸ[i˔v= wo/9,D]ɹ|UeU:ls+]c-6ėn]Fc|[ጧÊx2bc$YLBvQZHCE$0z`Lx *hu%el2CXUj%#*azMnw58 F.lJĐ&W/.eCD4{޼hHpm,W u^1+/yo c줄AK6 endstream endobj 19 0 obj <>stream HWYW}k xP Ƞ Q#2IH' vUv_8cvB\75\fEI.!qO\SqmFGpG?m3`3ij+QЦ X)^5Mcx0fA7h01TXfI+JxWՠei܃̸H:2-SKuiT(hFwRoM,7YA ^=T:8i Cd:X15׈泂W"GxP eTBլf %/%i Q?MboHKai0ʍRP\bVIO{PO4­;^'L!4Z0+v[<ڳ8Ќ4Ƴ)9Ti4"&eͱhb8(p6vh-s*iǖ4=4t;>WF;9Ffu3ɲo[T-]m-+ E*C )iۓ]aFe.ebǴoe4j+~!3[3j'_+,}kr;ItQv5LϪQ,ƭ:gn/aZVEX#B::z[֊ոV7[}B80 *h3`6u p\ֵ ol㸕vRr7 oV4kvUhf931ݎHsvtjC%ؼ􂦈]У? fT-hA4A_ÂHLoLJp XE{R؎LF~|pƂ*TkM{7 &~&/ Oo)c\ ]vg:1Kqu{&!AA6Vb%T'IgnﰙSe6a#ʡz.~ RuE!4 xT!_<"2趗[Cp%oPą;xv%i-zQB"$nk{uArʨq{Cl~uu%| 7+Yڀ,\g!~R+{!mZMcD-eGq+Ų4 ܜa]+aBQ+g_((hz[;؏\#vpv]A-$4\u1 xih)-* ӥzM( ~Pf7?Ga,_6m*-w:@t=~a'Mf'4\-lȿ0~(~+N?JՍR'W&7G۩%z":D@b8(6D MhF'2^"c$ eDԆ4>fլf["w8ښQyvhFuBa\;L#i9f*Hi VlZԘ0Mh%7iٓv8TĊ].ړ"'LhM2V4C",p#\1)FrX)FKSGJESr(с\qi^48(P6>gQ(m+T\\)MN{t; fQDcFY:`)Bn3pQ.vf>k7uMO-#൛ c޴=)VpU2:^֟e_ƒZkI} Ņ1EA$x&+RAP4m~-쮪7]x WQA>+sɖBk} YfDrs'Ο9wQJ%  _=p4v8{ Z_UAy){LzQ f6}Bq @ꝏ[Ջ3X6 -k?#ӷ.n /.m2E}ɡOUH3:\]ܣIx"kt}YgJߴVE)ָ"z0kE@Xzq_s@0*hBOY2}vá5(fI=by-7I U.<%UW3!C&/&|#Xo7 nM&R:?M(y*Q9mA o($/EG_!0Wb\7."aQ] ԋ<"uqгڃgHRF_iv|{^0Tuh5N؈i4'mh3Eo *&3ϼQqt @ZTzkŦ?>~}s%p@ܸXL .7v.Zn_*m$a*{ ,t87h뫐`A?&T:CΚxidkQt+ꃛ0Np ߢg:Ԝ?d˒Y!'uѪ8jHq_-@Y0?Cݽ(mRwdJ@^ R5X q Lm%baUܸ6Ti4Ui%P)l5-Zq@o|Edq>K0\o7;Pc7ksge@vu0VKa;AWF peەq-6XN` å Fy3;S 7;b1;PVl.e=G^Ζlv8`ͥ]$c{!ii:eI"w̷"u8dL][ʭt۱_nӤ⸎r{{M8>9Üp[9crfsv=t,{r퐦9Saz/bdvXx9c !c0$O^)!}'d=Ɵ#sƻy}x`Qb 6!hӍ ;(7"u8tT`'EPuA5 T/ 4c9p[2oO@/ȣK'5H}4$0l)C}uD?o(DqNhK 5\ ,귑^ R^=,\o9+qEId]QQ')XfIKB?#b'(U"'2z3қ#)&ixUB'q$`5 3Dya t {Pd#Ң1*H+(XIx+d~d$& mZMi&͎kA9*6A2 mPWd5“UUIokuVcK<.=ēe&a>rC $Fx}89l=ٕ(4S͇4ZVl@M=amE j ZJ|_Bo[SRKDZbhQXlG}s +gzȂqڠ PTC?Lp0C;?!䪒XJ#Cu j4#666"89S\ߥ'QM-+)=wAd0/7 09E0~,krMZTr>*GvKȽ,%7[(L9YctvxEeXR{T.'#c9䛔uo ? <~z0ÓR٬Uv_ _1kacc̚a41f0f1۞`'}:tGxU?t=Fɴz 4<m߉dr\HXA ubȺ1Ъ4 %tj+`XO٧K*J @H!Y(($1`&s1'骮U8L_<2(ّ?w}ŗl禥TcS[U(2ƀf=j>X:Ǧ{fX(B) m7z7B߰XƇ)x:  qb; f5 ɦYnEWZ ־QBȟ-90*;92l=Wnza)TFmeZ! |7!ŏGls5JH]Sj SUٞsGBP^y`1驏0D4bv '6PR7Cz>WJb'R^ԚЁ-V VYa Zl,KXx*LT oǩ'qYVI6QW0G=d-l͊j5 P@B WEWƒ aS@E/Usx87"edv `z詺0x,MxN`ܼ| a|$?EFV"Pަ8C6-Tj@ CmxSjP4aL5HN1΋:l Ԣۮ{Gh cOAj/811Q pU HiWk&+Om/l>|wƪ3/ ?wMg' v+z|%CWJo.#/"Yo/|P'QQ~8gP>@ME_zgpgg%grXO-3rzQb3!t–u|*_Y8pچY?fI]6n.ٍ`ӬVMG ›>Qɰ@V T 4(r<OO n **%DR%ЉGݥ ?\#g05ܵ:ܥ|j,F;\*ِz>d(cDJUd5LOrQ`ZQWPEBN ~"Ƣr~ғ?O$~Je14U{a<.zA os[sZa߲ WwEy޶򪯺6%"&.ON 3`ِ;!34#Nlt76 |-+\ ˿*oVW ezR8zD1ΕHG y91.,/l 8&UmZ6 K }S7sf,hmt'mSQ.?]+("k¢yqo(kmg g/TLg+o/0$K]c,ɹXٻa3ሚD>ڄ6W 5M2֮ksfsY6h5e.1 p8tR&$:5AM' W'*Q{Lg|x |ejžwoONZAC&B⒖T4dT)SၪJj&֚ޚHI&q7FF 'W-oJ?g/ƅ zw 7j5re7F##fbihR.O)VFZK'*ীG{{=h^#U*L sz <6 \Ã?m=!-? ^Z ??/!8; y8р!I%km)ll12=瞮4c`Bgw&dl-,c 2'&w$U'} endstream endobj 9 0 obj <>stream %%BoundingBox: -70 37 543 830 %%HiResBoundingBox: -69.7129 37.5566 542.2871 829.5562 %AI7_Thumbnail: 100 128 8 %%BeginData: 2466 Hex Bytes %0000330000660000990000CC0033000033330033660033990033CC0033FF %0066000066330066660066990066CC0066FF009900009933009966009999 %0099CC0099FF00CC0000CC3300CC6600CC9900CCCC00CCFF00FF3300FF66 %00FF9900FFCC3300003300333300663300993300CC3300FF333300333333 %3333663333993333CC3333FF3366003366333366663366993366CC3366FF %3399003399333399663399993399CC3399FF33CC0033CC3333CC6633CC99 %33CCCC33CCFF33FF0033FF3333FF6633FF9933FFCC33FFFF660000660033 %6600666600996600CC6600FF6633006633336633666633996633CC6633FF %6666006666336666666666996666CC6666FF669900669933669966669999 %6699CC6699FF66CC0066CC3366CC6666CC9966CCCC66CCFF66FF0066FF33 %66FF6666FF9966FFCC66FFFF9900009900339900669900999900CC9900FF %9933009933339933669933999933CC9933FF996600996633996666996699 %9966CC9966FF9999009999339999669999999999CC9999FF99CC0099CC33 %99CC6699CC9999CCCC99CCFF99FF0099FF3399FF6699FF9999FFCC99FFFF %CC0000CC0033CC0066CC0099CC00CCCC00FFCC3300CC3333CC3366CC3399 %CC33CCCC33FFCC6600CC6633CC6666CC6699CC66CCCC66FFCC9900CC9933 %CC9966CC9999CC99CCCC99FFCCCC00CCCC33CCCC66CCCC99CCCCCCCCCCFF %CCFF00CCFF33CCFF66CCFF99CCFFCCCCFFFFFF0033FF0066FF0099FF00CC %FF3300FF3333FF3366FF3399FF33CCFF33FFFF6600FF6633FF6666FF6699 %FF66CCFF66FFFF9900FF9933FF9966FF9999FF99CCFF99FFFFCC00FFCC33 %FFCC66FFCC99FFCCCCFFCCFFFFFF33FFFF66FFFF99FFFFCC110000001100 %000011111111220000002200000022222222440000004400000044444444 %550000005500000055555555770000007700000077777777880000008800 %000088888888AA000000AA000000AAAAAAAABB000000BB000000BBBBBBBB %DD000000DD000000DDDDDDDDEE000000EE000000EEEEEEEE0000000000FF %00FF0000FFFFFF0000FF00FFFFFF00FFFFFF %524C45FDFCFFFDFCFFFDFCFFFDFCFFFDFCFFFDFCFFFDFCFFFDFCFFFDFCFF %FDFCFFFDFCFFFDFCFFFDFCFFFDFCFFFDFCFFFDFCFFFDFCFFFDFCFFFDFCFF %FDFCFFFDFCFFFDFCFFFDFCFFFDFCFFFDFCFFFDFCFFFDFCFFFDFCFFFDFCFF %FDFCFFFDFCFFFDFCFFFDFCFFFDFCFFFDFCFFFDFCFFFD8FFF527D527D527D %527D527D527D52527DFD04FFFD06A8FFFFA8A8FD46FF7D27F827F827F827 %F827F827F827F852FD04FF525252A827282752275227A8FD44FFA8F827F8 %27F827F827F827F827F82752FD05FFA8FD4EFF7D21F827F821F827F821F8 %27F821F852FD54FFA8F827F827F827F827F827F827F82752FD54FF7D27F8 %27F827F827F827F827F827F852FD54FFA8F827F827F827F827F827F827F8 %2752FD54FF7D27F821F827F821F827F821F827F852FD54FFA8F827F827F8 %27F827F827F827F82752FD54FF7D27F827F827F827F827F827F827F852FD %54FFA8F8FD0D2752FD56FFA8FFA8FFA8FFA8FFA8FFA8FFA8FDFCFFFDFCFF %FDB7FFA8A8FFA8FD60FF7D7D27527D7D7D537DFD62FFA8FDFCFFFDFCFFFD %FCFFFDFCFFFDFCFFFDFCFFFD3FFFFF %%EndData endstream endobj 10 0 obj <>stream HW[o8~}(<If,$j3&h XYNvo9H";sxDL͝yzM<;XVc~{ PsZj)_mەMQ;^_8ƪ+ ܔP`2!" 8PN%i(뇤cxИ@?oms96cQ tf3l_v]TM-y ٪j>Ie6S{];6;SOo-lmlX->2?񇕾YuZҵS wGT-^'CYoݝtHz>Yo;=;`ؾh Wz隡hztyqp}"4@q4,_ (Fs&Ao#yS2' esci?-7MmX)?BsP,fۡm]:˦"~x$<il TC;ZDGy$֫W,ǼD@`H |8$9D>,:v~ʫkU[> _ЖsA9/b.&{V>&͔^NZ#_޸.f*g!>K</^.3"߇xl YК6@Xzh#hܙΆPȃ=W‡yxMBWpo~ fcڦ`wxߕ+ IGߎ3@O!e C[ۆvlSnqcâIu%+JŠ fp8 mkm`شng[]Y5sTuӇۧa `iwfXH-X]j@+6췭7zSz^{oelǓ$3f|FB8i=nMu?80I*JդjWVBBy1xs}[Z1r<~hp5\M ƜNv}^unGۉ(\mōZ c&f mNNpsÎvn=ٕV9jI՛cNĠ9c#h:/N6O`<g+=Bz`2]o_7p* z]v=;9k㣭!5`mfeb}] mo^Gko#Sn PabL) 4~)? p _(7O*)Ɣ3>qj`Wwyۛqv3wyvGڡNY^n6˺W@$S{S?r ְU7Uv~[n^g}1Iw>~w킍o"T/R{8?WjN&_ϒ?;PWq\ݗP6{w:3Ƚ0*S6c;iǾLG?fl9Yu{:gom$T}R~Fpmam#1^‡Iϸ=?\YIr,y(ttBs4ձ&k,teid*\2fqF2,JTYIR,i(1#?9&a*L)15 L ӣ)m.)ۮr7e_nL(LLTH_" 81 G&" 44*M#+7KHMh'qk4YlhviVj9ybs :?>/Up2q[(XF ;;@-b85bхxت-R$ߠm[,Qs]c65:!52a%؛j*K+X* ,0 aGFCDZT@Oo3Ho &B6b,/ߴE,f4Yt u͢lYêpE,Jg:)7r,* -˚3kifB/)^ˋQ23چ6FW fre6ftnY-y۰\hTHʹ@_BTrB@بHO:8B)Bĸq!=2O?Y'֟3e#WĈSenʌ"jq4bݴ~%Ìb]!gvk]nUջVnf|^5[kۊDU (6(pVg@|P Mej uۈ8S/_ scDXE&ydVDed^E&:ck,r#cF6" (p$ZŃ0ɛ & `r8 y."3PU/@ΊUSqE#"` 2#4ˌ0I UwGxFhYlAX^ ~ίtq\He, (# Ōж(i VvSɜ2.3 rj\?ig)۳7ӼSsuy[uۼ9KMuΓD?^/׻lVn7Z-<_a1D j`yq@ŁJ* T* (T4)B@e*Tï56*^eQ]lں+뮫~ MuIQI[ Q*KhnĴCDu׵.Q{ӯ _w3|1|ءdb%?z{Ixld'ZYn, 3X_+7(D,rQ 2prI^38-8RXΣ{"R9Ӆ|W)27 RKWMU(2HJ9pw,) Į"R(T-Dѐ)D:TEȈRbBlČF)"MJqdD~M2R$wtS_3lҌxKqߖ{(2DHgr8Ț;>~zzoO߷SI[G7\@tZfmy4>7'IH&~^>o?[tC$nK LJ ȠKZrK.YԄMLQmܴRFDY( L9r}/}O@gml+rho [ɬHc)z_ Ub.臔_ېI#PSd|qA/is CqA|u1F|8xA^fFc*GY#{3֖c }LKvBEFk"hw S[W IJ"~ yyNkكTďg6cg|W_d)ߔ2}6cSFk;zYv 8^ "s BbcAm9"VRnh/_θ8v[Am7KduQBrː=ys: ]YD!Kڈ_G )GnAG0H$(tM C8\P")SY_dIYkb _g5Ka&ӷ6AބsŚď8< />l ;Q -6qZ"K'*V>75# BZӌTP?ϐ{ =:Z *J}@,\=6EPvc* :2O Hx@4:2P\:H=g3##@mH;(x``TM+͞7wW7ҏJ#1P:eR=etrlg |טF3>v30J=cg@x.@јL 3mPye |DBg.{'VoLY!ߩ_&[sY(>ze]/6ClI33 #n3sY"K3 *i`?imSi/Wu6?ɾ"jEU?bd\?]:]?=yLTP/<\ Q뇞,f>e7tU?[ \UW'5uHm'h')u6{)F _ϜRf?x?66k^U,EҦDz?CaDc= Z4NiAE/]qYV\Ќr=qd].ß!?:?ҫn}U>ptOiɟ6:t'i]Ǻ%=l.O_"h%c-5" j|X;cOrD@u*WUP?cP{5" #j]Ȧۊy|mufD@ԸW5?"pi %#"`oWDljW4w0ZD@ԫ+Vܾn >#ry51){d)l6ژ4Y0 D=g$@}\ 6">DDʕ"j$@JLV$@~hiWr rTZ gj$OBz% G0+H^JH#j$@ە#)L P u @4Me f|@4l3$@G/3[@nU{ה2u 玗A}p5r*Q5 嗁yu/q/ >헁3܊m Fu0u-2Σ6|(MJ4RpQc@@4 DFQ.ќ+b̂e2@sve`Aԥ@uJ|JC Ki'@P_4A6%dJ KĞ<z/1+SnaR@|#$(/D0'8gd=os69m)T<d=_,Nk9rEu)b>Lc9[llKC n0h?{8ӦOveYqAs?Zڿ?N CȰO'珵q['6?i9ZuMΟ3?I"f )Z.F_?6/YY~E@45>'9" :KD@?+fUP?cP{5" #j]Ȧۊy|mufD@ԸW̝ "" jD]*gDoXJy7+YxFDw6QwQ"^_0OS j R%" j@4l@#e,e^&Y*`gh zH mD|}dʕ"j$@JLV$@~hiWr rTZ gj$OJ$@`W9Y ýҕ>#ꎨnWfzHZ3{$@[$@֭Q|fprW<(A8v:DtK:εbZ#8tD-An%gj $0K~6S8t /@|62 E"ȕ6BXN'uZR'vrr_ [پ\Բ#2A=lZ +IB2A\}/n @_ެv#,V;(Gds(Sُ f䗂SěVz) f>nR//Y[A6 V^ θLP7׿r!YJ2Fnp*|8cr'7p[i bHpF-n y>@")o'Om=R '@+/}9 HLMc Wl7\2:*=b= _ҔQzH8_hT `i3i 2: d3sGn lv o4+dRlUC}yrk61w;&e~&׬{.Ħtg.kq ]X%+kS."6,wMלĢ Ă#$ W.,LRD3$ .r'g FY+sM yI5,駉S͖[YhY&`6QxʵEodzMMcii"^D~O7"D˙)V+#r!Vo\M! q"r[Z4Z8E42ͣ"V!d0jOăFve6YRyˤuqxG6[#>~r/?|o~W1P_/>}Ͽۗ|__~5eYNDWvGd$  "!!s.w$DBٙS}o?;[_W_+o?NincoCYZu!-gz~r{G#1_0΅!u`̮}֤39O܅&]q{F=׬=>ǛF I*b=n=֢}cj{0h3[]] {>l{Yhfnjy`_+F=c&a*%?~أ]K {=V {y\G.G1Er0b=Fnڄg=cY~=*=p+ qk==ggG6|ڃlo%|9b9CN='Q`,x篋ݞTkj<ig[OCoV^o$s~ ?k 24qi#1|{O3D?Y/~N?=EMS kBx 3n/qimݜ ~[Bn7So.oɕxi4Z\mG-]%*#[MGk%M8 ݎO~_Ko71)M,W5|\o퍷 >45gĥZ&-_dž㳷gZnEo.MsP(Yp|ۊ?߶18p:[[~*^vHZro}?hr?FV[R)J c+9R/J.>'6Ov'b=d?R|\Z!؂?Jn4[1Dm%0ĭVoVܲbI 8y_z 'CIy#7xf!qη'Gz>D'G/b}Hef9r4su61жcJ~>D'IV 'l-=Nb݇Rn+(Nnf>:y:9eD֐-KOn3Nf& °{``(z|a5/֚VTZ&7Be`-mqCubZ4yV%l~MZ$%H˞vҢںW#5Ñ_btwt8CYu,ӐE2VL "E,j͟))XEN嗷ś0*hP"AY\ YdqY[@ u'")67eрsʢKk@Rq +8d'`,3Yʇf,_+aYbEbej,>Ԋ:هU7#}(>~{~ɧV!7>xfNMe1|lEn |HCrwE{\سԳqAbS=`BOг%g\_Yq gyv$~sJ>{И"eEY1trOmL=T !r9[pOeɾD{M:fY|ɇbᎋ,!Q_5DV?}|p\|t֞3"+|Uꍿ.%;ϡKxu8I}>s 1@ɔ>"yD1K !Ƈ}U>Cz؇C,^Yt6H|,ϲ4|W1xS99 !??gCUEJr!V"8pT V IFZM4"[V^{rI"!{lmuphż\FˁG7Q\}ZD@^r Ys~bJEMz@ɏFD :l5/3ױK@>2蕢2]+2n / KV-y3ѯKVYs 䈤"E@f2HB2W dN=\eb ;{}h!d r}3YnyhZ}hE` r%=d $d ` $2в["7?a1g@\FK.@h~V~X!ڋdeMC:ڋ@+vvbe{00aۇ)lA`;C~2lv@{}|(&ln@& оnA}ps&8B^!g@a#@+Td0Њß3p_d3r@|xr<@4葁v!gwr:H@JM5 ydQF YYKn" ]N$U6eXFdDFEb=T!6(=}oq94ڃ׉ZmdK[@AEmVoP$i<Ĵo>\Xsv`r@=E껭 | ?ÿ%/zKduG5\s W,xl6˿b3m& >,9 M K@4\G*( 2p뷀S`:-`٧W(#eGFr [@6fY0dzoo]$oiV{<1- 3yYeڸ`FT}/1rP55fy%Mݺ D*_h< 0wM 52WC ۩-zf2hC@KȬRn}\ x9q h')v@̳ 6/6@V 37eh|+@*3 th0M gje- 'RJh܌Zvlk g hZ^}2-/ /A6/fKqT|0nsCJ7 ss|P xM=ƍ=xOS/WLJu~ £_sjYCvxO:jri~'ƣUk l(&S?4jCn,UꇦY~ȣOj!= ƍ{j-CO?6NCyd?|/4G4~kC̵??HƟߤVFK }?4Egs2˼CcϦa?!}S)zIr1nm?OړiJh9ĄmMmZJ %`u{1p|T-DKTz FZ $Is ASk A\`2'  rr) AA!O5D1dIρ &+<rbA.Ru'>:de!8Y RG0aEKL(<!8jFW0a{; &hD/\AyaCA|]Af\A݋WOտ&V<D A\#XcX\.I8B4`Jq[劃I q⥪qtjC,zmxceqVIi{b1XDH.b騈*BQrQ,n>PĸzP,JǚzȳPo=Pge"O&H2͜Y&S&q6!C_hL2E+T\Pmעr5S[E/!Gu}^[Ge~QTf3/9}gn:E,yLaĬ/nm22T1`%ld!n#FBL,̟׿~>~?l{o_}?w?oǟ~ok__ޯ~_w?'G}_? ?)5 .;۰ؘrf]EMKyhY < ȱzɴN3mMcȵ=6I~`,ߑ;ð+S!SӫULAYY{0&V-EãUߍmb6,ְ`W \]4rEO1}ݣec>" {H}u{v7g;월_=ybEOVniû%&jf}t{udwWn RL`j^yrnb&f'r#}yFrnjMpnzy7j 383/2.T/Js 1s4ݬ|PVÏ>H-Ң6|s?+-o>ƕiJa!>]pڇ z IvP,*EeYՏK #}|?<[YvW?Vuノ!=x~M_8SHJn{"=SljvQ9aJ^X8?Tsh\.gC4y!7_];CZ?DQe"/A`Rݖ;{7\k /]" DVYa r5Eqi rk= D&x$zi(hqA+.彻 tA+6 Zu Zѻ`[6V- Zng<הqTL8Tqmgw2hڦ\-5l v\AӞ&V{12<] Jk}DI.Bq5 o{w }MY-:m5bA|gtP >wEBAU s bR>CA+*ȉ "oȠ"A%g 2HsC"\!E_YudA!$ ,QACAu((QЊv]P"hQ-A}_ث'[_mAAmDbwq Dвh5 יZhI]:?@v@k{4PlGmb~ZA^@˶@+zv UIk}b.Zփb*hV -lWA+:*6%z4 (eRA碣 iUSA7eTP@Uګ M*s*S55X; 证,"/'bTnβUUjcAT% _1 hT-9?Ev-9k&{|raA% .Tv*h "k VO G "/ i5A+;DՂAu2 Ze`ZM qdp2 P "7O2&CG0'&xl rj ZmA+`_i5Xqв7A˶îڼo; V{ܽj0hYgA+vˠ6UŻ9m0h|l@j`2hEP.[ "7dŞ cPy}5=DA)"\"^y/Z dE9 rGqgdٶ^^1W:ƯUp`ΗAV5D$>(j(Hr?̻ rL>&D@}[A^U"c@ "(6 &Uk hٵKQ"Zs W@Y7C@w<ҹ>.zGzuUU{D^}8HDxJzq cq/?b8 ,Y_ &{@+zvܹ-O hŭ*!kʲe@uyG-nЊ~h?jr3rODG@tI C(8с"K/(4IEH r%o, K @႐@i[v ثSaa@m r!a-!ak{0/ #zR д ~ c>$^Fg3g$>H` Lb$lc KtcmD}p0xmpb;qBDN"*?ma;^1LE3V %`rcL6H$s h &pA! QIq RrM!kP>AA$1e M:z3$3eB$#mC_>|w~O~>/ˏ?o~x_?g}~4_߾+|tB^iܱf%LYPސ" !\n <-lER#eJ8t/%JflAϴ}AO10cqS:ahJ|•HW=3 )PۢTǠH1ӾV3 &&|FGKhRV+C,O2c!@ 'H!,.gFGS{-GPLtiQ ,$uKI꼁$X'JMd WЂПipйu %&m7p))\B0ExFu -G}Q-@ xPPOeF>Am:t>e$DCT΋N%jA5%rq JtL~ذx{Ѫ:vnđB f6;9,3žma;giJ'ΨS9? ug,,MYQۡl-ʢeQFP6@ы:f#/|0߃Fk\7k#ԃZʜn2A-aP ]Fz6Z):jIkmkhA|;Wa-fmbظNm36[$SKzKA,t)eǯ`m'(S>u)c0Cg9J=]cٻ~~>,Q >>!tPh>hLP|zA |$࣮Xsti׊c2xS1pA8di@נvN[ؚ.3(5s8ؕoU[M蹺Å{ch0C)msr{ٜ{[{1v`ѹWyKE>CNIH>b_wȧ䣮{|6hS9UrWح_;ᣦOj+4}% >nUa9%S胮6GBS=c٧`j>Ҹ'>icGo1k76Q2}|aۉ}1.1c?aOd3L1:̡GpQ^n1{wmrlQO3\4%j! ^+!F Fgq\ dƶz5 ڌorÖK`u,M@q/ :!RٞՋVWʍ@[ni#镁 @j-#[Pu5 0Iw}p!k@8 䛁K@l@-֛$X6 T y?kL%9Y(]3PJb&(3Ъk~NkIv ;9f@OHZXԡgg u2}v璁|&Woj^@h[wR7kzH=Jqrl0vm:gb ! ȡfA1:̬."֕@H\00nmwl`K; b ~O:Kraz.\ vqd2LlE|(4,EaA4@X\7zSZ8ca{b+vz < ]/v"! %w,v?򋞭'XY*B@=Jk62ﶒ@bnYh4 czEZ 0|>'^ y=B~41?6O@9"h)5@ ֘/E"ܨzL'm:?2ǿǭ_yj&|9Ғ\8 gZ4u3t?3-MsŎx-CƋu?5EoQ^wl}> Q_) (G۸Dq61w;Ƽdt,,=SʃN ! sv Ȣ?6|]2y_ӿIEy5K(k[@.g=[EiA-aО\5 @4wo ~ y ^ /yn?--"G@f]#]G@V2@g<XI s]- DE k.8$/ʇ@V  0?;d:m@:du$7Hx6I`f ynQ$'=:oQk24ou3E?yB"vbu%5xC shp w5 th7(EK[G cT@#j| @0yKyZdqXO_!e[HA`缓FQF#`ur]x+ dt>l_eI`ϛ@i2ϖw,b{0k(`:ϡ2=7 1 @F"KKU3CsJf캓Џ)-\օ_\vϸ~K"9^Q?殁5y~lB?'~n\{qNCmNvC|` ԊB?oG?inPܵZꇼکhx3>!z=glnPĖ2~g?f~G?:Xz}CleX ^!!m_|{/>M_JGXźLɺ'l]͟=O~?ES٭K=}$#pSj (f >F?oO'7D.IBrlx"KsAhK?gTG"f.u%7}[{u&aMcb RW`9`h|}!XC47J6(X@G D|Rpk=C(ȓ 7)<{)h}Q4){QleEBA A9# dc T;Ee WO`l?7t~ DSf?Iﴙ&CJYrcǁM ^OA -H76ѪP?ҧQ֞C/ a\+ƂѬ͛McX85}g X8cz(a j G/9n]wbzHBKi%(+-  )zrũƞDBKWϚ$5շ&R?AKY"xs}X0gmg6D3b߳!35gc JâcἦNQ=Ut<ꉢ}ؗ'oDXEkڍ"CDLxq endstream endobj 11 0 obj <>stream HMe ~)LX%*/J-$ٕfh0]tsM 3~9>xd]!Ͼk]o~_U*-7LE#6{es6w sxdUBN^}tvsh&ӜIYR7?{=hLS1O&_I>뾈=yI0u MS1$|4~iie^cAa BȍfMw7sEH#6j>f =[DZXfѡ'fngW/Ia ^nWkA'?}7뇯}/>=}?~??}͗?s|+?_ew=wwV }C-Et{{.C5פ!IT#aT{HVFH EFJhK-,;nEў$K6BZk1Q Zǘ.8S #o=6kc1v#"@^F ?3,mv؁ o`ƈP@[2>`wb_5#,COӤؤ1*h3U3HhDF!q)JCdG sE#{weIN#8'ʲcRE wHvCwVU\/=vϱi;XF-3kcP"c#!>ݲL-~mpѡaƩE6<* ߝb|6Eca(& d4NM+"O6DvL9) o)KVTo(K( ݔ`ma\~ayZu)nqZZJ"6QRǑbÓ7k)tq`ZTb9 Z [Q"- iͥZuvz]Ik^ p>@ % Уݜur<9f\/Άs.8:YIW/̺rR=)!6e]i'ecr7ElxE٘HGQǼ@R`*QAЭ i&'e=F1(k8sOz,yCS,/^ Mnƺ&yX]+R^&yXgX9q"ڮ1_=sO2>׬>7ef(+|&2\73O7y/ YChϵ#~$l Myϥ=_$sŽZ/Az|z: zꅹ =UFA:2iCw'``@zʚ=5L=x,ڋ{QFr]o=hhΥQӁLUs==ֲ^h=hD53SI-DgU싂hT ܾ&[/M׾‹}.dL&!M6z׽L y1:o7b䵊f5~Mʢ ]7\%]` F& C@ ̉+B/ؽH<!n@hD }M X-.BA@X:(Bj7"M@^< w!Zi\`I@`Xj{ @CZOY {@iy"0YF6 9eES{10&2)y ƾ,z@*M^B'#U7] d7'a\ ,-F~"0LZ9r|20FQ F1u}e`7e܃% t 4͋Z0ud+[>Y9@ F``h擁1r F1еf~OGyoʮk_H0Օ-u#@n7[:[" vY.OfD6 3x^yԽ0for3_h d ~_Los'x R 0ЧwT2)HgKƒoDY{@,QyJ&БpC?e`Y= * rY# |wla,ν 0^NMQ]!6N o_ PfteM&WeFBĮ'A,@ lGdDF@a9Uv#&&3Um".Lo@ĥ \:ׯg>"0?uzI,}_*W/5bVz +'64_n?$wf!՗v@r26EVb] ,*"nioJ[DnJP 5ub.CB@]G- }d*jRB@62)![@ƾT5Kd-rGGer LV6z J:VxE( KR@9Xݵk9қg{}@"9C_% sdrU2@1@[oR&M@.Yɬ7;G@+ӳC/dL6/ _PYd,*@.)$[=c,9n=c,u~G?;=ك~%$c<~Lv/GӏI~~ >:lUφ͏`sƥ_n%Fkeg[?${/%Ca#~o͚ĕ1V~Cn1C?~4ޮ c\Aw3;~9tT "Y @G)Gלo 0_4ya *3* X+a ܃@.B.p65>^ RG7&P=RTM ez) ፱ 8-(?_zP;ILчftAe3(R!:S HؑFPWL$4e7!4Cf{{ KĽBH;!2m"H|"2MTKw"ǵ|zC,*u`7|!ϚCCr(6Eڠ(h DCE!騈dUJ(:$PTz7o#6ic ֜~)7< 5P\gm"O&*Ngȃ&1=>&2ց&lg?Lb*MdȜx1TTIrVW!E݃Zii34tx,f-")pex3v`Ļ[d CxoO&;g62=C_5G&!& eπ?}o>?>_~?z+?Çuo?7gc[}훿O/8w,XFek*{$3a\Xݨ&Sbkc6H\nz,}Oݓ q `-n+aj`dQEwb&Ӵߕ3c;ЭLD]3:C p}{P&s`7DmBu6Z2snRR Mku`X‹l๟b0}:߽Pyn]m83q=6{d[߳_nM}X촳oe:f,LxpLjʰ7VR`.؝PaZlA\H/7{#9=9Il+F٦k6xcQZQMUnQס5 MlKXůq5/+iƅœ mfP`OmjNVCGT ߃/kCdA\+Ak{-3nz3lE,W}agN+.~lTe2Gnuݤq~XT:,c uч>^!mfoю[|?"F~Eَ^"i Ȧ6ssC->O+j:no-CL~eI#6ٻʛmdpKhq凷Ax˱}-|ům#%` _ ۙX9y}VIJ["K\ø]}5\dMml|5+ԖTImjkXfhJlۋ-X+Ew[Cc-fZ9:Zq9fS>^iY؜]ڿ[|GZّԢ)OWZ/rk)ܚ$M h7ZN5y6RZ;i9~,ZġBØ(Vr12W8[W֘,qTe9"[ìbl,J T?䲚(?>"?M52~k?dB?Ϲ8B^Ǐ7)?f>JM|ʇTg§\HuC>)!OY3SC"&>tk Yv|CcyChi}:bgcm-Kv.m@^3ws=7. d.m s5:Fܻ+‹ _uI*h Iv9_Q8 "Ade6}bVK/ j:H}&mxDq j壂}a2b&2%d1Z>gf_AD/kyHKA{MA>i2ykH=&{t;V `;ȹ"U+B>Ú3=T^QBlɠ4%Rˠ: zsZ{בz.#dqϏtzDqywvydΙ"2믃(Ɵ28mpƾm;ytof:%7Af]YPdDox{JtOqq^eA(F&u:ex;l`k܎c.j 8X. `rԞ o} qxiV/<@1ϜA? /A{ OkRYQM& '|t,<9Ȣ W;WԏfW[A~U WjHMAWARSA3\jtPANy5tsCr}ybA1( ~`\4d[ɏu(nC."X-C^gbmA Ԋ$,1Ad9J]75}\ \ oE94a b1H>l]e\G5]c YX].\V?ji hXY2۶\|lA~=F ?rlϣ {`*LRA.G I]A9GYfrE[A_*∦,NV< 2K,7]1U/t=1n`z[r!nC dz,= w ^AXE|$l 6EY =AL!"i>EyFsܓGAި s`mGT,yWyJwyl,c%2{21Aed]MaqƦ VqΠ=AJds.d6d?2׮3ca/(bx{20ko`*Q>wNjAo 6= "heE]2AD v#{DqbW 6p_Q5DE%d1A[MAk"ȼ$c, V5#\l : 5s&c^=3#g3eٗrhAΪW:d'a/I2'IW{EtdNNG祯lAO1&m>#lk$7/Uu{aG ]Yڛlc7+ jF t}#`2 /e}y|dqXMyOZY1-5v7# qzVCK1G ,V.^QyK}D1z- fD+ KEn-N4m 2l/(ZQM~s Xωh <[Y/,jN`qZ\Xbtn2wk/~M@/L-q%Esòr,Y/(Z6ЧaZܪ\xf~8|S(TЅ**7*5d.1_UǧD1:d Tn+8hNh1uL\Gkx!D'MLGKi7!b=!%tlKu!}gLuk즡W/;NV  DPjXs8O.ElP59~nKb| {[(6{3 $o!.k DvpU !hujSN$Fp·4mne{` L(\ L a:6&xn0xɢrH6 IYrHh>H=vRzH^Hy3[CBhI !-Cs'!C [c}<8`A<6|8ߓ 6<גzp8=88|6ߞ{`Ih+~F`p `M"Վ2fr`mfy86 93@o2F-]QF 0V|rCQH```X9Lr8q5}Lׇ ^j\|qr,:`D0yMs5NCF-IwɈkS]"v CqUZ 8DlYyˆFYm2ܕ8"Eё,Zёz$_|449댏Գ'b_j"݌L m__髏?|of/޽}>׷Ͼ?|?|o?}ۯ޽ʮ?a]d/؟o~v}g޾3/:jBArc$AP١~f-QHPKی@*FBԧ1!)%Iv%̃Vט~#K{OƟA!j \nҹc2Xƥ۰YaiiC&fg*jȡCXh)AXqBô¢hGo7bw 6ՃX\ 6Ժ9Pf)ky`f3YhY+kcz8˚nrZ9͇(,38k1󜳐PVwJ+ZzZ)C"AYkPz.*j B6xrCAT *.Kb,2G0ִKm_Xe4t22ގ/f"=Y5ˋr -&a9҃jϿ˭ʹmfILNCV77axa#4?`WVAԹ>יm5mJ+U:k['^ٔG`m7QtcN JE=7(i7=az7'xMz =% AУ#coEo`m[ A/!f'|E̓U=y2ƁtOcRI =n16L@ãśZ019 1zԹ̛z z/7jM={JPZ|2ySςгx}GC=N:E=;U'Q2IW!OeSO Գkeh=hɢ=ZecK=@=9ܳ`i ʸgrL;O{ɹ^7K{ ^ܣ6{ ]T"c'CtVCp}Xf>^ݫLvnG]Qn1{Q&>4ll?GI5=_c,= PA6ݴCp3_xYUM?Ĥn#IZ M4=˲x_ [o7,tZ6^ǠhGm?$% Qw Rʍ?IMƟ=[F.Ygz5? J s wT?fM5gZGREn1YE ?˾oY]?e3L YmxW8`?RR.ٍsN=G=oUd)ۙwS?.Z@D0[GȇAFMD]ēED|P#䡮f:B|(_A\ws!/z"ڴU 3>@sLcHl_T$sG0WsQL2ȉ*;1/5 4vgxe/?~ۏ_ث_|?_�?~o^E|߭߿/ij/^|tC Mx@BhѰUhdj?1>R}Uw A[75ZWu[~vIbav&nt|Qij\ C A#b!F/l]G/ƇH5OӞ= qDz)%j2 (\B0O3D9`C' kL!][jlFsֲXMĉAgF\sy.Ո‡f`c |MHCv6acƽ@5QP *ߍਚbDDOaVW h15)gjʻk'쩻tފxrZWۊ\mVjہ꯶^Lm=Im\c"pZ}X뵹Z"-ڮ֣֋ޤ+8\iqv{ELicvKZ:Zo-Klg쯳y,>$ҒYzMgy#l2i"l fY&~?b}2dӰyAˇY/]e ]e}֎qPV̋,vE5?z ~r5;y,W?G?3&Rϋs#YwN :Çڼ1>JO<%,CS^P䦰ECW>Hki.yfc7ɞ3왟5r7{S%Ze,'Bg)D#DhyNGܜ9kn 2KQ>C|k)Ҿ>䩯|S>6S>RcER>>xYzCęE}ȸco-C8Ѿzc'}n:Ї_Gk?bjr{[>,k/+U-3B>.Cm}\q~M'~[%oR?vDԏ9X{?T-cVr:>/WryCl_FO(kz>,D;'FCc9&+ "Dn2S@:EȪvD\1 ^6$]=wf~TtciLRAE*Ez<AϾA/Q*Ԫf1K6tcMzqh4{܃ͩ/^:$fSү(_DPIk#KG AZ"NsAf"2~3MSAHW*V~m1UQAXl[A,f*ee!CV˰WAVq]"=zіD,K#E_Y2Ǖ UW 2 "k\UO^C6%즂EQ_| 2Qc֨ r*E=CA*\wN:5\*I̊TyTW z rUEn[Az5[WAV[*GF=Q`[ntgP.EЋKx+7{ `ɱ-,EDQ׫`~,Wl*?%ӋSv (ۨ*&@O-Ex?3UGu(E-*sZ |⌃O(x.r\ CqP %=ؐ FDslⵂm 0} ĪZqУ"4k Wjc ҙ60Ƨ |SI)Na [$(3d>@bi F>^0P0%?k~eo6Iwƚv %b=k@}K 4v ?dC/1+/zPm XDOh6R@#gnZC@<8XyxWjP|iE?c`V5q}s]^ 㙹,nHk'Vz P+(=@N@'zZ)` u}ѓXl6mbIa'wMA $)șfP3=/6 v%0}_s7YoAAN=: |)y  5c{n i w.ϞO "4 "@dG"f`p* {u1gL0 - &  EP`dpHMpp uރwltBl~qދ̼ü`Occ )vR7XY=9Q~V ]/ "Y "z y:=!TgtC'U| H > '9mA!6WnA7 1r9A%˲{@0*K_ &I &R_8hj7QrnABn 6 Qetb! Mi w'yҐo+C ˷ZDdt4UM &&v:Amn-+T$""2-g>:4Tj?DUex`uĺ?s/w(/Z`,lN0xRO' \-łh+o`B*]XeIW~i'y#Xa!]T-Jbŧϴ!o"EE>MEuQ"+/6~X|Ӈ;%".jss .B7Q"> )`'+y2~;ĶT'W!0;T Ě1t. F#Ҿ:/6DUVlɏ&'HF )6 2KLt |_ /~ÿ~_3o~ۻw_㇏oҘ1wרg?|r}w߾ o=;+Te9ZYᩆSno@Uf=:,kO23JtDC='`Ir {t3H +t!k.z R/˲4$Pj`A\RA `TlP;G_|H˷L; DBe7>cJ1]{Zg9n:/s?o&CA>cPפ ҋ&shPX sW`pgIpgLhBqPcTA';Ev Ú}pRWnI{9uV|>Mڧ7(G.Iho<&mֆN?s n E08Y{{ʑēO&5ރiˍke!7mQMAN>O"A[苤^Q2NvzRx̂)`-r>X\IoZVo^N""]ZhAZm :{A\|jZ䠥e5;gY4Y=,dYMR+ߜU rsVrJ\Y1ݴov^h/2Oד̨Gp_2'gmcrܘU"mSՐ,u/~j7e)}],T_ Kې:d Yk`,'u1 AUI?I~rA>J}MFD}Qft=ѧX>h,a>ꩧ<u}\$Y Q[?OoiZ|p!~ލ=n6{\Ğjtr=J; = Z#8ɇ`ւ||=|6"&a@H/&1䳁t+G=I>8&tA>\cV? }|Tso/ƿN݂}fOZ>=kNmaks\[beO!`U-gp) [=٧T˨m] ?SEs>`7${Od*8RKNN·I?e/Q6~uΎiZx:a@)}Ri1ҥԲrN@ʽ H]F; <Hݚ BvnB bf tΓh`n6>q t DF@> M=1Jm\Cul5 nv]nR"hI6!H=j R[)'lCOcm5htY AG-To `R7, lE䛂J:N *Wk R;A7 AQ% (, FR;!`^7%}aQP*夠#((FP]k-9xGol@͙SLwrTlҫ & 3m*/*Ȣj*\F{D=SAGPz> t'GPгRAd4LGA  2[k />(_UrZSAK}T`x-D4T6A "e߮QԖ bK`ᒮMRr F|(DsڬӢO~A[ꐋ 1cvк v ֹ r*QD_"[A*}WA~h*ZWA(z/3Xj|+]LA47@ߩ*i D.E[^$.NLGHA/=Ƣ8@n=4ȯ:@}> gK HC \N%u[& %yxN٨r}2."Qf X8ͯ <}.?nu\+~ Zq Xn! 2ޭEَƇ{T4QK J"kc 6KG Dl@j+! ufY1@'c s'c 0Py\- d?^Y E@fߨ?{ W#H-q*k ׳~ 5iC vvn@º>5Uj"kxA [Nm@c(Ks;J@$c /T55y_5b8^Y\n JyDQ\ ZK"Ȣٟ"A|lU.;AJ1& :d:Aic" W["<am["X!g"X٢ {( F* ș X;Vj"ʋ }%ț@y |D^mj"X|EE$ȭtM,;z2ۇ@:ȼ&S%!=  ˰@{[,Dk1o85Z5k.\϶ 6sY:aUj V:]X j2 ^1:]Y4 kM) tc_'Lfƴz"?JDK >o$9S@A̵ n̵y> t&y.W5MM?njy9$EJ?Cu&!/sOfM?a"{(Cڂ?>;$?iť*?xු!VCl"V'#}ycqt> i@ @ bWfx/2Q_&!8/@%#p@lb?r,]/(i+ 7H%"͗@^GNg@ogS~"i sYz| Ć}~@vƏsPcqȌ*hjM[AdRA6Rca2"v^OdK %{d6dOs8 2A^|lV_5|Ι "4_B0ȅQAg>\ uA|dM:7u$Y2j])X|T ƛ A0G3Q2XڛBڇAl&r:O_Xcvg_(3>d":ƷyiMu8(: 0y&A~掁*Ț n[TD*GAg~䃭e VapݦD'A#AA Pk"9"X"HqE"Ȍzd:@"^)M^Q % didc ,2_q+cIp jqWgpЬqU!-%כğz)5:!-D^:}GC,'5=gȫ_ .D:?X~r Q3Z*҈_YJ喆 c_jχxâO|:?!C|Yr2V,Ⰴn+b庈r\7uz endstream endobj 12 0 obj <>stream HK % Ud ,bxxsJR03[Uǻwֵ>JQV+t1(àg%klih, %%<Ƴ4k/4vC{5ƪK0z݈uՕڽYU^, 5e˭ɬhﭭ:H"2VS׈\k-RC)ձUĔR"XLYZdQ)=.4yecEQyZ: ,tBs3TF1X7 :ԽXުl#' `Y-Y+ώZTIG eC6lv+-|O>݇oO<@O?~|Ňߏ_oǏgj/Q}cꗩkG?*9yY[+@h" ߝ(-@{oؼ`"ޔeexhg="Ʀ@#  R{ Iʂ`.mB!/I.BlЙ^,tY{! 2yF7=0lm/ A''agoCY_([*LVmC3s unR'S[eBZjyěaAWqR| ͒;1ۘ{^lapw ̾ '=x .XMM 2^z B ]_r, f,1 2{od仍̌" E LaXLH~a,4AZtLPHAHȱBj0&)%=Q ; iJC& %r4=ƌXBD0[cZ/RfwҔly G^7 9II\;FIt!lZ@1pu@4jp@k؉).@"5c"ռ-n rZu1./naV u@vP=^x1  Oxb9q'a!aU+ BIJ}% =/'N1 "£ x"L+ȗ\RtPD=7K]y%z?=p 9XBRVbgUuv:(`lܺ^_ ZDr<_]kgt Rt x|&]I68r9re\(qΡk {j!b=ʏɛ_j{obPV]8Tipeq\^9ĚB//"8*XY3:4-/ 'g ⻮SCI/35D\5njKCk_2![~iXw!^) KXPvbȑSv`o.rj!ެxҐZF `nbھc,&H4,aҌ!\4DVh"sKC$qq\ -(N J\tpa3l2[022NL0#/tZCѧC&xp2.uP? nRcd*!㖼aAi=r@ 7. >ՋXYQrM 'ͦ!"!Fé!¨ojQ)_4`ĖouhXgYC?4f*.%CCja{ɮ2nGyIFpCeɨo%)>yek1^yx,Z!C yE!Q+{xȸb!}65t*ڦH Cd1iyڱ엇;^AD6q-;~ mQMC)C$b !Ƕ "57;f,g"g%`""n]DLDDvbs8r&by5ED9g DX`_Dl0"BTܫUE`[umyKmY"v D5>*"Bޗ"QݞDtQ*)i(D">J\It!s'GLd ژ$zp."u"Uo LƲ@ϺiCAH\D/L]@ɛjr)byMk;<*m@Aa2nrqʢt*X}xY_w-KJLDByG{-GQS ܾ"w.-dt6^l?sٚو>Ld#Y#d±/Jt.!C \{r8rYOE#bllE#Ɩc~G{LQ_FF$ŕ+ܖ!.!Ew'!ܻ1, Kna _]Cr6K!`@Oځ %r^yb7("s&<29#!}D |3UR' ڔHE^ Wyi0 9#ѧKb*baUX>]HLNXM!k3"1>4H| j PXw&̌ȥ ،D;|fJ25v0XB$5|cN~Б\acbIg0W*$4+Vݙâ`~w% p'qebaWa $F>^:lr'cin!KOiwRr}SQT=!7@(S%-vG|%n/B}{.z$ F,| Pz6|LA' Q/LeX,^{4SM⛁U|l%&83!;2q(MභFw`"@ą36^bDbS 赇 '"9Fa _*yӉSZI98Tf/>scՠ>,(u44lk3zonf5%k T%mn-"ґjy V%4<з-DBYf=;J:[3E`*E~£vVKbhz}m F|Zw-ran]\zkPvApI:#Džún80W:s5Z'KG:^T((\0Ruΐ2M}l^=ѮowW酠ݲg)LviM5xݏudfqRe'd_:3zD ՟V撈Z9RO0ӳFHck3~E3~\玟{cOߎ+ĠzeG`cspH5 tI3sMr8`ֶ':i06h_9代cԽ7Mmcgc,::oeWldlm_;":]. Ƥc82gjE +# wE))b^"L46gZjkVNQMc#HODXZ P!u.6GMNh2ߧZ ?ELi\XJ+%7UJ;iWn7z%+ u*6}`Lndacl^""4 fqe0L}cl(7˼oV;+zNm)ڥ7.zJslcK6]qo*4#Įj6U4x',+C@ؚ4QþU:mPA>C۩Thj]-bx r0"'U+Ӕ~^oa!#$7w/m8{w8zC Iu`|ҍ9Ff fF"1h.s6 lWdŕXR#}t4x0xIV]p7:,,+G`;^`="K=nu^]ҰD6y̔"[}9J޹s$F%A$ 0X9 i6Lӻ c*@N`rS @6(2#%^uAW 0w՚]CX` `9@,{G*"ݧ@Lmi Q;DCi]nKk.|*.9=$I4tko[t~W}uerxpSS 歇c\)ZvX*5q3Wrղ,(l9;ZMThkGvs2syu=G/#uti5Y}Wj\|7K>G!!!`G"`$\ǎߟٚcȥ5=kuWWW3 >v^m< YԤZ3o Cw:OlVMŖG&8[0? n!v_%+d@vg :D-E {B(>nd)XDlk2Ga/bfRS͌&OԽ#nVLATFm"vďZ׎2G8O?>cmÉ85c:Im@5\AV8x-7ɵڴSbgWS(e|$A^v7_NlB_ؒ^n%j^F}|[ݛ'syl^|;~pǿ݇c"UX^\= 'C\?R_~ >q6hFlV눿~de؁>~_H+'.?9#h (\l @Ei CL)>X4pGGRa+3&"tJ#F8[ͥx1 IA8Ob +JtƄGdO ϣ/ M 嚧R3!@4%3tN2sbc86GNb(ȃamdKja69ц9ؔ/7z:8L%;Š9Y1M%qզwˣh6OvM9& 29S/lI1$}.3#iE19ES N`*l}b" '7< 8D,ma%T.]m$Z KS-1 !J2-U_:Ԭ#&/EϤڍZq$ZX, VGiQTL:Ab6IikJ.{o}&H5R1=e61 9yN^_kc.ns]Jn1Nk ɤJ*C+NK;uP6QqÜ:g6vf3. â>RgnE'gf#Cg7$ʚb9]ҴUf"erՒ_'syl^|;~pǿ݇c"|IϮR\RI.忾O_rO\$tCP|[tՠM'^'xh泸^?PPUB" .w݂FʴŴP!{V8GX{q-ܺʭaT}Kb܉hQ t*eh"8)= 8G{ŠOkT/N{X Œoxy9ZHZKŤ-+Q+S3.#6۪ևSkkfȤ>bX-l3F}a%lL {* ଱)DĨQ4}ѾT0hkm;+shK$\0nߩZ_@K%}½o=X[aۚ AggAB 6]G7>} mM^MoT܇% Isa..c?,~yRs {0V0b~P 19'sCr;ʠ77Zd.#Xp{eyH,d`,oh ߟ}&4ČK /rZP^UsƵfpD$749]ډ_bѽ;hO-.qUzAyi;"x4wJ"qZw;ë?;58 Nm5W\v~}]Yk$>Qگ~C :5?&^?𪻃۶/I`YCef58aV> "%EƲZ ac%5bKoǢURi#Jt_sJ/ Zp7\ ymY`f剐d) 5\P ^(l>D2 E `ϖ^Y(_ۓ׆g}ӳ1ȃb{dm/mN b/ H [ŵPz>aDM rӽ 6O2~e qTv}L?JuH",ոeXA;_xW fx}|v^Ŋ("_kB~/+ɒаji7|zدP_ue틟v-9W5{v d\7ew];jruc 5LB!h C$fql#~ l~}Ep$EDSd&w$Dii*|33ؽsR8,-{!=aopxeD|*oX,J>{"}`9]˫l);J;-Ǵ/> %YJ&QaeY 2a?A3[}U7D]֖ f}ZBH:\_еIg޷Tw#]>hߕɪ>?HxYG[S-}TCByJl%㛵iacJMʠa$f(.oԔ}}9$nV;ϜiOz JYyOΉ"W9zu[×#X{8zOeĔZa ";fm,3zxd݇Urh,] oU3XbpI(,dYBe awaTH[6jFrvL;6,. vKjBI(՛(zZObUꪏ9 %S^oZ/Mn%IoAoŶF Yj}Ϲ7~ Z>U,}#dM"IH݊o ˽%96lDf=4̸mç%f~x=cEe F@Fmnyqq ;K ɔNZ<=u5۵3f%f/~Ҡq(.17~$u؊pܠ~+ck'ER vq(; J EM>OlsH\Ќ|o"g>8:M}p86Dr?E6Jt>pWd̈$P{e g\tW]f xn m`ٲe_&^RJ ٥_^ #KswS6,,K3#=kj4'@i[X¼=ݧG_łl2LD:BFa,T˵5toa]311Ek&eD] %0yxs8 ;xFhX//v%͵-#$?s,Qo\z#O'lh~% 58|CCR~|$׹&B S$KXn .Pb^¿p'!-ϙ^ {G.!$ n-]>VM8s3)ԛ&zuxIzz<[nv2[K\u}`Oбl+b-{ :/đ݋_g4I-$<sx;esZKV;]օgmMibp>=$K]}WұSvBlKE`χ:|ZDv:*"JQKxp8֩==#-ؘXMD8]tF<;-Avّ]8` \eҞ VCcQ6> }1b̌XJāP9Lx 1( Pju0,j& rBul޵\W ]o -z%k )$+ObQEEQEͫ!~j`|Z/p._. csN&T9ܻF%ga 04N|oyxIV1yu\B$@emy2sDcͨMqT=*xr@B ;6׌`hv#Ndc"|KGf^.+FKϹ@VXdeIC:-^nbp'|VF.p=TRa+`)naUJfn8\z&Kl֯qex)blF٫nF6e$r>O+#Nj#3B-4 0+gMjy`Tl?I?:P#ekn 82QgU;`;^VF!q =ƗDp%swpXDP?@z$OAha2FzZq Q-'ɤ+8)YHq+hv)(YKin-J,Ah?# H@VwB|!&vmJٕ FUp={phk`Iu/Kmp5!hk?ifـkx 2s; h'n\b38ޓ831 V[0vE}SLw#"r 8-NB\Px8?ktL4yl#pKN]5) JiW':1v57A7G%sp+9y2,!Vζ |378-7qH@k4B-``H)"8fY-oV|2ஹtmSecEƸRó},6 t`eC׋N=% 7;@:2G ,xm|;&Bܒ}z C|"tܻnٽ3B7x es9a nN=x Qi^$'3Zu19YJ Gnw1&*x5 ^S{*#̳P!|O4zưcl@4CoQ;sSgp X]Sp4r7ҍ|Llp}Fhi== Dp\AQޢĎ`IYmM8e{K)5%Y;)Xdm8Yΰxu6-jůŰIa,&( _ZAtKN[}r()$GSJ&H¼'yaYi8*J4 SPS|SS׹RhH.!Ll^pgO 1qrvA,ЋI0~bʄ'E~ vق8̑}2%BI֗ l _m+L!V$qgq12PӁ]®ԟܕf7 &EVcT_pn2s,^OnYa"CR'ٗOnT4g\ZW˨R1 x >jotw%kk]ەY@ꙷ]٧ݼDC+8h\9gz{m "qT.vVٴ7_i.,Lj1):Gsmydn |vUQ6Q˪H]8L$p ^1h,$w=&.;p{:fl\{* RK0}JDJ=΂6տy) 4"ܱ Z[_PҭQ5{JzXE:"nrA>/䁛c'!3xǕqiT-Õ%(i Al_.{jBbs*nN1W-.~"qrso-X/]5j70~RKrKv=pB7h* nm< []v2=bWT0Kilfvpu|1/Ѝ1fPސր5E2Z;x⻟,+m5fq*b۟00xDafbKubvG#`l/۝JvQ>o?3u> U6Þ,$^]),QO aGFWyYu2]EǺt3Wu&ؼjc'k& kpcQ1) Τ"^ D)5i2#1\p`,ɚ4zsJ;7}j:%l?9X$Fet؛׮\ţtsp2v.{T%R=ZlV]*Ğ &> ?og8!,[j`覿[qךuϱ1>7_wԹPa; _I&׋.pYAn=kp=6"7UEu(9I'{?$f`*kԮ$ןXuQ.Fun_c(@}'Œ.Ëq轟i+}m o_Z AAr>G453:ܕؼ .b,A{zޑƤjЕ~Ѽc9Y{khի}Jwp5Q%Ӛ/<pt D^q j":(}.Y7]~VdY+-}VRY#n)Rv [MXZi["(3NF"h" HëgW3YpBgr^Mc[ڍ I ށˆ2hpʱU啣-ه*P-,$Q΀+rA+(|}4UV"=PSyD -0>f<]oGv]z"(3 HV|HhU.o,!\pR'UFcR%k 2Td["5Lm0 d`QH>>rxKX1wX[]_)q8FTt^B߮8|`rP1]".5<1-dTG*eSuU8T!pBnrY"WNQTci]iXCE!fWBjTZ DlL6-LspWZ ̜HA`Dx܃v93ETLթؓ>궰uepk! y_ =/2H'@/t9ZCޤՐ?bk18yD vnz0XlM0V` ^`hVxHM+mA\Un%޽xG@[3E!`,-i ӍlXю*l^U cXj2̇TSDwO54ζ0"~Y+|û>w ]er2y\W4Jq)Z=[)6G8'W.sxwק}aQ^]뫹):`pNc*-6IfZ4`֨[pHzpwz_IO鐖)<-#_mh ޚ^[~;"!QT9VUj% ~;a1ʵssY b |xn?]k+ 6=9. .Yx9 7}$ZqEOqP~ s>[ja!5l֔M{8c_ n*arh?؄ٛ. '^E7\jHX:eεH5lkO%Xqs_+|B=~Lhx"Yn0* srF] W4o Lj4o|e://|7o~?|ǿ__|O77[C}.>'ܒoVoo g&JʤyxF҂7kx+x&ߨC7?P2~-&Lr)jc <@dd8j}fRJ]wpT$B=΍\yַ*JhvSVب 8\t.v@!T^v u^4o>t|(v(PIӊ*w pX"}j|.ĀؖecGrpeĨ+ugBﯞ.1kLkt"'fJĪN^L:[$BBp[0}x$.Z-",6l+%:֐ܢO9)5C'ud0 8$ȜU2j%v(3%Z,AK L!ٙ5Fj0 f.#G88:`-}#hpnd`2|/bDMou+#;7e 9A{{h n'4:. gUD2@id11ܯfYwbJ'-?d,nW싩0Pnxŵm5!4\4~K+`Y_K9u갉x!f\,7P/*4 &fÈðtK;Y BFEjV h1^mL '7ƝCV|X0,k3$z8*jdi b `]p?E~z}dyPcx8*: endstream endobj 13 0 obj <>stream Ht]^ M t3i>tťH(ľHIg!?֙=34~̇&9T&CW׃ [p?,7XXaqNG&r2 _`OfOzTIlM)_a֣Km+y cբ UVl5MKѪT9׺A_=v]E.Txےo5gKv(bt.0im`=28Z" "Q(`F5!RGadi@V)7V27Ly ILS`z[n = [28Ö-hF.xUTDp1H|PΛ]=zu+7)`= ;- lͫ7rmZP^{=䀥4_B(j Fe)l{`hk'^klJ7(" ^4N`SjFh=3S< 0uݰt $-9J=!eP7#YZO!MXꋦm(.ڵHW=[RŸgU{rV=HY&Q&GJ-SޠO0"75:&}:tRO ,9)pyp5=qiJ!WTكSQ] 1TL|6'.BFB%7^pZ (*`vp [Jܴ=1To*tNT)1%[)Kfr F?9pu+oHĥx6ſճCR119Xt,_O#EzP3OWJnclDz\]rym-؂ORj\dSt8ǰĬr8|\y+AmgbuC.m { ӨKWкŠUEkl)u]%:ڜ`DHHՁ̥s4d,Pr\3v ;45ӿ+DCN":zQ|vpqks{0DsI N[|BUt=,]{k0L@xoAZ!4bȳpG&Kh"Gbicq:!m7\R`X#&(D6s: j0Sb>|)׽ V3,WZ%awn&p( xGc#bOسYͿ~1ch F<>9A9g1a aykC:L̦6,UE[:dzH s} Ne`O1+6Z+xk>áypU'tsG)V.kJ.d,X? #D$hàRye8bޡ_Qۃa:b2>5̝rT!j >mКLA!sl,nѭ`Q!ʟX\m?۸?^)]ޢAuU~=3?l\[yRNqblQgp)?Bi1<9UHfI=r6"/|_|ŗw_}~~x>hz_ׯ~?#ӿ~z5=73{ǣϧ Cj+t|H+ ~3c_gNmQ C>bBCPR;Du~gwhRXm76$38~zbI5/#c.* R)tAr>٠r,PQOPƲk-B'$,nZ+]~tAjls^K0qLS;2Ԓ 60 '\9vۃ)XSfm9ıKf ۣkBL(9se{טRY9a7UQ%dyLMe"\`0Fƌ.hZ:1ɞ-8`:J1ȀB,?Bqn{S_gLsـs0d*_V+q["0 w3?2*o&Lz`KkY ņk,^?ye˲`UQE.XX̕z=rB(jOTɵI;*scTiVopspPOğs&]+l<٭upڻgd+̹fraSyZpQ@DswhvP8'`CԬuo;^>$JEy%@d-,hܕBsmg^"`D_:Wv<̑-z"Bmq^r~^փZM: $*1&~fn/4b!E}j%soMMFH.ޗژ=L;O/\-cz/cX{fܢ ڏ1Ni;਽h8_[YqL{Y9$cV-Kc9P Y巪»XUUΒ14rzc>}}aF e93/KYS#K/w+o`$vmVӝWH t1v zV\^5Hz wuVX_yЀoc+5-f'WZ5SW3=n uXٞ0RQ5%5CCO5bT C`;3u<?0Tn@.v9A83U0r^aٝ,8%˨ɖd@BT8}DaŒdux)1&,[*I>"xXEpT{m1jH׎>@5zsᢖb,Pͺ?@tzh0,ǘ9nZ7DXO]V,2K.lkO5бӜy1̏1z;-`):4M }1M!&8W/v K(<4]ȿk#`nHd>uג6; W58csGF|>x`y[ CՓ: l&XEސZȽ[O, tM=jwibͥ\)ooOWڋ^0*۩ Z)>kl5vWvJc*c A"%FlG/ >e*pwdi6MjR;TM5вrlyӪ|.yٟҸ;}Tc]g~TI^ﬖ hS|5{0ԻwV z'MVz- `V1- Tܜ?d+L;T΅yPNU9˹sTO_d2tC.%!5*1kn֪ͧڗ0Gx?{.s\gYwSx[~wkҝ K;sYN! I^1ѷH%]?)LIP)jxû\kB*3An"Qtblq5.nyⵖ; O#}6]Fg=뷗hGN@M6XRH^g9Ɵ{|^ҞJ6%"0fyi 8hwh>kl{T>P~=^Gnt"H\KCh@[ 1=Uklu",@I:\%Q][f42|vI Ȣ&Q uJU*-\ ॖ/Қau|+(vՊUD!$ЗJE: c]3.eHlj} `khiI?zؿZ-p$w+䝵ٯm$*^\lY1$`ʁVk)M"3;v.W?J"wCOplI,Cx#(d*8I`ہqjod6dʔu+dvGYK遨8AxCE _|rJGnCtg6cxCC >8i(B"q΁vN C8јsNA>.Cƴ}6>@10:.-k:P3jq3nLh[v^j!T!Z}բTxA惋sƟcp-c3;=B^ki:"$z=){8)C\OCCE  gcv삠-B& >޼AE,J mh/68,88t'ҳЂP̺EGP02npAC "Z[BjHˁMd=c|ܰ%. xoȼ)îq)n+;\Gy<.]RU *4zߕi^!:_?z6Qb"''vn{rOפCF4>stream HQo7 ;hbI/ɲ`#.\зJL%+ŻvqF=c3w766'{Cc;9sN܍K3N^_~? ?NcߝlȵajBq-Xo?K)FuF_=tϬ.V[7efpWKqtpsRd&Vb{,<_;]PJmenjT|/feC› ujmT8ITmn_qהR 9]: Q%QkptHPD4s4R#mcيﻯuNa|;!WVx ӱEa<݇ɨA=BR~μr,7JPOь&Qwfa`碄 IwҘGۛAǣ@mQ_E* g+,FU#݆C>h0 4Ho~&v`lʕ 0~*VIB_ws ȼ&T)zG+ {>Y)ϭnTrF:"%*&%=JlEXnZYH8[;:IS7TGs_ObӡN`x9,( ?;[:ŗ+  f¯AY>"ՂYZV .Fc PP-<qRh9Cfp!K3\U,蒶X#aTQc^KR 3֕XIMfA;xӰ!x b(NH/U%!hs0Q<#T+4{ϼr,7JC٤l%qhH(h0 4Ho~&v`lʕ 0~*VIB_ws ȼ&T)v  G¢gVs&=M-)!c*RRjRJM`X妕Ŭ"fZp6Y)lgS`Xx,˝<dyo2{{yQ|]w^C6)~4R=H?dc{C䍱LKBjѡ®4intsxhKGaApu@UK f F~opQ|zh Rx.je2UH8XJa)\ZH<2U6!o35@)C| Y"`Jf .Dks ]v&*f^ͦuE\If68 gzx60E'4yV\p/d&Vb{,<_;U4r,0㺢Ǯ/i-'{V )5rh('%ro$A-飉><mc GNXdQS]z=#p/ 8qT rej}+~B)f# 4A Y&m(e(]o!6r 2 :z)S o3Y*t=iK0{=:4k6]jxw@s $R΅Ӷ c4Ys@>Z|,VRTŒ늦Pv*ADtZԤcZOh<KH-aǶ 9ސ`ZIϸkskJ/ k%r'_py\mg!'ߡ k#ViCu4W$6)O/M.>n T݅),2-m 0h`LvVV9F _]5\ CӴ'*7R@t hJeʫ.!nBfp1kR"hUb# R+D/ [x >DooVt]v6Kd.#;NȟR"zx8C)DUKҫD;HiAW"z*|Q0.W tסc5i2A6*-eh6ʴ?e6'(iR(ݪI0&U+&NspE;$H@lr 4AVdDνE l? ~fPeM_Jo_T-j+u$6k늲0U&p& Ґr5\THRA)}?> wR+c/cmD?o?dha.wRlT4Vq.Xx&[y uT?eK.|x越 4m%B!WD~5|]C7KnX6?Vor6'63. Ia}ULes^lF4ޫLج(_ּrNN6w9EӚx.ƹv&3UпcJ9-=J` Y.cF;׫RW2RN̈2ޞX6' F7)dK0~˸Se \vQJW'^ #mK{1eu8t0bbwDr]c P?įs^YBYQ}*8+ʂ p8`25 qhϾ_ϓS( 7؉vEk4Z^k+%!_&aILعkd\@N#6s!l:;)|,f WURo2X)( l.Qњ@f,@J[o؈!O7zo\3#\&FqOB"3Fo6:=#xM8 - l@7؉vE=[>Vx^Rg[m˕`0w endstream endobj 15 0 obj <>stream HW]oX}$&Xaa]VQt;ඃԽ^X9m%juョSuTYvw7+˪mMrӬs>lW?Lg/7_)%[a +6HSQGA7pD x곳yR48CES+߫C6\3f͛{'q5I]m>{1EFGYy9~qsqp>9Nzahm>i뮚zͨEr/͕Mk&mV<}h^6 ،CeyDOAcZUEEoE+Ƃ`U7{ =cAd4珛}W mg-ܨq +?fkx*XmlXq] YS6H\X=.=g͛?ϒ'Þx;xz*o>i^v՛96c6heM{\Fty'}x8bڞ/y;bXӷ=j ?5lB<i`m:.σb7 իF7Xϻr/֏ۢ%EQ|eXP`U7{>i@\3ZM 4珛}`FlCn$-2Y.Åz{ŀet{E:{dˣo(ouT\GcFǗmt{FmSNZMntrTWMQ-?9X_NY'e`w%?t%9>R2=_%;sl1Qɳ?X2^=ǔI2q«x%Y 2o,eʜL`&J جL4P$q@J$Tl(oJ d= 7(kGQ@Ċh]гXuC 9X4&In" o"ϡ4"0zd,J[- /iƼ;1c!qzF ΄EW N sh{ӧ盃% \bDDDNH,E2|@8oOUWc KVl{_Cl/g#z*lw:&xi0v{kg}:,-`NR5@q 5/8[8OꐯUM#9];R,Ss@0FFVI5E~!O= ËV܋Ө:7ӊxLaI2wfu&K(CU)u JWO׾醣u'e!ai1TWE)bj!E[nFQHEc9c 1TtTw_AC],ٙ#{jvݖ@0(NU|olY>"@Q6$uߚlnj_iizt@gC-PDpU&DfEOY&: v*ѥ"vT'1s9"cf2D uV:rD `~xGE1A|_W/j|A0-82:w#T&!sJ,H*m8x>P,W N;YU$XޑRnLmӆRMts *rQoNCs]R~y6'ȓSگ LQa% >Tֺo-MaBdŰٞU00eѿtlp][k;1pU4$y5?> XKRئaت14Nwmgb]x k^a8#Xdz"a?ǛJmߝQ /P~Vwq峽]2ƙ L_ F2_Su ;ljuRK6om@QFt$dA >^c{R;@V@`^^٥7ê=//h:CఋKuKuaKXa.8bNb+{'͛N*sWoV"@t5;9$ s;'Vrx&*)X7状%9V3u`] pRh 6I=n$ծے>Mk="_TػHn~SR()np؄r]=ҌBAؑ->(6OEE h_⊻Ca# *<yp67Ԗt{:.0*nB0 m$.4׋B'bݢs3$!ʤ4G 91T+)P"%o$D!D_6TM;1NtoY%*PTt{;[uM,6) ]nz )Md qKˣHjPP5S@UT}ε.bR%R?U q>`^=ЛY'ql { Cx,hG`e6;;*h/,$Sf3ux2ВG@BlnK8xG}u)MQwp((O_`FwD$3tP̧8p>bI$XǶ\6Z)D\dmtas\CC׶{p¬tvk`4jq5zbh@A@ֳUk<vh]z)r0_gA%J<9+d`nJLO6%g;i5zr؎z#A_O#\Y?5tɐCy:&u; i y|M 3uˌNc<34b ߷2橙!sJNtʄm @1bGag&#}.@HeGb =PTpDhlB=8} SEZ/?;_ȗ?{q{gͫo+{_~_(?3/Ћ_?o޼~w>O_<_| ton^]g}.`? ٍ0w4[X@-gh=z˿?k?\O3]#3B[չUK;f[jw%;nFs*P< >,gϝG|*=&wb]}kG7T8Eˇk58w_0 $-X -"Y`uњ>df0f0[O06Xz 8OehєbZjMZx0,0Rܠw0F){> ,$8zޣT4w~Fm&kp62td9SNM rVsxVG%GW )Qum sf5A2nabA? Ι|Ûڿc6HKoQ#e`{FvB\ap j_b$!|ha_b1'bѭo2*|;8i987Rk UړSg,[pv)f$hvcס;TUuuo}hJop(pZ硗 ;UD^yo#߉ؑX!8z-3F’m+cKR*acM]-71@j>*>v ͆(wlttY0'ת5:yeOce?Xnmw٩ %s_Dv'^v w'dԡNy# x6 !G&7|=!)&͋Ū޵)/9"9]W!ǐ@1!IJi+3W`uIfV7]O;w_0Y Z=wn`d=ȀOa!NOqS f*_G ֿfW+g%KZ Bt0] *38=3' @x Kqj;qkk0qk'ћEۨMs(ɆKYzU%3l"_TL{WN<\Mf'".Fbf+DJ$9Ⱥ%}ؤN ޡ@]d)vg\IFZn'I9aR~Ĥ7uhu-Zo3$n hM ;a،+>5=:`, 'cV3CXMqw\3AfEӜh3uzCjY1Fp=]H-h= 4g)\ddۨsYueBTt$h8ZMeON{6;L勆åΐDg]`GP63vEͰDn=8Z>OPz(C󫦪MpBc) zlMsٍ0ة7a&DQY\)y_5EE8Xu /b͵gFIy7ޤ9~FrmSovDg7;#)ZOX$ }[9,+cz?UȗyA}]C Vap ʲXWG%dymbIzZpɼLv?#KܚO | ,cx]u8 auyiGrcS]U;} Ws >^"|m|hermDor мղp9m>.Ze&dz!c<_!޲ dDGG^h+9m&Aԓ @)<|3# UB'Łؔ\e8L=w}FZ2wrJ9BT-7B'Rbc'3G k0E N޿,h)x(Եſc)>] 8AB8R>~@4`di,#8FPyz\yd].])eK AVlYCބҘ^1ɼ Hu:HYHHz2xqA㭵|{ϐzV-۟\RO7ϺGRG1xL@%FpU۔uBԴ\YiD`1Qݞ!gaߥq6eaZîi$;w)N<K='J:N=eBMuoWߥAc%>vtGGDLIA6 + 1ۨ-r_} D@oyNz!L!ś]Z";w7ezFF þKK}\o>l-X֙f-la毖*>s@1*O;gơ{w :>(JjW.Zw$ j(4v0P"%:ċ(<<$U=ա{\ sTÝ%1k ֮5O5q#,v bm:M:k߫ӃW>lo|s`ІO_=q"(ӣ!8n78=R33:Ϗ@gϰ˛wo۞c끝p_Il7bIv, (ғ2NBPz}"@,*:`,oqk#M #QɋU1r* R{cR<܉ Uǧ]^ʶ~OQzոRZ^RfԈv( $)Ǖ(evn2A8ܴu صnSn`J1O,;iz/n{,w4a'=((eFko<,ÿS-X'> avwmB|ޗRhn_UfޖSWqܢu"3B H]BM-K4qVWPj8G3)ϮxSXHԢx$j+Dئu1Qpt .v"Eٮ &WKOW&}4RE\lYtNhWΑyPx"]!b,ɲ(I`#TϡwP,Sd[\']5?b?ikNeCV(>/p6#{JΖ=2_g.V;>%(9eټY>B\Idkq^#=ąB#LbQ&x8M)txuTmcLJg Z==H2Q*{3pdj[`cxm $^2:1RTNo~|X,6Шg=낥­*ҽTU =J8guL b%h> uRCT{]1)HulZba3"Ad=YABRzxErm2oRMk1t eץu1GBHs AW jL)|XLX9>Hh_ }d=cZҸ8`1Z pB従Zm2*)h^Vp"{UV9JLkgI?ZW..ATԬ!WIc4 ]q4D@zq'"aܵqe;ۆ&uQ(վJ .D `2˖2GÃq~ɭPJ0"Ȝmw<@MPʋb8В&+4_MQjk9fKh">ʴ7Cvb\|I`' <k g#6ca8O]qmN3 up;]4h掫/eg2eZf!Cg8+=^(<ʗӣg?Xb֐қGP(hGb -&Gh[1l{LdQ6l\a\L+,*tqPЮإI £!vcaum?r,zggQiU\Fg[DnZd@.DO먖FWUJV%mr[(^'_kJ,6Yl<[<((+HBH3>wdZU@7*uqZ#i{.F;0c0ϰQ QbQ%LMu5ϦjLwj ܎Me2c24pIP<MKq z-:a9N`Z3Ra)SR,)X)Qoнʟ2Pʘ#vBJ:FhM+vldth6mC8zvdF,:\+%uSb99t}$15RsmZCrф9h(3mEϳ|cqR-2 ϐ:b3_ޖC♋ͮz 1CC1qcL2>.ct$/foBy- EĀCr>Φ@UmUZ ѾF|s<*8#ifUK19U_'Ŕ^v,:ܓ^ W"3hލ.5pJͤ卄ǖMdAS[Xd u ^ B8I_n"up΢zb^=I.բSK-R5%I {$0@>ېfŖUTf.[bc,\pr`v$ϲEÉGLI.HjUqV`0f T;*BA)& K'2PFewgmam@xށj \Ka7Uw xEq9Uhm cư]hErGVMizus0#Wpk}@A[kҙ9'$=̐Q7$H+g|õ?f9gxL➅׃z5:+ք$L-_/ușto̒ʹ`Uԃ^xd͈مG^Gl)c_N.\pVB2*>F| YGר`6nsNfjϰ ;rTU$%!%iUmWہFQЬq AO%_0l/vtŸ]dãrYp4m c֧Ⱒ-0KEh,9\)MTFMŋ@)8 oZBj *(c*,8 , 4 '$\ĥ2jf*3mUt֡3H9 lLOכƝ Ca9LiC\3T_vHPe G!̜0uװ$R$Ɛnl;ә.d42\Uxi586u3At7ۻX;8Z/91iP!3yF|`0zrwU0 &R9tqٛ7NHۼ[3Zo ʝȈE.7yٹbN5džP˹bQ׾kM굼w'=Ng 'k/7\Ȋ_]"@+[CάrhvuS&euzf%Yi ܄( ) s:xYl+0K%כ,TV/(sK041 `/.=enCxς^8ҭ:y+\+$hUEsc<7sm ےqC$ ."sRXhלPS-#åqٙ 5x팂yFm v碮 N'Hڑ-S4GKQn)4=H.!zuɁh^Ƴs~SKͩ| A [;ǣ?|ϟ{^~^p|O?w|CS7>8iUZտLFwԹtCM嫢zE_^~/ԯ=y^;~>߽~_ӝ>9~6M~1?.GOo}ր]ISL[g Do* &&s*J5/f2bj4mqbb`a}Ol0u9-Sf:.((䞜aSXۮ";d'g>~f~GePd[\|][I!^Ɵd|OY{8?ǣҳ"d77|~o" OV,Cv8nszT͉GJFF$sD<>IVxλIr <.tSʛhm5c[:*k=#ϕ'6Y0%8ngɧɳ$wv3@P<7 T<+ 3ão<{XGzEz [H+ BUģC3s5@^'/^ymq6/!9eA)JS0|t=tԒS q .'R7j`AfeGC85lƍ7]rx? ,g$6Aъ4@Ηyy?rh-G>K=0-;x(sˤ*z >꫷v[j~c  Wezm7Dq,y ^Pcm= 幖T$7C!A|<.oպ51  bVW(֏ =3͸sisqy/2X1O: kƎ-cRَX=Y&QzՠHlݔa.ONfqem_w֛[qQDSI=3[ Jk>05\*`2-a@9Ŝ/Dϐ PbnKw,A^o;oW[1zU~s;?wx˿|{g/>_/x.tItǟ߽A% Ճʧl%%vTL6`?ɩ=LbzN7|./_zηO]~![~-Iw?x-ӓ8‡փ 6aP mj #Q8u(,`VS24濦z}d= s&DKFFAsCVz2%HIn*:X c% Fvlh}3ik֪V%e1,l"qt_i6ee3j_3#Qw# MpŨ`ֽ`Sx; L3\AlFSY9wӈj2X15>P+Hi5 'Baz <{$+Y, ZLHVN6'l֐KNp+j`u˴CF&I)*ZTK/+'dc>$N&Sj51rPAKĭT.q֜C .T'GL`X-bWD|hV@ދVU 0R%4fqGԻL#lȎlE'W5.2űpie9zy䚌Ҟ(y&>o),JGrs6ňЭhA+1Mrx+l>}0J n|6FN69BկO.ÙCGxXCH_o=^Eb `t 9A1Eu*fHCGXsVl"ߜ%y#ؿ[DjGGPNL^mRA+(N(<\*%fQ, `1ڑ7DQp3;:D7= RHbQ K-\gIqD4؎FEm@.Зc\U,ɆQ%N=;Bj7_W1hJDj7Xw?9]/}3~F=~ i ;d88_}W^H~W*Dԫ7miHM\E??8c=B\et}7X0Z0w"/wpٍ`=s1YWS^X:+sۍW8r ЛN2df7 G`jT5GbŒws~kF;v7'f'ݎ TZfZG"CQ*P3#Qlʕ}.iY!lH$/mF j e[."S[+D׍2t>0TE8rޏ[%o3;G}|^;7U7N850Vʽw4RѷsMѫc~Y>`z#k7!uFVR!MQ{XQ"Hz~dI<xtuN&'J$]{C!RCjU~sG]\RSjd3$Z:]I pk+ bBu) g- |OQtH y*W8Ұ`5:< $ʬhɔ3iz]E2i; B vy(Uܠ8P҅V @N?"xcHi:YNkYv%r啍IWaV+p9B|jk_?505>T{{5N^Vjtt pq d1,zl@$OFa V3=#кLpJk }WvI@.شjnE{˝M Z| |n^b>Og0?BwNGHYG`;mO#qKfhG4Y48z+j+|ˈV0:3M5"5_]KƱ^-5fQ)J\14H)xjAICS`h؛ђ0 D2 pwy8mz{ |6lsK QXv}y(R6k%Y/%S(i|ڭ 6dftaٖFF%'ܜ$%dssV'{ bY٘ᘪN0ixs/H:+O#&  ̜!!j`U ސJy`H&U''B:4hRv-l1 `Rs |P՝+a:-]1wZz]#pT P-2J@PyzOoxv>xx:%ێCQ\鋍>[o;I8֕' m#~{F=T_K.>kl?|:T82QtNG9>Y:bpi[XUܠWG"P&3g |&EP1o $ ኌ_VXzI]IF|DI1 endstream endobj 16 0 obj <>stream HW[XG ~G8/ Nۧt  UQhvQHyl3'Y@akg>x$o}{rjr暖)"鲹Xr~Kn}$ɪ{)k ^a{ 1 hJn_J5YV Uʦ#S{0Fmϙ=Y rZTwC&s5'{ai҈L38|ѹ ;o}'44842,޶cdNiǙiGx; 4s?4N$PQԴTH{ҧ#ލVaELJ:ߢ$gf<(ơ-%cYTak7Sߥu=IiEN3(bnՄ V} {>1)Fk' 4z~ۣW?mzϟ?p[؞~'?H*8$o_6 qGjubaT(~zÏqpg/~xWllׯ^u3M~|L{Z|?{ZOo|jԇl>DF?PH|X[F2$9sQf1 h-C}tk( ֍ԡQ,ӬZ#:t9J1n}-2Y(&}wUӀtLTzm#C8͖^dEtTb5ս;ϩ@5X=q, A4'(NυZB70٤eZ;@@[hW>E 1aNjQi=cf>"63Rgp9x\ԋƔ/GF=nYrFھ! tSnE_ s3g24ȿ<55[%$kJ*Y_21sajѾ\/K4ZLALWcd@ eCY:0 9FO_)I# eN(2VnńQ6\Heyɑ|x hGOL%T?.(Cp\x!3KPΡI.̹61_0ڵjjJd륬h5^;6*4>-s`{?#m_T탠nD`iƬj1 sh@*eũ暶Go{v;7Hn}۴=0?2/s:I@dcS |y>GCt.+`B'oIrli:VQ!שkjk̤^t7n{YH*nUF:uepaoN %r,՘bG?XqNVh94;AW_&]WHFIϝ3xSBHF8l4J%\-pQl4^DS^=&/+'4,ų Y5=IUo+ }Y@ȕbٌvϽ1MQWc,9zXk%e<Ɇ=Ҁ9Z5{K KYVSD SK=ES-ĕ^^Hx8=!GUVNJMmo6{FS(<S:H/.:´"HYXR" -A9!i[35՛c 5zuxR@5<rem\꿱^{{]Nso7P [ zr:!Pl]ͲSBT!h1'FW'I[ֳv]_|Zmkd N|؀]T_Aƣc=^[#Cs_9GPzCįa6Kg㱘gyD˚BR]ޒ-*=ޭ1(w[Ŵ7K#gfa[@6=KW]GT9l2 6d*JbC;݌k0:dr;w]{{*pF#%GוuO-^ KCMH8}ep;NsZѓޫ3;a3n sӷڑ1F B900Æ F%49}͓‘܎,VG2[8M55;jFgsmuHa`~hMxi)6!EXn"  R#3cxJ?mՂPUHfTQ}s|ǿ EBa;{<96x}{g415ަJ=ec,o)GO+ wJq!o`}4ѺAOZZV6wI(Ϻ+)e.=STZCrO6Wi =EW 2VZ);@OzlrSf [6ݚSUnQgQm( %Z+6BS|I{J[sfEunfWx1ƻ#b]ã$A1kŽ{ٵr]Bo:EQBvA%ϰ ll*j3.˚*K13&Ss68qV!<|Pg6L*G`M MHHOXNǧQPAřFMVzvhaL#{Dܘc2mN?:+GsM^ir=C'_n'mmjlaDeinb|*nW:xvB>9^g/?o{rБ{?vbם(?J?vyfv>2O%wy}NG'o~8~1lG_} 3o^~5{r|,% [<.uIE׽Wɧ9s$,:ʴMϧYpu.߯϶Iֈ6%K[^W\`w oJN^Բ&,MSؚZ!,əlsJlc9;3FIc ~'6tWD" M{rհ!+}s۟NMy6%,ss0MKXbOz+S-1̓7i/Oi0.l2U*cF[cqvBxy`e2i{7Jn4jS5T=/R H2&1N-[.4HR#:sX'g>0#Ķ.F"&SA ɃE^p-y85!p%]@= QцX;m3c k +ˁ갵[%lX4\}%^c*NyCD+L8=]ƽzG=xhmtpO˂kYʌ. }e@J( AC^bηL=v w҃^ۚ%B$.y4'îNFqS^ul$$'FG]Y%#Wy]h[ ] N(Sc-,rQ]K(z)Ӳ+Ӑk Bd TΘ :f~8R=0#LfhhXQAg v>l#3Aq_\O4ʄT"dP*Pat6"LϠ !<[ʐ?<JCmƎSp`2.j`Zz)lqg]FFlB/VnJ7S,+?ju½< bDw۷ˢǶy֤c0G4cD%$j3*@H %1h Ba{U5LZ9y7[lu ~vzmzC^Yֽ(웧mLݐhu^7'ӖzfI2sU`r?:xp6hTu;O[+EB;%ō(E]i0^vaEkuu^MKF0g wVQEf>f|s%o^xe/=zc]|q8c J<%A8Q 0'ՀG»8˫k'Wgצ9w`G}WpTH qP#hټUFhǂ|88P=};aO01F~Y~YzjPm7!(lj (>@p.Ss]BOV׸T{ևǠMa K{tqrry >K|O?#5N>L-w~@5K)nǾG9HFMj]xQƖ&l{ 8p?g5Ț@%'t^&)ԃZsezO ߨZ< |֐4|i6B5Ѥԋڶv@09톺vachUCz.8[c.]CyJm MK(ǷHTjSN!MTպle-*KTƍZJe)PW-UBǤ >*((F Two/؜i_UjE#M h̡[t}j`R}ےDA(^16 .ѻ9I؞4I!Hm8Helb_:NI3!,nĭ?^5sT\ ;MX mqpӤ,? ]gr#4 xئn(RPCzLQmwc92X* nǙ6HKN៎Dslbv(k9 |ASX(JuA-O:ݽ\gi}# K:vL]ȾaHbyҫSf\佞 R 4!y- 塞6(kx}. 爬Lɑ8*Idڈj}@[_4v.6[¶X/svTX%/S /訣s@v~cͩǨ3j!+| ֯TVObn9kRTb>ke N5rC^-Gm> L{oGVC&+j5e;fz-A!, x!hp .-Y MOP*zh-J_Ig?Kiqܑj|ZӏtDJ q4 u҆HXZ.ZZE5xLx1wS&7S#d݄2;RZrt. _sCc!AGZD9(ND+CsXqj(V:^,^/G|:9(qV0(ZZu EK 6e "?k ECN Phț6WNYhqZ[&+-+r:#glZ_Mu.i٠l1MƓu0m^N˹vwd锏gjF);FqK8e,NҸ@nEIۼLVft%͂Czձ4o„SHMT +], !Ec𴴻{Y(0YR0զ}ǾX@ &mgMΓ'YMnL3Ii޵|*>0'|ۇ/^˫Gϯޘ{߽1?_\=0XuHڒ_@qB%hEo[pV]|Nd˳kӜ{V]zuL;0#ǾY|r*x1JM8X6N Ѐ͹yTta g?F\rY;JN1"ց<8[䰎zy/{RɇCw;J~f;ʡz῝}v;}r} z}S]>wp˚[_z!>@,E,Ț?E!U__?}0d~2f)̞<շ#+҂͐@/T'(C>@0ᕱr!I/Q 8!_XdTxuSa głw y}C'NZ3f,Y3pXژ΂u 8îc,̊cBrWFp\e'︯3l YlfZOcl((+į |m }1ymlޑtVTO@&o#ݨ&'4?Xij/H;QVBW 'tu y[^.;EÝ0-1D5BL $&;"ϽmjR:TΎ+.@3<ml*9|K ᪑ܖ.FP7]{˾VfOK4rlEVNO0ìɭAFzD9H]Wh.Mia-R</龼{=ږ/qw"z{}{.m$Ç? 5DT}@CֽU[Kє}bE0TKHy`MF.]a!EHōL|vxӛd!wS!m_eo]wrAUd'XT3[?"$ܬC݆~ :V?/6XA#6AM?YfP˯H:y(> f'io\]IKv@Ćm;ZZ'K/>*_-~g<._l6ժOi1T]}5XHQL_u OzHafCPܥZ$Q/Ұ٨RmC6}IJhNkSЌQZGa#坝@1(PcՔHROhf H>KR@:뭗U\ w 23puiW3'd"PzIk:#5/!%#>VW#20vKCS%-'j̒'jh-yG*Hu?I?ڞ9h$^6)L='%=Ԃ5Յ{-1h35Lyo{=R!h[BYrW҄uNfR#^tr$R\-iZP k5{XKPFC7"bDXv\$RW7|)fm`C /ja}p YOdzoG#x.IUz5FKIΎ_q %!+z%u*ڠ=}&1KՃxI .k=_AUta]( cHՃH)Ja4gHw40ӯ͞IAZW 5r֬5J}%?ɛƦdmG68>Jta yt-ϛ=8ZJ%}]ˑrJ"ArAu*.`0uMV ?(dŧ:>ҳfBCߣ.~?ۏDžOx*=#鿟~~ǟ=w?8}Run"}O6:O`'>2۸t>JOa}HHO}8F>} >D>݇(t>A!>?nA7~$S.[E?.Uw QR1ݲF|ĥn\It*&neԎnnxٝ kVA.εtRQsnӛӌ}O7*Cs|[d #.0.yԑC}H!}G$d4}/ 6~yqET \7C*3$6_3ƛ_qu;c2Fw{|j&Ef3ヘѭYj!1SZq& =Sf a;gI3N0x nkhY񡧴)z57歑@[#c>l_h9̘; cv()?=YevxvDSN9Ƴ _DF+Sa"6)#ss>@Z#:<|%VFX:Q!zP  4İW16[vc7ůVn6Eudy9YvFޘx񰆃ʺ2o|&so[g/7]y"V,~-QeR ۧ(b[uGEZJQi̫_%6ӂv8P30ݓl(T.ylJYᾰa@ TCHm̐9T05yxyP+A  WLZ҃bWccoM(eF}Xs€Y/3MliA88q {G+W[.]v=w?Cxevë^;x8E6f,f=04a,er'v؍mau Z.c#@UlOt{{pr~Ryv?E@ŗzouw+'nkP7b^z1E"lLPʡӒzeBMu/5-qO" e44 7cwM36Jd#q^/*؎L{7Y)*r5zm('/d5{9izRj0sxM ^RK-T0UNU)%-9vx{VR+l~"5<#CnDp:l "ŏA"32:qY%I{-y=wA޴UwJe;)N;bc1Ϟ}(dLʎ%q+l>|<VG!,ȃ?fjopoj&JgŮ* p淭dgġD\uŴ,hXcIo?7MKOrG]ˌwU&n1ș>-[cn_:N ^y3.p\Ǒ3sZ&UYZ!Sx(ÑBE%# }dO3^[ޘCI.#P1~2GQBZўmU;B &Z3Lm36it9`_I;I{dpS7v#ZX_jpgkL,@+w8N ib #ld&zFٟ4ʌDjaQeg͜`G몽E趛ۇ<zxӫ,x<~!⩲@Qi`yS𹙓ʈ0 M$D#q Gޟz+p_Œo"y0 'Ė8NVMfn.'˵?띹Kf_-p0!n9Q9GvSW>JvNuB!Qd7*LPdQe^3ߋ QxӤQxˣ3&oUw5Ǩ]2#vх\ FZmߗa5jތ ua"Qus\ Bw3p&7Y֭ỖvY~o: s;me~cYrXW:!̹AvyMwr uђ,(00cLˏIB{?N AΈ37m=W]97^yC n) =O&36ak_׵N gnp854^(HWq&Gn>j0_\8FYxB?Ez/,%HY-py3a/ȓWqa*ī;hަ;h#ֻ+}.U}GŔ?Lr/o6rȥ;x#$$g3ZWznh)p1b۸tbTa'Ӈfys{(WӬ3Ωc2"?bJ]4p4rQp&8+39Ų j%N= `Z΋zdڂG4X@=[8E܅^|#4,){~,wPd|V<@u1[L/^0#%R[[+S;/+)x}`~ RiD АKy \ $`Fr!O8 al,[۪e|7Ջ{` @ !op 1)r=߭IنLi)ܴ͜^-Nwym.UA.{~ݠm EVg{gJz{]cWK$j#չu'p4jXI<(ki52^nZ?a2@(")*|QZgmE8`=~Fߠm%A``˘t6\ .ưqO*Oa 7 VzbfYu?cp^ '.V=P+5˷u| '{5w8%ja:x(x޳x4U \3/ xK4fE)o{qפz5>ZT_Cak\OCA x,f|N.S9rQz eΚ?o6~]ʡ{tlpٛCvh)Bsҥ* =ONeFƊ1,/u&Skʘ54$yjf iNxRЈ/ٜ;m`0Gm_aŚpNH0G[ Mj29q>ug*="ڠ8(c$K}SX/Í#-;cLj6wyɷfigSްO[挙x,X <8 ǩ #xoY}kך&`kr/Sw z )_'cq&)76Gt_ VU@]AQTk٭is-na] [˫o.J@A-B\ȗ ݌3{3_M*td9w& .qp JMӮ-sKJ]dLZa_|2^ ݮ52mop9gs#,ƿFt1%pmG8)` Jn nHYw݌$N];8J o;pu QK%Z/,&%[P DD[_PN,+^{ g+}$ u6?ʹ8WhQkysy+,ܝ= 5a-Q}n-N~JQyplc5=Py1 j 1JH3ٵÈD2RVpiWi`D':{Il&kt;'lAX:Fu`Y#RJj5<*'d˕HD,]':n#9V5du<]NPiH9Hy@{/箏5>r?x-;/qS1ab|xikLJkx},h*j۶G}Q|</VslgφFYŽsa)jx1f[\׷PkJp\"~ LI-sm -2e=;3"{7?M9&֠}%خӠ !@80XGxh=|!S?_8m!y{;$A6-y8  PSa8=^17R24- жL biޤEW34y4ru 8jzDH*y-K89(H_mN)nn:f PD/a HAHqhs@&Du}ym!a,Qyf=Zr<ndFyy;xIƆGK|I|001ȳk~i^#B Ǔ<x84=h)y%]ԾC.C\VO#V0Ŝ#\S:G[- vdr$4 V@vO[gͳs%svs6U.9U4k'@<,7oM6M@ݸ*qrI[pV/a& /ƵGQJy8)^sHSp4tV 緱Cy,WzQ(0bM>]ZT5x`ݦrwX̛6jhC4xLA"PP%|9T =}G^3iliH|;i|v@Ћqy75vdsM0A4si,Zm4i NÚ(iRoԥA uZpѢI Cſ讣ad fKPC kqS^>Drq`Mk kH,xRG 5͂Y0 iPz `e80JTyT#>]Oy:,N 9g7.tN`۪p+]󡲏B i\ՕU*yҁ &^{H'y ̑+p_+UhoVNaKLFJ;Q 1v0SJM92nr`Y3ۢvgDh蒳Z '#w)o:2xcmjAv|궇'MAR@4QAin<&>-BqF$d #5AxLM8l%Iߊ'#Tfڴړ zC4BmvM/ю]{ Q]5ݔ:Wr)eSX:5oLXk|;Ւ{~!mnKth)-kVe]{0Sl*t6Iޮ*ZN #2T2hOir;Ay 3=~!L0=k9^mO-raww[%fȎ(ۺxU,Rdxu\w~1XpUZ'YV E!aK`̀,[Nu"0svSgIS`#hֺ "~%]ʌQ9F89>s(pW"m.+Jlڱc!"/h W`_H`w8 QF% D< ̝JAAnӧOWw߼>=zۯ~w?ww?*cEt w_ɡbE])GI,lXgF|i\̔FIlsV͑Gzeo5bN "2l ETH*|%+.Pj00ʥDa{Wyֳ v/\=C!E$`n*`}A(*t).u?d/11@ ذ-ķKp/H0*hY;#j:IFt dȹJ8XX^tkx9CeB1@rOAZW; )_1A,l07+[|d'}BQ86Ղ*ZpƦY~CJMҪ 'VGBG0,\#SI7 v11֫M'`C3! ,s0Ԃ !$+"v0Wu@UccbQ.]> (%j ៰ ;#qŖj 4]ԝ1e$6IZSR$ *+@3ߣ[ZDTh}k*$3CLU{[PkC z=1(6lVGڐC--yn&[ {Xr(ٛÊ-JG^1帏ze29آs%H18OIll0}7o 'Z4gnbm|@-K] |qE-ꈷC nE GG2Q09e߰EeP*s]&i @T*e8LP,WDynWfq .Afڿ{þ9yBkHjRBOl9L)y̿(˫NS?+]5Y}GK7s> I*w Ev˪ Purup;ZqpN"<<(]:ly`\r&]G = kMH-U2X],ؒ|vڋf/K5rŴּ^ .AV>穕tYh)f b<؆ʃuFNH=ޑ 5۸T9dP";N"xF@lޔ<8G1ʦP.^&G bkXap C}g)k7 j'0]G1r\UD x7_:02[`٪snz/w˒[t$)5'-נܳt4pDF%a }7[PఉQέ|GMh[S5HCKZsZï؈겕ɀȭ e6`y|RhlY%.]ՠiWQf; -,%>S͖Ѷw%H;Aķ{{ +\S.ͅO|HQ-> OjrJF*]v6ZիVԐ!'^nۆ[)f]ݦuh`@6y {i6Udٲ)I؅668ײBlAA$̠R%x QMi#}N5?%˒[ t8?mw.@23iqgd[+rqU-19Ǣ鹱g%]z^7)~rD SN@0$y:}Ͽ\cq 04H^; 48y,mGhܦj_޶Iqx "nazEudIל* N7x #>rraUyj19Ffzqna @rJ#@ٗfcR( HMO%_JEm,xo{4H{(ddkvy.9-nlf[!"0Aꗺ`i{ ybiB>*w 3I(.]9v3t\fC}|{Ea2zg>H=c;S@wpHnJoUXOyB=gwyeL >L^,^~&œJv:J4́ h~jcbϬX2csh ܋%p=q_2d-~t9Dh "ǩr}Ɯ0bN/6JzI0rqpt%\VwiN6|L$χoԕIPF0Ulg|4 l!6/VQ) AqbGg7CfKS\"kxDP<}Ƅ5tӐFq6ۺ$̓6 G}d'L72V{ ȇunH\.E )s=t.U*ص8 ^ j64̧LJ z!]Q*J{hxY}@;g2SɄ4<Ȫ8 L)jrV(o9J(Rv7nwv^ q7\|t|\#:}~늞\l~|3JS~)J4JbN::9Z8Dq M&-88!fԞ x1s;ww~?za ?;uV > x2I͋ׄ]}b(:[b"n{^7T9FP8يK_bڲi)롷$O+98{XX+-K9x^k#K-с&wN98=;nm!m9lIC>b]ВPD m^AՅeHKa7*jഗގD=wrpقIniE ^i0޽1cFwv<~)j1g:lc*m*s)wP'M8EՁ`lbU~"<2p]3ɦ cWtIZ zsg4 anDy )X,vƷF {نhiWBZuFɋc}@"`B(DmG/*">~eMN>V#2;tܤdcd͟k2׎́6ڹTYo HqCS /!%C7Y0rG0DGO.$nib&^p7v}UP2[&b,Päx(vm'_ks_ʃĔ=I1YW.O,q+##Ñ9{hWg\X q,2< ܘʝݐC/kUCixUF::m[6qӳq|-̓I$IRfQy!ECF <aM91*ZfAeiTxu9/+x}-?H|;mk3V1~[<XE_?^[>bPXWPn>}=uV̚_Z]s䚿/F8>AWUu2@DJ!"ZW.~Z],RS>`#;W g\LZCaT&[Z | ij&aj0Hlv{@50QC!$vơIK={j>Fӱ }p_R0SI[5]C{D8hz8f1#R}- ݲ K/A('؄|-=0;ˋ8`XWg悧+׌w ㌈7)͜TrMEt @َ>|Ήc>5ALr@ "*3;qQ36?A EFUبlsvl9dcoS!Eyg N`K~-xKVܧQ%sYi%]Tz{rn/>άBԌًm2(=,åwx}7:9HVYmImoT`#>~%>-R- 2Iep]E3|8|Qb!C1}iں-pۅM>52Ɍx 9]i0ң^ʖ^{PO>tS3(,] I3&nҜO\^O %l5,uG'+3˙#RB$Ғؘl̈:adK0 d=ߦR'ٽR% f=ߧCiN؃ ,duIEh(kqAk`XH9b e~>6RjlB3,b7 ۯoS_49M!n/JҵU ?"ݎ %Pk* O endstream endobj 17 0 obj <>stream HlWK%7;w 8COz0GukdjS1Ap Y_[Y'u?bNk8^j`sM5č҃K?::ZvK:s MDy\gY8../pȥcvxt}Ι|<.$'i\Ǹo1i׌2DߌmG/Lpk!w~aH|} A?ۓN>њnN8 \g.aTE5ƪȇLGƜ|)t:VU%2NlHz3)Q)o+]јʉw~~!N,0@3]ٵ IԶ[RJB"ǭ;{}p@S _ND$]fY~TA q_[4bL5cGstrjZHnltkgc]=?@}#W~&;_!jF,ܴ+0*fq+w03`q߻H'n`3 S7Ӹ/(@S\f{Voyxk=J2_pѨOPɹ=~ͳJI23zB? q0+4V&Dc 8YiIn}|G{)fPXpBuE1c2bGNFk4vA;8$> F:8;cc60 Y2yΖS^a@0IG01: ҹ`,d(k^8"W겪`aiNL0L(C!l5lHBT-{Of).V.0-R20vapo >'Ē45$N_'%T\95Jo?"ok, &xpBY'{?0SE7ju_Q"?5E*O)e[X!'s5;/F$zHJwz$݊2s笈tZ9㒭;  ,^[H0OG `,T`Zg1ay*Cf7SXzVopT-zSZIldͧQ50 n}s+7kż^.kcA۾, bPMlx6K,E\]GyaB|KxF[.>Z[DF|~ܒ+5}@F{lzHx2Mc*Rst@ekIHS+:Tr4Z2bSY-9 srGwd[B#K70x{n9A 2*p'fD,#J>|HW1~&ZFvdm&Hoh53ĝzJ6N^kApGMs7l)x6K\KF2(7𗏩kl5 Y4(xlr- y#U#oThAvuaxn;I@ d2,8xbA9Uk{b:{Uz5\/Vjgqu!/]sbAtVr))lqIz9ݻ"!v DS6vwLZ.v,Tma7WoOvGzfpQk)\%Q_}>u,a@+w~ ducqUn7FzO>lq)Rg #7>dʀ(c=v9+oZ|혊IpJ3JpSfnpuĩWLG2%!{xbv:^X %DޖlYm7L-v1u}(&0BM Rf *1Xm9@mDٷd4n{"u+mȳEX15z65"?vDH`EZ{& H̓CRf5 4[D&dt4ܫ]a.1Q0޶o%E\yb\)] ]Bi[rp,"}(yLܩ<*}0nxJE[$gwܖxНN2<#10;;;7$ U 38Vu‘kP@Z3} =0}<2p7P@r u5TilK%BIΚw,m-Ew{dd|ظpR7>EBg[8z{5 K,HO}}ݕbቜJgkhA_0KlgLK}hɃJ݊ 9i~- ,*ƥz$%/ mfrq-I jϯ.$˫ҝ3xtnW [of_rҴ>g9F%e%Q2 [9 dxƥOrpS 6rYcO0Ћ7-;ݏlW.tmEE6O"\{EW{ O񺫐V>h 9q٦mk1qeaV_ ثVB$+D@k4ʤ̩m9aJ[ -V]&*6؋;Ń[:, mk> ]Wkm8`o}t1Yyzou}De]Vg:P/זl+ƋBtm"c9jكI`>'5!57TLSᜇҶ݃11&-߬h$QZdg˧x; TE5:*@!^62ZbY\!Ɛ1zK&&+L}azң<_ fgXpnO/(CF;fɵ4`#WZ$Wu8@H.-|Uy;*޵W7n~)!)y7jLɽ'5Zg; zx>Q0Y_% V7`,ꮠXT&!lԞ}D7dX//<T^0u 䭘V|EJ:..w޺I~ E5(9:rólg*OϓD<oϧ۾(M >o{l8IH__˧_|ǟ{#/ӗ_oǏ/tu띭]|* 񲥃6#Uiul%#޻E(i+ c ѓ{(A M#Ie/taefz'؏{0}3ۉ0Hu\fQcw{V)\}V_ќ[߫OC~oQ5AxxUU. == EMԻ=yL0Sv̝\viagG_sa7/)N H!# 2ME z n㐎Bc Cf[[{? +T+dh(MHi"WTiFncCzv^r݊7tΔ>NΟK+46RWuU: dtfv uI/(b:ffeuxai OOn{f;;0(fYcoQV`eYnЫq߿&=}x?,!?_/?Uϫ0҄*HDۤNJ5{ì1-MC2Y{3fR Pӓ_wљtųw||?z?!d3O?|xݛxDޞ2o޼xœt%|ÓWqo ۗn-鿗OB[׿+"8jiJidxA"}ySI6~.8.qZA@~L.-d.썭+{)=8\A blMUPD,u8fR FEEǔY2EK Mb] W=Ӱ@x#{5tM:ڮK܇àôhX6B:/z)0jpe||{9ˈF0`]t )J-4b,T YjǣgZH"Tל"졸pdmX*^1=兰^~UHGKpМ>Q_4aNy 3FK3Ǟ]ԻkBbLN,P,TH%ȬI.$y C _*-UP,^ۡ=!oL?jUg*hq=\WEOI֮~|3; g!Y%v3BnrswXʆ9HG3v0l'~I\]ZP+뭣 kPlS>mڧűD֥uG8DJ2% ϭA67A# B2 ѵyyJ{ӌovVD)$#=CSFiS #g%$PA/ >RF ߍi1QvPcg_.pⱞk9;Ġ$/>nuP/@H)Ch&лPq$1%x:˔|U&qFƧrK\Qü_e;211XR!:a̹OqCx$ pD욨F/en.< %ѠF/)Y jY0%T1.d,KBv r΃a/7bE;@p`}!bXOqr,I4jZ?7dNvj+0%%ɸ`ҳ9+qa :X{"@\3y)EiW]BHnrW%c.L2p:{@]pnmY9,S.Lh _*2w|'`2Ȗ:`1 9-`$RаM+ q;1O:0𝛋$_#%ж&Y a!h7y@J2T@ ee1Q/)nsE .x8h?{vw㚕摯/y [XZ?}&8@L89"D](B7qT=rTVVrW['6G00|!p{f!2oO+v2Y{=IӼ6Q!J EPɲ2~=@Sz%dÙh3a=\1P1Utg *͑_1ǭ+V2dEP!R24@:y)UQн{}bo<)r5or˃Hu5Ѕ=jK.C J C} "|uX#лΡK0 E s_JqiG*4ݴyٟCqpɑx>M^b8d>92 R3ez* ġu@dJ@?moB %9-"DMTtpC#$[^NS%VMHPV)ҨmS XT|^EC E]bt0ӳ;6,p bO7غ\|kQ_ĬLtvic?u!@S-Wz"(YyqKp^z|4qAĩMr 3f<^ʧV.%0dg,F4JJ'XOQƄnmY>BZ܁M_ U ͥu@J>e']nLo ,r6ZG P<zܽrQV Y%Qk׽ `E^V6Q~< wwY8؍DdhlGt^M+!cښE^܄ǯ4{\ iuF|`CTe7w( dQ񛓛c`g*V6p\Ʒz~KK8R%$&%杛:P+J͗!k4S1MtxK!X?1'g9pYg. nB,nU3J]SKG27qq"r2@jeCp<a?eQn_*Mv1+r꠼eˡzq8☖8Q<{i D!}DeI}1 a9i Oayy.EsdOf-mWaE8VM  (PtP|N`j(+.pn x M;B R*قXA^KM0^ZFYd&E_ a>SX#;ͪIǠ ~ d6/d2ws ֫࠲ZCk d>K>օ4aZ+C֑NeIZTA &jQ'H%i@NJ\ }I @dӤ|&RA^wYŻ_q,JEHu9mFTefIgjㅡ.Cn sx$gU(ON) AO, fLU&=@T l1,2Han2㣆-QU |a8EMsq$GW8$6P\ C T>%mur%(eoZR ,ќQ7Q1ި\Ɩ!5o2hz Ptk٦KI7V(zp ;b.*FEPX0`TXs<n#lj""ˇ{߾0xa#^9b6/`9|v8qI}PjXq ,֓, >:]m=J6i5*q#zL= ֡nK0FK'aYev=yӂ5y/_(IV-J"y CJUC><}yãϟ]^~~q{~ǣ?LmL#! moNpU(p`H1NyK[i\6w=ݤ-inۖeYI+h{IJ`wFY|_g9HLs?lcAeZ0`@TRڦYgJ,/~GRH)$*(V}`^eپvʐָ00XT_j]5LgRh.4w;{[>琷qc.C hS@W5&˪+XЁ/BpR!VN}5 !Ԡ" }v 6'{Jir=G֢XIs E׏2XTXCFUgD,f:eУeYvq]X2;b^{>Š نM߰EXM=([nJ1P);Y7s0C4XZ>`e1몹ex C dh/R`JmPeL07f722HPM1hUB"(ay@e]?!*%4u&kPpui)[y.aN U}>wD0G*#b M'(];zaȭQ+Jb\Eˀ\P`݆?Ǔ*2mIЖ MS' >747(‚x^.RSC8fj_DJ>Xtiqgý*uuۈz؆=]֤9 dHўY2D >sU'AQMW@ܴR2ְbtsGp#}kŞI}K0{HHIAphޏ~hġMԦ4Eکu)0TyInɬa S+VCQ*֑;G2`(t!9U=J{S[ΠmԿfx8#Lh~|n}kQAp|4|BCQzLɷzQj, SmIf=hG~b_ãgWw7/~~N4?>2O~w3C7zwo\}8ӫÏݼywxBn=|qsjA@8Dgg>ᯇ; +'}2,}!!!r x>i3p ,g9 «1-gpmHS:T}L|dAp at 7κųe,d"& dsﻪpsO͖J%+Z0Ehj_+}Y.cWm#%Ve}V(0F=SU*T󓝶 LieoA(}G]m7]SGw[4CיM žb'.RX7X8"3nnsL&Jr#j B!2YT>ሆq\%j!r;qB)46dN\-ԳӦ;NP'"*AXTNED,&}B(]ތ#۷4 b 1B(F*BY = nK_޾(!! S cg|y  ~}Av2M]# >%Wܿ3H)$>KxϣW> lVr!`rR $B,Mㄆ([ܹ%gP:Οf+eW|ӯ^j7F!a{#5J k5`uBD=!k pO9~e:. Wsa]ZipO= ipcAg]_Р]M<{&3gB{τ{&-Z{2 ^wd.#yotaq`嬷v달9IZ;bJ9KBs XaܧqRp3 "|.|z Nh<z!~`P^S/ÔdT mI?!JX#2 YqQq_BMP;n2L=Ѵ}lӻoޠ̚ޘxK)-D#.4s˗߽_e2tbt8$lu^<} wm;̾R{b<YFq 'EBsصx 垰d8L9ګYwlȻ^KI:EY@ʉ3I09%!lRM @2)UANh)=cGj iJOpO-L$ 36i73s5]*sxDhtt9SiKr|C燦a]R{]%h#aP~[B"-(U. c; iQȭ)l)qCQ  ]8]D wtp~H|WX^^P"Wu/7ZN SJkez]_cp@SdsϹ= -W~P[SWLŠ0Xٰ]-Zv)vђFPw11[ I*2U;U;W.qѽ'cT}*lG2pTwrS5OxWx .]/Ԑ♎<+[aqF|WsW)t"J0w€l"UOLz#-ȬYRT57/ o5KklmƷY"CӢ SBQ WRs:ɶ/P8a`2LȠ L^DKL̫fn]UVͶj,N\b;P.cPsYi,4)*r2܊T_nV+J%Pw3|58mh mN>ո M+58=ix7T 4v[j[j5׷V@Ro\Mb~쏋.l׳s~Y \ p=/x xIҌE tlΚWX>2X2㨹 ok7 9yu3$1q'sNɈ|wI<CCNKOśJqMhUFܗ'I2iv3 jߛv_NBbj9)yFRqco@h8ȋ8d ڿiH>M?,}q_mm@W0ӗd%Œ-)eqJR$ `PaXA 2M*yu=% :vyV(e[ oL7*!%.5%?E1 8]̀@I/O8a`R?.ǂ] lX0cƙ"pJ{J4j)οm[Z}mib!1X$"8LPdR g ^@fZvXW>rKdJv@tKy9ԄYNI[0)<^R2}벃4㨷+i/$?PO2CXyFiȦ6Sp=MvC|gL@ B?J$rqnk {1a)ݱTnnHkT/c3 {>y).]#^x[kzr[5P +5G(?itdvθt>7RZ}ʝy2zV{ASCB&pkWݨGm Qd{qP$$:fii Oځau\[n֑<$%}v+a#i,.c]f"^VL3׽a)Gm%Rbr\-ox2;={6FwO<J!P%U:6A, Q'2|[jAu* "YHd pgSeBJ@5-r{ Pul8T @%RX) Zhɿ[h`u0>vᕫBĵք \Y{yc "uζ  V=H7z"(iC: endstream endobj 28 0 obj <> endobj xref 0 35 0000000003 65535 f 0000000016 00000 n 0000041498 00000 n 0000000004 00001 f 0000000021 00000 f 0000041549 00000 n 0000046667 00000 n 0000046739 00000 n 0000047121 00000 n 0000071032 00000 n 0000073703 00000 n 0000094867 00000 n 0000116321 00000 n 0000138349 00000 n 0000147580 00000 n 0000151373 00000 n 0000169330 00000 n 0000192542 00000 n 0000048157 00000 n 0000063716 00000 n 0000042565 00000 n 0000000022 00001 f 0000000000 00001 f 0000042678 00000 n 0000044445 00000 n 0000043034 00000 n 0000043264 00000 n 0000042048 00000 n 0000211331 00000 n 0000044694 00000 n 0000043509 00000 n 0000046105 00000 n 0000046153 00000 n 0000042339 00000 n 0000000077 00000 n trailer <<2E3A232DA26DAD40B4BA526B7F172E8A>]>> startxref 211501 %%EOF podofo-0.9.3/test/CreationTest/CMakeLists.txt0000664000175000017500000000075710714372313021016 0ustar dominikdominikADD_EXECUTABLE(CreationTest CreationTest.cpp) TARGET_LINK_LIBRARIES(CreationTest ${PODOFO_LIB} ${PODOFO_LIB_DEPENDS}) SET_TARGET_PROPERTIES(CreationTest PROPERTIES COMPILE_FLAGS "${PODOFO_CFLAGS}") ADD_DEPENDENCIES(CreationTest ${PODOFO_DEPEND_TARGET}) # Copy the test samples over to the build tree ADD_CUSTOM_COMMAND( TARGET CreationTest POST_BUILD COMMAND "${CMAKE_COMMAND}" -E copy_directory "${CMAKE_CURRENT_SOURCE_DIR}/resources" "${CMAKE_CURRENT_BINARY_DIR}/resources" ) podofo-0.9.3/test/CreationTest/CreationTest.cpp0000664000175000017500000010476212347347566021407 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2005 by Dominik Seichter * * domseichter@web.de * * * * 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., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "../PdfTest.h" #include #include using namespace PoDoFo; #define CONVERSION_CONSTANT 0.002834645669291339 const char* pszLoremIpsum = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse lacinia sollicitudin viverra. Praesent augue tellus, feugiat vel tempus ac, semper in tellus. Maecenas et vehicula urna. Suspendisse ullamcorper molestie leo id aliquet. Mauris ultricies porttitor lectus vel facilisis. Integer euismod libero ut lectus mattis sed venenatis metus molestie. Aliquam feugiat, dolor a adipiscing ullamcorper, sapien orci ultrices erat, eget porttitor ipsum purus id magna. Morbi malesuada malesuada sagittis. Curabitur viverra posuere sem, quis condimentum eros viverra et. Pellentesque tristique aliquam orci a aliquam.\n\nIn hac habitasse platea dictumst. Maecenas vitae lorem velit. Donec at ultrices arcu. Phasellus et justo in quam fermentum volutpat. Nam vestibulum tempus lorem nec lacinia. Cras ac dignissim tortor. Morbi pellentesque, nisi sit amet sollicitudin accumsan, ante quam egestas lorem, a dapibus quam orci quis nulla. Donec quis orci ut lacus dictum sollicitudin at eget turpis. Nam condimentum iaculis enim, id volutpat est dapibus id. Quisque sed enim in est condimentum convallis. Cras at posuere ipsum. Cras tempor dui nunc, vel malesuada odio."; void WriteStringToStream( const PdfString & rsString, std::ostringstream & oss, PdfFont* pFont ) { PdfEncoding* pEncoding = new PdfIdentityEncoding( 0, 0xffff, true ); PdfRefCountedBuffer buffer = pEncoding->ConvertToEncoding( rsString, pFont ); pdf_long lLen = 0; char* pBuffer = NULL; std::auto_ptr pFilter = PdfFilterFactory::Create( ePdfFilter_ASCIIHexDecode ); pFilter->Encode( buffer.GetBuffer(), buffer.GetSize(), &pBuffer, &lLen ); oss << "<"; oss << std::string( pBuffer, lLen ); oss << ">"; free( pBuffer ); delete pEncoding; } void CreateUnicodeAnnotationText( PdfPage* pPage, PdfDocument* /*pDocument*/ ) { PdfString sJap(reinterpret_cast("「PoDoFo」は今から日本語も話せます。")); PdfAnnotation* pAnnotation = pPage->CreateAnnotation( ePdfAnnotation_Text, PdfRect( 400.0, 200.0, 20.0, 20.0 ) ); PdfString sGerman(reinterpret_cast("Unicode Umlauts: ÄÖÜß")); pAnnotation->SetTitle( sGerman ); pAnnotation->SetContents( sJap ); pAnnotation->SetOpen( true ); } void CreateUnicodeAnnotationFreeText( PdfPage* pPage, PdfDocument* pDocument ) { PdfString sJap(reinterpret_cast("「PoDoFo」は今から日本語も話せます。")); PdfFont* pFont = pDocument->CreateFont( "Arial Unicode MS", false, new PdfIdentityEncoding( 0, 0xffff, true ) ); PdfRect rect( 200.0, 200.0, 200.0, 200.0 ); /* PdfXObject xObj( rect, pDocument ); PdfPainter painter; painter.SetPage( &xObj ); painter.SetFont( pFont ); painter.SetColor( 1.0, 0.0, 0.0 ); painter.Rectangle( 10.0, 10.0, 100.0, 100.0 ); painter.FillAndStroke(); painter.DrawText( 100.0, 100.0, sJap ); painter.FinishPage(); */ std::ostringstream oss; oss << "BT" << std::endl << "/" << pFont->GetIdentifier().GetName() << " " << pFont->GetFontSize() << " Tf " << std::endl; WriteStringToStream( sJap, oss, pFont ); oss << "Tj ET" << std::endl; PdfDictionary fonts; fonts.AddKey(pFont->GetIdentifier().GetName(), pFont->GetObject()->Reference()); PdfDictionary resources; resources.AddKey( PdfName("Fonts"), fonts ); PdfAnnotation* pAnnotation = pPage->CreateAnnotation( ePdfAnnotation_FreeText, rect ); PdfString sGerman(reinterpret_cast("Unicode Umlauts: ÄÖÜß")); pAnnotation->SetTitle( sGerman ); pAnnotation->SetContents( sJap ); //pAnnotation->SetAppearanceStream( &xObj ); pAnnotation->GetObject()->GetDictionary().AddKey( PdfName("DA"), PdfString(oss.str()) ); pAnnotation->GetObject()->GetDictionary().AddKey( PdfName("DR"), resources ); } void LineTest( PdfPainter* pPainter, PdfPage* pPage, PdfDocument* pDocument ) { double x = 10000 * CONVERSION_CONSTANT; double y = pPage->GetPageSize().GetHeight() - 10000 * CONVERSION_CONSTANT; PdfFont* pFont; const double dLineLength = 50000 * CONVERSION_CONSTANT; // 5cm double h; double w; int i; /* pFont = pDocument->CreateFont( "Arial Unicode MS", new PdfIdentityEncoding( 0, 0xffff, true ) ); printf("GOT: %s\n", pFont->GetFontMetrics()->GetFontname() ); PdfString sJap(reinterpret_cast("「Po\tDoFo」は今から日本語も話せます。")); const long lUtf8BufferLen = 256; pdf_utf8 pUtf8Buffer[lUtf8BufferLen]; PdfString::ConvertUTF16toUTF8( sJap.GetUnicode(), sJap.GetUnicodeLength(), pUtf8Buffer, lUtf8BufferLen ); printf("UNIC: %s\n", pUtf8Buffer ); pFont->SetFontSize( 8.0 ); pPainter->SetFont( pFont ); pPainter->DrawText( 100.0, 100.0, sJap ); */ std::vector vecCharacters; vecCharacters.push_back( static_cast('C') ); vecCharacters.push_back( static_cast('G') ); vecCharacters.push_back( static_cast('a') ); vecCharacters.push_back( static_cast('c') ); vecCharacters.push_back( static_cast('e') ); vecCharacters.push_back( static_cast('l') ); vecCharacters.push_back( static_cast('o') ); vecCharacters.push_back( static_cast('p') ); vecCharacters.push_back( static_cast('s') ); vecCharacters.push_back( static_cast('r') ); vecCharacters.push_back( static_cast('y') ); vecCharacters.push_back( static_cast(' ') ); vecCharacters.push_back( static_cast('-') ); pFont = pDocument->CreateFont( "Comic Sans MS", false, false ); //, vecCharacters ); if( !pFont ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } pFont->SetFontSize( 16.0 ); const wchar_t* msg = L"Grayscale - Colorspace"; h = pFont->GetFontMetrics()->GetLineSpacing(); w = pFont->GetFontMetrics()->StringWidth( msg ); pPainter->SetFont( pFont ); pPainter->DrawText( 120000 * CONVERSION_CONSTANT, y - pFont->GetFontMetrics()->GetLineSpacing(), msg ); pPainter->Rectangle( 120000 * CONVERSION_CONSTANT, y - pFont->GetFontMetrics()->GetLineSpacing(), w, h ); pPainter->Stroke(); // Draw 10 lines in gray scale for( i = 0; i < 10; i++ ) { x += (10000 * CONVERSION_CONSTANT); pPainter->SetStrokeWidth( (i*1000) * CONVERSION_CONSTANT ); pPainter->SetStrokingGray( static_cast(i)/10.0 ); pPainter->DrawLine( x, y, x, y - dLineLength ); } x = 10000 * CONVERSION_CONSTANT; y -= dLineLength; y -= (10000 * CONVERSION_CONSTANT); pFont = pDocument->CreateFont( "Arial", true, false ); // arial bold - not italic if( !pFont ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } pFont->SetFontSize( 16.0 ); pPainter->SetFont( pFont ); pPainter->DrawText( 120000 * CONVERSION_CONSTANT, y - pFont->GetFontMetrics()->GetLineSpacing(), "RGB Colorspace" ); // Draw 10 lines in rgb for( i = 0; i < 10; i++ ) { x += (10000 * CONVERSION_CONSTANT); pPainter->SetStrokeWidth( (i*1000) * CONVERSION_CONSTANT ); pPainter->SetStrokingColor( static_cast(i)/10.0, 0.0, static_cast(10-i)/10.0 ); pPainter->DrawLine( x, y, x, y - dLineLength ); } x = 10000 * CONVERSION_CONSTANT; y -= dLineLength; y -= (10000 * CONVERSION_CONSTANT); pFont = pDocument->CreateFont( "Arial", false, true ); // arial italic - not bold if( !pFont ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } pFont->SetFontSize( 16.0 ); pPainter->SetFont( pFont ); pPainter->DrawText( 120000 * CONVERSION_CONSTANT, y - pFont->GetFontMetrics()->GetLineSpacing(), "CMYK Colorspace" ); // Draw 10 lines in cmyk for( i = 0; i < 10; i++ ) { x += (10000 * CONVERSION_CONSTANT); pPainter->SetStrokeWidth( (i*1000) * CONVERSION_CONSTANT ); pPainter->SetStrokingColorCMYK( static_cast(i)/10.0, 0.0, static_cast(10-i)/10.0, 0.0 ); pPainter->DrawLine( x, y, x, y - dLineLength ); } x = 20000 * CONVERSION_CONSTANT; y -= 60000 * CONVERSION_CONSTANT; pPainter->SetStrokeWidth( 1000 * CONVERSION_CONSTANT ); pPainter->SetStrokingColor( 0.0, 0.0, 0.0 ); pPainter->SetStrokeStyle( ePdfStrokeStyle_Solid ); pPainter->DrawLine( x, y, x + (100000 * CONVERSION_CONSTANT), y ); y -= (10000 * CONVERSION_CONSTANT); pPainter->SetStrokeStyle( ePdfStrokeStyle_Dash ); pPainter->DrawLine( x, y, x + (100000 * CONVERSION_CONSTANT), y ); y -= (10000 * CONVERSION_CONSTANT); pPainter->SetStrokeStyle( ePdfStrokeStyle_Dot ); pPainter->DrawLine( x, y, x + (100000 * CONVERSION_CONSTANT), y ); y -= (10000 * CONVERSION_CONSTANT); pPainter->SetStrokeStyle( ePdfStrokeStyle_DashDot ); pPainter->DrawLine( x, y, x + (100000 * CONVERSION_CONSTANT), y ); y -= (10000 * CONVERSION_CONSTANT); pPainter->SetStrokeStyle( ePdfStrokeStyle_DashDotDot ); pPainter->DrawLine( x, y, x + (100000 * CONVERSION_CONSTANT), y ); y -= (10000 * CONVERSION_CONSTANT); pPainter->SetStrokeStyle( ePdfStrokeStyle_Custom, "[7 9 2] 4" ); pPainter->DrawLine( x, y, x + (100000 * CONVERSION_CONSTANT), y ); y -= (10000 * CONVERSION_CONSTANT); //CreateUnicodeAnnotationText( pPage, pDocument ); CreateUnicodeAnnotationFreeText( pPage, pDocument ); return; /////////////////////// pPage = pDocument->CreatePage( PdfPage::CreateStandardPageSize( ePdfPageSize_A4 ) ); pPainter->SetPage( pPage ); x = 10000 * CONVERSION_CONSTANT; y = pPage->GetPageSize().GetHeight() - 10000 * CONVERSION_CONSTANT; char buffer[1024]; double dStroke = 0.01; double dLine = pPainter->GetFont()->GetFontMetrics()->GetLineSpacing(); for( i=0;i<23; i++ ) { sprintf( buffer, "Linewidth: %.3fpt", dStroke ); pPainter->DrawText( x, y, PdfString( buffer ) ); pPainter->Save(); pPainter->SetStrokeWidth( dStroke ); pPainter->DrawLine( x + 60000 * CONVERSION_CONSTANT, y + dLine/2.0, x + 140000 * CONVERSION_CONSTANT, y + dLine/2.0 ); pPainter->DrawLine( x + 60000 * CONVERSION_CONSTANT, y, x + 140000 * CONVERSION_CONSTANT, y ); pPainter->DrawLine( x + 60000 * CONVERSION_CONSTANT, y + dLine, x + 140000 * CONVERSION_CONSTANT, y + dLine ); pPainter->DrawLine( x + 60000 * CONVERSION_CONSTANT, y, x + 60000 * CONVERSION_CONSTANT, y + dLine ); pPainter->DrawLine( x + 140000 * CONVERSION_CONSTANT, y, x + 140000 * CONVERSION_CONSTANT, y + dLine ); pPainter->Restore(); dStroke += 0.05; y -= dLine*2.0; } } void RectTest( PdfPainter* pPainter, PdfPage* pPage, PdfDocument* pDocument ) { double x = 10000 * CONVERSION_CONSTANT; double y = pPage->GetPageSize().GetHeight() - 10000 * CONVERSION_CONSTANT; PdfFont* pFont; const double dWidth = 50000 * CONVERSION_CONSTANT; // 5cm const double dHeight = 30000 * CONVERSION_CONSTANT; // 3cm y -= dHeight; pFont = pDocument->CreateFont( "Arial" ); if( !pFont ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } pFont->SetFontSize( 16.0 ); pPainter->SetFont( pFont ); pPainter->DrawText( 125000 * CONVERSION_CONSTANT, y - pFont->GetFontMetrics()->GetLineSpacing(), "Rectangles" ); pPainter->SetStrokeWidth( 100 * CONVERSION_CONSTANT ); pPainter->SetStrokingColor( 0.0, 0.0, 0.0 ); pPainter->Rectangle( x, y, dWidth, dHeight ); pPainter->Stroke(); PdfString sMultiLine("Hello World! We try to draw text using PdfPainter and DrawMultiLineText into an rectangle - including wordwrapping."); pPainter->DrawMultiLineText( x, y, dWidth, dHeight, sMultiLine ); x += dWidth; x += 10000 * CONVERSION_CONSTANT; pPainter->SetStrokeWidth( 1000 * CONVERSION_CONSTANT ); pPainter->SetStrokingColor( 0.0, 0.0, 0.0 ); pPainter->Rectangle( x, y, dWidth, dHeight ); pPainter->Stroke(); y -= dHeight; y -= 10000 * CONVERSION_CONSTANT; x = 10000 * CONVERSION_CONSTANT; pPainter->SetStrokeWidth( 100 * CONVERSION_CONSTANT ); pPainter->SetStrokingColor( 1.0, 0.0, 0.0 ); pPainter->Rectangle( x, y, dWidth, dHeight ); pPainter->Stroke(); x += dWidth; x += 10000 * CONVERSION_CONSTANT; pPainter->SetStrokeWidth( 1000 * CONVERSION_CONSTANT ); pPainter->SetStrokingColor( 0.0, 1.0, 0.0 ); pPainter->Rectangle( x, y, dWidth, dHeight ); pPainter->Stroke(); y -= dHeight; y -= 10000 * CONVERSION_CONSTANT; x = 10000 * CONVERSION_CONSTANT; pPainter->SetStrokeWidth( 100 * CONVERSION_CONSTANT ); pPainter->SetStrokingColor( 0.0, 0.0, 0.0 ); pPainter->SetColor( 1.0, 0.0, 0.0 ); pPainter->Rectangle( x, y, dWidth, dHeight ); pPainter->FillAndStroke(); x += dWidth; x += 10000 * CONVERSION_CONSTANT; pPainter->SetStrokeWidth( 100 * CONVERSION_CONSTANT ); pPainter->SetStrokingColor( 0.0, 1.0, 0.0 ); pPainter->SetColor( 0.0, 0.0, 1.0 ); x = 0.0; y = 0.0; pPainter->Rectangle( x, y, 50000 * CONVERSION_CONSTANT, 50000 * CONVERSION_CONSTANT); pPainter->FillAndStroke(); y -= dHeight; y -= 10000 * CONVERSION_CONSTANT; x = (10000 * CONVERSION_CONSTANT) + dWidth; pPainter->DrawText( 120000 * CONVERSION_CONSTANT, y - pFont->GetFontMetrics()->GetLineSpacing(), "Triangles" ); // Draw a triangle at the current position pPainter->SetColor( 0.0, 1.0, 1.0 ); pPainter->MoveTo( x, y ); pPainter->LineTo( x+dWidth, y-dHeight ); pPainter->LineTo( x-dWidth, y-dHeight ); pPainter->ClosePath(); pPainter->Fill(); y -= dHeight; y -= 10000 * CONVERSION_CONSTANT; x = (10000 * CONVERSION_CONSTANT) + dWidth; pPainter->SetStrokingColor( 0.0, 0.0, 0.0 ); pPainter->MoveTo( x, y ); pPainter->LineTo( x+dWidth, y-dHeight ); pPainter->LineTo( x-dWidth, y-dHeight ); pPainter->ClosePath(); pPainter->Stroke(); } void TextTest( PdfPainter* pPainter, PdfPage* pPage, PdfDocument* pDocument ) { double x = 10000 * CONVERSION_CONSTANT; double y = pPage->GetPageSize().GetHeight() - 10000 * CONVERSION_CONSTANT; printf("Embedding Font\n"); printf("!!!!!!!!!!!!!!!\n"); pPainter->SetFont( pDocument->CreateFont( "Times New Roman" ) ); pPainter->GetFont()->SetFontSize( 24.0 ); printf("!!!!!!!!!!!!!!!\n"); y -= pPainter->GetFont()->GetFontMetrics()->GetLineSpacing(); pPainter->SetColor( 0.0, 0.0, 0.0 ); pPainter->DrawText( x, y, "Hallo Welt!" ); y -= pPainter->GetFont()->GetFontMetrics()->GetLineSpacing(); pPainter->GetFont()->SetUnderlined( true ); pPainter->SetStrokingColor( 1.0, 0.0, 0.0 ); pPainter->DrawText( x, y, "Underlined text in the same font!" ); pPainter->GetFont()->SetUnderlined( false ); y -= pPainter->GetFont()->GetFontMetrics()->GetLineSpacing(); pPainter->DrawText( x, y, "Disabled the underline again..." ); y -= pPainter->GetFont()->GetFontMetrics()->GetLineSpacing(); PdfFont* pFont = pDocument->CreateFont( "Arial" ); pFont->SetFontSize( 12.0 ); pPainter->SetFont( pFont ); pPainter->DrawText( x, y, "Normal" ); y -= pPainter->GetFont()->GetFontMetrics()->GetLineSpacing(); pPainter->GetFont()->SetUnderlined( true ); pPainter->DrawText( x, y, "Normal+underlinded" ); y -= pPainter->GetFont()->GetFontMetrics()->GetLineSpacing(); pPainter->GetFont()->SetUnderlined( false ); pFont->SetFontCharSpace( 100.0 ); pPainter->DrawText( x, y, "Mormal+spaced" ); y -= pPainter->GetFont()->GetFontMetrics()->GetLineSpacing(); pPainter->GetFont()->SetUnderlined( true ); pPainter->DrawText( x, y, "Normal+underlined+spaced" ); y -= pPainter->GetFont()->GetFontMetrics()->GetLineSpacing(); pPainter->GetFont()->SetUnderlined( false ); pFont->SetFontCharSpace( 0.0 ); y -= pPainter->GetFont()->GetFontMetrics()->GetLineSpacing(); pFont->SetFontScale( 50.0 ); pPainter->DrawText( x, y, "Condensed" ); y -= pPainter->GetFont()->GetFontMetrics()->GetLineSpacing(); pFont->SetFontCharSpace( 0.0 ); pPainter->GetFont()->SetUnderlined( true ); pPainter->DrawText( x, y, "Condensed+underlinded" ); y -= pPainter->GetFont()->GetFontMetrics()->GetLineSpacing(); pPainter->GetFont()->SetUnderlined( false ); pFont->SetFontCharSpace( 100.0 ); pPainter->DrawText( x, y, "Condensed+spaced" ); y -= pPainter->GetFont()->GetFontMetrics()->GetLineSpacing(); pPainter->GetFont()->SetUnderlined( true ); pPainter->DrawText( x, y, "Condensed+underlined+spaced" ); y -= pPainter->GetFont()->GetFontMetrics()->GetLineSpacing(); pPainter->GetFont()->SetUnderlined( false ); pFont->SetFontCharSpace( 0.0 ); y -= pPainter->GetFont()->GetFontMetrics()->GetLineSpacing(); pFont->SetFontScale( 200.0 ); pPainter->DrawText( x, y, "Expanded" ); y -= pPainter->GetFont()->GetFontMetrics()->GetLineSpacing(); pPainter->GetFont()->SetUnderlined( true ); pPainter->DrawText( x, y, "Expanded+underlinded" ); y -= pPainter->GetFont()->GetFontMetrics()->GetLineSpacing(); pPainter->GetFont()->SetUnderlined( false ); pFont->SetFontCharSpace( 100.0 ); pPainter->DrawText( x, y, "Expanded+spaced" ); y -= pPainter->GetFont()->GetFontMetrics()->GetLineSpacing(); pPainter->GetFont()->SetUnderlined( true ); pPainter->DrawText( x, y, "Expanded+underlined+spaced" ); y -= pPainter->GetFont()->GetFontMetrics()->GetLineSpacing(); pPainter->GetFont()->SetUnderlined( false ); pFont->SetFontCharSpace( 0.0 ); pFont->SetFontScale( 100.0 ); y -= pPainter->GetFont()->GetFontMetrics()->GetLineSpacing(); y -= pPainter->GetFont()->GetFontMetrics()->GetLineSpacing(); pPainter->GetFont()->SetStrikeOut( true ); pPainter->DrawText( x, y, "Strikeout" ); y -= pPainter->GetFont()->GetFontMetrics()->GetLineSpacing(); pPainter->GetFont()->SetUnderlined( false ); pPainter->DrawText( x, y, "PoDoFo rocks!" ); } void ImageTest( PdfPainter* pPainter, PdfPage* pPage, PdfDocument* pDocument ) { double y = pPage->GetPageSize().GetHeight() - 60000 * CONVERSION_CONSTANT; #ifdef PODOFO_HAVE_JPEG_LIB PdfImage image( pDocument ); #endif // PODOFO_HAVE_JPEG_LIB PdfRect rect( 0, 0, 50000 * CONVERSION_CONSTANT, 50000 * CONVERSION_CONSTANT ); PdfRect rect1( 80000 * CONVERSION_CONSTANT, 3000 * CONVERSION_CONSTANT, 20000 * CONVERSION_CONSTANT, 20000 * CONVERSION_CONSTANT ); PdfRect rect2( 40000 * CONVERSION_CONSTANT, y, 50000 * CONVERSION_CONSTANT, 50000 * CONVERSION_CONSTANT ); PdfXObject xObj( rect, pDocument ); PdfPainter pnt; // XObject painter #ifdef PODOFO_HAVE_JPEG_LIB image.LoadFromFile( "resources/lena.jpg" ); #endif // PODOFO_HAVE_JPEG_LIB pnt.SetPage( &xObj ); // Draw onto the XObject pnt.SetFont( pDocument->CreateFont( "Comic Sans MS" ) ); pnt.GetFont()->SetFontSize( 8.0 ); pnt.SetStrokingColor( 1.0, 1.0, 1.0 ); pnt.SetColor( 1.0, 1.0, 0.0 ); pnt.Rectangle( 0, 0, xObj.GetPageSize().GetWidth(), xObj.GetPageSize().GetHeight() ); pnt.Fill(); pnt.SetColor( 0.0, 0.0, 0.0 ); pnt.Rectangle( 0, 1000 * CONVERSION_CONSTANT, 1000 * CONVERSION_CONSTANT, 1000 * CONVERSION_CONSTANT ); pnt.Stroke(); pnt.DrawText( 0, 1000 * CONVERSION_CONSTANT, "I am a XObject." ); pnt.FinishPage(); printf("Drawing on the page!\n"); // Draw onto the page #ifdef PODOFO_HAVE_JPEG_LIB /* pPainter->DrawImage( 40000 * CONVERSION_CONSTANT, y, &image, 0.3, 0.3 ); pPainter->DrawImage( 40000 * CONVERSION_CONSTANT, y - (100000 * CONVERSION_CONSTANT), &image, 0.2, 0.5 ); pPainter->DrawImage( 40000 * CONVERSION_CONSTANT, y - (200000 * CONVERSION_CONSTANT), &image, 0.3, 0.3 ); */ pPainter->DrawImage( 0.0, pPage->GetPageSize().GetHeight() - image.GetHeight(), &image ); #endif // PODOFO_HAVE_JPEG_LIB pPainter->DrawXObject( 120000 * CONVERSION_CONSTANT, y - (50000 * CONVERSION_CONSTANT), &xObj ); pPainter->Rectangle( 120000 * CONVERSION_CONSTANT, y - (50000 * CONVERSION_CONSTANT), 1000 * CONVERSION_CONSTANT, 1000 * CONVERSION_CONSTANT ); pPainter->Fill(); PdfAnnotation* pAnnot1 = pPage->CreateAnnotation( ePdfAnnotation_Widget, rect1 ); PdfAnnotation* pAnnot2 = pPage->CreateAnnotation( ePdfAnnotation_Link, rect2 ); PdfAnnotation* pAnnot3 = pPage->CreateAnnotation( ePdfAnnotation_Text, PdfRect( 20.0, 20.0, 20.0, 20.0 ) ); PdfAnnotation* pAnnot4 = pPage->CreateAnnotation( ePdfAnnotation_FreeText, PdfRect( 70.0, 20.0, 250.0, 50.0 ) ); PdfAnnotation* pAnnot5 = pPage->CreateAnnotation( ePdfAnnotation_Popup, PdfRect( 300.0, 20.0, 250.0, 50.0 ) ); pAnnot1->SetTitle( PdfString("Author: Dominik Seichter") ); pAnnot1->SetContents( PdfString("Hallo Welt!") ); pAnnot1->SetAppearanceStream( &xObj ); PdfAction action( ePdfAction_URI, pDocument ); action.SetURI( PdfString("http://podofo.sf.net") ); //pAnnot2->SetDestination( pPage ); pAnnot2->SetAction( action ); pAnnot2->SetFlags( ePdfAnnotationFlags_NoZoom ); pAnnot3->SetTitle( "A text annotation" ); pAnnot3->SetContents( "Lorum ipsum dolor..." ); pAnnot4->SetContents( "An annotation of type ePdfAnnotation_FreeText." ); pAnnot5->SetContents( "A popup annotation." ); pAnnot5->SetOpen( true ); } void EllipseTest( PdfPainter* pPainter, PdfPage* pPage, PdfDocument* pDocument ) { PdfAnnotation* pFileAnnotation; double dX = 10000 * CONVERSION_CONSTANT; double dY = pPage->GetPageSize().GetHeight() - 40000 * CONVERSION_CONSTANT; pPainter->SetStrokingColor( 0.0, 0.0, 0.0 ); pPainter->Ellipse( dX, dY, 20000 * CONVERSION_CONSTANT, 20000 * CONVERSION_CONSTANT ); pPainter->Stroke(); dY -= 30000 * CONVERSION_CONSTANT; pPainter->SetColor( 1.0, 0.0, 0.0 ); pPainter->Ellipse( dX, dY, 20000 * CONVERSION_CONSTANT, 20000 * CONVERSION_CONSTANT ); pPainter->Fill(); PdfFileSpec file( "resources/lena.jpg", true, pDocument ); pFileAnnotation = pPage->CreateAnnotation( ePdfAnnotation_FileAttachement, PdfRect( 300.0, 400.0, 250.0, 50.0 ) ); pFileAnnotation->SetContents( "A JPEG image of Lena" ); pFileAnnotation->SetFileAttachement( file ); } void XObjectTest( PdfPainter* pPainter, PdfPage* pPage, PdfDocument* pDocument ) { double x = 10000 * CONVERSION_CONSTANT; double y = pPage->GetPageSize().GetHeight() - 10000 * CONVERSION_CONSTANT; const double dWidth = 180000 * CONVERSION_CONSTANT; // 18cm const double dHeight = 270000 * CONVERSION_CONSTANT; // 27cm pPainter->SetColor( 1.0, 0.8, 0.8 ); pPainter->Rectangle( x, y - dHeight, dWidth, dHeight ); pPainter->Fill(); // Das funktioniert immer PdfXObject xObj1( "resources/Illust.pdf", 0, pDocument ); pPainter->DrawXObject( x + 90000 * CONVERSION_CONSTANT, y - dHeight, &xObj1 ); pPainter->SetColor( 1.0, 0.0, 0.0 ); pPainter->Rectangle( x + 90000 * CONVERSION_CONSTANT, y - dHeight, 1000 * CONVERSION_CONSTANT, 1000 * CONVERSION_CONSTANT ); pPainter->Fill(); // Test XObject in XObject PdfRect rectX( 0, 0, 50000 * CONVERSION_CONSTANT, 50000 * CONVERSION_CONSTANT ); PdfXObject xObj3( rectX, pDocument ); PdfXObject xObj4( rectX, pDocument ); // Draw text onto the XObject3 pPainter->SetPage( &xObj3 ); pPainter->SetColor( 0.0, 1.0, 0.0 ); pPainter->Rectangle( 0.0, 0.0, rectX.GetWidth(), rectX.GetHeight() ); pPainter->Fill(); pPainter->SetFont( pDocument->CreateFont( "Comic Sans MS" ) ); pPainter->SetColor( 0.0, 0.0, 0.0 ); pPainter->DrawText( 0, 1000 * CONVERSION_CONSTANT, "I am XObject 3." ); pPainter->FinishPage(); // Draw text and pdf onto the XObject4 pPainter->SetPage( &xObj4 ); pPainter->SetColor( 0.0, 1.0, 0.0 ); pPainter->Rectangle( 0.0, 0.0, rectX.GetWidth(), rectX.GetHeight() ); pPainter->Fill(); pPainter->SetFont( pDocument->CreateFont( "Comic Sans MS" ) ); pPainter->SetColor( 0.0, 0.0, 0.0 ); pPainter->DrawText( 0, 1000 * CONVERSION_CONSTANT, "I am XObject 4." ); PdfXObject xObj5( "resources/Illust.pdf", 0, pDocument ); pPainter->DrawXObject( 5000 * CONVERSION_CONSTANT, 5000 * CONVERSION_CONSTANT, &xObj5, 0.1, 0.1 ); pPainter->FinishPage(); // Switch back to page and draw Xobject 3+4 pPainter->SetPage( pPage ); pPainter->DrawXObject( 20000 * CONVERSION_CONSTANT, y - 60000 * CONVERSION_CONSTANT, &xObj3 ); pPainter->DrawXObject( 120000 * CONVERSION_CONSTANT, y - 60000 * CONVERSION_CONSTANT, &xObj4 ); } void MMTest( PdfPainterMM* pPainter, PdfPage* pPage, PdfDocument* pDocument ) { long lX = 10000; long lY = static_cast(pPage->GetPageSize().GetHeight()/CONVERSION_CONSTANT) - 40000; pPainter->SetStrokingColor( 0.0, 0.0, 0.0 ); pPainter->EllipseMM( lX, lY, 20000, 20000 ); pPainter->Stroke(); lY -= 30000; pPainter->SetColor( 1.0, 0.0, 0.0 ); pPainter->EllipseMM( lX, lY, 20000, 20000 ); pPainter->Fill(); lY -= 60000; // let's test out the opacity features PdfExtGState trans( pDocument ); trans.SetFillOpacity( 0.5 ); pPainter->SetExtGState( &trans ); pPainter->SetColor( 1.0, 0.0, 0.0 ); pPainter->EllipseMM( lX, lY, 20000, 20000 ); pPainter->Fill(); pPainter->SetColor( 0.0, 1.0, 0.0 ); pPainter->EllipseMM( lX+20000, lY, 20000, 20000 ); pPainter->Fill(); pPainter->SetColor( 0.0, 0.0, 1.0 ); pPainter->EllipseMM( lX+10000, lY-10000, 20000, 20000 ); pPainter->Fill(); } void TableTest( PdfPainter* pPainter, PdfPage* pPage, PdfDocument* pDocument ) { int i,z; double dX = 10000 * CONVERSION_CONSTANT; double dY = (pPage->GetPageSize().GetHeight() - 40000 * CONVERSION_CONSTANT); PdfFont* pFont = pDocument->CreateFont( "Comic Sans MS" ); pFont->SetFontSize( 12.0f ); pPainter->SetFont( pFont ); const int nCols = 3; const int nRows = 10; PdfSimpleTableModel model( nCols, nRows ); for(i=0;iGetPageSize().GetHeight()/2.0 - 30000 * CONVERSION_CONSTANT; dX = 2000.0 * CONVERSION_CONSTANT; const int nCols2 = 5; const int nRows2 = 4; PdfSimpleTableModel model2( nCols2, nRows2 ); model2.SetAlignment( ePdfAlignment_Center ); model2.SetBackgroundColor( PdfColor( 0.3 ) ); model2.SetBackgroundEnabled( true ); for(i=0;iCreateRoot("PoDoFo Test Document" ); pPage = writer.CreatePage( PdfPage::CreateStandardPageSize( ePdfPageSize_A4 ) ); painter.SetPage( pPage ); pRoot->CreateChild( "Line Test", PdfDestination( pPage ) ); printf("Drawing the first page with various lines.\n"); TEST_SAFE_OP( LineTest( &painter, pPage, &writer ) ); pPage = writer.CreatePage( PdfPage::CreateStandardPageSize( ePdfPageSize_Letter ) ); painter.SetPage( pPage ); PdfString sLoremIpsum( pszLoremIpsum ); painter.DrawMultiLineText( 50.0, 50.0, pPage->GetMediaBox().GetWidth() - 100.0, pPage->GetMediaBox().GetHeight() - 100.0, sLoremIpsum ); painter.FinishPage(); /* pPage = writer.CreatePage( PdfPage::CreateStandardPageSize( ePdfPageSize_Letter ) ); painter.SetPage( pPage ); pRoot->Last()->CreateNext( "Rectangles Test", PdfDestination( pPage ) ); printf("Drawing the second page with various rectangle and triangles.\n"); TEST_SAFE_OP( RectTest( &painter, pPage, &writer ) ); pPage = writer.CreatePage( PdfPage::CreateStandardPageSize( ePdfPageSize_A4 ) ); painter.SetPage( pPage ); pRoot->Last()->CreateNext( "Text Test", PdfDestination( pPage ) ); printf("Drawing some text.\n"); TEST_SAFE_OP( TextTest( &painter, pPage, &writer ) ); pPage = writer.CreatePage( PdfPage::CreateStandardPageSize( ePdfPageSize_A4 ) ); painter.SetPage( pPage ); pRoot->Last()->CreateNext( "Image Test", PdfDestination( pPage ) ); printf("Drawing some images.\n"); TEST_SAFE_OP( ImageTest( &painter, pPage, &writer ) ); pPage = writer.CreatePage( PdfPage::CreateStandardPageSize( ePdfPageSize_A4 ) ); painter.SetPage( pPage ); pRoot->Last()->CreateNext( "Circle Test", PdfDestination( pPage ) ); printf("Drawing some circles and ellipsis.\n"); TEST_SAFE_OP( EllipseTest( &painter, pPage, &writer ) ); painter.FinishPage(); printf("Drawing some XObject's.\n"); pPage = writer.CreatePage( PdfPage::CreateStandardPageSize( ePdfPageSize_A4 ) ); painter.SetPage( pPage ); TEST_SAFE_OP( XObjectTest( &painter, pPage, &writer ) ); painter.FinishPage(); printf("Drawing using PdfTable.\n"); pPage = writer.CreatePage( PdfPage::CreateStandardPageSize( ePdfPageSize_A4 ) ); painter.SetPage( pPage ); pRoot->Last()->CreateNext( "PdfTable Test", PdfDestination( pPage ) ); TEST_SAFE_OP( TableTest( &painter, pPage, &writer ) ); painter.FinishPage(); printf("Drawing using PdfPainterMM.\n"); pPage = writer.CreatePage( PdfPage::CreateStandardPageSize( ePdfPageSize_A4 ) ); painterMM.SetPage( pPage ); pRoot->Last()->CreateNext( "MM Test", PdfDestination( pPage ) ); TEST_SAFE_OP( MMTest( &painterMM, pPage, &writer ) ); painterMM.FinishPage(); */ #if 0 /** Create a really large name tree to test the name tree implementation */ for( int zz=1;zz<500;zz++ ) { std::ostringstream oss; oss << "A" << zz; writer.GetNamesTree()->AddValue( "TestDict", PdfString( oss.str() ), PdfVariant( static_cast(zz) ) ); } writer.GetNamesTree()->AddValue( "TestDict", PdfString( "Berta" ), PdfVariant( 42L ) ); #endif printf("Setting document informations.\n\n"); // Setup the document information dictionary TEST_SAFE_OP( writer.GetInfo()->SetCreator ( PdfString("CreationTest - A simple test application") ) ); TEST_SAFE_OP( writer.GetInfo()->SetAuthor ( PdfString("Dominik Seichter") ) ); TEST_SAFE_OP( writer.GetInfo()->SetTitle ( PdfString("Test Document") ) ); //TEST_SAFE_OP( writer.GetInfo()->SetSubject ( PdfString("Testing the PDF Library") ) ); TEST_SAFE_OP( writer.GetInfo()->SetSubject ( PdfString(reinterpret_cast("「PoDoFo」は今から日本語も話せます。") ) ) ); TEST_SAFE_OP( writer.GetInfo()->SetKeywords( PdfString("Test;PDF;") ) ); //xTEST_SAFE_OP( writer.AttachFile( PdfFileSpec("../../../podofo/test/CreationTest/CreationTest.cpp", true, &writer ) ) ); TEST_SAFE_OP( writer.Write( argv[1] ) ); //TEST_SAFE_OP( writer.Close() ); #ifdef TEST_MEM_BUFFER // --- const char* pszMemFile = "./mem_out.pdf"; FILE* hFile; PdfRefCountedBuffer buffer; PdfOutputDevice device( &buffer ); printf("Writing document from a memory buffer to: %s\n", pszMemFile ); TEST_SAFE_OP( writer.Write( &device ) ); hFile = fopen( pszMemFile, "wb" ); if( !hFile ) { fprintf( stderr, "Cannot open file %s for writing.\n", pszMemFile ); return ePdfError_InvalidHandle; } long lBufferLen = device.GetLength(); printf("lBufferLen=%li\n", lBufferLen ); printf("Wrote=%i\n", static_cast(fwrite( buffer.GetBuffer(), lBufferLen, sizeof( char ), hFile )) ); fclose( hFile ); #endif return 0; } podofo-0.9.3/test/PdfTest.h0000664000175000017500000000100711460071654015364 0ustar dominikdominik #include /* Common defines needed in all tests */ #define TEST_SAFE_OP( x ) try { x; } catch( PdfError & e ) { \ e.AddToCallstack( __FILE__, __LINE__, NULL ); \ e.PrintErrorMsg();\ return e.GetError();\ } #define TEST_SAFE_OP_IGNORE( x ) try { x; } catch( PdfError & e ) { \ e.AddToCallstack( __FILE__, __LINE__, NULL ); \ e.PrintErrorMsg();\ } podofo-0.9.3/test/FilterTest/0000775000175000017500000000000012356565164015742 5ustar dominikdominikpodofo-0.9.3/test/FilterTest/CMakeLists.txt0000664000175000017500000000036310614703752020474 0ustar dominikdominikADD_EXECUTABLE(FilterTest FilterTest.cpp) TARGET_LINK_LIBRARIES(FilterTest ${PODOFO_LIB} ${PODOFO_LIB_DEPENDS}) SET_TARGET_PROPERTIES(FilterTest PROPERTIES COMPILE_FLAGS "${PODOFO_CFLAGS}") ADD_DEPENDENCIES(FilterTest ${PODOFO_DEPEND_TARGET}) podofo-0.9.3/test/FilterTest/FilterTest.cpp0000664000175000017500000002457411460071654020536 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2006 by Dominik Seichter * * domseichter@web.de * * * * 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., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "../PdfTest.h" #include #include using namespace PoDoFo; namespace { const char pTestBuffer1[] = "Man is distinguished, not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure."; // We treat the buffer as _excluding_ the trailing \0 const pdf_long lTestLength1 = strlen(pTestBuffer1); const char pTestBuffer2[] = { 0x01, 0x64, 0x65, 0xFE, 0x6B, 0x80, 0x45, 0x32, 0x88, 0x12, 0x71, 0xEA, 0x01, 0x01, 0x64, 0x65, 0xFE, 0x6B, 0x80, 0x45, 0x32, 0x88, 0x12, 0x71, 0xEA, 0x03, 0x01, 0x64, 0x65, 0xFE, 0x6B, 0x80, 0x45, 0x32, 0x88, 0x12, 0x71, 0xEA, 0x02, 0x01, 0x64, 0x65, 0xFE, 0x6B, 0x80, 0x45, 0x32, 0x88, 0x12, 0x71, 0xEA, 0x00, 0x01, 0x64, 0x65, 0xFE, 0x6B, 0x80, 0x45, 0x32, 0x88, 0x12, 0x71, 0xEA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; const pdf_long lTestLength2 = 6*13; void test_filter( EPdfFilter eFilter, const char * pTestBuffer, const pdf_long lTestLength ) { char* pEncoded; char* pDecoded; pdf_long lEncoded; pdf_long lDecoded; std::auto_ptr pFilter = PdfFilterFactory::Create( eFilter ); if( !pFilter.get() ) { printf("!!! Filter %i not implemented.\n", eFilter); return; } printf("Testing Algorithm %i:\n", eFilter); printf("\t-> Testing Encoding\n"); try { pFilter->Encode( pTestBuffer, lTestLength, &pEncoded, &lEncoded ); } catch( PdfError & e ) { if( e == ePdfError_UnsupportedFilter ) { printf("\t-> Encoding not supported for filter %i.\n", eFilter ); return; } else { e.AddToCallstack( __FILE__, __LINE__ ); throw e; } } printf("\t-> Testing Decoding\n"); try { pFilter->Decode( pEncoded, lEncoded, &pDecoded, &lDecoded ); } catch( PdfError & e ) { if( e == ePdfError_UnsupportedFilter ) { printf("\t-> Decoding not supported for filter %i.\n", eFilter); return; } else { e.AddToCallstack( __FILE__, __LINE__ ); throw e; } } printf("\t-> Original Data Length: %li\n", lTestLength ); printf("\t-> Encoded Data Length: %li\n", lEncoded ); printf("\t-> Decoded Data Length: %li\n", lDecoded ); if( static_cast(lTestLength) != lDecoded ) { fprintf( stderr, "Error: Decoded Length != Original Length\n"); /* fprintf( stderr, "Data:\n%s\n", pEncoded ); fprintf( stderr, "DecodedData:\n%s\n", pDecoded ); */ PODOFO_RAISE_ERROR( ePdfError_TestFailed ); } if( memcmp( pTestBuffer, pDecoded, lTestLength ) != 0 ) { printf("\t-> Original Data: <%s>\n", pTestBuffer ); printf("\t-> Encoded Data: <%s>\n", pEncoded ); printf("\t-> Decoded Data: <%s>\n", pDecoded ); fprintf( stderr, "Error: Decoded Data does not match original data.\n"); PODOFO_RAISE_ERROR( ePdfError_TestFailed ); } printf("\t-> Test succeeded!\n"); } void test_filter_queque( const char* pBuffer, long lLen ) { char* pEncoded; pdf_long lEncoded; char* pDecoded; pdf_long lDecoded; TVecFilters filters; filters.push_back( ePdfFilter_ASCIIHexDecode ); filters.push_back( ePdfFilter_ASCII85Decode ); filters.push_back( ePdfFilter_FlateDecode ); printf("Testing queque of filters:\n"); printf("\tePdfFilter_ASCIIHexDecode\n"); printf("\tePdfFilter_ASCII85Decode\n"); printf("\tePdfFilter_FlateDecode\n"); PdfMemoryOutputStream stream; PdfOutputStream* pEncode = PdfFilterFactory::CreateEncodeStream( filters, &stream ); pEncode->Write( pBuffer, lLen ); pEncode->Close(); delete pEncode; lEncoded = stream.GetLength(); pEncoded = stream.TakeBuffer(); PdfMemoryOutputStream stream2; PdfOutputStream* pDecode = PdfFilterFactory::CreateDecodeStream( filters, &stream2 ); pDecode->Write( pEncoded, lEncoded ); pDecode->Close(); delete pDecode; lDecoded = stream2.GetLength(); pDecoded = stream2.TakeBuffer(); printf("\t-> Original Data Length: %li\n", lLen ); printf("\t-> Encoded Data Length: %li\n", lEncoded ); printf("\t-> Decoded Data Length: %li\n", lDecoded ); if( lDecoded != lLen ) { fprintf( stderr, "Error: Decoded data length does not match original data length.\n"); PODOFO_RAISE_ERROR( ePdfError_TestFailed ); } if( memcmp( pBuffer, pDecoded, lLen ) != 0 ) { printf("\t-> Original Data: <%s>\n", pBuffer ); printf("\t-> Encoded Data: \n<%s>\n", pEncoded ); printf("\t-> Decoded Data: \n<%s>\n", pDecoded ); fprintf( stderr, "Error: Decoded Data does not match original data.\n"); PODOFO_RAISE_ERROR( ePdfError_TestFailed ); } free( pDecoded ); free( pEncoded ); } void test_stream( const char* pBuffer, pdf_long lLen ) { char* pDecoded; pdf_long lDecoded; PdfObject object; PdfMemStream stream( &object ); printf("Testing PdfStream:\n"); stream.Set( const_cast(pBuffer), lLen ); stream.GetFilteredCopy( &pDecoded, &lDecoded ); printf("\t-> Original Data Length: %li\n", lLen ); printf("\t-> Encoded Data Length: %lu\n", stream.GetLength() ); printf("\t-> Decoded Data Length: %li\n", lDecoded ); if( lDecoded != lLen ) { fprintf( stderr, "Error: Decoded data length does not match original data length.\n"); PODOFO_RAISE_ERROR( ePdfError_TestFailed ); } if( memcmp( pBuffer, pDecoded, lLen ) != 0 ) { printf("\t-> Original Data: <%s>\n", pBuffer ); printf("\t-> Decoded Data: \n<%s>\n", pDecoded ); fprintf( stderr, "Error: Decoded Data does not match original data.\n"); PODOFO_RAISE_ERROR( ePdfError_TestFailed ); } free( pDecoded ); } } // end anon namespace int main() { printf("This test tests all filters of PoDoFo\n"); printf("---\n"); printf("ePdfFilter_ASCIIHexDecode = 0\n"); printf("ePdfFilter_ASCII85Decode = 1\n"); printf("ePdfFilter_LZWDecode = 2\n"); printf("ePdfFilter_FlateDecode = 3\n"); printf("ePdfFilter_RunLengthDecode = 4\n"); printf("ePdfFilter_CCITTFaxDecode = 5\n"); printf("ePdfFilter_JBIG2Decode = 6\n"); printf("ePdfFilter_DCTDecode = 7\n"); printf("ePdfFilter_JPXDecode = 8\n"); printf("ePdfFilter_Crypt = 9\n"); // Data from stream of obj 9 0 R const char pszInputAscii85Lzw[] = "J..)6T`?q0\"W37&!thJ^C,m/iL/?:-g&uFOK1b,*F;>>qM[VuU#oJ230p2o6!o^dK\r=tpu7Tr'VZ1gWb9&Im[N#Q~>"; pdf_long lLargeBufer1 = strlen(pszInputAscii85Lzw) * 6; pdf_long lLargeBufer2 = strlen(pszInputAscii85Lzw) * 6; char* pLargeBuffer1 = static_cast(malloc( strlen(pszInputAscii85Lzw) * 6 )); char* pLargeBuffer2 = static_cast(malloc( strlen(pszInputAscii85Lzw) * 6 )); std::auto_ptr pFilter = PdfFilterFactory::Create( ePdfFilter_ASCII85Decode ); pFilter->Decode( pszInputAscii85Lzw, strlen(pszInputAscii85Lzw), &pLargeBuffer1, &lLargeBufer1 ); pFilter->Encode( pLargeBuffer1, lLargeBufer1, &pLargeBuffer2, &lLargeBufer2 ); if( memcmp( pszInputAscii85Lzw, pLargeBuffer2, lLargeBufer2 ) != 0 ) { printf("\tROACH -> Original Data: <%s>\n", pszInputAscii85Lzw ); printf("\tROACH -> Encoded Data: <%s>\n", pLargeBuffer1 ); printf("\tROACH -> Decoded Data: <%s>\n", pLargeBuffer2 ); fprintf( stderr, "Error: Decoded Data does not match original data.\n"); PODOFO_RAISE_ERROR( ePdfError_TestFailed ); } if( static_cast(strlen(pszInputAscii85Lzw)) != lLargeBufer2 ) { fprintf( stderr, "ROACH Error: Decoded Length != Original Length\n"); fprintf( stderr, "ROACH Original: %li\n", strlen(pszInputAscii85Lzw) ); fprintf( stderr, "ROACH Encode: %li\n", lLargeBufer2 ); PODOFO_RAISE_ERROR( ePdfError_TestFailed ); } // ASCII 85 decode and re-encode delivers same results printf("ROACH ASCII encode/decode OK\n"); try { for( int i =0; i<=ePdfFilter_Crypt; i++ ) { test_filter( static_cast(i), pTestBuffer1, lTestLength1 ); test_filter( static_cast(i), pTestBuffer2, lTestLength2 ); } test_filter_queque( pTestBuffer1, lTestLength1 ); test_filter_queque( pTestBuffer2, lTestLength2 ); test_stream( pTestBuffer1, lTestLength1 ); test_stream( pTestBuffer2, lTestLength2 ); } catch( PdfError & e ) { e.PrintErrorMsg(); return e.GetError(); } printf("All tests sucessfull!\n"); return 0; } podofo-0.9.3/test/unit/0000775000175000017500000000000012356565164014634 5ustar dominikdominikpodofo-0.9.3/test/unit/FontTest.cpp0000664000175000017500000001342211434740242017074 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2009 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "FontTest.h" #include #include #include FT_FREETYPE_H using namespace PoDoFo; CPPUNIT_TEST_SUITE_REGISTRATION( FontTest ); void FontTest::setUp() { m_pDoc = new PdfMemDocument(); m_pVecObjects = new PdfVecObjects(); m_pFontCache = new PdfFontCache( m_pVecObjects ); } void FontTest::tearDown() { delete m_pDoc; delete m_pFontCache; delete m_pVecObjects; } #if defined(PODOFO_HAVE_FONTCONFIG) void FontTest::testFonts() { FcObjectSet* objectSet = NULL; FcFontSet* fontSet = NULL; FcPattern* pattern = NULL; FcConfig* pConfig = NULL; // Initialize fontconfig CPPUNIT_ASSERT_EQUAL( !FcInit(), false ); pConfig = FcInitLoadConfigAndFonts(); CPPUNIT_ASSERT_EQUAL( !pConfig, false ); // Get all installed fonts pattern = FcPatternCreate(); objectSet = FcObjectSetBuild( FC_FAMILY, FC_STYLE, FC_FILE, FC_SLANT, FC_WEIGHT, NULL ); fontSet = FcFontList( NULL, pattern, objectSet ); FcObjectSetDestroy( objectSet ); FcPatternDestroy( pattern ); if( fontSet ) { printf("Testing %i fonts\n", fontSet->nfont ); int j; for (j = 0; j < fontSet->nfont; j++) { testSingleFont( fontSet->fonts[j], pConfig ); } FcFontSetDestroy( fontSet ); } // Shut fontconfig down // Causes an assertion in fontconfig FcFini(); } void FontTest::testSingleFont(FcPattern* pFont, FcConfig* pConfig) { std::string sFamily; std::string sPath; bool bBold; bool bItalic; if( GetFontInfo( pFont, sFamily, sPath, bBold, bItalic ) ) { std::string sPodofoFontPath = m_pFontCache->GetFontConfigFontPath( pConfig, sFamily.c_str(), bBold, bItalic ); std::string msg = "Font failed: " + sPodofoFontPath; EPdfFontType eFontType = PdfFontFactory::GetFontType( sPath.c_str() ); if( eFontType == ePdfFontType_TrueType ) { // Only TTF fonts can use identity encoding PdfFont* pFont = m_pDoc->CreateFont( sFamily.c_str(), bBold, bItalic, new PdfIdentityEncoding() ); CPPUNIT_ASSERT_EQUAL_MESSAGE( msg, pFont != NULL, true ); } else if( eFontType != ePdfFontType_Unknown ) { PdfFont* pFont = m_pDoc->CreateFont( sFamily.c_str(), bBold, bItalic ); CPPUNIT_ASSERT_EQUAL_MESSAGE( msg, pFont != NULL, true ); } else { printf("Ignoring font: %s\n", sPodofoFontPath.c_str()); } } } void FontTest::testCreateFontFtFace() { FT_Face face; FT_Error error; // TODO: Find font file on disc! error = FT_New_Face( m_pDoc->GetFontLibrary(), "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 0, &face ); if( !error ) { PdfFont* pFont = m_pDoc->CreateFont( face ); CPPUNIT_ASSERT_MESSAGE( "Cannot create font from FT_Face.", pFont != NULL ); } } bool FontTest::GetFontInfo( FcPattern* pFont, std::string & rsFamily, std::string & rsPath, bool & rbBold, bool & rbItalic ) { FcChar8* family = NULL; FcChar8* file = NULL; int slant; int weight; if( FcPatternGetString(pFont, FC_FAMILY, 0, &family) == FcResultMatch ) { rsFamily = reinterpret_cast(family); if( FcPatternGetString(pFont, FC_FILE, 0, &file) == FcResultMatch ) { rsPath = reinterpret_cast(file); if( FcPatternGetInteger(pFont, FC_SLANT, 0, &slant) == FcResultMatch ) { if(slant == FC_SLANT_ROMAN) rbItalic = false; else if(slant == FC_SLANT_ITALIC) rbItalic = true; else return false; if( FcPatternGetInteger(pFont, FC_WEIGHT, 0, &weight) == FcResultMatch ) { if(weight == FC_WEIGHT_MEDIUM) rbBold = false; else if(weight == FC_WEIGHT_BOLD) rbBold = true; else return false; return true; } } //free( file ); } //free( family ); } return false; } #endif podofo-0.9.3/test/unit/EncodingTest.h0000664000175000017500000000441011043316236017354 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2008 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #ifndef _ENCODING_TEST_H_ #define _ENCODING_TEST_H_ #include namespace PoDoFo { class PdfEncoding; }; /** This test tests the various class PdfEncoding classes */ class EncodingTest : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE( EncodingTest ); CPPUNIT_TEST( testDifferences ); CPPUNIT_TEST( testDifferencesEncoding ); CPPUNIT_TEST( testDifferencesObject ); CPPUNIT_TEST( testUnicodeNames ); CPPUNIT_TEST( testGetCharCode ); CPPUNIT_TEST_SUITE_END(); public: void setUp(); void tearDown(); void testDifferences(); void testDifferencesObject(); void testDifferencesEncoding(); void testUnicodeNames(); void testGetCharCode(); private: bool outofRangeHelper( PoDoFo::PdfEncoding* pEncoding, std::string & rMsg, const char* pszName ); }; #endif // _STRING_TEST_H_ podofo-0.9.3/test/unit/FilterTest.h0000664000175000017500000000376710736717750017107 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2007 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #ifndef _FILTER_TEST_H_ #define _FILTER_TEST_H_ #include #include /** This test tests the various PdfFilter classes */ class FilterTest : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE( FilterTest ); CPPUNIT_TEST( testFilters ); CPPUNIT_TEST( testCCITT ); CPPUNIT_TEST_SUITE_END(); public: void setUp(); void tearDown(); void testFilters(); void testCCITT(); private: void TestFilter( PoDoFo::EPdfFilter eFilter, const char * pTestBuffer, const long lTestLength ); }; #endif // _FILTER_TEST_H_ podofo-0.9.3/test/unit/ElementTest.cpp0000664000175000017500000000627211403202272017554 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2010 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "ElementTest.h" #include using namespace PoDoFo; CPPUNIT_TEST_SUITE_REGISTRATION( ElementTest ); void ElementTest::setUp() { } void ElementTest::tearDown() { } void ElementTest::testTypeToIndexAnnotation() { // Check last entry in the type names array of PdfAnnotation PdfObject object; object.GetDictionary().AddKey( PdfName("Type"), PdfName("Annot") ); object.GetDictionary().AddKey( PdfName("Subtype"), PdfName("RichMedia") ); PdfAnnotation annot(&object, NULL); CPPUNIT_ASSERT_EQUAL( ePdfAnnotation_RichMedia, annot.GetType() ); } void ElementTest::testTypeToIndexAction() { // Check last entry in the type names array of PdfAction PdfObject object; object.GetDictionary().AddKey( PdfName("Type"), PdfName("Action") ); object.GetDictionary().AddKey( PdfName("S"), PdfName("GoTo3DView") ); PdfAction action(&object); CPPUNIT_ASSERT_EQUAL( ePdfAction_GoTo3DView, action.GetType() ); } void ElementTest::testTypeToIndexAnnotationUnknown() { // Check last entry in the type names array of PdfAnnotation PdfObject object; object.GetDictionary().AddKey( PdfName("Type"), PdfName("Annot") ); object.GetDictionary().AddKey( PdfName("Subtype"), PdfName("PoDoFoRocksUnknownType") ); PdfAnnotation annot(&object, NULL); CPPUNIT_ASSERT_EQUAL( ePdfAnnotation_Unknown, annot.GetType() ); } void ElementTest::testTypeToIndexActionUnknown() { // Check last entry in the type names array of PdfAction PdfObject object; object.GetDictionary().AddKey( PdfName("Type"), PdfName("Action") ); object.GetDictionary().AddKey( PdfName("S"), PdfName("PoDoFoRocksUnknownType") ); PdfAction action(&object); CPPUNIT_ASSERT_EQUAL( ePdfAction_Unknown, action.GetType() ); } podofo-0.9.3/test/unit/StringTest.h0000664000175000017500000000445011474747376017125 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2007 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #ifndef _STRING_TEST_H_ #define _STRING_TEST_H_ #include #ifndef __clang__ /** This test tests the class PdfString */ class StringTest : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE( StringTest ); CPPUNIT_TEST( testGetStringUtf8 ); CPPUNIT_TEST( testUtf16beContructor ); CPPUNIT_TEST( testWCharConstructor ); CPPUNIT_TEST( testEscapeBrackets ); CPPUNIT_TEST( testWriteEscapeSequences ); CPPUNIT_TEST( testEmptyString ); CPPUNIT_TEST_SUITE_END(); public: void setUp(); void tearDown(); void testGetStringUtf8(); void testUtf16beContructor(); void testWCharConstructor(); void testEscapeBrackets(); void testWriteEscapeSequences(); void testEmptyString(); private: void TestWriteEscapeSequences(const char* pszSource, const char* pszExpected); }; #endif // __clang__ #endif // _STRING_TEST_H_ podofo-0.9.3/test/unit/EncryptTest.h0000664000175000017500000000602012062205562017252 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2008 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #ifndef _ENCRYPT_TEST_H_ #define _ENCRYPT_TEST_H_ #include #include namespace PoDoFo { class PdfEncrypt; } /** This test tests the class PdfString */ class EncryptTest : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE( EncryptTest ); CPPUNIT_TEST( testDefault ); CPPUNIT_TEST( testRC4 ); CPPUNIT_TEST( testRC4v2_40 ); CPPUNIT_TEST( testRC4v2_56 ); CPPUNIT_TEST( testRC4v2_80 ); CPPUNIT_TEST( testRC4v2_96 ); CPPUNIT_TEST( testRC4v2_128 ); CPPUNIT_TEST( testAESV2 ); #ifdef PODOFO_HAVE_LIBIDN CPPUNIT_TEST( testAESV3 ); #endif // PODOFO_HAVE_LIBIDN CPPUNIT_TEST( testLoadEncrypedFilePdfParser ); CPPUNIT_TEST( testLoadEncrypedFilePdfMemDocument ); CPPUNIT_TEST( testEnableAlgorithms ); CPPUNIT_TEST_SUITE_END(); public: void setUp(); void tearDown(); void testDefault(); void testRC4(); void testRC4v2_40(); void testRC4v2_56(); void testRC4v2_80(); void testRC4v2_96(); void testRC4v2_128(); void testAESV2(); #ifdef PODOFO_HAVE_LIBIDN void testAESV3(); #endif // PODOFO_HAVE_LIBIDN void testLoadEncrypedFilePdfParser(); void testLoadEncrypedFilePdfMemDocument(); void testEnableAlgorithms(); private: void TestAuthenticate( PoDoFo::PdfEncrypt* pEncrypt, int keyLength, int rValue ); void TestEncrypt( PoDoFo::PdfEncrypt* pEncrypt ); /** * Create an encrypted PDF. * * @param pszFilename save the encrypted PDF here. */ void CreateEncryptedPdf( const char* pszFilename ); private: char* m_pEncBuffer; long m_lLen; int m_protection; }; #endif // _ENCRYPT_TEST_H_ podofo-0.9.3/test/unit/PageTest.h0000664000175000017500000000366011403002240016473 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2009 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #ifndef _PAGE_TEST_H_ #define _PAGE_TEST_H_ #include namespace PoDoFo { class PdfPage; }; /** This test tests the class PdfPagesTree */ class PageTest : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE( PageTest ); CPPUNIT_TEST( testEmptyContents ); CPPUNIT_TEST( testEmptyContentsStream ); CPPUNIT_TEST_SUITE_END(); public: void setUp(); void tearDown(); void testEmptyContents(); void testEmptyContentsStream(); }; #endif // _PAGE_TEST_H_ podofo-0.9.3/test/unit/TestUtils.cpp0000664000175000017500000000555311705105566017301 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2010 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "TestUtils.h" #include #include #include #include #if defined(_WIN32) || defined(_WIN64) #include #ifdef CreateFont #undef CreateFont #endif // CreateFont #ifdef DrawText #undef DrawText #endif // DrawText #endif // _WIN32 || _WIN64 #include std::string TestUtils::getTempFilename() { const long lLen = 256; char tmpFilename[lLen]; #if defined(_WIN32) || defined(_WIN64) char tmpDir[lLen]; GetTempPathA(lLen, tmpDir); GetTempFileNameA(tmpDir, "podofo", 0, tmpFilename); #else strncpy( tmpFilename, "/tmp/podofoXXXXXX", lLen); int handle = mkstemp(tmpFilename); close(handle); #endif // _WIN32 || _WIN64 printf("Created tempfile: %s\n", tmpFilename); std::string sFilename = tmpFilename; return sFilename; } void TestUtils::deleteFile( const char* pszFilename ) { #if defined(_WIN32) || defined(_WIN64) _unlink(pszFilename); #else unlink(pszFilename); #endif // _WIN32 || _WIN64 } char* TestUtils::readDataFile( const char* pszFilename ) { // TODO: determine correct prefix during runtime std::string sFilename = "/home/dominik/podofotmp/test/unit/data/"; sFilename = sFilename + pszFilename; PoDoFo::PdfFileInputStream stream( sFilename.c_str() ); long lLen = stream.GetFileLength(); char* pBuffer = static_cast(malloc(sizeof(char) * lLen)); stream.Read(pBuffer, lLen); return pBuffer; } podofo-0.9.3/test/unit/VariantTest.h0000664000175000017500000000410611245541723017241 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2008 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #ifndef _VARIANT_TEST_H_ #define _VARIANT_TEST_H_ #include /** This test tests the class PdfVariant */ class VariantTest : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE( VariantTest ); CPPUNIT_TEST( testEmptyObject ); CPPUNIT_TEST( testEmptyStream ); CPPUNIT_TEST( testNameObject ); CPPUNIT_TEST( testIsDirtyTrue ); CPPUNIT_TEST( testIsDirtyFalse ); CPPUNIT_TEST_SUITE_END(); public: void setUp(); void tearDown(); void testEmptyObject(); void testEmptyStream(); void testNameObject(); void testIsDirtyTrue(); void testIsDirtyFalse(); private: }; #endif // _VARIANT_TEST_H_ podofo-0.9.3/test/unit/NameTest.cpp0000664000175000017500000001634611455342347017065 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2007 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "NameTest.h" #include using namespace PoDoFo; // Registers the fixture into the 'registry' CPPUNIT_TEST_SUITE_REGISTRATION( NameTest ); void NameTest::setUp() { } void NameTest::tearDown() { } void NameTest::testParseAndWrite() { const char* pszData = "/#E5#8A#A8#E6#80#81#E8#BF#9E#E6#8E#A5#E7#BA#BF"; PdfTokenizer tokenizer(pszData, strlen(pszData)); const char* pszToken; EPdfTokenType eType; bool bGotToken = tokenizer.GetNextToken( pszToken, &eType ); CPPUNIT_ASSERT_EQUAL( bGotToken, true ); CPPUNIT_ASSERT_EQUAL( eType, ePdfTokenType_Delimiter ); bGotToken = tokenizer.GetNextToken( pszToken, &eType ); CPPUNIT_ASSERT_EQUAL( bGotToken, true ); CPPUNIT_ASSERT_EQUAL( eType, ePdfTokenType_Token ); // Test with const char* constructor PdfName name = PdfName::FromEscaped( pszToken ); PdfVariant var( name ); std::string str; var.ToString( str ); CPPUNIT_ASSERT_EQUAL( str == pszData, true ); // str.c_str() + 1 <- ignore leading slash CPPUNIT_ASSERT_EQUAL( name.GetEscapedName() == (str.c_str() + 1), true ); // Test with std::string constructor std::string sToken = pszToken; PdfName name2 = PdfName::FromEscaped( sToken ); PdfVariant var2( name ); std::string str2; var.ToString( str2 ); CPPUNIT_ASSERT_EQUAL( str2 == pszData, true ); // str.c_str() + 1 <- ignore leading slash CPPUNIT_ASSERT_EQUAL( name2.GetEscapedName() == (str2.c_str() + 1), true ); } void NameTest::testNameEncoding() { // Test some names. The first argument is the unencoded representation, the second // is the expected encoded result. The result must not only be /a/ correct encoded // name for the unencoded form, but must be the exact one PoDoFo should produce. TestName( "Length With Spaces", "Length#20With#20Spaces" ); TestName( "Length\001\002\003Spaces\177", "Length#01#02#03Spaces#7F" ); TestName( "Length#01#02#03Spaces#7F", "Length#2301#2302#2303Spaces#237F" ); TestName( "Tab\tTest", "Tab#09Test" ); } void NameTest::testEncodedNames() { // Test some pre-encoded names. The first argument is the encoded name that'll be // read from the PDF; the second is the expected representation. TestEncodedName( "PANTONE#205757#20CV", "PANTONE 5757 CV"); TestEncodedName( "paired#28#29parentheses", "paired()parentheses"); TestEncodedName( "The_Key_of_F#23_Minor", "The_Key_of_F#_Minor"); TestEncodedName( "A#42", "AB"); TestEncodedName( "ANPA#20723-0#20AdPro", "ANPA 723-0 AdPro" ); } void NameTest::testEquality() { // Make sure differently encoded names compare equal if their decoded values // are equal. TestNameEquality( "With Spaces", "With#20Spaces" ); TestNameEquality( "#57#69#74#68#20#53#70#61#63#65#73", "With#20Spaces" ); } void NameTest::testWrite() { // Make sure all names are written correctly to an output device! TestWrite( "Length With Spaces", "/Length#20With#20Spaces" ); TestWrite( "Length\001\002\003Spaces\177", "/Length#01#02#03Spaces#7F" ); TestWrite( "Tab\tTest", "/Tab#09Test" ); TestWrite( "ANPA 723-0 AdPro", "/ANPA#20723-0#20AdPro" ); } void NameTest::testFromEscaped() { TestFromEscape( "ANPA#20723-0#20AdPro", "ANPA 723-0 AdPro" ); TestFromEscape( "Length#20With#20Spaces", "Length With Spaces" ); } // // Test encoding of names. // pszString : internal representation, ie unencoded name // pszExpectedEncoded: the encoded string PoDoFo should produce // void NameTest::TestName( const char* pszString, const char* pszExpectedEncoded ) { printf("Testing name: %s\n", pszString ); PdfName name( pszString ); printf(" -> Expected Value: %s\n", pszExpectedEncoded ); printf(" -> Got Value: %s\n", name.GetEscapedName().c_str() ); printf(" -> Unescaped Value: %s\n", name.GetName().c_str() ); CPPUNIT_ASSERT_EQUAL( strcmp( pszExpectedEncoded, name.GetEscapedName().c_str() ), 0 ); // Ensure the encoded string compares equal to its unencoded // variant CPPUNIT_ASSERT_EQUAL( name == PdfName::FromEscaped(pszExpectedEncoded), true ); } void NameTest::TestEncodedName( const char* pszString, const char* pszExpected ) { PdfName name( PdfName::FromEscaped(pszString) ); printf("Testing encoded name: %s\n", pszString ); printf(" -> Expected Value: %s\n", pszExpected ); printf(" -> Got Value: %s\n", name.GetName().c_str() ); printf(" -> Escaped Value: %s\n", name.GetEscapedName().c_str() ); if ( strcmp( pszExpected, name.GetName().c_str() ) != 0 ) { PODOFO_RAISE_ERROR( ePdfError_TestFailed ); } // Ensure the name compares equal with one constructed from the // expected unescaped form CPPUNIT_ASSERT_EQUAL( name == PdfName(pszExpected), true ); } void NameTest::TestNameEquality( const char * pszName1, const char* pszName2 ) { PdfName name1( PdfName::FromEscaped(pszName1) ); PdfName name2( PdfName::FromEscaped(pszName2) ); printf("Testing equality of encoded names '%s' and '%s'\n", pszName1, pszName2); printf(" -> Name1 Decoded Value: %s\n", name1.GetName().c_str()); printf(" -> Name2 Decoded Value: %s\n", name2.GetName().c_str()); CPPUNIT_ASSERT_EQUAL( name1 == name2, true ); // use operator== CPPUNIT_ASSERT_EQUAL( name1 != name2, false ); // use operator!= } void NameTest::TestWrite( const char * pszName, const char* pszResult ) { std::ostringstream oss; PdfName name( pszName ); PdfOutputDevice device( &oss ); name.Write( &device, ePdfWriteMode_Default ); CPPUNIT_ASSERT_EQUAL( oss.str() == pszResult, true ); } void NameTest::TestFromEscape( const char* pszName1, const char* pszName2 ) { PdfName name = PdfName::FromEscaped( pszName1, strlen( pszName1 ) ); CPPUNIT_ASSERT_EQUAL( name.GetName() == pszName2, true ); } podofo-0.9.3/test/unit/BasicTypeTest.cpp0000664000175000017500000000360511403202272020043 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2008 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "BasicTypeTest.h" #include #include using namespace PoDoFo; // Registers the fixture into the 'registry' CPPUNIT_TEST_SUITE_REGISTRATION( BasicTypeTest ); void BasicTypeTest::setUp() { } void BasicTypeTest::tearDown() { } void BasicTypeTest::testXrefOffsetTypeSize() { CPPUNIT_ASSERT_MESSAGE("pdf_uint64 is big enough to hold an xref entry", std::numeric_limits::max() >= PODOFO_ULL_LITERAL(9999999999) ); } podofo-0.9.3/test/unit/BasicTypeTest.h0000664000175000017500000000410111233264622017510 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2008 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #ifndef _BASICTYPE_TEST_H_ #define _BASICTYPE_TEST_H_ #include /** This class tests the basic integer and other types PoDoFo uses * to make sure they satisfy its requirements for behaviour, size, etc. * * We now detect what types to use using CMake, so it's important to * test that detection and make sure it's doing the right thing. */ class BasicTypeTest : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE( BasicTypeTest ); CPPUNIT_TEST( testXrefOffsetTypeSize ); CPPUNIT_TEST_SUITE_END(); public: void setUp(); void tearDown(); void testXrefOffsetTypeSize(); private: }; #endif podofo-0.9.3/test/unit/DateTest.cpp0000664000175000017500000000612212347347566017062 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2012 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "DateTest.h" #include using namespace PoDoFo; // Registers the fixture into the 'registry' CPPUNIT_TEST_SUITE_REGISTRATION( DateTest ); void DateTest::setUp() { } void DateTest::tearDown() { } void checkExpected(const char *pszDate, bool bExpected) { PdfString tmp(pszDate); PdfDate date(tmp); CPPUNIT_ASSERT_EQUAL(bExpected,date.IsValid()); } void DateTest::testCreateDateFromString() { checkExpected(NULL,false); checkExpected("D:2012",true); checkExpected("D:20120",false); checkExpected("D:201201",true); checkExpected("D:2012010",false); checkExpected("D:20120101",true); checkExpected("D:201201012",false); checkExpected("D:2012010123",true); checkExpected("D:20120101235",false); checkExpected("D:201201012359",true); checkExpected("D:2012010123595",false); checkExpected("D:20120101235959",true); checkExpected("D:20120120135959Z",false); checkExpected("D:20120120135959Z0",false); checkExpected("D:20120120135959Z00",true); checkExpected("D:20120120135959Z00'",false); checkExpected("D:20120120135959Z00'0",false); checkExpected("D:20120120135959Z00'00",false); checkExpected("D:20120120135959Z00'00'",true); } void DateTest::testDateValue() { PdfDate date(PdfString("D:20120530235959Z00'00'")); CPPUNIT_ASSERT_EQUAL(true,date.IsValid()); const time_t &time = date.GetTime(); struct tm _tm; memset (&_tm, 0, sizeof(struct tm)); _tm.tm_year = 2012-1900; _tm.tm_mon = 4; _tm.tm_mday = 30; _tm.tm_hour = 23; _tm.tm_min = 59; _tm.tm_sec = 59; time_t time2 = mktime(&_tm); CPPUNIT_ASSERT_EQUAL(true,time==time2); } podofo-0.9.3/test/unit/ColorTest.h0000664000175000017500000000660311472721772016725 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2010 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #ifndef _COLOR_TEST_H_ #define _COLOR_TEST_H_ #include class ColorTest : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE( ColorTest ); CPPUNIT_TEST( testDefaultConstructor ); CPPUNIT_TEST( testGreyConstructor ); CPPUNIT_TEST( testGreyConstructorInvalid ); CPPUNIT_TEST( testRGBConstructor ); CPPUNIT_TEST( testRGBConstructorInvalid ); CPPUNIT_TEST( testCMYKConstructor ); CPPUNIT_TEST( testCMYKConstructorInvalid ); CPPUNIT_TEST( testCopyConstructor ); CPPUNIT_TEST( testAssignmentOperator ); CPPUNIT_TEST( testEqualsOperator ); CPPUNIT_TEST( testHexNames ); CPPUNIT_TEST( testNamesGeneral ); CPPUNIT_TEST( testNamesOneByOne ); CPPUNIT_TEST( testColorGreyConstructor ); CPPUNIT_TEST( testColorRGBConstructor ); CPPUNIT_TEST( testColorCMYKConstructor ); CPPUNIT_TEST( testColorSeparationAllConstructor ); CPPUNIT_TEST( testColorSeparationNoneConstructor ); CPPUNIT_TEST( testColorSeparationConstructor ); CPPUNIT_TEST( testColorCieLabConstructor ); CPPUNIT_TEST( testRGBtoCMYKConversions ); CPPUNIT_TEST_SUITE_END(); public: virtual void setUp(); virtual void tearDown(); protected: void testDefaultConstructor(); void testGreyConstructor(); void testGreyConstructorInvalid(); void testRGBConstructor(); void testRGBConstructorInvalid(); void testCMYKConstructor(); void testCMYKConstructorInvalid(); void testCopyConstructor(); void testAssignmentOperator(); void testEqualsOperator(); void testHexNames(); void testNamesGeneral(); void testNamesOneByOne(); void testColorGreyConstructor(); void testColorRGBConstructor(); void testColorCMYKConstructor(); void testColorSeparationAllConstructor(); void testColorSeparationNoneConstructor(); void testColorSeparationConstructor(); void testColorCieLabConstructor(); void testRGBtoCMYKConversions(); }; #endif podofo-0.9.3/test/unit/EncryptTest.cpp0000664000175000017500000003376412062205562017624 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2008 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "EncryptTest.h" #include "TestUtils.h" #include using namespace PoDoFo; // Registers the fixture into the 'registry' CPPUNIT_TEST_SUITE_REGISTRATION( EncryptTest ); void EncryptTest::setUp() { const char* pBuffer1 = "Somekind of drawing \001 buffer that possibly \003 could contain PDF drawing commands"; const char* pBuffer2 = " possibly could contain PDF drawing\003 commands"; m_lLen = strlen( pBuffer1 ) + 2 * strlen( pBuffer2 ); m_pEncBuffer = static_cast(malloc( sizeof(char) * m_lLen )); memcpy( m_pEncBuffer, pBuffer1, strlen( pBuffer1 ) * sizeof(char) ); memcpy( m_pEncBuffer + strlen(pBuffer1), pBuffer2, strlen( pBuffer2 ) ); memcpy( m_pEncBuffer + strlen(pBuffer1) + strlen( pBuffer2 ), pBuffer2, strlen( pBuffer2 ) ); m_protection = PdfEncrypt::ePdfPermissions_Print | PdfEncrypt::ePdfPermissions_Edit | PdfEncrypt::ePdfPermissions_Copy | PdfEncrypt::ePdfPermissions_EditNotes | PdfEncrypt::ePdfPermissions_FillAndSign | PdfEncrypt::ePdfPermissions_Accessible | PdfEncrypt::ePdfPermissions_DocAssembly | PdfEncrypt::ePdfPermissions_HighPrint; } void EncryptTest::tearDown() { free( m_pEncBuffer ); } void EncryptTest::testDefault() { PdfEncrypt* pEncrypt = PdfEncrypt::CreatePdfEncrypt( "user", "podofo" ); TestAuthenticate( pEncrypt, 40, 2 ); TestEncrypt( pEncrypt ); delete pEncrypt; } void EncryptTest::testRC4() { PdfEncrypt* pEncrypt = PdfEncrypt::CreatePdfEncrypt( "user", "podofo", m_protection, PdfEncrypt::ePdfEncryptAlgorithm_RC4V1, PdfEncrypt::ePdfKeyLength_40 ); TestAuthenticate( pEncrypt, 40, 3 ); TestEncrypt( pEncrypt ); delete pEncrypt; } void EncryptTest::testRC4v2_40() { PdfEncrypt* pEncrypt = PdfEncrypt::CreatePdfEncrypt( "user", "podofo", m_protection, PdfEncrypt::ePdfEncryptAlgorithm_RC4V2, PdfEncrypt::ePdfKeyLength_40 ); TestAuthenticate( pEncrypt, 40, 3 ); TestEncrypt( pEncrypt ); delete pEncrypt; } void EncryptTest::testRC4v2_56() { PdfEncrypt* pEncrypt = PdfEncrypt::CreatePdfEncrypt( "user", "podofo", m_protection, PdfEncrypt::ePdfEncryptAlgorithm_RC4V2, PdfEncrypt::ePdfKeyLength_56 ); TestAuthenticate( pEncrypt, 56, 3 ); TestEncrypt( pEncrypt ); delete pEncrypt; } void EncryptTest::testRC4v2_80() { PdfEncrypt* pEncrypt = PdfEncrypt::CreatePdfEncrypt( "user", "podofo", m_protection, PdfEncrypt::ePdfEncryptAlgorithm_RC4V2, PdfEncrypt::ePdfKeyLength_80 ); TestAuthenticate( pEncrypt, 80, 3 ); TestEncrypt( pEncrypt ); delete pEncrypt; } void EncryptTest::testRC4v2_96() { PdfEncrypt* pEncrypt = PdfEncrypt::CreatePdfEncrypt( "user", "podofo", m_protection, PdfEncrypt::ePdfEncryptAlgorithm_RC4V2, PdfEncrypt::ePdfKeyLength_96 ); TestAuthenticate( pEncrypt, 96, 3 ); TestEncrypt( pEncrypt ); delete pEncrypt; } void EncryptTest::testRC4v2_128() { PdfEncrypt* pEncrypt = PdfEncrypt::CreatePdfEncrypt( "user", "podofo", m_protection, PdfEncrypt::ePdfEncryptAlgorithm_RC4V2, PdfEncrypt::ePdfKeyLength_128 ); TestAuthenticate( pEncrypt, 128, 3 ); TestEncrypt( pEncrypt ); delete pEncrypt; } void EncryptTest::testAESV2() { PdfEncrypt* pEncrypt = PdfEncrypt::CreatePdfEncrypt( "user", "podofo", m_protection, PdfEncrypt::ePdfEncryptAlgorithm_AESV2, PdfEncrypt::ePdfKeyLength_128 ); TestAuthenticate( pEncrypt, 128, 4 ); // AES decryption is not yet implemented. // Therefore we have to disable this test. // TestEncrypt( pEncrypt ); delete pEncrypt; } #ifdef PODOFO_HAVE_LIBIDN void EncryptTest::testAESV3() { PdfEncrypt* pEncrypt = PdfEncrypt::CreatePdfEncrypt( "user", "podofo", m_protection, PdfEncrypt::ePdfEncryptAlgorithm_AESV3, PdfEncrypt::ePdfKeyLength_256 ); TestAuthenticate( pEncrypt, 256, 5 ); // AES decryption is not yet implemented. // Therefore we have to disable this test. // TestEncrypt( pEncrypt ); delete pEncrypt; } #endif // PODOFO_HAVE_LIBIDN void EncryptTest::TestAuthenticate( PdfEncrypt* pEncrypt, int keyLength, int rValue ) { PdfString documentId; documentId.SetHexData( "BF37541A9083A51619AD5924ECF156DF", 32 ); pEncrypt->GenerateEncryptionKey( documentId ); CPPUNIT_ASSERT_EQUAL_MESSAGE( "authenticate using user password", pEncrypt->Authenticate(std::string("user"), documentId), true ); CPPUNIT_ASSERT_EQUAL_MESSAGE( "authenticate using wrong user password", pEncrypt->Authenticate(std::string("wrongpassword"), documentId), false ); CPPUNIT_ASSERT_EQUAL_MESSAGE( "authenticate using owner password", pEncrypt->Authenticate(std::string("podofo"), documentId), true ); CPPUNIT_ASSERT_EQUAL_MESSAGE( "authenticate using wrong owner password", pEncrypt->Authenticate(std::string("wrongpassword"), documentId), false ); } void EncryptTest::TestEncrypt( PdfEncrypt* pEncrypt ) { pEncrypt->SetCurrentReference( PdfReference( 7, 0 ) ); int nOutputLen = pEncrypt->CalculateStreamLength(m_lLen); unsigned char *pEncryptedBuffer = new unsigned char[nOutputLen]; unsigned char *pDecryptedBuffer = new unsigned char[m_lLen]; // Encrypt buffer try { pEncrypt->Encrypt( reinterpret_cast(m_pEncBuffer), m_lLen, pEncryptedBuffer, nOutputLen ); } catch (PdfError &e) { CPPUNIT_FAIL(e.ErrorMessage(e.GetError())); } // Decrypt buffer try { pEncrypt->Decrypt( pEncryptedBuffer, nOutputLen, pDecryptedBuffer, m_lLen ); } catch (PdfError &e) { CPPUNIT_FAIL(e.ErrorMessage(e.GetError())); } CPPUNIT_ASSERT_EQUAL_MESSAGE( "compare encrypted and decrypted buffers", 0, memcmp( m_pEncBuffer, pDecryptedBuffer, m_lLen ) ); delete[] pEncryptedBuffer; delete[] pDecryptedBuffer; } void EncryptTest::testLoadEncrypedFilePdfParser() { std::string sFilename = TestUtils::getTempFilename(); try { CreateEncryptedPdf( sFilename.c_str() ); // Try loading with PdfParser PdfVecObjects objects; PdfParser parser( &objects ); try { parser.ParseFile( sFilename.c_str(), true ); // Must throw an exception CPPUNIT_FAIL("Encrypted file not recognized!"); } catch( const PdfError & e ) { if( e.GetError() != ePdfError_InvalidPassword ) { CPPUNIT_FAIL("Invalid encryption exception thrown!"); } } parser.SetPassword( "user" ); } catch( PdfError & e ) { e.PrintErrorMsg(); printf("Removing temp file: %s\n", sFilename.c_str()); TestUtils::deleteFile(sFilename.c_str()); throw e; } printf("Removing temp file: %s\n", sFilename.c_str()); TestUtils::deleteFile(sFilename.c_str()); } void EncryptTest::testLoadEncrypedFilePdfMemDocument() { std::string sFilename = TestUtils::getTempFilename(); try { CreateEncryptedPdf( sFilename.c_str() ); // Try loading with PdfParser PdfMemDocument document; try { document.Load( sFilename.c_str() ); // Must throw an exception CPPUNIT_FAIL("Encrypted file not recognized!"); } catch( const PdfError & e ) { if( e.GetError() != ePdfError_InvalidPassword ) { CPPUNIT_FAIL("Invalid encryption exception thrown!"); } } document.SetPassword( "user" ); } catch( PdfError & e ) { e.PrintErrorMsg(); printf("Removing temp file: %s\n", sFilename.c_str()); TestUtils::deleteFile(sFilename.c_str()); throw e; } printf("Removing temp file: %s\n", sFilename.c_str()); TestUtils::deleteFile(sFilename.c_str()); } void EncryptTest::CreateEncryptedPdf( const char* pszFilename ) { PdfMemDocument writer; PdfPage* pPage = writer.CreatePage( PdfPage::CreateStandardPageSize( ePdfPageSize_A4 ) ); PdfPainter painter; painter.SetPage( pPage ); PdfFont* pFont = writer.CreateFont( "Arial", PdfEncodingFactory::GlobalWinAnsiEncodingInstance(), false ); if( !pFont ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } pFont->SetFontSize( 16.0 ); painter.SetFont( pFont ); painter.DrawText( 100, 100, "Hello World" ); painter.FinishPage(); writer.SetEncrypted( "user", "owner" ); writer.Write( pszFilename ); printf( "Wrote: %s (R=%i)\n", pszFilename, writer.GetEncrypt()->GetRevision() ); } void EncryptTest::testEnableAlgorithms() { int nDefault = PdfEncrypt::GetEnabledEncryptionAlgorithms(); // By default every algorithms should be enabled CPPUNIT_ASSERT( PdfEncrypt::IsEncryptionEnabled( PdfEncrypt::ePdfEncryptAlgorithm_RC4V1 ) ); CPPUNIT_ASSERT( PdfEncrypt::IsEncryptionEnabled( PdfEncrypt::ePdfEncryptAlgorithm_RC4V2 ) ); CPPUNIT_ASSERT( PdfEncrypt::IsEncryptionEnabled( PdfEncrypt::ePdfEncryptAlgorithm_AESV2 ) ); #ifdef PODOFO_HAVE_LIBIDN CPPUNIT_ASSERT( PdfEncrypt::IsEncryptionEnabled( PdfEncrypt::ePdfEncryptAlgorithm_AESV3 ) ); #endif // PODOFO_HAVE_LIBIDN CPPUNIT_ASSERT_EQUAL( PdfEncrypt::ePdfEncryptAlgorithm_RC4V1 | PdfEncrypt::ePdfEncryptAlgorithm_RC4V2 | PdfEncrypt::ePdfEncryptAlgorithm_AESV2 #ifdef PODOFO_HAVE_LIBIDN | PdfEncrypt::ePdfEncryptAlgorithm_AESV3 #endif // PODOFO_HAVE_LIBIDN , PdfEncrypt::GetEnabledEncryptionAlgorithms() ); // Disable AES PdfEncrypt::SetEnabledEncryptionAlgorithms( PdfEncrypt::ePdfEncryptAlgorithm_RC4V1 | PdfEncrypt::ePdfEncryptAlgorithm_RC4V2 ); CPPUNIT_ASSERT( PdfEncrypt::IsEncryptionEnabled( PdfEncrypt::ePdfEncryptAlgorithm_RC4V1 ) ); CPPUNIT_ASSERT( PdfEncrypt::IsEncryptionEnabled( PdfEncrypt::ePdfEncryptAlgorithm_RC4V2 ) ); CPPUNIT_ASSERT( !PdfEncrypt::IsEncryptionEnabled( PdfEncrypt::ePdfEncryptAlgorithm_AESV2 ) ); CPPUNIT_ASSERT_EQUAL( PdfEncrypt::ePdfEncryptAlgorithm_RC4V1 | PdfEncrypt::ePdfEncryptAlgorithm_RC4V2, PdfEncrypt::GetEnabledEncryptionAlgorithms() ); PdfObject object; object.GetDictionary().AddKey(PdfName("Filter"), PdfName("Standard")); object.GetDictionary().AddKey(PdfName("V"), static_cast(4L)); object.GetDictionary().AddKey(PdfName("R"), static_cast(4L)); object.GetDictionary().AddKey(PdfName("P"), static_cast(1L)); object.GetDictionary().AddKey(PdfName("O"), PdfString("")); object.GetDictionary().AddKey(PdfName("U"), PdfString("")); try { (void)PdfEncrypt::CreatePdfEncrypt( &object ); CPPUNIT_ASSERT( false ); } catch( PdfError & rError ) { CPPUNIT_ASSERT_EQUAL( rError.GetError(), ePdfError_UnsupportedFilter ); } // Restore default PdfEncrypt::SetEnabledEncryptionAlgorithms( nDefault ); } /* PdfMemoryOutputStream mem( lLen ); PdfOutputStream* pStream = enc.CreateEncryptionOutputStream( &mem ); pStream->Write( pBuffer1, strlen( pBuffer1 ) ); pStream->Write( pBuffer2, strlen( pBuffer2 ) ); pStream->Write( pBuffer2, strlen( pBuffer2 ) ); pStream->Close(); printf("Result: %i \n", memcmp( pEncBuffer, mem.TakeBuffer(), lLen ) ); enc.Encrypt( reinterpret_cast(pEncBuffer), lLen ); printf("Decrypted buffer: %s\n", pEncBuffer ); */ podofo-0.9.3/test/unit/CMakeLists.txt0000664000175000017500000000147111763153744017375 0ustar dominikdominik IF(PODOFO_HAVE_CPPUNIT) INCLUDE_DIRECTORIES( ${PROJ_SOURCE_DIR}/src ${PROJ_BINARY_DIR}/src ${PROJ_BINARY_DIR}/src/os ${PROJ_BINARY_DIR}/src/os/${OROCOS_TARGET}) ADD_DEFINITIONS("-g") # repeat for each test ADD_EXECUTABLE( podofo-test main.cpp ColorTest.cpp ElementTest.cpp EncodingTest.cpp EncryptTest.cpp FilterTest.cpp FontTest.cpp NameTest.cpp PagesTreeTest.cpp PageTest.cpp PainterTest.cpp TokenizerTest.cpp StringTest.cpp VariantTest.cpp BasicTypeTest.cpp TestUtils.cpp DateTest.cpp ) ADD_DEPENDENCIES( podofo-test ${PODOFO_DEPEND_TARGET}) TARGET_LINK_LIBRARIES( podofo-test ${PODOFO_LIB} ${PODOFO_LIB_DEPENDS} ${CPPUNIT_LIBRARIES} ) SET_TARGET_PROPERTIES( podofo-test PROPERTIES COMPILE_FLAGS "${PODOFO_CFLAGS}") ADD_TEST( podofo-test podofo-test ) ENDIF(PODOFO_HAVE_CPPUNIT) podofo-0.9.3/test/unit/StringTest.cpp0000664000175000017500000003266311474747376017467 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2007 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "StringTest.h" #include #ifndef __clang__ using namespace PoDoFo; // Registers the fixture into the 'registry' CPPUNIT_TEST_SUITE_REGISTRATION( StringTest ); inline std::ostream& operator<<(std::ostream& o, const PdfString& s) { return o << s.GetStringUtf8(); } void StringTest::setUp() { } void StringTest::tearDown() { } void StringTest::testGetStringUtf8() { const std::string src1 = "Hello World!"; const std::string src2 = src1; const std::string src3 = "「Po\tDoFo」は今から日本語も話せます。"; // Normal ascii string should be converted to UTF8 PdfString str1( src1.c_str() ); std::string res1 = str1.GetStringUtf8(); CPPUNIT_ASSERT_EQUAL_MESSAGE( "testing const char* ASCII -> UTF8", src1, res1 ); // Normal std::string string should be converted to UTF8 PdfString str2( src2 ); std::string res2 = str2.GetStringUtf8(); CPPUNIT_ASSERT_EQUAL_MESSAGE( "testing std::string ASCII -> UTF8", src2, res2 ); // UTF8 data in std::string cannot be converted as we do not know it is UTF8 PdfString str3( src3 ); std::string res3 = str3.GetStringUtf8(); CPPUNIT_ASSERT_EQUAL_MESSAGE( "testing std::string UTF8 -> UTF8", (res3 != src3) , true ); // UTF8 data as pdf_utf8* must be convertible PdfString str4( reinterpret_cast(src3.c_str()) ); std::string res4 = str4.GetStringUtf8(); CPPUNIT_ASSERT_EQUAL_MESSAGE( "testing pdf_utf8* UTF8 -> UTF8", res4, src3 ); } void StringTest::testUtf16beContructor() { const char* pszStringJapUtf8 = "「PoDoFo」は今から日本語も話せます。"; // The same string as a NULL-terminated UTF-8 string. This is a UTF-8 literal, so your editor // must be configured to handle this file as UTF-8 to see something sensible below. // The same string in UTF16BE encoding const char psStringJapUtf16BE[44] = { 0x30, 0x0c, 0x00, 0x50, 0x00, 0x6f, 0x00, 0x44, 0x00, 0x6f, 0x00, 0x46, 0x00, 0x6f, 0x30, 0x0d, 0x30, 0x6f, 0x4e, 0xca, 0x30, 0x4b, 0x30, 0x89, 0x65, 0xe5, 0x67, 0x2c, 0x8a, 0x9e, 0x30, 0x82, 0x8a, 0x71, 0x30, 0x5b, 0x30, 0x7e, 0x30, 0x59, 0x30, 0x02, 0x00, 0x00 }; PdfString strUtf8( reinterpret_cast(pszStringJapUtf8) ); PdfString strUtf16( reinterpret_cast(psStringJapUtf16BE), 21 ); PdfString strUtf16b( reinterpret_cast(psStringJapUtf16BE), 21 ); /* std::cout << std::endl; std::cout << "utf8 :" << strUtf8 << " " << strUtf8.GetCharacterLength() << std::endl; std::cout << "utf16:" << strUtf16 << " " << strUtf16.GetCharacterLength() << std::endl; std::cout << "wide : "; for( int i=0;i<=strUtf16.GetCharacterLength();i++ ) printf("%04x ", strUtf16.GetUnicode()[i]); std::cout << std::endl; std::cout << "wide : "; for( int i=0;i<=strUtf16.GetCharacterLength();i++ ) printf("%4i ", i ); std::cout << std::endl; */ // Compare UTF16 to UTF8 string CPPUNIT_ASSERT_EQUAL_MESSAGE( "Comparing string length", strUtf8.GetCharacterLength(), strUtf16.GetCharacterLength() ); CPPUNIT_ASSERT_EQUAL_MESSAGE( "Comparing UTF8 and UTF16 string converted to UTF8", strUtf8.GetStringUtf8(), strUtf16.GetStringUtf8() ); CPPUNIT_ASSERT_EQUAL_MESSAGE( "Comparing UTF8 and UTF16 string", strUtf8, strUtf16 ); // Compare two UTF16 strings CPPUNIT_ASSERT_EQUAL( strUtf16.GetCharacterLength(), strUtf16b.GetCharacterLength() ); CPPUNIT_ASSERT_EQUAL( strUtf16.GetStringUtf8(), strUtf16b.GetStringUtf8() ); CPPUNIT_ASSERT_EQUAL( strUtf16, strUtf16b ); } void StringTest::testWCharConstructor() { CPPUNIT_ASSERT_EQUAL( PdfString("Hallo World"), PdfString(L"Hallo World") ); CPPUNIT_ASSERT_EQUAL( PdfString(L"Hallo World"), PdfString(L"Hallo World") ); } void StringTest::testEscapeBrackets() { // Test balanced brackets ansi const char* pszAscii = "Hello (balanced) World"; const char* pszAsciiExpect = "(Hello \\(balanced\\) World)"; PdfString sAscii( pszAscii ); PdfVariant varAscii( sAscii ); std::string strAscii; varAscii.ToString( strAscii ); CPPUNIT_ASSERT_EQUAL( strAscii == pszAsciiExpect, true ); // Test un-balanced brackets ansi const char* pszAscii2 = "Hello ((unbalanced World"; const char* pszAsciiExpect2 = "(Hello \\(\\(unbalanced World)"; PdfString sAscii2( pszAscii2 ); PdfVariant varAscii2( sAscii2 ); std::string strAscii2; varAscii2.ToString( strAscii2 ); CPPUNIT_ASSERT_EQUAL( strAscii2 == pszAsciiExpect2, true ); // Test balanced brackets unicode const char* pszUnic = "Hello (balanced) World"; const char pszUnicExpect[]= { 0x28, 0xFE, 0xFF, 0x00, 0x48, 0x00, 0x65, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6F, 0x00, 0x20, 0x00, 0x5C, 0x28, 0x00, 0x62, 0x00, 0x61, 0x00, 0x6C, 0x00, 0x61, 0x00, 0x6E, 0x00, 0x63, 0x00, 0x65, 0x00, 0x64, 0x00, 0x5C, 0x29, 0x00, 0x20, 0x00, 0x57, 0x00, 0x6F, 0x00, 0x72, 0x00, 0x6C, 0x00, 0x64, 0x29, 0x00, 0x00 }; // Force unicode string PdfString sUnic( reinterpret_cast(pszUnic) ); PdfVariant varUnic( sUnic ); std::string strUnic; varUnic.ToString( strUnic ); CPPUNIT_ASSERT_EQUAL( memcmp( strUnic.c_str(), pszUnicExpect, strUnic.length() ) == 0, true ); // Test un-balanced brackets unicode const char* pszUnic2 = "Hello ((unbalanced World"; const char pszUnicExpect2[]= { 0x28, 0xFE, 0xFF, 0x00, 0x48, 0x00, 0x65, 0x00, 0x6C, 0x00, 0x6C, 0x00, 0x6F, 0x00, 0x20, 0x00, 0x5C, 0x28, 0x00, 0x5C, 0x28, 0x00, 0x75, 0x00, 0x6E, 0x00, 0x62, 0x00, 0x61, 0x00, 0x6C, 0x00, 0x61, 0x00, 0x6E, 0x00, 0x63, 0x00, 0x65, 0x00, 0x64, 0x00, 0x20, 0x00, 0x57, 0x00, 0x6F, 0x00, 0x72, 0x00, 0x6C, 0x00, 0x64, 0x29 }; // Force unicode string PdfString sUnic2( reinterpret_cast(pszUnic2) ); PdfVariant varUnic2( sUnic2 ); std::string strUnic2; varUnic2.ToString( strUnic2 ); CPPUNIT_ASSERT_EQUAL( memcmp( strUnic2.c_str(), pszUnicExpect2, strUnic2.length() ) == 0, true ); // Test reading the unicode string back in PdfVariant varRead; PdfTokenizer tokenizer( strUnic2.c_str(), strUnic2.length() ); tokenizer.GetNextVariant( varRead, NULL ); CPPUNIT_ASSERT_EQUAL( varRead.GetString() == sUnic2, true ); } void StringTest::testWriteEscapeSequences() { TestWriteEscapeSequences("(Hello\\nWorld)", "(Hello\\nWorld)"); TestWriteEscapeSequences("(Hello\nWorld)", "(Hello\\nWorld)"); TestWriteEscapeSequences("(Hello\012World)", "(Hello\\nWorld)"); TestWriteEscapeSequences("(Hello\\012World)", "(Hello\\nWorld)"); TestWriteEscapeSequences("(Hello\\rWorld)", "(Hello\\rWorld)"); TestWriteEscapeSequences("(Hello\rWorld)", "(Hello\\rWorld)"); TestWriteEscapeSequences("(Hello\015World)", "(Hello\\rWorld)"); TestWriteEscapeSequences("(Hello\\015World)", "(Hello\\rWorld)"); TestWriteEscapeSequences("(Hello\\tWorld)", "(Hello\\tWorld)"); TestWriteEscapeSequences("(Hello\tWorld)", "(Hello\\tWorld)"); TestWriteEscapeSequences("(Hello\011World)", "(Hello\\tWorld)"); TestWriteEscapeSequences("(Hello\\011World)", "(Hello\\tWorld)"); TestWriteEscapeSequences("(Hello\\fWorld)", "(Hello\\fWorld)"); TestWriteEscapeSequences("(Hello\fWorld)", "(Hello\\fWorld)"); TestWriteEscapeSequences("(Hello\014World)", "(Hello\\fWorld)"); TestWriteEscapeSequences("(Hello\\014World)", "(Hello\\fWorld)"); TestWriteEscapeSequences("(Hello\\(World)", "(Hello\\(World)"); TestWriteEscapeSequences("(Hello\\050World)", "(Hello\\(World)"); TestWriteEscapeSequences("(Hello\\)World)", "(Hello\\)World)"); TestWriteEscapeSequences("(Hello\\051World)", "(Hello\\)World)"); TestWriteEscapeSequences("(Hello\\\\World)", "(Hello\\\\World)"); TestWriteEscapeSequences("(Hello\\\134World)", "(Hello\\\\World)"); // Special case, \ at end of line TestWriteEscapeSequences("(Hello\\\nWorld)", "(HelloWorld)"); TestWriteEscapeSequences("(Hello\003World)", "(Hello\003World)"); } void StringTest::TestWriteEscapeSequences(const char* pszSource, const char* pszExpected) { PdfVariant variant; std::string ret; std::string expected = pszExpected; printf("Testing with value: %s\n", pszSource ); PdfTokenizer tokenizer( pszSource, strlen( pszSource ) ); tokenizer.GetNextVariant( variant, NULL ); CPPUNIT_ASSERT_EQUAL( variant.GetDataType(), ePdfDataType_String ); variant.ToString( ret ); printf(" -> Convert To String: %s\n", ret.c_str() ); CPPUNIT_ASSERT_EQUAL( expected, ret ); } void StringTest::testEmptyString() { const char* pszEmpty = ""; std::string sEmpty; std::string sEmpty2( pszEmpty ); PdfString str1; PdfString str2( sEmpty ); PdfString str3( sEmpty2 ); PdfString str4( pszEmpty ); PdfString str5( pszEmpty, 0, false ); PdfString str6( reinterpret_cast(pszEmpty) ); PdfString str7( reinterpret_cast(pszEmpty), 0 ); PdfString str8( reinterpret_cast(L""), 0 ); CPPUNIT_ASSERT( !str1.IsValid() ); CPPUNIT_ASSERT( str2.IsValid() ); CPPUNIT_ASSERT_EQUAL( static_cast(0), str2.GetLength() ); CPPUNIT_ASSERT_EQUAL( static_cast(0), str2.GetCharacterLength() ); CPPUNIT_ASSERT_EQUAL( std::string(), str2.GetStringUtf8() ); CPPUNIT_ASSERT_EQUAL( std::string(""), str2.GetStringUtf8() ); CPPUNIT_ASSERT( str3.IsValid() ); CPPUNIT_ASSERT_EQUAL( static_cast(0), str3.GetLength() ); CPPUNIT_ASSERT_EQUAL( static_cast(0), str3.GetCharacterLength() ); CPPUNIT_ASSERT_EQUAL( std::string(), str3.GetStringUtf8() ); CPPUNIT_ASSERT_EQUAL( std::string(""), str3.GetStringUtf8() ); CPPUNIT_ASSERT( str4.IsValid() ); CPPUNIT_ASSERT_EQUAL( static_cast(0), str4.GetLength() ); CPPUNIT_ASSERT_EQUAL( static_cast(0), str4.GetCharacterLength() ); CPPUNIT_ASSERT_EQUAL( std::string(), str4.GetStringUtf8() ); CPPUNIT_ASSERT_EQUAL( std::string(""), str4.GetStringUtf8() ); CPPUNIT_ASSERT( str5.IsValid() ); CPPUNIT_ASSERT_EQUAL( static_cast(0), str5.GetLength() ); CPPUNIT_ASSERT_EQUAL( static_cast(0), str5.GetCharacterLength() ); CPPUNIT_ASSERT_EQUAL( std::string(), str5.GetStringUtf8() ); CPPUNIT_ASSERT_EQUAL( std::string(""), str5.GetStringUtf8() ); CPPUNIT_ASSERT( str6.IsValid() ); CPPUNIT_ASSERT_EQUAL( static_cast(0), str6.GetLength() ); CPPUNIT_ASSERT_EQUAL( static_cast(0), str6.GetCharacterLength() ); CPPUNIT_ASSERT_EQUAL( std::string(), str6.GetStringUtf8() ); CPPUNIT_ASSERT_EQUAL( std::string(""), str6.GetStringUtf8() ); CPPUNIT_ASSERT( str7.IsValid() ); CPPUNIT_ASSERT_EQUAL( static_cast(0), str7.GetLength() ); CPPUNIT_ASSERT_EQUAL( static_cast(0), str7.GetCharacterLength() ); CPPUNIT_ASSERT_EQUAL( std::string(), str7.GetStringUtf8() ); CPPUNIT_ASSERT_EQUAL( std::string(""), str7.GetStringUtf8() ); CPPUNIT_ASSERT( str8.IsValid() ); CPPUNIT_ASSERT_EQUAL( static_cast(0), str8.GetLength() ); CPPUNIT_ASSERT_EQUAL( static_cast(0), str8.GetCharacterLength() ); CPPUNIT_ASSERT_EQUAL( std::string(), str8.GetStringUtf8() ); CPPUNIT_ASSERT_EQUAL( std::string(""), str8.GetStringUtf8() ); } #endif // __clang__ podofo-0.9.3/test/unit/TokenizerTest.cpp0000664000175000017500000002274011455342347020152 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2007 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "TokenizerTest.h" #include using namespace PoDoFo; CPPUNIT_TEST_SUITE_REGISTRATION( TokenizerTest ); void TokenizerTest::Test( const char* pszString, EPdfDataType eDataType, const char* pszExpected ) { PdfVariant variant; std::string ret; std::string expected; expected = pszExpected ? pszExpected : pszString; printf("Testing with value: %s\n", pszString ); PdfTokenizer tokenizer( pszString, strlen( pszString ) ); tokenizer.GetNextVariant( variant, NULL ); printf(" -> Expected Datatype: %i\n", eDataType ); printf(" -> Got Datatype: %i\n", variant.GetDataType() ); CPPUNIT_ASSERT_EQUAL( variant.GetDataType(), eDataType ); variant.ToString( ret ); printf(" -> Convert To String: %s\n", ret.c_str() ); CPPUNIT_ASSERT_EQUAL( expected, ret ); } void TokenizerTest::setUp() { // Nothing todo here } void TokenizerTest::tearDown() { // Nothing todo here } void TokenizerTest::testArrays() { Test( "[]", ePdfDataType_Array, "[ ]" ); Test( "[ ]", ePdfDataType_Array ); Test( "[ / ]", ePdfDataType_Array, "[ / ]" ); // empty names are legal, too! Test( "[ / [ ] ]", ePdfDataType_Array, "[ / [ ] ]" ); // empty names are legal, too! Test( "[/[]]", ePdfDataType_Array, "[ / [ ] ]" ); // empty names are legal, too! Test( "[ 1 2 3 4 ]", ePdfDataType_Array ); Test( "[1 2 3 4]", ePdfDataType_Array, "[ 1 2 3 4 ]" ); Test( "[ 2 (Hallo Welt!) 3.500000 /FMC ]", ePdfDataType_Array ); Test( "[ [ 1 2 ] (Hallo Welt!) 3.500000 /FMC ]", ePdfDataType_Array ); Test( "[/ImageA/ImageB/ImageC]", ePdfDataType_Array, "[ /ImageA /ImageB /ImageC ]" ); Test( "[<530464995927cef8aaf46eb953b93373><530464995927cef8aaf46eb953b93373>]", ePdfDataType_Array, "[ <530464995927CEF8AAF46EB953B93373> <530464995927CEF8AAF46EB953B93373> ]" ); Test( "[ 2 0 R (Test Data) 4 << /Key /Data >> 5 0 R ]", ePdfDataType_Array, "[ 2 0 R (Test Data) 4 <<\n/Key /Data\n>> 5 0 R ]" ); Test( "[<>2 0 R]", ePdfDataType_Array, "[ <<\n/key /name\n>> 2 0 R ]" ); Test( "[<>2 0 R]", ePdfDataType_Array,"[ <<\n/ /name\n>> 2 0 R ]" ); Test( "[ 27.673200 27.673200 566.256000 651.295000 ]", ePdfDataType_Array ); } void TokenizerTest::testBool() { Test( "false", ePdfDataType_Bool); Test( "true", ePdfDataType_Bool); } void TokenizerTest::testHexString() { Test( "", ePdfDataType_HexString ); Test( "", ePdfDataType_HexString, "" ); Test( "<>", ePdfDataType_HexString ); } void TokenizerTest::testName() { Test( "/Type", ePdfDataType_Name ); Test( "/Length", ePdfDataType_Name ); Test( "/Adobe#20Green", ePdfDataType_Name ); Test( "/$$", ePdfDataType_Name ); Test( "/1.2", ePdfDataType_Name ); Test( "/.notdef", ePdfDataType_Name ); Test( "/@pattern", ePdfDataType_Name ); Test( "/A;Name_With-Various***Characters?", ePdfDataType_Name ); Test( "/", ePdfDataType_Name ); // empty names are legal, too! // Some additional tests, which cause errors for Sebastian Loch const char* pszString = "/CheckBox#C3#9Cbersetzungshinweis"; PdfVariant variant; PdfTokenizer tokenizer( pszString, strlen( pszString ) ); tokenizer.GetNextVariant( variant, NULL ); PdfName name2( variant.GetName() ); std::ostringstream oss; PdfOutputDevice output(&oss); name2.Write(&output, ePdfWriteMode_Default); CPPUNIT_ASSERT_EQUAL( variant.GetName().GetName(), name2.GetName() ); CPPUNIT_ASSERT_EQUAL( oss.str(), std::string(pszString) ); printf("!!! Name=[%s]\n", variant.GetName().GetName().c_str() ); printf("!!! Name2=[%s]\n", name2.GetName().c_str() ); printf("!!! oss=[%s]\n", oss.str().c_str() ); } void TokenizerTest::testNull() { Test( "null", ePdfDataType_Null ); } void TokenizerTest::testNumbers() { Test( "145", ePdfDataType_Number ); Test( "-12", ePdfDataType_Number ); Test( "3.141230", ePdfDataType_Real ); Test( "-2.970000", ePdfDataType_Real ); Test( "0", ePdfDataType_Number ); Test( "4.", ePdfDataType_Real, "4.000000" ); } void TokenizerTest::testReference() { Test( "2 0 R", ePdfDataType_Reference ); Test( "3 0 R", ePdfDataType_Reference ); Test( "4 1 R", ePdfDataType_Reference ); } void TokenizerTest::testString() { // testing strings Test( "(Hallo Welt!)", ePdfDataType_String ); Test( "(Hallo \\(schöne\\) Welt!)", ePdfDataType_String ); Test( "(Balanced () brackets are (ok ()) in PDF Strings)", ePdfDataType_String, "(Balanced \\(\\) brackets are \\(ok \\(\\)\\) in PDF Strings)" ); Test( "()", ePdfDataType_String ); // Test octal strings Test( "(Test: \\064)", ePdfDataType_String, "(Test: \064)" ); Test( "(Test: \\064\\064)", ePdfDataType_String, "(Test: \064\064)" ); Test( "(Test: \\0645)", ePdfDataType_String, "(Test: 45)" ); Test( "(Test: \\478)", ePdfDataType_String, "(Test: '8)" ); // Test line breaks Test( "(Hallo\nWelt!)", ePdfDataType_String, "(Hallo\\nWelt!)" ); Test( "(These \\\ntwo strings \\\nare the same.)", ePdfDataType_String, "(These two strings are the same.)" ); // Test escape sequences Test( "(Hallo\\nWelt!)", ePdfDataType_String, "(Hallo\\nWelt!)" ); Test( "(Hallo\\rWelt!)", ePdfDataType_String, "(Hallo\\rWelt!)" ); Test( "(Hallo\\tWelt!)", ePdfDataType_String, "(Hallo\\tWelt!)" ); Test( "(Hallo\\bWelt!)", ePdfDataType_String, "(Hallo\\bWelt!)" ); Test( "(Hallo\\fWelt!)", ePdfDataType_String, "(Hallo\\fWelt!)" ); } void TokenizerTest::testDictionary() { const char* pszDictIn = "<< /CheckBox#C3#9Cbersetzungshinweis(False)/Checkbox#C3#9Cbersetzungstabelle(False) >>"; const char* pszDictOut = "<<\n/CheckBox#C3#9Cbersetzungshinweis (False)\n/Checkbox#C3#9Cbersetzungstabelle (False)\n>>"; Test( pszDictIn, ePdfDataType_Dictionary, pszDictOut ); } void TokenizerTest::TestStream( const char* pszBuffer, const char* pszTokens[] ) { long lLen = strlen( pszBuffer ); PdfTokenizer tokenizer( pszBuffer, lLen ); EPdfTokenType eType; const char* pszCur; int i = 0; while( pszTokens[i] ) { CPPUNIT_ASSERT_EQUAL( tokenizer.GetNextToken( pszCur, &eType ), true ); std::string sCur( pszCur ); std::string sToken( pszTokens[i] ); CPPUNIT_ASSERT_EQUAL( sCur, sToken ); ++i; } // We are at the end, so GetNextToken has to return false! CPPUNIT_ASSERT_EQUAL( tokenizer.GetNextToken( pszCur, &eType ), false ); } void TokenizerTest::TestStreamIsNextToken( const char* pszBuffer, const char* pszTokens[] ) { long lLen = strlen( pszBuffer ); PdfTokenizer tokenizer( pszBuffer, lLen ); int i = 0; while( pszTokens[i] ) CPPUNIT_ASSERT_EQUAL( tokenizer.IsNextToken( pszTokens[i++] ), true ); } void TokenizerTest::testTokens() { const char* pszBuffer = "613 0 obj" "<< /Length 141 /Filter [ /ASCII85Decode /FlateDecode ] >>" "endobj"; const char* pszTokens[] = { "613", "0", "obj", "<<", "/", "Length", "141", "/", "Filter", "[", "/", "ASCII85Decode", "/", "FlateDecode", "]", ">>", "endobj", NULL }; TestStream( pszBuffer, pszTokens ); TestStreamIsNextToken( pszBuffer, pszTokens ); } void TokenizerTest::testComments() { const char* pszBuffer = "613 0 obj\n" "% A comment that should be ignored\n" "<< /Length 141 /Filter\n% A comment in a dictionary\n[ /ASCII85Decode /FlateDecode ] >>" "endobj"; const char* pszTokens[] = { "613", "0", "obj", "<<", "/", "Length", "141", "/", "Filter", "[", "/", "ASCII85Decode", "/", "FlateDecode", "]", ">>", "endobj", NULL }; TestStream( pszBuffer, pszTokens ); TestStreamIsNextToken( pszBuffer, pszTokens ); } void TokenizerTest::testLocale() { // Test with a locale thate uses "," instead of "." for doubles char *old = setlocale( LC_ALL, "de_DE" ); const char* pszNumber = "3.140000"; Test( pszNumber, ePdfDataType_Real, pszNumber ); setlocale( LC_ALL, old ); } podofo-0.9.3/test/unit/PageTest.cpp0000664000175000017500000000602511523003150017030 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2000 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "PageTest.h" #include "TestUtils.h" #include using namespace PoDoFo; // Registers the fixture into the 'registry' CPPUNIT_TEST_SUITE_REGISTRATION( PageTest ); void PageTest::setUp() { } void PageTest::tearDown() { } void PageTest::testEmptyContents() { PdfVecObjects vecObjects; PdfObject object( PdfReference( 1, 0 ), "Page" ); vecObjects.push_back( &object ); const std::deque parents; PdfPage page( &object, parents ); CPPUNIT_ASSERT( NULL != page.GetContents() ); } void PageTest::testEmptyContentsStream() { PdfMemDocument doc; PdfPage* pPage = doc.CreatePage( PdfPage::CreateStandardPageSize( ePdfPageSize_A4 ) ); PdfAnnotation* pAnnot = pPage->CreateAnnotation( ePdfAnnotation_Popup, PdfRect( 300.0, 20.0, 250.0, 50.0 ) ); PdfString sTitle("Author: Dominik Seichter"); pAnnot->SetContents( sTitle ); pAnnot->SetOpen( true ); std::string sFilename = TestUtils::getTempFilename(); doc.Write( sFilename.c_str() ); // Read annotation again PdfMemDocument doc2( sFilename.c_str() ); CPPUNIT_ASSERT_EQUAL( 1, doc2.GetPageCount() ); PdfPage* pPage2 = doc2.GetPage( 0 ); CPPUNIT_ASSERT( NULL != pPage2 ); CPPUNIT_ASSERT_EQUAL( 1, pPage2->GetNumAnnots() ); PdfAnnotation* pAnnot2 = pPage2->GetAnnotation( 0 ); CPPUNIT_ASSERT( NULL != pAnnot2 ); CPPUNIT_ASSERT( sTitle == pAnnot2->GetContents() ); PdfObject* pPageObject = pPage2->GetObject(); CPPUNIT_ASSERT( !pPageObject->GetDictionary().HasKey("Contents") ); TestUtils::deleteFile( sFilename.c_str() ); } podofo-0.9.3/test/unit/PagesTreeTest.cpp0000664000175000017500000002570512347271543020063 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2008 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "PagesTreeTest.h" #include #define PODOFO_TEST_PAGE_KEY "PoDoFoTestPageNumber" #define PODOFO_TEST_NUM_PAGES 100 using namespace PoDoFo; // Registers the fixture into the 'registry' CPPUNIT_TEST_SUITE_REGISTRATION( PagesTreeTest ); void PagesTreeTest::setUp() { } void PagesTreeTest::tearDown() { } void PagesTreeTest::testEmptyTree() { PdfMemDocument writer; // Empty document must have page count == 0 CPPUNIT_ASSERT_EQUAL( writer.GetPageCount(), 0 ); // Retrieving any page from an empty document must be NULL PdfPage* pPage = writer.GetPagesTree()->GetPage( 0 ); CPPUNIT_ASSERT_EQUAL( pPage, static_cast(NULL) ); pPage = writer.GetPagesTree()->GetPage( -1 ); CPPUNIT_ASSERT_EQUAL( pPage, static_cast(NULL) ); pPage = writer.GetPagesTree()->GetPage( 1 ); CPPUNIT_ASSERT_EQUAL( pPage, static_cast(NULL) ); } void PagesTreeTest::testEmptyDoc() { // PdfPagesTree does not throw exceptions but PdfDocument does PdfMemDocument writer; // Empty document must have page count == 0 CPPUNIT_ASSERT_EQUAL( writer.GetPageCount(), 0 ); // Retrieving any page from an empty document must be NULL CPPUNIT_ASSERT_THROW( writer.GetPage( 0 ), PdfError ); CPPUNIT_ASSERT_THROW( writer.GetPage( -1 ), PdfError ); CPPUNIT_ASSERT_THROW( writer.GetPage( 1 ), PdfError ); } void PagesTreeTest::testCreateDelete() { PdfMemDocument writer; PdfPage* pPage; PdfPainter painter; PdfFont * pFont; // create font pFont = writer.CreateFont( "Arial" ); if( !pFont ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } pFont->SetFontSize( 16.0 ); // write 1. page pPage = writer.CreatePage( PdfPage::CreateStandardPageSize( ePdfPageSize_A4 ) ); painter.SetPage( pPage ); painter.SetFont( pFont ); painter.DrawText( 200, 200, "Page 1" ); painter.FinishPage(); CPPUNIT_ASSERT_EQUAL( writer.GetPageCount(), 1 ); // write 2. page pPage = writer.CreatePage( PdfPage::CreateStandardPageSize( ePdfPageSize_A4 ) ); painter.SetPage( pPage ); painter.DrawText( 200, 200, "Page 2" ); painter.FinishPage(); CPPUNIT_ASSERT_EQUAL( writer.GetPageCount(), 2 ); // try to delete second page, index is 0 based writer.DeletePages( 1, 1 ); CPPUNIT_ASSERT_EQUAL( writer.GetPageCount(), 1 ); // write 3. page pPage = writer.CreatePage( PdfPage::CreateStandardPageSize( ePdfPageSize_A4 ) ); painter.SetPage( pPage ); painter.DrawText( 200, 200, "Page 3" ); painter.FinishPage(); CPPUNIT_ASSERT_EQUAL( writer.GetPageCount(), 2 ); } void PagesTreeTest::testGetPagesCustom() { PdfMemDocument doc; CreateTestTreeCustom( doc ); testGetPages( doc ); } void PagesTreeTest::testGetPagesPoDoFo() { PdfMemDocument doc; CreateTestTreePoDoFo( doc ); testGetPages( doc ); } void PagesTreeTest::testGetPages( PdfMemDocument & doc ) { for(int i=0; iDeletePage( 0 ); for(int i=0; iDeletePage( DELETED_PAGE ); for(int i=0; i=0; i--) { PdfPage* pPage = doc.GetPage( i ); CPPUNIT_ASSERT_EQUAL( pPage != NULL, true ); CPPUNIT_ASSERT_EQUAL( IsPageNumber( pPage, i ), true ); } // Now delete first page doc.GetPagesTree()->DeletePage( 0 ); for(int i=PODOFO_TEST_NUM_PAGES-2; i>=0; i--) { PdfPage* pPage = doc.GetPage( i ); CPPUNIT_ASSERT_EQUAL( pPage != NULL, true ); CPPUNIT_ASSERT_EQUAL( IsPageNumber( pPage, i + 1 ), true ); } } void PagesTreeTest::testInsertCustom() { PdfMemDocument doc; CreateTestTreeCustom( doc ); testInsert( doc ); } void PagesTreeTest::testInsertPoDoFo() { PdfMemDocument doc; CreateTestTreePoDoFo( doc ); testInsert( doc ); } void PagesTreeTest::testInsert( PdfMemDocument & doc ) { const int INSERTED_PAGE_FLAG= 1234; const int INSERTED_PAGE_FLAG1= 1234 + 1; const int INSERTED_PAGE_FLAG2= 1234 + 2; PdfPage* pPage = new PdfPage( PdfPage::CreateStandardPageSize( ePdfPageSize_A4 ), &(doc.GetObjects()) ); pPage->GetObject()->GetDictionary().AddKey( PODOFO_TEST_PAGE_KEY, static_cast(INSERTED_PAGE_FLAG) ); // Insert page at the beginning doc.GetPagesTree()->InsertPage( ePdfPageInsertionPoint_InsertBeforeFirstPage, pPage ); delete pPage; // Find inserted page (beginning) pPage = doc.GetPage( 0 ); CPPUNIT_ASSERT_EQUAL( IsPageNumber( pPage, INSERTED_PAGE_FLAG ), true ); // Find old first page pPage = doc.GetPage( 1 ); CPPUNIT_ASSERT_EQUAL( IsPageNumber( pPage, 0 ), true ); // Insert at end pPage = doc.CreatePage( PdfPage::CreateStandardPageSize( ePdfPageSize_A4 ) ); pPage->GetObject()->GetDictionary().AddKey( PODOFO_TEST_PAGE_KEY, static_cast(INSERTED_PAGE_FLAG1) ); pPage = doc.GetPage( doc.GetPageCount() - 1 ); CPPUNIT_ASSERT_EQUAL( IsPageNumber( pPage, INSERTED_PAGE_FLAG1 ), true ); // Insert in middle pPage = new PdfPage( PdfPage::CreateStandardPageSize( ePdfPageSize_A4 ), &(doc.GetObjects()) ); pPage->GetObject()->GetDictionary().AddKey( PODOFO_TEST_PAGE_KEY, static_cast(INSERTED_PAGE_FLAG2) ); const int INSERT_POINT = 50; doc.GetPagesTree()->InsertPage( INSERT_POINT, pPage ); delete pPage; pPage = doc.GetPage( INSERT_POINT + 1 ); CPPUNIT_ASSERT_EQUAL( IsPageNumber( pPage, INSERTED_PAGE_FLAG2 ), true ); } void PagesTreeTest::testDeleteAllCustom() { PdfMemDocument doc; CreateTestTreeCustom( doc ); testDeleteAll( doc ); } void PagesTreeTest::testDeleteAllPoDoFo() { PdfMemDocument doc; CreateTestTreePoDoFo( doc ); testDeleteAll( doc ); } void PagesTreeTest::testDeleteAll( PdfMemDocument & doc ) { for(int i=0; iDeletePage(0); CPPUNIT_ASSERT_EQUAL( doc.GetPageCount(), PODOFO_TEST_NUM_PAGES - (i + 1) ); } CPPUNIT_ASSERT_EQUAL( doc.GetPageCount(), 0 ); } void PagesTreeTest::CreateTestTreePoDoFo( PoDoFo::PdfMemDocument & rDoc ) { for(int i=0; iGetObject()->GetDictionary().AddKey( PODOFO_TEST_PAGE_KEY, static_cast(i) ); CPPUNIT_ASSERT_EQUAL( rDoc.GetPageCount(), i + 1 ); } } void PagesTreeTest::CreateTestTreeCustom( PoDoFo::PdfMemDocument & rDoc ) { const int COUNT = PODOFO_TEST_NUM_PAGES / 10; PdfObject* pRoot = rDoc.GetPagesTree()->GetObject(); PdfArray rootKids; for(int z=0; zGetObject()->GetDictionary().AddKey( PODOFO_TEST_PAGE_KEY, static_cast(z * COUNT + i) ); //printf("Creating page %i z=%i i=%i\n", z * COUNT + i, z, i ); nodeKids.push_back( pPage->GetObject()->Reference() ); } pNode->GetDictionary().AddKey( PdfName("Kids"), nodeKids ); pNode->GetDictionary().AddKey( PdfName("Count"), static_cast(COUNT) ); rootKids.push_back( pNode->Reference() ); } pRoot->GetDictionary().AddKey( PdfName("Kids"), rootKids ); pRoot->GetDictionary().AddKey( PdfName("Count"), static_cast(PODOFO_TEST_NUM_PAGES) ); } bool PagesTreeTest::IsPageNumber( PoDoFo::PdfPage* pPage, int nNumber ) { pdf_int64 lPageNumber = pPage->GetObject()->GetDictionary().GetKeyAsLong( PODOFO_TEST_PAGE_KEY, -1 ); if( lPageNumber != static_cast(nNumber) ) { printf("PagesTreeTest: Expected page number %i but got %"PDF_FORMAT_INT64".\n", nNumber, lPageNumber); return false; } else return true; } podofo-0.9.3/test/unit/VariantTest.cpp0000664000175000017500000004510211246160175017574 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2008 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "VariantTest.h" #include using namespace PoDoFo; // Registers the fixture into the 'registry' CPPUNIT_TEST_SUITE_REGISTRATION( VariantTest ); static const char* s_pszObjectData = "242 0 obj\n" "<<\n" "/Type /Metadata\n" "/Length 9393\n" "/Subtype /XML\n" ">>\n" "stream\n" "\n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" "\n" "\n" "endstream\n" "endobj\n"; void VariantTest::setUp() { } void VariantTest::tearDown() { } void VariantTest::testEmptyObject() { const char* pszObject = "10 0 obj\nendobj\n"; PdfRefCountedInputDevice device( pszObject, strlen( pszObject ) ); PdfRefCountedBuffer buffer( 1024 ); PdfVecObjects vecObjects; PdfParserObject parser( &vecObjects, device, buffer, 0 ); parser.SetLoadOnDemand( false ); parser.ParseFile( NULL ); CPPUNIT_ASSERT_EQUAL( parser.IsNull(), true ); } void VariantTest::testEmptyStream() { const char* pszObject = "10 0 obj<>stream\nendstream\nendobj\n"; PdfRefCountedInputDevice device( pszObject, strlen( pszObject ) ); PdfRefCountedBuffer buffer( 1024 ); PdfVecObjects vecObjects; PdfParserObject parser( &vecObjects, device, buffer, 0 ); parser.SetLoadOnDemand( false ); parser.ParseFile( NULL ); CPPUNIT_ASSERT_EQUAL( parser.IsDictionary(), true ); CPPUNIT_ASSERT_EQUAL( parser.HasStream(), true ); CPPUNIT_ASSERT_EQUAL( parser.GetStream()->GetLength(), static_cast(0) ); } void VariantTest::testNameObject() { const char* pszObject = "10 0 obj / endobj\n"; PdfRefCountedInputDevice device( pszObject, strlen( pszObject ) ); PdfRefCountedBuffer buffer( 1024 ); PdfVecObjects vecObjects; PdfParserObject parser( &vecObjects, device, buffer, 0 ); parser.SetLoadOnDemand( false ); parser.ParseFile( NULL ); CPPUNIT_ASSERT_EQUAL( parser.IsName(), true ); CPPUNIT_ASSERT_EQUAL( parser.GetName().GetName(), std::string("") ); } void VariantTest::testIsDirtyTrue() { PdfArray array; PdfDictionary dict; PdfVariant varBool( true ); PdfVariant varLong( static_cast(1LL) ); PdfVariant varDouble( 1.0 ); PdfVariant varStr( PdfString("Any") ); PdfVariant varName( PdfName("Name") ); PdfVariant varRef( PdfReference( 0, 0 ) ); PdfVariant varArray( array ); PdfVariant varDict( dict ); PdfVariant varVariant( varBool ); varBool.SetBool( false ); varLong.SetNumber( static_cast(2LL) ); varDouble.SetReal( 2.0 ); varStr = PdfString("Other"); varName = PdfName("Name2"); varRef = PdfReference( 2, 0 ); varArray.GetArray().push_back( varBool ); varDict.GetDictionary().AddKey( varName.GetName(), varStr ); varVariant = varLong; CPPUNIT_ASSERT_EQUAL_MESSAGE( "BOOL IsDirty() == true", true, varBool.IsDirty() ); CPPUNIT_ASSERT_EQUAL_MESSAGE( "LONG IsDirty() == true", true, varLong.IsDirty() ); CPPUNIT_ASSERT_EQUAL_MESSAGE( "DOUBLE IsDirty() == true", true, varDouble.IsDirty() ); CPPUNIT_ASSERT_EQUAL_MESSAGE( "STRING IsDirty() == true", true, varStr.IsDirty() ); CPPUNIT_ASSERT_EQUAL_MESSAGE( "REFERENCE IsDirty() == true", true, varRef.IsDirty() ); CPPUNIT_ASSERT_EQUAL_MESSAGE( "ARRAY IsDirty() == true", true, varArray.IsDirty() ); CPPUNIT_ASSERT_EQUAL_MESSAGE( "DICT IsDirty() == true", true, varDict.IsDirty() ); CPPUNIT_ASSERT_EQUAL_MESSAGE( "VARIANT IsDirty() == true", true, varVariant.IsDirty() ); PdfRefCountedInputDevice device( s_pszObjectData, strlen( s_pszObjectData ) ); PdfRefCountedBuffer buffer( 1024 ); PdfVecObjects vecObjects; PdfParserObject parser( &vecObjects, device, buffer, 0 ); parser.SetLoadOnDemand( false ); parser.ParseFile( NULL ); // After reading const stream it has still to be clean PdfStream* pStream = parser.GetStream(); CPPUNIT_ASSERT_EQUAL( static_cast(pStream->GetLength()), 9381L ); CPPUNIT_ASSERT_EQUAL_MESSAGE( "STREAM IsDirty() == true", true, parser.IsDirty() ); } void VariantTest::testIsDirtyFalse() { PdfArray array; PdfDictionary dict; PdfData data("/Name"); PdfVariant varEmpty; PdfVariant varBool( true ); PdfVariant varLong( static_cast(1LL) ); PdfVariant varDouble( 1.0 ); PdfVariant varStr( PdfString("Any") ); PdfVariant varName( PdfName("Name") ); PdfVariant varRef( PdfReference( 0, 0 ) ); PdfVariant varArray( array ); PdfVariant varDict( dict ); PdfVariant varData( data ); PdfVariant varVariant( varBool ); // IsDirty() should be false after construction CPPUNIT_ASSERT_EQUAL_MESSAGE( "EMPTY IsDirty() == false", false, varEmpty.IsDirty() ); CPPUNIT_ASSERT_EQUAL_MESSAGE( "BOOL IsDirty() == false", false, varBool.IsDirty() ); CPPUNIT_ASSERT_EQUAL_MESSAGE( "LONG IsDirty() == false", false, varLong.IsDirty() ); CPPUNIT_ASSERT_EQUAL_MESSAGE( "DOUBLE IsDirty() == false", false, varDouble.IsDirty() ); CPPUNIT_ASSERT_EQUAL_MESSAGE( "STRING IsDirty() == false", false, varStr.IsDirty() ); CPPUNIT_ASSERT_EQUAL_MESSAGE( "REFERENCE IsDirty() == false", false, varRef.IsDirty() ); CPPUNIT_ASSERT_EQUAL_MESSAGE( "ARRAY IsDirty() == false", false, varArray.IsDirty() ); CPPUNIT_ASSERT_EQUAL_MESSAGE( "DICT IsDirty() == false", false, varDict.IsDirty() ); CPPUNIT_ASSERT_EQUAL_MESSAGE( "DATA IsDirty() == false", false, varData.IsDirty() ); CPPUNIT_ASSERT_EQUAL_MESSAGE( "VARIANT IsDirty() == false", false, varVariant.IsDirty() ); // IsDirty() should be false after calling const getter (void)varBool.GetBool(); (void)varLong.GetNumber(); (void)varDouble.GetReal(); (void)varStr.GetString(); (void)varName.GetName(); (void)varRef.GetReference(); (void)static_cast(varArray).GetArray(); (void)static_cast(varDict).GetDictionary(); (void)varVariant.GetBool(); CPPUNIT_ASSERT_EQUAL_MESSAGE( "BOOL IsDirty() == false", false, varBool.IsDirty() ); CPPUNIT_ASSERT_EQUAL_MESSAGE( "LONG IsDirty() == false", false, varLong.IsDirty() ); CPPUNIT_ASSERT_EQUAL_MESSAGE( "DOUBLE IsDirty() == false", false, varDouble.IsDirty() ); CPPUNIT_ASSERT_EQUAL_MESSAGE( "STRING IsDirty() == false", false, varStr.IsDirty() ); CPPUNIT_ASSERT_EQUAL_MESSAGE( "REFERENCE IsDirty() == false", false, varRef.IsDirty() ); CPPUNIT_ASSERT_EQUAL_MESSAGE( "ARRAY IsDirty() == false", false, varArray.IsDirty() ); CPPUNIT_ASSERT_EQUAL_MESSAGE( "DICT IsDirty() == false", false, varDict.IsDirty() ); CPPUNIT_ASSERT_EQUAL_MESSAGE( "VARIANT IsDirty() == false", false, varVariant.IsDirty() ); // IsDirty() should be false after calling non const getter, but not modifying object (void) varArray.GetArray(); (void) varDict.GetDictionary(); CPPUNIT_ASSERT_EQUAL_MESSAGE( "ARRAY IsDirty() == false", false, varArray.IsDirty() ); CPPUNIT_ASSERT_EQUAL_MESSAGE( "DICT IsDirty() == false", false, varDict.IsDirty() ); // IsDirty() should be false after reading an object PdfRefCountedInputDevice device( s_pszObjectData, strlen( s_pszObjectData ) ); PdfRefCountedBuffer buffer( 1024 ); PdfVecObjects vecObjects; PdfParserObject parser( &vecObjects, device, buffer, 0 ); parser.SetLoadOnDemand( false ); parser.ParseFile( NULL ); // Newly create Object has to be clean CPPUNIT_ASSERT_EQUAL_MESSAGE( "OBJECT IsDirty() == false", false, parser.IsDirty() ); // After reading const stream it has still to be clean const PdfStream* pStream = static_cast(&parser)->GetStream(); CPPUNIT_ASSERT_EQUAL( static_cast(pStream->GetLength()), 9381L ); CPPUNIT_ASSERT_EQUAL_MESSAGE( "STREAM IsDirty() == false", false, parser.IsDirty() ); } podofo-0.9.3/test/unit/NameTest.h0000664000175000017500000000514111067226502016512 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2007 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #ifndef _NAME_TEST_H_ #define _NAME_TEST_H_ #include /** This test tests the class PdfName */ class NameTest : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE( NameTest ); CPPUNIT_TEST( testParseAndWrite ); CPPUNIT_TEST( testNameEncoding ); CPPUNIT_TEST( testEncodedNames ); CPPUNIT_TEST( testEquality ); CPPUNIT_TEST( testWrite ); CPPUNIT_TEST( testFromEscaped ); CPPUNIT_TEST_SUITE_END(); public: void setUp(); void tearDown(); void testParseAndWrite(); void testNameEncoding(); void testEncodedNames(); void testEquality(); void testWrite(); void testFromEscaped(); private: void TestName( const char* pszString, const char* pszExpectedEncoded ); void TestEncodedName( const char* pszString, const char* pszExpected ); /** Tests if both names are equal */ void TestNameEquality( const char * pszName1, const char* pszName2 ); /** Test if pszName interpreted as PdfName and written * to a PdfOutputDevice equals pszResult */ void TestWrite( const char * pszName, const char* pszResult ); void TestFromEscape( const char* pszName1, const char* pszName2 ); }; #endif // _NAME_TEST_H_ podofo-0.9.3/test/unit/PainterTest.cpp0000664000175000017500000000520311523003150017553 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2011 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "PainterTest.h" #include "TestUtils.h" #include using namespace PoDoFo; // Registers the fixture into the 'registry' CPPUNIT_TEST_SUITE_REGISTRATION( PainterTest ); void PainterTest::setUp() { } void PainterTest::tearDown() { } void PainterTest::CompareStreamContent(PdfStream* pStream, const char* pszExpected) { char* pBuffer; pdf_long lLen; pStream->GetFilteredCopy( &pBuffer, &lLen ); std::string str(pBuffer, lLen); CPPUNIT_ASSERT_EQUAL( std::string(pszExpected), str ); free( pBuffer ); } void PainterTest::testAppend() { const char* pszExample1 = "BT (Hallo) Tj ET"; const char* pszColor = " 1.000 1.000 1.000 rg\n"; PdfMemDocument doc; PdfPage* pPage = doc.CreatePage( PdfPage::CreateStandardPageSize( ePdfPageSize_A4 ) ); pPage->GetContents()->GetStream()->Set(pszExample1) ; this->CompareStreamContent(pPage->GetContents()->GetStream(), pszExample1); PdfPainter painter; painter.SetPage( pPage ); painter.SetColor( 1.0, 1.0, 1.0 ); painter.FinishPage(); std::string newContent = pszExample1; newContent += pszColor; this->CompareStreamContent(pPage->GetContents()->GetStream(), newContent.c_str()); } podofo-0.9.3/test/unit/cppunitextensions.h0000664000175000017500000001407212347312510020574 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2010 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include #include // Registers the fixture into the 'registry' CPPUNIT_TEST_SUITE_REGISTRATION( ColorTest ); /** Added by RG to check if a suitable error message is returned * Asserts that the given expression throws an exception of the specified type. * \ingroup Assertions * Example of usage: * \code * std::vector v; * CPPUNIT_ASSERT_THROW( v.at( 50 ), std::out_of_range ); * \endcode */ # define CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( expression, ExceptionType, errorType ) \ CPPUNIT_ASSERT_THROW_MESSAGE_WITH_ERROR_TYPE( CPPUNIT_NS::AdditionalMessage(), \ expression, \ ExceptionType, \ errorType) /** Added by RG to check if a suitable error message is returned * Asserts that the given expression throws an exception of the specified type, * setting a user supplied message in case of failure. * \ingroup Assertions * Example of usage: * \code * std::vector v; * CPPUNIT_ASSERT_THROW_MESSAGE( "- std::vector v;", v.at( 50 ), std::out_of_range ); * \endcode */ # define CPPUNIT_ASSERT_THROW_MESSAGE_WITH_ERROR_TYPE( message, expression, ExceptionType, errorType ) \ do { \ bool cpputCorrectExceptionThrown_ = false; \ CPPUNIT_NS::Message cpputMsg_( "expected exception not thrown" ); \ cpputMsg_.addDetail( message ); \ cpputMsg_.addDetail( "Expected: " \ CPPUNIT_GET_PARAMETER_STRING( ExceptionType ) ); \ \ try { \ expression; \ } catch ( const ExceptionType &e) { \ if (e.GetError() == errorType) \ { \ cpputCorrectExceptionThrown_ = true; \ } \ else \ { \ cpputMsg_.addDetail( "Error type mismatch. Actual: " #errorType ); \ cpputMsg_.addDetail( std::string("What() : ") + e.ErrorName(e.GetError()) ); \ } \ } catch ( const std::exception &e) { \ cpputMsg_.addDetail( "Actual : " + \ CPPUNIT_EXTRACT_EXCEPTION_TYPE_( e, \ "std::exception or derived") ); \ cpputMsg_.addDetail( std::string("What() : ") + e.what() ); \ } catch ( ... ) { \ cpputMsg_.addDetail( "Actual : unknown."); \ } \ \ if ( cpputCorrectExceptionThrown_ ) \ break; \ \ CPPUNIT_NS::Asserter::fail( cpputMsg_, \ CPPUNIT_SOURCELINE() ); \ } while ( false ) //GoogleTest compatible macros #define ASSERT_TRUE(x) CPPUNIT_ASSERT(x) #define ASSERT_FALSE(x) CPPUNIT_ASSERT(!(x)) #define EXPECT_TRUE(x) CPPUNIT_ASSERT(x) #define EXPECT_FALSE(x) CPPUNIT_ASSERT(!(x)) #define EXPECT_EQ(expected, actual) CPPUNIT_ASSERT_EQUAL(expected, actual) #define ASSERT_EQ(expected, actual) CPPUNIT_ASSERT_EQUAL(expected, actual) #define EXPECT_NE(expected, actual) CPPUNIT_ASSERT(expected != actual) #define ASSERT_NE(expected, actual) CPPUNIT_ASSERT(expected != actual) #define EXPECT_DOUBLE_EQ(expected, actual, delta) CPPUNIT_ASSERT_DOUBLES_EQUAL(expected, actual, delta) #define ASSERT_DOUBLE_EQ(expected, actual, delta) CPPUNIT_ASSERT_DOUBLES_EQUAL(expected, actual, delta) podofo-0.9.3/test/unit/DateTest.h0000664000175000017500000000352111763153744016521 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2012 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #ifndef _DATE_TEST_H_ #define _DATE_TEST_H_ #include class DateTest : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE( DateTest ); CPPUNIT_TEST( testCreateDateFromString ); CPPUNIT_TEST( testDateValue ); CPPUNIT_TEST_SUITE_END(); public: void setUp(); void tearDown(); void testCreateDateFromString(); void testDateValue(); }; #endif podofo-0.9.3/test/unit/FilterTest.cpp0000664000175000017500000001150111175404250017405 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2007 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "FilterTest.h" #include #include using namespace PoDoFo; CPPUNIT_TEST_SUITE_REGISTRATION( FilterTest ); static const char s_pTestBuffer1[] = "Man is distinguished, not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure."; // We treat the buffer as _excluding_ the trailing \0 static const long s_lTestLength1 = strlen(s_pTestBuffer1); const char s_pTestBuffer2[] = { 0x01, 0x64, 0x65, 0xFE, 0x6B, 0x80, 0x45, 0x32, 0x88, 0x12, 0x71, 0xEA, 0x01, 0x01, 0x64, 0x65, 0xFE, 0x6B, 0x80, 0x45, 0x32, 0x88, 0x12, 0x71, 0xEA, 0x03, 0x01, 0x64, 0x65, 0xFE, 0x6B, 0x80, 0x45, 0x32, 0x88, 0x12, 0x71, 0xEA, 0x02, 0x01, 0x64, 0x65, 0xFE, 0x6B, 0x80, 0x45, 0x32, 0x88, 0x12, 0x71, 0xEA, 0x00, 0x01, 0x64, 0x65, 0xFE, 0x6B, 0x80, 0x45, 0x32, 0x88, 0x12, 0x71, 0xEA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; const long s_lTestLength2 = 6*13; void FilterTest::setUp() { } void FilterTest::tearDown() { } void FilterTest::TestFilter( EPdfFilter eFilter, const char * pTestBuffer, const long lTestLength ) { char* pEncoded; char* pDecoded; pdf_long lEncoded; pdf_long lDecoded; std::auto_ptr pFilter = PdfFilterFactory::Create( eFilter ); if( !pFilter.get() ) { printf("!!! Filter %i not implemented.\n", eFilter); return; } printf("Testing Algorithm %i:\n", eFilter); printf("\t-> Testing Encoding\n"); try { pFilter->Encode( pTestBuffer, lTestLength, &pEncoded, &lEncoded ); } catch( PdfError & e ) { if( e == ePdfError_UnsupportedFilter ) { printf("\t-> Encoding not supported for filter %i.\n", eFilter ); return; } else { e.AddToCallstack( __FILE__, __LINE__ ); throw e; } } printf("\t-> Testing Decoding\n"); try { pFilter->Decode( pEncoded, lEncoded, &pDecoded, &lDecoded ); } catch( PdfError & e ) { if( e == ePdfError_UnsupportedFilter ) { printf("\t-> Decoding not supported for filter %i.\n", eFilter); return; } else { e.AddToCallstack( __FILE__, __LINE__ ); throw e; } } printf("\t-> Original Data Length: %li\n", lTestLength ); printf("\t-> Encoded Data Length: %li\n", lEncoded ); printf("\t-> Decoded Data Length: %li\n", lDecoded ); CPPUNIT_ASSERT_EQUAL( static_cast(lTestLength), static_cast(lDecoded) ); CPPUNIT_ASSERT_EQUAL( memcmp( pTestBuffer, pDecoded, lTestLength ), 0 ); free( pEncoded ); free( pDecoded ); printf("\t-> Test succeeded!\n"); } void FilterTest::testFilters() { for( int i =0; i<=ePdfFilter_Crypt; i++ ) { TestFilter( static_cast(i), s_pTestBuffer1, s_lTestLength1 ); TestFilter( static_cast(i), s_pTestBuffer2, s_lTestLength2 ); } } void FilterTest::testCCITT() { std::auto_ptr pFilter = PdfFilterFactory::Create( ePdfFilter_CCITTFaxDecode ); if( !pFilter.get() ) { printf("!!! ePdfFilter_CCITTFaxDecode not implemented skipping test!\n"); return; } } podofo-0.9.3/test/unit/PainterTest.h0000664000175000017500000000440311523003150017221 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2011 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #ifndef _PAINTER_TEST_H_ #define _PAINTER_TEST_H_ #include namespace PoDoFo { class PdfPage; class PdfStream; }; /** This test tests the class PdfPainter */ class PainterTest : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE( PainterTest ); CPPUNIT_TEST( testAppend ); CPPUNIT_TEST_SUITE_END(); public: void setUp(); void tearDown(); /** * Test if contents are appended correctly * to pages with existing contents. */ void testAppend(); private: /** * Compare the filtered contents of a PdfStream object * with a string and assert if the contents do not match! * * @param pStream PdfStream object * @param pszContent expected contents */ void CompareStreamContent(PoDoFo::PdfStream* pStream, const char* pszExpected); }; #endif // _PAINTER_TEST_H_ podofo-0.9.3/test/unit/PagesTreeTest.h0000664000175000017500000000725211201067720017511 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2008 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #ifndef _PAGES_TREE_TEST_H_ #define _PAGES_TREE_TEST_H_ #include namespace PoDoFo { class PdfMemDocument; class PdfPage; }; /** This test tests the class PdfPagesTree */ class PagesTreeTest : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE( PagesTreeTest ); CPPUNIT_TEST( testEmptyTree ); CPPUNIT_TEST( testEmptyDoc ); CPPUNIT_TEST( testCreateDelete ); CPPUNIT_TEST( testGetPagesCustom ); CPPUNIT_TEST( testGetPagesPoDoFo ); CPPUNIT_TEST( testGetPagesReverseCustom ); CPPUNIT_TEST( testGetPagesReversePoDoFo ); CPPUNIT_TEST( testInsertCustom ); CPPUNIT_TEST( testInsertPoDoFo ); CPPUNIT_TEST( testDeleteAllCustom ); CPPUNIT_TEST( testDeleteAllPoDoFo ); CPPUNIT_TEST_SUITE_END(); public: void setUp(); void tearDown(); void testEmptyTree(); void testEmptyDoc(); void testCreateDelete(); void testGetPagesCustom(); void testGetPagesPoDoFo(); void testGetPagesReverseCustom(); void testGetPagesReversePoDoFo(); void testInsertCustom(); void testInsertPoDoFo(); void testDeleteAllCustom(); void testDeleteAllPoDoFo(); private: void testGetPages( PoDoFo::PdfMemDocument & doc ); void testGetPagesReverse( PoDoFo::PdfMemDocument & doc ); void testInsert( PoDoFo::PdfMemDocument & doc ); void testDeleteAll( PoDoFo::PdfMemDocument & doc ); /** * Create a pages tree with 100 pages, * where every page object has an additional * key PoDoFoTestPageNumber with the original * page number of the page. * * This method uses PoDoFo's build in PdfPagesTree * which creates a flat tree. * * You can check the page number ussing IsPageNumber() * * @see IsPageNumber */ void CreateTestTreePoDoFo( PoDoFo::PdfMemDocument & rDoc ); /** * Create a pages tree with 100 pages, * where every page object has an additional * key PoDoFoTestPageNumber with the original * page number of the page. * * This builds a pages tree manually an makes * sure a real tree structure is build. * * You can check the page number ussing IsPageNumber() * * @see IsPageNumber */ void CreateTestTreeCustom( PoDoFo::PdfMemDocument & rDoc ); bool IsPageNumber( PoDoFo::PdfPage* pPage, int nNumber ); }; #endif // _PAGES_TREE_TEST_H_ podofo-0.9.3/test/unit/TestUtils.h0000664000175000017500000000375611423516632016746 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2010 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #ifndef _TEST_UTILS_H_ #define _TEST_UTILS_H_ #include /** * This class contains utility methods that are * often needed when writing tests. */ class TestUtils { public: static std::string getTempFilename(); static void deleteFile( const char* pszFilename ); /** * Read a test data file into memory and return a malloc'ed buffer. * * @param pszFilename filename of the data file. The path will be determined automatically. */ static char* readDataFile( const char* pszFilename ); }; #endif // _TEST_UTILS_H_ podofo-0.9.3/test/unit/ColorTest.cpp0000664000175000017500000024511411473153124017251 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2010 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "ColorTest.h" #include #include "cppunitextensions.h" #include #include #include using namespace PoDoFo; // Registers the fixture into the 'registry' CPPUNIT_TEST_SUITE_REGISTRATION( ColorTest ); //#define DEBUG_INFO void ColorTest::setUp() { } void ColorTest::tearDown() { } void ColorTest::testDefaultConstructor() { #ifdef DEBUG_INFO std::cout << "testDefaultConstructor" << std::endl; #endif PdfColor color; ASSERT_FALSE(color.IsGrayScale()); ASSERT_FALSE(color.IsRGB()); ASSERT_FALSE(color.IsCMYK()); ASSERT_FALSE(color.IsSeparation()); ASSERT_FALSE(color.IsCieLab()); ASSERT_EQ(color.GetColorSpace(), ePdfColorSpace_Unknown); CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( color.GetAlternateColorSpace(), PdfError, ePdfError_InternalLogic); CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( color.GetGrayScale(), PdfError, ePdfError_InternalLogic); CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( color.GetRed(), PdfError, ePdfError_InternalLogic); CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( color.GetGreen(), PdfError, ePdfError_InternalLogic); CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( color.GetBlue(), PdfError, ePdfError_InternalLogic); CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( color.GetCyan(), PdfError, ePdfError_InternalLogic); CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( color.GetMagenta(), PdfError, ePdfError_InternalLogic); CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( color.GetYellow(), PdfError, ePdfError_InternalLogic); CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( color.GetBlack(), PdfError, ePdfError_InternalLogic); CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( color.GetName(), PdfError, ePdfError_InternalLogic); CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( color.GetDensity(), PdfError, ePdfError_InternalLogic); CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( color.GetCieL(), PdfError, ePdfError_InternalLogic); CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( color.GetCieA(), PdfError, ePdfError_InternalLogic); CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( color.GetCieB(), PdfError, ePdfError_InternalLogic); CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( color.ConvertToGrayScale(), PdfError, ePdfError_CannotConvertColor); CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( color.ConvertToRGB(), PdfError, ePdfError_CannotConvertColor); CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( color.ConvertToCMYK(), PdfError, ePdfError_CannotConvertColor); CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( color.ToArray(), PdfError, ePdfError_CannotConvertColor); } void ColorTest::testGreyConstructor() { #ifdef DEBUG_INFO std::cout << "testGreyConstructor" << std::endl; #endif const double GREY_VALUE = 0.123; PdfColor color(GREY_VALUE); ASSERT_TRUE(color.IsGrayScale()); ASSERT_FALSE(color.IsRGB()); ASSERT_FALSE(color.IsCMYK()); ASSERT_FALSE(color.IsSeparation()); ASSERT_FALSE(color.IsCieLab()); ASSERT_EQ(color.GetColorSpace(), ePdfColorSpace_DeviceGray); CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( color.GetAlternateColorSpace(), PdfError, ePdfError_InternalLogic); ASSERT_EQ(color.GetGrayScale(), GREY_VALUE); CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( color.GetRed(), PdfError, ePdfError_InternalLogic); CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( color.GetGreen(), PdfError, ePdfError_InternalLogic); CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( color.GetBlue(), PdfError, ePdfError_InternalLogic); CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( color.GetCyan(), PdfError, ePdfError_InternalLogic); CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( color.GetMagenta(), PdfError, ePdfError_InternalLogic); CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( color.GetYellow(), PdfError, ePdfError_InternalLogic); CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( color.GetBlack(), PdfError, ePdfError_InternalLogic); CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( color.GetName(), PdfError, ePdfError_InternalLogic); CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( color.GetDensity(), PdfError, ePdfError_InternalLogic); CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( color.GetCieL(), PdfError, ePdfError_InternalLogic); CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( color.GetCieA(), PdfError, ePdfError_InternalLogic); CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( color.GetCieB(), PdfError, ePdfError_InternalLogic); ASSERT_TRUE(color == color.ConvertToGrayScale()); ASSERT_TRUE(PdfColor(GREY_VALUE, GREY_VALUE, GREY_VALUE) == color.ConvertToRGB()); ASSERT_TRUE(color.ConvertToRGB().ConvertToCMYK() == color.ConvertToCMYK()); const PdfArray COLOR_ARRAY = color.ToArray(); ASSERT_TRUE(1 == COLOR_ARRAY.GetSize()); ASSERT_TRUE(PdfObject(GREY_VALUE) == COLOR_ARRAY[0]); } void ColorTest::testGreyConstructorInvalid() { #ifdef DEBUG_INFO std::cout << "testGreyConstructorInvalid" << std::endl; #endif { const double GREY_VALUE = 1.01; CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( const PdfColor TEST_COLOR(GREY_VALUE), PdfError, ePdfError_ValueOutOfRange); } { const double GREY_VALUE = -0.01; CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( const PdfColor TEST_COLOR(GREY_VALUE), PdfError, ePdfError_ValueOutOfRange); } } void ColorTest::testRGBConstructor() { #ifdef DEBUG_INFO std::cout << "testRGBConstructor" << std::endl; #endif const double R_VALUE = 0.023; const double G_VALUE = 0.345; const double B_VALUE = 0.678; PdfColor color(R_VALUE, G_VALUE, B_VALUE); ASSERT_FALSE(color.IsGrayScale()); ASSERT_TRUE(color.IsRGB()); ASSERT_FALSE(color.IsCMYK()); ASSERT_FALSE(color.IsSeparation()); ASSERT_FALSE(color.IsCieLab()); ASSERT_EQ(color.GetColorSpace(), ePdfColorSpace_DeviceRGB); CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( color.GetAlternateColorSpace(), PdfError, ePdfError_InternalLogic); CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( color.GetGrayScale(), PdfError, ePdfError_InternalLogic); ASSERT_EQ(color.GetRed(), R_VALUE); ASSERT_EQ(color.GetGreen(), G_VALUE); ASSERT_EQ(color.GetBlue(), B_VALUE); CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( color.GetCyan(), PdfError, ePdfError_InternalLogic); CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( color.GetMagenta(), PdfError, ePdfError_InternalLogic); CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( color.GetYellow(), PdfError, ePdfError_InternalLogic); CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( color.GetBlack(), PdfError, ePdfError_InternalLogic); CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( color.GetName(), PdfError, ePdfError_InternalLogic); CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( color.GetDensity(), PdfError, ePdfError_InternalLogic); CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( color.GetCieL(), PdfError, ePdfError_InternalLogic); CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( color.GetCieA(), PdfError, ePdfError_InternalLogic); CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( color.GetCieB(), PdfError, ePdfError_InternalLogic); ASSERT_TRUE(PdfColor(0.299*R_VALUE + 0.587*G_VALUE + 0.114*B_VALUE) == color.ConvertToGrayScale()); ASSERT_TRUE(PdfColor(R_VALUE, G_VALUE, B_VALUE) == color.ConvertToRGB()); { double dBlack = PDF_MIN( 1.0-R_VALUE, PDF_MIN( 1.0-G_VALUE, 1.0-B_VALUE )); double dCyan = (1.0-R_VALUE-dBlack) /(1.0-dBlack); double dMagenta = (1.0-G_VALUE-dBlack)/(1.0-dBlack); double dYellow = (1.0-B_VALUE-dBlack) /(1.0-dBlack); ASSERT_TRUE(PdfColor( dCyan, dMagenta, dYellow, dBlack ) == color.ConvertToCMYK()); } const PdfArray COLOR_ARRAY = color.ToArray(); ASSERT_TRUE(3 == COLOR_ARRAY.GetSize()); ASSERT_TRUE(PdfObject(R_VALUE) == COLOR_ARRAY[0]); ASSERT_TRUE(PdfObject(G_VALUE) == COLOR_ARRAY[1]); ASSERT_TRUE(PdfObject(B_VALUE) == COLOR_ARRAY[2]); } void ColorTest::testRGBConstructorInvalid() { #ifdef DEBUG_INFO std::cout << "testRGBConstructorInvalid" << std::endl; #endif { const double R_VALUE = 1.023; const double G_VALUE = 0.345; const double B_VALUE = 0.678; CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( const PdfColor TEST_COLOR(R_VALUE, G_VALUE, B_VALUE), PdfError, ePdfError_ValueOutOfRange); } { const double R_VALUE = 0.023; const double G_VALUE = 1.345; const double B_VALUE = 0.678; CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( const PdfColor TEST_COLOR(R_VALUE, G_VALUE, B_VALUE), PdfError, ePdfError_ValueOutOfRange); } { const double R_VALUE = 0.023; const double G_VALUE = 0.345; const double B_VALUE = 2.678; CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( const PdfColor TEST_COLOR(R_VALUE, G_VALUE, B_VALUE), PdfError, ePdfError_ValueOutOfRange); } { const double R_VALUE = -0.023; const double G_VALUE = 0.345; const double B_VALUE = 0.678; CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( const PdfColor TEST_COLOR(R_VALUE, G_VALUE, B_VALUE), PdfError, ePdfError_ValueOutOfRange); } { const double R_VALUE = 0.023; const double G_VALUE = -0.345; const double B_VALUE = 0.678; CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( const PdfColor TEST_COLOR(R_VALUE, G_VALUE, B_VALUE), PdfError, ePdfError_ValueOutOfRange); } { const double R_VALUE = 0.023; const double G_VALUE = 0.345; const double B_VALUE = -0.678; CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( const PdfColor TEST_COLOR(R_VALUE, G_VALUE, B_VALUE), PdfError, ePdfError_ValueOutOfRange); } } void ColorTest::testCMYKConstructor() { #ifdef DEBUG_INFO std::cout << "testCMYKConstructor" << std::endl; #endif const double C_VALUE = 0.1; const double M_VALUE = 0.2; const double Y_VALUE = 0.3; const double B_VALUE = 0.4; PdfColor color(C_VALUE, M_VALUE, Y_VALUE, B_VALUE); ASSERT_FALSE(color.IsGrayScale()); ASSERT_FALSE(color.IsRGB()); ASSERT_TRUE(color.IsCMYK()); ASSERT_FALSE(color.IsSeparation()); ASSERT_FALSE(color.IsCieLab()); ASSERT_EQ(color.GetColorSpace(), ePdfColorSpace_DeviceCMYK); CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( color.GetAlternateColorSpace(), PdfError, ePdfError_InternalLogic); CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( color.GetGrayScale(), PdfError, ePdfError_InternalLogic); CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( color.GetRed(), PdfError, ePdfError_InternalLogic); CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( color.GetGreen(), PdfError, ePdfError_InternalLogic); CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( color.GetBlue(), PdfError, ePdfError_InternalLogic); ASSERT_EQ(color.GetCyan(), C_VALUE); ASSERT_EQ(color.GetMagenta(), M_VALUE); ASSERT_EQ(color.GetYellow(), Y_VALUE); ASSERT_EQ(color.GetBlack(), B_VALUE); CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( color.GetName(), PdfError, ePdfError_InternalLogic); CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( color.GetDensity(), PdfError, ePdfError_InternalLogic); CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( color.GetCieL(), PdfError, ePdfError_InternalLogic); CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( color.GetCieA(), PdfError, ePdfError_InternalLogic); CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( color.GetCieB(), PdfError, ePdfError_InternalLogic); ASSERT_TRUE(color.ConvertToRGB().ConvertToGrayScale() == color.ConvertToGrayScale()); { double dRed = C_VALUE * (1.0 - B_VALUE) + B_VALUE; double dGreen = M_VALUE * (1.0 - B_VALUE) + B_VALUE; double dBlue = Y_VALUE * (1.0 - B_VALUE) + B_VALUE; ASSERT_TRUE(PdfColor( 1.0 - dRed, 1.0 - dGreen, 1.0 - dBlue ) == color.ConvertToRGB()); } ASSERT_TRUE(PdfColor(C_VALUE, M_VALUE, Y_VALUE, B_VALUE) == color.ConvertToCMYK()); const PdfArray COLOR_ARRAY = color.ToArray(); ASSERT_TRUE(4 == COLOR_ARRAY.GetSize()); ASSERT_TRUE(PdfObject(C_VALUE) == COLOR_ARRAY[0]); ASSERT_TRUE(PdfObject(M_VALUE) == COLOR_ARRAY[1]); ASSERT_TRUE(PdfObject(Y_VALUE) == COLOR_ARRAY[2]); ASSERT_TRUE(PdfObject(B_VALUE) == COLOR_ARRAY[3]); } void ColorTest::testCMYKConstructorInvalid() { #ifdef DEBUG_INFO std::cout << "testCMYKConstructorInvalid" << std::endl; #endif { const double C_VALUE = 1.1; const double M_VALUE = 0.2; const double Y_VALUE = 0.3; const double B_VALUE = 0.4; CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( const PdfColor TEST_COLOR(C_VALUE, M_VALUE, Y_VALUE, B_VALUE), PdfError, ePdfError_ValueOutOfRange); } { const double C_VALUE = 0.1; const double M_VALUE = 1.2; const double Y_VALUE = 0.3; const double B_VALUE = 0.4; CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( const PdfColor TEST_COLOR(C_VALUE, M_VALUE, Y_VALUE, B_VALUE), PdfError, ePdfError_ValueOutOfRange); } { const double C_VALUE = 0.1; const double M_VALUE = 0.2; const double Y_VALUE = 1.3; const double B_VALUE = 0.4; CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( const PdfColor TEST_COLOR(C_VALUE, M_VALUE, Y_VALUE, B_VALUE), PdfError, ePdfError_ValueOutOfRange); } { const double C_VALUE = 0.1; const double M_VALUE = 0.2; const double Y_VALUE = 0.3; const double B_VALUE = 1.4; CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( const PdfColor TEST_COLOR(C_VALUE, M_VALUE, Y_VALUE, B_VALUE), PdfError, ePdfError_ValueOutOfRange); } { const double C_VALUE = -0.1; const double M_VALUE = 0.2; const double Y_VALUE = 0.3; const double B_VALUE = 0.4; CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( const PdfColor TEST_COLOR(C_VALUE, M_VALUE, Y_VALUE, B_VALUE), PdfError, ePdfError_ValueOutOfRange); } { const double C_VALUE = 0.1; const double M_VALUE = -0.2; const double Y_VALUE = 0.3; const double B_VALUE = 0.4; CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( const PdfColor TEST_COLOR(C_VALUE, M_VALUE, Y_VALUE, B_VALUE), PdfError, ePdfError_ValueOutOfRange); } { const double C_VALUE = 0.1; const double M_VALUE = 0.2; const double Y_VALUE = -0.3; const double B_VALUE = 0.4; CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( const PdfColor TEST_COLOR(C_VALUE, M_VALUE, Y_VALUE, B_VALUE), PdfError, ePdfError_ValueOutOfRange); } { const double C_VALUE = 0.1; const double M_VALUE = 0.2; const double Y_VALUE = 0.3; const double B_VALUE = -0.4; CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( const PdfColor TEST_COLOR(C_VALUE, M_VALUE, Y_VALUE, B_VALUE), PdfError, ePdfError_ValueOutOfRange); } } void ColorTest::testCopyConstructor() { #ifdef DEBUG_INFO std::cout << "testCopyConstructor" << std::endl; #endif { const double GREY_VALUE = 0.123; PdfColor initialColor(GREY_VALUE); PdfColor color(initialColor); ASSERT_TRUE(color.IsGrayScale()); ASSERT_FALSE(color.IsRGB()); ASSERT_FALSE(color.IsCMYK()); ASSERT_FALSE(color.IsSeparation()); ASSERT_FALSE(color.IsCieLab()); ASSERT_EQ(color.GetColorSpace(), ePdfColorSpace_DeviceGray); ASSERT_EQ(color.GetGrayScale(), GREY_VALUE); } { const double R_VALUE = 0.023; const double G_VALUE = 0.345; const double B_VALUE = 0.678; PdfColor initialColor(R_VALUE, G_VALUE, B_VALUE); PdfColor color(initialColor); ASSERT_FALSE(color.IsGrayScale()); ASSERT_TRUE(color.IsRGB()); ASSERT_FALSE(color.IsCMYK()); ASSERT_FALSE(color.IsSeparation()); ASSERT_FALSE(color.IsCieLab()); ASSERT_EQ(color.GetColorSpace(), ePdfColorSpace_DeviceRGB); ASSERT_EQ(color.GetRed(), R_VALUE); ASSERT_EQ(color.GetGreen(), G_VALUE); ASSERT_EQ(color.GetBlue(), B_VALUE); } { const double C_VALUE = 0.1; const double M_VALUE = 0.2; const double Y_VALUE = 0.3; const double B_VALUE = 0.4; PdfColor initialColor(C_VALUE, M_VALUE, Y_VALUE, B_VALUE); PdfColor color(initialColor); ASSERT_FALSE(color.IsGrayScale()); ASSERT_FALSE(color.IsRGB()); ASSERT_TRUE(color.IsCMYK()); ASSERT_FALSE(color.IsSeparation()); ASSERT_FALSE(color.IsCieLab()); ASSERT_EQ(color.GetColorSpace(), ePdfColorSpace_DeviceCMYK); ASSERT_EQ(color.GetCyan(), C_VALUE); ASSERT_EQ(color.GetMagenta(), M_VALUE); ASSERT_EQ(color.GetYellow(), Y_VALUE); ASSERT_EQ(color.GetBlack(), B_VALUE); } } void ColorTest::testAssignmentOperator() { #ifdef DEBUG_INFO std::cout << "testAssignmentOperator" << std::endl; #endif { const double GREY_VALUE = 0.123; PdfColor initialColor(GREY_VALUE); PdfColor color; color = initialColor; ASSERT_TRUE(color.IsGrayScale()); ASSERT_FALSE(color.IsRGB()); ASSERT_FALSE(color.IsCMYK()); ASSERT_FALSE(color.IsSeparation()); ASSERT_FALSE(color.IsCieLab()); ASSERT_EQ(color.GetColorSpace(), ePdfColorSpace_DeviceGray); ASSERT_EQ(color.GetGrayScale(), GREY_VALUE); } { const double R_VALUE = 0.023; const double G_VALUE = 0.345; const double B_VALUE = 0.678; PdfColor initialColor(R_VALUE, G_VALUE, B_VALUE); PdfColor color; color = initialColor; ASSERT_FALSE(color.IsGrayScale()); ASSERT_TRUE(color.IsRGB()); ASSERT_FALSE(color.IsCMYK()); ASSERT_FALSE(color.IsSeparation()); ASSERT_FALSE(color.IsCieLab()); ASSERT_EQ(color.GetColorSpace(), ePdfColorSpace_DeviceRGB); ASSERT_EQ(color.GetRed(), R_VALUE); ASSERT_EQ(color.GetGreen(), G_VALUE); ASSERT_EQ(color.GetBlue(), B_VALUE); } { const double C_VALUE = 0.1; const double M_VALUE = 0.2; const double Y_VALUE = 0.3; const double B_VALUE = 0.4; PdfColor initialColor(C_VALUE, M_VALUE, Y_VALUE, B_VALUE); PdfColor color; color = initialColor; ASSERT_FALSE(color.IsGrayScale()); ASSERT_FALSE(color.IsRGB()); ASSERT_TRUE(color.IsCMYK()); ASSERT_FALSE(color.IsSeparation()); ASSERT_FALSE(color.IsCieLab()); ASSERT_EQ(color.GetColorSpace(), ePdfColorSpace_DeviceCMYK); ASSERT_EQ(color.GetCyan(), C_VALUE); ASSERT_EQ(color.GetMagenta(), M_VALUE); ASSERT_EQ(color.GetYellow(), Y_VALUE); ASSERT_EQ(color.GetBlack(), B_VALUE); } } void ColorTest::testEqualsOperator() { #ifdef DEBUG_INFO std::cout << "testEqualsOperator" << std::endl; #endif //Grey test { //Positive const double GREY_VALUE = 0.123; PdfColor lColor(GREY_VALUE); PdfColor rColor(GREY_VALUE); ASSERT_TRUE(lColor == rColor); } { //Negative const double L_GREY_VALUE = 0.123; PdfColor lColor(L_GREY_VALUE); const double R_GREY_VALUE = 0.124; PdfColor rColor(R_GREY_VALUE); ASSERT_FALSE(L_GREY_VALUE == R_GREY_VALUE); ASSERT_FALSE(lColor == rColor); } //RGB tests { //Positive const double L_R_VALUE = 0.023; const double L_G_VALUE = 0.345; const double L_B_VALUE = 0.678; PdfColor lColor(L_R_VALUE, L_G_VALUE, L_B_VALUE); const double R_R_VALUE = 0.023; const double R_G_VALUE = 0.345; const double R_B_VALUE = 0.678; PdfColor rColor(R_R_VALUE, R_G_VALUE, R_B_VALUE); ASSERT_TRUE(L_R_VALUE == R_R_VALUE); ASSERT_TRUE(L_G_VALUE == R_G_VALUE); ASSERT_TRUE(L_B_VALUE == R_B_VALUE); ASSERT_TRUE(lColor == rColor); } { //Negative const double L_R_VALUE = 0.023; const double L_G_VALUE = 0.345; const double L_B_VALUE = 0.678; PdfColor lColor(L_R_VALUE, L_G_VALUE, L_B_VALUE); const double R_R_VALUE = 0.100; const double R_G_VALUE = 0.345; const double R_B_VALUE = 0.678; PdfColor rColor(R_R_VALUE, R_G_VALUE, R_B_VALUE); ASSERT_FALSE(L_R_VALUE == R_R_VALUE); ASSERT_TRUE(L_G_VALUE == R_G_VALUE); ASSERT_TRUE(L_B_VALUE == R_B_VALUE); ASSERT_FALSE(lColor == rColor); } { //Negative const double L_R_VALUE = 0.023; const double L_G_VALUE = 0.345; const double L_B_VALUE = 0.678; PdfColor lColor(L_R_VALUE, L_G_VALUE, L_B_VALUE); const double R_R_VALUE = 0.023; const double R_G_VALUE = 0.340; const double R_B_VALUE = 0.678; PdfColor rColor(R_R_VALUE, R_G_VALUE, R_B_VALUE); ASSERT_TRUE(L_R_VALUE == R_R_VALUE); ASSERT_FALSE(L_G_VALUE == R_G_VALUE); ASSERT_TRUE(L_B_VALUE == R_B_VALUE); ASSERT_FALSE(lColor == rColor); } { //Negative const double L_R_VALUE = 0.023; const double L_G_VALUE = 0.345; const double L_B_VALUE = 0.678; PdfColor lColor(L_R_VALUE, L_G_VALUE, L_B_VALUE); const double R_R_VALUE = 0.023; const double R_G_VALUE = 0.345; const double R_B_VALUE = 0.677; PdfColor rColor(R_R_VALUE, R_G_VALUE, R_B_VALUE); ASSERT_TRUE(L_R_VALUE == R_R_VALUE); ASSERT_TRUE(L_G_VALUE == R_G_VALUE); ASSERT_FALSE(L_B_VALUE == R_B_VALUE); ASSERT_FALSE(lColor == rColor); } //CMYB tests { //Positive const double L_C_VALUE = 0.1; const double L_M_VALUE = 0.2; const double L_Y_VALUE = 0.3; const double L_B_VALUE = 0.4; PdfColor lColor(L_C_VALUE, L_M_VALUE, L_Y_VALUE, L_B_VALUE); const double R_C_VALUE = 0.1; const double R_M_VALUE = 0.2; const double R_Y_VALUE = 0.3; const double R_B_VALUE = 0.4; PdfColor rColor(R_C_VALUE, R_M_VALUE, R_Y_VALUE, R_B_VALUE); ASSERT_TRUE(L_C_VALUE == R_C_VALUE); ASSERT_TRUE(L_M_VALUE == R_M_VALUE); ASSERT_TRUE(L_Y_VALUE == R_Y_VALUE); ASSERT_TRUE(L_B_VALUE == R_B_VALUE); ASSERT_TRUE(lColor == rColor); } { //Negative const double L_C_VALUE = 0.1; const double L_M_VALUE = 0.2; const double L_Y_VALUE = 0.3; const double L_B_VALUE = 0.4; PdfColor lColor(L_C_VALUE, L_M_VALUE, L_Y_VALUE, L_B_VALUE); const double R_C_VALUE = 0.11; const double R_M_VALUE = 0.2; const double R_Y_VALUE = 0.3; const double R_B_VALUE = 0.4; PdfColor rColor(R_C_VALUE, R_M_VALUE, R_Y_VALUE, R_B_VALUE); ASSERT_FALSE(L_C_VALUE == R_C_VALUE); ASSERT_TRUE(L_M_VALUE == R_M_VALUE); ASSERT_TRUE(L_Y_VALUE == R_Y_VALUE); ASSERT_TRUE(L_B_VALUE == R_B_VALUE); ASSERT_FALSE(lColor == rColor); } { //Negative const double L_C_VALUE = 0.1; const double L_M_VALUE = 0.2; const double L_Y_VALUE = 0.3; const double L_B_VALUE = 0.4; PdfColor lColor(L_C_VALUE, L_M_VALUE, L_Y_VALUE, L_B_VALUE); const double R_C_VALUE = 0.1; const double R_M_VALUE = 0.21; const double R_Y_VALUE = 0.3; const double R_B_VALUE = 0.4; PdfColor rColor(R_C_VALUE, R_M_VALUE, R_Y_VALUE, R_B_VALUE); ASSERT_TRUE(L_C_VALUE == R_C_VALUE); ASSERT_FALSE(L_M_VALUE == R_M_VALUE); ASSERT_TRUE(L_Y_VALUE == R_Y_VALUE); ASSERT_TRUE(L_B_VALUE == R_B_VALUE); ASSERT_FALSE(lColor == rColor); } { //Negative const double L_C_VALUE = 0.1; const double L_M_VALUE = 0.2; const double L_Y_VALUE = 0.31; const double L_B_VALUE = 0.4; PdfColor lColor(L_C_VALUE, L_M_VALUE, L_Y_VALUE, L_B_VALUE); const double R_C_VALUE = 0.1; const double R_M_VALUE = 0.2; const double R_Y_VALUE = 0.3; const double R_B_VALUE = 0.4; PdfColor rColor(R_C_VALUE, R_M_VALUE, R_Y_VALUE, R_B_VALUE); ASSERT_TRUE(L_C_VALUE == R_C_VALUE); ASSERT_TRUE(L_M_VALUE == R_M_VALUE); ASSERT_FALSE(L_Y_VALUE == R_Y_VALUE); ASSERT_TRUE(L_B_VALUE == R_B_VALUE); ASSERT_FALSE(lColor == rColor); } { //Negative const double L_C_VALUE = 0.1; const double L_M_VALUE = 0.2; const double L_Y_VALUE = 0.3; const double L_B_VALUE = 0.4; PdfColor lColor(L_C_VALUE, L_M_VALUE, L_Y_VALUE, L_B_VALUE); const double R_C_VALUE = 0.1; const double R_M_VALUE = 0.2; const double R_Y_VALUE = 0.3; const double R_B_VALUE = 0.45; PdfColor rColor(R_C_VALUE, R_M_VALUE, R_Y_VALUE, R_B_VALUE); ASSERT_TRUE(L_C_VALUE == R_C_VALUE); ASSERT_TRUE(L_M_VALUE == R_M_VALUE); ASSERT_TRUE(L_Y_VALUE == R_Y_VALUE); ASSERT_FALSE(L_B_VALUE == R_B_VALUE); ASSERT_FALSE(lColor == rColor); } } void ColorTest::testHexNames() { #ifdef DEBUG_INFO std::cout << "testHexNames" << std::endl; #endif { PdfColor rgb = PdfColor::FromString( "#FF0AEF"); ASSERT_TRUE(rgb.IsRGB()); ASSERT_EQ(static_cast(rgb.GetRed() * 255.0), 0xFF); ASSERT_EQ(static_cast(rgb.GetGreen() * 255.0), 0x0A); ASSERT_EQ(static_cast(rgb.GetBlue() * 255.0), 0xEF); } { PdfColor rgb = PdfColor::FromString( "#012345"); ASSERT_TRUE(rgb.IsRGB()); ASSERT_EQ(static_cast(rgb.GetRed() * 255.0), 0x01); ASSERT_EQ(static_cast(rgb.GetGreen() * 255.0), 0x23); ASSERT_EQ(static_cast(rgb.GetBlue() * 255.0), 0x45); } { PdfColor rgb = PdfColor::FromString( "#ABCDEF"); ASSERT_TRUE(rgb.IsRGB()); ASSERT_EQ(static_cast(rgb.GetRed() * 255.0), 0xAB); ASSERT_EQ(static_cast(rgb.GetGreen() * 255.0), 0xCD); ASSERT_EQ(static_cast(rgb.GetBlue() * 255.0), 0xEF); } { PdfColor rgb = PdfColor::FromString( "#abcdef"); ASSERT_TRUE(rgb.IsRGB()); ASSERT_EQ(static_cast(rgb.GetRed() * 255.0), 0xAB); ASSERT_EQ(static_cast(rgb.GetGreen() * 255.0), 0xCD); ASSERT_EQ(static_cast(rgb.GetBlue() * 255.0), 0xEF); } { PdfColor invalidColour = PdfColor::FromString( "#01"); ASSERT_TRUE(invalidColour == PdfColor()); } { PdfColor invalidColour = PdfColor::FromString( "#123456789"); ASSERT_TRUE(invalidColour == PdfColor()); } { CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( PdfColor::FromString( "#12345g" ), PdfError, ePdfError_CannotConvertColor); } { CPPUNIT_ASSERT_THROW_WITH_ERROR_TYPE( PdfColor::FromString( "#1234g5" ), PdfError, ePdfError_CannotConvertColor); } PdfColor cmyk = PdfColor::FromString( "#ABCDEF01"); ASSERT_TRUE(cmyk.IsCMYK()); ASSERT_EQ(static_cast(cmyk.GetCyan() * 255.0), 0xAB); ASSERT_EQ(static_cast(cmyk.GetMagenta() * 255.0), 0xCD); ASSERT_EQ(static_cast(cmyk.GetYellow() * 255.0), 0xEF); ASSERT_EQ(static_cast(cmyk.GetBlack() * 255.0), 0x01); } void ColorTest::testNamesGeneral() { #ifdef DEBUG_INFO std::cout << "testNames" << std::endl; #endif PdfColor aliceBlue = PdfColor::FromString( "aliceblue"); ASSERT_TRUE(aliceBlue == PdfColor::FromString("#F0F8FF")); ASSERT_EQ(aliceBlue.GetRed(), static_cast(0xF0)/255.0); ASSERT_EQ(aliceBlue.GetGreen(), static_cast(0xF8)/255.0); ASSERT_EQ(aliceBlue.GetBlue(), static_cast(0xFF)/255.0); PdfColor lime = PdfColor::FromString( "lime"); ASSERT_TRUE(lime == PdfColor(0.000, 1.000, 0.000)); PdfColor yellowGreen = PdfColor::FromString( "yellowgreen"); ASSERT_TRUE(yellowGreen == PdfColor::FromString("#9ACD32")); { // Test a not existing color PdfColor notExist = PdfColor::FromString( "asfaf9q341"); ASSERT_TRUE(notExist == PdfColor()); } { // Test a not existing color PdfColor notExist = PdfColor::FromString( "A"); ASSERT_TRUE(notExist == PdfColor()); } { // Test a not existing color PdfColor notExist = PdfColor::FromString( ""); ASSERT_TRUE(notExist == PdfColor()); } { // Test a not existing color PdfColor notExist = PdfColor::FromString( "yellowgree"); ASSERT_TRUE(notExist == PdfColor()); } { // Test a not existing color PdfColor notExist = PdfColor::FromString( "yellowgreem"); ASSERT_TRUE(notExist == PdfColor()); } { // Test a not existing color PdfColor notExist = PdfColor::FromString( "yellowgreen "); ASSERT_TRUE(notExist == PdfColor()); } } namespace { class TestColor { public: TestColor(int r, int g, int b, const char* colorName) : m_r(static_cast(r)/255.0), m_g(static_cast(g)/255.0), m_b(static_cast(b)/255.0), m_colorName(colorName) { //do nothing } ~TestColor() {} double getR() const { return m_r; } double getG() const { return m_g; } double getB() const { return m_b; } const char* getColorName() const { return m_colorName; } TestColor(const TestColor& rhs) : m_r(rhs.m_r), m_g(rhs.m_g), m_b(rhs.m_b), m_colorName(rhs.m_colorName) { //do nothing } private: TestColor(); TestColor& operator=(const TestColor&); double m_r; double m_g; double m_b; const char* m_colorName; }; } void ColorTest::testNamesOneByOne() { #ifdef DEBUG_INFO std::cout << "testNames" << std::endl; #endif //Copied and adjusted from http://cvsweb.xfree86.org/cvsweb/xc/programs/rgb/rgb.txt?rev=1.2 const TestColor TABLE_OF_TEST_COLORS[] = { TestColor(255, 250, 250, "snow"), TestColor(248, 248, 255, "GhostWhite"), TestColor(245, 245, 245, "WhiteSmoke"), TestColor(220, 220, 220, "gainsboro"), TestColor(255, 250, 240, "FloralWhite"), TestColor(253, 245, 230, "OldLace"), TestColor(250, 240, 230, "linen"), TestColor(250, 235, 215, "AntiqueWhite"), TestColor(255, 239, 213, "PapayaWhip"), TestColor(255, 235, 205, "BlanchedAlmond"), TestColor(255, 228, 196, "bisque"), TestColor(255, 218, 185, "PeachPuff"), TestColor(255, 222, 173, "NavajoWhite"), TestColor(255, 228, 181, "moccasin"), TestColor(255, 248, 220, "cornsilk"), TestColor(255, 255, 240, "ivory"), TestColor(255, 250, 205, "LemonChiffon"), TestColor(255, 245, 238, "seashell"), TestColor(240, 255, 240, "honeydew"), TestColor(245, 255, 250, "MintCream"), TestColor(240, 255, 255, "azure"), TestColor(240, 248, 255, "AliceBlue"), TestColor(230, 230, 250, "lavender"), TestColor(255, 240, 245, "LavenderBlush"), TestColor(255, 228, 225, "MistyRose"), TestColor(255, 255, 255, "white"), TestColor(0, 0, 0, "black"), TestColor(47, 79, 79, "DarkSlateGray"), TestColor(47, 79, 79, "DarkSlateGrey"), TestColor(105, 105, 105, "DimGray"), TestColor(105, 105, 105, "DimGrey"), TestColor(112, 128, 144, "SlateGray"), TestColor(112, 128, 144, "SlateGrey"), TestColor(119, 136, 153, "LightSlateGray"), TestColor(119, 136, 153, "LightSlateGrey"), TestColor(190, 190, 190, "gray"), TestColor(190, 190, 190, "grey"), TestColor(211, 211, 211, "LightGrey"), TestColor(211, 211, 211, "LightGray"), TestColor(25, 25, 112, "MidnightBlue"), TestColor(0, 0, 128, "navy"), TestColor(0, 0, 128, "NavyBlue"), TestColor(100, 149, 237, "CornflowerBlue"), TestColor(72, 61, 139, "DarkSlateBlue"), TestColor(106, 90, 205, "SlateBlue"), TestColor(123, 104, 238, "MediumSlateBlue"), TestColor(132, 112, 255, "LightSlateBlue"), TestColor(0, 0, 205, "MediumBlue"), TestColor(65, 105, 225, "RoyalBlue"), TestColor(0, 0, 255, "blue"), TestColor(30, 144, 255, "DodgerBlue"), TestColor(0, 191, 255, "DeepSkyBlue"), TestColor(135, 206, 235, "SkyBlue"), TestColor(135, 206, 250, "LightSkyBlue"), TestColor(70, 130, 180, "SteelBlue"), TestColor(176, 196, 222, "LightSteelBlue"), TestColor(173, 216, 230, "LightBlue"), TestColor(176, 224, 230, "PowderBlue"), TestColor(175, 238, 238, "PaleTurquoise"), TestColor(0, 206, 209, "DarkTurquoise"), TestColor(72, 209, 204, "MediumTurquoise"), TestColor(64, 224, 208, "turquoise"), TestColor(0, 255, 255, "cyan"), TestColor(224, 255, 255, "LightCyan"), TestColor(95, 158, 160, "CadetBlue"), TestColor(102, 205, 170, "MediumAquamarine"), TestColor(127, 255, 212, "aquamarine"), TestColor(0, 100, 0, "DarkGreen"), TestColor(85, 107, 47, "DarkOliveGreen"), TestColor(143, 188, 143, "DarkSeaGreen"), TestColor(46, 139, 87, "SeaGreen"), TestColor(60, 179, 113, "MediumSeaGreen"), TestColor(32, 178, 170, "LightSeaGreen"), TestColor(152, 251, 152, "PaleGreen"), TestColor(0, 255, 127, "SpringGreen"), TestColor(124, 252, 0, "LawnGreen"), TestColor(0, 255, 0, "green"), TestColor(127, 255, 0, "chartreuse"), TestColor(0, 250, 154, "MediumSpringGreen"), TestColor(173, 255, 47, "GreenYellow"), TestColor(50, 205, 50, "LimeGreen"), TestColor(154, 205, 50, "YellowGreen"), TestColor(34, 139, 34, "ForestGreen"), TestColor(107, 142, 35, "OliveDrab"), TestColor(189, 183, 107, "DarkKhaki"), TestColor(240, 230, 140, "khaki"), TestColor(238, 232, 170, "PaleGoldenrod"), TestColor(250, 250, 210, "LightGoldenrodYellow"), TestColor(255, 255, 224, "LightYellow"), TestColor(255, 255, 0, "yellow"), TestColor(255, 215, 0, "gold"), TestColor(238, 221, 130, "LightGoldenrod"), TestColor(218, 165, 32, "goldenrod"), TestColor(184, 134, 11, "DarkGoldenrod"), TestColor(188, 143, 143, "RosyBrown"), TestColor(205, 92, 92, "IndianRed"), TestColor(139, 69, 19, "SaddleBrown"), TestColor(160, 82, 45, "sienna"), TestColor(205, 133, 63, "peru"), TestColor(222, 184, 135, "burlywood"), TestColor(245, 245, 220, "beige"), TestColor(245, 222, 179, "wheat"), TestColor(244, 164, 96, "SandyBrown"), TestColor(210, 180, 140, "tan"), TestColor(210, 105, 30, "chocolate"), TestColor(178, 34, 34, "firebrick"), TestColor(165, 42, 42, "brown"), TestColor(233, 150, 122, "DarkSalmon"), TestColor(250, 128, 114, "salmon"), TestColor(255, 160, 122, "LightSalmon"), TestColor(255, 165, 0, "orange"), TestColor(255, 140, 0, "DarkOrange"), TestColor(255, 127, 80, "coral"), TestColor(240, 128, 128, "LightCoral"), TestColor(255, 99, 71, "tomato"), TestColor(255, 69, 0, "OrangeRed"), TestColor(255, 0, 0, "red"), TestColor(255, 105, 180, "HotPink"), TestColor(255, 20, 147, "DeepPink"), TestColor(255, 192, 203, "pink"), TestColor(255, 182, 193, "LightPink"), TestColor(219, 112, 147, "PaleVioletRed"), TestColor(176, 48, 96, "maroon"), TestColor(199, 21, 133, "MediumVioletRed"), TestColor(208, 32, 144, "VioletRed"), TestColor(255, 0, 255, "magenta"), TestColor(238, 130, 238, "violet"), TestColor(221, 160, 221, "plum"), TestColor(218, 112, 214, "orchid"), TestColor(186, 85, 211, "MediumOrchid"), TestColor(153, 50, 204, "DarkOrchid"), TestColor(148, 0, 211, "DarkViolet"), TestColor(138, 43, 226, "BlueViolet"), TestColor(160, 32, 240, "purple"), TestColor(147, 112, 219, "MediumPurple"), TestColor(216, 191, 216, "thistle"), TestColor(255, 250, 250, "snow1"), TestColor(238, 233, 233, "snow2"), TestColor(205, 201, 201, "snow3"), TestColor(139, 137, 137, "snow4"), TestColor(255, 245, 238, "seashell1"), TestColor(238, 229, 222, "seashell2"), TestColor(205, 197, 191, "seashell3"), TestColor(139, 134, 130, "seashell4"), TestColor(255, 239, 219, "AntiqueWhite1"), TestColor(238, 223, 204, "AntiqueWhite2"), TestColor(205, 192, 176, "AntiqueWhite3"), TestColor(139, 131, 120, "AntiqueWhite4"), TestColor(255, 228, 196, "bisque1"), TestColor(238, 213, 183, "bisque2"), TestColor(205, 183, 158, "bisque3"), TestColor(139, 125, 107, "bisque4"), TestColor(255, 218, 185, "PeachPuff1"), TestColor(238, 203, 173, "PeachPuff2"), TestColor(205, 175, 149, "PeachPuff3"), TestColor(139, 119, 101, "PeachPuff4"), TestColor(255, 222, 173, "NavajoWhite1"), TestColor(238, 207, 161, "NavajoWhite2"), TestColor(205, 179, 139, "NavajoWhite3"), TestColor(139, 121, 94, "NavajoWhite4"), TestColor(255, 250, 205, "LemonChiffon1"), TestColor(238, 233, 191, "LemonChiffon2"), TestColor(205, 201, 165, "LemonChiffon3"), TestColor(139, 137, 112, "LemonChiffon4"), TestColor(255, 248, 220, "cornsilk1"), TestColor(238, 232, 205, "cornsilk2"), TestColor(205, 200, 177, "cornsilk3"), TestColor(139, 136, 120, "cornsilk4"), TestColor(255, 255, 240, "ivory1"), TestColor(238, 238, 224, "ivory2"), TestColor(205, 205, 193, "ivory3"), TestColor(139, 139, 131, "ivory4"), TestColor(240, 255, 240, "honeydew1"), TestColor(224, 238, 224, "honeydew2"), TestColor(193, 205, 193, "honeydew3"), TestColor(131, 139, 131, "honeydew4"), TestColor(255, 240, 245, "LavenderBlush1"), TestColor(238, 224, 229, "LavenderBlush2"), TestColor(205, 193, 197, "LavenderBlush3"), TestColor(139, 131, 134, "LavenderBlush4"), TestColor(255, 228, 225, "MistyRose1"), TestColor(238, 213, 210, "MistyRose2"), TestColor(205, 183, 181, "MistyRose3"), TestColor(139, 125, 123, "MistyRose4"), TestColor(240, 255, 255, "azure1"), TestColor(224, 238, 238, "azure2"), TestColor(193, 205, 205, "azure3"), TestColor(131, 139, 139, "azure4"), TestColor(131, 111, 255, "SlateBlue1"), TestColor(122, 103, 238, "SlateBlue2"), TestColor(105, 89, 205, "SlateBlue3"), TestColor(71, 60, 139, "SlateBlue4"), TestColor(72, 118, 255, "RoyalBlue1"), TestColor(67, 110, 238, "RoyalBlue2"), TestColor(58, 95, 205, "RoyalBlue3"), TestColor(39, 64, 139, "RoyalBlue4"), TestColor(0, 0, 255, "blue1"), TestColor(0, 0, 238, "blue2"), TestColor(0, 0, 205, "blue3"), TestColor(0, 0, 139, "blue4"), TestColor(30, 144, 255, "DodgerBlue1"), TestColor(28, 134, 238, "DodgerBlue2"), TestColor(24, 116, 205, "DodgerBlue3"), TestColor(16, 78, 139, "DodgerBlue4"), TestColor(99, 184, 255, "SteelBlue1"), TestColor(92, 172, 238, "SteelBlue2"), TestColor(79, 148, 205, "SteelBlue3"), TestColor(54, 100, 139, "SteelBlue4"), TestColor(0, 191, 255, "DeepSkyBlue1"), TestColor(0, 178, 238, "DeepSkyBlue2"), TestColor(0, 154, 205, "DeepSkyBlue3"), TestColor(0, 104, 139, "DeepSkyBlue4"), TestColor(135, 206, 255, "SkyBlue1"), TestColor(126, 192, 238, "SkyBlue2"), TestColor(108, 166, 205, "SkyBlue3"), TestColor(74, 112, 139, "SkyBlue4"), TestColor(176, 226, 255, "LightSkyBlue1"), TestColor(164, 211, 238, "LightSkyBlue2"), TestColor(141, 182, 205, "LightSkyBlue3"), TestColor(96, 123, 139, "LightSkyBlue4"), TestColor(198, 226, 255, "SlateGray1"), TestColor(185, 211, 238, "SlateGray2"), TestColor(159, 182, 205, "SlateGray3"), TestColor(108, 123, 139, "SlateGray4"), TestColor(202, 225, 255, "LightSteelBlue1"), TestColor(188, 210, 238, "LightSteelBlue2"), TestColor(162, 181, 205, "LightSteelBlue3"), TestColor(110, 123, 139, "LightSteelBlue4"), TestColor(191, 239, 255, "LightBlue1"), TestColor(178, 223, 238, "LightBlue2"), TestColor(154, 192, 205, "LightBlue3"), TestColor(104, 131, 139, "LightBlue4"), TestColor(224, 255, 255, "LightCyan1"), TestColor(209, 238, 238, "LightCyan2"), TestColor(180, 205, 205, "LightCyan3"), TestColor(122, 139, 139, "LightCyan4"), TestColor(187, 255, 255, "PaleTurquoise1"), TestColor(174, 238, 238, "PaleTurquoise2"), TestColor(150, 205, 205, "PaleTurquoise3"), TestColor(102, 139, 139, "PaleTurquoise4"), TestColor(152, 245, 255, "CadetBlue1"), TestColor(142, 229, 238, "CadetBlue2"), TestColor(122, 197, 205, "CadetBlue3"), TestColor(83, 134, 139, "CadetBlue4"), TestColor(0, 245, 255, "turquoise1"), TestColor(0, 229, 238, "turquoise2"), TestColor(0, 197, 205, "turquoise3"), TestColor(0, 134, 139, "turquoise4"), TestColor(0, 255, 255, "cyan1"), TestColor(0, 238, 238, "cyan2"), TestColor(0, 205, 205, "cyan3"), TestColor(0, 139, 139, "cyan4"), TestColor(151, 255, 255, "DarkSlateGray1"), TestColor(141, 238, 238, "DarkSlateGray2"), TestColor(121, 205, 205, "DarkSlateGray3"), TestColor(82, 139, 139, "DarkSlateGray4"), TestColor(127, 255, 212, "aquamarine1"), TestColor(118, 238, 198, "aquamarine2"), TestColor(102, 205, 170, "aquamarine3"), TestColor(69, 139, 116, "aquamarine4"), TestColor(193, 255, 193, "DarkSeaGreen1"), TestColor(180, 238, 180, "DarkSeaGreen2"), TestColor(155, 205, 155, "DarkSeaGreen3"), TestColor(105, 139, 105, "DarkSeaGreen4"), TestColor(84, 255, 159, "SeaGreen1"), TestColor(78, 238, 148, "SeaGreen2"), TestColor(67, 205, 128, "SeaGreen3"), TestColor(46, 139, 87, "SeaGreen4"), TestColor(154, 255, 154, "PaleGreen1"), TestColor(144, 238, 144, "PaleGreen2"), TestColor(124, 205, 124, "PaleGreen3"), TestColor(84, 139, 84, "PaleGreen4"), TestColor(0, 255, 127, "SpringGreen1"), TestColor(0, 238, 118, "SpringGreen2"), TestColor(0, 205, 102, "SpringGreen3"), TestColor(0, 139, 69, "SpringGreen4"), TestColor(0, 255, 0, "green1"), TestColor(0, 238, 0, "green2"), TestColor(0, 205, 0, "green3"), TestColor(0, 139, 0, "green4"), TestColor(127, 255, 0, "chartreuse1"), TestColor(118, 238, 0, "chartreuse2"), TestColor(102, 205, 0, "chartreuse3"), TestColor(69, 139, 0, "chartreuse4"), TestColor(192, 255, 62, "OliveDrab1"), TestColor(179, 238, 58, "OliveDrab2"), TestColor(154, 205, 50, "OliveDrab3"), TestColor(105, 139, 34, "OliveDrab4"), TestColor(202, 255, 112, "DarkOliveGreen1"), TestColor(188, 238, 104, "DarkOliveGreen2"), TestColor(162, 205, 90, "DarkOliveGreen3"), TestColor(110, 139, 61, "DarkOliveGreen4"), TestColor(255, 246, 143, "khaki1"), TestColor(238, 230, 133, "khaki2"), TestColor(205, 198, 115, "khaki3"), TestColor(139, 134, 78, "khaki4"), TestColor(255, 236, 139, "LightGoldenrod1"), TestColor(238, 220, 130, "LightGoldenrod2"), TestColor(205, 190, 112, "LightGoldenrod3"), TestColor(139, 129, 76, "LightGoldenrod4"), TestColor(255, 255, 224, "LightYellow1"), TestColor(238, 238, 209, "LightYellow2"), TestColor(205, 205, 180, "LightYellow3"), TestColor(139, 139, 122, "LightYellow4"), TestColor(255, 255, 0, "yellow1"), TestColor(238, 238, 0, "yellow2"), TestColor(205, 205, 0, "yellow3"), TestColor(139, 139, 0, "yellow4"), TestColor(255, 215, 0, "gold1"), TestColor(238, 201, 0, "gold2"), TestColor(205, 173, 0, "gold3"), TestColor(139, 117, 0, "gold4"), TestColor(255, 193, 37, "goldenrod1"), TestColor(238, 180, 34, "goldenrod2"), TestColor(205, 155, 29, "goldenrod3"), TestColor(139, 105, 20, "goldenrod4"), TestColor(255, 185, 15, "DarkGoldenrod1"), TestColor(238, 173, 14, "DarkGoldenrod2"), TestColor(205, 149, 12, "DarkGoldenrod3"), TestColor(139, 101, 8, "DarkGoldenrod4"), TestColor(255, 193, 193, "RosyBrown1"), TestColor(238, 180, 180, "RosyBrown2"), TestColor(205, 155, 155, "RosyBrown3"), TestColor(139, 105, 105, "RosyBrown4"), TestColor(255, 106, 106, "IndianRed1"), TestColor(238, 99, 99, "IndianRed2"), TestColor(205, 85, 85, "IndianRed3"), TestColor(139, 58, 58, "IndianRed4"), TestColor(255, 130, 71, "sienna1"), TestColor(238, 121, 66, "sienna2"), TestColor(205, 104, 57, "sienna3"), TestColor(139, 71, 38, "sienna4"), TestColor(255, 211, 155, "burlywood1"), TestColor(238, 197, 145, "burlywood2"), TestColor(205, 170, 125, "burlywood3"), TestColor(139, 115, 85, "burlywood4"), TestColor(255, 231, 186, "wheat1"), TestColor(238, 216, 174, "wheat2"), TestColor(205, 186, 150, "wheat3"), TestColor(139, 126, 102, "wheat4"), TestColor(255, 165, 79, "tan1"), TestColor(238, 154, 73, "tan2"), TestColor(205, 133, 63, "tan3"), TestColor(139, 90, 43, "tan4"), TestColor(255, 127, 36, "chocolate1"), TestColor(238, 118, 33, "chocolate2"), TestColor(205, 102, 29, "chocolate3"), TestColor(139, 69, 19, "chocolate4"), TestColor(255, 48, 48, "firebrick1"), TestColor(238, 44, 44, "firebrick2"), TestColor(205, 38, 38, "firebrick3"), TestColor(139, 26, 26, "firebrick4"), TestColor(255, 64, 64, "brown1"), TestColor(238, 59, 59, "brown2"), TestColor(205, 51, 51, "brown3"), TestColor(139, 35, 35, "brown4"), TestColor(255, 140, 105, "salmon1"), TestColor(238, 130, 98, "salmon2"), TestColor(205, 112, 84, "salmon3"), TestColor(139, 76, 57, "salmon4"), TestColor(255, 160, 122, "LightSalmon1"), TestColor(238, 149, 114, "LightSalmon2"), TestColor(205, 129, 98, "LightSalmon3"), TestColor(139, 87, 66, "LightSalmon4"), TestColor(255, 165, 0, "orange1"), TestColor(238, 154, 0, "orange2"), TestColor(205, 133, 0, "orange3"), TestColor(139, 90, 0, "orange4"), TestColor(255, 127, 0, "DarkOrange1"), TestColor(238, 118, 0, "DarkOrange2"), TestColor(205, 102, 0, "DarkOrange3"), TestColor(139, 69, 0, "DarkOrange4"), TestColor(255, 114, 86, "coral1"), TestColor(238, 106, 80, "coral2"), TestColor(205, 91, 69, "coral3"), TestColor(139, 62, 47, "coral4"), TestColor(255, 99, 71, "tomato1"), TestColor(238, 92, 66, "tomato2"), TestColor(205, 79, 57, "tomato3"), TestColor(139, 54, 38, "tomato4"), TestColor(255, 69, 0, "OrangeRed1"), TestColor(238, 64, 0, "OrangeRed2"), TestColor(205, 55, 0, "OrangeRed3"), TestColor(139, 37, 0, "OrangeRed4"), TestColor(255, 0, 0, "red1"), TestColor(238, 0, 0, "red2"), TestColor(205, 0, 0, "red3"), TestColor(139, 0, 0, "red4"), TestColor(255, 20, 147, "DeepPink1"), TestColor(238, 18, 137, "DeepPink2"), TestColor(205, 16, 118, "DeepPink3"), TestColor(139, 10, 80, "DeepPink4"), TestColor(255, 110, 180, "HotPink1"), TestColor(238, 106, 167, "HotPink2"), TestColor(205, 96, 144, "HotPink3"), TestColor(139, 58, 98, "HotPink4"), TestColor(255, 181, 197, "pink1"), TestColor(238, 169, 184, "pink2"), TestColor(205, 145, 158, "pink3"), TestColor(139, 99, 108, "pink4"), TestColor(255, 174, 185, "LightPink1"), TestColor(238, 162, 173, "LightPink2"), TestColor(205, 140, 149, "LightPink3"), TestColor(139, 95, 101, "LightPink4"), TestColor(255, 130, 171, "PaleVioletRed1"), TestColor(238, 121, 159, "PaleVioletRed2"), TestColor(205, 104, 137, "PaleVioletRed3"), TestColor(139, 71, 93, "PaleVioletRed4"), TestColor(255, 52, 179, "maroon1"), TestColor(238, 48, 167, "maroon2"), TestColor(205, 41, 144, "maroon3"), TestColor(139, 28, 98, "maroon4"), TestColor(255, 62, 150, "VioletRed1"), TestColor(238, 58, 140, "VioletRed2"), TestColor(205, 50, 120, "VioletRed3"), TestColor(139, 34, 82, "VioletRed4"), TestColor(255, 0, 255, "magenta1"), TestColor(238, 0, 238, "magenta2"), TestColor(205, 0, 205, "magenta3"), TestColor(139, 0, 139, "magenta4"), TestColor(255, 131, 250, "orchid1"), TestColor(238, 122, 233, "orchid2"), TestColor(205, 105, 201, "orchid3"), TestColor(139, 71, 137, "orchid4"), TestColor(255, 187, 255, "plum1"), TestColor(238, 174, 238, "plum2"), TestColor(205, 150, 205, "plum3"), TestColor(139, 102, 139, "plum4"), TestColor(224, 102, 255, "MediumOrchid1"), TestColor(209, 95, 238, "MediumOrchid2"), TestColor(180, 82, 205, "MediumOrchid3"), TestColor(122, 55, 139, "MediumOrchid4"), TestColor(191, 62, 255, "DarkOrchid1"), TestColor(178, 58, 238, "DarkOrchid2"), TestColor(154, 50, 205, "DarkOrchid3"), TestColor(104, 34, 139, "DarkOrchid4"), TestColor(155, 48, 255, "purple1"), TestColor(145, 44, 238, "purple2"), TestColor(125, 38, 205, "purple3"), TestColor(85, 26, 139, "purple4"), TestColor(171, 130, 255, "MediumPurple1"), TestColor(159, 121, 238, "MediumPurple2"), TestColor(137, 104, 205, "MediumPurple3"), TestColor(93, 71, 139, "MediumPurple4"), TestColor(255, 225, 255, "thistle1"), TestColor(238, 210, 238, "thistle2"), TestColor(205, 181, 205, "thistle3"), TestColor(139, 123, 139, "thistle4"), TestColor(0, 0, 0, "gray0"), TestColor(0, 0, 0, "grey0"), TestColor(3, 3, 3, "gray1"), TestColor(3, 3, 3, "grey1"), TestColor(5, 5, 5, "gray2"), TestColor(5, 5, 5, "grey2"), TestColor(8, 8, 8, "gray3"), TestColor(8, 8, 8, "grey3"), TestColor(10, 10, 10, "gray4"), TestColor(10, 10, 10, "grey4"), TestColor(13, 13, 13, "gray5"), TestColor(13, 13, 13, "grey5"), TestColor(15, 15, 15, "gray6"), TestColor(15, 15, 15, "grey6"), TestColor(18, 18, 18, "gray7"), TestColor(18, 18, 18, "grey7"), TestColor(20, 20, 20, "gray8"), TestColor(20, 20, 20, "grey8"), TestColor(23, 23, 23, "gray9"), TestColor(23, 23, 23, "grey9"), TestColor(26, 26, 26, "gray10"), TestColor(26, 26, 26, "grey10"), TestColor(28, 28, 28, "gray11"), TestColor(28, 28, 28, "grey11"), TestColor(31, 31, 31, "gray12"), TestColor(31, 31, 31, "grey12"), TestColor(33, 33, 33, "gray13"), TestColor(33, 33, 33, "grey13"), TestColor(36, 36, 36, "gray14"), TestColor(36, 36, 36, "grey14"), TestColor(38, 38, 38, "gray15"), TestColor(38, 38, 38, "grey15"), TestColor(41, 41, 41, "gray16"), TestColor(41, 41, 41, "grey16"), TestColor(43, 43, 43, "gray17"), TestColor(43, 43, 43, "grey17"), TestColor(46, 46, 46, "gray18"), TestColor(46, 46, 46, "grey18"), TestColor(48, 48, 48, "gray19"), TestColor(48, 48, 48, "grey19"), TestColor(51, 51, 51, "gray20"), TestColor(51, 51, 51, "grey20"), TestColor(54, 54, 54, "gray21"), TestColor(54, 54, 54, "grey21"), TestColor(56, 56, 56, "gray22"), TestColor(56, 56, 56, "grey22"), TestColor(59, 59, 59, "gray23"), TestColor(59, 59, 59, "grey23"), TestColor(61, 61, 61, "gray24"), TestColor(61, 61, 61, "grey24"), TestColor(64, 64, 64, "gray25"), TestColor(64, 64, 64, "grey25"), TestColor(66, 66, 66, "gray26"), TestColor(66, 66, 66, "grey26"), TestColor(69, 69, 69, "gray27"), TestColor(69, 69, 69, "grey27"), TestColor(71, 71, 71, "gray28"), TestColor(71, 71, 71, "grey28"), TestColor(74, 74, 74, "gray29"), TestColor(74, 74, 74, "grey29"), TestColor(77, 77, 77, "gray30"), TestColor(77, 77, 77, "grey30"), TestColor(79, 79, 79, "gray31"), TestColor(79, 79, 79, "grey31"), TestColor(82, 82, 82, "gray32"), TestColor(82, 82, 82, "grey32"), TestColor(84, 84, 84, "gray33"), TestColor(84, 84, 84, "grey33"), TestColor(87, 87, 87, "gray34"), TestColor(87, 87, 87, "grey34"), TestColor(89, 89, 89, "gray35"), TestColor(89, 89, 89, "grey35"), TestColor(92, 92, 92, "gray36"), TestColor(92, 92, 92, "grey36"), TestColor(94, 94, 94, "gray37"), TestColor(94, 94, 94, "grey37"), TestColor(97, 97, 97, "gray38"), TestColor(97, 97, 97, "grey38"), TestColor(99, 99, 99, "gray39"), TestColor(99, 99, 99, "grey39"), TestColor(102, 102, 102, "gray40"), TestColor(102, 102, 102, "grey40"), TestColor(105, 105, 105, "gray41"), TestColor(105, 105, 105, "grey41"), TestColor(107, 107, 107, "gray42"), TestColor(107, 107, 107, "grey42"), TestColor(110, 110, 110, "gray43"), TestColor(110, 110, 110, "grey43"), TestColor(112, 112, 112, "gray44"), TestColor(112, 112, 112, "grey44"), TestColor(115, 115, 115, "gray45"), TestColor(115, 115, 115, "grey45"), TestColor(117, 117, 117, "gray46"), TestColor(117, 117, 117, "grey46"), TestColor(120, 120, 120, "gray47"), TestColor(120, 120, 120, "grey47"), TestColor(122, 122, 122, "gray48"), TestColor(122, 122, 122, "grey48"), TestColor(125, 125, 125, "gray49"), TestColor(125, 125, 125, "grey49"), TestColor(127, 127, 127, "gray50"), TestColor(127, 127, 127, "grey50"), TestColor(130, 130, 130, "gray51"), TestColor(130, 130, 130, "grey51"), TestColor(133, 133, 133, "gray52"), TestColor(133, 133, 133, "grey52"), TestColor(135, 135, 135, "gray53"), TestColor(135, 135, 135, "grey53"), TestColor(138, 138, 138, "gray54"), TestColor(138, 138, 138, "grey54"), TestColor(140, 140, 140, "gray55"), TestColor(140, 140, 140, "grey55"), TestColor(143, 143, 143, "gray56"), TestColor(143, 143, 143, "grey56"), TestColor(145, 145, 145, "gray57"), TestColor(145, 145, 145, "grey57"), TestColor(148, 148, 148, "gray58"), TestColor(148, 148, 148, "grey58"), TestColor(150, 150, 150, "gray59"), TestColor(150, 150, 150, "grey59"), TestColor(153, 153, 153, "gray60"), TestColor(153, 153, 153, "grey60"), TestColor(156, 156, 156, "gray61"), TestColor(156, 156, 156, "grey61"), TestColor(158, 158, 158, "gray62"), TestColor(158, 158, 158, "grey62"), TestColor(161, 161, 161, "gray63"), TestColor(161, 161, 161, "grey63"), TestColor(163, 163, 163, "gray64"), TestColor(163, 163, 163, "grey64"), TestColor(166, 166, 166, "gray65"), TestColor(166, 166, 166, "grey65"), TestColor(168, 168, 168, "gray66"), TestColor(168, 168, 168, "grey66"), TestColor(171, 171, 171, "gray67"), TestColor(171, 171, 171, "grey67"), TestColor(173, 173, 173, "gray68"), TestColor(173, 173, 173, "grey68"), TestColor(176, 176, 176, "gray69"), TestColor(176, 176, 176, "grey69"), TestColor(179, 179, 179, "gray70"), TestColor(179, 179, 179, "grey70"), TestColor(181, 181, 181, "gray71"), TestColor(181, 181, 181, "grey71"), TestColor(184, 184, 184, "gray72"), TestColor(184, 184, 184, "grey72"), TestColor(186, 186, 186, "gray73"), TestColor(186, 186, 186, "grey73"), TestColor(189, 189, 189, "gray74"), TestColor(189, 189, 189, "grey74"), TestColor(191, 191, 191, "gray75"), TestColor(191, 191, 191, "grey75"), TestColor(194, 194, 194, "gray76"), TestColor(194, 194, 194, "grey76"), TestColor(196, 196, 196, "gray77"), TestColor(196, 196, 196, "grey77"), TestColor(199, 199, 199, "gray78"), TestColor(199, 199, 199, "grey78"), TestColor(201, 201, 201, "gray79"), TestColor(201, 201, 201, "grey79"), TestColor(204, 204, 204, "gray80"), TestColor(204, 204, 204, "grey80"), TestColor(207, 207, 207, "gray81"), TestColor(207, 207, 207, "grey81"), TestColor(209, 209, 209, "gray82"), TestColor(209, 209, 209, "grey82"), TestColor(212, 212, 212, "gray83"), TestColor(212, 212, 212, "grey83"), TestColor(214, 214, 214, "gray84"), TestColor(214, 214, 214, "grey84"), TestColor(217, 217, 217, "gray85"), TestColor(217, 217, 217, "grey85"), TestColor(219, 219, 219, "gray86"), TestColor(219, 219, 219, "grey86"), TestColor(222, 222, 222, "gray87"), TestColor(222, 222, 222, "grey87"), TestColor(224, 224, 224, "gray88"), TestColor(224, 224, 224, "grey88"), TestColor(227, 227, 227, "gray89"), TestColor(227, 227, 227, "grey89"), TestColor(229, 229, 229, "gray90"), TestColor(229, 229, 229, "grey90"), TestColor(232, 232, 232, "gray91"), TestColor(232, 232, 232, "grey91"), TestColor(235, 235, 235, "gray92"), TestColor(235, 235, 235, "grey92"), TestColor(237, 237, 237, "gray93"), TestColor(237, 237, 237, "grey93"), TestColor(240, 240, 240, "gray94"), TestColor(240, 240, 240, "grey94"), TestColor(242, 242, 242, "gray95"), TestColor(242, 242, 242, "grey95"), TestColor(245, 245, 245, "gray96"), TestColor(245, 245, 245, "grey96"), TestColor(247, 247, 247, "gray97"), TestColor(247, 247, 247, "grey97"), TestColor(250, 250, 250, "gray98"), TestColor(250, 250, 250, "grey98"), TestColor(252, 252, 252, "gray99"), TestColor(252, 252, 252, "grey99"), TestColor(255, 255, 255, "gray100"), TestColor(255, 255, 255, "grey100"), TestColor(169, 169, 169, "DarkGrey"), TestColor(169, 169, 169, "DarkGray"), TestColor(0, 0, 139, "DarkBlue"), TestColor(0, 139, 139, "DarkCyan"), TestColor(139, 0, 139, "DarkMagenta"), TestColor(139, 0, 0, "DarkRed"), TestColor(144, 238, 144, "LightGreen") }; const size_t SIZE_OF_TABLE_OF_TEST_COLORS = sizeof(TABLE_OF_TEST_COLORS)/sizeof(TestColor); for (size_t i=0; i TPairOfColors; typedef std::map TMapOfColors; TMapOfColors colorTable; colorTable["red"] = TPairOfColors(PdfColor(1.0, 0.0, 0.0), PdfColor(0.0, 1.0, 1.0, 0.0)); colorTable["green"] = TPairOfColors(PdfColor(0.0, 1.0, 0.0), PdfColor(1.0, 0.0, 1.0, 0.0)); colorTable["blue"] = TPairOfColors(PdfColor(0.0, 0.0, 1.0), PdfColor(1.0, 1.0, 0.0, 0.0)); colorTable["white"] = TPairOfColors(PdfColor(1.0, 1.0, 1.0), PdfColor(0.0, 0.0, 0.0, 0.0)); colorTable["black"] = TPairOfColors(PdfColor(0.0, 0.0, 0.0), PdfColor(0.0, 0.0, 0.0, 1.0)); colorTable["cyan"] = TPairOfColors(PdfColor(0.0, 1.0, 1.0), PdfColor(1.0, 0.0, 0.0, 0.0)); colorTable["magenta"]= TPairOfColors(PdfColor(1.0, 0.0, 1.0), PdfColor(0.0, 1.0, 0.0, 0.0)); colorTable["yellow"] = TPairOfColors(PdfColor(1.0, 1.0, 0.0), PdfColor(0.0, 0.0, 1.0, 0.0)); for(TMapOfColors::const_iterator iter(colorTable.begin()), iterEnd(colorTable.end()); iter != iterEnd; ++iter) { const std::string COLOR_NAME(iter->first); PdfColor namedColor(PdfColor::FromString(COLOR_NAME.c_str())); PdfColor rgbColor(iter->second.first); PdfColor cmykColor(iter->second.second); ASSERT_TRUE(namedColor.ConvertToRGB() == rgbColor); ASSERT_TRUE(rgbColor.ConvertToCMYK() == cmykColor); ASSERT_TRUE(rgbColor == cmykColor.ConvertToRGB()); } } podofo-0.9.3/test/unit/TokenizerTest.h0000664000175000017500000000675211205021044017601 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2007 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #ifndef _TOKENIZER_TEST_H_ #define _TOKENIZER_TEST_H_ #include #include /** This test tests the class PdfTokenizer * * Currently the following methods are tested * - void PdfTokenizer::GetNextVariant( PdfVariant& rVariant, PdfEncrypt* pEncrypt ); * - bool PdfTokenizer::GetNextToken( const char *& pszToken, EPdfTokenType* peType = NULL); * - void PdfTokenizer::IsNextToken( const char* pszToken ); */ class TokenizerTest : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE( TokenizerTest ); CPPUNIT_TEST( testArrays ); CPPUNIT_TEST( testBool ); CPPUNIT_TEST( testHexString ); CPPUNIT_TEST( testName ); CPPUNIT_TEST( testNull ); CPPUNIT_TEST( testNumbers ); CPPUNIT_TEST( testReference ); CPPUNIT_TEST( testString ); CPPUNIT_TEST( testTokens ); CPPUNIT_TEST( testComments ); CPPUNIT_TEST( testDictionary ); CPPUNIT_TEST( testLocale ); CPPUNIT_TEST_SUITE_END(); public: void setUp(); void tearDown(); void testArrays(); void testBool(); void testHexString(); void testName(); void testNull(); void testNumbers(); void testReference(); void testString(); void testDictionary(); void testTokens(); void testComments(); void testLocale(); private: void Test( const char* pszString, PoDoFo::EPdfDataType eDataType, const char* pszExpected = NULL ); /** Test parsing a stream. * * \param pszBuffer a string buffer that will be parsed * \param pszTokens a NULL terminated list of all tokens in the * order PdfTokenizer should read them from pszBuffer */ void TestStream( const char* pszBuffer, const char* pszTokens[] ); /** Test parsing a stream. As above but this time using PdfTokenizer::IsNextToken() * * \param pszBuffer a string buffer that will be parsed * \param pszTokens a NULL terminated list of all tokens in the * order PdfTokenizer should read them from pszBuffer */ void TestStreamIsNextToken( const char* pszBuffer, const char* pszTokens[] ); }; #endif // _TOKENIZER_TEST_H_ podofo-0.9.3/test/unit/ElementTest.h0000664000175000017500000000406711403202272017221 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2010 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #ifndef _ELEMENT_TEST_H_ #define _ELEMENT_TEST_H_ #include class ElementTest : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE( ElementTest ); CPPUNIT_TEST( testTypeToIndexAnnotation ); CPPUNIT_TEST( testTypeToIndexAction ); CPPUNIT_TEST( testTypeToIndexAnnotationUnknown ); CPPUNIT_TEST( testTypeToIndexActionUnknown ); CPPUNIT_TEST_SUITE_END(); public: void setUp(); void tearDown(); void testTypeToIndexAnnotation(); void testTypeToIndexAction(); void testTypeToIndexAnnotationUnknown(); void testTypeToIndexActionUnknown(); private: }; #endif // _ELEMENT_TEST_H_ podofo-0.9.3/test/unit/EncodingTest.cpp0000664000175000017500000003154212347347566017737 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2008 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include using namespace PoDoFo; inline std::ostream& operator<<(std::ostream& o, const PdfVariant& s) { std::string str; s.ToString(str); return o << str; } // Needs to be included after the redifition of operator<< // or it won't compile using clang #include "EncodingTest.h" // Registers the fixture into the 'registry' CPPUNIT_TEST_SUITE_REGISTRATION( EncodingTest ); void EncodingTest::setUp() { } void EncodingTest::tearDown() { } void EncodingTest::testDifferences() { PdfEncodingDifference difference; // Newly created encoding should be empty CPPUNIT_ASSERT_EQUAL( static_cast(difference.GetCount()), 0 ); // Adding 0 should work difference.AddDifference( 0, 0, PdfName("A") ); CPPUNIT_ASSERT_EQUAL( static_cast(difference.GetCount()), 1 ); // Adding 255 should work difference.AddDifference( 255, 0, PdfName("B") ); CPPUNIT_ASSERT_EQUAL( static_cast(difference.GetCount()), 2 ); // Adding out of range should throw exception CPPUNIT_ASSERT_THROW( difference.AddDifference( -1, 0, PdfName("C") );, PdfError ); CPPUNIT_ASSERT_THROW( difference.AddDifference( 256, 0, PdfName("D") );, PdfError ); CPPUNIT_ASSERT_EQUAL( static_cast(difference.GetCount()), 2 ); // Convert to array PdfArray data; PdfArray expected; expected.push_back( static_cast(0LL) ); expected.push_back( PdfName("A") ); expected.push_back( static_cast(255LL) ); expected.push_back( PdfName("B") ); difference.ToArray( data ); CPPUNIT_ASSERT_EQUAL( data.GetSize(), expected.GetSize() ); for( unsigned int i=0;i(0LL) ); expected.push_back( PdfName("A") ); expected.push_back( static_cast(255LL) ); expected.push_back( PdfName("X") ); difference.AddDifference( 255, 0, PdfName("X") ); difference.ToArray( data ); CPPUNIT_ASSERT_EQUAL( data.GetSize(), expected.GetSize() ); for( unsigned int i=0;i(0LL) ); expected.push_back( PdfName("A") ); expected.push_back( PdfName("B") ); expected.push_back( PdfName("C") ); expected.push_back( static_cast(4LL) ); expected.push_back( PdfName("D") ); expected.push_back( PdfName("E") ); expected.push_back( static_cast(9LL) ); expected.push_back( PdfName("F") ); expected.push_back( static_cast(255LL) ); expected.push_back( PdfName("X") ); difference.AddDifference( 1, 0, PdfName("B") ); difference.AddDifference( 2, 0, PdfName("C") ); difference.AddDifference( 4, 0, PdfName("D") ); difference.AddDifference( 5, 0, PdfName("E") ); difference.AddDifference( 9, 0, PdfName("F") ); difference.ToArray( data ); CPPUNIT_ASSERT_EQUAL( data.GetSize(), expected.GetSize() ); for( unsigned int i=0;i(value), 0x4100 ); #else CPPUNIT_ASSERT_EQUAL( static_cast(value), 0x0041 ); #endif //PODOFO_IS_LITTLE_ENDIAN CPPUNIT_ASSERT_EQUAL( difference.Contains( 9, name, value ), true ); CPPUNIT_ASSERT_EQUAL( name, PdfName("F") ); #ifdef PODOFO_IS_LITTLE_ENDIAN CPPUNIT_ASSERT_EQUAL( static_cast(value), 0x4600 ); #else CPPUNIT_ASSERT_EQUAL( static_cast(value), 0x0046 ); #endif //PODOFO_IS_LITTLE_ENDIAN CPPUNIT_ASSERT_EQUAL( difference.Contains( 255, name, value ), true ); CPPUNIT_ASSERT_EQUAL( name, PdfName("X") ); #ifdef PODOFO_IS_LITTLE_ENDIAN CPPUNIT_ASSERT_EQUAL( static_cast(value), 0x5800 ); #else CPPUNIT_ASSERT_EQUAL( static_cast(value), 0x0058 ); #endif //PODOFO_IS_LITTLE_ENDIAN CPPUNIT_ASSERT_EQUAL( difference.Contains( 100, name,value ), false ); } void EncodingTest::testDifferencesObject() { PdfMemDocument doc; PdfEncodingDifference difference; difference.AddDifference( 1, 0, PdfName("B") ); difference.AddDifference( 2, 0, PdfName("C") ); difference.AddDifference( 4, 0, PdfName("D") ); difference.AddDifference( 5, 0, PdfName("E") ); difference.AddDifference( 9, 0, PdfName("F") ); PdfDifferenceEncoding encoding( difference, PdfDifferenceEncoding::eBaseEncoding_MacRoman, &doc ); // Check for encoding key PdfObject* pObj = doc.GetObjects().CreateObject(); encoding.AddToDictionary( pObj->GetDictionary() ); CPPUNIT_ASSERT_EQUAL( true, pObj->GetDictionary().HasKey( PdfName("Encoding") ) ); PdfObject* pKey = pObj->GetDictionary().GetKey( PdfName("Encoding") ); CPPUNIT_ASSERT_EQUAL( true, pKey->IsReference() ); PdfObject* pEncoding = doc.GetObjects().GetObject( pKey->GetReference() ); // Test BaseEncoding PdfObject* pBase = pEncoding->GetDictionary().GetKey( PdfName("BaseEncoding" ) ); CPPUNIT_ASSERT_EQUAL( pBase->GetName(), PdfName("MacRomanEncoding") ); // Test differences PdfObject* pDiff = pEncoding->GetDictionary().GetKey( PdfName("Differences" ) ); PdfArray expected; expected.push_back( static_cast(1LL) ); expected.push_back( PdfName("B") ); expected.push_back( PdfName("C") ); expected.push_back( static_cast(4LL) ); expected.push_back( PdfName("D") ); expected.push_back( PdfName("E") ); expected.push_back( static_cast(9LL) ); expected.push_back( PdfName("F") ); const PdfArray & data = pDiff->GetArray(); CPPUNIT_ASSERT_EQUAL( data.GetSize(), expected.GetSize() ); for( unsigned int i=0;i(4), encodingStr.GetSize() ); CPPUNIT_ASSERT_EQUAL( memcmp("BAAB", encodingStr.GetBuffer(), encodingStr.GetSize()), 0 ); } void EncodingTest::testUnicodeNames() { // List of items which are defined twice and cause // other ids to be returned than those which where send in const char* pszDuplicated[] = { "Delta", "fraction", "hyphen", "macron", "mu", "Omega", "periodcentered", "scedilla", "Scedilla", "space", "tcommaaccent", "Tcommaaccent", "exclamsmall", "dollaroldstyle", "zerooldstyle", "oneoldstyle", "twooldstyle", "threeoldstyle", "fouroldstyle", "fiveoldstyle", "sixoldstyle", "sevenoldstyle", "eightoldstyle", "nineoldstyle", "ampersandsmall", "questionsmall", NULL }; int nCount = 0; for( int i = 0;i<=0xFFFF; i++ ) { PdfName name = PdfDifferenceEncoding::UnicodeIDToName( static_cast(i) ); pdf_utf16be id = PdfDifferenceEncoding::NameToUnicodeID( name ); bool bFound = false; const char** pszDup = pszDuplicated; while( *pszDup ) { if( PdfName( *pszDup ) == name ) { bFound = true; break; } ++pszDup; } if( !bFound ) { // Does not work because of 2 many duplicates... //CPPUNIT_ASSERT_EQUAL_MESSAGE( name.GetName(), id, static_cast(i) ); if( id == static_cast(i) ) ++nCount; } } CPPUNIT_ASSERT_EQUAL_MESSAGE( "Compared codes count", 65422, nCount ); } void EncodingTest::testGetCharCode() { std::string msg; bool ret; PdfWinAnsiEncoding cWinAnsiEncoding; ret = outofRangeHelper( &cWinAnsiEncoding, msg, "PdfWinAnsiEncoding" ); CPPUNIT_ASSERT_EQUAL_MESSAGE( msg, ret, true ); PdfMacRomanEncoding cMacRomanEncoding; ret = outofRangeHelper( &cMacRomanEncoding, msg, "PdfMacRomanEncoding" ); CPPUNIT_ASSERT_EQUAL_MESSAGE( msg, ret, true ); PdfIdentityEncoding cIdentityEncoding; ret = outofRangeHelper( &cIdentityEncoding, msg, "PdfIdentityEncoding" ); CPPUNIT_ASSERT_EQUAL_MESSAGE( msg, ret, true ); PdfVecObjects vec; vec.SetAutoDelete( true ); PdfEncodingDifference difference; difference.AddDifference( 0x0041, 0, PdfName("B") ); difference.AddDifference( 0x0042, 0, PdfName("A") ); PdfDifferenceEncoding cDifferenceEncoding( difference, PdfDifferenceEncoding::eBaseEncoding_WinAnsi, &vec ); ret = outofRangeHelper( &cDifferenceEncoding, msg, "PdfDifferenceEncoding" ); CPPUNIT_ASSERT_EQUAL_MESSAGE( msg, ret, true ); #ifdef PODOFO_IS_LITTLE_ENDIAN CPPUNIT_ASSERT_EQUAL( static_cast(0x4200), cDifferenceEncoding.GetCharCode( 0x0041 ) ); CPPUNIT_ASSERT_EQUAL( static_cast(0x4100), cDifferenceEncoding.GetCharCode( 0x0042 ) ); #else CPPUNIT_ASSERT_EQUAL( static_cast(0x0042), cDifferenceEncoding.GetCharCode( 0x0041 ) ); CPPUNIT_ASSERT_EQUAL( static_cast(0x0041), cDifferenceEncoding.GetCharCode( 0x0042 ) ); #endif // PODOFO_IS_LITTLE_ENDIAN } bool EncodingTest::outofRangeHelper( PdfEncoding* pEncoding, std::string & rMsg, const char* pszName ) { bool exception = false; try { pEncoding->GetCharCode( pEncoding->GetFirstChar() ); } catch( const PdfError & rError ) { // This may not throw! rMsg = "pEncoding->GetCharCode( pEncoding->GetFirstChar() ) failed"; return false; } try { pEncoding->GetCharCode( pEncoding->GetFirstChar() - 1 ); } catch( const PdfError & rError ) { // This has to throw! exception = true; } if( !exception ) { rMsg = "pEncoding->GetCharCode( pEncoding->GetFirstChar() - 1 ); failed"; return false; } try { pEncoding->GetCharCode( pEncoding->GetLastChar() ); } catch( const PdfError & rError ) { // This may not throw! rMsg = "pEncoding->GetCharCode( pEncoding->GetLastChar() ); failed"; return false; } exception = false; try { pEncoding->GetCharCode( pEncoding->GetLastChar() + 1 ); } catch( const PdfError & rError ) { // This has to throw! exception = true; } if( !exception ) { rMsg = "pEncoding->GetCharCode( pEncoding->GetLastChar() + 1 ); failed"; return false; } PdfEncoding::const_iterator it = pEncoding->begin(); int nCount = pEncoding->GetFirstChar(); while( it != pEncoding->end() ) { CPPUNIT_ASSERT_EQUAL_MESSAGE( pszName, *it, pEncoding->GetCharCode( nCount ) ); ++nCount; ++it; } return true; } podofo-0.9.3/test/unit/main.cpp0000664000175000017500000000752711232616441016262 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2007 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include #include #include #include #include void show_help() { std::cout << "podofo-test" << std::endl << std::endl; std::cout << "Supported commandline switches:" << std::endl; std::cout << "\t --help\t So this help message." << std::endl; std::cout << "\t --selftest\t Output in compiler compatible format." << std::endl; std::cout << "\t --test [name]\t Run only the test case [name]." << std::endl; std::cout << std::endl; } int main(int argc, char* argv[]) { // Get the top level suite from the registry CppUnit::Test *suite = CppUnit::TestFactoryRegistry::getRegistry().makeTest(); // Adds the test to the list of test to run CppUnit::TextUi::TestRunner runner; runner.addTest( suite ); // check some commandline arguments std::string sTestName = ""; bool bSelfTest = false; if( argc > 1 ) { for(int i=1;i #include #if defined(PODOFO_HAVE_FONTCONFIG) #include #endif /** This test tests the various PdfFont classes */ class FontTest : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE( FontTest ); #if defined(PODOFO_HAVE_FONTCONFIG) CPPUNIT_TEST( testFonts ); CPPUNIT_TEST( testCreateFontFtFace ); #endif CPPUNIT_TEST_SUITE_END(); public: void setUp(); void tearDown(); #if defined(PODOFO_HAVE_FONTCONFIG) void testFonts(); void testCreateFontFtFace(); #endif private: #if defined(PODOFO_HAVE_FONTCONFIG) void testSingleFont(FcPattern* pFont, FcConfig* pConfig); bool GetFontInfo( FcPattern* pFont, std::string & rsFamily, std::string & rsPath, bool & rbBold, bool & rbItalic ); #endif private: PoDoFo::PdfMemDocument* m_pDoc; PoDoFo::PdfVecObjects* m_pVecObjects; PoDoFo::PdfFontCache* m_pFontCache; }; #endif // _FONT_TEST_H_ podofo-0.9.3/test/WatermarkTest/0000775000175000017500000000000012356565165016453 5ustar dominikdominikpodofo-0.9.3/test/WatermarkTest/WatermarkTest.cpp0000664000175000017500000000557311460071654021754 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2005 by Dominik Seichter * * domseichter@web.de * * * * 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., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "../PdfTest.h" #include using namespace PoDoFo; void WatermarkFile( const char* pszInFilename, const char* pszOutFilename ) { printf("Running watermark test\n"); PdfMemDocument doc( pszInFilename ); PdfPainter painter; PdfPage* pPage; PdfRect rect; int i; for(i=0;iGetPageSize(); painter.SetPage( pPage ); painter.SetStrokingColor( 1.0, 0.0, 0.0 ); painter.SetStrokeWidth( 5 ); painter.DrawLine( 0.0, 0.0, rect.GetWidth(), rect.GetHeight() ); painter.DrawLine( 0, rect.GetHeight(), rect.GetWidth(), 0.0 ); painter.FinishPage(); } printf("writing document back\n"); doc.Write( pszOutFilename ); } int main( int argc, char* argv[] ) { if( argc != 3 ) { printf("Usage: WatermarkTest input_filename output_filename\n"); return 0; } printf("This test tests the PdfWriter and PdfDocument classes.\n"); printf("It opens an existing PDF and draws an X on each page.\n"); printf("---\n"); printf("Watermarking....\n"); try { WatermarkFile( argv[1], argv[2] ); } catch( const PdfError & e ) { e.PrintErrorMsg(); return e.GetError(); } return 0; } podofo-0.9.3/test/WatermarkTest/CMakeLists.txt0000664000175000017500000000040210614703752021176 0ustar dominikdominikADD_EXECUTABLE(WatermarkTest WatermarkTest.cpp) TARGET_LINK_LIBRARIES(WatermarkTest ${PODOFO_LIB} ${PODOFO_LIB_DEPENDS}) SET_TARGET_PROPERTIES(WatermarkTest PROPERTIES COMPILE_FLAGS "${PODOFO_CFLAGS}") ADD_DEPENDENCIES(WatermarkTest ${PODOFO_DEPEND_TARGET}) podofo-0.9.3/test/WatermarkTest/WatermarkTest.vcproj0000664000175000017500000000673110475170454022475 0ustar dominikdominik podofo-0.9.3/test/valgrind.suppressions0000664000175000017500000000015610564241471020153 0ustar dominikdominik{ SeeZLibFAQ Memcheck:Cond obj:/usr/lib/libz.so.1.2.3 obj:/usr/lib/libz.so.1.2.3 fun:deflate } podofo-0.9.3/COPYING0000664000175000017500000004313110432364310013712 0ustar dominikdominik GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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. podofo-0.9.3/cmake/0000775000175000017500000000000012356565165013757 5ustar dominikdominikpodofo-0.9.3/cmake/modules/0000775000175000017500000000000012356565165015427 5ustar dominikdominikpodofo-0.9.3/cmake/modules/FindLIBIDN.cmake0000664000175000017500000000256011725624277020175 0ustar dominikdominik# - Find libidn # Find the native LIBIDN includes and library # # LIBIDN_INCLUDE_DIR - where to find stringprep.h, etc. # LIBIDN_LIBRARIES - List of libraries when using libidn. # LIBIDN_FOUND - True if libidn found. IF (LIBIDN_INCLUDE_DIR) # Already in cache, be silent SET(LIBIDN_FIND_QUIETLY TRUE) ENDIF (LIBIDN_INCLUDE_DIR) FIND_PATH(LIBIDN_INCLUDE_DIR stringprep.h) SET(LIBIDN_LIBRARY_NAMES_RELEASE ${LIBIDN_LIBRARY_NAMES_RELEASE} ${LIBIDN_LIBRARY_NAMES} idn) FIND_LIBRARY(LIBIDN_LIBRARY_RELEASE NAMES ${LIBIDN_LIBRARY_NAMES_RELEASE} ) # Find a debug library if one exists and use that for debug builds. # This really only does anything for win32, but does no harm on other # platforms. SET(LIBIDN_LIBRARY_NAMES_DEBUG ${LIBIDN_LIBRARY_NAMES_DEBUG} idnd) FIND_LIBRARY(LIBIDN_LIBRARY_DEBUG NAMES ${LIBIDN_LIBRARY_NAMES_DEBUG}) INCLUDE(LibraryDebugAndRelease) SET_LIBRARY_FROM_DEBUG_AND_RELEASE(LIBIDN) # handle the QUIETLY and REQUIRED arguments and set LIBIDN_FOUND to TRUE if # all listed variables are TRUE INCLUDE(PoDoFoFindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(LIBIDN DEFAULT_MSG LIBIDN_LIBRARY LIBIDN_INCLUDE_DIR) IF(LIBIDN_FOUND) SET( LIBIDN_LIBRARIES ${LIBIDN_LIBRARY} ) ELSE(LIBIDN_FOUND) SET( LIBIDN_LIBRARIES ) ENDIF(LIBIDN_FOUND) MARK_AS_ADVANCED( LIBIDN_LIBRARY LIBIDN_INCLUDE_DIR ) podofo-0.9.3/cmake/modules/FindBoost.cmake0000664000175000017500000001417711734606101020313 0ustar dominikdominik# - Find the Boost includes and libraries. # The following variables are set if Boost is found. If Boost is not # found, Boost_FOUND is set to false. # Boost_FOUND - True when the Boost include directory is found. # Boost_INCLUDE_DIRS - the path to where the boost include files are. # Boost_LIBRARY_DIRS - The path to where the boost library files are. # Boost_LIB_DIAGNOSTIC_DEFINITIONS - Only set if using Windows. # ---------------------------------------------------------------------------- # If you have installed Boost in a non-standard location or you have # just staged the boost files using bjam then you have three # options. In the following comments, it is assumed that # points to the root directory of the include directory of Boost. e.g # If you have put boost in C:\development\Boost then is # "C:/development/Boost" and in this directory there will be two # directories, one called either "boost" or "include" and the other called "lib". # 1) After CMake runs, set Boost_INCLUDE_DIR to /include/boost<-version> # 2) Use CMAKE_INCLUDE_PATH to set a path to /include. This will allow FIND_PATH() # to locate Boost_INCLUDE_DIR by utilizing the PATH_SUFFIXES option. e.g. # SET(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "/include") # 3) Set an environment variable called ${BOOST_ROOT} that points to the root of where you have # installed Boost, e.g. . It is assumed that there is at least a subdirectory called # include in this path. # # Note: # 1) If you are just using the boost headers, then you do not need to use # Boost_LIBRARY_DIRS in your CMakeLists.txt file. # 2) If Boost has not been installed, then when setting Boost_LIBRARY_DIRS # the script will look for /lib first and, if this fails, then for /stage/lib. # # Usage: # In your CMakeLists.txt file do something like this: # ... # # Boost # FIND_PACKAGE(Boost) # ... # INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS}) # LINK_DIRECTORIES(${Boost_LIBRARY_DIRS}) # # In Windows, we make the assumption that, if the Boost files are installed, the default directory # will be C:\boost. # # TODO: # # 1) Automatically find the Boost library files and eliminate the need # to use Link Directories. # IF(WIN32) # In windows, automatic linking is performed, so you do not have to specify the libraries. # If you are linking to a dynamic runtime, then you can choose to link to either a static or a # dynamic Boost library, the default is to do a static link. You can alter this for a specific # library "whatever" by defining BOOST_WHATEVER_DYN_LINK to force Boost library "whatever" to # be linked dynamically. Alternatively you can force all Boost libraries to dynamic link by # defining BOOST_ALL_DYN_LINK. # This feature can be disabled for Boost library "whatever" by defining BOOST_WHATEVER_NO_LIB, # or for all of Boost by defining BOOST_ALL_NO_LIB. # If you want to observe which libraries are being linked against then defining # BOOST_LIB_DIAGNOSTIC will cause the auto-linking code to emit a #pragma message each time # a library is selected for linking. SET(Boost_LIB_DIAGNOSTIC_DEFINITIONS "-DBOOST_LIB_DIAGNOSTIC") ENDIF(WIN32) SET(BOOST_INCLUDE_PATH_DESCRIPTION "directory containing the boost include files, e.g. /usr/local/include/boost-1_33_1 or c:/boost/include/boost-1_33_1") SET(BOOST_DIR_MESSAGE "Set the Boost_INCLUDE_DIR cmake cache entry to the ${BOOST_INCLUDE_PATH_DESCRIPTION} or set the BOOST_ROOT environment variable and re-run cmake.") SET(BOOST_DIR_SEARCH "$ENV{BOOST_ROOT}") IF(BOOST_DIR_SEARCH) FILE(TO_CMAKE_PATH "${BOOST_DIR_SEARCH}" BOOST_DIR_SEARCH) SET(BOOST_DIR_SEARCH "${BOOST_DIR_SEARCH}" "${BOOST_DIR_SEARCH}/include") ENDIF(BOOST_DIR_SEARCH) IF(WIN32) SET(BOOST_DIR_SEARCH "${BOOST_DIR_SEARCH}" C:/boost/include D:/boost/include C:/boost D:/boost ) ELSE(WIN32) SET(BOOST_DIR_SEARCH "${BOOST_DIR_SEARCH}" /usr/include/boost/ ) ENDIF(WIN32) # Add in some path suffixes. These will have to be updated whenever a new Boost version comes out. SET(SUFFIX_FOR_PATH boost-1_34_1 boost-1_34_0 boost-1_33_1 boost-1_33_0 ) # # Look for an installation. # FIND_PATH(Boost_INCLUDE_DIR NAMES boost/config.hpp PATH_SUFFIXES ${SUFFIX_FOR_PATH} PATHS # Look in other places. ${BOOST_DIR_SEARCH} # Help the user find it if we cannot. DOC "The ${BOOST_INCLUDE_PATH_DESCRIPTION}" ) SET(Boost_INCLUDE_DIRS "${Boost_INCLUDE_DIR}") # Now try to get the include and library path. IF(Boost_INCLUDE_DIR) # Look for the boost library path. # Note that the user may not have installed any libraries # so it is quite possible the Boost_LIBRARY_PATH may not exist. SET(Boost_LIBRARY_DIR ${Boost_INCLUDE_DIR}) IF("${Boost_LIBRARY_DIR}" MATCHES "boost-[0-9]+") GET_FILENAME_COMPONENT(Boost_LIBRARY_DIR ${Boost_LIBRARY_DIR} PATH) ENDIF ("${Boost_LIBRARY_DIR}" MATCHES "boost-[0-9]+") IF("${Boost_LIBRARY_DIR}" MATCHES "/include$") # Strip off the trailing "/include" in the path. GET_FILENAME_COMPONENT(Boost_LIBRARY_DIR ${Boost_LIBRARY_DIR} PATH) ENDIF("${Boost_LIBRARY_DIR}" MATCHES "/include$") IF(EXISTS "${Boost_LIBRARY_DIR}/lib") SET (Boost_LIBRARY_DIR ${Boost_LIBRARY_DIR}/lib) ELSE(EXISTS "${Boost_LIBRARY_DIR}/lib") IF(EXISTS "${Boost_LIBRARY_DIR}/stage/lib") SET(Boost_LIBRARY_DIR ${Boost_LIBRARY_DIR}/stage/lib) ELSE(EXISTS "${Boost_LIBRARY_DIR}/stage/lib") SET(Boost_LIBRARY_DIR "") ENDIF(EXISTS "${Boost_LIBRARY_DIR}/stage/lib") ENDIF(EXISTS "${Boost_LIBRARY_DIR}/lib") IF(Boost_LIBRARY_DIR AND EXISTS "${Boost_LIBRARY_DIR}") SET(Boost_LIBRARY_DIRS ${Boost_LIBRARY_DIR}) ENDIF(Boost_LIBRARY_DIR AND EXISTS "${Boost_LIBRARY_DIR}") ENDIF(Boost_INCLUDE_DIR) # We have found boost. It is possible that the user has not # compiled any libraries so we set Boost_FOUND to be true here. # handle the QUIETLY and REQUIRED arguments and set BOOST_FOUND to TRUE if # all listed variables are TRUE INCLUDE(PoDoFoFindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(Boost "Boost was not found. ${BOOST_DIR_MESSAGE}" Boost_INCLUDE_DIR ) SET(Boost_FOUND ${BOOST_FOUND}) MARK_AS_ADVANCED(Boost_INCLUDE_DIR) podofo-0.9.3/cmake/modules/MacroEnsureVersion.cmake0000664000175000017500000000665610720646026022224 0ustar dominikdominik# This macro compares version numbers of the form "x.y.z" # MACRO_ENSURE_VERSION( FOO_MIN_VERSION FOO_VERSION_FOUND FOO_VERSION_OK) # will set FOO_VERSIN_OK to true if FOO_VERSION_FOUND >= FOO_MIN_VERSION # where both have to be in a 3-part-version format, leading and trailing # text is ok, e.g. # MACRO_ENSURE_VERSION( "2.5.31" "flex 2.5.4a" VERSION_OK) # which means 2.5.31 is required and "flex 2.5.4a" is what was found on the system # Copyright (c) 2006, David Faure, # # Redistribution and use is allowed according to the terms of the BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. MACRO(MACRO_ENSURE_VERSION requested_version found_version var_too_old) # parse the parts of the version string STRING(REGEX REPLACE "([0-9]+)\\.[0-9]+\\.[0-9]+" "\\1" req_major_vers "${requested_version}") STRING(REGEX REPLACE "[0-9]+\\.([0-9]+)\\.[0-9]+" "\\1" req_minor_vers "${requested_version}") STRING(REGEX REPLACE "[0-9]+\\.[0-9]+\\.([0-9]+)" "\\1" req_patch_vers "${requested_version}") STRING(REGEX REPLACE "[^0-9]*([0-9]+)\\.[0-9]+\\.[0-9]+.*" "\\1" found_major_vers "${found_version}") STRING(REGEX REPLACE "[^0-9]*[0-9]+\\.([0-9]+)\\.[0-9]+.*" "\\1" found_minor_vers "${found_version}") STRING(REGEX REPLACE "[^0-9]*[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" found_patch_vers "${found_version}") # compute an overall version number which can be compared at once MATH(EXPR req_vers_num "${req_major_vers}*10000 + ${req_minor_vers}*100 + ${req_patch_vers}") MATH(EXPR found_vers_num "${found_major_vers}*10000 + ${found_minor_vers}*100 + ${found_patch_vers}") if (found_vers_num LESS req_vers_num) set( ${var_too_old} FALSE ) else (found_vers_num LESS req_vers_num) set( ${var_too_old} TRUE ) endif (found_vers_num LESS req_vers_num) ENDMACRO(MACRO_ENSURE_VERSION) # This macro compares version numbers of the form "x.y" # MACRO_ENSURE_VERSION( FOO_MIN_VERSION FOO_VERSION_FOUND FOO_VERSION_OK) # will set FOO_VERSIN_OK to true if FOO_VERSION_FOUND >= FOO_MIN_VERSION # where both have to be in a 2-part-version format, leading and trailing # text is ok, e.g. # MACRO_ENSURE_VERSION( "0.5" "foo 0.6" VERSION_OK) # which means 0.5 is required and "foo 0.6" is what was found on the system # Copyright (c) 2006, David Faure, # Copyright (c) 2007, Pino Toscano, # # Redistribution and use is allowed according to the terms of the BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. MACRO(MACRO_ENSURE_VERSION2 requested_version found_version var_too_old) # parse the parts of the version string STRING(REGEX REPLACE "([0-9]+)\\.[0-9]+" "\\1" req_major_vers "${requested_version}") STRING(REGEX REPLACE "[0-9]+\\.([0-9]+)" "\\1" req_minor_vers "${requested_version}") STRING(REGEX REPLACE "[^0-9]*([0-9]+)\\.[0-9]+.*" "\\1" found_major_vers "${found_version}") STRING(REGEX REPLACE "[^0-9]*[0-9]+\\.([0-9]+).*" "\\1" found_minor_vers "${found_version}") # compute an overall version number which can be compared at once MATH(EXPR req_vers_num "${req_major_vers}*100 + ${req_minor_vers}") MATH(EXPR found_vers_num "${found_major_vers}*100 + ${found_minor_vers}") if (found_vers_num LESS req_vers_num) set( ${var_too_old} FALSE ) else (found_vers_num LESS req_vers_num) set( ${var_too_old} TRUE ) endif (found_vers_num LESS req_vers_num) ENDMACRO(MACRO_ENSURE_VERSION2) podofo-0.9.3/cmake/modules/FindPkgConfig.cmake0000664000175000017500000000452211075540405021067 0ustar dominikdominik## FindPkgConfig.cmake ## by Albert Strasheim ## ## This module finds packages using pkg-config, which retrieves ## information about packages from special metadata files. ## ## See http://www . freedesktop . org/Software/pkgconfig/ ## ## ------------------------------------------------------------------- ## ## Usage: ## ## INCLUDE( ${CMAKE_ROOT}/Modules/FindPkgConfig.cmake) ## PKGCONFIG("libxml-2.0 >= 1.3") ## IF(PKGCONFIG_FOUND) ## # do something with CMAKE_PKGCONFIG_C_FLAGS ## # do something with PKGCONFIG_LIBRARIES ## ELSE(PKGCONFIG_FOUND) # MESSAGE("Cannot find libxml2 version 1.3 or above") ## ENDIF(PKGCONFIG_FOUND) ## ## Notes: ## ## You can set the PKG_CONFIG_PATH environment variable to tell ## pkg-config where to search for .pc files. See pkg-config(1) for ## more information. #FIXME: IF(WIN32) pkg-config --msvc-syntax ENDIF(WIN32) ??? FIND_PROGRAM(CMAKE_PKGCONFIG_EXECUTABLE pkg-config) MARK_AS_ADVANCED(CMAKE_PKGCONFIG_EXECUTABLE) MACRO(PKGCONFIG LIBRARY) SET(PKGCONFIG_FOUND 0) # MESSAGE("DEBUG: find library '${LIBRARY}'") IF(CMAKE_PKGCONFIG_EXECUTABLE) # MESSAGE("DEBUG: pkg-config executable found") EXEC_PROGRAM(${CMAKE_PKGCONFIG_EXECUTABLE} ARGS "'${LIBRARY}'" OUTPUT_VARIABLE PKGCONFIG_OUTPUT RETURN_VALUE PKGCONFIG_RETURN) IF(NOT PKGCONFIG_RETURN) # MESSAGE("DEBUG: packages found") # set C_FLAGS and CXX_FLAGS EXEC_PROGRAM(${CMAKE_PKGCONFIG_EXECUTABLE} ARGS "--cflags '${LIBRARY}'" OUTPUT_VARIABLE CMAKE_PKGCONFIG_C_FLAGS) SET(CMAKE_PKGCONFIG_CXX_FLAGS "${CMAKE_PKGCONFIG_C_FLAGS}") # set LIBRARIES EXEC_PROGRAM(${CMAKE_PKGCONFIG_EXECUTABLE} ARGS "--libs '${LIBRARY}'" OUTPUT_VARIABLE PKGCONFIG_LIBRARIES) SET(PKGCONFIG_FOUND 1) ELSE(NOT PKGCONFIG_RETURN) # MESSAGE("DEBUG '${LIBRARY}' NOT FOUND by pkg-config") SET(CMAKE_PKGCONFIG_C_FLAGS "") SET(CMAKE_PKGCONFIG_CXX_FLAGS "") SET(PKGCONFIG_LIBRARIES "") ENDIF(NOT PKGCONFIG_RETURN) # ELSE(CMAKE_PKGCONFIG_EXECUTABLE) # MESSAGE("DEBUG: pkg-config executable NOT FOUND") ENDIF(CMAKE_PKGCONFIG_EXECUTABLE) # MESSAGE("DEBUG: CMAKE_PKGCONFIG_C_FLAGS=${CMAKE_PKGCONFIG_C_FLAGS}") # MESSAGE("DEBUG: PKGCONFIG_LIBRARIES=${PKGCONFIG_LIBRARIES}") ENDMACRO(PKGCONFIG) podofo-0.9.3/cmake/modules/LibraryDebugAndRelease.cmake0000664000175000017500000000251510714374660022725 0ustar dominikdominik# # This macro is used when we may have a debug and or release build of a library, # and we want to produce a single easy to use library string that'll do the right # thing. If both debug and release versions are available, we'll automatically use the # debug version for debug builds and the release version for release builds. # # If only one build exists, we use that one irrespective of build type. # MACRO(SET_LIBRARY_FROM_DEBUG_AND_RELEASE _NAME) IF(NOT DEFINED "${_NAME}_LIBRARY_RELEASE" OR NOT DEFINED "${_NAME}_LIBRARY_DEBUG") MESSAGE(FATAL_ERROR "${_NAME}_LIBRARY_DEBUG OR ${_NAME}_LIBRARY_RELEASE undefined") ENDIF(NOT DEFINED "${_NAME}_LIBRARY_RELEASE" OR NOT DEFINED "${_NAME}_LIBRARY_DEBUG") IF(${_NAME}_LIBRARY_RELEASE AND ${_NAME}_LIBRARY_DEBUG) SET(${_NAME}_LIBRARY "optimized;${${_NAME}_LIBRARY_RELEASE};debug;${${_NAME}_LIBRARY_DEBUG}") ELSE(${_NAME}_LIBRARY_RELEASE AND ${_NAME}_LIBRARY_DEBUG) IF(${_NAME}_LIBRARY_DEBUG) MESSAGE("WARNING: ${_NAME} debug library will be used even for release builds") SET(${_NAME}_LIBRARY ${${_NAME}_LIBRARY_DEBUG}) ELSE(${_NAME}_LIBRARY_DEBUG) SET(${_NAME}_LIBRARY ${${_NAME}_LIBRARY_RELEASE}) ENDIF(${_NAME}_LIBRARY_DEBUG) ENDIF(${_NAME}_LIBRARY_RELEASE AND ${_NAME}_LIBRARY_DEBUG) ENDMACRO(SET_LIBRARY_FROM_DEBUG_AND_RELEASE) podofo-0.9.3/cmake/modules/FindLIBCRYPTO.cmake0000664000175000017500000000402112320241736020560 0ustar dominikdominik# - Find libCrypto # Find the native OpenSSL LIBCRYPTO includes and library # # LIBCRYPTO_INCLUDE_DIR - where to find sha.h, etc. # LIBCRYPTO_LIBRARIES - List of libraries when using libCrypto. # LIBCRYPTO_FOUND - True if libCrypto found. IF (LIBCRYPTO_INCLUDE_DIR) # Already in cache, be silent SET(LIBCRYPTO_FIND_QUIETLY TRUE) ENDIF (LIBCRYPTO_INCLUDE_DIR) # Require a regular OpenSSL even on OSX/iOS # IF(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") # # MacOSX has deprecated the use of openssl crypto functions # # and replaced it with API-compatible CommonCrypto # FIND_PATH(LIBCRYPTO_INCLUDE_DIR CommonCrypto/CommonDigest.h) # SET(LIBCRYPTO_LIBRARY_NAMES_RELEASE ${LIBCRYPTO_LIBRARY_NAMES_RELEASE} ${LIBCRYPTO_LIBRARY_NAMES} ssl) # SET(LIBCRYPTO_LIBRARY_NAMES_DEBUG ${LIBCRYPTO_LIBRARY_NAMES_DEBUG} ssld) # ELSE(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") FIND_PATH(LIBCRYPTO_INCLUDE_DIR openssl/sha.h) SET(LIBCRYPTO_LIBRARY_NAMES_RELEASE ${LIBCRYPTO_LIBRARY_NAMES_RELEASE} ${LIBCRYPTO_LIBRARY_NAMES} crypto) SET(LIBCRYPTO_LIBRARY_NAMES_DEBUG ${LIBCRYPTO_LIBRARY_NAMES_DEBUG} cryptod) # ENDIF(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") FIND_LIBRARY(LIBCRYPTO_LIBRARY_RELEASE NAMES ${LIBCRYPTO_LIBRARY_NAMES_RELEASE} ) # Find a debug library if one exists and use that for debug builds. # This really only does anything for win32, but does no harm on other # platforms. FIND_LIBRARY(LIBCRYPTO_LIBRARY_DEBUG NAMES ${LIBCRYPTO_LIBRARY_NAMES_DEBUG}) INCLUDE(LibraryDebugAndRelease) SET_LIBRARY_FROM_DEBUG_AND_RELEASE(LIBCRYPTO) # handle the QUIETLY and REQUIRED arguments and set LIBCRYPTO_FOUND to TRUE if # all listed variables are TRUE INCLUDE(PoDoFoFindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(LIBCRYPTO DEFAULT_MSG LIBCRYPTO_LIBRARY LIBCRYPTO_INCLUDE_DIR) IF(LIBCRYPTO_FOUND) SET( LIBCRYPTO_LIBRARIES ${LIBCRYPTO_LIBRARY} ) ELSE(LIBCRYPTO_FOUND) SET( LIBCRYPTO_LIBRARIES ) ENDIF(LIBCRYPTO_FOUND) MARK_AS_ADVANCED( LIBCRYPTO_LIBRARY LIBCRYPTO_INCLUDE_DIR ) podofo-0.9.3/cmake/modules/FindLua51.cmake0000664000175000017500000000340711077325327020116 0ustar dominikdominik# Locate Lua library # This module defines # LUA_LIBRARIES # LUA_FOUND, if false, do not try to link to Lua # LUA_INCLUDE_DIR, where to find lua.h # # Note that the expected include convention is # #include "lua.h" # and not # #include # This is because, the lua location is not standardized and may exist # in locations other than lua/ FIND_PATH(LUA_INCLUDE_DIR lua.h PATHS $ENV{LUA_DIR} NO_DEFAULT_PATH PATH_SUFFIXES include/lua51 include/lua5.1 include/lua include ) FIND_PATH(LUA_INCLUDE_DIR lua.h PATHS ~/Library/Frameworks /Library/Frameworks /usr/local /usr /sw # Fink /opt/local # DarwinPorts /opt/csw # Blastwave /opt PATH_SUFFIXES include/lua51 include/lua5.1 include/lua include ) FIND_LIBRARY(LUA_LIBRARY NAMES lua51 lua5.1 lua PATHS $ENV{LUA_DIR} NO_DEFAULT_PATH PATH_SUFFIXES lib64 lib ) FIND_LIBRARY(LUA_LIBRARY NAMES lua51 lua5.1 lua PATHS ~/Library/Frameworks /Library/Frameworks /usr/local /usr /sw /opt/local /opt/csw /opt PATH_SUFFIXES lib64 lib ) IF(LUA_LIBRARY) # include the math library for Unix IF(UNIX AND NOT APPLE) FIND_LIBRARY(LUA_MATH_LIBRARY m) SET( LUA_LIBRARIES "${LUA_LIBRARY};${LUA_MATH_LIBRARY}" CACHE STRING "Lua Libraries") # For Windows and Mac, don't need to explicitly include the math library ELSE(UNIX AND NOT APPLE) SET( LUA_LIBRARIES "${LUA_LIBRARY}" CACHE STRING "Lua Libraries") ENDIF(UNIX AND NOT APPLE) ENDIF(LUA_LIBRARY) INCLUDE(PoDoFoFindPackageHandleStandardArgs) # handle the QUIETLY and REQUIRED arguments and set LUA_FOUND to TRUE if # all listed variables are TRUE FIND_PACKAGE_HANDLE_STANDARD_ARGS(Lua50 DEFAULT_MSG LUA_LIBRARIES LUA_INCLUDE_DIR) MARK_AS_ADVANCED(LUA_INCLUDE_DIR LUA_LIBRARIES LUA_LIBRARY LUA_MATH_LIBRARY) podofo-0.9.3/cmake/modules/FindLIBJPEG.cmake0000664000175000017500000000251611014031047020263 0ustar dominikdominik# - Find LIBJPEG # Find the native LIBJPEG includes and library # This module defines # LIBJPEG_INCLUDE_DIR, where to find jpeglib.h, etc. # LIBJPEG_LIBRARIES, the libraries needed to use LIBJPEG. # LIBJPEG_FOUND, If false, do not try to use LIBJPEG. # also defined, but not for general use are # LIBJPEG_LIBRARY, where to find the LIBJPEG library. FIND_PATH(LIBJPEG_INCLUDE_DIR jpeglib.h) SET(LIBJPEG_LIBRARY_NAMES_RELEASE ${LIBJPEG_LIBRARY_NAMES_RELEASE} ${LIBJPEG_LIBRARY_NAMES} jpeg libjpeg) FIND_LIBRARY(LIBJPEG_LIBRARY_RELEASE NAMES ${LIBJPEG_LIBRARY_NAMES_RELEASE} ) SET(LIBJPEG_LIBRARY_NAMES_DEBUG ${LIBJPEG_LIBRARY_NAMES_DEBUG} jpegd libjpegd jpeg_d libjpeg_d) FIND_LIBRARY(LIBJPEG_LIBRARY_DEBUG NAMES ${LIBJPEG_LIBRARY_NAMES_DEBUG} ) INCLUDE(LibraryDebugAndRelease) SET_LIBRARY_FROM_DEBUG_AND_RELEASE(LIBJPEG) # handle the QUIETLY and REQUIRED arguments and set LIBJPEG_FOUND to TRUE if # all listed variables are TRUE INCLUDE(PoDoFoFindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(LIBJPEG DEFAULT_MSG LIBJPEG_LIBRARY LIBJPEG_INCLUDE_DIR) IF(LIBJPEG_FOUND) SET(LIBJPEG_LIBRARIES ${LIBJPEG_LIBRARY}) ELSE(LIBJPEG_FOUND) MESSAGE("libjpeg not found: Library ${LIBJPEG_LIBRARY}, headers ${LIBJPEG_INCLUDE_DIR}") ENDIF(LIBJPEG_FOUND) MARK_AS_ADVANCED(LIBJPEG_LIBRARY LIBJPEG_INCLUDE_DIR ) podofo-0.9.3/cmake/modules/FindFREETYPE.cmake0000664000175000017500000000700012312006110020416 0ustar dominikdominik# # Find the native FREETYPE includes and library # # This module defines # FREETYPE_INCLUDE_DIR, where to find ft2build.h, ftheader.h, ... # FREETYPE_LIBRARIES, the libraries to link against to use FREETYPE. # FREETYPE_FOUND, If false, do not try to use FREETYPE. # also defined, but not for general use are # FREETYPE_LIBRARY, where to find the FREETYPE library. SET(FREETYPE_FIND_QUIETLY 1) # first we try to find ft2build.h in the new location as # of freetype 2.5.1 FIND_PATH(FREETYPE_INCLUDE_DIR_FT2BUILD ft2build.h /usr/include/freetype2 /usr/local/include/freetype2 /usr/X11/include/freetype2 NO_CMAKE_SYSTEM_PATH ) # in case we couldn't find it in the new location # we check the old location IF (NOT FREETYPE_INCLUDE_DIR_FT2BUILD) FIND_PATH(FREETYPE_INCLUDE_DIR_FT2BUILD ft2build.h /usr/include /usr/local/include /usr/X11/include NO_CMAKE_SYSTEM_PATH ) ENDIF (NOT FREETYPE_INCLUDE_DIR_FT2BUILD) # now try to find ftheader.h in the new location first FIND_PATH(FREETYPE_INCLUDE_DIR_FTHEADER config/ftheader.h /usr/include/freetype2 /usr/local/include/freetype2 /usr/X11/include/freetype2 ${FREETYPE_INCLUDE_DIR_FT2BUILD} NO_CMAKE_SYSTEM_PATH ) # in case we couldn't find it in the new location # we check the old location IF (NOT FREETYPE_INCLUDE_DIR_FTHEADER) FIND_PATH(FREETYPE_INCLUDE_DIR_FTHEADER freetype/config/ftheader.h /usr/include/freetype2 /usr/local/include/freetype2 /usr/X11/include/freetype2 ${FREETYPE_INCLUDE_DIR_FT2BUILD} ${FREETYPE_INCLUDE_DIR_FT2BUILD}/freetype2 NO_CMAKE_SYSTEM_PATH ) ENDIF (NOT FREETYPE_INCLUDE_DIR_FTHEADER) IF ( FREETYPE_INCLUDE_DIR_FTHEADER AND FREETYPE_INCLUDE_DIR_FT2BUILD ) SET(FREETYPE_INCLUDE_DIR ${FREETYPE_INCLUDE_DIR_FTHEADER} ${FREETYPE_INCLUDE_DIR_FT2BUILD}) ENDIF ( FREETYPE_INCLUDE_DIR_FTHEADER AND FREETYPE_INCLUDE_DIR_FT2BUILD ) LIST(REMOVE_DUPLICATES FREETYPE_INCLUDE_DIR) IF(NOT FREETYPE_FIND_QUIETLY) MESSAGE("FREETYPE_INCLUDE_DIR_FT2BUILD ${FREETYPE_INCLUDE_DIR_FT2BUILD}") MESSAGE("FREETYPE_INCLUDE_DIR_FTHEADER ${FREETYPE_INCLUDE_DIR_FTHEADER}") MESSAGE("FREETYPE_INCLUDE_DIR ${FREETYPE_INCLUDE_DIR}") ENDIF(NOT FREETYPE_FIND_QUIETLY) SET(FREETYPE_LIBRARY_NAMES_DEBUG ${FREETYPE_LIBRARY_NAMES_DEBUG} freetyped libfreetyped) SET(FREETYPE_LIBRARY_NAMES_RELEASE ${FREETYPE_LIBRARY_NAMES_RELEASE} freetype libfreetype) SET(FREETYPE_LIB_PATHS /usr/lib /usr/local/lib /usr/X11/lib) FIND_LIBRARY(FREETYPE_LIBRARY_RELEASE ${FREETYPE_LIBRARY_NAMES_RELEASE} ${FREETYPE_LIBRARY_NAMES} PATHS ${FREETYPE_LIB_PATHS} ) FIND_LIBRARY(FREETYPE_LIBRARY_DEBUG ${FREETYPE_LIBRARY_NAMES_DEBUG} PATHS ${FREETYPE_LIB_PATHS} ) INCLUDE(LibraryDebugAndRelease) SET_LIBRARY_FROM_DEBUG_AND_RELEASE(FREETYPE) SET(FREETYPE_LIBRARIES ${FREETYPE_LIBRARY}) IF(NOT FREETYPE_FIND_QUIETLY) MESSAGE("FREETYPE_LIBRARY_DEBUG ${FREETYPE_LIBRARY_DEBUG}") MESSAGE("FREETYPE_LIBRARY_RELEASE ${FREETYPE_LIBRARY_RELEASE}") MESSAGE("FREETYPE_LIBRARY ${FREETYPE_LIBRARY}") ENDIF(NOT FREETYPE_FIND_QUIETLY) # MESSAGE(STATUS "ft lib ${FREETYPE_LIBRARY}") # MESSAGE(STATUS "ft2 build ${FREETYPE_INCLUDE_DIR_FT2BUILD}") # MESSAGE(STATUS "ft header ${FREETYPE_INCLUDE_DIR_FTHEADER}") INCLUDE(PoDoFoFindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(FREETYPE DEFAULT_MSG FREETYPE_LIBRARY FREETYPE_INCLUDE_DIR) IF (NOT FREETYPE_FIND_QUIETLY) MESSAGE(STATUS "Found Freetype2: ${FREETYPE_LIBRARY}") ENDIF (NOT FREETYPE_FIND_QUIETLY) podofo-0.9.3/cmake/modules/FindCppUnit.cmake0000664000175000017500000000522310720646026020603 0ustar dominikdominik# - Try to find the libcppunit libraries # Once done this will define # # CppUnit_FOUND - system has libcppunit # CPPUNIT_INCLUDE_DIR - the libcppunit include directory # CPPUNIT_LIBRARIES - libcppunit library include (MacroEnsureVersion) if(NOT CPPUNIT_MIN_VERSION) SET(CPPUNIT_MIN_VERSION 1.12.0) endif(NOT CPPUNIT_MIN_VERSION) FIND_PROGRAM(CPPUNIT_CONFIG_EXECUTABLE cppunit-config ) IF(CPPUNIT_INCLUDE_DIR AND CPPUNIT_LIBRARIES) # in cache already SET(CppUnit_FOUND TRUE) ELSE(CPPUNIT_INCLUDE_DIR AND CPPUNIT_LIBRARIES) SET(CPPUNIT_INCLUDE_DIR) SET(CPPUNIT_LIBRARIES) IF(CPPUNIT_CONFIG_EXECUTABLE) EXEC_PROGRAM(${CPPUNIT_CONFIG_EXECUTABLE} ARGS --cflags RETURN_VALUE _return_VALUE OUTPUT_VARIABLE CPPUNIT_CFLAGS) EXEC_PROGRAM(${CPPUNIT_CONFIG_EXECUTABLE} ARGS --libs RETURN_VALUE _return_VALUE OUTPUT_VARIABLE CPPUNIT_LIBRARIES) EXEC_PROGRAM(${CPPUNIT_CONFIG_EXECUTABLE} ARGS --version RETURN_VALUE _return_VALUE OUTPUT_VARIABLE CPPUNIT_INSTALLED_VERSION) STRING(REGEX REPLACE "-I(.+)" "\\1" CPPUNIT_CFLAGS "${CPPUNIT_CFLAGS}") ELSE(CPPUNIT_CONFIG_EXECUTABLE) # in case win32 needs to find it the old way? FIND_PATH(CPPUNIT_CFLAGS cppunit/TestRunner.h PATHS /usr/include /usr/local/include ) FIND_LIBRARY(CPPUNIT_LIBRARIES NAMES cppunit PATHS /usr/lib /usr/local/lib ) # how can we find cppunit version? MESSAGE (STATUS "Ensure you cppunit installed version is at least ${CPPUNIT_MIN_VERSION}") SET (CPPUNIT_INSTALLED_VERSION ${CPPUNIT_MIN_VERSION}) ENDIF(CPPUNIT_CONFIG_EXECUTABLE) SET(CPPUNIT_INCLUDE_DIR ${CPPUNIT_CFLAGS} "${CPPUNIT_CFLAGS}/cppunit") ENDIF(CPPUNIT_INCLUDE_DIR AND CPPUNIT_LIBRARIES) IF(CPPUNIT_INCLUDE_DIR AND CPPUNIT_LIBRARIES) SET(CppUnit_FOUND TRUE) if(NOT CppUnit_FIND_QUIETLY) MESSAGE (STATUS "Found cppunit: ${CPPUNIT_LIBRARIES}") endif(NOT CppUnit_FIND_QUIETLY) IF(CPPUNIT_CONFIG_EXECUTABLE) EXEC_PROGRAM(${CPPUNIT_CONFIG_EXECUTABLE} ARGS --version RETURN_VALUE _return_VALUE OUTPUT_VARIABLE CPPUNIT_INSTALLED_VERSION) ENDIF(CPPUNIT_CONFIG_EXECUTABLE) macro_ensure_version( ${CPPUNIT_MIN_VERSION} ${CPPUNIT_INSTALLED_VERSION} CPPUNIT_INSTALLED_VERSION_OK ) IF(NOT CPPUNIT_INSTALLED_VERSION_OK) MESSAGE ("** CppUnit version is too old: found ${CPPUNIT_INSTALLED_VERSION} installed, ${CPPUNIT_MIN_VERSION} or major is required") SET(CppUnit_FOUND FALSE) ENDIF(NOT CPPUNIT_INSTALLED_VERSION_OK) ELSE(CPPUNIT_INCLUDE_DIR AND CPPUNIT_LIBRARIES) SET(CppUnit_FOUND FALSE CACHE BOOL "Not found cppunit library") ENDIF(CPPUNIT_INCLUDE_DIR AND CPPUNIT_LIBRARIES) MARK_AS_ADVANCED(CPPUNIT_INCLUDE_DIR CPPUNIT_LIBRARIES) podofo-0.9.3/cmake/modules/FindFONTCONFIG.cmake0000664000175000017500000000265611073313756020667 0ustar dominikdominik# - Try to find the Fontconfig # Once done this will define # # FONTCONFIG_FOUND - system has Fontconfig # FONTCONFIG_LIBRARIES - Link these to use FONTCONFIG # FONTCONFIG_DEFINITIONS - Compiler switches required for using FONTCONFIG # Copyright (c) 2006,2007 Laurent Montel, # # Redistribution and use is allowed according to the terms of the BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. FIND_PACKAGE(PkgConfig) if (FONTCONFIG_LIBRARIES AND FONTCONFIG_INCLUDE_DIR) # in cache already set(FONTCONFIG_FOUND TRUE) else (FONTCONFIG_LIBRARIES AND FONTCONFIG_INCLUDE_DIR) if (PKG_CONFIG_FOUND) # use pkg-config to get the directories and then use these values # in the FIND_PATH() and FIND_LIBRARY() calls pkg_check_modules(FONTCONFIG fontconfig) set(FONTCONFIG_DEFINITIONS ${FONTCONFIG_CFLAGS} CACHE INTERNAL "The compilation flags for fontconfig") endif (PKG_CONFIG_FOUND) find_path(FONTCONFIG_INCLUDE_DIR fontconfig/fontconfig.h PATHS ${FONTCONFIG_INCLUDE_DIRS} /usr/X11/include ) find_library(FONTCONFIG_LIBRARIES NAMES fontconfig PATHS ${FONTCONFIG_LIBRARY_DIRS} ) include(PoDoFoFindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(Fontconfig DEFAULT_MSG FONTCONFIG_LIBRARIES FONTCONFIG_INCLUDE_DIR ) mark_as_advanced(FONTCONFIG_LIBRARIES FONTCONFIG_INCLUDE_DIR) endif (FONTCONFIG_LIBRARIES AND FONTCONFIG_INCLUDE_DIR) podofo-0.9.3/cmake/modules/FindLUA.cmake0000664000175000017500000000146111126410427017635 0ustar dominikdominik# LUA_FOUND - system has Fontconfig # LUA_LIBRARIES - Link these to use LUA # LUA_DEFINITIONS - Compiler switches required for using LUA # # Based on FindFONTCONFIG.cmake Copyright (c) 2006,2007 Laurent Montel, # # Redistribution and use is allowed according to the terms of the BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # # TODO: Update this code to handle debug/release builds on win32. if (LUA_LIBRARIES AND LUA_INCLUDE_DIR) # in cache already set(LUA_FOUND TRUE) else (LUA_LIBRARIES AND LUA_INCLUDE_DIR) FIND_PACKAGE(Lua51) include(PoDoFoFindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(Lua DEFAULT_MSG LUA_LIBRARIES LUA_INCLUDE_DIR ) mark_as_advanced(LUA_LIBRARIES LUA_INCLUDE_DIR) endif (LUA_LIBRARIES AND LUA_INCLUDE_DIR) podofo-0.9.3/cmake/modules/FindOpenSSL.cmake0000664000175000017500000000506611014031047020475 0ustar dominikdominik# - Try to find the OpenSSL encryption library # Once done this will define # # OPENSSL_FOUND - system has the OpenSSL library # OPENSSL_INCLUDE_DIR - the OpenSSL include directory # OPENSSL_LIBRARIES - The libraries needed to use OpenSSL # Copyright (c) 2006, Alexander Neundorf, # Modified by Craig Ringer, 2008: # - Handle !REQUIRED # # Redistribution and use is allowed according to the terms of the BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. IF(OPENSSL_LIBRARIES) SET(OpenSSL_FIND_QUIETLY TRUE) ENDIF(OPENSSL_LIBRARIES) IF(SSL_EAY_DEBUG AND SSL_EAY_RELEASE) SET(LIB_FOUND 1) ENDIF(SSL_EAY_DEBUG AND SSL_EAY_RELEASE) FIND_PATH(OPENSSL_INCLUDE_DIR openssl/ssl.h ) IF(WIN32 AND MSVC) # /MD and /MDd are the standard values - if somone wants to use # others, the libnames have to change here too # use also ssl and ssleay32 in debug as fallback for openssl < 0.9.8b FIND_LIBRARY(SSL_EAY_DEBUG NAMES ssleay32MDd ssl ssleay32) FIND_LIBRARY(SSL_EAY_RELEASE NAMES ssleay32MD ssl ssleay32) IF(MSVC_IDE) IF(SSL_EAY_DEBUG AND SSL_EAY_RELEASE) SET(OPENSSL_LIBRARIES optimized ${SSL_EAY_RELEASE} debug ${SSL_EAY_DEBUG}) ELSE(SSL_EAY_DEBUG AND SSL_EAY_RELEASE) MESSAGE("OpenSSL: Could not find the debug and release version of openssl") MESSAGE("OpenSSL: Disabling OpenSSL") SET(OPENSSL_LIBRARIES) ENDIF(SSL_EAY_DEBUG AND SSL_EAY_RELEASE) ELSE(MSVC_IDE) STRING(TOLOWER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE_TOLOWER) IF(CMAKE_BUILD_TYPE_TOLOWER MATCHES debug) SET(OPENSSL_LIBRARIES ${SSL_EAY_DEBUG}) ELSE(CMAKE_BUILD_TYPE_TOLOWER MATCHES debug) SET(OPENSSL_LIBRARIES ${SSL_EAY_RELEASE}) ENDIF(CMAKE_BUILD_TYPE_TOLOWER MATCHES debug) ENDIF(MSVC_IDE) MARK_AS_ADVANCED(SSL_EAY_DEBUG SSL_EAY_RELEASE) ELSE(WIN32 AND MSVC) FIND_LIBRARY(OPENSSL_LIBRARIES NAMES ssl ssleay32 ssleay32MD ) ENDIF(WIN32 AND MSVC) IF(OPENSSL_INCLUDE_DIR AND OPENSSL_LIBRARIES) SET(OPENSSL_FOUND TRUE) ELSE(OPENSSL_INCLUDE_DIR AND OPENSSL_LIBRARIES) SET(OPENSSL_FOUND FALSE) ENDIF (OPENSSL_INCLUDE_DIR AND OPENSSL_LIBRARIES) IF (OPENSSL_FOUND) IF (NOT OpenSSL_FIND_QUIETLY) MESSAGE(STATUS "Found OpenSSL: ${OPENSSL_LIBRARIES}") ENDIF (NOT OpenSSL_FIND_QUIETLY) ELSE (OPENSSL_FOUND) IF (OpenSSL_FIND_REQUIRED) MESSAGE(FATAL_ERROR "Could NOT find OpenSSL") ENDIF (OpenSSL_FIND_REQUIRED) ENDIF (OPENSSL_FOUND) MARK_AS_ADVANCED(OPENSSL_INCLUDE_DIR OPENSSL_LIBRARIES) podofo-0.9.3/cmake/modules/FindTIFF.cmake0000664000175000017500000000210710714374660017754 0ustar dominikdominik# - Find TIFF library # Find the native TIFF includes and library # This module defines # TIFF_INCLUDE_DIR, where to find tiff.h, etc. # TIFF_LIBRARIES, libraries to link against to use TIFF. # TIFF_FOUND, If false, do not try to use TIFF. # also defined, but not for general use are # TIFF_LIBRARY, where to find the TIFF library. FIND_PATH(TIFF_INCLUDE_DIR tiff.h) SET(TIFF_LIBRARY_NAMES_RELEASE ${TIFF_LIBRARY_NAMES_RELEASE} ${TIFF_LIBRARY_NAMES} tiff libtiff) SET(TIFF_LIBRARY_NAMES_DEBUG ${TIFF_LIBRARY_NAMES_DEBUG} tiffd libtiffd) FIND_LIBRARY(TIFF_LIBRARY_RELEASE NAMES ${TIFF_LIBRARY_NAMES_RELEASE} ) FIND_LIBRARY(TIFF_LIBRARY_DEBUG NAMES ${TIFF_LIBRARY_NAMES_DEBUG} ) INCLUDE(LibraryDebugAndRelease) SET_LIBRARY_FROM_DEBUG_AND_RELEASE(TIFF) # handle the QUIETLY and REQUIRED arguments and set TIFF_FOUND to TRUE if # all listed variables are TRUE INCLUDE(PoDoFoFindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(TIFF DEFAULT_MSG TIFF_LIBRARY TIFF_INCLUDE_DIR) IF(TIFF_FOUND) SET( TIFF_LIBRARIES ${TIFF_LIBRARY} ) ENDIF(TIFF_FOUND) podofo-0.9.3/cmake/modules/PoDoFoFindPackageHandleStandardArgs.cmake0000664000175000017500000000524210714374660025243 0ustar dominikdominik# # This file was copied from CMake 2.5. It's used to permit CMake 2.4 # to use the CMake 2.5-derived find scripts here. # IF (NOT ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} LESS 2.5) # Use the original from cmake 2.5 if possible INCLUDE(FindPackageHandleStandardArgs) ELSE(NOT ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} LESS 2.5) # or define our own... # FIND_PACKAGE_HANDLE_STANDARD_ARGS(NAME (DEFAULT_MSG|"Custom failure message") VAR1 ... ) # This macro is intended to be used in FindXXX.cmake modules files. # It handles the REQUIRED and QUIET argument to FIND_PACKAGE() and # it also sets the _FOUND variable. # The package is found if all variables listed are TRUE. # Example: # # FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibXml2 DEFAULT_MSG LIBXML2_LIBRARIES LIBXML2_INCLUDE_DIR) # # LibXml2 is considered to be found, if both LIBXML2_LIBRARIES and # LIBXML2_INCLUDE_DIR are valid. Then also LIBXML2_FOUND is set to TRUE. # If it is not found and REQUIRED was used, it fails with FATAL_ERROR, # independent whether QUIET was used or not. # If it is found, the location is reported using the VAR1 argument, so # here a message "Found LibXml2: /usr/lib/libxml2.so" will be printed out. # If the second argument is DEFAULT_MSG, the message in the failure case will # be "Could NOT find LibXml2", if you don't like this message you can specify # your own custom failure message there. MACRO(FIND_PACKAGE_HANDLE_STANDARD_ARGS _NAME _FAIL_MSG _VAR1 ) IF("${_FAIL_MSG}" STREQUAL "DEFAULT_MSG") SET(_FAIL_MESSAGE "Could NOT find ${_NAME}") ELSE("${_FAIL_MSG}" STREQUAL "DEFAULT_MSG") SET(_FAIL_MESSAGE "${_FAIL_MSG}") ENDIF("${_FAIL_MSG}" STREQUAL "DEFAULT_MSG") STRING(TOUPPER ${_NAME} _NAME_UPPER) SET(${_NAME_UPPER}_FOUND TRUE) IF(NOT ${_VAR1}) SET(${_NAME_UPPER}_FOUND FALSE) ENDIF(NOT ${_VAR1}) FOREACH(_CURRENT_VAR ${ARGN}) IF(NOT ${_CURRENT_VAR}) SET(${_NAME_UPPER}_FOUND FALSE) ENDIF(NOT ${_CURRENT_VAR}) ENDFOREACH(_CURRENT_VAR) IF (${_NAME_UPPER}_FOUND) IF (NOT ${_NAME}_FIND_QUIETLY) MESSAGE(STATUS "Found ${_NAME}: ${${_VAR1}}") ENDIF (NOT ${_NAME}_FIND_QUIETLY) ELSE (${_NAME_UPPER}_FOUND) IF (${_NAME}_FIND_REQUIRED) MESSAGE(FATAL_ERROR "${_FAIL_MESSAGE}") ELSE (${_NAME}_FIND_REQUIRED) IF (NOT ${_NAME}_FIND_QUIETLY) MESSAGE(STATUS "${_FAIL_MESSAGE}") ENDIF (NOT ${_NAME}_FIND_QUIETLY) ENDIF (${_NAME}_FIND_REQUIRED) ENDIF (${_NAME_UPPER}_FOUND) ENDMACRO(FIND_PACKAGE_HANDLE_STANDARD_ARGS) ENDIF(NOT ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} LESS 2.5) podofo-0.9.3/cmake/modules/FindLIBSTLPORT.cmake0000664000175000017500000000074610714374660020731 0ustar dominikdominikFIND_PATH(LIBSTLPORT_INCLUDE_DIR NAMES stl/_stlport_version.h PATHS /usr/include/stlport ) FIND_LIBRARY(LIBSTLPORT_LIBRARY NAMES stlport libstlport) IF(LIBSTLPORT_INCLUDE_DIR AND LIBSTLPORT_LIBRARY) SET(LIBSTLPORT_FOUND TRUE CACHE BOOLEAN "Was libstlport found?") ELSE(LIBSTLPORT_INCLUDE_DIR AND LIBSTLPORT_LIBRARY) SET(LIBSTLPORT_FOUND FALSE CACHE BOOLEAN "Was libstlport found?") ENDIF(LIBSTLPORT_INCLUDE_DIR AND LIBSTLPORT_LIBRARY) SET(LIBJPEG_LIBRARIES ${LIBJPEG_LIBRARY}) podofo-0.9.3/cmake/modules/FindZLIB.cmake0000664000175000017500000000376110714374660017773 0ustar dominikdominik# - Find zlib # Find the native ZLIB includes and library # # ZLIB_INCLUDE_DIR - where to find zlib.h, etc. # ZLIB_LIBRARIES - List of libraries when using zlib. # ZLIB_FOUND - True if zlib found. IF (ZLIB_INCLUDE_DIR) # Already in cache, be silent SET(ZLIB_FIND_QUIETLY TRUE) ENDIF (ZLIB_INCLUDE_DIR) FIND_PATH(ZLIB_INCLUDE_DIR zlib.h) # On win32, qt statically links to zlib and libpng, and exports their symbols. # We can just link to Qt to get zlib and libpng. We still require the user to # supply their own headers on the search path, but they can and should just # specify ${QTDIR}/src/3rdparty/zlib/include . # To use this, you must use FindQt before FindZlib. IF(QT_QTCORE_LIBRARY AND USE_QT_ZLIB_PNGLIB) MESSAGE("Using zlib from qt") SET(ZLIB_LIBRARY_RELEASE ${QT_QTCORE_LIBRARY_RELEASE}) SET(ZLIB_LIBRARY_DEBUG ${QT_QTCORE_LIBRARY_DEBUG}) SET(ZLIB_LIBRARY ${QT_QTCORE_LIBRARY}) ELSE(QT_QTCORE_LIBRARY AND USE_QT_ZLIB_PNGLIB) SET(ZLIB_LIBRARY_NAMES_RELEASE ${ZLIB_LIBRARY_NAMES_RELEASE} ${ZLIB_LIBRARY_NAMES} zlib1 zlib zdll z) FIND_LIBRARY(ZLIB_LIBRARY_RELEASE NAMES ${ZLIB_LIBRARY_NAMES_RELEASE} ) # Find a debug library if one exists and use that for debug builds. # This really only does anything for win32, but does no harm on other # platforms. SET(ZLIB_LIBRARY_NAMES_DEBUG ${ZLIB_LIBRARY_NAMES_DEBUG} zlib1d zlibd zdlld) FIND_LIBRARY(ZLIB_LIBRARY_DEBUG NAMES ${ZLIB_LIBRARY_NAMES_DEBUG}) INCLUDE(LibraryDebugAndRelease) SET_LIBRARY_FROM_DEBUG_AND_RELEASE(ZLIB) ENDIF(QT_QTCORE_LIBRARY AND USE_QT_ZLIB_PNGLIB) # handle the QUIETLY and REQUIRED arguments and set ZLIB_FOUND to TRUE if # all listed variables are TRUE INCLUDE(PoDoFoFindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(ZLIB DEFAULT_MSG ZLIB_LIBRARY ZLIB_INCLUDE_DIR) IF(ZLIB_FOUND) SET( ZLIB_LIBRARIES ${ZLIB_LIBRARY} ) ELSE(ZLIB_FOUND) SET( ZLIB_LIBRARIES ) ENDIF(ZLIB_FOUND) MARK_AS_ADVANCED( ZLIB_LIBRARY ZLIB_INCLUDE_DIR ) podofo-0.9.3/CMakeLists.txt0000664000175000017500000005220212347347566015443 0ustar dominikdominikCMAKE_MINIMUM_REQUIRED(VERSION 2.6) #***************** IMPORTANT ************* IMPORTANT ********************** # Look at http://www.vtk.org/Wiki/CMake_HowToDoPlatformChecks # and the other wiki entries before you add anything. You might not need to. #**************************************************************************** # # Project name and version # PROJECT(PoDoFo) SET(PODOFO_VERSION_MAJOR "0" CACHE STRING "Major part of PoDoFo version number") SET(PODOFO_VERSION_MINOR "9" CACHE STRING "Minor part of PoDoFo version number") SET(PODOFO_VERSION_PATCH "3" CACHE STRING "Patchlevel part of PoDoFo version number") SET(PODOFO_SOVERSION "${PODOFO_VERSION_MAJOR}.${PODOFO_VERSION_MINOR}.${PODOFO_VERSION_PATCH}") SET(PODOFO_LIBVERSION "${PODOFO_SOVERSION}") # # Main includes # INCLUDE(CheckIncludeFile) INCLUDE(CheckLibraryExists) INCLUDE(UsePkgConfig) INCLUDE(TestBigEndian) INCLUDE(CheckTypeSize) # Load modules from our source tree too SET(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules") # Builds must use this CMakeLists.txt, not the one in src/ or somewhere else. # If users try to use something else the results can be confusing. We set a # variable here that we require to be set elsewhere, otherwise we'll complain. SET(PODOFO_MAIN_CMAKELISTS_READ TRUE) # If the user hasn't told use specifically what they want, build only # a static library. IF(NOT DEFINED PODOFO_BUILD_SHARED AND NOT DEFINED PODOFO_BUILD_STATIC) SET(PODOFO_BUILD_STATIC TRUE) SET(PODOFO_BUILD_SHARED FALSE) ENDIF(NOT DEFINED PODOFO_BUILD_SHARED AND NOT DEFINED PODOFO_BUILD_STATIC) IF(DEFINED PODOFO_BUILD_SHARED AND NOT DEFINED PODOFO_BUILD_STATIC) SET(PODOFO_BUILD_SHARED NOT ${PODOFO_BUILD_SHARED}) ENDIF(DEFINED PODOFO_BUILD_SHARED AND NOT DEFINED PODOFO_BUILD_STATIC) IF(NOT DEFINED PODOFO_BUILD_SHARED AND DEFINED PODOFO_BUILD_STATIC) SET(PODOFO_BUILD_SHARED NOT ${PODOFO_BUILD_STATIC}) ENDIF(NOT DEFINED PODOFO_BUILD_SHARED AND DEFINED PODOFO_BUILD_STATIC) # Some 64 bit linux distros use /usr/lib64 for 64 bit libraries. # on these platforms we must IF(NOT DEFINED WANT_LIB64) # TODO: detect 64-bit build and existance of /usr/lib64 and set to TRUE. MESSAGE("WANT_LIB64 unset; assuming normal library directory names") SET(WANT_LIB64 FALSE) ENDIF(NOT DEFINED WANT_LIB64) IF(WANT_LIB64) SET(LIBDIRNAME "lib64") ELSE(WANT_LIB64) SET(LIBDIRNAME "lib") ENDIF(WANT_LIB64) MESSAGE("Will install libraries to ${CMAKE_INSTALL_PREFIX}/${LIBDIRNAME}") # Some headers that tend to vary a bit CHECK_INCLUDE_FILE("strings.h" PODOFO_HAVE_STRINGS_H) CHECK_INCLUDE_FILE("arpa/inet.h" PODOFO_HAVE_ARPA_INET_H) CHECK_INCLUDE_FILE("winsock2.h" PODOFO_HAVE_WINSOCK2_H) CHECK_INCLUDE_FILE("mem.h" PODOFO_HAVE_MEM_H) CHECK_INCLUDE_FILE("ctype.h" PODOFO_HAVE_CTYPE_H) # Do some type size detection and provide yet another set of typedefs for fixed # font sizes. We can't use the c99 / c++0x uint32_t etc, because people use # ancient compilers that don't and will never support the standard. CHECK_INCLUDE_FILE("sys/types.h" PODOFO_HAVE_SYS_TYPES_H) CHECK_INCLUDE_FILE("stdint.h" PODOFO_HAVE_STDINT_H) # See: http://msdn.microsoft.com/en-us/library/aa384264(VS.85).aspx CHECK_INCLUDE_FILE("BaseTsd.h" PODOFO_HAVE_BASETSD_H) CHECK_TYPE_SIZE("long int" SZ_LONG) # We cache integer type detection results, and don't repeat them # (and overwrite the user's manual changes) if they've been done already. IF(NOT PDF_INT64_TYPENAME) # I hate old compilers. IF(PODOFO_HAVE_STDINT_H) SET(pdfint8 "int8_t") SET(pdfint16 "int16_t") SET(pdfint32 "int32_t") SET(pdfint64 "int64_t") SET(pdfuint8 "uint8_t") SET(pdfuint16 "uint16_t") SET(pdfuint32 "uint32_t") SET(pdfuint64 "uint64_t") CHECK_TYPE_SIZE("int64_t" SZ_INT64) ELSE(PODOFO_HAVE_STDINT_H) # No stdint.h . Try BaseTsd.h windows types. IF(PODOFO_HAVE_BASETSD_H) # We have BaseTsd.h, so use those types. SET(pdfint8 "signed char") SET(pdfint16 "short") SET(pdfint32 "INT32") SET(pdfint64 "INT64") SET(pdfuint8 "unsigned char") SET(pdfuint16 "unsigned short") SET(pdfuint32 "UINT32") SET(pdfuint64 "UINT64") CHECK_TYPE_SIZE("INT64" SZ_INT64) ELSE(PODOFO_HAVE_BASETSD_H) # No BaseTsd.h either. Assume the standard types, and go poking # for a sane 64-bit integer. # # First, though, make sure sizeof(int) = 4 and if not, scream, because # hopefully this case will never be hit and we'll never have to write # the horrible code check for CHECK_TYPE_SIZE("signed char" SZ_TINY_INT) CHECK_TYPE_SIZE("unsigned char" SZ_TINY_UINT) CHECK_TYPE_SIZE("short int" SZ_SHORT_INT) CHECK_TYPE_SIZE("int" SZ_INT) CHECK_TYPE_SIZE("unsigned short int" SZ_UINT) CHECK_TYPE_SIZE("unsigned int" SZ_SHORT_UINT) SET(smallintsok SZ_INT == 4 AND SZ_UINT == 4 AND SZ_SHORT_INT == 2 AND SZ_SHORT_UINT == 2 AND SZ_TINY_INT == 1 AND SZ_TINY_UINT == 1) IF(NOT smallintsok) MESSAGE(FATAL "sizeof(int) != 4 and/or sizeof(short) != 2 and no stdint.h or BaseTsd.h found. We don't know how to cope with this.") ENDIF(NOT smallintsok) SET(pdfint8 "signed char") SET(pdfint16 "short") SET(pdfint32 "int") SET(pdfuint8 "unsigned char") SET(pdfuint16 "unsigned short") SET(pdfuint32 "unsigned int") # Now we just have to figure out what 64-bit integer type we can use. # # Do we have VC >= 6's __uint64 and __int64? # See: http://icfun.blogspot.com/2008/04/use-of-int64-variable-in-c.html CHECK_TYPE_SIZE("__int64" SZ___INT64) CHECK_TYPE_SIZE("__uint64" SZ___UINT64) IF(SZ___INT64 == 8 AND SZ___UINT64 == 8) # MS compiler, VC6 or newer without BaseTsd.h in SDK SET(pdfint64 "__int64") SET(pdfuint64 "__uint64") CHECK_TYPE_SIZE("__int64" SZ_INT64) ELSE(SZ___INT64 AND SZ___UINT64) # Still no luck. Old unix compiler, Borland, or some other monster? # Are we lucky and sizeof(long) == 8? CHECK_TYPE_SIZE("unsigned long int" SZ_ULONG) IF(SZ_LONG == 8 AND SZ_ULONG == 8) # Must be on a LP64 platform, sizeof(long) = 8 SET(pdfint64 "long int") SET(pdfuint64 "unsigned long int") CHECK_TYPE_SIZE("long int" SZ_INT64) ELSE(SZ_LONG == 8 AND SZ_ULONG == 8) # See if the compiler implements "long long int", _int64, int64, __int64 or int64_t IF(PODOFO_HAVE_SYS_TYPES_H) SET(CMAKE_EXTRA_INCLUDE_FILES "sys/types.h") ENDIF(PODOFO_HAVE_SYS_TYPES_H) CHECK_TYPE_SIZE("long long int" SZ_LONG_LONG) CHECK_TYPE_SIZE("unsigned long long int" SZ_UNSIGNED_LONG_LONG) IF(SZ_LONG_LONG == 8 AND SZ_UNSIGNED_LONG_LONG == 8) SET(pdfint64 "long int") SET(pdfuint64 "unsigned long int") CHECK_TYPE_SIZE("long int" SZ_INT64) ELSE(SZ_LONG_LONG == 8 AND SZ_UNSIGNED_LONG_LONG == 8) CHECK_TYPE_SIZE("int64_t" SZ_INT64_T) CHECK_TYPE_SIZE("uint64_t" SZ_UINT64_T) IF(SZ_INT64_T AND SZ_UINT64_T) SET(pdfint64 "int64_t") SET(pdfuint64 "uint64_t") CHECK_TYPE_SIZE("int64_t" SZ_INT64) ELSE(SZ_INT64_T AND SZ_UINT64_T) CHECK_TYPE_SIZE("int64" SZ_INT64) CHECK_TYPE_SIZE("uint64" SZ_UINT64) IF(SZ_INT64 AND SZ_UINT64) SET(pdfint64 "int64") SET(pdfuint64 "uint64") CHECK_TYPE_SIZE("int64" SZ_INT64) ELSE(SZ_INT64 AND SZ_UINT64) CHECK_TYPE_SIZE("_int64" SZ__INT64) CHECK_TYPE_SIZE("_uint64" SZ__UINT64) IF(SZ__INT64 AND SZ__UINT64) SET(pdfint64 "_int64") SET(pdfuint64 "_uint64") CHECK_TYPE_SIZE("_int64" SZ_INT64) ELSE(SZ__INT64 AND SZ__UINT64) MESSAGE("Oh my lord, your compiler doesn't seem to support any of the int64 type flavours we tried.") MESSAGE(WARNING "You must set the PDF_INTxx_TYPENAME and PDF_UINTxx_TYPENAME variables manually") ENDIF(SZ__INT64 AND SZ__UINT64) ENDIF(SZ_INT64 AND SZ_UINT64) ENDIF(SZ_INT64_T AND SZ_UINT64_T) ENDIF(SZ_LONG_LONG == 8 AND SZ_UNSIGNED_LONG_LONG == 8) ENDIF(SZ_LONG == 8 AND SZ_ULONG == 8) ENDIF(SZ___INT64 AND SZ___UINT64) ENDIF(PODOFO_HAVE_BASETSD_H) ENDIF(PODOFO_HAVE_STDINT_H) SET(CMAKE_EXTRA_INCLUDE_FILES) ENDIF(NOT PDF_INT64_TYPENAME) IF(NOT PDF_INT64_TYPENAME AND pdfint64) SET(PDF_INT64_TYPENAME "${pdfint64}" CACHE STRING "Name of detected 64-bit signed integer type to use") SET(PDF_INT32_TYPENAME "${pdfint32}" CACHE STRING "Name of detected 32-bit signed integer type to use") SET(PDF_INT16_TYPENAME "${pdfint16}" CACHE STRING "Name of detected 16-bit signed integer type to use") SET(PDF_INT8_TYPENAME "${pdfint8}" CACHE STRING "Name of detected 8-bit signed integer type to use") SET(PDF_UINT64_TYPENAME "${pdfuint64}" CACHE STRING "Name of detected 64-bit unsigned integer type to use") SET(PDF_UINT32_TYPENAME "${pdfuint32}" CACHE STRING "Name of detected 32-bit unsigned integer type to use") SET(PDF_UINT16_TYPENAME "${pdfuint16}" CACHE STRING "Name of detected 16-bit unsigned integer type to use") SET(PDF_UINT8_TYPENAME "${pdfuint8}" CACHE STRING "Name of detected 8-bit unsigned integer type to use") ENDIF(NOT PDF_INT64_TYPENAME AND pdfint64) # Linux packagers want an uninstall target. CONFIGURE_FILE( "${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" IMMEDIATE @ONLY) ADD_CUSTOM_TARGET(uninstall "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake") # Check if we are big endian TEST_BIG_ENDIAN(TEST_BIG) IF(WIN32) # On win32 we support EITHER shared OR static builds. # If both are enabled (default), turn off generation of the # static library. IF(PODOFO_BUILD_SHARED AND PODOFO_BUILD_STATIC) MESSAGE("Both PODOFO_BUILD_SHARED and PODOFO_BUILD_STATIC set") MESSAGE(" so disabling shared library generation (win32)") SET(PODOFO_BUILD_SHARED FALSE) SET(PODOFO_BUILD_STATIC TRUE) ENDIF(PODOFO_BUILD_SHARED AND PODOFO_BUILD_STATIC) # We must explicitly link to the core win32 libraries, and we need winsock2 # to get some byte-order conversion routines too. SET(PLATFORM_SYSTEM_LIBRARIES kernel32 user32 gdi32 winspool comdlg32 advapi32 shell32 ole32 oleaut32 uuid WS2_32) # Microsoft deprecate certain POSIX functions that we use. # for now, turn off these warnings. ADD_DEFINITIONS(-D_CRT_SECURE_NO_DEPRECATE) # We need a fake unistd.h for some libraries to build. They try to include # which is not available under win32 with MSVC++, but everything in unistd.h is defined, # so an empty file solves the issue. SET(EXTRA_INCLUDES ${PoDoFo_SOURCE_DIR}/vcincludes) ELSE(WIN32) SET(PLATFORM_SYSTEM_LIBRARIES) SET(EXTRA_INCLUDES) ENDIF(WIN32) IF(UNIX AND NOT PODOFO_NO_FONTMANAGER) SET(WANT_FONTCONFIG TRUE CACHE INTERNAL "True if PoDoFo should be built with fontconfig support") ELSE(UNIX AND NOT PODOFO_NO_FONTMANAGER) SET(WANT_FONTCONFIG FALSE CACHE INTERNAL "True if PoDoFo should be built with fontconfig support") ENDIF(UNIX AND NOT PODOFO_NO_FONTMANAGER) IF(CMAKE_COMPILER_IS_GNUCXX) MESSAGE("Using gcc specific compiler options") # We can be more specific about what we want out of g++ # than with most other compilers. # Attempt to detect the gcc version. You must not rely on # this; use the detected version as a guide only. EXEC_PROGRAM(gcc ARGS --version OUTPUT_VARIABLE GCC_VERSION) IF(GCC_VERSION MATCHES ".*\\(GCC\\) 4\\.[0-9].*") MESSAGE("Have gcc 4.x") SET(PODOFO_HAVE_GCC4 1) ELSE(GCC_VERSION MATCHES ".*\\(GCC\\) 4\\.[0-9].*") SET(PODOFO_HAVE_GCC4 0) ENDIF(GCC_VERSION MATCHES ".*\\(GCC\\) 4\\.[0-9].*") # If the user hasn't specifically said whether they want # -fvisibility=hidden or not, turn it on for gcc4 and off # for other gcc versions. IF(NOT DEFINED PODOFO_USE_VISIBILITY) SET(PODOFO_USE_VISIBILITY ${PODOFO_HAVE_GCC4}) ENDIF(NOT DEFINED PODOFO_USE_VISIBILITY) # We can't request C++98 compliance on win32, because mingw # will hide _tzset() and _timezone, which we need for PdfDate. # At least until that code is replaced with something better, # just don't enable it on win32. IF(NOT WIN32) ADD_DEFINITIONS(-std=c++98) ENDIF(NOT WIN32) ADD_DEFINITIONS( -Wall -Woverloaded-virtual -Wswitch-enum -Wcast-qual -Wwrite-strings -Wredundant-decls -Wreorder #-Wold-style-cast ) # # Note that we do not need debug definitions here. Set # -DCMAKE_BUILD_TYPE=debug or (if you want an optimised # release build with debug info) -DCMAKE_CXX_FLAGS="-g3" # # We add -W unless we're using gcc on win32, where it produces # spurious warnings about dllimport of inlines because of a dllimport # declaration on the whole class. IF(NOT WIN32) ADD_DEFINITIONS(-W) ENDIF(NOT WIN32) # If they've enabled the use of gcc4 symbol visibility, use it. IF(PODOFO_USE_VISIBILITY) ADD_DEFINITIONS( -DPODOFO_HAVE_GCC_SYMBOL_VISIBILITY -fvisibility=hidden ) ENDIF(PODOFO_USE_VISIBILITY) ENDIF(CMAKE_COMPILER_IS_GNUCXX) FIND_PACKAGE(ZLIB REQUIRED) MESSAGE("Found zlib headers in ${ZLIB_INCLUDE_DIR}, library at ${ZLIB_LIBRARIES}") FIND_PACKAGE(LIBCRYPTO) IF(LIBCRYPTO_FOUND) SET(PODOFO_HAVE_OPENSSL TRUE) MESSAGE("Found OpenSSL's libCrypto headers in ${LIBCRYPTO_INCLUDE_DIR}, library at ${LIBCRYPTO_LIBRARIES}") ELSE(LIBCRYPTO_FOUND) MESSAGE("OpenSSL's libCrypto not found. Encryption support will be disabled") ENDIF(LIBCRYPTO_FOUND) FIND_PACKAGE(LIBIDN) IF(LIBIDN_FOUND) MESSAGE("Found libidn headers in ${LIBIDN_INCLUDE_DIR}, library at ${LIBIDN_LIBRARIES}") ENDIF(LIBIDN_FOUND) IF(LIBIDN_FOUND) SET(PODOFO_HAVE_LIBIDN TRUE) INCLUDE_DIRECTORIES(${LIBIDN_INCLUDE_DIR}) MESSAGE("Libidn found. AES-256 Encryption support will be enabled") ELSE(LIBIDN_FOUND) MESSAGE("Libidn not found. AES-256 Encryption support will be disabled") ENDIF(LIBIDN_FOUND) FIND_PACKAGE(LIBJPEG) IF(LIBJPEG_FOUND) MESSAGE("Found libjpeg headers in ${LIBJPEG_INCLUDE_DIR}, library at ${LIBJPEG_LIBRARIES}") SET(PODOFO_HAVE_JPEG_LIB TRUE) INCLUDE_DIRECTORIES(${LIBJPEG_INCLUDE_DIR}) ELSE(LIBJPEG_FOUND) MESSAGE("Libjpeg not found. JPEG support will be disabled") ENDIF(LIBJPEG_FOUND) FIND_PACKAGE(TIFF) IF(TIFF_FOUND) MESSAGE("Found libtiff headers in ${TIFF_INCLUDE_DIR}, library at ${TIFF_LIBRARIES}") SET(PODOFO_HAVE_TIFF_LIB TRUE) INCLUDE_DIRECTORIES(${TIFF_INCLUDE_DIR}) ELSE(TIFF_FOUND) MESSAGE("Libtiff not found. TIFF support will be disabled") ENDIF(TIFF_FOUND) FIND_PACKAGE(PNG) IF(PNG_FOUND) MESSAGE("Found LibPng headers in ${PNG_INCLUDE_DIR}, library at ${PNG_LIBRARIES}") SET(PODOFO_HAVE_PNG_LIB TRUE) INCLUDE_DIRECTORIES(${PNG_INCLUDE_DIR}) ELSE(PNG_FOUND) MESSAGE("LibPng not found. PNG support will be disabled") ENDIF(PNG_FOUND) IF(NOT PODOFO_BUILD_LIB_ONLY) FIND_PACKAGE(CppUnit) IF(CppUnit_FOUND) MESSAGE("Found cppunit. Unit tests will be built.") SET(PODOFO_HAVE_CPPUNIT CppUnit_FOUND) INCLUDE_DIRECTORIES(${CPPUNIT_INCLUDE_DIR}) ELSE(CppUnit_FOUND) MESSAGE("Cppunit not found. No unit tests will be built.") ENDIF(CppUnit_FOUND) ENDIF(NOT PODOFO_BUILD_LIB_ONLY) FIND_PACKAGE(OpenSSL) FIND_PACKAGE(FREETYPE REQUIRED) MESSAGE("Found freetype library at ${FREETYPE_LIBRARIES}, headers ${FREETYPE_INCLUDE_DIR}") FIND_PACKAGE(LIBSTLPORT) SET(stlport_libraries_if_use_stlport) IF(USE_STLPORT) IF(LIBSTLPORT_FOUND) MESSAGE("Using STLPort") INCLUDE_DIRECTORIES(${LIBSTLPORT_HEADERS}) LINK_DIRECTORIES(${LIBSTLPORT_LIB}) SET(stlport_libraries_if_use_stlport stlport) # Use the threaded STLPort ADD_DEFINITIONS(-D_PTHREADS) ELSE(LIBSTLPORT_FOUND) MESSAGE(FATAL_ERROR "STLPort use requested, but STLPort not found.") ENDIF(LIBSTLPORT_FOUND) ENDIF(USE_STLPORT) IF(WANT_FONTCONFIG) FIND_PACKAGE(FONTCONFIG REQUIRED) SET(PODOFO_HAVE_FONTCONFIG TRUE) SET(PODOFO_LIB_FONTCONFIG:STRING fontconfig) IF(FONTCONFIG_FOUND) MESSAGE("Found fontconfig headers in ${FONTCONFIG_INCLUDE_DIR}, library at ${FONTCONFIG_LIBRARIES}") ELSE(FONTCONFIG_FOUND) MESSAGE("Could not find fontconfig.") ENDIF(FONTCONFIG_FOUND) ELSE(WANT_FONTCONFIG) # Might as well look for it anyway. This also sets the appropriate # variables to empty values. FIND_PACKAGE(FONTCONFIG) SET(PODOFO_LIB_FONTCONFIG:STRING) ENDIF(WANT_FONTCONFIG) # libjpeg has routines that take a FILE*. This is safe if and only # if the C runtime podofo is built against is the same as the C runtime # libjpeg is built against. That is not always the case. # # If the user has explicitly told us that libjpeg's libc is binary compatible, # don't worry about using workarounds. Otherwise, on Windows we assume it's not # compatible and on other platforms we'll assume it is. This change currently # only affects PdfImage.cpp. # IF(DEFINED JPEG_RUNTIME_COMPATIBLE) IF(JPEG_RUNTIME_COMPATIBLE) # Trust the user to know what they're doing and pass a FILE* SET(PODOFO_JPEG_RUNTIME_COMPATIBLE TRUE) ENDIF(JPEG_RUNTIME_COMPATIBLE) ELSE(DEFINED JPEG_RUNTIME_COMPATIBLE) IF(NOT WIN32) # It's a sensible platform and the user hasn't told us # otherwise - pass a FILE* . SET(PODOFO_JPEG_RUNTIME_COMPATIBLE TRUE) ENDIF(NOT WIN32) ENDIF(DEFINED JPEG_RUNTIME_COMPATIBLE) IF(NOT PODOFO_BUILD_LIB_ONLY) FIND_PACKAGE(LUA) IF(LUA_FOUND) # If we have lua, we can build podofoimpose. MESSAGE("Lua found - PoDoFoImpose and PoDoFoColor will be built with Lua support") MESSAGE(" * Lua include directory: ${LUA_INCLUDE_DIR}") MESSAGE(" * Lua libraries: ${LUA_LIBRARIES}") INCLUDE_DIRECTORIES(${LUA_INCLUDE_DIR}) SET(PODOFO_HAVE_LUA TRUE) ELSE(LUA_FOUND) MESSAGE("Lua not found - PoDoFoImpose and PoDoFoColor will be built without Lua support") ENDIF(LUA_FOUND) ENDIF(NOT PODOFO_BUILD_LIB_ONLY) # Check if we should build a multithreaded version of PoDoFo IF(DEFINED PODOFO_NO_MULTITHREAD) MESSAGE("Building non multithreaded version of PoDoFo.") SET(PODOFO_MULTI_THREAD FALSE) ELSE(DEFINED PODOFO_NO_MULTITHREAD) MESSAGE("Building multithreaded version of PoDoFo.") SET(PODOFO_MULTI_THREAD TRUE) FIND_PACKAGE(Threads) SET(PLATFORM_SYSTEM_LIBRARIES ${CMAKE_THREAD_LIBS_INIT} ${PLATFORM_SYSTEM_LIBRARIES}) ENDIF(DEFINED PODOFO_NO_MULTITHREAD) IF(WANT_BOOST) MESSAGE("Looking optional for Boost.") MESSAGE("Boost is optional, so don't worry if it is not found.") MESSAGE("Set the BOOST_ROOT env var if you have problems.") FIND_PACKAGE(Boost) IF(BOOST_FOUND) SET(PODOFO_HAVE_BOOST TRUE) INCLUDE_DIRECTORIES(${BOOST_INCLUDE_DIR}) ELSE(BOOST_FOUND) MESSAGE("If you don't need graph support you can ignore the above error.") ENDIF(BOOST_FOUND) ENDIF(WANT_BOOST) INCLUDE_DIRECTORIES( ${PoDoFo_BINARY_DIR} ${PoDoFo_SOURCE_DIR} ${PoDoFo_SOURCE_DIR}/src ${FREETYPE_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR} ${EXTRA_INCLUDES} ) LINK_DIRECTORIES( ${PoDoFo_BINARY_DIR}/src/ ) # # The PoDoFo library needs to be linked to these libraries, # as do any apps or libraries linking to PoDoFo. PODOFO_LIB # will include these and the correct podofo target, so clients # should specify only PODOFO_LIB . # SET(PODOFO_LIB_DEPENDS ${ZLIB_LIBRARIES} ${LIBIDN_LIBRARIES} ${LIBCRYPTO_LIBRARIES} ${LIBJPEG_LIBRARIES} ${PLATFORM_SYSTEM_LIBRARIES} ${stlport_libraries_if_use_stlport} ${FREETYPE_LIBRARIES} ${PNG_LIBRARIES} ${TIFF_LIBRARIES} ) IF(FONTCONFIG_FOUND AND WANT_FONTCONFIG) SET(PODOFO_LIB_DEPENDS ${FONTCONFIG_LIBRARIES} ${PODOFO_LIB_DEPENDS}) INCLUDE_DIRECTORIES(${FONTCONFIG_INCLUDE_DIR}) ENDIF(FONTCONFIG_FOUND AND WANT_FONTCONFIG) SET(PODOFO_LIB podofo ${PODOFO_LIB_DEPENDS} ) # # Setup directories we will need # SET(MANDIR "share/man/") # Create the config file. It'll be appended to as the subdirs run though # then dependency information will be written to it at the end of the # build. FILE(WRITE "${PoDoFo_BINARY_DIR}/PoDoFoConfig.cmake" "# CMake module for PoDoFo\n" ) FILE(APPEND "${PoDoFo_BINARY_DIR}/PoDoFoConfig.cmake" "SET(PODOFO_INCLUDES ${PoDoFo_SOURCE_DIR}/src)\n" ) ADD_SUBDIRECTORY(src) IF(NOT PODOFO_BUILD_LIB_ONLY) ADD_SUBDIRECTORY(test) ADD_SUBDIRECTORY(tools) ADD_SUBDIRECTORY(examples) ADD_SUBDIRECTORY(debian) ENDIF(NOT PODOFO_BUILD_LIB_ONLY) # Generate our configure file CONFIGURE_FILE(${PoDoFo_SOURCE_DIR}/podofo_config.h.in ${PoDoFo_BINARY_DIR}/podofo_config.h) # Export some variables into the config file so it's easier for others # to build and link against PoDoFo # To use these dependencies set PODOFO_DIR to the podofo BUILD directory in # your build (eg -DPODOFO_DIR=/path/to/podofo when running cmake to configure # the app that'll use podofo). See: FIND_PACKAGE(...) in the cmake docs. EXPORT_LIBRARY_DEPENDENCIES( "${CMAKE_CURRENT_BINARY_DIR}/PoDoFoConfig.cmake" APPEND) podofo-0.9.3/src/0000775000175000017500000000000012356565167013470 5ustar dominikdominikpodofo-0.9.3/src/doc/0000775000175000017500000000000012356565166014234 5ustar dominikdominikpodofo-0.9.3/src/doc/PdfElement.h0000664000175000017500000001741312344436402016421 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2006 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_ELEMENT_H_ #define _PDF_ELEMENT_H_ #include "podofo/base/PdfDefines.h" #include "podofo/base/PdfObject.h" namespace PoDoFo { class PdfStreamedDocument; class PdfVecObjects; /** PdfElement is a common base class for all elements * in a PDF file. For example pages, action and annotations. * * Every PDF element has one PdfObject and provides an easier * interface to modify the contents of the dictionary. * * A PdfElement base class can be created from an existing PdfObject * or created from scratch. In the later case, the PdfElement creates * a PdfObject and adds it to a vector of objects. * * A PdfElement cannot be created directly. Use one * of the subclasses which implement real functionallity. * * \see PdfPage \see PdfAction \see PdfAnnotation */ class PODOFO_DOC_API PdfElement { public: virtual ~PdfElement(); /** Get access to the internal object * \returns the internal PdfObject */ inline PdfObject* GetObject(); /** Get access to the internal object * This is an overloaded member function. * * \returns the internal PdfObject */ inline const PdfObject* GetObject() const; protected: /** Creates a new PdfElement * \param pszType type entry of the elements object * \param pParent parent vector of objects. * Add a newly created object to this vector. */ PdfElement( const char* pszType, PdfVecObjects* pParent ); /** Creates a new PdfElement * \param pszType type entry of the elements object * \param pParent parent PdfDocument. * Add a newly created object to this vector. */ PdfElement( const char* pszType, PdfDocument* pParent ); /** Create a PdfElement from an existing PdfObject * The object must be a dictionary. * * \param pszType type entry of the elements object. * Throws an exception if the type in the * PdfObject differs from pszType. * \param pObject pointer to the PdfObject that is modified * by this PdfElement */ PdfElement( const char* pszType, PdfObject* pObject ); /** Create a PdfElement from an existing PdfObject * The object might be of any data type, * PdfElement will throw an exception if the PdfObject * if not of the same datatype as the expected one. * This is necessary in rare cases. E.g. in PdfContents. * * \param eExpectedDataType the expected datatype of this object * \param pObject pointer to the PdfObject that is modified * by this PdfElement */ PdfElement( EPdfDataType eExpectedDataType, PdfObject* pObject ); /** Convert an enum or index to its string representation * which can be written to the PDF file. * * This is a helper function for various PdfElement * subclasses that need strings and enums for their * SubTypes keys. * * \param i the index or enum value * \param ppTypes an array of strings containing * the string mapping of the index * \param lLen the length of the string array * * \returns the string representation or NULL for * values out of range */ const char* TypeNameForIndex( int i, const char** ppTypes, long lLen ) const; /** Convert a string type to an array index or enum. * * This is a helper function for various PdfElement * subclasses that need strings and enums for their * SubTypes keys. * * \param pszType the type as string * \param ppTypes an array of strings containing * the string mapping of the index * \param lLen the length of the string array * \param nUnknownValue the value that is returned when the type is unknown * * \returns the index of the string in the array */ int TypeNameToIndex( const char* pszType, const char** ppTypes, long lLen, int nUnknownValue ) const; /** Create a PdfObject in the parent of this PdfElement which * might either be a PdfStreamedDocument, a PdfDocument or * a PdfVecObjects * * Use this function in an own subclass of PdfElement to create new * PdfObjects. * * \param pszType an optional /Type key of the created object * * \returns a PdfObject which is owned by the parent */ PdfObject* CreateObject( const char* pszType = NULL ); /** Get access to the internal object. * Use this method if you need access to the internal * object in a const-method without having to do a const cast. * * \returns the internal PdfObject */ inline PdfObject* GetNonConstObject() const; private: PdfObject* m_pObject; }; // ----------------------------------------------------- // // ----------------------------------------------------- inline PdfObject* PdfElement::GetObject() { return m_pObject; } // ----------------------------------------------------- // // ----------------------------------------------------- inline const PdfObject* PdfElement::GetObject() const { return m_pObject; } // ----------------------------------------------------- // // ----------------------------------------------------- inline PdfObject* PdfElement::GetNonConstObject() const { return const_cast(this)->m_pObject; } }; #endif // PDF_ELEMENT_H_ podofo-0.9.3/src/doc/PdfAcroForm.h0000664000175000017500000001174012262234754016542 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2007 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_ACRO_FORM_H_ #define _PDF_ACRO_FORM_H_ #include "podofo/base/PdfDefines.h" #include "PdfElement.h" namespace PoDoFo { class PdfDocument; enum EPdfAcroFormDefaulAppearance { ePdfAcroFormDefaultAppearance_None, ///< Do not add a default appearrance ePdfAcroFormDefaultAppearance_BlackText12pt ///< Add a default appearance with Arial embedded and black text 12pt if no other DA key is present }; class PODOFO_DOC_API PdfAcroForm : public PdfElement { public: /** Create a new PdfAcroForm dictionary object * \param pDoc parent of this action * \param eDefaultAppearance specifies if a default appearance should be added */ PdfAcroForm( PdfDocument* pDoc, EPdfAcroFormDefaulAppearance eDefaultAppearance = ePdfAcroFormDefaultAppearance_BlackText12pt ); /** Create a PdfAcroForm dictionary object from an existing PdfObject * \param pDoc parent document * \param pObject the object to create from * \param eDefaultAppearance specifies if a default appearance should be added */ PdfAcroForm( PdfDocument* pDoc, PdfObject* pObject, EPdfAcroFormDefaulAppearance eDefaultAppearance = ePdfAcroFormDefaultAppearance_BlackText12pt ); virtual ~PdfAcroForm() { } /** Get the document that is associated with this * acro forms dictionary. * * \returns a valid pointer to the parent document */ inline PdfDocument* GetDocument(); /** Set the value of the NeedAppearances key in the interactive forms * dictionary. * * \param bNeedAppearances A flag specifying whether to construct appearance streams * and appearance dictionaries for all widget annotations in * the document. Default value is false. */ void SetNeedAppearances( bool bNeedAppearances ); /** Retrieve the value of the NeedAppearances key in the interactive forms * dictionary. * * \returns value of the NeedAppearances key * * \see SetNeedAppearances */ bool GetNeedAppearances() const; private: /** Initialize this object * with a default appearance * \param eDefaultAppearance specifies if a default appearance should be added */ void Init( EPdfAcroFormDefaulAppearance eDefaultAppearance ); private: PdfDocument* m_pDocument; }; // ----------------------------------------------------- // // ----------------------------------------------------- PdfDocument* PdfAcroForm::GetDocument() { return m_pDocument; } }; #endif // _PDF_ACRO_FORM_H_ podofo-0.9.3/src/doc/PdfCMapEncoding.h0000664000175000017500000000754412344436402017323 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2011 by Dominik Seichter * * domseichter@web.de * * * * Pdf CMAP encoding by kalyan * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_CMAP_ENCODING_H #define _PDF_CMAP_ENCODING_H #include "podofo/base/PdfDefines.h" #include "podofo/base/PdfEncoding.h" #include "PdfElement.h" namespace PoDoFo { class PODOFO_DOC_API PdfCMapEncoding: public PdfEncoding, private PdfElement{ public: enum EBaseEncoding { eBaseEncoding_Font, ///< Use The fonts encoding as base eBaseEncoding_WinAnsi, ///< Use WinAnsiEncoding as base encoding eBaseEncoding_MacRoman, ///< Use MacRomanEncoding as base encoding eBaseEncoding_MacExpert ///< Use MacExpertEncoding as base encoding }; PdfCMapEncoding(PdfObject* pObject, PdfObject* pToUnicode = NULL); virtual PdfString ConvertToUnicode(const PdfString& rEncodedString, const PdfFont* pFont) const; virtual void AddToDictionary(PdfDictionary & rDictionary ) const; virtual PdfRefCountedBuffer ConvertToEncoding(const PdfString& rString, const PdfFont* pFont) const; virtual bool IsAutoDelete() const; virtual bool IsSingleByteEncoding() const; virtual pdf_utf16be GetCharCode(int nIndex) const; virtual const PdfName & GetID() const; const PdfEncoding* GetBaseEncoding() const; private: pdf_utf16be *cMapEncoding; EBaseEncoding m_baseEncoding; }; }; /*PoDoFo namespace end*/ #endif // _PDF_CMAP_ENCODING_H podofo-0.9.3/src/doc/PdfFontTrueType.h0000664000175000017500000001051412344436402017433 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2007 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_FONT_TRUE_TYPE_H_ #define _PDF_FONT_TRUE_TYPE_H_ #include "podofo/base/PdfDefines.h" #include "PdfFontSimple.h" namespace PoDoFo { /** A PdfFont implementation that can be used * to embedd truetype fonts into a PDF file * or to draw with truetype fonts. * * TrueType fonts are always embedded as suggested in the PDF reference. */ class PdfFontTrueType : public PdfFontSimple { public: /** Create a new TrueType font. * * It will get embedded automatically. * * \param pMetrics pointer to a font metrics object. The font in the PDF * file will match this fontmetrics object. The metrics object is * deleted along with the font. * \param pEncoding the encoding of this font. The font will take ownership of this object * depending on pEncoding->IsAutoDelete() * \param pParent parent of the font object * \param bEmbed if true the font will get embedded. * */ PdfFontTrueType( PdfFontMetrics* pMetrics, const PdfEncoding* const pEncoding, PdfVecObjects* pParent, bool bEmbed ); /** Create a PdfFont based on an existing PdfObject * \param pMetrics pointer to a font metrics object. The font in the PDF * file will match this fontmetrics object. The metrics object is * deleted along with the font. * \param pEncoding the encoding of this font. The font will take ownership of this object * depending on pEncoding->IsAutoDelete() * \param pObject an existing PdfObject */ PdfFontTrueType( PdfFontMetrics* pMetrics, const PdfEncoding* const pEncoding, PdfObject* pObject ); private: /** Embed the font file directly into the PDF file. * * \param pDescriptor font descriptor object */ void EmbedFontFile( PdfObject* pDescriptor ); }; }; #endif // _PDF_FONT_TRUE_TYPE_H_ podofo-0.9.3/src/doc/PdfFontCache.cpp0000664000175000017500000010050712347316204017212 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2007 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfFontCache.h" #include "base/PdfDefinesPrivate.h" #include "base/PdfDictionary.h" #include "base/PdfInputDevice.h" #include "base/PdfOutputDevice.h" #include "PdfDifferenceEncoding.h" #include "PdfFont.h" #include "PdfFontFactory.h" #include "PdfFontMetricsFreetype.h" #include "PdfFontMetricsBase14.h" #include "PdfFontTTFSubset.h" #include "PdfFontType1.h" #include #ifdef _WIN32 //#include // Undefined stuff which windows does // define that breaks are build // e.g. GetObject is defined to either GetObjectA or GetObjectW #ifdef GetObject #undef GetObject #endif // GetObject #ifdef CreateFont #undef CreateFont #endif // CreateFont #endif // _WIN32 #include #include FT_FREETYPE_H #if defined(PODOFO_HAVE_FONTCONFIG) #include #include "base/util/PdfMutexWrapper.h" #endif using namespace std; //us: I know the endian functions are redundant, but they are not availabe in a .h file, right? // Ohh, C++ should have these as intrinsic operators, since processors just need one SWAP directive. #ifdef PODOFO_IS_LITTLE_ENDIAN inline unsigned long FromBigEndian(unsigned long i) { return ((i << 24) & 0xFF000000) | ((i << 8) & 0x00FF0000) | ((i >> 8) & 0x0000FF00) | ((i >> 24) & 0x000000FF); } inline unsigned short ShortFromBigEndian(unsigned short i) { return ((i << 8) & 0xFF00) | ((i >> 8) & 0x00FF); } #else inline unsigned long FromBigEndian(unsigned long i) { return i; } inline unsigned short ShortFromBigEndian(unsigned short i) { return i; } #endif namespace PoDoFo { #if defined(_WIN32) && !defined(PODOFO_NO_FONTMANAGER) // The function receives a buffer containing a true type collection and replaces the buffer // by a new buffer with the extracted font. // On error the function returns false. static bool GetFontFromCollection(char *&buffer, unsigned int &bufferLen, unsigned int bufferOffset, const LOGFONTW* inFont) { bool ok = false; // these properties are extracted to match the font wchar_t fontFamily[1024]; wchar_t fontStyle[1024]; wchar_t fontFullName[1024]; wchar_t fontPostscriptName[1024]; fontFamily[0] = 0; fontStyle[0] = 0; fontFullName[0] = 0; fontPostscriptName[0] = 0; unsigned int fontFileSize = 12; //us: see "http://www.microsoft.com/typography/otspec/otff.htm" USHORT numTables = ShortFromBigEndian(*(USHORT *)(buffer + bufferOffset + 4)); char *entry = buffer + bufferOffset + 12; for(int i=0; i bufferLen) return false; // truncated or corrupted buffer if(strcmp(tag, "name") == 0) { //us: see "http://www.microsoft.com/typography/otspec/name.htm" char *nameTable = buffer + offset; USHORT format = ShortFromBigEndian(*(USHORT *)(nameTable)); USHORT nameCount = ShortFromBigEndian(*(USHORT *)(nameTable+2)); USHORT stringOffset = ShortFromBigEndian(*(USHORT *)(nameTable+4)); char *stringArea = nameTable + stringOffset; char *nameRecord = nameTable + 6; for(int n=0; n= sizeof(name)) length = sizeof(name) - sizeof(wchar_t); unsigned int charCount = length / sizeof(wchar_t); for(unsigned int i=0; ilfFaceName) == 0; //..TODO.. check additional styles (check fontStyle, fontFullName, fontPostscriptName) ? // extract font if(isMatchingFont) { char *newBuffer = (char *) malloc(fontFileSize); // copy font header and table index (offsets need to be still adjusted) memcpy(newBuffer, buffer + bufferOffset, 12+16*numTables); unsigned int dstDataOffset = 12+16*numTables; // process tables char *srcEntry = buffer + bufferOffset + 12; char *dstEntry = newBuffer + 12; for(int table=0; table < numTables; table++) { // read source entry ULONG offset = FromBigEndian(*(ULONG *)(srcEntry+8)); ULONG length = FromBigEndian(*(ULONG *)(srcEntry+12)); length = (length+3) & ~3; // adjust offset // U can use FromBigEndian() also to convert _to_ big endian *(ULONG *)(dstEntry+8) = FromBigEndian(dstDataOffset); //copy data memcpy(newBuffer + dstDataOffset, buffer + offset, length); dstDataOffset += length; // adjust table entry pointers for loop srcEntry += 16; dstEntry += 16; } // replace old buffer //assert(dstDataOffset==fontFileSize) free(buffer); buffer = newBuffer; bufferLen = fontFileSize; ok = true; } return ok; } static bool GetDataFromHFONT( HFONT hf, char** outFontBuffer, unsigned int& outFontBufferLen, const LOGFONTW* inFont ) { HDC hdc = GetDC(0); if ( hdc == NULL ) return false; HGDIOBJ oldFont = SelectObject(hdc, hf); // Petr Petrov (22 December 2009) bool ok = false; // try get data from true type collection char *buffer = NULL; unsigned int bufferLen = 0; bool hasData = false; const DWORD ttcf_const = 0x66637474; DWORD dwTable = ttcf_const; bufferLen = GetFontData(hdc, dwTable, 0, 0, 0); if (bufferLen == GDI_ERROR) { dwTable = 0; bufferLen = GetFontData(hdc, dwTable, 0, 0, 0); } if (bufferLen != GDI_ERROR) { buffer = (char *) malloc( bufferLen ); hasData = GetFontData( hdc, dwTable, 0, buffer, (DWORD) bufferLen ) != GDI_ERROR; } if(hasData) { if(((DWORD *)buffer)[0] == ttcf_const) { // true type collection data unsigned int numFonts = FromBigEndian(((unsigned int *)buffer)[2]); for(unsigned int i=0; iEmptyCache(); if( m_ftLibrary ) { FT_Done_FreeType( m_ftLibrary ); m_ftLibrary = NULL; } } void PdfFontCache::Init(void) { m_sSubsetBasename[0] = 0; char *p = m_sSubsetBasename; int ii; for (ii = 0; ii < SUBSET_BASENAME_LEN; ii++, p++) { *p = 'A'; } p[0] = '+'; p[1] = 0; m_sSubsetBasename[0]--; // Initialize all the fonts stuff if( FT_Init_FreeType( &m_ftLibrary ) ) { PODOFO_RAISE_ERROR( ePdfError_FreeType ); } } void PdfFontCache::EmptyCache() { TISortedFontList itFont = m_vecFonts.begin(); while( itFont != m_vecFonts.end() ) { delete (*itFont).m_pFont; ++itFont; } itFont = m_vecFontSubsets.begin(); while( itFont != m_vecFontSubsets.end() ) { delete (*itFont).m_pFont; ++itFont; } m_vecFonts.clear(); m_vecFontSubsets.clear(); } PdfFont* PdfFontCache::GetFont( PdfObject* pObject ) { TCISortedFontList it = m_vecFonts.begin(); const PdfReference & ref = pObject->Reference(); // Search if the object is a cached normal font while( it != m_vecFonts.end() ) { if( (*it).m_pFont->GetObject()->Reference() == ref ) return (*it).m_pFont; ++it; } // Search if the object is a cached font subset it = m_vecFontSubsets.begin(); while( it != m_vecFontSubsets.end() ) { if( (*it).m_pFont->GetObject()->Reference() == ref ) return (*it).m_pFont; ++it; } // Create a new font PdfFont* pFont = PdfFontFactory::CreateFont( &m_ftLibrary, pObject ); if( pFont ) { TFontCacheElement element; element.m_pFont = pFont; element.m_bBold = pFont->IsBold(); element.m_bItalic = pFont->IsItalic(); element.m_sFontName = pFont->GetFontMetrics()->GetFontname(); element.m_pEncoding = NULL; element.m_bIsSymbolCharset = pFont->GetFontMetrics()->IsSymbol(); m_vecFonts .push_back( element ); // Now sort the font list std::sort( m_vecFonts.begin(), m_vecFonts.end() ); } return pFont; } PdfFont* PdfFontCache::GetFont( const char* pszFontName, bool bBold, bool bItalic, bool bSymbolCharset, bool bEmbedd, EFontCreationFlags eFontCreationFlags, const PdfEncoding * const pEncoding, const char* pszFileName) { PODOFO_ASSERT( pEncoding ); PdfFont* pFont = NULL; PdfFontMetrics* pMetrics = NULL; std::pair it; it = std::equal_range( m_vecFonts.begin(), m_vecFonts.end(), TFontCacheElement( pszFontName, bBold, bItalic, bSymbolCharset, pEncoding ) ); if( it.first == it.second ) { if ( (eFontCreationFlags & eFontCreationFlags_AutoSelectBase14) && PODOFO_Base14FontDef_FindBuiltinData(pszFontName)) { int nFlags = ePdfFont_Normal; if( bBold ) nFlags |= ePdfFont_Bold; if( bItalic ) nFlags |= ePdfFont_Italic; pFont = PdfFontFactory::CreateBase14Font(pszFontName, nFlags, pEncoding, m_pParent); if( pFont ) { TFontCacheElement element; element.m_pFont = pFont; element.m_bBold = pFont->IsBold(); element.m_bItalic = pFont->IsItalic(); element.m_sFontName = pszFontName; element.m_pEncoding = pEncoding; element.m_bIsSymbolCharset = bSymbolCharset; // Do a sorted insert, so no need to sort again //rvecContainer.insert( itSorted, element ); m_vecFonts.insert( it.first, element ); } } if (!pFont) { std::string sPath; if ( pszFileName == NULL ) sPath = this->GetFontPath( pszFontName, bBold, bItalic ); else sPath = pszFileName; if( sPath.empty() ) { #if defined(_WIN32) && !defined(PODOFO_NO_FONTMANAGER) pFont = GetWin32Font( it.first, m_vecFonts, pszFontName, bBold, bItalic, bSymbolCharset, bEmbedd, pEncoding ); #endif // _WIN32 } else { bool bSubsetting = (eFontCreationFlags & eFontCreationFlags_Type1Subsetting) != 0; pMetrics = new PdfFontMetricsFreetype( &m_ftLibrary, sPath.c_str(), bSymbolCharset, bSubsetting ? genSubsetBasename() : NULL ); pFont = this->CreateFontObject( it.first, m_vecFonts, pMetrics, bEmbedd, bBold, bItalic, pszFontName, pEncoding, bSubsetting ); } } } else pFont = (*it.first).m_pFont; #if !(defined(_WIN32) && !defined(PODOFO_NO_FONTMANAGER)) if (!pFont) PdfError::LogMessage( eLogSeverity_Critical, "No path was found for the specified fontname: %s\n", pszFontName ); #endif return pFont; } #if defined(_WIN32) && !defined(PODOFO_NO_FONTMANAGER) PdfFont* PdfFontCache::GetFont( const wchar_t* pszFontName, bool bBold, bool bItalic, bool bSymbolCharset, bool bEmbedd, const PdfEncoding * const pEncoding ) { PODOFO_ASSERT( pEncoding ); PdfFont* pFont; std::pair it; it = std::equal_range( m_vecFonts.begin(), m_vecFonts.end(), TFontCacheElement( pszFontName, bBold, bItalic, bSymbolCharset, pEncoding ) ); if( it.first == it.second ) return GetWin32Font( it.first, m_vecFonts, pszFontName, bBold, bItalic, bSymbolCharset, bEmbedd, pEncoding ); else pFont = (*it.first).m_pFont; return pFont; } PdfFont* PdfFontCache::GetFont( const LOGFONTA &logFont, bool bEmbedd, const PdfEncoding * const pEncoding ) { PODOFO_ASSERT( pEncoding ); PdfFont* pFont; std::pair it; it = std::equal_range( m_vecFonts.begin(), m_vecFonts.end(), TFontCacheElement( logFont.lfFaceName, logFont.lfWeight >= FW_BOLD ? true : false, logFont.lfItalic ? true : false, logFont.lfCharSet == SYMBOL_CHARSET, pEncoding ) ); if( it.first == it.second ) return GetWin32Font( it.first, m_vecFonts, logFont, bEmbedd, pEncoding ); else pFont = (*it.first).m_pFont; return pFont; } PdfFont* PdfFontCache::GetFont( const LOGFONTW &logFont, bool bEmbedd, const PdfEncoding * const pEncoding ) { PODOFO_ASSERT( pEncoding ); PdfFont* pFont; std::pair it; it = std::equal_range( m_vecFonts.begin(), m_vecFonts.end(), TFontCacheElement( logFont.lfFaceName, logFont.lfWeight >= FW_BOLD ? true : false, logFont.lfItalic ? true : false, logFont.lfCharSet == SYMBOL_CHARSET, pEncoding ) ); if( it.first == it.second ) return GetWin32Font( it.first, m_vecFonts, logFont, bEmbedd, pEncoding ); else pFont = (*it.first).m_pFont; return pFont; } #endif // _WIN32 PdfFont* PdfFontCache::GetFont( FT_Face face, bool bSymbolCharset, bool bEmbedd, const PdfEncoding * const pEncoding ) { PdfFont* pFont; PdfFontMetrics* pMetrics; std::pair it; std::string sName = FT_Get_Postscript_Name( face ); if( sName.empty() ) { PdfError::LogMessage( eLogSeverity_Critical, "Could not retrieve fontname for font!\n" ); return NULL; } bool bBold = ((face->style_flags & FT_STYLE_FLAG_BOLD) != 0); bool bItalic = ((face->style_flags & FT_STYLE_FLAG_ITALIC) != 0); it = std::equal_range( m_vecFonts.begin(), m_vecFonts.end(), TFontCacheElement( sName.c_str(), bBold, bItalic, bSymbolCharset, pEncoding ) ); if( it.first == it.second ) { pMetrics = new PdfFontMetricsFreetype( &m_ftLibrary, face, bSymbolCharset ); pFont = this->CreateFontObject( it.first, m_vecFonts, pMetrics, bEmbedd, bBold, bItalic, sName.c_str(), pEncoding ); } else pFont = (*it.first).m_pFont; return pFont; } PdfFont* PdfFontCache::GetDuplicateFontType1( PdfFont * pFont, const char* pszSuffix ) { TCISortedFontList it = m_vecFonts.begin(); std::string id = pFont->GetIdentifier().GetName(); id += pszSuffix; // Search if the object is a cached normal font while( it != m_vecFonts.end() ) { if( (*it).m_pFont->GetIdentifier() == id ) return (*it).m_pFont; ++it; } // Search if the object is a cached font subset it = m_vecFontSubsets.begin(); while( it != m_vecFontSubsets.end() ) { if( (*it).m_pFont->GetIdentifier() == id ) return (*it).m_pFont; ++it; } // Create a copy of the font PODOFO_ASSERT( pFont->GetFontMetrics()->GetFontType() == ePdfFontType_Type1Pfb ); PdfFontMetrics* pMetrics = new PdfFontMetricsFreetype( &m_ftLibrary, pFont->GetFontMetrics()->GetFilename(), pFont->GetFontMetrics()->IsSymbol() ); PdfFont* newFont = new PdfFontType1( static_cast(pFont), pMetrics, pszSuffix, m_pParent ); if( newFont ) { std::string name = newFont->GetFontMetrics()->GetFontname(); name += pszSuffix; TFontCacheElement element; element.m_pFont = newFont; element.m_bBold = newFont->IsBold(); element.m_bItalic = newFont->IsItalic(); element.m_sFontName = name; element.m_pEncoding = newFont->GetEncoding(); element.m_bIsSymbolCharset = pFont->GetFontMetrics()->IsSymbol(); m_vecFonts .push_back( element ); // Now sort the font list std::sort( m_vecFonts.begin(), m_vecFonts.end() ); } return newFont; } PdfFont* PdfFontCache::GetFontSubset( const char* pszFontName, bool bBold, bool bItalic, bool bSymbolCharset, const PdfEncoding * const pEncoding, const char* pszFileName ) { PdfFont* pFont; PdfFontMetrics* pMetrics; std::pair it; // WARNING: The characters are completely ignored right now! it = std::equal_range( m_vecFontSubsets.begin(), m_vecFontSubsets.end(), TFontCacheElement( pszFontName, bBold, bItalic, bSymbolCharset, pEncoding ) ); if( it.first == it.second ) { std::string sPath; if( pszFileName == NULL ) { sPath = this->GetFontPath( pszFontName, bBold, bItalic ); if( sPath.empty() ) { #if defined(_WIN32) && !defined(PODOFO_NO_FONTMANAGER) return GetWin32Font( it.first, m_vecFontSubsets, pszFontName, bBold, bItalic, bSymbolCharset, true, pEncoding, true ); #else PdfError::LogMessage( eLogSeverity_Critical, "No path was found for the specified fontname: %s\n", pszFontName ); return NULL; #endif // _WIN32 } } else sPath = pszFileName; pMetrics = new PdfFontMetricsFreetype( &m_ftLibrary, sPath.c_str(), bSymbolCharset ); if( !(pMetrics && pMetrics->GetFontType() == ePdfFontType_TrueType ) ) { PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidFontFile, "Subsetting is only supported for TrueType fonts." ); } PdfInputDevice input( sPath.c_str() ); PdfRefCountedBuffer buffer; PdfOutputDevice output( &buffer ); PdfFontTTFSubset subset( &input, pMetrics, PdfFontTTFSubset::eFontFileType_TTF ); PdfEncoding::const_iterator itChar = pEncoding->begin(); int cpt = 0; while( itChar != pEncoding->end() ) { subset.AddCharacter( *itChar ); ++itChar; cpt++; } subset.BuildFont( &output ); // Delete metrics object, as it was only used so that PdfFontTTFSubset could // match unicode character points to glyph indeces delete pMetrics; pMetrics = new PdfFontMetricsFreetype( &m_ftLibrary, buffer, bSymbolCharset, genSubsetBasename() ); pFont = this->CreateFontObject( it.first, m_vecFontSubsets, pMetrics, true, bBold, bItalic, pszFontName, pEncoding ); } else pFont = (*it.first).m_pFont; return pFont; } void PdfFontCache::EmbedSubsetFonts() { TCISortedFontList it = m_vecFontSubsets.begin(); while( it != m_vecFontSubsets.end() ) { if( (*it).m_pFont->IsSubsetting() ) { (*it).m_pFont->EmbedSubsetFont(); } ++it; } } #if defined(_WIN32) && !defined(PODOFO_NO_FONTMANAGER) PdfFont* PdfFontCache::GetWin32Font( TISortedFontList itSorted, TSortedFontList & vecContainer, const char* pszFontName, bool bBold, bool bItalic, bool bSymbolCharset, bool bEmbedd, const PdfEncoding * const pEncoding, bool pSubsetting ) { LOGFONTW lf; lf.lfHeight = 0; lf.lfWidth = 0; lf.lfEscapement = 0; lf.lfOrientation = 0; lf.lfWeight = bBold ? FW_BOLD : 0; lf.lfItalic = bItalic; lf.lfUnderline = 0; lf.lfStrikeOut = 0; lf.lfCharSet = bSymbolCharset ? SYMBOL_CHARSET : DEFAULT_CHARSET; lf.lfOutPrecision = OUT_DEFAULT_PRECIS; lf.lfClipPrecision = CLIP_DEFAULT_PRECIS; lf.lfQuality = DEFAULT_QUALITY; lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE; if (strlen(pszFontName) >= LF_FACESIZE) return NULL; memset(&(lf.lfFaceName), 0, LF_FACESIZE); //strcpy( lf.lfFaceName, pszFontName ); /*int destLen =*/ MultiByteToWideChar (0, 0, pszFontName, -1, lf.lfFaceName, LF_FACESIZE); return GetWin32Font(itSorted, vecContainer, lf, bEmbedd, pEncoding, pSubsetting); } PdfFont* PdfFontCache::GetWin32Font( TISortedFontList itSorted, TSortedFontList & vecContainer, const wchar_t* pszFontName, bool bBold, bool bItalic, bool bSymbolCharset, bool bEmbedd, const PdfEncoding * const pEncoding, bool pSubsetting ) { LOGFONTW lf; lf.lfHeight = 0; lf.lfWidth = 0; lf.lfEscapement = 0; lf.lfOrientation = 0; lf.lfWeight = bBold ? FW_BOLD : 0; lf.lfItalic = bItalic; lf.lfUnderline = 0; lf.lfStrikeOut = 0; lf.lfCharSet = bSymbolCharset ? SYMBOL_CHARSET : DEFAULT_CHARSET; lf.lfOutPrecision = OUT_DEFAULT_PRECIS; lf.lfClipPrecision = CLIP_DEFAULT_PRECIS; lf.lfQuality = DEFAULT_QUALITY; lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE; pdf_long lFontNameLen = wcslen(pszFontName); if (lFontNameLen >= LF_FACESIZE) return NULL; memset(&(lf.lfFaceName), 0, LF_FACESIZE); wcscpy( static_cast(lf.lfFaceName), pszFontName ); return GetWin32Font(itSorted, vecContainer, lf, bEmbedd, pEncoding, pSubsetting); } PdfFont* PdfFontCache::GetWin32Font( TISortedFontList itSorted, TSortedFontList & vecContainer, const LOGFONTA &logFont, bool bEmbedd, const PdfEncoding * const pEncoding, bool pSubsetting) { char* pBuffer = NULL; unsigned int nLen; if( !GetDataFromLPFONT( &logFont, &pBuffer, nLen ) ) return NULL; PdfFontMetrics* pMetrics; PdfFont* pFont = NULL; try { pMetrics = new PdfFontMetricsFreetype( &m_ftLibrary, pBuffer, nLen, logFont.lfCharSet == SYMBOL_CHARSET, pSubsetting ? genSubsetBasename() : NULL ); pFont = this->CreateFontObject( itSorted, vecContainer, pMetrics, bEmbedd, logFont.lfWeight >= FW_BOLD ? true : false, logFont.lfItalic ? true : false, logFont.lfFaceName, pEncoding, pSubsetting ); } catch( PdfError & error ) { free( pBuffer ); throw error; } free( pBuffer ); return pFont; } PdfFont* PdfFontCache::GetWin32Font( TISortedFontList itSorted, TSortedFontList & vecContainer, const LOGFONTW &logFont, bool bEmbedd, const PdfEncoding * const pEncoding, bool pSubsetting) { pdf_long lFontNameLen = wcslen(logFont.lfFaceName); if (lFontNameLen >= LF_FACESIZE) return NULL; char* pBuffer = NULL; unsigned int nLen; if( !GetDataFromLPFONT( &logFont, &pBuffer, nLen ) ) return NULL; pdf_long lMaxLen = lFontNameLen * 5; char* pmbFontName = static_cast(malloc(lMaxLen)); if( !pmbFontName ) { free( pBuffer ); PODOFO_RAISE_ERROR( ePdfError_OutOfMemory ); } if( wcstombs( pmbFontName, logFont.lfFaceName, lMaxLen ) <= 0 ) { free( pBuffer ); free( pmbFontName ); PODOFO_RAISE_ERROR_INFO( ePdfError_InternalLogic, "Conversion to multibyte char failed" ); } PdfFontMetrics* pMetrics; PdfFont* pFont = NULL; try { pMetrics = new PdfFontMetricsFreetype( &m_ftLibrary, pBuffer, nLen, logFont.lfCharSet == SYMBOL_CHARSET, pSubsetting ? genSubsetBasename() : NULL ); pFont = this->CreateFontObject( itSorted, vecContainer, pMetrics, bEmbedd, logFont.lfWeight >= FW_BOLD ? true : false, logFont.lfItalic ? true : false, pmbFontName, pEncoding, pSubsetting ); free( pmbFontName ); pmbFontName = NULL; } catch( PdfError & error ) { free( pmbFontName ); pmbFontName = NULL; free( pBuffer ); throw error; } free( pBuffer ); return pFont; } #endif // _WIN32 #if defined(PODOFO_HAVE_FONTCONFIG) std::string PdfFontCache::GetFontConfigFontPath( FcConfig* pConfig, const char* pszFontName, bool bBold, bool bItalic ) { FcPattern* pattern; FcPattern* matched; FcResult result = FcResultMatch; FcValue v; std::string sPath; // Build a pattern to search using fontname, bold and italic pattern = FcPatternBuild (0, FC_FAMILY, FcTypeString, pszFontName, FC_WEIGHT, FcTypeInteger, (bBold ? FC_WEIGHT_BOLD : FC_WEIGHT_MEDIUM), FC_SLANT, FcTypeInteger, (bItalic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN), static_cast(0)); FcDefaultSubstitute( pattern ); if( !FcConfigSubstitute( pConfig, pattern, FcMatchFont ) ) { FcPatternDestroy( pattern ); return sPath; } matched = FcFontMatch( pConfig, pattern, &result ); if( result != FcResultNoMatch ) { result = FcPatternGet( matched, FC_FILE, 0, &v ); sPath = reinterpret_cast(v.u.s); #ifdef PODOFO_VERBOSE_DEBUG PdfError::LogMessage( eLogSeverity_Debug, "Got Font %s for for %s\n", sPath.c_str(), pszFontName ); #endif // PODOFO_DEBUG } FcPatternDestroy( pattern ); FcPatternDestroy( matched ); return sPath; } #endif // PODOFO_HAVE_FONTCONFIG std::string PdfFontCache::GetFontPath( const char* pszFontName, bool bBold, bool bItalic ) { #if defined(PODOFO_HAVE_FONTCONFIG) Util::PdfMutexWrapper mutex(m_fontConfig.GetFontConfigMutex()); FcConfig* pFcConfig = static_cast(m_fontConfig.GetFontConfig()); std::string sPath = this->GetFontConfigFontPath( pFcConfig, pszFontName, bBold, bItalic ); #else std::string sPath = ""; #endif return sPath; } PdfFont* PdfFontCache::CreateFontObject( TISortedFontList itSorted, TSortedFontList & rvecContainer, PdfFontMetrics* pMetrics, bool bEmbedd, bool bBold, bool bItalic, const char* pszFontName, const PdfEncoding * const pEncoding, bool bSubsetting ) { PdfFont* pFont; try { int nFlags = ePdfFont_Normal; if ( bSubsetting ) nFlags |= ePdfFont_Subsetting; if( bEmbedd ) nFlags |= ePdfFont_Embedded; if( bBold ) nFlags |= ePdfFont_Bold; if( bItalic ) nFlags |= ePdfFont_Italic; pFont = PdfFontFactory::CreateFontObject( pMetrics, nFlags, pEncoding, m_pParent ); if( pFont ) { TFontCacheElement element; element.m_pFont = pFont; element.m_bBold = pFont->IsBold(); element.m_bItalic = pFont->IsItalic(); element.m_sFontName = pszFontName; element.m_pEncoding = pEncoding; element.m_bIsSymbolCharset = pMetrics->IsSymbol(); // Do a sorted insert, so no need to sort again rvecContainer.insert( itSorted, element ); } } catch( PdfError & e ) { e.AddToCallstack( __FILE__, __LINE__ ); e.PrintErrorMsg(); PdfError::LogMessage( eLogSeverity_Error, "Cannot initialize font: %s\n", pszFontName ? pszFontName : "" ); return NULL; } return pFont; } const char *PdfFontCache::genSubsetBasename(void) { int ii = 0; while(ii < SUBSET_BASENAME_LEN) { m_sSubsetBasename[ii]++; if (m_sSubsetBasename[ii] <= 'Z') { break; } m_sSubsetBasename[ii] = 'A'; ii++; } return m_sSubsetBasename; } }; podofo-0.9.3/src/doc/PdfFontMetricsFreetype.h0000664000175000017500000002763212347317314021000 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2005 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_FONT_METRICS_FREETYPE_H_ #define _PDF_FONT_METRICS_FREETYPE_H_ #include "podofo/base/PdfDefines.h" #include "podofo/base/Pdf3rdPtyForwardDecl.h" #include "podofo/base/PdfString.h" #include "PdfFontMetrics.h" namespace PoDoFo { class PdfArray; class PdfObject; class PdfVariant; class PODOFO_DOC_API PdfFontMetricsFreetype : public PdfFontMetrics { public: /** Create a font metrics object for a given true type file * \param pLibrary handle to an initialized FreeType2 library handle * \param pszFilename filename of a truetype file * \param pIsSymbol whether use a symbol encoding, rather than unicode * \param pszSubsetPrefix unique prefix for font subsets (see GetFontSubsetPrefix) */ PdfFontMetricsFreetype( FT_Library* pLibrary, const char* pszFilename, bool pIsSymbol, const char* pszSubsetPrefix = NULL ); /** Create a font metrics object for a given memory buffer * \param pLibrary handle to an initialized FreeType2 library handle * \param pBuffer block of memory representing the font data (PdfFontMetricsFreetype will copy the buffer) * \param nBufLen the length of the buffer * \param pIsSymbol whether use a symbol encoding, rather than unicode * \param pszSubsetPrefix unique prefix for font subsets (see GetFontSubsetPrefix) */ PdfFontMetricsFreetype( FT_Library* pLibrary, const char* pBuffer, unsigned int nBufLen, bool pIsSymbol, const char* pszSubsetPrefix = NULL); /** Create a font metrics object for a given true type file * \param pLibrary handle to an initialized FreeType2 library handle * \param rBuffer a buffer containing a font file * \param pIsSymbol whether use a symbol encoding, rather than unicode * \param pszSubsetPrefix unique prefix for font subsets (see GetFontSubsetPrefix) */ PdfFontMetricsFreetype( FT_Library* pLibrary, const PdfRefCountedBuffer & rBuffer, bool pIsSymbol, const char* pszSubsetPrefix = NULL); /** Create a font metrics object for a given freetype font. * \param pLibrary handle to an initialized FreeType2 library handle * \param face a valid freetype font face * \param pIsSymbol whether use a symbol encoding, rather than unicode * \param pszSubsetPrefix unique prefix for font subsets (see GetFontSubsetPrefix) */ PdfFontMetricsFreetype( FT_Library* pLibrary, FT_Face face, bool pIsSymbol, const char* pszSubsetPrefix = NULL); /** Create a font metrics object based on an existing PdfObject * * \param pLibrary handle to an initialized FreeType2 library handle * \param pObject an existing font descriptor object */ PdfFontMetricsFreetype( FT_Library* pLibrary, PdfObject* pDescriptor ); virtual ~PdfFontMetricsFreetype(); /** Create a width array for this font which is a required part * of every font dictionary. * \param var the final width array is written to this PdfVariant * \param nFirst first character to be in the array * \param nLast last character code to be in the array */ virtual void GetWidthArray( PdfVariant & var, unsigned int nFirst, unsigned int nLast ) const; /** Get the width of a single glyph id * * \param nGlyphId id of the glyph * \returns the width of a single glyph id */ virtual double GetGlyphWidth( int nGlyphId ) const; /** Get the width of a single named glyph * * \param pszGlyphname name of the glyph * \returns the width of a single named glyph */ virtual double GetGlyphWidth( const char* pszGlyphname ) const; /** Create the bounding box array as required by the PDF reference * so that it can be written directly to a PDF file. * * \param array write the bounding box to this array. */ virtual void GetBoundingBox( PdfArray & array ) const; /** Retrieve the width of the given character in PDF units in the current font * \param c character * \returns the width in PDF units */ virtual double CharWidth( unsigned char c ) const; // Peter Petrov 20 March 2009 /** Retrieve the width of the given character in PDF units in the current font * \param c character * \returns the width in PDF units */ virtual double UnicodeCharWidth( unsigned short c ) const; /** Retrieve the line spacing for this font * \returns the linespacing in PDF units */ virtual double GetLineSpacing() const; /** Get the width of the underline for the current * font size in PDF units * \returns the thickness of the underline in PDF units */ virtual double GetUnderlineThickness() const; /** Return the position of the underline for the current font * size in PDF units * \returns the underline position in PDF units */ virtual double GetUnderlinePosition() const; /** Return the position of the strikeout for the current font * size in PDF units * \returns the underline position in PDF units */ virtual double GetStrikeOutPosition() const; /** Get the width of the strikeout for the current * font size in PDF units * \returns the thickness of the strikeout in PDF units */ virtual double GetStrikeoutThickness() const; /** Get a string with the postscript name of the font. * \returns the postscript name of the font or NULL string if no postscript name is available. */ virtual const char* GetFontname() const; /** Get the weight of this font. * Used to build the font dictionay * \returns the weight of this font (500 is normal). */ virtual unsigned int GetWeight() const; /** Get the ascent of this font in PDF * units for the current font size. * * \returns the ascender for this font * * \see GetPdfAscent */ virtual double GetAscent() const; /** Get the ascent of this font * Used to build the font dictionay * \returns the ascender for this font * * \see GetAscent */ virtual double GetPdfAscent() const; /** Get the descent of this font in PDF * units for the current font size. * This value is usually negative! * * \returns the descender for this font * * \see GetPdfDescent */ virtual double GetDescent() const; /** Get the descent of this font * Used to build the font dictionay * \returns the descender for this font * * \see GetDescent */ virtual double GetPdfDescent() const; /** Get the italic angle of this font. * Used to build the font dictionay * \returns the italic angle of this font. */ virtual int GetItalicAngle() const; /** Get the glyph id for a unicode character * in the current font. * * \param lUnicode the unicode character value * \returns the glyhph id for the character or 0 if the glyph was not found. */ virtual long GetGlyphId( long lUnicode ) const; /** Symbol fonts do need special treatment in a few cases. * Use this method to check if the current font is a symbol * font. Symbold fonts are detected by checking * if they use FT_ENCODING_MS_SYMBOL as internal encoding. * * \returns true if this is a symbol font */ virtual bool IsSymbol() const; /** Get a pointer to the actual font data - if it was loaded from memory. * \returns a binary buffer of data containing the font data */ virtual const char* GetFontData() const; /** Get the length of the actual font data - if it was loaded from memory. * \returns a the length of the font data */ virtual pdf_long GetFontDataLen() const; /** Get whether the internal font style flags contain the Bold flag. * \returns whether the Bold style flag is set on the font */ bool IsBold(void) const; /** Get whether the internal font style flags contain the Italic flag. * \returns whether the Italic style flag is set on the font */ bool IsItalic(void) const; /** Get direct access to the internal FreeType handle * * \returns the internal freetype handle */ inline FT_Face GetFace(); private: /** Initialize this object from an in memory buffer * Called internally by the constructors * \param pIsSymbol Whether use a symbol charset, rather than unicode */ void InitFromBuffer(bool pIsSymbol); /** Load the metric data from the FTFace data * Called internally by the constructors * \param pIsSymbol Whether use a symbol charset, rather than unicode */ void InitFromFace(bool pIsSymbol); void InitFontSizes(); protected: FT_Library* m_pLibrary; FT_Face m_pFace; private: bool m_bSymbol; ///< Internal member to singnal a symbol font bool m_bIsBold; bool m_bIsItalic; unsigned int m_nWeight; int m_nItalicAngle; double m_dAscent; double m_dPdfAscent; double m_dDescent; double m_dPdfDescent; double m_dLineSpacing; double m_dUnderlineThickness; double m_dUnderlinePosition; double m_dStrikeOutThickness; double m_dStrikeOutPosition; PdfRefCountedBuffer m_bufFontData; std::vector m_vecWidth; }; // ----------------------------------------------------- // // ----------------------------------------------------- FT_Face PdfFontMetricsFreetype::GetFace() { return m_pFace; } }; #endif // _PDF_FONT_METRICS_FREETYPE_H_ podofo-0.9.3/src/doc/PdfFontMetricsBase14.h0000664000175000017500000002425112344436402020223 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2010 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_FONT_METRICS_BASE14_H_ #define _PDF_FONT_METRICS_BASE14_H_ #include "podofo/base/PdfDefines.h" #include "podofo/base/PdfRect.h" #include "podofo/base/PdfVariant.h" #include "PdfFontMetrics.h" #include /* The following are the Base 14 fonts data copied from libharu. - kaushik April 12 2010 */ namespace PoDoFo { struct PODOFO_CharData; class PdfArray; /* This is the main class to handle the base14 metric data. The member functions are accessed only through PDFFontmetrics. For eg. pdffontmetrics->GetFontSize would check if it is a base14 font, and call PdfFontMetricsBase14->GetFontSize. This is done to ensure all existing paths work as is. The changes to Base 14 get added without affecting the existing workflow and fit in exactly. Ideally PdfFontMetrics should be abstract or the metric related interface should be seperated out from the implementation details - such as whether the font metric data is read from a file/buffer/hard coded. Kaushik : April 12th 2010 */ class PODOFO_DOC_API PdfFontMetricsBase14 : public PdfFontMetrics { public: PdfFontMetricsBase14(const char *mfont_name, const PODOFO_CharData *mwidths_table, bool mis_font_specific, pdf_int16 mascent, pdf_int16 mdescent, pdf_uint16 mx_height, pdf_uint16 mcap_height, const PdfRect & mbbox); ~PdfFontMetricsBase14(); friend PdfFontMetricsBase14* PODOFO_Base14FontDef_FindBuiltinData (const char *font_name); /** Create a width array for this font which is a required part * of every font dictionary. * \param var the final width array is written to this PdfVariant * \param nFirst first character to be in the array * \param nLast last character code to be in the array */ virtual void GetWidthArray( PdfVariant & var, unsigned int nFirst, unsigned int nLast ) const; /** Get the width of a single glyph id * * \returns the width of a single glyph id */ virtual double GetGlyphWidth( int nGlyphId ) const; /** Get the width of a single named glyph * * \param pszGlyphname name of the glyph * \returns the width of a single named glyph */ virtual double GetGlyphWidth( const char* pszGlyphname ) const; /** Create the bounding box array as required by the PDF reference * so that it can be written directly to a PDF file. * * \param array write the bounding box to this array. */ virtual void GetBoundingBox( PdfArray & array ) const; /** Retrieve the width of the given character in PDF units in the current font * \param c character * \returns the width in PDF units */ virtual double CharWidth( unsigned char c ) const; // Peter Petrov 20 March 2009 /** Retrieve the width of the given character in PDF units in the current font * \param c character * \returns the width in PDF units */ virtual double UnicodeCharWidth( unsigned short c ) const; /** Retrieve the line spacing for this font * \returns the linespacing in PDF units */ virtual double GetLineSpacing() const; /** Get the width of the underline for the current * font size in PDF units * \returns the thickness of the underline in PDF units */ virtual double GetUnderlineThickness() const; /** Return the position of the underline for the current font * size in PDF units * \returns the underline position in PDF units */ virtual double GetUnderlinePosition() const; /** Return the position of the strikeout for the current font * size in PDF units * \returns the underline position in PDF units */ virtual double GetStrikeOutPosition() const; /** Get the width of the strikeout for the current * font size in PDF units * \returns the thickness of the strikeout in PDF units */ virtual double GetStrikeoutThickness() const; /** Get a string with the postscript name of the font. * \returns the postscript name of the font or NULL string if no postscript name is available. */ virtual const char* GetFontname() const; /** Get the weight of this font. * Used to build the font dictionay * \returns the weight of this font (500 is normal). */ virtual unsigned int GetWeight() const; /** Get the ascent of this font in PDF * units for the current font size. * * \returns the ascender for this font * * \see GetPdfAscent */ virtual double GetAscent() const; /** Get the ascent of this font * Used to build the font dictionay * \returns the ascender for this font * * \see GetAscent */ virtual double GetPdfAscent() const; /** Get the descent of this font in PDF * units for the current font size. * This value is usually negative! * * \returns the descender for this font * * \see GetPdfDescent */ virtual double GetDescent() const; /** Get the descent of this font * Used to build the font dictionay * \returns the descender for this font * * \see GetDescent */ virtual double GetPdfDescent() const; /** Get the italic angle of this font. * Used to build the font dictionay * \returns the italic angle of this font. */ virtual int GetItalicAngle() const; /** Get the glyph id for a unicode character * in the current font. * * \param lUnicode the unicode character value * \returns the glyhph id for the character or 0 if the glyph was not found. */ virtual long GetGlyphId( long lUnicode ) const; /** Symbol fonts do need special treatment in a few cases. * Use this method to check if the current font is a symbol * font. Symbold fonts are detected by checking * if they use FT_ENCODING_MS_SYMBOL as internal encoding. * * \returns true if this is a symbol font */ virtual bool IsSymbol() const; /** Get a pointer to the actual font data - if it was loaded from memory. * \returns a binary buffer of data containing the font data */ virtual const char* GetFontData() const; /** Get the length of the actual font data - if it was loaded from memory. * \returns a the length of the font data */ virtual pdf_long GetFontDataLen() const; inline double GetCapHeight() const; private: long GetGlyphIdUnicode( long lUnicode ) const; private : // const PODOFO_Base14FontDefDataRec& base14font_data; const char *font_name; const PODOFO_CharData *widths_table; bool is_font_specific; pdf_int16 ascent; pdf_int16 descent; pdf_uint16 x_height; pdf_uint16 cap_height; PdfRect bbox; bool m_bSymbol; ///< Internal member to singnal a symbol font unsigned int m_nWeight; int m_nItalicAngle; double m_dAscent; double m_dPdfAscent; double m_dDescent; double m_dPdfDescent; double m_dLineSpacing; double m_dUnderlineThickness; double m_dUnderlinePosition; double m_dStrikeOutThickness; double m_dStrikeOutPosition; int units_per_EM; }; PdfFontMetricsBase14* PODOFO_Base14FontDef_FindBuiltinData (const char *font_name); // ----------------------------------------------------- // // ----------------------------------------------------- inline double PdfFontMetricsBase14::GetCapHeight() const { return cap_height; } }; #endif // _PDF_FONT_METRICS_BASE14_H_ podofo-0.9.3/src/doc/PdfTable.cpp0000664000175000017500000004343312347306415016416 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2007 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfTable.h" #include "base/PdfDefinesPrivate.h" #include "base/PdfCanvas.h" #include "base/PdfRect.h" #include "PdfFont.h" #include "PdfImage.h" #include "PdfPainter.h" #include "PdfPage.h" #include namespace PoDoFo { PdfSimpleTableModel::PdfSimpleTableModel() : m_pFont( NULL ), m_eAlignment( ePdfAlignment_Left ), m_eVerticalAlignment( ePdfVerticalAlignment_Center ), m_bWordWrap( false), m_clForeground( 1.0 ), m_bBackground( false ), m_clBackground( 0.0 ), m_ppData( NULL ), m_nCols( 0 ), m_nRows( 0 ), m_bBorder( true ), m_dBorder( 1.0 ) { } PdfSimpleTableModel::PdfSimpleTableModel( int nCols, int nRows ) : m_pFont( NULL ), m_eAlignment( ePdfAlignment_Left ), m_eVerticalAlignment( ePdfVerticalAlignment_Center ), m_bWordWrap( false ), m_clForeground( 1.0 ), m_bBackground( false ), m_clBackground( 0.0 ), m_nCols( nCols ), m_nRows( nRows ), m_bBorder( true ), m_dBorder( 1.0 ) { m_ppData = static_cast(malloc( sizeof(PdfString*) * nRows )); if( !m_ppData ) { PODOFO_RAISE_ERROR( ePdfError_OutOfMemory ); } for( int i=0;iGetCols()]; double* pdRowHeights = new double[this->GetRows()]; bool bBorders = !m_pModel || (m_pModel && m_pModel->HasBorders() ); // Calculate all necessary sizes this->CalculateTableSize( dX, dY, pPainter->GetPage(), pdColWidths, pdRowHeights, &dWidth, &dHeight ); if( !(!static_cast(rClipRect.GetBottom()) && !static_cast(rClipRect.GetLeft()) && !static_cast(rClipRect.GetWidth()) && !static_cast(rClipRect.GetHeight())) ) m_curClipRect = rClipRect; else { m_curClipRect = PdfRect( 0.0, dX, pPainter->GetPage()->GetPageSize().GetWidth() - dX, dY ); } // Draw the table pPainter->Save(); PdfFont* pDefaultFont = pPainter->GetFont(); // get the default font PdfFont* pFont; // draw contents if( m_pModel ) { pPainter->SetStrokeWidth( m_pModel->GetBorderWidth() ); if( bBorders ) // draw top border this->DrawHorizontalBorders( 0, dX, dY, pPainter, pdColWidths ); for( j=0;jCheckForNewPage( &dY, &dCurY, pdRowHeights[j], pPainter ) && bBorders ) // draw top border on new page this->DrawHorizontalBorders( j, dX, dY, pPainter, pdColWidths ); dCurX = 0.0; dCurY += pdRowHeights[j]; for( i=0;iSave(); pPainter->SetClipRect( dX + dCurX, dY - dCurY, pdColWidths[i], pdRowHeights[j] ); // Draw background double dBorder = bBorders ? m_pModel->GetBorderWidth()/2.0 : 0.0; if( m_pModel->HasBackgroundColor( i, j ) ) { pPainter->Save(); pPainter->SetColor( m_pModel->GetBackgroundColor( i, j ) ); // Make sure that FillRect only fills inside the border // rectangle and not over the border. This is necessary // because we draw the border first and than the contents. pPainter->Rectangle( dX + dCurX + dBorder, dY - dCurY + dBorder, pdColWidths[i] - 2.0 * dBorder, pdRowHeights[j] - 2.0 * dBorder ); pPainter->Fill(); pPainter->Restore(); } // draw an image PdfImage* pImage = m_pModel->GetImage( i, j ); double dImageWidth = 0.0; if( m_pModel->HasImage( i, j ) && pImage ) { double dScaleX = (pdColWidths[i]) / pImage->GetPageSize().GetWidth(); double dScaleY = (pdRowHeights[j] - 2.0 * dBorder) / pImage->GetPageSize().GetHeight(); double dScale = PDF_MIN( dScaleX, dScaleY ); dImageWidth = pImage->GetPageSize().GetWidth() * dScale; pPainter->DrawImage( dX + dCurX, dY - dCurY + dBorder, pImage, dScale, dScale ); } // Set the correct font pFont = m_pModel->GetFont( i, j ); pFont = pFont ? pFont : pDefaultFont; pPainter->SetFont( pFont ); pPainter->SetColor( m_pModel->GetForegroundColor( i, j ) ); // draw text if( m_pModel->HasWordWrap( i, j ) ) { // Make sure we have at least 1 dot free space at each side of the rectangle pPainter->DrawMultiLineText( dX + dCurX + 1.0 + dImageWidth, dY - dCurY, pdColWidths[i] - 2.0 - dImageWidth, pdRowHeights[j], m_pModel->GetText( i, j ), m_pModel->GetAlignment( i, j ), m_pModel->GetVerticalAlignment( i, j ) ); } else { // calculate vertical alignment switch( m_pModel->GetVerticalAlignment( i, j ) ) { default: case ePdfVerticalAlignment_Top: dVertical = 0.0; break; case ePdfVerticalAlignment_Center: dVertical = (pdRowHeights[j] - pFont->GetFontMetrics()->GetLineSpacing()) / 2.0; break; case ePdfVerticalAlignment_Bottom: dVertical = (pdRowHeights[j] - pFont->GetFontMetrics()->GetLineSpacing()); break; } // Make sure we have at least 1 dot free space at each side of the rectangle pPainter->DrawTextAligned( dX + dCurX + 1 + dImageWidth, dY - dCurY + dVertical, pdColWidths[i] - 2.0 - dImageWidth, m_pModel->GetText( i, j ), m_pModel->GetAlignment( i, j ) ); } pPainter->Restore(); if( bBorders ) // draw left x border { // use always the border color of the left to the current cell pPainter->SetStrokingColor( m_pModel->GetBorderColor( i>0 ? i-1 : i, j ) ); pPainter->DrawLine( dX + dCurX, dY - dCurY, dX + dCurX, dY - dCurY + pdRowHeights[j] ); } dCurX += pdColWidths[i]; } if( bBorders ) { // Draw last X border if( i > 0 ) { pPainter->SetStrokingColor( m_pModel->GetBorderColor( i-1, j ) ); pPainter->DrawLine( dX + dCurX, dY - dCurY, dX + dCurX, dY - dCurY + pdRowHeights[j] ); } // draw border below row this->DrawHorizontalBorders( j, dX, dY - dCurY, pPainter, pdColWidths ); } } } pPainter->Restore(); if( pdLastX ) *pdLastX = dX + dWidth; if( pdLastY ) *pdLastY = dY - dCurY; // Free allocated memory delete [] pdColWidths; delete [] pdRowHeights; } void PdfTable::DrawHorizontalBorders( int nRow, double dX, double dY, PdfPainter* pPainter, double* pdColWidths ) { double dCurX = 0.0; pPainter->Save(); pPainter->SetLineCapStyle( ePdfLineCapStyle_Square ); for( int i=0;iSetStrokingColor( m_pModel->GetBorderColor( i, nRow ) ); pPainter->DrawLine( dX + dCurX, dY, dX + dCurX + pdColWidths[i], dY ); dCurX += pdColWidths[i]; } pPainter->Restore(); } double PdfTable::GetWidth( double dX, double dY, PdfCanvas* pPage ) const { double dWidth; double dHeight; double* pdColWidths = new double[this->GetCols()]; double* pdRowHeights = new double[this->GetRows()]; // Calculate all necessary sizes this->CalculateTableSize( dX, dY, pPage, pdColWidths, pdRowHeights, &dWidth, &dHeight ); delete [] pdColWidths; delete [] pdRowHeights; return dWidth; } double PdfTable::GetHeight( double dX, double dY, PdfCanvas* pPage ) const { double dWidth; double dHeight; double* pdColWidths = new double[this->GetCols()]; double* pdRowHeights = new double[this->GetRows()]; // Calculate all necessary sizes this->CalculateTableSize( dX, dY, pPage, pdColWidths, pdRowHeights, &dWidth, &dHeight ); delete [] pdColWidths; delete [] pdRowHeights; return dHeight; } void PdfTable::CalculateTableSize( const double dX, const double dY, const PdfCanvas* pCanvas, double* pdWidths, double* pdHeights, double* pdWidth, double* pdHeight ) const { int i; double dWidth = m_dColWidth; double dHeight = m_dRowHeight; // ----------------------------------------------------- // This functions works as follows: // (Description only for width, but the is true for height) // // If the user specified an array of row-widths using SetColumnWidths // just copy the array and use this values. // // Else check if the user has specified a total width for the table // devide the table width through the amount of rows and use the same // width for each row. // // If the user has not specified a table width, use the page width // and devide the page width through the amount of rows. // ----------------------------------------------------- if( m_pdColWidths ) memcpy( pdWidths, m_pdColWidths, sizeof(double) * m_nCols ); else { if( dWidth <= 0.0 ) { double dTableWidth = m_dTableWidth; if( (dTableWidth <= 0.0) ) { // Remove the x border at both sides of the table! dTableWidth = pCanvas->GetPageSize().GetWidth() - dX * 2.0; } dWidth = dTableWidth / static_cast(m_nCols); } for(i=0;i(m_nRows); } for(i=0;iRestore(); PdfPage* pPage = (*m_fpCallback)( m_curClipRect, m_pCustomData ); pPainter->SetPage( pPage ); pPainter->Save(); *pdY = m_curClipRect.GetBottom() + m_curClipRect.GetHeight(); *pdCurY = 0.0; return true; } return false; } void PdfTable::SetColumnWidths( double* pdWidths ) { if( m_pdColWidths ) { delete [] m_pdColWidths; m_pdColWidths = NULL; } if( pdWidths ) { m_pdColWidths = new double[this->GetCols()]; memcpy( m_pdColWidths, pdWidths, this->GetCols() * sizeof(double) ); } } void PdfTable::SetRowHeights( double* pdHeights ) { if( m_pdRowHeights ) { delete [] m_pdRowHeights; m_pdRowHeights = NULL; } if( pdHeights ) { m_pdRowHeights = new double[this->GetRows()]; memcpy( m_pdRowHeights, pdHeights, this->GetRows() * sizeof(double) ); } } /* void CReport::CreateTable( double dX, double dY, int iCols, int iRows, const char** apsTable, double* pdColWidths, double* pdRowHeights, bool bFillBackground ) { int i, j; double dWidth = 0.0; double dHeight = 0.0; const double dcTableBorder = 1000.0 * CONVERSION; mcPainter.Save(); PdfFont* pFont = mpDocument->CreateFont( "Arial" ); pFont->SetFontSize( 8.0f ); mcPainter.SetFont( pFont ); mcPainter.SetStrokeWidth( 1.0 * CONVERSION ); for( i=0;i namespace PoDoFo { PdfExtGState::PdfExtGState( PdfVecObjects* pParent ) : PdfElement( "ExtGState", pParent ) { std::ostringstream out; // We probably aren't doing anything locale sensitive here, but it's // best to be sure. PdfLocaleImbue(out); // Implementation note: the identifier is always // Prefix+ObjectNo. Prefix is /Ft for fonts. out << "ExtGS" << this->GetObject()->Reference().ObjectNumber(); m_Identifier = PdfName( out.str().c_str() ); this->Init(); } PdfExtGState::PdfExtGState( PdfDocument* pParent ) : PdfElement( "ExtGState", pParent ) { std::ostringstream out; // We probably aren't doing anything locale sensitive here, but it's // best to be sure. PdfLocaleImbue(out); // Implementation note: the identifier is always // Prefix+ObjectNo. Prefix is /Ft for fonts. out << "ExtGS" << this->GetObject()->Reference().ObjectNumber(); m_Identifier = PdfName( out.str().c_str() ); this->Init(); } PdfExtGState::~PdfExtGState() { } void PdfExtGState::Init( void ) { } void PdfExtGState::SetFillOpacity( float opac ) { this->GetObject()->GetDictionary().AddKey( "ca", PdfVariant( static_cast(opac) ) ); } void PdfExtGState::SetStrokeOpacity( float opac ) { this->GetObject()->GetDictionary().AddKey( "CA", PdfVariant( opac ) ); } void PdfExtGState::SetBlendMode( const char* blendMode ) { this->GetObject()->GetDictionary().AddKey( "BM", PdfVariant( PdfName( blendMode ) ) ); } void PdfExtGState::SetOverprint( bool enable ) { this->GetObject()->GetDictionary().AddKey( "OP", PdfVariant( enable ) ); } void PdfExtGState::SetFillOverprint( bool enable ) { this->GetObject()->GetDictionary().AddKey( "op", PdfVariant( enable ) ); } void PdfExtGState::SetStrokeOverprint( bool enable ) { this->GetObject()->GetDictionary().AddKey( "OP", PdfVariant( enable ) ); } void PdfExtGState::SetNonZeroOverprint( bool enable ) { this->GetObject()->GetDictionary().AddKey( "OPM", PdfVariant( static_cast(enable ? PODOFO_LL_LITERAL(1) : PODOFO_LL_LITERAL(0)) ) ); } void PdfExtGState::SetRenderingIntent( const char* intent ) { this->GetObject()->GetDictionary().AddKey( "RI", PdfVariant( PdfName( intent ) ) ); } void PdfExtGState::SetFrequency( double frequency ) { PdfDictionary halftoneDict; halftoneDict.AddKey( "HalftoneType", PdfVariant( static_cast(PODOFO_LL_LITERAL(1)) ) ); halftoneDict.AddKey( "Frequency", PdfVariant( frequency ) ); halftoneDict.AddKey( "Angle", PdfVariant( 45.0 ) ); halftoneDict.AddKey( "SpotFunction", PdfName( "SimpleDot" ) ); this->GetObject()->GetDictionary().AddKey( "HT", halftoneDict); } } // end namespace podofo-0.9.3/src/doc/PdfField.cpp0000664000175000017500000007775612347271543016434 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2007 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfField.h" #include "base/PdfDefinesPrivate.h" #include "base/PdfArray.h" #include "base/PdfDictionary.h" #include "PdfAcroForm.h" #include "PdfDocument.h" #include "PdfPainter.h" #include "PdfPage.h" #include "PdfStreamedDocument.h" #include "PdfXObject.h" #include namespace PoDoFo { PdfField::PdfField( EPdfField eField, PdfAnnotation* pWidget, PdfAcroForm* pParent ) : m_pObject( pWidget->GetObject() ), m_pWidget( pWidget ), m_eField( eField ) { Init( pParent ); } PdfField::PdfField( EPdfField eField, PdfPage* pPage, const PdfRect & rRect, PdfAcroForm* pParent ) : m_eField( eField ) { m_pWidget = pPage->CreateAnnotation( ePdfAnnotation_Widget, rRect ); m_pObject = m_pWidget->GetObject(); Init( pParent ); } PdfField::PdfField( EPdfField eField, PdfPage* pPage, const PdfRect & rRect, PdfDocument* pDoc ) : m_eField( eField ) { m_pWidget = pPage->CreateAnnotation( ePdfAnnotation_Widget, rRect ); m_pObject = m_pWidget->GetObject(); Init( pDoc->GetAcroForm() ); } PdfField::PdfField( EPdfField eField, PdfPage* pPage, const PdfRect & rRect, PdfStreamedDocument* pDoc ) : m_eField( eField ) { m_pWidget = pPage->CreateAnnotation( ePdfAnnotation_Widget, rRect ); m_pObject = m_pWidget->GetObject(); Init( pDoc->GetAcroForm() ); } PdfField::PdfField( EPdfField eField, PdfAnnotation* pWidget, PdfAcroForm* pParent, PdfDocument* pDoc) : m_pObject( pWidget->GetObject() ), m_pWidget( pWidget ), m_eField( eField ) { Init( pParent ); PdfObject* pFields = pParent->GetObject()->GetDictionary().GetKey( PdfName("Fields") ); if( pFields && pFields->IsReference()) { PdfObject *pRefFld = pDoc->GetObjects()->GetObject(pFields->GetReference()); if(pRefFld) pRefFld->GetArray().push_back( m_pObject->Reference() ); } } PdfField::PdfField( EPdfField eField, PdfPage* pPage, const PdfRect & rRect, PdfDocument* pDoc, bool bAppearanceNone) : m_eField( eField ) { m_pWidget = pPage->CreateAnnotation( ePdfAnnotation_Widget, rRect ); m_pObject = m_pWidget->GetObject(); Init( pDoc->GetAcroForm(true, bAppearanceNone ? ePdfAcroFormDefaultAppearance_None : ePdfAcroFormDefaultAppearance_BlackText12pt )); } PdfField::PdfField( const PdfField & rhs ) : m_pObject( NULL ), m_pWidget( NULL ), m_eField( ePdfField_Unknown ) { this->operator=( rhs ); } void PdfField::Init( PdfAcroForm* pParent ) { // Insert into the parents kids array PdfObject* pFields = pParent->GetObject()->GetDictionary().GetKey( PdfName("Fields") ); if( pFields ) { if(!pFields->IsReference() ) { pFields->GetArray().push_back( m_pObject->Reference() ); } } else { PODOFO_RAISE_ERROR( ePdfError_NoObject ); } switch( m_eField ) { case ePdfField_PushButton: case ePdfField_CheckBox: case ePdfField_RadioButton: m_pObject->GetDictionary().AddKey( PdfName("FT"), PdfName("Btn") ); break; case ePdfField_TextField: m_pObject->GetDictionary().AddKey( PdfName("FT"), PdfName("Tx") ); break; case ePdfField_ComboBox: case ePdfField_ListBox: m_pObject->GetDictionary().AddKey( PdfName("FT"), PdfName("Ch") ); break; case ePdfField_Signature: m_pObject->GetDictionary().AddKey( PdfName("FT"), PdfName("Sig") ); break; case ePdfField_Unknown: default: { PODOFO_RAISE_ERROR( ePdfError_InternalLogic ); } break; } m_pWidget->SetBorderStyle( 0.0, 0.0, 5.0 ); // Create a unique fieldname, because Acrobat Reader crashes if the field has no field name std::ostringstream out; PdfLocaleImbue(out); out << "podofo_field_" << m_pObject->Reference().ObjectNumber(); } PdfField::PdfField( PdfObject* pObject, PdfAnnotation* pWidget ) : m_pObject( pObject ), m_pWidget( pWidget ), m_eField( ePdfField_Unknown ) { // ISO 32000:2008, Section 12.7.3.1, Table 220, Page #432. const PdfObject *pFT = m_pObject->GetDictionary().GetKey(PdfName("FT") ); if (!pFT && m_pObject->GetDictionary().HasKey( PdfName ("Parent") ) ) { const PdfObject *pTemp = m_pObject->GetIndirectKey ( PdfName("Parent") ); if (!pTemp) { PODOFO_RAISE_ERROR (ePdfError_InvalidDataType); } pFT = pTemp->GetDictionary().GetKey( PdfName ("FT") ); } if (!pFT) { PODOFO_RAISE_ERROR (ePdfError_NoObject); } const PdfName fieldType = pFT->GetName(); if( fieldType == PdfName("Btn") ) { PdfButton button( *this ); if( button.IsPushButton() ) m_eField = ePdfField_PushButton; else if( button.IsCheckBox() ) m_eField = ePdfField_CheckBox; else if (button.IsRadioButton() ) m_eField = ePdfField_RadioButton; } else if( fieldType == PdfName("Tx") ) m_eField = ePdfField_TextField; else if( fieldType == PdfName("Ch") ) { PdfListField listField( *this ); m_eField = listField.IsComboBox() ? ePdfField_ComboBox : ePdfField_ListBox; } else if( fieldType == PdfName("Sig") ) m_eField = ePdfField_Signature; } PdfObject* PdfField::GetAppearanceCharacteristics( bool bCreate ) const { PdfObject* pMK = NULL; if( !m_pObject->GetDictionary().HasKey( PdfName("MK") ) && bCreate ) { PdfDictionary dictionary; const_cast(this)->m_pObject->GetDictionary().AddKey( PdfName("MK"), dictionary ); } pMK = m_pObject->GetDictionary().GetKey( PdfName("MK") ); return pMK; } void PdfField::SetFieldFlag( long lValue, bool bSet ) { pdf_int64 lCur = 0; if( m_pObject->GetDictionary().HasKey( PdfName("Ff") ) ) lCur = m_pObject->GetDictionary().GetKey( PdfName("Ff") )->GetNumber(); if( bSet ) lCur |= lValue; else { if( (lCur & lValue) == lValue ) lCur ^= lValue; } m_pObject->GetDictionary().AddKey( PdfName("Ff"), lCur ); } bool PdfField::GetFieldFlag( long lValue, bool bDefault ) const { pdf_int64 lCur = 0; if( m_pObject->GetDictionary().HasKey( PdfName("Ff") ) ) { lCur = m_pObject->GetDictionary().GetKey( PdfName("Ff") )->GetNumber(); return (lCur & lValue) == lValue; } return bDefault; } void PdfField::SetHighlightingMode( EPdfHighlightingMode eMode ) { PdfName value; switch( eMode ) { case ePdfHighlightingMode_None: value = PdfName("N"); break; case ePdfHighlightingMode_Invert: value = PdfName("I"); break; case ePdfHighlightingMode_InvertOutline: value = PdfName("O"); break; case ePdfHighlightingMode_Push: value = PdfName("P"); break; case ePdfHighlightingMode_Unknown: default: PODOFO_RAISE_ERROR( ePdfError_InvalidName ); break; } m_pObject->GetDictionary().AddKey( PdfName("H"), value ); } EPdfHighlightingMode PdfField::GetHighlightingMode() const { EPdfHighlightingMode eMode = ePdfHighlightingMode_Invert; if( m_pObject->GetDictionary().HasKey( PdfName("H") ) ) { PdfName value = m_pObject->GetDictionary().GetKey( PdfName("H") )->GetName(); if( value == PdfName("N") ) return ePdfHighlightingMode_None; else if( value == PdfName("I") ) return ePdfHighlightingMode_Invert; else if( value == PdfName("O") ) return ePdfHighlightingMode_InvertOutline; else if( value == PdfName("P") ) return ePdfHighlightingMode_Push; } return eMode; } void PdfField::SetBorderColorTransparent() { PdfArray array; PdfObject* pMK = this->GetAppearanceCharacteristics( true ); pMK->GetDictionary().AddKey( PdfName("BC"), array ); } void PdfField::SetBorderColor( double dGray ) { PdfArray array; array.push_back( dGray ); PdfObject* pMK = this->GetAppearanceCharacteristics( true ); pMK->GetDictionary().AddKey( PdfName("BC"), array ); } void PdfField::SetBorderColor( double dRed, double dGreen, double dBlue ) { PdfArray array; array.push_back( dRed ); array.push_back( dGreen ); array.push_back( dBlue ); PdfObject* pMK = this->GetAppearanceCharacteristics( true ); pMK->GetDictionary().AddKey( PdfName("BC"), array ); } void PdfField::SetBorderColor( double dCyan, double dMagenta, double dYellow, double dBlack ) { PdfArray array; array.push_back( dCyan ); array.push_back( dMagenta ); array.push_back( dYellow ); array.push_back( dBlack ); PdfObject* pMK = this->GetAppearanceCharacteristics( true ); pMK->GetDictionary().AddKey( PdfName("BC"), array ); } void PdfField::SetBackgroundColorTransparent() { PdfArray array; PdfObject* pMK = this->GetAppearanceCharacteristics( true ); pMK->GetDictionary().AddKey( PdfName("BG"), array ); } void PdfField::SetBackgroundColor( double dGray ) { PdfArray array; array.push_back( dGray ); PdfObject* pMK = this->GetAppearanceCharacteristics( true ); pMK->GetDictionary().AddKey( PdfName("BG"), array ); } void PdfField::SetBackgroundColor( double dRed, double dGreen, double dBlue ) { PdfArray array; array.push_back( dRed ); array.push_back( dGreen ); array.push_back( dBlue ); PdfObject* pMK = this->GetAppearanceCharacteristics( true ); pMK->GetDictionary().AddKey( PdfName("BG"), array ); } void PdfField::SetBackgroundColor( double dCyan, double dMagenta, double dYellow, double dBlack ) { PdfArray array; array.push_back( dCyan ); array.push_back( dMagenta ); array.push_back( dYellow ); array.push_back( dBlack ); PdfObject* pMK = this->GetAppearanceCharacteristics( true ); pMK->GetDictionary().AddKey( PdfName("BG"), array ); } void PdfField::SetFieldName( const PdfString & rsName ) { m_pObject->GetDictionary().AddKey( PdfName("T"), rsName ); } PdfString PdfField::GetFieldName() const { if( m_pObject->GetDictionary().HasKey( PdfName("T" ) ) ) return m_pObject->GetDictionary().GetKey( PdfName("T" ) )->GetString(); return PdfString::StringNull; } void PdfField::SetAlternateName( const PdfString & rsName ) { m_pObject->GetDictionary().AddKey( PdfName("TU"), rsName ); } PdfString PdfField::GetAlternateName() const { if( m_pObject->GetDictionary().HasKey( PdfName("TU" ) ) ) return m_pObject->GetDictionary().GetKey( PdfName("TU" ) )->GetString(); return PdfString::StringNull; } void PdfField::SetMappingName( const PdfString & rsName ) { m_pObject->GetDictionary().AddKey( PdfName("TM"), rsName ); } PdfString PdfField::GetMappingName() const { if( m_pObject->GetDictionary().HasKey( PdfName("TM" ) ) ) return m_pObject->GetDictionary().GetKey( PdfName("TM" ) )->GetString(); return PdfString::StringNull; } void PdfField::AddAlternativeAction( const PdfName & rsName, const PdfAction & rAction ) { if( !m_pObject->GetDictionary().HasKey( PdfName("AA") ) ) m_pObject->GetDictionary().AddKey( PdfName("AA"), PdfDictionary() ); PdfObject* pAA = m_pObject->GetDictionary().GetKey( PdfName("AA") ); pAA->GetDictionary().AddKey( rsName, rAction.GetObject()->Reference() ); } ///////////////////////////////////////////////////////////////////////////// PdfButton::PdfButton( EPdfField eField, PdfAnnotation* pWidget, PdfAcroForm* pParent ) : PdfField( eField, pWidget, pParent ) { } PdfButton::PdfButton( EPdfField eField, PdfPage* pPage, const PdfRect & rRect, PdfAcroForm* pParent ) : PdfField( eField, pPage, rRect, pParent ) { } PdfButton::PdfButton( EPdfField eField, PdfPage* pPage, const PdfRect & rRect, PdfDocument* pDoc ) : PdfField( eField, pPage, rRect, pDoc ) { } PdfButton::PdfButton( EPdfField eField, PdfPage* pPage, const PdfRect & rRect, PdfStreamedDocument* pDoc ) : PdfField( eField, pPage, rRect, pDoc ) { } PdfButton::PdfButton( const PdfField & rhs ) : PdfField( rhs ) { } void PdfButton::SetCaption( const PdfString & rsText ) { PdfObject* pMK = this->GetAppearanceCharacteristics( true ); pMK->GetDictionary().AddKey( PdfName("CA"), rsText ); } const PdfString PdfButton::GetCaption() const { PdfObject* pMK = this->GetAppearanceCharacteristics( false ); if( pMK && pMK->GetDictionary().HasKey( PdfName("CA") ) ) return pMK->GetDictionary().GetKey( PdfName("CA") )->GetString(); return PdfString::StringNull; } ///////////////////////////////////////////////////////////////////////////// PdfPushButton::PdfPushButton( PdfAnnotation* pWidget, PdfAcroForm* pParent ) : PdfButton( ePdfField_PushButton, pWidget, pParent ) { Init(); } PdfPushButton::PdfPushButton( PdfPage* pPage, const PdfRect & rRect, PdfAcroForm* pParent ) : PdfButton( ePdfField_PushButton, pPage, rRect, pParent ) { Init(); } PdfPushButton::PdfPushButton( PdfPage* pPage, const PdfRect & rRect, PdfDocument* pDoc ) : PdfButton( ePdfField_PushButton, pPage, rRect, pDoc ) { Init(); } PdfPushButton::PdfPushButton( PdfPage* pPage, const PdfRect & rRect, PdfStreamedDocument* pDoc ) : PdfButton( ePdfField_PushButton, pPage, rRect, pDoc ) { Init(); } PdfPushButton::PdfPushButton( const PdfField & rhs ) : PdfButton( rhs ) { if( this->GetType() != ePdfField_CheckBox ) { PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidDataType, "Field cannot be converted into a PdfPushButton" ); } } void PdfPushButton::Init() { // make a push button this->SetFieldFlag( static_cast(ePdfButton_PushButton), true ); //m_pWidget->SetFlags( 4 ); /* m_pObject->GetDictionary().AddKey( PdfName("H"), PdfName("I") ); if( !m_pWidget->HasAppearanceStream() ) { // Create the default appearance stream PdfRect rect( 0.0, 0.0, m_pWidget->GetRect().GetWidth(), m_pWidget->GetRect().GetHeight() ); PdfXObject xObjOff( rect, m_pObject->GetOwner() ); PdfXObject xObjYes( rect, m_pObject->GetOwner() ); PdfPainter painter; painter.SetPage( &xObjOff ); painter.SetColor( 0.5, 0.5, 0.5 ); painter.FillRect( 0, xObjOff.GetPageSize().GetHeight(), xObjOff.GetPageSize().GetWidth(), xObjOff.GetPageSize().GetHeight() ); painter.FinishPage(); painter.SetPage( &xObjYes ); painter.SetColor( 1.0, 0.0, 0.0 ); painter.FillRect( 0, xObjYes.GetPageSize().GetHeight(), xObjYes.GetPageSize().GetWidth(), xObjYes.GetPageSize().GetHeight() ); painter.FinishPage(); PdfDictionary dict; PdfDictionary internal; internal.AddKey( "On", xObjYes.GetObject()->Reference() ); internal.AddKey( "Off", xObjOff.GetObject()->Reference() ); dict.AddKey( "N", internal ); m_pWidget->GetObject()->GetDictionary().AddKey( "AP", dict ); m_pWidget->GetObject()->GetDictionary().AddKey( "AS", PdfName("Off") ); //pWidget->SetAppearanceStream( &xObj ); } */ } void PdfPushButton::SetRolloverCaption( const PdfString & rsText ) { PdfObject* pMK = this->GetAppearanceCharacteristics( true ); pMK->GetDictionary().AddKey( PdfName("RC"), rsText ); } const PdfString PdfPushButton::GetRolloverCaption() const { PdfObject* pMK = this->GetAppearanceCharacteristics( false ); if( pMK && pMK->GetDictionary().HasKey( PdfName("RC") ) ) return pMK->GetDictionary().GetKey( PdfName("RC") )->GetString(); return PdfString::StringNull; } void PdfPushButton::SetAlternateCaption( const PdfString & rsText ) { PdfObject* pMK = this->GetAppearanceCharacteristics( true ); pMK->GetDictionary().AddKey( PdfName("AC"), rsText ); } const PdfString PdfPushButton::GetAlternateCaption() const { PdfObject* pMK = this->GetAppearanceCharacteristics( false ); if( pMK && pMK->GetDictionary().HasKey( PdfName("AC") ) ) return pMK->GetDictionary().GetKey( PdfName("AC") )->GetString(); return PdfString::StringNull; } ///////////////////////////////////////////////////////////////////////////// PdfCheckBox::PdfCheckBox( PdfAnnotation* pWidget, PdfAcroForm* pParent ) : PdfButton( ePdfField_CheckBox, pWidget, pParent ) { Init(); } PdfCheckBox::PdfCheckBox( PdfPage* pPage, const PdfRect & rRect, PdfAcroForm* pParent ) : PdfButton( ePdfField_CheckBox, pPage, rRect, pParent ) { Init(); } PdfCheckBox::PdfCheckBox( PdfPage* pPage, const PdfRect & rRect, PdfDocument* pDoc ) : PdfButton( ePdfField_CheckBox, pPage, rRect, pDoc ) { Init(); } PdfCheckBox::PdfCheckBox( PdfPage* pPage, const PdfRect & rRect, PdfStreamedDocument* pDoc ) : PdfButton( ePdfField_CheckBox, pPage, rRect, pDoc ) { Init(); } PdfCheckBox::PdfCheckBox( const PdfField & rhs ) : PdfButton( rhs ) { if( this->GetType() != ePdfField_CheckBox ) { PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidDataType, "Field cannot be converted into a PdfCheckBox" ); } } void PdfCheckBox::Init() { double dWidth = PDF_MIN( m_pWidget->GetRect().GetWidth(), m_pWidget->GetRect().GetHeight() ) * 0.1; dWidth = PDF_MAX( dWidth, 1.0 ); // Date: 20/10/2007 // Prashanth Udupa. // We expect PDF3DWidgetStyle to provide appearence streams. So we can comment this here. /*if( !m_pWidget->HasAppearanceStream() ) { // Create the default appearance stream PdfRect rect( 0.0, 0.0, m_pWidget->GetRect().GetWidth(), m_pWidget->GetRect().GetHeight() ); PdfXObject xObjOff( rect, m_pObject->GetOwner() ); PdfXObject xObjYes( rect, m_pObject->GetOwner() ); PdfPainter painter; painter.SetPage( &xObjOff ); painter.SetColor( 1.0, 1.0, 1.0 ); painter.FillRect( 0, xObjOff.GetPageSize().GetHeight(), xObjOff.GetPageSize().GetWidth(), xObjOff.GetPageSize().GetHeight() ); painter.SetColor( 0.0, 0.0, 0.0 ); painter.SetStrokeWidth( dWidth ); painter.DrawRect( 0.0, m_pWidget->GetRect().GetHeight(), m_pWidget->GetRect().GetWidth(), m_pWidget->GetRect().GetHeight() ); painter.FinishPage(); painter.SetPage( &xObjYes ); painter.SetColor( 1.0, 1.0, 1.0 ); painter.FillRect( 0, xObjYes.GetPageSize().GetHeight(), xObjYes.GetPageSize().GetWidth(), xObjYes.GetPageSize().GetHeight() ); painter.SetColor( 0.0, 0.0, 0.0 ); painter.SetStrokeWidth( dWidth ); painter.DrawLine( 0.0, 0.0, m_pWidget->GetRect().GetWidth(), m_pWidget->GetRect().GetHeight() ); painter.DrawLine( 0.0, m_pWidget->GetRect().GetHeight(), m_pWidget->GetRect().GetWidth(), 0.0 ); painter.DrawRect( 0.0, m_pWidget->GetRect().GetHeight(), m_pWidget->GetRect().GetWidth(), m_pWidget->GetRect().GetHeight() ); painter.FinishPage(); this->SetAppearanceChecked( xObjYes ); this->SetAppearanceUnchecked( xObjOff ); this->SetChecked( false ); }*/ } void PdfCheckBox::AddAppearanceStream( const PdfName & rName, const PdfReference & rReference ) { if( !m_pObject->GetDictionary().HasKey( PdfName("AP") ) ) m_pObject->GetDictionary().AddKey( PdfName("AP"), PdfDictionary() ); if( !m_pObject->GetDictionary().GetKey( PdfName("AP") )->GetDictionary().HasKey( PdfName("N") ) ) m_pObject->GetDictionary().GetKey( PdfName("AP") )->GetDictionary().AddKey( PdfName("N"), PdfDictionary() ); m_pObject->GetDictionary().GetKey( PdfName("AP") )-> GetDictionary().GetKey( PdfName("N") )->GetDictionary().AddKey( rName, rReference ); } void PdfCheckBox::SetAppearanceChecked( const PdfXObject & rXObject ) { this->AddAppearanceStream( PdfName("Yes"), rXObject.GetObject()->Reference() ); } void PdfCheckBox::SetAppearanceUnchecked( const PdfXObject & rXObject ) { this->AddAppearanceStream( PdfName("Off"), rXObject.GetObject()->Reference() ); } void PdfCheckBox::SetChecked( bool bChecked ) { m_pObject->GetDictionary().AddKey( PdfName("V"), (bChecked ? PdfName("Yes") : PdfName("Off")) ); m_pObject->GetDictionary().AddKey( PdfName("AS"), (bChecked ? PdfName("Yes") : PdfName("Off")) ); } bool PdfCheckBox::IsChecked() const { PdfDictionary dic = m_pObject->GetDictionary(); if (dic.HasKey(PdfName("V"))) { PdfName name = dic.GetKey( PdfName("V") )->GetName(); return (name == PdfName("Yes") || name == PdfName("On")); } else if (dic.HasKey(PdfName("AS"))) { PdfName name = dic.GetKey( PdfName("AS") )->GetName(); return (name == PdfName("Yes") || name == PdfName("On")); } return false; } ///////////////////////////////////////////////////////////////////////////// PdfTextField::PdfTextField( PdfAnnotation* pWidget, PdfAcroForm* pParent ) : PdfField( ePdfField_TextField, pWidget, pParent ) { Init(); } PdfTextField::PdfTextField( PdfPage* pPage, const PdfRect & rRect, PdfAcroForm* pParent ) : PdfField( ePdfField_TextField, pPage, rRect, pParent ) { Init(); } PdfTextField::PdfTextField( PdfPage* pPage, const PdfRect & rRect, PdfDocument* pDoc ) : PdfField( ePdfField_TextField, pPage, rRect, pDoc ) { Init(); } PdfTextField::PdfTextField( PdfPage* pPage, const PdfRect & rRect, PdfStreamedDocument* pDoc ) : PdfField( ePdfField_TextField, pPage, rRect, pDoc ) { Init(); } PdfTextField::PdfTextField( const PdfField & rhs ) : PdfField( rhs ) { if( this->GetType() != ePdfField_TextField ) { PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidDataType, "Field cannot be converted into a PdfTextField" ); } } void PdfTextField::Init() { if( !m_pObject->GetDictionary().HasKey( PdfName("DS") ) ) m_pObject->GetDictionary().AddKey( PdfName("DS"), PdfString("font: 12pt Helvetica") ); } void PdfTextField::SetText( const PdfString & rsText ) { PdfName key = this->IsRichText() ? PdfName("RV") : PdfName("V"); // if rsText is longer than maxlen, truncate it pdf_long nMax = this->GetMaxLen(); if( nMax != -1 && rsText.GetLength() > nMax ) m_pObject->GetDictionary().AddKey( key, PdfString( rsText.GetString(), nMax ) ); else m_pObject->GetDictionary().AddKey( key, rsText ); } PdfString PdfTextField::GetText() const { PdfName key = this->IsRichText() ? PdfName("RV") : PdfName("V"); PdfString str; if( m_pObject->GetDictionary().HasKey( key ) ) str = m_pObject->GetDictionary().GetKey( key )->GetString(); return str; } void PdfTextField::SetMaxLen( pdf_long nMaxLen ) { m_pObject->GetDictionary().AddKey( PdfName("MaxLen"), static_cast(nMaxLen) ); } pdf_long PdfTextField::GetMaxLen() const { return static_cast(m_pObject->GetDictionary().HasKey( PdfName("MaxLen") ) ? m_pObject->GetDictionary().GetKey( PdfName("MaxLen") )->GetNumber() : -1); } ///////////////////////////////////////////////////////////////////////////// PdfListField::PdfListField( EPdfField eField, PdfAnnotation* pWidget, PdfAcroForm* pParent ) : PdfField( eField, pWidget, pParent ) { } PdfListField::PdfListField( EPdfField eField, PdfPage* pPage, const PdfRect & rRect, PdfAcroForm* pParent ) : PdfField( eField, pPage, rRect, pParent ) { } PdfListField::PdfListField( EPdfField eField, PdfPage* pPage, const PdfRect & rRect, PdfDocument* pDoc ) : PdfField( eField, pPage, rRect, pDoc ) { } PdfListField::PdfListField( EPdfField eField, PdfPage* pPage, const PdfRect & rRect, PdfStreamedDocument* pDoc ) : PdfField( eField, pPage, rRect, pDoc ) { } PdfListField::PdfListField( const PdfField & rhs ) : PdfField( rhs ) { } void PdfListField::InsertItem( const PdfString & rsValue, const PdfString & rsDisplayName ) { PdfVariant var; PdfArray opt; if( rsDisplayName == PdfString::StringNull ) var = rsValue; else { PdfArray array; array.push_back( rsValue ); array.push_back( rsDisplayName ); var = array; } if( m_pObject->GetDictionary().HasKey( PdfName("Opt") ) ) opt = m_pObject->GetDictionary().GetKey( PdfName("Opt") )->GetArray(); // TODO: Sorting opt.push_back( var ); m_pObject->GetDictionary().AddKey( PdfName("Opt"), opt ); /* m_pObject->GetDictionary().AddKey( PdfName("V"), rsValue ); PdfArray array; array.push_back( 0L ); m_pObject->GetDictionary().AddKey( PdfName("I"), array ); */ } void PdfListField::RemoveItem( int nIndex ) { PdfArray opt; if( m_pObject->GetDictionary().HasKey( PdfName("Opt") ) ) opt = m_pObject->GetDictionary().GetKey( PdfName("Opt") )->GetArray(); if( nIndex < 0 || nIndex > static_cast(opt.size()) ) { PODOFO_RAISE_ERROR( ePdfError_ValueOutOfRange ); } opt.erase( opt.begin() + nIndex ); m_pObject->GetDictionary().AddKey( PdfName("Opt"), opt ); } const PdfString PdfListField::GetItem( int nIndex ) const { PdfArray opt; if( m_pObject->GetDictionary().HasKey( PdfName("Opt") ) ) opt = m_pObject->GetDictionary().GetKey( PdfName("Opt") )->GetArray(); if( nIndex < 0 || nIndex > static_cast(opt.size()) ) { PODOFO_RAISE_ERROR( ePdfError_ValueOutOfRange ); } PdfVariant var = opt[nIndex]; if( var.IsArray() ) { if( var.GetArray().size() < 2 ) { PODOFO_RAISE_ERROR( ePdfError_InvalidDataType ); } else return var.GetArray()[0].GetString(); } return var.GetString(); } const PdfString PdfListField::GetItemDisplayText( int nIndex ) const { PdfArray opt; if( m_pObject->GetDictionary().HasKey( PdfName("Opt") ) ) opt = m_pObject->GetDictionary().GetKey( PdfName("Opt") )->GetArray(); if( nIndex < 0 || nIndex > static_cast(opt.size()) ) { PODOFO_RAISE_ERROR( ePdfError_ValueOutOfRange ); } PdfVariant var = opt[nIndex]; if( var.IsArray() ) { if( var.GetArray().size() < 2 ) { PODOFO_RAISE_ERROR( ePdfError_InvalidDataType ); } else return var.GetArray()[1].GetString(); } return var.GetString(); } size_t PdfListField::GetItemCount() const { PdfArray opt; if( m_pObject->GetDictionary().HasKey( PdfName("Opt") ) ) opt = m_pObject->GetDictionary().GetKey( PdfName("Opt") )->GetArray(); return opt.size(); } void PdfListField::SetSelectedItem( int nIndex ) { PdfString selected = this->GetItem( nIndex ); m_pObject->GetDictionary().AddKey( PdfName("V"), selected ); } int PdfListField::GetSelectedItem() const { if( m_pObject->GetDictionary().HasKey( PdfName("V") ) ) { PdfObject* pValue = m_pObject->GetDictionary().GetKey( PdfName("V") ); if( pValue->IsString() || pValue->IsHexString() ) { PdfString value = pValue->GetString(); for( int i=0;i(this->GetItemCount());i++ ) { if( this->GetItem( i ) == value ) return i; } } } return -1; } ///////////////////////////////////////////////////////////////////////////// PdfComboBox::PdfComboBox( PdfAnnotation* pWidget, PdfAcroForm* pParent ) : PdfListField( ePdfField_ComboBox, pWidget, pParent ) { this->SetFieldFlag( static_cast(ePdfListField_Combo), true ); m_pWidget->SetBorderStyle( 0.0, 0.0, 1.0 ); } PdfComboBox::PdfComboBox( PdfPage* pPage, const PdfRect & rRect, PdfAcroForm* pParent ) : PdfListField( ePdfField_ComboBox, pPage, rRect, pParent ) { this->SetFieldFlag( static_cast(ePdfListField_Combo), true ); m_pWidget->SetBorderStyle( 0.0, 0.0, 1.0 ); } PdfComboBox::PdfComboBox( PdfPage* pPage, const PdfRect & rRect, PdfDocument* pDoc ) : PdfListField( ePdfField_ComboBox, pPage, rRect, pDoc ) { this->SetFieldFlag( static_cast(ePdfListField_Combo), true ); m_pWidget->SetBorderStyle( 0.0, 0.0, 1.0 ); } PdfComboBox::PdfComboBox( PdfPage* pPage, const PdfRect & rRect, PdfStreamedDocument* pDoc ) : PdfListField( ePdfField_ComboBox, pPage, rRect, pDoc ) { this->SetFieldFlag( static_cast(ePdfListField_Combo), true ); m_pWidget->SetBorderStyle( 0.0, 0.0, 1.0 ); } PdfComboBox::PdfComboBox( const PdfField & rhs ) : PdfListField( rhs ) { if( this->GetType() != ePdfField_ComboBox ) { PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidDataType, "Field cannot be converted into a PdfTextField" ); } } ///////////////////////////////////////////////////////////////////////////// PdfListBox::PdfListBox( PdfAnnotation* pWidget, PdfAcroForm* pParent ) : PdfListField( ePdfField_ListBox, pWidget, pParent ) { this->SetFieldFlag( static_cast(ePdfListField_Combo), false ); m_pWidget->SetBorderStyle( 0.0, 0.0, 1.0 ); } PdfListBox::PdfListBox( PdfPage* pPage, const PdfRect & rRect, PdfAcroForm* pParent ) : PdfListField( ePdfField_ListBox, pPage, rRect, pParent ) { this->SetFieldFlag( static_cast(ePdfListField_Combo), false ); m_pWidget->SetBorderStyle( 0.0, 0.0, 1.0 ); } PdfListBox::PdfListBox( PdfPage* pPage, const PdfRect & rRect, PdfDocument* pDoc ) : PdfListField( ePdfField_ListBox, pPage, rRect, pDoc ) { this->SetFieldFlag( static_cast(ePdfListField_Combo), false ); m_pWidget->SetBorderStyle( 0.0, 0.0, 1.0 ); } PdfListBox::PdfListBox( PdfPage* pPage, const PdfRect & rRect, PdfStreamedDocument* pDoc ) : PdfListField( ePdfField_ListBox, pPage, rRect, pDoc ) { this->SetFieldFlag( static_cast(ePdfListField_Combo), false ); m_pWidget->SetBorderStyle( 0.0, 0.0, 1.0 ); } PdfListBox::PdfListBox( const PdfField & rhs ) : PdfListField( rhs ) { if( this->GetType() != ePdfField_ListBox ) { PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidDataType, "Field cannot be converted into a PdfTextField" ); } } }; podofo-0.9.3/src/doc/PdfFontCID.h0000664000175000017500000001300212347317314016247 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2007 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_FONT_CID_H_ #define _PDF_FONT_CID_H_ #include "podofo/base/PdfDefines.h" #include "PdfFont.h" #include namespace PoDoFo { class PdfFontMetricsFreetype; /** A PdfFont that represents a CID font. */ class PdfFontCID : public PdfFont { public: /** Create a new CID font. * * \param pMetrics pointer to a font metrics object. The font in the PDF * file will match this fontmetrics object. The metrics object is * deleted along with the font. * \param pEncoding the encoding of this font. The font will take ownership of this object * depending on pEncoding->IsAutoDelete() * \param pParent parent of the font object * \param bEmbed specifies the embedding of font * \param bSubset specifies the subsetting of the font; forces bEmbed to false, if set * */ PdfFontCID( PdfFontMetrics* pMetrics, const PdfEncoding* const pEncoding, PdfVecObjects* pParent, bool bEmbed, bool bSubset ); // Peter Petrov 30 April 2008 /** Create a PdfFont based on an existing PdfObject * \param pMetrics pointer to a font metrics object. The font in the PDF * file will match this fontmetrics object. The metrics object is * deleted along with the font. * \param pEncoding the encoding of this font. The font will take ownership of this object * depending on pEncoding->IsAutoDelete() * \param pObject an existing PdfObject * \param bEmbed specifies the embedding of font */ PdfFontCID( PdfFontMetrics* pMetrics, const PdfEncoding* const pEncoding, PdfObject* pObject, bool bEmbed ); // Peter Petrov 24 September 2008 /** Embeds the font into PDF page * */ virtual void EmbedFont(); virtual void EmbedSubsetFont(); virtual void AddUsedSubsettingGlyphs (const PdfString &sText, long lStringLen); private: /** Create the DW and W entries which contain * all glyph width in the given font dictionary. * * \param pFontDict a CID font dictionary */ void CreateWidth( PdfObject* pFontDict ) const; /** Create a ToUnicode CMap and write it to the stream * of the given object. * * \param pUnicode the object which will contain the CMap */ void CreateCMap( PdfObject* pUnicode ) const; protected: /** Initialize this font object. * * \param bEmbed if true embed the font data into the PDF file. * \param bSubset specifies the subsetting of the font; forces bEmbed to false, if set */ void Init( bool bEmbed, bool bSubset ); /** Embed the font file directly into the PDF file. * * \param pDescriptor font descriptor object */ void EmbedFont( PdfObject* pDescriptor ); PdfObject *m_pDescendantFonts; protected: // Peter Petrov 24 September 2008 PdfObject* m_pDescriptor; std::set m_setUsed; void MaybeUpdateBaseFontKey(void); /* to update "BaseFont" key */ virtual void SetBold( bool bBold ); virtual void SetItalic( bool bItalic ); }; }; #endif // _PDF_FONT_CID_H_ podofo-0.9.3/src/doc/PdfStreamedDocument.h0000664000175000017500000003303012344436402020264 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2007 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_STREAMED_DOCUMENT_H_ #define _PDF_STREAMED_DOCUMENT_H_ #include "podofo/base/PdfDefines.h" #include "podofo/base/PdfImmediateWriter.h" #include "PdfDocument.h" namespace PoDoFo { class PdfOutputDevice; /** PdfStreamedDocument is the preferred class for * creating new PDF documents. * * Page contents, fonts and images are written to disk * as soon as possible and are not kept in memory. * This results in faster document generation and * less memory being used. * * Please use PdfMemDocument if you intend to work * on the object structure of a PDF file. * * One of the design goals of PdfStreamedDocument was * to hide the underlying object structure of a PDF * file as far as possible. * * \see PdfDocument * \see PdfMemDocument * * Example of using PdfStreamedDocument: * * PdfStreamedDocument document( "outputfile.pdf" ); * PdfPage* pPage = document.CreatePage( PdfPage::CreateStandardPageSize( ePdfPageSize_A4 ) ); * PdfFont* pFont = document.CreateFont( "Arial" ); * * PdfPainter painter; * painter.SetPage( pPage ); * painter.SetFont( pFont ); * painter.DrawText( 56.69, pPage->GetPageSize().GetHeight() - 56.69, "Hello World!" ); * painter.FinishPage(); * * document.Close(); */ class PODOFO_DOC_API PdfStreamedDocument : public PdfDocument { friend class PdfImage; friend class PdfElement; public: /** Create a new PdfStreamedDocument. * All data is written to an output device * immediately. * * \param pDevice an output device * \param eVersion the PDF version of the document to write. * The PDF version can only be set in the constructor * as it is the first item written to the document on disk. * \param pEncrypt pointer to an encryption object or NULL. If not NULL * the PdfEncrypt object will be copied and used to encrypt the * created document. * \param eWriteMode additional options for writing the pdf */ PdfStreamedDocument( PdfOutputDevice* pDevice, EPdfVersion eVersion = ePdfVersion_Default, PdfEncrypt* pEncrypt = NULL, EPdfWriteMode eWriteMode = ePdfWriteMode_Default ); /** Create a new PdfStreamedDocument. * All data is written to a file immediately. * * \param pszFilename resulting PDF file * \param eVersion the PDF version of the document to write. * The PDF version can only be set in the constructor * as it is the first item written to the document on disk. * \param pEncrypt pointer to an encryption object or NULL. If not NULL * the PdfEncrypt object will be copied and used to encrypt the * created document. * \param eWriteMode additional options for writing the pdf */ PdfStreamedDocument( const char* pszFilename, EPdfVersion eVersion = ePdfVersion_Default, PdfEncrypt* pEncrypt = NULL, EPdfWriteMode eWriteMode = ePdfWriteMode_Default ); #ifdef _WIN32 /** Create a new PdfStreamedDocument. * All data is written to a file immediately. * * \param pszFilename resulting PDF file * \param eVersion the PDF version of the document to write. * The PDF version can only be set in the constructor * as it is the first item written to the document on disk. * \param pEncrypt pointer to an encryption object or NULL. If not NULL * the PdfEncrypt object will be copied and used to encrypt the * created document. * \param eWriteMode additional options for writing the pdf * * This is an overloaded member function to allow working * with unicode characters. On Unix systes you can also path * UTF-8 to the const char* overload. */ PdfStreamedDocument( const wchar_t* pszFilename, EPdfVersion eVersion = ePdfVersion_Default, PdfEncrypt* pEncrypt = NULL, EPdfWriteMode eWriteMode = ePdfWriteMode_Default ); #endif // _WIN32 ~PdfStreamedDocument(); /** Close the document. The PDF file on disk is finished. * No other member function of this class maybe called * after calling this function. */ void Close(); /** Get the write mode used for wirting the PDF * \returns the write mode */ inline virtual EPdfWriteMode GetWriteMode() const; /** Get the PDF version of the document * \returns EPdfVersion version of the pdf document */ inline virtual EPdfVersion GetPdfVersion() const; /** Returns wether this PDF document is linearized, aka * weboptimized * \returns true if the PDF document is linearized */ inline virtual bool IsLinearized() const; /** Checks if printing this document is allowed. * Every PDF consuming applications has to adhere this value! * * \returns true if you are allowed to print this document * * \see PdfEncrypt to set own document permissions. */ inline virtual bool IsPrintAllowed() const; /** Checks if modifiying this document (besides annotations, form fields or changing pages) is allowed. * Every PDF consuming applications has to adhere this value! * * \returns true if you are allowed to modfiy this document * * \see PdfEncrypt to set own document permissions. */ inline virtual bool IsEditAllowed() const; /** Checks if text and graphics extraction is allowed. * Every PDF consuming applications has to adhere this value! * * \returns true if you are allowed to extract text and graphics from this document * * \see PdfEncrypt to set own document permissions. */ inline virtual bool IsCopyAllowed() const; /** Checks if it is allowed to add or modify annotations or form fields * Every PDF consuming applications has to adhere this value! * * \returns true if you are allowed to add or modify annotations or form fields * * \see PdfEncrypt to set own document permissions. */ inline virtual bool IsEditNotesAllowed() const; /** Checks if it is allowed to fill in existing form or signature fields * Every PDF consuming applications has to adhere this value! * * \returns true if you are allowed to fill in existing form or signature fields * * \see PdfEncrypt to set own document permissions. */ inline virtual bool IsFillAndSignAllowed() const; /** Checks if it is allowed to extract text and graphics to support users with disabillities * Every PDF consuming applications has to adhere this value! * * \returns true if you are allowed to extract text and graphics to support users with disabillities * * \see PdfEncrypt to set own document permissions. */ inline virtual bool IsAccessibilityAllowed() const; /** Checks if it is allowed to insert, create, rotate, delete pages or add bookmarks * Every PDF consuming applications has to adhere this value! * * \returns true if you are allowed to insert, create, rotate, delete pages or add bookmarks * * \see PdfEncrypt to set own document permissions. */ inline virtual bool IsDocAssemblyAllowed() const; /** Checks if it is allowed to print a high quality version of this document * Every PDF consuming applications has to adhere this value! * * \returns true if you are allowed to print a high quality version of this document * * \see PdfEncrypt to set own document permissions. */ inline virtual bool IsHighPrintAllowed() const; private: /** Initialize the PdfStreamedDocument with an output device * \param pDevice write to this device * \param eVersion the PDF version of the document to write. * The PDF version can only be set in the constructor * as it is the first item written to the document on disk. * \param pEncrypt pointer to an encryption object or NULL. If not NULL * the PdfEncrypt object will be copied and used to encrypt the * created document. * \param eWriteMode additional options for writing the pdf */ void Init( PdfOutputDevice* pDevice, EPdfVersion eVersion = ePdfVersion_Default, PdfEncrypt* pEncrypt = NULL, EPdfWriteMode eWriteMode = ePdfWriteMode_Default ); private: PdfImmediateWriter* m_pWriter; PdfOutputDevice* m_pDevice; PdfEncrypt* m_pEncrypt; bool m_bOwnDevice; ///< If true m_pDevice is owned by this object and has to be deleted }; // ----------------------------------------------------- // // ----------------------------------------------------- EPdfWriteMode PdfStreamedDocument::GetWriteMode() const { return m_pWriter->GetWriteMode(); } // ----------------------------------------------------- // // ----------------------------------------------------- EPdfVersion PdfStreamedDocument::GetPdfVersion() const { return m_pWriter->GetPdfVersion(); } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfStreamedDocument::IsLinearized() const { // Linearization is currently not supported by PdfStreamedDocument return false; } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfStreamedDocument::IsPrintAllowed() const { return m_pEncrypt ? m_pEncrypt->IsPrintAllowed() : true; } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfStreamedDocument::IsEditAllowed() const { return m_pEncrypt ? m_pEncrypt->IsEditAllowed() : true; } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfStreamedDocument::IsCopyAllowed() const { return m_pEncrypt ? m_pEncrypt->IsCopyAllowed() : true; } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfStreamedDocument::IsEditNotesAllowed() const { return m_pEncrypt ? m_pEncrypt->IsEditNotesAllowed() : true; } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfStreamedDocument::IsFillAndSignAllowed() const { return m_pEncrypt ? m_pEncrypt->IsFillAndSignAllowed() : true; } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfStreamedDocument::IsAccessibilityAllowed() const { return m_pEncrypt ? m_pEncrypt->IsAccessibilityAllowed() : true; } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfStreamedDocument::IsDocAssemblyAllowed() const { return m_pEncrypt ? m_pEncrypt->IsDocAssemblyAllowed() : true; } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfStreamedDocument::IsHighPrintAllowed() const { return m_pEncrypt ? m_pEncrypt->IsHighPrintAllowed() : true; } }; #endif /* _PDF_STREAMED_DOCUMENT_H_ */ podofo-0.9.3/src/doc/PdfFontConfigWrapper.cpp0000664000175000017500000001071012344436402020751 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2011 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfFontConfigWrapper.h" #if defined(PODOFO_HAVE_FONTCONFIG) #include #include "base/util/PdfMutexWrapper.h" #endif namespace PoDoFo { #if defined(PODOFO_HAVE_FONTCONFIG) Util::PdfMutex PdfFontConfigWrapper::m_FcMutex; #endif PdfFontConfigWrapper::PdfFontConfigWrapper() : m_pFontConfig( NULL ) { #if defined(PODOFO_HAVE_FONTCONFIG) this->m_pFontConfig = new TRefCountedFontConfig(); this->m_pFontConfig->m_lRefCount = 1; this->m_pFontConfig->m_bInitialized = false; this->m_pFontConfig->m_pFcConfig = NULL; #endif } PdfFontConfigWrapper::PdfFontConfigWrapper(const PdfFontConfigWrapper & rhs) { this->operator=(rhs); } PdfFontConfigWrapper::~PdfFontConfigWrapper() { this->DerefBuffer(); } const PdfFontConfigWrapper & PdfFontConfigWrapper::operator=(const PdfFontConfigWrapper & rhs) { // Self assignment is a no-op if (this == &rhs) return rhs; DerefBuffer(); this->m_pFontConfig = rhs.m_pFontConfig; if( m_pFontConfig ) { this->m_pFontConfig->m_lRefCount++; } return *this; } void PdfFontConfigWrapper::DerefBuffer() { if ( m_pFontConfig && !(--m_pFontConfig->m_lRefCount) ) { #if defined(PODOFO_HAVE_FONTCONFIG) if( this->m_pFontConfig->m_bInitialized ) { Util::PdfMutexWrapper mutex(m_FcMutex); FcConfigDestroy( static_cast(m_pFontConfig->m_pFcConfig) ); } #endif delete m_pFontConfig; } // Whether or not it still exists, we no longer have anything to do with // the buffer we just released our claim on. m_pFontConfig = NULL; } void PdfFontConfigWrapper::InitializeFontConfig() { #if defined(PODOFO_HAVE_FONTCONFIG) if( !this->m_pFontConfig->m_bInitialized ) { Util::PdfMutexWrapper mutex(m_FcMutex); if( !this->m_pFontConfig->m_bInitialized ) { this->m_pFontConfig->m_pFcConfig = static_cast(FcInitLoadConfigAndFonts()); this->m_pFontConfig->m_bInitialized = true; } } #endif } }; podofo-0.9.3/src/doc/PdfPage.cpp0000664000175000017500000004622712347354102016243 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2005 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfPage.h" #include "base/PdfDefinesPrivate.h" #include "base/PdfDictionary.h" #include "base/PdfRect.h" #include "base/PdfVariant.h" #include "base/PdfWriter.h" #include "base/PdfStream.h" #include "PdfDocument.h" namespace PoDoFo { PdfPage::PdfPage( const PdfRect & rSize, PdfDocument* pParent ) : PdfElement( "Page", pParent ), PdfCanvas(), m_pContents( NULL ) { InitNewPage( rSize ); } PdfPage::PdfPage( const PdfRect & rSize, PdfVecObjects* pParent ) : PdfElement( "Page", pParent ), PdfCanvas(), m_pContents( NULL ) { InitNewPage( rSize ); } PdfPage::PdfPage( PdfObject* pObject, const std::deque & rListOfParents ) : PdfElement( "Page", pObject ), PdfCanvas() { m_pResources = this->GetObject()->GetIndirectKey( "Resources" ); if( !m_pResources ) { // Resources might be inherited std::deque::const_reverse_iterator it = rListOfParents.rbegin(); while( it != rListOfParents.rend() && !m_pResources ) { m_pResources = (*it)->GetIndirectKey( "Resources" ); ++it; } } PdfObject* pContents = this->GetObject()->GetIndirectKey( "Contents" ); if (pContents) { m_pContents = new PdfContents( pContents ); } else { // Create object on demand m_pContents = NULL; } } PdfPage::~PdfPage() { TIMapAnnotation it = m_mapAnnotations.begin(); while( it != m_mapAnnotations.end() ) { delete (*it).second; ++it; } delete m_pContents; // just clears the C++ object from memory, NOT the PdfObject } void PdfPage::InitNewPage( const PdfRect & rSize ) { PdfVariant mediabox; rSize.ToVariant( mediabox ); this->GetObject()->GetDictionary().AddKey( "MediaBox", mediabox ); // The PDF specification suggests that we send all available PDF Procedure sets this->GetObject()->GetDictionary().AddKey( "Resources", PdfObject( PdfDictionary() ) ); m_pResources = this->GetObject()->GetIndirectKey( "Resources" ); m_pResources->GetDictionary().AddKey( "ProcSet", PdfCanvas::GetProcSet() ); } void PdfPage::CreateContents() { if( !m_pContents ) { m_pContents = new PdfContents( this ); this->GetObject()->GetDictionary().AddKey( PdfName::KeyContents, m_pContents->GetContents()->Reference()); } } PdfObject* PdfPage::GetContents() const { if( !m_pContents ) { const_cast(this)->CreateContents(); } return m_pContents->GetContents(); } PdfObject* PdfPage::GetContentsForAppending() const { if( !m_pContents ) { const_cast(this)->CreateContents(); } return m_pContents->GetContentsForAppending(); } PdfRect PdfPage::CreateStandardPageSize( const EPdfPageSize ePageSize, bool bLandscape ) { PdfRect rect; switch( ePageSize ) { case ePdfPageSize_A0: rect.SetWidth( 2384.0 ); rect.SetHeight( 3370.0 ); break; case ePdfPageSize_A1: rect.SetWidth( 1684.0 ); rect.SetHeight( 2384.0 ); break; case ePdfPageSize_A2: rect.SetWidth( 1191.0 ); rect.SetHeight( 1684.0 ); break; case ePdfPageSize_A3: rect.SetWidth( 842.0 ); rect.SetHeight( 1190.0 ); break; case ePdfPageSize_A4: rect.SetWidth( 595.0 ); rect.SetHeight( 842.0 ); break; case ePdfPageSize_A5: rect.SetWidth( 420.0 ); rect.SetHeight( 595.0 ); break; case ePdfPageSize_A6: rect.SetWidth( 297.0 ); rect.SetHeight( 420.0 ); break; case ePdfPageSize_Letter: rect.SetWidth( 612.0 ); rect.SetHeight( 792.0 ); break; case ePdfPageSize_Legal: rect.SetWidth( 612.0 ); rect.SetHeight( 1008.0 ); break; case ePdfPageSize_Tabloid: rect.SetWidth( 792.0 ); rect.SetHeight( 1224.0 ); break; default: break; } if( bLandscape ) { double dTmp = rect.GetWidth(); rect.SetWidth ( rect.GetHeight() ); rect.SetHeight( dTmp ); } return rect; } const PdfObject* PdfPage::GetInheritedKeyFromObject( const char* inKey, const PdfObject* inObject ) const { const PdfObject* pObj = NULL; // check for it in the object itself if ( inObject->GetDictionary().HasKey( inKey ) ) { pObj = inObject->GetDictionary().GetKey( inKey ); if ( !pObj->IsNull() ) return pObj; } // if we get here, we need to go check the parent - if there is one! if( inObject->GetDictionary().HasKey( "Parent" ) ) { pObj = inObject->GetIndirectKey( "Parent" ); if( pObj ) pObj = GetInheritedKeyFromObject( inKey, pObj ); } return pObj; } const PdfRect PdfPage::GetPageBox( const char* inBox ) const { PdfRect pageBox; const PdfObject* pObj; // Take advantage of inherited values - walking up the tree if necessary pObj = GetInheritedKeyFromObject( inBox, this->GetObject() ); // Sometime page boxes are defined using reference objects while ( pObj && pObj->IsReference() ) { pObj = this->GetObject()->GetOwner()->GetObject( pObj->GetReference() ); } // assign the value of the box from the array if ( pObj && pObj->IsArray() ) { pageBox.FromArray( pObj->GetArray() ); } else if ( strcmp( inBox, "ArtBox" ) == 0 || strcmp( inBox, "BleedBox" ) == 0 || strcmp( inBox, "TrimBox" ) == 0 ) { // If those page boxes are not specified then // default to CropBox per PDF Spec (3.6.2) pageBox = GetPageBox( "CropBox" ); } else if ( strcmp( inBox, "CropBox" ) == 0 ) { // If crop box is not specified then // default to MediaBox per PDF Spec (3.6.2) pageBox = GetPageBox( "MediaBox" ); } return pageBox; } int PdfPage::GetRotation() const { int rot = 0; const PdfObject* pObj = GetInheritedKeyFromObject( "Rotate", this->GetObject() ); if ( pObj && pObj->IsNumber() ) rot = static_cast(pObj->GetNumber()); return rot; } void PdfPage::SetRotation(int nRotation) { if( nRotation != 0 && nRotation != 90 && nRotation != 180 && nRotation != 270 ) PODOFO_RAISE_ERROR( ePdfError_ValueOutOfRange ); this->GetObject()->GetDictionary().AddKey( "Rotate", PdfVariant(static_cast(nRotation)) ); } PdfObject* PdfPage::GetAnnotationsArray( bool bCreate ) const { PdfObject* pObj; // check for it in the object itself if ( this->GetObject()->GetDictionary().HasKey( "Annots" ) ) { pObj = this->GetObject()->GetIndirectKey( "Annots" ); if( pObj && pObj->IsArray() ) return pObj; } else if( bCreate ) { PdfArray array; this->GetNonConstObject()->GetDictionary().AddKey( "Annots", array ); return const_cast(this->GetObject()->GetDictionary().GetKey( "Annots" )); } return NULL; } int PdfPage::GetNumAnnots() const { PdfObject* pObj = this->GetAnnotationsArray(); return pObj ? static_cast(pObj->GetArray().size()) : 0; } PdfAnnotation* PdfPage::CreateAnnotation( EPdfAnnotation eType, const PdfRect & rRect ) { PdfAnnotation* pAnnot = new PdfAnnotation( this, eType, rRect, this->GetObject()->GetOwner() ); PdfObject* pObj = this->GetAnnotationsArray( true ); PdfReference ref = pAnnot->GetObject()->Reference(); pObj->GetArray().push_back( ref ); m_mapAnnotations[ref] = pAnnot; return pAnnot; } PdfAnnotation* PdfPage::GetAnnotation( int index ) { PdfAnnotation* pAnnot; PdfReference ref; PdfObject* pObj = this->GetAnnotationsArray( false ); if( !(pObj && pObj->IsArray()) ) { PODOFO_RAISE_ERROR( ePdfError_InvalidDataType ); } if( index < 0 && static_cast(index) >= pObj->GetArray().size() ) { PODOFO_RAISE_ERROR( ePdfError_ValueOutOfRange ); } ref = pObj->GetArray()[index].GetReference(); pAnnot = m_mapAnnotations[ref]; if( !pAnnot ) { pObj = this->GetObject()->GetOwner()->GetObject( ref ); if( !pObj ) { PdfError::DebugMessage( "Error looking up object %i %i R\n", ref.ObjectNumber(), ref.GenerationNumber() ); PODOFO_RAISE_ERROR( ePdfError_NoObject ); } pAnnot = new PdfAnnotation( pObj, this ); m_mapAnnotations[ref] = pAnnot; } return pAnnot; } void PdfPage::DeleteAnnotation( int index ) { PdfReference ref; PdfObject* pObj = this->GetAnnotationsArray( false ); if( !(pObj && pObj->IsArray()) ) { PODOFO_RAISE_ERROR( ePdfError_InvalidDataType ); } if( index < 0 && static_cast(index) >= pObj->GetArray().size() ) { PODOFO_RAISE_ERROR( ePdfError_ValueOutOfRange ); } ref = pObj->GetArray()[index].GetReference(); this->DeleteAnnotation( ref ); } void PdfPage::DeleteAnnotation( const PdfReference & ref ) { PdfAnnotation* pAnnot; PdfArray::iterator it; PdfObject* pObj = this->GetAnnotationsArray( false ); bool bFound = false; // delete the annotation from the array if( !(pObj && pObj->IsArray()) ) { PODOFO_RAISE_ERROR( ePdfError_InvalidDataType ); } it = pObj->GetArray().begin(); while( it != pObj->GetArray().end() ) { if( (*it).GetReference() == ref ) { pObj->GetArray().erase( it ); bFound = true; break; } ++it; } // if no such annotation was found // throw an error instead of deleting // another object with this reference if( !bFound ) { PODOFO_RAISE_ERROR( ePdfError_NoObject ); } // delete any cached PdfAnnotations pAnnot = m_mapAnnotations[ref]; if( pAnnot ) { delete pAnnot; m_mapAnnotations.erase( ref ); } // delete the PdfObject in the file delete this->GetObject()->GetOwner()->RemoveObject( ref ); } // added by Petr P. Petrov 21 Febrary 2010 bool PdfPage::SetPageWidth(int newWidth) { PdfObject* pObjMediaBox; // Take advantage of inherited values - walking up the tree if necessary pObjMediaBox = const_cast(GetInheritedKeyFromObject( "MediaBox", this->GetObject() )); // assign the value of the box from the array if ( pObjMediaBox && pObjMediaBox->IsArray() ) { pObjMediaBox->GetArray()[2].SetNumber(newWidth); PdfObject* pObjCropBox; // Take advantage of inherited values - walking up the tree if necessary pObjCropBox = const_cast(GetInheritedKeyFromObject( "CropBox", this->GetObject() )); if ( pObjCropBox && pObjCropBox->IsArray() ) { pObjCropBox->GetArray()[2].SetNumber(newWidth); return true; }else { return false; } }else { return false; } } // added by Petr P. Petrov 21 Febrary 2010 bool PdfPage::SetPageHeight(int newHeight) { PdfObject* pObj; // Take advantage of inherited values - walking up the tree if necessary pObj = const_cast(GetInheritedKeyFromObject( "MediaBox", this->GetObject() )); // assign the value of the box from the array if ( pObj && pObj->IsArray() ) { pObj->GetArray()[3].SetNumber(newHeight); PdfObject* pObjCropBox; // Take advantage of inherited values - walking up the tree if necessary pObjCropBox = const_cast(GetInheritedKeyFromObject( "CropBox", this->GetObject() )); if ( pObjCropBox && pObjCropBox->IsArray() ) { pObjCropBox->GetArray()[3].SetNumber(newHeight); return true; }else { return false; } }else { return false; } } void PdfPage::SetTrimBox( const PdfRect & rSize ) { PdfVariant trimbox; rSize.ToVariant( trimbox ); this->GetObject()->GetDictionary().AddKey( "TrimBox", trimbox ); } unsigned int PdfPage::GetPageNumber() const { unsigned int nPageNumber = 0; PdfObject* pParent = this->GetObject()->GetIndirectKey( "Parent" ); PdfReference ref = this->GetObject()->Reference(); while( pParent ) { PdfObject* pKids = pParent->GetIndirectKey( "Kids" ); if ( pKids != NULL ) { const PdfArray& kids = pKids->GetArray(); PdfArray::const_iterator it = kids.begin(); while( it != kids.end() && (*it).GetReference() != ref ) { PdfObject* pNode = this->GetObject()->GetOwner()->GetObject( (*it).GetReference() ); if( pNode->GetDictionary().GetKey( PdfName::KeyType ) != NULL && pNode->GetDictionary().GetKey( PdfName::KeyType )->GetName() == PdfName( "Pages" ) ) { PdfObject* pCount = pNode->GetIndirectKey( "Count" ); if( pCount != NULL ) { nPageNumber += static_cast(pCount->GetNumber()); } } else { // if we do not have a page tree node, // we most likely have a page object: // so the page count is 1 ++nPageNumber; } ++it; } } ref = pParent->Reference(); pParent = pParent->GetIndirectKey( "Parent" ); } return ++nPageNumber; } int PdfPage::GetNumFields() const { int nCount = 0; int nAnnots = this->GetNumAnnots(); const PdfAnnotation* pAnnot = NULL; for( int i=0;i(this)->GetAnnotation( i ); // Count every widget annotation with a FieldType as PdfField if( pAnnot->GetType() == ePdfAnnotation_Widget ) ++nCount; } return nCount; } PdfField PdfPage::GetField( int index ) { int nCount = 0; int nAnnots = this->GetNumAnnots(); PdfAnnotation* pAnnot = NULL; for( int i=0;iGetAnnotation( i ); // Count every widget annotation with a FieldType as PdfField if( pAnnot->GetType() == ePdfAnnotation_Widget ) { if( nCount == index ) { return PdfField( pAnnot->GetObject(), pAnnot ); } else ++nCount; } } PODOFO_RAISE_ERROR( ePdfError_ValueOutOfRange ); } const PdfField PdfPage::GetField( int index ) const { PdfField field = const_cast(this)->GetField( index ); return field; } PdfObject* PdfPage::GetFromResources( const PdfName & rType, const PdfName & rKey ) { if( m_pResources->GetDictionary().HasKey( rType ) ) { // OC 15.08.2010 BugFix: Ghostscript creates here sometimes an indirect reference to a directory // PdfObject* pType = m_pResources->GetDictionary().GetKey( rType ); PdfObject* pType = m_pResources->GetIndirectKey( rType ); if( pType->IsDictionary() && pType->GetDictionary().HasKey( rKey ) ) { const PdfReference & ref = pType->GetDictionary().GetKey( rKey )->GetReference(); return this->GetObject()->GetOwner()->GetObject( ref ); } } return NULL; } PdfObject* PdfPage::GetOwnAnnotationsArray( bool bCreate, PdfDocument *pDocument) { PdfObject* pObj; if ( this->GetObject()->GetDictionary().HasKey( "Annots" ) ) { pObj = this->GetObject()->GetIndirectKey( "Annots" ); if(!pObj) { pObj = this->GetObject()->GetDictionary().GetKey("Annots"); if( pObj->IsReference() ) { if( !pDocument ) { PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidHandle, "Object is a reference but does not have an owner!" ); } pObj = pDocument->GetObjects()->GetObject( pObj->GetReference() ); if(pObj) { pObj->SetOwner(this->GetObject()->GetOwner()); } } else pObj->SetOwner( this->GetObject()->GetOwner() );// even directs might want an owner... } if( pObj && pObj->IsArray() ) return pObj; } else if( bCreate ) { PdfArray array; this->GetNonConstObject()->GetDictionary().AddKey( "Annots", array ); return const_cast(this->GetObject()->GetDictionary().GetKey( "Annots" )); } return NULL; } }; podofo-0.9.3/src/doc/PdfFontMetrics.h0000664000175000017500000005013712344436402017265 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2005 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_FONT_METRICS_H_ #define _PDF_FONT_METRICS_H_ #include "podofo/base/PdfDefines.h" #include "podofo/base/Pdf3rdPtyForwardDecl.h" #include "podofo/base/PdfString.h" namespace PoDoFo { class PdfArray; class PdfObject; class PdfVariant; /** * This abstract class provides access * to fontmetrics informations. */ class PODOFO_DOC_API PdfFontMetrics { public: PdfFontMetrics( EPdfFontType eFontType, const char* pszFilename, const char* pszSubsetPrefix ); virtual ~PdfFontMetrics(); /** Create a width array for this font which is a required part * of every font dictionary. * \param var the final width array is written to this PdfVariant * \param nFirst first character to be in the array * \param nLast last character code to be in the array */ virtual void GetWidthArray( PdfVariant & var, unsigned int nFirst, unsigned int nLast ) const = 0; /** Get the width of a single glyph id * * \param nGlyphId id of the glyph * \returns the width of a single glyph id */ virtual double GetGlyphWidth( int nGlyphId ) const = 0; /** Get the width of a single named glyph * * \param pszGlyphname name of the glyph * \returns the width of a single named glyph */ virtual double GetGlyphWidth( const char* pszGlyphname ) const = 0; /** Create the bounding box array as required by the PDF reference * so that it can be written directly to a PDF file. * * \param array write the bounding box to this array. */ virtual void GetBoundingBox( PdfArray & array ) const = 0; /** Retrieve the width of a given text string in PDF units when * drawn with the current font * \param rsString a PdfString from which the width shall be calculated * \returns the width in PDF units * * This is an overloaded method for your convinience! */ inline double StringWidth( const PdfString & rsString ) const; /** Retrieve the width of a given text string in PDF units when * drawn with the current font * \param pszText a text string of which the width should be calculated * \param nLength if != 0 only the width of the nLength first characters is calculated * \returns the width in PDF units */ double StringWidth( const char* pszText, pdf_long nLength = 0 ) const; /** Retrieve the width of a given text string in PDF units when * drawn with the current font * \param pszText a text string of which the width should be calculated * \param nLength if != 0 only the width of the nLength first characters is calculated * \returns the width in PDF units */ double StringWidth( const pdf_utf16be* pszText, unsigned int nLength = 0 ) const; #ifndef _WCHAR_T_DEFINED #if defined(_MSC_VER) && _MSC_VER <= 1200 // nicht fr Visualstudio 6 #else /** Retrieve the width of a given text string in PDF units when * drawn with the current font * \param pszText a text string of which the width should be calculated * \param nLength if != 0 only the width of the nLength first characters is calculated * \returns the width in PDF units */ double StringWidth( const wchar_t* pszText, unsigned int nLength = 0 ) const; #endif #endif /** Retrieve the width of a given text string in 1/1000th mm when * drawn with the current font * \param pszText a text string of which the width should be calculated * \param nLength if != 0 only the width of the nLength first characters is calculated * \returns the width in 1/1000th mm */ inline unsigned long StringWidthMM( const char* pszText, unsigned int nLength = 0 ) const; /** Retrieve the width of a given text string in 1/1000th mm when * drawn with the current font * \param pszText a text string of which the width should be calculated * \param nLength if != 0 only the width of the nLength first characters is calculated * \returns the width in 1/1000th mm */ inline unsigned long StringWidthMM( const pdf_utf16be* pszText, unsigned int nLength = 0 ) const; #ifndef _WCHAR_T_DEFINED #if defined(_MSC_VER) && _MSC_VER <= 1200 // nicht fr Visualstudio 6 #else /** Retrieve the width of a given text string in 1/1000th mm when * drawn with the current font * \param pszText a text string of which the width should be calculated * \param nLength if != 0 only the width of the nLength first characters is calculated * \returns the width in 1/1000th mm */ inline unsigned long StringWidthMM( const wchar_t* pszText, unsigned int nLength = 0 ) const; #endif #endif /** Retrieve the width of the given character in PDF units in the current font * \param c character * \returns the width in PDF units */ virtual double CharWidth( unsigned char c ) const = 0; // Peter Petrov 20 March 2009 /** Retrieve the width of the given character in PDF units in the current font * \param c character * \returns the width in PDF units */ virtual double UnicodeCharWidth( unsigned short c ) const = 0; /** Retrieve the width of the given character in 1/1000th mm in the current font * \param c character * \returns the width in 1/1000th mm */ inline unsigned long CharWidthMM( unsigned char c ) const; /** Retrieve the line spacing for this font * \returns the linespacing in PDF units */ virtual double GetLineSpacing() const = 0; /** Retrieve the line spacing for this font * \returns the linespacing in 1/1000th mm */ inline unsigned long GetLineSpacingMM() const; /** Get the width of the underline for the current * font size in PDF units * \returns the thickness of the underline in PDF units */ virtual double GetUnderlineThickness() const = 0; /** Get the width of the underline for the current * font size in 1/1000th mm * \returns the thickness of the underline in 1/1000th mm */ inline unsigned long GetUnderlineThicknessMM() const; /** Return the position of the underline for the current font * size in PDF units * \returns the underline position in PDF units */ virtual double GetUnderlinePosition() const = 0; /** Return the position of the underline for the current font * size in 1/1000th mm * \returns the underline position in 1/1000th mm */ inline long GetUnderlinePositionMM() const; /** Return the position of the strikeout for the current font * size in PDF units * \returns the underline position in PDF units */ virtual double GetStrikeOutPosition() const = 0; /** Return the position of the strikeout for the current font * size in 1/1000th mm * \returns the underline position in 1/1000th mm */ inline unsigned long GetStrikeOutPositionMM() const; /** Get the width of the strikeout for the current * font size in PDF units * \returns the thickness of the strikeout in PDF units */ virtual double GetStrikeoutThickness() const = 0; /** Get the width of the strikeout for the current * font size in 1/1000th mm * \returns the thickness of the strikeout in 1/1000th mm */ inline unsigned long GetStrikeoutThicknessMM() const; /** Get a pointer to the path of the font file. * \returns a zero terminated string containing the filename of the font file */ inline const char* GetFilename() const; /** Get a pointer to the actual font data - if it was loaded from memory. * \returns a binary buffer of data containing the font data */ virtual const char* GetFontData() const = 0; /** Get the length of the actual font data - if it was loaded from memory. * \returns a the length of the font data */ virtual pdf_long GetFontDataLen() const = 0; /** Get a string with the postscript name of the font. * \returns the postscript name of the font or NULL string if no postscript name is available. */ virtual const char* GetFontname() const = 0; /** * \returns NULL or a 6 uppercase letter and "+" sign prefix * used for font subsets */ inline const char* GetSubsetFontnamePrefix() const; /** Get the weight of this font. * Used to build the font dictionay * \returns the weight of this font (500 is normal). */ virtual unsigned int GetWeight() const = 0; /** Get the ascent of this font in PDF * units for the current font size. * * \returns the ascender for this font * * \see GetPdfAscent */ virtual double GetAscent() const = 0; /** Get the ascent of this font * Used to build the font dictionay * \returns the ascender for this font * * \see GetAscent */ virtual double GetPdfAscent() const = 0; /** Get the descent of this font in PDF * units for the current font size. * This value is usually negative! * * \returns the descender for this font * * \see GetPdfDescent */ virtual double GetDescent() const = 0; /** Get the descent of this font * Used to build the font dictionay * \returns the descender for this font * * \see GetDescent */ virtual double GetPdfDescent() const = 0; /** Get the italic angle of this font. * Used to build the font dictionay * \returns the italic angle of this font. */ virtual int GetItalicAngle() const = 0; /** Set the font size of this metrics object for width and height * calculations. * This is typically called from PdfFont for you. * * \param fSize font size in points */ inline void SetFontSize( float fSize ); /** Retrieve the current font size of this metrics object * \returns the current font size */ inline float GetFontSize() const; /** Set the horizontal scaling of the font for compressing (< 100) and expanding (>100) * This is typically called from PdfFont for you. * * \param fScale scaling in percent */ inline void SetFontScale( float fScale ); /** Retrieve the current horizontal scaling of this metrics object * \returns the current font scaling */ inline float GetFontScale() const; /** Set the character spacing of this metrics object * \param fCharSpace character spacing in percent */ inline void SetFontCharSpace( float fCharSpace ); /** Retrieve the current character spacing of this metrics object * \returns the current font character spacing */ inline float GetFontCharSpace() const; /** Set the word spacing of this metrics object * \param fWordSpace word spacing in PDF units */ inline void SetWordSpace( float fWordSpace ); /** Retrieve the current word spacing of this metrics object * \returns the current font word spacing in PDF units */ inline float GetWordSpace() const; /** * \returns the fonttype of the loaded font */ inline EPdfFontType GetFontType() const; /** Get the glyph id for a unicode character * in the current font. * * \param lUnicode the unicode character value * \returns the glyhph id for the character or 0 if the glyph was not found. */ virtual long GetGlyphId( long lUnicode ) const = 0; /** Symbol fonts do need special treatment in a few cases. * Use this method to check if the current font is a symbol * font. Symbold fonts are detected by checking * if they use FT_ENCODING_MS_SYMBOL as internal encoding. * * \returns true if this is a symbol font */ virtual bool IsSymbol() const = 0; /** Try to detect the internal fonttype from * the file extension of a fontfile. * * \param pszFilename must be the filename of a font file * * \return font type */ static EPdfFontType FontTypeFromFilename( const char* pszFilename ); protected: /** * Set the fonttype. * \param eFontType fonttype */ inline void SetFontType(EPdfFontType eFontType); protected: std::string m_sFilename; float m_fFontSize; float m_fFontScale; float m_fFontCharSpace; float m_fWordSpace; std::vector m_vecWidth; EPdfFontType m_eFontType; std::string m_sFontSubsetPrefix; }; // ----------------------------------------------------- // // ----------------------------------------------------- unsigned long PdfFontMetrics::CharWidthMM( unsigned char c ) const { return static_cast(this->CharWidth( c ) / PODOFO_CONVERSION_CONSTANT); } // ----------------------------------------------------- // // ----------------------------------------------------- double PdfFontMetrics::StringWidth( const PdfString & rsString ) const { return (rsString.IsUnicode() ? this->StringWidth( rsString.GetUnicode() ) : this->StringWidth( rsString.GetString() )); } // ----------------------------------------------------- // // ----------------------------------------------------- unsigned long PdfFontMetrics::StringWidthMM( const char* pszText, unsigned int nLength ) const { return static_cast(this->StringWidth( pszText, nLength ) / PODOFO_CONVERSION_CONSTANT); } // ----------------------------------------------------- // // ----------------------------------------------------- unsigned long PdfFontMetrics::StringWidthMM( const pdf_utf16be* pszText, unsigned int nLength ) const { return static_cast(this->StringWidth( pszText, nLength ) / PODOFO_CONVERSION_CONSTANT); } // ----------------------------------------------------- // // ----------------------------------------------------- #ifndef _WCHAR_T_DEFINED #if defined(_MSC_VER) && _MSC_VER <= 1200 // nicht fr Visualstudio 6 #else unsigned long PdfFontMetrics::StringWidthMM( const wchar_t* pszText, unsigned int nLength ) const { return static_cast(this->StringWidth( pszText, nLength ) / PODOFO_CONVERSION_CONSTANT); } #endif #endif // ----------------------------------------------------- // // ----------------------------------------------------- unsigned long PdfFontMetrics::GetLineSpacingMM() const { return static_cast(this->GetLineSpacing() / PODOFO_CONVERSION_CONSTANT); } // ----------------------------------------------------- // // ----------------------------------------------------- long PdfFontMetrics::GetUnderlinePositionMM() const { return static_cast(this->GetUnderlinePosition() / PODOFO_CONVERSION_CONSTANT); } // ----------------------------------------------------- // // ----------------------------------------------------- unsigned long PdfFontMetrics::GetStrikeOutPositionMM() const { return static_cast(this->GetStrikeOutPosition() / PODOFO_CONVERSION_CONSTANT); } // ----------------------------------------------------- // // ----------------------------------------------------- unsigned long PdfFontMetrics::GetUnderlineThicknessMM() const { return static_cast(this->GetUnderlineThickness() / PODOFO_CONVERSION_CONSTANT); } // ----------------------------------------------------- // // ----------------------------------------------------- unsigned long PdfFontMetrics::GetStrikeoutThicknessMM() const { return static_cast(this->GetStrikeoutThickness() / PODOFO_CONVERSION_CONSTANT); } // ----------------------------------------------------- // // ----------------------------------------------------- const char* PdfFontMetrics::GetFilename() const { return m_sFilename.c_str(); } // ----------------------------------------------------- // // ----------------------------------------------------- EPdfFontType PdfFontMetrics::GetFontType() const { return m_eFontType; } // ----------------------------------------------------- // // ----------------------------------------------------- void PdfFontMetrics::SetFontType(EPdfFontType eFontType) { m_eFontType = eFontType; } // ----------------------------------------------------- // // ----------------------------------------------------- float PdfFontMetrics::GetFontSize() const { return m_fFontSize; } // ----------------------------------------------------- // // ----------------------------------------------------- void PdfFontMetrics::SetFontSize( float fSize ) { m_fFontSize = fSize; } // ----------------------------------------------------- // // ----------------------------------------------------- float PdfFontMetrics::GetFontScale() const { return m_fFontScale; } // ----------------------------------------------------- // // ----------------------------------------------------- float PdfFontMetrics::GetFontCharSpace() const { return m_fFontCharSpace; } // ----------------------------------------------------- // // ----------------------------------------------------- inline float PdfFontMetrics::GetWordSpace() const { return m_fWordSpace; } // ----------------------------------------------------- // // ----------------------------------------------------- const char* PdfFontMetrics::GetSubsetFontnamePrefix() const { return m_sFontSubsetPrefix.c_str(); } // ----------------------------------------------------- // // ----------------------------------------------------- void PdfFontMetrics::SetFontScale( float fScale ) { m_fFontScale = fScale; } // ----------------------------------------------------- // // ----------------------------------------------------- void PdfFontMetrics::SetFontCharSpace( float fCharSpace ) { m_fFontCharSpace = fCharSpace; } // ----------------------------------------------------- // // ----------------------------------------------------- inline void PdfFontMetrics::SetWordSpace( float fWordSpace ) { m_fWordSpace = fWordSpace; } }; #endif // _PDF_FONT_METRICS_H_ podofo-0.9.3/src/doc/PdfFontConfigWrapper.h0000664000175000017500000001202712344436402020421 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2011 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_FONT_CONFIG_WRAPPER_H_ #define _PDF_FONT_CONFIG_WRAPPER_H_ #include "podofo/base/PdfDefines.h" #include "podofo/base/Pdf3rdPtyForwardDecl.h" #include "podofo/base/util/PdfMutex.h" namespace PoDoFo { /** * This class initializes and destroys the FontConfig library. * * As initializing fontconfig can take a long time, you * can create a wrapper by yourself to cache initialization of * fontconfig. * * This class is reference counted. The last user of the fontconfig library * will destroy the fontconfig handle. * * The fontconfig library is initialized on first used (lazy loading!) */ class PODOFO_DOC_API PdfFontConfigWrapper { public: /** * Create a new FontConfigWrapper and initialize the fontconfig library. */ PdfFontConfigWrapper(); /** * Copy an existing PdfFontConfigWrapper */ PdfFontConfigWrapper(const PdfFontConfigWrapper & rhs); ~PdfFontConfigWrapper(); /** * Get access to the internal fontconfig handle. * Accesses to this handle have to be synchronized using a mutex! * * \see GetFontConfigMutex * * \returns a FcConfig handle (you can cast to FcConfig) */ inline void * GetFontConfig(); #if defined(PODOFO_HAVE_FONTCONFIG) /** * Mutex which has to be used to synchronize uses of FontConfig */ inline Util::PdfMutex & GetFontConfigMutex(); #endif const PdfFontConfigWrapper & operator=(const PdfFontConfigWrapper & rhs); private: /** * Destroy fontconfig reference if reference count is 0 */ void DerefBuffer(); /** * Do the lazy initialization of fontconfig */ void InitializeFontConfig(); private: #if defined(PODOFO_HAVE_FONTCONFIG) static Util::PdfMutex m_FcMutex; #endif struct TRefCountedFontConfig { void* m_pFcConfig; ///< Handle to fontconfig on unix systems long m_lRefCount; bool m_bInitialized; ///< Is fontconfig initialized yet? }; TRefCountedFontConfig* m_pFontConfig; }; // ----------------------------------------------------- // // ----------------------------------------------------- void* PdfFontConfigWrapper::GetFontConfig() { if( m_pFontConfig != NULL ) { InitializeFontConfig(); return m_pFontConfig->m_pFcConfig; } else { return NULL; } } #if defined(PODOFO_HAVE_FONTCONFIG) // ----------------------------------------------------- // // ----------------------------------------------------- Util::PdfMutex & PdfFontConfigWrapper::GetFontConfigMutex() { return m_FcMutex; } #endif }; // PoDoFo #endif // _PDF_FONT_WRAPPER_H_ podofo-0.9.3/src/doc/PdfSignatureField.h0000664000175000017500000000743612262234754017746 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2011 by Dominik Seichter * * domseichter@web.de * * by Petr Pytelka * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_SIGNATURE_FIELD_H_ #define _PDF_SIGNATURE_FIELD_H_ #include "PdfField.h" #include "podofo/base/PdfDate.h" namespace PoDoFo { /** Signature field */ class PODOFO_DOC_API PdfSignatureField :public PdfField { protected: PdfObject* m_pSignatureObj; void Init(); public: /** Create a new PdfSignatureField */ PdfSignatureField( PdfPage* pPage, const PdfRect & rRect, PdfDocument* pDoc ); PdfSignatureField( PdfAnnotation* pWidget, PdfAcroForm* pParent, PdfDocument* pDoc); void SetAppearanceStream(PdfXObject *pObject); /** Create space for signature * * \param signatureData String used to locate reserved space for signature. * This string will be replaiced with signature. * * Structure of the PDF file - before signing: * < * Have to be replaiced with the following structure: * < */ void SetSignature(const PdfData &signatureData); /** Set reason of the signature * * \param rsText the reason of signature */ void SetSignatureReason(const PdfString & rsText); /** Date of signature */ void SetSignatureDate(const PdfDate &sigDate); }; } #endif podofo-0.9.3/src/doc/PdfSigIncPainter.cpp0000664000175000017500000001457512262234754020075 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2014 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #if defined(_MSC_VER) && _MSC_VER <= 1200 #pragma warning(disable: 4786) #endif #include "base/PdfObject.h" #include "base/PdfStream.h" #include "base/PdfCanvas.h" #include "PdfDocument.h" #include "PdfSigIncPainter.h" using namespace std; namespace PoDoFo { PdfSigIncPainter::PdfSigIncPainter(PdfDocument *pDocument, bool bLinear) : PdfPainter() { m_pDocument = pDocument; m_bLinearized = bLinear; } PdfSigIncPainter::~PdfSigIncPainter() { } void PdfSigIncPainter::SetPageCanvas( PdfCanvas *pPage, PdfObject* pContents ) { if(m_bLinearized) { SetPage(pPage); return; } if( m_pPage != pPage ) { if( m_pCanvas ) m_pCanvas->EndAppend(); m_pPage = pPage; } EndCanvas(); m_pCanvas = pContents->GetStream(); if ( m_pCanvas ) { m_pCanvas->BeginAppend( false ); if ( m_pCanvas->GetLength() ) { m_pCanvas->Append( " " ); } } else { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } } void PdfSigIncPainter::EndCanvas() { if(m_bLinearized) return; try { if( m_pCanvas ) m_pCanvas->EndAppend(); } catch( const PdfError & e ) { // clean up, even in case of error m_pCanvas = NULL; throw e; } m_pCanvas = NULL; } void PdfSigIncPainter::AddToPageResources( const PdfName & rIdentifier, const PdfReference & rRef, const PdfName & rName ) { if(m_bLinearized) PdfPainter::AddToPageResources(rIdentifier, rRef, rName); /*Pro podpis nedavat font do stranky, ale do XObject resources*/ return; } void PdfSigIncPainter::DrawMultiLineText( const PdfRect & rRect, const PdfString & rsText, EPdfAlignment eAlignment, EPdfVerticalAlignment eVertical) { PODOFO_RAISE_LOGIC_IF( !m_pCanvas, "Call SetPage() first before doing drawing operations." ); double dX = rRect.GetLeft(); double dY = rRect.GetBottom(); double dWidth = rRect.GetWidth(); double dHeight = rRect.GetHeight(); if( !m_pFont || !m_pPage || !rsText.IsValid() ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } m_pFont->EmbedFont(); if( dWidth <= 0.0 || dHeight <= 0.0 ) // nonsense arguments return; this->Save(); this->SetClipRect( dX, dY, dWidth, dHeight ); PdfString sString = this->ExpandTabs( rsText, rsText.GetCharacterLength() ); if(sString.IsUnicode()) { vector > vecLines = GetMultiLineTextAsLines(sString.GetUnicode(), dWidth); DrawMultiLineText(dX, dY, dWidth, dHeight, eAlignment, eVertical, vecLines); } else { vector > vecLines = GetMultiLineTextAsLines(sString.GetString(), dWidth); DrawMultiLineText(dX, dY, dWidth, dHeight, eAlignment, eVertical, vecLines); } this->Restore(); } int PdfSigIncPainter::IsLf(const char *pszChar) { return *pszChar == '\n'; } int PdfSigIncPainter::IsSpace(const char *pszChar) { return isspace( static_cast(static_cast(*pszChar))); } int PdfSigIncPainter::IsLf(const pdf_utf16be *pszChar) { const pdf_utf16be cLf = 0x0a00; return *pszChar == cLf; } int PdfSigIncPainter::IsSpace(const pdf_utf16be *pszChar) { const pdf_utf16be cTab = 0x0900; const pdf_utf16be cSpace = 0x2000; const pdf_utf16be cLf = 0x0a00; const pdf_utf16be cVt = 0x0b00; const pdf_utf16be cFeed = 0x0c00; const pdf_utf16be cCr = 0x0d00; if(*pszChar == cTab || *pszChar == cSpace || *pszChar == cLf || *pszChar == cVt || *pszChar == cFeed || *pszChar == cCr) return 1; return 0; } double PdfSigIncPainter::GetFontCharWidth(const pdf_utf16be *pszChar) { if( !m_pFont) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } return m_pFont->GetFontMetrics()->UnicodeCharWidth( *pszChar); } double PdfSigIncPainter::GetFontCharWidth(const char *pszChar) { if( !m_pFont) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } return m_pFont->GetFontMetrics()->UnicodeCharWidth(*pszChar); } }; podofo-0.9.3/src/doc/PdfFontType3.cpp0000664000175000017500000000626012347347566017233 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2005 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfFontType3.h" #include "base/PdfDefinesPrivate.h" #include "base/PdfArray.h" #include "base/PdfDictionary.h" #include "base/PdfName.h" #include "base/PdfStream.h" namespace PoDoFo { PdfFontType3::PdfFontType3( PdfFontMetrics* pMetrics, const PdfEncoding* const pEncoding, PdfVecObjects* pParent, bool bEmbed ) : PdfFontSimple( pMetrics, pEncoding, pParent ) { this->Init( bEmbed, PdfName("Type3") ); } PdfFontType3::PdfFontType3( PdfFontMetrics* pMetrics, const PdfEncoding* const pEncoding, PdfObject* pObject ) : PdfFontSimple( pMetrics, pEncoding, pObject ) { } void PdfFontType3::EmbedFontFile( PdfObject* /*pDescriptor*/ ) { PODOFO_RAISE_ERROR( ePdfError_UnsupportedFontFormat ); } }; podofo-0.9.3/src/doc/PdfSigIncPainter.h0000664000175000017500000002250612262234754017533 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2014 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_SIGINCPAINTER_H_ #define _PDF_SIGINCPAINTER_H_ #include "podofo/base/PdfDefines.h" #include "PdfPainter.h" namespace PoDoFo { template struct TExLineElement { TExLineElement() : pszStart( NULL ), lLen( 0L ) { } const T* pszStart; pdf_long lLen; }; class PdfPainter; class PODOFO_DOC_API PdfSigIncPainter : public PdfPainter { public: PdfSigIncPainter(PdfDocument *pDocument, bool bLinear); virtual ~PdfSigIncPainter(); void SetPageCanvas(PdfCanvas *pPage, PdfObject* pContents ); void EndCanvas(); void DrawMultiLineText( const PdfRect & rRect, const PdfString & rsText, EPdfAlignment eAlignment = ePdfAlignment_Left, EPdfVerticalAlignment eVertical=ePdfVerticalAlignment_Top); protected: int IsSpace(const char *pszChar); int IsLf(const char *pszChar); int IsSpace(const pdf_utf16be *pszChar); int IsLf(const pdf_utf16be *pszChar); double GetFontCharWidth(const char *pszChar); double GetFontCharWidth(const pdf_utf16be *pszChar); virtual void AddToPageResources( const PdfName & rIdentifier, const PdfReference & rRef, const PdfName & rName ); template void DrawMultiLineText(double dX, double dY, double dWidth, double dHeight, EPdfAlignment eAlignment, EPdfVerticalAlignment eVertical, const std::vector< TExLineElement > &vecLines) { // Do vertical alignment switch( eVertical ) { default: case ePdfVerticalAlignment_Top: dY += dHeight; break; case ePdfVerticalAlignment_Bottom: dY += m_pFont->GetFontMetrics()->GetLineSpacing() * vecLines.size(); break; case ePdfVerticalAlignment_Center: dY += (dHeight - ((dHeight - (m_pFont->GetFontMetrics()->GetLineSpacing() * vecLines.size()))/2.0)); break; } typedef typename std::vector< TExLineElement >::const_iterator TExLineElementVectorIterator; TExLineElementVectorIterator it = vecLines.begin(); while( it != vecLines.end() ) { dY -= m_pFont->GetFontMetrics()->GetLineSpacing(); if( (*it).pszStart ) this->DrawTextAligned( dX, dY, dWidth, PdfString( (*it).pszStart, (*it).lLen ), eAlignment ); ++it; } } template std::vector > GetMultiLineTextAsLines(const T *mainText, double dWidth) { PODOFO_RAISE_LOGIC_IF( !m_pCanvas, "Call SetPage() first before doing drawing operations." ); if( !m_pFont || !m_pPage || mainText == NULL ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } std::vector > vecLines; if( dWidth <= 0.0 ) // nonsense arguments return vecLines; TExLineElement tLine; tLine.pszStart = mainText; const T* pszCurrentCharacter = tLine.pszStart; const T* pszStartOfCurrentWord = tLine.pszStart; bool startOfWord = true; double dCurWidthOfLine = 0.0; // do simple word wrapping while( *pszCurrentCharacter ) { if( IsLf(pszCurrentCharacter) ) // hard-break! { tLine.lLen = pszCurrentCharacter - tLine.pszStart; vecLines.push_back( tLine ); ++pszCurrentCharacter; // skip the line feed tLine.pszStart = pszCurrentCharacter; startOfWord = true; dCurWidthOfLine = 0.0; } else if(IsSpace(pszCurrentCharacter)) { if( dCurWidthOfLine > dWidth ) { // The previous word does not fit in the current line. // -> Move it to the next one. tLine.lLen = pszStartOfCurrentWord - tLine.pszStart; vecLines.push_back( tLine ); tLine.pszStart = pszStartOfCurrentWord; if (!startOfWord) { dCurWidthOfLine = m_pFont->GetFontMetrics()->StringWidth( pszStartOfCurrentWord, pszCurrentCharacter-pszStartOfCurrentWord ); } else { dCurWidthOfLine = 0.0; } } else { dCurWidthOfLine += GetFontCharWidth(pszCurrentCharacter ); } startOfWord = true; } else { if (startOfWord) { pszStartOfCurrentWord = pszCurrentCharacter; startOfWord = false; } //else do nothing if ((dCurWidthOfLine + GetFontCharWidth(pszCurrentCharacter )) > dWidth) { if ( tLine.pszStart == pszStartOfCurrentWord ) { // This word takes up the whole line. // Put as much as possible on this line. tLine.lLen = pszCurrentCharacter - tLine.pszStart; vecLines.push_back( tLine ); tLine.pszStart = pszCurrentCharacter; pszStartOfCurrentWord = pszCurrentCharacter; dCurWidthOfLine = GetFontCharWidth(pszCurrentCharacter ); } else { // The current word does not fit in the current line. // -> Move it to the next one. tLine.lLen = pszStartOfCurrentWord - tLine.pszStart; vecLines.push_back( tLine ); tLine.pszStart = pszStartOfCurrentWord; dCurWidthOfLine = m_pFont->GetFontMetrics()->StringWidth( pszStartOfCurrentWord, (pszCurrentCharacter-pszStartOfCurrentWord) + 1 ); } } else { dCurWidthOfLine +=GetFontCharWidth(pszCurrentCharacter ); } } ++pszCurrentCharacter; } if( pszCurrentCharacter-tLine.pszStart > 0 ) { if( dCurWidthOfLine > dWidth ) { // The previous word does not fit in the current line. // -> Move it to the next one. tLine.lLen = pszStartOfCurrentWord - tLine.pszStart; vecLines.push_back( tLine ); tLine.pszStart = pszStartOfCurrentWord; } //else do nothing if( pszCurrentCharacter-tLine.pszStart > 0 ) { tLine.lLen = pszCurrentCharacter - tLine.pszStart; vecLines.push_back( tLine ); } //else do nothing } return vecLines; } private: PdfDocument *m_pDocument; bool m_bLinearized; }; }; #endif podofo-0.9.3/src/doc/PdfFunction.h0000664000175000017500000002514112344436402016612 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2007 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_FUNCTION_H_ #define _PDF_FUNCTION_H_ #include "podofo/base/PdfDefines.h" #include "PdfElement.h" #include namespace PoDoFo { class PdfArray; /** * The function type of a mathematical function in a PDF file. */ enum EPdfFunctionType { ePdfFunctionType_Sampled = 0, ///< A sampled function (Type1) ePdfFunctionType_Exponential = 2, ///< An exponential interpolation function (Type2) ePdfFunctionType_Stitching = 3, ///< A stitching function (Type3) ePdfFunctionType_PostScript = 4 ///< A PostScript calculator function (Type4) }; /** * This class defines a PdfFunction. * A function can be used in various ways in a PDF file. * Examples are device dependent rasterization for high quality * printing or color transformation functions for certain colorspaces. */ class PODOFO_DOC_API PdfFunction : public PdfElement { public: typedef std::list List; typedef std::list Sample; virtual ~PdfFunction(); protected: /** Create a new PdfFunction object. * * \param eType the function type * \param rDomain this array describes the input parameters of this PdfFunction. If this * function has m input parameters, this array has to contain 2*m numbers * where each number describes either the lower or upper boundary of the input range. * \param pParent parent vector of objects * */ PdfFunction( EPdfFunctionType eType, const PdfArray & rDomain, PdfVecObjects* pParent ); /** Create a new PdfFunction object. * * \param eType the function type * \param rDomain this array describes the input parameters of this PdfFunction. If this * function has m input parameters, this array has to contain 2*m numbers * where each number describes either the lower or upper boundary of the input range. * \param pParent parent document * */ PdfFunction( EPdfFunctionType eType, const PdfArray & rDomain, PdfDocument* pParent ); private: /** Initialize this object. * * \param eType the function type * \param rDomain this array describes the input parameters of this PdfFunction. If this * function has m input parameters, this array has to contain 2*m numbers * where each number describes either the lower or upper boundary of the input range. */ void Init( EPdfFunctionType eType, const PdfArray & rDomain ); }; /** This class is a PdfSampledFunction. */ class PODOFO_DOC_API PdfSampledFunction : public PdfFunction { public: /** Create a new PdfSampledFunction object. * * \param rDomain this array describes the input parameters of this PdfFunction. If this * function has m input parameters, this array has to contain 2*m numbers * where each number describes either the lower or upper boundary of the input range. * \param rRange this array describes the output parameters of this PdfFunction. If this * function has n input parameters, this array has to contain 2*n numbers * where each number describes either the lower or upper boundary of the output range. * \param rlstSamples a list of bytes which are used to build up this function sample data * \param pParent parent vector of objects */ PdfSampledFunction( const PdfArray & rDomain, const PdfArray & rRange, const PdfFunction::Sample & rlstSamples, PdfVecObjects* pParent ); /** Create a new PdfSampledFunction object. * * \param rDomain this array describes the input parameters of this PdfFunction. If this * function has m input parameters, this array has to contain 2*m numbers * where each number describes either the lower or upper boundary of the input range. * \param rRange this array describes the output parameters of this PdfFunction. If this * function has n input parameters, this array has to contain 2*n numbers * where each number describes either the lower or upper boundary of the output range. * \param rlstSamples a list of bytes which are used to build up this function sample data * \param pParent parent document */ PdfSampledFunction( const PdfArray & rDomain, const PdfArray & rRange, const PdfFunction::Sample & rlstSamples, PdfDocument* pParent ); private: /** Initialize this object. */ void Init( const PdfArray & rDomain, const PdfArray & rRange, const PdfFunction::Sample & rlstSamples ); }; /** This class is a PdfExponentialFunction. */ class PODOFO_DOC_API PdfExponentialFunction : public PdfFunction { public: /** Create a new PdfExponentialFunction object. * * \param rDomain this array describes the input parameters of this PdfFunction. If this * function has m input parameters, this array has to contain 2*m numbers * where each number describes either the lower or upper boundary of the input range. * \param rC0 * \param rC1 * \param dExponent * \param pParent parent vector of objects */ PdfExponentialFunction( const PdfArray & rDomain, const PdfArray & rC0, const PdfArray & rC1, double dExponent, PdfVecObjects* pParent ); /** Create a new PdfExponentialFunction object. * * \param rDomain this array describes the input parameters of this PdfFunction. If this * function has m input parameters, this array has to contain 2*m numbers * where each number describes either the lower or upper boundary of the input range. * \param rC0 * \param rC1 * \param dExponent * \param pParent parent document */ PdfExponentialFunction( const PdfArray & rDomain, const PdfArray & rC0, const PdfArray & rC1, double dExponent, PdfDocument* pParent ); private: /** Initialize this object. */ void Init( const PdfArray & rC0, const PdfArray & rC1, double dExponent ); }; /** This class is a PdfStitchingFunction, i.e. a PdfFunction that combines * more than one PdfFunction into one. * * It combines several PdfFunctions that take 1 input parameter to * a new PdfFunction taking again only 1 input parameter. */ class PODOFO_DOC_API PdfStitchingFunction : public PdfFunction { public: /** Create a new PdfStitchingFunction object. * * \param rlstFunctions a list of functions which are used to built up this function object * \param rDomain this array describes the input parameters of this PdfFunction. If this * function has m input parameters, this array has to contain 2*m numbers * where each number describes either the lower or upper boundary of the input range. * \param rBounds the bounds array * \param rEncode the encode array * \param pParent parent vector of objects * */ PdfStitchingFunction( const PdfFunction::List & rlstFunctions, const PdfArray & rDomain, const PdfArray & rBounds, const PdfArray & rEncode, PdfVecObjects* pParent ); /** Create a new PdfStitchingFunction object. * * \param rlstFunctions a list of functions which are used to built up this function object * \param rDomain this array describes the input parameters of this PdfFunction. If this * function has m input parameters, this array has to contain 2*m numbers * where each number describes either the lower or upper boundary of the input range. * \param rBounds the bounds array * \param rEncode the encode array * \param pParent parent document * */ PdfStitchingFunction( const PdfFunction::List & rlstFunctions, const PdfArray & rDomain, const PdfArray & rBounds, const PdfArray & rEncode, PdfDocument* pParent ); private: /** Initialize this object. * * \param rlstFunctions a list of functions which are used to built up this function object * \param rBounds the bounds array * \param rEncode the encode array */ void Init( const PdfFunction::List & rlstFunctions, const PdfArray & rBounds, const PdfArray & rEncode ); }; }; #endif // _PDF_FUNCTION_H_ podofo-0.9.3/src/doc/PdfPainterMM.cpp0000664000175000017500000000524512322532431017212 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2010 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfPainterMM.h" #include "base/PdfDefinesPrivate.h" namespace PoDoFo { /* Defining the virtual destructor here rather than in the header * ensures that the vtable gets output correctly by all compilers. */ PdfPainterMM::~PdfPainterMM() { } }; podofo-0.9.3/src/doc/PdfFontCID.cpp0000664000175000017500000005127212347317314016615 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2007 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfFontCID.h" #include "base/PdfDefinesPrivate.h" #include "base/PdfArray.h" #include "base/PdfDictionary.h" #include "base/PdfEncoding.h" #include "base/PdfLocale.h" #include "base/PdfName.h" #include "base/PdfStream.h" #include "PdfFontMetricsFreetype.h" #include "PdfFontTTFSubset.h" #include "base/PdfInputDevice.h" #include "base/PdfOutputDevice.h" #include #include FT_FREETYPE_H #include namespace PoDoFo { struct TBFRange { int srcCode; std::vector vecDest; }; PdfFontCID::PdfFontCID( PdfFontMetrics* pMetrics, const PdfEncoding* const pEncoding, PdfObject* pObject, bool ) : PdfFont( pMetrics, pEncoding, pObject ), m_pDescendantFonts( NULL ) { /* this->Init( bEmbed, false ); */ } PdfFontCID::PdfFontCID( PdfFontMetrics* pMetrics, const PdfEncoding* const pEncoding, PdfVecObjects* pParent, bool bEmbed, bool bSubset ) : PdfFont( pMetrics, pEncoding, pParent ), m_pDescendantFonts( NULL ) { this->Init( bEmbed, bSubset ); } void PdfFontCID::Init( bool bEmbed, bool bSubset ) { PdfObject* pDescriptor; PdfObject* pCIDSystemInfo; PdfObject* pUnicode; PdfVariant var; PdfArray array; // The descendant font is a CIDFont: m_pDescendantFonts = this->GetObject()->GetOwner()->CreateObject("Font"); pCIDSystemInfo = this->GetObject()->GetOwner()->CreateObject(); pDescriptor = this->GetObject()->GetOwner()->CreateObject("FontDescriptor"); pUnicode = this->GetObject()->GetOwner()->CreateObject(); // The ToUnicode CMap // Now setting each of the entries of the font this->GetObject()->GetDictionary().AddKey( PdfName::KeySubtype, PdfName("Type0") ); this->GetObject()->GetDictionary().AddKey( "BaseFont", this->GetBaseFont() ); this->GetObject()->GetDictionary().AddKey( "ToUnicode", pUnicode->Reference() ); // The encoding is here usually a (Predefined) CMap from PdfIdentityEncoding: m_pEncoding->AddToDictionary( this->GetObject()->GetDictionary() ); // The DecendantFonts, should be an indirect object: array.push_back( m_pDescendantFonts->Reference() ); this->GetObject()->GetDictionary().AddKey( "DescendantFonts", array ); // Setting the DescendantFonts paras // This is a type2 CIDFont, which is also known as TrueType: m_pDescendantFonts->GetDictionary().AddKey( PdfName::KeySubtype, PdfName("CIDFontType2") ); // Same base font as the owner font: m_pDescendantFonts->GetDictionary().AddKey( "BaseFont", this->GetBaseFont() ); // The CIDSystemInfo, should be an indirect object: m_pDescendantFonts->GetDictionary().AddKey( "CIDSystemInfo", pCIDSystemInfo->Reference() ); // The FontDescriptor, should be an indirect object: m_pDescendantFonts->GetDictionary().AddKey( "FontDescriptor", pDescriptor->Reference() ); m_pDescendantFonts->GetDictionary().AddKey( "CIDToGIDMap", PdfName("Identity") ); // Add the width keys this->CreateWidth( m_pDescendantFonts ); // Create the ToUnicode CMap this->CreateCMap( pUnicode ); // Setting the CIDSystemInfo paras: pCIDSystemInfo->GetDictionary().AddKey( "Registry", PdfString("Adobe") ); pCIDSystemInfo->GetDictionary().AddKey( "Ordering", PdfString("Identity") ); pCIDSystemInfo->GetDictionary().AddKey( "Supplement", PdfVariant(static_cast(PODOFO_LL_LITERAL(0))) ); // Setting the FontDescriptor paras: array.Clear(); m_pMetrics->GetBoundingBox( array ); pDescriptor->GetDictionary().AddKey( "FontName", this->GetBaseFont() ); pDescriptor->GetDictionary().AddKey( PdfName::KeyFlags, PdfVariant( static_cast(PODOFO_LL_LITERAL(32)) ) ); // TODO: 0 ???? pDescriptor->GetDictionary().AddKey( "FontBBox", array ); pDescriptor->GetDictionary().AddKey( "ItalicAngle", PdfVariant( static_cast(m_pMetrics->GetItalicAngle()) ) ); pDescriptor->GetDictionary().AddKey( "Ascent", m_pMetrics->GetPdfAscent() ); pDescriptor->GetDictionary().AddKey( "Descent", m_pMetrics->GetPdfDescent() ); pDescriptor->GetDictionary().AddKey( "CapHeight", m_pMetrics->GetPdfAscent() ); // m_pMetrics->CapHeight() ); pDescriptor->GetDictionary().AddKey( "StemV", PdfVariant( static_cast(PODOFO_LL_LITERAL(1)) ) ); // m_pMetrics->StemV() ); // Peter Petrov 24 September 2008 m_pDescriptor = pDescriptor; m_bIsSubsetting = bSubset; if( bEmbed && !bSubset) { this->EmbedFont( pDescriptor ); m_bWasEmbedded = true; } else if (!bEmbed) { // it's not asked to be embedded, thus mark as embedded already, to not do that at PdfFontCID::EmbedFont() m_bWasEmbedded = true; } } void PdfFontCID::EmbedFont() { if (!m_bWasEmbedded) { this->EmbedFont( m_pDescriptor ); m_bWasEmbedded = true; } } void PdfFontCID::EmbedSubsetFont() { EmbedFont(); } void PdfFontCID::AddUsedSubsettingGlyphs (const PdfString &sText, long lStringLen) { if (IsSubsetting()) { PODOFO_ASSERT( sText.IsUnicode() ); const pdf_utf16be *uniChars = sText.GetUnicode(); for (long ii = 0; ii < lStringLen; ii++) { m_setUsed.insert(uniChars[ii]); } } } void PdfFontCID::EmbedFont( PdfObject* pDescriptor ) { bool fallback = true; m_bWasEmbedded = true; if (IsSubsetting() && !m_setUsed.empty()) { PdfFontMetrics *metrics = GetFontMetrics2(); if (metrics && metrics->GetFontDataLen() && metrics->GetFontData()) { PdfInputDevice input(metrics->GetFontData(), metrics->GetFontDataLen()); PdfRefCountedBuffer buffer; PdfOutputDevice output(&buffer); PdfFontTTFSubset subset(&input, metrics, PdfFontTTFSubset::eFontFileType_TTF); std::set::const_iterator it, end = m_setUsed.end(); for (it = m_setUsed.begin(); it != end; it++) { subset.AddCharacter(*it); } subset.BuildFont( &output ); PdfObject *pContents; pContents = this->GetObject()->GetOwner()->CreateObject(); if( !pContents ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } pDescriptor->GetDictionary().AddKey( "FontFile2", pContents->Reference() ); pdf_long lSize = buffer.GetSize(); pContents->GetDictionary().AddKey("Length1", PdfVariant(static_cast(lSize))); pContents->GetStream()->Set(buffer.GetBuffer(), lSize); fallback = false; } } if (fallback) { PdfObject* pContents; pdf_long lSize = 0; pContents = this->GetObject()->GetOwner()->CreateObject(); if( !pContents ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } pDescriptor->GetDictionary().AddKey( "FontFile2", pContents->Reference() ); // if the data was loaded from memory - use it from there // otherwise, load from disk if ( m_pMetrics->GetFontDataLen() && m_pMetrics->GetFontData() ) { // FIXME const_cast is dangerous if string literals may ever be passed char* pBuffer = const_cast( m_pMetrics->GetFontData() ); lSize = m_pMetrics->GetFontDataLen(); // Set Length1 before creating the stream // as PdfStreamedDocument does not allow // adding keys to an object after a stream was written pContents->GetDictionary().AddKey( "Length1", PdfVariant( static_cast(lSize) ) ); pContents->GetStream()->Set( pBuffer, lSize ); } else { PdfFileInputStream stream( m_pMetrics->GetFilename() ); lSize = stream.GetFileLength(); // Set Length1 before creating the stream // as PdfStreamedDocument does not allow // adding keys to an object after a stream was written pContents->GetDictionary().AddKey( "Length1", PdfVariant( static_cast(lSize) ) ); pContents->GetStream()->Set( &stream ); } } } void PdfFontCID::CreateWidth( PdfObject* pFontDict ) const { const int cAbsoluteMax = 0xffff; int nFirstChar = m_pEncoding->GetFirstChar(); int nLastChar = m_pEncoding->GetLastChar(); int i; // Allocate an initialize an array, large enough to // hold a width value for every possible glyph index double* pdWidth = static_cast(malloc( sizeof(double) * cAbsoluteMax ) ); if( !pdWidth ) { PODOFO_RAISE_ERROR( ePdfError_OutOfMemory ); } for( i=0;iGetGlyphId( i ); if( lGlyph ) { nMin = PDF_MIN( static_cast(nMin), lGlyph ); nMax = PDF_MAX( static_cast(nMax), lGlyph ); nMax = PDF_MIN( nMax, cAbsoluteMax ); if( lGlyph < cAbsoluteMax ) pdWidth[lGlyph] = m_pMetrics->GetGlyphWidth( lGlyph ); } } if (nMax >= nMin) { // Now compact the array std::ostringstream oss; PdfArray array; array.reserve( nMax - nMin + 1 ); i = nMin; double dCurWidth = pdWidth[i]; pdf_int64 lCurIndex = i++; pdf_int64 lCurLength = 1L; for( ;i<=nMax;i++ ) { if( static_cast(pdWidth[i] - dCurWidth) == 0 ) ++lCurLength; else { if( lCurLength > 1 ) { array.push_back( lCurIndex ); pdf_int64 temp = lCurIndex + lCurLength - 1; array.push_back( temp ); array.push_back( dCurWidth ); } else { if( array.size() && array.back().IsArray() ) { array.back().GetArray().push_back( dCurWidth ); } else { PdfArray tmp; tmp.push_back( dCurWidth ); array.push_back( lCurIndex ); array.push_back( tmp ); } } lCurIndex = i; lCurLength = 1L; dCurWidth = pdWidth[i]; } } if (array.size() == 0) { array.push_back( lCurIndex = nMin ); array.push_back( lCurIndex = nMax ); array.push_back( dCurWidth ); } pFontDict->GetDictionary().AddKey( PdfName("W"), array ); } free( pdWidth ); } void PdfFontCID::CreateCMap( PdfObject* pUnicode ) const { PdfFontMetricsFreetype* pFreetype = dynamic_cast(m_pMetrics); if (!pFreetype) return; int nFirstChar = m_pEncoding->GetFirstChar(); int nLastChar = m_pEncoding->GetLastChar(); std::ostringstream oss; FT_Face face = pFreetype->GetFace(); FT_ULong charcode; FT_UInt gindex; TBFRange curRange; curRange.srcCode = -1; std::vector vecRanges; // Only 255 sequent characters are allowed to be in one range! const unsigned int MAX_CHARS_IN_RANGE = 255; charcode = FT_Get_First_Char( face, &gindex ); while ( gindex != 0 ) { if( static_cast(charcode) > nLastChar ) { break; } else if( static_cast(charcode) >= nFirstChar ) { if( curRange.vecDest.size() == 0 ) { curRange.srcCode = gindex; curRange.vecDest.push_back( charcode ); } else if( (curRange.srcCode + curRange.vecDest.size() == gindex) && ((gindex - curRange.srcCode + curRange.vecDest.size()) < MAX_CHARS_IN_RANGE) ) { curRange.vecDest.push_back( charcode ); } else { // Create a new bfrange vecRanges.push_back( curRange ); curRange.srcCode = gindex; curRange.vecDest.clear(); curRange.vecDest.push_back( charcode ); } } charcode = FT_Get_Next_Char( face, charcode, &gindex ); } if( curRange.vecDest.size() ) vecRanges.push_back( curRange ); // Now transform it into a string // Make sure each bfrange section has a maximum of // 100 entries. If there are more Acrobat Reader might crash std::ostringstream range; int numberOfEntries = 0; std::vector::const_iterator it = vecRanges.begin(); const int BUFFER_LEN = 5; char buffer[BUFFER_LEN]; // buffer of the format "XXXX\0" while( it != vecRanges.end() ) { if( numberOfEntries == 99 ) { oss << numberOfEntries << " beginbfrange" << std::endl; oss << range.str(); oss << "endbfrange" << std::endl; numberOfEntries = 0; range.str(""); } pdf_long iStart = (*it).srcCode; pdf_long iEnd = (*it).srcCode + (*it).vecDest.size() - 1; snprintf( buffer, BUFFER_LEN, "%04X", static_cast(iStart) ); range << "<" << buffer << "> <"; snprintf( buffer, BUFFER_LEN, "%04X", static_cast(iEnd) ); range << buffer << "> [ "; std::vector::const_iterator it2 = (*it).vecDest.begin(); while( it2 != (*it).vecDest.end() ) { snprintf( buffer, BUFFER_LEN, "%04X", *it2 ); range << "<" << buffer << "> "; ++it2; } range << "]" << std::endl; ++it; ++numberOfEntries; } if( numberOfEntries > 0 ) { oss << numberOfEntries << " beginbfrange" << std::endl; oss << range.str(); oss << "endbfrange" << std::endl; } /* // Create the beginbfchar section std::ostringstream oss; std::ostringstream tmp; const int BUFFER_LEN = 14; char buffer[BUFFER_LEN]; // buffer of the format " \0" bool bLittle = podofo_is_little_endian(); int nCount = 1; while( nFirstChar <= nLastChar ) { lGlyph = m_pMetrics->GetGlyphId( nFirstChar ); if( lGlyph && lGlyph <= 0xffff) { if( bLittle ) snprintf( buffer, BUFFER_LEN, "<%04X> <%04X>", static_cast(lGlyph), ((nFirstChar & 0xff00) >> 8) | ((nFirstChar & 0x00ff) << 8) ); else snprintf( buffer, BUFFER_LEN, "<%04X> <%04X>", static_cast(lGlyph), nFirstChar ); tmp << buffer << std::endl; if( nCount % 100 == 0 ) { // There can be at maximum 100 lines in a bfchar section oss << nCount - 1 << " beginbfchar" << std::endl << tmp.str() << "endbfchar" << std::endl; tmp.str(""); // clear the stream nCount = 0; } ++nCount; } ++nFirstChar; } if( nCount > 1 ) oss << nCount - 1 << " beginbfchar" << std::endl << tmp.str() << "endbfchar" << std::endl; */ // Create the CMap pUnicode->GetStream()->BeginAppend(); pUnicode->GetStream()->Append("/CIDInit /ProcSet findresource begin\n"); pUnicode->GetStream()->Append("10000 dict begin\n"); pUnicode->GetStream()->Append("begincmap\n"); pUnicode->GetStream()->Append("/CIDSystemInfo\n"); pUnicode->GetStream()->Append("<< /Registry (Adobe)\n"); pUnicode->GetStream()->Append("/Ordering (UCS)\n"); pUnicode->GetStream()->Append("/Supplement 0\n"); pUnicode->GetStream()->Append(">> def\n"); pUnicode->GetStream()->Append("/CMapName /Adobe-Identity-UCS def\n"); pUnicode->GetStream()->Append("/CMapType 2 def\n"); pUnicode->GetStream()->Append("1 begincodespacerange\n"); pUnicode->GetStream()->Append("<0000> \n"); pUnicode->GetStream()->Append("endcodespacerange\n"); pUnicode->GetStream()->Append( oss.str().c_str() ); pUnicode->GetStream()->Append("endcmap\n"); pUnicode->GetStream()->Append("CMapName currentdict /CMap defineresource pop\n"); pUnicode->GetStream()->Append("end\n"); pUnicode->GetStream()->Append("end\n"); pUnicode->GetStream()->EndAppend(); } /* // Get the string in UTF-16be format PdfString sStr = rsString.ToUnicode(); const pdf_utf16be* pStr = sStr.GetUnicode(); long lGlyphId; const bool bLittle = podofo_is_little_endian(); std::ostringstream out; PdfLocaleImbue(out); out << "<"; while( *pStr ) { //printf("Current byte: %04x\n", *pStr ); if( bLittle ) lGlyphId = m_pMetrics->GetGlyphId( (((*pStr & 0xff) << 8) | ((*pStr & 0xff00) >> 8)) ); else lGlyphId = m_pMetrics->GetGlyphId( *pStr ); out << ToHex( (lGlyphId & 0xf000) >> 12 ) << ToHex( (lGlyphId & 0x0f00) >> 8 ); out << ToHex( (lGlyphId & 0xf0) >> 4 ) << ToHex( lGlyphId & 0x0f ); ++pStr; } out << ">"; pStream->Append( out.str().c_str(), out.str().length() ); */ void PdfFontCID::MaybeUpdateBaseFontKey(void) { if (!m_pDescendantFonts) { return; } const PdfFontMetricsFreetype *pFreetype = dynamic_cast(this->GetFontMetrics()); if (!pFreetype) { return; } std::string name = this->GetBaseFont().GetName(); if (this->IsBold() && this->IsItalic()) { if (pFreetype->IsBold() && pFreetype->IsItalic()) { return; } if (pFreetype->IsBold() && !pFreetype->IsItalic()) { name += ",Italic"; } else if (!pFreetype->IsBold() && pFreetype->IsItalic()) { name += ",Bold"; } else { name += ",BoldItalic"; } } else if (this->IsBold()) { if (pFreetype->IsBold()) { return; } name += ",Bold"; } else if (this->IsItalic()) { if (pFreetype->IsItalic()) { return; } name += ",Italic"; } else { return; } m_pDescendantFonts->GetDictionary().AddKey("BaseFont", PdfName( name ) ); } void PdfFontCID::SetBold( bool bBold ) { PdfFont::SetBold(bBold); MaybeUpdateBaseFontKey(); } void PdfFontCID::SetItalic( bool bItalic ) { PdfFont::SetItalic(bItalic); MaybeUpdateBaseFontKey(); } }; podofo-0.9.3/src/doc/PdfFontFactoryBase14Data.h0000664000175000017500000032422112344436402021016 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2010 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_FONT_FACTORY_BASE14_DATA_H_ #define _PDF_FONT_FACTORY_BASE14_DATA_H_ #include "podofo/base/PdfDefines.h" #include "podofo/base/PdfRect.h" #include "PdfFontMetricsBase14.h" /* * The following are the Base 14 fonts data copied from libharu. * - kaushik April 12 2010 */ namespace PoDoFo { struct PODOFO_CharData { pdf_int16 char_cd; pdf_uint16 unicode; pdf_int16 width; } ; static const PODOFO_CharData CHAR_DATA_COURIER[316] = { {32, 0x0020, 600}, {33, 0x0021, 600}, {34, 0x0022, 600}, {35, 0x0023, 600}, {36, 0x0024, 600}, {37, 0x0025, 600}, {38, 0x0026, 600}, {39, 0x2019, 600}, {40, 0x0028, 600}, {41, 0x0029, 600}, {42, 0x002A, 600}, {43, 0x002B, 600}, {44, 0x002C, 600}, {45, 0x002D, 600}, {46, 0x002E, 600}, {47, 0x002F, 600}, {48, 0x0030, 600}, {49, 0x0031, 600}, {50, 0x0032, 600}, {51, 0x0033, 600}, {52, 0x0034, 600}, {53, 0x0035, 600}, {54, 0x0036, 600}, {55, 0x0037, 600}, {56, 0x0038, 600}, {57, 0x0039, 600}, {58, 0x003A, 600}, {59, 0x003B, 600}, {60, 0x003C, 600}, {61, 0x003D, 600}, {62, 0x003E, 600}, {63, 0x003F, 600}, {64, 0x0040, 600}, {65, 0x0041, 600}, {66, 0x0042, 600}, {67, 0x0043, 600}, {68, 0x0044, 600}, {69, 0x0045, 600}, {70, 0x0046, 600}, {71, 0x0047, 600}, {72, 0x0048, 600}, {73, 0x0049, 600}, {74, 0x004A, 600}, {75, 0x004B, 600}, {76, 0x004C, 600}, {77, 0x004D, 600}, {78, 0x004E, 600}, {79, 0x004F, 600}, {80, 0x0050, 600}, {81, 0x0051, 600}, {82, 0x0052, 600}, {83, 0x0053, 600}, {84, 0x0054, 600}, {85, 0x0055, 600}, {86, 0x0056, 600}, {87, 0x0057, 600}, {88, 0x0058, 600}, {89, 0x0059, 600}, {90, 0x005A, 600}, {91, 0x005B, 600}, {92, 0x005C, 600}, {93, 0x005D, 600}, {94, 0x005E, 600}, {95, 0x005F, 600}, {96, 0x2018, 600}, {97, 0x0061, 600}, {98, 0x0062, 600}, {99, 0x0063, 600}, {100, 0x0064, 600}, {101, 0x0065, 600}, {102, 0x0066, 600}, {103, 0x0067, 600}, {104, 0x0068, 600}, {105, 0x0069, 600}, {106, 0x006A, 600}, {107, 0x006B, 600}, {108, 0x006C, 600}, {109, 0x006D, 600}, {110, 0x006E, 600}, {111, 0x006F, 600}, {112, 0x0070, 600}, {113, 0x0071, 600}, {114, 0x0072, 600}, {115, 0x0073, 600}, {116, 0x0074, 600}, {117, 0x0075, 600}, {118, 0x0076, 600}, {119, 0x0077, 600}, {120, 0x0078, 600}, {121, 0x0079, 600}, {122, 0x007A, 600}, {123, 0x007B, 600}, {124, 0x007C, 600}, {125, 0x007D, 600}, {126, 0x007E, 600}, {161, 0x00A1, 600}, {162, 0x00A2, 600}, {163, 0x00A3, 600}, {164, 0x2044, 600}, {165, 0x00A5, 600}, {166, 0x0192, 600}, {167, 0x00A7, 600}, {168, 0x00A4, 600}, {169, 0x0027, 600}, {170, 0x201C, 600}, {171, 0x00AB, 600}, {172, 0x2039, 600}, {173, 0x203A, 600}, {174, 0xFB01, 600}, {175, 0xFB02, 600}, {177, 0x2013, 600}, {178, 0x2020, 600}, {179, 0x2021, 600}, {180, 0x00B7, 600}, {182, 0x00B6, 600}, {183, 0x2022, 600}, {184, 0x201A, 600}, {185, 0x201E, 600}, {186, 0x201D, 600}, {187, 0x00BB, 600}, {188, 0x2026, 600}, {189, 0x2030, 600}, {191, 0x00BF, 600}, {193, 0x0060, 600}, {194, 0x00B4, 600}, {195, 0x02C6, 600}, {196, 0x02DC, 600}, {197, 0x00AF, 600}, {198, 0x02D8, 600}, {199, 0x02D9, 600}, {200, 0x00A8, 600}, {202, 0x02DA, 600}, {203, 0x00B8, 600}, {205, 0x02DD, 600}, {206, 0x02DB, 600}, {207, 0x02C7, 600}, {208, 0x2014, 600}, {225, 0x00C6, 600}, {227, 0x00AA, 600}, {232, 0x0141, 600}, {233, 0x00D8, 600}, {234, 0x0152, 600}, {235, 0x00BA, 600}, {241, 0x00E6, 600}, {245, 0x0131, 600}, {248, 0x0142, 600}, {249, 0x00F8, 600}, {250, 0x0153, 600}, {251, 0x00DF, 600}, {-1, 0x00CF, 600}, {-1, 0x00E9, 600}, {-1, 0x0103, 600}, {-1, 0x0171, 600}, {-1, 0x011B, 600}, {-1, 0x0178, 600}, {-1, 0x00F7, 600}, {-1, 0x00DD, 600}, {-1, 0x00C2, 600}, {-1, 0x00E1, 600}, {-1, 0x00DB, 600}, {-1, 0x00FD, 600}, {-1, 0x0219, 600}, {-1, 0x00EA, 600}, {-1, 0x016E, 600}, {-1, 0x00DC, 600}, {-1, 0x0105, 600}, {-1, 0x00DA, 600}, {-1, 0x0173, 600}, {-1, 0x00CB, 600}, {-1, 0x0110, 600}, {-1, 0xF6C3, 600}, {-1, 0x00A9, 600}, {-1, 0x0112, 600}, {-1, 0x010D, 600}, {-1, 0x00E5, 600}, {-1, 0x0145, 600}, {-1, 0x013A, 600}, {-1, 0x00E0, 600}, {-1, 0x0162, 600}, {-1, 0x0106, 600}, {-1, 0x00E3, 600}, {-1, 0x0116, 600}, {-1, 0x0161, 600}, {-1, 0x015F, 600}, {-1, 0x00ED, 600}, {-1, 0x25CA, 600}, {-1, 0x0158, 600}, {-1, 0x0122, 600}, {-1, 0x00FB, 600}, {-1, 0x00E2, 600}, {-1, 0x0100, 600}, {-1, 0x0159, 600}, {-1, 0x00E7, 600}, {-1, 0x017B, 600}, {-1, 0x00DE, 600}, {-1, 0x014C, 600}, {-1, 0x0154, 600}, {-1, 0x015A, 600}, {-1, 0x010F, 600}, {-1, 0x016A, 600}, {-1, 0x016F, 600}, {-1, 0x00B3, 600}, {-1, 0x00D2, 600}, {-1, 0x00C0, 600}, {-1, 0x0102, 600}, {-1, 0x00D7, 600}, {-1, 0x00FA, 600}, {-1, 0x0164, 600}, {-1, 0x2202, 600}, {-1, 0x00FF, 600}, {-1, 0x0143, 600}, {-1, 0x00EE, 600}, {-1, 0x00CA, 600}, {-1, 0x00E4, 600}, {-1, 0x00EB, 600}, {-1, 0x0107, 600}, {-1, 0x0144, 600}, {-1, 0x016B, 600}, {-1, 0x0147, 600}, {-1, 0x00CD, 600}, {-1, 0x00B1, 600}, {-1, 0x00A6, 600}, {-1, 0x00AE, 600}, {-1, 0x011E, 600}, {-1, 0x0130, 600}, {-1, 0x2211, 600}, {-1, 0x00C8, 600}, {-1, 0x0155, 600}, {-1, 0x014D, 600}, {-1, 0x0179, 600}, {-1, 0x017D, 600}, {-1, 0x2265, 600}, {-1, 0x00D0, 600}, {-1, 0x00C7, 600}, {-1, 0x013C, 600}, {-1, 0x0165, 600}, {-1, 0x0119, 600}, {-1, 0x0172, 600}, {-1, 0x00C1, 600}, {-1, 0x00C4, 600}, {-1, 0x00E8, 600}, {-1, 0x017A, 600}, {-1, 0x012F, 600}, {-1, 0x00D3, 600}, {-1, 0x00F3, 600}, {-1, 0x0101, 600}, {-1, 0x015B, 600}, {-1, 0x00EF, 600}, {-1, 0x00D4, 600}, {-1, 0x00D9, 600}, {-1, 0x0394, 600}, {-1, 0x00FE, 600}, {-1, 0x00B2, 600}, {-1, 0x00D6, 600}, {-1, 0x00B5, 600}, {-1, 0x00EC, 600}, {-1, 0x0151, 600}, {-1, 0x0118, 600}, {-1, 0x0111, 600}, {-1, 0x00BE, 600}, {-1, 0x015E, 600}, {-1, 0x013E, 600}, {-1, 0x0136, 600}, {-1, 0x0139, 600}, {-1, 0x2122, 600}, {-1, 0x0117, 600}, {-1, 0x00CC, 600}, {-1, 0x012A, 600}, {-1, 0x013D, 600}, {-1, 0x00BD, 600}, {-1, 0x2264, 600}, {-1, 0x00F4, 600}, {-1, 0x00F1, 600}, {-1, 0x0170, 600}, {-1, 0x00C9, 600}, {-1, 0x0113, 600}, {-1, 0x011F, 600}, {-1, 0x00BC, 600}, {-1, 0x0160, 600}, {-1, 0x0218, 600}, {-1, 0x0150, 600}, {-1, 0x00B0, 600}, {-1, 0x00F2, 600}, {-1, 0x010C, 600}, {-1, 0x00F9, 600}, {-1, 0x221A, 600}, {-1, 0x010E, 600}, {-1, 0x0157, 600}, {-1, 0x00D1, 600}, {-1, 0x00F5, 600}, {-1, 0x0156, 600}, {-1, 0x013B, 600}, {-1, 0x00C3, 600}, {-1, 0x0104, 600}, {-1, 0x00C5, 600}, {-1, 0x00D5, 600}, {-1, 0x017C, 600}, {-1, 0x011A, 600}, {-1, 0x012E, 600}, {-1, 0x0137, 600}, {-1, 0x2212, 600}, {-1, 0x00CE, 600}, {-1, 0x0148, 600}, {-1, 0x0163, 600}, {-1, 0x00AC, 600}, {-1, 0x00F6, 600}, {-1, 0x00FC, 600}, {-1, 0x2260, 600}, {-1, 0x0123, 600}, {-1, 0x00F0, 600}, {-1, 0x017E, 600}, {-1, 0x0146, 600}, {-1, 0x00B9, 600}, {-1, 0x012B, 600}, {-1, 0x20AC, 600}, {-1, 0xFFFF, 0} }; static const PODOFO_CharData CHAR_DATA_COURIER_BOLD[316] = { {32, 0x0020, 600}, {33, 0x0021, 600}, {34, 0x0022, 600}, {35, 0x0023, 600}, {36, 0x0024, 600}, {37, 0x0025, 600}, {38, 0x0026, 600}, {39, 0x2019, 600}, {40, 0x0028, 600}, {41, 0x0029, 600}, {42, 0x002A, 600}, {43, 0x002B, 600}, {44, 0x002C, 600}, {45, 0x002D, 600}, {46, 0x002E, 600}, {47, 0x002F, 600}, {48, 0x0030, 600}, {49, 0x0031, 600}, {50, 0x0032, 600}, {51, 0x0033, 600}, {52, 0x0034, 600}, {53, 0x0035, 600}, {54, 0x0036, 600}, {55, 0x0037, 600}, {56, 0x0038, 600}, {57, 0x0039, 600}, {58, 0x003A, 600}, {59, 0x003B, 600}, {60, 0x003C, 600}, {61, 0x003D, 600}, {62, 0x003E, 600}, {63, 0x003F, 600}, {64, 0x0040, 600}, {65, 0x0041, 600}, {66, 0x0042, 600}, {67, 0x0043, 600}, {68, 0x0044, 600}, {69, 0x0045, 600}, {70, 0x0046, 600}, {71, 0x0047, 600}, {72, 0x0048, 600}, {73, 0x0049, 600}, {74, 0x004A, 600}, {75, 0x004B, 600}, {76, 0x004C, 600}, {77, 0x004D, 600}, {78, 0x004E, 600}, {79, 0x004F, 600}, {80, 0x0050, 600}, {81, 0x0051, 600}, {82, 0x0052, 600}, {83, 0x0053, 600}, {84, 0x0054, 600}, {85, 0x0055, 600}, {86, 0x0056, 600}, {87, 0x0057, 600}, {88, 0x0058, 600}, {89, 0x0059, 600}, {90, 0x005A, 600}, {91, 0x005B, 600}, {92, 0x005C, 600}, {93, 0x005D, 600}, {94, 0x005E, 600}, {95, 0x005F, 600}, {96, 0x2018, 600}, {97, 0x0061, 600}, {98, 0x0062, 600}, {99, 0x0063, 600}, {100, 0x0064, 600}, {101, 0x0065, 600}, {102, 0x0066, 600}, {103, 0x0067, 600}, {104, 0x0068, 600}, {105, 0x0069, 600}, {106, 0x006A, 600}, {107, 0x006B, 600}, {108, 0x006C, 600}, {109, 0x006D, 600}, {110, 0x006E, 600}, {111, 0x006F, 600}, {112, 0x0070, 600}, {113, 0x0071, 600}, {114, 0x0072, 600}, {115, 0x0073, 600}, {116, 0x0074, 600}, {117, 0x0075, 600}, {118, 0x0076, 600}, {119, 0x0077, 600}, {120, 0x0078, 600}, {121, 0x0079, 600}, {122, 0x007A, 600}, {123, 0x007B, 600}, {124, 0x007C, 600}, {125, 0x007D, 600}, {126, 0x007E, 600}, {161, 0x00A1, 600}, {162, 0x00A2, 600}, {163, 0x00A3, 600}, {164, 0x2044, 600}, {165, 0x00A5, 600}, {166, 0x0192, 600}, {167, 0x00A7, 600}, {168, 0x00A4, 600}, {169, 0x0027, 600}, {170, 0x201C, 600}, {171, 0x00AB, 600}, {172, 0x2039, 600}, {173, 0x203A, 600}, {174, 0xFB01, 600}, {175, 0xFB02, 600}, {177, 0x2013, 600}, {178, 0x2020, 600}, {179, 0x2021, 600}, {180, 0x00B7, 600}, {182, 0x00B6, 600}, {183, 0x2022, 600}, {184, 0x201A, 600}, {185, 0x201E, 600}, {186, 0x201D, 600}, {187, 0x00BB, 600}, {188, 0x2026, 600}, {189, 0x2030, 600}, {191, 0x00BF, 600}, {193, 0x0060, 600}, {194, 0x00B4, 600}, {195, 0x02C6, 600}, {196, 0x02DC, 600}, {197, 0x00AF, 600}, {198, 0x02D8, 600}, {199, 0x02D9, 600}, {200, 0x00A8, 600}, {202, 0x02DA, 600}, {203, 0x00B8, 600}, {205, 0x02DD, 600}, {206, 0x02DB, 600}, {207, 0x02C7, 600}, {208, 0x2014, 600}, {225, 0x00C6, 600}, {227, 0x00AA, 600}, {232, 0x0141, 600}, {233, 0x00D8, 600}, {234, 0x0152, 600}, {235, 0x00BA, 600}, {241, 0x00E6, 600}, {245, 0x0131, 600}, {248, 0x0142, 600}, {249, 0x00F8, 600}, {250, 0x0153, 600}, {251, 0x00DF, 600}, {-1, 0x00CF, 600}, {-1, 0x00E9, 600}, {-1, 0x0103, 600}, {-1, 0x0171, 600}, {-1, 0x011B, 600}, {-1, 0x0178, 600}, {-1, 0x00F7, 600}, {-1, 0x00DD, 600}, {-1, 0x00C2, 600}, {-1, 0x00E1, 600}, {-1, 0x00DB, 600}, {-1, 0x00FD, 600}, {-1, 0x0219, 600}, {-1, 0x00EA, 600}, {-1, 0x016E, 600}, {-1, 0x00DC, 600}, {-1, 0x0105, 600}, {-1, 0x00DA, 600}, {-1, 0x0173, 600}, {-1, 0x00CB, 600}, {-1, 0x0110, 600}, {-1, 0xF6C3, 600}, {-1, 0x00A9, 600}, {-1, 0x0112, 600}, {-1, 0x010D, 600}, {-1, 0x00E5, 600}, {-1, 0x0145, 600}, {-1, 0x013A, 600}, {-1, 0x00E0, 600}, {-1, 0x0162, 600}, {-1, 0x0106, 600}, {-1, 0x00E3, 600}, {-1, 0x0116, 600}, {-1, 0x0161, 600}, {-1, 0x015F, 600}, {-1, 0x00ED, 600}, {-1, 0x25CA, 600}, {-1, 0x0158, 600}, {-1, 0x0122, 600}, {-1, 0x00FB, 600}, {-1, 0x00E2, 600}, {-1, 0x0100, 600}, {-1, 0x0159, 600}, {-1, 0x00E7, 600}, {-1, 0x017B, 600}, {-1, 0x00DE, 600}, {-1, 0x014C, 600}, {-1, 0x0154, 600}, {-1, 0x015A, 600}, {-1, 0x010F, 600}, {-1, 0x016A, 600}, {-1, 0x016F, 600}, {-1, 0x00B3, 600}, {-1, 0x00D2, 600}, {-1, 0x00C0, 600}, {-1, 0x0102, 600}, {-1, 0x00D7, 600}, {-1, 0x00FA, 600}, {-1, 0x0164, 600}, {-1, 0x2202, 600}, {-1, 0x00FF, 600}, {-1, 0x0143, 600}, {-1, 0x00EE, 600}, {-1, 0x00CA, 600}, {-1, 0x00E4, 600}, {-1, 0x00EB, 600}, {-1, 0x0107, 600}, {-1, 0x0144, 600}, {-1, 0x016B, 600}, {-1, 0x0147, 600}, {-1, 0x00CD, 600}, {-1, 0x00B1, 600}, {-1, 0x00A6, 600}, {-1, 0x00AE, 600}, {-1, 0x011E, 600}, {-1, 0x0130, 600}, {-1, 0x2211, 600}, {-1, 0x00C8, 600}, {-1, 0x0155, 600}, {-1, 0x014D, 600}, {-1, 0x0179, 600}, {-1, 0x017D, 600}, {-1, 0x2265, 600}, {-1, 0x00D0, 600}, {-1, 0x00C7, 600}, {-1, 0x013C, 600}, {-1, 0x0165, 600}, {-1, 0x0119, 600}, {-1, 0x0172, 600}, {-1, 0x00C1, 600}, {-1, 0x00C4, 600}, {-1, 0x00E8, 600}, {-1, 0x017A, 600}, {-1, 0x012F, 600}, {-1, 0x00D3, 600}, {-1, 0x00F3, 600}, {-1, 0x0101, 600}, {-1, 0x015B, 600}, {-1, 0x00EF, 600}, {-1, 0x00D4, 600}, {-1, 0x00D9, 600}, {-1, 0x0394, 600}, {-1, 0x00FE, 600}, {-1, 0x00B2, 600}, {-1, 0x00D6, 600}, {-1, 0x00B5, 600}, {-1, 0x00EC, 600}, {-1, 0x0151, 600}, {-1, 0x0118, 600}, {-1, 0x0111, 600}, {-1, 0x00BE, 600}, {-1, 0x015E, 600}, {-1, 0x013E, 600}, {-1, 0x0136, 600}, {-1, 0x0139, 600}, {-1, 0x2122, 600}, {-1, 0x0117, 600}, {-1, 0x00CC, 600}, {-1, 0x012A, 600}, {-1, 0x013D, 600}, {-1, 0x00BD, 600}, {-1, 0x2264, 600}, {-1, 0x00F4, 600}, {-1, 0x00F1, 600}, {-1, 0x0170, 600}, {-1, 0x00C9, 600}, {-1, 0x0113, 600}, {-1, 0x011F, 600}, {-1, 0x00BC, 600}, {-1, 0x0160, 600}, {-1, 0x0218, 600}, {-1, 0x0150, 600}, {-1, 0x00B0, 600}, {-1, 0x00F2, 600}, {-1, 0x010C, 600}, {-1, 0x00F9, 600}, {-1, 0x221A, 600}, {-1, 0x010E, 600}, {-1, 0x0157, 600}, {-1, 0x00D1, 600}, {-1, 0x00F5, 600}, {-1, 0x0156, 600}, {-1, 0x013B, 600}, {-1, 0x00C3, 600}, {-1, 0x0104, 600}, {-1, 0x00C5, 600}, {-1, 0x00D5, 600}, {-1, 0x017C, 600}, {-1, 0x011A, 600}, {-1, 0x012E, 600}, {-1, 0x0137, 600}, {-1, 0x2212, 600}, {-1, 0x00CE, 600}, {-1, 0x0148, 600}, {-1, 0x0163, 600}, {-1, 0x00AC, 600}, {-1, 0x00F6, 600}, {-1, 0x00FC, 600}, {-1, 0x2260, 600}, {-1, 0x0123, 600}, {-1, 0x00F0, 600}, {-1, 0x017E, 600}, {-1, 0x0146, 600}, {-1, 0x00B9, 600}, {-1, 0x012B, 600}, {-1, 0x20AC, 600}, {-1, 0xFFFF, 0} }; static const PODOFO_CharData CHAR_DATA_COURIER_BOLD_OBLIQUE[316] = { {32, 0x0020, 600}, {33, 0x0021, 600}, {34, 0x0022, 600}, {35, 0x0023, 600}, {36, 0x0024, 600}, {37, 0x0025, 600}, {38, 0x0026, 600}, {39, 0x2019, 600}, {40, 0x0028, 600}, {41, 0x0029, 600}, {42, 0x002A, 600}, {43, 0x002B, 600}, {44, 0x002C, 600}, {45, 0x002D, 600}, {46, 0x002E, 600}, {47, 0x002F, 600}, {48, 0x0030, 600}, {49, 0x0031, 600}, {50, 0x0032, 600}, {51, 0x0033, 600}, {52, 0x0034, 600}, {53, 0x0035, 600}, {54, 0x0036, 600}, {55, 0x0037, 600}, {56, 0x0038, 600}, {57, 0x0039, 600}, {58, 0x003A, 600}, {59, 0x003B, 600}, {60, 0x003C, 600}, {61, 0x003D, 600}, {62, 0x003E, 600}, {63, 0x003F, 600}, {64, 0x0040, 600}, {65, 0x0041, 600}, {66, 0x0042, 600}, {67, 0x0043, 600}, {68, 0x0044, 600}, {69, 0x0045, 600}, {70, 0x0046, 600}, {71, 0x0047, 600}, {72, 0x0048, 600}, {73, 0x0049, 600}, {74, 0x004A, 600}, {75, 0x004B, 600}, {76, 0x004C, 600}, {77, 0x004D, 600}, {78, 0x004E, 600}, {79, 0x004F, 600}, {80, 0x0050, 600}, {81, 0x0051, 600}, {82, 0x0052, 600}, {83, 0x0053, 600}, {84, 0x0054, 600}, {85, 0x0055, 600}, {86, 0x0056, 600}, {87, 0x0057, 600}, {88, 0x0058, 600}, {89, 0x0059, 600}, {90, 0x005A, 600}, {91, 0x005B, 600}, {92, 0x005C, 600}, {93, 0x005D, 600}, {94, 0x005E, 600}, {95, 0x005F, 600}, {96, 0x2018, 600}, {97, 0x0061, 600}, {98, 0x0062, 600}, {99, 0x0063, 600}, {100, 0x0064, 600}, {101, 0x0065, 600}, {102, 0x0066, 600}, {103, 0x0067, 600}, {104, 0x0068, 600}, {105, 0x0069, 600}, {106, 0x006A, 600}, {107, 0x006B, 600}, {108, 0x006C, 600}, {109, 0x006D, 600}, {110, 0x006E, 600}, {111, 0x006F, 600}, {112, 0x0070, 600}, {113, 0x0071, 600}, {114, 0x0072, 600}, {115, 0x0073, 600}, {116, 0x0074, 600}, {117, 0x0075, 600}, {118, 0x0076, 600}, {119, 0x0077, 600}, {120, 0x0078, 600}, {121, 0x0079, 600}, {122, 0x007A, 600}, {123, 0x007B, 600}, {124, 0x007C, 600}, {125, 0x007D, 600}, {126, 0x007E, 600}, {161, 0x00A1, 600}, {162, 0x00A2, 600}, {163, 0x00A3, 600}, {164, 0x2044, 600}, {165, 0x00A5, 600}, {166, 0x0192, 600}, {167, 0x00A7, 600}, {168, 0x00A4, 600}, {169, 0x0027, 600}, {170, 0x201C, 600}, {171, 0x00AB, 600}, {172, 0x2039, 600}, {173, 0x203A, 600}, {174, 0xFB01, 600}, {175, 0xFB02, 600}, {177, 0x2013, 600}, {178, 0x2020, 600}, {179, 0x2021, 600}, {180, 0x00B7, 600}, {182, 0x00B6, 600}, {183, 0x2022, 600}, {184, 0x201A, 600}, {185, 0x201E, 600}, {186, 0x201D, 600}, {187, 0x00BB, 600}, {188, 0x2026, 600}, {189, 0x2030, 600}, {191, 0x00BF, 600}, {193, 0x0060, 600}, {194, 0x00B4, 600}, {195, 0x02C6, 600}, {196, 0x02DC, 600}, {197, 0x00AF, 600}, {198, 0x02D8, 600}, {199, 0x02D9, 600}, {200, 0x00A8, 600}, {202, 0x02DA, 600}, {203, 0x00B8, 600}, {205, 0x02DD, 600}, {206, 0x02DB, 600}, {207, 0x02C7, 600}, {208, 0x2014, 600}, {225, 0x00C6, 600}, {227, 0x00AA, 600}, {232, 0x0141, 600}, {233, 0x00D8, 600}, {234, 0x0152, 600}, {235, 0x00BA, 600}, {241, 0x00E6, 600}, {245, 0x0131, 600}, {248, 0x0142, 600}, {249, 0x00F8, 600}, {250, 0x0153, 600}, {251, 0x00DF, 600}, {-1, 0x00CF, 600}, {-1, 0x00E9, 600}, {-1, 0x0103, 600}, {-1, 0x0171, 600}, {-1, 0x011B, 600}, {-1, 0x0178, 600}, {-1, 0x00F7, 600}, {-1, 0x00DD, 600}, {-1, 0x00C2, 600}, {-1, 0x00E1, 600}, {-1, 0x00DB, 600}, {-1, 0x00FD, 600}, {-1, 0x0219, 600}, {-1, 0x00EA, 600}, {-1, 0x016E, 600}, {-1, 0x00DC, 600}, {-1, 0x0105, 600}, {-1, 0x00DA, 600}, {-1, 0x0173, 600}, {-1, 0x00CB, 600}, {-1, 0x0110, 600}, {-1, 0xF6C3, 600}, {-1, 0x00A9, 600}, {-1, 0x0112, 600}, {-1, 0x010D, 600}, {-1, 0x00E5, 600}, {-1, 0x0145, 600}, {-1, 0x013A, 600}, {-1, 0x00E0, 600}, {-1, 0x0162, 600}, {-1, 0x0106, 600}, {-1, 0x00E3, 600}, {-1, 0x0116, 600}, {-1, 0x0161, 600}, {-1, 0x015F, 600}, {-1, 0x00ED, 600}, {-1, 0x25CA, 600}, {-1, 0x0158, 600}, {-1, 0x0122, 600}, {-1, 0x00FB, 600}, {-1, 0x00E2, 600}, {-1, 0x0100, 600}, {-1, 0x0159, 600}, {-1, 0x00E7, 600}, {-1, 0x017B, 600}, {-1, 0x00DE, 600}, {-1, 0x014C, 600}, {-1, 0x0154, 600}, {-1, 0x015A, 600}, {-1, 0x010F, 600}, {-1, 0x016A, 600}, {-1, 0x016F, 600}, {-1, 0x00B3, 600}, {-1, 0x00D2, 600}, {-1, 0x00C0, 600}, {-1, 0x0102, 600}, {-1, 0x00D7, 600}, {-1, 0x00FA, 600}, {-1, 0x0164, 600}, {-1, 0x2202, 600}, {-1, 0x00FF, 600}, {-1, 0x0143, 600}, {-1, 0x00EE, 600}, {-1, 0x00CA, 600}, {-1, 0x00E4, 600}, {-1, 0x00EB, 600}, {-1, 0x0107, 600}, {-1, 0x0144, 600}, {-1, 0x016B, 600}, {-1, 0x0147, 600}, {-1, 0x00CD, 600}, {-1, 0x00B1, 600}, {-1, 0x00A6, 600}, {-1, 0x00AE, 600}, {-1, 0x011E, 600}, {-1, 0x0130, 600}, {-1, 0x2211, 600}, {-1, 0x00C8, 600}, {-1, 0x0155, 600}, {-1, 0x014D, 600}, {-1, 0x0179, 600}, {-1, 0x017D, 600}, {-1, 0x2265, 600}, {-1, 0x00D0, 600}, {-1, 0x00C7, 600}, {-1, 0x013C, 600}, {-1, 0x0165, 600}, {-1, 0x0119, 600}, {-1, 0x0172, 600}, {-1, 0x00C1, 600}, {-1, 0x00C4, 600}, {-1, 0x00E8, 600}, {-1, 0x017A, 600}, {-1, 0x012F, 600}, {-1, 0x00D3, 600}, {-1, 0x00F3, 600}, {-1, 0x0101, 600}, {-1, 0x015B, 600}, {-1, 0x00EF, 600}, {-1, 0x00D4, 600}, {-1, 0x00D9, 600}, {-1, 0x0394, 600}, {-1, 0x00FE, 600}, {-1, 0x00B2, 600}, {-1, 0x00D6, 600}, {-1, 0x00B5, 600}, {-1, 0x00EC, 600}, {-1, 0x0151, 600}, {-1, 0x0118, 600}, {-1, 0x0111, 600}, {-1, 0x00BE, 600}, {-1, 0x015E, 600}, {-1, 0x013E, 600}, {-1, 0x0136, 600}, {-1, 0x0139, 600}, {-1, 0x2122, 600}, {-1, 0x0117, 600}, {-1, 0x00CC, 600}, {-1, 0x012A, 600}, {-1, 0x013D, 600}, {-1, 0x00BD, 600}, {-1, 0x2264, 600}, {-1, 0x00F4, 600}, {-1, 0x00F1, 600}, {-1, 0x0170, 600}, {-1, 0x00C9, 600}, {-1, 0x0113, 600}, {-1, 0x011F, 600}, {-1, 0x00BC, 600}, {-1, 0x0160, 600}, {-1, 0x0218, 600}, {-1, 0x0150, 600}, {-1, 0x00B0, 600}, {-1, 0x00F2, 600}, {-1, 0x010C, 600}, {-1, 0x00F9, 600}, {-1, 0x221A, 600}, {-1, 0x010E, 600}, {-1, 0x0157, 600}, {-1, 0x00D1, 600}, {-1, 0x00F5, 600}, {-1, 0x0156, 600}, {-1, 0x013B, 600}, {-1, 0x00C3, 600}, {-1, 0x0104, 600}, {-1, 0x00C5, 600}, {-1, 0x00D5, 600}, {-1, 0x017C, 600}, {-1, 0x011A, 600}, {-1, 0x012E, 600}, {-1, 0x0137, 600}, {-1, 0x2212, 600}, {-1, 0x00CE, 600}, {-1, 0x0148, 600}, {-1, 0x0163, 600}, {-1, 0x00AC, 600}, {-1, 0x00F6, 600}, {-1, 0x00FC, 600}, {-1, 0x2260, 600}, {-1, 0x0123, 600}, {-1, 0x00F0, 600}, {-1, 0x017E, 600}, {-1, 0x0146, 600}, {-1, 0x00B9, 600}, {-1, 0x012B, 600}, {-1, 0x20AC, 600}, {-1, 0xFFFF, 0} }; static const PODOFO_CharData CHAR_DATA_COURIER_OBLIQUE[316] = { {32, 0x0020, 600}, {33, 0x0021, 600}, {34, 0x0022, 600}, {35, 0x0023, 600}, {36, 0x0024, 600}, {37, 0x0025, 600}, {38, 0x0026, 600}, {39, 0x2019, 600}, {40, 0x0028, 600}, {41, 0x0029, 600}, {42, 0x002A, 600}, {43, 0x002B, 600}, {44, 0x002C, 600}, {45, 0x002D, 600}, {46, 0x002E, 600}, {47, 0x002F, 600}, {48, 0x0030, 600}, {49, 0x0031, 600}, {50, 0x0032, 600}, {51, 0x0033, 600}, {52, 0x0034, 600}, {53, 0x0035, 600}, {54, 0x0036, 600}, {55, 0x0037, 600}, {56, 0x0038, 600}, {57, 0x0039, 600}, {58, 0x003A, 600}, {59, 0x003B, 600}, {60, 0x003C, 600}, {61, 0x003D, 600}, {62, 0x003E, 600}, {63, 0x003F, 600}, {64, 0x0040, 600}, {65, 0x0041, 600}, {66, 0x0042, 600}, {67, 0x0043, 600}, {68, 0x0044, 600}, {69, 0x0045, 600}, {70, 0x0046, 600}, {71, 0x0047, 600}, {72, 0x0048, 600}, {73, 0x0049, 600}, {74, 0x004A, 600}, {75, 0x004B, 600}, {76, 0x004C, 600}, {77, 0x004D, 600}, {78, 0x004E, 600}, {79, 0x004F, 600}, {80, 0x0050, 600}, {81, 0x0051, 600}, {82, 0x0052, 600}, {83, 0x0053, 600}, {84, 0x0054, 600}, {85, 0x0055, 600}, {86, 0x0056, 600}, {87, 0x0057, 600}, {88, 0x0058, 600}, {89, 0x0059, 600}, {90, 0x005A, 600}, {91, 0x005B, 600}, {92, 0x005C, 600}, {93, 0x005D, 600}, {94, 0x005E, 600}, {95, 0x005F, 600}, {96, 0x2018, 600}, {97, 0x0061, 600}, {98, 0x0062, 600}, {99, 0x0063, 600}, {100, 0x0064, 600}, {101, 0x0065, 600}, {102, 0x0066, 600}, {103, 0x0067, 600}, {104, 0x0068, 600}, {105, 0x0069, 600}, {106, 0x006A, 600}, {107, 0x006B, 600}, {108, 0x006C, 600}, {109, 0x006D, 600}, {110, 0x006E, 600}, {111, 0x006F, 600}, {112, 0x0070, 600}, {113, 0x0071, 600}, {114, 0x0072, 600}, {115, 0x0073, 600}, {116, 0x0074, 600}, {117, 0x0075, 600}, {118, 0x0076, 600}, {119, 0x0077, 600}, {120, 0x0078, 600}, {121, 0x0079, 600}, {122, 0x007A, 600}, {123, 0x007B, 600}, {124, 0x007C, 600}, {125, 0x007D, 600}, {126, 0x007E, 600}, {161, 0x00A1, 600}, {162, 0x00A2, 600}, {163, 0x00A3, 600}, {164, 0x2044, 600}, {165, 0x00A5, 600}, {166, 0x0192, 600}, {167, 0x00A7, 600}, {168, 0x00A4, 600}, {169, 0x0027, 600}, {170, 0x201C, 600}, {171, 0x00AB, 600}, {172, 0x2039, 600}, {173, 0x203A, 600}, {174, 0xFB01, 600}, {175, 0xFB02, 600}, {177, 0x2013, 600}, {178, 0x2020, 600}, {179, 0x2021, 600}, {180, 0x00B7, 600}, {182, 0x00B6, 600}, {183, 0x2022, 600}, {184, 0x201A, 600}, {185, 0x201E, 600}, {186, 0x201D, 600}, {187, 0x00BB, 600}, {188, 0x2026, 600}, {189, 0x2030, 600}, {191, 0x00BF, 600}, {193, 0x0060, 600}, {194, 0x00B4, 600}, {195, 0x02C6, 600}, {196, 0x02DC, 600}, {197, 0x00AF, 600}, {198, 0x02D8, 600}, {199, 0x02D9, 600}, {200, 0x00A8, 600}, {202, 0x02DA, 600}, {203, 0x00B8, 600}, {205, 0x02DD, 600}, {206, 0x02DB, 600}, {207, 0x02C7, 600}, {208, 0x2014, 600}, {225, 0x00C6, 600}, {227, 0x00AA, 600}, {232, 0x0141, 600}, {233, 0x00D8, 600}, {234, 0x0152, 600}, {235, 0x00BA, 600}, {241, 0x00E6, 600}, {245, 0x0131, 600}, {248, 0x0142, 600}, {249, 0x00F8, 600}, {250, 0x0153, 600}, {251, 0x00DF, 600}, {-1, 0x00CF, 600}, {-1, 0x00E9, 600}, {-1, 0x0103, 600}, {-1, 0x0171, 600}, {-1, 0x011B, 600}, {-1, 0x0178, 600}, {-1, 0x00F7, 600}, {-1, 0x00DD, 600}, {-1, 0x00C2, 600}, {-1, 0x00E1, 600}, {-1, 0x00DB, 600}, {-1, 0x00FD, 600}, {-1, 0x0219, 600}, {-1, 0x00EA, 600}, {-1, 0x016E, 600}, {-1, 0x00DC, 600}, {-1, 0x0105, 600}, {-1, 0x00DA, 600}, {-1, 0x0173, 600}, {-1, 0x00CB, 600}, {-1, 0x0110, 600}, {-1, 0xF6C3, 600}, {-1, 0x00A9, 600}, {-1, 0x0112, 600}, {-1, 0x010D, 600}, {-1, 0x00E5, 600}, {-1, 0x0145, 600}, {-1, 0x013A, 600}, {-1, 0x00E0, 600}, {-1, 0x0162, 600}, {-1, 0x0106, 600}, {-1, 0x00E3, 600}, {-1, 0x0116, 600}, {-1, 0x0161, 600}, {-1, 0x015F, 600}, {-1, 0x00ED, 600}, {-1, 0x25CA, 600}, {-1, 0x0158, 600}, {-1, 0x0122, 600}, {-1, 0x00FB, 600}, {-1, 0x00E2, 600}, {-1, 0x0100, 600}, {-1, 0x0159, 600}, {-1, 0x00E7, 600}, {-1, 0x017B, 600}, {-1, 0x00DE, 600}, {-1, 0x014C, 600}, {-1, 0x0154, 600}, {-1, 0x015A, 600}, {-1, 0x010F, 600}, {-1, 0x016A, 600}, {-1, 0x016F, 600}, {-1, 0x00B3, 600}, {-1, 0x00D2, 600}, {-1, 0x00C0, 600}, {-1, 0x0102, 600}, {-1, 0x00D7, 600}, {-1, 0x00FA, 600}, {-1, 0x0164, 600}, {-1, 0x2202, 600}, {-1, 0x00FF, 600}, {-1, 0x0143, 600}, {-1, 0x00EE, 600}, {-1, 0x00CA, 600}, {-1, 0x00E4, 600}, {-1, 0x00EB, 600}, {-1, 0x0107, 600}, {-1, 0x0144, 600}, {-1, 0x016B, 600}, {-1, 0x0147, 600}, {-1, 0x00CD, 600}, {-1, 0x00B1, 600}, {-1, 0x00A6, 600}, {-1, 0x00AE, 600}, {-1, 0x011E, 600}, {-1, 0x0130, 600}, {-1, 0x2211, 600}, {-1, 0x00C8, 600}, {-1, 0x0155, 600}, {-1, 0x014D, 600}, {-1, 0x0179, 600}, {-1, 0x017D, 600}, {-1, 0x2265, 600}, {-1, 0x00D0, 600}, {-1, 0x00C7, 600}, {-1, 0x013C, 600}, {-1, 0x0165, 600}, {-1, 0x0119, 600}, {-1, 0x0172, 600}, {-1, 0x00C1, 600}, {-1, 0x00C4, 600}, {-1, 0x00E8, 600}, {-1, 0x017A, 600}, {-1, 0x012F, 600}, {-1, 0x00D3, 600}, {-1, 0x00F3, 600}, {-1, 0x0101, 600}, {-1, 0x015B, 600}, {-1, 0x00EF, 600}, {-1, 0x00D4, 600}, {-1, 0x00D9, 600}, {-1, 0x0394, 600}, {-1, 0x00FE, 600}, {-1, 0x00B2, 600}, {-1, 0x00D6, 600}, {-1, 0x00B5, 600}, {-1, 0x00EC, 600}, {-1, 0x0151, 600}, {-1, 0x0118, 600}, {-1, 0x0111, 600}, {-1, 0x00BE, 600}, {-1, 0x015E, 600}, {-1, 0x013E, 600}, {-1, 0x0136, 600}, {-1, 0x0139, 600}, {-1, 0x2122, 600}, {-1, 0x0117, 600}, {-1, 0x00CC, 600}, {-1, 0x012A, 600}, {-1, 0x013D, 600}, {-1, 0x00BD, 600}, {-1, 0x2264, 600}, {-1, 0x00F4, 600}, {-1, 0x00F1, 600}, {-1, 0x0170, 600}, {-1, 0x00C9, 600}, {-1, 0x0113, 600}, {-1, 0x011F, 600}, {-1, 0x00BC, 600}, {-1, 0x0160, 600}, {-1, 0x0218, 600}, {-1, 0x0150, 600}, {-1, 0x00B0, 600}, {-1, 0x00F2, 600}, {-1, 0x010C, 600}, {-1, 0x00F9, 600}, {-1, 0x221A, 600}, {-1, 0x010E, 600}, {-1, 0x0157, 600}, {-1, 0x00D1, 600}, {-1, 0x00F5, 600}, {-1, 0x0156, 600}, {-1, 0x013B, 600}, {-1, 0x00C3, 600}, {-1, 0x0104, 600}, {-1, 0x00C5, 600}, {-1, 0x00D5, 600}, {-1, 0x017C, 600}, {-1, 0x011A, 600}, {-1, 0x012E, 600}, {-1, 0x0137, 600}, {-1, 0x2212, 600}, {-1, 0x00CE, 600}, {-1, 0x0148, 600}, {-1, 0x0163, 600}, {-1, 0x00AC, 600}, {-1, 0x00F6, 600}, {-1, 0x00FC, 600}, {-1, 0x2260, 600}, {-1, 0x0123, 600}, {-1, 0x00F0, 600}, {-1, 0x017E, 600}, {-1, 0x0146, 600}, {-1, 0x00B9, 600}, {-1, 0x012B, 600}, {-1, 0x20AC, 600}, {-1, 0xFFFF, 0} }; static const PODOFO_CharData CHAR_DATA_HELVETICA[316] = { {32, 0x0020, 278}, {33, 0x0021, 278}, {34, 0x0022, 355}, {35, 0x0023, 556}, {36, 0x0024, 556}, {37, 0x0025, 889}, {38, 0x0026, 667}, {39, 0x2019, 222}, {40, 0x0028, 333}, {41, 0x0029, 333}, {42, 0x002A, 389}, {43, 0x002B, 584}, {44, 0x002C, 278}, {45, 0x002D, 333}, {46, 0x002E, 278}, {47, 0x002F, 278}, {48, 0x0030, 556}, {49, 0x0031, 556}, {50, 0x0032, 556}, {51, 0x0033, 556}, {52, 0x0034, 556}, {53, 0x0035, 556}, {54, 0x0036, 556}, {55, 0x0037, 556}, {56, 0x0038, 556}, {57, 0x0039, 556}, {58, 0x003A, 278}, {59, 0x003B, 278}, {60, 0x003C, 584}, {61, 0x003D, 584}, {62, 0x003E, 584}, {63, 0x003F, 556}, {64, 0x0040, 1015}, {65, 0x0041, 667}, {66, 0x0042, 667}, {67, 0x0043, 722}, {68, 0x0044, 722}, {69, 0x0045, 667}, {70, 0x0046, 611}, {71, 0x0047, 778}, {72, 0x0048, 722}, {73, 0x0049, 278}, {74, 0x004A, 500}, {75, 0x004B, 667}, {76, 0x004C, 556}, {77, 0x004D, 833}, {78, 0x004E, 722}, {79, 0x004F, 778}, {80, 0x0050, 667}, {81, 0x0051, 778}, {82, 0x0052, 722}, {83, 0x0053, 667}, {84, 0x0054, 611}, {85, 0x0055, 722}, {86, 0x0056, 667}, {87, 0x0057, 944}, {88, 0x0058, 667}, {89, 0x0059, 667}, {90, 0x005A, 611}, {91, 0x005B, 278}, {92, 0x005C, 278}, {93, 0x005D, 278}, {94, 0x005E, 469}, {95, 0x005F, 556}, {96, 0x2018, 222}, {97, 0x0061, 556}, {98, 0x0062, 556}, {99, 0x0063, 500}, {100, 0x0064, 556}, {101, 0x0065, 556}, {102, 0x0066, 278}, {103, 0x0067, 556}, {104, 0x0068, 556}, {105, 0x0069, 222}, {106, 0x006A, 222}, {107, 0x006B, 500}, {108, 0x006C, 222}, {109, 0x006D, 833}, {110, 0x006E, 556}, {111, 0x006F, 556}, {112, 0x0070, 556}, {113, 0x0071, 556}, {114, 0x0072, 333}, {115, 0x0073, 500}, {116, 0x0074, 278}, {117, 0x0075, 556}, {118, 0x0076, 500}, {119, 0x0077, 722}, {120, 0x0078, 500}, {121, 0x0079, 500}, {122, 0x007A, 500}, {123, 0x007B, 334}, {124, 0x007C, 260}, {125, 0x007D, 334}, {126, 0x007E, 584}, {161, 0x00A1, 333}, {162, 0x00A2, 556}, {163, 0x00A3, 556}, {164, 0x2044, 167}, {165, 0x00A5, 556}, {166, 0x0192, 556}, {167, 0x00A7, 556}, {168, 0x00A4, 556}, {169, 0x0027, 191}, {170, 0x201C, 333}, {171, 0x00AB, 556}, {172, 0x2039, 333}, {173, 0x203A, 333}, {174, 0xFB01, 500}, {175, 0xFB02, 500}, {177, 0x2013, 556}, {178, 0x2020, 556}, {179, 0x2021, 556}, {180, 0x00B7, 278}, {182, 0x00B6, 537}, {183, 0x2022, 350}, {184, 0x201A, 222}, {185, 0x201E, 333}, {186, 0x201D, 333}, {187, 0x00BB, 556}, {188, 0x2026, 1000}, {189, 0x2030, 1000}, {191, 0x00BF, 611}, {193, 0x0060, 333}, {194, 0x00B4, 333}, {195, 0x02C6, 333}, {196, 0x02DC, 333}, {197, 0x00AF, 333}, {198, 0x02D8, 333}, {199, 0x02D9, 333}, {200, 0x00A8, 333}, {202, 0x02DA, 333}, {203, 0x00B8, 333}, {205, 0x02DD, 333}, {206, 0x02DB, 333}, {207, 0x02C7, 333}, {208, 0x2014, 1000}, {225, 0x00C6, 1000}, {227, 0x00AA, 370}, {232, 0x0141, 556}, {233, 0x00D8, 778}, {234, 0x0152, 1000}, {235, 0x00BA, 365}, {241, 0x00E6, 889}, {245, 0x0131, 278}, {248, 0x0142, 222}, {249, 0x00F8, 611}, {250, 0x0153, 944}, {251, 0x00DF, 611}, {-1, 0x00CF, 278}, {-1, 0x00E9, 556}, {-1, 0x0103, 556}, {-1, 0x0171, 556}, {-1, 0x011B, 556}, {-1, 0x0178, 667}, {-1, 0x00F7, 584}, {-1, 0x00DD, 667}, {-1, 0x00C2, 667}, {-1, 0x00E1, 556}, {-1, 0x00DB, 722}, {-1, 0x00FD, 500}, {-1, 0x0219, 500}, {-1, 0x00EA, 556}, {-1, 0x016E, 722}, {-1, 0x00DC, 722}, {-1, 0x0105, 556}, {-1, 0x00DA, 722}, {-1, 0x0173, 556}, {-1, 0x00CB, 667}, {-1, 0x0110, 722}, {-1, 0xF6C3, 250}, {-1, 0x00A9, 737}, {-1, 0x0112, 667}, {-1, 0x010D, 500}, {-1, 0x00E5, 556}, {-1, 0x0145, 722}, {-1, 0x013A, 222}, {-1, 0x00E0, 556}, {-1, 0x0162, 611}, {-1, 0x0106, 722}, {-1, 0x00E3, 556}, {-1, 0x0116, 667}, {-1, 0x0161, 500}, {-1, 0x015F, 500}, {-1, 0x00ED, 278}, {-1, 0x25CA, 471}, {-1, 0x0158, 722}, {-1, 0x0122, 778}, {-1, 0x00FB, 556}, {-1, 0x00E2, 556}, {-1, 0x0100, 667}, {-1, 0x0159, 333}, {-1, 0x00E7, 500}, {-1, 0x017B, 611}, {-1, 0x00DE, 667}, {-1, 0x014C, 778}, {-1, 0x0154, 722}, {-1, 0x015A, 667}, {-1, 0x010F, 643}, {-1, 0x016A, 722}, {-1, 0x016F, 556}, {-1, 0x00B3, 333}, {-1, 0x00D2, 778}, {-1, 0x00C0, 667}, {-1, 0x0102, 667}, {-1, 0x00D7, 584}, {-1, 0x00FA, 556}, {-1, 0x0164, 611}, {-1, 0x2202, 476}, {-1, 0x00FF, 500}, {-1, 0x0143, 722}, {-1, 0x00EE, 278}, {-1, 0x00CA, 667}, {-1, 0x00E4, 556}, {-1, 0x00EB, 556}, {-1, 0x0107, 500}, {-1, 0x0144, 556}, {-1, 0x016B, 556}, {-1, 0x0147, 722}, {-1, 0x00CD, 278}, {-1, 0x00B1, 584}, {-1, 0x00A6, 260}, {-1, 0x00AE, 737}, {-1, 0x011E, 778}, {-1, 0x0130, 278}, {-1, 0x2211, 600}, {-1, 0x00C8, 667}, {-1, 0x0155, 333}, {-1, 0x014D, 556}, {-1, 0x0179, 611}, {-1, 0x017D, 611}, {-1, 0x2265, 549}, {-1, 0x00D0, 722}, {-1, 0x00C7, 722}, {-1, 0x013C, 222}, {-1, 0x0165, 316}, {-1, 0x0119, 556}, {-1, 0x0172, 722}, {-1, 0x00C1, 667}, {-1, 0x00C4, 667}, {-1, 0x00E8, 556}, {-1, 0x017A, 500}, {-1, 0x012F, 222}, {-1, 0x00D3, 778}, {-1, 0x00F3, 556}, {-1, 0x0101, 556}, {-1, 0x015B, 500}, {-1, 0x00EF, 278}, {-1, 0x00D4, 778}, {-1, 0x00D9, 722}, {-1, 0x0394, 612}, {-1, 0x00FE, 556}, {-1, 0x00B2, 333}, {-1, 0x00D6, 778}, {-1, 0x00B5, 556}, {-1, 0x00EC, 278}, {-1, 0x0151, 556}, {-1, 0x0118, 667}, {-1, 0x0111, 556}, {-1, 0x00BE, 834}, {-1, 0x015E, 667}, {-1, 0x013E, 299}, {-1, 0x0136, 667}, {-1, 0x0139, 556}, {-1, 0x2122, 1000}, {-1, 0x0117, 556}, {-1, 0x00CC, 278}, {-1, 0x012A, 278}, {-1, 0x013D, 556}, {-1, 0x00BD, 834}, {-1, 0x2264, 549}, {-1, 0x00F4, 556}, {-1, 0x00F1, 556}, {-1, 0x0170, 722}, {-1, 0x00C9, 667}, {-1, 0x0113, 556}, {-1, 0x011F, 556}, {-1, 0x00BC, 834}, {-1, 0x0160, 667}, {-1, 0x0218, 667}, {-1, 0x0150, 778}, {-1, 0x00B0, 400}, {-1, 0x00F2, 556}, {-1, 0x010C, 722}, {-1, 0x00F9, 556}, {-1, 0x221A, 453}, {-1, 0x010E, 722}, {-1, 0x0157, 333}, {-1, 0x00D1, 722}, {-1, 0x00F5, 556}, {-1, 0x0156, 722}, {-1, 0x013B, 556}, {-1, 0x00C3, 667}, {-1, 0x0104, 667}, {-1, 0x00C5, 667}, {-1, 0x00D5, 778}, {-1, 0x017C, 500}, {-1, 0x011A, 667}, {-1, 0x012E, 278}, {-1, 0x0137, 500}, {-1, 0x2212, 584}, {-1, 0x00CE, 278}, {-1, 0x0148, 556}, {-1, 0x0163, 278}, {-1, 0x00AC, 584}, {-1, 0x00F6, 556}, {-1, 0x00FC, 556}, {-1, 0x2260, 549}, {-1, 0x0123, 556}, {-1, 0x00F0, 556}, {-1, 0x017E, 500}, {-1, 0x0146, 556}, {-1, 0x00B9, 333}, {-1, 0x012B, 278}, {-1, 0x20AC, 556}, {-1, 0xFFFF, 0} }; static const PODOFO_CharData CHAR_DATA_HELVETICA_BOLD[316] = { {32, 0x0020, 278}, {33, 0x0021, 333}, {34, 0x0022, 474}, {35, 0x0023, 556}, {36, 0x0024, 556}, {37, 0x0025, 889}, {38, 0x0026, 722}, {39, 0x2019, 278}, {40, 0x0028, 333}, {41, 0x0029, 333}, {42, 0x002A, 389}, {43, 0x002B, 584}, {44, 0x002C, 278}, {45, 0x002D, 333}, {46, 0x002E, 278}, {47, 0x002F, 278}, {48, 0x0030, 556}, {49, 0x0031, 556}, {50, 0x0032, 556}, {51, 0x0033, 556}, {52, 0x0034, 556}, {53, 0x0035, 556}, {54, 0x0036, 556}, {55, 0x0037, 556}, {56, 0x0038, 556}, {57, 0x0039, 556}, {58, 0x003A, 333}, {59, 0x003B, 333}, {60, 0x003C, 584}, {61, 0x003D, 584}, {62, 0x003E, 584}, {63, 0x003F, 611}, {64, 0x0040, 975}, {65, 0x0041, 722}, {66, 0x0042, 722}, {67, 0x0043, 722}, {68, 0x0044, 722}, {69, 0x0045, 667}, {70, 0x0046, 611}, {71, 0x0047, 778}, {72, 0x0048, 722}, {73, 0x0049, 278}, {74, 0x004A, 556}, {75, 0x004B, 722}, {76, 0x004C, 611}, {77, 0x004D, 833}, {78, 0x004E, 722}, {79, 0x004F, 778}, {80, 0x0050, 667}, {81, 0x0051, 778}, {82, 0x0052, 722}, {83, 0x0053, 667}, {84, 0x0054, 611}, {85, 0x0055, 722}, {86, 0x0056, 667}, {87, 0x0057, 944}, {88, 0x0058, 667}, {89, 0x0059, 667}, {90, 0x005A, 611}, {91, 0x005B, 333}, {92, 0x005C, 278}, {93, 0x005D, 333}, {94, 0x005E, 584}, {95, 0x005F, 556}, {96, 0x2018, 278}, {97, 0x0061, 556}, {98, 0x0062, 611}, {99, 0x0063, 556}, {100, 0x0064, 611}, {101, 0x0065, 556}, {102, 0x0066, 333}, {103, 0x0067, 611}, {104, 0x0068, 611}, {105, 0x0069, 278}, {106, 0x006A, 278}, {107, 0x006B, 556}, {108, 0x006C, 278}, {109, 0x006D, 889}, {110, 0x006E, 611}, {111, 0x006F, 611}, {112, 0x0070, 611}, {113, 0x0071, 611}, {114, 0x0072, 389}, {115, 0x0073, 556}, {116, 0x0074, 333}, {117, 0x0075, 611}, {118, 0x0076, 556}, {119, 0x0077, 778}, {120, 0x0078, 556}, {121, 0x0079, 556}, {122, 0x007A, 500}, {123, 0x007B, 389}, {124, 0x007C, 280}, {125, 0x007D, 389}, {126, 0x007E, 584}, {161, 0x00A1, 333}, {162, 0x00A2, 556}, {163, 0x00A3, 556}, {164, 0x2044, 167}, {165, 0x00A5, 556}, {166, 0x0192, 556}, {167, 0x00A7, 556}, {168, 0x00A4, 556}, {169, 0x0027, 238}, {170, 0x201C, 500}, {171, 0x00AB, 556}, {172, 0x2039, 333}, {173, 0x203A, 333}, {174, 0xFB01, 611}, {175, 0xFB02, 611}, {177, 0x2013, 556}, {178, 0x2020, 556}, {179, 0x2021, 556}, {180, 0x00B7, 278}, {182, 0x00B6, 556}, {183, 0x2022, 350}, {184, 0x201A, 278}, {185, 0x201E, 500}, {186, 0x201D, 500}, {187, 0x00BB, 556}, {188, 0x2026, 1000}, {189, 0x2030, 1000}, {191, 0x00BF, 611}, {193, 0x0060, 333}, {194, 0x00B4, 333}, {195, 0x02C6, 333}, {196, 0x02DC, 333}, {197, 0x00AF, 333}, {198, 0x02D8, 333}, {199, 0x02D9, 333}, {200, 0x00A8, 333}, {202, 0x02DA, 333}, {203, 0x00B8, 333}, {205, 0x02DD, 333}, {206, 0x02DB, 333}, {207, 0x02C7, 333}, {208, 0x2014, 1000}, {225, 0x00C6, 1000}, {227, 0x00AA, 370}, {232, 0x0141, 611}, {233, 0x00D8, 778}, {234, 0x0152, 1000}, {235, 0x00BA, 365}, {241, 0x00E6, 889}, {245, 0x0131, 278}, {248, 0x0142, 278}, {249, 0x00F8, 611}, {250, 0x0153, 944}, {251, 0x00DF, 611}, {-1, 0x00CF, 278}, {-1, 0x00E9, 556}, {-1, 0x0103, 556}, {-1, 0x0171, 611}, {-1, 0x011B, 556}, {-1, 0x0178, 667}, {-1, 0x00F7, 584}, {-1, 0x00DD, 667}, {-1, 0x00C2, 722}, {-1, 0x00E1, 556}, {-1, 0x00DB, 722}, {-1, 0x00FD, 556}, {-1, 0x0219, 556}, {-1, 0x00EA, 556}, {-1, 0x016E, 722}, {-1, 0x00DC, 722}, {-1, 0x0105, 556}, {-1, 0x00DA, 722}, {-1, 0x0173, 611}, {-1, 0x00CB, 667}, {-1, 0x0110, 722}, {-1, 0xF6C3, 250}, {-1, 0x00A9, 737}, {-1, 0x0112, 667}, {-1, 0x010D, 556}, {-1, 0x00E5, 556}, {-1, 0x0145, 722}, {-1, 0x013A, 278}, {-1, 0x00E0, 556}, {-1, 0x0162, 611}, {-1, 0x0106, 722}, {-1, 0x00E3, 556}, {-1, 0x0116, 667}, {-1, 0x0161, 556}, {-1, 0x015F, 556}, {-1, 0x00ED, 278}, {-1, 0x25CA, 494}, {-1, 0x0158, 722}, {-1, 0x0122, 778}, {-1, 0x00FB, 611}, {-1, 0x00E2, 556}, {-1, 0x0100, 722}, {-1, 0x0159, 389}, {-1, 0x00E7, 556}, {-1, 0x017B, 611}, {-1, 0x00DE, 667}, {-1, 0x014C, 778}, {-1, 0x0154, 722}, {-1, 0x015A, 667}, {-1, 0x010F, 743}, {-1, 0x016A, 722}, {-1, 0x016F, 611}, {-1, 0x00B3, 333}, {-1, 0x00D2, 778}, {-1, 0x00C0, 722}, {-1, 0x0102, 722}, {-1, 0x00D7, 584}, {-1, 0x00FA, 611}, {-1, 0x0164, 611}, {-1, 0x2202, 494}, {-1, 0x00FF, 556}, {-1, 0x0143, 722}, {-1, 0x00EE, 278}, {-1, 0x00CA, 667}, {-1, 0x00E4, 556}, {-1, 0x00EB, 556}, {-1, 0x0107, 556}, {-1, 0x0144, 611}, {-1, 0x016B, 611}, {-1, 0x0147, 722}, {-1, 0x00CD, 278}, {-1, 0x00B1, 584}, {-1, 0x00A6, 280}, {-1, 0x00AE, 737}, {-1, 0x011E, 778}, {-1, 0x0130, 278}, {-1, 0x2211, 600}, {-1, 0x00C8, 667}, {-1, 0x0155, 389}, {-1, 0x014D, 611}, {-1, 0x0179, 611}, {-1, 0x017D, 611}, {-1, 0x2265, 549}, {-1, 0x00D0, 722}, {-1, 0x00C7, 722}, {-1, 0x013C, 278}, {-1, 0x0165, 389}, {-1, 0x0119, 556}, {-1, 0x0172, 722}, {-1, 0x00C1, 722}, {-1, 0x00C4, 722}, {-1, 0x00E8, 556}, {-1, 0x017A, 500}, {-1, 0x012F, 278}, {-1, 0x00D3, 778}, {-1, 0x00F3, 611}, {-1, 0x0101, 556}, {-1, 0x015B, 556}, {-1, 0x00EF, 278}, {-1, 0x00D4, 778}, {-1, 0x00D9, 722}, {-1, 0x0394, 612}, {-1, 0x00FE, 611}, {-1, 0x00B2, 333}, {-1, 0x00D6, 778}, {-1, 0x00B5, 611}, {-1, 0x00EC, 278}, {-1, 0x0151, 611}, {-1, 0x0118, 667}, {-1, 0x0111, 611}, {-1, 0x00BE, 834}, {-1, 0x015E, 667}, {-1, 0x013E, 400}, {-1, 0x0136, 722}, {-1, 0x0139, 611}, {-1, 0x2122, 1000}, {-1, 0x0117, 556}, {-1, 0x00CC, 278}, {-1, 0x012A, 278}, {-1, 0x013D, 611}, {-1, 0x00BD, 834}, {-1, 0x2264, 549}, {-1, 0x00F4, 611}, {-1, 0x00F1, 611}, {-1, 0x0170, 722}, {-1, 0x00C9, 667}, {-1, 0x0113, 556}, {-1, 0x011F, 611}, {-1, 0x00BC, 834}, {-1, 0x0160, 667}, {-1, 0x0218, 667}, {-1, 0x0150, 778}, {-1, 0x00B0, 400}, {-1, 0x00F2, 611}, {-1, 0x010C, 722}, {-1, 0x00F9, 611}, {-1, 0x221A, 549}, {-1, 0x010E, 722}, {-1, 0x0157, 389}, {-1, 0x00D1, 722}, {-1, 0x00F5, 611}, {-1, 0x0156, 722}, {-1, 0x013B, 611}, {-1, 0x00C3, 722}, {-1, 0x0104, 722}, {-1, 0x00C5, 722}, {-1, 0x00D5, 778}, {-1, 0x017C, 500}, {-1, 0x011A, 667}, {-1, 0x012E, 278}, {-1, 0x0137, 556}, {-1, 0x2212, 584}, {-1, 0x00CE, 278}, {-1, 0x0148, 611}, {-1, 0x0163, 333}, {-1, 0x00AC, 584}, {-1, 0x00F6, 611}, {-1, 0x00FC, 611}, {-1, 0x2260, 549}, {-1, 0x0123, 611}, {-1, 0x00F0, 611}, {-1, 0x017E, 500}, {-1, 0x0146, 611}, {-1, 0x00B9, 333}, {-1, 0x012B, 278}, {-1, 0x20AC, 556}, {-1, 0xFFFF, 0} }; static const PODOFO_CharData CHAR_DATA_HELVETICA_BOLD_OBLIQUE[316] = { {32, 0x0020, 278}, {33, 0x0021, 333}, {34, 0x0022, 474}, {35, 0x0023, 556}, {36, 0x0024, 556}, {37, 0x0025, 889}, {38, 0x0026, 722}, {39, 0x2019, 278}, {40, 0x0028, 333}, {41, 0x0029, 333}, {42, 0x002A, 389}, {43, 0x002B, 584}, {44, 0x002C, 278}, {45, 0x002D, 333}, {46, 0x002E, 278}, {47, 0x002F, 278}, {48, 0x0030, 556}, {49, 0x0031, 556}, {50, 0x0032, 556}, {51, 0x0033, 556}, {52, 0x0034, 556}, {53, 0x0035, 556}, {54, 0x0036, 556}, {55, 0x0037, 556}, {56, 0x0038, 556}, {57, 0x0039, 556}, {58, 0x003A, 333}, {59, 0x003B, 333}, {60, 0x003C, 584}, {61, 0x003D, 584}, {62, 0x003E, 584}, {63, 0x003F, 611}, {64, 0x0040, 975}, {65, 0x0041, 722}, {66, 0x0042, 722}, {67, 0x0043, 722}, {68, 0x0044, 722}, {69, 0x0045, 667}, {70, 0x0046, 611}, {71, 0x0047, 778}, {72, 0x0048, 722}, {73, 0x0049, 278}, {74, 0x004A, 556}, {75, 0x004B, 722}, {76, 0x004C, 611}, {77, 0x004D, 833}, {78, 0x004E, 722}, {79, 0x004F, 778}, {80, 0x0050, 667}, {81, 0x0051, 778}, {82, 0x0052, 722}, {83, 0x0053, 667}, {84, 0x0054, 611}, {85, 0x0055, 722}, {86, 0x0056, 667}, {87, 0x0057, 944}, {88, 0x0058, 667}, {89, 0x0059, 667}, {90, 0x005A, 611}, {91, 0x005B, 333}, {92, 0x005C, 278}, {93, 0x005D, 333}, {94, 0x005E, 584}, {95, 0x005F, 556}, {96, 0x2018, 278}, {97, 0x0061, 556}, {98, 0x0062, 611}, {99, 0x0063, 556}, {100, 0x0064, 611}, {101, 0x0065, 556}, {102, 0x0066, 333}, {103, 0x0067, 611}, {104, 0x0068, 611}, {105, 0x0069, 278}, {106, 0x006A, 278}, {107, 0x006B, 556}, {108, 0x006C, 278}, {109, 0x006D, 889}, {110, 0x006E, 611}, {111, 0x006F, 611}, {112, 0x0070, 611}, {113, 0x0071, 611}, {114, 0x0072, 389}, {115, 0x0073, 556}, {116, 0x0074, 333}, {117, 0x0075, 611}, {118, 0x0076, 556}, {119, 0x0077, 778}, {120, 0x0078, 556}, {121, 0x0079, 556}, {122, 0x007A, 500}, {123, 0x007B, 389}, {124, 0x007C, 280}, {125, 0x007D, 389}, {126, 0x007E, 584}, {161, 0x00A1, 333}, {162, 0x00A2, 556}, {163, 0x00A3, 556}, {164, 0x2044, 167}, {165, 0x00A5, 556}, {166, 0x0192, 556}, {167, 0x00A7, 556}, {168, 0x00A4, 556}, {169, 0x0027, 238}, {170, 0x201C, 500}, {171, 0x00AB, 556}, {172, 0x2039, 333}, {173, 0x203A, 333}, {174, 0xFB01, 611}, {175, 0xFB02, 611}, {177, 0x2013, 556}, {178, 0x2020, 556}, {179, 0x2021, 556}, {180, 0x00B7, 278}, {182, 0x00B6, 556}, {183, 0x2022, 350}, {184, 0x201A, 278}, {185, 0x201E, 500}, {186, 0x201D, 500}, {187, 0x00BB, 556}, {188, 0x2026, 1000}, {189, 0x2030, 1000}, {191, 0x00BF, 611}, {193, 0x0060, 333}, {194, 0x00B4, 333}, {195, 0x02C6, 333}, {196, 0x02DC, 333}, {197, 0x00AF, 333}, {198, 0x02D8, 333}, {199, 0x02D9, 333}, {200, 0x00A8, 333}, {202, 0x02DA, 333}, {203, 0x00B8, 333}, {205, 0x02DD, 333}, {206, 0x02DB, 333}, {207, 0x02C7, 333}, {208, 0x2014, 1000}, {225, 0x00C6, 1000}, {227, 0x00AA, 370}, {232, 0x0141, 611}, {233, 0x00D8, 778}, {234, 0x0152, 1000}, {235, 0x00BA, 365}, {241, 0x00E6, 889}, {245, 0x0131, 278}, {248, 0x0142, 278}, {249, 0x00F8, 611}, {250, 0x0153, 944}, {251, 0x00DF, 611}, {-1, 0x00CF, 278}, {-1, 0x00E9, 556}, {-1, 0x0103, 556}, {-1, 0x0171, 611}, {-1, 0x011B, 556}, {-1, 0x0178, 667}, {-1, 0x00F7, 584}, {-1, 0x00DD, 667}, {-1, 0x00C2, 722}, {-1, 0x00E1, 556}, {-1, 0x00DB, 722}, {-1, 0x00FD, 556}, {-1, 0x0219, 556}, {-1, 0x00EA, 556}, {-1, 0x016E, 722}, {-1, 0x00DC, 722}, {-1, 0x0105, 556}, {-1, 0x00DA, 722}, {-1, 0x0173, 611}, {-1, 0x00CB, 667}, {-1, 0x0110, 722}, {-1, 0xF6C3, 250}, {-1, 0x00A9, 737}, {-1, 0x0112, 667}, {-1, 0x010D, 556}, {-1, 0x00E5, 556}, {-1, 0x0145, 722}, {-1, 0x013A, 278}, {-1, 0x00E0, 556}, {-1, 0x0162, 611}, {-1, 0x0106, 722}, {-1, 0x00E3, 556}, {-1, 0x0116, 667}, {-1, 0x0161, 556}, {-1, 0x015F, 556}, {-1, 0x00ED, 278}, {-1, 0x25CA, 494}, {-1, 0x0158, 722}, {-1, 0x0122, 778}, {-1, 0x00FB, 611}, {-1, 0x00E2, 556}, {-1, 0x0100, 722}, {-1, 0x0159, 389}, {-1, 0x00E7, 556}, {-1, 0x017B, 611}, {-1, 0x00DE, 667}, {-1, 0x014C, 778}, {-1, 0x0154, 722}, {-1, 0x015A, 667}, {-1, 0x010F, 743}, {-1, 0x016A, 722}, {-1, 0x016F, 611}, {-1, 0x00B3, 333}, {-1, 0x00D2, 778}, {-1, 0x00C0, 722}, {-1, 0x0102, 722}, {-1, 0x00D7, 584}, {-1, 0x00FA, 611}, {-1, 0x0164, 611}, {-1, 0x2202, 494}, {-1, 0x00FF, 556}, {-1, 0x0143, 722}, {-1, 0x00EE, 278}, {-1, 0x00CA, 667}, {-1, 0x00E4, 556}, {-1, 0x00EB, 556}, {-1, 0x0107, 556}, {-1, 0x0144, 611}, {-1, 0x016B, 611}, {-1, 0x0147, 722}, {-1, 0x00CD, 278}, {-1, 0x00B1, 584}, {-1, 0x00A6, 280}, {-1, 0x00AE, 737}, {-1, 0x011E, 778}, {-1, 0x0130, 278}, {-1, 0x2211, 600}, {-1, 0x00C8, 667}, {-1, 0x0155, 389}, {-1, 0x014D, 611}, {-1, 0x0179, 611}, {-1, 0x017D, 611}, {-1, 0x2265, 549}, {-1, 0x00D0, 722}, {-1, 0x00C7, 722}, {-1, 0x013C, 278}, {-1, 0x0165, 389}, {-1, 0x0119, 556}, {-1, 0x0172, 722}, {-1, 0x00C1, 722}, {-1, 0x00C4, 722}, {-1, 0x00E8, 556}, {-1, 0x017A, 500}, {-1, 0x012F, 278}, {-1, 0x00D3, 778}, {-1, 0x00F3, 611}, {-1, 0x0101, 556}, {-1, 0x015B, 556}, {-1, 0x00EF, 278}, {-1, 0x00D4, 778}, {-1, 0x00D9, 722}, {-1, 0x0394, 612}, {-1, 0x00FE, 611}, {-1, 0x00B2, 333}, {-1, 0x00D6, 778}, {-1, 0x00B5, 611}, {-1, 0x00EC, 278}, {-1, 0x0151, 611}, {-1, 0x0118, 667}, {-1, 0x0111, 611}, {-1, 0x00BE, 834}, {-1, 0x015E, 667}, {-1, 0x013E, 400}, {-1, 0x0136, 722}, {-1, 0x0139, 611}, {-1, 0x2122, 1000}, {-1, 0x0117, 556}, {-1, 0x00CC, 278}, {-1, 0x012A, 278}, {-1, 0x013D, 611}, {-1, 0x00BD, 834}, {-1, 0x2264, 549}, {-1, 0x00F4, 611}, {-1, 0x00F1, 611}, {-1, 0x0170, 722}, {-1, 0x00C9, 667}, {-1, 0x0113, 556}, {-1, 0x011F, 611}, {-1, 0x00BC, 834}, {-1, 0x0160, 667}, {-1, 0x0218, 667}, {-1, 0x0150, 778}, {-1, 0x00B0, 400}, {-1, 0x00F2, 611}, {-1, 0x010C, 722}, {-1, 0x00F9, 611}, {-1, 0x221A, 549}, {-1, 0x010E, 722}, {-1, 0x0157, 389}, {-1, 0x00D1, 722}, {-1, 0x00F5, 611}, {-1, 0x0156, 722}, {-1, 0x013B, 611}, {-1, 0x00C3, 722}, {-1, 0x0104, 722}, {-1, 0x00C5, 722}, {-1, 0x00D5, 778}, {-1, 0x017C, 500}, {-1, 0x011A, 667}, {-1, 0x012E, 278}, {-1, 0x0137, 556}, {-1, 0x2212, 584}, {-1, 0x00CE, 278}, {-1, 0x0148, 611}, {-1, 0x0163, 333}, {-1, 0x00AC, 584}, {-1, 0x00F6, 611}, {-1, 0x00FC, 611}, {-1, 0x2260, 549}, {-1, 0x0123, 611}, {-1, 0x00F0, 611}, {-1, 0x017E, 500}, {-1, 0x0146, 611}, {-1, 0x00B9, 333}, {-1, 0x012B, 278}, {-1, 0x20AC, 556}, {-1, 0xFFFF, 0} }; static const PODOFO_CharData CHAR_DATA_HELVETICA_OBLIQUE[316] = { {32, 0x0020, 278}, {33, 0x0021, 278}, {34, 0x0022, 355}, {35, 0x0023, 556}, {36, 0x0024, 556}, {37, 0x0025, 889}, {38, 0x0026, 667}, {39, 0x2019, 222}, {40, 0x0028, 333}, {41, 0x0029, 333}, {42, 0x002A, 389}, {43, 0x002B, 584}, {44, 0x002C, 278}, {45, 0x002D, 333}, {46, 0x002E, 278}, {47, 0x002F, 278}, {48, 0x0030, 556}, {49, 0x0031, 556}, {50, 0x0032, 556}, {51, 0x0033, 556}, {52, 0x0034, 556}, {53, 0x0035, 556}, {54, 0x0036, 556}, {55, 0x0037, 556}, {56, 0x0038, 556}, {57, 0x0039, 556}, {58, 0x003A, 278}, {59, 0x003B, 278}, {60, 0x003C, 584}, {61, 0x003D, 584}, {62, 0x003E, 584}, {63, 0x003F, 556}, {64, 0x0040, 1015}, {65, 0x0041, 667}, {66, 0x0042, 667}, {67, 0x0043, 722}, {68, 0x0044, 722}, {69, 0x0045, 667}, {70, 0x0046, 611}, {71, 0x0047, 778}, {72, 0x0048, 722}, {73, 0x0049, 278}, {74, 0x004A, 500}, {75, 0x004B, 667}, {76, 0x004C, 556}, {77, 0x004D, 833}, {78, 0x004E, 722}, {79, 0x004F, 778}, {80, 0x0050, 667}, {81, 0x0051, 778}, {82, 0x0052, 722}, {83, 0x0053, 667}, {84, 0x0054, 611}, {85, 0x0055, 722}, {86, 0x0056, 667}, {87, 0x0057, 944}, {88, 0x0058, 667}, {89, 0x0059, 667}, {90, 0x005A, 611}, {91, 0x005B, 278}, {92, 0x005C, 278}, {93, 0x005D, 278}, {94, 0x005E, 469}, {95, 0x005F, 556}, {96, 0x2018, 222}, {97, 0x0061, 556}, {98, 0x0062, 556}, {99, 0x0063, 500}, {100, 0x0064, 556}, {101, 0x0065, 556}, {102, 0x0066, 278}, {103, 0x0067, 556}, {104, 0x0068, 556}, {105, 0x0069, 222}, {106, 0x006A, 222}, {107, 0x006B, 500}, {108, 0x006C, 222}, {109, 0x006D, 833}, {110, 0x006E, 556}, {111, 0x006F, 556}, {112, 0x0070, 556}, {113, 0x0071, 556}, {114, 0x0072, 333}, {115, 0x0073, 500}, {116, 0x0074, 278}, {117, 0x0075, 556}, {118, 0x0076, 500}, {119, 0x0077, 722}, {120, 0x0078, 500}, {121, 0x0079, 500}, {122, 0x007A, 500}, {123, 0x007B, 334}, {124, 0x007C, 260}, {125, 0x007D, 334}, {126, 0x007E, 584}, {161, 0x00A1, 333}, {162, 0x00A2, 556}, {163, 0x00A3, 556}, {164, 0x2044, 167}, {165, 0x00A5, 556}, {166, 0x0192, 556}, {167, 0x00A7, 556}, {168, 0x00A4, 556}, {169, 0x0027, 191}, {170, 0x201C, 333}, {171, 0x00AB, 556}, {172, 0x2039, 333}, {173, 0x203A, 333}, {174, 0xFB01, 500}, {175, 0xFB02, 500}, {177, 0x2013, 556}, {178, 0x2020, 556}, {179, 0x2021, 556}, {180, 0x00B7, 278}, {182, 0x00B6, 537}, {183, 0x2022, 350}, {184, 0x201A, 222}, {185, 0x201E, 333}, {186, 0x201D, 333}, {187, 0x00BB, 556}, {188, 0x2026, 1000}, {189, 0x2030, 1000}, {191, 0x00BF, 611}, {193, 0x0060, 333}, {194, 0x00B4, 333}, {195, 0x02C6, 333}, {196, 0x02DC, 333}, {197, 0x00AF, 333}, {198, 0x02D8, 333}, {199, 0x02D9, 333}, {200, 0x00A8, 333}, {202, 0x02DA, 333}, {203, 0x00B8, 333}, {205, 0x02DD, 333}, {206, 0x02DB, 333}, {207, 0x02C7, 333}, {208, 0x2014, 1000}, {225, 0x00C6, 1000}, {227, 0x00AA, 370}, {232, 0x0141, 556}, {233, 0x00D8, 778}, {234, 0x0152, 1000}, {235, 0x00BA, 365}, {241, 0x00E6, 889}, {245, 0x0131, 278}, {248, 0x0142, 222}, {249, 0x00F8, 611}, {250, 0x0153, 944}, {251, 0x00DF, 611}, {-1, 0x00CF, 278}, {-1, 0x00E9, 556}, {-1, 0x0103, 556}, {-1, 0x0171, 556}, {-1, 0x011B, 556}, {-1, 0x0178, 667}, {-1, 0x00F7, 584}, {-1, 0x00DD, 667}, {-1, 0x00C2, 667}, {-1, 0x00E1, 556}, {-1, 0x00DB, 722}, {-1, 0x00FD, 500}, {-1, 0x0219, 500}, {-1, 0x00EA, 556}, {-1, 0x016E, 722}, {-1, 0x00DC, 722}, {-1, 0x0105, 556}, {-1, 0x00DA, 722}, {-1, 0x0173, 556}, {-1, 0x00CB, 667}, {-1, 0x0110, 722}, {-1, 0xF6C3, 250}, {-1, 0x00A9, 737}, {-1, 0x0112, 667}, {-1, 0x010D, 500}, {-1, 0x00E5, 556}, {-1, 0x0145, 722}, {-1, 0x013A, 222}, {-1, 0x00E0, 556}, {-1, 0x0162, 611}, {-1, 0x0106, 722}, {-1, 0x00E3, 556}, {-1, 0x0116, 667}, {-1, 0x0161, 500}, {-1, 0x015F, 500}, {-1, 0x00ED, 278}, {-1, 0x25CA, 471}, {-1, 0x0158, 722}, {-1, 0x0122, 778}, {-1, 0x00FB, 556}, {-1, 0x00E2, 556}, {-1, 0x0100, 667}, {-1, 0x0159, 333}, {-1, 0x00E7, 500}, {-1, 0x017B, 611}, {-1, 0x00DE, 667}, {-1, 0x014C, 778}, {-1, 0x0154, 722}, {-1, 0x015A, 667}, {-1, 0x010F, 643}, {-1, 0x016A, 722}, {-1, 0x016F, 556}, {-1, 0x00B3, 333}, {-1, 0x00D2, 778}, {-1, 0x00C0, 667}, {-1, 0x0102, 667}, {-1, 0x00D7, 584}, {-1, 0x00FA, 556}, {-1, 0x0164, 611}, {-1, 0x2202, 476}, {-1, 0x00FF, 500}, {-1, 0x0143, 722}, {-1, 0x00EE, 278}, {-1, 0x00CA, 667}, {-1, 0x00E4, 556}, {-1, 0x00EB, 556}, {-1, 0x0107, 500}, {-1, 0x0144, 556}, {-1, 0x016B, 556}, {-1, 0x0147, 722}, {-1, 0x00CD, 278}, {-1, 0x00B1, 584}, {-1, 0x00A6, 260}, {-1, 0x00AE, 737}, {-1, 0x011E, 778}, {-1, 0x0130, 278}, {-1, 0x2211, 600}, {-1, 0x00C8, 667}, {-1, 0x0155, 333}, {-1, 0x014D, 556}, {-1, 0x0179, 611}, {-1, 0x017D, 611}, {-1, 0x2265, 549}, {-1, 0x00D0, 722}, {-1, 0x00C7, 722}, {-1, 0x013C, 222}, {-1, 0x0165, 316}, {-1, 0x0119, 556}, {-1, 0x0172, 722}, {-1, 0x00C1, 667}, {-1, 0x00C4, 667}, {-1, 0x00E8, 556}, {-1, 0x017A, 500}, {-1, 0x012F, 222}, {-1, 0x00D3, 778}, {-1, 0x00F3, 556}, {-1, 0x0101, 556}, {-1, 0x015B, 500}, {-1, 0x00EF, 278}, {-1, 0x00D4, 778}, {-1, 0x00D9, 722}, {-1, 0x0394, 612}, {-1, 0x00FE, 556}, {-1, 0x00B2, 333}, {-1, 0x00D6, 778}, {-1, 0x00B5, 556}, {-1, 0x00EC, 278}, {-1, 0x0151, 556}, {-1, 0x0118, 667}, {-1, 0x0111, 556}, {-1, 0x00BE, 834}, {-1, 0x015E, 667}, {-1, 0x013E, 299}, {-1, 0x0136, 667}, {-1, 0x0139, 556}, {-1, 0x2122, 1000}, {-1, 0x0117, 556}, {-1, 0x00CC, 278}, {-1, 0x012A, 278}, {-1, 0x013D, 556}, {-1, 0x00BD, 834}, {-1, 0x2264, 549}, {-1, 0x00F4, 556}, {-1, 0x00F1, 556}, {-1, 0x0170, 722}, {-1, 0x00C9, 667}, {-1, 0x0113, 556}, {-1, 0x011F, 556}, {-1, 0x00BC, 834}, {-1, 0x0160, 667}, {-1, 0x0218, 667}, {-1, 0x0150, 778}, {-1, 0x00B0, 400}, {-1, 0x00F2, 556}, {-1, 0x010C, 722}, {-1, 0x00F9, 556}, {-1, 0x221A, 453}, {-1, 0x010E, 722}, {-1, 0x0157, 333}, {-1, 0x00D1, 722}, {-1, 0x00F5, 556}, {-1, 0x0156, 722}, {-1, 0x013B, 556}, {-1, 0x00C3, 667}, {-1, 0x0104, 667}, {-1, 0x00C5, 667}, {-1, 0x00D5, 778}, {-1, 0x017C, 500}, {-1, 0x011A, 667}, {-1, 0x012E, 278}, {-1, 0x0137, 500}, {-1, 0x2212, 584}, {-1, 0x00CE, 278}, {-1, 0x0148, 556}, {-1, 0x0163, 278}, {-1, 0x00AC, 584}, {-1, 0x00F6, 556}, {-1, 0x00FC, 556}, {-1, 0x2260, 549}, {-1, 0x0123, 556}, {-1, 0x00F0, 556}, {-1, 0x017E, 500}, {-1, 0x0146, 556}, {-1, 0x00B9, 333}, {-1, 0x012B, 278}, {-1, 0x20AC, 556}, {-1, 0xFFFF, 0} }; static const PODOFO_CharData CHAR_DATA_TIMES_ROMAN[316] = { {32, 0x0020, 250}, {33, 0x0021, 333}, {34, 0x0022, 408}, {35, 0x0023, 500}, {36, 0x0024, 500}, {37, 0x0025, 833}, {38, 0x0026, 778}, {39, 0x2019, 333}, {40, 0x0028, 333}, {41, 0x0029, 333}, {42, 0x002A, 500}, {43, 0x002B, 564}, {44, 0x002C, 250}, {45, 0x002D, 333}, {46, 0x002E, 250}, {47, 0x002F, 278}, {48, 0x0030, 500}, {49, 0x0031, 500}, {50, 0x0032, 500}, {51, 0x0033, 500}, {52, 0x0034, 500}, {53, 0x0035, 500}, {54, 0x0036, 500}, {55, 0x0037, 500}, {56, 0x0038, 500}, {57, 0x0039, 500}, {58, 0x003A, 278}, {59, 0x003B, 278}, {60, 0x003C, 564}, {61, 0x003D, 564}, {62, 0x003E, 564}, {63, 0x003F, 444}, {64, 0x0040, 921}, {65, 0x0041, 722}, {66, 0x0042, 667}, {67, 0x0043, 667}, {68, 0x0044, 722}, {69, 0x0045, 611}, {70, 0x0046, 556}, {71, 0x0047, 722}, {72, 0x0048, 722}, {73, 0x0049, 333}, {74, 0x004A, 389}, {75, 0x004B, 722}, {76, 0x004C, 611}, {77, 0x004D, 889}, {78, 0x004E, 722}, {79, 0x004F, 722}, {80, 0x0050, 556}, {81, 0x0051, 722}, {82, 0x0052, 667}, {83, 0x0053, 556}, {84, 0x0054, 611}, {85, 0x0055, 722}, {86, 0x0056, 722}, {87, 0x0057, 944}, {88, 0x0058, 722}, {89, 0x0059, 722}, {90, 0x005A, 611}, {91, 0x005B, 333}, {92, 0x005C, 278}, {93, 0x005D, 333}, {94, 0x005E, 469}, {95, 0x005F, 500}, {96, 0x2018, 333}, {97, 0x0061, 444}, {98, 0x0062, 500}, {99, 0x0063, 444}, {100, 0x0064, 500}, {101, 0x0065, 444}, {102, 0x0066, 333}, {103, 0x0067, 500}, {104, 0x0068, 500}, {105, 0x0069, 278}, {106, 0x006A, 278}, {107, 0x006B, 500}, {108, 0x006C, 278}, {109, 0x006D, 778}, {110, 0x006E, 500}, {111, 0x006F, 500}, {112, 0x0070, 500}, {113, 0x0071, 500}, {114, 0x0072, 333}, {115, 0x0073, 389}, {116, 0x0074, 278}, {117, 0x0075, 500}, {118, 0x0076, 500}, {119, 0x0077, 722}, {120, 0x0078, 500}, {121, 0x0079, 500}, {122, 0x007A, 444}, {123, 0x007B, 480}, {124, 0x007C, 200}, {125, 0x007D, 480}, {126, 0x007E, 541}, {161, 0x00A1, 333}, {162, 0x00A2, 500}, {163, 0x00A3, 500}, {164, 0x2044, 167}, {165, 0x00A5, 500}, {166, 0x0192, 500}, {167, 0x00A7, 500}, {168, 0x00A4, 500}, {169, 0x0027, 180}, {170, 0x201C, 444}, {171, 0x00AB, 500}, {172, 0x2039, 333}, {173, 0x203A, 333}, {174, 0xFB01, 556}, {175, 0xFB02, 556}, {177, 0x2013, 500}, {178, 0x2020, 500}, {179, 0x2021, 500}, {180, 0x00B7, 250}, {182, 0x00B6, 453}, {183, 0x2022, 350}, {184, 0x201A, 333}, {185, 0x201E, 444}, {186, 0x201D, 444}, {187, 0x00BB, 500}, {188, 0x2026, 1000}, {189, 0x2030, 1000}, {191, 0x00BF, 444}, {193, 0x0060, 333}, {194, 0x00B4, 333}, {195, 0x02C6, 333}, {196, 0x02DC, 333}, {197, 0x00AF, 333}, {198, 0x02D8, 333}, {199, 0x02D9, 333}, {200, 0x00A8, 333}, {202, 0x02DA, 333}, {203, 0x00B8, 333}, {205, 0x02DD, 333}, {206, 0x02DB, 333}, {207, 0x02C7, 333}, {208, 0x2014, 1000}, {225, 0x00C6, 889}, {227, 0x00AA, 276}, {232, 0x0141, 611}, {233, 0x00D8, 722}, {234, 0x0152, 889}, {235, 0x00BA, 310}, {241, 0x00E6, 667}, {245, 0x0131, 278}, {248, 0x0142, 278}, {249, 0x00F8, 500}, {250, 0x0153, 722}, {251, 0x00DF, 500}, {-1, 0x00CF, 333}, {-1, 0x00E9, 444}, {-1, 0x0103, 444}, {-1, 0x0171, 500}, {-1, 0x011B, 444}, {-1, 0x0178, 722}, {-1, 0x00F7, 564}, {-1, 0x00DD, 722}, {-1, 0x00C2, 722}, {-1, 0x00E1, 444}, {-1, 0x00DB, 722}, {-1, 0x00FD, 500}, {-1, 0x0219, 389}, {-1, 0x00EA, 444}, {-1, 0x016E, 722}, {-1, 0x00DC, 722}, {-1, 0x0105, 444}, {-1, 0x00DA, 722}, {-1, 0x0173, 500}, {-1, 0x00CB, 611}, {-1, 0x0110, 722}, {-1, 0xF6C3, 250}, {-1, 0x00A9, 760}, {-1, 0x0112, 611}, {-1, 0x010D, 444}, {-1, 0x00E5, 444}, {-1, 0x0145, 722}, {-1, 0x013A, 278}, {-1, 0x00E0, 444}, {-1, 0x0162, 611}, {-1, 0x0106, 667}, {-1, 0x00E3, 444}, {-1, 0x0116, 611}, {-1, 0x0161, 389}, {-1, 0x015F, 389}, {-1, 0x00ED, 278}, {-1, 0x25CA, 471}, {-1, 0x0158, 667}, {-1, 0x0122, 722}, {-1, 0x00FB, 500}, {-1, 0x00E2, 444}, {-1, 0x0100, 722}, {-1, 0x0159, 333}, {-1, 0x00E7, 444}, {-1, 0x017B, 611}, {-1, 0x00DE, 556}, {-1, 0x014C, 722}, {-1, 0x0154, 667}, {-1, 0x015A, 556}, {-1, 0x010F, 588}, {-1, 0x016A, 722}, {-1, 0x016F, 500}, {-1, 0x00B3, 300}, {-1, 0x00D2, 722}, {-1, 0x00C0, 722}, {-1, 0x0102, 722}, {-1, 0x00D7, 564}, {-1, 0x00FA, 500}, {-1, 0x0164, 611}, {-1, 0x2202, 476}, {-1, 0x00FF, 500}, {-1, 0x0143, 722}, {-1, 0x00EE, 278}, {-1, 0x00CA, 611}, {-1, 0x00E4, 444}, {-1, 0x00EB, 444}, {-1, 0x0107, 444}, {-1, 0x0144, 500}, {-1, 0x016B, 500}, {-1, 0x0147, 722}, {-1, 0x00CD, 333}, {-1, 0x00B1, 564}, {-1, 0x00A6, 200}, {-1, 0x00AE, 760}, {-1, 0x011E, 722}, {-1, 0x0130, 333}, {-1, 0x2211, 600}, {-1, 0x00C8, 611}, {-1, 0x0155, 333}, {-1, 0x014D, 500}, {-1, 0x0179, 611}, {-1, 0x017D, 611}, {-1, 0x2265, 549}, {-1, 0x00D0, 722}, {-1, 0x00C7, 667}, {-1, 0x013C, 278}, {-1, 0x0165, 326}, {-1, 0x0119, 444}, {-1, 0x0172, 722}, {-1, 0x00C1, 722}, {-1, 0x00C4, 722}, {-1, 0x00E8, 444}, {-1, 0x017A, 444}, {-1, 0x012F, 278}, {-1, 0x00D3, 722}, {-1, 0x00F3, 500}, {-1, 0x0101, 444}, {-1, 0x015B, 389}, {-1, 0x00EF, 278}, {-1, 0x00D4, 722}, {-1, 0x00D9, 722}, {-1, 0x0394, 612}, {-1, 0x00FE, 500}, {-1, 0x00B2, 300}, {-1, 0x00D6, 722}, {-1, 0x00B5, 500}, {-1, 0x00EC, 278}, {-1, 0x0151, 500}, {-1, 0x0118, 611}, {-1, 0x0111, 500}, {-1, 0x00BE, 750}, {-1, 0x015E, 556}, {-1, 0x013E, 344}, {-1, 0x0136, 722}, {-1, 0x0139, 611}, {-1, 0x2122, 980}, {-1, 0x0117, 444}, {-1, 0x00CC, 333}, {-1, 0x012A, 333}, {-1, 0x013D, 611}, {-1, 0x00BD, 750}, {-1, 0x2264, 549}, {-1, 0x00F4, 500}, {-1, 0x00F1, 500}, {-1, 0x0170, 722}, {-1, 0x00C9, 611}, {-1, 0x0113, 444}, {-1, 0x011F, 500}, {-1, 0x00BC, 750}, {-1, 0x0160, 556}, {-1, 0x0218, 556}, {-1, 0x0150, 722}, {-1, 0x00B0, 400}, {-1, 0x00F2, 500}, {-1, 0x010C, 667}, {-1, 0x00F9, 500}, {-1, 0x221A, 453}, {-1, 0x010E, 722}, {-1, 0x0157, 333}, {-1, 0x00D1, 722}, {-1, 0x00F5, 500}, {-1, 0x0156, 667}, {-1, 0x013B, 611}, {-1, 0x00C3, 722}, {-1, 0x0104, 722}, {-1, 0x00C5, 722}, {-1, 0x00D5, 722}, {-1, 0x017C, 444}, {-1, 0x011A, 611}, {-1, 0x012E, 333}, {-1, 0x0137, 500}, {-1, 0x2212, 564}, {-1, 0x00CE, 333}, {-1, 0x0148, 500}, {-1, 0x0163, 278}, {-1, 0x00AC, 564}, {-1, 0x00F6, 500}, {-1, 0x00FC, 500}, {-1, 0x2260, 549}, {-1, 0x0123, 500}, {-1, 0x00F0, 500}, {-1, 0x017E, 444}, {-1, 0x0146, 500}, {-1, 0x00B9, 300}, {-1, 0x012B, 278}, {-1, 0x20AC, 500}, {-1, 0xFFFF, 0} }; static const PODOFO_CharData CHAR_DATA_TIMES_BOLD[316] = { {32, 0x0020, 250}, {33, 0x0021, 333}, {34, 0x0022, 555}, {35, 0x0023, 500}, {36, 0x0024, 500}, {37, 0x0025, 1000}, {38, 0x0026, 833}, {39, 0x2019, 333}, {40, 0x0028, 333}, {41, 0x0029, 333}, {42, 0x002A, 500}, {43, 0x002B, 570}, {44, 0x002C, 250}, {45, 0x002D, 333}, {46, 0x002E, 250}, {47, 0x002F, 278}, {48, 0x0030, 500}, {49, 0x0031, 500}, {50, 0x0032, 500}, {51, 0x0033, 500}, {52, 0x0034, 500}, {53, 0x0035, 500}, {54, 0x0036, 500}, {55, 0x0037, 500}, {56, 0x0038, 500}, {57, 0x0039, 500}, {58, 0x003A, 333}, {59, 0x003B, 333}, {60, 0x003C, 570}, {61, 0x003D, 570}, {62, 0x003E, 570}, {63, 0x003F, 500}, {64, 0x0040, 930}, {65, 0x0041, 722}, {66, 0x0042, 667}, {67, 0x0043, 722}, {68, 0x0044, 722}, {69, 0x0045, 667}, {70, 0x0046, 611}, {71, 0x0047, 778}, {72, 0x0048, 778}, {73, 0x0049, 389}, {74, 0x004A, 500}, {75, 0x004B, 778}, {76, 0x004C, 667}, {77, 0x004D, 944}, {78, 0x004E, 722}, {79, 0x004F, 778}, {80, 0x0050, 611}, {81, 0x0051, 778}, {82, 0x0052, 722}, {83, 0x0053, 556}, {84, 0x0054, 667}, {85, 0x0055, 722}, {86, 0x0056, 722}, {87, 0x0057, 1000}, {88, 0x0058, 722}, {89, 0x0059, 722}, {90, 0x005A, 667}, {91, 0x005B, 333}, {92, 0x005C, 278}, {93, 0x005D, 333}, {94, 0x005E, 581}, {95, 0x005F, 500}, {96, 0x2018, 333}, {97, 0x0061, 500}, {98, 0x0062, 556}, {99, 0x0063, 444}, {100, 0x0064, 556}, {101, 0x0065, 444}, {102, 0x0066, 333}, {103, 0x0067, 500}, {104, 0x0068, 556}, {105, 0x0069, 278}, {106, 0x006A, 333}, {107, 0x006B, 556}, {108, 0x006C, 278}, {109, 0x006D, 833}, {110, 0x006E, 556}, {111, 0x006F, 500}, {112, 0x0070, 556}, {113, 0x0071, 556}, {114, 0x0072, 444}, {115, 0x0073, 389}, {116, 0x0074, 333}, {117, 0x0075, 556}, {118, 0x0076, 500}, {119, 0x0077, 722}, {120, 0x0078, 500}, {121, 0x0079, 500}, {122, 0x007A, 444}, {123, 0x007B, 394}, {124, 0x007C, 220}, {125, 0x007D, 394}, {126, 0x007E, 520}, {161, 0x00A1, 333}, {162, 0x00A2, 500}, {163, 0x00A3, 500}, {164, 0x2044, 167}, {165, 0x00A5, 500}, {166, 0x0192, 500}, {167, 0x00A7, 500}, {168, 0x00A4, 500}, {169, 0x0027, 278}, {170, 0x201C, 500}, {171, 0x00AB, 500}, {172, 0x2039, 333}, {173, 0x203A, 333}, {174, 0xFB01, 556}, {175, 0xFB02, 556}, {177, 0x2013, 500}, {178, 0x2020, 500}, {179, 0x2021, 500}, {180, 0x00B7, 250}, {182, 0x00B6, 540}, {183, 0x2022, 350}, {184, 0x201A, 333}, {185, 0x201E, 500}, {186, 0x201D, 500}, {187, 0x00BB, 500}, {188, 0x2026, 1000}, {189, 0x2030, 1000}, {191, 0x00BF, 500}, {193, 0x0060, 333}, {194, 0x00B4, 333}, {195, 0x02C6, 333}, {196, 0x02DC, 333}, {197, 0x00AF, 333}, {198, 0x02D8, 333}, {199, 0x02D9, 333}, {200, 0x00A8, 333}, {202, 0x02DA, 333}, {203, 0x00B8, 333}, {205, 0x02DD, 333}, {206, 0x02DB, 333}, {207, 0x02C7, 333}, {208, 0x2014, 1000}, {225, 0x00C6, 1000}, {227, 0x00AA, 300}, {232, 0x0141, 667}, {233, 0x00D8, 778}, {234, 0x0152, 1000}, {235, 0x00BA, 330}, {241, 0x00E6, 722}, {245, 0x0131, 278}, {248, 0x0142, 278}, {249, 0x00F8, 500}, {250, 0x0153, 722}, {251, 0x00DF, 556}, {-1, 0x00CF, 389}, {-1, 0x00E9, 444}, {-1, 0x0103, 500}, {-1, 0x0171, 556}, {-1, 0x011B, 444}, {-1, 0x0178, 722}, {-1, 0x00F7, 570}, {-1, 0x00DD, 722}, {-1, 0x00C2, 722}, {-1, 0x00E1, 500}, {-1, 0x00DB, 722}, {-1, 0x00FD, 500}, {-1, 0x0219, 389}, {-1, 0x00EA, 444}, {-1, 0x016E, 722}, {-1, 0x00DC, 722}, {-1, 0x0105, 500}, {-1, 0x00DA, 722}, {-1, 0x0173, 556}, {-1, 0x00CB, 667}, {-1, 0x0110, 722}, {-1, 0xF6C3, 250}, {-1, 0x00A9, 747}, {-1, 0x0112, 667}, {-1, 0x010D, 444}, {-1, 0x00E5, 500}, {-1, 0x0145, 722}, {-1, 0x013A, 278}, {-1, 0x00E0, 500}, {-1, 0x0162, 667}, {-1, 0x0106, 722}, {-1, 0x00E3, 500}, {-1, 0x0116, 667}, {-1, 0x0161, 389}, {-1, 0x015F, 389}, {-1, 0x00ED, 278}, {-1, 0x25CA, 494}, {-1, 0x0158, 722}, {-1, 0x0122, 778}, {-1, 0x00FB, 556}, {-1, 0x00E2, 500}, {-1, 0x0100, 722}, {-1, 0x0159, 444}, {-1, 0x00E7, 444}, {-1, 0x017B, 667}, {-1, 0x00DE, 611}, {-1, 0x014C, 778}, {-1, 0x0154, 722}, {-1, 0x015A, 556}, {-1, 0x010F, 672}, {-1, 0x016A, 722}, {-1, 0x016F, 556}, {-1, 0x00B3, 300}, {-1, 0x00D2, 778}, {-1, 0x00C0, 722}, {-1, 0x0102, 722}, {-1, 0x00D7, 570}, {-1, 0x00FA, 556}, {-1, 0x0164, 667}, {-1, 0x2202, 494}, {-1, 0x00FF, 500}, {-1, 0x0143, 722}, {-1, 0x00EE, 278}, {-1, 0x00CA, 667}, {-1, 0x00E4, 500}, {-1, 0x00EB, 444}, {-1, 0x0107, 444}, {-1, 0x0144, 556}, {-1, 0x016B, 556}, {-1, 0x0147, 722}, {-1, 0x00CD, 389}, {-1, 0x00B1, 570}, {-1, 0x00A6, 220}, {-1, 0x00AE, 747}, {-1, 0x011E, 778}, {-1, 0x0130, 389}, {-1, 0x2211, 600}, {-1, 0x00C8, 667}, {-1, 0x0155, 444}, {-1, 0x014D, 500}, {-1, 0x0179, 667}, {-1, 0x017D, 667}, {-1, 0x2265, 549}, {-1, 0x00D0, 722}, {-1, 0x00C7, 722}, {-1, 0x013C, 278}, {-1, 0x0165, 416}, {-1, 0x0119, 444}, {-1, 0x0172, 722}, {-1, 0x00C1, 722}, {-1, 0x00C4, 722}, {-1, 0x00E8, 444}, {-1, 0x017A, 444}, {-1, 0x012F, 278}, {-1, 0x00D3, 778}, {-1, 0x00F3, 500}, {-1, 0x0101, 500}, {-1, 0x015B, 389}, {-1, 0x00EF, 278}, {-1, 0x00D4, 778}, {-1, 0x00D9, 722}, {-1, 0x0394, 612}, {-1, 0x00FE, 556}, {-1, 0x00B2, 300}, {-1, 0x00D6, 778}, {-1, 0x00B5, 556}, {-1, 0x00EC, 278}, {-1, 0x0151, 500}, {-1, 0x0118, 667}, {-1, 0x0111, 556}, {-1, 0x00BE, 750}, {-1, 0x015E, 556}, {-1, 0x013E, 394}, {-1, 0x0136, 778}, {-1, 0x0139, 667}, {-1, 0x2122, 1000}, {-1, 0x0117, 444}, {-1, 0x00CC, 389}, {-1, 0x012A, 389}, {-1, 0x013D, 667}, {-1, 0x00BD, 750}, {-1, 0x2264, 549}, {-1, 0x00F4, 500}, {-1, 0x00F1, 556}, {-1, 0x0170, 722}, {-1, 0x00C9, 667}, {-1, 0x0113, 444}, {-1, 0x011F, 500}, {-1, 0x00BC, 750}, {-1, 0x0160, 556}, {-1, 0x0218, 556}, {-1, 0x0150, 778}, {-1, 0x00B0, 400}, {-1, 0x00F2, 500}, {-1, 0x010C, 722}, {-1, 0x00F9, 556}, {-1, 0x221A, 549}, {-1, 0x010E, 722}, {-1, 0x0157, 444}, {-1, 0x00D1, 722}, {-1, 0x00F5, 500}, {-1, 0x0156, 722}, {-1, 0x013B, 667}, {-1, 0x00C3, 722}, {-1, 0x0104, 722}, {-1, 0x00C5, 722}, {-1, 0x00D5, 778}, {-1, 0x017C, 444}, {-1, 0x011A, 667}, {-1, 0x012E, 389}, {-1, 0x0137, 556}, {-1, 0x2212, 570}, {-1, 0x00CE, 389}, {-1, 0x0148, 556}, {-1, 0x0163, 333}, {-1, 0x00AC, 570}, {-1, 0x00F6, 500}, {-1, 0x00FC, 556}, {-1, 0x2260, 549}, {-1, 0x0123, 500}, {-1, 0x00F0, 500}, {-1, 0x017E, 444}, {-1, 0x0146, 556}, {-1, 0x00B9, 300}, {-1, 0x012B, 278}, {-1, 0x20AC, 500}, {-1, 0xFFFF, 0} }; static const PODOFO_CharData CHAR_DATA_TIMES_BOLD_ITALIC[316] = { {32, 0x0020, 250}, {33, 0x0021, 389}, {34, 0x0022, 555}, {35, 0x0023, 500}, {36, 0x0024, 500}, {37, 0x0025, 833}, {38, 0x0026, 778}, {39, 0x2019, 333}, {40, 0x0028, 333}, {41, 0x0029, 333}, {42, 0x002A, 500}, {43, 0x002B, 570}, {44, 0x002C, 250}, {45, 0x002D, 333}, {46, 0x002E, 250}, {47, 0x002F, 278}, {48, 0x0030, 500}, {49, 0x0031, 500}, {50, 0x0032, 500}, {51, 0x0033, 500}, {52, 0x0034, 500}, {53, 0x0035, 500}, {54, 0x0036, 500}, {55, 0x0037, 500}, {56, 0x0038, 500}, {57, 0x0039, 500}, {58, 0x003A, 333}, {59, 0x003B, 333}, {60, 0x003C, 570}, {61, 0x003D, 570}, {62, 0x003E, 570}, {63, 0x003F, 500}, {64, 0x0040, 832}, {65, 0x0041, 667}, {66, 0x0042, 667}, {67, 0x0043, 667}, {68, 0x0044, 722}, {69, 0x0045, 667}, {70, 0x0046, 667}, {71, 0x0047, 722}, {72, 0x0048, 778}, {73, 0x0049, 389}, {74, 0x004A, 500}, {75, 0x004B, 667}, {76, 0x004C, 611}, {77, 0x004D, 889}, {78, 0x004E, 722}, {79, 0x004F, 722}, {80, 0x0050, 611}, {81, 0x0051, 722}, {82, 0x0052, 667}, {83, 0x0053, 556}, {84, 0x0054, 611}, {85, 0x0055, 722}, {86, 0x0056, 667}, {87, 0x0057, 889}, {88, 0x0058, 667}, {89, 0x0059, 611}, {90, 0x005A, 611}, {91, 0x005B, 333}, {92, 0x005C, 278}, {93, 0x005D, 333}, {94, 0x005E, 570}, {95, 0x005F, 500}, {96, 0x2018, 333}, {97, 0x0061, 500}, {98, 0x0062, 500}, {99, 0x0063, 444}, {100, 0x0064, 500}, {101, 0x0065, 444}, {102, 0x0066, 333}, {103, 0x0067, 500}, {104, 0x0068, 556}, {105, 0x0069, 278}, {106, 0x006A, 278}, {107, 0x006B, 500}, {108, 0x006C, 278}, {109, 0x006D, 778}, {110, 0x006E, 556}, {111, 0x006F, 500}, {112, 0x0070, 500}, {113, 0x0071, 500}, {114, 0x0072, 389}, {115, 0x0073, 389}, {116, 0x0074, 278}, {117, 0x0075, 556}, {118, 0x0076, 444}, {119, 0x0077, 667}, {120, 0x0078, 500}, {121, 0x0079, 444}, {122, 0x007A, 389}, {123, 0x007B, 348}, {124, 0x007C, 220}, {125, 0x007D, 348}, {126, 0x007E, 570}, {161, 0x00A1, 389}, {162, 0x00A2, 500}, {163, 0x00A3, 500}, {164, 0x2044, 167}, {165, 0x00A5, 500}, {166, 0x0192, 500}, {167, 0x00A7, 500}, {168, 0x00A4, 500}, {169, 0x0027, 278}, {170, 0x201C, 500}, {171, 0x00AB, 500}, {172, 0x2039, 333}, {173, 0x203A, 333}, {174, 0xFB01, 556}, {175, 0xFB02, 556}, {177, 0x2013, 500}, {178, 0x2020, 500}, {179, 0x2021, 500}, {180, 0x00B7, 250}, {182, 0x00B6, 500}, {183, 0x2022, 350}, {184, 0x201A, 333}, {185, 0x201E, 500}, {186, 0x201D, 500}, {187, 0x00BB, 500}, {188, 0x2026, 1000}, {189, 0x2030, 1000}, {191, 0x00BF, 500}, {193, 0x0060, 333}, {194, 0x00B4, 333}, {195, 0x02C6, 333}, {196, 0x02DC, 333}, {197, 0x00AF, 333}, {198, 0x02D8, 333}, {199, 0x02D9, 333}, {200, 0x00A8, 333}, {202, 0x02DA, 333}, {203, 0x00B8, 333}, {205, 0x02DD, 333}, {206, 0x02DB, 333}, {207, 0x02C7, 333}, {208, 0x2014, 1000}, {225, 0x00C6, 944}, {227, 0x00AA, 266}, {232, 0x0141, 611}, {233, 0x00D8, 722}, {234, 0x0152, 944}, {235, 0x00BA, 300}, {241, 0x00E6, 722}, {245, 0x0131, 278}, {248, 0x0142, 278}, {249, 0x00F8, 500}, {250, 0x0153, 722}, {251, 0x00DF, 500}, {-1, 0x00CF, 389}, {-1, 0x00E9, 444}, {-1, 0x0103, 500}, {-1, 0x0171, 556}, {-1, 0x011B, 444}, {-1, 0x0178, 611}, {-1, 0x00F7, 570}, {-1, 0x00DD, 611}, {-1, 0x00C2, 667}, {-1, 0x00E1, 500}, {-1, 0x00DB, 722}, {-1, 0x00FD, 444}, {-1, 0x0219, 389}, {-1, 0x00EA, 444}, {-1, 0x016E, 722}, {-1, 0x00DC, 722}, {-1, 0x0105, 500}, {-1, 0x00DA, 722}, {-1, 0x0173, 556}, {-1, 0x00CB, 667}, {-1, 0x0110, 722}, {-1, 0xF6C3, 250}, {-1, 0x00A9, 747}, {-1, 0x0112, 667}, {-1, 0x010D, 444}, {-1, 0x00E5, 500}, {-1, 0x0145, 722}, {-1, 0x013A, 278}, {-1, 0x00E0, 500}, {-1, 0x0162, 611}, {-1, 0x0106, 667}, {-1, 0x00E3, 500}, {-1, 0x0116, 667}, {-1, 0x0161, 389}, {-1, 0x015F, 389}, {-1, 0x00ED, 278}, {-1, 0x25CA, 494}, {-1, 0x0158, 667}, {-1, 0x0122, 722}, {-1, 0x00FB, 556}, {-1, 0x00E2, 500}, {-1, 0x0100, 667}, {-1, 0x0159, 389}, {-1, 0x00E7, 444}, {-1, 0x017B, 611}, {-1, 0x00DE, 611}, {-1, 0x014C, 722}, {-1, 0x0154, 667}, {-1, 0x015A, 556}, {-1, 0x010F, 608}, {-1, 0x016A, 722}, {-1, 0x016F, 556}, {-1, 0x00B3, 300}, {-1, 0x00D2, 722}, {-1, 0x00C0, 667}, {-1, 0x0102, 667}, {-1, 0x00D7, 570}, {-1, 0x00FA, 556}, {-1, 0x0164, 611}, {-1, 0x2202, 494}, {-1, 0x00FF, 444}, {-1, 0x0143, 722}, {-1, 0x00EE, 278}, {-1, 0x00CA, 667}, {-1, 0x00E4, 500}, {-1, 0x00EB, 444}, {-1, 0x0107, 444}, {-1, 0x0144, 556}, {-1, 0x016B, 556}, {-1, 0x0147, 722}, {-1, 0x00CD, 389}, {-1, 0x00B1, 570}, {-1, 0x00A6, 220}, {-1, 0x00AE, 747}, {-1, 0x011E, 722}, {-1, 0x0130, 389}, {-1, 0x2211, 600}, {-1, 0x00C8, 667}, {-1, 0x0155, 389}, {-1, 0x014D, 500}, {-1, 0x0179, 611}, {-1, 0x017D, 611}, {-1, 0x2265, 549}, {-1, 0x00D0, 722}, {-1, 0x00C7, 667}, {-1, 0x013C, 278}, {-1, 0x0165, 366}, {-1, 0x0119, 444}, {-1, 0x0172, 722}, {-1, 0x00C1, 667}, {-1, 0x00C4, 667}, {-1, 0x00E8, 444}, {-1, 0x017A, 389}, {-1, 0x012F, 278}, {-1, 0x00D3, 722}, {-1, 0x00F3, 500}, {-1, 0x0101, 500}, {-1, 0x015B, 389}, {-1, 0x00EF, 278}, {-1, 0x00D4, 722}, {-1, 0x00D9, 722}, {-1, 0x0394, 612}, {-1, 0x00FE, 500}, {-1, 0x00B2, 300}, {-1, 0x00D6, 722}, {-1, 0x00B5, 576}, {-1, 0x00EC, 278}, {-1, 0x0151, 500}, {-1, 0x0118, 667}, {-1, 0x0111, 500}, {-1, 0x00BE, 750}, {-1, 0x015E, 556}, {-1, 0x013E, 382}, {-1, 0x0136, 667}, {-1, 0x0139, 611}, {-1, 0x2122, 1000}, {-1, 0x0117, 444}, {-1, 0x00CC, 389}, {-1, 0x012A, 389}, {-1, 0x013D, 611}, {-1, 0x00BD, 750}, {-1, 0x2264, 549}, {-1, 0x00F4, 500}, {-1, 0x00F1, 556}, {-1, 0x0170, 722}, {-1, 0x00C9, 667}, {-1, 0x0113, 444}, {-1, 0x011F, 500}, {-1, 0x00BC, 750}, {-1, 0x0160, 556}, {-1, 0x0218, 556}, {-1, 0x0150, 722}, {-1, 0x00B0, 400}, {-1, 0x00F2, 500}, {-1, 0x010C, 667}, {-1, 0x00F9, 556}, {-1, 0x221A, 549}, {-1, 0x010E, 722}, {-1, 0x0157, 389}, {-1, 0x00D1, 722}, {-1, 0x00F5, 500}, {-1, 0x0156, 667}, {-1, 0x013B, 611}, {-1, 0x00C3, 667}, {-1, 0x0104, 667}, {-1, 0x00C5, 667}, {-1, 0x00D5, 722}, {-1, 0x017C, 389}, {-1, 0x011A, 667}, {-1, 0x012E, 389}, {-1, 0x0137, 500}, {-1, 0x2212, 606}, {-1, 0x00CE, 389}, {-1, 0x0148, 556}, {-1, 0x0163, 278}, {-1, 0x00AC, 606}, {-1, 0x00F6, 500}, {-1, 0x00FC, 556}, {-1, 0x2260, 549}, {-1, 0x0123, 500}, {-1, 0x00F0, 500}, {-1, 0x017E, 389}, {-1, 0x0146, 556}, {-1, 0x00B9, 300}, {-1, 0x012B, 278}, {-1, 0x20AC, 500}, {-1, 0xFFFF, 0} }; static const PODOFO_CharData CHAR_DATA_TIMES_ITALIC[316] = { {32, 0x0020, 250}, {33, 0x0021, 333}, {34, 0x0022, 420}, {35, 0x0023, 500}, {36, 0x0024, 500}, {37, 0x0025, 833}, {38, 0x0026, 778}, {39, 0x2019, 333}, {40, 0x0028, 333}, {41, 0x0029, 333}, {42, 0x002A, 500}, {43, 0x002B, 675}, {44, 0x002C, 250}, {45, 0x002D, 333}, {46, 0x002E, 250}, {47, 0x002F, 278}, {48, 0x0030, 500}, {49, 0x0031, 500}, {50, 0x0032, 500}, {51, 0x0033, 500}, {52, 0x0034, 500}, {53, 0x0035, 500}, {54, 0x0036, 500}, {55, 0x0037, 500}, {56, 0x0038, 500}, {57, 0x0039, 500}, {58, 0x003A, 333}, {59, 0x003B, 333}, {60, 0x003C, 675}, {61, 0x003D, 675}, {62, 0x003E, 675}, {63, 0x003F, 500}, {64, 0x0040, 920}, {65, 0x0041, 611}, {66, 0x0042, 611}, {67, 0x0043, 667}, {68, 0x0044, 722}, {69, 0x0045, 611}, {70, 0x0046, 611}, {71, 0x0047, 722}, {72, 0x0048, 722}, {73, 0x0049, 333}, {74, 0x004A, 444}, {75, 0x004B, 667}, {76, 0x004C, 556}, {77, 0x004D, 833}, {78, 0x004E, 667}, {79, 0x004F, 722}, {80, 0x0050, 611}, {81, 0x0051, 722}, {82, 0x0052, 611}, {83, 0x0053, 500}, {84, 0x0054, 556}, {85, 0x0055, 722}, {86, 0x0056, 611}, {87, 0x0057, 833}, {88, 0x0058, 611}, {89, 0x0059, 556}, {90, 0x005A, 556}, {91, 0x005B, 389}, {92, 0x005C, 278}, {93, 0x005D, 389}, {94, 0x005E, 422}, {95, 0x005F, 500}, {96, 0x2018, 333}, {97, 0x0061, 500}, {98, 0x0062, 500}, {99, 0x0063, 444}, {100, 0x0064, 500}, {101, 0x0065, 444}, {102, 0x0066, 278}, {103, 0x0067, 500}, {104, 0x0068, 500}, {105, 0x0069, 278}, {106, 0x006A, 278}, {107, 0x006B, 444}, {108, 0x006C, 278}, {109, 0x006D, 722}, {110, 0x006E, 500}, {111, 0x006F, 500}, {112, 0x0070, 500}, {113, 0x0071, 500}, {114, 0x0072, 389}, {115, 0x0073, 389}, {116, 0x0074, 278}, {117, 0x0075, 500}, {118, 0x0076, 444}, {119, 0x0077, 667}, {120, 0x0078, 444}, {121, 0x0079, 444}, {122, 0x007A, 389}, {123, 0x007B, 400}, {124, 0x007C, 275}, {125, 0x007D, 400}, {126, 0x007E, 541}, {161, 0x00A1, 389}, {162, 0x00A2, 500}, {163, 0x00A3, 500}, {164, 0x2044, 167}, {165, 0x00A5, 500}, {166, 0x0192, 500}, {167, 0x00A7, 500}, {168, 0x00A4, 500}, {169, 0x0027, 214}, {170, 0x201C, 556}, {171, 0x00AB, 500}, {172, 0x2039, 333}, {173, 0x203A, 333}, {174, 0xFB01, 500}, {175, 0xFB02, 500}, {177, 0x2013, 500}, {178, 0x2020, 500}, {179, 0x2021, 500}, {180, 0x00B7, 250}, {182, 0x00B6, 523}, {183, 0x2022, 350}, {184, 0x201A, 333}, {185, 0x201E, 556}, {186, 0x201D, 556}, {187, 0x00BB, 500}, {188, 0x2026, 889}, {189, 0x2030, 1000}, {191, 0x00BF, 500}, {193, 0x0060, 333}, {194, 0x00B4, 333}, {195, 0x02C6, 333}, {196, 0x02DC, 333}, {197, 0x00AF, 333}, {198, 0x02D8, 333}, {199, 0x02D9, 333}, {200, 0x00A8, 333}, {202, 0x02DA, 333}, {203, 0x00B8, 333}, {205, 0x02DD, 333}, {206, 0x02DB, 333}, {207, 0x02C7, 333}, {208, 0x2014, 889}, {225, 0x00C6, 889}, {227, 0x00AA, 276}, {232, 0x0141, 556}, {233, 0x00D8, 722}, {234, 0x0152, 944}, {235, 0x00BA, 310}, {241, 0x00E6, 667}, {245, 0x0131, 278}, {248, 0x0142, 278}, {249, 0x00F8, 500}, {250, 0x0153, 667}, {251, 0x00DF, 500}, {-1, 0x00CF, 333}, {-1, 0x00E9, 444}, {-1, 0x0103, 500}, {-1, 0x0171, 500}, {-1, 0x011B, 444}, {-1, 0x0178, 556}, {-1, 0x00F7, 675}, {-1, 0x00DD, 556}, {-1, 0x00C2, 611}, {-1, 0x00E1, 500}, {-1, 0x00DB, 722}, {-1, 0x00FD, 444}, {-1, 0x0219, 389}, {-1, 0x00EA, 444}, {-1, 0x016E, 722}, {-1, 0x00DC, 722}, {-1, 0x0105, 500}, {-1, 0x00DA, 722}, {-1, 0x0173, 500}, {-1, 0x00CB, 611}, {-1, 0x0110, 722}, {-1, 0xF6C3, 250}, {-1, 0x00A9, 760}, {-1, 0x0112, 611}, {-1, 0x010D, 444}, {-1, 0x00E5, 500}, {-1, 0x0145, 667}, {-1, 0x013A, 278}, {-1, 0x00E0, 500}, {-1, 0x0162, 556}, {-1, 0x0106, 667}, {-1, 0x00E3, 500}, {-1, 0x0116, 611}, {-1, 0x0161, 389}, {-1, 0x015F, 389}, {-1, 0x00ED, 278}, {-1, 0x25CA, 471}, {-1, 0x0158, 611}, {-1, 0x0122, 722}, {-1, 0x00FB, 500}, {-1, 0x00E2, 500}, {-1, 0x0100, 611}, {-1, 0x0159, 389}, {-1, 0x00E7, 444}, {-1, 0x017B, 556}, {-1, 0x00DE, 611}, {-1, 0x014C, 722}, {-1, 0x0154, 611}, {-1, 0x015A, 500}, {-1, 0x010F, 544}, {-1, 0x016A, 722}, {-1, 0x016F, 500}, {-1, 0x00B3, 300}, {-1, 0x00D2, 722}, {-1, 0x00C0, 611}, {-1, 0x0102, 611}, {-1, 0x00D7, 675}, {-1, 0x00FA, 500}, {-1, 0x0164, 556}, {-1, 0x2202, 476}, {-1, 0x00FF, 444}, {-1, 0x0143, 667}, {-1, 0x00EE, 278}, {-1, 0x00CA, 611}, {-1, 0x00E4, 500}, {-1, 0x00EB, 444}, {-1, 0x0107, 444}, {-1, 0x0144, 500}, {-1, 0x016B, 500}, {-1, 0x0147, 667}, {-1, 0x00CD, 333}, {-1, 0x00B1, 675}, {-1, 0x00A6, 275}, {-1, 0x00AE, 760}, {-1, 0x011E, 722}, {-1, 0x0130, 333}, {-1, 0x2211, 600}, {-1, 0x00C8, 611}, {-1, 0x0155, 389}, {-1, 0x014D, 500}, {-1, 0x0179, 556}, {-1, 0x017D, 556}, {-1, 0x2265, 549}, {-1, 0x00D0, 722}, {-1, 0x00C7, 667}, {-1, 0x013C, 278}, {-1, 0x0165, 300}, {-1, 0x0119, 444}, {-1, 0x0172, 722}, {-1, 0x00C1, 611}, {-1, 0x00C4, 611}, {-1, 0x00E8, 444}, {-1, 0x017A, 389}, {-1, 0x012F, 278}, {-1, 0x00D3, 722}, {-1, 0x00F3, 500}, {-1, 0x0101, 500}, {-1, 0x015B, 389}, {-1, 0x00EF, 278}, {-1, 0x00D4, 722}, {-1, 0x00D9, 722}, {-1, 0x0394, 612}, {-1, 0x00FE, 500}, {-1, 0x00B2, 300}, {-1, 0x00D6, 722}, {-1, 0x00B5, 500}, {-1, 0x00EC, 278}, {-1, 0x0151, 500}, {-1, 0x0118, 611}, {-1, 0x0111, 500}, {-1, 0x00BE, 750}, {-1, 0x015E, 500}, {-1, 0x013E, 300}, {-1, 0x0136, 667}, {-1, 0x0139, 556}, {-1, 0x2122, 980}, {-1, 0x0117, 444}, {-1, 0x00CC, 333}, {-1, 0x012A, 333}, {-1, 0x013D, 611}, {-1, 0x00BD, 750}, {-1, 0x2264, 549}, {-1, 0x00F4, 500}, {-1, 0x00F1, 500}, {-1, 0x0170, 722}, {-1, 0x00C9, 611}, {-1, 0x0113, 444}, {-1, 0x011F, 500}, {-1, 0x00BC, 750}, {-1, 0x0160, 500}, {-1, 0x0218, 500}, {-1, 0x0150, 722}, {-1, 0x00B0, 400}, {-1, 0x00F2, 500}, {-1, 0x010C, 667}, {-1, 0x00F9, 500}, {-1, 0x221A, 453}, {-1, 0x010E, 722}, {-1, 0x0157, 389}, {-1, 0x00D1, 667}, {-1, 0x00F5, 500}, {-1, 0x0156, 611}, {-1, 0x013B, 556}, {-1, 0x00C3, 611}, {-1, 0x0104, 611}, {-1, 0x00C5, 611}, {-1, 0x00D5, 722}, {-1, 0x017C, 389}, {-1, 0x011A, 611}, {-1, 0x012E, 333}, {-1, 0x0137, 444}, {-1, 0x2212, 675}, {-1, 0x00CE, 333}, {-1, 0x0148, 500}, {-1, 0x0163, 278}, {-1, 0x00AC, 675}, {-1, 0x00F6, 500}, {-1, 0x00FC, 500}, {-1, 0x2260, 549}, {-1, 0x0123, 500}, {-1, 0x00F0, 500}, {-1, 0x017E, 389}, {-1, 0x0146, 500}, {-1, 0x00B9, 300}, {-1, 0x012B, 278}, {-1, 0x20AC, 500}, {-1, 0xFFFF, 0} }; static const PODOFO_CharData CHAR_DATA_ZAPF_DINGBATS[203] = { {32, 0x0020, 278}, {33, 0x0021, 974}, {34, 0x0022, 961}, {35, 0x0023, 974}, {36, 0x0024, 980}, {37, 0x0025, 719}, {38, 0x0026, 789}, {39, 0x0027, 790}, {40, 0x0028, 791}, {41, 0x0029, 690}, {42, 0x002A, 960}, {43, 0x002B, 939}, {44, 0x002C, 549}, {45, 0x002D, 855}, {46, 0x002E, 911}, {47, 0x002F, 933}, {48, 0x0030, 911}, {49, 0x0031, 945}, {50, 0x0032, 974}, {51, 0x0033, 755}, {52, 0x0034, 846}, {53, 0x0035, 762}, {54, 0x0036, 761}, {55, 0x0037, 571}, {56, 0x0038, 677}, {57, 0x0039, 763}, {58, 0x003A, 760}, {59, 0x003B, 759}, {60, 0x003C, 754}, {61, 0x003D, 494}, {62, 0x003E, 552}, {63, 0x003F, 537}, {64, 0x0040, 577}, {65, 0x0041, 692}, {66, 0x0042, 786}, {67, 0x0043, 788}, {68, 0x0044, 788}, {69, 0x0045, 790}, {70, 0x0046, 793}, {71, 0x0047, 794}, {72, 0x0048, 816}, {73, 0x0049, 823}, {74, 0x004A, 789}, {75, 0x004B, 841}, {76, 0x004C, 823}, {77, 0x004D, 833}, {78, 0x004E, 816}, {79, 0x004F, 831}, {80, 0x0050, 923}, {81, 0x0051, 744}, {82, 0x0052, 723}, {83, 0x0053, 749}, {84, 0x0054, 790}, {85, 0x0055, 792}, {86, 0x0056, 695}, {87, 0x0057, 776}, {88, 0x0058, 768}, {89, 0x0059, 792}, {90, 0x005A, 759}, {91, 0x005B, 707}, {92, 0x005C, 708}, {93, 0x005D, 682}, {94, 0x005E, 701}, {95, 0x005F, 826}, {96, 0x0060, 815}, {97, 0x0061, 789}, {98, 0x0062, 789}, {99, 0x0063, 707}, {100, 0x0064, 687}, {101, 0x0065, 696}, {102, 0x0066, 689}, {103, 0x0067, 786}, {104, 0x0068, 787}, {105, 0x0069, 713}, {106, 0x006A, 791}, {107, 0x006B, 785}, {108, 0x006C, 791}, {109, 0x006D, 873}, {110, 0x006E, 761}, {111, 0x006F, 762}, {112, 0x0070, 762}, {113, 0x0071, 759}, {114, 0x0072, 759}, {115, 0x0073, 892}, {116, 0x0074, 892}, {117, 0x0075, 788}, {118, 0x0076, 784}, {119, 0x0077, 438}, {120, 0x0078, 138}, {121, 0x0079, 277}, {122, 0x007A, 415}, {123, 0x007B, 392}, {124, 0x007C, 392}, {125, 0x007D, 668}, {126, 0x007E, 668}, {128, 0x0080, 390}, {129, 0x0081, 390}, {130, 0x0082, 317}, {131, 0x0083, 317}, {132, 0x0084, 276}, {133, 0x0085, 276}, {134, 0x0086, 509}, {135, 0x0087, 509}, {136, 0x0088, 410}, {137, 0x0089, 410}, {138, 0x008A, 234}, {139, 0x008B, 234}, {140, 0x008C, 334}, {141, 0x008D, 334}, {161, 0x00A1, 732}, {162, 0x00A2, 544}, {163, 0x00A3, 544}, {164, 0x00A4, 910}, {165, 0x00A5, 667}, {166, 0x00A6, 760}, {167, 0x00A7, 760}, {168, 0x00A8, 776}, {169, 0x00A9, 595}, {170, 0x00AA, 694}, {171, 0x00AB, 626}, {172, 0x00AC, 788}, {173, 0x00AD, 788}, {174, 0x00AE, 788}, {175, 0x00AF, 788}, {176, 0x00B0, 788}, {177, 0x00B1, 788}, {178, 0x00B2, 788}, {179, 0x00B3, 788}, {180, 0x00B4, 788}, {181, 0x00B5, 788}, {182, 0x00B6, 788}, {183, 0x00B7, 788}, {184, 0x00B8, 788}, {185, 0x00B9, 788}, {186, 0x00BA, 788}, {187, 0x00BB, 788}, {188, 0x00BC, 788}, {189, 0x00BD, 788}, {190, 0x00BE, 788}, {191, 0x00BF, 788}, {192, 0x00C0, 788}, {193, 0x00C1, 788}, {194, 0x00C2, 788}, {195, 0x00C3, 788}, {196, 0x00C4, 788}, {197, 0x00C5, 788}, {198, 0x00C6, 788}, {199, 0x00C7, 788}, {200, 0x00C8, 788}, {201, 0x00C9, 788}, {202, 0x00CA, 788}, {203, 0x00CB, 788}, {204, 0x00CC, 788}, {205, 0x00CD, 788}, {206, 0x00CE, 788}, {207, 0x00CF, 788}, {208, 0x00D0, 788}, {209, 0x00D1, 788}, {210, 0x00D2, 788}, {211, 0x00D3, 788}, {212, 0x00D4, 894}, {213, 0x00D5, 838}, {214, 0x00D6, 1016}, {215, 0x00D7, 458}, {216, 0x00D8, 748}, {217, 0x00D9, 924}, {218, 0x00DA, 748}, {219, 0x00DB, 918}, {220, 0x00DC, 927}, {221, 0x00DD, 928}, {222, 0x00DE, 928}, {223, 0x00DF, 834}, {224, 0x00E0, 873}, {225, 0x00E1, 828}, {226, 0x00E2, 924}, {227, 0x00E3, 924}, {228, 0x00E4, 917}, {229, 0x00E5, 930}, {230, 0x00E6, 931}, {231, 0x00E7, 463}, {232, 0x00E8, 883}, {233, 0x00E9, 836}, {234, 0x00EA, 836}, {235, 0x00EB, 867}, {236, 0x00EC, 867}, {237, 0x00ED, 696}, {238, 0x00EE, 696}, {239, 0x00EF, 874}, {241, 0x00F1, 874}, {242, 0x00F2, 760}, {243, 0x00F3, 946}, {244, 0x00F4, 771}, {245, 0x00F5, 865}, {246, 0x00F6, 771}, {247, 0x00F7, 888}, {248, 0x00F8, 967}, {249, 0x00F9, 888}, {250, 0x00FA, 831}, {251, 0x00FB, 873}, {252, 0x00FC, 927}, {253, 0x00FD, 970}, {254, 0x00FE, 918}, {-1, 0xFFFF, 0} }; static const PODOFO_CharData CHAR_DATA_SYMBOL[190] = { {32, 0x0020, 250}, {33, 0x0021, 333}, {34, 0x0022, 713}, {35, 0x0023, 500}, {36, 0x0024, 549}, {37, 0x0025, 833}, {38, 0x0026, 778}, {39, 0x0027, 439}, {40, 0x0028, 333}, {41, 0x0029, 333}, {42, 0x002A, 500}, {43, 0x002B, 549}, {44, 0x002C, 250}, {45, 0x002D, 549}, {46, 0x002E, 250}, {47, 0x002F, 278}, {48, 0x0030, 500}, {49, 0x0031, 500}, {50, 0x0032, 500}, {51, 0x0033, 500}, {52, 0x0034, 500}, {53, 0x0035, 500}, {54, 0x0036, 500}, {55, 0x0037, 500}, {56, 0x0038, 500}, {57, 0x0039, 500}, {58, 0x003A, 278}, {59, 0x003B, 278}, {60, 0x003C, 549}, {61, 0x003D, 549}, {62, 0x003E, 549}, {63, 0x003F, 444}, {64, 0x0040, 549}, {65, 0x0041, 722}, {66, 0x0042, 667}, {67, 0x0043, 722}, {68, 0x0044, 612}, {69, 0x0045, 611}, {70, 0x0046, 763}, {71, 0x0047, 603}, {72, 0x0048, 722}, {73, 0x0049, 333}, {74, 0x004A, 631}, {75, 0x004B, 722}, {76, 0x004C, 686}, {77, 0x004D, 889}, {78, 0x004E, 722}, {79, 0x004F, 722}, {80, 0x0050, 768}, {81, 0x0051, 741}, {82, 0x0052, 556}, {83, 0x0053, 592}, {84, 0x0054, 611}, {85, 0x0055, 690}, {86, 0x0056, 439}, {87, 0x0057, 768}, {88, 0x0058, 645}, {89, 0x0059, 795}, {90, 0x005A, 611}, {91, 0x005B, 333}, {92, 0x005C, 863}, {93, 0x005D, 333}, {94, 0x005E, 658}, {95, 0x005F, 500}, {96, 0x0060, 500}, {97, 0x0061, 631}, {98, 0x0062, 549}, {99, 0x0063, 549}, {100, 0x0064, 494}, {101, 0x0065, 439}, {102, 0x0066, 521}, {103, 0x0067, 411}, {104, 0x0068, 603}, {105, 0x0069, 329}, {106, 0x006A, 603}, {107, 0x006B, 549}, {108, 0x006C, 549}, {109, 0x006D, 576}, {110, 0x006E, 521}, {111, 0x006F, 549}, {112, 0x0070, 549}, {113, 0x0071, 521}, {114, 0x0072, 549}, {115, 0x0073, 603}, {116, 0x0074, 439}, {117, 0x0075, 576}, {118, 0x0076, 713}, {119, 0x0077, 686}, {120, 0x0078, 493}, {121, 0x0079, 686}, {122, 0x007A, 494}, {123, 0x007B, 480}, {124, 0x007C, 200}, {125, 0x007D, 480}, {126, 0x007E, 549}, {160, 0x00A0, 750}, {161, 0x00A1, 620}, {162, 0x00A2, 247}, {163, 0x00A3, 549}, {164, 0x00A4, 167}, {165, 0x00A5, 713}, {166, 0x00A6, 500}, {167, 0x00A7, 753}, {168, 0x00A8, 753}, {169, 0x00A9, 753}, {170, 0x00AA, 753}, {171, 0x00AB, 1042}, {172, 0x00AC, 987}, {173, 0x00AD, 603}, {174, 0x00AE, 987}, {175, 0x00AF, 603}, {176, 0x00B0, 400}, {177, 0x00B1, 549}, {178, 0x00B2, 411}, {179, 0x00B3, 549}, {180, 0x00B4, 549}, {181, 0x00B5, 713}, {182, 0x00B6, 494}, {183, 0x00B7, 460}, {184, 0x00B8, 549}, {185, 0x00B9, 549}, {186, 0x00BA, 549}, {187, 0x00BB, 549}, {188, 0x00BC, 1000}, {189, 0x00BD, 603}, {190, 0x00BE, 1000}, {191, 0x00BF, 658}, {192, 0x00C0, 823}, {193, 0x00C1, 686}, {194, 0x00C2, 795}, {195, 0x00C3, 987}, {196, 0x00C4, 768}, {197, 0x00C5, 768}, {198, 0x00C6, 823}, {199, 0x00C7, 768}, {200, 0x00C8, 768}, {201, 0x00C9, 713}, {202, 0x00CA, 713}, {203, 0x00CB, 713}, {204, 0x00CC, 713}, {205, 0x00CD, 713}, {206, 0x00CE, 713}, {207, 0x00CF, 713}, {208, 0x00D0, 768}, {209, 0x00D1, 713}, {210, 0x00D2, 790}, {211, 0x00D3, 790}, {212, 0x00D4, 890}, {213, 0x00D5, 823}, {214, 0x00D6, 549}, {215, 0x00D7, 250}, {216, 0x00D8, 713}, {217, 0x00D9, 603}, {218, 0x00DA, 603}, {219, 0x00DB, 1042}, {220, 0x00DC, 987}, {221, 0x00DD, 603}, {222, 0x00DE, 987}, {223, 0x00DF, 603}, {224, 0x00E0, 494}, {225, 0x00E1, 329}, {226, 0x00E2, 790}, {227, 0x00E3, 790}, {228, 0x00E4, 786}, {229, 0x00E5, 713}, {230, 0x00E6, 384}, {231, 0x00E7, 384}, {232, 0x00E8, 384}, {233, 0x00E9, 384}, {234, 0x00EA, 384}, {235, 0x00EB, 384}, {236, 0x00EC, 494}, {237, 0x00ED, 494}, {238, 0x00EE, 494}, {239, 0x00EF, 494}, {241, 0x00F1, 329}, {242, 0x00F2, 274}, {243, 0x00F3, 686}, {244, 0x00F4, 686}, {245, 0x00F5, 686}, {246, 0x00F6, 384}, {247, 0x00F7, 384}, {248, 0x00F8, 384}, {249, 0x00F9, 384}, {250, 0x00FA, 384}, {251, 0x00FB, 384}, {252, 0x00FC, 494}, {253, 0x00FD, 494}, {254, 0x00FE, 494}, {-1, 0xFFFF, 0} }; #define PODOFO_HPDF_FONT_COURIER "Courier" #define PODOFO_HPDF_FONT_COURIER_BOLD "Courier-Bold" #define PODOFO_HPDF_FONT_COURIER_OBLIQUE "Courier-Oblique" #define PODOFO_HPDF_FONT_COURIER_BOLD_OBLIQUE "Courier-BoldOblique" #define PODOFO_HPDF_FONT_HELVETICA "Helvetica" #define PODOFO_HPDF_FONT_HELVETICA_BOLD "Helvetica-Bold" #define PODOFO_HPDF_FONT_HELVETICA_OBLIQUE "Helvetica-Oblique" #define PODOFO_HPDF_FONT_HELVETICA_BOLD_OBLIQUE "Helvetica-BoldOblique" #define PODOFO_HPDF_FONT_TIMES_ROMAN "Times-Roman" #define PODOFO_HPDF_FONT_TIMES_BOLD "Times-Bold" #define PODOFO_HPDF_FONT_TIMES_ITALIC "Times-Italic" #define PODOFO_HPDF_FONT_TIMES_BOLD_ITALIC "Times-BoldItalic" #define PODOFO_HPDF_FONT_SYMBOL "Symbol" #define PODOFO_HPDF_FONT_ZAPF_DINGBATS "ZapfDingbats" const int PODOFO_TRUE=1; const int PODOFO_FALSE=0; /* static const PdfFontMetricsBase14Rec PODOFO_BUILTIN_FONTS[] = { { PODOFO_HPDF_FONT_COURIER, CHAR_DATA_COURIER, PODOFO_FALSE, 629, -157, 426, 562, {-23, -250, 715, 805} }, { PODOFO_HPDF_FONT_COURIER_BOLD, CHAR_DATA_COURIER_BOLD, PODOFO_FALSE, 629, -157, 439, 562, {-113, -250, 749, 801} }, { PODOFO_HPDF_FONT_COURIER_OBLIQUE, CHAR_DATA_COURIER_OBLIQUE, PODOFO_FALSE, 629, -157, 426, 562, {-27, -250, 849, 805} }, { PODOFO_HPDF_FONT_COURIER_BOLD_OBLIQUE, CHAR_DATA_COURIER_BOLD_OBLIQUE, PODOFO_FALSE, 629, -157, 439, 562, {-57, -250, 869, 801} }, { PODOFO_HPDF_FONT_HELVETICA, CHAR_DATA_HELVETICA, PODOFO_FALSE, 718, -207, 523, 718, {-166, -225, 1000, 931} }, { PODOFO_HPDF_FONT_HELVETICA_BOLD, CHAR_DATA_HELVETICA_BOLD, PODOFO_FALSE, 718, -207, 532, 718, {-170, -228, 1003, 962} }, { PODOFO_HPDF_FONT_HELVETICA_OBLIQUE, CHAR_DATA_HELVETICA_OBLIQUE, PODOFO_FALSE, 718, -207, 532, 718, {-170, -225, 1116, 931} }, { PODOFO_HPDF_FONT_HELVETICA_BOLD_OBLIQUE, CHAR_DATA_HELVETICA_BOLD_OBLIQUE, PODOFO_FALSE, 718, -207, 532, 718, {-174, -228, 1114, 962} }, { PODOFO_HPDF_FONT_TIMES_ROMAN, CHAR_DATA_TIMES_ROMAN, PODOFO_FALSE, 683, -217, 450, 662, {-168, -218, 1000, 898} }, { PODOFO_HPDF_FONT_TIMES_BOLD, CHAR_DATA_TIMES_BOLD, PODOFO_FALSE, 683, -217, 461, 676, {-168, -218, 1000, 935} }, { PODOFO_HPDF_FONT_TIMES_ITALIC, CHAR_DATA_TIMES_ITALIC, PODOFO_FALSE, 683, -217, 441, 653, {-169, -217, 1010, 883} }, { PODOFO_HPDF_FONT_TIMES_BOLD_ITALIC, CHAR_DATA_TIMES_BOLD_ITALIC, PODOFO_FALSE, 683, -217, 462, 669, {-200, -218, 996, 921} }, { PODOFO_HPDF_FONT_SYMBOL, CHAR_DATA_SYMBOL, PODOFO_TRUE, 0, 0, 0, 0, {-180, -293, 1090, 1010} }, { PODOFO_HPDF_FONT_ZAPF_DINGBATS, CHAR_DATA_ZAPF_DINGBATS, PODOFO_TRUE, 0, 0, 0, 0, {-1, -143, 981, 820} }, { NULL, NULL, PODOFO_FALSE, 0, 0, 0, 0, {0, 0, 0, 0} }, }; */ static PdfFontMetricsBase14 PODOFO_BUILTIN_FONTS[] = { PdfFontMetricsBase14(PODOFO_HPDF_FONT_COURIER, CHAR_DATA_COURIER, PODOFO_FALSE, 629, -157, 426, 562, PdfRect(-23, -250, 715, 805) ), PdfFontMetricsBase14( PODOFO_HPDF_FONT_COURIER_BOLD, CHAR_DATA_COURIER_BOLD, PODOFO_FALSE, 629, -157, 439, 562, PdfRect(-113, -250, 749, 801) ), PdfFontMetricsBase14( PODOFO_HPDF_FONT_COURIER_OBLIQUE, CHAR_DATA_COURIER_OBLIQUE, PODOFO_FALSE, 629, -157, 426, 562, PdfRect(-27, -250, 849, 805) ), PdfFontMetricsBase14( PODOFO_HPDF_FONT_COURIER_BOLD_OBLIQUE, CHAR_DATA_COURIER_BOLD_OBLIQUE, PODOFO_FALSE, 629, -157, 439, 562, PdfRect(-57, -250, 869, 801) ), PdfFontMetricsBase14( PODOFO_HPDF_FONT_HELVETICA, CHAR_DATA_HELVETICA, PODOFO_FALSE, 718, -207, 523, 718, PdfRect(-166, -225, 1000, 931) ), PdfFontMetricsBase14( PODOFO_HPDF_FONT_HELVETICA_BOLD, CHAR_DATA_HELVETICA_BOLD, PODOFO_FALSE, 718, -207, 532, 718, PdfRect(-170, -228, 1003, 962) ), PdfFontMetricsBase14( PODOFO_HPDF_FONT_HELVETICA_OBLIQUE, CHAR_DATA_HELVETICA_OBLIQUE, PODOFO_FALSE, 718, -207, 532, 718, PdfRect(-170, -225, 1116, 931) ), PdfFontMetricsBase14( PODOFO_HPDF_FONT_HELVETICA_BOLD_OBLIQUE, CHAR_DATA_HELVETICA_BOLD_OBLIQUE, PODOFO_FALSE, 718, -207, 532, 718, PdfRect(-174, -228, 1114, 962) ), PdfFontMetricsBase14( PODOFO_HPDF_FONT_TIMES_ROMAN, CHAR_DATA_TIMES_ROMAN, PODOFO_FALSE, 683, -217, 450, 662, PdfRect(-168, -218, 1000, 898) ), PdfFontMetricsBase14( PODOFO_HPDF_FONT_TIMES_BOLD, CHAR_DATA_TIMES_BOLD, PODOFO_FALSE, 683, -217, 461, 676, PdfRect(-168, -218, 1000, 935) ), PdfFontMetricsBase14( PODOFO_HPDF_FONT_TIMES_ITALIC, CHAR_DATA_TIMES_ITALIC, PODOFO_FALSE, 683, -217, 441, 653, PdfRect(-169, -217, 1010, 883) ), PdfFontMetricsBase14( PODOFO_HPDF_FONT_TIMES_BOLD_ITALIC, CHAR_DATA_TIMES_BOLD_ITALIC, PODOFO_FALSE, 683, -217, 462, 669, PdfRect(-200, -218, 996, 921) ), PdfFontMetricsBase14( PODOFO_HPDF_FONT_SYMBOL, CHAR_DATA_SYMBOL, PODOFO_TRUE, 683, -217, 462, 669, /* 0, 0, 0, 0, */ PdfRect(-180, -293, 1090, 1010) ), PdfFontMetricsBase14( PODOFO_HPDF_FONT_ZAPF_DINGBATS, CHAR_DATA_ZAPF_DINGBATS, PODOFO_TRUE, 683, -217, 462, 669, /* 0, 0, 0, 0, */ PdfRect(-1, -143, 981, 820) ), PdfFontMetricsBase14( NULL, NULL, PODOFO_FALSE, 0, 0, 0, 0, PdfRect(0, 0, 0, 0) ), }; }; #endif // _PDF_FONT_FACTORY_BASE14_DATA_H_ podofo-0.9.3/src/doc/PdfFontTTFSubset.h0000664000175000017500000001766112344436402017507 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2008 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_FONT_TTF_SUBSET_H_ #define _PDF_FONT_TTF_SUBSET_H_ #include "podofo/base/PdfDefines.h" #include "PdfFontMetrics.h" #include #include namespace PoDoFo { class PdfInputDevice; class PdfOutputDevice; // This code is based heabily on code by ZhangYang // (张杨.国际) // // (Do not put this into doxygen documentation blocks // as this will break latex documentation generation) /** * This class is able to build a new TTF font with only * certain glyphs from an existing font. * */ class PODOFO_DOC_API PdfFontTTFSubset { public: /** * Internal enum specifying the type of a fontfile. */ enum EFontFileType { eFontFileType_TTF, ///< TrueType Font eFontFileType_TTC, ///< TrueType Collection eFontFileType_OTF, ///< OpenType Font eFontFileType_Unknown ///< Unknown }; /** Create a new PdfFontTTFSubset from an existing * TTF font file. * * @param pszFontFileName path to a TTF file * @param pMetrics font metrics object for this font * @param nFaceIndex index of the face inside of the font */ PdfFontTTFSubset( const char* pszFontFileName, PdfFontMetrics* pMetrics, unsigned short nFaceIndex = 0 ); /** Create a new PdfFontTTFSubset from an existing * TTF font file using an input device. * * @param pDevice a PdfInputDevice * @param pMetrics font metrics object for this font * @param eType the type of the font * @param nFaceIndex index of the face inside of the font */ PdfFontTTFSubset( PdfInputDevice* pDevice, PdfFontMetrics* pMetrics, EFontFileType eType, unsigned short nFaceIndex = 0 ); ~PdfFontTTFSubset(); /** * Actually generate the subsetted font * * @param pOutputDevice write the font to this device */ void BuildFont( PdfOutputDevice* pOutputDevice ); /** Add a new glyph index to the subset. * * @param nGlyphIndex include this glyph in the final font * * Already existing values are ignored, so that every * glyph can be added only once. */ void AddGlyph( unsigned short nGlyphIndex ); /** Add an unicode character to the subset * * @param nCharCode unicode character code */ inline void AddCharacter( pdf_utf16be nCharCode ); /** Get the number of glyphs in this font. * * @returns the number of glyphs in this font. */ inline size_t GetSize() const; private: /** Hide default constructor */ PdfFontTTFSubset() : m_bOwnDevice( false ) {} /** copy constructor, not implemented */ PdfFontTTFSubset(const PdfFontTTFSubset& rhs); /** assignment operator, not implemented */ PdfFontTTFSubset& operator=(const PdfFontTTFSubset& rhs); void Init(); /** Get the offset of a specified table. * @param pszTableName name of the table */ unsigned long GetTableOffset( const char* pszTableName ); void GetNumberOfTables(); void GetNumberOfGlyphs(); void SeeIfLongLocaOrNot(); void InitTables(); void GetStartOfTTFOffsets(); /** Get sz bytes from the offset'th bytes of the input file * */ void GetData(unsigned long offset, void* address, unsigned long sz); /** Information of TrueType tables. */ struct TTrueTypeTable { unsigned char m_tableName[4]; unsigned long m_checksum; unsigned long m_length; unsigned long m_offset; std::string m_strTableName; // TODO: DS: REMOVE FIELD? }; /** GlyphData contains the glyph address relative * to the beginning of the glyf table. */ struct TGlyphData { unsigned long glyphIndex; unsigned long glyphLength; unsigned long glyphOldAddress; //In the original truetype file. unsigned long glyphNewAddress; //In the new generated truetype file. }; struct TGlyphDataShort { unsigned long glyphIndex; unsigned short glyphLength; unsigned short glyphOldAddress; unsigned long glyphOldAddressLong; //Real address, which is 2 times of glyphOldAddress. unsigned short glyphNewAddress; unsigned long glyphNewAddressLong; }; PdfFontMetrics* m_pMetrics; ///< FontMetrics object which is required to convert unicode character points to glyph ids EFontFileType m_eFontFileType; bool m_bIsLongLoca; unsigned short m_numTables; unsigned short m_numGlyphs; std::vector m_vTable; std::vector m_vGlyphIndice; unsigned short m_faceIndex; unsigned long m_ulStartOfTTFOffsets; ///< Start address of the truetype offset tables, differs from ttf to ttc. PdfInputDevice* m_pDevice; ///< Read data from this input device const bool m_bOwnDevice; ///< If the input device is owned by this object }; // ----------------------------------------------------- // // ----------------------------------------------------- inline size_t PdfFontTTFSubset::GetSize() const { return m_vGlyphIndice.size(); } // ----------------------------------------------------- // // ----------------------------------------------------- inline void PdfFontTTFSubset::AddCharacter( pdf_utf16be nCharCode ) { #ifdef PODOFO_IS_LITTLE_ENDIAN this->AddGlyph( static_cast(m_pMetrics->GetGlyphId( ((nCharCode & 0xff00) >> 8) | ((nCharCode & 0xff) << 8) )) ); #else this->AddGlyph( static_cast(m_pMetrics->GetGlyphId( nCharCode )) ); #endif // PODOFO_IS_LITTLE_ENDIAN } }; /* PoDoFo */ #endif /* _PDF_FONT_TRUE_TYPE_H_ */ podofo-0.9.3/src/doc/PdfCMapEncoding.cpp0000664000175000017500000002671012347347566017671 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2011 by Dominik Seichter * * domseichter@web.de * * * * Pdf CMAP encoding by kalyan * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfCMapEncoding.h" #include "base/PdfDefinesPrivate.h" #include "base/PdfEncodingFactory.h" #include "base/PdfObject.h" #include "base/PdfVariant.h" #include "base/PdfStream.h" #include "base/PdfContentsTokenizer.h" #include #include #include #include using namespace std; namespace PoDoFo { PdfCMapEncoding::PdfCMapEncoding (PdfObject * pObject, PdfObject * /*pToUnicode*/) : PdfEncoding(0x0000, 0xffff), PdfElement(NULL, pObject), m_baseEncoding( eBaseEncoding_Font ) { if(pObject->HasStream()) { stack < string > stkToken; int loop = 0; char *streamBuffer; const char *streamToken = NULL; EPdfTokenType *streamTokenType = NULL; pdf_long streamBufferLen; bool in_codespacerange = 0; bool in_beginbfrange = 0; bool in_beginbfchar = 0; int code_space_entries = 0; int range_entries = 0; int char_entries = 0; int inside_hex_string = 0; int inside_array = 0; int range_start; int range_end; int i = 0; int firstvalue = 0; pair < long, long >encodingRange; const PdfStream *CIDStreamdata = pObject->GetStream (); CIDStreamdata->GetFilteredCopy (&streamBuffer, &streamBufferLen); PdfContentsTokenizer streamTokenizer (streamBuffer, streamBufferLen); while (streamTokenizer.GetNextToken (streamToken, streamTokenType)) { stkToken.push (streamToken); if (strcmp (streamToken, ">") == 0) { if (inside_hex_string == 0) cout << "\n Pdf Error, got > before <"; else inside_hex_string = 0; i++; } if (strcmp (streamToken, "]") == 0) { if (inside_array == 0) cout << "\n Pdf Error, got ] before ["; else inside_array = 0; i++; } if (in_codespacerange == 1) { if (loop < code_space_entries) { if (inside_hex_string == 1) { unsigned int num_value; std::stringstream ss; ss << std::hex << streamToken; ss >> num_value; if (i % 2 == 0) { encodingRange.first = num_value; } if (i % 2 == 1) { encodingRange.second = num_value; loop++; } } } } if (in_beginbfrange == 1) { if (loop < range_entries) { if (inside_hex_string == 1) { unsigned int num_value; std::stringstream ss; ss << std::hex << streamToken; ss >> num_value; if (i % 3 == 0) range_start = num_value; if (i % 3 == 1) { range_end = num_value; } if (i % 3 == 2) { for (int k = range_start; k < range_end; k++) { *(cMapEncoding + k) = num_value; num_value++; } loop++; } } } } if (in_beginbfchar == 1) { if (loop < char_entries) { if (inside_hex_string == 1) { unsigned int num_value; std::stringstream ss; ss << std::hex << streamToken; ss >> num_value; if (i % 2 == 0) { firstvalue = num_value; } if (i % 2 == 1) { if (encodingRange.first <= static_cast(num_value) && static_cast(num_value) <= encodingRange.second) *(cMapEncoding + firstvalue-1) = num_value; else cout << "\n Error ... Value out of range" << endl; } } } } if (strcmp (streamToken, "<") == 0) { inside_hex_string = 1; } if (strcmp (streamToken, "[") == 0) { inside_array = 1; } if (strcmp (streamToken, "begincodespacerange") == 0) { in_codespacerange = 1; stkToken.pop (); std::stringstream ss; ss << std::hex << stkToken.top (); ss >> code_space_entries; } if (strcmp (streamToken, "endcodespacerange") == 0) { if (in_codespacerange == 0) cout << "\nError in pdf document got endcodespacerange before begincodespacerange"; in_codespacerange = 0; cMapEncoding = static_cast (calloc((encodingRange.second - encodingRange.first + 1), sizeof(pdf_utf16be))); i = 0; } if (strcmp (streamToken, "beginbfrange") == 0) { in_beginbfrange = 1; stkToken.pop (); std::stringstream ss; ss << std::hex << stkToken.top (); ss >> range_entries; } if (strcmp (streamToken, "endbfrange") == 0) { in_beginbfrange = 0; i = 0; } if (strcmp (streamToken, "beginbfchar") == 0) { in_beginbfchar = 1; stkToken.pop (); std::stringstream ss; ss << std::hex << stkToken.top (); ss >> char_entries; } if (strcmp (streamToken, "endbfchar") == 0) { in_beginbfchar = 0; i = 0; } } *(cMapEncoding + encodingRange.second-1) = 0; } } void PdfCMapEncoding::AddToDictionary(PdfDictionary &) const { } const PdfEncoding* PdfCMapEncoding::GetBaseEncoding() const { const PdfEncoding* pEncoding = NULL; switch( m_baseEncoding ) { case eBaseEncoding_WinAnsi: pEncoding = PdfEncodingFactory::GlobalWinAnsiEncodingInstance(); break; case eBaseEncoding_MacRoman: pEncoding = PdfEncodingFactory::GlobalMacRomanEncodingInstance(); break; case eBaseEncoding_MacExpert: case eBaseEncoding_Font: default: break; } if( !pEncoding ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } return pEncoding; } PdfString PdfCMapEncoding::ConvertToUnicode(const PdfString & rEncodedString, const PdfFont*) const { const PdfEncoding* const pEncoding = PdfEncodingFactory::GlobalPdfDocEncodingInstance(); if(rEncodedString.IsHex()) { PdfString PdfUnicodeString = rEncodedString.ToUnicode(); char * ptrHexString = static_cast( malloc( sizeof(char) * (rEncodedString.GetLength() + 2 ) ) ); pdf_utf16be* pszUtf16 = static_cast(malloc(sizeof(pdf_utf16be)*rEncodedString.GetLength())); memcpy( ptrHexString, rEncodedString.GetString(), rEncodedString.GetLength() ); for ( int strIndex = 0; strIndex < static_cast(rEncodedString.GetLength()); strIndex++ ) { *(pszUtf16 + strIndex) = pEncoding->GetCharCode(*(cMapEncoding + static_cast(ptrHexString[strIndex]) -1)); } PdfString ret(pszUtf16, rEncodedString.GetLength()); free( ptrHexString ); free( pszUtf16 ); return ret; } else { return(PdfString("\0")); } } PdfRefCountedBuffer PdfCMapEncoding::ConvertToEncoding(const PdfString &, const PdfFont*) const { PODOFO_RAISE_ERROR( ePdfError_NotImplemented ); return PdfRefCountedBuffer(); } bool PdfCMapEncoding::IsSingleByteEncoding() const { return false; } bool PdfCMapEncoding::IsAutoDelete() const { return true; } pdf_utf16be PdfCMapEncoding::GetCharCode(int) const { PODOFO_RAISE_ERROR( ePdfError_NotImplemented ); return static_cast(0); } const PdfName & PdfCMapEncoding::GetID() const { PODOFO_RAISE_ERROR( ePdfError_NotImplemented ); } }; podofo-0.9.3/src/doc/PdfOutlines.cpp0000664000175000017500000002641612344436402017170 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2006 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfOutlines.h" #include "base/PdfDefinesPrivate.h" #include "base/PdfArray.h" #include "base/PdfDictionary.h" #include "base/PdfObject.h" #include "PdfAction.h" #include "PdfDestination.h" namespace PoDoFo { PdfOutlineItem::PdfOutlineItem( const PdfString & sTitle, const PdfDestination & rDest, PdfOutlineItem* pParentOutline, PdfVecObjects* pParent ) : PdfElement( NULL, pParent ), m_pParentOutline( pParentOutline ), m_pPrev( NULL ), m_pNext( NULL ), m_pFirst( NULL ), m_pLast( NULL ), m_pDestination( NULL ), m_pAction( NULL ) { if( pParentOutline ) this->GetObject()->GetDictionary().AddKey( "Parent", pParentOutline->GetObject()->Reference() ); this->SetTitle( sTitle ); this->SetDestination( rDest ); } PdfOutlineItem::PdfOutlineItem( const PdfString & sTitle, const PdfAction & rAction, PdfOutlineItem* pParentOutline, PdfVecObjects* pParent ) : PdfElement( NULL, pParent ), m_pParentOutline( pParentOutline ), m_pPrev( NULL ), m_pNext( NULL ), m_pFirst( NULL ), m_pLast( NULL ), m_pDestination( NULL ), m_pAction( NULL ) { if( pParentOutline ) this->GetObject()->GetDictionary().AddKey( "Parent", pParentOutline->GetObject()->Reference() ); this->SetTitle( sTitle ); this->SetAction( rAction ); } PdfOutlineItem::PdfOutlineItem( PdfObject* pObject, PdfOutlineItem* pParentOutline, PdfOutlineItem* pPrevious ) : PdfElement( NULL, pObject ), m_pParentOutline( pParentOutline ), m_pPrev( pPrevious ), m_pNext( NULL ), m_pFirst( NULL ), m_pLast( NULL ), m_pDestination( NULL ), m_pAction( NULL ) { PdfReference first, next; if( this->GetObject()->GetDictionary().HasKey( "First" ) ) { first = this->GetObject()->GetDictionary().GetKey("First")->GetReference(); m_pFirst = new PdfOutlineItem( pObject->GetOwner()->GetObject( first ), this, NULL ); } if( this->GetObject()->GetDictionary().HasKey( "Next" ) ) { next = this->GetObject()->GetDictionary().GetKey("Next")->GetReference(); PdfObject* pObj = pObject->GetOwner()->GetObject( next ); m_pNext = new PdfOutlineItem( pObj, NULL, this ); } else { // if there is no next key, // we have to set ourself as the last item of the parent if( m_pParentOutline ) m_pParentOutline->SetLast( this ); } } PdfOutlineItem::PdfOutlineItem( PdfVecObjects* pParent ) : PdfElement( "Outlines", pParent ), m_pParentOutline( NULL ), m_pPrev( NULL ), m_pNext( NULL ), m_pFirst( NULL ), m_pLast( NULL ), m_pDestination( NULL ), m_pAction( NULL ) { } PdfOutlineItem::~PdfOutlineItem() { delete m_pNext; delete m_pFirst; } PdfOutlineItem* PdfOutlineItem::CreateChild( const PdfString & sTitle, const PdfDestination & rDest ) { PdfOutlineItem* pItem = new PdfOutlineItem( sTitle, rDest, this, this->GetObject()->GetOwner() ); this->InsertChild( pItem ); return pItem; } void PdfOutlineItem::InsertChild( PdfOutlineItem* pItem ) { if( m_pLast ) { m_pLast->SetNext( pItem ); pItem->SetPrevious( m_pLast ); } m_pLast = pItem; if( !m_pFirst ) m_pFirst = m_pLast; this->GetObject()->GetDictionary().AddKey( "First", m_pFirst->GetObject()->Reference() ); this->GetObject()->GetDictionary().AddKey( "Last", m_pLast->GetObject()->Reference() ); } PdfOutlineItem* PdfOutlineItem::CreateNext ( const PdfString & sTitle, const PdfDestination & rDest ) { PdfOutlineItem* pItem = new PdfOutlineItem( sTitle, rDest, m_pParentOutline, this->GetObject()->GetOwner() ); if( m_pNext ) { m_pNext->SetPrevious( pItem ); pItem->SetNext( m_pNext ); } m_pNext = pItem; m_pNext->SetPrevious( this ); this->GetObject()->GetDictionary().AddKey( "Next", m_pNext->GetObject()->Reference() ); if( m_pParentOutline && !m_pNext->Next() ) m_pParentOutline->SetLast( m_pNext ); return m_pNext; } PdfOutlineItem* PdfOutlineItem::CreateNext ( const PdfString & sTitle, const PdfAction & rAction ) { PdfOutlineItem* pItem = new PdfOutlineItem( sTitle, rAction, m_pParentOutline, this->GetObject()->GetOwner() ); if( m_pNext ) { m_pNext->SetPrevious( pItem ); pItem->SetNext( m_pNext ); } m_pNext = pItem; m_pNext->SetPrevious( this ); this->GetObject()->GetDictionary().AddKey( "Next", m_pNext->GetObject()->Reference() ); if( m_pParentOutline && !m_pNext->Next() ) m_pParentOutline->SetLast( m_pNext ); return m_pNext; } void PdfOutlineItem::SetPrevious( PdfOutlineItem* pItem ) { m_pPrev = pItem; this->GetObject()->GetDictionary().AddKey( "Prev", m_pPrev->GetObject()->Reference() ); } void PdfOutlineItem::SetNext( PdfOutlineItem* pItem ) { m_pNext = pItem; this->GetObject()->GetDictionary().AddKey( "Next", m_pNext->GetObject()->Reference() ); } void PdfOutlineItem::SetLast( PdfOutlineItem* pItem ) { m_pLast = pItem; if( m_pLast ) this->GetObject()->GetDictionary().AddKey( "Last", m_pLast->GetObject()->Reference() ); else this->GetObject()->GetDictionary().RemoveKey( "Last" ); } void PdfOutlineItem::SetFirst( PdfOutlineItem* pItem ) { m_pFirst = pItem; if( m_pFirst ) this->GetObject()->GetDictionary().AddKey( "First", m_pFirst->GetObject()->Reference() ); else this->GetObject()->GetDictionary().RemoveKey( "First" ); } void PdfOutlineItem::Erase() { while( m_pFirst ) { // erase will set a new first // if it has a next item m_pFirst->Erase(); } if( m_pPrev && m_pNext ) { m_pPrev->SetNext ( m_pNext ); m_pNext->SetPrevious( m_pPrev ); } if( !m_pPrev && m_pParentOutline ) m_pParentOutline->SetFirst( m_pNext ); if( !m_pNext && m_pParentOutline ) m_pParentOutline->SetLast( m_pPrev ); m_pNext = NULL; delete this; } void PdfOutlineItem::SetDestination( const PdfDestination & rDest ) { delete m_pDestination; m_pDestination = NULL; rDest.AddToDictionary( this->GetObject()->GetDictionary() ); } PdfDestination* PdfOutlineItem::GetDestination( PdfDocument* pDoc ) { if( !m_pDestination ) { PdfObject* dObj = this->GetObject()->GetIndirectKey( "Dest" ); if ( !dObj ) return NULL; m_pDestination = new PdfDestination( dObj, pDoc ); } return m_pDestination; } void PdfOutlineItem::SetAction( const PdfAction & rAction ) { delete m_pAction; m_pAction = NULL; rAction.AddToDictionary( this->GetObject()->GetDictionary() ); } PdfAction* PdfOutlineItem::GetAction( void ) { if( !m_pAction ) { PdfObject* dObj = this->GetObject()->GetIndirectKey( "A" ); if ( !dObj ) return NULL; m_pAction = new PdfAction( dObj ); } return m_pAction; } void PdfOutlineItem::SetTitle( const PdfString & sTitle ) { this->GetObject()->GetDictionary().AddKey( "Title", sTitle ); } const PdfString & PdfOutlineItem::GetTitle() const { return this->GetObject()->GetIndirectKey( "Title" )->GetString(); } void PdfOutlineItem::SetTextFormat( EPdfOutlineFormat eFormat ) { this->GetObject()->GetDictionary().AddKey( "F", static_cast(eFormat) ); } EPdfOutlineFormat PdfOutlineItem::GetTextFormat() const { if( this->GetObject()->GetDictionary().HasKey( "F" ) ) return static_cast(this->GetObject()->GetIndirectKey( "F" )->GetNumber()); return ePdfOutlineFormat_Default; } void PdfOutlineItem::SetTextColor( double r, double g, double b ) { PdfArray color; color.push_back( r ); color.push_back( g ); color.push_back( b ); this->GetObject()->GetDictionary().AddKey( "C", color ); } double PdfOutlineItem::GetTextColorRed() const { if( this->GetObject()->GetDictionary().HasKey( "C" ) ) return this->GetObject()->GetIndirectKey( "C" )->GetArray()[0].GetReal(); return 0.0; } double PdfOutlineItem::GetTextColorGreen() const { if( this->GetObject()->GetDictionary().HasKey( "C" ) ) return this->GetObject()->GetIndirectKey( "C" )->GetArray()[1].GetReal(); return 0.0; } double PdfOutlineItem::GetTextColorBlue() const { if( this->GetObject()->GetDictionary().HasKey( "C" ) ) return this->GetObject()->GetIndirectKey( "C" )->GetArray()[2].GetReal(); return 0.0; } /////////////////////////////////////////////////////////////////////////////////// // PdfOutlines /////////////////////////////////////////////////////////////////////////////////// PdfOutlines::PdfOutlines( PdfVecObjects* pParent ) : PdfOutlineItem( pParent ) { } PdfOutlines::PdfOutlines( PdfObject* pObject ) : PdfOutlineItem( pObject, NULL, NULL ) { } PdfOutlineItem* PdfOutlines::CreateRoot( const PdfString & sTitle ) { return this->CreateChild( sTitle, PdfDestination( GetObject()->GetOwner() ) ); } }; podofo-0.9.3/src/doc/PdfXObject.h0000664000175000017500000002026612347310654016371 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2006 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_XOBJECT_H_ #define _PDF_XOBJECT_H_ #include "podofo/base/PdfDefines.h" #include "podofo/base/PdfArray.h" #include "podofo/base/PdfCanvas.h" #include "podofo/base/PdfRect.h" #include "PdfElement.h" namespace PoDoFo { class PdfDictionary; class PdfObject; class PdfMemDocument; /** A XObject is a content stream with several drawing commands and data * which can be used throughout a PDF document. * * You can draw on a XObject like you would draw onto a page and can draw * this XObject later again using a PdfPainter. * * \see PdfPainter */ class PODOFO_DOC_API PdfXObject : public PdfElement, public PdfCanvas { public: /** Create a new XObject with a specified dimension * in a given document * * \param rRect the size of the XObject * \param pParent the parent document of the XObject * \param pszPrefix optional prefix for XObject-name * \param bWithoutObjNum do not create an object identifier name */ PdfXObject( const PdfRect & rRect, PdfDocument* pParent, const char* pszPrefix = NULL, bool bWithoutObjNum = false); /** Create a new XObject with a specified dimension * in a given vector of PdfObjects * * \param rRect the size of the XObject * \param pParent the parent vector of the XObject * \param pszPrefix optional prefix for XObject-name */ PdfXObject( const PdfRect & rRect, PdfVecObjects* pParent, const char* pszPrefix = NULL ); /** Create a new XObject from a page of another document * in a given document * * \param rSourceDoc the document to create the XObject from * \param nPage the page-number in rDoc to create the XObject from * \param pParent the parent document of the XObject * \param pszPrefix optional prefix for XObject-name * \param bUseTrimBox if true try to use trimbox for size of xobject */ PdfXObject( const PdfMemDocument & rSourceDoc, int nPage, PdfDocument* pParent, const char* pszPrefix = NULL, bool bUseTrimBox = false ); /** Create a new XObject from an existing page * * \param pDoc the document to create the XObject at * \param nPage the page-number in pDoc to create the XObject from * \param pszPrefix optional prefix for XObject-name * \param bUseTrimBox if true try to use trimbox for size of xobject */ PdfXObject( PdfDocument *pDoc, int nPage, const char* pszPrefix = NULL, bool bUseTrimBox = false ); /** Create a XObject from an existing PdfObject * * \param pObject an existing object which has to be * a XObject */ PdfXObject( PdfObject* pObject ); virtual ~PdfXObject() { } /** Get access to the contents object of this page. * If you want to draw onto the page, you have to add * drawing commands to the stream of the Contents object. * * The contents object is a this pointer in this case. * * \returns a contents object */ inline virtual PdfObject* GetContents() const; /** Get access to the contents object of this page. * If you want to draw onto the page, you have to add * drawing commands to the stream of the Contents object. * * The contents object is a this pointer in this case. * * \returns a contents object */ inline virtual PdfObject* GetContentsForAppending() const { return GetContents(); } /** Get access to the resources object of this page. * This is most likely an internal object. * \returns a resources object */ inline virtual PdfObject* GetResources() const; /** Get the current page size in PDF Units * \returns a PdfRect containing the page size available for drawing */ inline virtual const PdfRect GetPageSize() const; /** Get the identifier used for drawig this object * \returns identifier */ inline const PdfName & GetIdentifier() const; /** Get the reference to the XObject in the PDF file * without having to access the PdfObject. * * This allows to work with XObjects which have been * written to disk already. * * \returns the reference of the PdfObject for this XObject */ inline const PdfReference & GetObjectReference() const; protected: void InitXObject( const PdfRect & rRect, const char* pszPrefix = NULL ); PdfXObject( const char* pszSubType, PdfDocument* pParent, const char* pszPrefix = NULL ); PdfXObject( const char* pszSubType, PdfVecObjects* pParent, const char* pszPrefix = NULL ); PdfXObject( const char* pszSubType, PdfObject* pObject ); protected: PdfRect m_rRect; private: static PdfArray s_matrix; PdfObject* m_pResources; PdfName m_Identifier; PdfReference m_Reference; }; // ----------------------------------------------------- // // ----------------------------------------------------- inline PdfObject* PdfXObject::GetContents() const { return this->GetNonConstObject(); } // ----------------------------------------------------- // // ----------------------------------------------------- inline PdfObject* PdfXObject::GetResources() const { return m_pResources; } // ----------------------------------------------------- // // ----------------------------------------------------- inline const PdfRect PdfXObject::GetPageSize() const { return m_rRect; } // ----------------------------------------------------- // // ----------------------------------------------------- inline const PdfName & PdfXObject::GetIdentifier() const { return m_Identifier; } // ----------------------------------------------------- // // ----------------------------------------------------- inline const PdfReference & PdfXObject::GetObjectReference() const { return m_Reference; } }; #endif /* _PDF_XOBJECT_H_ */ podofo-0.9.3/src/doc/PdfFont.h0000664000175000017500000003467412347316204015746 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2007 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_FONT_H_ #define _PDF_FONT_H_ #include "podofo/base/PdfDefines.h" #include "podofo/base/PdfName.h" #include "podofo/base/PdfEncodingFactory.h" #include "PdfElement.h" #include "PdfFontMetrics.h" namespace PoDoFo { class PdfObject; class PdfPage; class PdfWriter; /** Before you can draw text on a PDF document, you have to create * a font object first. You can reuse this font object as often * as you want. * * Use PdfDocument::CreateFont to create a new font object. * It will choose a correct subclass using PdfFontFactory. * * This is only an abstract base class which is implemented * for different font formats. */ class PODOFO_DOC_API PdfFont : public PdfElement { friend class PdfFontFactory; public: /** Create a new PdfFont object which will introduce itself * automatically to every page object it is used on. * * The font has a default font size of 12.0pt. * * \param pMetrics pointer to a font metrics object. The font in the PDF * file will match this fontmetrics object. The metrics object is * deleted along with the font. * \param pEncoding the encoding of this font. The font will take ownership of this object * depending on pEncoding->IsAutoDelete() * \param pParent parent of the font object * */ PdfFont( PdfFontMetrics* pMetrics, const PdfEncoding* const pEncoding, PdfVecObjects* pParent ); /** Create a PdfFont based on an existing PdfObject * \param pMetrics pointer to a font metrics object. The font in the PDF * file will match this fontmetrics object. The metrics object is * deleted along with the font. * \param pEncoding the encoding of this font. The font will take ownership of this object * depending on pEncoding->IsAutoDelete() * \param pObject an existing PdfObject */ PdfFont( PdfFontMetrics* pMetrics, const PdfEncoding* const pEncoding, PdfObject* pObject ); virtual ~PdfFont(); /** Set the font size before drawing with this font. * \param fSize font size in points */ inline void SetFontSize( float fSize ); /** Retrieve the current font size of this font object * \returns the current font size */ inline float GetFontSize() const; /** Set the horizontal scaling of the font for compressing (< 100) and expanding (>100) * \param fScale scaling in percent */ inline void SetFontScale( float fScale ); /** Retrieve the current horizontal scaling of this font object * \returns the current font scaling */ inline float GetFontScale() const; /** Set the character spacing of the font * \param fCharSpace character spacing in percent */ inline void SetFontCharSpace( float fCharSpace ); /** Retrieve the current character spacing of this font object * \returns the current font character spacing */ inline float GetFontCharSpace() const; /** Set the word spacing of the font * \param fWordSpace word spacing in PDF units */ inline void SetWordSpace( float fWordSpace ); /** Retrieve the current word spacing of this font object * \returns the current font word spacing in PDF units */ inline float GetWordSpace() const; /** Set the underlined property of the font * \param bUnder if true any text drawn with this font * by a PdfPainter will be underlined. * Default is false */ inline void SetUnderlined( bool bUnder ); /** \returns true if the font is underlined * \see IsBold * \see IsItalic */ inline bool IsUnderlined() const; /** \returns true if this font is bold * \see IsItalic * \see IsUnderlined */ inline bool IsBold() const; /** \returns true if this font is italic * \see IsBold * \see IsUnderlined */ inline bool IsItalic() const; /** Set the strikeout property of the font * \param bStrikeOut if true any text drawn with this font * by a PdfPainter will be strikedout. * Default is false */ inline void SetStrikeOut( bool bStrikeOut ); /** \returns true if the font is striked out */ inline bool IsStrikeOut() const; /** Returns the identifier of this font how it is known * in the pages resource dictionary. * \returns PdfName containing the identifier (e.g. /Ft13) */ inline const PdfName & GetIdentifier() const; /** Returns a reference to the fonts encoding * \returns a PdfEncoding object. */ inline const PdfEncoding* GetEncoding() const; /** Returns a handle to the fontmetrics object of this font. * This can be used for size calculations of text strings when * drawn using this font. * \returns a handle to the font metrics object */ inline const PdfFontMetrics* GetFontMetrics() const; // Peter Petrov 19 March 2009 /** Returns a handle to the fontmetrics object of this font. * This can be used for size calculations of text strings when * drawn using this font. * \returns a handle to the font metrics object */ inline PdfFontMetrics* GetFontMetrics2(); /** Write a PdfString to a PdfStream in a format so that it can * be used with this font. * This is used by PdfPainter::DrawText to display a text string. * The following PDF operator will be Tj * * \param rsString a unicode or ansi string which will be displayed * \param pStream the string will be appended to pStream without any leading * or following whitespaces. */ virtual void WriteStringToStream( const PdfString & rsString, PdfStream* pStream ); // Peter Petrov 24 September 2008 /** Embeds the font into PDF page * */ virtual void EmbedFont(); /** Remember the glyphs used in the string in case of subsetting * * \param sText the text string which should be printed (is not allowed to be NULL!) * \param lStringLen draw only lLen characters of pszText * * Only call if IsSubsetting() returns true. Might throw an exception otherwise. * * \see IsSubsetting */ virtual void AddUsedSubsettingGlyphs( const PdfString & sText, long lStringLen ); /** Remember the glyphname in case of subsetting * * \param pszGlyphName Name of the glyph to remember */ virtual void AddUsedGlyphname( const char * pszGlyphName ); /** Embeds pending subset-font into PDF page * Only call if IsSubsetting() returns true. Might throw an exception otherwise. * * \see IsSubsetting */ virtual void EmbedSubsetFont(); /** Check if this is a subsetting font. * \returns true if this is a subsetting font */ inline bool IsSubsetting() const; protected: /** Get the base font name of this font * * \returns the base font name */ inline const PdfName& GetBaseFont() const; void InitBase14Font(); const PdfEncoding* const m_pEncoding; PdfFontMetrics* m_pMetrics; bool m_bBold; bool m_bItalic; bool m_bUnderlined; bool m_bStrikedOut; bool m_bWasEmbedded; bool m_isBase14; bool m_bIsSubsetting; PdfName m_Identifier; /** Used to specify if this represents a bold font * \param bBold if true this is a bold font. * * \see IsBold * * This can be called by PdfFontFactory to tell this font * object that it belongs to a bold font. */ virtual void SetBold( bool bBold ); /** Used to specify if this represents an italic font * \param bItalic if true this is an italic font. * * \see IsItalc * * This can be called by PdfFontFactory to tell this font * object that it belongs to an italic font. */ virtual void SetItalic( bool bItalic ); private: /** default constructor, not implemented */ PdfFont(void); /** copy constructor, not implemented */ PdfFont(const PdfFont& rhs); /** assignment operator, not implemented */ PdfFont& operator=(const PdfFont& rhs); /** Initialize all variables */ void InitVars(); PdfName m_BaseFont; }; // ----------------------------------------------------- // // ----------------------------------------------------- const PdfName& PdfFont::GetBaseFont() const { return m_BaseFont; } // ----------------------------------------------------- // // ----------------------------------------------------- const PdfName & PdfFont::GetIdentifier() const { return m_Identifier; } // ----------------------------------------------------- // // ----------------------------------------------------- void PdfFont::SetFontSize( float fSize ) { m_pMetrics->SetFontSize( fSize ); } // ----------------------------------------------------- // // ----------------------------------------------------- float PdfFont::GetFontSize() const { return m_pMetrics->GetFontSize(); } // ----------------------------------------------------- // // ----------------------------------------------------- void PdfFont::SetFontScale( float fScale ) { m_pMetrics->SetFontScale( fScale ); } // ----------------------------------------------------- // // ----------------------------------------------------- float PdfFont::GetFontScale() const { return m_pMetrics->GetFontScale(); } // ----------------------------------------------------- // // ----------------------------------------------------- void PdfFont::SetFontCharSpace( float fCharSpace ) { m_pMetrics->SetFontCharSpace( fCharSpace ); } // ----------------------------------------------------- // // ----------------------------------------------------- float PdfFont::GetFontCharSpace() const { return m_pMetrics->GetFontCharSpace(); } // ----------------------------------------------------- // // ----------------------------------------------------- inline void PdfFont::SetWordSpace( float fWordSpace ) { m_pMetrics->SetWordSpace( fWordSpace ); } // ----------------------------------------------------- // // ----------------------------------------------------- inline float PdfFont::GetWordSpace() const { return m_pMetrics->GetWordSpace(); } // ----------------------------------------------------- // // ----------------------------------------------------- const PdfEncoding* PdfFont::GetEncoding() const { return m_pEncoding; } // ----------------------------------------------------- // // ----------------------------------------------------- PdfFontMetrics* PdfFont::GetFontMetrics2() { return m_pMetrics; } // ----------------------------------------------------- // // ----------------------------------------------------- const PdfFontMetrics* PdfFont::GetFontMetrics() const { return m_pMetrics; } // ----------------------------------------------------- // // ----------------------------------------------------- void PdfFont::SetUnderlined( bool bUnder ) { m_bUnderlined = bUnder; } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfFont::IsUnderlined() const { return m_bUnderlined; } // ----------------------------------------------------- // // ----------------------------------------------------- void PdfFont::SetStrikeOut( bool bStrikeOut ) { m_bStrikedOut = bStrikeOut; } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfFont::IsStrikeOut() const { return m_bStrikedOut; } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfFont::IsBold() const { return m_bBold; } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfFont::IsItalic() const { return m_bItalic; } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfFont::IsSubsetting() const { return m_bIsSubsetting; } }; #endif // _PDF_FONT_H_ podofo-0.9.3/src/doc/PdfPagesTree.cpp0000664000175000017500000006534712347354102017252 0ustar dominikdominik/*************************************************************************** * Copyriht (C) 2006 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfPagesTree.h" #include "base/PdfDefinesPrivate.h" #include "base/PdfArray.h" #include "base/PdfDictionary.h" #include "base/PdfObject.h" #include "base/PdfOutputDevice.h" #include "base/PdfVecObjects.h" #include "PdfPage.h" #include namespace PoDoFo { PdfPagesTree::PdfPagesTree( PdfVecObjects* pParent ) : PdfElement( "Pages", pParent ), m_cache( 0 ) { GetObject()->GetDictionary().AddKey( "Kids", PdfArray() ); // kids->Reference() GetObject()->GetDictionary().AddKey( "Count", PdfObject( static_cast(PODOFO_LL_LITERAL(0)) ) ); } PdfPagesTree::PdfPagesTree( PdfObject* pPagesRoot ) : PdfElement( "Pages", pPagesRoot ), m_cache( GetChildCount( pPagesRoot ) ) { if( !this->GetObject() ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } } PdfPagesTree::~PdfPagesTree() { m_cache.ClearCache(); } int PdfPagesTree::GetTotalNumberOfPages() const { return GetChildCount( GetObject() ); } PdfPage* PdfPagesTree::GetPage( int nIndex ) { // if you try to get a page past the end, return NULL // we use >= since nIndex is 0 based if ( nIndex >= GetTotalNumberOfPages() ) return NULL; // Take a look into the cache first PdfPage* pPage = m_cache.GetPage( nIndex ); if( pPage ) return pPage; // Not in cache -> search tree PdfObjectList lstParents; PdfObject* pObj = this->GetPageNode(nIndex, this->GetRoot(), lstParents); if( pObj ) { pPage = new PdfPage( pObj, lstParents ); m_cache.AddPageObject( nIndex, pPage ); return pPage; } return NULL; } PdfPage* PdfPagesTree::GetPage( const PdfReference & ref ) { // We have to search through all pages, // as this is the only way // to instantiate the PdfPage with a correct list of parents for( int i=0;iGetTotalNumberOfPages();i++ ) { PdfPage* pPage = this->GetPage( i ); if( pPage && pPage->GetObject()->Reference() == ref ) return pPage; } return NULL; } void PdfPagesTree::InsertPage( int nAfterPageIndex, PdfPage* inPage ) { this->InsertPage( nAfterPageIndex, inPage->GetObject() ); } void PdfPagesTree::InsertPage( int nAfterPageIndex, PdfObject* pPage ) { bool bInsertBefore = false; if( ePdfPageInsertionPoint_InsertBeforeFirstPage == nAfterPageIndex ) { bInsertBefore = true; nAfterPageIndex = 0; } else if( nAfterPageIndex < 0 ) { // Only ePdfPageInsertionPoint_InsertBeforeFirstPage is valid here PdfError::LogMessage( eLogSeverity_Information, "Invalid argument to PdfPagesTree::InsertPage: %i (Only ePdfPageInsertionPoint_InsertBeforeFirstPage is valid here).", nAfterPageIndex ); return; } //printf("Fetching page node: %i\n", nAfterPageIndex); PdfObjectList lstParents; //printf("Searching page=%i\n", nAfterPageIndex ); PdfObject* pPageBefore = this->GetPageNode( nAfterPageIndex, this->GetRoot(), lstParents ); //printf("pPageBefore=%p lstParents=%i\n", pPageBefore,lstParents.size() ); if( !pPageBefore || lstParents.size() == 0 ) { if( this->GetTotalNumberOfPages() != 0 ) { PdfError::LogMessage( eLogSeverity_Critical, "Cannot find page %i or page %i has no parents. Cannot insert new page.", nAfterPageIndex, nAfterPageIndex ); return; } else { // We insert the first page into an empty pages tree PdfObjectList lstPagesTree; lstPagesTree.push_back( this->GetObject() ); // Use -1 as index to insert before the empty kids array InsertPageIntoNode( this->GetObject(), lstPagesTree, -1, pPage ); } } else { PdfObject* pParent = lstParents.back(); //printf("bInsertBefore=%i\n", bInsertBefore ); int nKidsIndex = bInsertBefore ? -1 : this->GetPosInKids( pPageBefore, pParent ); //printf("Inserting into node: %p at pos %i\n", pParent, nKidsIndex ); InsertPageIntoNode( pParent, lstParents, nKidsIndex, pPage ); } m_cache.InsertPage( (bInsertBefore && nAfterPageIndex == 0) ? ePdfPageInsertionPoint_InsertBeforeFirstPage : nAfterPageIndex ); } void PdfPagesTree::InsertPages( int nAfterPageIndex, const std::vector& vecPages ) { bool bInsertBefore = false; if( ePdfPageInsertionPoint_InsertBeforeFirstPage == nAfterPageIndex ) { bInsertBefore = true; nAfterPageIndex = 0; } else if( nAfterPageIndex < 0 ) { // Only ePdfPageInsertionPoint_InsertBeforeFirstPage is valid here PdfError::LogMessage( eLogSeverity_Information, "Invalid argument to PdfPagesTree::InsertPage: %i (Only ePdfPageInsertionPoint_InsertBeforeFirstPage is valid here).", nAfterPageIndex ); return; } PdfObjectList lstParents; PdfObject* pPageBefore = this->GetPageNode( nAfterPageIndex, this->GetRoot(), lstParents ); if( !pPageBefore || lstParents.size() == 0 ) { if( this->GetTotalNumberOfPages() != 0 ) { PdfError::LogMessage( eLogSeverity_Critical, "Cannot find page %i or page %i has no parents. Cannot insert new page.", nAfterPageIndex, nAfterPageIndex ); return; } else { // We insert the first page into an empty pages tree PdfObjectList lstPagesTree; lstPagesTree.push_back( this->GetObject() ); // Use -1 as index to insert before the empty kids array InsertPagesIntoNode( this->GetObject(), lstPagesTree, -1, vecPages ); } } else { PdfObject* pParent = lstParents.back(); int nKidsIndex = bInsertBefore ? -1 : this->GetPosInKids( pPageBefore, pParent ); InsertPagesIntoNode( pParent, lstParents, nKidsIndex, vecPages ); } m_cache.InsertPages( (bInsertBefore && nAfterPageIndex == 0) ? ePdfPageInsertionPoint_InsertBeforeFirstPage : nAfterPageIndex, vecPages.size() ); } PdfPage* PdfPagesTree::CreatePage( const PdfRect & rSize ) { PdfPage* pPage = new PdfPage( rSize, GetRoot()->GetOwner() ); InsertPage( this->GetTotalNumberOfPages() - 1, pPage ); m_cache.AddPageObject( this->GetTotalNumberOfPages(), pPage ); return pPage; } PdfPage* PdfPagesTree::InsertPage( const PdfRect & rSize, int atIndex) { PdfPage* pPage = new PdfPage( rSize, GetRoot()->GetOwner() ); if (atIndex < 0 || atIndex >= this->GetTotalNumberOfPages()) { atIndex = this->GetTotalNumberOfPages() - 1; } InsertPage( atIndex - 1, pPage ); m_cache.AddPageObject( atIndex, pPage ); return pPage; } void PdfPagesTree::CreatePages( const std::vector& vecSizes ) { std::vector vecPages; std::vector vecObjects; for (std::vector::const_iterator it = vecSizes.begin(); it != vecSizes.end(); ++it) { PdfPage* pPage = new PdfPage( (*it), GetRoot()->GetOwner() ); vecPages.push_back( pPage ); vecObjects.push_back( pPage->GetObject() ); } InsertPages( this->GetTotalNumberOfPages() - 1, vecObjects ); m_cache.AddPageObjects( this->GetTotalNumberOfPages(), vecPages ); } void PdfPagesTree::DeletePage( int nPageNumber ) { // Delete from cache m_cache.DeletePage( nPageNumber ); // Delete from pages tree PdfObjectList lstParents; PdfObject* pPageNode = this->GetPageNode( nPageNumber, this->GetRoot(), lstParents ); if( !pPageNode ) { PdfError::LogMessage( eLogSeverity_Information, "Invalid argument to PdfPagesTree::DeletePage: %i - Page not found\n", nPageNumber ); PODOFO_RAISE_ERROR( ePdfError_PageNotFound ); } if( lstParents.size() > 0 ) { PdfObject* pParent = lstParents.back(); int nKidsIndex = this->GetPosInKids( pPageNode, pParent ); DeletePageFromNode( pParent, lstParents, nKidsIndex, pPageNode ); } else { PdfError::LogMessage( eLogSeverity_Error, "PdfPagesTree::DeletePage: Page %i has no parent - cannot be deleted.\n", nPageNumber ); PODOFO_RAISE_ERROR( ePdfError_PageNotFound ); } } //////////////////////////////////////////////////// // Private methods //////////////////////////////////////////////////// PdfObject* PdfPagesTree::GetPageNode( int nPageNum, PdfObject* pParent, PdfObjectList & rLstParents ) { if( !pParent ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } if( !pParent->GetDictionary().HasKey( PdfName("Kids") ) ) { PODOFO_RAISE_ERROR( ePdfError_InvalidKey ); } const PdfObject* pObj = pParent->GetIndirectKey( "Kids" ); if( pObj == NULL || !pObj->IsArray() ) { PODOFO_RAISE_ERROR( ePdfError_InvalidDataType ); } const PdfArray & rKidsArray = pObj->GetArray(); PdfArray::const_iterator it = rKidsArray.begin(); const size_t numDirectKids = rKidsArray.size(); const size_t numKids = GetChildCount(pParent); if( static_cast(numKids) < nPageNum ) { PdfError::LogMessage( eLogSeverity_Critical, "Cannot retrieve page %i from a document with only %i pages.", nPageNum, static_cast(numKids) ); return NULL; } //printf("Fetching: %i %i %i\n", numDirectKids, numKids, nPageNum ); if( numDirectKids == numKids && static_cast(nPageNum) < numDirectKids ) { // This node has only page nodes as kids, // so we can access the array directly rLstParents.push_back( pParent ); return GetPageNodeFromArray( nPageNum, rKidsArray, rLstParents ); } else if( numDirectKids == numKids && static_cast(nPageNum) < numDirectKids ) { // This node has only page nodes as kids, // but does not contain our page, // skip it - this case should never occur because // of handling of childs in the else part below. return NULL; } else { // We have to traverse the tree while( it != rKidsArray.end() ) { if( (*it).IsArray() ) { // Fixes some broken PDFs who have trees with 1 element kids arrays rLstParents.push_back( pParent ); return GetPageNodeFromArray( nPageNum, (*it).GetArray(), rLstParents ); } else if( (*it).IsReference() ) { PdfObject* pChild = GetRoot()->GetOwner()->GetObject( (*it).GetReference() ); if (!pChild) { PdfError::LogMessage( eLogSeverity_Critical, "Requesting page index %i. Child not found: %s\n", nPageNum, (*it).GetReference().ToString().c_str()); return NULL; } if( this->IsTypePages(pChild) ) { int childCount = GetChildCount( pChild ); if( childCount < nPageNum + 1 ) // Pages are 0 based, but count is not { // skip this page node // and go to the next one nPageNum -= childCount; } else { rLstParents.push_back( pParent ); return this->GetPageNode( nPageNum, pChild, rLstParents ); } } else // Type == Page { if( 0 == nPageNum ) { rLstParents.push_back( pParent ); return pChild; } // Skip a normal page if(nPageNum > 0 ) nPageNum--; } } else { PdfError::LogMessage( eLogSeverity_Critical, "Requesting page index %i. Invalid datatype in kids array: %s\n", nPageNum, (*it).GetDataTypeString()); return NULL; } ++it; } } return NULL; } PdfObject* PdfPagesTree::GetPageNodeFromArray( int nPageNum, const PdfArray & rKidsArray, PdfObjectList & rLstParents ) { if( static_cast(nPageNum) >= rKidsArray.GetSize() ) { PdfError::LogMessage( eLogSeverity_Critical, "Requesting page index %i from array of size %i\n", nPageNum, rKidsArray.size() ); return NULL; } // TODO: Fill cache immediately with all pages // in this kids array PdfVariant rVar = rKidsArray[nPageNum]; while( true ) { if( rVar.IsArray() ) { // Fixes some broken PDFs who have trees with 1 element kids arrays return GetPageNodeFromArray( 0, rVar.GetArray(), rLstParents ); } else if( !rVar.IsReference() ) { PODOFO_RAISE_ERROR_INFO( ePdfError_NotImplemented, "Cannot handle inline pages." ); } PdfObject* pgObject = GetRoot()->GetOwner()->GetObject( rVar.GetReference() ); if(pgObject==NULL) { PODOFO_RAISE_ERROR_INFO( ePdfError_PageNotFound, "Invalid reference." ); } //printf("Reading %s\n", pgObject->Reference().ToString().c_str()); // make sure the object is a /Page and not a /Pages with a single kid if( this->IsTypePage(pgObject) ) { return pgObject; } // it's a /Pages with a single kid, so dereference and try again... if (this->IsTypePages(pgObject) ) { if( !pgObject->GetDictionary().HasKey( "Kids" ) ) return NULL; rLstParents.push_back( pgObject ); rVar = *(pgObject->GetDictionary().GetKey( "Kids" )); } else { // Reference to unexpected object PODOFO_RAISE_ERROR_INFO( ePdfError_PageNotFound, "Reference to unexpected object." ); } } return NULL; } bool PdfPagesTree::IsTypePage(const PdfObject* pObject) const { if( !pObject ) return false; if( pObject->GetDictionary().GetKeyAsName( PdfName( "Type" ) ) == PdfName( "Page" ) ) return true; return false; } bool PdfPagesTree::IsTypePages(const PdfObject* pObject) const { if( !pObject ) return false; if( pObject->GetDictionary().GetKeyAsName( PdfName( "Type" ) ) == PdfName( "Pages" ) ) return true; return false; } int PdfPagesTree::GetChildCount( const PdfObject* pNode ) const { if( !pNode ) return 0; const PdfObject *pCount = pNode->GetIndirectKey( "Count" ); if( pCount != 0 ) { return (pCount->GetDataType() == PoDoFo::ePdfDataType_Number) ? static_cast( pCount->GetNumber() ):0; } else { return 0; } } int PdfPagesTree::GetPosInKids( PdfObject* pPageObj, PdfObject* pPageParent ) { if( !pPageParent ) { //printf("pPageParent=%p\n", pPageParent ); return -1; } const PdfArray & rKids = pPageParent->GetDictionary().GetKey( PdfName("Kids") )->GetArray(); PdfArray::const_iterator it = rKids.begin(); int index = 0; while( it != rKids.end() ) { if( (*it).GetReference() == pPageObj->Reference() ) { //printf("Found at: %i \n", index ); return index; } ++index; ++it; } //printf("Not found %i 0 R in %i 0 R\n", pPageObj->Reference().ObjectNumber(), // pPageParent->Reference().ObjectNumber()); return -1; } void PdfPagesTree::InsertPageIntoNode( PdfObject* pParent, const PdfObjectList & rlstParents, int nIndex, PdfObject* pPage ) { if( !pParent || !pPage ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } // 1. Add the reference of the new page to the kids array of pParent // 2. Increase count of every node in lstParents (which also includes pParent) // 3. Add Parent key to the page // 1. Add reference const PdfArray oldKids = pParent->GetDictionary().GetKey( PdfName("Kids") )->GetArray(); PdfArray::const_iterator it = oldKids.begin(); PdfArray newKids; newKids.reserve( oldKids.GetSize() + 1 ); if( nIndex < 0 ) { newKids.push_back( pPage->Reference() ); } int i = 0; while( it != oldKids.end() ) { newKids.push_back( *it ); if( i == nIndex ) newKids.push_back( pPage->Reference() ); ++i; ++it; } /* PdfVariant var2( newKids ); std::string str2; var2.ToString(str2); printf("newKids= %s\n", str2.c_str() ); */ pParent->GetDictionary().AddKey( PdfName("Kids"), newKids ); // 2. increase count PdfObjectList::const_reverse_iterator itParents = rlstParents.rbegin(); while( itParents != rlstParents.rend() ) { this->ChangePagesCount( *itParents, 1 ); ++itParents; } // 3. add parent key to the page pPage->GetDictionary().AddKey( PdfName("Parent"), pParent->Reference() ); } void PdfPagesTree::InsertPagesIntoNode( PdfObject* pParent, const PdfObjectList & rlstParents, int nIndex, const std::vector& vecPages ) { if( !pParent || !vecPages.size() ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } // 1. Add the reference of the new page to the kids array of pParent // 2. Increase count of every node in lstParents (which also includes pParent) // 3. Add Parent key to the page // 1. Add reference const PdfArray oldKids = pParent->GetDictionary().GetKey( PdfName("Kids") )->GetArray(); PdfArray newKids; newKids.reserve( oldKids.GetSize() + vecPages.size() ); bool bIsPushedIn = false; int i=0; for (PdfArray::const_iterator it=oldKids.begin(); it!=oldKids.end(); ++it, ++i ) { if ( !bIsPushedIn && (nIndex < i) ) // Pushing before { for (std::vector::const_iterator itPages=vecPages.begin(); itPages!=vecPages.end(); ++itPages) { newKids.push_back( (*itPages)->Reference() ); // Push all new kids at once } bIsPushedIn = true; } newKids.push_back( *it ); // Push in the old kids } // If new kids are still not pushed in then they may be appending to the end if ( !bIsPushedIn && ( (nIndex + 1) == static_cast(oldKids.size())) ) { for (std::vector::const_iterator itPages=vecPages.begin(); itPages!=vecPages.end(); ++itPages) { newKids.push_back( (*itPages)->Reference() ); // Push all new kids at once } bIsPushedIn = true; } pParent->GetDictionary().AddKey( PdfName("Kids"), newKids ); // 2. increase count for ( PdfObjectList::const_reverse_iterator itParents = rlstParents.rbegin(); itParents != rlstParents.rend(); ++itParents ) { this->ChangePagesCount( *itParents, vecPages.size() ); } // 3. add parent key to each of the pages for (std::vector::const_iterator itPages=vecPages.begin(); itPages!=vecPages.end(); ++itPages) { (*itPages)->GetDictionary().AddKey( PdfName("Parent"), pParent->Reference() ); } } void PdfPagesTree::DeletePageFromNode( PdfObject* pParent, const PdfObjectList & rlstParents, int nIndex, PdfObject* pPage ) { if( !pParent || !pPage ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } // 1. Delete the reference from the kids array of pParent // 2. Decrease count of every node in lstParents (which also includes pParent) // 3. Remove empty page nodes // TODO: Tell cache to free page object // 1. Delete reference this->DeletePageNode( pParent, nIndex ) ; // 2. Decrease count PdfObjectList::const_reverse_iterator itParents = rlstParents.rbegin(); while( itParents != rlstParents.rend() ) { this->ChangePagesCount( *itParents, -1 ); ++itParents; } // 3. Remove empty pages nodes itParents = rlstParents.rbegin(); while( itParents != rlstParents.rend() ) { // Never delete root node if( IsEmptyPageNode( *itParents ) && *itParents != GetRoot() ) { PdfObject* pParentOfNode = *(itParents + 1); int nKidsIndex = this->GetPosInKids( *itParents, pParentOfNode ); DeletePageNode( pParentOfNode, nKidsIndex ); // Delete empty page nodes delete this->GetObject()->GetOwner()->RemoveObject( (*itParents)->Reference() ); } ++itParents; } } void PdfPagesTree::DeletePageNode( PdfObject* pParent, int nIndex ) { PdfArray kids = pParent->GetDictionary().GetKey( PdfName("Kids") )->GetArray(); kids.erase( kids.begin() + nIndex ); pParent->GetDictionary().AddKey( PdfName("Kids"), kids ); } int PdfPagesTree::ChangePagesCount( PdfObject* pPageObj, int nDelta ) { // Increment or decrement inPagesDict's Count by inDelta, and return the new count. // Simply return the current count if inDelta is 0. int cnt = GetChildCount( pPageObj ); if( 0 != nDelta ) { cnt += nDelta ; pPageObj->GetDictionary().AddKey( "Count", PdfVariant( static_cast(cnt) ) ); } return cnt ; } bool PdfPagesTree::IsEmptyPageNode( PdfObject* pPageNode ) { long lCount = GetChildCount( pPageNode ); bool bKidsEmpty = true; if( pPageNode->GetDictionary().HasKey( PdfName("Kids") ) ) { bKidsEmpty = pPageNode->GetDictionary().GetKey( PdfName("Kids") )->GetArray().empty(); } return ( lCount == 0L || bKidsEmpty ); } /* PdfObject* PdfPagesTree::GetPageNode( int nPageNum, PdfObject* pPagesObject, std::deque & rListOfParents ) { // recurse through the pages tree nodes PdfObject* pObj = NULL; if( !pPagesObject->GetDictionary().HasKey( "Kids" ) ) return NULL; pObj = pPagesObject->GetDictionary().GetKey( "Kids" ); if( !pObj->IsArray() ) return NULL; PdfArray& kidsArray = pObj->GetArray(); size_t numKids = kidsArray.size(); size_t kidsCount = GetChildCount( pPagesObject ); // All parents of the page node will be added to this lists, // so that the PdfPage can later access inherited attributes rListOfParents.push_back( pPagesObject ); // the pages tree node represented by pPagesObject has only page nodes in its kids array, // or pages nodes with a kid count of 1, so we can speed things up // by going straight to the desired node if ( numKids == kidsCount ) { if( nPageNum >= static_cast(kidsArray.size()) ) { PdfError::LogMessage( eLogSeverity_Critical, "Requesting page index %i from array of size %i\n", nPageNum, kidsArray.size() ); nPageNum--; } PdfVariant pgVar = kidsArray[ nPageNum ]; while ( true ) { if ( pgVar.IsArray() ) { // Fixes some broken PDFs who have trees with 1 element kids arrays return GetPageNodeFromTree( nPageNum, pgVar.GetArray(), rListOfParents ); } else if ( !pgVar.IsReference() ) return NULL; // can't handle inline pages just yet... PdfObject* pgObject = GetRoot()->GetOwner()->GetObject( pgVar.GetReference() ); // make sure the object is a /Page and not a /Pages with a single kid if ( pgObject->GetDictionary().GetKeyAsName( PdfName( "Type" ) ) == PdfName( "Page" ) ) return pgObject; // it's a /Pages with a single kid, so dereference and try again... if( !pgObject->GetDictionary().HasKey( "Kids" ) ) return NULL; rListOfParents.push_back( pgObject ); pgVar = *(pgObject->GetDictionary().GetKey( "Kids" )); } } else { return GetPageNodeFromTree( nPageNum, kidsArray, rListOfParents ); } // we should never exit from here - we should always have been able to return a page from above // assert( false ) ; return NULL; } */ }; podofo-0.9.3/src/doc/PdfImage.h0000664000175000017500000002537112347347566016073 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2005 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_IMAGE_H_ #define _PDF_IMAGE_H_ #include "podofo/base/PdfDefines.h" #include "podofo/base/PdfFilter.h" #include "PdfXObject.h" namespace PoDoFo { class PdfArray; class PdfDocument; class PdfInputStream; class PdfObject; class PdfVecObjects; /** A PdfImage object is needed when ever you want to embedd an image * file into a PDF document. * The PdfImage object is embedded once and can be drawn as often * as you want on any page in the document using PdfPainter * * \see GetImageReference * \see PdfPainter::DrawImage * * \see SetImageData */ class PODOFO_DOC_API PdfImage : public PdfXObject { public: /** Constuct a new PdfImage object * * \param pParent parent vector of this image * \param pszPrefix optional prefix for XObject-name */ PdfImage( PdfVecObjects* pParent, const char* pszPrefix = NULL ); /** Constuct a new PdfImage object * This is an overloaded constructor. * * \param pParent parent document * \param pszPrefix optional prefix for XObject-name */ PdfImage( PdfDocument* pParent, const char* pszPrefix = NULL ); /** Construct an image from an existing PdfObject * * \param pObject a PdfObject that has to be an image */ PdfImage( PdfObject* pObject ); ~PdfImage(); /** * Get a list of all image formats supported by this PoDoFo build. * * Example: { "JPEG", "TIFF", NULL } * * \returns a zero terminates list of all supported image formats */ static const char** GetSupportedFormats(); /** Set the color space of this image. The default value is * ePdfColorSpace_DeviceRGB. * \param eColorSpace one of ePdfColorSpace_DeviceGray, ePdfColorSpace_DeviceRGB and * ePdfColorSpace_DeviceCMYK, ePdfColorSpace_Indexed * \param indexedData this parameter is required only for ePdfColorSpace_Indexed and * it contains string with one number and then color palette, like "/DeviceRGB 15 <000000 00FF00...>" * or the string array can be a resource name. * * \see SetImageICCProfile to set an ICC profile instead of a simple colorspace */ void SetImageColorSpace( EPdfColorSpace eColorSpace, const PdfArray *indexedData = NULL ); /** Set an ICC profile for this image. * * \param pStream an input stream from which the ICC profiles data can be read * \param lColorComponents the number of colorcomponents of the ICC profile * \param eAlternateColorSpace an alternate colorspace to use if the ICC profile cannot be used * * \see SetImageColorSpace to set an colorspace instead of an ICC profile for this image */ void SetImageICCProfile( PdfInputStream* pStream, long lColorComponents, EPdfColorSpace eAlternateColorSpace = ePdfColorSpace_DeviceRGB ); //EPdfColorSpace GetImageColorSpace() const; /** Set a softmask for this image. * \param pSoftmask a PdfImage pointer to the image, which is to be set as softmask, must be 8-Bit-Grayscale * */ void SetImageSoftmask( const PdfImage* pSoftmask ); /** Get the width of the image when drawn in PDF units * \returns the width in PDF units */ inline double GetWidth() const; /** Get the height of the image when drawn in PDF units * \returns the height in PDF units */ inline double GetHeight() const; /** Set the actual image data from an input stream * * The image data will be flate compressed. * If you want no compression or another filter to be applied * use the overload of SetImageData which takes a TVecFilters * as argument. * * \param nWidth width of the image in pixels * \param nHeight height of the image in pixels * \param nBitsPerComponent bits per color component of the image (depends on the image colorspace you have set * but is 8 in most cases) * \param pStream stream supplieding raw image data * * \see SetImageData */ void SetImageData( unsigned int nWidth, unsigned int nHeight, unsigned int nBitsPerComponent, PdfInputStream* pStream ); /** Set the actual image data from an input stream * * \param nWidth width of the image in pixels * \param nHeight height of the image in pixels * \param nBitsPerComponent bits per color component of the image (depends on the image colorspace you have set * but is 8 in most cases) * \param pStream stream supplieding raw image data * \param vecFilters these filters will be applied to compress the image data */ void SetImageData( unsigned int nWidth, unsigned int nHeight, unsigned int nBitsPerComponent, PdfInputStream* pStream, const TVecFilters & vecFilters ); /** Set the actual image data from an input stream. * The data has to be encoded already and an appropriate * filters key entry has to be set manually before! * * \param nWidth width of the image in pixels * \param nHeight height of the image in pixels * \param nBitsPerComponent bits per color component of the image (depends on the image colorspace you have set * but is 8 in most cases) * \param pStream stream supplieding raw image data */ void SetImageDataRaw( unsigned int nWidth, unsigned int nHeight, unsigned int nBitsPerComponent, PdfInputStream* pStream ); /** Load the image data from a file * \param pszFilename */ void LoadFromFile( const char* pszFilename ); #ifdef PODOFO_HAVE_JPEG_LIB /** Load the image data from a JPEG file * \param pszFilename */ void LoadFromJpeg( const char* pszFilename ); /** Load the image data from JPEG bytes * \param pData JPEG bytes * \param dwLen number of bytes */ void LoadFromJpegData(const unsigned char* pData, pdf_long dwLen); #ifdef _WIN32 /** Load the image data from a JPEG file * \param pszFilename * * This is an overloaded member function to allow working * with unicode characters. On Unix systes you can also path * UTF-8 to the const char* overload. */ void LoadFromJpeg( const wchar_t* pszFilename ); #endif // _WIN32 #endif // PODOFO_HAVE_JPEG_LIB #ifdef PODOFO_HAVE_TIFF_LIB /** Load the image data from a TIFF file * \param pszFilename */ void LoadFromTiff( const char* pszFilename ); #endif // PODOFO_HAVE_TIFF_LIB #ifdef PODOFO_HAVE_PNG_LIB /** Load the image data from a PNG file * \param pszFilename */ void LoadFromPng( const char* pszFilename ); #endif // PODOFO_HAVE_PNG_LIB /** Set an color/chroma-key mask on an image. * The masked color will not be painted, i.e. masked as being transparent. * * \param r red RGB value of color that should be masked * \param g green RGB value of color that should be masked * \param b blue RGB value of color that should be masked * \param threshold colors are masked that are in the range [(r-threshold, r+threshold),(g-threshold, g+threshold),(b-threshold, b+threshold)] */ void SetImageChromaKeyMask(pdf_int64 r, pdf_int64 g, pdf_int64 b, pdf_int64 threshold = 0); /** * Apply an interpolation to the image if the source resolution * is lower than the resolution of the output device. * Default is false. * \param bValue whether the image should be interpolated */ void SetInterpolate(bool bValue); private: /** Converts a EPdfColorSpace enum to a name key which can be used in a * PDF dictionary. * \param eColorSpace a valid colorspace * \returns a valid key for this colorspace. */ static PdfName ColorspaceToName( EPdfColorSpace eColorSpace ); #ifdef PODOFO_HAVE_JPEG_LIB void LoadFromJpegHandle( PdfFileInputStream* pInStream ); #endif // PODOFO_HAVE_JPEG_LIB }; // ----------------------------------------------------- // // ----------------------------------------------------- inline double PdfImage::GetWidth() const { return this->GetPageSize().GetWidth(); } // ----------------------------------------------------- // // ----------------------------------------------------- inline double PdfImage::GetHeight() const { return this->GetPageSize().GetHeight(); } }; #endif // _PDF_IMAGE_H_ podofo-0.9.3/src/doc/PdfTTFWriter.h0000664000175000017500000006511712344436402016666 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2007 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_TTF_WRITER_H_ #define _PDF_TTF_WRITER_H_ #error "THIS SOURCE FILE WAS REPLACED BY PdfFontTTFSubset.h !" #include "PdfDefines.h" #include "PdfRefCountedBuffer.h" namespace PoDoFo { class PdfInputDevice; class PdfOutputDevice; namespace NonPublic { /** An internal class which can parse a TrueType font file * and write a subset of this TrueType font back to an output device. * * This class is used internally to do font subsetting. * * The usual way to use this class is: * * PdfTTFWriter writer; * writer.Read ( [an input device] ); // read the font from a device * writer.Subset ( ); // do the subsetting * writer.Write ( [an output device] ); // write the font back to a device */ class PODOFO_API PdfTTFWriter { // Some common datatypes used in TTF files typedef pdf_uint32 pdf_ttf_fixed; typedef pdf_uint16 pdf_ttf_ushort; typedef pdf_int16 pdf_ttf_short; typedef pdf_uint32 pdf_ttf_ulong; typedef pdf_int16 pdf_ttf_fword; typedef pdf_uint16 pdf_ttf_ufword; typedef pdf_int16 pdf_ttf_f2dot14; #pragma pack(1) /** The table dictionary is the starting point when reading * or writing a TTF file. */ struct TTableDirectory { pdf_ttf_fixed sfnt_version; ///< 0x00010000 for version 1.0 pdf_ttf_ushort numTables; ///< Number of tables in this file pdf_ttf_ushort searchRange; ///< (Maximum power of 2 <= numTables) * 16 pdf_ttf_ushort entrySelector; ///< Log2( Maximum power of 2 <= numTables) pdf_ttf_ushort rangeShift; ///< numTables * 16 - searchRange }; struct TTableDirectoryEntry { pdf_ttf_ulong tag; ///< 4 character identifier pdf_ttf_ulong checkSum; ///< Checksum of the table pdf_ttf_ulong offset; ///< Offset from the beginning of the file pdf_ttf_ulong length; ///< Length of this table }; typedef std::vector TVecTableDirectoryEntries; typedef TVecTableDirectoryEntries::iterator TIVecTableDirectoryEntries; typedef TVecTableDirectoryEntries::const_iterator TCIVecTableDirectoryEntries; struct TTable { TTable() : data( NULL ) { } ~TTable() { /* if( data ) free( data ); */ } pdf_ttf_ulong tag; ///< 4 character identifier pdf_ttf_ulong length; ///< Length of this table char* data; ///< Actual table data buffer }; typedef std::vector TVecTable; typedef TVecTable::iterator TIVecTable; typedef TVecTable::const_iterator TCIVecTable; struct TMaxP { pdf_ttf_fixed version; ///< The table versions 0x00010000 for version 1.0 pdf_ttf_ushort numGlyphs; ///< The number of glyphs in this font pdf_ttf_ushort maxPoints; ///< Maximum number of points in a non composite glyph pdf_ttf_ushort maxContours; ///< Maximum number of contours in a non composite glyph pdf_ttf_ushort maxCompositePoints; ///< Maximum number of points in a composite glyph pdf_ttf_ushort maxCompositeContours; ///< Maximum number of contours in a composite glyph pdf_ttf_ushort maxZones; ///< 1 if instrutions do not use Z0 or 2 if instrutions do use Z0 (twilight zone) pdf_ttf_ushort maxTwilightPoints; ///< Maximum points used in Z0 pdf_ttf_ushort maxStorage; ///< Maximum number of storage area locations pdf_ttf_ushort maxFunctionsDefs; ///< Number of FDEF's pdf_ttf_ushort maxInstructionDefs; ///< Number of IDEF's pdf_ttf_ushort maxStackElements; ///< Maximum stack depth pdf_ttf_ushort maxSizeOfInstruction; ///< Maximum byte count for glyph instruction pdf_ttf_ushort maxComponentElements; ///< Maximum number of components referenced at top level for composite glyph pdf_ttf_ushort maxComponentDepth; ///< Maximum level of recursions; 1 for simple components }; struct THead { pdf_ttf_fixed version; ///< The table versions 0x00010000 for version 1.0 pdf_ttf_fixed revision; ///< The revision set by the font manufacturer pdf_ttf_ulong checkSumAdjustment; ///< To compute: set it to 0, sum the entire font as ULONG, then store 0xB1B0AFBA - sum pdf_ttf_ulong magicNumber; ///< Set to 0x5F0F3CF5 pdf_ttf_ushort flags; ///< Font flags pdf_ttf_ushort unitsPerEm; char created[8]; char modified[8]; pdf_ttf_fword xMin; pdf_ttf_fword yMin; pdf_ttf_fword xMax; pdf_ttf_fword yMax; pdf_ttf_ushort macStyle; pdf_ttf_ushort lowestRecPPEM; pdf_ttf_short fontDirectionHint; pdf_ttf_short indexToLocForm; ///< 0 for short offsets, 1 for long offsets pdf_ttf_short glyphDataFormat; ///< 0 for current format }; struct TCMapEntry { pdf_ttf_ushort platformId; pdf_ttf_ushort encodingId; pdf_ttf_ulong offset; }; /** * Header of a single glyph in the glyf table */ struct TGlyphHeader { pdf_ttf_short numberOfContours; ///< If greater or equal 0, this is a single glyph, if negative it is a composite pdf_ttf_fword xMin; pdf_ttf_fword yMin; pdf_ttf_fword xMax; pdf_ttf_fword yMax; }; #pragma pack() class PdfTTFGlyph { public: /** Create a new glyph object. * * \param nIndex glyph index. * \param bComposite if true, this is a composite glyph * otherwise this object is simple glyph */ PdfTTFGlyph( int nIndex ) : m_nPosition( 0 ), m_nIndex( nIndex ), m_bComposite( false ), m_nInstructionLength( 0 ), m_pInstructions( NULL ) { printf("m_nIndex=%i\n", m_nIndex ); } PdfTTFGlyph( const PdfTTFGlyph & rhs ) { operator=( rhs ); } const PdfTTFGlyph & operator=( const PdfTTFGlyph & rhs ) { m_nIndex = rhs.m_nIndex; m_bComposite = rhs.m_bComposite; m_tHeader = rhs.m_tHeader; m_nPosition = rhs.m_nPosition; m_nInstructionLength = rhs.m_nInstructionLength; m_pInstructions = rhs.m_pInstructions; // simple vecEndPoints = rhs.vecEndPoints; vecXCoordinates = rhs.vecXCoordinates; vecYCoordinates = rhs.vecYCoordinates; vecFlags = rhs.vecFlags; vecFlagsOrig = rhs.vecFlagsOrig; // composite arg1 = rhs.arg1; arg2 = rhs.arg2; xx = rhs.xx; yy = rhs.yy; xy = rhs.xy; yx = rhs.yx; m_buffer = rhs.m_buffer; return *this; } inline bool IsComposite() const { return m_bComposite; } inline void SetComposite( bool b ) { m_bComposite = b; } inline int GetIndex() const { return m_nIndex; } inline int GetPosition() const { return m_nPosition; } inline void SetPosition( int nPos ) { m_nPosition = nPos; } inline pdf_ttf_ushort GetInstrunctionLength() const { return m_nInstructionLength; }; inline const char* GetInstrunctions() const { return m_pInstructions; } public: // TODO: add accessors int m_nPosition; PdfRefCountedBuffer m_buffer; // common int m_nIndex; bool m_bComposite; TGlyphHeader m_tHeader; pdf_ttf_ushort m_nInstructionLength; char* m_pInstructions; // simple glyph std::vector vecEndPoints; std::vector vecXCoordinates; std::vector vecYCoordinates; std::vector vecFlags; ///< Parsed font flags which are used to read glyf coordinates std::vector vecFlagsOrig; ///< Compressed files can be written out 1to1 to disk // composite pdf_ttf_short arg1; pdf_ttf_short arg2; pdf_ttf_short xx; pdf_ttf_short yy; pdf_ttf_short xy; pdf_ttf_short yx; }; #pragma pack(1) struct TCMapFormat4 { pdf_ttf_ushort format; pdf_ttf_ushort length; pdf_ttf_ushort version; pdf_ttf_ushort segCountX2; ///< 2 x segCount pdf_ttf_ushort searchRange; ///< 2 x (2**floor(log2(segCount))) pdf_ttf_ushort entrySelector; ///< log2(searchRange/2) pdf_ttf_ushort rangeShift; ///< 2 x segCount - searchRange }; struct TCMapRange { pdf_ttf_ushort nStart; pdf_ttf_ushort nEnd; pdf_ttf_short nDelta; pdf_ttf_ushort nOffset; TCMapRange() { } TCMapRange( const TCMapRange & rhs ) { this->operator=( rhs ); } const TCMapRange & operator=( const TCMapRange & rhs ) { nStart = rhs.nStart; nEnd = rhs.nEnd; nDelta = rhs.nDelta; nOffset = rhs.nOffset; return *this; } bool operator<( const TCMapRange & rhs ) const { return nStart < rhs.nStart; } }; typedef std::vector TVecGlyphs; typedef TVecGlyphs::iterator TIVecGlyphs; typedef TVecGlyphs::const_iterator TCIVecGlyphs; typedef std::vector TVecLoca; typedef TVecLoca::iterator TIVecLoca; typedef TVecLoca::const_iterator TCIVecLoca; struct THHea { pdf_ttf_fixed version; ///< version 0x00010000 pdf_ttf_fword ascender; pdf_ttf_fword descender; pdf_ttf_fword linegap; pdf_ttf_fword advanceWidthMax; ///< maximum advance width value in "hmtx" table pdf_ttf_fword minLeftSideBearing; ///< minimum left side bearing in hmtx table pdf_ttf_fword minRightSideBearing;///< minimum right side bearing in hmtx table pdf_ttf_fword xMaxExtent; ///< Max( lsb + (xMax - xMin) ); pdf_ttf_short caretSlopeRise; pdf_ttf_short caretSlopeRun; pdf_ttf_short reserved1; pdf_ttf_short reserved2; pdf_ttf_short reserved3; pdf_ttf_short reserved4; pdf_ttf_short reserved5; pdf_ttf_short metricDataFormat; pdf_ttf_ushort numberOfHMetrics; ///< Number of entries in the hmtx table }; struct TOs2 { pdf_ttf_ushort version; ///< version 0x00010000 pdf_ttf_short xAvgCharWidth; pdf_ttf_ushort usWeightClass; pdf_ttf_ushort usWidthClass; pdf_ttf_short fsType; pdf_ttf_short ySubscriptXSize; pdf_ttf_short ySubscriptYSize; pdf_ttf_short ySubscriptXOffset; pdf_ttf_short ySubscriptYOffset; pdf_ttf_short ySuperscriptXSize; pdf_ttf_short ySuperscriptYSize; pdf_ttf_short ySuperscriptXOffset; pdf_ttf_short ySuperscriptYOffset; pdf_ttf_short yStrikeoutSize; pdf_ttf_short yStrikeoutPosition; pdf_ttf_short sFamilyClass; char panose[10]; ///< Panose information pdf_ttf_ulong ulUnicodeRange1; pdf_ttf_ulong ulUnicodeRange2; pdf_ttf_ulong ulUnicodeRange3; pdf_ttf_ulong ulUnicodeRange4; char achVendID[4]; pdf_ttf_ushort fsSelection; pdf_ttf_ushort usFirstCharIndex; ///< The minimum unicode char index in this font pdf_ttf_ushort usLastCharIndex; ///< The maximum unicode char index in this font pdf_ttf_ushort sTypoAscender; pdf_ttf_ushort sTypoDescender; pdf_ttf_ushort sTypoLineGap; pdf_ttf_ushort usWinAscent; pdf_ttf_ushort usWinDescent; pdf_ttf_ulong ulCodePageRange1; pdf_ttf_ulong ulCodePageRange2; }; struct TLongHorMetric { pdf_ttf_ufword advanceWidth; pdf_ttf_fword leftSideBearing; }; struct TNameTable { // header pdf_ttf_ushort format; ///< 0 pdf_ttf_ushort numRecords; ///< 1 pdf_ttf_ushort offset; ///< 6 // body pdf_ttf_ushort platformId; ///< 3 (Microsoft) pdf_ttf_ushort encodingId; ///< 1 (Unicode) pdf_ttf_ushort languageId; ///< 0x0809 (british English) pdf_ttf_ushort nameId; ///< 1 (font family name) pdf_ttf_ushort stringLength; pdf_ttf_ushort stringOffset;///< 0 }; /** The postscript table */ struct TPost { pdf_ttf_fixed format; pdf_ttf_fixed italicAngle; pdf_ttf_fword underlinePosition; pdf_ttf_fword underlineThickness; pdf_ttf_ulong isFixedPitch; pdf_ttf_ulong minMemType42; pdf_ttf_ulong maxMemType42; pdf_ttf_ulong minMemType1; pdf_ttf_ulong maxMemType1; }; #pragma pack() public: /** Create a PdfTTFWriter object. * For testing purposes. * * TODO: Remove */ PdfTTFWriter(); PdfTTFWriter( const std::vector & rvecGlyphs ); ~PdfTTFWriter(); /** Fills the internal data structures * using an existing TrueType font. * * \param pDevice the TTF is read from this device */ void Read( PdfInputDevice* pDevice ); /** Do the actual subsetting of the font data * TODO */ void Subset(); /** Write a TTF font from the current internal structures * to an output device. * * \param pDevice write the font to this device */ void Write( PdfOutputDevice* pDevice ); private: /** Create a tag name from four characters, * so that the user readable tag can be put into * TTableDirectoryEntry. * * \returns the tag as a pdf_ttf_ulong */ inline pdf_ttf_ulong CreateTag( char a, char b, char c, char d ) const; /** Calculate the checksum of a table. * * The table is interpreted as a byte stream of unsigned longs * and has to be padded to a multiple of 4 bytes * * \param pTable pointer to the beginning of the table * \param lLength length of the table * * \returns the checksum of the table */ pdf_ttf_ulong CalculateChecksum( const pdf_ttf_ulong* pTable, pdf_ttf_ulong lLength ) const; /** Convert a pdf_ttf_ushort between big and little endian * * \param pShort a value to swap */ inline void SwapUShort( pdf_ttf_ushort* pShort ) const; /** Convert a pdf_ttf_short between big and little endian * * \param pShort a value to swap */ inline void SwapShort( pdf_ttf_short* pShort ) const; /** Convert a pdf_ttf_fword between big and little endian * * \param pFword a value to swap */ inline void SwapFWord( pdf_ttf_fword* pFword ) const; /** Convert a pdf_ttf_ulong between big and little endian * * \param pShort a value to swap */ inline void SwapULong( pdf_ttf_ulong* pLong ) const; /** Reads the table directory from the current position * of the input device, handling any necessary * conversion from big to little endian. * * \param pDevice read from the current position of this device. * * \see m_tTableDirectory */ void ReadTableDirectory( PdfInputDevice* pDevice ); /** Reads a table directory entry from the current position * of the input device, handling any necessary * conversion from big to little endian. * * \param pDevice read from the current position of this device. * \param pEntry store the result at this memory location */ void ReadTableDirectoryEntry( PdfInputDevice* pDevice, TTableDirectoryEntry* pEntry ); /** Writes a table directory entry at the current position * of the output device, handling any necessary * conversion from big to little endian. * * \param pDevice write at the current position of this device. * \param pEntry the entry which should be written */ void WriteTableDirectoryEntry( PdfOutputDevice* pDevice, TTableDirectoryEntry* pEntry ); /** Reads the head table from the current position of * the input device, handling any necessary conversion * from big to little endian. * * \param pDevice read from the current position of this device. * * \see m_tHead */ void ReadHeadTable( PdfInputDevice* pDevice ); /** Swap the endianess of the head table. * \see m_tHead */ void SwapHeadTable(); void ReadMaxpTable( PdfInputDevice* pDevice ); void ReadLocaTable( PdfInputDevice* pDevice ); void ReadHHeaTable( PdfInputDevice* pDevice ); void ReadCmapTable( PdfInputDevice* pDevice ); void ReadGlyfTable( PdfInputDevice* pDevice ); void ReadOs2Table ( PdfInputDevice* pDevice ); void ReadHmtxTable( PdfInputDevice* pDevice ); void ReadPostTable( PdfInputDevice* pDevice ); /** Writes the table directory at the current position * of the output device, handling any necessary * conversion from big to little endian. * * \param pDevice write at the current position of this device. * * \see m_tTableDirectory */ void WriteTableDirectory( PdfOutputDevice* pDevice ); /** Writes the head table at the current position * of the output device, handling any necessary * conversion from big to little endian. * * \param pDevice write at the current position of this device. * * \see m_tHead */ void WriteHeadTable( PdfOutputDevice* pDevice ); /** Writes the maxp table at the current position * of the output device, handling any necessary * conversion from big to little endian. * * \param pDevice write at the current position of this device. * * \see m_tMaxp */ void WriteMaxpTable( PdfOutputDevice* pDevice ); void WriteHHeaTable( PdfOutputDevice* pDevice ); void WriteLocaTable( PdfOutputDevice* pDevice ); void WriteCMapTable( PdfOutputDevice* pDevice ); void WriteGlyfTable( PdfOutputDevice* pDevice ); void WriteOs2Table ( PdfOutputDevice* pDevice ); void WriteNameTable( PdfOutputDevice* pDevice ); void WriteHmtxTable( PdfOutputDevice* pDevice ); void WritePostTable( PdfOutputDevice* pDevice ); /** * Write a table to an output device and create a table directory for it * with a correctly calculated checksum. * * \param pDevice the output device on which the table should be written * \param rToc add a table directory entry to this table directory. * \param tag the tag of the table (e.g. 'name' or 'os/2'). * \param WriteTableFunc a member function pointer to the function that actually write the data * * \see CreateTag */ void WriteTable( PdfOutputDevice* pDevice, TVecTableDirectoryEntries & rToc, pdf_ttf_ulong tag, void (PdfTTFWriter::*WriteTableFunc)( PdfOutputDevice* ) ); void SwapGlyfHeader( TGlyphHeader* pHeader ); /** Swap the endianess of the maxp table. * \see m_tMaxp */ void SwapMaxpTable(); void SwapHHeaTable(); void SwapOs2Table(); void SwapPostTable(); /** Read the glyph coordinates from an input device. * * \param pDevice read from this device * \param rvecFlags a vector of flags describing the coordinates to load * For each flag ONE coordinate is read. Not more, not less. * \param rvecCoordinates store all coordinates in this vector * \param nFlagShort the flag to use for x and y coordinates which determines a short coordinate * \param nFlag the flag to use (0x10 for x coordinates and 0x20 for y coordinates) */ void ReadSimpleGlyfCoordinates( PdfInputDevice* pDevice, const std::vector & rvecFlags, std::vector & rvecCoordinates, int nFlagShort, int nFlag ); void WriteSimpleGlyfCoordinates( PdfOutputDevice* pDevice, const std::vector & rvecFlags, std::vector & rvecCoordinates, int nFlagShort, int nFlag ); /** Get the offset to the location of the glyphs data. * * \param nIndex unicode index of the glyph to load * \param plLength pointer to an address where the length of the glyphdata can be stored * \param pDevice an input device which can be used to read the CMap table which is required for certain glyphs * * \return the offset to the glyph data or -1 if the glyph does not exist */ long GetGlyphDataLocation( unsigned int nIndex, long* plLength, PdfInputDevice* pDevice ) const; /** Load a glyph from an input device at a certain offset * * \param nIndex the index of the glyph to load * \param lOffset the offset at which the glyph is located in the file * \param pDevice the input device to read from * */ void LoadGlyph( int nIndex, long lOffset, PdfInputDevice* pDevice ); private: long m_lGlyphDataOffset; ///< Offset to the glyph data table long m_lCMapOffset; ///< Offset to the cmap table std::vector m_vecGlyphIndeces; ///< List of glyph indeces we would like to embedd TTableDirectory m_tTableDirectory; ///< The TTF header TVecTable m_vecTableData; ///< The actual data of the tables TMaxP m_tMaxp; ///< The maximum memory requirements of this font THead m_tHead; ///< The head table THHea m_tHHea; ///< The hhea table TOs2 m_tOs2; ///< The OS/2 table TPost m_tPost; ///< The post table TVecLoca m_tLoca; ///< The loca table in long format which is read in TVecLoca m_vecLoca; ///< The loca table in long format which is written out TVecGlyphs m_vecGlyphs; ///< All glyphs including their outlines std::vector m_ranges; ///< CMap ranges TCMapFormat4 format4; std::vector m_vecGlyphIds; std::vector m_vecHmtx; ///< Hmtx table in long format PdfRefCountedBuffer* m_pRefBuffer; ///< A temporary buffer which is used during writing a TTF file }; // ----------------------------------------------------- // // ----------------------------------------------------- inline PdfTTFWriter::pdf_ttf_ulong PdfTTFWriter::CreateTag( char a, char b, char c, char d ) const { return ( ( a << 24 )| ( b << 16 ) | ( c << 8 ) | d ); } // ----------------------------------------------------- // // ----------------------------------------------------- inline void PdfTTFWriter::SwapUShort( pdf_ttf_ushort* pShort ) const { *pShort = ((*pShort << 8) & 0xFF00) | ((*pShort >> 8) & 0x00FF); } // ----------------------------------------------------- // // ----------------------------------------------------- inline void PdfTTFWriter::SwapShort( pdf_ttf_short* pShort ) const { *pShort = ((*pShort << 8) & 0xFF00) | ((*pShort >> 8) & 0x00FF); } // ----------------------------------------------------- // // ----------------------------------------------------- inline void PdfTTFWriter::SwapFWord( pdf_ttf_fword* pFword ) const { *pFword = ((*pFword << 8) & 0xFF00) | ((*pFword >> 8) & 0x00FF); } // ----------------------------------------------------- // // ----------------------------------------------------- inline void PdfTTFWriter::SwapULong( pdf_ttf_ulong* pLong ) const { *pLong = ((*pLong << 24) & 0xFF000000) | ((*pLong << 8) & 0x00FF0000) | ((*pLong >> 8) & 0x0000FF00) | ((*pLong >> 24) & 0x000000FF) ; } }; }; #endif // _PDF_TTF_WRITER_H_ podofo-0.9.3/src/doc/PdfDocument.h0000664000175000017500000007430712347310502016606 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2006 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_DOCUMENT_H_ #define _PDF_DOCUMENT_H_ #include "podofo/base/PdfDefines.h" #include "podofo/base/PdfObject.h" #include "podofo/base/PdfParser.h" #include "podofo/base/PdfWriter.h" #include "PdfAcroForm.h" #include "PdfFontCache.h" #include "PdfInfo.h" namespace PoDoFo { class PdfDestination; class PdfDictionary; class PdfFileSpec; class PdfFont; class PdfFontConfigWrapper; class PdfInfo; class PdfMemDocument; class PdfNamesTree; class PdfOutlines; class PdfPage; class PdfPagesTree; class PdfRect; class PdfXObject; /** PdfDocument is the core interface for working with PDF documents. * * PdfDocument provides easy access to the individual pages * in the PDF file and to certain special dictionaries. * * PdfDocument cannot be used directly. * Use PdfMemDocument whenever you want to change the object structure * of a PDF file. * * When you are only creating PDF files, please use PdfStreamedDocument * which is usually faster for creating PDFs. * * \see PdfStreamedDocument * \see PdfMemDocument */ class PODOFO_DOC_API PdfDocument { friend class PdfElement; public: /** Close down/destruct the PdfDocument */ virtual ~PdfDocument(); /** Get the write mode used for wirting the PDF * \returns the write mode */ virtual EPdfWriteMode GetWriteMode() const = 0; /** Get the PDF version of the document * \returns EPdfVersion version of the pdf document */ virtual EPdfVersion GetPdfVersion() const = 0; /** Returns wether this PDF document is linearized, aka * weboptimized * \returns true if the PDF document is linearized */ virtual bool IsLinearized() const = 0; /** Get access to the internal Info dictionary * You can set the author, title etc. of the * document using the info dictionary. * * \returns the info dictionary */ PdfInfo* GetInfo() const { return m_pInfo; } /** Get access to the Outlines (Bookmarks) dictionary * The returned outlines object is owned by the PdfDocument. * * \param bCreate create the object if it does not exist (ePdfCreateObject) * or return NULL if it does not exist * \returns the Outlines/Bookmarks dictionary */ PdfOutlines* GetOutlines( bool bCreate = ePdfCreateObject ); /** Get access to the Names dictionary (where all the named objects are stored) * The returned PdfNamesTree object is owned by the PdfDocument. * * \param bCreate create the object if it does not exist (ePdfCreateObject) * or return NULL if it does not exist * \returns the Names dictionary */ PdfNamesTree* GetNamesTree( bool bCreate = ePdfCreateObject ); /** Get access to the AcroForm dictionary * * \param bCreate create the object if it does not exist (ePdfCreateObject) * or return NULL if it does not exist * \param eDefaultAppearance specifies if a default appearence shall be created * * \returns PdfObject the AcroForm dictionary */ PdfAcroForm* GetAcroForm( bool bCreate = ePdfCreateObject, EPdfAcroFormDefaulAppearance eDefaultAppearance = ePdfAcroFormDefaultAppearance_BlackText12pt); /** Get access to the pages tree. * Better use GetPage and CreatePage methods. * \returns the PdfPagesTree of this document. */ inline PdfPagesTree* GetPagesTree() const; /** Get the total number of pages in a document * \returns int number of pages */ int GetPageCount() const; /** Get the PdfPage for a specific page in a document * The returned page is owned by the PdfDocument * and will get deleted along with it! * * \param nIndex which page (0-based) * \returns a pointer to a PdfPage for the requested page. * The returned object is owned by the PdfDocument. */ PdfPage* GetPage( int nIndex ) const; /** Creates a PdfFont object * \param pszFontName name of the font as it is known to the system * \param bSymbolCharset whether to use symbol charset, rather than unicode charset * \param pEncoding the encoding of the font. The font will not take ownership of this object. * \param eFontCreationFlags special flag to specify how fonts should be created * \param bEmbedd specifies whether this font should be embedded in the PDF file. * Embedding fonts is usually a good idea. * * \returns PdfFont* a pointer to a new PdfFont object. * The returned object is owned by the PdfDocument. */ PdfFont* CreateFont( const char* pszFontName, bool bSymbolCharset = false, const PdfEncoding * const pEncoding = PdfEncodingFactory::GlobalWinAnsiEncodingInstance(), PdfFontCache::EFontCreationFlags eFontCreationFlags = PdfFontCache::eFontCreationFlags_AutoSelectBase14, bool bEmbedd = true ); /** Creates a PdfFont object * \param pszFontName name of the font as it is known to the system * \param bBold if true search for a bold font * \param bItalic if true search for an italic font * \param bSymbolCharset whether to use symbol charset, rather than unicode charset * \param pEncoding the encoding of the font. The font will not take ownership of this object. * \param eFontCreationFlags special flag to specify how fonts should be created * \param bEmbedd specifies whether this font should be embedded in the PDF file. * Embedding fonts is usually a good idea. * \param pszFileName path to a valid font file * * \returns PdfFont* a pointer to a new PdfFont object. */ PdfFont* CreateFont( const char* pszFontName, bool bBold, bool bItalic, bool bSymbolCharset = false, const PdfEncoding * const pEncoding = PdfEncodingFactory::GlobalWinAnsiEncodingInstance(), PdfFontCache::EFontCreationFlags eFontCreationFlags = PdfFontCache::eFontCreationFlags_AutoSelectBase14, bool bEmbedd = true, const char* pszFileName = NULL ); #ifdef _WIN32 /** Creates a PdfFont object * \param pszFontName name of the font as it is known to the system * \param bSymbolCharset whether to use symbol charset, rather than unicode charset * \param pEncoding the encoding of the font. The font will not take ownership of this object. * \param bEmbedd specifies whether this font should be embedded in the PDF file. * Embedding fonts is usually a good idea. * * \returns PdfFont* a pointer to a new PdfFont object. * The returned object is owned by the PdfDocument. * * This is an overloaded member function to allow working * with unicode characters. On Unix systes you can also path * UTF-8 to the const char* overload. */ PdfFont* CreateFont( const wchar_t* pszFontName, bool bSymbolCharset = false, const PdfEncoding * const pEncoding = PdfEncodingFactory::GlobalWinAnsiEncodingInstance(), bool bEmbedd = true ); /** Creates a PdfFont object * \param pszFontName name of the font as it is known to the system * \param bBold if true search for a bold font * \param bItalic if true search for an italic font * \param bSymbolCharset whether to use symbol charset, rather than unicode charset * \param pEncoding the encoding of the font. The font will not take ownership of this object. * \param bEmbedd specifies whether this font should be embedded in the PDF file. * Embedding fonts is usually a good idea. * \param optional: pszFileName path to a valid font file * * \returns PdfFont* a pointer to a new PdfFont object. * * This is an overloaded member function to allow working * with unicode characters. On Unix systes you can also path * UTF-8 to the const char* overload. */ PdfFont* CreateFont( const wchar_t* pszFontName, bool bBold, bool bItalic, bool bSymbolCharset = false, const PdfEncoding * const pEncoding = PdfEncodingFactory::GlobalWinAnsiEncodingInstance(), bool bEmbedd = true); PdfFont* CreateFont( const LOGFONTA &logFont, const PdfEncoding * const pEncoding = PdfEncodingFactory::GlobalWinAnsiEncodingInstance(), bool bEmbedd = true ); PdfFont* CreateFont( const LOGFONTW &logFont, const PdfEncoding * const pEncoding = PdfEncodingFactory::GlobalWinAnsiEncodingInstance(), bool bEmbedd = true ); #endif // _WIN32 /** Creates a PdfFont object * \param face a valid freetype font handle (will be free'd by PoDoFo) * \param bSymbolCharset whether to use symbol charset, rather than unicode charset * \param pEncoding the encoding of the font. The font will not take ownership of this object. * \param bEmbedd specifies whether this font should be embedded in the PDF file. * Embedding fonts is usually a good idea. * \returns PdfFont* a pointer to a new PdfFont object. * The returned object is owned by the PdfDocument. */ PdfFont* CreateFont( FT_Face face, bool bSymbolCharset = false, const PdfEncoding * const pEncoding = PdfEncodingFactory::GlobalWinAnsiEncodingInstance(), bool bEmbedd = true ); /** Creates a duplicate Type1-PdfFont with a new Id * \param pFont is the existing font * \param pszSuffix Suffix to add to font-id * The returned object is owned by the PdfDocument. * * TODO: DS: Make this generic so that it will work * for any font type! */ PdfFont* CreateDuplicateFontType1( PdfFont * pFont, const char * pszSuffix ); /** Creates a font subset which contains only a few characters and is embedded. * * THIS WORKS ONLY FOR TTF FONTS! * * \param pszFontName name of the font as it is known to the system * \param bBold if true search for a bold font * \param bItalic if true search for an italic font * \param bSymbolCharset whether to use symbol charset, rather than unicode charset * \param pEncoding the encoding of the font. The font will not take ownership of this object. * \param pszFileName optional path of a fontfile which should be used * * \returns PdfFont* a pointer to a new PdfFont object. */ PdfFont* CreateFontSubset( const char* pszFontName, bool bBold, bool bItalic, bool bSymbolCharset = false, const PdfEncoding * const pEncoding = PdfEncodingFactory::GlobalWinAnsiEncodingInstance(), const char* pszFileName = NULL); #ifdef _WIN32 /** Creates a font subset which contains only a few characters and is embedded. * * THIS WORKS ONLY FOR TTF FONTS! * * \param pszFontName name of the font as it is known to the system * \param bBold if true search for a bold font * \param bItalic if true search for an italic font * \param bSymbolCharset whether to use symbol charset, rather than unicode charset * \param pEncoding the encoding of the font. The font will not take ownership of this object. * * \returns PdfFont* a pointer to a new PdfFont object. * * This is an overloaded member function to allow working * with unicode characters. On Unix systes you can also path * UTF-8 to the const char* overload. */ PdfFont* CreateFontSubset( const wchar_t* pszFontName, bool bBold, bool bItalic, bool bSymbolCharset = false, const PdfEncoding * const = PdfEncodingFactory::GlobalWinAnsiEncodingInstance() ); #endif // _WIN32 // Peter Petrov 26 April 2008 /** Returns the font library from font cache * * \returns the internal handle to the freetype library */ inline FT_Library GetFontLibrary() const; /** Embeds all pending subset-fonts, is automatically done on Write(). * Just call explicit in case PdfDocument is needed as XObject * */ void EmbedSubsetFonts(); /** Creates a new page object and inserts it into the internal * page tree. * The returned page is owned by the PdfDocument * and will get deleted along with it! * * \param rSize a PdfRect spezifying the size of the page (i.e the /MediaBox key) in 1/1000th mm * \returns a pointer to a PdfPage object */ PdfPage* CreatePage( const PdfRect & rSize ); /** Creates several new page objects and inserts them into the internal * page tree. * The created pages are owned by the PdfDocument * and will get deleted along with it! * * \param vecSizes a vector PdfRect's specifying the size of the pages (i.e the /MediaBox key) in PDF Units */ void CreatePages( const std::vector& vecSizes ); /** Creates a new page object and inserts it at index atIndex. * The returned page is owned by the pages tree and will get deleted along * with it! * * \param rSize a PdfRect specifying the size of the page (i.e the /MediaBox key) in PDF units * \param atIndex index where to insert the new page (0-based) * \returns a pointer to a PdfPage object */ PdfPage* InsertPage( const PdfRect & rSize, int atIndex); /** Appends another PdfDocument to this document * \param rDoc the document to append * \param bAppendAll specifies whether pages and outlines are appended too * \returns this document */ const PdfDocument & Append( const PdfMemDocument & rDoc, bool bAppendAll = true ); /** Inserts existing page from another PdfMemDocument to this document * \param rDoc the document to append from * \param nPageIndex Page index to append (0-based), from rDoc * \param nAtIndex Index at which add the page in this document * \returns this document */ const PdfDocument &InsertExistingPageAt( const PdfMemDocument & rDoc, int nPageIndex, int nAtIndex); /** Fill an existing empty XObject from a page of another document * This will append the other document with this one * \param pXObj pointer to the XOject * \param rDoc the document to embedd into XObject * \param nPage page-number to embedd into XObject * \param bUseTrimBox if true try to use trimbox for size of xobject * \returns the bounding box */ PdfRect FillXObjectFromDocumentPage( PdfXObject * pXObj, const PdfMemDocument & rDoc, int nPage, bool bUseTrimBox ); /** Fill an existing empty XObject from an existing page from the current document * If you need a page from another document use FillXObjectFromDocumentPage, or append the documents manually * \param pXObj pointer to the XOject * \param nPage page-number to embedd into XObject * \param bUseTrimBox if true try to use trimbox for size of xobject * \returns the bounding box */ PdfRect FillXObjectFromExistingPage( PdfXObject * pXObj, int nPage, bool bUseTrimBox ); /** Fill an existing empty XObject from an existing page pointer from the current document * This is the implementation for FillXObjectFromDocumentPage and FillXObjectFromExistingPage, you should use those directly instead of this * \param pXObj pointer to the XOject * \param pPage pointer to the page to embedd into XObject * \param bUseTrimBox if true try to use trimbox for size of xobject * \returns the bounding box */ PdfRect FillXObjectFromPage( PdfXObject * pXObj, const PdfPage * pPage, bool bUseTrimBox, unsigned int difference ); /** Attach a file to the document. * \param rFileSpec a file specification */ void AttachFile( const PdfFileSpec & rFileSpec ); /** Get an attached file's filespec * \param rName the name of the attachment * \return the file specification object if the file exists, NULL otherwise * The file specification object is not owned by the document and must be deleted by the caller */ PdfFileSpec* GetAttachment( const PdfString & rName ); /** Adds a PdfDestination into the global Names tree * with the specified name, optionally replacing one of the same name * \param rDest the destination to be assigned * \param rsName the name for the destination */ void AddNamedDestination( const PdfDestination& rDest, const PdfString & rsName ); /** Sets the opening mode for a document * \param inMode which mode to set */ void SetPageMode( EPdfPageMode inMode ); /** Gets the opening mode for a document * \returns which mode is set */ EPdfPageMode GetPageMode( void ) const; /** Sets the opening mode for a document to be in full screen */ void SetUseFullScreen( void ); /** Sets the page layout for a document */ void SetPageLayout( EPdfPageLayout inLayout ); /** Set the document's Viewer Preferences: * Hide the toolbar in the viewer */ void SetHideToolbar( void ); /** Set the document's Viewer Preferences: * Hide the menubar in the viewer */ void SetHideMenubar( void ); /** Set the document's Viewer Preferences: * Show only the documents contents and no controll * elements such as buttons and scrollbars in the viewer */ void SetHideWindowUI( void ); /** Set the document's Viewer Preferences: * Fit the document in the viewers window */ void SetFitWindow( void ); /** Set the document's Viewer Preferences: * Center the document in the viewers window */ void SetCenterWindow( void ); /** Set the document's Viewer Preferences: * Display the title from the document information * in the title of the viewer. * * \see SetTitle */ void SetDisplayDocTitle( void ); /** Set the document's Viewer Preferences: * Set the default print scaling of the document * * TODO: DS use an enum here! */ void SetPrintScaling( PdfName& inScalingType ); /** Set the document's Viewer Preferences: * Set the base URI of the document * * TODO: DS document value! */ void SetBaseURI( const std::string& inBaseURI ); /** Set the document's Viewer Preferences: * Set the language of the document */ void SetLanguage( const std::string& inLanguage ); /** Set the document's Viewer Preferences: */ void SetBindingDirection( PdfName& inDirection ); /** Checks if printing this document is allowed. * Every PDF consuming applications has to adhere this value! * * \returns true if you are allowed to print this document * * \see PdfEncrypt to set own document permissions. */ virtual bool IsPrintAllowed() const = 0; /** Checks if modifiying this document (besides annotations, form fields or changing pages) is allowed. * Every PDF consuming applications has to adhere this value! * * \returns true if you are allowed to modfiy this document * * \see PdfEncrypt to set own document permissions. */ virtual bool IsEditAllowed() const = 0; /** Checks if text and graphics extraction is allowed. * Every PDF consuming applications has to adhere this value! * * \returns true if you are allowed to extract text and graphics from this document * * \see PdfEncrypt to set own document permissions. */ virtual bool IsCopyAllowed() const = 0; /** Checks if it is allowed to add or modify annotations or form fields * Every PDF consuming applications has to adhere this value! * * \returns true if you are allowed to add or modify annotations or form fields * * \see PdfEncrypt to set own document permissions. */ virtual bool IsEditNotesAllowed() const = 0; /** Checks if it is allowed to fill in existing form or signature fields * Every PDF consuming applications has to adhere this value! * * \returns true if you are allowed to fill in existing form or signature fields * * \see PdfEncrypt to set own document permissions. */ virtual bool IsFillAndSignAllowed() const = 0; /** Checks if it is allowed to extract text and graphics to support users with disabillities * Every PDF consuming applications has to adhere this value! * * \returns true if you are allowed to extract text and graphics to support users with disabillities * * \see PdfEncrypt to set own document permissions. */ virtual bool IsAccessibilityAllowed() const = 0; /** Checks if it is allowed to insert, create, rotate, delete pages or add bookmarks * Every PDF consuming applications has to adhere this value! * * \returns true if you are allowed to insert, create, rotate, delete pages or add bookmarks * * \see PdfEncrypt to set own document permissions. */ virtual bool IsDocAssemblyAllowed() const = 0; /** Checks if it is allowed to print a high quality version of this document * Every PDF consuming applications has to adhere this value! * * \returns true if you are allowed to print a high quality version of this document * * \see PdfEncrypt to set own document permissions. */ virtual bool IsHighPrintAllowed() const = 0; // Peter Petrov 26 April 2008 /** Get access to the internal vector of objects * or root object. * * \returns the vector of objects */ inline PdfVecObjects* GetObjects(); // Peter Petrov 26 April 2008 /** Get access to the internal vector of objects * or root object. * * \returns the vector of objects */ inline const PdfVecObjects* GetObjects() const; /** * Set wrapper for the fontconfig library. * Useful to avoid initializing Fontconfig multiple times. * * This setter can be called until first use of Fontconfig * as the library is initialized at first use. */ inline void SetFontConfigWrapper(const PdfFontConfigWrapper & rFontConfig); protected: /** Construct a new (empty) PdfDocument * \param bEmtpy if true NO default objects (such as catalog) are created. */ PdfDocument( bool bEmpty = false ); /** Set the info object containing meta information. * Deletes any old info object. * * @param pInfo the new info object (will be owned by PdfDocument) */ void SetInfo( PdfInfo* pInfo ); /** Get access to the internal Catalog dictionary * or root object. * * \returns PdfObject the documents catalog */ inline PdfObject* GetCatalog(); /** Get access to the internal Catalog dictionary * or root object. * * \returns PdfObject the documents catalog */ inline const PdfObject* GetCatalog() const; /** Set the catalog of this PdfDocument * deleting the old one. * * @param pObject the new catalog object * It will be owned by PdfDocument. */ inline void SetCatalog( PdfObject* pObject ); /** Get access to the internal trailer dictionary * or root object. * * \returns PdfObject the documents catalog */ inline PdfObject* GetTrailer(); /** Get access to the internal trailer dictionary * or root object. * * \returns PdfObject the documents catalog */ inline const PdfObject* GetTrailer() const; /** Set the trailer of this PdfDocument * deleting the old one. * * @param pObject the new trailer object * It will be owned by PdfDocument. */ void SetTrailer( PdfObject* pObject ); /** Get a dictioary from the catalog dictionary by its name. * \param pszName will be converted into a PdfName * \returns the dictionary if it was found or NULL */ PdfObject* GetNamedObjectFromCatalog( const char* pszName ) const; /** Internal method for initializing the pages tree for this document */ void InitPagesTree(); /** Recursively changes every PdfReference in the PdfObject and in any child * that is either an PdfArray or a direct object. * The reference is changed so that difference is added to the object number * if the reference. * \param pObject object to change * \param difference add this value to every reference that is encountered */ void FixObjectReferences( PdfObject* pObject, int difference ); /** Low level APIs for setting a viewer preference * \param whichPref the dictionary key to set * \param valueObj the object to be set */ void SetViewerPreference( const PdfName& whichPref, const PdfObject & valueObj ); /** Low level APIs for setting a viewer preference * Convinience overload. * \param whichPref the dictionary key to set * \param inValue the object to be set */ void SetViewerPreference( const PdfName& whichPref, bool inValue ); /** Clear all internal variables * And reset PdfDocument to an intial state */ void Clear(); protected: PdfFontCache m_fontCache; PdfObject* m_pTrailer; PdfObject* m_pCatalog; PdfInfo* m_pInfo; PdfPagesTree* m_pPagesTree; PdfAcroForm* m_pAcroForms; private: // Prevent use of copy constructor and assignment operator. These methods // should never be referenced (given that code referencing them outside // PdfDocument won't compile), and calling them will result in a link error // as they're not defined. explicit PdfDocument(const PdfDocument&); PdfDocument& operator=(const PdfDocument&); PdfVecObjects m_vecObjects; PdfOutlines* m_pOutlines; PdfNamesTree* m_pNamesTree; EPdfVersion m_eVersion; }; // ----------------------------------------------------- // // ----------------------------------------------------- inline PdfPagesTree* PdfDocument::GetPagesTree() const { return m_pPagesTree; } // ----------------------------------------------------- // // ----------------------------------------------------- inline PdfObject* PdfDocument::GetCatalog() { return m_pCatalog; } // ----------------------------------------------------- // // ----------------------------------------------------- inline const PdfObject* PdfDocument::GetCatalog() const { return m_pCatalog; } // ----------------------------------------------------- // // ----------------------------------------------------- inline void PdfDocument::SetCatalog( PdfObject* pObject ) { m_pCatalog = pObject; // m_pCatalog does not need to // be reowned as it should // alread by part of m_vecObjects } // ----------------------------------------------------- // // ----------------------------------------------------- inline PdfObject* PdfDocument::GetTrailer() { return m_pTrailer; } // ----------------------------------------------------- // // ----------------------------------------------------- inline const PdfObject* PdfDocument::GetTrailer() const { return m_pTrailer; } // ----------------------------------------------------- // // ----------------------------------------------------- inline PdfVecObjects* PdfDocument::GetObjects() { return &m_vecObjects; } // ----------------------------------------------------- // // ----------------------------------------------------- inline const PdfVecObjects* PdfDocument::GetObjects() const { return &m_vecObjects; } // Peter Petrov 26 April 2008 // ----------------------------------------------------- // // ----------------------------------------------------- inline FT_Library PdfDocument::GetFontLibrary() const { return this->m_fontCache.GetFontLibrary(); } // ----------------------------------------------------- // // ----------------------------------------------------- inline void PdfDocument::SetFontConfigWrapper(const PdfFontConfigWrapper & rFontConfig) { m_fontCache.SetFontConfigWrapper(rFontConfig); } }; #endif // _PDF_DOCUMENT_H_ podofo-0.9.3/src/doc/PdfFontMetricsObject.h0000664000175000017500000002216212344436554020421 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2010 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_FONT_METRICS_OBJECT_H_ #define _PDF_FONT_METRICS_OBJECT_H_ #include "podofo/base/PdfDefines.h" #include "podofo/base/PdfArray.h" #include "podofo/base/PdfName.h" #include "podofo/base/PdfString.h" #include "PdfFontMetrics.h" namespace PoDoFo { class PdfArray; class PdfObject; class PdfVariant; class PODOFO_DOC_API PdfFontMetricsObject : public PdfFontMetrics { public: /** Create a font metrics object based on an existing PdfObject * * \param pObject an existing font descriptor object * \param pEncoding a PdfEncoding which will NOT be owned by PdfFontMetricsObject */ PdfFontMetricsObject( PdfObject* pFont, PdfObject* pDescriptor, const PdfEncoding* const pEncoding ); virtual ~PdfFontMetricsObject(); /** Create a width array for this font which is a required part * of every font dictionary. * \param var the final width array is written to this PdfVariant * \param nFirst first character to be in the array * \param nLast last character code to be in the array */ virtual void GetWidthArray( PdfVariant & var, unsigned int nFirst, unsigned int nLast ) const; /** Get the width of a single glyph id * * \returns the width of a single glyph id */ virtual double GetGlyphWidth( int nGlyphId ) const; /** Get the width of a single named glyph * * \param pszGlyphname name of the glyph * \returns the width of a single named glyph */ virtual double GetGlyphWidth( const char* pszGlyphname ) const; /** Create the bounding box array as required by the PDF reference * so that it can be written directly to a PDF file. * * \param array write the bounding box to this array. */ virtual void GetBoundingBox( PdfArray & array ) const; /** Retrieve the width of the given character in PDF units in the current font * \param c character * \returns the width in PDF units */ virtual double CharWidth( unsigned char c ) const; // Peter Petrov 20 March 2009 /** Retrieve the width of the given character in PDF units in the current font * \param c character * \returns the width in PDF units */ virtual double UnicodeCharWidth( unsigned short c ) const; /** Retrieve the line spacing for this font * \returns the linespacing in PDF units */ virtual double GetLineSpacing() const; /** Get the width of the underline for the current * font size in PDF units * \returns the thickness of the underline in PDF units */ virtual double GetUnderlineThickness() const; /** Return the position of the underline for the current font * size in PDF units * \returns the underline position in PDF units */ virtual double GetUnderlinePosition() const; /** Return the position of the strikeout for the current font * size in PDF units * \returns the underline position in PDF units */ virtual double GetStrikeOutPosition() const; /** Get the width of the strikeout for the current * font size in PDF units * \returns the thickness of the strikeout in PDF units */ virtual double GetStrikeoutThickness() const; /** Get a string with the postscript name of the font. * \returns the postscript name of the font or NULL string if no postscript name is available. */ virtual const char* GetFontname() const; /** Get the weight of this font. * Used to build the font dictionay * \returns the weight of this font (500 is normal). */ virtual unsigned int GetWeight() const; /** Get the ascent of this font in PDF * units for the current font size. * * \returns the ascender for this font * * \see GetPdfAscent */ virtual double GetAscent() const; /** Get the ascent of this font * Used to build the font dictionay * \returns the ascender for this font * * \see GetAscent */ virtual double GetPdfAscent() const; /** Get the descent of this font in PDF * units for the current font size. * This value is usually negative! * * \returns the descender for this font * * \see GetPdfDescent */ virtual double GetDescent() const; /** Get the descent of this font * Used to build the font dictionay * \returns the descender for this font * * \see GetDescent */ virtual double GetPdfDescent() const; /** Get the italic angle of this font. * Used to build the font dictionay * \returns the italic angle of this font. */ virtual int GetItalicAngle() const; /** Get the glyph id for a unicode character * in the current font. * * \param lUnicode the unicode character value * \returns the glyhph id for the character or 0 if the glyph was not found. */ virtual long GetGlyphId( long lUnicode ) const; /** Symbol fonts do need special treatment in a few cases. * Use this method to check if the current font is a symbol * font. Symbold fonts are detected by checking * if they use FT_ENCODING_MS_SYMBOL as internal encoding. * * \returns true if this is a symbol font */ virtual bool IsSymbol() const; /** Get a pointer to the actual font data - if it was loaded from memory. * \returns a binary buffer of data containing the font data */ virtual const char* GetFontData() const; /** Get the length of the actual font data - if it was loaded from memory. * \returns a the length of the font data */ virtual pdf_long GetFontDataLen() const; private: /** default constructor, not implemented */ PdfFontMetricsObject(void); /** copy constructor, not implemented */ PdfFontMetricsObject(const PdfFontMetricsObject& rhs); /** assignment operator, not implemented */ PdfFontMetricsObject& operator=(const PdfFontMetricsObject& rhs); //Private members: const PdfEncoding* const m_pEncoding; PdfName m_sName; PdfArray m_bbox; PdfArray m_matrix; PdfArray m_width; PdfObject *m_missingWidth; int m_nFirst; int m_nLast; unsigned int m_nWeight; int m_nItalicAngle; double m_dPdfAscent; double m_dPdfDescent; double m_dAscent; double m_dDescent; double m_dLineSpacing; double m_dUnderlineThickness; double m_dUnderlinePosition; double m_dStrikeOutThickness; double m_dStrikeOutPosition; bool m_bSymbol; ///< Internal member to singnal a symbol font double m_dDefWidth; ///< default width }; }; #endif // _PDF_FONT_METRICS_OBJECT_H_ podofo-0.9.3/src/doc/PdfTTFWriter.cpp0000664000175000017500000014506512344436402017222 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2007 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfTTFWriter.h" #include "PdfInputDevice.h" #include "PdfOutputDevice.h" #include "PdfRefCountedBuffer.h" #include "PdfString.h" #include "PdfDefinesPrivate.h" #include #include #include #include FT_FREETYPE_H #if defined(_MSC_VER) && _MSC_VER == 1500 // Ignore those warnings from MS-VS2008 #pragma warning(disable: 4018) #pragma warning(disable: 4244) #endif namespace { // MSVC++ does not provide the c99 exp2(..) and log2(..) in since they // are not required by C++ . Use the gcc ones if we're on gcc. #if defined(__GNUC__) inline double PdfLog2(double x) { return log2(x); } inline double PdfExp2(double x) { return exp2(x); } #else inline double PdfLog2(double x) { return log(x)/log(2.0f); } inline double PdfExp2(double x) { return pow(static_cast(2.0f),static_cast(x)); } #endif } namespace PoDoFo { extern bool podofo_is_little_endian(); #define READ_TTF_USHORT( value ) { pDevice->Read( reinterpret_cast(&(value)), sizeof(pdf_ttf_ushort) ); \ if( podofo_is_little_endian() ) \ this->SwapUShort( &(value) ); } #define READ_TTF_SHORT( value ) { pDevice->Read( reinterpret_cast(&(value)), sizeof(pdf_ttf_short) ); \ if( podofo_is_little_endian() ) \ this->SwapShort( &(value) ); } #define READ_TTF_ULONG( value ) { pDevice->Read( reinterpret_cast(&(value)), sizeof(pdf_ttf_ulong) ); \ if( podofo_is_little_endian() ) \ this->SwapULong( &(value) ); } #define WRITE_TTF_USHORT( value ) { { if( podofo_is_little_endian() ) \ this->SwapUShort( &(value) ); } \ pDevice->Write( reinterpret_cast(&(value)), sizeof(pdf_ttf_ushort) ); } #define WRITE_TTF_SHORT( value ) { { if( podofo_is_little_endian() ) \ this->SwapShort( &(value) ); } \ pDevice->Write( reinterpret_cast(&(value)), sizeof(pdf_ttf_short) ); } #define WRITE_TTF_ULONG( value ) { { if( podofo_is_little_endian() ) \ this->SwapULong( &(value) ); } \ pDevice->Write( reinterpret_cast(&(value)), sizeof(pdf_ttf_ulong) ); } namespace NonPublic { /** * The TTF format. * * - Big endian * * - Required tables: * cmap character to glyph mapping CHK * glyf glyph data CHK * head font header CHK * hhea horizontal header CHK * hmtx horizontal metrics CHK * loca index to location CHK * maxp maximum profile CHK * name naming table CHK * post PostScript information * OS/2 OS/2 and Windows specific metrics CHK * */ PdfTTFWriter::PdfTTFWriter() : m_lGlyphDataOffset( -1L ), m_lCMapOffset( -1L ), m_pRefBuffer( NULL ) { m_vecGlyphIndeces.push_back( static_cast('H') ); m_vecGlyphIndeces.push_back( static_cast('a') ); m_vecGlyphIndeces.push_back( static_cast('l') ); m_vecGlyphIndeces.push_back( static_cast('o') ); m_vecGlyphIndeces.push_back( static_cast(' ') ); m_vecGlyphIndeces.push_back( static_cast('W') ); m_vecGlyphIndeces.push_back( static_cast('r') ); m_vecGlyphIndeces.push_back( static_cast('d') ); m_vecGlyphIndeces.push_back( static_cast('!') ); // Composites do not work yet: m_vecGlyphIndeces.push_back( 0x00E4 ); // A dieresis std::sort( m_vecGlyphIndeces.begin(), m_vecGlyphIndeces.end() ); } PdfTTFWriter::PdfTTFWriter( const std::vector & rvecGlyphs ) : m_lGlyphDataOffset( -1L ), m_lCMapOffset( -1L ), m_pRefBuffer( NULL ) { m_vecGlyphIndeces = rvecGlyphs; std::sort( m_vecGlyphIndeces.begin(), m_vecGlyphIndeces.end() ); } PdfTTFWriter::~PdfTTFWriter() { delete m_pRefBuffer; } void PdfTTFWriter::Read( PdfInputDevice* pDevice ) { long lHead = -1; long lHHea = -1; long lLoca = -1; long lMaxp = -1; long lOs2 = -1; long lHmtx = -1; long lPost = -1; // Read the table directory this->ReadTableDirectory( pDevice ); // read the table of contents TVecTableDirectoryEntries vecTables; TTableDirectoryEntry entry; vecTables.reserve( m_tTableDirectory.numTables ); for( int i=0;iReadTableDirectoryEntry( pDevice, &entry ); if( entry.tag == this->CreateTag( 'l', 'o', 'c', 'a' ) ) lLoca = entry.offset; else if( entry.tag == this->CreateTag( 'g', 'l', 'y', 'f' ) ) m_lGlyphDataOffset = entry.offset; else if( entry.tag == this->CreateTag( 'm', 'a', 'x', 'p' ) ) lMaxp = entry.offset; else if( entry.tag == this->CreateTag( 'h', 'e', 'a', 'd' ) ) lHead = entry.offset; else if( entry.tag == this->CreateTag( 'c', 'm', 'a', 'p' ) ) m_lCMapOffset = entry.offset; else if( entry.tag == this->CreateTag( 'h', 'h', 'e', 'a' ) ) lHHea = entry.offset; else if( entry.tag == this->CreateTag( 'O', 'S', '/', '2' ) ) lOs2 = entry.offset; else if( entry.tag == this->CreateTag( 'h', 'm', 't', 'x' ) ) lHmtx = entry.offset; else if( entry.tag == this->CreateTag( 'p', 'o', 's', 't' ) ) lPost = entry.offset; vecTables.push_back( entry ); } // check if all required tables have been found if( lLoca == -1 ) { PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidFontFile, "Table 'loca' not found." ); } else if( m_lGlyphDataOffset == -1 ) { PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidFontFile, "Table 'glyf' not found." ); } else if( lMaxp == -1 ) { PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidFontFile, "Table 'maxp' not found." ); } else if( lHead == -1 ) { PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidFontFile, "Table 'head' not found." ); } else if( m_lCMapOffset == -1 ) { PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidFontFile, "Table 'cmap' not found." ); } else if( lHHea == -1 ) { PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidFontFile, "Table 'hhea' not found." ); } else if( lOs2 == -1 ) { PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidFontFile, "Table 'OS/2' not found." ); } else if( lHmtx == -1 ) { PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidFontFile, "Table 'hmtx' not found." ); } else if( lPost == -1 ) { PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidFontFile, "Table 'post' not found." ); } // Read head table pDevice->Seek( lHead ); this->ReadHeadTable( pDevice ); // Read maxp table pDevice->Seek( lMaxp ); this->ReadMaxpTable( pDevice ); // Read loca table pDevice->Seek( lLoca ); this->ReadLocaTable( pDevice ); // Read hhea table pDevice->Seek( lHHea ); this->ReadHHeaTable( pDevice ); // Read cmap table pDevice->Seek( m_lCMapOffset ); this->ReadCmapTable( pDevice ); // Read glyf table pDevice->Seek( m_lGlyphDataOffset ); this->ReadGlyfTable( pDevice ); // Read OS/2 table pDevice->Seek( lOs2 ); this->ReadOs2Table( pDevice ); // Read hmtx table pDevice->Seek( lHmtx ); this->ReadHmtxTable( pDevice ); // Read post table pDevice->Seek( lPost ); this->ReadPostTable( pDevice ); // read the remaining data tables TIVecTableDirectoryEntries it = vecTables.begin(); while( it != vecTables.end() ) { // skip the 4 tables we have alread read if( (*it).tag != this->CreateTag( 'g', 'l', 'y', 'f' ) && (*it).tag != this->CreateTag( 'h', 'e', 'a', 'd' ) && (*it).tag != this->CreateTag( 'l', 'o', 'c', 'a' ) && (*it).tag != this->CreateTag( 'm', 'a', 'x', 'p' ) && (*it).tag != this->CreateTag( 'h', 'h', 'e', 'a' ) && (*it).tag != this->CreateTag( 'c', 'm', 'a', 'p' ) && (*it).tag != this->CreateTag( 'O', 'S', '/', '2' ) && (*it).tag != this->CreateTag( 'n', 'a', 'm', 'e' ) ) { TTable table; table.tag = (*it).tag; table.length = (*it).length; table.data = static_cast(malloc( sizeof(char) * (*it).length )); pDevice->Seek( (*it).offset ); pDevice->Read( table.data, (*it).length ); m_vecTableData.push_back( table ); } ++it; } } void PdfTTFWriter::ReadTableDirectory( PdfInputDevice* pDevice ) { pDevice->Read( reinterpret_cast(&m_tTableDirectory), sizeof(TTableDirectory) ); if( podofo_is_little_endian() ) { // Swap bytes SwapUShort( &m_tTableDirectory.numTables ); SwapUShort( &m_tTableDirectory.searchRange ); SwapUShort( &m_tTableDirectory.entrySelector ); SwapUShort( &m_tTableDirectory.rangeShift ); } } void PdfTTFWriter::WriteTableDirectory( PdfOutputDevice* pDevice ) { if( podofo_is_little_endian() ) { // Swap bytes SwapUShort( &m_tTableDirectory.numTables ); SwapUShort( &m_tTableDirectory.searchRange ); SwapUShort( &m_tTableDirectory.entrySelector ); SwapUShort( &m_tTableDirectory.rangeShift ); } pDevice->Write( reinterpret_cast(&m_tTableDirectory), sizeof(TTableDirectory) ); } void PdfTTFWriter::ReadTableDirectoryEntry( PdfInputDevice* pDevice, TTableDirectoryEntry* pEntry ) { pDevice->Read( reinterpret_cast(pEntry), sizeof(TTableDirectoryEntry) ); if( podofo_is_little_endian() ) { SwapULong( &pEntry->tag ); SwapULong( &pEntry->checkSum ); SwapULong( &pEntry->offset ); SwapULong( &pEntry->length ); } /* printf(" : Got table: %c%c%c%c length=%u\n", (pEntry->tag >> 24) & 0xff, (pEntry->tag >> 16) & 0xff, (pEntry->tag >> 8) & 0xff, (pEntry->tag ) & 0xff, pEntry->length ); */ } void PdfTTFWriter::ReadOs2Table( PdfInputDevice* pDevice ) { pDevice->Read( reinterpret_cast(&m_tOs2), sizeof(TOs2) ); if( podofo_is_little_endian() ) SwapOs2Table(); } void PdfTTFWriter::ReadHmtxTable( PdfInputDevice* pDevice ) { // read numOfHMetrics long values TLongHorMetric longValue; int n = m_tHHea.numberOfHMetrics; while( n-- ) { READ_TTF_USHORT( longValue.advanceWidth ); READ_TTF_SHORT ( longValue.leftSideBearing ); m_vecHmtx.push_back( longValue ); } // read numGlyphs - numOfHMetrics short values n = m_tHHea.numberOfHMetrics - m_tMaxp.numGlyphs; while( n-- ) { // advanceWidth stays the same as in the last read long value READ_TTF_SHORT ( longValue.leftSideBearing ); m_vecHmtx.push_back( longValue ); } } void PdfTTFWriter::SwapOs2Table() { SwapUShort ( &m_tOs2.version ); SwapShort ( &m_tOs2.xAvgCharWidth ); SwapUShort ( &m_tOs2.usWeightClass ); SwapUShort ( &m_tOs2.usWidthClass ); SwapShort ( &m_tOs2.fsType ); SwapShort ( &m_tOs2.ySubscriptXSize ); SwapShort ( &m_tOs2.ySubscriptYSize ); SwapShort ( &m_tOs2.ySubscriptXOffset ); SwapShort ( &m_tOs2.ySubscriptYOffset ); SwapShort ( &m_tOs2.ySuperscriptXSize ); SwapShort ( &m_tOs2.ySuperscriptYSize ); SwapShort ( &m_tOs2.ySuperscriptXOffset ); SwapShort ( &m_tOs2.ySuperscriptYOffset ); SwapShort ( &m_tOs2.yStrikeoutSize ); SwapShort ( &m_tOs2.yStrikeoutPosition ); SwapShort ( &m_tOs2.sFamilyClass ); SwapULong ( &m_tOs2.ulUnicodeRange1 ); SwapULong ( &m_tOs2.ulUnicodeRange2 ); SwapULong ( &m_tOs2.ulUnicodeRange3 ); SwapULong ( &m_tOs2.ulUnicodeRange4 ); SwapUShort ( &m_tOs2.fsSelection ); SwapUShort ( &m_tOs2.usFirstCharIndex ); SwapUShort ( &m_tOs2.usLastCharIndex ); SwapUShort ( &m_tOs2.sTypoAscender ); SwapUShort ( &m_tOs2.sTypoDescender ); SwapUShort ( &m_tOs2.sTypoLineGap ); SwapUShort ( &m_tOs2.usWinAscent ); SwapUShort ( &m_tOs2.usWinDescent ); SwapULong ( &m_tOs2.ulCodePageRange1 ); SwapULong ( &m_tOs2.ulCodePageRange2 ); } void PdfTTFWriter::ReadHeadTable( PdfInputDevice* pDevice ) { pDevice->Read( reinterpret_cast(&m_tHead), sizeof(THead) ); if( podofo_is_little_endian() ) SwapHeadTable(); } void PdfTTFWriter::SwapHeadTable() { // Swap bytes SwapULong ( &m_tHead.checkSumAdjustment ); SwapULong ( &m_tHead.magicNumber ); SwapUShort( &m_tHead.flags ); SwapUShort( &m_tHead.unitsPerEm ); SwapShort ( &m_tHead.fontDirectionHint ); SwapShort ( &m_tHead.indexToLocForm ); SwapShort ( &m_tHead.glyphDataFormat ); // Do not care for other values } void PdfTTFWriter::ReadMaxpTable( PdfInputDevice* pDevice ) { pDevice->Read( reinterpret_cast(&m_tMaxp), sizeof(TMaxP) ); if( podofo_is_little_endian() ) SwapMaxpTable(); } void PdfTTFWriter::SwapMaxpTable() { SwapUShort( &m_tMaxp.numGlyphs ); SwapUShort( &m_tMaxp.maxPoints ); SwapUShort( &m_tMaxp.maxContours ); SwapUShort( &m_tMaxp.maxCompositePoints ); SwapUShort( &m_tMaxp.maxCompositeContours ); SwapUShort( &m_tMaxp.maxZones ); SwapUShort( &m_tMaxp.maxTwilightPoints ); SwapUShort( &m_tMaxp.maxStorage ); SwapUShort( &m_tMaxp.maxFunctionsDefs ); SwapUShort( &m_tMaxp.maxInstructionDefs ); SwapUShort( &m_tMaxp.maxStackElements ); SwapUShort( &m_tMaxp.maxSizeOfInstruction ); SwapUShort( &m_tMaxp.maxComponentElements ); SwapUShort( &m_tMaxp.maxComponentDepth ); } void PdfTTFWriter::ReadHHeaTable( PdfInputDevice* pDevice ) { pDevice->Read( reinterpret_cast(&m_tHHea), sizeof(THHea) ); if( podofo_is_little_endian() ) SwapHHeaTable(); } void PdfTTFWriter::SwapHHeaTable() { SwapFWord ( &m_tHHea.advanceWidthMax ); SwapFWord ( &m_tHHea.minLeftSideBearing ); SwapFWord ( &m_tHHea.minRightSideBearing ); SwapFWord ( &m_tHHea.xMaxExtent ); SwapUShort ( &m_tHHea.numberOfHMetrics ); } void PdfTTFWriter::ReadPostTable( PdfInputDevice* pDevice ) { pDevice->Read( reinterpret_cast(&m_tPost), sizeof(TPost) ); if( podofo_is_little_endian() ) SwapPostTable(); } void PdfTTFWriter::SwapPostTable() { /* pdf_ttf_fixed format; pdf_ttf_fixed italicAngle; pdf_ttf_fword underlinePosition; pdf_ttf_fword underlineThickness; pdf_ttf_ulong isFixedPitch; pdf_ttf_ulong minMemType42; pdf_ttf_ulong maxMemType42; pdf_ttf_ulong minMemType1; pdf_ttf_ulong maxMemType1; */ } void PdfTTFWriter::ReadLocaTable( PdfInputDevice* pDevice ) { int n = m_tMaxp.numGlyphs + 1; pdf_ttf_ulong lValue; if( m_tHead.indexToLocForm == 0 ) { // short offsets pdf_ttf_ushort value; while( n-- ) { pDevice->Read( reinterpret_cast(&value), sizeof(pdf_ttf_ushort) ); this->SwapUShort( &value ); lValue = value; m_tLoca.push_back( lValue ); } } else if( m_tHead.indexToLocForm == 1 ) { // long offsets while( n-- ) { pDevice->Read( reinterpret_cast(&lValue), sizeof(pdf_ttf_ulong) ); this->SwapULong( &lValue ); m_tLoca.push_back( lValue ); } } else { PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidFontFile, "Format of loca table not recognized." ); } } void PdfTTFWriter::ReadCmapTable( PdfInputDevice* pDevice ) { TCMapEntry entry; int nUnicodeIndex = -1; pdf_ttf_ushort tableVersion; pdf_ttf_ushort numberOfTables; std::vector cmap; READ_TTF_USHORT( tableVersion ); READ_TTF_USHORT( numberOfTables ); while( numberOfTables-- ) { READ_TTF_USHORT( entry.platformId ); READ_TTF_USHORT( entry.encodingId ); READ_TTF_ULONG ( entry.offset ); //printf("Got cmap table: %u %u at %u\n",entry.platformId, entry.encodingId, entry.offset ); cmap.push_back( entry ); if( entry.platformId == 3 && entry.encodingId == 1 ) nUnicodeIndex = cmap.size() - 1; } if( nUnicodeIndex == -1 ) { PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidFontFile, "No unicode cmap table found." ); // TODO: Use other tables to build a unicode table. } m_lCMapOffset += cmap[nUnicodeIndex].offset; // Reset current cmap offset to actual cmap offset pDevice->Seek( m_lCMapOffset ); READ_TTF_USHORT( format4.format ); READ_TTF_USHORT( format4.length ); READ_TTF_USHORT( format4.version ); READ_TTF_USHORT( format4.segCountX2 ); READ_TTF_USHORT( format4.searchRange ); READ_TTF_USHORT( format4.entrySelector ); READ_TTF_USHORT( format4.rangeShift ); /* printf("Format: %i\n", format4.format ); printf("Length: %i\n", format4.length ); printf("SegCountX2: %i\n", format4.segCountX2 ); printf("Range Shift: %i\n", format4.rangeShift ); * */ int i; const int nSegCount = format4.segCountX2 >> 1; pdf_ttf_ushort nReservedPad; m_ranges.resize( nSegCount ); for( i=0;iTell(); READ_TTF_USHORT( m_ranges[i].nOffset ); /* if( m_ranges[i].nOffset ) { printf("BEFORE=%i\n", m_ranges[i].nOffset ); m_ranges[i].nOffset -= ((nSegCount - i) * 2); printf("AFTER =%i\n", static_cast(m_ranges[i].nOffset) ); } */ #if 0 if( m_ranges[i].nOffset ) { if( m_ranges[i].nStart == 160 ) { /* if(theLowByte >= firstCode && theLowByte < (firstCode + Int16FromMOTA(subHeader2s[k].entryCount))) { return *((&(subHeader2s[0].idRangeOffset)) + (Int16FromMOTA(subHeader2s[0].idRangeOffset)/2) + theLowByte - Int16FromMOTA(subHeader2s[0].firstCode) ); */ int c = 228; printf("OFFSET1 = %i\n", m_ranges[i].nOffset ); printf("OFFSET2 = %i\n", (c - m_ranges[i].nStart) ); printf("POS = %i\n", lPos ); //long lAddress = (m_ranges[i].nOffset/2 + (c - m_ranges[i].nStart) + lPos ); long lAddress = lPos + m_ranges[i].nOffset/2 + (c - m_ranges[i].nStart); printf("GOT ADDRESS: %x\n", lAddress - m_lCMapOffset ); pDevice->Seek( lAddress ); pdf_ttf_ushort u; READ_TTF_USHORT( u ); printf("Index=%u\n", u ); pDevice->Seek( lPos + sizeof(pdf_ttf_ushort) ); } } #endif // 0 } m_lCMapOffset = (pDevice->Tell() - m_lCMapOffset); long lGlyphIdArrayLen = (format4.length - m_lCMapOffset) / sizeof(pdf_ttf_ushort); pdf_ttf_ushort glyphId; m_vecGlyphIds.reserve( lGlyphIdArrayLen ); while( lGlyphIdArrayLen-- ) { READ_TTF_USHORT( glyphId ); m_vecGlyphIds.push_back( glyphId ); } // in case of broken TTF we have to sort this table std::sort( m_ranges.begin(), m_ranges.end() ); /* for( i=0;inumberOfContours ); SwapFWord ( &pHeader->xMin ); SwapFWord ( &pHeader->yMin ); SwapFWord ( &pHeader->xMax ); SwapFWord ( &pHeader->yMax ); } #define ARG_1_AND_2_ARE_WORDS 0x0001 #define ARGS_ARE_XY_VALUES 0x0002 #define ROUND_XY_TO_GRID 0x0004 #define WE_HAVE_A_SCALE 0x0008 #define RESERVED 0x0010 #define MORE_COMPONENTS 0x0020 #define WE_HAVE_AN_X_AND_Y_SCALE 0x0040 #define WE_HAVE_A_TWO_BY_TWO 0x0080 #define WE_HAVE_INSTRUCTIONS 0x0100 #define USE_MY_METRICS 0x0200 void PdfTTFWriter::ReadGlyfTable( PdfInputDevice* pDevice ) { std::vector::const_iterator it = m_vecGlyphIndeces.begin(); long lOffset; long lLength; while( it != m_vecGlyphIndeces.end() ) { lOffset = this->GetGlyphDataLocation( *it, &lLength, pDevice ); if( lOffset != -1 ) { PdfRefCountedBuffer buffer( lLength ); pDevice->Seek( lOffset ); pDevice->Read( buffer.GetBuffer(), lLength ); PdfTTFGlyph glyph( *it ); glyph.m_buffer = buffer; m_vecGlyphs.push_back( glyph ); //this->LoadGlyph( *it, lOffset, pDevice ); } else { PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidFontFile, "Charnotfound" ); } ++it; } } void PdfTTFWriter::LoadGlyph( int nIndex, long lOffset, PdfInputDevice* pDevice ) { printf("!!!! Loading glyph %i\n", nIndex ); PdfTTFGlyph glyph( nIndex ); pDevice->Seek( lOffset ); pDevice->Read( reinterpret_cast(&glyph.m_tHeader), sizeof(TGlyphHeader) ); if( podofo_is_little_endian() ) SwapGlyfHeader( &glyph.m_tHeader ); glyph.SetComposite( glyph.m_tHeader.numberOfContours == -1 ); printf("Glyph with index %i is %s. (contours) = %i\n", nIndex, glyph.IsComposite() ? "composite" : "simple", glyph.m_tHeader.numberOfContours ); if( !glyph.IsComposite() ) { // Read the end points int nContours = glyph.m_tHeader.numberOfContours; pdf_ttf_ushort nEndPoint; glyph.vecEndPoints.reserve( nContours ); while( nContours-- ) { READ_TTF_USHORT( nEndPoint ); printf("Reading endpoint: %i\n", nEndPoint ); glyph.vecEndPoints.push_back( nEndPoint ); } // read instructions pDevice->Read( reinterpret_cast(&glyph.m_nInstructionLength), sizeof(pdf_ttf_ushort) ); if( podofo_is_little_endian() ) SwapUShort( &glyph.m_nInstructionLength ); printf("Reading instructions: %i\n", glyph.m_nInstructionLength ); if( glyph.m_nInstructionLength ) { glyph.m_pInstructions = static_cast(malloc( glyph.m_nInstructionLength * sizeof(char) )); if( !glyph.m_pInstructions ) { PODOFO_RAISE_ERROR( ePdfError_OutOfMemory ); } pDevice->Read( glyph.m_pInstructions, glyph.m_nInstructionLength ); } unsigned char flag; unsigned char repeat; int nPoints = glyph.vecEndPoints.back(); // read flags printf("Reading flags: %i\n", nPoints ); while( --nPoints >= 0 ) { pDevice->Read( reinterpret_cast(&flag), sizeof(char) ); glyph.vecFlagsOrig.push_back( flag ); if( (flag & 0x08) == 0x08 ) // i.e. the next byte tells us how often this flag is to be repeated { pDevice->Read( reinterpret_cast(&repeat), sizeof(char) ); glyph.vecFlagsOrig.push_back( repeat ); /* while( repeat-- ) glyph.vecFlags.push_back( flag ); */ } }; printf("!!!XXXXXXX\n"); ReadSimpleGlyfCoordinates( pDevice, glyph.vecFlags, glyph.vecXCoordinates, 0x02, 0x10 ); printf("!!!YYYYYYY\n"); ReadSimpleGlyfCoordinates( pDevice, glyph.vecFlags, glyph.vecYCoordinates, 0x04, 0x20 ); /* for( int z=0;zRead( reinterpret_cast(&flags), sizeof(pdf_ttf_ushort) ); pDevice->Read( reinterpret_cast(&glyphIndex), sizeof(pdf_ttf_ushort) ); if( podofo_is_little_endian() ) { this->SwapUShort( &flags ); this->SwapUShort( &glyphIndex ); } printf("glyphIndex=%i and should be %i\n", glyphIndex, nIndex ); if( glyphIndex != nIndex ) { PODOFO_RAISE_ERROR( ePdfError_InvalidFontFile ); } if( flags & ARG_1_AND_2_ARE_WORDS ) { pDevice->Read( reinterpret_cast(&glyph.arg1), sizeof(pdf_ttf_short) ); pDevice->Read( reinterpret_cast(&glyph.arg2), sizeof(pdf_ttf_short) ); if( podofo_is_little_endian() ) { this->SwapShort( &glyph.arg1 ); this->SwapShort( &glyph.arg2 ); } } else { char cArg1; char cArg2; pDevice->Read( &cArg1, sizeof(char) ); pDevice->Read( &cArg2, sizeof(char) ); glyph.arg1 = cArg1; glyph.arg2 = cArg2; } // glyph.xx = glyph.yy = 0x10000L; glyph.xx = glyph.yy = 0x00; if ( flags & WE_HAVE_A_SCALE ) { //F2Dot14 scale; /* Format 2.14 */ pDevice->Read( reinterpret_cast(&glyph.xx), sizeof(pdf_ttf_short) ); if( podofo_is_little_endian() ) this->SwapShort( &glyph.xx ); glyph.yy = glyph.xx; } else if ( flags & WE_HAVE_AN_X_AND_Y_SCALE ) { //F2Dot14 xscale; /* Format 2.14 */ //F2Dot14 yscale; /* Format 2.14 */ pDevice->Read( reinterpret_cast(&glyph.xx), sizeof(pdf_ttf_short) ); pDevice->Read( reinterpret_cast(&glyph.yy), sizeof(pdf_ttf_short) ); if( podofo_is_little_endian() ) { this->SwapShort( &glyph.xx ); this->SwapShort( &glyph.yy ); } } else if ( flags & WE_HAVE_A_TWO_BY_TWO ) { pDevice->Read( reinterpret_cast(&glyph.xx), sizeof(pdf_ttf_short) ); pDevice->Read( reinterpret_cast(&glyph.yx), sizeof(pdf_ttf_short) ); pDevice->Read( reinterpret_cast(&glyph.yy), sizeof(pdf_ttf_short) ); pDevice->Read( reinterpret_cast(&glyph.xy), sizeof(pdf_ttf_short) ); if( podofo_is_little_endian() ) { this->SwapShort( &glyph.xx ); this->SwapShort( &glyph.yx ); this->SwapShort( &glyph.yy ); this->SwapShort( &glyph.xy ); } //F2Dot14 xscale; /* Format 2.14 */ //F2Dot14 scale01; /* Format 2.14 */ //F2Dot14 scale10; /* Format 2.14 */ //F2Dot14 yscale; /* Format 2.14 */ } } while( flags & MORE_COMPONENTS ); if( flags & WE_HAVE_INSTRUCTIONS ) { pDevice->Read( reinterpret_cast(&glyph.m_nInstructionLength), sizeof(pdf_ttf_ushort) ); if( podofo_is_little_endian() ) this->SwapUShort( &glyph.m_nInstructionLength ); if( glyph.m_nInstructionLength ) { glyph.m_pInstructions = static_cast(malloc( glyph.m_nInstructionLength * sizeof(char) )); if( !glyph.m_pInstructions ) { PODOFO_RAISE_ERROR( ePdfError_OutOfMemory ); } pDevice->Read( glyph.m_pInstructions, glyph.m_nInstructionLength ); } } } m_vecGlyphs.push_back( glyph ); } void PdfTTFWriter::Subset() { } // ----------------------------------------------------- // Writing out a TTF file from memory // ----------------------------------------------------- void PdfTTFWriter::Write( PdfOutputDevice* pDevice ) { m_tTableDirectory.numTables = 9; // DS TMP TTableDirectoryEntry entry; TVecTableDirectoryEntries vecToc; const long lTableOffset = sizeof(TTableDirectory); const long lNumTables = m_tTableDirectory.numTables; this->WriteTableDirectory( pDevice ); // write dummy table of contents memset( &entry, 0, sizeof(TTableDirectoryEntry) ); for( unsigned int i=0; i(lNumTables); i++ ) pDevice->Write( reinterpret_cast(&entry), sizeof(TTableDirectoryEntry) ); // write contents this->WriteTable( pDevice, vecToc, this->CreateTag( 'm', 'a', 'x', 'p' ), &PdfTTFWriter::WriteMaxpTable ); this->WriteTable( pDevice, vecToc, this->CreateTag( 'h', 'e', 'a', 'd' ), &PdfTTFWriter::WriteHeadTable ); this->WriteTable( pDevice, vecToc, this->CreateTag( 'g', 'l', 'y', 'f' ), &PdfTTFWriter::WriteGlyfTable ); this->WriteTable( pDevice, vecToc, this->CreateTag( 'c', 'm', 'a', 'p' ), &PdfTTFWriter::WriteCMapTable ); this->WriteTable( pDevice, vecToc, this->CreateTag( 'l', 'o', 'c', 'a' ), &PdfTTFWriter::WriteLocaTable ); this->WriteTable( pDevice, vecToc, this->CreateTag( 'h', 'h', 'e', 'a' ), &PdfTTFWriter::WriteHHeaTable ); this->WriteTable( pDevice, vecToc, this->CreateTag( 'O', 'S', '/', '2' ), &PdfTTFWriter::WriteOs2Table ); this->WriteTable( pDevice, vecToc, this->CreateTag( 'n', 'a', 'm', 'e' ), &PdfTTFWriter::WriteNameTable ); this->WriteTable( pDevice, vecToc, this->CreateTag( 'h', 'm', 't', 'x' ), &PdfTTFWriter::WriteHmtxTable ); this->WriteTable( pDevice, vecToc, this->CreateTag( 'p', 'o', 's', 't' ), &PdfTTFWriter::WritePostTable ); /* TCIVecTable it = m_vecTableData.begin(); while( it != m_vecTableData.end() ) { TTableDirectoryEntry entry; entry.tag = (*it).tag; entry.checkSum = this->CalculateChecksum( reinterpret_cast(&(*it).data), (*it).length ); entry.offset = pDevice->GetLength(); entry.length = (*it).length; vecToc.push_back( entry ); pDevice->Write( (*it).data, (*it).length ); free( (*it).data ); ++it; } */ // write actual table of contents pDevice->Seek( lTableOffset ); TIVecTableDirectoryEntries itToc = vecToc.begin(); while( itToc != vecToc.end() ) { this->WriteTableDirectoryEntry( pDevice, &(*itToc) ); ++itToc; } } void PdfTTFWriter::WriteTableDirectoryEntry( PdfOutputDevice* pDevice, TTableDirectoryEntry* pEntry ) { if( podofo_is_little_endian() ) { SwapULong( &pEntry->tag ); SwapULong( &pEntry->checkSum ); SwapULong( &pEntry->offset ); SwapULong( &pEntry->length ); } pDevice->Write( reinterpret_cast(pEntry), sizeof(TTableDirectoryEntry) ); } void PdfTTFWriter::WriteGlyfTable( PdfOutputDevice* pDevice ) { TIVecGlyphs it = m_vecGlyphs.begin(); int nPosition = 0; while( it != m_vecGlyphs.end() ) { // set the position of the glyph so that a cmap can be generated (*it).SetPosition( nPosition++ ); pDevice->Write( (*it).m_buffer.GetBuffer(), (*it).m_buffer.GetSize() ); // add value to new loca table so that it can be created correctly m_vecLoca.push_back( pDevice->Tell() ); #if 0 if( podofo_is_little_endian() ) SwapGlyfHeader( &(*it).m_tHeader ); pDevice->Write( reinterpret_cast(&(*it).m_tHeader), sizeof(TGlyphHeader) ); if( (*it).IsComposite() ) { // TODO: Write a composite glyph } else { // Write a simple glyph std::vector::iterator itEndPoints = (*it).vecEndPoints.begin(); while( itEndPoints != (*it).vecEndPoints.end() ) { WRITE_TTF_USHORT( *itEndPoints ); ++itEndPoints; } pdf_ttf_ushort nLength = (*it).GetInstrunctionLength(); WRITE_TTF_USHORT( nLength ); pDevice->Write( (*it).GetInstrunctions(), (*it).GetInstrunctionLength() ); printf("?????= Glyph flags size=%i\n", (*it).vecFlagsOrig.size() ); pDevice->Write( reinterpret_cast(&(*it).vecFlagsOrig[0]), sizeof(char) * (*it).vecFlagsOrig.size() ); WriteSimpleGlyfCoordinates( pDevice, (*it).vecFlags, (*it).vecXCoordinates, 0x02, 0x10 ); WriteSimpleGlyfCoordinates( pDevice, (*it).vecFlags, (*it).vecYCoordinates, 0x04, 0x20 ); } #endif // 0 ++it; } // add an additional entry to loca so that the length of the last character can be determined m_vecLoca.push_back( pDevice->Tell() ); } void PdfTTFWriter::WriteCMapTable( PdfOutputDevice* pDevice ) { pdf_ttf_ushort nValue = 0; pdf_ttf_ulong lValue = 12; WRITE_TTF_USHORT( nValue ); // table version nValue = 1; WRITE_TTF_USHORT( nValue ); // number of tables nValue = 3; WRITE_TTF_USHORT( nValue ); // platform id (microsoft) nValue = 1; WRITE_TTF_USHORT( nValue ); // encoding id (unicode) WRITE_TTF_ULONG ( lValue ); // offset // create a cmap table in ram std::vector vecRanges; TCMapRange current; TCIVecGlyphs it = m_vecGlyphs.begin(); bool bReset = true; while( it != m_vecGlyphs.end() ) { if( bReset ) { if( it != m_vecGlyphs.begin() ) vecRanges.push_back( current ); current.nStart = (*it).GetIndex(); current.nEnd = (*it).GetIndex(); current.nDelta = -((*it).GetIndex() - (*it).GetPosition()); current.nOffset = 0; bReset = false; ++it; } else { if( (*it).GetIndex() == current.nEnd + 1 ) { current.nEnd++; ++it; } else bReset = true; } } if( !bReset ) vecRanges.push_back( current ); // create the ending section current.nStart = 0xFFFF; current.nEnd = 0xFFFF; current.nDelta = 0; current.nOffset = 0; vecRanges.push_back( current ); int i; double dSearchRange = 2.0 * ( PdfExp2( floor( PdfLog2( vecRanges.size() ) ) ) ); pdf_ttf_ushort nSearchRange = static_cast(dSearchRange); // write the actual cmap table nValue = 4; WRITE_TTF_USHORT( nValue ); // format nValue = vecRanges.size() * sizeof(pdf_ttf_ushort) * 4 + 16; // 4 parallel array per segment + 16 bytes of header WRITE_TTF_USHORT( nValue ); // length nValue = 0; WRITE_TTF_USHORT( nValue ); // version nValue = vecRanges.size() * 2; WRITE_TTF_USHORT( nValue ); // seg count * 2 nValue = nSearchRange; WRITE_TTF_USHORT( nValue ); // search range nValue = static_cast(PdfLog2( vecRanges.size() >> 1 )); WRITE_TTF_USHORT( nValue ); // entry selector nValue = 2 * vecRanges.size() - nSearchRange; WRITE_TTF_USHORT( nValue ); // range shift for( i=0;i(vecRanges.size());i++ ) { WRITE_TTF_USHORT( vecRanges[i].nEnd ); } nValue = 0; WRITE_TTF_USHORT( nValue ); // reserve pad for( i=0;i(vecRanges.size());i++ ) { WRITE_TTF_USHORT( vecRanges[i].nStart ); } for( i=0;i(vecRanges.size());i++ ) { WRITE_TTF_SHORT( vecRanges[i].nDelta ); } for( i=0;i(vecRanges.size());i++ ) { WRITE_TTF_USHORT( vecRanges[i].nOffset ); } } void PdfTTFWriter::WriteHHeaTable( PdfOutputDevice* pDevice ) { // We always write the long loca format // numberOfHMetrics has to be equal to numGlyphs so // that we have only to write LongHorMetric values to Hmtx and no short values m_tHHea.numberOfHMetrics = m_vecGlyphs.size(); if( podofo_is_little_endian() ) SwapHHeaTable(); pDevice->Write( reinterpret_cast(&m_tHHea), sizeof(THHea) ); } void PdfTTFWriter::WriteHmtxTable( PdfOutputDevice* pDevice ) { TLongHorMetric entry; TCIVecGlyphs it = m_vecGlyphs.begin(); while( it != m_vecGlyphs.end() ) { entry = m_vecHmtx[(*it).GetIndex()]; WRITE_TTF_USHORT( entry.advanceWidth ); WRITE_TTF_SHORT ( entry.leftSideBearing ); ++it; } } void PdfTTFWriter::WriteLocaTable( PdfOutputDevice* pDevice ) { TCIVecLoca it = m_vecLoca.begin(); pdf_ttf_ulong lValue; // Write a 0 value for first glyph lValue = 0x00; this->SwapULong( &lValue ); pDevice->Write( reinterpret_cast(&lValue), sizeof(pdf_ttf_ulong) ); while( it != m_vecLoca.end() ) { lValue = (*it); this->SwapULong( &lValue ); pDevice->Write( reinterpret_cast(&lValue), sizeof(pdf_ttf_ulong) ); ++it; } } void PdfTTFWriter::WriteMaxpTable( PdfOutputDevice* pDevice ) { m_tMaxp.numGlyphs = m_vecGlyphs.size(); if( podofo_is_little_endian() ) SwapMaxpTable(); pDevice->Write( reinterpret_cast(&m_tMaxp), sizeof(TMaxP) ); } void PdfTTFWriter::WriteNameTable( PdfOutputDevice* pDevice ) { const char* pszFontName = "PoDoFo"; PdfString unicodeName = PdfString( pszFontName ).ToUnicode(); long lLen = unicodeName.GetLength(); // Create a custom nametable TNameTable tNameTable; tNameTable.format = 0; tNameTable.numRecords = 1; tNameTable.offset = 6; tNameTable.platformId = 0; tNameTable.encodingId = 3; tNameTable.languageId = 0x0809; tNameTable.nameId = 6; tNameTable.stringLength = static_cast(lLen); tNameTable.stringOffset = 12; SwapUShort( &tNameTable.format ); SwapUShort( &tNameTable.numRecords ); SwapUShort( &tNameTable.offset ); SwapUShort( &tNameTable.platformId ); SwapUShort( &tNameTable.encodingId ); SwapUShort( &tNameTable.languageId ); SwapUShort( &tNameTable.nameId ); SwapUShort( &tNameTable.stringLength ); SwapUShort( &tNameTable.stringOffset ); pDevice->Write( reinterpret_cast(&tNameTable), sizeof(TNameTable) ); pDevice->Write( unicodeName.GetString(), lLen ); } void PdfTTFWriter::WriteOs2Table( PdfOutputDevice* pDevice ) { // We always write the long loca format if( podofo_is_little_endian() ) SwapOs2Table(); pDevice->Write( reinterpret_cast(&m_tOs2), sizeof(TOs2) ); } void PdfTTFWriter::WriteHeadTable( PdfOutputDevice* pDevice ) { // We always write the long loca format m_tHead.indexToLocForm = 1; if( podofo_is_little_endian() ) SwapHeadTable(); pDevice->Write( reinterpret_cast(&m_tHead), sizeof(THead) ); } void PdfTTFWriter::WritePostTable( PdfOutputDevice* pDevice ) { m_tPost.format = 0x00020000; // write table header pDevice->Write( reinterpret_cast(&m_tPost), sizeof(TPost) ); // write format 2 post table int nNameIndexValue = 258; pdf_ttf_ushort nameIndex; pdf_ttf_ushort numberOfGlyphs = m_tMaxp.numGlyphs; // this value has already been swapped when writing the maxp-table pDevice->Write( reinterpret_cast(&numberOfGlyphs), sizeof(pdf_ttf_ushort) ); SwapUShort( &numberOfGlyphs ); // swap it to native format so that we can use it while( numberOfGlyphs-- ) { nameIndex = nNameIndexValue++; SwapUShort( &nameIndex ); pDevice->Write( reinterpret_cast(&nameIndex), sizeof(pdf_ttf_ushort) ); } // write names std::vector::const_iterator it = m_vecGlyphIndeces.begin(); while( it != m_vecGlyphIndeces.end() ) { const char* pszName = "Test"; unsigned char cLen = static_cast(strlen(pszName)); pDevice->Write( reinterpret_cast(&cLen), 1 ); pDevice->Write( pszName, cLen ); ++it; } } // ----------------------------------------------------- // Helper functions // ----------------------------------------------------- PdfTTFWriter::pdf_ttf_ulong PdfTTFWriter::CalculateChecksum( const pdf_ttf_ulong* pTable, pdf_ttf_ulong lLength ) const { // This code is taken from the TTF specification pdf_ttf_ulong lSum = 0L; const pdf_ttf_ulong* pEnd = pTable + ((lLength+3) & ~3) / sizeof(pdf_ttf_ulong); while( pTable < pEnd ) lSum += *pTable++; return lSum; } void PdfTTFWriter::WriteTable( PdfOutputDevice* pDevice, TVecTableDirectoryEntries & rToc, pdf_ttf_ulong tag, void (PdfTTFWriter::*WriteTableFunc)( PdfOutputDevice* ) ) { if( !m_pRefBuffer ) { // start with a 4MB buffer const long l4MB = 4 * 1024 * 1024; m_pRefBuffer = new PdfRefCountedBuffer( l4MB ); } PdfOutputDevice memDevice( m_pRefBuffer ); TTableDirectoryEntry entry; entry.tag = tag; entry.checkSum = 0; entry.length = 0; entry.offset = pDevice->Tell(); (this->*WriteTableFunc)( &memDevice ); // create toc entry entry.checkSum = this->CalculateChecksum( reinterpret_cast(m_pRefBuffer->GetBuffer()), memDevice.GetLength() );; entry.length = memDevice.GetLength(); rToc.push_back( entry ); // write data to the real device pDevice->Write( m_pRefBuffer->GetBuffer(), memDevice.GetLength() ); } void PdfTTFWriter::ReadSimpleGlyfCoordinates( PdfInputDevice* pDevice, const std::vector & rvecFlags, std::vector & rvecCoordinates, int nFlagShort, int nFlag ) { pdf_ttf_short longCoordinate; unsigned char shortCoordinate; printf("~~~~~~~~~~~\n"); printf("FLAGS: %i\n", rvecFlags.size() ); std::vector::const_iterator itFlags = rvecFlags.begin(); while( itFlags != rvecFlags.end() ) { if( (*itFlags & nFlagShort) == nFlagShort ) { // read a 1 byte long coordinate pDevice->Read( reinterpret_cast(&shortCoordinate), sizeof(char) ); printf("Got short: %i\n", shortCoordinate ); longCoordinate = static_cast(shortCoordinate); if( (*itFlags & nFlag) == nFlag ) longCoordinate = -longCoordinate; } else { // read a 2 byte long coordinate if( (*itFlags & nFlag) == nFlag ) { // DO NOTHING // the value of longCoordinate is the same as the last value // so simply reuse the old value } else { pdf_ttf_short coordinate; READ_TTF_SHORT( coordinate ); printf("Got long: %i\n", longCoordinate ); longCoordinate += coordinate; } } printf("Pushing: %i\n", longCoordinate ); rvecCoordinates.push_back( longCoordinate ); ++itFlags; } } void PdfTTFWriter::WriteSimpleGlyfCoordinates( PdfOutputDevice* pDevice, const std::vector & rvecFlags, std::vector & rvecCoordinates, int nFlagShort, int nFlag ) { pdf_ttf_short longCoordinate; pdf_ttf_short lastCoordinate; char shortCoordinate; std::vector::const_iterator itFlags = rvecFlags.begin(); std::vector::iterator itCoordinates = rvecCoordinates.begin(); while( itFlags != rvecFlags.end() ) { longCoordinate = (*itCoordinates)++; if( (*itFlags & nFlagShort) == nFlagShort ) { // read a 1 byte long coordinate if( (*itFlags & nFlag) == nFlag ) longCoordinate = -longCoordinate; shortCoordinate = static_cast(longCoordinate); pDevice->Write( &shortCoordinate, sizeof(char) ); lastCoordinate = longCoordinate; // TODO: check if it is ok to assign a negative value here } else { // read a 2 byte long coordinate if( (*itFlags & nFlag) == nFlag ) { // DO NOTHING // the value of longCoordinate is the same as the last value // so simply reuse the old value longCoordinate = lastCoordinate; } else { longCoordinate = longCoordinate - lastCoordinate; lastCoordinate = longCoordinate + lastCoordinate; } if( podofo_is_little_endian() ) this->SwapShort( &longCoordinate ); pDevice->Write( reinterpret_cast(&longCoordinate), sizeof(pdf_ttf_short) ); } ++itFlags; } } long PdfTTFWriter::GetGlyphDataLocation( unsigned int nIndex, long* plLength, PdfInputDevice* pDevice ) const { // find the correct cmap range std::vector::const_iterator it = m_ranges.begin(); // TODO: binary search!!! while( it != m_ranges.end() ) { if( (*it).nStart <= nIndex && (*it).nEnd > nIndex ) { // we got a position!! printf("Found Range for %u: %6u - %6u Delta: %6i Offset: %6u\n", nIndex, (*it).nStart, (*it).nEnd, (*it).nDelta, (*it).nOffset ); if( (*it).nOffset ) { const int nSegCount = format4.segCountX2 >> 1; int j = (*it).nOffset - (nSegCount - (it-m_ranges.begin())*2); printf("j1 = %i\n", j ); j = (nIndex - (*it).nStart) + j/2; printf("j2 = %i\n", j ); nIndex = m_vecGlyphIds[j]; printf("nIndex=%i\n", nIndex ); // 81 ??? // 1314 /* long lAddress = (*it).nOffset/2 + (nIndex - (*it).nStart) + (*it).nOffset; pDevice->Seek( lAddress + m_lCMapOffset ); pdf_ttf_ushort glyph; READ_TTF_USHORT( glyph ); printf("lAddress alone=%lx %li\n", lAddress, lAddress ); printf("lAddress=%lx\n", lAddress + m_lCMapOffset ); nIndex = glyph; printf("glyph=%u\n", glyph ); */ //nIndex = 108; //lAddress = 0x858a; //nIndex = *lAddress nach Seek } nIndex = static_cast( (nIndex + (*it).nDelta & 0xFFFFU ) ); break; } ++it; } if( it == m_ranges.end() ) // go to "missing glyph" if no glyph was found nIndex = 0; printf("INDEX: %i RANGE(0 - %i)\n", nIndex, m_tLoca.size() ); // check if the glyph index is in our current range if( nIndex < 0 || nIndex > m_tLoca.size() ) return -1; if( nIndex + 1 < m_tLoca.size() ) *plLength = m_tLoca[nIndex+1] - m_tLoca[nIndex]; else *plLength = 0; printf("Reading from index: %i (max: %i) len=%i\n", nIndex, m_tLoca.size(), *plLength ); return m_lGlyphDataOffset + m_tLoca[nIndex]; } }; }; podofo-0.9.3/src/doc/PdfAnnotation.cpp0000664000175000017500000002654512344436402017503 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2006 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfAnnotation.h" #include "base/PdfDefinesPrivate.h" #include "base/PdfArray.h" #include "base/PdfDictionary.h" #include "base/PdfDate.h" #include "PdfAction.h" #include "PdfFileSpec.h" #include "PdfPage.h" #include "base/PdfRect.h" #include "base/PdfVariant.h" #include "PdfXObject.h" namespace PoDoFo { const long PdfAnnotation::s_lNumActions = 27; const char* PdfAnnotation::s_names[] = { "Text", // - supported "Link", "FreeText", // PDF 1.3 // - supported "Line", // PDF 1.3 // - supported "Square", // PDF 1.3 "Circle", // PDF 1.3 "Polygon", // PDF 1.5 "PolyLine", // PDF 1.5 "Highlight", // PDF 1.3 "Underline", // PDF 1.3 "Squiggly", // PDF 1.4 "StrikeOut", // PDF 1.3 "Stamp", // PDF 1.3 "Caret", // PDF 1.5 "Ink", // PDF 1.3 "Popup", // PDF 1.3 "FileAttachment", // PDF 1.3 "Sound", // PDF 1.2 "Movie", // PDF 1.2 "Widget", // PDF 1.2 // - supported "Screen", // PDF 1.5 "PrinterMark", // PDF 1.4 "TrapNet", // PDF 1.3 "Watermark", // PDF 1.6 "3D", // PDF 1.6 "RichMedia", // PDF 1.7 ADBE ExtensionLevel 3 ALX: Petr P. Petrov "WebMedia", // PDF 1.7 IPDF ExtensionLevel 1 NULL }; PdfAnnotation::PdfAnnotation( PdfPage* pPage, EPdfAnnotation eAnnot, const PdfRect & rRect, PdfVecObjects* pParent ) : PdfElement( "Annot", pParent ), m_eAnnotation( eAnnot ), m_pAction( NULL ), m_pFileSpec( NULL ), m_pPage( pPage ) { PdfVariant rect; PdfDate date; PdfString sDate; const PdfName name( TypeNameForIndex( eAnnot, s_names, s_lNumActions ) ); if( !name.GetLength() ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } rRect.ToVariant( rect ); this->GetObject()->GetDictionary().AddKey( PdfName::KeyRect, rect ); rRect.ToVariant( rect ); date.ToString( sDate ); this->GetObject()->GetDictionary().AddKey( PdfName::KeySubtype, name ); this->GetObject()->GetDictionary().AddKey( PdfName::KeyRect, rect ); this->GetObject()->GetDictionary().AddKey( "P", pPage->GetObject()->Reference() ); this->GetObject()->GetDictionary().AddKey( "M", sDate ); } PdfAnnotation::PdfAnnotation( PdfObject* pObject, PdfPage* pPage ) : PdfElement( "Annot", pObject ), m_eAnnotation( ePdfAnnotation_Unknown ), m_pAction( NULL ), m_pFileSpec( NULL ), m_pPage( pPage ) { m_eAnnotation = static_cast(TypeNameToIndex( this->GetObject()->GetDictionary().GetKeyAsName( PdfName::KeySubtype ).GetName().c_str(), s_names, s_lNumActions, ePdfAnnotation_Unknown )); } PdfAnnotation::~PdfAnnotation() { delete m_pAction; delete m_pFileSpec; } PdfRect PdfAnnotation::GetRect() const { if( this->GetObject()->GetDictionary().HasKey( PdfName::KeyRect ) ) return PdfRect( this->GetObject()->GetDictionary().GetKey( PdfName::KeyRect )->GetArray() ); return PdfRect(); } void PdfAnnotation::SetAppearanceStream( PdfXObject* pObject ) { PdfDictionary dict; PdfDictionary internal; if( !pObject ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } internal.AddKey( "On", pObject->GetObject()->Reference() ); internal.AddKey( "Off", pObject->GetObject()->Reference() ); dict.AddKey( "N", internal ); this->GetObject()->GetDictionary().AddKey( "AP", dict ); this->GetObject()->GetDictionary().AddKey( "AS", PdfName("On") ); } bool PdfAnnotation::HasAppearanceStream() const { return this->GetObject()->GetDictionary().HasKey( "AP" ); } void PdfAnnotation::SetFlags( pdf_uint32 uiFlags ) { this->GetObject()->GetDictionary().AddKey( "F", PdfVariant( static_cast(uiFlags) ) ); } pdf_uint32 PdfAnnotation::GetFlags() const { if( this->GetObject()->GetDictionary().HasKey( "F" ) ) return static_cast(this->GetObject()->GetDictionary().GetKey( "F" )->GetNumber()); return static_cast(0); } void PdfAnnotation::SetBorderStyle( double dHCorner, double dVCorner, double dWidth ) { this->SetBorderStyle( dHCorner, dVCorner, dWidth, PdfArray() ); } void PdfAnnotation::SetBorderStyle( double dHCorner, double dVCorner, double dWidth, const PdfArray & rStrokeStyle ) { // TODO : Support for Border style for PDF Vers > 1.0 PdfArray aValues; aValues.push_back(dHCorner); aValues.push_back(dVCorner); aValues.push_back(dWidth); if( rStrokeStyle.size() ) aValues.push_back(rStrokeStyle); this->GetObject()->GetDictionary().AddKey( "Border", aValues ); } void PdfAnnotation::SetTitle( const PdfString & sTitle ) { this->GetObject()->GetDictionary().AddKey( "T", sTitle ); } PdfString PdfAnnotation::GetTitle() const { if( this->GetObject()->GetDictionary().HasKey( "T" ) ) return this->GetObject()->GetDictionary().GetKey( "T" )->GetString(); return PdfString(); } void PdfAnnotation::SetContents( const PdfString & sContents ) { this->GetObject()->GetDictionary().AddKey( "Contents", sContents ); } PdfString PdfAnnotation::GetContents() const { if( this->GetObject()->GetDictionary().HasKey( "Contents" ) ) return this->GetObject()->GetDictionary().GetKey( "Contents" )->GetString(); return PdfString(); } void PdfAnnotation::SetDestination( const PdfDestination & rDestination ) { rDestination.AddToDictionary( this->GetObject()->GetDictionary() ); } PdfDestination PdfAnnotation::GetDestination( PdfDocument* pDoc ) const { return PdfDestination( this->GetNonConstObject()->GetDictionary().GetKey( "Dest" ), pDoc ); } bool PdfAnnotation::HasDestination() const { return this->GetObject()->GetDictionary().HasKey( "Dest" ); } void PdfAnnotation::SetAction( const PdfAction & rAction ) { if( m_pAction ) delete m_pAction; m_pAction = new PdfAction( rAction ); this->GetObject()->GetDictionary().AddKey( "A", m_pAction->GetObject()->Reference() ); } PdfAction* PdfAnnotation::GetAction() const { if( !m_pAction && HasAction() ) const_cast(this)->m_pAction = new PdfAction( this->GetObject()->GetIndirectKey( "A" ) ); return m_pAction; } bool PdfAnnotation::HasAction() const { return this->GetObject()->GetDictionary().HasKey( "A" ); } void PdfAnnotation::SetOpen( bool b ) { this->GetObject()->GetDictionary().AddKey( "Open", b ); } bool PdfAnnotation::GetOpen() const { if( this->GetObject()->GetDictionary().HasKey( "Open" ) ) return this->GetObject()->GetDictionary().GetKey( "Open" )->GetBool(); return false; } bool PdfAnnotation::HasFileAttachement() const { return this->GetObject()->GetDictionary().HasKey( "FS" ); } void PdfAnnotation::SetFileAttachement( const PdfFileSpec & rFileSpec ) { if( m_pFileSpec ) delete m_pFileSpec; m_pFileSpec = new PdfFileSpec( rFileSpec ); this->GetObject()->GetDictionary().AddKey( "FS", m_pFileSpec->GetObject()->Reference() ); } PdfFileSpec* PdfAnnotation::GetFileAttachement() const { if( !m_pFileSpec && HasFileAttachement() ) const_cast(this)->m_pFileSpec = new PdfFileSpec( this->GetObject()->GetIndirectKey( "FS" ) ); return m_pFileSpec; } PdfArray PdfAnnotation::GetQuadPoints() const { if( this->GetObject()->GetDictionary().HasKey( "QuadPoints" ) ) return PdfArray( this->GetObject()->GetDictionary().GetKey( "QuadPoints" )->GetArray() ); return PdfArray(); } void PdfAnnotation::SetQuadPoints( const PdfArray & rQuadPoints ) { if ( m_eAnnotation != ePdfAnnotation_Highlight && m_eAnnotation != ePdfAnnotation_Underline && m_eAnnotation != ePdfAnnotation_Squiggly && m_eAnnotation != ePdfAnnotation_StrikeOut ) PODOFO_RAISE_ERROR_INFO( ePdfError_InternalLogic, "Must be a text markup annotation (hilight, underline, squiggly or strikeout) to set quad points" ); this->GetObject()->GetDictionary().AddKey( "QuadPoints", rQuadPoints ); } PdfArray PdfAnnotation::GetColor() const { if( this->GetObject()->GetDictionary().HasKey( "C" ) ) return PdfArray( this->GetObject()->GetDictionary().GetKey( "C" )->GetArray() ); return PdfArray(); } void PdfAnnotation::SetColor( double r, double g, double b ) { PdfArray c; c.push_back( PdfVariant( r ) ); c.push_back( PdfVariant( g ) ); c.push_back( PdfVariant( b ) ); this->GetObject()->GetDictionary().AddKey( "C", c ); } void PdfAnnotation::SetColor( double C, double M, double Y, double K ) { PdfArray c; c.push_back( PdfVariant( C ) ); c.push_back( PdfVariant( M ) ); c.push_back( PdfVariant( Y ) ); c.push_back( PdfVariant( K ) ); this->GetObject()->GetDictionary().AddKey( "C", c ); } void PdfAnnotation::SetColor( double gray ) { PdfArray c; c.push_back( PdfVariant( gray ) ); this->GetObject()->GetDictionary().AddKey( "C", c ); } void PdfAnnotation::SetColor() { PdfArray c; this->GetObject()->GetDictionary().AddKey( "C", c ); } }; podofo-0.9.3/src/doc/PdfAction.h0000664000175000017500000001260212344436402016240 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2006 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_ACTION_H_ #define _PDF_ACTION_H_ #include "podofo/base/PdfDefines.h" #include "PdfElement.h" namespace PoDoFo { class PdfObject; class PdfString; class PdfStreamedDocument; class PdfVecObjects; /** The type of the action. * PDF supports different action types, each of * them has different keys and propeties. * * Not all action types listed here are supported yet. * * Please make also sure that the action type you use is * supported by the PDF version you are using. */ enum EPdfAction { ePdfAction_GoTo = 0, ePdfAction_GoToR, ePdfAction_GoToE, ePdfAction_Launch, ePdfAction_Thread, ePdfAction_URI, ePdfAction_Sound, ePdfAction_Movie, ePdfAction_Hide, ePdfAction_Named, ePdfAction_SubmitForm, ePdfAction_ResetForm, ePdfAction_ImportData, ePdfAction_JavaScript, ePdfAction_SetOCGState, ePdfAction_Rendition, ePdfAction_Trans, ePdfAction_GoTo3DView, ePdfAction_RichMediaExecute, ePdfAction_Unknown = 0xff }; /** An action that can be performed in a PDF document */ class PODOFO_DOC_API PdfAction : public PdfElement { friend class PdfAnnotation; public: /** Create a new PdfAction object * \param eAction type of this action * \param pParent parent of this action */ PdfAction( EPdfAction eAction, PdfVecObjects* pParent ); /** Create a new PdfAction object * \param eAction type of this action * \param pParent parent of this action */ PdfAction( EPdfAction eAction, PdfDocument* pParent ); virtual ~PdfAction() { } /** Create a PdfAction object from an existing * PdfObject */ PdfAction( PdfObject* pObject ); /** Set the URI of an ePdfAction_URI * \param sUri must be a correct URI as PdfString */ void SetURI( const PdfString & sUri ); /** Get the URI of an ePdfAction_URI * \returns an URI */ PdfString GetURI() const; /** * \returns true if this action has an URI */ bool HasURI() const; void SetScript( const PdfString & sScript ); PdfString GetScript() const; bool HasScript() const; /** Get the type of this action * \returns the type of this action */ inline EPdfAction GetType() const; /** Adds this action to an dictionary. * This method handles the all the complexities of making sure it's added correctly * * If this action is empty. Nothing will be added. * * \param dictionary the action will be added to this dictionary */ void AddToDictionary( PdfDictionary & dictionary ) const; private: PdfAction( const PdfAction & rhs ); private: static const long s_lNumActions; static const char* s_names[]; private: EPdfAction m_eType; }; // ----------------------------------------------------- // // ----------------------------------------------------- inline EPdfAction PdfAction::GetType() const { return m_eType; } }; #endif // _PDF_ACTION_H_ podofo-0.9.3/src/doc/PdfFontSimple.h0000664000175000017500000001113112344436402017077 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2007 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_FONT_SIMPLE_H_ #define _PDF_FONT_SIMPLE_H_ #include "podofo/base/PdfDefines.h" #include "PdfFont.h" namespace PoDoFo { /** This is a common base class for simple fonts * like truetype or type1 fonts. */ class PdfFontSimple : public PdfFont { public: /** Create a new PdfFont object which will introduce itself * automatically to every page object it is used on. * * The font has a default font size of 12.0pt. * * \param pMetrics pointer to a font metrics object. The font in the PDF * file will match this fontmetrics object. The metrics object is * deleted along with the font. * \param pEncoding the encoding of this font. The font will take ownership of this object * depending on pEncoding->IsAutoDelete() * \param pParent parent of the font object * */ PdfFontSimple( PdfFontMetrics* pMetrics, const PdfEncoding* const pEncoding, PdfVecObjects* pParent ); /** Create a PdfFont based on an existing PdfObject * \param pMetrics pointer to a font metrics object. The font in the PDF * file will match this fontmetrics object. The metrics object is * deleted along with the font. * \param pEncoding the encoding of this font. The font will take ownership of this object * depending on pEncoding->IsAutoDelete() * \param pObject an existing PdfObject */ PdfFontSimple( PdfFontMetrics* pMetrics, const PdfEncoding* const pEncoding, PdfObject* pObject ); // Peter Petrov 24 September 2008 /** Embeds the font into PDF page * */ virtual void EmbedFont(); protected: /** Initialize this font object. * * \param bEmbed if true embed the font data into the PDF file. * \param rsSubType the subtype of the real font. */ void Init( bool bEmbed, const PdfName & rsSubType ); /** Embed the font file directly into the PDF file. * * \param pDescriptor font descriptor object */ virtual void EmbedFontFile( PdfObject* pDescriptor ) = 0; PdfObject* m_pDescriptor; }; }; #endif /* _PDF_FONT_SIMPLE_H_ */ podofo-0.9.3/src/doc/PdfFontType1.cpp0000664000175000017500000005161112347271543017220 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2005 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfFontType1.h" #include "base/PdfDefinesPrivate.h" #include "base/PdfArray.h" #include "base/PdfDictionary.h" #include "base/PdfName.h" #include "base/PdfStream.h" #include "PdfDifferenceEncoding.h" #include namespace PoDoFo { PdfFontType1::PdfFontType1( PdfFontMetrics* pMetrics, const PdfEncoding* const pEncoding, PdfVecObjects* pParent, bool bEmbed, bool bSubsetting ) : PdfFontSimple( pMetrics, pEncoding, pParent ) { memset( m_bUsed, 0, sizeof( m_bUsed ) ); m_bIsSubsetting = bSubsetting; this->Init( bEmbed, PdfName("Type1") ); } PdfFontType1::PdfFontType1( PdfFontMetrics* pMetrics, const PdfEncoding* const pEncoding, PdfObject* pObject ) : PdfFontSimple( pMetrics, pEncoding, pObject ) { memset( m_bUsed, 0, sizeof( m_bUsed ) ); } PdfFontType1::PdfFontType1( PdfFontType1* pFont, PdfFontMetrics* pMetrics, const char *pszSuffix, PdfVecObjects* pParent ) : PdfFontSimple( pMetrics, pFont->m_pEncoding, pParent ) { memset( m_bUsed, 0, sizeof( m_bUsed ) ); // don't embedd font Init( false, PdfName("Type1") ); // Use identical subset-names if ( pFont->IsSubsetting() ) GetObject()->GetDictionary().AddKey( "BaseFont", pFont->GetObject()->GetDictionary().GetKey( "BaseFont" ) ); // set identifier std::string id = pFont->GetIdentifier().GetName(); id += pszSuffix; m_Identifier = id; // remove new FontDescriptor and use FontDescriptor of source font instead PdfObject* pObj = pParent->RemoveObject( GetObject()->GetIndirectKey( "FontDescriptor" )->Reference() ); delete pObj; GetObject()->GetDictionary().AddKey( "FontDescriptor", pFont->GetObject()->GetDictionary().GetKey( "FontDescriptor" ) ); } void PdfFontType1::AddUsedSubsettingGlyphs( const PdfString & sText, long lStringLen ) { if ( m_bIsSubsetting ) { // TODO: Unicode and Hex not yet supported PODOFO_ASSERT( sText.IsUnicode() == false ); PODOFO_ASSERT( sText.IsHex() == false ); const unsigned char* strp = reinterpret_cast(sText.GetString()); // must be unsigned for access to m_bUsed-array for ( int i = 0; i < lStringLen; i++ ) { m_bUsed[strp[i] / 32] |= 1 << (strp[i] % 32 ); } } } void PdfFontType1::AddUsedGlyphname( const char * sGlyphName ) { if ( m_bIsSubsetting ) { m_sUsedGlyph.insert( sGlyphName ); } } void PdfFontType1::EmbedSubsetFont() { if ( !m_bIsSubsetting || m_bWasEmbedded == true ) return; pdf_long lSize = 0; pdf_int64 lLength1 = 0L; pdf_int64 lLength2 = 0L; pdf_int64 lLength3 = 0L; PdfObject* pContents; const char* pBuffer; char* pAllocated = NULL; int i; m_bWasEmbedded = true; pContents = this->GetObject()->GetOwner()->CreateObject(); if( !pContents ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } m_pDescriptor->GetDictionary().AddKey( "FontFile", pContents->Reference() ); // if the data was loaded from memory - use it from there // otherwise, load from disk if ( m_pMetrics->GetFontDataLen() && m_pMetrics->GetFontData() ) { pBuffer = m_pMetrics->GetFontData(); lSize = m_pMetrics->GetFontDataLen(); } else { FILE* hFile = fopen( m_pMetrics->GetFilename(), "rb" ); if( !hFile ) { PODOFO_RAISE_ERROR_INFO( ePdfError_FileNotFound, m_pMetrics->GetFilename() ); } fseek( hFile, 0L, SEEK_END ); lSize = ftell( hFile ); fseek( hFile, 0L, SEEK_SET ); pAllocated = static_cast(malloc( sizeof(char) * lSize )); if( !pAllocated ) { fclose( hFile ); PODOFO_RAISE_ERROR( ePdfError_OutOfMemory ); } fread( pAllocated, sizeof(char), lSize, hFile ); fclose( hFile ); pBuffer = pAllocated; } // Allocate buffer for subsetted font, worst case size is input size unsigned char * outBuff = new unsigned char[lSize]; int outIndex = 0; // unsigned to make comparisons work unsigned const char * inBuff = reinterpret_cast(pBuffer); int inIndex = 0; // 6-Byte binary header for leading ascii-part PODOFO_ASSERT( inBuff[inIndex + 0] == 0x80 ); PODOFO_ASSERT( inBuff[inIndex + 1] == 0x01 ); int length = inBuff[inIndex + 2] + (inBuff[inIndex + 3] << 8) + (inBuff[inIndex + 4] << 16) + (inBuff[inIndex + 5] << 24); // little endian inIndex += 6; PODOFO_ASSERT( memcmp( &inBuff[inIndex], "%!PS-AdobeFont-1.", 17 ) == 0 ); // transfer ascii-part, modify encoding dictionary (dup ...), if present std::string line; bool dupFound = false; for ( i = 0; i < length; i++ ) { line += static_cast( inBuff[inIndex+i] ); if ( inBuff[inIndex+i] == '\r' ) { if ( line.find( "dup " ) != 0 ) { memcpy( &outBuff[outIndex], line.c_str(), line.length() ); outIndex += line.length(); } else { if ( dupFound == false ) { // if first found, replace with new dictionary according to used glyphs // ignore further dup's for ( int i = 0; i < 256; i++ ) { if ( (m_bUsed[i / 32] & (1 << (i % 32 ))) != 0 ) { outIndex += sprintf( reinterpret_cast( &outBuff[outIndex] ), "dup %d /%s put\r", i, PdfDifferenceEncoding::UnicodeIDToName( GetEncoding()->GetCharCode(i) ).GetName().c_str() ); } } dupFound = true; } } #if defined(_MSC_VER) && _MSC_VER <= 1200 // Visual Studio 6 line.erase(); #else line.clear(); #endif } } inIndex += length; lLength1 = outIndex; // 6-Byte binary header for binary-part PODOFO_ASSERT( inBuff[inIndex + 0] == 0x80 ); PODOFO_ASSERT( inBuff[inIndex + 1] == 0x02 ); length = inBuff[inIndex + 2] + (inBuff[inIndex + 3] << 8) + (inBuff[inIndex + 4] << 16) + (inBuff[inIndex + 5] << 24); // little endian inIndex += 6; // copy binary using encrpytion int outIndexStart = outIndex; bool foundSeacGlyph; // if glyph contains seac-command, add the used base-glyphs and loop again do { PdfType1EncryptEexec inCrypt; outIndex = outIndexStart; #if defined(_MSC_VER) && _MSC_VER <= 1200 // Visual Studio 6 line.erase(); #else line.clear(); #endif foundSeacGlyph = false; bool inCharString = false; for ( int i = 0; i < length; ) { unsigned char plain = inCrypt.Decrypt( inBuff[inIndex+i] ); i++; line += static_cast(plain); // output is ssssbuild uncrypted, as parts might be skipped and cipher-engine must be unchanged if ( inCharString && line.find( "/" ) == 0 ) { // we are now inside a glyph, copy anything until RD or -| to output, // in case this glyph will be skipped we go back to saveOutIndex int outIndexSave = outIndex; outBuff[outIndex++] = plain; while ( line.find( "RD " ) == static_cast(-1) && line.find( "-| " ) == static_cast(-1) ) { plain = inCrypt.Decrypt( inBuff[inIndex+i] ); outBuff[outIndex++] = plain; line += static_cast(plain); i++; } // parse line for name and length of glyph char *glyphName = new char[line.length()]; int glyphLen; int result; if ( line.find( "RD " ) != static_cast(-1) ) { result = sscanf( line.c_str(), "%s %d RD ", glyphName, &glyphLen ); } else { result = sscanf( line.c_str(), "%s %d -| ", glyphName, &glyphLen ); } PODOFO_ASSERT( result == 2); bool useGlyph = false; // determine if this glyph is used in normal chars for ( int code = 0; code <= 255; code++ ) { if ( (m_bUsed[code / 32] & (1 << (code % 32 ))) != 0 && strcmp( glyphName+1, PdfDifferenceEncoding::UnicodeIDToName( GetEncoding()->GetCharCode(code) ).GetName().c_str() ) == 0 ) { useGlyph = true; break; } } // determine if this glyph is used in special chars if ( m_sUsedGlyph.find( glyphName+1 ) != m_sUsedGlyph.end() ) useGlyph = true; // always use .notdef if ( strcmp( glyphName, "/.notdef" ) == 0 ) useGlyph = true; // transfer glyph to output for ( int j = 0; j < glyphLen; j++, i++ ) outBuff[outIndex++] = inCrypt.Decrypt( inBuff[inIndex+i] ); // check used glyph for seac-command if ( useGlyph && FindSeac( &outBuff[outIndex - glyphLen], glyphLen ) ) foundSeacGlyph = true; delete[] glyphName; // transfer rest until end of line to output do { plain = inCrypt.Decrypt( inBuff[inIndex+i] ); outBuff[outIndex++] = plain; line += static_cast(plain); i++; } while ( plain != '\r' && plain != '\n' ); if ( useGlyph == false ) { // glyph is not used, go back to saved position outIndex = outIndexSave; } } else { // copy anything outside glyph to output outBuff[outIndex++] = plain; } if ( plain == '\r' || plain == '\n' ) { // parse for /CharStrings = begin of glyphs if ( line.find( "/CharStrings" ) != static_cast(-1) ) inCharString = true; #if defined(_MSC_VER) && _MSC_VER <= 1200 // Visual Studio 6 line.erase(); #else line.clear(); #endif } } } while ( foundSeacGlyph ); // now encrypt resulting output-buffer PdfType1EncryptEexec outCrypt; for ( i = outIndexStart; i < outIndex; i++ ) outBuff[i] = outCrypt.Encrypt( outBuff[i] ); lLength2 = outIndex - outIndexStart; inIndex += length; // 6-Byte binary header for ascii-part PODOFO_ASSERT( inBuff[inIndex + 0] == 0x80 ); PODOFO_ASSERT( inBuff[inIndex + 1] == 0x01 ); length = inBuff[inIndex + 2] + (inBuff[inIndex + 3] << 8) + (inBuff[inIndex + 4] << 16) + (inBuff[inIndex + 5] << 24); // little endian inIndex += 6; // copy ascii memcpy( &outBuff[outIndex], &inBuff[inIndex], length ); lLength3 = length; inIndex += length; outIndex += length; // now embed pContents->GetStream()->Set( reinterpret_cast(outBuff), outIndex ); // cleanup memory if( pAllocated ) free( pAllocated ); free( outBuff ); // enter length in dictionary pContents->GetDictionary().AddKey( "Length1", PdfVariant( lLength1 ) ); pContents->GetDictionary().AddKey( "Length2", PdfVariant( lLength2 ) ); pContents->GetDictionary().AddKey( "Length3", PdfVariant( lLength3 ) ); } void PdfFontType1::EmbedFontFile( PdfObject* pDescriptor ) { pdf_long lSize = 0; pdf_int64 lLength1 = 0L; pdf_int64 lLength2 = 0L; pdf_int64 lLength3 = 0L; PdfObject* pContents; const char* pBuffer; char* pAllocated = NULL; if (m_isBase14) { m_bWasEmbedded = false; return; } m_bWasEmbedded = true; pContents = this->GetObject()->GetOwner()->CreateObject(); if( !pContents ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } pDescriptor->GetDictionary().AddKey( "FontFile", pContents->Reference() ); // if the data was loaded from memory - use it from there // otherwise, load from disk if ( m_pMetrics->GetFontDataLen() && m_pMetrics->GetFontData() ) { pBuffer = m_pMetrics->GetFontData(); lSize = m_pMetrics->GetFontDataLen(); } else { FILE* hFile = fopen( m_pMetrics->GetFilename(), "rb" ); if( !hFile ) { PODOFO_RAISE_ERROR_INFO( ePdfError_FileNotFound, m_pMetrics->GetFilename() ); } fseek( hFile, 0L, SEEK_END ); lSize = ftell( hFile ); fseek( hFile, 0L, SEEK_SET ); pAllocated = static_cast(malloc( sizeof(char) * lSize )); if( !pAllocated ) { fclose( hFile ); PODOFO_RAISE_ERROR( ePdfError_OutOfMemory ); } fread( pAllocated, sizeof(char), lSize, hFile ); fclose( hFile ); pBuffer = pAllocated; } // Remove binary segment headers from pfb unsigned char *pBinary = reinterpret_cast(const_cast(pBuffer)); while( *pBinary == 0x80 ) // binary segment header { const int cHeaderLength = 6; int iSegmentType = pBinary[1]; // binary segment type long lSegmentLength = 0L; long lSegmentDelta = static_cast(&pBuffer[lSize] - reinterpret_cast(pBinary) ); switch( iSegmentType ) { case 1: // ASCII text lSegmentLength = pBinary[2] + // little endian pBinary[3] * 256L + pBinary[4] * 65536L + pBinary[5] * 16777216L; if( lLength1 == 0L ) lLength1 = lSegmentLength; else lLength3 = lSegmentLength; lSize -= cHeaderLength; memmove( pBinary, &pBinary[cHeaderLength], lSegmentDelta ); pBinary = &pBinary[lSegmentLength]; break; case 2: // binary data lSegmentLength = pBinary[2] + // little endian pBinary[3] * 256L + pBinary[4] * 65536L + pBinary[5] * 16777216L; lLength2 = lSegmentLength; lSize -= cHeaderLength; memmove( pBinary, &pBinary[cHeaderLength], lSegmentDelta ); pBinary = &pBinary[lSegmentLength]; break; case 3: // end-of-file pContents->GetStream()->Set( pBuffer, lSize - 2L ); if( pAllocated ) free( pAllocated ); pContents->GetDictionary().AddKey( "Length1", PdfVariant( lLength1 ) ); pContents->GetDictionary().AddKey( "Length2", PdfVariant( lLength2 ) ); pContents->GetDictionary().AddKey( "Length3", PdfVariant( lLength3 ) ); return; default: break; } } // Parse the font data buffer to get the values for length1, length2 and length3 lLength1 = FindInBuffer( "eexec", pBuffer, lSize ); if( lLength1 > 0 ) lLength1 += 6; // 6 == eexec + lf else lLength1 = 0; if( lLength1 ) { lLength2 = FindInBuffer( "cleartomark", pBuffer, lSize ); if( lLength2 > 0 ) lLength2 = lSize - lLength1 - 520; // 520 == 512 + strlen(cleartomark) else lLength1 = 0; } lLength3 = lSize - lLength2 - lLength1; // TODO: Pdf Supports only Type1 fonts with binary encrypted sections and not the hex format pContents->GetStream()->Set( pBuffer, lSize ); if( pAllocated ) free( pAllocated ); pContents->GetDictionary().AddKey( "Length1", PdfVariant( lLength1 ) ); pContents->GetDictionary().AddKey( "Length2", PdfVariant( lLength2 ) ); pContents->GetDictionary().AddKey( "Length3", PdfVariant( lLength3 ) ); } bool PdfFontType1::FindSeac( const unsigned char * buffer, int length ) { PdfType1EncryptCharstring crypt; const PdfEncoding * stdEncoding = PdfEncodingFactory::GlobalStandardEncodingInstance(); bool foundNewGlyph = false; int code1 = 0; int code2 = 0; for ( int j = 0; j < length; ) { unsigned char plain = crypt.Decrypt( buffer[j++] ); if ( j <= 4 ) { // skip first 4 bytes } else if ( plain < 32 ) { // decode commands switch ( plain ) { case 1: // hstem case 3: // vstem case 4: // rmoveto case 5: // rlineto case 6: // hlineto case 7: // vlineto case 8: // rrcurveto case 9: // closepath case 10: // callsubr case 11: // return break; case 12: // escape { plain = crypt.Decrypt( buffer[j++] ); switch ( plain ) { case 0: // dotsection case 1: // vstem3 case 2: // hstem3 break; case 6: // seac { // found seac command, use acquired code1 and code2 to get glyphname in standard-encoding std::string name; name = PdfDifferenceEncoding::UnicodeIDToName( stdEncoding->GetCharCode(code1) ).GetName().c_str(); if ( m_sUsedGlyph.find( name ) == m_sUsedGlyph.end() ) { // add new glyph m_sUsedGlyph.insert( name ); foundNewGlyph = true; } name = PdfDifferenceEncoding::UnicodeIDToName( stdEncoding->GetCharCode(code2) ).GetName().c_str(); if ( m_sUsedGlyph.find( name ) == m_sUsedGlyph.end() ) { // add new glyph m_sUsedGlyph.insert( name ); foundNewGlyph = true; } } break; case 7: // sbw case 12: // div case 16: // callothersubr case 17: // pop case 33: // setcurrentpoint break; default: // ??? break; } } break; case 13: // hsbw case 14: // endchar case 21: // rmoveto case 22: // hmoveto case 30: // vhcurveto case 31: // hcurveto break; default: // ??? break; } } else if ( plain >= 32 ) // && plain <= 255 ) { // this is a number int number = 0; if ( plain >= 32 && plain <= 246 ) { number = static_cast(plain-139); } else if ( plain >= 247 && plain <= 250 ) { unsigned char next = crypt.Decrypt( buffer[j++] ); number = (static_cast(plain)-247)*256 + next + 108; } else if ( plain >= 251 && plain <= 254 ) { unsigned char next = crypt.Decrypt( buffer[j++] ); number = -((static_cast(plain)-251)*256) - next - 108; } else if ( plain == 255 ) { unsigned char next1 = crypt.Decrypt( buffer[j++] ); unsigned char next2 = crypt.Decrypt( buffer[j++] ); unsigned char next3 = crypt.Decrypt( buffer[j++] ); unsigned char next4 = crypt.Decrypt( buffer[j++] ); number = (static_cast(next1) << 24) + (static_cast(next2) << 16) + (static_cast(next3) << 8) + next4 ; } char num[32]; sprintf( num, "%d ", number ); code1 = code2; code2 = number; } } return foundNewGlyph; } pdf_long PdfFontType1::FindInBuffer( const char* pszNeedle, const char* pszHaystack, pdf_long lLen ) const { // if lNeedleLen is 0 the while loop will not be executed and we return -1 pdf_long lNeedleLen = pszNeedle ? strlen( pszNeedle ) : 0; const char* pszEnd = pszHaystack + lLen - lNeedleLen; const char* pszStart = pszHaystack; while( pszHaystack < pszEnd ) { if( strncmp( pszHaystack, pszNeedle, lNeedleLen ) == 0 ) return pszHaystack - pszStart; ++pszHaystack; } return -1; } PdfType1EncryptEexec::PdfType1EncryptEexec() : PdfType1Encrypt() { m_r = 55665; } PdfType1EncryptCharstring::PdfType1EncryptCharstring() : PdfType1Encrypt() { m_r = 4330; } PdfType1Encrypt::PdfType1Encrypt() { m_c1 = 52845; m_c2 = 22719; } unsigned char PdfType1Encrypt::Encrypt( unsigned char plain ) { unsigned char cipher; cipher = (plain ^ (m_r >> 8)); m_r = ((cipher + m_r) * m_c1 + m_c2) & ((1<<16) -1); return cipher; } unsigned char PdfType1Encrypt::Decrypt( unsigned char cipher ) { unsigned char plain; plain = (cipher ^ (m_r >> 8)); m_r = (cipher + m_r) * m_c1 + m_c2; return plain; } }; podofo-0.9.3/src/doc/PdfSignOutputDevice.h0000664000175000017500000001211612262234754020271 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2011 by Dominik Seichter * * domseichter@web.de * * by Petr Pytelka * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PODOFO_SIGN_OUTPUT_DEVICE_H_ #define _PODOFO_SIGN_OUTPUT_DEVICE_H_ #include "../base/PdfOutputDevice.h" #include "../base/PdfData.h" #include "../base/PdfString.h" namespace PoDoFo { /** Signer class * * Class is used to locate place for signature in the stream. * Usage: * 1. Locate signature and adjust ByteRange * 2. Generate signature * 3. Insert new signature */ class PODOFO_DOC_API PdfSignOutputDevice :public PdfOutputDevice { PdfOutputDevice *m_pRealDevice; bool m_bDevOwner; PdfData *m_pSignatureBeacon; size_t m_sBeaconPos; bool m_bBeaconFound; void Init(); public: PdfSignOutputDevice(PdfOutputDevice *pRealDevice); PdfSignOutputDevice(const char* pszFilename); #ifdef WIN32 PdfSignOutputDevice( const wchar_t* pszFilename ); #endif virtual ~PdfSignOutputDevice(); /** Set string to lookup for * * \param lSignatureSize Total space reserved for signature */ virtual void SetSignatureSize(size_t lSignatureSize); /** Get expected size of signature. * * If reserved size if zero no signatures will be added. * \return Total space reserved for signature. */ virtual size_t GetSignatureSize()const; /** Return signature beacon * */ virtual const PdfData *GetSignatureBeacon()const{ return m_pSignatureBeacon; } virtual bool HasSignaturePosition()const { return m_bBeaconFound; } /** Modify ByteRange entry according to signature position * */ virtual void AdjustByteRange(); /** Read data for signature */ virtual size_t ReadForSignature(char* pBuffer, size_t lLen); /** Embed real signature in the PDF */ virtual void SetSignature(const PdfData &sigData); virtual inline size_t GetLength() const { return m_pRealDevice->GetLength(); } virtual void Print( const char* pszFormat, ... ) { va_list args; long lBytes; va_start( args, pszFormat ); lBytes = m_pRealDevice->PrintVLen(pszFormat, args); va_end( args ); va_start( args, pszFormat ); m_pRealDevice->PrintV(pszFormat, lBytes, args); va_end( args ); } virtual void Write( const char* pBuffer, size_t lLen ); virtual size_t Read( char* pBuffer, size_t lLen ) { return m_pRealDevice->Read(pBuffer, lLen); } virtual void Seek( size_t offset ) { m_pRealDevice->Seek(offset); } virtual inline size_t Tell() const { return m_pRealDevice->Tell(); } virtual void Flush() { m_pRealDevice->Flush(); } }; } #endif podofo-0.9.3/src/doc/PdfFontFactory.h0000664000175000017500000001167212347316204017267 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2007 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_FONT_FACTORY_H_ #define _PDF_FONT_FACTORY_H_ #include "podofo/base/PdfDefines.h" #include "PdfFont.h" namespace PoDoFo { class PdfFontMetrics; class PdfVecObjects; enum EPdfFontFlags { ePdfFont_Normal = 0x00, ePdfFont_Embedded = 0x01, ePdfFont_Bold = 0x02, ePdfFont_Italic = 0x04, ePdfFont_BoldItalic = ePdfFont_Bold | ePdfFont_Italic, ePdfFont_Subsetting = 0x08 }; /** This is a factory class which knows * which implementation of PdfFont is required * for a certain font type with certain features (like encoding). */ class PODOFO_DOC_API PdfFontFactory { public: /** Create a new PdfFont object. * * \param pMetrics pointer to a font metrics object. The font in the PDF * file will match this fontmetrics object. The metrics object is * deleted along with the created font. In case of an error, it is deleted * here. * \param nFlags font flags or'ed together, specifying the font style and if it should be embedded * \param pEncoding the encoding of this font. * \param pParent the parent of the created font. * * \returns a new PdfFont object or NULL */ static PdfFont* CreateFontObject( PdfFontMetrics* pMetrics, int nFlags, const PdfEncoding* const pEncoding, PdfVecObjects* pParent ); /** Create a new PdfFont from an existing * font in a PDF file. * * \param pLibrary handle to the FreeType library, so that a PdfFontMetrics * can be constructed for this font * \param pObject a PDF font object */ static PdfFont* CreateFont( FT_Library* pLibrary, PdfObject* pObject ); static PdfFont* CreateBase14Font(const char* pszFontName, int nFlags, const PdfEncoding * const pEncoding,PdfVecObjects *pvecObjects); /** Try to guess the fonttype from a the filename of a font file. * * \param pszFilename filename of a fontfile * \returns the font type */ static EPdfFontType GetFontType( const char* pszFilename ); private: /** Actually creates the font object for the requested type. * Throws an exception in case of an error. * * \returns a new PdfFont object or NULL */ static PdfFont* CreateFontForType( EPdfFontType eType, PdfFontMetrics* pMetrics, const PdfEncoding* const pEncoding, bool bEmbed, bool bSubsetting, PdfVecObjects* pParent ); }; }; #endif /* _PDF_FONT_FACTORY_H_ */ podofo-0.9.3/src/doc/PdfFontMetricsBase14.cpp0000664000175000017500000002120312344436402020550 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2010 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfFontMetricsBase14.h" #include "base/PdfDefinesPrivate.h" #include "base/PdfArray.h" #include "PdfFontFactoryBase14Data.h" namespace PoDoFo { PdfFontMetricsBase14::PdfFontMetricsBase14(const char *mfont_name, const PODOFO_CharData *mwidths_table, bool mis_font_specific, pdf_int16 mascent, pdf_int16 mdescent, pdf_uint16 mx_height, pdf_uint16 mcap_height, const PdfRect & mbbox) : PdfFontMetrics( ePdfFontType_Type1Base14, "", NULL), font_name(mfont_name), widths_table(mwidths_table), is_font_specific(mis_font_specific), ascent(mascent), descent(mdescent), x_height(mx_height), cap_height(mcap_height), bbox(mbbox), m_bSymbol(is_font_specific) { m_nWeight = 500; m_nItalicAngle = 0; m_dLineSpacing = 0.0; m_dUnderlineThickness = 0.0; m_dUnderlinePosition = 0.0; m_dStrikeOutPosition = 0.0; m_dStrikeOutThickness = 0.0; units_per_EM = 1000; m_dPdfAscent = ascent * 1000 / units_per_EM; m_dPdfDescent = descent * 1000 / units_per_EM; m_dAscent = ascent; m_dDescent = descent; // calculate the line spacing now, as it changes only with the font size m_dLineSpacing = (static_cast(ascent + abs(descent)) / units_per_EM); m_dAscent = static_cast(ascent) / units_per_EM; m_dDescent = static_cast(descent) / units_per_EM; // Set default values for strikeout, in case the font has no direct values m_dStrikeOutPosition = m_dAscent / 2.0; // m_dStrikeOutThickness = m_dUnderlineThickness; } PdfFontMetricsBase14::~PdfFontMetricsBase14() { } double PdfFontMetricsBase14::GetGlyphWidth( int nGlyphId ) const { return widths_table[static_cast(nGlyphId)].width; } double PdfFontMetricsBase14::GetGlyphWidth( const char* ) const { return 0.0; } double PdfFontMetricsBase14::CharWidth( unsigned char c ) const { double dWidth = widths_table[static_cast(GetGlyphId(c) )].width; return dWidth * static_cast(this->GetFontSize() * this->GetFontScale() / 100.0) / 1000.0 + static_cast( this->GetFontSize() * this->GetFontScale() / 100.0 * this->GetFontCharSpace() / 100.0); } double PdfFontMetricsBase14::UnicodeCharWidth( unsigned short c ) const { double dWidth = 0.0; dWidth = widths_table[static_cast(GetGlyphIdUnicode(c) )].width; return dWidth * static_cast(this->GetFontSize() * this->GetFontScale() / 100.0) / 1000.0 + static_cast( this->GetFontSize() * this->GetFontScale() / 100.0 * this->GetFontCharSpace() / 100.0); } inline double PdfFontMetricsBase14::GetLineSpacing() const { return m_dLineSpacing * this->GetFontSize(); } inline double PdfFontMetricsBase14::GetUnderlineThickness() const { return m_dUnderlineThickness * this->GetFontSize(); } inline double PdfFontMetricsBase14::GetUnderlinePosition() const { return m_dUnderlinePosition * this->GetFontSize(); } inline double PdfFontMetricsBase14::GetStrikeOutPosition() const { return m_dStrikeOutPosition * this->GetFontSize(); } inline double PdfFontMetricsBase14::GetStrikeoutThickness() const { return m_dStrikeOutThickness * this->GetFontSize(); } const char* PdfFontMetricsBase14::GetFontname() const { #ifdef MYASSERT assert(font_name != NULL); #endif return font_name; } unsigned int PdfFontMetricsBase14::GetWeight() const { return m_nWeight; } double PdfFontMetricsBase14::GetAscent() const { return m_dAscent * this->GetFontSize(); } double PdfFontMetricsBase14::GetPdfAscent() const { return m_dPdfAscent; } double PdfFontMetricsBase14::GetDescent() const { return m_dDescent * this->GetFontSize(); } double PdfFontMetricsBase14::GetPdfDescent() const { return m_dPdfDescent; } int PdfFontMetricsBase14::GetItalicAngle() const { return m_nItalicAngle; } long PdfFontMetricsBase14::GetGlyphIdUnicode( long lUnicode ) const { long lGlyph = 0; // Handle symbol fonts! /* if( m_bSymbol ) { lUnicode = lUnicode | 0xf000; } */ for(int i = 0; widths_table[i].unicode != 0xFFFF ; ++i) { if (widths_table[i].unicode == lUnicode) { lGlyph = i; //widths_table[i].char_cd ; break; } } //FT_Get_Char_Index( m_face, lUnicode ); return lGlyph; } long PdfFontMetricsBase14::GetGlyphId( long charId ) const { long lGlyph = 0; // Handle symbol fonts! /* if( m_bSymbol ) { charId = charId | 0xf000; } */ for(int i = 0; widths_table[i].unicode != 0xFFFF ; ++i) { if (widths_table[i].char_cd == charId) { lGlyph = i; //widths_table[i].char_cd ; break; } } //FT_Get_Char_Index( m_face, lUnicode ); return lGlyph; } inline bool PdfFontMetricsBase14::IsSymbol() const { return m_bSymbol; } void PdfFontMetricsBase14::GetBoundingBox( PdfArray & array ) const { array.Clear(); array.push_back( PdfVariant( bbox.GetLeft() * 1000.0 / units_per_EM ) ); array.push_back( PdfVariant( bbox.GetBottom() * 1000.0 / units_per_EM ) ); array.push_back( PdfVariant( bbox.GetWidth() * 1000.0 / units_per_EM ) ); array.push_back( PdfVariant( bbox.GetHeight() * 1000.0 / units_per_EM ) ); return; } void PdfFontMetricsBase14::GetWidthArray( PdfVariant & var, unsigned int nFirst, unsigned int nLast ) const { unsigned int i; PdfArray list; for( i=nFirst;i<=nLast;i++ ) { list.push_back( PdfVariant( double(widths_table[i].width) ) ); } var = PdfVariant( list ); } const char* PdfFontMetricsBase14::GetFontData() const { return NULL; } pdf_long PdfFontMetricsBase14::GetFontDataLen() const { return 0; } }; podofo-0.9.3/src/doc/PdfOutlines.h0000664000175000017500000002632412344436402016633 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2006 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_OUTLINE_H_ #define _PDF_OUTLINE_H_ #include "podofo/base/PdfDefines.h" #include "PdfElement.h" namespace PoDoFo { class PdfDestination; class PdfAction; class PdfObject; class PdfOutlineItem; class PdfString; class PdfVecObjects; /** * The title of an outline item can be displayed * in different formating styles since PDF 1.4. */ enum EPdfOutlineFormat { ePdfOutlineFormat_Default = 0x00, /**< Default format */ ePdfOutlineFormat_Italic = 0x01, /**< Italic */ ePdfOutlineFormat_Bold = 0x02, /**< Bold */ ePdfOutlineFormat_BoldItalic = 0x03, /**< Bold Italic */ ePdfOutlineFormat_Unknown = 0xFF }; /** * A PDF outline item has an title and a destination. * It is an element in the documents outline which shows * its hierarchical structure. * * \see PdfDocument * \see PdfOutlines * \see PdfDestination */ class PODOFO_DOC_API PdfOutlineItem : public PdfElement { public: virtual ~PdfOutlineItem(); /** Create a PdfOutlineItem that is a child of this item * \param sTitle title of this item * \param rDest destination of this item */ PdfOutlineItem* CreateChild( const PdfString & sTitle, const PdfDestination & rDest ); /** Create a PdfOutlineItem that is on the same level and follows the current item. * \param sTitle title of this item * \param rDest destination of this item */ PdfOutlineItem* CreateNext ( const PdfString & sTitle, const PdfDestination & rDest ); /** Create a PdfOutlineItem that is on the same level and follows the current item. * \param sTitle title of this item * \param rAction action of this item */ PdfOutlineItem* CreateNext ( const PdfString & sTitle, const PdfAction & rAction ); /** Inserts an existing PdfOutlineItem as a child * of this outline item. * * \param pItem an existing outline item */ void InsertChild( PdfOutlineItem* pItem ); /** * \returns the previous item or NULL if this is the first on the current level */ inline PdfOutlineItem* Prev() const; /** * \returns the next item or NULL if this is the last on the current level */ inline PdfOutlineItem* Next() const; /** * \returns the first outline item that is a child of this item */ inline PdfOutlineItem* First() const; /** * \returns the last outline item that is a child of this item */ inline PdfOutlineItem* Last() const; /** * \returns the parent item of this item or NULL if it is * the top level outlines dictionary */ inline PdfOutlineItem* GetParentOutline() const; /** Deletes this outline item and all its children from * the outline hierarchy and removes all objects from * the list of PdfObjects * All pointers to this item will be invalid after this function * call. */ void Erase(); /** Set the destination of this outline. * \param rDest the destination */ void SetDestination( const PdfDestination & rDest ); /** Get the destination of this outline. * \param pDoc a PdfDocument owning this annotation. * This is required to resolve names and pages. * \returns the destination, if there is one, or NULL */ PdfDestination* GetDestination( PdfDocument* pDoc ); /** Set the action of this outline. * \param rAction the action */ void SetAction( const PdfAction & rAction ); /** Get the action of this outline. * \returns the action, if there is one, or NULL */ PdfAction* GetAction( void ); /** Set the title of this outline item * \param sTitle the title to use */ void SetTitle( const PdfString & sTitle ); /** Get the title of this item * \returns the title as PdfString */ const PdfString & GetTitle() const; /** Set the text format of the title. * Supported since PDF 1.4. * * \param eFormat the formatting options * for the title */ void SetTextFormat( EPdfOutlineFormat eFormat ); /** Get the text format of the title * \returns the text format of the title */ EPdfOutlineFormat GetTextFormat() const; /** Set the color of the title of this item. * This property is supported since PDF 1.4. * \param r red color component * \param g green color component * \param b blue color component */ void SetTextColor( double r, double g, double b ); /** Get the color of the title of this item. * Supported since PDF 1.4. * \returns the red color component * * \see SetTextColor */ double GetTextColorRed() const; /** Get the color of the title of this item. * Supported since PDF 1.4. * \returns the red color component * * \see SetTextColor */ double GetTextColorBlue() const; /** Get the color of the title of this item. * Supported since PDF 1.4. * \returns the red color component * * \see SetTextColor */ double GetTextColorGreen() const; private: void SetPrevious( PdfOutlineItem* pItem ); void SetNext ( PdfOutlineItem* pItem ); void SetLast ( PdfOutlineItem* pItem ); void SetFirst ( PdfOutlineItem* pItem ); protected: /** Create a new PdfOutlineItem dictionary * \param pParent parent vector of objects */ PdfOutlineItem( PdfVecObjects* pParent ); /** Create a new PdfOutlineItem from scratch * \param sTitle title of this item * \param rDest destination of this item * \param pParentOutline parent of this outline item * in the outline item hierarchie * \param pParent parent vector of objects which is required * to create new objects */ PdfOutlineItem( const PdfString & sTitle, const PdfDestination & rDest, PdfOutlineItem* pParentOutline, PdfVecObjects* pParent ); /** Create a new PdfOutlineItem from scratch * \param sTitle title of this item * \param rAction action of this item * \param pParentOutline parent of this outline item * in the outline item hierarchie * \param pParent parent vector of objects which is required * to create new objects */ PdfOutlineItem( const PdfString & sTitle, const PdfAction & rAction, PdfOutlineItem* pParentOutline, PdfVecObjects* pParent ); /** Create a PdfOutlineItem from an existing PdfObject * \param pObject an existing outline item * \param pParentOutline parent of this outline item * in the outline item hierarchie * \param pPrevious previous item of this item */ PdfOutlineItem( PdfObject* pObject, PdfOutlineItem* pParentOutline, PdfOutlineItem* pPrevious ); private: PdfOutlineItem* m_pParentOutline; PdfOutlineItem* m_pPrev; PdfOutlineItem* m_pNext; PdfOutlineItem* m_pFirst; PdfOutlineItem* m_pLast; PdfDestination* m_pDestination; PdfAction* m_pAction; }; // ----------------------------------------------------- // // ----------------------------------------------------- inline PdfOutlineItem* PdfOutlineItem::GetParentOutline() const { return m_pParentOutline; } // ----------------------------------------------------- // // ----------------------------------------------------- inline PdfOutlineItem* PdfOutlineItem::First() const { return m_pFirst; } // ----------------------------------------------------- // // ----------------------------------------------------- inline PdfOutlineItem* PdfOutlineItem::Last() const { return m_pLast; } // ----------------------------------------------------- // // ----------------------------------------------------- inline PdfOutlineItem* PdfOutlineItem::Prev() const { return m_pPrev; } // ----------------------------------------------------- // // ----------------------------------------------------- inline PdfOutlineItem* PdfOutlineItem::Next() const { return m_pNext; } /** The main PDF outlines dictionary. * * Do not create it by yourself but * use PdfDocument::GetOutlines() instead. * * \see PdfDocument */ class PODOFO_DOC_API PdfOutlines : public PdfOutlineItem { public: /** Create a new PDF outlines dictionary * \param pParent parent vector of objects */ PdfOutlines( PdfVecObjects* pParent ); /** Create a PDF outlines object from an existing dictionary * \param pObject an existing outlines dictionary */ PdfOutlines( PdfObject* pObject ); virtual ~PdfOutlines() { } /** Create the root node of the * outline item tree. * * \param sTitle the title of the root node */ PdfOutlineItem* CreateRoot( const PdfString & sTitle ); }; }; #endif // _PDF_OUTLINE_H_ podofo-0.9.3/src/doc/PdfFileSpec.h0000664000175000017500000001500012347312750016512 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2006 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_FILE_SPEC_H_ #define _PDF_FILE_SPEC_H_ #include "podofo/base/PdfDefines.h" #include "podofo/base/PdfString.h" #include "PdfElement.h" namespace PoDoFo { class PdfDocument; /** * A file specification is used in the PDF file to referr to another file. * The other file can be a file outside of the PDF or can be embedded into * the PDF file itself. */ class PODOFO_DOC_API PdfFileSpec : public PdfElement { public: PdfFileSpec( const char* pszFilename, bool bEmbedd, PdfDocument* pParent, bool bStripPath = false); PdfFileSpec( const char* pszFilename, bool bEmbedd, PdfVecObjects* pParent, bool bStripPath = false ); /* Petr P. Petrov 17 September 2009*/ /** Embeds the file in memory from "data" buffer under "pszFileName" fie name. */ PdfFileSpec( const char* pszFilename, const unsigned char* data, ptrdiff_t size, PdfVecObjects* pParent, bool bStripPath = false); PdfFileSpec( const char* pszFilename, const unsigned char* data, ptrdiff_t size, PdfDocument* pParent, bool bStripPath = false); #ifdef _WIN32 PdfFileSpec( const wchar_t* pszFilename, bool bEmbedd, PdfDocument* pParent, bool bStripPath = false ); PdfFileSpec( const wchar_t* pszFilename, bool bEmbedd, PdfVecObjects* pParent, bool bStripPath = false ); PdfFileSpec( const wchar_t* pszFilename, const unsigned char* data, ptrdiff_t size, PdfVecObjects* pParent, bool bStripPath = false); PdfFileSpec( const wchar_t* pszFilename, const unsigned char* data, ptrdiff_t size, PdfDocument* pParent, bool bStripPath = false); #endif PdfFileSpec( PdfObject* pObject ); /** Gets file name for the FileSpec * \param canUnicode Whether can return file name in unicode (/UF) * \returns the filename of this file specification. * if no general name is available * it will try the Unix, Mac and DOS keys too. */ const PdfString & GetFilename(bool canUnicode) const; private: /** Initialize a filespecification from a filename * \param pszFilename filename * \param bEmbedd embedd the file data into the PDF file * \param bStripPath whether to strip path from the file name string */ void Init( const char* pszFilename, bool bEmbedd, bool bStripPath ); /** Initialize a filespecification from an in-memory buffer * \param pszFilename filename * \param data Data of the file * \param size size of the data buffer * \param bStripPath whether to strip path from the file name string */ void Init( const char* pszFilename, const unsigned char* data, ptrdiff_t size, bool bStripPath ); /** Create a file specification string from a filename * \param pszFilename filename * \returns a file specification string */ PdfString CreateFileSpecification( const char* pszFilename ) const; /** Embedd a file into a stream object * \param pStream write the file to this objects stream * \param pszFilename the file to embedd */ void EmbeddFile( PdfObject* pStream, const char* pszFilename ) const; /** Strips path from a file, according to \a bStripPath * \param pszFilename a file name string * \param bStripPath whether to strip path from the file name string * \returns Either unchanged \a pszFilename, if \a bStripPath is false; * or \a pszFilename without a path part, if \a bStripPath is true */ const char *MaybeStripPath( const char* pszFilename, bool bStripPath ) const; #ifdef _WIN32 void Init( const wchar_t* pszFilename, bool bEmbedd, bool bStripPath ); void Init( const wchar_t* pszFilename, const unsigned char* data, ptrdiff_t size, bool bStripPath ); PdfString CreateFileSpecification( const wchar_t* pszFilename ) const; void EmbeddFile( PdfObject* pStream, const wchar_t* pszFilename ) const; const wchar_t *MaybeStripPath( const wchar_t* pszFilename, bool bStripPath ) const; #endif /* Petr P. Petrov 17 September 2009*/ /** Embeds the file from memory */ void EmbeddFileFromMem( PdfObject* pStream, const unsigned char* data, ptrdiff_t size ) const; }; }; #endif // _PDF_FILE_SPEC_H_ podofo-0.9.3/src/doc/PdfSignOutputDevice.cpp0000664000175000017500000001745512354031431020624 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2011 by Dominik Seichter * * domseichter@web.de * * by Petr Pytelka * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfSignOutputDevice.h" #include "../base/PdfArray.h" #include namespace PoDoFo { PdfSignOutputDevice::PdfSignOutputDevice(PdfOutputDevice *pRealDevice) { Init(); m_pRealDevice = pRealDevice; } PdfSignOutputDevice::PdfSignOutputDevice(const char* pszFilename) { Init(); m_pRealDevice = new PdfOutputDevice(pszFilename); m_bDevOwner = true; } #ifdef WIN32 PdfSignOutputDevice::PdfSignOutputDevice( const wchar_t* pszFilename ) { Init(); m_pRealDevice = new PdfOutputDevice(pszFilename); m_bDevOwner = true; } #endif void PdfSignOutputDevice::Init() { m_pSignatureBeacon = NULL; m_bBeaconFound = false; m_bDevOwner = false; } PdfSignOutputDevice::~PdfSignOutputDevice() { if(m_pSignatureBeacon!=NULL) { delete m_pSignatureBeacon; } if(m_bDevOwner) { delete m_pRealDevice; } } void PdfSignOutputDevice::SetSignatureSize(size_t lSignatureSize) { if(m_pSignatureBeacon!=NULL) { delete m_pSignatureBeacon; } const char srcBeacon[] = "###HERE_WILL_BE_SIGNATURE___"; size_t lLen = sizeof(srcBeacon); lSignatureSize = 2*lSignatureSize; char* pData = static_cast(malloc(lSignatureSize)); for(size_t i=0; idata().size()/2); } void PdfSignOutputDevice::SetSignature(const PdfData &sigData) { if(!m_bBeaconFound) { PODOFO_RAISE_ERROR( ePdfError_InternalLogic ); } size_t maxSigSize = m_pSignatureBeacon->data().size(); size_t sigByteSize = sigData.data().size(); // check signature size if((sigByteSize*2)> maxSigSize) { PODOFO_RAISE_ERROR( ePdfError_ValueOutOfRange ); } PdfString sig(sigData.data().c_str(), sigByteSize, true); m_pRealDevice->Seek(m_sBeaconPos); sig.Write(m_pRealDevice, PoDoFo::ePdfWriteMode_Compact); // insert padding size_t numPadding = maxSigSize-2*sigByteSize; if(numPadding>0) { // Seek back m_pRealDevice->Seek(m_pRealDevice->Tell()-1); while(numPadding>0) { char c='0'; m_pRealDevice->Write(&c, 1); numPadding--; } } } void PdfSignOutputDevice::AdjustByteRange() { if(!m_bBeaconFound) { PODOFO_RAISE_ERROR( ePdfError_InternalLogic ); } // Get final position size_t sFileEnd = GetLength(); PdfArray arr; arr.push_back( PdfVariant(static_cast(0)) ); arr.push_back( PdfVariant(static_cast(m_sBeaconPos)) ); arr.push_back( PdfVariant(static_cast(m_sBeaconPos+m_pSignatureBeacon->data().size()+2) ) ); arr.push_back( PdfVariant(static_cast(sFileEnd-(m_sBeaconPos+m_pSignatureBeacon->data().size()+2)) ) ); std::string sPosition; PdfVariant(arr).ToString(sPosition, ePdfWriteMode_Compact); // Fill padding unsigned int sPosSize = sizeof("[ 0 1234567890 1234567890 1234567890]")-1; if(sPosition.size()Seek(m_sBeaconPos-sPosition.size()-9); char ch; size_t offset = m_pRealDevice->Tell(); /* Sanity test, the file position should be at the '[' now */ if (m_pRealDevice->Read(&ch, 1) != 1 || ch != '[') { PODOFO_RAISE_ERROR( ePdfError_InternalLogic ); } else { m_pRealDevice->Seek(offset); } m_pRealDevice->Write(sPosition.c_str(), sPosition.size()); } size_t PdfSignOutputDevice::ReadForSignature(char* pBuffer, size_t lLen) { if(!m_bBeaconFound) { PODOFO_RAISE_ERROR( ePdfError_InternalLogic ); } size_t pos = m_pRealDevice->Tell(); size_t numRead = 0; // Check if we are before beacon if(pos0) { numRead = m_pRealDevice->Read(pBuffer, readSize); pBuffer += numRead; lLen -= numRead; if(lLen==0) return numRead; } } // shift at the end of beacon if( (pos+numRead)>= m_sBeaconPos && pos < (m_sBeaconPos+(m_pSignatureBeacon->data().size()+2) ) ) { m_pRealDevice->Seek(m_sBeaconPos+(m_pSignatureBeacon->data().size()+2) ); } // read after beacon lLen = PODOFO_MIN(lLen, m_pRealDevice->GetLength()-m_pRealDevice->Tell()); if(lLen==0) return numRead; return numRead+m_pRealDevice->Read(pBuffer, lLen); } void PdfSignOutputDevice::Write( const char* pBuffer, size_t lLen ) { // Check if data with beacon if(m_pSignatureBeacon!=NULL) { const std::string &data = m_pSignatureBeacon->data(); if(data.size()<=lLen) { const char *pStart = pBuffer; const char *pStop = pStart + (lLen-data.size()); for(; pStart<=pStop; pStart++) { if(memcmp(pStart, data.c_str(), data.size())==0) { // beacon found m_sBeaconPos = Tell(); m_sBeaconPos += (pStart - pBuffer - 1); m_bBeaconFound = true; } } } } m_pRealDevice->Write(pBuffer, lLen); } } podofo-0.9.3/src/doc/PdfFontMetrics.cpp0000664000175000017500000010140212344436402017610 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2005 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfFontMetrics.h" #include "base/PdfDefinesPrivate.h" #include "base/PdfArray.h" #include "base/PdfDictionary.h" #include "base/PdfVariant.h" #include "PdfFontFactory.h" #include #include #include #include FT_FREETYPE_H #include FT_TRUETYPE_TABLES_H #define PODOFO_FIRST_READABLE 31 #define PODOFO_WIDTH_CACHE_SIZE 256 namespace PoDoFo { #if defined(__APPLE_CC__) && !defined(PODOFO_HAVE_FONTCONFIG) #include #endif PdfFontMetrics::PdfFontMetrics( EPdfFontType eFontType, const char* pszFilename, const char* pszSubsetPrefix ) : m_sFilename( pszFilename ), m_fFontSize( 0.0f ), m_fFontScale( 100.0f ), m_fFontCharSpace( 0.0f ), m_fWordSpace( 0.0f ), m_eFontType( eFontType ), m_sFontSubsetPrefix( pszSubsetPrefix ? pszSubsetPrefix : "" ) { } /* PdfFontMetrics::PdfFontMetrics( FT_Library* pLibrary, PdfObject* pDescriptor ) : m_sFilename( "" ), m_pLibrary( pLibrary ), m_pMetrics_base14(NULL), m_bSymbol( false ), m_fFontSize( 0.0f ), m_fFontScale( 100.0f ), m_fFontCharSpace( 0.0f ), m_eFontType( ePdfFontType_Unknown ) { m_face = NULL; if( !pDescriptor ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } PdfName sName = pDescriptor->GetDictionary().GetKey( "FontName" )->GetName(); m_nWeight = static_cast(pDescriptor->GetDictionary().GetKeyAsLong( "FontWeight", 400L )); m_nItalicAngle = static_cast(pDescriptor->GetDictionary().GetKeyAsLong( "ItalicAngle", 0L )); m_dPdfAscent = pDescriptor->GetDictionary().GetKeyAsReal( "Ascent", 0.0 ); m_dPdfDescent = pDescriptor->GetDictionary().GetKeyAsReal( "Descent", 0.0 ); } */ PdfFontMetrics::~PdfFontMetrics() { } #if defined(__APPLE_CC__) && !defined(PODOFO_HAVE_FONTCONFIG) && !defined(PODOFO_NO_FONTMANAGER) FT_Error My_FT_GetFile_From_Mac_ATS_Name( const char* fontName, FSSpec* pathSpec, FT_Long* face_index ) { CFStringRef cf_fontName; ATSFontRef ats_font_id; *face_index = 0; cf_fontName = CFStringCreateWithCString( NULL, fontName, kCFStringEncodingMacRoman ); ats_font_id = ATSFontFindFromName( cf_fontName, kATSOptionFlagsUnRestrictedScope ); if ( ats_font_id == 0 || ats_font_id == 0xFFFFFFFFUL ) return FT_Err_Unknown_File_Format; if ( 0 != ATSFontGetFileSpecification( ats_font_id, pathSpec ) ) return FT_Err_Unknown_File_Format; /* face_index calculation by searching preceding fontIDs */ /* with same FSRef */ { int i; FSSpec f; for ( i = 1; i < ats_font_id; i++ ) { if ( 0 != ATSFontGetFileSpecification( ats_font_id - i, &f ) || f.vRefNum != pathSpec->vRefNum || f.parID != pathSpec->parID || f.name[0] != pathSpec->name[0] || 0 != ft_strncmp( (char *)f.name + 1, (char *)pathSpec->name + 1, f.name[0] ) ) break; } *face_index = ( i - 1 ); } return FT_Err_Ok; } FT_Error My_FT_GetFile_From_Mac_Name( const char* fontName, FSSpec* pathSpec, FT_Long* face_index ) { OptionBits options = kFMUseGlobalScopeOption; FMFontFamilyIterator famIter; OSStatus status = FMCreateFontFamilyIterator( NULL, NULL, options, &famIter ); FMFont the_font = NULL; FMFontFamily family = NULL; *face_index = 0; while ( status == 0 && !the_font ) { status = FMGetNextFontFamily( &famIter, &family ); if ( status == 0 ) { int stat2; FMFontFamilyInstanceIterator instIter; Str255 famNameStr; char famName[256]; /* get the family name */ FMGetFontFamilyName( family, famNameStr ); ( famNameStr, famName ); // inLog.Debug( boost::format( "Found FontFamily: '%s'\n" ) % famName ); /* iterate through the styles */ FMCreateFontFamilyInstanceIterator( family, &instIter ); *face_index = 0; stat2 = 0; while ( stat2 == 0 && !the_font ) { FMFontStyle style; FMFontSize size; FMFont font; stat2 = FMGetNextFontFamilyInstance( &instIter, &font, &style, &size ); if ( stat2 == 0 && size == 0 ) { char fullName[256]; /* build up a complete face name */ ft_strcpy( fullName, famName ); if ( style & bold ) strcat( fullName, " Bold" ); if ( style & italic ) strcat( fullName, " Italic" ); // inLog.Debug( boost::format( "Checking Face: '%s'\n" ) % fullName ); /* compare with the name we are looking for */ if ( ft_strcmp( fullName, fontName ) == 0 ) { /* found it! */ the_font = font; } else ++(*face_index); } } FMDisposeFontFamilyInstanceIterator( &instIter ); } } FMDisposeFontFamilyIterator( &famIter ); if ( the_font ) { FMGetFontContainer( the_font, pathSpec ); return FT_Err_Ok; } else return FT_Err_Unknown_File_Format; } /* Given a PostScript font name, create the Macintosh LWFN file name. */ static void create_lwfn_name( char* ps_name, Str255 lwfn_file_name ) { int max = 5, count = 0; FT_Byte* p = lwfn_file_name; FT_Byte* q = (FT_Byte*)ps_name; lwfn_file_name[0] = 0; while ( *q ) { if ( ft_isupper( *q ) ) { if ( count ) max = 3; count = 0; } if ( count < max && ( ft_isalnum( *q ) || *q == '_' ) ) { *++p = *q; lwfn_file_name[0]++; count++; } q++; } } static short count_faces_sfnt( char *fond_data ) { /* The count is 1 greater than the value in the FOND. */ /* Isn't that cute? :-) */ return 1 + *( (short *)( fond_data + sizeof ( FamRec ) ) ); } static void parse_fond( char* fond_data, short* have_sfnt, short* sfnt_id, char* ps_name, Str255 lwfn_file_name, short face_index ) { AsscEntry* assoc; AsscEntry* base_assoc; FamRec* fond; *sfnt_id = 0; *have_sfnt = 0; lwfn_file_name[0] = 0; fond = (FamRec*)fond_data; assoc = (AsscEntry*)( fond_data + sizeof ( FamRec ) + 2 ); base_assoc = assoc; /* Let's do a little range checking before we get too excited here */ if ( face_index < count_faces_sfnt( fond_data ) ) { assoc += face_index; /* add on the face_index! */ /* if the face at this index is not scalable, fall back to the first one (old behavior) */ if ( assoc->fontSize == 0 ) { *have_sfnt = 1; *sfnt_id = assoc->fontID; } else if ( base_assoc->fontSize == 0 ) { *have_sfnt = 1; *sfnt_id = base_assoc->fontID; } } if ( fond->ffStylOff ) { unsigned char* p = (unsigned char*)fond_data; StyleTable* style; unsigned short string_count; unsigned char* names[64]; int i; // inLog.Debug( "Font has StylOff\n" ); p += fond->ffStylOff; style = (StyleTable*)p; p += sizeof ( StyleTable ); string_count = *(unsigned short*)(p); p += sizeof ( short ); for ( i = 0 ; i < string_count && i < 64; i++ ) { names[i] = p; p += names[i][0]; p++; // inLog.Debug( boost::format( "Name[%d] is '%s'\n" ) % i % &names[i][1] ); } { size_t ps_name_len = (size_t)names[0][0]; if ( ps_name_len != 0 ) { ft_memcpy(ps_name, names[0] + 1, ps_name_len); ps_name[ps_name_len] = 0; } if ( style->indexes[0] > 1 ) { unsigned char* suffixes = names[style->indexes[0] - 1]; // inLog.Debug( boost::format( "string_count = %d\tsuffixes = %d\n" ) % string_count % (int)suffixes[0] ); for ( i = 1; i <= suffixes[0]; i++ ) { unsigned char* s; size_t j = suffixes[i] - 1; if ( j < string_count && ( s = names[j] ) != NULL ) { size_t s_len = (size_t)s[0]; s[s_len] = 0; // inLog.Debug( boost::format( "Suffix %d:'%s'\n" ) % i % &s[1] ); if ( s_len != 0 && ps_name_len + s_len < sizeof ( ps_name ) ) { ft_memcpy( ps_name + ps_name_len, s + 1, s_len ); ps_name_len += s_len; ps_name[ps_name_len] = 0; } } } } } // inLog.Debug( boost::format( "Found PSName is '%s'\n" ) % ps_name ); create_lwfn_name( ps_name, lwfn_file_name ); } } /* Given a file reference, answer its location as a vRefNum and a dirID. */ static FT_Error get_file_location( short ref_num, short* v_ref_num, long* dir_id, unsigned char* file_name ) { FCBPBRec pb; OSErr error; pb.ioNamePtr = file_name; pb.ioVRefNum = 0; pb.ioRefNum = ref_num; pb.ioFCBIndx = 0; error = PBGetFCBInfoSync( &pb ); if ( error == noErr ) { *v_ref_num = pb.ioFCBVRefNum; *dir_id = pb.ioFCBParID; } return error; } /* Return the file type of the file specified by spec. */ static OSType get_file_type( const FSSpec* spec ) { FInfo finfo; if ( FSpGetFInfo( spec, &finfo ) != noErr ) return 0; /* file might not exist */ return finfo.fdType; } /* Make a file spec for an LWFN file from a FOND resource and a file name. */ static FT_Error make_lwfn_spec( Handle fond, const unsigned char* file_name, FSSpec* spec ) { FT_Error error; short ref_num, v_ref_num; long dir_id; Str255 fond_file_name; ref_num = HomeResFile( fond ); error = ResError(); if ( !error ) error = get_file_location( ref_num, &v_ref_num, &dir_id, fond_file_name ); if ( !error ) error = FSMakeFSSpec( v_ref_num, dir_id, file_name, spec ); return error; } /* Read Type 1 data from the POST resources inside the LWFN file, return a PFB buffer. This is somewhat convoluted because the FT2 PFB parser wants the ASCII header as one chunk, and the LWFN chunks are often not organized that way, so we'll glue chunks of the same type together. */ static FT_Error read_lwfn( short res_ref, FT_Byte** pfb_data, FT_ULong* size ) { FT_Error error = FT_Err_Ok; short res_id; unsigned char *buffer, *p, *size_p = NULL; FT_ULong total_size = 0; FT_ULong post_size, pfb_chunk_size; Handle post_data; char code, last_code; UseResFile( res_ref ); /* First pass: load all POST resources, and determine the size of */ /* the output buffer. */ res_id = 501; last_code = -1; for (;;) { post_data = Get1Resource( 'POST', res_id++ ); if ( post_data == NULL ) break; /* we're done */ code = (*post_data)[0]; if ( code != last_code ) { if ( code == 5 ) total_size += 2; /* just the end code */ else total_size += 6; /* code + 4 bytes chunk length */ } total_size += GetHandleSize( post_data ) - 2; last_code = code; } buffer = (unsigned char*)malloc( total_size ); if ( buffer == NULL ) goto Error; /* Second pass: append all POST data to the buffer, add PFB fields. */ /* Glue all consecutive chunks of the same type together. */ p = buffer; res_id = 501; last_code = -1; pfb_chunk_size = 0; for (;;) { post_data = Get1Resource( 'POST', res_id++ ); if ( post_data == NULL ) break; /* we're done */ post_size = (FT_ULong)GetHandleSize( post_data ) - 2; code = (*post_data)[0]; if ( code != last_code ) { if ( last_code != -1 ) { /* we're done adding a chunk, fill in the size field */ if ( size_p != NULL ) { *size_p++ = (FT_Byte)( pfb_chunk_size & 0xFF ); *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 8 ) & 0xFF ); *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 16 ) & 0xFF ); *size_p++ = (FT_Byte)( ( pfb_chunk_size >> 24 ) & 0xFF ); } pfb_chunk_size = 0; } *p++ = 0x80; if ( code == 5 ) *p++ = 0x03; /* the end */ else if ( code == 2 ) *p++ = 0x02; /* binary segment */ else *p++ = 0x01; /* ASCII segment */ if ( code != 5 ) { size_p = p; /* save for later */ p += 4; /* make space for size field */ } } ft_memcpy( p, *post_data + 2, post_size ); pfb_chunk_size += post_size; p += post_size; last_code = code; } *pfb_data = buffer; *size = total_size; Error: CloseResFile( res_ref ); return error; } static short count_faces( Handle fond ) { short sfnt_id, have_sfnt, have_lwfn = 0; Str255 lwfn_file_name; FSSpec lwfn_spec; char ps_name[256]; HLock( fond ); parse_fond( *fond, &have_sfnt, &sfnt_id, ps_name, lwfn_file_name, 0 ); HUnlock( fond ); if ( lwfn_file_name[0] ) { if ( make_lwfn_spec( fond, lwfn_file_name, &lwfn_spec ) == FT_Err_Ok ) have_lwfn = 1; /* yeah, we got one! */ else have_lwfn = 0; /* no LWFN file found */ } if ( have_lwfn && ( !have_sfnt /*|| PREFER_LWFN*/ ) ) return 1; else return count_faces_sfnt( *fond ); } static FT_Error LoadFontFromLWFN( FSRef inFileRef, FSSpec inSpec, const char* inFontName, FT_Long inFaceIndex, char** outBuffer, long& outBufLen ) { FT_Error error = FT_Err_Ok; short res_ref; FT_Byte* pfb_data; FT_ULong pfb_size; // open up the resource file error = FSOpenResourceFile( &inFileRef, 0, NULL, fsRdPerm, &res_ref ); if ( error != noErr ) { // try old fashioned way // inLog.Debug( boost::format( "FSOpenResourceFile failed - Error %d\n" ) % error ); res_ref = FSpOpenResFile( &inSpec, fsRdPerm ); if ( res_ref < 0 ) { // inLog.Debug( boost::format( "FSpOpenResFile failed- Error %d\n" ) % res_ref ); return FT_Err_Cannot_Open_Resource; } else { // inLog.Debug( "FSpOpenResFile Succeeded!\n" ); } error = 0; // reset it } UseResFile( res_ref ); error = read_lwfn( res_ref, &pfb_data, &pfb_size ); if ( !error ) { *outBuffer = (char*)pfb_data; outBufLen = pfb_size; } else { // inLog.Debug( "read_lwfn failed\n" ); } Error: CloseResFile( res_ref ); return error; } static FT_Error LoadFontFromDFont( FSRef inFileRef, FSSpec inSpec, const char* inFontName, FT_Long inFaceIndex, char** outBuffer, long& outBufLen ) { const bool PREFER_LWFN=false; FT_Error error = FT_Err_Ok; short res_ref, res_index = 1; Handle fond; short sfnt_id = 0, have_sfnt =0, have_lwfn = 0; short num_faces; char ps_name[128]; Str255 lwfn_file_name; FSSpec lwfn_spec; char localFontName[256]; #if 1 int j = 0; bool foundSpace = false; for ( int i=0; i(pszFontname), &fSpec, &fIndex ); if ( error ) { // try use the alternate name... std::string altName = Std2AltFontName( pszFontname ); // mLog.Debug( boost::format("Unable to locate - trying alternate '%s'\n") % altName.c_str() ); error = My_FT_GetFile_From_Mac_ATS_Name( const_cast(altName.c_str()), &fSpec, &fIndex ); if ( error ) { // mLog.Debug( boost::format("Unable to locate - trying as Postscript\n") ); // see if this is a Postscript name... CFStringRef cstr = CFStringCreateWithCString( NULL, pszFontname, kCFStringEncodingUTF8 ); if ( cstr != NULL ) { ATSFontRef fontRef = ATSFontFindFromPostScriptName( cstr, kATSOptionFlagsDefault ); if ( fontRef != kATSFontRefUnspecified ) { // mLog.Debug( "**Found it!\n" ); error = ATSFontGetFileSpecification( fontRef, &fSpec ); } else { // mLog.Debug( boost::format("*Unable to locate as Postscript - giving up!\n") ); } CFRelease( cstr ); } } } if ( !error ) { FSRef ref; OSErr err = FSpMakeFSRef( &fSpec, &ref ); if ( !err ) { CFURLRef url = CFURLCreateFromFSRef( kCFAllocatorDefault, &ref ); CFStringRef pathRef = CFURLCopyFileSystemPath( url, kCFURLPOSIXPathStyle ); CFIndex length = CFStringGetLength( pathRef ) + 0x02; char* path = (char *)calloc( length, sizeof( *path ) ); if ( CFStringGetCString( pathRef, path, length, kCFStringEncodingUTF8 ) ) { std::string fontPath( path ); if ( (fontPath.find( ".ttf" ) != fontPath.npos) || (fontPath.find( ".otf" ) != fontPath.npos) ) { // mLog.Debug( boost::format("Found matching TTF/OTF font for '%s', index %d\n") % pszFontname % fIndex ); #if 1 //def FILE_BASED CPDFFTFont* ftFont = new CPDFFTFont( *this, fontPath, fIndex ); #else std::string fontBufStr; StringUtils::ReadFileIntoString( fontPath, fontBufStr ); ASInt32 fontBufferLen = fontBufStr.length(); if (fontBufferLen == 0) { CFRelease( pathRef ); CFRelease( url ); free(path); return NULL; } char* fontBuffer = (char*)ASmalloc( fontBufferLen ); memcpy( fontBuffer, fontBufStr.c_str(), fontBufferLen ); CPDFFTFont* ftFont = new CPDFFTFont( *this, fontBuffer, fontBufferLen, fIndex ); #endif retFont = reinterpret_cast< CPDFFont* >( ftFont ); } else if ( fontPath.find( ".dfont" ) != fontPath.npos ) { char* fontBuffer = NULL; ASInt32 fontBufferLen = 0; // mLog.Debug( boost::format("Found a matching .dfont for '%s', index %d\n") % pszFontname % fIndex ); FT_Error dfErr = LoadFontFromDFont( mLog, ref, fSpec, pszFontname, fIndex, &fontBuffer, fontBufferLen ); if ( !dfErr ) { CPDFFTFont* ftFont = new CPDFFTFont( *this, fontBuffer, fontBufferLen, fIndex ); retFont = reinterpret_cast< CPDFFont* >( ftFont ); } } else { char* fontBuffer = NULL; ASInt32 fontBufferLen = 0; fSpec.name[ fSpec.name[0]+1 ] = 0; // zero term for C func // mLog.Debug( boost::format("Found a matching CLASSIC font for '%s' at '%s', index %d\n") % pszFontname % &fSpec.name[1] % fIndex ); FT_Error dfErr = 0; OSType file_type = get_file_type( &fSpec ); if ( file_type == 'LWFN' ) { // mLog.Debug( "Loading from LWFN...\n" ); if ( fIndex > 0 ) fIndex = 0; // don't need it anymore... dfErr = LoadFontFromLWFN( mLog, ref, fSpec, pszFontname, fIndex, &fontBuffer, fontBufferLen ); } else { // mLog.Debug( "Loading from Suitcase...\n" ); dfErr = LoadFontFromDFont( mLog, ref, fSpec, pszFontname, fIndex, &fontBuffer, fontBufferLen ); } if ( !dfErr ) { CPDFFTFont* ftFont = new CPDFFTFont( *this, fontBuffer, fontBufferLen, fIndex ); retFont = reinterpret_cast< CPDFFont* >( ftFont ); } else { // mLog.Debug( boost::format("FTError: '%d'\n") % dfErr ); } } } else { // mLog.Debug( boost::format("Unable to locate a matching font for '%s'\n") % pszFontname ); } free( path ); CFRelease( pathRef ); CFRelease( url ); } } else { // mLog.Debug( boost::format("Unable to locate a matching font for '%s'\n") % pszFontname ); } } #endif // apple double PdfFontMetrics::StringWidth( const char* pszText, pdf_long nLength ) const { double dWidth = 0.0; if( !pszText ) return dWidth; if( !nLength ) nLength = strlen( pszText ); const char *localText = pszText; for ( pdf_long i=0; i(((*localText & 0x00ff) << 8 | (*localText & 0xff00) >> 8)); #else uChar = static_cast(*localText); #endif // PODOFO_IS_LITTLE_ENDIAN dWidth += UnicodeCharWidth( uChar ); if ( uChar == 0x0020 ) dWidth += m_fWordSpace; localText++; } return dWidth; } #ifndef _WCHAR_T_DEFINED #if defined(_MSC_VER) && _MSC_VER <= 1200 // nicht fr Visualstudio 6 #else double PdfFontMetrics::StringWidth( const wchar_t* pszText, unsigned int nLength ) const { double dWidth = 0.0; if( !pszText ) return dWidth; if( !nLength ) nLength = static_cast(wcslen( pszText )); const wchar_t *localText = pszText; for ( unsigned int i=0; i(*localText) ); if ( static_cast(*localText) == 0x0020 ) dWidth += m_fWordSpace; localText++; } return dWidth; } #endif #endif EPdfFontType PdfFontMetrics::FontTypeFromFilename( const char* pszFilename ) { EPdfFontType eFontType = PdfFontFactory::GetFontType( pszFilename ); if( eFontType == ePdfFontType_Unknown ) PdfError::DebugMessage( "Warning: Unrecognized FontFormat: %s\n", pszFilename ); return eFontType; } }; podofo-0.9.3/src/doc/PdfXObject.cpp0000664000175000017500000002772512347310654016733 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2006 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfXObject.h" #include "base/PdfDefinesPrivate.h" #include "base/PdfDictionary.h" #include "base/PdfLocale.h" #include "base/PdfRect.h" #include "base/PdfVariant.h" #include "PdfImage.h" #include "PdfPage.h" #include "PdfMemDocument.h" #include "PdfDocument.h" #include #define PI 3.141592654f using namespace std; namespace PoDoFo { PdfArray PdfXObject::s_matrix; PdfXObject::PdfXObject( const PdfRect & rRect, PdfDocument* pParent, const char* pszPrefix, bool bWithoutIdentifier ) : PdfElement( "XObject", pParent ), PdfCanvas(), m_rRect( rRect ) { InitXObject( rRect, pszPrefix ); if( bWithoutIdentifier ) { m_Identifier = PdfName(pszPrefix); } } PdfXObject::PdfXObject( const PdfRect & rRect, PdfVecObjects* pParent, const char* pszPrefix ) : PdfElement( "XObject", pParent ), PdfCanvas(), m_rRect( rRect ) { InitXObject( rRect, pszPrefix ); } PdfXObject::PdfXObject( const PdfMemDocument & rDoc, int nPage, PdfDocument* pParent, const char* pszPrefix, bool bUseTrimBox ) : PdfElement( "XObject", pParent ), PdfCanvas() { m_rRect = PdfRect(); InitXObject( m_rRect, pszPrefix ); // Implementation note: source document must be different from distination if ( pParent == reinterpret_cast(&rDoc) ) { PODOFO_RAISE_ERROR( ePdfError_InternalLogic ); } // After filling set correct BBox, independent of rotation m_rRect = pParent->FillXObjectFromDocumentPage( this, rDoc, nPage, bUseTrimBox ); PdfVariant var; m_rRect.ToVariant( var ); this->GetObject()->GetDictionary().AddKey( "BBox", var ); int rotation = rDoc.GetPage( nPage )->GetRotation(); // correct negative rotation if ( rotation < 0 ) rotation = 360 + rotation; // Swap offsets/width/height for vertical rotation switch ( rotation ) { case 90: case 270: { double temp; temp = m_rRect.GetWidth(); m_rRect.SetWidth( m_rRect.GetHeight() ); m_rRect.SetHeight( temp ); temp = m_rRect.GetLeft(); m_rRect.SetLeft( m_rRect.GetBottom() ); m_rRect.SetBottom( temp ); } break; default: break; } // Build matrix for rotation and cropping double alpha = -rotation / 360.0 * 2.0 * PI; double a, b, c, d, e, f; a = cos( alpha ); b = sin( alpha ); c = -sin( alpha ); d = cos( alpha ); switch ( rotation ) { case 90: e = - m_rRect.GetLeft(); f = m_rRect.GetBottom() + m_rRect.GetHeight(); break; case 180: e = m_rRect.GetLeft() + m_rRect.GetWidth(); f = m_rRect.GetBottom() + m_rRect.GetHeight(); break; case 270: e = m_rRect.GetLeft() + m_rRect.GetWidth(); f = - m_rRect.GetBottom(); break; case 0: default: e = - m_rRect.GetLeft(); f = - m_rRect.GetBottom(); break; } PdfArray matrix; matrix.push_back( PdfVariant( a ) ); matrix.push_back( PdfVariant( b ) ); matrix.push_back( PdfVariant( c ) ); matrix.push_back( PdfVariant( d ) ); matrix.push_back( PdfVariant( e ) ); matrix.push_back( PdfVariant( f ) ); this->GetObject()->GetDictionary().AddKey( "Matrix", matrix ); } PdfXObject::PdfXObject( PdfDocument *pDoc, int nPage, const char* pszPrefix, bool bUseTrimBox ) : PdfElement( "XObject", pDoc ), PdfCanvas() { m_rRect = PdfRect(); InitXObject( m_rRect, pszPrefix ); // After filling set correct BBox, independent of rotation m_rRect = pDoc->FillXObjectFromExistingPage( this, nPage, bUseTrimBox ); PdfVariant var; m_rRect.ToVariant( var ); this->GetObject()->GetDictionary().AddKey( "BBox", var ); int rotation = pDoc->GetPage( nPage )->GetRotation(); // correct negative rotation if ( rotation < 0 ) rotation = 360 + rotation; // Swap offsets/width/height for vertical rotation switch ( rotation ) { case 90: case 270: { double temp; temp = m_rRect.GetWidth(); m_rRect.SetWidth( m_rRect.GetHeight() ); m_rRect.SetHeight( temp ); temp = m_rRect.GetLeft(); m_rRect.SetLeft( m_rRect.GetBottom() ); m_rRect.SetBottom( temp ); } break; default: break; } // Build matrix for rotation and cropping double alpha = -rotation / 360.0 * 2.0 * PI; double a, b, c, d, e, f; a = cos( alpha ); b = sin( alpha ); c = -sin( alpha ); d = cos( alpha ); switch ( rotation ) { case 90: e = - m_rRect.GetLeft(); f = m_rRect.GetBottom() + m_rRect.GetHeight(); break; case 180: e = m_rRect.GetLeft() + m_rRect.GetWidth(); f = m_rRect.GetBottom() + m_rRect.GetHeight(); break; case 270: e = m_rRect.GetLeft() + m_rRect.GetWidth(); f = - m_rRect.GetBottom(); break; case 0: default: e = - m_rRect.GetLeft(); f = - m_rRect.GetBottom(); break; } PdfArray matrix; matrix.push_back( PdfVariant( a ) ); matrix.push_back( PdfVariant( b ) ); matrix.push_back( PdfVariant( c ) ); matrix.push_back( PdfVariant( d ) ); matrix.push_back( PdfVariant( e ) ); matrix.push_back( PdfVariant( f ) ); this->GetObject()->GetDictionary().AddKey( "Matrix", matrix ); } PdfXObject::PdfXObject( PdfObject* pObject ) : PdfElement( "XObject", pObject ), PdfCanvas() { ostringstream out; PdfLocaleImbue(out); // Implementation note: the identifier is always // Prefix+ObjectNo. Prefix is /XOb for XObject. out << "XOb" << this->GetObject()->Reference().ObjectNumber(); m_pResources = pObject->GetIndirectKey( "Resources" ); m_Identifier = PdfName( out.str().c_str() ); m_rRect = PdfRect( this->GetObject()->GetIndirectKey( "BBox" )->GetArray() ); m_Reference = this->GetObject()->Reference(); } void PdfXObject::InitXObject( const PdfRect & rRect, const char* pszPrefix ) { PdfVariant var; ostringstream out; PdfLocaleImbue(out); // Initialize static data if( s_matrix.empty() ) { // This matrix is the same for all PdfXObjects so cache it s_matrix.push_back( PdfVariant( static_cast(PODOFO_LL_LITERAL(1)) ) ); s_matrix.push_back( PdfVariant( static_cast(PODOFO_LL_LITERAL(0)) ) ); s_matrix.push_back( PdfVariant( static_cast(PODOFO_LL_LITERAL(0)) ) ); s_matrix.push_back( PdfVariant( static_cast(PODOFO_LL_LITERAL(1)) ) ); s_matrix.push_back( PdfVariant( static_cast(PODOFO_LL_LITERAL(0)) ) ); s_matrix.push_back( PdfVariant( static_cast(PODOFO_LL_LITERAL(0)) ) ); } rRect.ToVariant( var ); this->GetObject()->GetDictionary().AddKey( "BBox", var ); this->GetObject()->GetDictionary().AddKey( PdfName::KeySubtype, PdfName("Form") ); this->GetObject()->GetDictionary().AddKey( "FormType", PdfVariant( static_cast(PODOFO_LL_LITERAL(1)) ) ); // only 1 is only defined in the specification. this->GetObject()->GetDictionary().AddKey( "Matrix", s_matrix ); // The PDF specification suggests that we send all available PDF Procedure sets this->GetObject()->GetDictionary().AddKey( "Resources", PdfObject( PdfDictionary() ) ); m_pResources = this->GetObject()->GetDictionary().GetKey( "Resources" ); m_pResources->GetDictionary().AddKey( "ProcSet", PdfCanvas::GetProcSet() ); // Implementation note: the identifier is always // Prefix+ObjectNo. Prefix is /XOb for XObject. if ( pszPrefix == NULL ) out << "XOb" << this->GetObject()->Reference().ObjectNumber(); else out << pszPrefix << this->GetObject()->Reference().ObjectNumber(); m_Identifier = PdfName( out.str().c_str() ); m_Reference = this->GetObject()->Reference(); } PdfXObject::PdfXObject( const char* pszSubType, PdfDocument* pParent, const char* pszPrefix ) : PdfElement( "XObject", pParent ) { ostringstream out; PdfLocaleImbue(out); // Implementation note: the identifier is always // Prefix+ObjectNo. Prefix is /XOb for XObject. if ( pszPrefix == NULL ) out << "XOb" << this->GetObject()->Reference().ObjectNumber(); else out << pszPrefix << this->GetObject()->Reference().ObjectNumber(); m_Identifier = PdfName( out.str().c_str() ); m_Reference = this->GetObject()->Reference(); this->GetObject()->GetDictionary().AddKey( PdfName::KeySubtype, PdfName( pszSubType ) ); } PdfXObject::PdfXObject( const char* pszSubType, PdfVecObjects* pParent, const char* pszPrefix ) : PdfElement( "XObject", pParent ) { ostringstream out; PdfLocaleImbue(out); // Implementation note: the identifier is always // Prefix+ObjectNo. Prefix is /XOb for XObject. if ( pszPrefix == NULL ) out << "XOb" << this->GetObject()->Reference().ObjectNumber(); else out << pszPrefix << this->GetObject()->Reference().ObjectNumber(); m_Identifier = PdfName( out.str().c_str() ); m_Reference = this->GetObject()->Reference(); this->GetObject()->GetDictionary().AddKey( PdfName::KeySubtype, PdfName( pszSubType ) ); } PdfXObject::PdfXObject( const char* pszSubType, PdfObject* pObject ) : PdfElement( "XObject", pObject ) { ostringstream out; PdfLocaleImbue(out); if( this->GetObject()->GetDictionary().GetKeyAsName( PdfName::KeySubtype ) != pszSubType ) { PODOFO_RAISE_ERROR( ePdfError_InvalidDataType ); } // Implementation note: the identifier is always // Prefix+ObjectNo. Prefix is /XOb for XObject. out << "XOb" << this->GetObject()->Reference().ObjectNumber(); m_Identifier = PdfName( out.str().c_str() ); m_Reference = this->GetObject()->Reference(); } }; podofo-0.9.3/src/doc/PdfPagesTreeCache.h0000664000175000017500000001172712344436402017635 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2009 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_PAGES_TREE_CACHE_H_ #define _PDF_PAGES_TREE_CACHE_H_ #include "podofo/base/PdfDefines.h" namespace PoDoFo { class PdfPage; /** * This class implements a cache infront of a PdfPagesTree * * \see PdfCachedPagesTree */ class PODOFO_DOC_API PdfPagesTreeCache { typedef std::deque< PdfPage* > PdfPageList; public: /** Construct a new PdfCachedPagesTree. * * @param nInitialSize initial size of the pagestree */ PdfPagesTreeCache( int nInitialSize ); /** Close/down destruct a PdfCachedPagesTree */ virtual ~PdfPagesTreeCache(); /** Return a PdfPage for the specified Page index * The returned page is owned by the pages tree and * deleted along with it. * * \param nIndex page index, 0-based * \returns a pointer to the requested page or NULL if it is not cached */ virtual PdfPage* GetPage( int nIndex ); /** * Add a PdfPage object to the cache * @param nIndex index of the page * @param pPage page object */ virtual void AddPageObject( int nIndex, PdfPage* pPage ); /** * Add several PdfPage objects to the cache, replacing any existing at the given index * @param nIndex zero based index of where the first page will be placed * @param vecPages vector of the page objects to add */ virtual void AddPageObjects( int nIndex, std::vector vecPages ); /** * A page was inserted into the pagestree, * therefore the cache has to be updated * * @param nAfterPageIndex zero based index of the page we are inserting after * - may be one of the special values from EPdfPageInsertionPoint. */ virtual void InsertPage( int nAfterPageIndex ); /** * Insert several pages into the pagestree, after the given index * therefore the cache has to be updated * * @param nAfterPageIndex zero based index of the page we are inserting after * - may be one of the special values from EPdfPageInsertionPoint. * @param nCount number of pages that were inserted */ virtual void InsertPages( int nAfterPageIndex, int nCount ); /** * Delete a PdfPage from the cache * @param nIndex index of the page */ virtual void DeletePage( int nIndex ); /** * Clear cache, i.e. remove all elements from the * cache. */ virtual void ClearCache(); private: /** * Avoid construction of empty objects */ PdfPagesTreeCache() { } private: PdfPageList m_deqPageObjs; }; }; #endif // _PDF_PAGES_TREE_CACHE_H_ podofo-0.9.3/src/doc/PdfFontFactory.cpp0000664000175000017500000003561512347316204017625 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2007 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfFontFactory.h" #include "base/PdfDefinesPrivate.h" #include "base/PdfArray.h" #include "base/PdfDictionary.h" #include "base/PdfEncoding.h" #include "base/PdfEncodingFactory.h" #include "PdfEncodingObjectFactory.h" #include "PdfFont.h" #include "PdfFontCID.h" #include "PdfFontMetrics.h" #include "PdfFontMetricsBase14.h" #include "PdfFontMetricsObject.h" #include "PdfFontType1.h" #include "PdfFontType3.h" #include "PdfFontType1Base14.h" #include "PdfFontTrueType.h" #include "PdfFontFactoryBase14Data.h" namespace PoDoFo { PdfFont* PdfFontFactory::CreateFontObject( PdfFontMetrics* pMetrics, int nFlags, const PdfEncoding* const pEncoding, PdfVecObjects* pParent ) { PdfFont* pFont = NULL; EPdfFontType eType = pMetrics->GetFontType(); bool bEmbed = nFlags & ePdfFont_Embedded; bool bSubsetting = (nFlags & ePdfFont_Subsetting) != 0; try { pFont = PdfFontFactory::CreateFontForType( eType, pMetrics, pEncoding, bEmbed, bSubsetting, pParent ); if( pFont ) { pFont->SetBold( nFlags & ePdfFont_Bold ? true : false ); pFont->SetItalic( nFlags & ePdfFont_Italic ? true : false ); } else { // something went wrong, so we have to delete // the font metrics delete pMetrics; // make sure this will be done before the catch block // as the encoding might be deleted already // afterwars, but we cannot set the pointer to NULL if( pEncoding && pEncoding->IsAutoDelete() ) delete pEncoding; } } catch( PdfError & e ) { // we have to delete the pMetrics object in case of error if( pFont ) { // The font will delete encoding and metrics delete pFont; pFont = NULL; } else { // something went wrong, so we have to delete // the font metrics (and if auto-delete, also the encoding) delete pMetrics; pMetrics = NULL; if( pEncoding && pEncoding->IsAutoDelete() ) delete pEncoding; } e.AddToCallstack( __FILE__, __LINE__, "Font creation failed." ); throw e; } return pFont; } PdfFont* PdfFontFactory::CreateFontForType( EPdfFontType eType, PdfFontMetrics* pMetrics, const PdfEncoding* const pEncoding, bool bEmbed, bool bSubsetting, PdfVecObjects* pParent ) { PdfFont* pFont = NULL; if( pEncoding->IsSingleByteEncoding() ) { switch( eType ) { case ePdfFontType_TrueType: // Peter Petrov 30 April 2008 - added bEmbed parameter pFont = new PdfFontTrueType( pMetrics, pEncoding, pParent, bEmbed ); break; case ePdfFontType_Type1Pfa: case ePdfFontType_Type1Pfb: if ( bSubsetting ) { // don't embed yet for subsetting pFont = new PdfFontType1( pMetrics, pEncoding, pParent, false, true ); } else pFont = new PdfFontType1( pMetrics, pEncoding, pParent, bEmbed ); break; case ePdfFontType_Type3: pFont = new PdfFontType3( pMetrics, pEncoding, pParent, bEmbed ); break; case ePdfFontType_Unknown: case ePdfFontType_Type1Base14: default: PdfError::LogMessage( eLogSeverity_Error, "The font format is unknown. Fontname: %s Filename: %s\n", (pMetrics->GetFontname() ? pMetrics->GetFontname() : ""), (pMetrics->GetFilename() ? pMetrics->GetFilename() : "") ); } } else { switch( eType ) { case ePdfFontType_TrueType: // Peter Petrov 30 April 2008 - added bEmbed parameter pFont = new PdfFontCID( pMetrics, pEncoding, pParent, bEmbed, bSubsetting ); break; case ePdfFontType_Type1Pfa: case ePdfFontType_Type1Pfb: case ePdfFontType_Type1Base14: case ePdfFontType_Type3: case ePdfFontType_Unknown: default: PdfError::LogMessage( eLogSeverity_Error, "The font format is unknown or no multibyte encoding defined. Fontname: %s Filename: %s\n", (pMetrics->GetFontname() ? pMetrics->GetFontname() : ""), (pMetrics->GetFilename() ? pMetrics->GetFilename() : "") ); } } return pFont; } PdfFont* PdfFontFactory::CreateFont( FT_Library*, PdfObject* pObject ) { PdfFontMetrics* pMetrics = NULL; PdfFont* pFont = NULL; PdfObject* pDescriptor = NULL; PdfObject* pEncoding = NULL; if( pObject->GetDictionary().GetKey( PdfName::KeyType )->GetName() != PdfName("Font") ) { PODOFO_RAISE_ERROR( ePdfError_InvalidDataType ); } const PdfName & rSubType = pObject->GetDictionary().GetKey( PdfName::KeySubtype )->GetName(); if( rSubType == PdfName("Type0") ) { // The PDF reference states that DescendantFonts must be an array, // some applications (e.g. MS Word) put the array into an indirect object though. const PdfArray & descendant = pObject->GetIndirectKey( "DescendantFonts" )->GetArray(); PdfObject* pFontObject = pObject->GetOwner()->GetObject( descendant[0].GetReference() ); pDescriptor = pFontObject->GetIndirectKey( "FontDescriptor" ); pEncoding = pObject->GetIndirectKey( "Encoding" ); if ( pEncoding && pDescriptor ) // OC 18.08.2010: Avoid sigsegv { // TODO: If /ToUnicode is absent, use the CID font's predefined character collection // (/CIDSystemInfo<>) const PdfEncoding* const pPdfEncoding = PdfEncodingObjectFactory::CreateEncoding( pEncoding, pObject->GetIndirectKey("ToUnicode") ); // OC 15.08.2010 BugFix: Parameter pFontObject added: TODO: untested pMetrics = new PdfFontMetricsObject( pFontObject, pDescriptor, pPdfEncoding ); pFont = new PdfFontCID( pMetrics, pPdfEncoding, pObject, false ); } } else if( rSubType == PdfName("Type1") ) { // TODO: Old documents do not have a FontDescriptor for // the 14 standard fonts. This suggestions is // deprecated now, but give us problems with old documents. pDescriptor = pObject->GetIndirectKey( "FontDescriptor" ); pEncoding = pObject->GetIndirectKey( "Encoding" ); // OC 13.08.2010: Handle missing FontDescriptor for the 14 standard fonts: if( !pDescriptor ) { // Check if its a PdfFontType1Base14 PdfObject* pBaseFont = NULL; pBaseFont = pObject->GetIndirectKey( "BaseFont" ); const char* pszBaseFontName = pBaseFont->GetName().GetName().c_str(); PdfFontMetricsBase14* pMetrics = PODOFO_Base14FontDef_FindBuiltinData(pszBaseFontName); if ( pMetrics != NULL ) { // pEncoding may be undefined, found a valid pdf with // 20 0 obj // << // /Type /Font // /BaseFont /ZapfDingbats // /Subtype /Type1 // >> // endobj // If pEncoding is null then // use StandardEncoding for Courier, Times, Helvetica font families // and special encodings for Symbol and ZapfDingbats const PdfEncoding* pPdfEncoding = NULL; if ( pEncoding!= NULL ) pPdfEncoding = PdfEncodingObjectFactory::CreateEncoding( pEncoding ); else if ( !pMetrics->IsSymbol() ) pPdfEncoding = PdfEncodingFactory::GlobalStandardEncodingInstance(); else if ( strcmp(pszBaseFontName, "Symbol") == 0 ) pPdfEncoding = PdfEncodingFactory::GlobalSymbolEncodingInstance(); else if ( strcmp(pszBaseFontName, "ZapfDingbats") == 0 ) pPdfEncoding = PdfEncodingFactory::GlobalZapfDingbatsEncodingInstance(); return new PdfFontType1Base14(pMetrics, pPdfEncoding, pObject); } } const PdfEncoding* pPdfEncoding = NULL; if ( pEncoding != NULL ) pPdfEncoding = PdfEncodingObjectFactory::CreateEncoding( pEncoding ); else if ( pDescriptor ) { // OC 18.08.2010 TODO: Encoding has to be taken from the font's built-in encoding // Its extremely complicated to interpret the type1 font programs // so i try to determine if its a symbolic font by reading the FontDescriptor Flags // Flags & 4 --> Symbolic, Flags & 32 --> Nonsymbolic pdf_int32 lFlags = static_cast(pDescriptor->GetDictionary().GetKeyAsLong( "Flags", 0L )); if ( lFlags & 32 ) // Nonsymbolic, otherwise pEncoding remains NULL pPdfEncoding = PdfEncodingFactory::GlobalStandardEncodingInstance(); } if ( pPdfEncoding && pDescriptor ) // OC 18.08.2010: Avoid sigsegv { // OC 15.08.2010 BugFix: Parameter pObject added: pMetrics = new PdfFontMetricsObject( pObject, pDescriptor, pPdfEncoding ); pFont = new PdfFontType1( pMetrics, pPdfEncoding, pObject ); } } else if( rSubType == PdfName("Type3") ) { pDescriptor = pObject->GetIndirectKey( "FontDescriptor" ); pEncoding = pObject->GetIndirectKey( "Encoding" ); if ( pEncoding ) // FontDescriptor may only be present in PDF 1.5+ { const PdfEncoding* const pPdfEncoding = PdfEncodingObjectFactory::CreateEncoding( pEncoding, NULL, true ); pMetrics = new PdfFontMetricsObject( pObject, pDescriptor, pPdfEncoding ); pFont = new PdfFontType3( pMetrics, pPdfEncoding, pObject ); } } else if( rSubType == PdfName("TrueType") ) { pDescriptor = pObject->GetIndirectKey( "FontDescriptor" ); pEncoding = pObject->GetIndirectKey( "Encoding" ); if ( pEncoding && pDescriptor ) // OC 18.08.2010: Avoid sigsegv { const PdfEncoding* const pPdfEncoding = PdfEncodingObjectFactory::CreateEncoding( pEncoding ); // OC 15.08.2010 BugFix: Parameter pObject added: pMetrics = new PdfFontMetricsObject( pObject, pDescriptor, pPdfEncoding ); pFont = new PdfFontTrueType( pMetrics, pPdfEncoding, pObject ); } } return pFont; } EPdfFontType PdfFontFactory::GetFontType( const char* pszFilename ) { EPdfFontType eFontType = ePdfFontType_Unknown; // We check by file extension right now // which is not quite correct, but still better than before if( pszFilename && strlen( pszFilename ) > 3 ) { const char* pszExtension = pszFilename + strlen( pszFilename ) - 3; if( PoDoFo::compat::strncasecmp( pszExtension, "ttf", 3 ) == 0 ) eFontType = ePdfFontType_TrueType; else if( PoDoFo::compat::strncasecmp( pszExtension, "pfa", 3 ) == 0 ) eFontType = ePdfFontType_Type1Pfa; else if( PoDoFo::compat::strncasecmp( pszExtension, "pfb", 3 ) == 0 ) eFontType = ePdfFontType_Type1Pfb; } return eFontType; } PdfFontMetricsBase14* PODOFO_Base14FontDef_FindBuiltinData(const char *font_name) { unsigned int i = 0; bool found = false; while (PODOFO_BUILTIN_FONTS[i].font_name) { if (strcmp(PODOFO_BUILTIN_FONTS[i].font_name, font_name) == 0) // kaushik : HPDFStrcmp changed to strcmp { found = true; break; } i++; } return found ? &PODOFO_BUILTIN_FONTS[i] : NULL; } PdfFont *PdfFontFactory::CreateBase14Font(const char* pszFontName, int nFlags, const PdfEncoding * const pEncoding, PdfVecObjects *pvecObjects) { PdfFont *pFont = new PdfFontType1Base14(PODOFO_Base14FontDef_FindBuiltinData(pszFontName), pEncoding, pvecObjects); if (pFont) { pFont->SetBold( nFlags & ePdfFont_Bold ? true : false ); pFont->SetItalic( nFlags & ePdfFont_Italic ? true : false ); } return pFont; } }; podofo-0.9.3/src/doc/PdfAnnotation.h0000664000175000017500000003512312344436402017140 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2006 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_ANNOTATION_H_ #define _PDF_ANNOTATION_H_ #include "podofo/base/PdfDefines.h" #include "PdfAction.h" #include "PdfDestination.h" #include "PdfElement.h" namespace PoDoFo { class PdfFileSpec; class PdfName; class PdfPage; class PdfRect; class PdfReference; class PdfString; class PdfXObject; /** The type of the annotation. * PDF supports different annotation types, each of * them has different keys and propeties. * * Not all annotation types listed here are supported yet. * * Please make also sure that the annotation type you use is * supported by the PDF version you are using. */ enum EPdfAnnotation { ePdfAnnotation_Text = 0, // - supported ePdfAnnotation_Link, // - supported ePdfAnnotation_FreeText, // PDF 1.3 // - supported ePdfAnnotation_Line, // PDF 1.3 // - supported ePdfAnnotation_Square, // PDF 1.3 ePdfAnnotation_Circle, // PDF 1.3 ePdfAnnotation_Polygon, // PDF 1.5 ePdfAnnotation_PolyLine, // PDF 1.5 ePdfAnnotation_Highlight, // PDF 1.3 ePdfAnnotation_Underline, // PDF 1.3 ePdfAnnotation_Squiggly, // PDF 1.4 ePdfAnnotation_StrikeOut, // PDF 1.3 ePdfAnnotation_Stamp, // PDF 1.3 ePdfAnnotation_Caret, // PDF 1.5 ePdfAnnotation_Ink, // PDF 1.3 ePdfAnnotation_Popup, // PDF 1.3 // - supported ePdfAnnotation_FileAttachement,// PDF 1.3 ePdfAnnotation_Sound, // PDF 1.2 ePdfAnnotation_Movie, // PDF 1.2 ePdfAnnotation_Widget, // PDF 1.2 // - supported ePdfAnnotation_Screen, // PDF 1.5 ePdfAnnotation_PrinterMark, // PDF 1.4 ePdfAnnotation_TrapNet, // PDF 1.3 ePdfAnnotation_Watermark, // PDF 1.6 ePdfAnnotation_3D, // PDF 1.6 ePdfAnnotation_RichMedia, // PDF 1.7 ADBE ExtensionLevel 3 ALX: Petr P. Petrov ePdfAnnotation_WebMedia, // PDF 1.7 IPDF ExtensionLevel 3 ePdfAnnotation_Unknown = 0xff }; /** Flags that control the appearance of a PdfAnnotation. * You can OR them together and pass it to * PdfAnnotation::SetFlags. */ enum EPdfAnnotationFlags { ePdfAnnotationFlags_Invisible = 0x0001, ePdfAnnotationFlags_Hidden = 0x0002, ePdfAnnotationFlags_Print = 0x0004, ePdfAnnotationFlags_NoZoom = 0x0008, ePdfAnnotationFlags_NoRotate = 0x0010, ePdfAnnotationFlags_NoView = 0x0020, ePdfAnnotationFlags_ReadOnly = 0x0040, ePdfAnnotationFlags_Locked = 0x0080, ePdfAnnotationFlags_ToggleNoView = 0x0100, ePdfAnnotationFlags_LockedContents = 0x0200, ePdfAnnotationFlags_Unknow = 0xffff }; /** An annotation to a PdfPage * To create an annotation use PdfPage::CreateAnnotation * * \see PdfPage::CreateAnnotation */ class PODOFO_DOC_API PdfAnnotation : public PdfElement { public: /** Create a new annotation object * * \param pPage the parent page of this annotation * \param eAnnot type of the annotation * \param rRect the rectangle in which the annotation will appear on the page * \param pParent parent of this annotation * * \see PdfPage::CreateAnnotation */ PdfAnnotation( PdfPage* pPage, EPdfAnnotation eAnnot, const PdfRect & rRect, PdfVecObjects* pParent ); /** Create a PdfAnnotation from an existing object * * \param pObject the annotations object * \param pPage the page of the annotation */ PdfAnnotation( PdfObject* pObject, PdfPage* pPage ); ~PdfAnnotation(); /** Set an appearance stream for this object * to specify its visual appearance * \param pObject an XObject */ void SetAppearanceStream( PdfXObject* pObject ); /** * \returns true if this annotation has an appearance stream */ bool HasAppearanceStream() const; /** Get the rectangle of this annotation * \returns a rectangle */ PdfRect GetRect() const; /** Set the flags of this annotation. * \param uiFlags is an unsigned 32bit integer with different * EPdfAnnotationFlags OR'ed together. * \see GetFlags */ void SetFlags( pdf_uint32 uiFlags ); /** Get the flags of this annotation. * \returns the flags which is an unsigned 32bit integer with different * EPdfAnnotationFlags OR'ed together. * * \see SetFlags */ pdf_uint32 GetFlags() const; /** Set the annotations border style. * \param dHCorner horitzontal corner radius * \param dVCorner vertical corner radius * \param dWidth width of border */ void SetBorderStyle( double dHCorner, double dVCorner, double dWidth ); /** Set the annotations border style. * \param dHCorner horitzontal corner radius * \param dVCorner vertical corner radius * \param dWidth width of border * \param rStrokeStyle a custom stroke style pattern */ void SetBorderStyle( double dHCorner, double dVCorner, double dWidth, const PdfArray & rStrokeStyle ); /** Set the title of this annotation. * \param sTitle title of the annoation as string in PDF format * * \see GetTitle */ void SetTitle( const PdfString & sTitle ); /** Get the title of this annotation * * \returns the title of this annotation * * \see SetTitle */ PdfString GetTitle() const; /** Set the text of this annotation. * * \param sContents text of the annoation as string in PDF format * * \see GetContents */ void SetContents( const PdfString & sContents ); /** Get the text of this annotation * * \returns the contents of this annotation * * \see SetContents */ PdfString GetContents() const; /** Set the destination for link annotations * \param rDestination target of the link * * \see GetDestination */ void SetDestination( const PdfDestination & rDestination ); /** Get the destination of a link annotations * \param pDoc a PdfDocument owning this annotation. * This is required to resolve names and pages. * \returns a destination object * * \see SetDestination */ PdfDestination GetDestination( PdfDocument* pDoc ) const; /** * \returns true if this annotation has an destination */ bool HasDestination() const; /** Set the action that is executed for this annotation * \param rAction an action object * * \see GetAction */ void SetAction( const PdfAction & rAction ); /** Get the action that is executed for this annotation * \returns an action object. The action object is owned * by the PdfAnnotation. * * \see SetAction */ PdfAction* GetAction() const; /** * \returns true if this annotation has an action */ bool HasAction() const; /** Sets wether this annotation is initialy open. * You should always set this true for popup annotations. * \param b if true open it */ void SetOpen( bool b ); /** * \returns true if this annotation should be opened immediately * by the viewer */ bool GetOpen() const; /** * \returns true if this annotation has a file attachement */ bool HasFileAttachement() const; /** Set a file attachment for this annotation. * The type of this annotation has to be * ePdfAnnotation_FileAttachement for file * attachements to work. * * \param rFileSpec a file specification */ void SetFileAttachement( const PdfFileSpec & rFileSpec ); /** Get a file attachement of this annotation. * \returns a file specification object. The file specification object is owned * by the PdfAnnotation. * * \see SetFileAttachement */ PdfFileSpec* GetFileAttachement() const; /** Get the quad points associated with the annotation (if appropriate). * This array is used in text markup annotations to describe the * regions affected by the markup (i.e. the hilighted words, one * quadrilateral per word) * * \returns a PdfArray of 8xn numbers describing the * x,y coordinates of BL BR TR TL corners of the * quadrilaterals. If inappropriate, returns * an empty array. */ PdfArray GetQuadPoints() const; /** Set the quad points associated with the annotation (if appropriate). * This array is used in text markup annotations to describe the * regions affected by the markup (i.e. the hilighted words, one * quadrilateral per word) * * \param rQuadPoints a PdfArray of 8xn numbers describing the * x,y coordinates of BL BR TR TL corners of the * quadrilaterals. */ void SetQuadPoints( const PdfArray & rQuadPoints ); /** Get the color key of the Annotation dictionary * which defines the color of the annotation, * as per 8.4 of the pdf spec. The PdfArray contains * 0 to four numbers, depending on the colorspace in * which the color is specified * 0 numbers means the annotation is transparent * 1 number specifies the intensity of the color in grayscale * 3 numbers specifie the color in the RGB colorspace and * 4 numbers specify the color in the CMYK colorspace * * \returns a PdfArray of either 0, 1, 3 or 4 numbers * depending on the colorspace in which the color * is specified */ PdfArray GetColor() const; /** Set the C key of the Annotation dictionary, which defines the * color of the annotation, as per 8.4 of the pdf spec. Parameters * give the color in rgb colorspace coordinates * * \param r number from 0 to 1, the intensity of the red channel * \param g number from 0 to 1, the intensity of the green channel * \param b number from 0 to 1, the intensity of the blue channel */ void SetColor( double r, double g, double b ); /** Set the C key of the Annotation dictionary, which defines the * color of the annotation, as per 8.4 of the pdf spec. Parameters * give the color in cmyk colorspace coordinates * * \param c number from 0 to 1, the intensity of the cyan channel * \param m number from 0 to 1, the intensity of the magneta channel * \param y number from 0 to 1, the intensity of the yellow channel * \param k number from 0 to 1, the intensity of the black channel */ void SetColor( double c, double m, double y, double k ); /** Set the C key of the Annotation dictionary, which defines the * color of the annotation, as per 8.4 of the pdf spec. Parameters * give the color in grayscale colorspace coordinates * * \param gray number from 0 to 1, the intensity of the black */ void SetColor( double gray ); /** Set the C key of the Annotation dictionary to an empty array, which, * as per 8.4 of the pdf spec., makes the annotation transparent * */ void SetColor(); /** Get the type of this annotation * \returns the annotation type */ inline EPdfAnnotation GetType() const; /** Get the page of this PdfField * * \returns the page of this PdfField */ inline PdfPage* GetPage() const; private: /** Convert an annotation enum to its string representation * which can be written to the PDF file. * \returns the string representation or NULL for unsupported annotation types */ static const long s_lNumActions; static const char* s_names[]; private: EPdfAnnotation m_eAnnotation; PdfAction* m_pAction; PdfFileSpec* m_pFileSpec; PdfPage* m_pPage; }; // ----------------------------------------------------- // // ----------------------------------------------------- inline EPdfAnnotation PdfAnnotation::GetType() const { return m_eAnnotation; } // ----------------------------------------------------- // // ----------------------------------------------------- inline PdfPage* PdfAnnotation::GetPage() const { return m_pPage; } }; #endif /* _PDF_ANNOTATION_H_ */ podofo-0.9.3/src/doc/PdfFontType1Base14.cpp0000664000175000017500000001141512344436402020150 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2010 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfFontType1Base14.h" #include "base/PdfDefinesPrivate.h" #include "base/PdfDictionary.h" #include "base/PdfEncoding.h" namespace PoDoFo { PdfFontType1Base14::PdfFontType1Base14( PdfFontMetrics* pMetrics, const PdfEncoding* const pEncoding, PdfVecObjects* pParent ) : PdfFontSimple( pMetrics, pEncoding, pParent ) { InitBase14Font( pMetrics ); } // OC 13.08.2010 New: PdfFontType1Base14::PdfFontType1Base14( PdfFontMetrics* pMetrics, const PdfEncoding* const pEncoding, PdfObject* pObject ) : PdfFontSimple( pMetrics, pEncoding, pObject ) { InitBase14Font( pMetrics ); } PdfFontType1Base14::~PdfFontType1Base14() { // FontMetrics of base14 fonts may not be deleted m_pMetrics = NULL; } /* kausik : April 12th 2010 This is the font dictionary. It gets added to the page resources dictionary of the pdf. */ void PdfFontType1Base14::InitBase14Font( PdfFontMetrics* pMetrics ) { PdfVariant var; this->GetObject()->GetDictionary().AddKey( PdfName::KeySubtype, PdfName("Type1")); this->GetObject()->GetDictionary().AddKey("BaseFont", PdfName( pMetrics->GetFontname() ) ); m_pEncoding->AddToDictionary( this->GetObject()->GetDictionary() ); // Add encoding key // pDescriptor->GetDictionary().AddKey( "FontName", this->GetBaseFont() ); //pDescriptor->GetDictionary().AddKey( "FontWeight", (long)m_pMetrics->Weight() ); // pDescriptor->GetDictionary().AddKey( PdfName::KeyFlags, PdfVariant( static_cast(32LL) ) ); // TODO: 0 ???? // pDescriptor->GetDictionary().AddKey( "FontBBox", array ); // pDescriptor->GetDictionary().AddKey( "ItalicAngle", PdfVariant( static_cast(m_pMetrics->GetItalicAngle()) ) ); // pDescriptor->GetDictionary().AddKey( "Ascent", m_pMetrics->GetPdfAscent() ); // pDescriptor->GetDictionary().AddKey( "Descent", m_pMetrics->GetPdfDescent() ); // pDescriptor->GetDictionary().AddKey( "CapHeight", m_pMetrics->GetPdfAscent() ); // m_pMetrics->CapHeight() ); // pDescriptor->GetDictionary().AddKey( "StemV", PdfVariant( static_cast(1LL) ) ); // m_pMetrics->StemV() ); // Peter Petrov 24 September 2008 // m_pDescriptor = pDescriptor; } void PdfFontType1Base14::EmbedFontFile( PdfObject* ) { // Do nothing, base 14 fonts do not need to be embedded } }; podofo-0.9.3/src/doc/PdfFontMetricsFreetype.cpp0000664000175000017500000004101512347347566021336 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2005 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfFontMetricsFreetype.h" #include "base/PdfDefinesPrivate.h" #include "base/PdfArray.h" #include "base/PdfDictionary.h" #include "base/PdfVariant.h" #include "PdfFontFactory.h" #include #include #include #include FT_FREETYPE_H #include FT_TRUETYPE_TABLES_H #define PODOFO_FIRST_READABLE 31 #define PODOFO_WIDTH_CACHE_SIZE 256 namespace PoDoFo { #if defined(__APPLE_CC__) && !defined(PODOFO_HAVE_FONTCONFIG) #include #endif PdfFontMetricsFreetype::PdfFontMetricsFreetype( FT_Library* pLibrary, const char* pszFilename, bool pIsSymbol, const char* pszSubsetPrefix ) : PdfFontMetrics( PdfFontMetrics::FontTypeFromFilename( pszFilename ), pszFilename, pszSubsetPrefix ), m_pLibrary( pLibrary ), m_pFace( NULL ), m_bSymbol( pIsSymbol ) { FT_Error err = FT_New_Face( *pLibrary, pszFilename, 0, &m_pFace ); if ( err ) { // throw an exception PdfError::LogMessage( eLogSeverity_Critical, "FreeType returned the error %i when calling FT_New_Face for font %s.", err, pszFilename ); PODOFO_RAISE_ERROR( ePdfError_FreeType ); } InitFromFace(pIsSymbol); } PdfFontMetricsFreetype::PdfFontMetricsFreetype( FT_Library* pLibrary, const char* pBuffer, unsigned int nBufLen, bool pIsSymbol, const char* pszSubsetPrefix ) : PdfFontMetrics( ePdfFontType_Unknown, "", pszSubsetPrefix ), m_pLibrary( pLibrary ), m_pFace( NULL ), m_bSymbol( pIsSymbol ) { m_bufFontData = PdfRefCountedBuffer( nBufLen ); // const_cast is ok, because we SetTakePossension to false! memcpy( m_bufFontData.GetBuffer(), pBuffer, nBufLen ); InitFromBuffer(pIsSymbol); } PdfFontMetricsFreetype::PdfFontMetricsFreetype( FT_Library* pLibrary, const PdfRefCountedBuffer & rBuffer, bool pIsSymbol, const char* pszSubsetPrefix ) : PdfFontMetrics( ePdfFontType_Unknown, "", pszSubsetPrefix ), m_pLibrary( pLibrary ), m_pFace( NULL ), m_bSymbol( pIsSymbol ), m_bufFontData( rBuffer ) { InitFromBuffer(pIsSymbol); } PdfFontMetricsFreetype::PdfFontMetricsFreetype( FT_Library* pLibrary, FT_Face face, bool pIsSymbol, const char* pszSubsetPrefix ) : PdfFontMetrics( ePdfFontType_TrueType, // Try to initialize the pathname from m_face // so that font embedding will work (face->stream ? reinterpret_cast(face->stream->pathname.pointer) : ""), pszSubsetPrefix ), m_pLibrary( pLibrary ), m_pFace( face ), m_bSymbol( pIsSymbol ) { // asume true type // m_eFontType = ePdfFontType_TrueType; InitFromFace(pIsSymbol); } PdfFontMetricsFreetype::~PdfFontMetricsFreetype() { if ( m_pFace ) { FT_Done_Face( m_pFace ); } } void PdfFontMetricsFreetype::InitFromBuffer(bool pIsSymbol) { FT_Error error = FT_New_Memory_Face( *m_pLibrary, reinterpret_cast(m_bufFontData.GetBuffer()), static_cast(m_bufFontData.GetSize()), 0, &m_pFace ); if( error ) { PdfError::LogMessage( eLogSeverity_Critical, "FreeType return edthe error %i when calling FT_New_Face for a buffered font.", error ); PODOFO_RAISE_ERROR( ePdfError_FreeType ); } else { // asume true type this->SetFontType( ePdfFontType_TrueType ); } InitFromFace(pIsSymbol); } void PdfFontMetricsFreetype::InitFromFace(bool pIsSymbol) { if ( m_eFontType == ePdfFontType_Unknown ) { // We need to have identified the font type by this point // Unsupported font. PODOFO_RAISE_ERROR_INFO( ePdfError_UnsupportedFontFormat, m_sFilename.c_str() ); } m_nWeight = 500; m_nItalicAngle = 0; m_dLineSpacing = 0.0; m_dUnderlineThickness = 0.0; m_dUnderlinePosition = 0.0; m_dStrikeOutPosition = 0.0; m_dStrikeOutThickness = 0.0; m_fFontSize = 0.0f; m_bSymbol = pIsSymbol; m_bIsBold = false; m_bIsItalic = false; if ( m_pFace ) { // better be, but just in case... m_dPdfAscent = m_pFace->ascender * 1000.0 / m_pFace->units_per_EM; m_dPdfDescent = m_pFace->descender * 1000.0 / m_pFace->units_per_EM; m_bIsBold = (m_pFace->style_flags & FT_STYLE_FLAG_BOLD) != 0; m_bIsItalic = (m_pFace->style_flags & FT_STYLE_FLAG_ITALIC) != 0; } // Try to get a unicode charmap FT_Select_Charmap( m_pFace, pIsSymbol ? FT_ENCODING_MS_SYMBOL : FT_ENCODING_UNICODE ); // Try to determine if it is a symbol font for( int c=0;cnum_charmaps;c++ ) { FT_CharMap charmap = m_pFace->charmaps[c]; if( charmap->encoding == FT_ENCODING_MS_SYMBOL ) { m_bSymbol = true; FT_Set_Charmap( m_pFace, charmap ); break; } // TODO: Also check for FT_ENCODING_ADOBE_CUSTOM and set it? } // we cache the 256 first width entries as they // are most likely needed quite often m_vecWidth.clear(); m_vecWidth.reserve( PODOFO_WIDTH_CACHE_SIZE ); for( unsigned int i=0;i(m_pFace->glyph->metrics.horiAdvance) * 1000.0 / m_pFace->units_per_EM ); } } InitFontSizes(); } void PdfFontMetricsFreetype::InitFontSizes() { if( !m_pFace ) { PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidHandle, "Cannot set font size on invalid font!" ); } float fSize = 1.0f; // TODO: Maybe we have to set this for charwidth!!! FT_Set_Char_Size( m_pFace, static_cast(fSize*64.0), 0, 72, 72 ); // calculate the line spacing now, as it changes only with the font size m_dLineSpacing = (static_cast(m_pFace->height) / m_pFace->units_per_EM); m_dUnderlineThickness = (static_cast(m_pFace->underline_thickness) / m_pFace->units_per_EM); m_dUnderlinePosition = (static_cast(m_pFace->underline_position) / m_pFace->units_per_EM); m_dAscent = static_cast(m_pFace->ascender) / m_pFace->units_per_EM; m_dDescent = static_cast(m_pFace->descender) / m_pFace->units_per_EM; // Set default values for strikeout, in case the font has no direct values m_dStrikeOutPosition = m_dAscent / 2.0; m_dStrikeOutThickness = m_dUnderlineThickness; TT_OS2* pOs2Table = static_cast(FT_Get_Sfnt_Table( m_pFace, ft_sfnt_os2 )); if( pOs2Table ) { m_dStrikeOutPosition = static_cast(pOs2Table->yStrikeoutPosition) / m_pFace->units_per_EM; m_dStrikeOutThickness = static_cast(pOs2Table->yStrikeoutSize) / m_pFace->units_per_EM; } } const char* PdfFontMetricsFreetype::GetFontname() const { const char* s = FT_Get_Postscript_Name( m_pFace ); return s ? s : ""; } void PdfFontMetricsFreetype::GetWidthArray( PdfVariant & var, unsigned int nFirst, unsigned int nLast ) const { unsigned int i; PdfArray list; if( !m_pFace ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } for( i=nFirst;i<=nLast;i++ ) { if( i < PODOFO_WIDTH_CACHE_SIZE ) list.push_back( PdfVariant( m_vecWidth[i] ) ); else { if( !FT_Load_Char( m_pFace, i, FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP ) ) // | FT_LOAD_NO_RENDER { //PODOFO_RAISE_ERROR( ePdfError_FreeType ); list.push_back( PdfVariant( 0.0 ) ); continue; } list.push_back( PdfVariant( m_pFace->glyph->metrics.horiAdvance * 1000.0 / m_pFace->units_per_EM ) ); } } var = PdfVariant( list ); } double PdfFontMetricsFreetype::GetGlyphWidth( int nGlyphId ) const { if( !m_pFace ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } if( !FT_Load_Glyph( m_pFace, nGlyphId, FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP ) ) // | FT_LOAD_NO_RENDER { // zero return code is success! return m_pFace->glyph->metrics.horiAdvance * 1000.0 / m_pFace->units_per_EM; } return 0.0; } double PdfFontMetricsFreetype::GetGlyphWidth( const char* pszGlyphname ) const { return GetGlyphWidth( FT_Get_Name_Index( m_pFace, const_cast(pszGlyphname) ) ); } void PdfFontMetricsFreetype::GetBoundingBox( PdfArray & array ) const { if( !m_pFace ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } array.Clear(); array.push_back( PdfVariant( m_pFace->bbox.xMin * 1000.0 / m_pFace->units_per_EM ) ); array.push_back( PdfVariant( m_pFace->bbox.yMin * 1000.0 / m_pFace->units_per_EM ) ); array.push_back( PdfVariant( m_pFace->bbox.xMax * 1000.0 / m_pFace->units_per_EM ) ); array.push_back( PdfVariant( m_pFace->bbox.yMax * 1000.0 / m_pFace->units_per_EM ) ); } double PdfFontMetricsFreetype::CharWidth( unsigned char c ) const { double dWidth = m_vecWidth[static_cast(c)]; return dWidth * static_cast(this->GetFontSize() * this->GetFontScale() / 100.0) / 1000.0 + static_cast( this->GetFontSize() * this->GetFontScale() / 100.0 * this->GetFontCharSpace() / 100.0); } double PdfFontMetricsFreetype::UnicodeCharWidth( unsigned short c ) const { FT_Error ftErr; double dWidth = 0.0; if( static_cast(c) < PODOFO_WIDTH_CACHE_SIZE ) { dWidth = m_vecWidth[static_cast(c)]; } else { ftErr = FT_Load_Char( m_pFace, static_cast(c), FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP ); if( ftErr ) return dWidth; dWidth = m_pFace->glyph->metrics.horiAdvance * 1000.0 / m_pFace->units_per_EM; } return dWidth * static_cast(this->GetFontSize() * this->GetFontScale() / 100.0) / 1000.0 + static_cast( this->GetFontSize() * this->GetFontScale() / 100.0 * this->GetFontCharSpace() / 100.0); } long PdfFontMetricsFreetype::GetGlyphId( long lUnicode ) const { long lGlyph = 0L; // Handle symbol fonts! if( m_bSymbol ) { lUnicode = lUnicode | 0xf000; } lGlyph = FT_Get_Char_Index( m_pFace, lUnicode ); return lGlyph; } bool PdfFontMetricsFreetype::IsBold(void) const { return m_bIsBold; } bool PdfFontMetricsFreetype::IsItalic(void) const { return m_bIsItalic; } // ----------------------------------------------------- // // ----------------------------------------------------- double PdfFontMetricsFreetype::GetLineSpacing() const { return m_dLineSpacing * this->GetFontSize(); } // ----------------------------------------------------- // // ----------------------------------------------------- double PdfFontMetricsFreetype::GetUnderlinePosition() const { return m_dUnderlinePosition * this->GetFontSize(); } // ----------------------------------------------------- // // ----------------------------------------------------- double PdfFontMetricsFreetype::GetStrikeOutPosition() const { return m_dStrikeOutPosition * this->GetFontSize(); } // ----------------------------------------------------- // // ----------------------------------------------------- double PdfFontMetricsFreetype::GetUnderlineThickness() const { return m_dUnderlineThickness * this->GetFontSize(); } // ----------------------------------------------------- // // ----------------------------------------------------- double PdfFontMetricsFreetype::GetStrikeoutThickness() const { return m_dStrikeOutThickness * this->GetFontSize(); } // ----------------------------------------------------- // // ----------------------------------------------------- const char* PdfFontMetricsFreetype::GetFontData() const { return m_bufFontData.GetBuffer(); } // ----------------------------------------------------- // // ----------------------------------------------------- pdf_long PdfFontMetricsFreetype::GetFontDataLen() const { return m_bufFontData.GetSize(); } // ----------------------------------------------------- // // ----------------------------------------------------- unsigned int PdfFontMetricsFreetype::GetWeight() const { return m_nWeight; } // ----------------------------------------------------- // // ----------------------------------------------------- double PdfFontMetricsFreetype::GetAscent() const { return m_dAscent * this->GetFontSize(); } // ----------------------------------------------------- // // ----------------------------------------------------- double PdfFontMetricsFreetype::GetPdfAscent() const { return m_dPdfAscent; } // ----------------------------------------------------- // // ----------------------------------------------------- double PdfFontMetricsFreetype::GetDescent() const { return m_dDescent * this->GetFontSize(); } // ----------------------------------------------------- // // ----------------------------------------------------- double PdfFontMetricsFreetype::GetPdfDescent() const { return m_dPdfDescent; } // ----------------------------------------------------- // // ----------------------------------------------------- int PdfFontMetricsFreetype::GetItalicAngle() const { return m_nItalicAngle; } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfFontMetricsFreetype::IsSymbol() const { return m_bSymbol; } }; podofo-0.9.3/src/doc/PdfInfo.h0000664000175000017500000002212212347307436015723 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2006 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_INFO_H_ #define _PDF_INFO_H_ #include "podofo/base/PdfDefines.h" #include "podofo/base/PdfName.h" #include "podofo/base/PdfDate.h" #include "PdfElement.h" namespace PoDoFo { class PdfString; /** This class provides access to the documents * info dictionary, which provides information * about the PDF document. */ class PODOFO_DOC_API PdfInfo : public PdfElement { public: /** * Enum to specifiy the initial information of the * info dictionary. */ enum EPdfInfoInitial { ePdfInfoInitial_WriteCreationTime = 0x01, ///< Write the creation time (current time). Default for new documents. ePdfInfoInitial_WriteModificationTime = 0x02, ///< Write the modification time (current time). Default for loaded documents. ePdfInfoInitial_WriteProducer = 0x04 ///< Write producer key. Default for new documents. }; /** Create a new PdfInfo object * \param pParent the parent of this object * \param eInitial which information should be * writting initially to the information dictionary */ PdfInfo( PdfVecObjects* pParent, int eInitial = ePdfInfoInitial_WriteCreationTime | ePdfInfoInitial_WriteProducer ); /** Create a PdfInfo object from an existing * object in the PDF file. * \param pObject must be an info dictionary. * \param eInitial which information should be * writting initially to the information */ PdfInfo( PdfObject* pObject, int eInitial = ePdfInfoInitial_WriteModificationTime ); /** Destructor */ ~PdfInfo(); /** Set the author of the document. * \param sAuthor author */ void SetAuthor( const PdfString & sAuthor ); /** Get the author of the document * \returns the author */ inline const PdfString & GetAuthor() const; /** Set the creator of the document. * Typically the name of the application using the library. * \param sCreator creator */ void SetCreator( const PdfString & sCreator ); /** Get the creator of the document * \returns the creator */ inline const PdfString & GetCreator() const; /** Set keywords for this document * \param sKeywords a list of keywords */ void SetKeywords( const PdfString & sKeywords ); /** Get the keywords of the document * \returns the keywords */ inline const PdfString & GetKeywords() const; /** Set the subject of the document. * \param sSubject subject */ void SetSubject( const PdfString & sSubject ); /** Get the subject of the document * \returns the subject */ inline const PdfString & GetSubject() const; /** Set the title of the document. * \param sTitle title */ void SetTitle( const PdfString & sTitle ); /** Get the title of the document * \returns the title */ inline const PdfString & GetTitle() const; // Peter Petrov 27 April 2008 /** Set the producer of the document. * \param sProducer producer */ void SetProducer( const PdfString & sProducer ); // Peter Petrov 27 April 2008 /** Get the producer of the document * \returns the producer */ inline const PdfString & GetProducer() const; /** Set the trapping state of the document. * \param sTrapped trapped */ void SetTrapped( const PdfName & sTrapped ); /** Get the trapping state of the document * \returns the title */ inline const PdfName & GetTrapped() const; /** Get creation date of document * \return creation date */ inline PdfDate GetCreationDate() const; /** Get modification date of document * \return modification date */ inline PdfDate GetModDate() const; /** Set custom info key. * \param sName Name of the key. * \param sValue Value of the key. */ void SetCustomKey(const PdfName &sName, const PdfString &sValue); private: /** Add the initial document information to the dictionary. * \param eInitial which information should be * writting initially to the information */ void Init( int eInitial ); /** Get a value from the info dictionary as name * \para rName the key to fetch from the info dictionary * \return a value from the info dictionary */ const PdfString & GetStringFromInfoDict( const PdfName & rName ) const; /** Get a value from the info dictionary as name * \para rName the key to fetch from the info dictionary * \return a value from the info dictionary */ const PdfName & GetNameFromInfoDict( const PdfName & rName ) const; }; // ----------------------------------------------------- // // ----------------------------------------------------- const PdfString & PdfInfo::GetAuthor() const { return this->GetStringFromInfoDict( PdfName("Author") ); } // ----------------------------------------------------- // // ----------------------------------------------------- const PdfString & PdfInfo::GetCreator() const { return this->GetStringFromInfoDict( PdfName("Creator") ); } // ----------------------------------------------------- // // ----------------------------------------------------- const PdfString & PdfInfo::GetKeywords() const { return this->GetStringFromInfoDict( PdfName("Keywords") ); } // ----------------------------------------------------- // // ----------------------------------------------------- const PdfString & PdfInfo::GetSubject() const { return this->GetStringFromInfoDict( PdfName("Subject") ); } // ----------------------------------------------------- // // ----------------------------------------------------- const PdfString & PdfInfo::GetTitle() const { return this->GetStringFromInfoDict( PdfName("Title") ); } // ----------------------------------------------------- // // ----------------------------------------------------- const PdfString & PdfInfo::GetProducer() const { return this->GetStringFromInfoDict( PdfName("Producer") ); } // ----------------------------------------------------- // // ----------------------------------------------------- const PdfName & PdfInfo::GetTrapped() const { return this->GetNameFromInfoDict( PdfName("Trapped") ); } // ----------------------------------------------------- // // ----------------------------------------------------- PdfDate PdfInfo::GetCreationDate() const { return PdfDate(this->GetStringFromInfoDict(PdfName("CreationDate"))); } // ----------------------------------------------------- // // ----------------------------------------------------- PdfDate PdfInfo::GetModDate() const { return PdfDate(this->GetStringFromInfoDict(PdfName("ModDate"))); } }; #endif // _PDF_INFO_H_ podofo-0.9.3/src/doc/PdfFontTrueType.cpp0000664000175000017500000001116312344436402017767 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2005 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfFontTrueType.h" #include "base/PdfDefinesPrivate.h" #include "base/PdfArray.h" #include "base/PdfDictionary.h" #include "base/PdfName.h" #include "base/PdfStream.h" namespace PoDoFo { PdfFontTrueType::PdfFontTrueType( PdfFontMetrics* pMetrics, const PdfEncoding* const pEncoding, PdfVecObjects* pParent, bool bEmbed ) : PdfFontSimple( pMetrics, pEncoding, pParent ) { this->Init( bEmbed, PdfName("TrueType") ); } PdfFontTrueType::PdfFontTrueType( PdfFontMetrics* pMetrics, const PdfEncoding* const pEncoding, PdfObject* pObject ) : PdfFontSimple( pMetrics, pEncoding, pObject ) { } void PdfFontTrueType::EmbedFontFile( PdfObject* pDescriptor ) { PdfObject* pContents; pdf_long lSize = 0; m_bWasEmbedded = true; pContents = this->GetObject()->GetOwner()->CreateObject(); if( !pContents ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } pDescriptor->GetDictionary().AddKey( "FontFile2", pContents->Reference() ); // if the data was loaded from memory - use it from there // otherwise, load from disk if ( m_pMetrics->GetFontDataLen() && m_pMetrics->GetFontData() ) { // FIXME const_cast is dangerous if string literals may ever be passed char* pBuffer = const_cast( m_pMetrics->GetFontData() ); lSize = m_pMetrics->GetFontDataLen(); // Set Length1 before creating the stream // as PdfStreamedDocument does not allow // adding keys to an object after a stream was written pContents->GetDictionary().AddKey( "Length1", PdfVariant( static_cast(lSize) ) ); pContents->GetStream()->Set( pBuffer, lSize ); } else { PdfFileInputStream stream( m_pMetrics->GetFilename() ); lSize = stream.GetFileLength(); // Set Length1 before creating the stream // as PdfStreamedDocument does not allow // adding keys to an object after a stream was written pContents->GetDictionary().AddKey( "Length1", PdfVariant( static_cast(lSize) ) ); pContents->GetStream()->Set( &stream ); } } }; podofo-0.9.3/src/doc/PdfPagesTree.h0000664000175000017500000003111712347310502016677 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2006 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_PAGES_TREE_H_ #define _PDF_PAGES_TREE_H_ #include "podofo/base/PdfDefines.h" #include "podofo/base/PdfArray.h" #include "PdfElement.h" #include "PdfPagesTreeCache.h" namespace PoDoFo { class PdfObject; class PdfPage; class PdfRect; enum EPdfPageInsertionPoint { ePdfPageInsertionPoint_InsertBeforeFirstPage = -1, ePdfPageInsertionPoint_InsertLastPage = -2, ePdfPageInsertionPoint_InsertAllPages = -3, ePdfPageInsertionPoint_InsertOddPagesOnly = -4, ePdfPageInsertionPoint_InsertEvenPagesOnly = -5 }; /** Class for managing the tree of Pages in a PDF document * Don't use this class directly. Use PdfDocument instead. * * \see PdfDocument */ class PODOFO_DOC_API PdfPagesTree : public PdfElement { typedef std::deque< PdfObject* > PdfObjectList; public: /** Construct a new PdfPagesTree */ PdfPagesTree( PdfVecObjects* pParent ); /** Construct a PdfPagesTree from the root /Pages object * \param pPagesRoot pointer to page tree dictionary */ PdfPagesTree( PdfObject* pPagesRoot ); /** Close/down destruct a PdfPagesTree */ virtual ~PdfPagesTree(); /** Return the number of pages in the entire tree * \returns number of pages */ int GetTotalNumberOfPages() const; /** Return a PdfPage for the specified Page index * The returned page is owned by the pages tree and * deleted along with it. * * \param nIndex page index, 0-based * \returns a pointer to the requested page */ PdfPage* GetPage( int nIndex ); /** Return a PdfPage for the specified Page reference. * The returned page is owned by the pages tree and * deleted along with it. * * \param ref the reference of the pages object * \returns a pointer to the requested page */ PdfPage* GetPage( const PdfReference & ref ); /** Inserts an existing page object into the internal page tree. * after the specified page number * * \param nAfterPageIndex an integer specifying after what page * - may be one of the special values from EPdfPageInsertionPoint. * Pages are 0 based. * * \param pPage musst be a PdfObject with type /Page */ void InsertPage( int nAfterPageIndex, PdfObject* pPage ); /** Inserts an existing page object into the internal page tree. * after the specified page number * * \param nAfterPageIndex an integer specifying after what page * - may be one of the special values from EPdfPageInsertionPoint. * Pages are 0 based. * \param pPage a PdfPage to be inserted, the PdfPage will not get owned by the PdfPagesTree */ void InsertPage( int nAfterPageIndex, PdfPage* pPage ); /** Inserts a vector of page objects at once into the internal page tree * after the specified page index (zero based index) * * \param nAfterPageIndex a zero based integer index specifying after what page to insert * - you need to pass ePdfPageInsertionPoint_InsertBeforeFirstPage if you want to insert before the first page. * * \param vecPages must be a vector of PdfObjects with type /Page */ void InsertPages( int nAfterPageIndex, const std::vector& vecPages ); /** Creates a new page object and inserts it into the internal * page tree. * The returned page is owned by the pages tree and will get deleted along * with it! * * \param rSize a PdfRect specifying the size of the page (i.e the /MediaBox key) in PDF units * \returns a pointer to a PdfPage object */ PdfPage* CreatePage( const PdfRect & rSize ); /** Creates several new page objects and inserts them into the internal * page tree. * The new pages are owned by the pages tree and will get deleted along * with it! * Note: this function will attach all new pages onto the same page node * which can cause the tree to be unbalanced if * * \param vecSizes a vector of PdfRect specifying the size of each of the pages to create (i.e the /MediaBox key) in PDF units */ void CreatePages( const std::vector& vecSizes ); /** Creates a new page object and inserts it at index atIndex. * The returned page is owned by the pages tree and will get deleted along * with it! * * \param rSize a PdfRect specifying the size of the page (i.e the /MediaBox key) in PDF units * \param atIndex index where to insert the new page (0-based) * \returns a pointer to a PdfPage object */ PdfPage* InsertPage( const PdfRect & rSize, int atIndex); /** Delete the specified page object from the internal pages tree. * It does NOT remove any PdfObjects from memory - just the reference from the tree * * \param inPageNumber the page number (0-based) to be removed * * The PdfPage object refering to this page will be deleted by this call! * Empty page nodes will also be deleted. * * \see PdfMemDocument::DeletePages */ void DeletePage( int inPageNumber ); /** * Clear internal cache of PdfPage objects. * All references to PdfPage object will become invalid * when calling this method. All PdfPages will be deleted. * * You normally will never have to call this method. * It is only useful if one modified the page nodes * of the pagestree manually. * */ inline void ClearCache(); private: PdfPagesTree(); // don't allow construction from nothing! PdfObject* GetPageNode( int nPageNum, PdfObject* pParent, PdfObjectList & rLstParents ); PdfObject* GetPageNodeFromArray( int nPageNum, const PdfArray & rKidsArray, PdfObjectList & rLstParents ); int GetChildCount( const PdfObject* pNode ) const; /** * Test if a PdfObject is a page node * @return true if PdfObject is a page node */ bool IsTypePage( const PdfObject* pObject ) const; /** * Test if a PdfObject is a pages node * @return true if PdfObject is a pages node */ bool IsTypePages( const PdfObject* pObject ) const; /** * Find the position of pPageObj in the kids array of pPageParent * * @returns the index in the kids array or -1 if pPageObj is no child of pPageParent */ int GetPosInKids( PdfObject* pPageObj, PdfObject* pPageParent ); /** Private method for adjusting the page count in a tree */ int ChangePagesCount( PdfObject* inPageObj, int inDelta ); /** * Insert a page object into a pages node * * @param pNode the pages node whete pPage is to be inserted * @param rlstParents list of all (future) parent pages nodes in the pages tree * of pPage * @param nIndex index where pPage is to be inserted in pNode's kids array * @param pPage the page object which is to be inserted */ void InsertPageIntoNode( PdfObject* pNode, const PdfObjectList & rlstParents, int nIndex, PdfObject* pPage ); /** * Insert a vector of page objects into a pages node * Same as InsertPageIntoNode except that it allows for adding multiple pages at one time * Note that adding many pages onto the same node will create an unbalanced page tree * * @param pNode the pages node whete pPage is to be inserted * @param rlstParents list of all (future) parent pages nodes in the pages tree * of pPage * @param nIndex index where pPage is to be inserted in pNode's kids array * @param vecPages a vector of the page objects which are to be inserted */ void InsertPagesIntoNode( PdfObject* pParent, const PdfObjectList & rlstParents, int nIndex, const std::vector& vecPages ); /** * Delete a page object from a pages node * * @param pNode which is the direct parent of pPage and where the page must be deleted * @param rlstParents list of all parent pages nodes in the pages tree * of pPage * @param nIndex index where pPage is to be deleted in pNode's kids array * @param pPage the page object which is to be deleted */ void DeletePageFromNode( PdfObject* pNode, const PdfObjectList & rlstParents, int nIndex, PdfObject* pPage ); /** * Delete a single page node or page object from the kids array of pParent * * @param pParent the parent of the page node which is deleted * @param nIndex index to remove from the kids array of pParent */ void DeletePageNode( PdfObject* pParent, int nIndex ); /** * Tests if a page node is emtpy * * @returns true if Count of page is 0 or the Kids array is empty */ bool IsEmptyPageNode( PdfObject* pPageNode ); /** Private method for actually traversing the /Pages tree * * \param rListOfParents all parents of the page node will be added to this lists, * so that the PdfPage can later access inherited attributes */ /* PdfObject* GetPageNode( int nPageNum, PdfObject* pPagesObject, std::deque & rListOfParents ); */ /** Private method for actually traversing the /Pages tree * This method directly traverses the tree and does no * optimization for nodes with only one element like GetPageNode does. * * \param rListOfParents all parents of the page node will be added to this lists, * so that the PdfPage can later access inherited attributes */ /* PdfObject* GetPageNodeFromTree( int nPageNum, const PdfArray & kidsArray, std::deque & rListOfParents ); */ /** Private method to access the Root of the tree using a logical name */ PdfObject* GetRoot() { return this->GetObject(); } const PdfObject* GetRoot() const { return this->GetObject(); } private: PdfPagesTreeCache m_cache; }; // ----------------------------------------------------- // // ----------------------------------------------------- inline void PdfPagesTree::ClearCache() { m_cache.ClearCache(); } }; #endif // _PDF_PAGES_TREE_H_ podofo-0.9.3/src/doc/PdfPainterMM.h0000664000175000017500000002573312347306415016673 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2006 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_PAINTER_MM_H_ #define _PDF_PAINTER_MM_H_ #include "podofo/base/PdfDefines.h" #include "PdfPainter.h" namespace PoDoFo { class PdfCanvas; class PdfFont; class PdfImage; class PdfName; class PdfObject; class PdfReference; class PdfStream; class PdfString; class PdfXObject; #ifndef CONVERSION_CONSTANT /** \def CONVERSION_CONSTANT * Conversation constant to convert 1/1000th mm to 1/72 inch * Internal use only. */ #define CONVERSION_CONSTANT 0.002834645669291339 #endif // CONVERSION_CONSTANT /** * This class provides an easy to use painter object which allows you to draw on a PDF page * object. * * During all drawing operations, you are still able to access the stream of the object you are * drawing on directly. * * This painter takes all coordinates in 1/1000th mm instead of PDF units. * * Developer note: we use ownership rather than inheritance here, so as to use the same * methods names a PdfPainter AND avoid compiler confusion on picking the right one. * * \see PdfPainter */ class PODOFO_DOC_API PdfPainterMM : public PdfPainter { public: /** Create a new PdfPainterMM object. */ PdfPainterMM() {} virtual ~PdfPainterMM(); /** Set the line width for all stroking operations. * \param lWidth in 1/1000th mm */ inline void SetStrokeWidthMM( long lWidth ); /** Draw a line with the current color and line settings. * \param lStartX x coordinate of the starting point * \param lStartY y coordinate of the starting point * \param lEndX x coordinate of the ending point * \param lEndY y coordinate of the ending point */ inline void DrawLineMM( long lStartX, long lStartY, long lEndX, long lEndY ); /** Add a rectangle into the current path * \param lX x coordinate of the rectangle * \param lY y coordinate of the rectangle * \param lWidth width of the rectangle * \param lHeight absolute height of the rectangle */ inline void RectangleMM( long lX, long lY, long lWidth, long lHeight ); /** Add an ellipse into the current path * \param lX x coordinate of the ellipse (left coordinate) * \param lY y coordinate of the ellipse (top coordinate) * \param lWidth width of the ellipse * \param lHeight absolute height of the ellipse */ inline void EllipseMM( long lX, long lY, long lWidth, long lHeight ); /** Draw a text string on a page using a given font object. * You have to call SetFont before calling this function. * \param lX the x coordinate * \param lY the y coordinate * \param sText the text string which should be printed * * \see PdfPainter::SetFont() */ inline void DrawTextMM( long lX, long lY, const PdfString & sText); /** Draw a text string on a page using a given font object. * You have to call SetFont before calling this function. * \param lX the x coordinate * \param lY the y coordinate * \param sText the text string which should be printed (is not allowed to be NULL!) * \param lLen draw only lLen characters of pszText * * \see PdfPainter::SetFont() */ inline void DrawTextMM( long lX, long lY, const PdfString & sText, long lLen ); /** Draw an image on the current page. * \param lX the x coordinate (bottom left position of the image) * \param lY the y coordinate (bottom position of the image) * \param pObject an PdfXObject * \param dScaleX option scaling factor in x direction * \param dScaleY option scaling factor in y direction */ inline void DrawImageMM( long lX, long lY, PdfImage* pObject, double dScaleX = 1.0, double dScaleY = 1.0); /** Draw an XObject on the current page. * \param lX the x coordinate (bottom left position of the XObject) * \param lY the y coordinate (bottom position of the XObject) * \param pObject an PdfXObject * \param dScaleX option scaling factor in x direction * \param dScaleY option scaling factor in y direction */ inline void DrawXObjectMM( long lX, long lY, PdfXObject* pObject, double dScaleX = 1.0, double dScaleY = 1.0); /** Append a line segment to the current path. Matches the PDF 'l' operator. * This function is useful to construct an own path * for drawing or clipping. * \param lX x position * \param lY y position */ inline void LineToMM( long lX, long lY ); /** Begin a new path. Matches the PDF 'm' operator. * This function is useful to construct an own path * for drawing or clipping. * \param lX x position * \param lY y position */ inline void MoveToMM( long lX, long lY ); }; // ----------------------------------------------------- // // ----------------------------------------------------- inline void PdfPainterMM::SetStrokeWidthMM( long lWidth ) { this->SetStrokeWidth( static_cast(lWidth) * CONVERSION_CONSTANT ); } // ----------------------------------------------------- // // ----------------------------------------------------- inline void PdfPainterMM::DrawLineMM( long lStartX, long lStartY, long lEndX, long lEndY ) { this->DrawLine( static_cast(lStartX) * CONVERSION_CONSTANT, static_cast(lStartY) * CONVERSION_CONSTANT, static_cast(lEndX) * CONVERSION_CONSTANT, static_cast(lEndY) * CONVERSION_CONSTANT ); } // ----------------------------------------------------- // // ----------------------------------------------------- inline void PdfPainterMM::RectangleMM( long lX, long lY, long lWidth, long lHeight ) { this->Rectangle( static_cast(lX) * CONVERSION_CONSTANT, static_cast(lY) * CONVERSION_CONSTANT, static_cast(lWidth) * CONVERSION_CONSTANT, static_cast(lHeight) * CONVERSION_CONSTANT ); } // ----------------------------------------------------- // // ----------------------------------------------------- inline void PdfPainterMM::EllipseMM( long lX, long lY, long lWidth, long lHeight ) { this->Ellipse( static_cast(lX) * CONVERSION_CONSTANT, static_cast(lY) * CONVERSION_CONSTANT, static_cast(lWidth) * CONVERSION_CONSTANT, static_cast(lHeight) * CONVERSION_CONSTANT ); } // ----------------------------------------------------- // // ----------------------------------------------------- inline void PdfPainterMM::DrawTextMM( long lX, long lY, const PdfString & sText) { this->DrawText( static_cast(lX) * CONVERSION_CONSTANT, static_cast(lY) * CONVERSION_CONSTANT, sText ); } // ----------------------------------------------------- // // ----------------------------------------------------- inline void PdfPainterMM::DrawTextMM( long lX, long lY, const PdfString & sText, long lLen ) { this->DrawText( static_cast(lX) * CONVERSION_CONSTANT, static_cast(lY) * CONVERSION_CONSTANT, sText, lLen ); } // ----------------------------------------------------- // // ----------------------------------------------------- inline void PdfPainterMM::DrawImageMM( long lX, long lY, PdfImage* pObject, double dScaleX, double dScaleY ) { this->DrawImage( static_cast(lX) * CONVERSION_CONSTANT, static_cast(lY) * CONVERSION_CONSTANT, pObject, dScaleX, dScaleY ); } // ----------------------------------------------------- // // ----------------------------------------------------- inline void PdfPainterMM::DrawXObjectMM( long lX, long lY, PdfXObject* pObject, double dScaleX, double dScaleY ) { this->DrawXObject( static_cast(lX) * CONVERSION_CONSTANT, static_cast(lY) * CONVERSION_CONSTANT, pObject, dScaleX, dScaleY ); } // ----------------------------------------------------- // // ----------------------------------------------------- inline void PdfPainterMM::LineToMM( long lX, long lY ) { this->LineTo( static_cast(lX) * CONVERSION_CONSTANT, static_cast(lY) * CONVERSION_CONSTANT ); } // ----------------------------------------------------- // // ----------------------------------------------------- inline void PdfPainterMM::MoveToMM( long lX, long lY ) { this->MoveTo( static_cast(lX) * CONVERSION_CONSTANT, static_cast(lY) * CONVERSION_CONSTANT ); } }; #endif // _PDF_PAINTER_MM_H_ podofo-0.9.3/src/doc/PdfFunction.cpp0000664000175000017500000001605712347271543017161 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2007 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfFunction.h" #include "base/PdfDefinesPrivate.h" #include "base/PdfArray.h" #include "base/PdfDictionary.h" #include "base/PdfStream.h" namespace PoDoFo { PdfFunction::PdfFunction( EPdfFunctionType eType, const PdfArray & rDomain, PdfVecObjects* pParent ) : PdfElement( NULL, pParent ) { Init( eType, rDomain ); } PdfFunction::PdfFunction( EPdfFunctionType eType, const PdfArray & rDomain, PdfDocument* pParent ) : PdfElement( NULL, pParent ) { Init( eType, rDomain ); } PdfFunction::~PdfFunction() { } void PdfFunction::Init( EPdfFunctionType eType, const PdfArray & rDomain ) { this->GetObject()->GetDictionary().AddKey( PdfName("FunctionType"), static_cast(eType) ); this->GetObject()->GetDictionary().AddKey( PdfName("Domain"), rDomain ); } ///////////////////////////////////////////////////////////////////////////// PdfSampledFunction::PdfSampledFunction( const PdfArray & rDomain, const PdfArray & rRange, const PdfFunction::Sample & rlstSamples, PdfVecObjects* pParent ) : PdfFunction( ePdfFunctionType_Sampled, rDomain, pParent ) { Init( rDomain, rRange, rlstSamples ); } PdfSampledFunction::PdfSampledFunction( const PdfArray & rDomain, const PdfArray & rRange, const PdfFunction::Sample & rlstSamples, PdfDocument* pParent ) : PdfFunction( ePdfFunctionType_Sampled, rDomain, pParent ) { Init( rDomain, rRange, rlstSamples ); } void PdfSampledFunction::Init( const PdfArray & rDomain, const PdfArray & rRange, const PdfFunction::Sample & rlstSamples ) { PdfArray Size; for( unsigned i = 0; i < rDomain.GetSize() / 2; i++ ) Size.push_back( PdfObject( static_cast(rDomain.GetSize() / 2L )) ); this->GetObject()->GetDictionary().AddKey( PdfName("Domain"), rDomain ); this->GetObject()->GetDictionary().AddKey( PdfName("Range"), rRange ); this->GetObject()->GetDictionary().AddKey( PdfName("Size"), Size ); this->GetObject()->GetDictionary().AddKey( PdfName("Order"), PdfObject( static_cast(PODOFO_LL_LITERAL(1)) ) ); this->GetObject()->GetDictionary().AddKey( PdfName("BitsPerSample"), PdfObject( static_cast(PODOFO_LL_LITERAL(8)) ) ); this->GetObject()->GetStream()->BeginAppend(); PdfFunction::Sample::const_iterator it = rlstSamples.begin(); while( it != rlstSamples.end() ) { this->GetObject()->GetStream()->Append( & ( *it ), 1 ); ++it; } this->GetObject()->GetStream()->EndAppend(); } ///////////////////////////////////////////////////////////////////////////// PdfExponentialFunction::PdfExponentialFunction( const PdfArray & rDomain, const PdfArray & rC0, const PdfArray & rC1, double dExponent, PdfVecObjects* pParent ) : PdfFunction( ePdfFunctionType_Exponential, rDomain, pParent ) { Init( rC0, rC1, dExponent ); } PdfExponentialFunction::PdfExponentialFunction( const PdfArray & rDomain, const PdfArray & rC0, const PdfArray & rC1, double dExponent, PdfDocument* pParent ) : PdfFunction( ePdfFunctionType_Exponential, rDomain, pParent ) { Init( rC0, rC1, dExponent ); } void PdfExponentialFunction::Init( const PdfArray & rC0, const PdfArray & rC1, double dExponent ) { this->GetObject()->GetDictionary().AddKey( PdfName("C0"), rC0 ); this->GetObject()->GetDictionary().AddKey( PdfName("C1"), rC1 ); this->GetObject()->GetDictionary().AddKey( PdfName("N"), dExponent ); } ///////////////////////////////////////////////////////////////////////////// PdfStitchingFunction::PdfStitchingFunction( const PdfFunction::List & rlstFunctions, const PdfArray & rDomain, const PdfArray & rBounds, const PdfArray & rEncode, PdfVecObjects* pParent ) : PdfFunction( ePdfFunctionType_Stitching, rDomain, pParent ) { Init( rlstFunctions, rBounds, rEncode ); } PdfStitchingFunction::PdfStitchingFunction( const PdfFunction::List & rlstFunctions, const PdfArray & rDomain, const PdfArray & rBounds, const PdfArray & rEncode, PdfDocument* pParent ) : PdfFunction( ePdfFunctionType_Stitching, rDomain, pParent ) { Init( rlstFunctions, rBounds, rEncode ); } void PdfStitchingFunction::Init( const PdfFunction::List & rlstFunctions, const PdfArray & rBounds, const PdfArray & rEncode ) { PdfArray functions; PdfFunction::List::const_iterator it = rlstFunctions.begin(); functions.reserve( rlstFunctions.size() ); while( it != rlstFunctions.end() ) { functions.push_back( (*it).GetObject()->Reference() ); ++it; } this->GetObject()->GetDictionary().AddKey( PdfName("Functions"), functions ); this->GetObject()->GetDictionary().AddKey( PdfName("Bounds"), rBounds ); this->GetObject()->GetDictionary().AddKey( PdfName("Encode"), rEncode ); } }; podofo-0.9.3/src/doc/PdfInfo.cpp0000664000175000017500000001246412347314126016260 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2006 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfInfo.h" #include "base/PdfDefinesPrivate.h" #include "base/PdfDate.h" #include "base/PdfDictionary.h" #include "base/PdfString.h" #define PRODUCER_STRING "PoDoFo - http:/" "/podofo.sf.net" namespace PoDoFo { PdfInfo::PdfInfo( PdfVecObjects* pParent, int eInitial ) : PdfElement( NULL, pParent ) { Init( eInitial ); } PdfInfo::PdfInfo( PdfObject* pObject, int eInitial ) : PdfElement( NULL, pObject ) { Init( eInitial ); } PdfInfo::~PdfInfo() { } void PdfInfo::Init( int eInitial ) { PdfDate date; PdfString str; date.ToString( str ); if( (eInitial & ePdfInfoInitial_WriteCreationTime) == ePdfInfoInitial_WriteCreationTime ) { this->GetObject()->GetDictionary().AddKey( "CreationDate", str ); } if( (eInitial & ePdfInfoInitial_WriteModificationTime) == ePdfInfoInitial_WriteModificationTime ) { this->GetObject()->GetDictionary().AddKey( "ModDate", str ); } if( (eInitial & ePdfInfoInitial_WriteProducer) == ePdfInfoInitial_WriteProducer ) { this->GetObject()->GetDictionary().AddKey( "Producer", PdfString(PRODUCER_STRING) ); } } const PdfString & PdfInfo::GetStringFromInfoDict( const PdfName & rName ) const { const PdfObject* pObj = this->GetObject()->GetDictionary().GetKey( rName ); return pObj && (pObj->IsString() || pObj->IsHexString()) ? pObj->GetString() : PdfString::StringNull; } const PdfName & PdfInfo::GetNameFromInfoDict(const PdfName & rName) const { const PdfObject* pObj = this->GetObject()->GetDictionary().GetKey( rName ); return pObj && pObj->IsName() ? pObj->GetName() : PdfName::KeyNull; } void PdfInfo::SetCustomKey(const PdfName &sName, const PdfString &sValue) { this->GetObject()->GetDictionary().AddKey( sName, sValue ); } void PdfInfo::SetAuthor( const PdfString & sAuthor ) { this->GetObject()->GetDictionary().AddKey( "Author", sAuthor ); } void PdfInfo::SetCreator( const PdfString & sCreator ) { this->GetObject()->GetDictionary().AddKey( "Creator", sCreator ); } void PdfInfo::SetKeywords( const PdfString & sKeywords ) { this->GetObject()->GetDictionary().AddKey( "Keywords", sKeywords ); } void PdfInfo::SetSubject( const PdfString & sSubject ) { this->GetObject()->GetDictionary().AddKey( "Subject", sSubject ); } void PdfInfo::SetTitle( const PdfString & sTitle ) { this->GetObject()->GetDictionary().AddKey( "Title", sTitle ); } // Peter Petrov 27 April 2008 // We have added a SetProducer() method in PdfInfo void PdfInfo::SetProducer( const PdfString & sProducer ) { this->GetObject()->GetDictionary().AddKey( "Producer", sProducer ); } void PdfInfo::SetTrapped(const PdfName & sTrapped) { if((sTrapped.GetEscapedName() == "True" ) || (sTrapped.GetEscapedName() == "False" )) this->GetObject()->GetDictionary().AddKey( "Trapped", sTrapped ); else this->GetObject()->GetDictionary().AddKey( "Trapped", PdfName( "Unknown" ) ); } }; podofo-0.9.3/src/doc/PdfTilingPattern.cpp0000664000175000017500000002265312355520733020154 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2007 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "PdfTilingPattern.h" #include "base/PdfDefinesPrivate.h" #include "base/PdfArray.h" #include "base/PdfColor.h" #include "base/PdfDictionary.h" #include "base/PdfLocale.h" #include "base/PdfRect.h" #include "base/PdfStream.h" #include "base/PdfWriter.h" #include "PdfFunction.h" #include "PdfImage.h" #include #include #include #include namespace PoDoFo { PdfTilingPattern::PdfTilingPattern( EPdfTilingPatternType eTilingType, double strokeR, double strokeG, double strokeB, bool doFill, double fillR, double fillG, double fillB, double offsetX, double offsetY, PdfImage *pImage, PdfVecObjects* pParent) : PdfElement( "Pattern", pParent ) { std::ostringstream out; // We probably aren't doing anything locale sensitive here, but it's // best to be sure. PdfLocaleImbue(out); // Implementation note: the identifier is always // Prefix+ObjectNo. Prefix is /Ft for fonts. out << "Ptrn" << this->GetObject()->Reference().ObjectNumber(); m_Identifier = PdfName( out.str().c_str() ); this->Init( eTilingType, strokeR, strokeG, strokeB, doFill, fillR, fillG, fillB, offsetX, offsetY, pImage); } PdfTilingPattern::PdfTilingPattern( EPdfTilingPatternType eTilingType, double strokeR, double strokeG, double strokeB, bool doFill, double fillR, double fillG, double fillB, double offsetX, double offsetY, PdfImage *pImage, PdfDocument* pParent) : PdfElement( "Pattern", pParent ) { std::ostringstream out; // We probably aren't doing anything locale sensitive here, but it's // best to be sure. PdfLocaleImbue(out); // Implementation note: the identifier is always // Prefix+ObjectNo. Prefix is /Ft for fonts. out << "Ptrn" << this->GetObject()->Reference().ObjectNumber(); m_Identifier = PdfName( out.str().c_str() ); this->Init( eTilingType, strokeR, strokeG, strokeB, doFill, fillR, fillG, fillB, offsetX, offsetY, pImage); } PdfTilingPattern::~PdfTilingPattern() { } void PdfTilingPattern::AddToResources(const PdfName &rIdentifier, const PdfReference &rRef, const PdfName &rName) { PdfObject* pResource = GetObject()->GetDictionary().GetKey( "Resources" ); if( !pResource ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } if( !pResource->GetDictionary().HasKey( rName ) ) { pResource->GetDictionary().AddKey( rName, PdfDictionary() ); } if (ePdfDataType_Reference == pResource->GetDictionary().GetKey( rName )->GetDataType()) { PdfObject *directObject = pResource->GetOwner()->GetObject(pResource->GetDictionary().GetKey( rName )->GetReference()); if (0 == directObject) { PODOFO_RAISE_ERROR( ePdfError_NoObject ); } if( !directObject->GetDictionary().HasKey( rIdentifier ) ) directObject->GetDictionary().AddKey( rIdentifier, rRef ); }else { if( !pResource->GetDictionary().GetKey( rName )->GetDictionary().HasKey( rIdentifier ) ) pResource->GetDictionary().GetKey( rName )->GetDictionary().AddKey( rIdentifier, rRef ); } } void PdfTilingPattern::Init( EPdfTilingPatternType eTilingType, double strokeR, double strokeG, double strokeB, bool doFill, double fillR, double fillG, double fillB, double offsetX, double offsetY, PdfImage *pImage) { if (eTilingType == ePdfTilingPatternType_Image && pImage == NULL) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } if (eTilingType != ePdfTilingPatternType_Image && pImage != NULL) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } PdfRect rRect; rRect.SetLeft(0); rRect.SetBottom(0); if (pImage) { rRect.SetWidth(pImage->GetWidth()); rRect.SetHeight(-pImage->GetHeight()); } else { rRect.SetWidth(8); rRect.SetHeight(8); } PdfVariant var; rRect.ToVariant( var ); this->GetObject()->GetDictionary().AddKey( PdfName("PatternType"), static_cast(1L) ); // Tiling pattern this->GetObject()->GetDictionary().AddKey( PdfName("PaintType"), static_cast(1L) ); // Colored this->GetObject()->GetDictionary().AddKey( PdfName("TilingType"), static_cast(1L) ); // Constant spacing this->GetObject()->GetDictionary().AddKey( PdfName("BBox"), var ); this->GetObject()->GetDictionary().AddKey( PdfName("XStep"), static_cast(rRect.GetWidth()) ); this->GetObject()->GetDictionary().AddKey( PdfName("YStep"), static_cast(rRect.GetHeight()) ); this->GetObject()->GetDictionary().AddKey( PdfName("Resources"), PdfObject( PdfDictionary() ) ); if (offsetX < -1e-9 || offsetX > 1e-9 || offsetY < -1e-9 || offsetY > 1e-9) { PdfArray array; array.push_back (static_cast(1)); array.push_back (static_cast(0)); array.push_back (static_cast(0)); array.push_back (static_cast(1)); array.push_back (offsetX); array.push_back (offsetY); this->GetObject()->GetDictionary().AddKey( PdfName("Matrix"), array ); } std::ostrstream out; out.flags( std::ios_base::fixed ); out.precision( 1L /* clPainterDefaultPrecision */ ); PdfLocaleImbue(out); if (pImage) { AddToResources(pImage->GetIdentifier(), pImage->GetObjectReference(), PdfName("XObject")); out << rRect.GetWidth() << " 0 0 " << rRect.GetHeight() << " " << rRect.GetLeft() << " " << rRect.GetBottom() << " cm" << std::endl; out << "/" << pImage->GetIdentifier().GetName() << " Do" << std::endl; } else { if (doFill) { out << fillR << " " << fillG << " " << fillB << " rg" << " "; out << rRect.GetLeft() << " " << rRect.GetBottom() << " " << rRect.GetWidth() << " " << rRect.GetHeight() << " re" << " "; out << "f" << " "; //fill rect } out << strokeR << " " << strokeG << " " << strokeB << " RG" << " "; out << "2 J" << " "; // line capability style out << "0.5 w" << " "; //line width double left, bottom, right, top, whalf, hhalf; left = rRect.GetLeft(); bottom = rRect.GetBottom(); right = left + rRect.GetWidth(); top = bottom + rRect.GetHeight(); whalf = rRect.GetWidth() / 2; hhalf = rRect.GetHeight() / 2; switch (eTilingType) { case ePdfTilingPatternType_BDiagonal: out << left << " " << bottom << " m " << right << " " << top << " l "; out << left - whalf << " " << top - hhalf << " m " << left + whalf << " " << top + hhalf << " l "; out << right - whalf << " " << bottom - hhalf << " m " << right + whalf << " " << bottom + hhalf << " l" << std::endl; break; case ePdfTilingPatternType_Cross: out << left << " " << bottom + hhalf << " m " << right << " " << bottom + hhalf << " l "; out << left + whalf << " " << bottom << " m " << left + whalf << " " << top << " l" << std::endl; break; case ePdfTilingPatternType_DiagCross: out << left << " " << bottom << " m " << right << " " << top << " l "; out << left << " " << top << " m " << right << " " << bottom << " l" << std::endl; break; case ePdfTilingPatternType_FDiagonal: out << left << " " << top << " m " << right << " " << bottom << " l "; out << left - whalf << " " << bottom + hhalf << " m " << left + whalf << " " << bottom - hhalf << " l "; out << right - whalf << " " << top + hhalf << " m " << right + whalf << " " << top - hhalf << " l" << std::endl; break; case ePdfTilingPatternType_Horizontal: out << left << " " << bottom + hhalf << " m " << right << " " << bottom + hhalf << " l "; break; case ePdfTilingPatternType_Vertical: out << left + whalf << " " << bottom << " m " << left + whalf << " " << top << " l" << std::endl; break; case ePdfTilingPatternType_Image: /* This is handled above, based on the 'pImage' variable */ default: PODOFO_RAISE_ERROR (ePdfError_InvalidEnumValue); break; } out << "S"; //stroke path } TVecFilters vecFlate; vecFlate.push_back( ePdfFilter_FlateDecode ); PdfMemoryInputStream stream(out.str(), out.pcount()); this->GetObject()->GetStream()->Set(&stream, vecFlate); } } // end namespace podofo-0.9.3/src/doc/PdfShadingPattern.cpp0000664000175000017500000005631412355520733020304 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2007 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfShadingPattern.h" #include "base/PdfDefinesPrivate.h" #include "base/PdfArray.h" #include "base/PdfColor.h" #include "base/PdfDictionary.h" #include "base/PdfLocale.h" #include "base/PdfStream.h" #include "base/PdfWriter.h" #include "PdfFunction.h" #include namespace PoDoFo { PdfShadingPattern::PdfShadingPattern( EPdfShadingPatternType eShadingType, PdfVecObjects* pParent ) : PdfElement( "Pattern", pParent ) { std::ostringstream out; // We probably aren't doing anything locale sensitive here, but it's // best to be sure. PdfLocaleImbue(out); // Implementation note: the identifier is always // Prefix+ObjectNo. Prefix is /Ft for fonts. out << "Sh" << this->GetObject()->Reference().ObjectNumber(); m_Identifier = PdfName( out.str().c_str() ); this->Init( eShadingType ); } PdfShadingPattern::PdfShadingPattern( EPdfShadingPatternType eShadingType, PdfDocument* pParent ) : PdfElement( "Pattern", pParent ) { std::ostringstream out; // We probably aren't doing anything locale sensitive here, but it's // best to be sure. PdfLocaleImbue(out); // Implementation note: the identifier is always // Prefix+ObjectNo. Prefix is /Ft for fonts. out << "Sh" << this->GetObject()->Reference().ObjectNumber(); m_Identifier = PdfName( out.str().c_str() ); this->Init( eShadingType ); } PdfShadingPattern::~PdfShadingPattern() { } void PdfShadingPattern::Init( EPdfShadingPatternType eShadingType ) { /* switch( eShadingType ) { case ePdfShadingPatternType_FunctionBase: { PODOFO_RAISE_ERROR( ePdfError_InternalLogic ); } break; case ePdfShadingPatternType_Radial: { PdfArray coords; coords.push_back( 0.0 ); coords.push_back( 0.0 ); coords.push_back( 0.096 ); coords.push_back( 0.0 ); coords.push_back( 0.0 ); coords.push_back( 1.0 ); PdfArray domain; domain.push_back( 0.0 ); domain.push_back( 1.0 ); PdfArray c0; c0.push_back( 0.929 ); c0.push_back( 0.357 ); c0.push_back( 1.0 ); c0.push_back( 0.298 ); PdfArray c1a; c0.push_back( 0.631 ); c0.push_back( 0.278 ); c0.push_back( 1.0 ); c0.push_back( 0.027 ); PdfArray c1b; c0.push_back( 0.94 ); c0.push_back( 0.4 ); c0.push_back( 1.0 ); c0.push_back( 0.102 ); PdfExponentialFunction f1( domain, c0, c1a, 1.048, this->GetObject()->GetOwner() ); PdfExponentialFunction f2( domain, c0, c1b, 1.374, this->GetObject()->GetOwner() ); PdfFunction::List list; list.push_back( f1 ); list.push_back( f2 ); PdfArray bounds; bounds.push_back( 0.708 ); PdfArray encode; encode.push_back( 1.0 ); encode.push_back( 0.0 ); encode.push_back( 0.0 ); encode.push_back( 1.0 ); PdfStitchingFunction function( list, domain, bounds, encode, this->GetObject()->GetOwner() ); shading.AddKey( PdfName("Coords"), coords ); shading.AddKey( PdfName("Function"), function.GetObject()->Reference() ); break; } case ePdfShadingPatternType_FreeForm: { PODOFO_RAISE_ERROR( ePdfError_InternalLogic ); } break; case ePdfShadingPatternType_LatticeForm: { PODOFO_RAISE_ERROR( ePdfError_InternalLogic ); } break; case ePdfShadingPatternType_CoonsPatch: { PODOFO_RAISE_ERROR( ePdfError_InternalLogic ); } break; case ePdfShadingPatternType_TensorProduct: { PODOFO_RAISE_ERROR( ePdfError_InternalLogic ); } break; default: { PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidEnumValue, "PdfShadingPattern::Init() failed because of an invalid shading pattern type." ); } }; */ // keys common to all shading directories PdfDictionary shading; shading.AddKey( PdfName("ShadingType"), static_cast(eShadingType) ); this->GetObject()->GetDictionary().AddKey( PdfName("PatternType"), static_cast(2L) ); // Shading pattern if (eShadingType < ePdfShadingPatternType_FreeForm) { this->GetObject()->GetDictionary().AddKey( PdfName("Shading"), shading ); } else { PdfObject *shadingObject = this->GetObject()->GetOwner()->CreateObject(shading); this->GetObject()->GetDictionary().AddKey(PdfName("Shading"), shadingObject->Reference()); this->GetObject()->GetDictionary().GetKey(PdfName("Shading"))->SetOwner(this->GetObject()->GetOwner()); } } PdfAxialShadingPattern::PdfAxialShadingPattern( double dX0, double dY0, double dX1, double dY1, const PdfColor & rStart, const PdfColor & rEnd, PdfVecObjects* pParent ) : PdfShadingPattern( ePdfShadingPatternType_Axial, pParent ) { Init( dX0, dY0, dX1, dY1, rStart, rEnd ); } PdfAxialShadingPattern::PdfAxialShadingPattern( double dX0, double dY0, double dX1, double dY1, const PdfColor & rStart, const PdfColor & rEnd, PdfDocument* pParent ) : PdfShadingPattern( ePdfShadingPatternType_Axial, pParent ) { Init( dX0, dY0, dX1, dY1, rStart, rEnd ); } void PdfAxialShadingPattern::Init( double dX0, double dY0, double dX1, double dY1, const PdfColor & rStart, const PdfColor & rEnd ) { PdfArray coords; coords.push_back( dX0 ); coords.push_back( dY0 ); coords.push_back( dX1 ); coords.push_back( dY1 ); if( rStart.GetColorSpace() != rEnd.GetColorSpace() ) { PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidDataType, "Colorspace of start and end color in PdfAxialShadingPattern does not match." ); } PdfArray c0 = rStart.ToArray(); PdfArray c1 = rEnd.ToArray(); PdfArray extend; extend.push_back( true ); extend.push_back( true ); PdfArray domain; domain.push_back( 0.0 ); domain.push_back( 1.0 ); PdfExponentialFunction function( domain, c0, c1, 1.0, this->GetObject()->GetOwner() ); PdfDictionary & shading = this->GetObject()->GetDictionary().GetKey( PdfName("Shading") )->GetDictionary(); switch( rStart.GetColorSpace() ) { case ePdfColorSpace_DeviceRGB: shading.AddKey( PdfName("ColorSpace"), PdfName("DeviceRGB") ); break; case ePdfColorSpace_DeviceCMYK: shading.AddKey( PdfName("ColorSpace"), PdfName("DeviceCMYK") ); break; case ePdfColorSpace_DeviceGray: shading.AddKey( PdfName("ColorSpace"), PdfName("DeviceGray") ); break; case ePdfColorSpace_CieLab: { PdfObject * csp = rStart.BuildColorSpace( this->GetObject()->GetOwner() ); shading.AddKey( PdfName("ColorSpace"), csp->Reference() ); } break; case ePdfColorSpace_Separation: { PdfObject * csp = rStart.BuildColorSpace( this->GetObject()->GetOwner() ); shading.AddKey( PdfName("ColorSpace"), csp->Reference() ); } break; case ePdfColorSpace_Indexed: case ePdfColorSpace_Unknown: default: PODOFO_RAISE_ERROR_INFO( ePdfError_CannotConvertColor, "Colorspace not supported in PdfAxialShadingPattern." ); break; } shading.AddKey( PdfName("Coords"), coords ); shading.AddKey( PdfName("Function"), function.GetObject()->Reference() ); shading.AddKey( PdfName("Extend"), extend ); } PdfFunctionBaseShadingPattern::PdfFunctionBaseShadingPattern( const PdfColor & rLL, const PdfColor & rUL, const PdfColor & rLR, const PdfColor & rUR, const PdfArray & rMatrix, PdfVecObjects* pParent ) : PdfShadingPattern( ePdfShadingPatternType_FunctionBase, pParent ) { Init( rLL, rUL, rLR, rUR, rMatrix ); } PdfFunctionBaseShadingPattern::PdfFunctionBaseShadingPattern( const PdfColor & rLL, const PdfColor & rUL, const PdfColor & rLR, const PdfColor & rUR, const PdfArray & rMatrix, PdfDocument* pParent ) : PdfShadingPattern( ePdfShadingPatternType_FunctionBase, pParent ) { Init( rLL, rUL, rLR, rUR, rMatrix ); } void PdfFunctionBaseShadingPattern::Init( const PdfColor & rLL, const PdfColor & rUL, const PdfColor & rLR, const PdfColor & rUR, const PdfArray & rMatrix ) { if( rLL.GetColorSpace() != rUL.GetColorSpace() || rUL.GetColorSpace() != rLR.GetColorSpace() || rLR.GetColorSpace() != rUR.GetColorSpace() ) { PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidDataType, "Colorspace of start and end color in PdfFunctionBaseShadingPattern does not match." ); } PdfArray domain; domain.push_back( 0.0 ); domain.push_back( 1.0 ); domain.push_back( 0.0 ); domain.push_back( 1.0 ); PdfDictionary & shading = this->GetObject()->GetDictionary().GetKey( PdfName("Shading") )->GetDictionary(); PdfArray range; PdfSampledFunction::Sample samples; switch ( rLL.GetColorSpace() ) { case ePdfColorSpace_DeviceRGB: { range.push_back( 0.0 ); range.push_back( 1.0 ); range.push_back( 0.0 ); range.push_back( 1.0 ); range.push_back( 0.0 ); range.push_back( 1.0 ); samples.insert( samples.end(), static_cast ( rLL.GetRed() *255.0 ) ); samples.insert( samples.end(), static_cast ( rLL.GetGreen() *255.0 ) ); samples.insert( samples.end(), static_cast ( rLL.GetBlue() *255.0 ) ); samples.insert( samples.end(), static_cast ( rLR.GetRed() *255.0 ) ); samples.insert( samples.end(), static_cast ( rLR.GetGreen() *255.0 ) ); samples.insert( samples.end(), static_cast ( rLR.GetBlue() *255.0 ) ); samples.insert( samples.end(), static_cast ( rUL.GetRed() *255.0 ) ); samples.insert( samples.end(), static_cast ( rUL.GetGreen() *255.0 ) ); samples.insert( samples.end(), static_cast ( rUL.GetBlue() *255.0 ) ); samples.insert( samples.end(), static_cast ( rUR.GetRed() *255.0 ) ); samples.insert( samples.end(), static_cast ( rUR.GetGreen() *255.0 ) ); samples.insert( samples.end(), static_cast ( rUR.GetBlue() *255.0 ) ); shading.AddKey( PdfName("ColorSpace"), PdfName("DeviceRGB") ); } break; case ePdfColorSpace_DeviceCMYK: { range.push_back( 0.0 ); range.push_back( 1.0 ); range.push_back( 0.0 ); range.push_back( 1.0 ); range.push_back( 0.0 ); range.push_back( 1.0 ); range.push_back( 0.0 ); range.push_back( 1.0 ); samples.insert( samples.end(), static_cast ( rLL.GetCyan() *255.0 ) ); samples.insert( samples.end(), static_cast ( rLL.GetMagenta() *255.0 ) ); samples.insert( samples.end(), static_cast ( rLL.GetYellow() *255.0 ) ); samples.insert( samples.end(), static_cast ( rLL.GetBlack() *255.0 ) ); samples.insert( samples.end(), static_cast ( rLR.GetCyan() *255.0 ) ); samples.insert( samples.end(), static_cast ( rLR.GetMagenta() *255.0 ) ); samples.insert( samples.end(), static_cast ( rLR.GetYellow() *255.0 ) ); samples.insert( samples.end(), static_cast ( rLR.GetBlack() *255.0 ) ); samples.insert( samples.end(), static_cast ( rUL.GetCyan() *255.0 ) ); samples.insert( samples.end(), static_cast ( rUL.GetMagenta() *255.0 ) ); samples.insert( samples.end(), static_cast ( rUL.GetYellow() *255.0 ) ); samples.insert( samples.end(), static_cast ( rUL.GetBlack() *255.0 ) ); samples.insert( samples.end(), static_cast ( rUR.GetCyan() *255.0 ) ); samples.insert( samples.end(), static_cast ( rUR.GetMagenta() *255.0 ) ); samples.insert( samples.end(), static_cast ( rUR.GetYellow() *255.0 ) ); samples.insert( samples.end(), static_cast ( rUR.GetBlack() *255.0 ) ); shading.AddKey( PdfName("ColorSpace"), PdfName("DeviceCMYK") ); } break; case ePdfColorSpace_DeviceGray: { range.push_back( 0.0 ); range.push_back( 1.0 ); samples.insert( samples.end(), static_cast ( rLL.GetGrayScale() *255.0 ) ); samples.insert( samples.end(), static_cast ( rLR.GetGrayScale() *255.0 ) ); samples.insert( samples.end(), static_cast ( rUL.GetGrayScale() *255.0 ) ); samples.insert( samples.end(), static_cast ( rUR.GetGrayScale() *255.0 ) ); shading.AddKey( PdfName("ColorSpace"), PdfName("DeviceGray") ); } break; case ePdfColorSpace_CieLab: { range.push_back( 0.0 ); range.push_back( 100.0 ); range.push_back( -128.0 ); range.push_back( 127.0 ); range.push_back( -128.0 ); range.push_back( 127.0 ); samples.insert( samples.end(), static_cast ( rLL.GetCieL() *2.55 ) ); samples.insert( samples.end(), static_cast ( rLL.GetCieA() +128 ) ); samples.insert( samples.end(), static_cast ( rLL.GetCieB() +128 ) ); samples.insert( samples.end(), static_cast ( rLR.GetCieL() *2.55 ) ); samples.insert( samples.end(), static_cast ( rLR.GetCieA() +128 ) ); samples.insert( samples.end(), static_cast ( rLR.GetCieB() +128 ) ); samples.insert( samples.end(), static_cast ( rUL.GetCieL() *2.55 ) ); samples.insert( samples.end(), static_cast ( rUL.GetCieA() +128 ) ); samples.insert( samples.end(), static_cast ( rUL.GetCieB() +128 ) ); samples.insert( samples.end(), static_cast ( rUR.GetCieL() *2.55 ) ); samples.insert( samples.end(), static_cast ( rUR.GetCieA() +128 ) ); samples.insert( samples.end(), static_cast ( rUR.GetCieB() +128 ) ); PdfObject * csp = rLL.BuildColorSpace( this->GetObject()->GetOwner() ); shading.AddKey( PdfName("ColorSpace"), csp->Reference() ); } break; case ePdfColorSpace_Separation: { range.push_back( 0.0 ); range.push_back( 1.0 ); samples.insert( samples.end(), static_cast ( rLL.GetDensity() *255.0 ) ); samples.insert( samples.end(), static_cast ( rLR.GetDensity() *255.0 ) ); samples.insert( samples.end(), static_cast ( rUL.GetDensity() *255.0 ) ); samples.insert( samples.end(), static_cast ( rUR.GetDensity() *255.0 ) ); PdfObject * csp = rLL.BuildColorSpace( this->GetObject()->GetOwner() ); shading.AddKey( PdfName("ColorSpace"), csp->Reference() ); } break; case ePdfColorSpace_Indexed: case ePdfColorSpace_Unknown: default: PODOFO_RAISE_ERROR_INFO( ePdfError_CannotConvertColor, "Colorspace not supported in PdfFunctionBaseShadingPattern." ); break; } PdfSampledFunction function( domain, range, samples, this->GetObject()->GetOwner() ); shading.AddKey( PdfName("Function"), function.GetObject()->Reference() ); shading.AddKey( PdfName("Domain"), domain ); shading.AddKey( PdfName("Matrix"), rMatrix ); } PdfRadialShadingPattern::PdfRadialShadingPattern( double dX0, double dY0, double dR0, double dX1, double dY1, double dR1, const PdfColor & rStart, const PdfColor & rEnd, PdfVecObjects* pParent ) : PdfShadingPattern( ePdfShadingPatternType_Radial, pParent ) { Init( dX0, dY0, dR0, dX1, dY1, dR1, rStart, rEnd ); } PdfRadialShadingPattern::PdfRadialShadingPattern( double dX0, double dY0, double dR0, double dX1, double dY1, double dR1, const PdfColor & rStart, const PdfColor & rEnd, PdfDocument* pParent ) : PdfShadingPattern( ePdfShadingPatternType_Radial, pParent ) { Init( dX0, dY0, dR0, dX1, dY1, dR1, rStart, rEnd ); } void PdfRadialShadingPattern::Init( double dX0, double dY0, double dR0, double dX1, double dY1, double dR1, const PdfColor & rStart, const PdfColor & rEnd ) { PdfArray coords; coords.push_back( dX0 ); coords.push_back( dY0 ); coords.push_back( dR0 ); coords.push_back( dX1 ); coords.push_back( dY1 ); coords.push_back( dR1 ); if( rStart.GetColorSpace() != rEnd.GetColorSpace() ) { PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidDataType, "Colorspace of start and end color in PdfRadialShadingPattern does not match." ); } PdfArray c0 = rStart.ToArray(); PdfArray c1 = rEnd.ToArray(); PdfArray extend; extend.push_back( true ); extend.push_back( true ); PdfArray domain; domain.push_back( 0.0 ); domain.push_back( 1.0 ); PdfExponentialFunction function( domain, c0, c1, 1.0, this->GetObject()->GetOwner() ); PdfDictionary & shading = this->GetObject()->GetDictionary().GetKey( PdfName("Shading") )->GetDictionary(); switch( rStart.GetColorSpace() ) { case ePdfColorSpace_DeviceRGB: shading.AddKey( PdfName("ColorSpace"), PdfName("DeviceRGB") ); break; case ePdfColorSpace_DeviceCMYK: shading.AddKey( PdfName("ColorSpace"), PdfName("DeviceCMYK") ); break; case ePdfColorSpace_DeviceGray: shading.AddKey( PdfName("ColorSpace"), PdfName("DeviceGray") ); break; case ePdfColorSpace_CieLab: { PdfObject * csp = rStart.BuildColorSpace( this->GetObject()->GetOwner() ); shading.AddKey( PdfName("ColorSpace"), csp->Reference() ); } break; case ePdfColorSpace_Separation: { PdfObject * csp = rStart.BuildColorSpace( this->GetObject()->GetOwner() ); shading.AddKey( PdfName("ColorSpace"), csp->Reference() ); } break; case ePdfColorSpace_Indexed: case ePdfColorSpace_Unknown: default: PODOFO_RAISE_ERROR_INFO( ePdfError_CannotConvertColor, "Colorspace not supported in PdfRadialShadingPattern." ); break; } shading.AddKey( PdfName("Coords"), coords ); shading.AddKey( PdfName("Function"), function.GetObject()->Reference() ); shading.AddKey( PdfName("Extend"), extend ); } PdfTriangleShadingPattern::PdfTriangleShadingPattern( double dX0, double dY0, const PdfColor &color0, double dX1, double dY1, const PdfColor &color1, double dX2, double dY2, const PdfColor &color2, PdfVecObjects* pParent ) : PdfShadingPattern( ePdfShadingPatternType_FreeForm, pParent ) { Init(dX0, dY0, color0, dX1, dY1, color1, dX2, dY2, color2 ); } PdfTriangleShadingPattern::PdfTriangleShadingPattern( double dX0, double dY0, const PdfColor &color0, double dX1, double dY1, const PdfColor &color1, double dX2, double dY2, const PdfColor &color2, PdfDocument* pParent ) : PdfShadingPattern( ePdfShadingPatternType_FreeForm, pParent ) { Init(dX0, dY0, color0, dX1, dY1, color1, dX2, dY2, color2 ); } void PdfTriangleShadingPattern::Init( double dX0, double dY0, const PdfColor &color0, double dX1, double dY1, const PdfColor &color1, double dX2, double dY2, const PdfColor &color2 ) { if (color0.GetColorSpace() != color1.GetColorSpace() || color0.GetColorSpace() != color2.GetColorSpace()) { PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidDataType, "Colorspace of start and end color in PdfTriangleShadingPattern does not match." ); } PdfColor rgb0 = color0.ConvertToRGB(); PdfColor rgb1 = color1.ConvertToRGB(); PdfColor rgb2 = color2.ConvertToRGB(); PdfArray decode; double minx, maxx, miny, maxy; #define mMIN(a,b) ((a) < (b) ? (a) : (b)) #define mMAX(a,b) ((a) > (b) ? (a) : (b)) minx = mMIN(mMIN(dX0, dX1), dX2); maxx = mMAX(mMAX(dX0, dX1), dX2); miny = mMIN(mMIN(dY0, dY1), dY2); maxy = mMAX(mMAX(dY0, dY1), dY2); #undef mMIN #undef mMAX decode.push_back(minx); decode.push_back(maxx); decode.push_back(miny); decode.push_back(maxy); decode.push_back(static_cast(0)); decode.push_back(static_cast(1)); decode.push_back(static_cast(0)); decode.push_back(static_cast(1)); decode.push_back(static_cast(0)); decode.push_back(static_cast(1)); PdfObject *shadingObject = this->GetObject()->GetIndirectKey(PdfName("Shading")); PdfDictionary &shading = shadingObject->GetDictionary(); shading.AddKey( PdfName("ColorSpace"), PdfName("DeviceRGB") ); shading.AddKey( PdfName("BitsPerCoordinate"), static_cast(8)); shading.AddKey( PdfName("BitsPerComponent"), static_cast(8)); shading.AddKey( PdfName("BitsPerFlag"), static_cast(8)); shading.AddKey( PdfName("Decode"), decode); // f x y c1 c2 c3 int len = (1 + 1 + 1 + 1 + 1 + 1) * 3; char buff[18]; buff[ 0] = 0; // flag - start new triangle buff[ 1] = static_cast(255.0 * (dX0 - minx) / (maxx - minx)); buff[ 2] = static_cast(255.0 * (dY0 - miny) / (maxy - miny)); buff[ 3] = static_cast(255.0 * rgb0.GetRed()); buff[ 4] = static_cast(255.0 * rgb0.GetGreen()); buff[ 5] = static_cast(255.0 * rgb0.GetBlue()); buff[ 6] = 0; // flag - start new triangle buff[ 7] = static_cast(255.0 * (dX1 - minx) / (maxx - minx)); buff[ 8] = static_cast(255.0 * (dY1 - miny) / (maxy - miny)); buff[ 9] = static_cast(255.0 * rgb1.GetRed()); buff[10] = static_cast(255.0 * rgb1.GetGreen()); buff[11] = static_cast(255.0 * rgb1.GetBlue()); buff[12] = 0; // flag - start new triangle buff[13] = static_cast(255.0 * (dX2 - minx) / (maxx - minx)); buff[14] = static_cast(255.0 * (dY2 - miny) / (maxy - miny)); buff[15] = static_cast(255.0 * rgb2.GetRed()); buff[16] = static_cast(255.0 * rgb2.GetGreen()); buff[17] = static_cast(255.0 * rgb2.GetBlue()); shadingObject->GetStream()->Set(buff, len); } } // end namespace podofo-0.9.3/src/doc/PdfSigIncMemDocument.h0000664000175000017500000001136012277220550020335 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2014 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_SIGMEM_DOCUMENT_H_ #define _PDF_SIGMEM_DOCUMENT_H_ #include "podofo/base/PdfDefines.h" #include "podofo/base/PdfObject.h" #include "PdfDocument.h" #include "PdfFontCache.h" #include "PdfSignOutputDevice.h" #include "podofo/base/PdfRefCountedInputDevice.h" #include "podofo/base/PdfRect.h" #include "podofo/base/PdfCanvas.h" #include "PdfPage.h" #include "PdfImage.h" #include "PdfSigIncSignatureField.h" namespace PoDoFo { class PdfMemDocument; class PODOFO_DOC_API PdfExMemDocument : public PdfMemDocument { private: pdf_long m_XRefOffset; bool m_bXRefStream; protected: virtual void InitFromParser( PdfParser* pParser ); public: PdfExMemDocument(const char* pszInpFilename); PdfExMemDocument(const PdfRefCountedInputDevice &rInputDevice); virtual ~PdfExMemDocument(); pdf_long GetXRefOffset(void) { return m_XRefOffset;} bool HasXRefStream(void) {return m_bXRefStream;} }; class PODOFO_DOC_API PdfSigIncMemDocument : private PdfMemDocument { private: const char* m_InpFilename; PdfRect m_SignRect; PdfExMemDocument *m_Document; pdf_int64 m_LastXRefOffset; std::vector m_PagesRef; PdfXObject *m_pImgXObj; PdfXObject *m_n2XObj; PdfFont *m_pFont; PdfSigIncSignatureField *m_pSignField; bool m_bLinearized; protected: void CreateAnnotation(PdfSignOutputDevice* pDevice, PdfPage* pPage); PdfAcroForm* GetExistedAcroForm(PdfAcroForm *pOldAcroForm); void AddSignImage(PdfImage &pdfImage, const wchar_t *signatureText, PdfPage *pPage, PdfRect &pdfRect); bool AddPageToIncDocument(PdfPage *pPage); //void CreateSignObject(int page, PdfRect &pdfRect); void CreateVisualSignRect(void); void AddVisualSign(PdfPage *pPage); public: PdfSigIncMemDocument(const char* pszInpFilename); virtual ~PdfSigIncMemDocument(); void Initialize(); int GetPageCount(void); PdfPage *GetPage(int page); PdfMemDocument *GetMainPdfDocument(void) {return m_Document;} PdfSigIncSignatureField *GetSignatureField(void) {return m_pSignField;} void Write( PdfSignOutputDevice* pDevice ); void CreateVisualSign(void); //void CreateSignImage(const char* pszInpFilename, int page, PdfRect &pdfRect); // void CreateSignText(const char* signText, int page, PdfRect &pdfRect); }; }; #endif // _PDF_SIGMEM_DOCUMENT_H_ podofo-0.9.3/src/doc/PdfSigIncSignatureField.cpp0000664000175000017500000001473212347347566021405 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2014 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfSigIncSignatureField.h" #include #include "PdfPage.h" namespace PoDoFo { PdfSigIncSignatureField::PdfSigIncSignatureField(PdfDocument *pDocument) { m_SignPage = -1; m_pImageData = NULL; m_ImageLen= 0; m_SignReason = PdfString("I agree"); m_FontSize = 8; m_pDocument = pDocument; m_Red = 0; m_Green = 0; m_Blue = 0; m_Threshold = -1; } PdfSigIncSignatureField::~PdfSigIncSignatureField() { } void PdfSigIncSignatureField::SetSignatureReason(const wchar_t *text) { m_SignReason = CreatePdfString(text); } void PdfSigIncSignatureField::SetSignatureDate(const PdfDate &sigDate) { m_SignDate = sigDate; } bool PdfSigIncSignatureField::HasSignatureText(void) { return m_SignText.GetLength() > 0; } bool PdfSigIncSignatureField::HasSignatureImage(void) { return m_ImageFile.GetLength() > 0 || (m_ImageLen > 0 && m_pImageData != NULL); } PdfString PdfSigIncSignatureField::CreatePdfString(const wchar_t *text) { #if defined(_MSC_VER) && _MSC_VER <= 1200 #ifdef PODOFO_IS_LITTLE_ENDIAN if(sizeof(wchar_t) == 2) { const size_t strLen = wcslen(text); wchar_t *buffer = new wchar_t[strLen + 2]; wcscpy(buffer, text); buffer[strLen] = '\0'; buffer[strLen] = '\0'; wchar_t *pszTxt = buffer; while( *pszTxt ) { *pszTxt = ((*pszTxt) << 8 | (*pszTxt) >> 8); ++pszTxt; } PdfString result(buffer); delete []buffer; return result; } else return PdfString(text); #else return PdfString(text); #endif #else return PdfString(text); #endif } void PdfSigIncSignatureField::SetSignatureText(const wchar_t *text, int page, int x, int y, int width, int height, float fontSize) { PdfRect pdfRect(x, y, width, height); PdfPage *pPage = m_pDocument->GetPage(page); if(pPage) { PdfRect size = pPage->GetPageSize(); double pHeight = size.GetHeight(); double newY = pHeight - (y + height); pdfRect.SetBottom(newY); } m_SignTextRect = pdfRect; m_SignPage = page; //Visual Studio 6 m_SignText = CreatePdfString(text); if(fontSize > 0) { m_FontSize = fontSize; } } void PdfSigIncSignatureField::SetSignatureImage(const char *fileName, int page, int x, int y, int width, int height) { PdfRect pdfRect(x, y, width, height); PdfPage *pPage = m_pDocument->GetPage(page); if(pPage) { PdfRect size = pPage->GetPageSize(); double pHeight = size.GetHeight(); double newY = pHeight - (y + height); pdfRect.SetBottom(newY); } m_SignImageRect = pdfRect; m_ImageFile = fileName; m_SignPage = page; } void PdfSigIncSignatureField::SetSignatureImage(const unsigned char *pData, pdf_long lLen, int page, int x, int y, int width, int height) { PdfRect pdfRect(x, y, width, height); PdfPage *pPage = m_pDocument->GetPage(page); if(pPage) { PdfRect size = pPage->GetPageSize(); double pHeight = size.GetHeight(); double newY = pHeight - (y + height); pdfRect.SetBottom(newY); } m_SignImageRect = pdfRect; m_pImageData = pData; m_ImageLen = lLen; m_SignPage = page; } void PdfSigIncSignatureField::SetImageChromaKeyMask(pdf_int64 r, pdf_int64 g, pdf_int64 b, pdf_int64 threshold) { m_Red = r; m_Green = g; m_Blue = b; m_Threshold = threshold; } PdfImage *PdfSigIncSignatureField::CreateSignatureImage(PdfDocument *pParent) { PdfImage *pPdfImage = NULL; #ifdef PODOFO_HAVE_JPEG_LIB if(m_ImageFile.GetLength() > 0) { pPdfImage = new PdfImage(pParent); pPdfImage->LoadFromJpeg(m_ImageFile.GetString()); } else if(m_ImageLen > 0 && m_pImageData != NULL) { pPdfImage = new PdfImage(pParent); pPdfImage->LoadFromJpegData((const unsigned char *) m_pImageData, m_ImageLen); } #endif if(pPdfImage != NULL && m_Threshold >= 0) { pPdfImage->SetImageChromaKeyMask(m_Red, m_Green, m_Blue, m_Threshold); } return pPdfImage; } void PdfSigIncSignatureField::FreeSignatureImage(PdfImage *img) { if(img) { delete img; } } } podofo-0.9.3/src/doc/PdfTilingPattern.h0000664000175000017500000001276012347301431017610 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2007 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #ifndef _PDF_TILING_PATTERN_H_ #define _PDF_TILING_PATTERN_H_ #include "podofo/base/PdfDefines.h" #include "podofo/base/PdfName.h" #include "PdfElement.h" namespace PoDoFo { class PdfImage; class PdfObject; class PdfPage; class PdfWriter; /** * This class defined a tiling pattern which can be used * to fill abitrary shapes with a pattern using PdfPainter. */ class PODOFO_DOC_API PdfTilingPattern : public PdfElement { public: virtual ~PdfTilingPattern(); /** Returns the identifier of this TilingPattern how it is known * in the pages resource dictionary. * \returns PdfName containing the identifier (e.g. /PtrnXXXXX) */ inline const PdfName & GetIdentifier() const; /** Create a new PdfTilingPattern object, which will introduce itself * automatically to every page object it is used on. * * \param eTilingType the type of this tiling pattern * \param strokeR strok color red component * \param strokeG strok color green component * \param strokeB strok color blue component * \param doFill whether tile fills content first, with fill color * \param fillR fill color red component * \param fillG fill color green component * \param fillB fill color blue component * \param offsetX tile offset on X axis * \param offsetY tile offset on Y axis * \param pImage image to use - can be set only if eTilingType is ePdfTilingPatternType_Image * \param pParent parent vector of objects * * \note stroke and fill colors are ignored if eTilingType is ePdfTilingPatternType_Image * \note fill color is ignored if doFill is false * \note pImage is ignored for all but ePdfTilingPatternType_Image eTilingType types, where it cannot be NULL * */ PdfTilingPattern( EPdfTilingPatternType eTilingType, double strokeR, double strokeG, double strokeB, bool doFill, double fillR, double fillG, double fillB, double offsetX, double offsetY, PdfImage *pImage, PdfVecObjects* pParent); /** Create a new PdfTilingPattern object, which will introduce itself * automatically to every page object it is used on. * * \param eTilingType the type of this tiling pattern * \param strokeR strok color red component * \param strokeG strok color green component * \param strokeB strok color blue component * \param doFill whether tile fills content first, with fill color * \param fillR fill color red component * \param fillG fill color green component * \param fillB fill color blue component * \param offsetX tile offset on X axis * \param offsetY tile offset on Y axis * \param pImage image to use - can be set only if eTilingType is ePdfTilingPatternType_Image * \param pParent parent document * * \note stroke and fill colors are ignored if eTilingType is ePdfTilingPatternType_Image * \note fill color is ignored if doFill is false * \note pImage is ignored for all but ePdfTilingPatternType_Image eTilingType types, where it cannot be NULL * */ PdfTilingPattern( EPdfTilingPatternType eTilingType, double strokeR, double strokeG, double strokeB, bool doFill, double fillR, double fillG, double fillB, double offsetX, double offsetY, PdfImage *pImage, PdfDocument* pParent); private: /** Initialize the object */ void Init( EPdfTilingPatternType eTilingType, double strokeR, double strokeG, double strokeB, bool doFill, double fillR, double fillG, double fillB, double offsetX, double offsetY, PdfImage *pImage); void AddToResources(const PdfName &rIdentifier, const PdfReference &rRef, const PdfName &rName); private: PdfName m_Identifier; }; // ----------------------------------------------------- // // ----------------------------------------------------- const PdfName & PdfTilingPattern::GetIdentifier() const { return m_Identifier; } } // end namespace #endif // _PDF_TILING_PATTERN_H_ podofo-0.9.3/src/doc/PdfContents.cpp0000664000175000017500000001141112344436402017150 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2006 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfContents.h" #include "base/PdfDefinesPrivate.h" #include "base/PdfArray.h" #include "base/PdfDictionary.h" #include "base/PdfName.h" #include "base/PdfOutputDevice.h" #include "PdfDocument.h" #include "PdfPage.h" #include namespace PoDoFo { PdfContents::PdfContents( PdfDocument* pParent ) : PdfElement( NULL, pParent ) { mContObj = this->GetObject(); } PdfContents::PdfContents( PdfVecObjects* pParent ) : PdfElement( NULL, pParent ) { mContObj = this->GetObject(); } PdfContents::PdfContents( PdfObject* inObj ) // A PdfElement expects normally a dictionary // But we may get here, a reference, a dictionary // or an array. Therefore, tell PdfElement // that we also want to accept the datatype of // the object we send in. : PdfElement( inObj->GetDataType(), inObj ) { if ( this->GetObject()->GetDataType() == ePdfDataType_Reference ) mContObj = inObj->GetOwner()->GetObject( this->GetObject()->GetReference() ); else mContObj = this->GetObject(); } PdfContents::PdfContents( PdfPage* pParent ) : PdfElement( NULL, pParent->GetObject()->GetOwner() ) { // TODO: Maybe create this only on demand pParent->GetObject()->GetDictionary().AddKey( "Contents", this->GetObject()->Reference() ); mContObj = this->GetObject(); } PdfObject* PdfContents::GetContentsForAppending() const { // if ( mContObj->GetDataType() == ePdfDataType_Stream || // mContObj->GetDataType() == ePdfDataType_Dictionary ) { // Use PdfObject::HasStream() instead of the datatype ePdfDataType_Stream // as large parts of the code rely on all PdfObjects having the datatype // ePdfDataType_Dictionary wether they have a stream or not if( mContObj->GetDataType() == ePdfDataType_Dictionary ) { return mContObj; // just return the stream itself } else if ( mContObj->GetDataType() == ePdfDataType_Array ) { /* Create a new stream, add it to the array, return it */ PdfObject* newStm = mContObj->GetOwner()->CreateObject(); newStm->GetStream(); PdfReference pdfr( newStm->Reference().ObjectNumber(), newStm->Reference().GenerationNumber() ); PdfArray& cArr = mContObj->GetArray(); cArr.push_back( pdfr ); return newStm; } else { PODOFO_RAISE_ERROR( ePdfError_InvalidDataType ); } } }; podofo-0.9.3/src/doc/PdfMemDocument.h0000664000175000017500000006002112320241722017227 0ustar dominikdominik/************************************************************************** * Copyright (C) 2006 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_MEM_DOCUMENT_H_ #define _PDF_MEM_DOCUMENT_H_ #include "podofo/base/PdfDefines.h" #include "podofo/base/PdfObject.h" #include "podofo/base/PdfExtension.h" #include "PdfDocument.h" #include "PdfFontCache.h" namespace PoDoFo { class PdfAcroForm; class PdfDestination; class PdfDictionary; class PdfEncrypt; class PdfFileSpec; class PdfFont; class PdfInfo; class PdfNamesTree; class PdfOutlines; class PdfPage; class PdfPagesTree; class PdfParser; class PdfRect; class PdfWriter; /** PdfMemDocument is the core class for reading and manipulating * PDF files and writing them back to disk. * * PdfMemDocument was designed to allow easy access to the object * structur of a PDF file. * * PdfMemDocument should be used whenever you want to change * the object structure of a PDF file. * * When you are only creating PDF files, please use PdfStreamedDocument * which is usually faster for creating PDFs. * * \see PdfDocument * \see PdfStreamedDocument * \see PdfParser * \see PdfWriter */ class PODOFO_DOC_API PdfMemDocument : public PdfDocument { friend class PdfWriter; public: /** Construct a new (empty) PdfMemDocument */ PdfMemDocument(); /** Construct a new (empty) PdfMemDocument */ PdfMemDocument( bool bOnlyTrailer ); /** Construct a PdfMemDocument from an existing PDF (on disk) * \param pszFilename filename of the file which is going to be parsed/opened * * This might throw a PdfError( ePdfError_InvalidPassword ) exception * if a password is required to read this PDF. * Call SetPassword with the correct password in this case. * * \see SetPassword */ PdfMemDocument( const char* pszFilename ); #ifdef _WIN32 #if defined(_MSC_VER) && _MSC_VER <= 1200 // nicht fr Visualstudio 6 #else /** Construct a PdfMemDocument from an existing PDF (on disk) * \param pszFilename filename of the file which is going to be parsed/opened * * This might throw a PdfError( ePdfError_InvalidPassword ) exception * if a password is required to read this PDF. * Call SetPassword with the correct password in this case. * * This is an overloaded member function to allow working * with unicode characters. On Unix systes you can also path * UTF-8 to the const char* overload. * * \see SetPassword */ PdfMemDocument( const wchar_t* pszFilename ); #endif #endif // _WIN32 /** Close down/destruct the PdfMemDocument */ virtual ~PdfMemDocument(); /** Load a PdfMemDocument from a file * * \param pszFilename filename of the file which is going to be parsed/opened * * This might throw a PdfError( ePdfError_InvalidPassword ) exception * if a password is required to read this PDF. * Call SetPassword with the correct password in this case. * * \see SetPassword */ void Load( const char* pszFilename ); #ifdef _WIN32 #if defined(_MSC_VER) && _MSC_VER <= 1200 // nicht fr Visualstudio 6 #else /** Load a PdfMemDocument from a file * * \param pszFilename filename of the file which is going to be parsed/opened * * This might throw a PdfError( ePdfError_InvalidPassword ) exception * if a password is required to read this PDF. * Call SetPassword with the correct password in this case. * * This is an overloaded member function to allow working * with unicode characters. On Unix systes you can also path * UTF-8 to the const char* overload. * * \see SetPassword */ void Load( const wchar_t* pszFilename ); #endif #endif // _WIN32 /** Load a PdfMemDocument from a buffer in memory * * \param pBuffer a memory area containing the PDF data * \param lLen length of the buffer * * This might throw a PdfError( ePdfError_InvalidPassword ) exception * if a password is required to read this PDF. * Call SetPassword with the correct password in this case. * * \see SetPassword */ void Load( const char* pBuffer, long lLen ); /** Load a PdfMemDocument from a PdfRefCountedInputDevice * * \param rDevice the input device containing the PDF * * This might throw a PdfError( ePdfError_InvalidPassword ) exception * if a password is required to read this PDF. * Call SetPassword with the correct password in this case. * * \see SetPassword */ void Load( const PdfRefCountedInputDevice & rDevice ); /** Writes the complete document to a file * * \param pszFilename filename of the document * * \see Write * * This is an overloaded member function for your convinience. */ void Write( const char* pszFilename ); #ifdef _WIN32 /** Writes the complete document to a file * * \param pszFilename filename of the document * * \see Write * * This is an overloaded member function to allow working * with unicode characters. On Unix systes you can also path * UTF-8 to the const char* overload. * * This is an overloaded member function for your convinience. */ void Write( const wchar_t* pszFilename ); #endif // _WIN32 /** Writes the complete document to an output device * * \param pDevice write to this output device */ void Write( PdfOutputDevice* pDevice ); /** Set the write mode to use when writing the PDF. * \param eWriteMode write mode */ void SetWriteMode( EPdfWriteMode eWriteMode ) { m_eWriteMode = eWriteMode; } /** Get the write mode used for wirting the PDF * \returns the write mode */ virtual EPdfWriteMode GetWriteMode() const { return m_eWriteMode; } /** Set the PDF Version of the document. Has to be called before Write() to * have an effect. * \param eVersion version of the pdf document */ void SetPdfVersion( EPdfVersion eVersion ) { m_eVersion = eVersion;} /** Get the PDF version of the document * \returns EPdfVersion version of the pdf document */ EPdfVersion GetPdfVersion() const { return m_eVersion; } /** Add a vendor-specific extension to the current PDF version. * \param ns namespace of the extension * \param level level of the extension */ void AddPdfExtension( const char* ns, pdf_int64 level ); /** Checks whether the documents is tagged to imlpement a vendor-specific * extension to the current PDF version. * \param ns namespace of the extension * \param level level of the extension */ bool HasPdfExtension( const char* ns, pdf_int64 level ) const; /** Remove a vendor-specific extension to the current PDF version. * \param ns namespace of the extension * \param level level of the extension */ void RemovePdfExtension( const char* ns, pdf_int64 level ); /** Return the list of all vendor-specific extensions to the current PDF version. * \param ns namespace of the extension * \param level level of the extension */ std::vector GetPdfExtensions() const; /** If you try to open an encrypted PDF file, which requires * a password to open, PoDoFo will throw a PdfError( ePdfError_InvalidPassword ) * exception. * * If you got such an exception, you have to set a password * which should be used for opening the PDF. * * The usual way will be to ask the user for the password * and set the password using this method. * * PdfParser will immediately continue to read the PDF file. * * \param sPassword a user or owner password which can be used to open an encrypted PDF file * If the password is invalid, a PdfError( ePdfError_InvalidPassword ) exception is thrown! */ void SetPassword( const std::string & sPassword ); /** Encrypt the document during writing. * * \param userPassword the user password (if empty the user does not have * to enter a password to open the document) * \param ownerPassword the owner password * \param protection several EPdfPermissions values or'ed together to set * the users permissions for this document * \param eAlgorithm the revision of the encryption algorithm to be used * \param eKeyLength the length of the encryption key ranging from 40 to 256 bits * (only used if eAlgorithm >= ePdfEncryptAlgorithm_RC4V2) * * \see PdfEncrypt */ void SetEncrypted( const std::string & userPassword, const std::string & ownerPassword, int protection = PdfEncrypt::ePdfPermissions_Print | PdfEncrypt::ePdfPermissions_Edit | PdfEncrypt::ePdfPermissions_Copy | PdfEncrypt::ePdfPermissions_EditNotes | PdfEncrypt::ePdfPermissions_FillAndSign | PdfEncrypt::ePdfPermissions_Accessible | PdfEncrypt::ePdfPermissions_DocAssembly | PdfEncrypt::ePdfPermissions_HighPrint, PdfEncrypt::EPdfEncryptAlgorithm eAlgorithm = PdfEncrypt::ePdfEncryptAlgorithm_RC4V1, PdfEncrypt::EPdfKeyLength eKeyLength = PdfEncrypt::ePdfKeyLength_40 ); /** Encrypt the document during writing using a PdfEncrypt object * * \param pEncrypt an encryption object that will be owned by PdfMemDocument */ void SetEncrypted( const PdfEncrypt & pEncrypt ); /** * \returns true if this PdfMemDocument creates an encrypted PDF file */ bool GetEncrypted() const { return (m_pEncrypt != NULL); } /** Returns wether this PDF document is linearized, aka * weboptimized * \returns true if the PDF document is linearized */ bool IsLinearized() const { return m_bLinearized; } /** Get a reference to the sorted internal objects vector. * \returns the internal objects vector. */ const PdfVecObjects & GetObjects() const { return *(PdfDocument::GetObjects()); } /** Get a reference to the sorted internal objects vector. * This is an overloaded function for your convinience. * \returns the internal objects vector. */ PdfVecObjects & GetObjects() { return *(PdfDocument::GetObjects()); } /** Get access to the internal Catalog dictionary * or root object. * * \returns PdfObject the documents catalog or NULL * if no catalog is available */ PdfObject* GetCatalog() { return PdfDocument::GetCatalog(); } /** Get access to the internal Catalog dictionary * or root object. * * \returns PdfObject the documents catalog or NULL * if no catalog is available */ const PdfObject* GetCatalog() const { return PdfDocument::GetCatalog(); } /** Get the trailer dictionary * which can be written unmodified to a pdf file. */ const PdfObject* GetTrailer() const { return PdfDocument::GetTrailer(); } /** Get access to the StructTreeRoot dictionary * \returns PdfObject the StructTreeRoot dictionary */ PdfObject* GetStructTreeRoot() const { return GetNamedObjectFromCatalog( "StructTreeRoot" ); } /** Get access to the Metadata stream * \returns PdfObject the Metadata stream (should be in XML, using XMP grammar) */ PdfObject* GetMetadata() const { return GetNamedObjectFromCatalog( "Metadata" ); } /** Get access to the MarkInfo dictionary (ISO 32000-1:2008 14.7.1) * \returns PdfObject the MarkInfo dictionary */ PdfObject* GetMarkInfo() const { return GetNamedObjectFromCatalog( "MarkInfo" ); } /** Get access to the RFC 3066 natural language id for the document (ISO 32000-1:2008 14.9.2.1) * \returns PdfObject the language ID string */ PdfObject* GetLanguage() const { return GetNamedObjectFromCatalog( "Lang" ); } /** Creates a PdfFont object from an existing font. * * \param pObject a PdfObject that is a font * \returns PdfFont* a pointer to a new PdfFont object. * The returned object is owned by the PdfDocument. */ PdfFont* GetFont( PdfObject* pObject ); /** Copies one or more pages from another PdfMemDocument to this document * \param rDoc the document to append * \param inFirstPage the first page number to copy (0-based) * \param inNumPages the number of pages to copy * \returns this document */ const PdfMemDocument & InsertPages( const PdfMemDocument & rDoc, int inFirstPage, int inNumPages ); /** Deletes one or more pages from this document * It does NOT remove any PdfObjects from memory - just the reference from the pages tree. * If you want to delete resources of this page, you have to delete them yourself, * but the resources might be used by other pages, too. * * \param inFirstPage the first page number to delete (0-based) * \param inNumPages the number of pages to delete * \returns this document */ void DeletePages( int inFirstPage, int inNumPages ); /** Checks if printing this document is allowed. * Every PDF consuming applications has to adhere this value! * * \returns true if you are allowed to print this document * * \see PdfEncrypt to set own document permissions. */ inline virtual bool IsPrintAllowed() const; /** Checks if modifiying this document (besides annotations, form fields or changing pages) is allowed. * Every PDF consuming applications has to adhere this value! * * \returns true if you are allowed to modfiy this document * * \see PdfEncrypt to set own document permissions. */ inline virtual bool IsEditAllowed() const; /** Checks if text and graphics extraction is allowed. * Every PDF consuming applications has to adhere this value! * * \returns true if you are allowed to extract text and graphics from this document * * \see PdfEncrypt to set own document permissions. */ inline virtual bool IsCopyAllowed() const; /** Checks if it is allowed to add or modify annotations or form fields * Every PDF consuming applications has to adhere this value! * * \returns true if you are allowed to add or modify annotations or form fields * * \see PdfEncrypt to set own document permissions. */ inline virtual bool IsEditNotesAllowed() const; /** Checks if it is allowed to fill in existing form or signature fields * Every PDF consuming applications has to adhere this value! * * \returns true if you are allowed to fill in existing form or signature fields * * \see PdfEncrypt to set own document permissions. */ inline virtual bool IsFillAndSignAllowed() const; /** Checks if it is allowed to extract text and graphics to support users with disabillities * Every PDF consuming applications has to adhere this value! * * \returns true if you are allowed to extract text and graphics to support users with disabillities * * \see PdfEncrypt to set own document permissions. */ inline virtual bool IsAccessibilityAllowed() const; /** Checks if it is allowed to insert, create, rotate, delete pages or add bookmarks * Every PDF consuming applications has to adhere this value! * * \returns true if you are allowed to insert, create, rotate, delete pages or add bookmarks * * \see PdfEncrypt to set own document permissions. */ inline virtual bool IsDocAssemblyAllowed() const; /** Checks if it is allowed to print a high quality version of this document * Every PDF consuming applications has to adhere this value! * * \returns true if you are allowed to print a high quality version of this document * * \see PdfEncrypt to set own document permissions. */ inline virtual bool IsHighPrintAllowed() const; /** Tries to free all memory allocated by the given * PdfObject (variables and streams) and reads * it from disk again if it is requested another time. * * This will only work if load on demand is used. Other- * wise any call to this method will be ignored. Load on * demand is currently always enabled when using PdfMemDocument. * If the object is dirty if will not be free'd. * * \param rRef free all memory allocated by the object * with this reference. * \param bForce if true the object will be free'd * even if IsDirty() returns true. * So you will loose any changes made * to this object. * * This is an overloaded member for your convinience. */ void FreeObjectMemory( const PdfReference & rRef, bool bForce = false ); /** Tries to free all memory allocated by the given * PdfObject (variables and streams) and reads * it from disk again if it is requested another time. * * This will only work if load on demand is used. Other- * wise any call to this method will be ignored. Load on * demand is currently always enabled when using PdfMemDocument. * If the object is dirty if will not be free'd. * * \param pObj free object from memory * \param bForce if true the object will be free'd * even if IsDirty() returns true. * So you will loose any changes made * to this object. * * \see IsDirty */ void FreeObjectMemory( PdfObject* pObj, bool bForce = false ); /** * \returns the parsers encryption object or NULL if the read PDF file was not encrypted */ inline const PdfEncrypt* GetEncrypt() const; //begin L.K protected: PdfObject* GetMainTrailer() { return PdfDocument::GetTrailer(); } //private /** Get a dictioary from the catalog dictionary by its name. * \param pszName will be converted into a PdfName * \returns the dictionary if it was found or NULL */ PdfObject* GetNamedObjectFromCatalog( const char* pszName ) const; //private /** Internal method to load all objects from a PdfParser object. * The objects will be removed from the parser and are now * owned by the PdfMemDocument. */ //void InitFromParser( PdfParser* pParser ); virtual void InitFromParser( PdfParser* pParser ); //end L.K private: /** Clear all internal variables */ void Clear(); /** Low level APIs for setting a viewer preference * \param whichPrefs the dictionary key to set * \param the object to be set */ void SetViewerPreference( const PdfName& whichPref, const PdfObject & valueObj ) const; void SetViewerPreference( const PdfName& whichPref, bool inValue ) const; private: // Prevent use of copy constructor and assignment operator. These methods // should never be referenced (given that code referencing them outside // PdfMemDocument won't compile), and calling them will result in a link error // as they're not defined. explicit PdfMemDocument(const PdfMemDocument&); PdfMemDocument& operator=(const PdfMemDocument&); bool m_bLinearized; EPdfVersion m_eVersion; PdfEncrypt* m_pEncrypt; PdfParser* m_pParser; ///< This will be temporarily initialized to a PdfParser object so that SetPassword can work EPdfWriteMode m_eWriteMode; }; // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfMemDocument::IsPrintAllowed() const { return m_pEncrypt ? m_pEncrypt->IsPrintAllowed() : true; } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfMemDocument::IsEditAllowed() const { return m_pEncrypt ? m_pEncrypt->IsEditAllowed() : true; } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfMemDocument::IsCopyAllowed() const { return m_pEncrypt ? m_pEncrypt->IsCopyAllowed() : true; } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfMemDocument::IsEditNotesAllowed() const { return m_pEncrypt ? m_pEncrypt->IsEditNotesAllowed() : true; } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfMemDocument::IsFillAndSignAllowed() const { return m_pEncrypt ? m_pEncrypt->IsFillAndSignAllowed() : true; } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfMemDocument::IsAccessibilityAllowed() const { return m_pEncrypt ? m_pEncrypt->IsAccessibilityAllowed() : true; } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfMemDocument::IsDocAssemblyAllowed() const { return m_pEncrypt ? m_pEncrypt->IsDocAssemblyAllowed() : true; } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfMemDocument::IsHighPrintAllowed() const { return m_pEncrypt ? m_pEncrypt->IsHighPrintAllowed() : true; } // ----------------------------------------------------- // // ----------------------------------------------------- const PdfEncrypt* PdfMemDocument::GetEncrypt() const { return m_pEncrypt; } }; #endif // _PDF_MEM_DOCUMENT_H_ podofo-0.9.3/src/doc/PdfAction.cpp0000664000175000017500000001247112344436402016577 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2006 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfAction.h" #include "base/PdfDefinesPrivate.h" #include "base/PdfDictionary.h" namespace PoDoFo { const long PdfAction::s_lNumActions = 18; const char* PdfAction::s_names[] = { "GoTo", "GoToR", "GoToE", "Launch", "Thread", "URI", "Sound", "Movie", "Hide", "Named", "SubmitForm", "ResetForm", "ImportData", "JavaScript", "SetOCGState", "Rendition", "Trans", "GoTo3DView", NULL }; PdfAction::PdfAction( EPdfAction eAction, PdfVecObjects* pParent ) : PdfElement( "Action", pParent ), m_eType( eAction ) { const PdfName type = PdfName( TypeNameForIndex( eAction, s_names, s_lNumActions ) ); if( !type.GetLength() ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } this->GetObject()->GetDictionary().AddKey( "S", type ); } PdfAction::PdfAction( EPdfAction eAction, PdfDocument* pParent ) : PdfElement( "Action", pParent ), m_eType( eAction ) { const PdfName type = PdfName( TypeNameForIndex( eAction, s_names, s_lNumActions ) ); if( !type.GetLength() ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } this->GetObject()->GetDictionary().AddKey( "S", type ); } PdfAction::PdfAction( PdfObject* pObject ) // The typename /Action is optional for PdfActions : PdfElement( NULL, pObject ) { m_eType = static_cast(TypeNameToIndex( this->GetObject()->GetDictionary().GetKeyAsName( "S" ).GetName().c_str(), s_names, s_lNumActions, ePdfAction_Unknown )); } PdfAction::PdfAction( const PdfAction & rhs ) : PdfElement( "Action", rhs.GetNonConstObject() ) { m_eType = static_cast(TypeNameToIndex( this->GetObject()->GetDictionary().GetKeyAsName( "S" ).GetName().c_str(), s_names, s_lNumActions, ePdfAction_Unknown )); } void PdfAction::SetURI( const PdfString & sUri ) { this->GetObject()->GetDictionary().AddKey( "URI", sUri ); } PdfString PdfAction::GetURI() const { return this->GetObject()->GetIndirectKey( "URI" )->GetString(); } bool PdfAction::HasURI() const { return (this->GetObject()->GetIndirectKey( "URI" ) != NULL); } void PdfAction::SetScript( const PdfString & sScript ) { this->GetObject()->GetDictionary().AddKey( "JS", sScript ); } PdfString PdfAction::GetScript() const { return this->GetObject()->GetDictionary().GetKey( "JS" )->GetString(); } bool PdfAction::HasScript() const { return this->GetObject()->GetDictionary().HasKey( "JS" ); } void PdfAction::AddToDictionary( PdfDictionary & dictionary ) const { // Do not add empty destinations // if( !m_array.size() ) // return; // since we can only have EITHER a Dest OR an Action // we check for an Action, and if already present, we throw if ( dictionary.HasKey( PdfName( "Dest" ) ) ) PODOFO_RAISE_ERROR( ePdfError_ActionAlreadyPresent ); dictionary.RemoveKey( "A" ); dictionary.AddKey( "A", this->GetObject() ); } }; podofo-0.9.3/src/doc/PdfSigIncSignatureField.h0000664000175000017500000001047212262234754021035 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2014 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_SIGINCSIGNATURE_FIELD_H_ #define _PDF_SIGINCSIGNATURE_FIELD_H_ #include "PdfField.h" #include "PdfSignatureField.h" #include "podofo/base/PdfDate.h" #include "PdfImage.h" #include "PdfDocument.h" namespace PoDoFo { class PODOFO_DOC_API PdfSigIncSignatureField { private: int m_SignPage; float m_FontSize; PdfString m_SignText; PdfRect m_SignTextRect; const unsigned char* m_pImageData; pdf_long m_ImageLen; PdfString m_ImageFile; PdfRect m_SignImageRect; PdfString m_SignReason; PdfDate m_SignDate; PdfDocument *m_pDocument; pdf_int64 m_Red; pdf_int64 m_Green; pdf_int64 m_Blue; pdf_int64 m_Threshold; private: PdfString CreatePdfString(const wchar_t *text); public: PdfSigIncSignatureField(PdfDocument *pDocument); virtual ~PdfSigIncSignatureField(); void SetSignatureReason(const wchar_t *text); PdfString &GetSignatuReason(void) {return m_SignReason;} void SetSignatureDate(const PdfDate &sigDate); PdfDate &GetSignatureDate(void) {return m_SignDate;} bool HasSignatureText(void); bool HasSignatureImage(void); PdfRect &GetTextRect(void) {return m_SignTextRect;} PdfRect &GetImageRect(void) {return m_SignImageRect;} PdfString &GetSignatureText(void) {return m_SignText;} int GetPage(void) {return m_SignPage;} float GetFontSize(void) {return m_FontSize;} PdfImage *CreateSignatureImage(PdfDocument *pParent); void FreeSignatureImage(PdfImage *img); void SetSignatureText(const wchar_t *text, int page, int x, int y, int width, int height, float fontSize); void SetSignatureImage(const char *fileName, int page, int x, int y, int width, int height); void SetSignatureImage(const unsigned char *pData, pdf_long lLen, int page, int x, int y, int width, int height); void SetImageChromaKeyMask(pdf_int64 r, pdf_int64 g, pdf_int64 b, pdf_int64 threshold); }; } #endif podofo-0.9.3/src/doc/PdfIdentityEncoding.cpp0000664000175000017500000002704412355520733020627 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2010 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfIdentityEncoding.h" #include "base/PdfDefinesPrivate.h" #include "base/PdfDictionary.h" #include "base/PdfLocale.h" #include "base/PdfStream.h" #include "base/PdfContentsTokenizer.h" #include "PdfFont.h" #include #include #include #include #include using namespace std; namespace PoDoFo { PdfIdentityEncoding::PdfIdentityEncoding( int nFirstChar, int nLastChar, bool bAutoDelete, PdfObject *pToUnicode ) : PdfEncoding( nFirstChar, nLastChar ), m_bAutoDelete( bAutoDelete ), m_pToUnicode(pToUnicode), m_bToUnicodeIsLoaded(false) { // create a unique ID std::ostringstream oss; oss << "/Identity-H" << nFirstChar << "_" << nLastChar; m_id = PdfName( oss.str() ); ParseToUnicode(); } void PdfIdentityEncoding::AddToDictionary( PdfDictionary & rDictionary ) const { rDictionary.AddKey( "Encoding", PdfName("Identity-H") ); } pdf_utf16be PdfIdentityEncoding::GetCharCode( int nIndex ) const { if( nIndex < this->GetFirstChar() || nIndex > this->GetLastChar() ) { PODOFO_RAISE_ERROR( ePdfError_ValueOutOfRange ); } #ifdef PODOFO_IS_LITTLE_ENDIAN return ((nIndex & 0xff00) >> 8) | ((nIndex & 0xff) << 8); #else return static_cast(nIndex); #endif // PODOFO_IS_LITTLE_ENDIAN } PdfString PdfIdentityEncoding::ConvertToUnicode( const PdfString & rEncodedString, const PdfFont* ) const { if(m_pToUnicode && m_bToUnicodeIsLoaded) { const pdf_utf16be* pStr = reinterpret_cast(rEncodedString.GetString()); const size_t lLen = rEncodedString.GetLength()/2; pdf_utf16be lCID, lUnicodeValue; pdf_utf16be* pszUtf16 = static_cast(malloc(sizeof(pdf_utf16be)*lLen)); if( !pszUtf16 ) { PODOFO_RAISE_ERROR( ePdfError_OutOfMemory ); } for(size_t i = 0 ; i> 8 ); #else lCID = pStr[i]; #endif // PODOFO_IS_LITTLE_ENDIAN lUnicodeValue = this->GetUnicodeValue(lCID); #ifdef PODOFO_IS_LITTLE_ENDIAN pszUtf16[i] = (lUnicodeValue << 8) | (lUnicodeValue >> 8 ); #else pszUtf16[i] = lUnicodeValue; #endif // PODOFO_IS_LITTLE_ENDIAN } PdfString ret( pszUtf16, lLen ); free( pszUtf16 ); return ret; } else return(PdfString("\0")); } PdfRefCountedBuffer PdfIdentityEncoding::ConvertToEncoding( const PdfString & rString, const PdfFont* pFont ) const { // Get the string in UTF-16be format PdfString sStr = rString.ToUnicode(); const pdf_utf16be* pStr = sStr.GetUnicode(); pdf_utf16be lUnicodeValue, lCID; std::ostringstream out; PdfLocaleImbue(out); while( *pStr ) { #ifdef PODOFO_IS_LITTLE_ENDIAN lUnicodeValue = (*pStr << 8) | (*pStr >> 8); #else lUnicodeValue = *pStr; #endif // PODOFO_IS_LITTLE_ENDIAN lCID = this->GetCIDValue(lUnicodeValue); if (lCID == 0 && pFont) { #ifdef PODOFO_IS_LITTLE_ENDIAN lCID = static_cast(pFont->GetFontMetrics()->GetGlyphId( (((*pStr & 0xff) << 8) | ((*pStr & 0xff00) >> 8)) )); #else lCID = static_cast(pFont->GetFontMetrics()->GetGlyphId( *pStr )); #endif // PODOFO_IS_LITTLE_ENDIAN } out << static_cast((lCID & 0xff00) >> 8); out << static_cast(lCID & 0x00ff); ++pStr; } PdfRefCountedBuffer buffer( out.str().length() ); memcpy( buffer.GetBuffer(), out.str().c_str(), out.str().length() ); return buffer; } pdf_utf16be PdfIdentityEncoding::GetUnicodeValue( pdf_utf16be value ) const { if(m_bToUnicodeIsLoaded) { const map::const_iterator found = m_cMapEncoding.find(value); return (found == m_cMapEncoding.end() ? 0 : found->second); } else return 0; } pdf_utf16be PdfIdentityEncoding::GetCIDValue( pdf_utf16be lUnicodeValue ) const { if(m_bToUnicodeIsLoaded) { // TODO: optimize for(map::const_iterator it = m_cMapEncoding.begin(); it != m_cMapEncoding.end(); ++it) if(it->second == lUnicodeValue) return it->first; } return 0; } void PdfIdentityEncoding::ParseToUnicode() { if (m_pToUnicode && m_pToUnicode->HasStream()) { stack stkToken; pdf_uint16 loop = 0; char *streamBuffer; const char *streamToken = NULL; EPdfTokenType *streamTokenType = NULL; pdf_long streamBufferLen; bool in_beginbfrange = 0; bool in_beginbfchar = 0; pdf_uint16 range_entries = 0; pdf_uint16 char_entries = 0; pdf_uint16 inside_hex_string = 0; pdf_uint16 inside_array = 0; pdf_uint16 range_start; pdf_uint16 range_end; pdf_uint16 i = 0; pdf_utf16be firstvalue = 0; const PdfStream *CIDStreamdata = m_pToUnicode->GetStream (); CIDStreamdata->GetFilteredCopy (&streamBuffer, &streamBufferLen); PdfContentsTokenizer streamTokenizer (streamBuffer, streamBufferLen); while (streamTokenizer.GetNextToken (streamToken, streamTokenType)) { stkToken.push (streamToken); if (strcmp (streamToken, ">") == 0) { if (inside_hex_string == 0) PODOFO_RAISE_ERROR_INFO(ePdfError_InvalidStream, "Pdf Error, got > before <") else inside_hex_string = 0; i++; } if (strcmp (streamToken, "]") == 0) { if (inside_array == 0) PODOFO_RAISE_ERROR_INFO(ePdfError_InvalidStream, "Pdf Error, got ] before [") else inside_array = 0; i++; } if (in_beginbfrange == 1) { if (loop < range_entries) { if (inside_hex_string == 1) { pdf_utf16be num_value; std::stringstream ss; ss << std::hex << streamToken; ss >> num_value; if (i % 3 == 0) range_start = num_value; if (i % 3 == 1) { range_end = num_value; } if (i % 3 == 2) { for (int k = range_start; k < range_end; k++) { m_cMapEncoding[k] = num_value; num_value++; } loop++; } } } } if (in_beginbfchar == 1) { if (loop < char_entries) { if (inside_hex_string == 1) { pdf_utf16be num_value; std::stringstream ss; ss << std::hex << streamToken; ss >> num_value; if (i % 2 == 0) { firstvalue = num_value; } if (i % 2 == 1) { m_cMapEncoding[firstvalue] = num_value; } } } } if (strcmp (streamToken, "<") == 0) { inside_hex_string = 1; } if (strcmp (streamToken, "[") == 0) { inside_array = 1; } if (strcmp (streamToken, "beginbfrange") == 0) { in_beginbfrange = 1; stkToken.pop (); std::stringstream ss; ss << std::hex << stkToken.top (); ss >> range_entries; } if (strcmp (streamToken, "endbfrange") == 0) { in_beginbfrange = 0; i = 0; } if (strcmp (streamToken, "beginbfchar") == 0) { in_beginbfchar = 1; stkToken.pop (); std::stringstream ss; ss << std::hex << stkToken.top (); ss >> char_entries; } if (strcmp (streamToken, "endbfchar") == 0) { in_beginbfchar = 0; i = 0; } } free(streamBuffer); m_bToUnicodeIsLoaded = true; } } }; /* namespace PoDoFo */ podofo-0.9.3/src/doc/PdfSigIncMemDocument.cpp0000664000175000017500000004732412351604471020702 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2014 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #if defined(_MSC_VER) && _MSC_VER <= 1200 #pragma warning(disable: 4786) #endif #include #include #include #include "PdfMemDocument.h" #include "PdfSigIncMemDocument.h" #include "base/PdfSigIncWriter.h" #include "base/PdfDictionary.h" #include "base/PdfInputStream.h" #include "PdfAnnotation.h" #include "PdfSignatureField.h" #include "PdfPagesTree.h" #include "PdfImage.h" #include "PdfPainter.h" #include "PdfSigIncPainter.h" #include "PdfIdentityEncoding.h" #include "base/PdfInputDevice.h" using namespace std; #define BUFFER_SIZE 4096 #ifdef PODOFO_HAVE_JPEG_LIB extern "C" { # ifndef XMD_H # define XMD_H # endif # ifdef _WIN32 // Collision between win and jpeg-headers # undef FAR # endif # include "jpeglib.h" } #endif // PODOFO_HAVE_JPEG_LIB namespace PoDoFo { ////////////////////////////PdfExMemDocument///////////////////////////////// PdfExMemDocument::PdfExMemDocument(const char* pszInpFilename) : PdfMemDocument() { m_XRefOffset = 0; m_bXRefStream = false; Load(pszInpFilename); } PdfExMemDocument::PdfExMemDocument(const PdfRefCountedInputDevice &rInputDevice) : PdfMemDocument() { m_XRefOffset = 0; m_bXRefStream = false; Load(rInputDevice); } PdfExMemDocument::~PdfExMemDocument() { } void PdfExMemDocument::InitFromParser( PdfParser* pParser ) { m_XRefOffset = pParser->GetXRefOffset(); PdfMemDocument::InitFromParser(pParser); m_bXRefStream = pParser->HasXRefStream(); } //////////////////////////////////////////////////////////////////////////////// ////////////////////////////PdfSigIncMemDocument///////////////////////////////// PdfSigIncMemDocument::PdfSigIncMemDocument(const char* pszInpFilename) : PdfMemDocument(true) { m_InpFilename = pszInpFilename; m_Document = new PdfExMemDocument(pszInpFilename); m_pSignField = new PdfSigIncSignatureField(m_Document); m_pImgXObj = NULL; m_n2XObj = NULL; m_pFont = NULL; m_bLinearized = false; } PdfSigIncMemDocument::~PdfSigIncMemDocument() { PdfAcroForm *pOldAcroForm = m_Document->GetAcroForm(false, ePdfAcroFormDefaultAppearance_None); if(pOldAcroForm == m_pAcroForms) m_pAcroForms = NULL; if(m_pSignField) delete m_pSignField; if(m_Document) delete m_Document; if(m_pImgXObj) delete m_pImgXObj; if(m_n2XObj) delete m_n2XObj; } int PdfSigIncMemDocument::GetPageCount(void) { return m_Document->GetPageCount(); } PdfPage *PdfSigIncMemDocument::GetPage(int page) { return m_Document->GetPage(page); } void PdfSigIncMemDocument::Initialize() { //TODO - linearizovany pdf a pdf s XRefStream se preulozi // tj. byli-li podepsany (muzou byt linearizovany soubory a soubory s XRefStream podepsany?) //-> zrusi se platnost podpisu if(m_Document->IsLinearized() || m_Document->HasXRefStream()) { m_bLinearized = true; PdfRefCountedBuffer outBuff; PdfOutputDevice outDvc(&outBuff); m_Document->Write(&outDvc); PdfRefCountedInputDevice inpDvc(outBuff.GetBuffer(), outBuff.GetSize()); delete m_Document; m_Document = new PdfExMemDocument(inpDvc); } CreateVisualSignRect(); m_LastXRefOffset = m_Document->GetXRefOffset(); PdfAcroForm *pOldAcroForm = m_Document->GetAcroForm(false, ePdfAcroFormDefaultAppearance_None); if(pOldAcroForm) { PdfObject *pCatalog = m_Document->GetCatalog(); if(pCatalog) { PdfReference pdfRef(pCatalog->Reference()); pdf_objnum objnum = pdfRef.ObjectNumber(); objnum = objnum - 1; pdfRef.SetObjectNumber(objnum); this->GetObjects().SetObjectCount(pdfRef); m_pCatalog = new PdfObject(*pCatalog); this->GetObjects().push_back(m_pCatalog); } else m_pCatalog = this->GetObjects().CreateObject( "Catalog" ); PdfAcroForm *pAcroForm = this->GetExistedAcroForm(pOldAcroForm); PdfObject *pNewFields = pAcroForm->GetObject()->GetDictionary().GetKey( PdfName("Fields") ); if(!pNewFields) { pAcroForm->GetObject()->GetDictionary().AddKey("Fields", PdfArray()); } PdfObject* pOldFields = m_Document->GetAcroForm()->GetObject()->GetDictionary().GetKey( PdfName("Fields") ); if( pOldFields ) { PdfObject* pFields = pAcroForm->GetObject()->GetDictionary().GetKey( PdfName("Fields") ); if(pFields) { if(pOldFields->GetDataType() == ePdfDataType_Array ) pFields->GetArray().insert(pFields->GetArray().begin(), pOldFields->GetArray().begin(), pOldFields->GetArray().end()); else if(pOldFields->GetDataType() == ePdfDataType_Reference ) { PdfObject *pExFldObj = m_Document->GetObjects().GetObject(pOldFields->GetReference()); if(pExFldObj) { if(pOldFields == pFields) { pFields = new PdfObject(*pExFldObj); PdfReference pdfRef(pExFldObj->Reference()); this->GetObjects().SetObjectCount(pdfRef); this->GetObjects().push_back(pFields); } else pFields->GetArray().insert(pFields->GetArray().begin(), pExFldObj->GetArray().begin(), pExFldObj->GetArray().end()); } } else PODOFO_RAISE_ERROR( ePdfError_InvalidDataType ); } } PdfObject* pagesRootObj = m_Document->GetCatalog()->GetIndirectKey( PdfName( "Pages" ) ); if ( pagesRootObj ) { if(!m_pCatalog->GetDictionary().HasKey("Pages")) m_pCatalog->GetDictionary().AddKey( "Pages", pagesRootObj->Reference() ); } PdfReference pdfRef; pdfRef.SetObjectNumber(m_Document->GetObjects().GetObjectCount() - 1); this->GetObjects().SetObjectCount(pdfRef); } else { PdfObject *pCatalog = m_Document->GetCatalog(); if(pCatalog) { PdfReference pdfRef(pCatalog->Reference()); pdf_objnum objnum = pdfRef.ObjectNumber(); objnum = objnum - 1; pdfRef.SetObjectNumber(objnum); this->GetObjects().SetObjectCount(pdfRef); m_pCatalog = new PdfObject(*pCatalog); this->GetObjects().push_back(m_pCatalog); } else m_pCatalog = this->GetObjects().CreateObject( "Catalog" ); PdfReference pdfRef; pdfRef.SetObjectNumber(m_Document->GetObjects().GetObjectCount() - 1); this->GetObjects().SetObjectCount(pdfRef); this->GetAcroForm(true, ePdfAcroFormDefaultAppearance_None); PdfObject* pagesRootObj = m_Document->GetCatalog()->GetIndirectKey( PdfName( "Pages" ) ); if ( pagesRootObj ) { m_pCatalog->GetDictionary().AddKey( "Pages", pagesRootObj->Reference() ); } } m_pInfo = new PdfInfo( &this->GetObjects() ); m_pTrailer = new PdfObject(); // The trailer is NO part of the vector of objects m_pTrailer->SetOwner( &this->GetObjects()); m_pTrailer->GetDictionary().AddKey( "Root", m_pCatalog->Reference() ); m_pTrailer->GetDictionary().AddKey( "Info", m_pInfo->GetObject()->Reference() ); } PdfAcroForm* PdfSigIncMemDocument::GetExistedAcroForm(PdfAcroForm *pOldAcroForm) { if( !m_pAcroForms ) { PdfReference pdfRef = pOldAcroForm->GetObject()->Reference(); if(pdfRef.IsIndirect()) { PdfObject* pOldFields = pOldAcroForm->GetObject()->GetDictionary().GetKey( PdfName("Fields") ); if(pOldFields) { if(pOldFields->GetDataType() == ePdfDataType_Array ) { pdfRef.SetObjectNumber(pOldAcroForm->GetObject()->Reference().ObjectNumber() - 1); this->GetObjects().SetObjectCount(pdfRef); PdfObject *pNewObj = this->GetObjects().CreateObject(); m_pAcroForms = new PdfAcroForm( this, pNewObj, ePdfAcroFormDefaultAppearance_None ); this->GetCatalog()->GetDictionary().AddKey( "AcroForm", m_pAcroForms->GetObject()->Reference() ); } else if(pOldFields->GetDataType() == ePdfDataType_Reference ) { m_pAcroForms = pOldAcroForm; } } else { pdfRef.SetObjectNumber(pOldAcroForm->GetObject()->Reference().ObjectNumber() - 1); this->GetObjects().SetObjectCount(pdfRef); PdfObject *pNewObj = this->GetObjects().CreateObject(); m_pAcroForms = new PdfAcroForm( this, pNewObj, ePdfAcroFormDefaultAppearance_None ); this->GetCatalog()->GetDictionary().AddKey( "AcroForm", m_pAcroForms->GetObject()->Reference() ); } } else { m_pAcroForms = pOldAcroForm; } } return m_pAcroForms; } void PdfSigIncMemDocument::Write( PdfSignOutputDevice* pDevice ) { if(m_bLinearized) { m_Document->Write(pDevice); } else { PdfFileInputStream inputStream(m_InpFilename); char *pBuffer = new char[BUFFER_SIZE]; pdf_long read = 0; pdf_long tmpRead = 0; do { tmpRead = inputStream.Read(pBuffer, BUFFER_SIZE); if(tmpRead != -1) { pDevice->Write(pBuffer, tmpRead); read += tmpRead; } } while(read < inputStream.GetFileLength() && tmpRead != -1); delete [] pBuffer; } //TODO - co kdyz nema zadnou page? PdfPage *pPage = m_Document->GetPage(m_Document->GetPageCount() - 1); CreateAnnotation(pDevice, pPage); const PdfObject *pTrailer = m_Document->GetTrailer(); if( pTrailer->GetDictionary().HasKey( "Root" ) ) { GetMainTrailer()->GetDictionary().AddKey( "Root", pTrailer->GetDictionary().GetKey( "Root" ) ); } if( pTrailer->GetDictionary().HasKey( "Info" ) ) GetMainTrailer()->GetDictionary().AddKey( "Info", pTrailer->GetDictionary().GetKey( "Info" ) ); if( pTrailer->GetDictionary().HasKey( "ID" ) ) GetMainTrailer()->GetDictionary().AddKey( "ID", pTrailer->GetDictionary().GetKey( "ID" ) ); PdfSigIncWriter writer( &(this->GetObjects()), this->GetTrailer()); writer.SetPdfVersion( this->GetPdfVersion() ); writer.SetWriteMode( ePdfWriteMode_Clean); writer.Write( pDevice, m_LastXRefOffset); vector::iterator it, end = m_PagesRef.end(); for(it = m_PagesRef.begin(); it != end; it++) { m_Document->GetObjects().RemoveObject((*it)->GetObject()->Reference()); } } void PdfSigIncMemDocument::CreateAnnotation(PdfSignOutputDevice* pDevice, PdfPage* pPage ) { PdfAnnotation* pAnnot = new PdfAnnotation(pPage, ePdfAnnotation_Widget, m_SignRect, &this->GetObjects()); pdf_int64 flags = 132; pAnnot->GetObject()->GetDictionary().AddKey("F", PdfObject(flags)); PdfAcroForm *pAcroForm = this->GetAcroForm(); if(pAcroForm) { if(!pAcroForm->GetObject()->GetDictionary().HasKey(PdfName("SigFlags"))) { pdf_int64 val = 3; pAcroForm->GetObject()->GetDictionary().AddKey("SigFlags", PdfObject(val)); } PdfSignatureField signField( pAnnot, pAcroForm, this); //TODO - musi byt unikatni char fldName[30]; sprintf(fldName, "SignatureFieldName %d", pAnnot->GetObject()->Reference().ObjectNumber()); PdfString name(fldName); signField.SetFieldName(name); signField.SetSignatureReason(m_pSignField->GetSignatuReason()); signField.SetSignatureDate( m_pSignField->GetSignatureDate() ); signField.SetSignature(*pDevice->GetSignatureBeacon()); if(m_pImgXObj != NULL) { signField.SetAppearanceStream(m_pImgXObj); } if(m_PagesRef.size() > 0) { PdfPage *pPage = m_PagesRef[0]; PdfObject *pAnnot = pPage->GetOwnAnnotationsArray(false, m_Document); if(!pAnnot) pAnnot = pPage->GetOwnAnnotationsArray(true, m_Document); else { if (pPage->GetObject()->GetDictionary().HasKey( "Annots" ) ) { PdfObject *pTmpObj = pPage->GetObject()->GetDictionary().GetKey( "Annots" ); if(pTmpObj->IsReference()) { PdfObject *newAnnot = new PdfObject(*pAnnot); this->GetObjects().push_back(newAnnot); pAnnot = newAnnot; } } } if(pAnnot) { pAnnot->GetArray().push_back(signField.GetFieldObject()->Reference()); } } } else PODOFO_RAISE_ERROR(ePdfError_InternalLogic); } void PdfSigIncMemDocument::CreateVisualSignRect(void) { PdfRect rect(0, 0, 50, 50); double dTRight = 0; double dTTop = 0; if(m_pSignField->HasSignatureText()) { PdfRect textRect = m_pSignField->GetTextRect(); rect.SetBottom(textRect.GetBottom()); rect.SetLeft(textRect.GetLeft()); rect.SetHeight(textRect.GetHeight()); rect.SetWidth(textRect.GetWidth()); dTTop = textRect.GetBottom() + textRect.GetHeight(); dTRight = textRect.GetLeft() + textRect.GetWidth(); } if(m_pSignField->HasSignatureImage()) { PdfRect imgRect = m_pSignField->GetImageRect(); if(!m_pSignField->HasSignatureText()) { rect.SetBottom(imgRect.GetBottom()); rect.SetLeft(imgRect.GetLeft()); } else { if(imgRect.GetLeft() < rect.GetLeft()) rect.SetLeft(imgRect.GetLeft()); if(imgRect.GetBottom() < rect.GetBottom()) rect.SetBottom(imgRect.GetBottom()); } double dITop = imgRect.GetBottom() + imgRect.GetHeight(); double dIRight = imgRect.GetLeft() + imgRect.GetWidth(); double dTMax = dITop > dTTop ? dITop : dTTop; double dRMax = dIRight > dTRight ? dIRight : dTRight; rect.SetHeight(dTMax - rect.GetBottom()); rect.SetWidth(dRMax - rect.GetLeft()); } m_SignRect = rect; } bool PdfSigIncMemDocument::AddPageToIncDocument(PdfPage *pPage) { bool bResult = true; if(m_Document->IsLinearized()) return bResult; PdfObject *objPage = pPage->GetObject(); if(objPage != NULL) { PdfObject *obj = this->GetObjects().GetObject(objPage->Reference()); if(!obj) { this->GetObjects().push_back(objPage); this->GetObjects().Sort(); } } else bResult = false; return bResult; } void PdfSigIncMemDocument::AddVisualSign(PdfPage *pPage) { if(AddPageToIncDocument(pPage)) { PdfRect objRect(0,0, m_SignRect.GetWidth(), m_SignRect.GetHeight()); bool bLinear = m_Document->IsLinearized(); PdfDocument *pDocument = bLinear ? (PdfDocument*) m_Document : this; m_pImgXObj = new PdfXObject(objRect, pDocument); PdfSigIncPainter pnt(pDocument, bLinear); pnt.SetPageCanvas(pPage, m_pImgXObj->GetContents()); PdfXObject frmXObj(objRect, pDocument, "FRM", true); m_pImgXObj->AddResource(PdfName("FRM"), frmXObj.GetObjectReference(), PdfName("XObject")); pnt.DrawXObject(0,0, &frmXObj); pnt.EndCanvas(); pnt.SetPageCanvas(pPage, frmXObj.GetContents()); PdfXObject n0XObj(objRect, pDocument, "n0", true); PdfXObject n2XObj(objRect, pDocument, "n2", true); frmXObj.AddResource(PdfName("n0"), n0XObj.GetObjectReference(), PdfName("XObject")); frmXObj.AddResource(PdfName("n2"), n2XObj.GetObjectReference(), PdfName("XObject")); pnt.DrawXObject(0,0, &n0XObj); pnt.DrawXObject(0,0, &n2XObj); pnt.EndCanvas(); PdfImage *pdfImage = NULL; if(m_pSignField->HasSignatureImage()) { pdfImage = m_pSignField->CreateSignatureImage(pDocument); } if(m_pSignField->HasSignatureText() || pdfImage != NULL) { pnt.SetPageCanvas(pPage, n2XObj.GetContents()); } if(pdfImage) { PdfRect imgRect = m_pSignField->GetImageRect(); n2XObj.AddResource(pdfImage->GetIdentifier(), pdfImage->GetObjectReference(), PdfName("XObject")); double scaleX = imgRect.GetWidth() / pdfImage->GetWidth(); double scaleY = imgRect.GetHeight() / pdfImage->GetHeight(); pnt.DrawImage(imgRect.GetLeft() - m_SignRect.GetLeft(), imgRect.GetBottom() - m_SignRect.GetBottom(), pdfImage, scaleX, scaleY); m_pSignField->FreeSignatureImage(pdfImage); } if(m_pSignField->HasSignatureText()) { if(m_pFont == NULL) { PdfIdentityEncoding *pdfEnc = new PdfIdentityEncoding(); m_pFont = pDocument->CreateFont("Arial", false, pdfEnc); m_pFont->SetFontSize(m_pSignField->GetFontSize()); } pnt.SetFont(m_pFont); n2XObj.AddResource(m_pFont->GetIdentifier(), m_pFont->GetObject()->Reference(), PdfName("Font")); PdfRect tRect = m_pSignField->GetTextRect(); PdfString text = m_pSignField->GetSignatureText(); PdfRect txtRect(tRect.GetLeft() - m_SignRect.GetLeft(), tRect.GetBottom() - m_SignRect.GetBottom(), tRect.GetWidth(), tRect.GetHeight()); pnt.DrawMultiLineText(txtRect, text); //pnt.DrawText(10,50, text); } pnt.FinishPage(); } else PODOFO_RAISE_ERROR(ePdfError_InternalLogic); } void PdfSigIncMemDocument::CreateVisualSign(void) { if(m_pSignField->GetPage() < 0) return; if(m_pSignField->GetPage() >= m_Document->GetPageCount()) PODOFO_RAISE_ERROR(ePdfError_InternalLogic); if(!m_pSignField->HasSignatureImage() && !m_pSignField->HasSignatureText()) return; PdfPage *pPage = m_Document->GetPage(m_pSignField->GetPage()); if(!m_Document->IsLinearized()) m_PagesRef.push_back(pPage); AddVisualSign(pPage); } }; podofo-0.9.3/src/doc/PdfFontMetricsObject.cpp0000664000175000017500000003071612344436554020760 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2010 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfFontMetricsObject.h" #include "base/PdfDefinesPrivate.h" #include "base/PdfDictionary.h" #include "base/PdfName.h" #include "base/PdfObject.h" #include "base/PdfVariant.h" namespace PoDoFo { PdfFontMetricsObject::PdfFontMetricsObject( PdfObject* pFont, PdfObject* pDescriptor, const PdfEncoding* const pEncoding ) : PdfFontMetrics( ePdfFontType_Unknown, "", NULL ), m_pEncoding( pEncoding ), m_dDefWidth(0.0) { const PdfName & rSubType = pFont->GetDictionary().GetKey( PdfName::KeySubtype )->GetName(); // OC 15.08.2010 BugFix: /FirstChar /LastChar /Widths are in the Font dictionary and not in the FontDescriptor if ( rSubType == PdfName("Type1") || rSubType == PdfName("Type3") || rSubType == PdfName("TrueType") ) { if ( pDescriptor ) { m_sName = pDescriptor->GetIndirectKey( "FontName" )->GetName(); m_bbox = pDescriptor->GetIndirectKey( "FontBBox" )->GetArray(); } else { m_sName = pFont->GetIndirectKey( "Name" )->GetName(); m_bbox = pFont->GetIndirectKey( "FontBBox" )->GetArray(); } if (pFont->GetDictionary().HasKey( "FontMatrix" )) { // Type3 fonts have a custom FontMatrix m_matrix = pFont->GetIndirectKey( "FontMatrix" )->GetArray(); } m_nFirst = static_cast(pFont->GetDictionary().GetKeyAsLong( "FirstChar", 0L )); m_nLast = static_cast(pFont->GetDictionary().GetKeyAsLong( "LastChar", 0L )); // OC 15.08.2010 BugFix: GetIndirectKey() instead of GetDictionary().GetKey() and "Widths" instead of "Width" PdfObject* widths = pFont->GetIndirectKey( "Widths" ); if( widths != NULL ) { m_width = widths->GetArray(); m_missingWidth = NULL; } else { if ( pDescriptor ) { widths = pDescriptor->GetDictionary().GetKey( "MissingWidth" ); } else { widths = pFont->GetDictionary().GetKey( "MissingWidth" ); } if( widths == NULL ) { PODOFO_RAISE_ERROR_INFO( ePdfError_NoObject, "Font object defines neither Widths, nor MissingWidth values!" ); m_missingWidth = widths; } } } else if ( rSubType == PdfName("CIDFontType0") || rSubType == PdfName("CIDFontType2") ) { PdfObject *pObj = pDescriptor->GetIndirectKey( "FontName" ); if (pObj) { m_sName = pObj->GetName(); } pObj = pDescriptor->GetIndirectKey( "FontBBox" ); if (pObj) { m_bbox = pObj->GetArray(); } m_nFirst = 0; m_nLast = 0; m_dDefWidth = static_cast(pFont->GetDictionary().GetKeyAsLong( "DW", 1000L )); PdfVariant default_width(m_dDefWidth); PdfObject * pw = pFont->GetIndirectKey( "W" ); for (int i = m_nFirst; i <= m_nLast; ++i) { m_width.push_back(default_width); } if (pw) { PdfArray w = pw->GetArray(); int pos = 0; while (pos < static_cast(w.GetSize())) { int start = static_cast(w[pos++].GetNumber()); PODOFO_ASSERT (start >= 0); if (w[pos].IsArray()) { PdfArray widths = w[pos++].GetArray(); int length = start + static_cast(widths.GetSize()); PODOFO_ASSERT (length >= start); if (length > static_cast(m_width.GetSize())) { m_width.resize(length, default_width); } for (int i = 0; i < static_cast(widths.GetSize()); ++i) { m_width[start + i] = widths[i]; } } else { int end = static_cast(w[pos++].GetNumber()); int length = end + 1; PODOFO_ASSERT (length >= start); if (length > static_cast(m_width.GetSize())) { m_width.resize(length, default_width); } pdf_int64 width = w[pos++].GetNumber(); for (int i = start; i <= end; ++i) m_width[i] = PdfVariant(width); } } } m_nLast = m_width.GetSize() - 1; } else { PODOFO_RAISE_ERROR_INFO( ePdfError_UnsupportedFontFormat, rSubType.GetEscapedName().c_str() ); } if ( pDescriptor ) { m_nWeight = static_cast(pDescriptor->GetDictionary().GetKeyAsLong( "FontWeight", 400L )); m_nItalicAngle = static_cast(pDescriptor->GetDictionary().GetKeyAsLong( "ItalicAngle", 0L )); m_dPdfAscent = pDescriptor->GetDictionary().GetKeyAsReal( "Ascent", 0.0 ); m_dPdfDescent = pDescriptor->GetDictionary().GetKeyAsReal( "Descent", 0.0 ); } else { m_nWeight = 400L; m_nItalicAngle = 0L; m_dPdfAscent = 0.0; m_dPdfDescent = 0.0; } if (m_matrix.size() == 0) { // Default FontMatrix for all font types: [0.001 0 0 0.001 0 0] m_matrix.push_back(0.001); m_matrix.push_back(0.0); m_matrix.push_back(0.0); m_matrix.push_back(0.001); m_matrix.push_back(0.0); m_matrix.push_back(0.0); } m_dAscent = m_dPdfAscent * m_matrix[3].GetReal(); m_dDescent = m_dPdfDescent * m_matrix[3].GetReal(); m_dLineSpacing = m_dAscent + m_dDescent; // Try to fine some sensible values m_dUnderlineThickness = 1.0; m_dUnderlinePosition = 0.0; m_dStrikeOutThickness = m_dUnderlinePosition; m_dStrikeOutPosition = m_dAscent / 2.0; m_bSymbol = false; // TODO } PdfFontMetricsObject::~PdfFontMetricsObject() { } const char* PdfFontMetricsObject::GetFontname() const { return m_sName.GetName().c_str(); } void PdfFontMetricsObject::GetBoundingBox( PdfArray & array ) const { array = m_bbox; } double PdfFontMetricsObject::CharWidth( unsigned char c ) const { if( c >= m_nFirst && c <= m_nLast && c - m_nFirst < static_cast(m_width.GetSize()) ) { double dWidth = m_width[c - m_nFirst].GetReal(); return dWidth * static_cast(this->GetFontSize() * this->GetFontScale() / 100.0) * m_matrix.front().GetReal() + static_cast( this->GetFontSize() * this->GetFontScale() / 100.0 * this->GetFontCharSpace() / 100.0); } if( m_missingWidth != NULL ) return m_missingWidth->GetReal (); else return m_dDefWidth; } double PdfFontMetricsObject::UnicodeCharWidth( unsigned short c ) const { if( c >= m_nFirst && c <= m_nLast && c - m_nFirst < static_cast(m_width.GetSize()) ) { double dWidth = m_width[c - m_nFirst].GetReal(); return dWidth * static_cast(this->GetFontSize() * this->GetFontScale() / 100.0) * m_matrix.front().GetReal() + static_cast( this->GetFontSize() * this->GetFontScale() / 100.0 * this->GetFontCharSpace() / 100.0); } if( m_missingWidth != NULL ) return m_missingWidth->GetReal (); else return m_dDefWidth; } void PdfFontMetricsObject::GetWidthArray( PdfVariant & var, unsigned int, unsigned int ) const { var = m_width; } double PdfFontMetricsObject::GetGlyphWidth( int ) const { // TODO return 0.0; // OC 13.08.2010 BugFix: Avoid microsoft compiler error } double PdfFontMetricsObject::GetGlyphWidth( const char* ) const { // TODO return 0.0; } long PdfFontMetricsObject::GetGlyphId( long ) const { // TODO return 0; // OC 13.08.2010 BugFix: Avoid microsoft compiler error } // ----------------------------------------------------- // // ----------------------------------------------------- double PdfFontMetricsObject::GetLineSpacing() const { return m_dLineSpacing * this->GetFontSize(); } // ----------------------------------------------------- // // ----------------------------------------------------- double PdfFontMetricsObject::GetUnderlinePosition() const { return m_dUnderlinePosition * this->GetFontSize(); } // ----------------------------------------------------- // // ----------------------------------------------------- double PdfFontMetricsObject::GetStrikeOutPosition() const { return m_dStrikeOutPosition * this->GetFontSize(); } // ----------------------------------------------------- // // ----------------------------------------------------- double PdfFontMetricsObject::GetUnderlineThickness() const { return m_dUnderlineThickness * this->GetFontSize(); } // ----------------------------------------------------- // // ----------------------------------------------------- double PdfFontMetricsObject::GetStrikeoutThickness() const { return m_dStrikeOutThickness * this->GetFontSize(); } // ----------------------------------------------------- // // ----------------------------------------------------- const char* PdfFontMetricsObject::GetFontData() const { return NULL; } // ----------------------------------------------------- // // ----------------------------------------------------- pdf_long PdfFontMetricsObject::GetFontDataLen() const { return 0; } // ----------------------------------------------------- // // ----------------------------------------------------- unsigned int PdfFontMetricsObject::GetWeight() const { return m_nWeight; } // ----------------------------------------------------- // // ----------------------------------------------------- double PdfFontMetricsObject::GetAscent() const { return m_dAscent * this->GetFontSize(); } // ----------------------------------------------------- // // ----------------------------------------------------- double PdfFontMetricsObject::GetPdfAscent() const { return m_dPdfAscent; } // ----------------------------------------------------- // // ----------------------------------------------------- double PdfFontMetricsObject::GetDescent() const { return m_dDescent * this->GetFontSize(); } // ----------------------------------------------------- // // ----------------------------------------------------- double PdfFontMetricsObject::GetPdfDescent() const { return m_dPdfDescent; } // ----------------------------------------------------- // // ----------------------------------------------------- int PdfFontMetricsObject::GetItalicAngle() const { return m_nItalicAngle; } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfFontMetricsObject::IsSymbol() const { return m_bSymbol; } }; podofo-0.9.3/src/doc/PdfFontSimple.cpp0000664000175000017500000001320712347271543017446 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2007 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfFontSimple.h" #include "base/PdfDefinesPrivate.h" #include "base/PdfArray.h" #include "base/PdfDictionary.h" #include "base/PdfEncoding.h" #include "base/PdfFilter.h" #include "base/PdfName.h" #include "base/PdfStream.h" namespace PoDoFo { PdfFontSimple::PdfFontSimple( PdfFontMetrics* pMetrics, const PdfEncoding* const pEncoding, PdfVecObjects* pParent ) : PdfFont( pMetrics, pEncoding, pParent ) { } PdfFontSimple::PdfFontSimple( PdfFontMetrics* pMetrics, const PdfEncoding* const pEncoding, PdfObject* pObject ) : PdfFont( pMetrics, pEncoding, pObject ) { } void PdfFontSimple::Init( bool bEmbed, const PdfName & rsSubType ) { PdfObject* pWidth; PdfObject* pDescriptor; PdfVariant var; PdfArray array; pWidth = this->GetObject()->GetOwner()->CreateObject(); if( !pWidth ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } m_pMetrics->GetWidthArray( *pWidth, m_pEncoding->GetFirstChar(), m_pEncoding->GetLastChar() ); pDescriptor = this->GetObject()->GetOwner()->CreateObject( "FontDescriptor" ); if( !pDescriptor ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } std::string name; if ( m_bIsSubsetting ) name = this->GetObject()->GetOwner()->GetNextSubsetPrefix(); name += this->GetBaseFont().GetName(); this->GetObject()->GetDictionary().AddKey( PdfName::KeySubtype, rsSubType ); this->GetObject()->GetDictionary().AddKey("BaseFont", PdfName( name ) ); this->GetObject()->GetDictionary().AddKey("FirstChar", PdfVariant( static_cast(m_pEncoding->GetFirstChar()) ) ); this->GetObject()->GetDictionary().AddKey("LastChar", PdfVariant( static_cast(m_pEncoding->GetLastChar()) ) ); m_pEncoding->AddToDictionary( this->GetObject()->GetDictionary() ); // Add encoding key this->GetObject()->GetDictionary().AddKey("Widths", pWidth->Reference() ); this->GetObject()->GetDictionary().AddKey( "FontDescriptor", pDescriptor->Reference() ); m_pMetrics->GetBoundingBox( array ); pDescriptor->GetDictionary().AddKey( "FontName", PdfName( name ) ); //pDescriptor->GetDictionary().AddKey( "FontWeight", (long)m_pMetrics->Weight() ); pDescriptor->GetDictionary().AddKey( PdfName::KeyFlags, PdfVariant( static_cast(PODOFO_LL_LITERAL(32)) ) ); // TODO: 0 ???? pDescriptor->GetDictionary().AddKey( "FontBBox", array ); pDescriptor->GetDictionary().AddKey( "ItalicAngle", PdfVariant( static_cast(m_pMetrics->GetItalicAngle()) ) ); pDescriptor->GetDictionary().AddKey( "Ascent", m_pMetrics->GetPdfAscent() ); pDescriptor->GetDictionary().AddKey( "Descent", m_pMetrics->GetPdfDescent() ); pDescriptor->GetDictionary().AddKey( "CapHeight", m_pMetrics->GetPdfAscent() ); // m_pMetrics->CapHeight() ); pDescriptor->GetDictionary().AddKey( "StemV", PdfVariant( static_cast(PODOFO_LL_LITERAL(1)) ) ); // m_pMetrics->StemV() ); // Peter Petrov 24 September 2008 m_pDescriptor = pDescriptor; if( bEmbed ) { this->EmbedFontFile( pDescriptor ); m_bWasEmbedded = true; } } void PdfFontSimple::EmbedFont() { if (!m_bWasEmbedded) { this->EmbedFontFile( m_pDescriptor ); m_bWasEmbedded = true; } } }; podofo-0.9.3/src/doc/PdfTable.h0000664000175000017500000007121412344436402016056 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2007 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_TABLE_H_ #define _PDF_TABLE_H_ #include "podofo/base/PdfDefines.h" #include "podofo/base/PdfColor.h" #include "podofo/base/PdfRect.h" #include "podofo/base/PdfString.h" #include namespace PoDoFo { class PdfCanvas; class PdfFont; class PdfImage; class PdfPainter; class PdfPage; /** * This is an abstract interface of a model that can provide * data and formatting informations to a PdfTable. * * You can implement your own PdfTableModel to supply data * to a PdfTable. * PdfSimpleTableModel is an example of a simple model. * * * \see PdfTable * \see PdfSimpleTableModel */ class PODOFO_DOC_API PdfTableModel { public: virtual ~PdfTableModel() {}; /** * \param col the column of the table cell * \param row the row of the table cell * * \returns the contents string of this table cell */ virtual PdfString GetText ( int col, int row ) const = 0; /** * \param col the column of the table cell * \param row the row of the table cell * * \returns the horizontal alignment of the contents in the cell */ virtual EPdfAlignment GetAlignment ( int col, int row ) const = 0; /** * \param col the column of the table cell * \param row the row of the table cell * * \returns the vertical alignment of the contents in the cell */ virtual EPdfVerticalAlignment GetVerticalAlignment ( int col, int row ) const = 0; /** * \param col the column of the table cell * \param row the row of the table cell * * \returns the font of this table cell or NULL to use the default font */ virtual PdfFont* GetFont ( int col, int row ) const = 0; /** * \param col the column of the table cell * \param row the row of the table cell * * \returns true if this cell has a background color */ virtual bool HasBackgroundColor( int col, int row ) const = 0; /** * \param col the column of the table cell * \param row the row of the table cell * * \returns the background color of the specified cell */ virtual PdfColor GetBackgroundColor( int col, int row ) const = 0; /** * \param col the column of the table cell * \param row the row of the table cell * * \returns the foreground (text) color of the specified cell */ virtual PdfColor GetForegroundColor( int col, int row ) const = 0; /** * \param col the column of the table cell * \param row the row of the table cell * * \returns true if the specified cell should use wordwrapping */ virtual bool HasWordWrap( int col, int row ) const = 0; /** * \returns true if the table should have * a border around all cells. * \returns false if no cell border should be visible * * Cell borders are always drawn using the current PdfPainter * settings. */ virtual bool HasBorders() const = 0; /** * \returns the stroke witdth of the border line */ virtual double GetBorderWidth() const = 0; /** * \param col the column of the table cell * \param row the row of the table cell * * \returns the border color */ virtual PdfColor GetBorderColor( int col, int row ) const = 0; /** * \param col the column of the table cell * \param row the row of the table cell * * \returns true if the table cell contains an image */ virtual bool HasImage( int col, int row ) const = 0; /** * \param col the column of the table cell * \param row the row of the table cell * * \returns the image for the specified cell or NULL if the cell has no image */ virtual PdfImage* GetImage( int col, int row ) const = 0; }; /** * An implementation of a simple PdfTableModel. * */ class PODOFO_DOC_API PdfSimpleTableModel : public PdfTableModel { public: /** Creates an empty PdfSimpleTableModel * that does not contain any data. * * Using this model will result in drawing an empty table! */ PdfSimpleTableModel(); /** Creates an empty PdfSimpleTableModel * that does not contain any data. * * Using this model will result in drawing an empty table! * * \param nCols number of columns of the data in this table model (must match the PdfTable object) * \param nRows number of rows of the data in this table model (must match the PdfTable object) * * You can set the tables data using SetText. * \see SetText */ PdfSimpleTableModel( int nCols, int nRows ); virtual ~PdfSimpleTableModel(); /** Set the font that will be used to draw all table contents. * * \param pFont the font for the table contents */ inline void SetFont( PdfFont* pFont ); /** Set the horizontal alignment of the contents in all table cells * * \param eAlignment the horizontal alignment of text in a table cell */ inline void SetAlignment( EPdfAlignment eAlignment ); /** Set the vertical alignment of the contents in all table cells * * \param eAlignment the vertiical alignment of text in a table cell */ inline void SetAlignment( EPdfVerticalAlignment eAlignment ); /** Set the background color of the table cells * * \param rColor the background color */ inline void SetBackgroundColor( const PdfColor & rColor ); /** Set the foreground color of the table cells * * \param rColor the foreground color */ inline void SetForegroundColor( const PdfColor & rColor ); /** Sets wether all cells have a background color or not * * \param bEnable if true all cells have a background color */ inline void SetBackgroundEnabled( bool bEnable ); /** Sets wether all cells have wordwrapping or not * * \param bEnable if true all cells have wordwrapping */ inline void SetWordWrapEnabled( bool bEnable ); /** Sets wether all cells have a border or not. * * \param bEnable if true a border will be drawn * using the current PdfPainter settings */ inline void SetBorderEnabled( bool bEnable ); /** Sets the stroke width of the border around * the table. * * \param dWidth the stroke width of the border */ inline void SetBorderWidth( double dWidth ); /** Sets the contents of a specific cell * * \param col the column of the table cell * \param row the row of the table cell * \param rsString the contents of this cell */ inline void SetText( int col, int row, const PdfString & rsString ); /** * \param col the column of the table cell * \param row the row of the table cell * * \returns the contents string of this table cell */ inline virtual PdfString GetText ( int col, int row ) const; /** * \param col the column of the table cell * \param row the row of the table cell * * \returns the horizontal alignment of the contents in the cell */ inline virtual EPdfAlignment GetAlignment ( int col, int row ) const; /** * \param col the column of the table cell * \param row the row of the table cell * * \returns the vertical alignment of the contents in the cell */ inline virtual EPdfVerticalAlignment GetVerticalAlignment ( int col, int row ) const; /** * \param col the column of the table cell * \param row the row of the table cell * * \returns the font of this table cell or NULL to use the default font */ inline virtual PdfFont* GetFont ( int col, int row ) const; /** * \param col the column of the table cell * \param row the row of the table cell * * \returns true if this cell has a background color */ inline virtual bool HasBackgroundColor( int col, int row ) const; /** * \param col the column of the table cell * \param row the row of the table cell * * \returns the background color of the specified cell */ inline virtual PdfColor GetBackgroundColor( int col, int row ) const; /** * \param col the column of the table cell * \param row the row of the table cell * * \returns the foreground (text) color of the specified cell */ inline virtual PdfColor GetForegroundColor( int col, int row ) const; /** * \param col the column of the table cell * \param row the row of the table cell * * \returns true if the specified cell should use wordwrapping */ inline virtual bool HasWordWrap( int col, int row ) const; /** * \returns true if the table should have * a border around all cells. * \returns false if no cell border should be visible * * Cell borders are always drawn using the current PdfPainter * settings. */ inline virtual bool HasBorders() const; /** * \returns the stroke witdth of the border line */ inline virtual double GetBorderWidth() const; /** * \param col the column of the table cell * \param row the row of the table cell * * \returns the border color */ inline virtual PdfColor GetBorderColor( int col, int row ) const; /** * \param col the column of the table cell * \param row the row of the table cell * * \returns true if the table cell contains an image */ inline virtual bool HasImage( int col, int row ) const; /** * \param col the column of the table cell * \param row the row of the table cell * * \returns the image for the specified cell or NULL if the cell has no image */ inline virtual PdfImage* GetImage( int col, int row ) const; private: PdfFont* m_pFont; EPdfAlignment m_eAlignment; EPdfVerticalAlignment m_eVerticalAlignment; bool m_bWordWrap; PdfColor m_clForeground; bool m_bBackground; PdfColor m_clBackground; PdfString** m_ppData; int m_nCols; int m_nRows; bool m_bBorder; double m_dBorder; }; // ----------------------------------------------------- // // ----------------------------------------------------- void PdfSimpleTableModel::SetFont( PdfFont* pFont ) { m_pFont = pFont; } // ----------------------------------------------------- // // ----------------------------------------------------- void PdfSimpleTableModel::SetAlignment( EPdfAlignment eAlignment ) { m_eAlignment = eAlignment; } // ----------------------------------------------------- // // ----------------------------------------------------- void PdfSimpleTableModel::SetAlignment( EPdfVerticalAlignment eAlignment ) { m_eVerticalAlignment = eAlignment; } // ----------------------------------------------------- // // ----------------------------------------------------- void PdfSimpleTableModel::SetBackgroundEnabled( bool bEnable ) { m_bBackground = bEnable; } // ----------------------------------------------------- // // ----------------------------------------------------- void PdfSimpleTableModel::SetWordWrapEnabled( bool bEnable ) { m_bWordWrap = bEnable; } // ----------------------------------------------------- // // ----------------------------------------------------- void PdfSimpleTableModel::SetBorderEnabled( bool bEnable ) { m_bBorder = bEnable; } // ----------------------------------------------------- // // ----------------------------------------------------- void PdfSimpleTableModel::SetBorderWidth( double dWidth ) { m_dBorder = dWidth; } // ----------------------------------------------------- // // ----------------------------------------------------- void PdfSimpleTableModel::SetBackgroundColor( const PdfColor & rColor ) { m_clBackground = rColor; } // ----------------------------------------------------- // // ----------------------------------------------------- void PdfSimpleTableModel::SetForegroundColor( const PdfColor & rColor ) { m_clForeground = rColor; } // ----------------------------------------------------- // // ----------------------------------------------------- void PdfSimpleTableModel::SetText( int col, int row, const PdfString & rsString ) { if( !m_ppData || row >= m_nRows || col >= m_nCols ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } m_ppData[row][col] = rsString; } // ----------------------------------------------------- // // ----------------------------------------------------- PdfString PdfSimpleTableModel::GetText ( int col, int row ) const { if( !m_ppData || row >= m_nRows || col >= m_nCols ) return PdfString(); else return m_ppData[row][col].IsValid() ? m_ppData[row][col] : PdfString(""); } // ----------------------------------------------------- // // ----------------------------------------------------- EPdfAlignment PdfSimpleTableModel::GetAlignment ( int, int ) const { return m_eAlignment; } // ----------------------------------------------------- // // ----------------------------------------------------- EPdfVerticalAlignment PdfSimpleTableModel::GetVerticalAlignment ( int, int ) const { return m_eVerticalAlignment; } // ----------------------------------------------------- // // ----------------------------------------------------- PdfFont* PdfSimpleTableModel::GetFont ( int, int ) const { return m_pFont; } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfSimpleTableModel::HasBackgroundColor ( int, int ) const { return m_bBackground; } // ----------------------------------------------------- // // ----------------------------------------------------- PdfColor PdfSimpleTableModel::GetBackgroundColor ( int, int ) const { return m_clBackground; } // ----------------------------------------------------- // // ----------------------------------------------------- PdfColor PdfSimpleTableModel::GetForegroundColor( int, int ) const { return m_clForeground; } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfSimpleTableModel::HasWordWrap( int, int ) const { return m_bWordWrap; } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfSimpleTableModel::HasBorders() const { return m_bBorder; } // ----------------------------------------------------- // // ----------------------------------------------------- double PdfSimpleTableModel::GetBorderWidth() const { return m_dBorder; } // ----------------------------------------------------- // // ----------------------------------------------------- PdfColor PdfSimpleTableModel::GetBorderColor( int, int ) const { // always return black return PdfColor( 0.0, 0.0, 0.0 ); } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfSimpleTableModel::HasImage( int, int ) const { return false; } // ----------------------------------------------------- // // ----------------------------------------------------- PdfImage* PdfSimpleTableModel::GetImage( int, int ) const { return NULL; } /** * This is a high level class of a table which can be drawn to a PdfPainter. * * Use this class if you have to include data into your PDF as an table. * */ class PODOFO_DOC_API PdfTable { public: /** Callback to create a new page for PdfTable. * * \see SetAutoPageBreak * * \param rClipRect this is an output parameter which has * to be set to the clipping rectangle * of the new page. If the new page has * no clipping rectangle set it to * PdfRect( 0, 0, PdfPage::GetPageSize().GetWidth(), PdfPage::GetPageSize().GetHeight() ) * \param pCustom pointer to user defined data */ typedef PdfPage* (*CreatePageCallback)( PdfRect & rClipRect, void* pCustom ); /** Create a new PdfTable object. * * \param nCols number of columns in the table. * \param nRows number of rows in the table. */ PdfTable( int nCols, int nRows ); virtual ~PdfTable(); /** Draw the table with its current settings * on a PdfPainter. * * \param dX x coordinate of top left of the table * \param dY y coordinate of top left of the table * \param pPainter the painter to draw on. The painter has to have a page set currently. * \param rClipRect the clipping rectangle on the current page * \param pdLastX the last used X position by the table on the current page will be written to this value (usually bottom right) * \param pdLastY the last used Y positon by the table on the current page will be written to this value (usually bottom right) */ virtual void Draw( double dX, double dY, PdfPainter* pPainter, const PdfRect & rClipRect = PdfRect(), double* pdLastX = NULL, double* pdLastY = NULL ); /** Get the width of the table when drawn with the current settings at a certain position. * \param dX x coordinate of top left of the table * \param dY y coordinate of top left of the table * \param pPage the page on which the table will be drawn * * \returns the width of the table */ virtual double GetWidth( double dX, double dY, PdfCanvas* pPage ) const; /** Get the width of the table when drawn with the current settings at a certain position. * \param dX x coordinate of top left of the table * \param dY y coordinate of top left of the table * \param pPage the page on which the table will be drawn * * \returns the width of the table */ virtual double GetHeight( double dX, double dY, PdfCanvas* pPage ) const; /** Set the PdfTableModel that will supply all * contents and formatting informations to the table. * * \param pModel a PdfTableModel * * The model will not be owned by the PdfTable and has to be deleted * by the caller. * * \see GetModel */ inline void SetModel( PdfTableModel* pModel ); /** Get the current PdfTableModel * * \returns the currently set PdfTableModel or NULL if none was set */ inline const PdfTableModel* GetModel() const; /** Set the width of all columns. * * \param pdWidths a pointer to an array of GetCols() doubles * which are the individual width of a column. * * \see GetCols() */ void SetColumnWidths( double* pdWidths ); /** Set the height of all rows. * * \param pdHeights a pointer to an array of GetRows() doubles * which are the individual heights of a row. * * \see GetRows() */ void SetRowHeights( double* pdHeights ); /** Set all columns to have the same width. * * \param dWidth the width of every column * * By default the column with is calculated automatically * from either the table width or if no table width is set * from the width of the page on which the table is drawn. */ inline void SetColumnWidth( double dWidth ); /** Set all rows to have the same height. * * \param dHeight the height of every row * * By default the row height is calculated automatically * from either the table height or if no table height is set * from the height of the page on which the table is drawn. */ inline void SetRowHeight( double dHeight ); /** Set the width of the table. * * \param dWidth the width of the whole table. * * This width is used if no column width is set * to calculate the width of every column. * If this width is not set, the width of the page * on which this table is drawn is used. */ inline void SetTableWidth( double dWidth ); /** Set the height of the table. * * \param dHeight the height of the whole table. * * This height is used if no row height is set * to calculate the height of every row. * If this height is not set, the height of the page * on which this table is drawn is used. */ inline void SetTableHeight( double dHeight ); /** Automatically create a new page and continue * drawing the table on the new page, * if there is not enough space on the current page. * * The newly created page will be set as the current page * on the painter used to draw and will be created using the * same size as the old page. * * \param bPageBreak if true automatically create new pages * if required. * \param callback a callback function that is called to create * a new page. Please note: PdfTable cannot create new pages on its * own. You always have to implement a callback which does the new page * creation for the PdfTable. * \param pCustomData custom data that is passed to the callback * * By default this feature is turned off and contents are clipped * that do not fit on the current page. * * \see GetAutoPageBreak */ inline void SetAutoPageBreak( bool bPageBreak, CreatePageCallback callback, void* pCustomData = NULL); /** * \returns true if a new page is created automatically if more * space is required to draw the table. * * \see SetAutoPageBreak */ inline bool GetAutoPageBreak() const; /** * \returns the number of columns in the table. */ inline int GetCols() const; /** * \returns the number of rows in the table. */ inline int GetRows() const; protected: /** Internal functions that calculates the total table size * for a table with the current settings when drawn on a certain page. * * \param dX the X coordinate of top left at which is drawn * \param dY the Y coordinate of top left at which is drawn * \param pCanvas the canvas object (usually a page) on which the table will be drawn. * \param pdWidths pointer to an array with GetCols() doubles * where the width for each column will be stored * \param pdHeights pointer to an array with GetRows() doublesd * where the height for each row will be stored * * \param pdWidth pointer to a double where the total width of the table will be stored * \param pdHeight pointer to a double where the total height of the table will be stored */ void CalculateTableSize( const double dX, const double dY, const PdfCanvas* pCanvas, double* pdWidths, double* pdHeights, double* pdWidth, double* pdHeight ) const; /** Draw one row of horizontal cell borders using the correct color * for each cell. * * @param nRow the current row * @param dX left x coordinate * @param dY y coordinate * @param pPainter use this painter object * @param pdColWidths an array containing all colomun widths */ void DrawHorizontalBorders( int nRow, double dX, double dY, PdfPainter* pPainter, double* pdColWidths ); /** Checks if there is enough space on the current page * for one row! If necessary a new page is created. * * If GetAutoPageBreak is false, this method does nothing. * * \param pdY top of the table * \param pdCurY pointer to the current y position on the page. * Might be reset to a new y position. * \param dRowHeight height of the next row. * \param pPainter painter used for drawing * * \returns true if a new page was created, otherwise false */ bool CheckForNewPage( double* pdY, double* pdCurY, double dRowHeight, PdfPainter* pPainter ); protected: PdfTableModel* m_pModel; int m_nCols; int m_nRows; double m_dColWidth; double m_dRowHeight; double m_dTableWidth; double m_dTableHeight; double* m_pdColWidths; double* m_pdRowHeights; bool m_bAutoPageBreak; void* m_pCustomData; CreatePageCallback m_fpCallback; PdfRect m_curClipRect; }; // ----------------------------------------------------- // // ----------------------------------------------------- void PdfTable::SetModel( PdfTableModel* pModel ) { m_pModel = pModel; } // ----------------------------------------------------- // // ----------------------------------------------------- const PdfTableModel* PdfTable::GetModel() const { return m_pModel; } // ----------------------------------------------------- // // ----------------------------------------------------- void PdfTable::SetColumnWidth( double dWidth ) { m_dColWidth = dWidth; } // ----------------------------------------------------- // // ----------------------------------------------------- void PdfTable::SetRowHeight( double dHeight ) { m_dRowHeight = dHeight; } // ----------------------------------------------------- // // ----------------------------------------------------- void PdfTable::SetTableWidth( double dWidth ) { m_dTableWidth = dWidth; } // ----------------------------------------------------- // // ----------------------------------------------------- void PdfTable::SetTableHeight( double dHeight ) { m_dTableHeight = dHeight; } // ----------------------------------------------------- // // ----------------------------------------------------- void PdfTable::SetAutoPageBreak( bool bPageBreak, CreatePageCallback callback, void* pCustomData ) { m_bAutoPageBreak = bPageBreak; m_fpCallback = callback; m_pCustomData = pCustomData; } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfTable::GetAutoPageBreak() const { return m_bAutoPageBreak; } // ----------------------------------------------------- // // ----------------------------------------------------- int PdfTable::GetCols() const { return m_nCols; } // ----------------------------------------------------- // // ----------------------------------------------------- int PdfTable::GetRows() const { return m_nRows; } }; #endif // _PDF_TABLE_H_ podofo-0.9.3/src/doc/PdfDestination.h0000664000175000017500000003301312344436402017303 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2006 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_DESTINATION_H_ #define _PDF_DESTINATION_H_ #include "podofo/base/PdfDefines.h" #include "podofo/base/PdfArray.h" #include "podofo/base/PdfRect.h" #include "podofo/base/PdfReference.h" namespace PoDoFo { class PdfAction; class PdfPage; class PdfRect; enum EPdfDestinationFit { ePdfDestinationFit_Fit, ePdfDestinationFit_FitH, ePdfDestinationFit_FitV, ePdfDestinationFit_FitB, ePdfDestinationFit_FitBH, ePdfDestinationFit_FitBV, ePdfDestinationFit_Unknown = 0xFF }; /** Destination type, as per 12.3.2.2 of the Pdf spec. * * (see table 151 in the pdf spec) */ enum EPdfDestinationType { ePdfDestinationType_XYZ, ePdfDestinationType_Fit, ePdfDestinationType_FitH, ePdfDestinationType_FitV, ePdfDestinationType_FitR, ePdfDestinationType_FitB, ePdfDestinationType_FitBH, ePdfDestinationType_FitBV, ePdfDestinationType_Unknown = 0xFF }; /** A destination in a PDF file. * A destination can either be a page or an action. * * \see PdfOutlineItem \see PdfAnnotation \see PdfDocument */ class PODOFO_DOC_API PdfDestination { public: /** Create an empty destination - points to nowhere */ PdfDestination( PdfVecObjects* pParent ); /** Create a new PdfDestination from an existing PdfObject (such as loaded from a doc) * \param pObject the object to construct from * \param pDocument a PDF document owning this destination, needed to resolve pages */ PdfDestination( PdfObject* pObject, PdfDocument* pDocument ); /** Create a new PdfDestination from an existing PdfObject (such as loaded from a doc) * \param pObject the object to construct from * \param pVecObjects a PdfVecObjects owning this destination, needed to resolve pages */ PdfDestination( PdfObject* pObject, PdfVecObjects* pVecObjects ); /** Create a new PdfDestination with a page as destination * \param pPage a page which is the destination * \param eFit fit mode for the page. Must be ePdfDestinationFit_Fit or ePdfDestinationFit_FitB */ PdfDestination( const PdfPage* pPage, EPdfDestinationFit eFit = ePdfDestinationFit_Fit ); /** Create a destination to a page with its contents magnified to fit into the given rectangle * \param pPage a page which is the destination * \param rRect magnify the page so that the contents of the rectangle are visible */ PdfDestination( const PdfPage* pPage, const PdfRect & rRect ); /** Create a new destination to a page with specified left * and top coordinates and a zoom factor. * \param pPage a page which is the destination * \param dLeft left coordinate * \param dTop top coordinate * \param dZoom zoom factor in the viewer */ PdfDestination( const PdfPage* pPage, double dLeft, double dTop, double dZoom ); /** Create a new destination to a page. * \param pPage a page which is the destination * \param eFit fit mode for the Page. Allowed values are ePdfDestinationFit_FitH, * ePdfDestinationFit_FitV, ePdfDestinationFit_FitBH, ePdfDestinationFit_FitBV * \param dValue value which is a required argument for the selected fit mode */ PdfDestination( const PdfPage* pPage, EPdfDestinationFit eFit, double dValue ); /** Copy an existing PdfDestination * \param rhs copy this PdfDestination */ PdfDestination( const PdfDestination & rhs ); /** Copy an existing PdfDestination * \param rhs copy this PdfDestination * \returns this object */ const PdfDestination & operator=( const PdfDestination & rhs ); /** Get the page that this destination points to * Requires that this PdfDestination was somehow * created by or from a PdfDocument. Won't work otherwise. * \param pDoc a PDF document owning this destination, needed to resolve pages * * \returns the referenced PdfPage */ PdfPage* GetPage( PdfDocument* pDoc ); /** Get the page that this destination points to * Requires that this PdfDestination was somehow * created by or from a PdfDocument. Won't work otherwise. * \param pVecObjects a PdfVecObjects owning this destination, needed to resolve pages * * \returns the referenced PdfPage */ PdfPage* GetPage( PdfVecObjects* pVecObjects ); /** Get the destination fit type * * \returns the fit type */ inline EPdfDestinationType GetType() const; /** Get the destination zoom * Destination must be of type XYZ * otherwise exception is thrown. * * \returns the zoom */ inline double GetZoom() const; /** Get the destination rect * Destination must be of type FirR * otherwise exception is thrown * * \returns the destination rect */ inline PdfRect GetRect() const; /** Get the destination Top position * Destination must be of type XYZ, FitH, FitR, FitBH * otherwise exception is thrown. * * \returns the Top position */ inline double GetTop() const; /** Get the destination Left position * Destination must be of type XYZ, FitV or FitR * otherwise exception is thrown. * * \returns the Left position */ inline double GetLeft() const; /** Get the destination Value * Destination must be of type FitH, FitV * or FitBH, otherwise exception is thrown * * \returns the destination Value */ inline double GetDValue() const; /** Get access to the internal object * * \returns the internal PdfObject */ inline PdfObject* GetObject(); /** Get access to the internal object * This is an overloaded member function. * * \returns the internal PdfObject */ inline const PdfObject* GetObject() const; /** Get access to the internal array * \returns the internal PdfArray */ inline PdfArray &GetArray(); /** Get access to the internal array * This is an overloaded member function. * * \returns the internal PdfArray */ inline const PdfArray &GetArray() const; /** Adds this destination to an dictionary. * This method handles the all the complexities of making sure it's added correctly * * If this destination is empty. Nothing will be added. * * \param dictionary the destination will be added to this dictionary */ void AddToDictionary( PdfDictionary & dictionary ) const; private: /** Initialize a new PdfDestination from an existing PdfObject (such as loaded from a doc) * and a document. * * \param pObject the object to construct from * \param pDoc a PDF document owning this destination, needed to resolve pages */ void Init( PdfObject* pObject, PdfDocument* pDocument ); private: static const long s_lNumDestinations; static const char* s_names[]; PdfArray m_array; PdfObject* m_pObject; /** Create an empty destination - NOT ALLOWED */ PdfDestination(); }; // ----------------------------------------------------- // // ----------------------------------------------------- inline PdfObject* PdfDestination::GetObject() { return m_pObject; } // ----------------------------------------------------- // // ----------------------------------------------------- inline const PdfObject* PdfDestination::GetObject() const { return m_pObject; } // ----------------------------------------------------- // // ----------------------------------------------------- inline PdfArray &PdfDestination::GetArray() { return m_array; } // ----------------------------------------------------- // // ----------------------------------------------------- inline const PdfArray &PdfDestination::GetArray() const { return m_array; } // ----------------------------------------------------- // // ----------------------------------------------------- inline EPdfDestinationType PdfDestination::GetType() const { if ( !m_array.size() ) return ePdfDestinationType_Unknown; PdfName tp = m_array[1].GetName(); if ( tp == PdfName("XYZ") ) return ePdfDestinationType_XYZ; if ( tp == PdfName("Fit") ) return ePdfDestinationType_Fit; if ( tp == PdfName("FitH") ) return ePdfDestinationType_FitH; if ( tp == PdfName("FitV") ) return ePdfDestinationType_FitV; if ( tp == PdfName("FitR") ) return ePdfDestinationType_FitR; if ( tp == PdfName("FitB") ) return ePdfDestinationType_FitB; if ( tp == PdfName("FitBH") ) return ePdfDestinationType_FitBH; if ( tp == PdfName("FitBV") ) return ePdfDestinationType_FitBV; return ePdfDestinationType_Unknown; } // ----------------------------------------------------- // // ----------------------------------------------------- inline double PdfDestination::GetDValue() const { EPdfDestinationType tp = GetType(); if ( tp != ePdfDestinationType_FitH && tp != ePdfDestinationType_FitV && tp != ePdfDestinationType_FitBH ) { PODOFO_RAISE_ERROR( ePdfError_WrongDestinationType ); } return m_array[2].GetReal(); } // ----------------------------------------------------- // // ----------------------------------------------------- inline double PdfDestination::GetLeft() const { EPdfDestinationType tp = GetType(); if ( tp != ePdfDestinationType_FitV && tp != ePdfDestinationType_XYZ && tp != ePdfDestinationType_FitR ) { PODOFO_RAISE_ERROR( ePdfError_WrongDestinationType ); } return m_array[2].GetReal(); } // ----------------------------------------------------- // // ----------------------------------------------------- inline PdfRect PdfDestination::GetRect() const { if ( GetType() != ePdfDestinationType_FitR ) { PODOFO_RAISE_ERROR( ePdfError_WrongDestinationType ); } return PdfRect(m_array[2].GetReal(), m_array[3].GetReal(), m_array[4].GetReal(), m_array[5].GetReal()); } // ----------------------------------------------------- // // ----------------------------------------------------- inline double PdfDestination::GetTop() const { EPdfDestinationType tp = GetType(); switch (tp) { case ePdfDestinationType_XYZ: return m_array[3].GetReal(); case ePdfDestinationType_FitH: case ePdfDestinationType_FitBH: return m_array[2].GetReal(); case ePdfDestinationType_FitR: return m_array[5].GetReal(); case ePdfDestinationType_Fit: case ePdfDestinationType_FitV: case ePdfDestinationType_FitB: case ePdfDestinationType_FitBV: case ePdfDestinationType_Unknown: default: { PODOFO_RAISE_ERROR( ePdfError_WrongDestinationType ); } }; } // ----------------------------------------------------- // // ----------------------------------------------------- inline double PdfDestination::GetZoom() const { if ( GetType() != ePdfDestinationType_XYZ ) { PODOFO_RAISE_ERROR( ePdfError_WrongDestinationType ); } return m_array[4].GetReal(); } }; #endif // _PDF_DESTINATION_H_ podofo-0.9.3/src/doc/PdfAcroForm.cpp0000664000175000017500000001307512347303775017104 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2007 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfAcroForm.h" #include "base/PdfDefinesPrivate.h" #include "base/PdfArray.h" #include "base/PdfDictionary.h" #include "PdfDocument.h" #include "PdfFont.h" #include namespace PoDoFo { /* We use NULL for the PdfElement name, since the AcroForm dict does NOT have a /Type key! */ PdfAcroForm::PdfAcroForm( PdfDocument* pDoc, EPdfAcroFormDefaulAppearance eDefaultAppearance ) : PdfElement( NULL, pDoc ), m_pDocument( pDoc ) { // Initialize with an empty fields array this->GetObject()->GetDictionary().AddKey( PdfName("Fields"), PdfArray() ); Init( eDefaultAppearance ); } PdfAcroForm::PdfAcroForm( PdfDocument* pDoc, PdfObject* pObject, EPdfAcroFormDefaulAppearance eDefaultAppearance ) : PdfElement( NULL, pObject ), m_pDocument( pDoc ) { Init( eDefaultAppearance ); } void PdfAcroForm::Init( EPdfAcroFormDefaulAppearance eDefaultAppearance ) { // Add default appearance: black text, 12pt times // -> only if we do not have a DA key yet // Peter Petrov 27 April 2008 //this->GetObject()->GetDictionary().AddKey( PdfName("NeedAppearances"), PdfVariant(true) ); if( !this->GetObject()->GetDictionary().HasKey("DA") && eDefaultAppearance == ePdfAcroFormDefaultAppearance_BlackText12pt ) { PdfFont* pFont = m_pDocument->CreateFont( "Helvetica", false, PdfEncodingFactory::GlobalWinAnsiEncodingInstance(), PdfFontCache::eFontCreationFlags_AutoSelectBase14, false ); //PdfFont* pFont = m_pDocument->CreateFont( "Arial" ); PdfObject* pResource; PdfObject* pFontDict; // Create DR key if( !this->GetObject()->GetDictionary().HasKey( PdfName("DR") ) ) this->GetObject()->GetDictionary().AddKey( PdfName("DR"), PdfDictionary() ); pResource = this->GetObject()->GetDictionary().GetKey( PdfName("DR") ); if( !pResource->GetDictionary().HasKey( PdfName("Font") ) ) pResource->GetDictionary().AddKey( PdfName("Font"), PdfDictionary() ); pFontDict = pResource->GetDictionary().GetKey( PdfName("Font") ); pFontDict->GetDictionary().AddKey( pFont->GetIdentifier(), pFont->GetObject()->Reference() ); // Create DA key std::ostringstream oss; PdfLocaleImbue(oss); oss << "0 0 0 rg /" << pFont->GetIdentifier().GetName() << " 12 Tf"; this->GetObject()->GetDictionary().AddKey( PdfName("DA"), PdfString( oss.str() ) ); } } /* int PdfAcroForm::GetCount() { PdfObject* pFields = this->GetObject()->GetDictionary().GetKey( PdfName("Fields") ); if( pFields ) { return pFields->GetArray().size(); } else { PODOFO_RAISE_ERROR( ePdfError_NoObject ); } } */ void PdfAcroForm::SetNeedAppearances( bool bNeedAppearances ) { this->GetObject()->GetDictionary().AddKey( PdfName("NeedAppearances"), PdfVariant(bNeedAppearances) ); } bool PdfAcroForm::GetNeedAppearances() const { return this->GetObject()->GetDictionary().GetKeyAsBool( PdfName("NeedAppearances"), false ); } }; podofo-0.9.3/src/doc/PdfExtGState.h0000664000175000017500000000571612347276455016720 0ustar dominikdominik #ifndef _PDF_EXTGSTATE_H_ #define _PDF_EXTGSTATE_H_ #include "podofo/base/PdfDefines.h" #include "podofo/base/PdfName.h" #include "PdfElement.h" namespace PoDoFo { class PdfObject; class PdfPage; class PdfWriter; /** This class wraps the ExtGState object used in the Resource * Dictionary of a Content-supporting element (page, Pattern, etc.) * The main usage is for transparency, but it also support a variety * of prepress features. */ class PODOFO_DOC_API PdfExtGState : public PdfElement { public: /** Create a new PdfExtGState object which will introduce itself * automatically to every page object it is used on. * * \param pParent parent vector of objects * */ PdfExtGState( PdfVecObjects* pParent ); /** Create a new PdfExtGState object which will introduce itself * automatically to every page object it is used on. * * \param pParent parent document * */ PdfExtGState( PdfDocument* pParent ); virtual ~PdfExtGState(); /** Returns the identifier of this ExtGState how it is known * in the pages resource dictionary. * \returns PdfName containing the identifier (e.g. /ExtGS13) */ inline const PdfName & GetIdentifier() const; /** Sets the opacity value to be used for fill operations * \param opac a floating point value from 0 (transparent) to 1 (opaque) */ void SetFillOpacity( float opac ); /** Sets the opacity value to be used for stroking operations * \param opac a floating point value from 0 (transparent) to 1 (opaque) */ void SetStrokeOpacity( float opac ); /** Sets the transparency blend mode * \param blendMode one of the predefined blending modes (see PodofoDefines.h) */ void SetBlendMode( const char* blendMode ); /** Enables/Disables overprinting for both Fill & Stroke * \param enable enable or disable */ void SetOverprint( bool enable=true ); /** Enables/Disables overprinting for Fill operations * \param enable enable or disable */ void SetFillOverprint( bool enable=true ); /** Enables/Disables overprinting for Stroke operations * \param enable enable or disable */ void SetStrokeOverprint( bool enable=true ); /** Enables/Disables non-zero overprint mode * \param enable enable or disable */ void SetNonZeroOverprint( bool enable=true ); /** Set the Rendering Intent * \param intent one of the predefined intents (see Podofo.h) */ void SetRenderingIntent( const char* intent ); /** Set the frequency for halftones * \param frequency screen frequency, measured in halftone cells per inch in device space */ void SetFrequency( double frequency ); private: /** Initialize the object */ void Init( void ); private: PdfName m_Identifier; }; const PdfName & PdfExtGState::GetIdentifier() const { return m_Identifier; } }; #endif // _PDF_EXTGSTATE_H_ podofo-0.9.3/src/doc/PdfDestination.cpp0000664000175000017500000001665712344436402017655 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2006 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfDestination.h" #include "base/PdfDictionary.h" #include "base/PdfDefinesPrivate.h" #include "PdfAction.h" #include "PdfDocument.h" #include "PdfNamesTree.h" #include "PdfPage.h" #include "PdfPagesTree.h" namespace PoDoFo { const long PdfDestination::s_lNumDestinations = 19; const char* PdfDestination::s_names[] = { "Fit", "FitH", "FitV", "FitB", "FitBH", "FitBV", NULL }; PdfDestination::PdfDestination( PdfVecObjects* pParent ) { m_pObject = pParent->CreateObject( m_array ); } PdfDestination::PdfDestination( PdfObject* pObject, PdfDocument* pDocument ) { Init( pObject, pDocument ); } PdfDestination::PdfDestination( PdfObject* pObject, PdfVecObjects* pVecObjects ) { PdfDocument* pDocument = pVecObjects->GetParentDocument(); if( !pDocument ) { PODOFO_RAISE_ERROR( ePdfError_InvalidDataType ); } Init( pObject, pDocument ); } PdfDestination::PdfDestination( const PdfPage* pPage, EPdfDestinationFit eFit ) { PdfName type = PdfName("Fit"); if( eFit == ePdfDestinationFit_Fit ) type = PdfName("Fit"); else if( eFit == ePdfDestinationFit_FitB ) type = PdfName("FitB"); else { // Peter Petrov 6 June 2008 // silent mode //PODOFO_RAISE_ERROR( ePdfError_InvalidKey ); } m_array.push_back( pPage->GetObject()->Reference() ); m_array.push_back( type ); m_pObject = pPage->GetObject()->GetOwner()->CreateObject( m_array ); } PdfDestination::PdfDestination( const PdfPage* pPage, const PdfRect & rRect ) { PdfVariant var; rRect.ToVariant( var ); m_array.push_back( pPage->GetObject()->Reference() ); m_array.push_back( PdfName("FitR") ); m_array.insert( m_array.end(), var.GetArray().begin(), var.GetArray().end() ); m_pObject = pPage->GetObject()->GetOwner()->CreateObject( m_array ); } PdfDestination::PdfDestination( const PdfPage* pPage, double dLeft, double dTop, double dZoom ) { m_array.push_back( pPage->GetObject()->Reference() ); m_array.push_back( PdfName("XYZ") ); m_array.push_back( dLeft ); m_array.push_back( dTop ); m_array.push_back( dZoom ); m_pObject = pPage->GetObject()->GetOwner()->CreateObject( m_array ); } PdfDestination::PdfDestination( const PdfPage* pPage, EPdfDestinationFit eFit, double dValue ) { PdfName type; if( eFit == ePdfDestinationFit_FitH ) type = PdfName("FitH"); else if( eFit == ePdfDestinationFit_FitV ) type = PdfName("FitV"); else if( eFit == ePdfDestinationFit_FitBH ) type = PdfName("FitBH"); else if( eFit == ePdfDestinationFit_FitBV ) type = PdfName("FitBV"); else { PODOFO_RAISE_ERROR( ePdfError_InvalidKey ); } m_array.push_back( pPage->GetObject()->Reference() ); m_array.push_back( type ); m_array.push_back( dValue ); m_pObject = pPage->GetObject()->GetOwner()->CreateObject( m_array ); } PdfDestination::PdfDestination( const PdfDestination & rhs ) { this->operator=( rhs ); } const PdfDestination & PdfDestination::operator=( const PdfDestination & rhs ) { m_array = rhs.m_array; m_pObject = rhs.m_pObject; return *this; } void PdfDestination::Init( PdfObject* pObject, PdfDocument* pDocument ) { if ( pObject->GetDataType() == ePdfDataType_Array ) { m_array = pObject->GetArray(); } else if( pObject->GetDataType() == ePdfDataType_String ) { PdfNamesTree* pNames = pDocument->GetNamesTree( ePdfDontCreateObject ); if( !pNames ) { PODOFO_RAISE_ERROR( ePdfError_NoObject ); } PdfObject* pValue = pNames->GetValue( "Dests", pObject->GetString() ); if( !pValue ) { PODOFO_RAISE_ERROR( ePdfError_InvalidName ); } if( pValue->IsArray() ) m_array = pValue->GetArray(); else if( pValue->IsDictionary() ) m_array = pValue->GetDictionary().GetKey( "D" )->GetArray(); } m_pObject = pObject; } void PdfDestination::AddToDictionary( PdfDictionary & dictionary ) const { // Do not add empty destinations if( !m_array.size() ) return; // since we can only have EITHER a Dest OR an Action // we check for an Action, and if already present, we throw if ( dictionary.HasKey( PdfName( "A" ) ) ) PODOFO_RAISE_ERROR( ePdfError_ActionAlreadyPresent ); dictionary.RemoveKey( "Dest" ); dictionary.AddKey( "Dest", m_pObject ); } PdfPage* PdfDestination::GetPage( PdfDocument* pDoc ) { if( !m_array.size() ) return NULL; // first entry in the array is the page - so just make a new page from it! return pDoc->GetPagesTree()->GetPage( m_array[0].GetReference() ); } PdfPage* PdfDestination::GetPage( PdfVecObjects* pVecObjects ) { PdfDocument* pDoc = pVecObjects->GetParentDocument(); if( !pDoc ) { PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidHandle, "PdfVecObjects needs a parent PdfDocument to resolve pages." ); } return this->GetPage( pDoc ); } }; podofo-0.9.3/src/doc/PdfPagesTreeCache.cpp0000664000175000017500000001301612344436402020161 0ustar dominikdominik/*************************************************************************** * Copyriht (C) 2009 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfPagesTreeCache.h" #include "base/PdfDefinesPrivate.h" #include "PdfPage.h" #include "PdfPagesTree.h" namespace PoDoFo { PdfPagesTreeCache::PdfPagesTreeCache( int nInitialSize ) { m_deqPageObjs.resize( nInitialSize ); } PdfPagesTreeCache::~PdfPagesTreeCache() { this->ClearCache(); } PdfPage* PdfPagesTreeCache::GetPage( int nIndex ) { if( nIndex < 0 || nIndex >= static_cast(m_deqPageObjs.size()) ) { PdfError::LogMessage( eLogSeverity_Error, "PdfPagesTreeCache::GetPage( %i ) index out of range. Size of cache is %i\n", nIndex, m_deqPageObjs.size() ); return NULL; } return m_deqPageObjs[nIndex]; } void PdfPagesTreeCache::AddPageObject( int nIndex, PdfPage* pPage ) { // Delete an old page if it is at the same position PdfPage* pOldPage = GetPage( nIndex ); delete pOldPage; if( nIndex >= static_cast(m_deqPageObjs.size()) ) { m_deqPageObjs.resize( nIndex + 1 ); } m_deqPageObjs[nIndex] = pPage; } void PdfPagesTreeCache::AddPageObjects( int nIndex, std::vector vecPages ) { if( (nIndex + static_cast(vecPages.size())) >= static_cast(m_deqPageObjs.size()) ) { m_deqPageObjs.resize( nIndex + vecPages.size() + 1 ); } for (size_t i=0; i= static_cast(m_deqPageObjs.size()) ) m_deqPageObjs.resize( nBeforeIndex + 1 ); m_deqPageObjs.insert( m_deqPageObjs.begin() + nBeforeIndex, static_cast(NULL) ); } void PdfPagesTreeCache::InsertPages( int nAfterPageIndex, int nCount ) { const int nBeforeIndex = ( nAfterPageIndex == ePdfPageInsertionPoint_InsertBeforeFirstPage ) ? 0 : nAfterPageIndex+1; if( nBeforeIndex+nCount >= static_cast(m_deqPageObjs.size()) ) m_deqPageObjs.resize( nBeforeIndex + nCount + 1 ); for (int i=0; i(NULL) ); } void PdfPagesTreeCache::DeletePage( int nIndex ) { if( nIndex < 0 || nIndex >= static_cast(m_deqPageObjs.size()) ) { PdfError::LogMessage( eLogSeverity_Error, "PdfPagesTreeCache::DeletePage( %i ) index out of range. Size of cache is %i\n", nIndex, m_deqPageObjs.size() ); return; } delete m_deqPageObjs[nIndex]; m_deqPageObjs.erase( m_deqPageObjs.begin() + nIndex ); } void PdfPagesTreeCache::ClearCache() { PdfPageList::iterator it = m_deqPageObjs.begin(); while( it != m_deqPageObjs.end() ) { delete (*it); ++it; } m_deqPageObjs.clear(); } }; podofo-0.9.3/src/doc/PdfNamesTree.h0000664000175000017500000001711112344436402016706 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2006 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_NAMES_TREE_H_ #define _PDF_NAMES_TREE_H_ #include "podofo/base/PdfDefines.h" #include "PdfElement.h" namespace PoDoFo { class PdfDictionary; class PdfName; class PdfObject; class PdfString; class PdfVecObjects; enum EPdfNameLimits { ePdfNameLimits_Before, ePdfNameLimits_Inside, ePdfNameLimits_After }; class PODOFO_DOC_API PdfNamesTree : public PdfElement { public: /** Create a new PdfNamesTree object * \param pParent parent of this action */ PdfNamesTree( PdfVecObjects* pParent ); /** Create a PdfNamesTree object from an existing PdfObject * \param pObject the object to create from * \param pCatalog the Catalog dictionary of the owning PDF */ PdfNamesTree( PdfObject* pObject, PdfObject* pCatalog ); virtual ~PdfNamesTree() { } /** Insert a key and value in one of the dictionaries of the name tree. * \param tree name of the tree to search for the key. * \param key the key to insert. If it exists, it will be overwritten. * \param rValue the value to insert. */ void AddValue( const PdfName & tree, const PdfString & key, const PdfObject & rValue ); /** Get the object referenced by a string key in one of the dictionaries * of the name tree. * \param tree name of the tree to search for the key. * \param key the key to search for * \returns the value of the key or NULL if the key was not found. * if the value is a reference, the object referenced by * this reference is returned. */ PdfObject* GetValue( const PdfName & tree, const PdfString & key ) const; /** Tests wether a certain nametree has a value. * * It is generally faster to use GetValue and check for NULL * as return value. * * \param tree name of the tree to search for the key. * \param key name of the key to look for * \returns true if the dictionary has such a key. */ bool HasValue( const PdfName & tree, const PdfString & key ) const; /** Tests wether a key is in the range of a limits entry of a name tree node * \returns ePdfNameLimits_Inside if the key is inside of the range * \returns ePdfNameLimits_After if the key is greater than the specified range * \returns ePdfNameLimits_Before if the key is smalelr than the specified range * * Internal use only. */ static EPdfNameLimits CheckLimits( const PdfObject* pObj, const PdfString & key ); /** * Adds all keys and values from a name tree to a dictionary. * Removes all keys that have been previously in the dictionary. * * \param tree the name of the tree to convert into a dictionary * \param rDict add all keys and values to this dictionary */ void ToDictionary( const PdfName & dictionary, PdfDictionary& rDict ); /** Peter Petrov: 23 May 2008 * I have made it for access to "JavaScript" dictonary. This is "document-level javascript storage" * \param bCreate if true the javascript node is created if it does not exists. */ inline PdfObject* GetJavaScriptNode(bool bCreate = false) const; /** Peter Petrov: 6 June 2008 * I have made it for access to "Dest" dictionary. This is "document-level named destination storage" * \param bCreate if true the dests node is created if it does not exists. */ inline PdfObject* GetDestsNode(bool bCreate = false) const; private: /** Get a PdfNameTrees root node for a certain name. * \param name that identifies a specific name tree. * Valid names are: * - Dests * - AP * - JavaScript * - Pages * - Templates * - IDS * - URLS * - EmbeddedFiles * - AlternatePresentations * - Renditions * * \param bCreate if true the root node is created if it does not exists. * \returns the root node of the tree or NULL if it does not exists */ PdfObject* GetRootNode( const PdfName & name, bool bCreate = false ) const; /** Recursively walk through the name tree and find the value for key. * \param pObj the name tree * \param key the key to find a value for * \return the value for the key or NULL if it was not found */ PdfObject* GetKeyValue( PdfObject* pObj, const PdfString & key ) const; /** * Add all keys and values from an object and its children to a dictionary. * \param pObj a pdf name tree node * \param rDict a dictionary */ void AddToDictionary( PdfObject* pObj, PdfDictionary & rDict ); private: PdfObject* m_pCatalog; }; // ----------------------------------------------------- // // ----------------------------------------------------- PdfObject* PdfNamesTree::GetJavaScriptNode(bool bCreate) const { return this->GetRootNode( PdfName("JavaScript"), bCreate ); } // ----------------------------------------------------- // // ----------------------------------------------------- PdfObject* PdfNamesTree::GetDestsNode(bool bCreate) const { return this->GetRootNode( PdfName("Dests"), bCreate ); } }; #endif // _PDF_NAMES_TREE_H_ podofo-0.9.3/src/doc/PdfImage.cpp0000664000175000017500000006372712347347566016435 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2005 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfImage.h" #include "base/PdfDefinesPrivate.h" #include "base/PdfArray.h" #include "base/PdfColor.h" #include "base/PdfStream.h" #include "base/PdfFiltersPrivate.h" #include #include #include #define PODOFO_JPEG_RUNTIME_COMPATIBLE #ifdef PODOFO_HAVE_TIFF_LIB extern "C" { # include "tiffio.h" # ifdef _WIN32 // Collision between tiff and jpeg-headers # ifndef XMD_H # define XMD_H # endif # undef FAR # endif } #endif // PODOFO_HAVE_TIFF_LIB #ifdef PODOFO_HAVE_JPEG_LIB extern "C" { # ifndef XMD_H # define XMD_H # endif # include "jpeglib.h" } #endif // PODOFO_HAVE_JPEG_LIB #ifdef PODOFO_HAVE_PNG_LIB #include #endif /// PODOFO_HAVE_PNG_LIB // defines an annoying GetObject macro that changes uses of GetObject to // GetObjectA . Since macros aren't scope and namespace aware that breaks our code. // Since we won't be using the Win32 resource manager API here, just undefine it. #if defined(GetObject) #undef GetObject #endif using namespace std; namespace PoDoFo { PdfImage::PdfImage( PdfVecObjects* pParent, const char* pszPrefix ) : PdfXObject( "Image", pParent, pszPrefix ) { m_rRect = PdfRect(); this->SetImageColorSpace( ePdfColorSpace_DeviceRGB ); } PdfImage::PdfImage( PdfDocument* pParent, const char* pszPrefix ) : PdfXObject( "Image", pParent, pszPrefix ) { m_rRect = PdfRect(); this->SetImageColorSpace( ePdfColorSpace_DeviceRGB ); } PdfImage::PdfImage( PdfObject* pObject ) : PdfXObject( "Image", pObject ) { m_rRect.SetHeight( static_cast(this->GetObject()->GetDictionary().GetKey( "Height" )->GetNumber()) ); m_rRect.SetWidth ( static_cast(this->GetObject()->GetDictionary().GetKey( "Width" )->GetNumber()) ); } PdfImage::~PdfImage() { } /* Example: { "JPEG", "TIFF", NULL } * * \returns a zero terminates list of all supported image formats */ const char** PdfImage::GetSupportedFormats() { static const char* ppszFormats[] = { #ifdef PODOFO_HAVE_JPEG_LIB "JPEG", #endif // PODOFO_HAVE_JPEG_LIB #ifdef PODOFO_HAVE_PNG_LIB "PNG", #endif // PODOFO_HAVE_PNG_LIB #ifdef PODOFO_HAVE_TIFF_LIB "TIFF", #endif // PODOFO_HAVE_TIFF_LIB NULL }; return ppszFormats; } void PdfImage::SetImageColorSpace( EPdfColorSpace eColorSpace, const PdfArray *indexedData ) { if (eColorSpace == ePdfColorSpace_Indexed) { PODOFO_RAISE_LOGIC_IF( !indexedData, "PdfImage::SetImageColorSpace: indexedData cannot be NULL for Indexed color space." ); PdfArray array(*indexedData); array.insert(array.begin(), ColorspaceToName( eColorSpace )); this->GetObject()->GetDictionary().AddKey( PdfName("ColorSpace"), array ); } else { this->GetObject()->GetDictionary().AddKey( PdfName("ColorSpace"), ColorspaceToName( eColorSpace ) ); } } void PdfImage::SetImageICCProfile( PdfInputStream* pStream, long lColorComponents, EPdfColorSpace eAlternateColorSpace ) { // Check lColorComponents for a valid value if( lColorComponents != 1 && lColorComponents != 3 && lColorComponents != 4 ) { PODOFO_RAISE_ERROR_INFO( ePdfError_ValueOutOfRange, "SetImageICCProfile lColorComponents must be 1,3 or 4!" ); } // Create a colorspace object PdfObject* pIccObject = this->GetObject()->GetOwner()->CreateObject(); pIccObject->GetDictionary().AddKey( PdfName("Alternate"), ColorspaceToName( eAlternateColorSpace ) ); pIccObject->GetDictionary().AddKey( PdfName("N"), static_cast(lColorComponents) ); pIccObject->GetStream()->Set( pStream ); // Add the colorspace to our image PdfArray array; array.push_back( PdfName("ICCBased") ); array.push_back( pIccObject->Reference() ); this->GetObject()->GetDictionary().AddKey( PdfName("ColorSpace"), array ); } void PdfImage::SetImageSoftmask( const PdfImage* pSoftmask ) { GetObject()->GetDictionary().AddKey( "SMask", pSoftmask->GetObject()->Reference() ); } void PdfImage::SetImageData( unsigned int nWidth, unsigned int nHeight, unsigned int nBitsPerComponent, PdfInputStream* pStream ) { TVecFilters vecFlate; vecFlate.push_back( ePdfFilter_FlateDecode ); this->SetImageData( nWidth, nHeight, nBitsPerComponent, pStream, vecFlate ); } void PdfImage::SetImageData( unsigned int nWidth, unsigned int nHeight, unsigned int nBitsPerComponent, PdfInputStream* pStream, const TVecFilters & vecFilters ) { m_rRect.SetWidth( nWidth ); m_rRect.SetHeight( nHeight ); this->GetObject()->GetDictionary().AddKey( "Width", PdfVariant( static_cast(nWidth) ) ); this->GetObject()->GetDictionary().AddKey( "Height", PdfVariant( static_cast(nHeight) ) ); this->GetObject()->GetDictionary().AddKey( "BitsPerComponent", PdfVariant( static_cast(nBitsPerComponent) ) ); PdfVariant var; m_rRect.ToVariant( var ); this->GetObject()->GetDictionary().AddKey( "BBox", var ); this->GetObject()->GetStream()->Set( pStream, vecFilters ); } void PdfImage::SetImageDataRaw( unsigned int nWidth, unsigned int nHeight, unsigned int nBitsPerComponent, PdfInputStream* pStream ) { m_rRect.SetWidth( nWidth ); m_rRect.SetHeight( nHeight ); this->GetObject()->GetDictionary().AddKey( "Width", PdfVariant( static_cast(nWidth) ) ); this->GetObject()->GetDictionary().AddKey( "Height", PdfVariant( static_cast(nHeight) ) ); this->GetObject()->GetDictionary().AddKey( "BitsPerComponent", PdfVariant( static_cast(nBitsPerComponent) ) ); PdfVariant var; m_rRect.ToVariant( var ); this->GetObject()->GetDictionary().AddKey( "BBox", var ); this->GetObject()->GetStream()->SetRawData( pStream, -1 ); } void PdfImage::LoadFromFile( const char* pszFilename ) { if( pszFilename && strlen( pszFilename ) > 3 ) { const char* pszExtension = pszFilename + strlen( pszFilename ) - 3; #ifdef PODOFO_HAVE_TIFF_LIB if( PoDoFo::compat::strncasecmp( pszExtension, "tif", 3 ) == 0 || PoDoFo::compat::strncasecmp( pszExtension, "iff", 3 ) == 0 ) // "tiff" { LoadFromTiff( pszFilename ); return; } #endif #ifdef PODOFO_HAVE_JPEG_LIB if( PoDoFo::compat::strncasecmp( pszExtension, "jpg", 3 ) == 0 ) { LoadFromJpeg( pszFilename ); return; } #endif #ifdef PODOFO_HAVE_PNG_LIB if( PoDoFo::compat::strncasecmp( pszExtension, "png", 3 ) == 0 ) { LoadFromPng( pszFilename ); return; } #endif } PODOFO_RAISE_ERROR_INFO( ePdfError_UnsupportedImageFormat, pszFilename ); } #ifdef PODOFO_HAVE_JPEG_LIB extern "C" { static void JPegErrorExit(j_common_ptr cinfo) { #if 1 char buffer[JMSG_LENGTH_MAX]; /* Create the message */ (*cinfo->err->format_message) (cinfo, buffer); #endif jpeg_destroy(cinfo); PODOFO_RAISE_ERROR_INFO( ePdfError_UnsupportedImageFormat, buffer); } static void JPegErrorOutput(j_common_ptr, int) { } }; void PdfImage::LoadFromJpeg( const char* pszFilename ) { /* Constructor will throw exception */ PdfFileInputStream stream( pszFilename ); LoadFromJpegHandle( &stream ); } #ifdef _WIN32 void PdfImage::LoadFromJpeg( const wchar_t* pszFilename ) { PdfFileInputStream stream( pszFilename ); LoadFromJpegHandle( &stream ); } #endif // _WIN32 void PdfImage::LoadFromJpegHandle( PdfFileInputStream* pInStream ) { struct jpeg_decompress_struct cinfo; struct jpeg_error_mgr jerr; cinfo.err = jpeg_std_error(&jerr); jerr.error_exit = &JPegErrorExit; jerr.emit_message = &JPegErrorOutput; jpeg_create_decompress(&cinfo); #if !defined(PODOFO_JPEG_RUNTIME_COMPATIBLE) const long lSize = 1024; PdfRefCountedBuffer buffer( lSize ); fread( buffer.GetBuffer(), sizeof(char), lSize, hInfile ); // On WIN32, you can only pass a FILE Handle to DLLs which where compiled using the same // C library. This is usually not the case with LibJpeg on WIN32. // As a reason we use a memory buffer to determine the header information. // // If you are sure that libJpeg is compiled against the same C library as your application // you can removed this ifdef. jpeg_memory_src ( &cinfo, reinterpret_cast(buffer.GetBuffer()), buffer.GetSize() ); #else jpeg_stdio_src(&cinfo, pInStream->GetHandle()); #endif // PODOFO_JPEG_RUNTIME_COMPATIBLE if( jpeg_read_header(&cinfo, TRUE) <= 0 ) { (void) jpeg_destroy_decompress(&cinfo); PODOFO_RAISE_ERROR( ePdfError_UnexpectedEOF ); } jpeg_start_decompress(&cinfo); m_rRect.SetWidth( cinfo.output_width ); m_rRect.SetHeight( cinfo.output_height ); // I am not sure wether this switch is fully correct. // it should handle all cases though. // Index jpeg files might look strange as jpeglib+ // returns 1 for them. switch( cinfo.output_components ) { case 3: this->SetImageColorSpace( ePdfColorSpace_DeviceRGB ); break; case 4: { this->SetImageColorSpace( ePdfColorSpace_DeviceCMYK ); // The jpeg-doc ist not specific in this point, but cmyk's seem to be stored // in a inverted fashion. Fix by attaching a decode array PdfArray decode; decode.push_back( 1.0 ); decode.push_back( 0.0 ); decode.push_back( 1.0 ); decode.push_back( 0.0 ); decode.push_back( 1.0 ); decode.push_back( 0.0 ); decode.push_back( 1.0 ); decode.push_back( 0.0 ); this->GetObject()->GetDictionary().AddKey( PdfName("Decode"), decode ); } break; default: this->SetImageColorSpace( ePdfColorSpace_DeviceGray ); break; } // Set the filters key to DCTDecode this->GetObject()->GetDictionary().AddKey( PdfName::KeyFilter, PdfName( "DCTDecode" ) ); // Do not apply any filters as JPEG data is already DCT encoded. fseeko( pInStream->GetHandle(), 0L, SEEK_SET ); this->SetImageDataRaw( cinfo.output_width, cinfo.output_height, 8, pInStream ); (void) jpeg_destroy_decompress(&cinfo); } void PdfImage::LoadFromJpegData(const unsigned char* pData, pdf_long dwLen) { struct jpeg_decompress_struct cinfo; struct jpeg_error_mgr jerr; cinfo.err = jpeg_std_error(&jerr); jerr.error_exit = &JPegErrorExit; jerr.emit_message = &JPegErrorOutput; jpeg_create_decompress(&cinfo); jpeg_memory_src(&cinfo, pData, dwLen); if( jpeg_read_header(&cinfo, TRUE) <= 0 ) { (void) jpeg_destroy_decompress(&cinfo); PODOFO_RAISE_ERROR( ePdfError_UnexpectedEOF ); } jpeg_start_decompress(&cinfo); m_rRect.SetWidth( cinfo.output_width ); m_rRect.SetHeight( cinfo.output_height ); // I am not sure wether this switch is fully correct. // it should handle all cases though. // Index jpeg files might look strange as jpeglib+ // returns 1 for them. switch( cinfo.output_components ) { case 3: this->SetImageColorSpace( ePdfColorSpace_DeviceRGB ); break; case 4: { this->SetImageColorSpace( ePdfColorSpace_DeviceCMYK ); // The jpeg-doc ist not specific in this point, but cmyk's seem to be stored // in a inverted fashion. Fix by attaching a decode array PdfArray decode; decode.push_back( 1.0 ); decode.push_back( 0.0 ); decode.push_back( 1.0 ); decode.push_back( 0.0 ); decode.push_back( 1.0 ); decode.push_back( 0.0 ); decode.push_back( 1.0 ); decode.push_back( 0.0 ); this->GetObject()->GetDictionary().AddKey( PdfName("Decode"), decode ); } break; default: this->SetImageColorSpace( ePdfColorSpace_DeviceGray ); break; } // Set the filters key to DCTDecode this->GetObject()->GetDictionary().AddKey( PdfName::KeyFilter, PdfName( "DCTDecode" ) ); PdfMemoryInputStream fInpStream( (const char*)pData, (pdf_long) dwLen); this->SetImageDataRaw( cinfo.output_width, cinfo.output_height, 8, &fInpStream ); (void) jpeg_destroy_decompress(&cinfo); } #endif // PODOFO_HAVE_JPEG_LIB #ifdef PODOFO_HAVE_TIFF_LIB static void TIFFErrorWarningHandler(const char*, const char*, va_list) { } void PdfImage::LoadFromTiff( const char* pszFilename ) { TIFFSetErrorHandler(TIFFErrorWarningHandler); TIFFSetWarningHandler(TIFFErrorWarningHandler); if( !pszFilename ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } TIFF* hInfile = TIFFOpen(pszFilename, "rb"); if( !hInfile ) { PODOFO_RAISE_ERROR_INFO( ePdfError_FileNotFound, pszFilename ); } int32 row, width, height; uint16 samplesPerPixel, bitsPerSample; uint16* sampleInfo; uint16 extraSamples; uint16 planarConfig, photoMetric, orientation; int32 resolutionUnit; TIFFGetField(hInfile, TIFFTAG_IMAGEWIDTH, &width); TIFFGetField(hInfile, TIFFTAG_IMAGELENGTH, &height); TIFFGetFieldDefaulted(hInfile, TIFFTAG_BITSPERSAMPLE, &bitsPerSample); TIFFGetFieldDefaulted(hInfile, TIFFTAG_SAMPLESPERPIXEL, &samplesPerPixel); TIFFGetFieldDefaulted(hInfile, TIFFTAG_PLANARCONFIG, &planarConfig); TIFFGetFieldDefaulted(hInfile, TIFFTAG_PHOTOMETRIC, &photoMetric); TIFFGetFieldDefaulted(hInfile, TIFFTAG_EXTRASAMPLES, &extraSamples, &sampleInfo); TIFFGetFieldDefaulted(hInfile, TIFFTAG_ORIENTATION, &orientation); resolutionUnit = 0; float resX; float resY; TIFFGetFieldDefaulted(hInfile, TIFFTAG_XRESOLUTION, &resX); TIFFGetFieldDefaulted(hInfile, TIFFTAG_YRESOLUTION, &resY); TIFFGetFieldDefaulted(hInfile, TIFFTAG_RESOLUTIONUNIT, &resolutionUnit); int colorChannels = samplesPerPixel - extraSamples; int bitsPixel = bitsPerSample * samplesPerPixel; // TODO: implement special cases if( TIFFIsTiled(hInfile) ) { TIFFClose(hInfile); PODOFO_RAISE_ERROR( ePdfError_UnsupportedImageFormat ); } if ( planarConfig != PLANARCONFIG_CONTIG && colorChannels != 1 ) { TIFFClose(hInfile); PODOFO_RAISE_ERROR( ePdfError_UnsupportedImageFormat ); } if ( orientation != ORIENTATION_TOPLEFT ) { TIFFClose(hInfile); PODOFO_RAISE_ERROR( ePdfError_UnsupportedImageFormat ); } switch(photoMetric) { case PHOTOMETRIC_MINISBLACK: { if( bitsPixel == 1 ) { PdfArray decode; decode.insert( decode.end(), PdfVariant( static_cast(0) ) ); decode.insert( decode.end(), PdfVariant( static_cast(1) ) ); this->GetObject()->GetDictionary().AddKey( PdfName("Decode"), decode ); this->GetObject()->GetDictionary().AddKey( PdfName("ImageMask"), PdfVariant( true ) ); this->GetObject()->GetDictionary().RemoveKey( PdfName("ColorSpace") ); } else if ( bitsPixel == 8) SetImageColorSpace(ePdfColorSpace_DeviceGray); else { TIFFClose(hInfile); PODOFO_RAISE_ERROR( ePdfError_UnsupportedImageFormat ); } } break; case PHOTOMETRIC_MINISWHITE: { if( bitsPixel == 1 ) { PdfArray decode; decode.insert( decode.end(), PdfVariant( static_cast(1) ) ); decode.insert( decode.end(), PdfVariant( static_cast(0) ) ); this->GetObject()->GetDictionary().AddKey( PdfName("Decode"), decode ); this->GetObject()->GetDictionary().AddKey( PdfName("ImageMask"), PdfVariant( true ) ); this->GetObject()->GetDictionary().RemoveKey( PdfName("ColorSpace") ); } else if ( bitsPixel == 8) SetImageColorSpace(ePdfColorSpace_DeviceGray); else { TIFFClose(hInfile); PODOFO_RAISE_ERROR( ePdfError_UnsupportedImageFormat ); } } break; case PHOTOMETRIC_RGB: if ( bitsPixel != 24 ) { TIFFClose(hInfile); PODOFO_RAISE_ERROR( ePdfError_UnsupportedImageFormat ); } SetImageColorSpace(ePdfColorSpace_DeviceRGB); break; case PHOTOMETRIC_SEPARATED: if( bitsPixel != 32) { TIFFClose(hInfile); PODOFO_RAISE_ERROR( ePdfError_UnsupportedImageFormat ); } SetImageColorSpace(ePdfColorSpace_DeviceCMYK); break; case PHOTOMETRIC_PALETTE: { int numColors = (1 << bitsPixel); PdfArray decode; decode.insert( decode.end(), PdfVariant( static_cast(0) ) ); decode.insert( decode.end(), PdfVariant( static_cast(numColors-1) ) ); this->GetObject()->GetDictionary().AddKey( PdfName("Decode"), decode ); uint16 * rgbRed; uint16 * rgbGreen; uint16 * rgbBlue; TIFFGetField(hInfile, TIFFTAG_COLORMAP, &rgbRed, &rgbGreen, &rgbBlue); char *datap = new char[numColors*3]; for ( int clr = 0; clr < numColors; clr++ ) { datap[3*clr+0] = rgbRed[clr]/257; datap[3*clr+1] = rgbGreen[clr]/257; datap[3*clr+2] = rgbBlue[clr]/257; } PdfMemoryInputStream stream( datap, numColors*3 ); // Create a colorspace object PdfObject* pIdxObject = this->GetObject()->GetOwner()->CreateObject(); pIdxObject->GetStream()->Set( &stream ); // Add the colorspace to our image PdfArray array; array.push_back( PdfName("Indexed") ); array.push_back( PdfName("DeviceRGB") ); array.push_back( static_cast(numColors-1) ); array.push_back( pIdxObject->Reference() ); this->GetObject()->GetDictionary().AddKey( PdfName("ColorSpace"), array ); delete[] datap; } break; default: TIFFClose(hInfile); PODOFO_RAISE_ERROR( ePdfError_UnsupportedImageFormat ); break; } int32 scanlineSize = TIFFScanlineSize(hInfile); long bufferSize = scanlineSize * height; char *buffer = new char[bufferSize]; if( !buffer ) { TIFFClose(hInfile); PODOFO_RAISE_ERROR( ePdfError_OutOfMemory ); } for(row = 0; row < height; row++) { if(TIFFReadScanline(hInfile, &buffer[row * scanlineSize], row) == (-1)) { TIFFClose(hInfile); PODOFO_RAISE_ERROR( ePdfError_UnsupportedImageFormat ); } } PdfMemoryInputStream stream(buffer, bufferSize); SetImageData(static_cast(width), static_cast(height), static_cast(bitsPerSample), &stream); delete[] buffer; TIFFClose(hInfile); } #endif // PODOFO_HAVE_TIFF_LIB #ifdef PODOFO_HAVE_PNG_LIB void PdfImage::LoadFromPng( const char* pszFilename ) { if( !pszFilename ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } FILE* hFile = fopen(pszFilename, "rb"); if( !hFile ) { PODOFO_RAISE_ERROR_INFO( ePdfError_FileNotFound, pszFilename ); } png_byte header[8]; fread(header, 1, 8, hFile); if( png_sig_cmp(header, 0, 8) ) { fclose( hFile ); PODOFO_RAISE_ERROR_INFO( ePdfError_UnsupportedImageFormat, "The file could not be recognized as a PNG file." ); } png_structp pPng = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if( !pPng ) { fclose( hFile ); PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } png_infop pInfo = png_create_info_struct(pPng); if( !pInfo ) { png_destroy_read_struct(&pPng, (png_infopp)NULL, (png_infopp)NULL); fclose( hFile ); PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } if( setjmp(png_jmpbuf(pPng)) ) { png_destroy_read_struct(&pPng, &pInfo, (png_infopp)NULL); fclose( hFile ); PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } png_init_io(pPng, hFile); png_set_sig_bytes(pPng, 8); png_read_info(pPng, pInfo); // Begin png_uint_32 width; png_uint_32 height; int depth; int color_type; int interlace; png_get_IHDR (pPng, pInfo, &width, &height, &depth, &color_type, &interlace, NULL, NULL); /* convert palette/gray image to rgb */ if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(pPng); if (color_type & PNG_COLOR_MASK_ALPHA) png_set_strip_alpha(pPng); #if 0 /* expand gray bit depth if needed */ if (color_type == PNG_COLOR_TYPE_GRAY) { #if PNG_LIBPNG_VER >= 10209 png_set_expand_gray_1_2_4_to_8 (pPng); #else png_set_gray_1_2_4_to_8 (pPng); #endif } #endif /* transform transparency to alpha */ if (png_get_valid (pPng, pInfo, PNG_INFO_tRNS)) png_set_tRNS_to_alpha (pPng); if (depth == 16) png_set_strip_16(pPng); if (depth < 8) png_set_packing(pPng); #if 0 /* convert grayscale to RGB */ if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { png_set_gray_to_rgb (pPng); } #endif if (interlace != PNG_INTERLACE_NONE) png_set_interlace_handling(pPng); //png_set_filler (pPng, 0xff, PNG_FILLER_AFTER); /* recheck header after setting EXPAND options */ png_read_update_info(pPng, pInfo); png_get_IHDR (pPng, pInfo, &width, &height, &depth, &color_type, &interlace, NULL, NULL); // End // // Read the file if( setjmp(png_jmpbuf(pPng)) ) { png_destroy_read_struct(&pPng, &pInfo, (png_infopp)NULL); fclose( hFile ); PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } long lLen = static_cast(png_get_rowbytes(pPng, pInfo) * height); char* pBuffer = static_cast(malloc(sizeof(char) * lLen)); png_bytepp pRows = static_cast(malloc(sizeof(png_bytep)*height)); for(unsigned int y=0; y(pBuffer + (y * png_get_rowbytes(pPng, pInfo))); } png_read_image(pPng, pRows); fclose(hFile); m_rRect.SetWidth( width ); m_rRect.SetHeight( height ); switch( png_get_channels( pPng, pInfo ) ) { case 3: this->SetImageColorSpace( ePdfColorSpace_DeviceRGB ); break; case 4: { this->SetImageColorSpace( ePdfColorSpace_DeviceCMYK ); // The jpeg-doc ist not specific in this point, but cmyk's seem to be stored // in a inverted fashion. Fix by attaching a decode array PdfArray decode; decode.push_back( 1.0 ); decode.push_back( 0.0 ); decode.push_back( 1.0 ); decode.push_back( 0.0 ); decode.push_back( 1.0 ); decode.push_back( 0.0 ); decode.push_back( 1.0 ); decode.push_back( 0.0 ); this->GetObject()->GetDictionary().AddKey( PdfName("Decode"), decode ); } break; default: this->SetImageColorSpace( ePdfColorSpace_DeviceGray ); break; } // Set the image data and flate compress it PdfMemoryInputStream stream( pBuffer, lLen ); this->SetImageData( width, height, depth, &stream ); free(pBuffer); free(pRows); png_destroy_read_struct(&pPng, &pInfo, (png_infopp)NULL); } #endif // PODOFO_HAVE_PNG_LIB PdfName PdfImage::ColorspaceToName( EPdfColorSpace eColorSpace ) { return PdfColor::GetNameForColorSpace( eColorSpace ).GetName(); } void PdfImage::SetImageChromaKeyMask(pdf_int64 r, pdf_int64 g, pdf_int64 b, pdf_int64 threshold) { PdfArray array; array.push_back(r - threshold); array.push_back(r + threshold); array.push_back(g - threshold); array.push_back(g + threshold); array.push_back(b - threshold); array.push_back(b + threshold); this->GetObject()->GetDictionary().AddKey( "Mask", array); } void PdfImage::SetInterpolate(bool bValue) { this->GetObject()->GetDictionary().AddKey( "Interpolate", PdfVariant(bValue)); } }; podofo-0.9.3/src/doc/PdfNamesTree.cpp0000664000175000017500000004316612344436402017252 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2006 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfNamesTree.h" #include "base/PdfDefinesPrivate.h" #include "base/PdfArray.h" #include "base/PdfDictionary.h" #include "base/PdfOutputDevice.h" #include namespace PoDoFo { #define BALANCE_TREE_MAX 65 /* #define BALANCE_TREE_MAX 9 */ class PdfNameTreeNode { public: PdfNameTreeNode( PdfNameTreeNode* pParent, PdfObject* pObject ) : m_pParent( pParent ), m_pObject( pObject ) { m_bHasKids = m_pObject->GetDictionary().HasKey("Kids"); } bool AddValue( const PdfString & key, const PdfObject & value ); void SetLimits(); inline PdfObject* GetObject() { return m_pObject; } private: bool Rebalance(); private: PdfNameTreeNode* m_pParent; PdfObject* m_pObject; bool m_bHasKids; }; bool PdfNameTreeNode::AddValue( const PdfString & key, const PdfObject & rValue ) { if( m_bHasKids ) { const PdfArray & kids = this->GetObject()->GetDictionary().GetKey("Kids")->GetArray(); PdfArray::const_iterator it = kids.begin(); PdfObject* pChild = NULL; EPdfNameLimits eLimits = ePdfNameLimits_Before; // RG: TODO Compiler complains that this variable should be initialised while( it != kids.end() ) { pChild = this->GetObject()->GetOwner()->GetObject( (*it).GetReference() ); if( !pChild ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } eLimits = PdfNamesTree::CheckLimits( pChild, key ); if( (eLimits == ePdfNameLimits_Before) || (eLimits == ePdfNameLimits_Inside) ) { break; } ++it; } if( it == kids.end() ) { // not added, so add to last child pChild = this->GetObject()->GetOwner()->GetObject( kids.back().GetReference() ); if( !pChild ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } eLimits = ePdfNameLimits_After; } PdfNameTreeNode child( this, pChild ); if( child.AddValue( key, rValue ) ) { // if a child insert the key in a way that the limits // are changed, we have to change our limits as well! // our parent has to change his parents too! if( eLimits != ePdfNameLimits_Inside ) this->SetLimits(); this->Rebalance(); return true; } else return false; } else { bool bRebalance = false; PdfArray limits; if( this->GetObject()->GetDictionary().HasKey( "Names" ) ) { PdfArray& array = this->GetObject()->GetDictionary().GetKey("Names")->GetArray(); PdfArray::iterator it = array.begin(); while( it != array.end() ) { if( (*it).GetString() == key ) { // no need to write the key as it is anyways the same ++it; // write the value *it = rValue; break; } else if( (*it).GetString() > key ) { it = array.insert( it, rValue ); // array.insert invalidates the iterator it = array.insert( it, key ); break; } it += 2; } if( it == array.end() ) { array.push_back( key ); array.push_back( rValue ); } limits.push_back( (*array.begin()) ); limits.push_back( (*(array.end()-2)) ); bRebalance = true; } else { // we create a completely new node PdfArray array; array.push_back( key ); array.push_back( rValue ); limits.push_back( key ); limits.push_back( key ); // create a child object PdfObject* pChild = this->GetObject()->GetOwner()->CreateObject(); pChild->GetDictionary().AddKey( "Names", array ); pChild->GetDictionary().AddKey( "Limits", limits ); PdfArray kids( pChild->Reference() ); this->GetObject()->GetDictionary().AddKey( "Kids", kids ); m_bHasKids = true; } if( m_pParent ) { // Root node is not allowed to have a limits key! this->GetObject()->GetDictionary().AddKey( "Limits", limits ); } if( bRebalance ) this->Rebalance(); return true; } } void PdfNameTreeNode::SetLimits() { PdfArray limits; if( m_bHasKids ) { if( this->GetObject()->GetDictionary().HasKey( PdfName("Kids") ) && this->GetObject()->GetDictionary().GetKey( PdfName("Kids") )->IsArray() ) { const PdfReference & rRefFirst = (*this->GetObject()->GetDictionary().GetKey("Kids")->GetArray().begin()).GetReference(); PdfObject* pChild = this->GetObject()->GetOwner()->GetObject( rRefFirst ); if( pChild && pChild->GetDictionary().HasKey( PdfName("Limits") ) && pChild->GetDictionary().GetKey( PdfName("Limits") )->IsArray() ) limits.push_back( *(pChild->GetDictionary().GetKey("Limits")->GetArray().begin()) ); const PdfReference & rRefLast = this->GetObject()->GetDictionary().GetKey("Kids")->GetArray().back().GetReference(); pChild = this->GetObject()->GetOwner()->GetObject( rRefLast ); if( pChild && pChild->GetDictionary().HasKey( PdfName("Limits") ) && pChild->GetDictionary().GetKey( PdfName("Limits") )->IsArray() ) limits.push_back( pChild->GetDictionary().GetKey("Limits")->GetArray().back() ); } else PdfError::LogMessage( eLogSeverity_Error, "Object %i %si does not have Kids array.", this->GetObject()->Reference().ObjectNumber(), this->GetObject()->Reference().GenerationNumber() ); } else // has "Names" { if( this->GetObject()->GetDictionary().HasKey( PdfName("Names") ) && this->GetObject()->GetDictionary().GetKey( PdfName("Names") )->IsArray() ) { limits.push_back( (*this->GetObject()->GetDictionary().GetKey("Names")->GetArray().begin()) ); limits.push_back( (*(this->GetObject()->GetDictionary().GetKey("Names")->GetArray().end()-2)) ); } else PdfError::LogMessage( eLogSeverity_Error, "Object %i %si does not have Names array.", this->GetObject()->Reference().ObjectNumber(), this->GetObject()->Reference().GenerationNumber() ); } if( m_pParent ) { // Root node is not allowed to have a limits key! this->GetObject()->GetDictionary().AddKey("Limits", limits ); } } bool PdfNameTreeNode::Rebalance() { PdfArray* pArray = m_bHasKids ? &(this->GetObject()->GetDictionary().GetKey("Kids")->GetArray()) : &(this->GetObject()->GetDictionary().GetKey("Names")->GetArray()); const PdfName& key = m_bHasKids ? PdfName("Kids") : PdfName("Names"); const unsigned int nLength = m_bHasKids ? BALANCE_TREE_MAX : BALANCE_TREE_MAX * 2; if( !pArray ) return false; if( pArray->size() > nLength ) { PdfArray first; PdfArray second; PdfArray kids; first.insert( first.end(), pArray->begin(), pArray->begin()+(nLength/2)+1 ); second.insert( second.end(), pArray->begin()+(nLength/2)+1, pArray->end() ); PdfObject* pChild1; PdfObject* pChild2 = this->GetObject()->GetOwner()->CreateObject(); if( !m_pParent ) { m_bHasKids = true; pChild1 = this->GetObject()->GetOwner()->CreateObject(); this->GetObject()->GetDictionary().RemoveKey( "Names" ); } else { pChild1 = this->GetObject(); kids = m_pParent->GetObject()->GetDictionary().GetKey("Kids")->GetArray(); } pChild1->GetDictionary().AddKey( key, first ); pChild2->GetDictionary().AddKey( key, second ); PdfArray::iterator it = kids.begin(); while( it != kids.end() ) { if( (*it).GetReference() == pChild1->Reference() ) { ++it; it = kids.insert( it, pChild2->Reference() ); break; } ++it; } if( it == kids.end() ) { kids.push_back( pChild1->Reference() ); kids.push_back( pChild2->Reference() ); } if( m_pParent ) m_pParent->GetObject()->GetDictionary().AddKey( "Kids", kids ); else this->GetObject()->GetDictionary().AddKey( "Kids", kids ); // Important is to the the limits // of the children first, // because SetLimits( pParent ) // depends on the /Limits key of all its children! PdfNameTreeNode( NULL, pChild1 ).SetLimits(); PdfNameTreeNode( NULL, pChild2 ).SetLimits(); // limits do only change if splitting name arrays if( m_bHasKids ) this->SetLimits(); else if( m_pParent ) m_pParent->SetLimits(); return true; } return false; } /////////////////////////////////////////////////////////////////////// /* We use NULL for the PdfElement name, since the NamesTree dict does NOT have a /Type key! */ PdfNamesTree::PdfNamesTree( PdfVecObjects* pParent ) : PdfElement( NULL, pParent ), m_pCatalog( NULL ) { } PdfNamesTree::PdfNamesTree( PdfObject* pObject, PdfObject* pCatalog ) : PdfElement( NULL, pObject ), m_pCatalog( pCatalog ) { } void PdfNamesTree::AddValue( const PdfName & tree, const PdfString & key, const PdfObject & rValue ) { PdfNameTreeNode root( NULL, this->GetRootNode( tree, true ) ); if( !root.AddValue( key, rValue ) ) { PODOFO_RAISE_ERROR( ePdfError_InternalLogic ); } } PdfObject* PdfNamesTree::GetValue( const PdfName & tree, const PdfString & key ) const { PdfObject* pObject = this->GetRootNode( tree ); PdfObject* pResult = NULL; if( pObject ) { pResult = this->GetKeyValue( pObject, key ); if( pResult && pResult->IsReference() ) pResult = this->GetObject()->GetOwner()->GetObject( pResult->GetReference() ); } return pResult; } PdfObject* PdfNamesTree::GetKeyValue( PdfObject* pObj, const PdfString & key ) const { if( PdfNamesTree::CheckLimits( pObj, key ) != ePdfNameLimits_Inside ) return NULL; if( pObj->GetDictionary().HasKey("Kids") ) { const PdfArray & kids = pObj->GetDictionary().GetKey("Kids")->GetArray(); PdfArray::const_iterator it = kids.begin(); while( it != kids.end() ) { PdfObject* pChild = this->GetObject()->GetOwner()->GetObject( (*it).GetReference() ); if( pChild ) { PdfObject* pResult = GetKeyValue( pChild, key ); if( pResult ) // If recursive call returns NULL, // continue with the next element // in the kids array. return pResult; } else PdfError::LogMessage( eLogSeverity_Debug, "Object %lu %lu is child of nametree but was not found!", (*it).GetReference().ObjectNumber(), (*it).GetReference().GenerationNumber() ); ++it; } } else { const PdfArray & names = pObj->GetDictionary().GetKey("Names")->GetArray(); PdfArray::const_iterator it = names.begin(); // a names array is a set of PdfString/PdfObject pairs // so we loop in sets of two - getting each pair while( it != names.end() ) { if( (*it).GetString() == key ) { ++it; return this->GetObject()->GetOwner()->GetObject( (*it).GetReference() ); } it += 2; } } return NULL; } PdfObject* PdfNamesTree::GetRootNode( const PdfName & name, bool bCreate ) const { PdfObject* pObj = this->GetObject()->GetIndirectKey( name ); if( !pObj && bCreate ) { pObj = this->GetObject()->GetOwner()->CreateObject(); this->GetNonConstObject()->GetDictionary().AddKey( name, pObj->Reference() ); } return pObj; } bool PdfNamesTree::HasValue( const PdfName & tree, const PdfString & key ) const { return ( this->GetValue( tree, key ) != NULL ); } EPdfNameLimits PdfNamesTree::CheckLimits( const PdfObject* pObj, const PdfString & key ) { if( pObj->GetDictionary().HasKey("Limits") ) { const PdfArray & limits = pObj->GetDictionary().GetKey("Limits")->GetArray(); if( limits[0].GetString() > key ) return ePdfNameLimits_Before; if( limits[1].GetString() < key ) return ePdfNameLimits_After; } else { PdfError::LogMessage( eLogSeverity_Debug, "Name tree object %lu %lu does not have a limits key!", pObj->Reference().ObjectNumber(), pObj->Reference().GenerationNumber() ); } return ePdfNameLimits_Inside; } void PdfNamesTree::ToDictionary( const PdfName & tree, PdfDictionary& rDict ) { rDict.Clear(); PdfObject* pObj = this->GetRootNode( tree ); if( pObj ) AddToDictionary( pObj, rDict ); } void PdfNamesTree::AddToDictionary( PdfObject* pObj, PdfDictionary & rDict ) { if( pObj->GetDictionary().HasKey("Kids") ) { const PdfArray & kids = pObj->GetDictionary().GetKey("Kids")->GetArray(); PdfArray::const_iterator it = kids.begin(); while( it != kids.end() ) { PdfObject* pChild = this->GetObject()->GetOwner()->GetObject( (*it).GetReference() ); if( pChild ) this->AddToDictionary( pChild, rDict ); else PdfError::LogMessage( eLogSeverity_Debug, "Object %lu %lu is child of nametree but was not found!\n", (*it).GetReference().ObjectNumber(), (*it).GetReference().GenerationNumber() ); ++it; } } else if( pObj->GetDictionary().HasKey("Names") ) { const PdfArray & names = pObj->GetDictionary().GetKey("Names")->GetArray(); PdfArray::const_iterator it = names.begin(); // a names array is a set of PdfString/PdfObject pairs // so we loop in sets of two - getting each pair while( it != names.end() ) { // convert all strings into names PdfName name( (*it).GetString().GetString() ); ++it; rDict.AddKey( name, *(it) ); ++it; } } } }; podofo-0.9.3/src/doc/PdfStreamedDocument.cpp0000664000175000017500000001005012344436402020614 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2007 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfStreamedDocument.h" #include "base/PdfDefinesPrivate.h" namespace PoDoFo { PdfStreamedDocument::PdfStreamedDocument( PdfOutputDevice* pDevice, EPdfVersion eVersion, PdfEncrypt* pEncrypt, EPdfWriteMode eWriteMode ) : m_pWriter( NULL ), m_pDevice( NULL ), m_pEncrypt( pEncrypt ), m_bOwnDevice( false ) { Init( pDevice, eVersion, pEncrypt, eWriteMode ); } PdfStreamedDocument::PdfStreamedDocument( const char* pszFilename, EPdfVersion eVersion, PdfEncrypt* pEncrypt, EPdfWriteMode eWriteMode ) : m_pWriter( NULL ), m_pEncrypt( pEncrypt ), m_bOwnDevice( true ) { m_pDevice = new PdfOutputDevice( pszFilename ); Init( m_pDevice, eVersion, pEncrypt, eWriteMode ); } #ifdef _WIN32 PdfStreamedDocument::PdfStreamedDocument( const wchar_t* pszFilename, EPdfVersion eVersion, PdfEncrypt* pEncrypt, EPdfWriteMode eWriteMode ) : m_pWriter( NULL ), m_pEncrypt( pEncrypt ), m_bOwnDevice( true ) { m_pDevice = new PdfOutputDevice( pszFilename ); Init( m_pDevice, eVersion, pEncrypt, eWriteMode ); } #endif // _WIN32 PdfStreamedDocument::~PdfStreamedDocument() { delete m_pWriter; if( m_bOwnDevice ) delete m_pDevice; } void PdfStreamedDocument::Init( PdfOutputDevice* pDevice, EPdfVersion eVersion, PdfEncrypt* pEncrypt, EPdfWriteMode eWriteMode ) { m_pWriter = new PdfImmediateWriter( pDevice, this->GetObjects(), this->GetTrailer(), eVersion, pEncrypt, eWriteMode ); } void PdfStreamedDocument::Close() { // TODO: Check if this works correctly // makes sure pending subset-fonts are embedded m_fontCache.EmbedSubsetFonts(); this->GetObjects()->Finish(); } }; podofo-0.9.3/src/doc/PdfFont.cpp0000664000175000017500000001504712347316204016272 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2005 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfFont.h" #include "base/PdfDefinesPrivate.h" #include "base/PdfArray.h" #include "base/PdfEncoding.h" #include "base/PdfInputStream.h" #include "base/PdfStream.h" #include "base/PdfWriter.h" #include "base/PdfLocale.h" #include "PdfFontMetrics.h" #include "PdfPage.h" #include #include #include using namespace std; namespace PoDoFo { PdfFont::PdfFont( PdfFontMetrics* pMetrics, const PdfEncoding* const pEncoding, PdfVecObjects* pParent ) : PdfElement( "Font", pParent ), m_pEncoding( pEncoding ), m_pMetrics( pMetrics ), m_bBold( false ), m_bItalic( false ), m_isBase14( false ), m_bIsSubsetting( false ) { this->InitVars(); } PdfFont::PdfFont( PdfFontMetrics* pMetrics, const PdfEncoding* const pEncoding, PdfObject* pObject ) : PdfElement( "Font", pObject ), m_pEncoding( pEncoding ), m_pMetrics( pMetrics ), m_bBold( false ), m_bItalic( false ), m_isBase14( false ), m_bIsSubsetting( false ) { this->InitVars(); // Implementation note: the identifier is always // Prefix+ObjectNo. Prefix is /Ft for fonts. ostringstream out; PdfLocaleImbue(out); out << "PoDoFoFt" << this->GetObject()->Reference().ObjectNumber(); m_Identifier = PdfName( out.str().c_str() ); } PdfFont::~PdfFont() { if (m_pMetrics) delete m_pMetrics; if( m_pEncoding && m_pEncoding->IsAutoDelete() ) delete m_pEncoding; } void PdfFont::InitVars() { ostringstream out; PdfLocaleImbue(out); m_pMetrics->SetFontSize( 12.0 ); m_pMetrics->SetFontScale( 100.0 ); m_pMetrics->SetFontCharSpace( 0.0 ); // Peter Petrov 24 Spetember 2008 m_bWasEmbedded = false; m_bUnderlined = false; m_bStrikedOut = false; // Implementation note: the identifier is always // Prefix+ObjectNo. Prefix is /Ft for fonts. out << "Ft" << this->GetObject()->Reference().ObjectNumber(); m_Identifier = PdfName( out.str().c_str() ); // replace all spaces in the base font name as suggested in // the PDF reference section 5.5.2# int curPos = 0; std::string sTmp = m_pMetrics->GetFontname(); const char* pszPrefix = m_pMetrics->GetSubsetFontnamePrefix(); if( pszPrefix ) { std::string sPrefix = pszPrefix; sTmp = sPrefix + sTmp; } for(unsigned int i = 0; i < sTmp.size(); i++) { if(sTmp[i] != ' ') sTmp[curPos++] = sTmp[i]; } sTmp.resize(curPos); m_BaseFont = PdfName( sTmp.c_str() ); } inline char ToHex( const char byte ) { static const char* s_pszHex = "0123456789ABCDEF"; return s_pszHex[byte % 16]; } void PdfFont::WriteStringToStream( const PdfString & rsString, PdfStream* pStream ) { if( !m_pEncoding ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } PdfRefCountedBuffer buffer = m_pEncoding->ConvertToEncoding( rsString, this ); pdf_long lLen = 0; char* pBuffer = NULL; std::auto_ptr pFilter = PdfFilterFactory::Create( ePdfFilter_ASCIIHexDecode ); pFilter->Encode( buffer.GetBuffer(), buffer.GetSize(), &pBuffer, &lLen ); pStream->Append( "<", 1 ); pStream->Append( pBuffer, lLen ); pStream->Append( ">", 1 ); free( pBuffer ); } // Peter Petrov 5 January 2009 void PdfFont::EmbedFont() { if (!m_bWasEmbedded) { // Now we embed the font // Now we set the flag m_bWasEmbedded = true; } } void PdfFont::EmbedSubsetFont() { //virtual function is only implemented in derived class PODOFO_RAISE_ERROR_INFO( ePdfError_NotImplemented, "Subsetting not implemented for this font type." ); } void PdfFont::AddUsedSubsettingGlyphs( const PdfString & , long ) { //virtual function is only implemented in derived class PODOFO_RAISE_ERROR_INFO( ePdfError_NotImplemented, "Subsetting not implemented for this font type." ); } void PdfFont::AddUsedGlyphname( const char * ) { //virtual function is only implemented in derived class PODOFO_RAISE_ERROR_INFO( ePdfError_NotImplemented, "Subsetting not implemented for this font type." ); } void PdfFont::SetBold( bool bBold ) { m_bBold = bBold; } void PdfFont::SetItalic( bool bItalic ) { m_bItalic = bItalic; } }; podofo-0.9.3/src/doc/PdfHintStream.cpp0000664000175000017500000003240712344436402017441 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2006 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfHintStream.h" #include "base/PdfDefinesPrivate.h" #include "base/PdfData.h" #include "base/PdfDictionary.h" #include "base/PdfStream.h" #include "base/PdfVariant.h" #include "base/PdfVecObjects.h" #include "PdfPage.h" #include "PdfPagesTree.h" // See PdfWriter.cpp #define LINEARIZATION_PADDING "1234567890" using namespace PoDoFo; namespace { struct TPageEntrySharedObjectInfo { pdf_uint16 nIndex; pdf_uint16 nNumerator; }; typedef std::vector TVecPageEntrySharedObjectInfo; typedef TVecPageEntrySharedObjectInfo::iterator TIVecPageEntrySharedObjectInfo; typedef TVecPageEntrySharedObjectInfo::const_iterator TCIVecPageEntrySharedObjectInfo; class PdfPageOffsetEntry { public: PdfPageOffsetEntry() : nObjectsPerPage( 0 ), nPageLength( 0 ), nSharedObjects( 0 ), nContentsOffset( 0 ), nContentsLength( 0 ) { vecSharedObjects.resize( 0 ); } pdf_uint16 nObjectsPerPage; pdf_uint16 nPageLength; pdf_uint16 nSharedObjects; // item4 and item5: TVecPageEntrySharedObjectInfo vecSharedObjects; pdf_uint16 nContentsOffset; pdf_uint16 nContentsLength; public: void Write( PoDoFo::NonPublic::PdfHintStream* pHint ); }; void PdfPageOffsetEntry::Write( PoDoFo::NonPublic::PdfHintStream* pHint ) { TCIVecPageEntrySharedObjectInfo it; pHint->WriteUInt16( nObjectsPerPage ); pHint->WriteUInt16( nPageLength ); pHint->WriteUInt16( nSharedObjects ); it = vecSharedObjects.begin(); while( it != vecSharedObjects.end() ) { pHint->WriteUInt16( (*it).nIndex ); ++it; } it = vecSharedObjects.begin(); while( it != vecSharedObjects.end() ) { pHint->WriteUInt16( (*it).nNumerator ); ++it; } pHint->WriteUInt16( nContentsOffset ); pHint->WriteUInt16( nContentsLength ); } class PdfPageOffsetHeader { public: PdfPageOffsetHeader() : nLeastNumberOfObjects( 0 ), nFirstPageObject( 0 ), nBitsPageObject( 0 ), nLeastPageLength( 0 ), nBitsPageLength( 0 ), nOffsetContentStream( 0 ), nBitsContentStream( 0 ), nLeastContentStreamLength( 0 ), nBitsLeastContentStreamLength( 0 ), nBitsNumSharedObjects( 0 ), nBitsGreatestSharedObject( 0 ), nItem12( 0 ), nItem13( 0 ) { } // item1: The least number of objects in a page including the page itself pdf_uint32 nLeastNumberOfObjects; // item2: The location of the first pages page object pdf_uint32 nFirstPageObject; // (*pXRef)[0].vecOffsets[ m_pPagesTree->GetPage( 0 )->Object()->Reference().ObjectNumber() ].lOffset; // item3: The number of bits needed to represent the difference between the // greatest and least number of objects in a page pdf_uint16 nBitsPageObject; // (pdf_uint16)ceil( logb( (double)(max-least) ) ); // item4: The least length of a page in bytes pdf_uint32 nLeastPageLength; // item5: The number of bits needed to represent the greatest difference // between the greatest and the least length of a page in bytes pdf_uint16 nBitsPageLength; // item6: The least offset of the start of a content stream, relative // to the beginning of a file. // --> Always set to 0 by acrobat pdf_uint32 nOffsetContentStream; // item7: The number of bits needed to represent the greatest difference // between the greatest and the least offset of a the start of a content // stream relative to the beginning of a file // --> Always set to 0 by acrobat pdf_uint16 nBitsContentStream; // item8: The least content stream length pdf_uint32 nLeastContentStreamLength; // item9: The number of bits needed to represent the greatest difference // between the greatest and the least length of a content stream pdf_uint16 nBitsLeastContentStreamLength; // item10: The number of bits needed to represent the greatest number // of shared object references. pdf_uint16 nBitsNumSharedObjects; // item11: The number of bits needed to represent the nummerically // greatest shared object identifyer used by pages pdf_uint16 nBitsGreatestSharedObject; // item12: pdf_uint16 nItem12; // item13: pdf_uint16 nItem13; void Write( PoDoFo::NonPublic::PdfHintStream* pHint ) { pHint->WriteUInt32( nLeastNumberOfObjects ); pHint->WriteUInt32( nFirstPageObject ); pHint->WriteUInt16( nBitsPageObject ); pHint->WriteUInt32( nLeastPageLength ); pHint->WriteUInt16( nBitsPageLength ); pHint->WriteUInt32( nOffsetContentStream ); pHint->WriteUInt16( nBitsContentStream ); pHint->WriteUInt32( nLeastContentStreamLength ); pHint->WriteUInt16( nBitsLeastContentStreamLength ); pHint->WriteUInt16( nBitsNumSharedObjects ); pHint->WriteUInt16( nBitsGreatestSharedObject ); pHint->WriteUInt16( nItem12 ); pHint->WriteUInt16( nItem13 ); } }; class PdfSharedObjectHeader { public: PdfSharedObjectHeader() : nFirstObjectNumber( 0 ), nFirstObjectLocation( 0 ), nNumSharedObjectsFirstPage( 0 ), nNumSharedObjects( 0 ), nNumBits( 0 ), nLeastLength( 0 ), nNumBitsLengthDifference( 0 ) { } pdf_uint32 nFirstObjectNumber; pdf_uint32 nFirstObjectLocation; pdf_uint32 nNumSharedObjectsFirstPage; pdf_uint32 nNumSharedObjects; // i.e. including nNumSharedObjectsFirstPage pdf_uint16 nNumBits; pdf_uint32 nLeastLength; pdf_uint16 nNumBitsLengthDifference; public: void Write( PoDoFo::NonPublic::PdfHintStream* pHint ) { pHint->WriteUInt32( nFirstObjectNumber ); pHint->WriteUInt32( nFirstObjectLocation ); pHint->WriteUInt32( nNumSharedObjectsFirstPage ); pHint->WriteUInt32( nNumSharedObjects ); pHint->WriteUInt16( nNumBits ); pHint->WriteUInt32( nLeastLength ); pHint->WriteUInt16( nNumBitsLengthDifference ); } }; }; // end anon namespace namespace PoDoFo { namespace NonPublic { PdfHintStream::PdfHintStream( PdfVecObjects* pParent, PdfPagesTree* pPagesTree ) : PdfElement( NULL, pParent ), m_pPagesTree( pPagesTree ) { // This is overwritten later with valid data! PdfVariant place_holder( PdfData( LINEARIZATION_PADDING ) ); this->GetObject()->GetDictionary().AddKey( "S", place_holder ); // shared object hint table } PdfHintStream::~PdfHintStream() { } /* void PdfHintStream::Create( TVecXRefTable* pXRef ) { this->CreatePageHintTable( pXRef ); this->CreateSharedObjectHintTable(); } void PdfHintStream::CreatePageHintTable( TVecXRefTable* pXRef ) { TPdfReferenceList lstPages; TCIPdfReferenceList it; int i; int nPageCount = m_pPagesTree->GetTotalNumberOfPages(); PdfPageOffsetHeader header; #if 1 // this will init/construct each of the objects in the vector // AND it compiles on all platforms - where the below code // isn't 100% valid for all C++ compilers std::vector< PdfPageOffsetEntry > vecPages( nPageCount ); #else // use an array instead of an vector, // to make sure the constructors are called, // which they are apparently not when using vector.resize PdfPageOffsetEntry vecPages[nPageCount]; #endif pdf_uint32 max; pdf_uint32 least = 0; pdf_uint32 maxNumberOfObjects = 0; pdf_uint32 maxPageLength = 0; pdf_uint32 value; PdfReference maxRef; for( i=0;iGetObject()->GetParent()->GetObjectDependencies( m_pPagesTree->GetPage( i )->GetObject(), &lstPages ); vecPages[i].nObjectsPerPage = lstPages.size(); if( !header.nLeastNumberOfObjects || header.nLeastNumberOfObjects > lstPages.size() ) header.nLeastNumberOfObjects = lstPages.size(); if( !maxNumberOfObjects || maxNumberOfObjects < lstPages.size() ) maxNumberOfObjects = lstPages.size(); it = lstPages.begin(); least = 0; max = 0; while( it != lstPages.end() ) { value = (*pXRef)[0].vecOffsets[ (*it).ObjectNumber() ].lOffset; if( !least || least > value ) least = value; if( !max || max < value ) { max = value; maxRef = *it; } ++it; } max += this->GetObject()->GetParent()->GetObject( maxRef )->GetObjectLength(); vecPages[i].nPageLength = max - least; if( !header.nLeastPageLength || header.nLeastPageLength > vecPages[i].nPageLength ) header.nLeastPageLength = vecPages[i].nPageLength; if( !maxPageLength || maxPageLength < max ) maxPageLength = max; vecPages[i].nSharedObjects = 0; vecPages[i].nContentsOffset = 0; vecPages[i].nContentsLength = 0; } header.nFirstPageObject = (*pXRef)[0].vecOffsets[ m_pPagesTree->GetPage( 0 )->GetObject()->Reference().ObjectNumber() ].lOffset; header.nBitsPageObject = (pdf_uint16)ceil( logb( static_cast(maxNumberOfObjects-header.nLeastNumberOfObjects) ) ); header.nBitsPageLength = (pdf_uint16)ceil( logb( static_cast(maxPageLength - header.nLeastPageLength) ) ); header.nOffsetContentStream = 0; // acrobat sets this to 0 and ignores it header.nBitsContentStream = 0; // acrobat sets this to 0 and ignores it header.nLeastContentStreamLength = 0; // acrobat sets this to 0 and ignores it header.nBitsLeastContentStreamLength = 0; // acrobat sets this to 0 and ignores it header.nBitsNumSharedObjects = 0; header.nBitsGreatestSharedObject = 0; header.nItem12 = 0; header.nItem13 = 0; for( i=0;i(this->GetObject()->GetStream()->GetLength()) ); offset.SetPaddingLength( LINEARIZATION_PADDING ); this->GetObject()->GetDictionary().AddKey( "S", offset ); // shared object hint table } */ void PdfHintStream::WriteUInt16( pdf_uint16 val ) { val = ::PoDoFo::compat::podofo_htons(val); this->GetObject()->GetStream()->Append( reinterpret_cast(&val), 2 ); } void PdfHintStream::WriteUInt32( pdf_uint32 val ) { val = ::PoDoFo::compat::podofo_htonl(val); this->GetObject()->GetStream()->Append( reinterpret_cast(&val), 4 ); } }; // end namespace PoDoFo::NonPublic }; // end namespace PoDoFo podofo-0.9.3/src/doc/PdfIdentityEncoding.h0000664000175000017500000001632512344436402020271 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2010 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_IDENTITY_ENCODING_H_ #define _PDF_IDENTITY_ENCODING_H_ #include "podofo/base/PdfDefines.h" #include "podofo/base/PdfEncoding.h" #include "podofo/base/PdfObject.h" namespace PoDoFo { /** PdfIdentityEncoding is a two-byte encoding which can be * used with TrueType fonts to represent all characters * present in a font. If the font contains all unicode * glyphs, PdfIdentityEncoding will support all unicode * characters. */ class PODOFO_DOC_API PdfIdentityEncoding : public PdfEncoding { public: /** * Create a new PdfIdentityEncoding. * * \param nFirstChar the first supported unicode character code (at least 0) * \param nLastChar the last supported unicode character code, * must be larger than nFirstChar (max value is 0xffff) * \param bAutoDelete if true the encoding is deleted by its owning font */ PdfIdentityEncoding( int nFirstChar = 0, int nLastChar = 0xffff, bool bAutoDelete = true, PdfObject* pToUnicode = NULL ); /** Add this encoding object to a dictionary * usually be adding an /Encoding key in font dictionaries. * * \param rDictionary add the encoding to this dictionary */ virtual void AddToDictionary( PdfDictionary & rDictionary ) const; /** Convert a string that is encoded with this encoding * to an unicode PdfString. * * \param rEncodedString a string encoded by this encoding. * Usually this string was read from a content stream. * \param pFont the font for which this string is converted * * \returns an unicode PdfString. */ virtual PdfString ConvertToUnicode( const PdfString & rEncodedString, const PdfFont* pFont ) const; /** Convert a unicode PdfString to a string encoded with this encoding. * * \param rString an unicode PdfString. * \param pFont the font for which this string is converted * * \returns an encoded PdfRefCountedBuffer. The PdfRefCountedBuffer is treated as a series of bytes * and is allowed to have 0 bytes. The returned buffer must not be a unicode string. */ virtual PdfRefCountedBuffer ConvertToEncoding( const PdfString & rString, const PdfFont* pFont ) const; /** * PdfIdentityEncoding is usually delete along with the font. * * \returns true if this encoding should be deleted automatically with the * font. */ virtual bool IsAutoDelete() const; /** * \returns true if this is a single byte encoding with a maximum of 256 values. */ virtual bool IsSingleByteEncoding() const; /** Get the unicode character code for this encoding * at the position nIndex. nIndex is a position between * GetFirstChar() and GetLastChar() * * \param nIndex character code at position index * \returns unicode character code * * \see GetFirstChar * \see GetLastChar * * Will throw an exception if nIndex is out of range. */ virtual pdf_utf16be GetCharCode( int nIndex ) const; protected: /** Get a unique ID for this encoding * which can used for comparisons! * * \returns a unique id for this encoding! */ inline virtual const PdfName & GetID() const; private: /** Gets the unicode value from a char code in this font * * \param lCharCode the character code (i.e. glyph id) * * \returns an unicode value */ pdf_utf16be GetUnicodeValue( pdf_utf16be lCharCode ) const; /** Gets the char code from a uniode value * * \param lUnicodeValue the unicode valye * * \returns the character code (i.e. glyph id) */ pdf_utf16be GetCIDValue( pdf_utf16be lUnicodeValue ) const; private: bool m_bAutoDelete; ///< If true this encoding is deleted by its font. PdfName m_id; ///< Unique ID of this encoding PdfObject* m_pToUnicode; ///< Pointer to /ToUnicode object, if any bool m_bToUnicodeIsLoaded; ///< If true, ToUnicode has been parsed std::map m_cMapEncoding; /** Parse the /ToUnicode object */ void ParseToUnicode(); }; // ----------------------------------------------------- // // ----------------------------------------------------- inline const PdfName & PdfIdentityEncoding::GetID() const { return m_id; } // ----------------------------------------------------- // // ----------------------------------------------------- inline bool PdfIdentityEncoding::IsAutoDelete() const { return m_bAutoDelete; } // ----------------------------------------------------- // // ----------------------------------------------------- inline bool PdfIdentityEncoding::IsSingleByteEncoding() const { return false; } }; /* namespace PoDoFo */ #endif // _PDF_IDENTITY_ENCODING_H_ podofo-0.9.3/src/doc/PdfField.h0000664000175000017500000012222312262234754016054 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2007 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_FIELD_H_ #define _PDF_FIELD_H_ #include "podofo/base/PdfDefines.h" #include "podofo/base/PdfName.h" #include "podofo/base/PdfString.h" #include "PdfAnnotation.h" namespace PoDoFo { class PdfAcroForm; class PdfAction; class PdfAnnotation; class PdfDocument; class PdfObject; class PdfPage; class PdfRect; class PdfReference; class PdfStreamedDocument; /** The type of PDF field */ enum EPdfField { ePdfField_PushButton, ePdfField_CheckBox, ePdfField_RadioButton, ePdfField_TextField, ePdfField_ComboBox, ePdfField_ListBox, ePdfField_Signature, ePdfField_Unknown = 0xff }; /** The possible highlighting modes * for a PdfField. I.e the visual effect * that is to be used when the mouse * button is pressed. * * The default value is * ePdfHighlightingMode_Invert */ enum EPdfHighlightingMode { ePdfHighlightingMode_None, ///< Do no highlighting ePdfHighlightingMode_Invert, ///< Invert the PdfField ePdfHighlightingMode_InvertOutline, ///< Invert the fields border ePdfHighlightingMode_Push, ///< Display the fields down appearance (requires an additional appearance stream to be set) ePdfHighlightingMode_Unknown = 0xff }; class PODOFO_DOC_API PdfField { enum { ePdfField_ReadOnly = 0x0001, ePdfField_Required = 0x0002, ePdfField_NoExport = 0x0004 }; protected: /** Create a new PdfAcroForm dictionary object * \param pParent parent of this action */ PdfField( EPdfField eField, PdfAnnotation* pWidget, PdfAcroForm* pParent ); PdfField( EPdfField eField, PdfPage* pPage, const PdfRect & rRect, PdfAcroForm* pParent ); PdfField( EPdfField eField, PdfPage* pPage, const PdfRect & rRect, PdfDocument* pDoc ); PdfField( EPdfField eField, PdfPage* pPage, const PdfRect & rRect, PdfStreamedDocument* pDoc ); PdfField( EPdfField eField, PdfAnnotation* pWidget, PdfAcroForm* pParent, PdfDocument* pDoc); PdfField( EPdfField eField, PdfPage* pPage, const PdfRect & rRect, PdfDocument* pDoc, bool bDefaultApperance); /** Create a copy of a PdfField object. * Not the field on the page is copied - only the PdfField * object referring to the field on the page is copied! * * \param rhs the field to copy * \returns this field */ //inline virtual const PdfField & operator=( const PdfField & rhs ); /** * Set a bit in the field flags value of the fields dictionary. * * \param lValue the value specifying the bits to set * \param bSet if true the value will be set otherwise * they will be cleared. * * \see GetFieldFlag */ void SetFieldFlag( long lValue, bool bSet ); /** * \param lValue it is checked if these bits are set * \param bDefault the returned value if no field flags are specified * * \returns true if given bits are set in the field flags * * \see SetFieldFlag */ bool GetFieldFlag( long lValue, bool bDefault ) const; /** * \param bCreate create the dictionary if it does not exist * * \returns a pointer to the appearance characteristics dictionary * of this object or NULL if it does not exists. */ PdfObject* GetAppearanceCharacteristics( bool bCreate ) const; public: /** Create a PdfAcroForm dictionary object from an existing PdfObject * \param pObject the object to create from * \param pWidget the widget annotation of this field */ PdfField( PdfObject* pObject, PdfAnnotation* pWidget ); /** Create a copy of a PdfField object. * Not the field on the page is copied - only the PdfField * object referring to the field on the page is copied! * * \param rhs the field to copy */ PdfField( const PdfField & rhs ); virtual ~PdfField() { } /** Get the page of this PdfField * * \returns the page of this PdfField */ inline PdfPage* GetPage() const; /** Set the highlighting mode which should be used when the user * presses the mouse button over this widget. * * \param eMode the highliting mode * * The default value is ePdfHighlightingMode_Invert */ void SetHighlightingMode( EPdfHighlightingMode eMode ); /** * \returns the highlighting mode to be used when the user * presses the mouse button over this widget */ EPdfHighlightingMode GetHighlightingMode() const; /** * Sets the border color of the field to be transparent */ void SetBorderColorTransparent(); /** * Sets the border color of the field * * \param dGray gray value of the color */ void SetBorderColor( double dGray ); /** * Sets the border color of the field * * \param dRed red * \param dGreen green * \param dBlue blue */ void SetBorderColor( double dRed, double dGreen, double dBlue ); /** * Sets the border color of the field * * \param dCyan cyan * \param dMagenta magenta * \param dYellow yellow * \param dBlack black */ void SetBorderColor( double dCyan, double dMagenta, double dYellow, double dBlack ); /** * Sets the background color of the field to be transparent */ void SetBackgroundColorTransparent(); /** * Sets the background color of the field * * \param dGray gray value of the color */ void SetBackgroundColor( double dGray ); /** * Sets the background color of the field * * \param dRed red * \param dGreen green * \param dBlue blue */ void SetBackgroundColor( double dRed, double dGreen, double dBlue ); /** * Sets the background color of the field * * \param dCyan cyan * \param dMagenta magenta * \param dYellow yellow * \param dBlack black */ void SetBackgroundColor( double dCyan, double dMagenta, double dYellow, double dBlack ); /** Sets the field name of this PdfField * * PdfFields require a field name to work correctly in acrobat reader! * This name can be used to access the field in JavaScript actions. * * \param rsName the field name of this pdf field */ void SetFieldName( const PdfString & rsName ); /** \returns the field name of this PdfField */ PdfString GetFieldName() const; /** * Set the alternate name of this field which * is used to display the fields name to the user * (e.g. in error messages). * * \param rsName a name that can be displayed to the user */ void SetAlternateName( const PdfString & rsName ); /** \returns the fields alternate name */ PdfString GetAlternateName() const; /** * Sets the fields mapping name which is used when exporting * the fields data * * \param rsName the mapping name of this PdfField */ void SetMappingName( const PdfString & rsName ); /** \returns the mapping name of this field */ PdfString GetMappingName() const; /** Set this field to be readonly. * I.e. it will not interact with the user * and respond to mouse button events. * * This is useful for fields that are pure calculated. * * \param bReadOnly specifies if this field is read-only. */ inline void SetReadOnly( bool bReadOnly ); /** * \returns true if this field is read-only * * \see SetReadOnly */ inline bool IsReadOnly() const; /** Required fields must have a value * at the time the value is exported by a submit action * * \param bRequired if true this field requires a value for submit actions */ inline void SetRequired( bool bRequired ); /** * \returns true if this field is required for submit actions * * \see SetRequired */ inline bool IsRequired() const; /** Sets if this field can be exported by a submit action * * Fields can be exported by default. * * \param bExport if false this field cannot be exported by submit actions */ inline void SetExport( bool bExport ); /** * \returns true if this field can be exported by submit actions * * \see SetExport */ inline bool IsExport() const; inline void SetMouseEnterAction( const PdfAction & rAction ); inline void SetMouseLeaveAction( const PdfAction & rAction ); inline void SetMouseDownAction( const PdfAction & rAction ); inline void SetMouseUpAction( const PdfAction & rAction ); inline void SetFocusEnterAction( const PdfAction & rAction ); inline void SetFocusLeaveAction( const PdfAction & rAction ); inline void SetPageOpenAction( const PdfAction & rAction ); inline void SetPageCloseAction( const PdfAction & rAction ); inline void SetPageVisibleAction( const PdfAction & rAction ); inline void SetPageInvisibleAction( const PdfAction & rAction ); /* Peter Petrov 15 October 2008 */ inline void SetKeystrokeAction( const PdfAction & rAction ); inline void SetValidateAction( const PdfAction & rAction ); /** * \returns the type of this field */ inline EPdfField GetType() const; private: /** * Initialize this PdfField. * * \param pParent parent acro forms dictionary */ void Init( PdfAcroForm* pParent ); void AddAlternativeAction( const PdfName & rsName, const PdfAction & rAction ); protected: PdfObject* m_pObject; PdfAnnotation* m_pWidget; private: EPdfField m_eField; // Peter Petrov 27 April 2008 public: inline PdfAnnotation* GetWidgetAnnotation() const; inline PdfObject* GetFieldObject() const; }; // ----------------------------------------------------- // // ----------------------------------------------------- /* inline const PdfField & PdfField::operator=( const PdfField & rhs ) { // DominikS: Reference counted vectors could be nice here. In case // the PdfField handling makes sense the way it is now, // we could discuss using reference counted vectors // and implement PdfAction, PdfAnnotation ... similar to PdfField m_pObject = rhs.m_pObject; m_pWidget = rhs.m_pWidget; m_eField = rhs.m_eField; return *this; }*/ // ----------------------------------------------------- // // ----------------------------------------------------- inline void PdfField::SetReadOnly( bool bReadOnly ) { this->SetFieldFlag( static_cast(ePdfField_ReadOnly), bReadOnly ); } // ----------------------------------------------------- // // ----------------------------------------------------- inline bool PdfField::IsReadOnly() const { return this->GetFieldFlag( static_cast(ePdfField_ReadOnly), false ); } // ----------------------------------------------------- // // ----------------------------------------------------- inline void PdfField::SetRequired( bool bRequired ) { this->SetFieldFlag( static_cast(ePdfField_Required), bRequired ); } // ----------------------------------------------------- // // ----------------------------------------------------- inline bool PdfField::IsRequired() const { return this->GetFieldFlag( static_cast(ePdfField_Required), false ); } // ----------------------------------------------------- // // ----------------------------------------------------- inline void PdfField::SetExport( bool bExport ) { this->SetFieldFlag( static_cast(ePdfField_NoExport), bExport ); } // ----------------------------------------------------- // // ----------------------------------------------------- inline bool PdfField::IsExport() const { return this->GetFieldFlag( static_cast(ePdfField_NoExport), true ); } // ----------------------------------------------------- // // ----------------------------------------------------- inline PdfPage* PdfField::GetPage() const { return m_pWidget->GetPage(); } // ----------------------------------------------------- // // ----------------------------------------------------- inline void PdfField::SetMouseEnterAction( const PdfAction & rAction ) { this->AddAlternativeAction( PdfName("E"), rAction ); } // ----------------------------------------------------- // // ----------------------------------------------------- inline void PdfField::SetMouseLeaveAction( const PdfAction & rAction ) { this->AddAlternativeAction( PdfName("X"), rAction ); } // ----------------------------------------------------- // // ----------------------------------------------------- inline void PdfField::SetMouseDownAction( const PdfAction & rAction ) { this->AddAlternativeAction( PdfName("D"), rAction ); } // ----------------------------------------------------- // // ----------------------------------------------------- inline void PdfField::SetMouseUpAction( const PdfAction & rAction ) { this->AddAlternativeAction( PdfName("U"), rAction ); } // ----------------------------------------------------- // // ----------------------------------------------------- inline void PdfField::SetFocusEnterAction( const PdfAction & rAction ) { this->AddAlternativeAction( PdfName("Fo"), rAction ); } // ----------------------------------------------------- // // ----------------------------------------------------- inline void PdfField::SetFocusLeaveAction( const PdfAction & rAction ) { this->AddAlternativeAction( PdfName("BI"), rAction ); } // ----------------------------------------------------- // // ----------------------------------------------------- inline void PdfField::SetPageOpenAction( const PdfAction & rAction ) { this->AddAlternativeAction( PdfName("PO"), rAction ); } // ----------------------------------------------------- // // ----------------------------------------------------- inline void PdfField::SetPageCloseAction( const PdfAction & rAction ) { this->AddAlternativeAction( PdfName("PC"), rAction ); } // ----------------------------------------------------- // // ----------------------------------------------------- inline void PdfField::SetPageVisibleAction( const PdfAction & rAction ) { this->AddAlternativeAction( PdfName("PV"), rAction ); } // ----------------------------------------------------- // // ----------------------------------------------------- inline void PdfField::SetPageInvisibleAction( const PdfAction & rAction ) { this->AddAlternativeAction( PdfName("PI"), rAction ); } /* Peter Petrov 15 October 2008 */ // ----------------------------------------------------- // // ----------------------------------------------------- inline void PdfField::SetKeystrokeAction( const PdfAction & rAction ) { this->AddAlternativeAction( PdfName("K"), rAction); } /* Peter Petrov 15 October 2008 */ // ----------------------------------------------------- // // ----------------------------------------------------- inline void PdfField::SetValidateAction( const PdfAction & rAction ) { this->AddAlternativeAction( PdfName("V"), rAction); } // ----------------------------------------------------- // // ----------------------------------------------------- inline EPdfField PdfField::GetType() const { return m_eField; } // Peter Petrov 27 April 2008 // ----------------------------------------------------- // // ----------------------------------------------------- inline PdfAnnotation* PdfField::GetWidgetAnnotation() const { return m_pWidget; } // Peter Petrov 27 April 2008 // ----------------------------------------------------- // // ----------------------------------------------------- inline PdfObject* PdfField::GetFieldObject() const { return m_pObject; } class PODOFO_DOC_API PdfButton : public PdfField { protected: enum { ePdfButton_NoToggleOff = 0x0004000, ePdfButton_Radio = 0x0008000, ePdfButton_PushButton = 0x0010000, ePdfButton_RadioInUnison = 0x2000000 }; /** Create a new PdfButton */ PdfButton( EPdfField eField, PdfAnnotation* pWidget, PdfAcroForm* pParent ); /** Create a new PdfButton */ PdfButton( EPdfField eField, PdfPage* pPage, const PdfRect & rRect, PdfAcroForm* pParent ); /** Create a new PdfButton */ PdfButton( EPdfField eField, PdfPage* pPage, const PdfRect & rRect, PdfDocument* pDoc ); /** Create a new PdfButton */ PdfButton( EPdfField eField, PdfPage* pPage, const PdfRect & rRect, PdfStreamedDocument* pDoc ); public: /** Create a PdfButton from a PdfField * \param rhs a PdfField that is a button * * Internal usage only. */ PdfButton( const PdfField & rhs ); /** * \returns true if this is a pushbutton */ inline bool IsPushButton() const; /** * \returns true if this is a checkbox */ inline bool IsCheckBox() const; /** * \returns true if this is a radiobutton */ inline bool IsRadioButton() const; /** Set the normal caption of this button * * \param rsText the caption */ void SetCaption( const PdfString & rsText ); /** * \returns the caption of this button */ const PdfString GetCaption() const; }; // ----------------------------------------------------- // // ----------------------------------------------------- inline bool PdfButton::IsPushButton() const { return this->GetFieldFlag( static_cast(ePdfButton_PushButton), false ); } // ----------------------------------------------------- // // ----------------------------------------------------- inline bool PdfButton::IsCheckBox() const { return (!this->GetFieldFlag( static_cast(ePdfButton_Radio), false ) && !this->GetFieldFlag( static_cast(ePdfButton_PushButton), false ) ); } // ----------------------------------------------------- // // ----------------------------------------------------- inline bool PdfButton::IsRadioButton() const { return this->GetFieldFlag( static_cast(ePdfButton_Radio), false ); } /** A push button is a button which has no state and value * but can toggle actions. */ class PODOFO_DOC_API PdfPushButton : public PdfButton { public: /** Create a new PdfPushButton */ PdfPushButton( PdfAnnotation* pWidget, PdfAcroForm* pParent ); /** Create a new PdfPushButton */ PdfPushButton( PdfPage* pPage, const PdfRect & rRect, PdfAcroForm* pParent ); /** Create a new PdfPushButton */ PdfPushButton( PdfPage* pPage, const PdfRect & rRect, PdfDocument* pDoc ); /** Create a new PdfPushButton */ PdfPushButton( PdfPage* pPage, const PdfRect & rRect, PdfStreamedDocument* pDoc ); /** Create a PdfPushButton from a PdfField * \param rhs a PdfField that is a push button button * * Raises an error if PdfField::GetType() != ePdfField_PushButton */ PdfPushButton( const PdfField & rhs ); /** Set the rollover caption of this button * which is displayed when the cursor enters the field * without the mouse button being pressed * * \param rsText the caption */ void SetRolloverCaption( const PdfString & rsText ); /** * \returns the rollover caption of this button */ const PdfString GetRolloverCaption() const; /** Set the alternate caption of this button * which is displayed when the button is pressed. * * \param rsText the caption */ void SetAlternateCaption( const PdfString & rsText ); /** * \returns the rollover caption of this button */ const PdfString GetAlternateCaption() const; private: void Init(); }; /** A checkbox can be checked or unchecked by the user */ class PODOFO_DOC_API PdfCheckBox : public PdfButton { public: /** Create a new PdfCheckBox */ PdfCheckBox( PdfAnnotation* pWidget, PdfAcroForm* pParent ); /** Create a new PdfCheckBox */ PdfCheckBox( PdfPage* pPage, const PdfRect & rRect, PdfAcroForm* pParent ); /** Create a new PdfCheckBox */ PdfCheckBox( PdfPage* pPage, const PdfRect & rRect, PdfDocument* pDoc ); /** Create a new PdfCheckBox */ PdfCheckBox( PdfPage* pPage, const PdfRect & rRect, PdfStreamedDocument* pDoc ); /** Create a PdfCheckBox from a PdfField * \param rhs a PdfField that is a check box * * Raises an error if PdfField::GetType() != ePdfField_CheckBox */ PdfCheckBox( const PdfField & rhs ); /** Set the appearance stream which is displayed when the checkbox * is checked. * * \param rXObject an xobject which contains the drawing commands for a checked checkbox */ void SetAppearanceChecked( const PdfXObject & rXObject ); /** Set the appearance stream which is displayed when the checkbox * is unchecked. * * \param rXObject an xobject which contains the drawing commands for an unchecked checkbox */ void SetAppearanceUnchecked( const PdfXObject & rXObject ); /** Sets the state of this checkbox * * \param bChecked if true the checkbox will be checked */ void SetChecked( bool bChecked ); /** * \returns true if the checkbox is checked */ bool IsChecked() const; private: void Init(); /** Add a appearance stream to this checkbox * * \param rName name of the appearance stream * \param rReference reference to the XObject containing the appearance stream */ void AddAppearanceStream( const PdfName & rName, const PdfReference & rReference ); }; // TODO: Dominiks PdfRadioButton /** A textfield in a PDF file. * * Users can enter text into a text field. * Single and multi line text is possible, * as well as richtext. The text can be interpreted * as path to a file which is going to be submitted. */ class PODOFO_DOC_API PdfTextField : public PdfField { private: enum { ePdfTextField_MultiLine = 0x0001000, ePdfTextField_Password = 0x0002000, ePdfTextField_FileSelect = 0x0100000, ePdfTextField_NoSpellcheck = 0x0400000, ePdfTextField_NoScroll = 0x0800000, ePdfTextField_Comb = 0x1000000, ePdfTextField_RichText = 0x2000000 }; public: /** Create a new PdfTextField */ PdfTextField( PdfAnnotation* pWidget, PdfAcroForm* pParent ); /** Create a new PdfTextField */ PdfTextField( PdfPage* pPage, const PdfRect & rRect, PdfAcroForm* pParent ); /** Create a new PdfTextField */ PdfTextField( PdfPage* pPage, const PdfRect & rRect, PdfDocument* pDoc ); /** Create a new PdfTextField */ PdfTextField( PdfPage* pPage, const PdfRect & rRect, PdfStreamedDocument* pDoc ); /** Create a PdfTextField from a PdfField * * \param rhs a PdfField that is a PdfTextField * * Raises an error if PdfField::GetType() != ePdfField_TextField */ PdfTextField( const PdfField & rhs ); /** Sets the text contents of this text field. * * \param rsText the text of this field */ void SetText( const PdfString & rsText ); /** * \returns the text contents of this text field */ PdfString GetText() const; /** Sets the max length in characters of this textfield * \param nMaxLen the max length of this textfields in characters */ void SetMaxLen( pdf_long nMaxLen ); /** * \returns the max length of this textfield in characters or -1 * if no max length was specified */ pdf_long GetMaxLen() const; /** * Create a multi-line text field that can contains multiple lines of text. * \param bMultiLine if true a multi line field is generated, otherwise * the text field can contain only a single line of text. * * The default is to create a single line text field. */ inline void SetMultiLine( bool bMultiLine ); /** * \returns true if this text field can contain multiple lines of text */ inline bool IsMultiLine() const; /** * Create a password text field that should not echo entered * characters visibly to the screen. * * \param bPassword if true a password field is created * * The default is to create no password field */ inline void SetPasswordField( bool bPassword ); /** * \returns true if this field is a password field that does * not echo entered characters on the screen */ inline bool IsPasswordField() const; /** * Create a file selection field. * The entered contents are treated as filename to a file * whose contents are submitted as the value of the field. * * \param bFile if true the contents are treated as a pathname * to a file to submit */ inline void SetFileField( bool bFile ); /** * \returns true if the contents are treated as filename */ inline bool IsFileField() const; /** * Enable/disable spellchecking for this text field * * \param bSpellcheck if true spellchecking will be enabled * * Text fields are spellchecked by default */ inline void SetSpellcheckingEnabled( bool bSpellcheck ); /** * \returns true if spellchecking is enabled for this text field */ inline bool IsSpellcheckingEnabled() const; /** * Enable/disable scrollbars for this text field * * \param bScroll if true scrollbars will be enabled * * Text fields have scrollbars by default */ inline void SetScrollBarsEnabled( bool bScroll ); /** * \returns true if scrollbars are enabled for this text field */ inline bool IsScrollBarsEnabled() const; /** * Divide the text field into max-len equal * combs. * * \param bCombs if true enable division into combs * * By default coms are disabled. Requires the max len * property to be set. * * \see SetMaxLen */ inline void SetCombs( bool bCombs ); /** * \returns true if the text field is divided in to equal combs */ inline bool IsCombs() const; /** * Creates a richtext field. * * \param bRichText if true creates a richtext field * * By default richtext is disabled. */ inline void SetRichText( bool bRichText ); /** * \returns true if this is a richtext text field */ inline bool IsRichText() const; private: void Init(); }; // ----------------------------------------------------- // // ----------------------------------------------------- inline void PdfTextField::SetMultiLine( bool bMultiLine ) { this->SetFieldFlag( static_cast(ePdfTextField_MultiLine), bMultiLine ); } // ----------------------------------------------------- // // ----------------------------------------------------- inline bool PdfTextField::IsMultiLine() const { return this->GetFieldFlag( static_cast(ePdfTextField_MultiLine), false ); } // ----------------------------------------------------- // // ----------------------------------------------------- inline void PdfTextField::SetPasswordField( bool bPassword ) { this->SetFieldFlag( static_cast(ePdfTextField_Password), bPassword ); } // ----------------------------------------------------- // // ----------------------------------------------------- inline bool PdfTextField::IsPasswordField() const { return this->GetFieldFlag( static_cast(ePdfTextField_Password), false ); } // ----------------------------------------------------- // // ----------------------------------------------------- inline void PdfTextField::SetFileField( bool bFile ) { this->SetFieldFlag( static_cast(ePdfTextField_FileSelect), bFile ); } // ----------------------------------------------------- // // ----------------------------------------------------- inline bool PdfTextField::IsFileField() const { return this->GetFieldFlag( static_cast(ePdfTextField_FileSelect), false ); } // ----------------------------------------------------- // // ----------------------------------------------------- inline void PdfTextField::SetSpellcheckingEnabled( bool bSpellcheck ) { this->SetFieldFlag( static_cast(ePdfTextField_NoSpellcheck), !bSpellcheck ); } // ----------------------------------------------------- // // ----------------------------------------------------- inline bool PdfTextField::IsSpellcheckingEnabled() const { return this->GetFieldFlag( static_cast(ePdfTextField_NoSpellcheck), true ); } // ----------------------------------------------------- // // ----------------------------------------------------- inline void PdfTextField::SetScrollBarsEnabled( bool bScroll ) { this->SetFieldFlag( static_cast(ePdfTextField_NoScroll), !bScroll ); } // ----------------------------------------------------- // // ----------------------------------------------------- inline bool PdfTextField::IsScrollBarsEnabled() const { return this->GetFieldFlag( static_cast(ePdfTextField_NoScroll), true ); } // ----------------------------------------------------- // // ----------------------------------------------------- inline void PdfTextField::SetCombs( bool bCombs ) { this->SetFieldFlag( static_cast(ePdfTextField_Comb), bCombs ); } // ----------------------------------------------------- // // ----------------------------------------------------- inline bool PdfTextField::IsCombs() const { return this->GetFieldFlag( static_cast(ePdfTextField_Comb), false ); } // ----------------------------------------------------- // // ----------------------------------------------------- inline void PdfTextField::SetRichText( bool bRichText ) { this->SetFieldFlag( static_cast(ePdfTextField_RichText), bRichText); } // ----------------------------------------------------- // // ----------------------------------------------------- inline bool PdfTextField::IsRichText() const { return this->GetFieldFlag( static_cast(ePdfTextField_RichText), false ); } /** A list of items in a PDF file. * You cannot create this object directly, use * PdfComboBox or PdfListBox instead. * * \see PdfComboBox * \see PdfListBox */ class PODOFO_DOC_API PdfListField : public PdfField { protected: enum { ePdfListField_Combo = 0x0020000, ePdfListField_Edit = 0x0040000, ePdfListField_Sort = 0x0080000, ePdfListField_MultiSelect = 0x0200000, ePdfListField_NoSpellcheck = 0x0400000, ePdfListField_CommitOnSelChange = 0x4000000 }; /** Create a new PdfTextField */ PdfListField( EPdfField eField, PdfAnnotation* pWidget, PdfAcroForm* pParent ); /** Create a new PdfTextField */ PdfListField( EPdfField eField, PdfPage* pPage, const PdfRect & rRect, PdfAcroForm* pParent ); /** Create a new PdfTextField */ PdfListField( EPdfField eField, PdfPage* pPage, const PdfRect & rRect, PdfDocument* pDoc ); /** Create a new PdfTextField */ PdfListField( EPdfField eField, PdfPage* pPage, const PdfRect & rRect, PdfStreamedDocument* pDoc ); public: /** Create a PdfListField from a PdfField * \param rhs a PdfField that is a list field * * Internal usage only. */ PdfListField( const PdfField & rhs ); //const PdfString & GetSelectedItem(); /// ??? /** * Inserts a new item into the list * * @param rsValue the value of the item * @param rsDisplayName an optional display string that is displayed in the viewer * instead of the value */ void InsertItem( const PdfString & rsValue, const PdfString & rsDisplayName = PdfString::StringNull ); /** * Removes an item for the list * * @param nIndex index of the item to remove */ void RemoveItem( int nIndex ); /** * @param nIndex index of the item * @returns the value of the item at the specified index */ const PdfString GetItem( int nIndex ) const; /** * @param nIndex index of the item * @returns the display text of the item or if it has no display text * its value is returned. This call is equivalent to GetItem() * in this case * * \see GetItem */ const PdfString GetItemDisplayText( int nIndex ) const; /** * \returns the number of items in this list */ size_t GetItemCount() const; /** Sets the currently selected item * \param nIndex index of the currently selected item */ void SetSelectedItem( int nIndex ); /** Sets the currently selected item * * \returns the selected item or -1 if no item was selected */ int GetSelectedItem() const; #if 0 // TODO: #error "Only allow these if multiselect is true!" void SetSelectedItems( ... ); PdfArray GetSelectedItems() ; #endif /** * \returns true if this PdfListField is a PdfComboBox and false * if it is a PdfListBox */ inline bool IsComboBox() const; /** * Enable/disable spellchecking for this combobox * * \param bSpellcheck if true spellchecking will be enabled * * combobox are spellchecked by default */ inline void SetSpellcheckingEnabled( bool bSpellcheck ); /** * \returns true if spellchecking is enabled for this combobox */ inline bool IsSpellcheckingEnabled() const; /** * Enable or disable sorting of items. * The sorting does not happen in acrobat reader * but whenever adding items using PoDoFo or another * PDF editing application. * * \param bSorted enable/disable sorting */ inline void SetSorted( bool bSorted ); /** * \returns true if sorting is enabled */ inline bool IsSorted() const; /** * Sets wether multiple items can be selected by the * user in the list. * * \param bMulti if true multiselect will be enabled * * By default multiselection is turned off. */ inline void SetMultiSelect( bool bMulti ); /** * \returns true if multi selection is enabled * for this list */ inline bool IsMultiSelect() const; inline void SetCommitOnSelectionChange( bool bCommit ); inline bool IsCommitOnSelectionChange() const; }; // ----------------------------------------------------- // // ----------------------------------------------------- inline bool PdfListField::IsComboBox() const { return this->GetFieldFlag( static_cast(ePdfListField_Combo), false ); } // ----------------------------------------------------- // // ----------------------------------------------------- inline void PdfListField::SetSpellcheckingEnabled( bool bSpellcheck ) { this->SetFieldFlag( static_cast(ePdfListField_NoSpellcheck), !bSpellcheck ); } // ----------------------------------------------------- // // ----------------------------------------------------- inline bool PdfListField::IsSpellcheckingEnabled() const { return this->GetFieldFlag( static_cast(ePdfListField_NoSpellcheck), true ); } // ----------------------------------------------------- // // ----------------------------------------------------- inline void PdfListField::SetSorted( bool bSorted ) { this->SetFieldFlag( static_cast(ePdfListField_Sort), bSorted ); } // ----------------------------------------------------- // // ----------------------------------------------------- inline bool PdfListField::IsSorted() const { return this->GetFieldFlag( static_cast(ePdfListField_Sort), false ); } // ----------------------------------------------------- // // ----------------------------------------------------- inline void PdfListField::SetMultiSelect( bool bMulti ) { this->SetFieldFlag( static_cast(ePdfListField_MultiSelect), bMulti ); } // ----------------------------------------------------- // // ----------------------------------------------------- inline bool PdfListField::IsMultiSelect() const { return this->GetFieldFlag( static_cast(ePdfListField_MultiSelect), false ); } // ----------------------------------------------------- // // ----------------------------------------------------- inline void PdfListField::SetCommitOnSelectionChange( bool bCommit ) { this->SetFieldFlag( static_cast(ePdfListField_CommitOnSelChange), bCommit ); } // ----------------------------------------------------- // // ----------------------------------------------------- inline bool PdfListField::IsCommitOnSelectionChange() const { return this->GetFieldFlag( static_cast(ePdfListField_CommitOnSelChange), false ); } /** A combo box with a drop down list of items. */ class PODOFO_DOC_API PdfComboBox : public PdfListField { public: /** Create a new PdfTextField */ PdfComboBox( PdfAnnotation* pWidget, PdfAcroForm* pParent ); /** Create a new PdfTextField */ PdfComboBox( PdfPage* pPage, const PdfRect & rRect, PdfAcroForm* pParent ); /** Create a new PdfTextField */ PdfComboBox( PdfPage* pPage, const PdfRect & rRect, PdfDocument* pDoc ); /** Create a new PdfTextField */ PdfComboBox( PdfPage* pPage, const PdfRect & rRect, PdfStreamedDocument* pDoc ); /** Create a PdfComboBox from a PdfField * * \param rhs a PdfField that is a PdfComboBox * * Raises an error if PdfField::GetType() != ePdfField_ComboBox */ PdfComboBox( const PdfField & rhs ); /** * Sets the combobox to be editable * * \param bEdit if true the combobox can be edited by the user * * By default a combobox is not editable */ inline void SetEditable( bool bEdit ); /** * \returns true if this is an editable combobox */ inline bool IsEditable() const; }; // ----------------------------------------------------- // // ----------------------------------------------------- inline void PdfComboBox::SetEditable( bool bEdit ) { this->SetFieldFlag( static_cast(ePdfListField_Edit), bEdit); } // ----------------------------------------------------- // // ----------------------------------------------------- inline bool PdfComboBox::IsEditable() const { return this->GetFieldFlag( static_cast(ePdfListField_Edit), false ); } /** A list box */ class PODOFO_DOC_API PdfListBox : public PdfListField { public: /** Create a new PdfTextField */ PdfListBox( PdfAnnotation* pWidget, PdfAcroForm* pParent ); /** Create a new PdfTextField */ PdfListBox( PdfPage* pPage, const PdfRect & rRect, PdfAcroForm* pParent ); /** Create a new PdfTextField */ PdfListBox( PdfPage* pPage, const PdfRect & rRect, PdfDocument* pDoc ); /** Create a new PdfTextField */ PdfListBox( PdfPage* pPage, const PdfRect & rRect, PdfStreamedDocument* pDoc ); /** Create a PdfListBox from a PdfField * * \param rhs a PdfField that is a PdfComboBox * * Raises an error if PdfField::GetType() != ePdfField_ListBox */ PdfListBox( const PdfField & rhs ); }; }; #endif // _PDF_ACRO_FORM_H__PDF_NAMES_TREE_H_ podofo-0.9.3/src/doc/PdfFontType1Base14.h0000664000175000017500000001040012344436402017606 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2010 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_FONT_TYPE1_BASE14_H_ #define _PDF_FONT_TYPE1_BASE14_H_ #include "podofo/base/PdfDefines.h" #include "PdfFontSimple.h" namespace PoDoFo { /** A PdfFont implementation that can be used * draw with base14 type1 fonts into a PDF file. */ class PdfFontType1Base14 : public PdfFontSimple { public: /** Create a new Type1 font object. * * \param pMetrics pointer to a font metrics object. The font in the PDF * file will match this fontmetrics object. The metrics object is * deleted along with the font. * \param pEncoding the encoding of this font. The font will take ownership of this object * depending on pEncoding->IsAutoDelete() * \param pParent parent of the font object * */ PdfFontType1Base14( PdfFontMetrics* pMetrics, const PdfEncoding* const pEncoding, PdfVecObjects* pParent ); // OC 13.08.2010 New: /** Create a new Type1 font object based on an existing PdfObject * \param pMetrics pointer to a font metrics object. The font in the PDF * file will match this fontmetrics object. The metrics object is * deleted along with the font. * \param pEncoding the encoding of this font. The font will take ownership of this object * depending on pEncoding->IsAutoDelete() * \param pObject an existing PdfObject */ PdfFontType1Base14( PdfFontMetrics* pMetrics, const PdfEncoding* const pEncoding, PdfObject* pObject ); ~PdfFontType1Base14(); protected: /** Embed the font file directly into the PDF file. * * \param pDescriptor font descriptor object */ virtual void EmbedFontFile( PdfObject* pDescriptor ); private: void InitBase14Font( PdfFontMetrics* pMetrics ); }; }; #endif // _PDF_FONT_TYPE1_BASE14_H_ podofo-0.9.3/src/doc/PdfMemDocument.cpp0000664000175000017500000004141612320241722017571 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2006 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #if defined(_MSC_VER) && _MSC_VER <= 1200 #pragma warning(disable: 4786) #endif #include #include #include #include "PdfMemDocument.h" #include "base/PdfDefinesPrivate.h" #include "base/PdfArray.h" #include "base/PdfDictionary.h" #include "base/PdfImmediateWriter.h" #include "base/PdfObject.h" #include "base/PdfParserObject.h" #include "base/PdfStream.h" #include "base/PdfVecObjects.h" #include "PdfAcroForm.h" #include "PdfDestination.h" #include "PdfFileSpec.h" #include "PdfFont.h" #include "PdfFontMetrics.h" #include "PdfInfo.h" #include "PdfNamesTree.h" #include "PdfOutlines.h" #include "PdfPage.h" #include "PdfPagesTree.h" using namespace std; namespace PoDoFo { PdfMemDocument::PdfMemDocument() : PdfDocument(), m_pEncrypt( NULL ), m_pParser( NULL ) { m_eVersion = ePdfVersion_Default; m_eWriteMode = ePdfWriteMode_Default; m_bLinearized = false; } PdfMemDocument::PdfMemDocument(bool bOnlyTrailer) : PdfDocument(bOnlyTrailer), m_pEncrypt( NULL ), m_pParser( NULL ) { m_eVersion = ePdfVersion_Default; m_eWriteMode = ePdfWriteMode_Default; m_bLinearized = false; } PdfMemDocument::PdfMemDocument( const char* pszFilename ) : PdfDocument(), m_pEncrypt( NULL ), m_pParser( NULL ) { this->Load( pszFilename ); } #ifdef _WIN32 #if defined(_MSC_VER) && _MSC_VER <= 1200 // nicht fr Visualstudio 6 #else PdfMemDocument::PdfMemDocument( const wchar_t* pszFilename ) : PdfDocument(), m_pEncrypt( NULL ), m_pParser( NULL ) { this->Load( pszFilename ); } #endif #endif // _WIN32 PdfMemDocument::~PdfMemDocument() { this->Clear(); } void PdfMemDocument::Clear() { if( m_pEncrypt ) { delete m_pEncrypt; m_pEncrypt = NULL; } if( m_pParser ) { delete m_pParser; m_pParser = NULL; } m_eWriteMode = ePdfWriteMode_Default; PdfDocument::Clear(); } void PdfMemDocument::InitFromParser( PdfParser* pParser ) { m_eVersion = pParser->GetPdfVersion(); m_bLinearized = pParser->IsLinearized(); PdfObject* pTrailer = new PdfObject( *(pParser->GetTrailer()) ); this->SetTrailer ( pTrailer ); // Set immediately as trailer // so that pTrailer has an owner // and GetIndirectKey will work if(PdfError::DebugEnabled()) { // OC 17.08.2010: Avoid using cout here: // PdfOutputDevice debug( &(std::cout) ); // pTrailer->Write( &debug ); // debug.Write("\n", 1); // OC 17.08.2010: Append Linefeed PdfRefCountedBuffer buf; PdfOutputDevice debug( &buf ); pTrailer->Write( &debug, m_eWriteMode ); debug.Write("\n", 1); // OC 17.08.2010: Append Linefeed size_t siz = buf.GetSize(); char* ptr = buf.GetBuffer(); PdfError::LogMessage(eLogSeverity_Information, "%.*s", siz, ptr); } PdfObject* pCatalog = pTrailer->GetIndirectKey( "Root" ); if( !pCatalog ) { PODOFO_RAISE_ERROR_INFO( ePdfError_NoObject, "Catalog object not found!" ); } PdfObject* pInfo = pTrailer->GetIndirectKey( "Info" ); PdfInfo* pInfoObj; if( !pInfo ) { pInfoObj = new PdfInfo( PdfDocument::GetObjects() ); pTrailer->GetDictionary().AddKey( "Info", pInfoObj->GetObject()->Reference() ); } else pInfoObj = new PdfInfo( pInfo ); if( pParser->GetEncrypted() ) { // All PdfParserObjects have a pointer to the PdfEncrypt obkect // So we have to take ownership of it. delete m_pEncrypt; m_pEncrypt = pParser->TakeEncrypt(); } this->SetCatalog ( pCatalog ); this->SetInfo ( pInfoObj ); } void PdfMemDocument::Load( const char* pszFilename ) { this->Clear(); // Call parse file instead of using the constructor // so that m_pParser is initialized for encrypted documents m_pParser = new PdfParser( PdfDocument::GetObjects() ); m_pParser->ParseFile( pszFilename, true ); InitFromParser( m_pParser ); InitPagesTree(); // Delete the temporary pdfparser object. // It is only set to m_pParser so that SetPassword can work delete m_pParser; m_pParser = NULL; } #ifdef _WIN32 #if defined(_MSC_VER) && _MSC_VER <= 1200 // nicht fr Visualstudio 6 #else void PdfMemDocument::Load( const wchar_t* pszFilename ) { this->Clear(); // Call parse file instead of using the constructor // so that m_pParser is initialized for encrypted documents m_pParser = new PdfParser( PdfDocument::GetObjects() ); m_pParser->ParseFile( pszFilename, true ); InitFromParser( m_pParser ); InitPagesTree(); // Delete the temporary pdfparser object. // It is only set to m_pParser so that SetPassword can work delete m_pParser; m_pParser = NULL; } #endif #endif // _WIN32 void PdfMemDocument::Load( const char* pBuffer, long lLen ) { this->Clear(); // Call parse file instead of using the constructor // so that m_pParser is initialized for encrypted documents m_pParser = new PdfParser( PdfDocument::GetObjects() ); m_pParser->ParseFile( pBuffer, lLen, true ); InitFromParser( m_pParser ); InitPagesTree(); // Delete the temporary pdfparser object. // It is only set to m_pParser so that SetPassword can work delete m_pParser; m_pParser = NULL; } void PdfMemDocument::Load( const PdfRefCountedInputDevice & rDevice ) { this->Clear(); // Call parse file instead of using the constructor // so that m_pParser is initialized for encrypted documents m_pParser = new PdfParser( PdfDocument::GetObjects() ); m_pParser->ParseFile( rDevice, true ); InitFromParser( m_pParser ); InitPagesTree(); // Delete the temporary pdfparser object. // It is only set to m_pParser so that SetPassword can work delete m_pParser; m_pParser = NULL; } /** Add a vendor-specific extension to the current PDF version. * \param ns namespace of the extension * \param level level of the extension */ void PdfMemDocument::AddPdfExtension( const char* ns, pdf_int64 level ) { if (!this->HasPdfExtension(ns, level)) { PdfObject* pExtensions = this->GetCatalog()->GetIndirectKey("Extensions"); PdfDictionary newExtension; newExtension.AddKey("BaseVersion", PdfName(s_szPdfVersionNums[m_eVersion])); newExtension.AddKey("ExtensionLevel", PdfVariant(level)); if (pExtensions && pExtensions->IsDictionary()) { pExtensions->GetDictionary().AddKey(ns, newExtension); } else { PdfDictionary extensions; extensions.AddKey(ns, newExtension); this->GetCatalog()->GetDictionary().AddKey("Extensions", extensions); } } } /** Checks whether the documents is tagged to imlpement a vendor-specific * extension to the current PDF version. * \param ns namespace of the extension * \param level level of the extension */ bool PdfMemDocument::HasPdfExtension( const char* ns, pdf_int64 level ) const { PdfObject* pExtensions = this->GetCatalog()->GetIndirectKey("Extensions"); if (pExtensions) { PdfObject* pExtension = pExtensions->GetIndirectKey(ns); if (pExtension) { PdfObject* pLevel = pExtension->GetIndirectKey("ExtensionLevel"); if (pLevel && pLevel->IsNumber() && pLevel->GetNumber() == level) return true; } } return false; } /** Return the list of all vendor-specific extensions to the current PDF version. * \param ns namespace of the extension * \param level level of the extension */ std::vector PdfMemDocument::GetPdfExtensions() const { std::vector result; PdfObject* pExtensions = this->GetCatalog()->GetIndirectKey("Extensions"); if (pExtensions) { // Loop through all declared extensions for (TKeyMap::const_iterator it = pExtensions->GetDictionary().GetKeys().begin(); it != pExtensions->GetDictionary().GetKeys().end(); ++it) { PdfObject *bv = it->second->GetIndirectKey("BaseVersion"); PdfObject *el = it->second->GetIndirectKey("ExtensionLevel"); if (bv && el && bv->IsName() && el->IsNumber()) { // Convert BaseVersion name to EPdfVersion for(int i=0; i<=MAX_PDF_VERSION_STRING_INDEX; i++) { if(bv->GetName().GetName() == s_szPdfVersionNums[i]) { result.push_back(PdfExtension(it->first.GetName().c_str(), static_cast(i), el->GetNumber())); } } } } } return result; } /** Remove a vendor-specific extension to the current PDF version. * \param ns namespace of the extension * \param level level of the extension */ void PdfMemDocument::RemovePdfExtension( const char* ns, pdf_int64 level ) { if (this->HasPdfExtension(ns, level)) this->GetCatalog()->GetIndirectKey("Extensions")->GetDictionary().RemoveKey("ns"); } void PdfMemDocument::SetPassword( const std::string & sPassword ) { PODOFO_RAISE_LOGIC_IF( !m_pParser, "SetPassword called without reading a PDF file." ); m_pParser->SetPassword( sPassword ); InitFromParser( m_pParser ); InitPagesTree(); } void PdfMemDocument::Write( const char* pszFilename ) { /** TODO: * We will get problems here on linux, * if we write to the same filename we read the * document from. * Because the PdfParserObjects will read there streams * data from the file while we are writing it. * The problem is that the stream data won't exist at this time * as we truncated the file already to zero length by opening * it writeable. */ // makes sure pending subset-fonts are embedded m_fontCache.EmbedSubsetFonts(); PdfOutputDevice device( pszFilename ); this->Write( &device ); } #ifdef _WIN32 void PdfMemDocument::Write( const wchar_t* pszFilename ) { /** TODO: * We will get problems here on linux, * if we write to the same filename we read the * document from. * Because the PdfParserObjects will read there streams * data from the file while we are writing it. * The problem is that the stream data won't exist at this time * as we truncated the file already to zero length by opening * it writeable. */ PdfOutputDevice device( pszFilename ); this->Write( &device ); } #endif // _WIN32 void PdfMemDocument::Write( PdfOutputDevice* pDevice ) { /** TODO: * We will get problems here on linux, * if we write to the same filename we read the * document from. * Because the PdfParserObjects will read there streams * data from the file while we are writing it. * The problem is that the stream data won't exist at this time * as we truncated the file already to zero length by opening * it writeable. */ PdfWriter writer( &(this->GetObjects()), this->GetTrailer() ); writer.SetPdfVersion( this->GetPdfVersion() ); writer.SetWriteMode( m_eWriteMode ); if( m_pEncrypt ) writer.SetEncrypted( *m_pEncrypt ); writer.Write( pDevice ); } PdfObject* PdfMemDocument::GetNamedObjectFromCatalog( const char* pszName ) const { return this->GetCatalog()->GetIndirectKey( PdfName( pszName ) ); } void PdfMemDocument::DeletePages( int inFirstPage, int inNumPages ) { for( int i = 0 ; i < inNumPages ; i++ ) { this->GetPagesTree()->DeletePage( inFirstPage ) ; } } const PdfMemDocument & PdfMemDocument::InsertPages( const PdfMemDocument & rDoc, int inFirstPage, int inNumPages ) { /* This function works a bit different than one might expect. Rather than copying one page at a time - we copy the ENTIRE document and then delete the pages we aren't interested in. We do this because 1) SIGNIFICANTLY simplifies the process 2) Guarantees that shared objects aren't copied multiple times 3) offers MUCH faster performance for the common cases HOWEVER: because PoDoFo doesn't currently do any sort of "object garbage collection" during a Write() - we will end up with larger documents, since the data from unused pages will also be in there. */ // calculate preliminary "left" and "right" page ranges to delete // then offset them based on where the pages were inserted // NOTE: some of this will change if/when we support insertion at locations // OTHER than the end of the document! int leftStartPage = 0 ; int leftCount = inFirstPage ; int rightStartPage = inFirstPage + inNumPages ; int rightCount = rDoc.GetPageCount() - rightStartPage ; int pageOffset = this->GetPageCount(); leftStartPage += pageOffset ; rightStartPage += pageOffset ; // append in the whole document this->Append( rDoc ); // delete if( rightCount > 0 ) this->DeletePages( rightStartPage, rightCount ) ; if( leftCount > 0 ) this->DeletePages( leftStartPage, leftCount ) ; return *this; } void PdfMemDocument::SetEncrypted( const std::string & userPassword, const std::string & ownerPassword, int protection, PdfEncrypt::EPdfEncryptAlgorithm eAlgorithm, PdfEncrypt::EPdfKeyLength eKeyLength ) { delete m_pEncrypt; m_pEncrypt = PdfEncrypt::CreatePdfEncrypt( userPassword, ownerPassword, protection, eAlgorithm, eKeyLength ); } void PdfMemDocument::SetEncrypted( const PdfEncrypt & pEncrypt ) { delete m_pEncrypt; m_pEncrypt = PdfEncrypt::CreatePdfEncrypt( pEncrypt ); } PdfFont* PdfMemDocument::GetFont( PdfObject* pObject ) { return m_fontCache.GetFont( pObject ); } void PdfMemDocument::FreeObjectMemory( const PdfReference & rRef, bool bForce ) { FreeObjectMemory( this->GetObjects().GetObject( rRef ), bForce ); } void PdfMemDocument::FreeObjectMemory( PdfObject* pObj, bool bForce ) { if( !pObj ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } PdfParserObject* pParserObject = dynamic_cast(pObj); if( !pParserObject ) { PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidHandle, "FreeObjectMemory works only on classes of type PdfParserObject." ); } pParserObject->FreeObjectMemory( bForce ); } }; podofo-0.9.3/src/doc/PdfDifferenceEncoding.h0000664000175000017500000003254512347277655020554 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2008 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_DIFFERENCE_ENCODING_H_ #define _PDF_DIFFERENCE_ENCODING_H_ #include "podofo/base/PdfDefines.h" #include "podofo/base/PdfEncoding.h" #include "PdfElement.h" #include namespace PoDoFo { /** A helper class for PdfDifferenceEncoding that * can be used to create a differences array. */ class PODOFO_DOC_API PdfEncodingDifference { struct TDifference { int nCode; PdfName name; pdf_utf16be unicodeValue; }; typedef std::vector TVecDifferences; typedef std::vector::iterator TIVecDifferences; typedef std::vector::const_iterator TCIVecDifferences; public: /** Create a PdfEncodingDifference object. */ PdfEncodingDifference(); /** Copy a PdfEncodingDifference object. */ PdfEncodingDifference( const PdfEncodingDifference & rhs ); /** Copy a PdfEncodingDifference object. */ const PdfEncodingDifference & operator=( const PdfEncodingDifference & rhs ); /** Add a difference to the object. * * \param nCode unicode code point of the difference (0 to 255 are legal values) * \param unicodeValue actual unicode value for nCode; can be 0 * * \see AddDifference if you know the name of the code point * use the overload below which is faster */ void AddDifference( int nCode, pdf_utf16be unicodeValue ); /** Add a difference to the object. * * \param nCode unicode code point of the difference (0 to 255 are legal values) * \param unicodeValue actual unicode value for nCode; can be 0 * \param rName name of the different code point or .notdef if none * \param bExplicitKeys if true, the unicode value is set to nCode as rName is meaningless (Type3 fonts) */ void AddDifference( int nCode, pdf_utf16be unicodeValue, const PdfName & rName, bool bExplicitNames = false ); /** Tests if the specified code is part of the * differences. * * \param nCode test if the given code is part of the differences * \param rName write the associated name into this object if the * code is part of the difference * \param rValue write the associated unicode value of the name to this value * * \returns true if the code is part of the difference */ bool Contains( int nCode, PdfName & rName, pdf_utf16be & rValue ) const; bool ContainsUnicodeValue( pdf_utf16be unicodeValue, char &rValue ) const; /** Convert the PdfEncodingDifference to an array * * \param rArray write to this array */ void ToArray( PdfArray & rArray ); /** Get the number of differences in this object. * If the user added .notdef as a difference it is * counted, even it is no real difference in the final encoding. * * \returns the number of differences in this object */ inline size_t GetCount() const; private: struct DifferenceComparatorPredicate { public: inline bool operator()( const TDifference & rDif1, const TDifference & rDif2 ) const { return rDif1.nCode < rDif2.nCode; } }; TVecDifferences m_vecDifferences; }; // ----------------------------------------------------- // // ----------------------------------------------------- inline size_t PdfEncodingDifference::GetCount() const { return m_vecDifferences.size(); } /** PdfDifferenceEncoding is an encoding, which is based * on either the fonts encoding or a predefined encoding * and defines differences to this base encoding. */ class PODOFO_DOC_API PdfDifferenceEncoding : public PdfEncoding, private PdfElement { public: /** * Defines the base encoding from which a * PdfDifferenceEncoding differs. */ enum EBaseEncoding { eBaseEncoding_Font, ///< Use The fonts encoding as base eBaseEncoding_WinAnsi, ///< Use WinAnsiEncoding as base encoding eBaseEncoding_MacRoman, ///< Use MacRomanEncoding as base encoding eBaseEncoding_MacExpert ///< Use MacExpertEncoding as base encoding }; /** Create a new PdfDifferenceEncoding which is based on * the fonts encoding. * * \param rDifference the differences in this encoding * \param pParent parent PdfVecObjects. * Add a newly created object to this vector. * \param bAutoDelete if true the encoding is deleted by its owning font */ PdfDifferenceEncoding( const PdfEncodingDifference & rDifference, PdfDocument* pParent, bool bAutoDelete = true ); /** Create a new PdfDifferenceEncoding which is based on * the fonts encoding. * * \param rDifference the differences in this encoding * \param pParent parent PdfDocument. * Add a newly created object to this vector. * \param bAutoDelete if true the encoding is deleted by its owning font */ PdfDifferenceEncoding( const PdfEncodingDifference & rDifference, PdfVecObjects* pParent, bool bAutoDelete = true ); /** Create a new PdfDifferenceEncoding which is based on * a predefined encoding. * * \param rDifference the differences in this encoding * \param eBaseEncoding the base encoding of this font * \param pParent parent PdfDocument. * Add a newly created object to this vector. * \param bAutoDelete if true the encoding is deleted by its owning font */ PdfDifferenceEncoding( const PdfEncodingDifference & rDifference, EBaseEncoding eBaseEncoding, PdfDocument* pParent, bool bAutoDelete = true ); /** Create a new PdfDifferenceEncoding which is based on * a predefined encoding. * * \param rDifference the differences in this encoding * \param eBaseEncoding the base encoding of this font * \param pParent parent PdfVecObjects. * Add a newly created object to this vector. * \param bAutoDelete if true the encoding is deleted by its owning font */ PdfDifferenceEncoding( const PdfEncodingDifference & rDifference, EBaseEncoding eBaseEncoding, PdfVecObjects* pParent, bool bAutoDelete = true ); /** Create a new PdfDifferenceEncoding from an existing object * in a PDF file. * * \param pObject an existing differences encoding * \param bAutoDelete if true the encoding is deleted by its owning font * \param bExplicitNames if true, glyph names are meaningless explicit keys on the font (used for Type3 fonts) */ PdfDifferenceEncoding( PdfObject* pObject, bool bAutoDelete = true, bool bExplicitNames = false ); /** Convert a standard character name to a unicode code point * * \param rName a standard character name * \returns an unicode code point */ static pdf_utf16be NameToUnicodeID( const PdfName & rName ); /** Convert an unicode code point to a standard character name * * \param inCodePoint a code point * \returns a standard character name of /.notdef if none could be found */ static PdfName UnicodeIDToName( pdf_utf16be inCodePoint ); /** Add this encoding object to a dictionary * usually be adding an /Encoding key in font dictionaries. * * \param rDictionary add the encoding to this dictionary */ virtual void AddToDictionary( PdfDictionary & rDictionary ) const; /** Convert a string that is encoded with this encoding * to an unicode PdfString. * * \param rEncodedString a string encoded by this encoding. * Usually this string was read from a content stream. * \param pFont the font for which this string is converted * * \returns an unicode PdfString. */ virtual PdfString ConvertToUnicode( const PdfString & rEncodedString, const PdfFont* pFont ) const; /** Convert a unicode PdfString to a string encoded with this encoding. * * \param rString an unicode PdfString. * \param pFont the font for which this string is converted * * \returns an encoded PdfRefCountedBuffer. The PdfRefCountedBuffer is treated as a series of bytes * and is allowed to have 0 bytes. The returned buffer must not be a unicode string. */ virtual PdfRefCountedBuffer ConvertToEncoding( const PdfString & rString, const PdfFont* pFont ) const; /** * \returns true if this encoding should be deleted automatically with the * font. */ virtual bool IsAutoDelete() const; /** * \returns true if this is a single byte encoding with a maximum of 256 values. */ virtual bool IsSingleByteEncoding() const; /** * Get read-only access to the object containing the actual * differences. * * \returns the container with the actual differences */ inline const PdfEncodingDifference & GetDifferences() const; /** Get the unicode character code for this encoding * at the position nIndex. nIndex is a position between * GetFirstChar() and GetLastChar() * * \param nIndex character code at position index * \returns unicode character code * * \see GetFirstChar * \see GetLastChar * * Will throw an exception if nIndex is out of range. */ virtual pdf_utf16be GetCharCode( int nIndex ) const; protected: /** Get a unique ID for this encoding * which can used for comparisons! * * \returns a unique id for this encoding! */ virtual const PdfName & GetID() const; private: /** Initialize this object */ void Init(); /** Create a unique ID for this encoding */ void CreateID(); /** Get an object of type baseencoding * * \returns a base encoding */ const PdfEncoding* GetBaseEncoding() const; private: PdfEncodingDifference m_differences; bool m_bAutoDelete; ///< If true this encoding is deleted by its font. PdfName m_id; ///< Unique ID of this encoding EBaseEncoding m_baseEncoding; ///< The base encoding of this font }; // ----------------------------------------------------- // // ----------------------------------------------------- inline const PdfName & PdfDifferenceEncoding::GetID() const { return m_id; } // ----------------------------------------------------- // // ----------------------------------------------------- inline bool PdfDifferenceEncoding::IsAutoDelete() const { return m_bAutoDelete; } // ----------------------------------------------------- // // ----------------------------------------------------- inline bool PdfDifferenceEncoding::IsSingleByteEncoding() const { return true; } // ----------------------------------------------------- // // ----------------------------------------------------- inline const PdfEncodingDifference & PdfDifferenceEncoding::GetDifferences() const { return m_differences; } }; /* PoDoFo */ #endif // _PDF_DIFFERENCE_ENCODING_H_ podofo-0.9.3/src/doc/PdfElement.cpp0000664000175000017500000001111512344436402016745 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2006 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfElement.h" #include "base/PdfDefinesPrivate.h" #include "base/PdfDictionary.h" #include "base/PdfObject.h" #include "base/PdfVecObjects.h" #include "PdfStreamedDocument.h" #include namespace PoDoFo { PdfElement::PdfElement( const char* pszType, PdfVecObjects* pParent ) { m_pObject = pParent->CreateObject( pszType ); } PdfElement::PdfElement( const char* pszType, PdfDocument* pParent ) { m_pObject = pParent->m_vecObjects.CreateObject( pszType ); } PdfElement::PdfElement( const char* pszType, PdfObject* pObject ) { if( !pObject ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } m_pObject = pObject; if( !m_pObject->IsDictionary() ) { PODOFO_RAISE_ERROR( ePdfError_InvalidDataType ); } if( pszType && m_pObject->GetDictionary().HasKey( PdfName::KeyType ) && m_pObject->GetDictionary().GetKeyAsName( PdfName::KeyType ) != pszType ) { PdfError::LogMessage( eLogSeverity_Debug, "Expected key %s but got key %s.", pszType, m_pObject->GetDictionary().GetKeyAsName( PdfName::KeyType ).GetName().c_str() ); PODOFO_RAISE_ERROR( ePdfError_InvalidDataType ); } } PdfElement::PdfElement( EPdfDataType eExpectedDataType, PdfObject* pObject ) { if( !pObject ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } m_pObject = pObject; if( m_pObject->GetDataType() != eExpectedDataType ) { PODOFO_RAISE_ERROR( ePdfError_InvalidDataType ); } } PdfElement::~PdfElement() { } const char* PdfElement::TypeNameForIndex( int i, const char** ppTypes, long lLen ) const { return ( i >= lLen ? NULL : ppTypes[i] ); } int PdfElement::TypeNameToIndex( const char* pszType, const char** ppTypes, long lLen, int nUnknownValue ) const { int i; if( !pszType ) return nUnknownValue; for( i=0; iGetOwner()->CreateObject( pszType ); } }; podofo-0.9.3/src/doc/PdfFileSpec.cpp0000664000175000017500000002703712347313527017065 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2006 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfFileSpec.h" #include "base/PdfDefinesPrivate.h" #include "base/PdfDictionary.h" #include "base/PdfInputStream.h" #include "base/PdfObject.h" #include "base/PdfStream.h" #include namespace PoDoFo { PdfFileSpec::PdfFileSpec( const char* pszFilename, bool bEmbedd, PdfDocument* pParent, bool bStripPath) : PdfElement( "Filespec", pParent ) { Init( pszFilename, bEmbedd, bStripPath ); } PdfFileSpec::PdfFileSpec( const char* pszFilename, bool bEmbedd, PdfVecObjects* pParent, bool bStripPath) : PdfElement( "Filespec", pParent ) { Init( pszFilename, bEmbedd, bStripPath ); } PdfFileSpec::PdfFileSpec( const char* pszFilename, const unsigned char* data, ptrdiff_t size, PdfVecObjects* pParent, bool bStripPath) : PdfElement( "Filespec", pParent ) { Init( pszFilename, data, size, bStripPath ); } PdfFileSpec::PdfFileSpec( const char* pszFilename, const unsigned char* data, ptrdiff_t size, PdfDocument* pParent, bool bStripPath) : PdfElement( "Filespec", pParent ) { Init( pszFilename, data, size, bStripPath ); } PdfFileSpec::PdfFileSpec( PdfObject* pObject ) : PdfElement( "Filespec", pObject ) { } #ifdef _WIN32 PdfFileSpec::PdfFileSpec( const wchar_t* pszFilename, bool bEmbedd, PdfDocument* pParent, bool bStripPath) : PdfElement( "Filespec", pParent ) { Init( pszFilename, bEmbedd, bStripPath ); } PdfFileSpec::PdfFileSpec( const wchar_t* pszFilename, bool bEmbedd, PdfVecObjects* pParent, bool bStripPath) : PdfElement( "Filespec", pParent ) { Init( pszFilename, bEmbedd, bStripPath ); } PdfFileSpec::PdfFileSpec( const wchar_t* pszFilename, const unsigned char* data, ptrdiff_t size, PdfVecObjects* pParent, bool bStripPath) : PdfElement( "Filespec", pParent ) { Init( pszFilename, data, size, bStripPath ); } PdfFileSpec::PdfFileSpec( const wchar_t* pszFilename, const unsigned char* data, ptrdiff_t size, PdfDocument* pParent, bool bStripPath) : PdfElement( "Filespec", pParent ) { Init( pszFilename, data, size, bStripPath ); } void PdfFileSpec::Init( const wchar_t* pszFilename, bool bEmbedd, bool bStripPath) { PdfObject* pEmbeddedStream; PdfString filename; filename.setFromWchar_t( MaybeStripPath( pszFilename, true) ); this->GetObject()->GetDictionary().AddKey( "F", this->CreateFileSpecification( MaybeStripPath( pszFilename, bStripPath ) ) ); this->GetObject()->GetDictionary().AddKey( "UF", filename.ToUnicode () ); if( bEmbedd ) { PdfDictionary ef; pEmbeddedStream = this->CreateObject( "EmbeddedFile" ); this->EmbeddFile( pEmbeddedStream, pszFilename ); ef.AddKey( "F", pEmbeddedStream->Reference() ); this->GetObject()->GetDictionary().AddKey( "EF", ef ); } } void PdfFileSpec::Init( const wchar_t* pszFilename, const unsigned char* data, ptrdiff_t size, bool bStripPath) { PdfObject* pEmbeddedStream; PdfString filename; filename.setFromWchar_t( MaybeStripPath( pszFilename, true) ); this->GetObject()->GetDictionary().AddKey( "F", this->CreateFileSpecification( MaybeStripPath( pszFilename, bStripPath ) ) ); this->GetObject()->GetDictionary().AddKey( "UF", filename.ToUnicode() ); PdfDictionary ef; pEmbeddedStream = this->CreateObject( "EmbeddedFile" ); this->EmbeddFileFromMem( pEmbeddedStream, data, size ); ef.AddKey( "F", pEmbeddedStream->Reference() ); this->GetObject()->GetDictionary().AddKey( "EF", ef ); } PdfString PdfFileSpec::CreateFileSpecification( const wchar_t* pszFilename ) const { std::ostringstream str; size_t nLen = wcslen( pszFilename ); char buff[5]; // Construct a platform independent file specifier for( size_t i=0;i= L'a' && ch <= L'z') || (ch >= L'A' && ch <= L'Z') || (ch >= L'0' && ch <= L'9') || ch == L'_') { str.put( ch & 0xFF ); } else if (ch == L'/') { str.put( '\\' ); str.put( '\\' ); str.put( '/' ); } else { sprintf(buff, "%04X", ch & 0xFFFF); str << buff; } } return PdfString( str.str() ); } void PdfFileSpec::EmbeddFile( PdfObject* pStream, const wchar_t* pszFilename ) const { PdfFileInputStream stream( pszFilename ); pStream->GetStream()->Set( &stream ); // Add additional information about the embedded file to the stream PdfDictionary params; params.AddKey( "Size", static_cast(stream.GetFileLength()) ); // TODO: CreationDate and ModDate pStream->GetDictionary().AddKey("Params", params ); } const wchar_t *PdfFileSpec::MaybeStripPath( const wchar_t* pszFilename, bool bStripPath ) const { if (!bStripPath) { return pszFilename; } const wchar_t *lastFrom = pszFilename; while (pszFilename && *pszFilename) { if ( #ifdef _WIN32 *pszFilename == L':' || *pszFilename == L'\\' || #endif // _WIN32 *pszFilename == L'/') { lastFrom = pszFilename + 1; } pszFilename++; } return lastFrom; } #endif // _WIN32 void PdfFileSpec::Init( const char* pszFilename, bool bEmbedd, bool bStripPath ) { PdfObject* pEmbeddedStream; PdfString filename( MaybeStripPath( pszFilename, true) ); this->GetObject()->GetDictionary().AddKey( "F", this->CreateFileSpecification( MaybeStripPath( pszFilename, bStripPath ) ) ); this->GetObject()->GetDictionary().AddKey( "UF", filename.ToUnicode () ); if( bEmbedd ) { PdfDictionary ef; pEmbeddedStream = this->CreateObject( "EmbeddedFile" ); this->EmbeddFile( pEmbeddedStream, pszFilename ); ef.AddKey( "F", pEmbeddedStream->Reference() ); this->GetObject()->GetDictionary().AddKey( "EF", ef ); } } void PdfFileSpec::Init( const char* pszFilename, const unsigned char* data, ptrdiff_t size, bool bStripPath ) { PdfObject* pEmbeddedStream; PdfString filename( MaybeStripPath( pszFilename, true) ); this->GetObject()->GetDictionary().AddKey( "F", this->CreateFileSpecification( MaybeStripPath( pszFilename, bStripPath) ) ); this->GetObject()->GetDictionary().AddKey( "UF", filename.ToUnicode () ); PdfDictionary ef; pEmbeddedStream = this->CreateObject( "EmbeddedFile" ); this->EmbeddFileFromMem( pEmbeddedStream, data, size ); ef.AddKey( "F", pEmbeddedStream->Reference() ); this->GetObject()->GetDictionary().AddKey( "EF", ef ); } PdfString PdfFileSpec::CreateFileSpecification( const char* pszFilename ) const { std::ostringstream str; size_t nLen = strlen( pszFilename ); char buff[5]; // Construct a platform independent file specifier for( size_t i=0;i= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9') || ch == '_') { str.put( ch & 0xFF ); } else if (ch == '/') { str.put( '\\' ); str.put( '\\' ); str.put( '/' ); } else { sprintf(buff, "%02X", ch & 0xFF); str << buff; } } return PdfString( str.str() ); } void PdfFileSpec::EmbeddFile( PdfObject* pStream, const char* pszFilename ) const { PdfFileInputStream stream( pszFilename ); pStream->GetStream()->Set( &stream ); // Add additional information about the embedded file to the stream PdfDictionary params; params.AddKey( "Size", static_cast(stream.GetFileLength()) ); // TODO: CreationDate and ModDate pStream->GetDictionary().AddKey("Params", params ); } const char *PdfFileSpec::MaybeStripPath( const char* pszFilename, bool bStripPath ) const { if (!bStripPath) { return pszFilename; } const char *lastFrom = pszFilename; while (pszFilename && *pszFilename) { if ( #ifdef _WIN32 *pszFilename == ':' || *pszFilename == '\\' || #endif // _WIN32 *pszFilename == '/') { lastFrom = pszFilename + 1; } pszFilename++; } return lastFrom; } void PdfFileSpec::EmbeddFileFromMem( PdfObject* pStream, const unsigned char* data, ptrdiff_t size ) const { PdfMemoryInputStream memstream(reinterpret_cast(data),size); pStream->GetStream()->Set( &memstream ); // Add additional information about the embedded file to the stream PdfDictionary params; params.AddKey( "Size", static_cast(size) ); pStream->GetDictionary().AddKey("Params", params ); } const PdfString & PdfFileSpec::GetFilename(bool canUnicode) const { if( canUnicode && this->GetObject()->GetDictionary().HasKey( "UF" ) ) { return this->GetObject()->GetDictionary().GetKey( "UF" )->GetString(); } if( this->GetObject()->GetDictionary().HasKey( "F" ) ) { return this->GetObject()->GetDictionary().GetKey( "F" )->GetString(); } PODOFO_RAISE_ERROR( ePdfError_InvalidDataType ); } }; podofo-0.9.3/src/doc/PdfContents.h0000664000175000017500000000763212344436402016627 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2006 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_CONTENTS_H_ #define _PDF_CONTENTS_H_ #include "podofo/base/PdfDefines.h" #include "PdfElement.h" namespace PoDoFo { class PdfObject; class PdfPage; /** A interface that provides a wrapper around "PDF content" - the instructions that are used to draw on the PDF "canvas". */ class PODOFO_DOC_API PdfContents : private PdfElement { public: /** Construct a new/empty set of contents in the owning objects */ PdfContents( PdfDocument* pParent ); /** Construct a new/empty set of contents in the owning objects */ PdfContents( PdfVecObjects* pParent ); /** Construct the contents from an existing PdfObject */ PdfContents( PdfObject* inObj ); /** Create the contents for an existing page which does not yet * have a contents object. * * \param pParent a /Contents key will be added to this page * and a contents object will be created. */ PdfContents( PdfPage* pParent ); /** Virtual destructor - because ALL destructors should be... */ virtual ~PdfContents() {}; /** Get access to the raw contents object. * It will either be a PdfStream or a PdfArray * \returns a contents object */ virtual PdfObject* GetContents() const { return mContObj; } /** Get access to an object into which you can add contents * at the end of the "stream". */ virtual PdfObject* GetContentsForAppending() const; private: PdfObject* mContObj; }; }; #endif /* _PDF_CONTENTS_H_ */ podofo-0.9.3/src/doc/PdfDocument.cpp0000664000175000017500000010065312347312750017142 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2006 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #if defined(_MSC_VER) && _MSC_VER <= 1200 #pragma warning(disable: 4786) #endif #include #include #include #include "PdfDocument.h" #include "base/PdfDefinesPrivate.h" #include "base/PdfArray.h" #include "base/PdfDictionary.h" #include "base/PdfImmediateWriter.h" #include "base/PdfObject.h" #include "base/PdfStream.h" #include "base/PdfVecObjects.h" #include "PdfAcroForm.h" #include "PdfDestination.h" #include "PdfFileSpec.h" #include "PdfFont.h" #include "PdfFontMetrics.h" #include "PdfInfo.h" #include "PdfMemDocument.h" #include "PdfNamesTree.h" #include "PdfOutlines.h" #include "PdfPage.h" #include "PdfPagesTree.h" #include "PdfXObject.h" using namespace std; namespace PoDoFo { PdfDocument::PdfDocument(bool bEmpty) : m_fontCache( &m_vecObjects ), m_pTrailer(NULL), m_pCatalog(NULL), m_pInfo(NULL), m_pPagesTree( NULL ), m_pAcroForms( NULL ), m_pOutlines( NULL ), m_pNamesTree( NULL ) { m_vecObjects.SetParentDocument( this ); if( !bEmpty ) { m_pTrailer = new PdfObject(); // The trailer is NO part of the vector of objects m_pTrailer->SetOwner( &m_vecObjects ); m_pCatalog = m_vecObjects.CreateObject( "Catalog" ); m_pInfo = new PdfInfo( &m_vecObjects ); m_pTrailer->GetDictionary().AddKey( "Root", m_pCatalog->Reference() ); m_pTrailer->GetDictionary().AddKey( "Info", m_pInfo->GetObject()->Reference() ); InitPagesTree(); } } PdfDocument::~PdfDocument() { this->Clear(); } void PdfDocument::Clear() { TIVecObjects it = m_vecObjects.begin(); m_fontCache.EmptyCache(); while( it != m_vecObjects.end() ) { delete (*it); ++it; } m_vecObjects.Clear(); m_vecObjects.SetParentDocument( this ); if( m_pInfo ) { delete m_pInfo; m_pInfo = NULL; } if( m_pNamesTree ) { delete m_pNamesTree; m_pNamesTree = NULL; } if( m_pPagesTree ) { delete m_pPagesTree; m_pPagesTree = NULL; } if( m_pOutlines ) { delete m_pOutlines; m_pOutlines = NULL; } if( m_pAcroForms ) { delete m_pAcroForms; m_pAcroForms = NULL; } if( m_pTrailer ) { delete m_pTrailer; m_pTrailer = NULL; } m_pCatalog = NULL; } void PdfDocument::InitPagesTree() { PdfObject* pagesRootObj = this->GetCatalog()->GetIndirectKey( PdfName( "Pages" ) ); if ( pagesRootObj ) { m_pPagesTree = new PdfPagesTree( pagesRootObj ); } else { m_pPagesTree = new PdfPagesTree( &m_vecObjects ); m_pCatalog->GetDictionary().AddKey( "Pages", m_pPagesTree->GetObject()->Reference() ); } } PdfObject* PdfDocument::GetNamedObjectFromCatalog( const char* pszName ) const { return m_pCatalog->GetIndirectKey( PdfName( pszName ) ); } int PdfDocument::GetPageCount() const { return m_pPagesTree->GetTotalNumberOfPages(); } PdfPage* PdfDocument::GetPage( int nIndex ) const { if( nIndex < 0 || nIndex >= m_pPagesTree->GetTotalNumberOfPages() ) { PODOFO_RAISE_ERROR( ePdfError_PageNotFound ); } return m_pPagesTree->GetPage( nIndex ); } PdfFont* PdfDocument::CreateFont( const char* pszFontName, bool bSymbolCharset, const PdfEncoding * const pEncoding, PdfFontCache::EFontCreationFlags eFontCreationFlags, bool bEmbedd ) { return m_fontCache.GetFont( pszFontName, false, false, bSymbolCharset, bEmbedd, eFontCreationFlags, pEncoding ); } PdfFont* PdfDocument::CreateFont( const char* pszFontName, bool bBold, bool bItalic, bool bSymbolCharset, const PdfEncoding * const pEncoding, PdfFontCache::EFontCreationFlags eFontCreationFlags, bool bEmbedd, const char* pszFileName ) { return m_fontCache.GetFont( pszFontName, bBold, bItalic, bSymbolCharset, bEmbedd, eFontCreationFlags, pEncoding, pszFileName ); } #if defined(_WIN32) && !defined(PODOFO_NO_FONTMANAGER) PdfFont* PdfDocument::CreateFont( const wchar_t* pszFontName, bool bSymbolCharset, const PdfEncoding * const pEncoding, bool bEmbedd ) { return m_fontCache.GetFont( pszFontName, false, false, bSymbolCharset, bEmbedd, pEncoding ); } PdfFont* PdfDocument::CreateFont( const wchar_t* pszFontName, bool bBold, bool bItalic, bool bSymbolCharset, const PdfEncoding * const pEncoding, bool bEmbedd ) { return m_fontCache.GetFont( pszFontName, bBold, bItalic, bSymbolCharset, bEmbedd, pEncoding ); } PdfFont* PdfDocument::CreateFont( const LOGFONTA &logFont, const PdfEncoding * const pEncoding, bool bEmbedd ) { return m_fontCache.GetFont( logFont, bEmbedd, pEncoding ); } PdfFont* PdfDocument::CreateFont( const LOGFONTW &logFont, const PdfEncoding * const pEncoding, bool bEmbedd ) { return m_fontCache.GetFont( logFont, bEmbedd, pEncoding ); } #endif // _WIN32 PdfFont* PdfDocument::CreateFontSubset( const char* pszFontName, bool bBold, bool bItalic, bool bSymbolCharset, const PdfEncoding * const pEncoding, const char* pszFileName ) { return m_fontCache.GetFontSubset( pszFontName, bBold, bItalic, bSymbolCharset, pEncoding, pszFileName ); } #if defined(_WIN32) && !defined(PODOFO_NO_FONTMANAGER) PdfFont* PdfDocument::CreateFontSubset( const wchar_t* pszFontName, bool bBold, bool bItalic, bool bSymbolCharset, const PdfEncoding * const pEncoding) { PODOFO_RAISE_ERROR_INFO( ePdfError_Unknown, "Subsets are not yet implemented for unicode on windows." ); } #endif // _WIN32 PdfFont* PdfDocument::CreateFont( FT_Face face, bool bSymbolCharset, const PdfEncoding * const pEncoding, bool bEmbedd ) { return m_fontCache.GetFont( face, bSymbolCharset, bEmbedd, pEncoding ); } PdfFont* PdfDocument::CreateDuplicateFontType1( PdfFont * pFont, const char * pszSuffix ) { return m_fontCache.GetDuplicateFontType1( pFont, pszSuffix ); } PdfPage* PdfDocument::CreatePage( const PdfRect & rSize ) { return m_pPagesTree->CreatePage( rSize ); } void PdfDocument::CreatePages( const std::vector& vecSizes ) { m_pPagesTree->CreatePages( vecSizes ); } PdfPage* PdfDocument::InsertPage( const PdfRect & rSize, int atIndex) { return m_pPagesTree->InsertPage( rSize, atIndex ); } void PdfDocument::EmbedSubsetFonts() { m_fontCache.EmbedSubsetFonts(); } const PdfDocument & PdfDocument::Append( const PdfMemDocument & rDoc, bool bAppendAll ) { unsigned int difference = static_cast(m_vecObjects.GetSize() + m_vecObjects.GetFreeObjects().size()); // Ulrich Arnold 30.7.2009: Because GetNextObject uses m_nObjectCount instead // of m_vecObjects.GetSize()+m_vecObjects.GetFreeObjects().size()+1 // make sure the free objects are already present before appending to // prevent overlapping obj-numbers // create all free objects again, to have a clean free object list TCIPdfReferenceList itFree = rDoc.GetObjects().GetFreeObjects().begin(); while( itFree != rDoc.GetObjects().GetFreeObjects().end() ) { m_vecObjects.AddFreeObject( PdfReference( (*itFree).ObjectNumber() + difference, (*itFree).GenerationNumber() ) ); ++itFree; } // append all objects first and fix their references TCIVecObjects it = rDoc.GetObjects().begin(); while( it != rDoc.GetObjects().end() ) { PdfObject* pObj = new PdfObject( PdfReference( static_cast((*it)->Reference().ObjectNumber() + difference), (*it)->Reference().GenerationNumber() ), *(*it) ); m_vecObjects.push_back( pObj ); if( (*it)->IsDictionary() && (*it)->HasStream() ) *(pObj->GetStream()) = *((*it)->GetStream()); PdfError::LogMessage( eLogSeverity_Information, "Fixing references in %i %i R by %i\n", pObj->Reference().ObjectNumber(), pObj->Reference().GenerationNumber(), difference ); FixObjectReferences( pObj, difference ); ++it; } if( bAppendAll ) { const PdfName inheritableAttributes[] = { PdfName("Resources"), PdfName("MediaBox"), PdfName("CropBox"), PdfName("Rotate"), PdfName::KeyNull }; // append all pages now to our page tree for(int i=0;iGetObject()->Reference().ObjectNumber() + difference, pPage->GetObject()->Reference().GenerationNumber() ) ); if( pObj->IsDictionary() && pObj->GetDictionary().HasKey( "Parent" ) ) pObj->GetDictionary().RemoveKey( "Parent" ); // Deal with inherited attributes const PdfName* pInherited = inheritableAttributes; while( pInherited->GetLength() != 0 ) { const PdfObject* pAttribute = pPage->GetInheritedKey( *pInherited ); if( pAttribute ) { PdfObject attribute( *pAttribute ); FixObjectReferences( &attribute, difference ); pObj->GetDictionary().AddKey( *pInherited, attribute ); } ++pInherited; } m_pPagesTree->InsertPage( this->GetPageCount()-1, pObj ); } // append all outlines PdfOutlineItem* pRoot = this->GetOutlines(); PdfOutlines* pAppendRoot = const_cast(rDoc).GetOutlines( PoDoFo::ePdfDontCreateObject ); if( pAppendRoot && pAppendRoot->First() ) { // only append outlines if appended document has outlines while( pRoot && pRoot->Next() ) pRoot = pRoot->Next(); PdfReference ref( pAppendRoot->First()->GetObject()->Reference().ObjectNumber() + difference, pAppendRoot->First()->GetObject()->Reference().GenerationNumber() ); pRoot->InsertChild( new PdfOutlines( m_vecObjects.GetObject( ref ) ) ); } } // TODO: merge name trees // ToDictionary -> then iteratate over all keys and add them to the new one return *this; } const PdfDocument &PdfDocument::InsertExistingPageAt( const PdfMemDocument & rDoc, int nPageIndex, int nAtIndex) { /* copy of PdfDocument::Append, only restricts which page to add */ unsigned int difference = static_cast(m_vecObjects.GetSize() + m_vecObjects.GetFreeObjects().size()); // Ulrich Arnold 30.7.2009: Because GetNextObject uses m_nObjectCount instead // of m_vecObjects.GetSize()+m_vecObjects.GetFreeObjects().size()+1 // make sure the free objects are already present before appending to // prevent overlapping obj-numbers // create all free objects again, to have a clean free object list TCIPdfReferenceList itFree = rDoc.GetObjects().GetFreeObjects().begin(); while( itFree != rDoc.GetObjects().GetFreeObjects().end() ) { m_vecObjects.AddFreeObject( PdfReference( (*itFree).ObjectNumber() + difference, (*itFree).GenerationNumber() ) ); ++itFree; } // append all objects first and fix their references TCIVecObjects it = rDoc.GetObjects().begin(); while( it != rDoc.GetObjects().end() ) { PdfObject* pObj = new PdfObject( PdfReference( static_cast((*it)->Reference().ObjectNumber() + difference), (*it)->Reference().GenerationNumber() ), *(*it) ); m_vecObjects.push_back( pObj ); if( (*it)->IsDictionary() && (*it)->HasStream() ) *(pObj->GetStream()) = *((*it)->GetStream()); PdfError::LogMessage( eLogSeverity_Information, "Fixing references in %i %i R by %i\n", pObj->Reference().ObjectNumber(), pObj->Reference().GenerationNumber(), difference ); FixObjectReferences( pObj, difference ); ++it; } const PdfName inheritableAttributes[] = { PdfName("Resources"), PdfName("MediaBox"), PdfName("CropBox"), PdfName("Rotate"), PdfName::KeyNull }; // append all pages now to our page tree for(int i=0;iGetObject()->Reference().ObjectNumber() + difference, pPage->GetObject()->Reference().GenerationNumber() ) ); if( pObj->IsDictionary() && pObj->GetDictionary().HasKey( "Parent" ) ) pObj->GetDictionary().RemoveKey( "Parent" ); // Deal with inherited attributes const PdfName* pInherited = inheritableAttributes; while( pInherited->GetLength() != 0 ) { const PdfObject* pAttribute = pPage->GetInheritedKey( *pInherited ); if( pAttribute ) { PdfObject attribute( *pAttribute ); FixObjectReferences( &attribute, difference ); pObj->GetDictionary().AddKey( *pInherited, attribute ); } ++pInherited; } m_pPagesTree->InsertPage( nAtIndex <= 0 ? ePdfPageInsertionPoint_InsertBeforeFirstPage : nAtIndex - 1, pObj ); } // append all outlines PdfOutlineItem* pRoot = this->GetOutlines(); PdfOutlines* pAppendRoot = const_cast(rDoc).GetOutlines( PoDoFo::ePdfDontCreateObject ); if( pAppendRoot && pAppendRoot->First() ) { // only append outlines if appended document has outlines while( pRoot && pRoot->Next() ) pRoot = pRoot->Next(); PdfReference ref( pAppendRoot->First()->GetObject()->Reference().ObjectNumber() + difference, pAppendRoot->First()->GetObject()->Reference().GenerationNumber() ); pRoot->InsertChild( new PdfOutlines( m_vecObjects.GetObject( ref ) ) ); } // TODO: merge name trees // ToDictionary -> then iteratate over all keys and add them to the new one return *this; } PdfRect PdfDocument::FillXObjectFromDocumentPage( PdfXObject * pXObj, const PdfMemDocument & rDoc, int nPage, bool bUseTrimBox ) { unsigned int difference = static_cast(m_vecObjects.GetSize() + m_vecObjects.GetFreeObjects().size()); Append( rDoc, false ); PdfPage* pPage = rDoc.GetPage( nPage ); return FillXObjectFromPage( pXObj, pPage, bUseTrimBox, difference ); } PdfRect PdfDocument::FillXObjectFromExistingPage( PdfXObject * pXObj, int nPage, bool bUseTrimBox ) { PdfPage* pPage = GetPage( nPage ); return FillXObjectFromPage( pXObj, pPage, bUseTrimBox, 0 ); } PdfRect PdfDocument::FillXObjectFromPage( PdfXObject * pXObj, const PdfPage * pPage, bool bUseTrimBox, unsigned int difference ) { // TODO: remove unused objects: page, ... PdfObject* pObj = m_vecObjects.GetObject( PdfReference( pPage->GetObject()->Reference().ObjectNumber() + difference, pPage->GetObject()->Reference().GenerationNumber() ) ); PdfRect box = pPage->GetMediaBox(); // intersect with crop-box box.Intersect( pPage->GetCropBox() ); // intersect with trim-box according to parameter if ( bUseTrimBox ) box.Intersect( pPage->GetTrimBox() ); // link resources from external doc to x-object if( pObj->IsDictionary() && pObj->GetDictionary().HasKey( "Resources" ) ) pXObj->GetContentsForAppending()->GetDictionary().AddKey( "Resources" , pObj->GetDictionary().GetKey( "Resources" ) ); // copy top-level content from external doc to x-object if( pObj->IsDictionary() && pObj->GetDictionary().HasKey( "Contents" ) ) { // get direct pointer to contents PdfObject* pContents; if( pObj->GetDictionary().GetKey( "Contents" )->IsReference() ) pContents = m_vecObjects.GetObject( pObj->GetDictionary().GetKey( "Contents" )->GetReference() ); else pContents = pObj->GetDictionary().GetKey( "Contents" ); if( pContents->IsArray() ) { // copy array as one stream to xobject PdfArray pArray = pContents->GetArray(); PdfObject* pObj = pXObj->GetContentsForAppending(); PdfStream* pObjStream = pObj->GetStream(); TVecFilters vFilters; vFilters.push_back( ePdfFilter_FlateDecode ); pObjStream->BeginAppend( vFilters ); TIVariantList it; for(it = pArray.begin(); it != pArray.end(); it++) { if ( it->IsReference() ) { // TODO: not very efficient !! PdfObject* pObj = GetObjects()->GetObject( it->GetReference() ); while (pObj!=NULL) { if (pObj->IsReference()) // Recursively look for the stream { pObj = GetObjects()->GetObject( pObj->GetReference() ); } else if (pObj->HasStream()) { PdfStream* pcontStream = pObj->GetStream(); char* pcontStreamBuffer; pdf_long pcontStreamLength; pcontStream->GetFilteredCopy( &pcontStreamBuffer, &pcontStreamLength ); pObjStream->Append( pcontStreamBuffer, pcontStreamLength ); free( pcontStreamBuffer ); break; } else { throw ePdfError_InvalidStream; break; } } } else { string str; it->ToString( str ); pObjStream->Append( str ); pObjStream->Append( " " ); } } pObjStream->EndAppend(); } else if( pContents->HasStream() ) { // copy stream to xobject PdfObject* pObj = pXObj->GetContentsForAppending(); PdfStream* pObjStream = pObj->GetStream(); PdfStream* pcontStream = pContents->GetStream(); char* pcontStreamBuffer; pdf_long pcontStreamLength; TVecFilters vFilters; vFilters.push_back( ePdfFilter_FlateDecode ); pObjStream->BeginAppend( vFilters ); pcontStream->GetFilteredCopy( &pcontStreamBuffer, &pcontStreamLength ); pObjStream->Append( pcontStreamBuffer, pcontStreamLength ); free( pcontStreamBuffer ); pObjStream->EndAppend(); } else { PODOFO_RAISE_ERROR( ePdfError_InternalLogic ); } } return box; } void PdfDocument::FixObjectReferences( PdfObject* pObject, int difference ) { if( !pObject ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } if( pObject->IsDictionary() ) { TKeyMap::iterator it = pObject->GetDictionary().GetKeys().begin(); while( it != pObject->GetDictionary().GetKeys().end() ) { if( (*it).second->IsReference() ) { *(*it).second = PdfReference( (*it).second->GetReference().ObjectNumber() + difference, (*it).second->GetReference().GenerationNumber() ); } else if( (*it).second->IsDictionary() || (*it).second->IsArray() ) { FixObjectReferences( (*it).second, difference ); } ++it; } } else if( pObject->IsArray() ) { PdfArray::iterator it = pObject->GetArray().begin(); while( it != pObject->GetArray().end() ) { if( (*it).IsReference() ) { (*it) = PdfReference( (*it).GetReference().ObjectNumber() + difference, (*it).GetReference().GenerationNumber() ); } else if( (*it).IsDictionary() || (*it).IsArray() ) FixObjectReferences( &(*it), difference ); ++it; } } else if( pObject->IsReference() ) { *pObject = PdfReference( pObject->GetReference().ObjectNumber() + difference, pObject->GetReference().GenerationNumber() ); } } EPdfPageMode PdfDocument::GetPageMode( void ) const { // PageMode is optional; the default value is UseNone EPdfPageMode thePageMode = ePdfPageModeUseNone; PdfObject* pageModeObj = GetCatalog()->GetIndirectKey( PdfName( "PageMode" ) ); if ( pageModeObj != NULL ) { PdfName pmName = pageModeObj->GetName(); if( PdfName( "UseNone" ) == pmName ) thePageMode = ePdfPageModeUseNone ; else if( PdfName( "UseThumbs" ) == pmName ) thePageMode = ePdfPageModeUseThumbs ; else if( PdfName( "UseOutlines" ) == pmName ) thePageMode = ePdfPageModeUseBookmarks ; else if( PdfName( "FullScreen" ) == pmName ) thePageMode = ePdfPageModeFullScreen ; else if( PdfName( "UseOC" ) == pmName ) thePageMode = ePdfPageModeUseOC ; else if( PdfName( "UseAttachments" ) == pmName ) thePageMode = ePdfPageModeUseAttachments ; else PODOFO_RAISE_ERROR( ePdfError_InvalidName ); } return thePageMode ; } void PdfDocument::SetPageMode( EPdfPageMode inMode ) { switch ( inMode ) { default: case ePdfPageModeDontCare: // GetCatalog()->RemoveKey( PdfName( "PageMode" ) ); // this value means leave it alone! break; case ePdfPageModeUseNone: GetCatalog()->GetDictionary().AddKey( PdfName( "PageMode" ), PdfName( "UseNone" ) ); break; case ePdfPageModeUseThumbs: GetCatalog()->GetDictionary().AddKey( PdfName( "PageMode" ), PdfName( "UseThumbs" ) ); break; case ePdfPageModeUseBookmarks: GetCatalog()->GetDictionary().AddKey( PdfName( "PageMode" ), PdfName( "UseOutlines" ) ); break; case ePdfPageModeFullScreen: GetCatalog()->GetDictionary().AddKey( PdfName( "PageMode" ), PdfName( "FullScreen" ) ); break; case ePdfPageModeUseOC: GetCatalog()->GetDictionary().AddKey( PdfName( "PageMode" ), PdfName( "UseOC" ) ); break; case ePdfPageModeUseAttachments: GetCatalog()->GetDictionary().AddKey( PdfName( "PageMode" ), PdfName( "UseAttachments" ) ); break; } } void PdfDocument::SetUseFullScreen( void ) { // first, we get the current mode EPdfPageMode curMode = GetPageMode(); // if current mode is anything but "don't care", we need to move that to non-full-screen if ( curMode != ePdfPageModeDontCare ) SetViewerPreference( PdfName( "NonFullScreenPageMode" ), PdfObject( *(GetCatalog()->GetIndirectKey( PdfName( "PageMode" ) )) ) ); SetPageMode( ePdfPageModeFullScreen ); } void PdfDocument::SetViewerPreference( const PdfName& whichPref, const PdfObject & valueObj ) { PdfObject* prefsObj = GetCatalog()->GetIndirectKey( PdfName( "ViewerPreferences" ) ); if ( prefsObj == NULL ) { // make me a new one and add it PdfDictionary vpDict; vpDict.AddKey( whichPref, valueObj ); GetCatalog()->GetDictionary().AddKey( PdfName( "ViewerPreferences" ), PdfObject( vpDict ) ); } else { // modify the existing one prefsObj->GetDictionary().AddKey( whichPref, valueObj ); } } void PdfDocument::SetViewerPreference( const PdfName& whichPref, bool inValue ) { SetViewerPreference( whichPref, PdfObject( inValue ) ); } void PdfDocument::SetHideToolbar( void ) { SetViewerPreference( PdfName( "HideToolbar" ), true ); } void PdfDocument::SetHideMenubar( void ) { SetViewerPreference( PdfName( "HideMenubar" ), true ); } void PdfDocument::SetHideWindowUI( void ) { SetViewerPreference( PdfName( "HideWindowUI" ), true ); } void PdfDocument::SetFitWindow( void ) { SetViewerPreference( PdfName( "FitWindow" ), true ); } void PdfDocument::SetCenterWindow( void ) { SetViewerPreference( PdfName( "CenterWindow" ), true ); } void PdfDocument::SetDisplayDocTitle( void ) { SetViewerPreference( PdfName( "DisplayDocTitle" ), true ); } void PdfDocument::SetPrintScaling( PdfName& inScalingType ) { SetViewerPreference( PdfName( "PrintScaling" ), inScalingType ); } void PdfDocument::SetBaseURI( const std::string& inBaseURI ) { PdfDictionary uriDict; uriDict.AddKey( PdfName( "Base" ), new PdfObject( PdfString( inBaseURI ) ) ); GetCatalog()->GetDictionary().AddKey( PdfName( "URI" ), new PdfObject( uriDict ) ); } void PdfDocument::SetLanguage( const std::string& inLanguage ) { GetCatalog()->GetDictionary().AddKey( PdfName( "Lang" ), new PdfObject( PdfString( inLanguage ) ) ); } void PdfDocument::SetBindingDirection( PdfName& inDirection ) { SetViewerPreference( PdfName( "Direction" ), inDirection ); } void PdfDocument::SetPageLayout( EPdfPageLayout inLayout ) { switch ( inLayout ) { default: case ePdfPageLayoutIgnore: break; // means do nothing case ePdfPageLayoutDefault: GetCatalog()->GetDictionary().RemoveKey( PdfName( "PageLayout" ) ); break; case ePdfPageLayoutSinglePage: GetCatalog()->GetDictionary().AddKey( PdfName( "PageLayout" ), PdfName( "SinglePage" ) ); break; case ePdfPageLayoutOneColumn: GetCatalog()->GetDictionary().AddKey( PdfName( "PageLayout" ), PdfName( "OneColumn" ) ); break; case ePdfPageLayoutTwoColumnLeft: GetCatalog()->GetDictionary().AddKey( PdfName( "PageLayout" ), PdfName( "TwoColumnLeft" ) ); break; case ePdfPageLayoutTwoColumnRight: GetCatalog()->GetDictionary().AddKey( PdfName( "PageLayout" ), PdfName( "TwoColumnRight" ) ); break; case ePdfPageLayoutTwoPageLeft: GetCatalog()->GetDictionary().AddKey( PdfName( "PageLayout" ), PdfName( "TwoPageLeft" ) ); break; case ePdfPageLayoutTwoPageRight: GetCatalog()->GetDictionary().AddKey( PdfName( "PageLayout" ), PdfName( "TwoPageRight" ) ); break; } } PdfOutlines* PdfDocument::GetOutlines( bool bCreate ) { PdfObject* pObj; if( !m_pOutlines ) { pObj = GetNamedObjectFromCatalog( "Outlines" ); if( !pObj ) { if ( !bCreate ) return NULL; m_pOutlines = new PdfOutlines( &m_vecObjects ); this->GetCatalog()->GetDictionary().AddKey( "Outlines", m_pOutlines->GetObject()->Reference() ); } else if ( pObj->GetDataType() != ePdfDataType_Dictionary ) { PODOFO_RAISE_ERROR( ePdfError_InvalidDataType ); } else m_pOutlines = new PdfOutlines( pObj ); } return m_pOutlines; } PdfNamesTree* PdfDocument::GetNamesTree( bool bCreate ) { PdfObject* pObj; if( !m_pNamesTree ) { pObj = GetNamedObjectFromCatalog( "Names" ); if( !pObj ) { if ( !bCreate ) return NULL; PdfNamesTree tmpTree ( &m_vecObjects ); pObj = tmpTree.GetObject(); this->GetCatalog()->GetDictionary().AddKey( "Names", pObj->Reference() ); m_pNamesTree = new PdfNamesTree( pObj, this->GetCatalog() ); } else if ( pObj->GetDataType() != ePdfDataType_Dictionary ) { PODOFO_RAISE_ERROR( ePdfError_InvalidDataType ); } else m_pNamesTree = new PdfNamesTree( pObj, this->GetCatalog() ); } return m_pNamesTree; } PdfAcroForm* PdfDocument::GetAcroForm( bool bCreate, EPdfAcroFormDefaulAppearance eDefaultAppearance ) { PdfObject* pObj; if( !m_pAcroForms ) { pObj = GetNamedObjectFromCatalog( "AcroForm" ); if( !pObj ) { if ( !bCreate ) return NULL; m_pAcroForms = new PdfAcroForm( this, eDefaultAppearance ); this->GetCatalog()->GetDictionary().AddKey( "AcroForm", m_pAcroForms->GetObject()->Reference() ); } else if ( pObj->GetDataType() != ePdfDataType_Dictionary ) { PODOFO_RAISE_ERROR( ePdfError_InvalidDataType ); } else m_pAcroForms = new PdfAcroForm( this, pObj, eDefaultAppearance ); } return m_pAcroForms; } void PdfDocument::AddNamedDestination( const PdfDestination& rDest, const PdfString & rName ) { PdfNamesTree* nameTree = GetNamesTree(); nameTree->AddValue( PdfName("Dests"), rName, rDest.GetObject()->Reference() ); } void PdfDocument::AttachFile( const PdfFileSpec & rFileSpec ) { PdfNamesTree* pNames = this->GetNamesTree( true ); if( !pNames ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } pNames->AddValue( "EmbeddedFiles", rFileSpec.GetFilename(false), rFileSpec.GetObject()->Reference() ); } PdfFileSpec* PdfDocument::GetAttachment( const PdfString & rName ) { PdfNamesTree* pNames = this->GetNamesTree(); if( !pNames ) { return NULL; } PdfObject* pObj = pNames->GetValue( "EmbeddedFiles", rName ); if( !pObj ) { return NULL; } return new PdfFileSpec(pObj); } void PdfDocument::SetInfo( PdfInfo* pInfo ) { delete m_pInfo; m_pInfo = pInfo; } void PdfDocument::SetTrailer( PdfObject* pObject ) { delete m_pTrailer; m_pTrailer = pObject; // Set owner so that GetIndirectKey will work m_pTrailer->SetOwner( &m_vecObjects ); } }; podofo-0.9.3/src/doc/PdfFontCache.h0000664000175000017500000004527612347303775016703 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2007 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_FONT_CACHE_H_ #define _PDF_FONT_CACHE_H_ #include "podofo/base/PdfDefines.h" #include "podofo/base/Pdf3rdPtyForwardDecl.h" #include "podofo/base/PdfEncoding.h" #include "podofo/base/PdfEncodingFactory.h" #include "PdfFont.h" #include "PdfFontConfigWrapper.h" #ifdef _WIN32 // to have LOGFONTA/LOGFONTW available #include // Undefined stuff which windows does // define that breaks are build // e.g. GetObject is defined to either GetObjectA or GetObjectW #ifdef GetObject #undef GetObject #endif // GetObject #ifdef CreateFont #undef CreateFont #endif // CreateFont #ifdef DrawText #undef DrawText #endif // DrawText #endif // __WIN32 namespace PoDoFo { class PdfFontMetrics; class PdfVecObjects; /** A private structure, * which represents a font in the cache. */ struct TFontCacheElement { TFontCacheElement() : m_pFont( NULL ), m_pEncoding( NULL ), m_bBold( false ), m_bItalic( false ), m_bIsSymbolCharset (false) { } TFontCacheElement( const char* pszFontName, bool bBold, bool bItalic, bool bIsSymbolCharset, const PdfEncoding * const pEncoding ) : m_pFont(NULL), m_pEncoding( pEncoding ), m_bBold( bBold ), m_bItalic( bItalic ), m_sFontName( reinterpret_cast(pszFontName) ), m_bIsSymbolCharset (bIsSymbolCharset) { } #if defined(_WIN32) && !defined(PODOFO_NO_FONTMANAGER) TFontCacheElement( const wchar_t* pszFontName, bool bBold, bool bItalic, bool bIsSymbolCharset, const PdfEncoding * const pEncoding ) : m_pFont(NULL), m_pEncoding( pEncoding ), m_bBold( bBold ), m_bItalic( bItalic ), m_sFontName( pszFontName ), m_bIsSymbolCharset (bIsSymbolCharset) { } #endif // _WIN32 TFontCacheElement( const TFontCacheElement & rhs ) { this->operator=(rhs); } const TFontCacheElement & operator=( const TFontCacheElement & rhs ) { m_pFont = rhs.m_pFont; m_pEncoding = rhs.m_pEncoding; m_bBold = rhs.m_bBold; m_bItalic = rhs.m_bItalic; m_sFontName = rhs.m_sFontName; m_bIsSymbolCharset = rhs.m_bIsSymbolCharset; return *this; } bool operator<( const TFontCacheElement & rhs ) const { if (m_bIsSymbolCharset != rhs.m_bIsSymbolCharset) { return m_bIsSymbolCharset < rhs.m_bIsSymbolCharset; } if( m_sFontName == rhs.m_sFontName ) { if( m_pEncoding == NULL || rhs.m_pEncoding == NULL || *m_pEncoding == *rhs.m_pEncoding ) { if( m_bBold == rhs.m_bBold) return m_bItalic < rhs.m_bItalic; else return m_bBold < rhs.m_bBold; } else return *m_pEncoding < *rhs.m_pEncoding; } else return (m_sFontName < rhs.m_sFontName); } inline bool operator()( const TFontCacheElement& r1, const TFontCacheElement& r2 ) const { return r1 < r2; } PdfFont* m_pFont; const PdfEncoding* m_pEncoding; bool m_bBold; bool m_bItalic; PdfString m_sFontName; ///< We use PdfString here as it can easily handle unicode on windows bool m_bIsSymbolCharset; }; /** * This class assists PdfDocument * with caching font information. * * Additional to font caching, this class is also * responsible for font matching. * * PdfFont is an actual font that can be used in * a PDF file (i.e. it does also font embedding) * and PdfFontMetrics provides only metrics informations. * * This class is an internal class of PoDoFo * and should not be used in user applications * * \see PdfDocument */ class PODOFO_DOC_API PdfFontCache { typedef std::vector TSortedFontList; typedef TSortedFontList::iterator TISortedFontList; typedef TSortedFontList::const_iterator TCISortedFontList; public: /** * Flags to control font creation. */ enum EFontCreationFlags { eFontCreationFlags_None = 0, ///< No special settings eFontCreationFlags_AutoSelectBase14 = 1, ///< Create automatically a base14 font if the fontname matches one of them eFontCreationFlags_Type1Subsetting = 2 ///< Create subsetted type1-font, which includes only used characters }; /** Create an empty font cache * * \param pParent a PdfVecObjects which is required * to create new font objects */ PdfFontCache( PdfVecObjects* pParent ); /** Create an empty font cache * * \param rFontConfig provide a handle to fontconfig, as initializing a * new fontconfig intance might be time consuming. * \param pParent a PdfVecObjects which is required * to create new font objects */ PdfFontCache( const PdfFontConfigWrapper & rFontConfig, PdfVecObjects* pParent ); /** Destroy and empty the font cache */ ~PdfFontCache(); /** * Empty the internal font cache. * This should be done when ever a new document * is created or openened. */ void EmptyCache(); /** Get a font from the cache. If the font does not yet * exist, add it to the cache. This font is created * from an existing object. * * \param pObject a PdfObject that is a font * * \returns a PdfFont object or NULL if the font could * not be created or found. */ PdfFont* GetFont( PdfObject* pObject ); /** Get a font from the cache. If the font does not yet * exist, add it to the cache. * * \param pszFontName a valid fontname * \param bBold if true search for a bold font * \param bItalic if true search for an italic font * \param bSymbolCharset whether to use symbol charset, rather than unicode charset * \param bEmbedd if true a font for embedding into * PDF will be created * \param eFontCreationFlags special flag to specify how fonts should be created * \param pEncoding the encoding of the font. The font will not take ownership of this object. * \param pszFileName optional path to a valid font file * * \returns a PdfFont object or NULL if the font could * not be created or found. */ PdfFont* GetFont( const char* pszFontName, bool bBold, bool bItalic, bool bSymbolCharset, bool bEmbedd, EFontCreationFlags eFontCreationFlags = eFontCreationFlags_AutoSelectBase14, const PdfEncoding * const = PdfEncodingFactory::GlobalWinAnsiEncodingInstance(), const char* pszFileName = NULL ); #if defined(_WIN32) && !defined(PODOFO_NO_FONTMANAGER) /** Get a font from the cache. If the font does not yet * exist, add it to the cache. * * \param pszFontName a valid fontname * \param bBold if true search for a bold font * \param bItalic if true search for an italic font * \param bSymbolCharset whether to use symbol charset, rather than unicode charset * \param bEmbedd if true a font for embedding into * PDF will be created * \param pEncoding the encoding of the font. The font will not take ownership of this object. * * \returns a PdfFont object or NULL if the font could * not be created or found. * * This is an overloaded member function to allow working * with unicode characters. On Unix systes you can also path * UTF-8 to the const char* overload. */ PdfFont* GetFont( const wchar_t* pszFontName, bool bBold, bool bItalic, bool bSymbolCharset, bool bEmbedd, const PdfEncoding * const = PdfEncodingFactory::GlobalWinAnsiEncodingInstance() ); PdfFont* GetFont( const LOGFONTA &logFont, bool bEmbedd, const PdfEncoding * const pEncoding ); PdfFont* GetFont( const LOGFONTW &logFont, bool bEmbedd, const PdfEncoding * const pEncoding ); #endif // _WIN32 /** Get a font from the cache. If the font does not yet * exist, add it to the cache. * * \param face a valid freetype font face (will be free'd by PoDoFo) * \param bSymbolCharset whether to use symbol charset, rather than unicode charset * \param bEmbedd if true a font for embedding into * PDF will be created * \param pEncoding the encoding of the font. The font will not take ownership of this object. * * \returns a PdfFont object or NULL if the font could * not be created or found. */ PdfFont* GetFont( FT_Face face, bool bSymbolCharset, bool bEmbedd, const PdfEncoding * const = PdfEncodingFactory::GlobalWinAnsiEncodingInstance() ); /** Get a font with specific id from the cache. If the font does not yet * exist, copy from existing type1-font and set id. * * \param pFont an existing font * \param pszSuffix Suffix to add to font-id * * \returns a PdfFont object or NULL if the font could * not be created or found. */ PdfFont* GetDuplicateFontType1( PdfFont* pFont, const char* pszSuffix ); /** Get a fontsubset from the cache. If the font does not yet * exist, add it to the cache. * * \param pszFontName a valid fontname * \param bBold if true search for a bold font * \param bItalic if true search for an italic font * \param bSymbolCharset whether to use symbol charset, rather than unicode charset * \param pEncoding the encoding of the font. All characters * of the encoding will be included in this subset. * The font will not take ownership of this object. * \param pszFileName optional path to a valid font file * * \returns a PdfFont object or NULL if the font could * not be created or found. */ PdfFont* GetFontSubset( const char* pszFontName, bool bBold, bool bItalic, bool bSymbolCharset, const PdfEncoding * const = PdfEncodingFactory::GlobalWinAnsiEncodingInstance(), const char* pszFileName = NULL); /** Embeds all pending subset-fonts * */ void EmbedSubsetFonts(); #if defined(PODOFO_HAVE_FONTCONFIG) /** Get the path of a font file on a Unix system using fontconfig * * This method is only available if PoDoFo was compiled with * fontconfig support. Make sure to lock any FontConfig mutexes before * calling this method by yourself! * * \param pConfig a handle to an initialized fontconfig library * \param pszFontName name of the requested font * \param bBold if true find a bold font * \param bItalic if true find an italic font * \returns the path to the fontfile or an empty string */ static std::string GetFontConfigFontPath( FcConfig* pConfig, const char* pszFontName, bool bBold, bool bItalic ); #endif // defined(PODOFO_HAVE_FONTCONFIG) // Peter Petrov: 26 April 2008 /** Returns the font library from font cache * * \returns the internal handle to the freetype library */ inline FT_Library GetFontLibrary() const; /** * Set wrapper for the fontconfig library. * Useful to avoid initializing Fontconfig multiple times. * * This setter can be called until first use of Fontconfig * as the library is initialized at first use. */ inline void SetFontConfigWrapper(const PdfFontConfigWrapper & rFontConfig); private: /** * Get the path to a font file for a certain fontname * * \param pszFontName a valid fontname * \param bBold if true search for a bold font * \param bItalic if true search for an italic font * * \returns the path to the fonts file if it was found. */ std::string GetFontPath( const char* pszFontName, bool bBold, bool bItalic ); /** Create a font and put it into the fontcache * * \param itSorted iterator pointing to a location in vecContainer * where a sorted insert can be made * \param vecContainer container where the font object should be added * \param pMetrics a font metrics * \param bEmbedd if true the font will be embedded in the pdf file * \param bBold if true this font will be treated as bold font * \param bItalic if true this font will be treated as italic font * \param pszFontName a font name for debug output * \param pEncoding the encoding of the font. The font will not take ownership of this object. * \param bSubsetting if true the font will be subsetted in the pdf file * * \returns a font handle or NULL in case of error */ PdfFont* CreateFontObject( TISortedFontList itSorted, TSortedFontList & vecContainer, PdfFontMetrics* pMetrics, bool bEmbedd, bool bBold, bool bItalic, const char* pszFontName, const PdfEncoding * const pEncoding, bool bSubsetting = false ); /** Create a font subset. * \param pMetrics a font metrics * \param pszFontName a font name for debug output * \param bBold if true this font will be treated as bold font * \param bItalic if true this font will be treated as italic font * \param vecCharacters a list of Unicode character indeces that should be embedded in the subset * * \returns a font handle or NULL in case of error */ /* PdfFont* CreateFontSubset( PdfFontMetrics* pMetrics, const char* pszFontName, bool bBold, bool bItalic, const std::vector & vecCharacters ); */ #if defined(_WIN32) && !defined(PODOFO_NO_FONTMANAGER) /** Load and create a font with windows API calls * * This method is only available on Windows systems. * * \param itSorted iterator pointing to a location in vecContainer * where a sorted insert can be made * \param vecContainer container where the font object should be added * \param pszFontName a fontname * \param bBold if true search for a bold font * \param bItalic if true search for an italic font * \param bEmbedd if true embedd the font * \param pEncoding the encoding of the font. The font will not take ownership of this object. * * \returns a font handle or NULL in case of error */ PdfFont* GetWin32Font( TISortedFontList itSorted, TSortedFontList & vecContainer, const char* pszFontName, bool bBold, bool bItalic, bool bSymbolCharset, bool bEmbedd, const PdfEncoding * const pEncoding, bool pSubsetting = false ); PdfFont* GetWin32Font( TISortedFontList itSorted, TSortedFontList & vecContainer, const wchar_t* pszFontName, bool bBold, bool bItalic, bool bSymbolCharset, bool bEmbedd, const PdfEncoding * const pEncoding, bool pSubsetting = false ); PdfFont* GetWin32Font( TISortedFontList itSorted, TSortedFontList & vecContainer, const LOGFONTA &logFont, bool bEmbedd, const PdfEncoding * const pEncoding, bool pSubsetting = false ); PdfFont* GetWin32Font( TISortedFontList itSorted, TSortedFontList & vecContainer, const LOGFONTW &logFont, bool bEmbedd, const PdfEncoding * const pEncoding, bool pSubsetting = false ); #endif // _WIN32 #define SUBSET_BASENAME_LEN 6 // + 2 for "+\0" // kind of ABCDEF+ const char *genSubsetBasename(void); protected: void Init(void); private: TSortedFontList m_vecFonts; ///< Sorted list of all fonts, currently in the cache TSortedFontList m_vecFontSubsets; FT_Library m_ftLibrary; ///< Handle to the freetype library PdfVecObjects* m_pParent; ///< Handle to parent for creating new fonts and objects PdfFontConfigWrapper m_fontConfig; ///< Handle to the fontconfig library char m_sSubsetBasename[SUBSET_BASENAME_LEN + 2]; //< For genSubsetBasename() }; // Peter Petrov: 26 April 2008 // ----------------------------------------------------- // // ----------------------------------------------------- FT_Library PdfFontCache::GetFontLibrary() const { return this->m_ftLibrary; } // ----------------------------------------------------- // // ----------------------------------------------------- inline void PdfFontCache::SetFontConfigWrapper(const PdfFontConfigWrapper & rFontConfig) { m_fontConfig = rFontConfig; } }; #endif /* _PDF_FONT_CACHE_H_ */ podofo-0.9.3/src/doc/PdfFontType1.h0000664000175000017500000001522012344436402016653 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2007 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_FONT_TYPE1_H_ #define _PDF_FONT_TYPE1_H_ #include "podofo/base/PdfDefines.h" #include "PdfFontSimple.h" namespace PoDoFo { /** A PdfFont implementation that can be used * to embedd type1 fonts into a PDF file * or to draw with type1 fonts. */ class PdfFontType1 : public PdfFontSimple { public: /** Create a new Type1 font object. * * \param pMetrics pointer to a font metrics object. The font in the PDF * file will match this fontmetrics object. The metrics object is * deleted along with the font. * \param pEncoding the encoding of this font. The font will take ownership of this object * depending on pEncoding->IsAutoDelete() * \param pParent parent of the font object * \param bEmbed if true the font will get embedded. * \param bSubsetting if true the font will use subsetting. * */ PdfFontType1( PdfFontMetrics* pMetrics, const PdfEncoding* const pEncoding, PdfVecObjects* pParent, bool bEmbed, bool bSubsetting = false ); /** Create a PdfFont based on an existing PdfObject * \param pMetrics pointer to a font metrics object. The font in the PDF * file will match this fontmetrics object. The metrics object is * deleted along with the font. * \param pEncoding the encoding of this font. The font will take ownership of this object * depending on pEncoding->IsAutoDelete() * \param pObject an existing PdfObject */ PdfFontType1( PdfFontMetrics* pMetrics, const PdfEncoding* const pEncoding, PdfObject* pObject ); /** Create a PdfFont based on an existing PdfFont with a new id * \param pFont pointer to existing font * \param pMetrics pointer to a font metrics object. The font in the PDF * file will match this fontmetrics object. The metrics object is * deleted along with the font. * \param pszSuffix Suffix to add to font-id * \param pParent parent of the font object */ PdfFontType1( PdfFontType1* pFont, PdfFontMetrics* pMetrics, const char *pszSuffix, PdfVecObjects* pParent ); void InitBase14Font(); protected: /** Remember the glyphs used in the string in case of subsetting * * \param sText the text string which should be printed (is not allowed to be NULL!) * \param lStringLen draw only lLen characters of pszText */ virtual void AddUsedSubsettingGlyphs( const PdfString & sText, long lStringLen ); /** Remember the glyphname in case of subsetting * * \param sGlyphName Name of the glyph to remember */ virtual void AddUsedGlyphname( const char* sGlyphName ); /** Embeds pending subset-font into PDF page * */ virtual void EmbedSubsetFont(); /** Embed the font file directly into the PDF file. * * \param pDescriptor font descriptor object */ virtual void EmbedFontFile( PdfObject* pDescriptor ); private: bool FindSeac( const unsigned char * buffer, int length ); pdf_long FindInBuffer( const char* pszNeedle, const char* pszHaystack, pdf_long lLen ) const; int m_bUsed[8]; // bitmask for usage if char 00..ff std::set m_sUsedGlyph; // array for special chars }; /** Helper Class needed for parsing type1-font for subsetting */ class PdfType1Encrypt { public: /** Create a new PdfTypeEncrypt object. * */ PdfType1Encrypt(); /** Encrypts a character * * \param plain the character to encrypt. * * \return encrypted cipher * */ unsigned char Encrypt( unsigned char plain ); /** Decrypts a character * * \param cipher the cipher to decrypt. * * \return decrypted character * */ unsigned char Decrypt( unsigned char cipher ); protected: unsigned short int m_r; unsigned short int m_c1; unsigned short int m_c2; }; class PdfType1EncryptEexec : public PdfType1Encrypt { public: /** Create a new PdfType1EncryptEexec object. * */ PdfType1EncryptEexec(); }; class PdfType1EncryptCharstring : public PdfType1Encrypt { public: /** Create a new PdfType1EncryptCharstring object. * */ PdfType1EncryptCharstring(); }; }; #endif // _PDF_FONT_TYPE1_H_ podofo-0.9.3/src/doc/PdfEncodingObjectFactory.h0000664000175000017500000000661712344436554021251 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2010 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_ENCODING_OBJECT_FACTORY_H_ #define _PDF_ENCODING_OBJECT_FACTORY_H_ #include "podofo/base/PdfDefines.h" namespace PoDoFo { class PdfEncoding; class PdfObject; /** This factory creates a PdfEncoding * from an existing object in the PDF. */ class PODOFO_DOC_API PdfEncodingObjectFactory { public: /** Create a new PdfEncoding from either an * encoding name or an encoding dictionary. * * \param pObject must be a name or an encoding dictionary * \param pToUnicode the optional ToUnicode dictionary * \param bExplicitNames if true, glyph names are meaningless explicit keys on the font (used for Type3 fonts) * * \returns a PdfEncoding or NULL */ static const PdfEncoding* CreateEncoding( PdfObject* pObject, PdfObject *pToUnicode = NULL, bool bExplicitNames = false ); private: /** * Hidden default constructor */ PdfEncodingObjectFactory(); }; }; /* namespace PoDoFo */ #endif // _PDF_ENCODING_OBJECT_FACTORY_H_ podofo-0.9.3/src/doc/PdfEncodingObjectFactory.cpp0000664000175000017500000001077112344436554021600 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2010 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfEncodingObjectFactory.h" #include "base/PdfDefinesPrivate.h" #include "base/PdfEncodingFactory.h" #include "base/PdfObject.h" #include "base/PdfVecObjects.h" #include "PdfDifferenceEncoding.h" #include "PdfIdentityEncoding.h" #include "PdfCMapEncoding.h" //For temporary purpose #include using namespace std; namespace PoDoFo { const PdfEncoding *PdfEncodingObjectFactory::CreateEncoding (PdfObject *pObject, PdfObject *pToUnicode, bool bExplicitNames) { if (pObject->IsReference ()) { // resolve any references pObject = pObject->GetOwner ()->GetObject (pObject->GetReference ()); } if (pObject->IsName ()) { const PdfName & rName = pObject->GetName (); if (rName == PdfName ("WinAnsiEncoding")) return PdfEncodingFactory::GlobalWinAnsiEncodingInstance (); else if (rName == PdfName ("MacRomanEncoding")) return PdfEncodingFactory::GlobalMacRomanEncodingInstance (); else if (rName == PdfName ("StandardEncoding")) // OC 13.08.2010 return PdfEncodingFactory::GlobalStandardEncodingInstance (); else if (rName == PdfName ("MacExpertEncoding")) // OC 13.08.2010 TODO solved return PdfEncodingFactory::GlobalMacExpertEncodingInstance (); else if (rName == PdfName ("SymbolEncoding")) // OC 13.08.2010 return PdfEncodingFactory::GlobalSymbolEncodingInstance (); else if (rName == PdfName ("ZapfDingbatsEncoding")) // OC 13.08.2010 return PdfEncodingFactory::GlobalZapfDingbatsEncodingInstance (); else if (rName == PdfName ("Identity-H")) return new PdfIdentityEncoding (0, 0xffff, true, pToUnicode); } else if (pObject->HasStream ()) { return new PdfCMapEncoding(pObject, pToUnicode); } else if (pObject->IsDictionary ()) { return new PdfDifferenceEncoding (pObject, true, bExplicitNames); } PODOFO_RAISE_ERROR_INFO (ePdfError_InternalLogic, "Unsupported encoding detected!"); //return NULL; Unreachable code } }; /* namespace PoDoFo */ podofo-0.9.3/src/doc/PdfDifferenceEncoding.cpp0000664000175000017500000021342212347347566021101 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2008 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfDifferenceEncoding.h" #include "base/PdfDefinesPrivate.h" #include "base/PdfArray.h" #include "base/PdfDictionary.h" #include "PdfFont.h" #include #include #include #include namespace PoDoFo { static struct { pdf_utf16be u; // in fact this might be little endian on LE systems const char *name; } nameToUnicodeTab[] = { {0x0021, "!"}, {0x0023, "#"}, {0x0024, "$"}, {0x0025, "%"}, {0x0026, "&"}, {0x0027, "'"}, {0x0028, "("}, {0x0029, ")"}, {0x002a, "*"}, {0x002b, "+"}, {0x002c, ","}, {0x002d, "-"}, {0x002e, "."}, {0x002f, "/"}, {0x0030, "0"}, {0x0031, "1"}, {0x0032, "2"}, {0x0033, "3"}, {0x0034, "4"}, {0x0035, "5"}, {0x0036, "6"}, {0x0037, "7"}, {0x0038, "8"}, {0x0039, "9"}, {0x003a, ":"}, {0x003b, ";"}, {0x003c, "<"}, {0x003d, "="}, {0x003e, ">"}, {0x003f, "?"}, {0x0040, "@"}, {0x0041, "A"}, {0x00c6, "AE"}, {0x01fc, "AEacute"}, {0x00c6, "AEsmall"}, {0x00c1, "Aacute"}, {0x00c1, "Aacutesmall"}, {0x0102, "Abreve"}, {0x00c2, "Acircumflex"}, {0x00c2, "Acircumflexsmall"}, {0xf6c9, "Acute"}, {0xf6c9, "Acutesmall"}, {0x00c4, "Adieresis"}, {0x00c4, "Adieresissmall"}, {0x00c0, "Agrave"}, {0x00c0, "Agravesmall"}, {0x0391, "Alpha"}, {0x0386, "Alphatonos"}, {0x0100, "Amacron"}, {0x0104, "Aogonek"}, {0x00c5, "Aring"}, {0x01fa, "Aringacute"}, {0x00c5, "Aringsmall"}, {0x0041, "Asmall"}, {0x00c3, "Atilde"}, {0x00c3, "Atildesmall"}, {0x0042, "B"}, {0x0392, "Beta"}, {0xf6f4, "Brevesmall"}, {0x0042, "Bsmall"}, {0x0043, "C"}, {0x0106, "Cacute"}, {0xf6ca, "Caron"}, {0xf6ca, "Caronsmall"}, {0x010c, "Ccaron"}, {0x00c7, "Ccedilla"}, {0x00c7, "Ccedillasmall"}, {0x0108, "Ccircumflex"}, {0x010a, "Cdotaccent"}, {0xf7b8, "Cedillasmall"}, {0x03a7, "Chi"}, {0xf6f6, "Circumflexsmall"}, {0x0043, "Csmall"}, {0x0044, "D"}, {0x010e, "Dcaron"}, {0x0110, "Dcroat"}, {0x2206, "Delta"}, {0xf6cb, "Dieresis"}, {0xf6cc, "DieresisAcute"}, {0xf6cd, "DieresisGrave"}, {0xf6cb, "Dieresissmall"}, {0xf6f7, "Dotaccentsmall"}, {0x0044, "Dsmall"}, {0x0045, "E"}, {0x00c9, "Eacute"}, {0x00c9, "Eacutesmall"}, {0x0114, "Ebreve"}, {0x011a, "Ecaron"}, {0x00ca, "Ecircumflex"}, {0x00ca, "Ecircumflexsmall"}, {0x00cb, "Edieresis"}, {0x00cb, "Edieresissmall"}, {0x0116, "Edotaccent"}, {0x00c8, "Egrave"}, {0x00c8, "Egravesmall"}, {0x0112, "Emacron"}, {0x014a, "Eng"}, {0x0118, "Eogonek"}, {0x0395, "Epsilon"}, {0x0388, "Epsilontonos"}, {0x0045, "Esmall"}, {0x0397, "Eta"}, {0x0389, "Etatonos"}, {0x00d0, "Eth"}, {0x00d0, "Ethsmall"}, {0x20ac, "Euro"}, {0x0046, "F"}, {0x0046, "Fsmall"}, {0x0047, "G"}, {0x0393, "Gamma"}, {0x011e, "Gbreve"}, {0x01e6, "Gcaron"}, {0x011c, "Gcircumflex"}, {0x0122, "Gcommaaccent"}, {0x0120, "Gdotaccent"}, {0xf6ce, "Grave"}, {0xf6ce, "Gravesmall"}, {0x0047, "Gsmall"}, {0x0048, "H"}, {0x25cf, "H18533"}, {0x25aa, "H18543"}, {0x25ab, "H18551"}, {0x25a1, "H22073"}, {0x0126, "Hbar"}, {0x0124, "Hcircumflex"}, {0x0048, "Hsmall"}, {0xf6cf, "Hungarumlaut"}, {0xf6cf, "Hungarumlautsmall"}, {0x0049, "I"}, {0x0132, "IJ"}, {0x00cd, "Iacute"}, {0x00cd, "Iacutesmall"}, {0x012c, "Ibreve"}, {0x00ce, "Icircumflex"}, {0x00ce, "Icircumflexsmall"}, {0x00cf, "Idieresis"}, {0x00cf, "Idieresissmall"}, {0x0130, "Idotaccent"}, {0x2111, "Ifraktur"}, {0x00cc, "Igrave"}, {0x00cc, "Igravesmall"}, {0x012a, "Imacron"}, {0x012e, "Iogonek"}, {0x0399, "Iota"}, {0x03aa, "Iotadieresis"}, {0x038a, "Iotatonos"}, {0x0049, "Ismall"}, {0x0128, "Itilde"}, {0x004a, "J"}, {0x0134, "Jcircumflex"}, {0x004a, "Jsmall"}, {0x004b, "K"}, {0x039a, "Kappa"}, {0x0136, "Kcommaaccent"}, {0x004b, "Ksmall"}, {0x004c, "L"}, {0xf6bf, "LL"}, {0x0139, "Lacute"}, {0x039b, "Lambda"}, {0x013d, "Lcaron"}, {0x013b, "Lcommaaccent"}, {0x013f, "Ldot"}, {0x0141, "Lslash"}, {0x0141, "Lslashsmall"}, {0x004c, "Lsmall"}, {0x004d, "M"}, {0xf6d0, "Macron"}, {0xf6d0, "Macronsmall"}, {0x004d, "Msmall"}, {0x039c, "Mu"}, {0x004e, "N"}, {0x0143, "Nacute"}, {0x0147, "Ncaron"}, {0x0145, "Ncommaaccent"}, {0x004e, "Nsmall"}, {0x00d1, "Ntilde"}, {0x00d1, "Ntildesmall"}, {0x039d, "Nu"}, {0x004f, "O"}, {0x0152, "OE"}, {0x0152, "OEsmall"}, {0x00d3, "Oacute"}, {0x00d3, "Oacutesmall"}, {0x014e, "Obreve"}, {0x00d4, "Ocircumflex"}, {0x00d4, "Ocircumflexsmall"}, {0x00d6, "Odieresis"}, {0x00d6, "Odieresissmall"}, {0xf6fb, "Ogoneksmall"}, {0x00d2, "Ograve"}, {0x00d2, "Ogravesmall"}, {0x01a0, "Ohorn"}, {0x0150, "Ohungarumlaut"}, {0x014c, "Omacron"}, {0x2126, "Omega"}, {0x038f, "Omegatonos"}, {0x039f, "Omicron"}, {0x038c, "Omicrontonos"}, {0x00d8, "Oslash"}, {0x01fe, "Oslashacute"}, {0x00d8, "Oslashsmall"}, {0x004f, "Osmall"}, {0x00d5, "Otilde"}, {0x00d5, "Otildesmall"}, {0x0050, "P"}, {0x03a6, "Phi"}, {0x03a0, "Pi"}, {0x03a8, "Psi"}, {0x0050, "Psmall"}, {0x0051, "Q"}, {0x0051, "Qsmall"}, {0x0052, "R"}, {0x0154, "Racute"}, {0x0158, "Rcaron"}, {0x0156, "Rcommaaccent"}, {0x211c, "Rfraktur"}, {0x03a1, "Rho"}, {0xf6fc, "Ringsmall"}, {0x0052, "Rsmall"}, {0x0053, "S"}, {0x250c, "SF010000"}, {0x2514, "SF020000"}, {0x2510, "SF030000"}, {0x2518, "SF040000"}, {0x253c, "SF050000"}, {0x252c, "SF060000"}, {0x2534, "SF070000"}, {0x251c, "SF080000"}, {0x2524, "SF090000"}, {0x2500, "SF100000"}, {0x2502, "SF110000"}, {0x2561, "SF190000"}, {0x2562, "SF200000"}, {0x2556, "SF210000"}, {0x2555, "SF220000"}, {0x2563, "SF230000"}, {0x2551, "SF240000"}, {0x2557, "SF250000"}, {0x255d, "SF260000"}, {0x255c, "SF270000"}, {0x255b, "SF280000"}, {0x255e, "SF360000"}, {0x255f, "SF370000"}, {0x255a, "SF380000"}, {0x2554, "SF390000"}, {0x2569, "SF400000"}, {0x2566, "SF410000"}, {0x2560, "SF420000"}, {0x2550, "SF430000"}, {0x256c, "SF440000"}, {0x2567, "SF450000"}, {0x2568, "SF460000"}, {0x2564, "SF470000"}, {0x2565, "SF480000"}, {0x2559, "SF490000"}, {0x2558, "SF500000"}, {0x2552, "SF510000"}, {0x2553, "SF520000"}, {0x256b, "SF530000"}, {0x256a, "SF540000"}, {0x015a, "Sacute"}, {0x0160, "Scaron"}, {0x0160, "Scaronsmall"}, {0x015e, "Scedilla"}, {0x015c, "Scircumflex"}, {0x0218, "Scommaaccent"}, {0x03a3, "Sigma"}, {0x0053, "Ssmall"}, {0x0054, "T"}, {0x03a4, "Tau"}, {0x0166, "Tbar"}, {0x0164, "Tcaron"}, {0x0162, "Tcommaaccent"}, {0x0398, "Theta"}, {0x00de, "Thorn"}, {0x00de, "Thornsmall"}, {0xf6fe, "Tildesmall"}, {0x0054, "Tsmall"}, {0x0055, "U"}, {0x00da, "Uacute"}, {0x00da, "Uacutesmall"}, {0x016c, "Ubreve"}, {0x00db, "Ucircumflex"}, {0x00db, "Ucircumflexsmall"}, {0x00dc, "Udieresis"}, {0x00dc, "Udieresissmall"}, {0x00d9, "Ugrave"}, {0x00d9, "Ugravesmall"}, {0x01af, "Uhorn"}, {0x0170, "Uhungarumlaut"}, {0x016a, "Umacron"}, {0x0172, "Uogonek"}, {0x03a5, "Upsilon"}, {0x03d2, "Upsilon1"}, {0x03ab, "Upsilondieresis"}, {0x038e, "Upsilontonos"}, {0x016e, "Uring"}, {0x0055, "Usmall"}, {0x0168, "Utilde"}, {0x0056, "V"}, {0x0056, "Vsmall"}, {0x0057, "W"}, {0x1e82, "Wacute"}, {0x0174, "Wcircumflex"}, {0x1e84, "Wdieresis"}, {0x1e80, "Wgrave"}, {0x0057, "Wsmall"}, {0x0058, "X"}, {0x039e, "Xi"}, {0x0058, "Xsmall"}, {0x0059, "Y"}, {0x00dd, "Yacute"}, {0x00dd, "Yacutesmall"}, {0x0176, "Ycircumflex"}, {0x0178, "Ydieresis"}, {0x0178, "Ydieresissmall"}, {0x1ef2, "Ygrave"}, {0x0059, "Ysmall"}, {0x005a, "Z"}, {0x0179, "Zacute"}, {0x017d, "Zcaron"}, {0x017d, "Zcaronsmall"}, {0x017b, "Zdotaccent"}, {0x0396, "Zeta"}, {0x005a, "Zsmall"}, {0x0022, "\""}, {0x005c, "\\"}, {0x005d, "]"}, {0x005e, "^"}, {0x005f, "_"}, {0x0060, "`"}, {0x0061, "a"}, {0x00e1, "aacute"}, {0x0103, "abreve"}, {0x00e2, "acircumflex"}, {0x00b4, "acute"}, {0x0301, "acutecomb"}, {0x00e4, "adieresis"}, {0x00e6, "ae"}, {0x01fd, "aeacute"}, {0x2015, "afii00208"}, {0x0410, "afii10017"}, {0x0411, "afii10018"}, {0x0412, "afii10019"}, {0x0413, "afii10020"}, {0x0414, "afii10021"}, {0x0415, "afii10022"}, {0x0401, "afii10023"}, {0x0416, "afii10024"}, {0x0417, "afii10025"}, {0x0418, "afii10026"}, {0x0419, "afii10027"}, {0x041a, "afii10028"}, {0x041b, "afii10029"}, {0x041c, "afii10030"}, {0x041d, "afii10031"}, {0x041e, "afii10032"}, {0x041f, "afii10033"}, {0x0420, "afii10034"}, {0x0421, "afii10035"}, {0x0422, "afii10036"}, {0x0423, "afii10037"}, {0x0424, "afii10038"}, {0x0425, "afii10039"}, {0x0426, "afii10040"}, {0x0427, "afii10041"}, {0x0428, "afii10042"}, {0x0429, "afii10043"}, {0x042a, "afii10044"}, {0x042b, "afii10045"}, {0x042c, "afii10046"}, {0x042d, "afii10047"}, {0x042e, "afii10048"}, {0x042f, "afii10049"}, {0x0490, "afii10050"}, {0x0402, "afii10051"}, {0x0403, "afii10052"}, {0x0404, "afii10053"}, {0x0405, "afii10054"}, {0x0406, "afii10055"}, {0x0407, "afii10056"}, {0x0408, "afii10057"}, {0x0409, "afii10058"}, {0x040a, "afii10059"}, {0x040b, "afii10060"}, {0x040c, "afii10061"}, {0x040e, "afii10062"}, {0xf6c4, "afii10063"}, {0xf6c5, "afii10064"}, {0x0430, "afii10065"}, {0x0431, "afii10066"}, {0x0432, "afii10067"}, {0x0433, "afii10068"}, {0x0434, "afii10069"}, {0x0435, "afii10070"}, {0x0451, "afii10071"}, {0x0436, "afii10072"}, {0x0437, "afii10073"}, {0x0438, "afii10074"}, {0x0439, "afii10075"}, {0x043a, "afii10076"}, {0x043b, "afii10077"}, {0x043c, "afii10078"}, {0x043d, "afii10079"}, {0x043e, "afii10080"}, {0x043f, "afii10081"}, {0x0440, "afii10082"}, {0x0441, "afii10083"}, {0x0442, "afii10084"}, {0x0443, "afii10085"}, {0x0444, "afii10086"}, {0x0445, "afii10087"}, {0x0446, "afii10088"}, {0x0447, "afii10089"}, {0x0448, "afii10090"}, {0x0449, "afii10091"}, {0x044a, "afii10092"}, {0x044b, "afii10093"}, {0x044c, "afii10094"}, {0x044d, "afii10095"}, {0x044e, "afii10096"}, {0x044f, "afii10097"}, {0x0491, "afii10098"}, {0x0452, "afii10099"}, {0x0453, "afii10100"}, {0x0454, "afii10101"}, {0x0455, "afii10102"}, {0x0456, "afii10103"}, {0x0457, "afii10104"}, {0x0458, "afii10105"}, {0x0459, "afii10106"}, {0x045a, "afii10107"}, {0x045b, "afii10108"}, {0x045c, "afii10109"}, {0x045e, "afii10110"}, {0x040f, "afii10145"}, {0x0462, "afii10146"}, {0x0472, "afii10147"}, {0x0474, "afii10148"}, {0xf6c6, "afii10192"}, {0x045f, "afii10193"}, {0x0463, "afii10194"}, {0x0473, "afii10195"}, {0x0475, "afii10196"}, {0xf6c7, "afii10831"}, {0xf6c8, "afii10832"}, {0x04d9, "afii10846"}, {0x200e, "afii299"}, {0x200f, "afii300"}, {0x200d, "afii301"}, {0x066a, "afii57381"}, {0x060c, "afii57388"}, {0x0660, "afii57392"}, {0x0661, "afii57393"}, {0x0662, "afii57394"}, {0x0663, "afii57395"}, {0x0664, "afii57396"}, {0x0665, "afii57397"}, {0x0666, "afii57398"}, {0x0667, "afii57399"}, {0x0668, "afii57400"}, {0x0669, "afii57401"}, {0x061b, "afii57403"}, {0x061f, "afii57407"}, {0x0621, "afii57409"}, {0x0622, "afii57410"}, {0x0623, "afii57411"}, {0x0624, "afii57412"}, {0x0625, "afii57413"}, {0x0626, "afii57414"}, {0x0627, "afii57415"}, {0x0628, "afii57416"}, {0x0629, "afii57417"}, {0x062a, "afii57418"}, {0x062b, "afii57419"}, {0x062c, "afii57420"}, {0x062d, "afii57421"}, {0x062e, "afii57422"}, {0x062f, "afii57423"}, {0x0630, "afii57424"}, {0x0631, "afii57425"}, {0x0632, "afii57426"}, {0x0633, "afii57427"}, {0x0634, "afii57428"}, {0x0635, "afii57429"}, {0x0636, "afii57430"}, {0x0637, "afii57431"}, {0x0638, "afii57432"}, {0x0639, "afii57433"}, {0x063a, "afii57434"}, {0x0640, "afii57440"}, {0x0641, "afii57441"}, {0x0642, "afii57442"}, {0x0643, "afii57443"}, {0x0644, "afii57444"}, {0x0645, "afii57445"}, {0x0646, "afii57446"}, {0x0648, "afii57448"}, {0x0649, "afii57449"}, {0x064a, "afii57450"}, {0x064b, "afii57451"}, {0x064c, "afii57452"}, {0x064d, "afii57453"}, {0x064e, "afii57454"}, {0x064f, "afii57455"}, {0x0650, "afii57456"}, {0x0651, "afii57457"}, {0x0652, "afii57458"}, {0x0647, "afii57470"}, {0x06a4, "afii57505"}, {0x067e, "afii57506"}, {0x0686, "afii57507"}, {0x0698, "afii57508"}, {0x06af, "afii57509"}, {0x0679, "afii57511"}, {0x0688, "afii57512"}, {0x0691, "afii57513"}, {0x06ba, "afii57514"}, {0x06d2, "afii57519"}, {0x06d5, "afii57534"}, {0x20aa, "afii57636"}, {0x05be, "afii57645"}, {0x05c3, "afii57658"}, {0x05d0, "afii57664"}, {0x05d1, "afii57665"}, {0x05d2, "afii57666"}, {0x05d3, "afii57667"}, {0x05d4, "afii57668"}, {0x05d5, "afii57669"}, {0x05d6, "afii57670"}, {0x05d7, "afii57671"}, {0x05d8, "afii57672"}, {0x05d9, "afii57673"}, {0x05da, "afii57674"}, {0x05db, "afii57675"}, {0x05dc, "afii57676"}, {0x05dd, "afii57677"}, {0x05de, "afii57678"}, {0x05df, "afii57679"}, {0x05e0, "afii57680"}, {0x05e1, "afii57681"}, {0x05e2, "afii57682"}, {0x05e3, "afii57683"}, {0x05e4, "afii57684"}, {0x05e5, "afii57685"}, {0x05e6, "afii57686"}, {0x05e7, "afii57687"}, {0x05e8, "afii57688"}, {0x05e9, "afii57689"}, {0x05ea, "afii57690"}, {0xfb2a, "afii57694"}, {0xfb2b, "afii57695"}, {0xfb4b, "afii57700"}, {0xfb1f, "afii57705"}, {0x05f0, "afii57716"}, {0x05f1, "afii57717"}, {0x05f2, "afii57718"}, {0xfb35, "afii57723"}, {0x05b4, "afii57793"}, {0x05b5, "afii57794"}, {0x05b6, "afii57795"}, {0x05bb, "afii57796"}, {0x05b8, "afii57797"}, {0x05b7, "afii57798"}, {0x05b0, "afii57799"}, {0x05b2, "afii57800"}, {0x05b1, "afii57801"}, {0x05b3, "afii57802"}, {0x05c2, "afii57803"}, {0x05c1, "afii57804"}, {0x05b9, "afii57806"}, {0x05bc, "afii57807"}, {0x05bd, "afii57839"}, {0x05bf, "afii57841"}, {0x05c0, "afii57842"}, {0x02bc, "afii57929"}, {0x2105, "afii61248"}, {0x2113, "afii61289"}, {0x2116, "afii61352"}, {0x202c, "afii61573"}, {0x202d, "afii61574"}, {0x202e, "afii61575"}, {0x200c, "afii61664"}, {0x066d, "afii63167"}, {0x02bd, "afii64937"}, {0x00e0, "agrave"}, {0x2135, "aleph"}, {0x03b1, "alpha"}, {0x03ac, "alphatonos"}, {0x0101, "amacron"}, {0x0026, "ampersand"}, {0x0026, "ampersandsmall"}, {0x2220, "angle"}, {0x2329, "angleleft"}, {0x232a, "angleright"}, {0x0387, "anoteleia"}, {0x0105, "aogonek"}, {0x2248, "approxequal"}, {0x00e5, "aring"}, {0x01fb, "aringacute"}, {0x2194, "arrowboth"}, {0x21d4, "arrowdblboth"}, {0x21d3, "arrowdbldown"}, {0x21d0, "arrowdblleft"}, {0x21d2, "arrowdblright"}, {0x21d1, "arrowdblup"}, {0x2193, "arrowdown"}, {0xf8e7, "arrowhorizex"}, {0x2190, "arrowleft"}, {0x2192, "arrowright"}, {0x2191, "arrowup"}, {0x2195, "arrowupdn"}, {0x21a8, "arrowupdnbse"}, {0xf8e6, "arrowvertex"}, {0x005e, "asciicircum"}, {0x007e, "asciitilde"}, {0x002a, "asterisk"}, {0x2217, "asteriskmath"}, {0xf6e9, "asuperior"}, {0x0040, "at"}, {0x00e3, "atilde"}, {0x0062, "b"}, {0x005c, "backslash"}, {0x007c, "bar"}, {0x03b2, "beta"}, {0x2588, "block"}, {0xf8f4, "braceex"}, {0x007b, "braceleft"}, {0xf8f3, "braceleftbt"}, {0xf8f2, "braceleftmid"}, {0xf8f1, "bracelefttp"}, {0x007d, "braceright"}, {0xf8fe, "bracerightbt"}, {0xf8fd, "bracerightmid"}, {0xf8fc, "bracerighttp"}, {0x005b, "bracketleft"}, {0xf8f0, "bracketleftbt"}, {0xf8ef, "bracketleftex"}, {0xf8ee, "bracketlefttp"}, {0x005d, "bracketright"}, {0xf8fb, "bracketrightbt"}, {0xf8fa, "bracketrightex"}, {0xf8f9, "bracketrighttp"}, {0x02d8, "breve"}, {0x00a6, "brokenbar"}, {0xf6ea, "bsuperior"}, {0x2022, "bullet"}, {0x0063, "c"}, {0x0107, "cacute"}, {0x02c7, "caron"}, {0x21b5, "carriagereturn"}, {0x010d, "ccaron"}, {0x00e7, "ccedilla"}, {0x0109, "ccircumflex"}, {0x010b, "cdotaccent"}, {0x00b8, "cedilla"}, {0x00a2, "cent"}, {0xf6df, "centinferior"}, {0x00a2, "centoldstyle"}, {0xf6e0, "centsuperior"}, {0x03c7, "chi"}, {0x25cb, "circle"}, {0x2297, "circlemultiply"}, {0x2295, "circleplus"}, {0x02c6, "circumflex"}, {0x2663, "club"}, {0x003a, "colon"}, {0x20a1, "colonmonetary"}, {0x002c, "comma"}, {0xf6c3, "commaaccent"}, {0xf6e1, "commainferior"}, {0xf6e2, "commasuperior"}, {0x2245, "congruent"}, {0x00a9, "copyright"}, {0x00a9, "copyrightsans"}, {0x00a9, "copyrightserif"}, {0x00a4, "currency"}, {0xf6d1, "cyrBreve"}, {0xf6d2, "cyrFlex"}, {0xf6d4, "cyrbreve"}, {0xf6d5, "cyrflex"}, {0x0064, "d"}, {0x2020, "dagger"}, {0x2021, "daggerdbl"}, {0xf6d3, "dblGrave"}, {0xf6d6, "dblgrave"}, {0x010f, "dcaron"}, {0x0111, "dcroat"}, {0x00b0, "degree"}, {0x03b4, "delta"}, {0x2666, "diamond"}, {0x00a8, "dieresis"}, {0xf6d7, "dieresisacute"}, {0xf6d8, "dieresisgrave"}, {0x0385, "dieresistonos"}, {0x00f7, "divide"}, {0x2593, "dkshade"}, {0x2584, "dnblock"}, {0x0024, "dollar"}, {0xf6e3, "dollarinferior"}, {0x0024, "dollaroldstyle"}, {0xf6e4, "dollarsuperior"}, {0x20ab, "dong"}, {0x02d9, "dotaccent"}, {0x0323, "dotbelowcomb"}, {0x0131, "dotlessi"}, {0xf6be, "dotlessj"}, {0x22c5, "dotmath"}, {0xf6eb, "dsuperior"}, {0x0065, "e"}, {0x00e9, "eacute"}, {0x0115, "ebreve"}, {0x011b, "ecaron"}, {0x00ea, "ecircumflex"}, {0x00eb, "edieresis"}, {0x0117, "edotaccent"}, {0x00e8, "egrave"}, {0x0038, "eight"}, {0x2088, "eightinferior"}, {0x0038, "eightoldstyle"}, {0x2078, "eightsuperior"}, {0x2208, "element"}, {0x2026, "ellipsis"}, {0x0113, "emacron"}, {0x2014, "emdash"}, {0x2205, "emptyset"}, {0x2013, "endash"}, {0x014b, "eng"}, {0x0119, "eogonek"}, {0x03b5, "epsilon"}, {0x03ad, "epsilontonos"}, {0x003d, "equal"}, {0x2261, "equivalence"}, {0x212e, "estimated"}, {0xf6ec, "esuperior"}, {0x03b7, "eta"}, {0x03ae, "etatonos"}, {0x00f0, "eth"}, {0x0021, "exclam"}, {0x203c, "exclamdbl"}, {0x00a1, "exclamdown"}, {0x00a1, "exclamdownsmall"}, {0x0021, "exclamleft"}, {0x0021, "exclamsmall"}, {0x2203, "existential"}, {0x0066, "f"}, {0xfb00, "ff"}, {0xfb03, "ffi"}, {0xfb04, "ffl"}, {0xfb01, "fi"}, {0xfb00, "f_f"}, {0xfb03, "f_f_i"}, {0xfb04, "f_f_l"}, {0xfb01, "f_i"}, {0x2640, "female"}, {0x2012, "figuredash"}, {0x25a0, "filledbox"}, {0x25ac, "filledrect"}, {0x0035, "five"}, {0x215d, "fiveeighths"}, {0x2085, "fiveinferior"}, {0x0035, "fiveoldstyle"}, {0x2075, "fivesuperior"}, {0xfb02, "fl"}, {0xfb02, "f_l"}, {0x0192, "florin"}, {0x0034, "four"}, {0x2084, "fourinferior"}, {0x0034, "fouroldstyle"}, {0x2074, "foursuperior"}, {0x2044, "fraction"}, {0x20a3, "franc"}, {0x0067, "g"}, {0x03b3, "gamma"}, {0x011f, "gbreve"}, {0x01e7, "gcaron"}, {0x011d, "gcircumflex"}, {0x0123, "gcommaaccent"}, {0x0121, "gdotaccent"}, {0x00df, "germandbls"}, {0x2207, "gradient"}, {0x0060, "grave"}, {0x0300, "gravecomb"}, {0x003e, "greater"}, {0x2265, "greaterequal"}, {0x00ab, "guillemotleft"}, {0x00bb, "guillemotright"}, {0x2039, "guilsinglleft"}, {0x203a, "guilsinglright"}, {0x0068, "h"}, {0x0127, "hbar"}, {0x0125, "hcircumflex"}, {0x2665, "heart"}, {0x0309, "hookabovecomb"}, {0x2302, "house"}, {0x02dd, "hungarumlaut"}, {0x002d, "hyphen"}, {0xf6e5, "hypheninferior"}, {0xf6e6, "hyphensuperior"}, {0x0069, "i"}, {0x00ed, "iacute"}, {0x012d, "ibreve"}, {0x00ee, "icircumflex"}, {0x00ef, "idieresis"}, {0x00ec, "igrave"}, {0x0133, "ij"}, {0x012b, "imacron"}, {0x221e, "infinity"}, {0x222b, "integral"}, {0x2321, "integralbt"}, {0xf8f5, "integralex"}, {0x2320, "integraltp"}, {0x2229, "intersection"}, {0x25d8, "invbullet"}, {0x25d9, "invcircle"}, {0x263b, "invsmileface"}, {0x012f, "iogonek"}, {0x03b9, "iota"}, {0x03ca, "iotadieresis"}, {0x0390, "iotadieresistonos"}, {0x03af, "iotatonos"}, {0xf6ed, "isuperior"}, {0x0129, "itilde"}, {0x006a, "j"}, {0x0135, "jcircumflex"}, {0x006b, "k"}, {0x03ba, "kappa"}, {0x0137, "kcommaaccent"}, {0x0138, "kgreenlandic"}, {0x006c, "l"}, {0x013a, "lacute"}, {0x03bb, "lambda"}, {0x013e, "lcaron"}, {0x013c, "lcommaaccent"}, {0x0140, "ldot"}, {0x003c, "less"}, {0x2264, "lessequal"}, {0x258c, "lfblock"}, {0x20a4, "lira"}, {0xf6c0, "ll"}, {0x2227, "logicaland"}, {0x00ac, "logicalnot"}, {0x2228, "logicalor"}, {0x017f, "longs"}, {0x25ca, "lozenge"}, {0x0142, "lslash"}, {0xf6ee, "lsuperior"}, {0x2591, "ltshade"}, {0x006d, "m"}, {0x00af, "macron"}, {0x2642, "male"}, {0x2212, "minus"}, {0x2032, "minute"}, {0xf6ef, "msuperior"}, {0x00b5, "mu"}, {0x00d7, "multiply"}, {0x266a, "musicalnote"}, {0x266b, "musicalnotedbl"}, {0x006e, "n"}, {0x0144, "nacute"}, {0x0149, "napostrophe"}, {0x00a0, "nbspace"}, {0x0148, "ncaron"}, {0x0146, "ncommaaccent"}, {0x0039, "nine"}, {0x2089, "nineinferior"}, {0x0039, "nineoldstyle"}, {0x2079, "ninesuperior"}, {0x00a0, "nonbreakingspace"}, {0x2209, "notelement"}, {0x2260, "notequal"}, {0x2284, "notsubset"}, {0x207f, "nsuperior"}, {0x00f1, "ntilde"}, {0x03bd, "nu"}, {0x0023, "numbersign"}, {0x006f, "o"}, {0x00f3, "oacute"}, {0x014f, "obreve"}, {0x00f4, "ocircumflex"}, {0x00f6, "odieresis"}, {0x0153, "oe"}, {0x02db, "ogonek"}, {0x00f2, "ograve"}, {0x01a1, "ohorn"}, {0x0151, "ohungarumlaut"}, {0x014d, "omacron"}, {0x03c9, "omega"}, {0x03d6, "omega1"}, {0x03ce, "omegatonos"}, {0x03bf, "omicron"}, {0x03cc, "omicrontonos"}, {0x0031, "one"}, {0x2024, "onedotenleader"}, {0x215b, "oneeighth"}, {0xf6dc, "onefitted"}, {0x00bd, "onehalf"}, {0x2081, "oneinferior"}, {0x0031, "oneoldstyle"}, {0x00bc, "onequarter"}, {0x00b9, "onesuperior"}, {0x2153, "onethird"}, {0x25e6, "openbullet"}, {0x00aa, "ordfeminine"}, {0x00ba, "ordmasculine"}, {0x221f, "orthogonal"}, {0x00f8, "oslash"}, {0x01ff, "oslashacute"}, {0xf6f0, "osuperior"}, {0x00f5, "otilde"}, {0x0070, "p"}, {0x00b6, "paragraph"}, {0x0028, "parenleft"}, {0xf8ed, "parenleftbt"}, {0xf8ec, "parenleftex"}, {0x208d, "parenleftinferior"}, {0x207d, "parenleftsuperior"}, {0xf8eb, "parenlefttp"}, {0x0029, "parenright"}, {0xf8f8, "parenrightbt"}, {0xf8f7, "parenrightex"}, {0x208e, "parenrightinferior"}, {0x207e, "parenrightsuperior"}, {0xf8f6, "parenrighttp"}, {0x2202, "partialdiff"}, {0x0025, "percent"}, {0x002e, "period"}, {0x00b7, "periodcentered"}, {0xf6e7, "periodinferior"}, {0xf6e8, "periodsuperior"}, {0x22a5, "perpendicular"}, {0x2030, "perthousand"}, {0x20a7, "peseta"}, {0x03c6, "phi"}, {0x03d5, "phi1"}, {0x03c0, "pi"}, {0x002b, "plus"}, {0x00b1, "plusminus"}, {0x211e, "prescription"}, {0x220f, "product"}, {0x2282, "propersubset"}, {0x2283, "propersuperset"}, {0x221d, "proportional"}, {0x03c8, "psi"}, {0x0071, "q"}, {0x003f, "question"}, {0x00bf, "questiondown"}, {0x00bf, "questiondownsmall"}, {0x003f, "questionsmall"}, {0x0022, "quotedbl"}, {0x201e, "quotedblbase"}, {0x201c, "quotedblleft"}, {0x201d, "quotedblright"}, {0x2018, "quoteleft"}, {0x201b, "quotereversed"}, {0x2019, "quoteright"}, {0x201a, "quotesinglbase"}, {0x0027, "quotesingle"}, {0x0072, "r"}, {0x0155, "racute"}, {0x221a, "radical"}, {0xf8e5, "radicalex"}, {0x0159, "rcaron"}, {0x0157, "rcommaaccent"}, {0x2286, "reflexsubset"}, {0x2287, "reflexsuperset"}, {0x00ae, "registered"}, {0x00ae, "registersans"}, {0x00ae, "registerserif"}, {0x2310, "revlogicalnot"}, {0x03c1, "rho"}, {0x02da, "ring"}, {0xf6f1, "rsuperior"}, {0x2590, "rtblock"}, {0xf6dd, "rupiah"}, {0x0073, "s"}, {0x015b, "sacute"}, {0x0161, "scaron"}, {0x015f, "scedilla"}, {0x015d, "scircumflex"}, {0x0219, "scommaaccent"}, {0x2033, "second"}, {0x00a7, "section"}, {0x003b, "semicolon"}, {0x0037, "seven"}, {0x215e, "seveneighths"}, {0x2087, "seveninferior"}, {0x0037, "sevenoldstyle"}, {0x2077, "sevensuperior"}, {0x2592, "shade"}, {0x03c3, "sigma"}, {0x03c2, "sigma1"}, {0x223c, "similar"}, {0x0036, "six"}, {0x2086, "sixinferior"}, {0x0036, "sixoldstyle"}, {0x2076, "sixsuperior"}, {0x002f, "slash"}, {0x263a, "smileface"}, {0x0020, "space"}, {0x2660, "spade"}, {0xf6f2, "ssuperior"}, {0x00a3, "sterling"}, {0x220b, "suchthat"}, {0x2211, "summation"}, {0x263c, "sun"}, {0x0074, "t"}, {0x03c4, "tau"}, {0x0167, "tbar"}, {0x0165, "tcaron"}, {0x0163, "tcommaaccent"}, {0x2234, "therefore"}, {0x03b8, "theta"}, {0x03d1, "theta1"}, {0x00fe, "thorn"}, {0x0033, "three"}, {0x215c, "threeeighths"}, {0x2083, "threeinferior"}, {0x0033, "threeoldstyle"}, {0x00be, "threequarters"}, {0xf6de, "threequartersemdash"}, {0x00b3, "threesuperior"}, {0x02dc, "tilde"}, {0x0303, "tildecomb"}, {0x0384, "tonos"}, {0x2122, "trademark"}, {0x2122, "trademarksans"}, {0x2122, "trademarkserif"}, {0x25bc, "triagdn"}, {0x25c4, "triaglf"}, {0x25ba, "triagrt"}, {0x25b2, "triagup"}, {0xf6f3, "tsuperior"}, {0x0032, "two"}, {0x2025, "twodotenleader"}, {0x2082, "twoinferior"}, {0x0032, "twooldstyle"}, {0x00b2, "twosuperior"}, {0x2154, "twothirds"}, {0x0075, "u"}, {0x00fa, "uacute"}, {0x016d, "ubreve"}, {0x00fb, "ucircumflex"}, {0x00fc, "udieresis"}, {0x00f9, "ugrave"}, {0x01b0, "uhorn"}, {0x0171, "uhungarumlaut"}, {0x016b, "umacron"}, {0x005f, "underscore"}, {0x2017, "underscoredbl"}, {0x222a, "union"}, {0x2200, "universal"}, {0x0173, "uogonek"}, {0x2580, "upblock"}, {0x03c5, "upsilon"}, {0x03cb, "upsilondieresis"}, {0x03b0, "upsilondieresistonos"}, {0x03cd, "upsilontonos"}, {0x016f, "uring"}, {0x0169, "utilde"}, {0x0076, "v"}, {0x0077, "w"}, {0x1e83, "wacute"}, {0x0175, "wcircumflex"}, {0x1e85, "wdieresis"}, {0x2118, "weierstrass"}, {0x1e81, "wgrave"}, {0x0078, "x"}, {0x03be, "xi"}, {0x0079, "y"}, {0x00fd, "yacute"}, {0x0177, "ycircumflex"}, {0x00ff, "ydieresis"}, {0x00a5, "yen"}, {0x1ef3, "ygrave"}, {0x007a, "z"}, {0x017a, "zacute"}, {0x017e, "zcaron"}, {0x017c, "zdotaccent"}, {0x0030, "zero"}, {0x2080, "zeroinferior"}, {0x0030, "zerooldstyle"}, {0x2070, "zerosuperior"}, {0x03b6, "zeta"}, {0x007b, "{"}, {0x007c, "|"}, {0x007d, "}"}, {0x007e, "~"}, { 0, NULL } }; static struct { pdf_utf16be u; const char *name; } UnicodeToNameTab[] = { {0x0000, ".notdef"}, {0x0020, "space"}, {0x0021, "exclam"}, {0x0022, "quotedbl"}, {0x0023, "numbersign"}, {0x0024, "dollar"}, {0x0025, "percent"}, {0x0026, "ampersand"}, {0x0027, "quotesingle"}, {0x0028, "parenleft"}, {0x0029, "parenright"}, {0x002A, "asterisk"}, {0x002B, "plus"}, {0x002C, "comma"}, {0x002D, "hyphen"}, {0x002E, "period"}, {0x002F, "slash"}, {0x0030, "zero"}, {0x0031, "one"}, {0x0032, "two"}, {0x0033, "three"}, {0x0034, "four"}, {0x0035, "five"}, {0x0036, "six"}, {0x0037, "seven"}, {0x0038, "eight"}, {0x0039, "nine"}, {0x003A, "colon"}, {0x003B, "semicolon"}, {0x003C, "less"}, {0x003D, "equal"}, {0x003E, "greater"}, {0x003F, "question"}, {0x0040, "at"}, {0x0041, "A"}, {0x0042, "B"}, {0x0043, "C"}, {0x0044, "D"}, {0x0045, "E"}, {0x0046, "F"}, {0x0047, "G"}, {0x0048, "H"}, {0x0049, "I"}, {0x004A, "J"}, {0x004B, "K"}, {0x004C, "L"}, {0x004D, "M"}, {0x004E, "N"}, {0x004F, "O"}, {0x0050, "P"}, {0x0051, "Q"}, {0x0052, "R"}, {0x0053, "S"}, {0x0054, "T"}, {0x0055, "U"}, {0x0056, "V"}, {0x0057, "W"}, {0x0058, "X"}, {0x0059, "Y"}, {0x005A, "Z"}, {0x005B, "bracketleft"}, {0x005C, "backslash"}, {0x005D, "bracketright"}, {0x005E, "asciicircum"}, {0x005F, "underscore"}, {0x0060, "grave"}, {0x0061, "a"}, {0x0062, "b"}, {0x0063, "c"}, {0x0064, "d"}, {0x0065, "e"}, {0x0066, "f"}, {0x0067, "g"}, {0x0068, "h"}, {0x0069, "i"}, {0x006A, "j"}, {0x006B, "k"}, {0x006C, "l"}, {0x006D, "m"}, {0x006E, "n"}, {0x006F, "o"}, {0x0070, "p"}, {0x0071, "q"}, {0x0072, "r"}, {0x0073, "s"}, {0x0074, "t"}, {0x0075, "u"}, {0x0076, "v"}, {0x0077, "w"}, {0x0078, "x"}, {0x0079, "y"}, {0x007A, "z"}, {0x007B, "braceleft"}, {0x007C, "bar"}, {0x007D, "braceright"}, {0x007E, "asciitilde"}, {0x00A0, "space"}, {0x00A1, "exclamdown"}, {0x00A2, "cent"}, {0x00A3, "sterling"}, {0x00A4, "currency"}, {0x00A5, "yen"}, {0x00A6, "brokenbar"}, {0x00A7, "section"}, {0x00A8, "dieresis"}, {0x00A9, "copyright"}, {0x00AA, "ordfeminine"}, {0x00AB, "guillemotleft"}, {0x00AC, "logicalnot"}, {0x00AD, "hyphen"}, {0x00AE, "registered"}, {0x00AF, "macron"}, {0x00B0, "degree"}, {0x00B1, "plusminus"}, {0x00B2, "twosuperior"}, {0x00B3, "threesuperior"}, {0x00B4, "acute"}, {0x00B5, "mu"}, {0x00B6, "paragraph"}, {0x00B7, "periodcentered"}, {0x00B8, "cedilla"}, {0x00B9, "onesuperior"}, {0x00BA, "ordmasculine"}, {0x00BB, "guillemotright"}, {0x00BC, "onequarter"}, {0x00BD, "onehalf"}, {0x00BE, "threequarters"}, {0x00BF, "questiondown"}, {0x00C0, "Agrave"}, {0x00C1, "Aacute"}, {0x00C2, "Acircumflex"}, {0x00C3, "Atilde"}, {0x00C4, "Adieresis"}, {0x00C5, "Aring"}, {0x00C6, "AE"}, {0x00C7, "Ccedilla"}, {0x00C8, "Egrave"}, {0x00C9, "Eacute"}, {0x00CA, "Ecircumflex"}, {0x00CB, "Edieresis"}, {0x00CC, "Igrave"}, {0x00CD, "Iacute"}, {0x00CE, "Icircumflex"}, {0x00CF, "Idieresis"}, {0x00D0, "Eth"}, {0x00D1, "Ntilde"}, {0x00D2, "Ograve"}, {0x00D3, "Oacute"}, {0x00D4, "Ocircumflex"}, {0x00D5, "Otilde"}, {0x00D6, "Odieresis"}, {0x00D7, "multiply"}, {0x00D8, "Oslash"}, {0x00D9, "Ugrave"}, {0x00DA, "Uacute"}, {0x00DB, "Ucircumflex"}, {0x00DC, "Udieresis"}, {0x00DD, "Yacute"}, {0x00DE, "Thorn"}, {0x00DF, "germandbls"}, {0x00E0, "agrave"}, {0x00E1, "aacute"}, {0x00E2, "acircumflex"}, {0x00E3, "atilde"}, {0x00E4, "adieresis"}, {0x00E5, "aring"}, {0x00E6, "ae"}, {0x00E7, "ccedilla"}, {0x00E8, "egrave"}, {0x00E9, "eacute"}, {0x00EA, "ecircumflex"}, {0x00EB, "edieresis"}, {0x00EC, "igrave"}, {0x00ED, "iacute"}, {0x00EE, "icircumflex"}, {0x00EF, "idieresis"}, {0x00F0, "eth"}, {0x00F1, "ntilde"}, {0x00F2, "ograve"}, {0x00F3, "oacute"}, {0x00F4, "ocircumflex"}, {0x00F5, "otilde"}, {0x00F6, "odieresis"}, {0x00F7, "divide"}, {0x00F8, "oslash"}, {0x00F9, "ugrave"}, {0x00FA, "uacute"}, {0x00FB, "ucircumflex"}, {0x00FC, "udieresis"}, {0x00FD, "yacute"}, {0x00FE, "thorn"}, {0x00FF, "ydieresis"}, {0x0100, "Amacron"}, {0x0101, "amacron"}, {0x0102, "Abreve"}, {0x0103, "abreve"}, {0x0104, "Aogonek"}, {0x0105, "aogonek"}, {0x0106, "Cacute"}, {0x0107, "cacute"}, {0x0108, "Ccircumflex"}, {0x0109, "ccircumflex"}, {0x010A, "Cdotaccent"}, {0x010B, "cdotaccent"}, {0x010C, "Ccaron"}, {0x010D, "ccaron"}, {0x010E, "Dcaron"}, {0x010F, "dcaron"}, {0x0110, "Dcroat"}, {0x0111, "dcroat"}, {0x0112, "Emacron"}, {0x0113, "emacron"}, {0x0114, "Ebreve"}, {0x0115, "ebreve"}, {0x0116, "Edotaccent"}, {0x0117, "edotaccent"}, {0x0118, "Eogonek"}, {0x0119, "eogonek"}, {0x011A, "Ecaron"}, {0x011B, "ecaron"}, {0x011C, "Gcircumflex"}, {0x011D, "gcircumflex"}, {0x011E, "Gbreve"}, {0x011F, "gbreve"}, {0x0120, "Gdotaccent"}, {0x0121, "gdotaccent"}, {0x0122, "Gcommaaccent"}, {0x0123, "gcommaaccent"}, {0x0124, "Hcircumflex"}, {0x0125, "hcircumflex"}, {0x0126, "Hbar"}, {0x0127, "hbar"}, {0x0128, "Itilde"}, {0x0129, "itilde"}, {0x012A, "Imacron"}, {0x012B, "imacron"}, {0x012C, "Ibreve"}, {0x012D, "ibreve"}, {0x012E, "Iogonek"}, {0x012F, "iogonek"}, {0x0130, "Idotaccent"}, {0x0131, "dotlessi"}, {0x0132, "IJ"}, {0x0133, "ij"}, {0x0134, "Jcircumflex"}, {0x0135, "jcircumflex"}, {0x0136, "Kcommaaccent"}, {0x0137, "kcommaaccent"}, {0x0138, "kgreenlandic"}, {0x0139, "Lacute"}, {0x013A, "lacute"}, {0x013B, "Lcommaaccent"}, {0x013C, "lcommaaccent"}, {0x013D, "Lcaron"}, {0x013E, "lcaron"}, {0x013F, "Ldot"}, {0x0140, "ldot"}, {0x0141, "Lslash"}, {0x0142, "lslash"}, {0x0143, "Nacute"}, {0x0144, "nacute"}, {0x0145, "Ncommaaccent"}, {0x0146, "ncommaaccent"}, {0x0147, "Ncaron"}, {0x0148, "ncaron"}, {0x0149, "napostrophe"}, {0x014A, "Eng"}, {0x014B, "eng"}, {0x014C, "Omacron"}, {0x014D, "omacron"}, {0x014E, "Obreve"}, {0x014F, "obreve"}, {0x0150, "Ohungarumlaut"}, {0x0151, "ohungarumlaut"}, {0x0152, "OE"}, {0x0153, "oe"}, {0x0154, "Racute"}, {0x0155, "racute"}, {0x0156, "Rcommaaccent"}, {0x0157, "rcommaaccent"}, {0x0158, "Rcaron"}, {0x0159, "rcaron"}, {0x015A, "Sacute"}, {0x015B, "sacute"}, {0x015C, "Scircumflex"}, {0x015D, "scircumflex"}, {0x015E, "Scedilla"}, {0x015F, "scedilla"}, {0x0160, "Scaron"}, {0x0161, "scaron"}, {0x0162, "Tcommaaccent"}, {0x0163, "tcommaaccent"}, {0x0164, "Tcaron"}, {0x0165, "tcaron"}, {0x0166, "Tbar"}, {0x0167, "tbar"}, {0x0168, "Utilde"}, {0x0169, "utilde"}, {0x016A, "Umacron"}, {0x016B, "umacron"}, {0x016C, "Ubreve"}, {0x016D, "ubreve"}, {0x016E, "Uring"}, {0x016F, "uring"}, {0x0170, "Uhungarumlaut"}, {0x0171, "uhungarumlaut"}, {0x0172, "Uogonek"}, {0x0173, "uogonek"}, {0x0174, "Wcircumflex"}, {0x0175, "wcircumflex"}, {0x0176, "Ycircumflex"}, {0x0177, "ycircumflex"}, {0x0178, "Ydieresis"}, {0x0179, "Zacute"}, {0x017A, "zacute"}, {0x017B, "Zdotaccent"}, {0x017C, "zdotaccent"}, {0x017D, "Zcaron"}, {0x017E, "zcaron"}, {0x017F, "longs"}, {0x0192, "florin"}, {0x01A0, "Ohorn"}, {0x01A1, "ohorn"}, {0x01AF, "Uhorn"}, {0x01B0, "uhorn"}, {0x01E6, "Gcaron"}, {0x01E7, "gcaron"}, {0x01FA, "Aringacute"}, {0x01FB, "aringacute"}, {0x01FC, "AEacute"}, {0x01FD, "aeacute"}, {0x01FE, "Oslashacute"}, {0x01FF, "oslashacute"}, {0x0218, "Scommaaccent"}, {0x0219, "scommaaccent"}, {0x021A, "Tcommaaccent"}, {0x021B, "tcommaaccent"}, {0x02BC, "afii57929"}, {0x02BD, "afii64937"}, {0x02C6, "circumflex"}, {0x02C7, "caron"}, {0x02C9, "macron"}, {0x02D8, "breve"}, {0x02D9, "dotaccent"}, {0x02DA, "ring"}, {0x02DB, "ogonek"}, {0x02DC, "tilde"}, {0x02DD, "hungarumlaut"}, {0x0300, "gravecomb"}, {0x0301, "acutecomb"}, {0x0303, "tildecomb"}, {0x0309, "hookabovecomb"}, {0x0323, "dotbelowcomb"}, {0x0384, "tonos"}, {0x0385, "dieresistonos"}, {0x0386, "Alphatonos"}, {0x0387, "anoteleia"}, {0x0388, "Epsilontonos"}, {0x0389, "Etatonos"}, {0x038A, "Iotatonos"}, {0x038C, "Omicrontonos"}, {0x038E, "Upsilontonos"}, {0x038F, "Omegatonos"}, {0x0390, "iotadieresistonos"}, {0x0391, "Alpha"}, {0x0392, "Beta"}, {0x0393, "Gamma"}, {0x0394, "Delta"}, {0x0395, "Epsilon"}, {0x0396, "Zeta"}, {0x0397, "Eta"}, {0x0398, "Theta"}, {0x0399, "Iota"}, {0x039A, "Kappa"}, {0x039B, "Lambda"}, {0x039C, "Mu"}, {0x039D, "Nu"}, {0x039E, "Xi"}, {0x039F, "Omicron"}, {0x03A0, "Pi"}, {0x03A1, "Rho"}, {0x03A3, "Sigma"}, {0x03A4, "Tau"}, {0x03A5, "Upsilon"}, {0x03A6, "Phi"}, {0x03A7, "Chi"}, {0x03A8, "Psi"}, {0x03A9, "Omega"}, {0x03AA, "Iotadieresis"}, {0x03AB, "Upsilondieresis"}, {0x03AC, "alphatonos"}, {0x03AD, "epsilontonos"}, {0x03AE, "etatonos"}, {0x03AF, "iotatonos"}, {0x03B0, "upsilondieresistonos"}, {0x03B1, "alpha"}, {0x03B2, "beta"}, {0x03B3, "gamma"}, {0x03B4, "delta"}, {0x03B5, "epsilon"}, {0x03B6, "zeta"}, {0x03B7, "eta"}, {0x03B8, "theta"}, {0x03B9, "iota"}, {0x03BA, "kappa"}, {0x03BB, "lambda"}, {0x03BC, "mu"}, {0x03BD, "nu"}, {0x03BE, "xi"}, {0x03BF, "omicron"}, {0x03C0, "pi"}, {0x03C1, "rho"}, {0x03C2, "sigma1"}, {0x03C3, "sigma"}, {0x03C4, "tau"}, {0x03C5, "upsilon"}, {0x03C6, "phi"}, {0x03C7, "chi"}, {0x03C8, "psi"}, {0x03C9, "omega"}, {0x03CA, "iotadieresis"}, {0x03CB, "upsilondieresis"}, {0x03CC, "omicrontonos"}, {0x03CD, "upsilontonos"}, {0x03CE, "omegatonos"}, {0x03D1, "theta1"}, {0x03D2, "Upsilon1"}, {0x03D5, "phi1"}, {0x03D6, "omega1"}, {0x0401, "afii10023"}, {0x0402, "afii10051"}, {0x0403, "afii10052"}, {0x0404, "afii10053"}, {0x0405, "afii10054"}, {0x0406, "afii10055"}, {0x0407, "afii10056"}, {0x0408, "afii10057"}, {0x0409, "afii10058"}, {0x040A, "afii10059"}, {0x040B, "afii10060"}, {0x040C, "afii10061"}, {0x040E, "afii10062"}, {0x040F, "afii10145"}, {0x0410, "afii10017"}, {0x0411, "afii10018"}, {0x0412, "afii10019"}, {0x0413, "afii10020"}, {0x0414, "afii10021"}, {0x0415, "afii10022"}, {0x0416, "afii10024"}, {0x0417, "afii10025"}, {0x0418, "afii10026"}, {0x0419, "afii10027"}, {0x041A, "afii10028"}, {0x041B, "afii10029"}, {0x041C, "afii10030"}, {0x041D, "afii10031"}, {0x041E, "afii10032"}, {0x041F, "afii10033"}, {0x0420, "afii10034"}, {0x0421, "afii10035"}, {0x0422, "afii10036"}, {0x0423, "afii10037"}, {0x0424, "afii10038"}, {0x0425, "afii10039"}, {0x0426, "afii10040"}, {0x0427, "afii10041"}, {0x0428, "afii10042"}, {0x0429, "afii10043"}, {0x042A, "afii10044"}, {0x042B, "afii10045"}, {0x042C, "afii10046"}, {0x042D, "afii10047"}, {0x042E, "afii10048"}, {0x042F, "afii10049"}, {0x0430, "afii10065"}, {0x0431, "afii10066"}, {0x0432, "afii10067"}, {0x0433, "afii10068"}, {0x0434, "afii10069"}, {0x0435, "afii10070"}, {0x0436, "afii10072"}, {0x0437, "afii10073"}, {0x0438, "afii10074"}, {0x0439, "afii10075"}, {0x043A, "afii10076"}, {0x043B, "afii10077"}, {0x043C, "afii10078"}, {0x043D, "afii10079"}, {0x043E, "afii10080"}, {0x043F, "afii10081"}, {0x0440, "afii10082"}, {0x0441, "afii10083"}, {0x0442, "afii10084"}, {0x0443, "afii10085"}, {0x0444, "afii10086"}, {0x0445, "afii10087"}, {0x0446, "afii10088"}, {0x0447, "afii10089"}, {0x0448, "afii10090"}, {0x0449, "afii10091"}, {0x044A, "afii10092"}, {0x044B, "afii10093"}, {0x044C, "afii10094"}, {0x044D, "afii10095"}, {0x044E, "afii10096"}, {0x044F, "afii10097"}, {0x0451, "afii10071"}, {0x0452, "afii10099"}, {0x0453, "afii10100"}, {0x0454, "afii10101"}, {0x0455, "afii10102"}, {0x0456, "afii10103"}, {0x0457, "afii10104"}, {0x0458, "afii10105"}, {0x0459, "afii10106"}, {0x045A, "afii10107"}, {0x045B, "afii10108"}, {0x045C, "afii10109"}, {0x045E, "afii10110"}, {0x045F, "afii10193"}, {0x0462, "afii10146"}, {0x0463, "afii10194"}, {0x0472, "afii10147"}, {0x0473, "afii10195"}, {0x0474, "afii10148"}, {0x0475, "afii10196"}, {0x0490, "afii10050"}, {0x0491, "afii10098"}, {0x04D9, "afii10846"}, {0x05B0, "afii57799"}, {0x05B1, "afii57801"}, {0x05B2, "afii57800"}, {0x05B3, "afii57802"}, {0x05B4, "afii57793"}, {0x05B5, "afii57794"}, {0x05B6, "afii57795"}, {0x05B7, "afii57798"}, {0x05B8, "afii57797"}, {0x05B9, "afii57806"}, {0x05BB, "afii57796"}, {0x05BC, "afii57807"}, {0x05BD, "afii57839"}, {0x05BE, "afii57645"}, {0x05BF, "afii57841"}, {0x05C0, "afii57842"}, {0x05C1, "afii57804"}, {0x05C2, "afii57803"}, {0x05C3, "afii57658"}, {0x05D0, "afii57664"}, {0x05D1, "afii57665"}, {0x05D2, "afii57666"}, {0x05D3, "afii57667"}, {0x05D4, "afii57668"}, {0x05D5, "afii57669"}, {0x05D6, "afii57670"}, {0x05D7, "afii57671"}, {0x05D8, "afii57672"}, {0x05D9, "afii57673"}, {0x05DA, "afii57674"}, {0x05DB, "afii57675"}, {0x05DC, "afii57676"}, {0x05DD, "afii57677"}, {0x05DE, "afii57678"}, {0x05DF, "afii57679"}, {0x05E0, "afii57680"}, {0x05E1, "afii57681"}, {0x05E2, "afii57682"}, {0x05E3, "afii57683"}, {0x05E4, "afii57684"}, {0x05E5, "afii57685"}, {0x05E6, "afii57686"}, {0x05E7, "afii57687"}, {0x05E8, "afii57688"}, {0x05E9, "afii57689"}, {0x05EA, "afii57690"}, {0x05F0, "afii57716"}, {0x05F1, "afii57717"}, {0x05F2, "afii57718"}, {0x060C, "afii57388"}, {0x061B, "afii57403"}, {0x061F, "afii57407"}, {0x0621, "afii57409"}, {0x0622, "afii57410"}, {0x0623, "afii57411"}, {0x0624, "afii57412"}, {0x0625, "afii57413"}, {0x0626, "afii57414"}, {0x0627, "afii57415"}, {0x0628, "afii57416"}, {0x0629, "afii57417"}, {0x062A, "afii57418"}, {0x062B, "afii57419"}, {0x062C, "afii57420"}, {0x062D, "afii57421"}, {0x062E, "afii57422"}, {0x062F, "afii57423"}, {0x0630, "afii57424"}, {0x0631, "afii57425"}, {0x0632, "afii57426"}, {0x0633, "afii57427"}, {0x0634, "afii57428"}, {0x0635, "afii57429"}, {0x0636, "afii57430"}, {0x0637, "afii57431"}, {0x0638, "afii57432"}, {0x0639, "afii57433"}, {0x063A, "afii57434"}, {0x0640, "afii57440"}, {0x0641, "afii57441"}, {0x0642, "afii57442"}, {0x0643, "afii57443"}, {0x0644, "afii57444"}, {0x0645, "afii57445"}, {0x0646, "afii57446"}, {0x0647, "afii57470"}, {0x0648, "afii57448"}, {0x0649, "afii57449"}, {0x064A, "afii57450"}, {0x064B, "afii57451"}, {0x064C, "afii57452"}, {0x064D, "afii57453"}, {0x064E, "afii57454"}, {0x064F, "afii57455"}, {0x0650, "afii57456"}, {0x0651, "afii57457"}, {0x0652, "afii57458"}, {0x0660, "afii57392"}, {0x0661, "afii57393"}, {0x0662, "afii57394"}, {0x0663, "afii57395"}, {0x0664, "afii57396"}, {0x0665, "afii57397"}, {0x0666, "afii57398"}, {0x0667, "afii57399"}, {0x0668, "afii57400"}, {0x0669, "afii57401"}, {0x066A, "afii57381"}, {0x066D, "afii63167"}, {0x0679, "afii57511"}, {0x067E, "afii57506"}, {0x0686, "afii57507"}, {0x0688, "afii57512"}, {0x0691, "afii57513"}, {0x0698, "afii57508"}, {0x06A4, "afii57505"}, {0x06AF, "afii57509"}, {0x06BA, "afii57514"}, {0x06D2, "afii57519"}, {0x06D5, "afii57534"}, {0x1E80, "Wgrave"}, {0x1E81, "wgrave"}, {0x1E82, "Wacute"}, {0x1E83, "wacute"}, {0x1E84, "Wdieresis"}, {0x1E85, "wdieresis"}, {0x1EF2, "Ygrave"}, {0x1EF3, "ygrave"}, {0x200C, "afii61664"}, {0x200D, "afii301"}, {0x200E, "afii299"}, {0x200F, "afii300"}, {0x2012, "figuredash"}, {0x2013, "endash"}, {0x2014, "emdash"}, {0x2015, "afii00208"}, {0x2017, "underscoredbl"}, {0x2018, "quoteleft"}, {0x2019, "quoteright"}, {0x201A, "quotesinglbase"}, {0x201B, "quotereversed"}, {0x201C, "quotedblleft"}, {0x201D, "quotedblright"}, {0x201E, "quotedblbase"}, {0x2020, "dagger"}, {0x2021, "daggerdbl"}, {0x2022, "bullet"}, {0x2024, "onedotenleader"}, {0x2025, "twodotenleader"}, {0x2026, "ellipsis"}, {0x202C, "afii61573"}, {0x202D, "afii61574"}, {0x202E, "afii61575"}, {0x2030, "perthousand"}, {0x2032, "minute"}, {0x2033, "second"}, {0x2039, "guilsinglleft"}, {0x203A, "guilsinglright"}, {0x203C, "exclamdbl"}, {0x2044, "fraction"}, {0x2070, "zerosuperior"}, {0x2074, "foursuperior"}, {0x2075, "fivesuperior"}, {0x2076, "sixsuperior"}, {0x2077, "sevensuperior"}, {0x2078, "eightsuperior"}, {0x2079, "ninesuperior"}, {0x207D, "parenleftsuperior"}, {0x207E, "parenrightsuperior"}, {0x207F, "nsuperior"}, {0x2080, "zeroinferior"}, {0x2081, "oneinferior"}, {0x2082, "twoinferior"}, {0x2083, "threeinferior"}, {0x2084, "fourinferior"}, {0x2085, "fiveinferior"}, {0x2086, "sixinferior"}, {0x2087, "seveninferior"}, {0x2088, "eightinferior"}, {0x2089, "nineinferior"}, {0x208D, "parenleftinferior"}, {0x208E, "parenrightinferior"}, {0x20A1, "colonmonetary"}, {0x20A3, "franc"}, {0x20A4, "lira"}, {0x20A7, "peseta"}, {0x20AA, "afii57636"}, {0x20AB, "dong"}, {0x20AC, "Euro"}, {0x2105, "afii61248"}, {0x2111, "Ifraktur"}, {0x2113, "afii61289"}, {0x2116, "afii61352"}, {0x2118, "weierstrass"}, {0x211C, "Rfraktur"}, {0x211E, "prescription"}, {0x2122, "trademark"}, {0x2126, "Omega"}, {0x212E, "estimated"}, {0x2135, "aleph"}, {0x2153, "onethird"}, {0x2154, "twothirds"}, {0x215B, "oneeighth"}, {0x215C, "threeeighths"}, {0x215D, "fiveeighths"}, {0x215E, "seveneighths"}, {0x2190, "arrowleft"}, {0x2191, "arrowup"}, {0x2192, "arrowright"}, {0x2193, "arrowdown"}, {0x2194, "arrowboth"}, {0x2195, "arrowupdn"}, {0x21A8, "arrowupdnbse"}, {0x21B5, "carriagereturn"}, {0x21D0, "arrowdblleft"}, {0x21D1, "arrowdblup"}, {0x21D2, "arrowdblright"}, {0x21D3, "arrowdbldown"}, {0x21D4, "arrowdblboth"}, {0x2200, "universal"}, {0x2202, "partialdiff"}, {0x2203, "existential"}, {0x2205, "emptyset"}, {0x2206, "Delta"}, {0x2207, "gradient"}, {0x2208, "element"}, {0x2209, "notelement"}, {0x220B, "suchthat"}, {0x220F, "product"}, {0x2211, "summation"}, {0x2212, "minus"}, {0x2215, "fraction"}, {0x2217, "asteriskmath"}, {0x2219, "periodcentered"}, {0x221A, "radical"}, {0x221D, "proportional"}, {0x221E, "infinity"}, {0x221F, "orthogonal"}, {0x2220, "angle"}, {0x2227, "logicaland"}, {0x2228, "logicalor"}, {0x2229, "intersection"}, {0x222A, "union"}, {0x222B, "integral"}, {0x2234, "therefore"}, {0x223C, "similar"}, {0x2245, "congruent"}, {0x2248, "approxequal"}, {0x2260, "notequal"}, {0x2261, "equivalence"}, {0x2264, "lessequal"}, {0x2265, "greaterequal"}, {0x2282, "propersubset"}, {0x2283, "propersuperset"}, {0x2284, "notsubset"}, {0x2286, "reflexsubset"}, {0x2287, "reflexsuperset"}, {0x2295, "circleplus"}, {0x2297, "circlemultiply"}, {0x22A5, "perpendicular"}, {0x22C5, "dotmath"}, {0x2302, "house"}, {0x2310, "revlogicalnot"}, {0x2320, "integraltp"}, {0x2321, "integralbt"}, {0x2329, "angleleft"}, {0x232A, "angleright"}, {0x2500, "SF100000"}, {0x2502, "SF110000"}, {0x250C, "SF010000"}, {0x2510, "SF030000"}, {0x2514, "SF020000"}, {0x2518, "SF040000"}, {0x251C, "SF080000"}, {0x2524, "SF090000"}, {0x252C, "SF060000"}, {0x2534, "SF070000"}, {0x253C, "SF050000"}, {0x2550, "SF430000"}, {0x2551, "SF240000"}, {0x2552, "SF510000"}, {0x2553, "SF520000"}, {0x2554, "SF390000"}, {0x2555, "SF220000"}, {0x2556, "SF210000"}, {0x2557, "SF250000"}, {0x2558, "SF500000"}, {0x2559, "SF490000"}, {0x255A, "SF380000"}, {0x255B, "SF280000"}, {0x255C, "SF270000"}, {0x255D, "SF260000"}, {0x255E, "SF360000"}, {0x255F, "SF370000"}, {0x2560, "SF420000"}, {0x2561, "SF190000"}, {0x2562, "SF200000"}, {0x2563, "SF230000"}, {0x2564, "SF470000"}, {0x2565, "SF480000"}, {0x2566, "SF410000"}, {0x2567, "SF450000"}, {0x2568, "SF460000"}, {0x2569, "SF400000"}, {0x256A, "SF540000"}, {0x256B, "SF530000"}, {0x256C, "SF440000"}, {0x2580, "upblock"}, {0x2584, "dnblock"}, {0x2588, "block"}, {0x258C, "lfblock"}, {0x2590, "rtblock"}, {0x2591, "ltshade"}, {0x2592, "shade"}, {0x2593, "dkshade"}, {0x25A0, "filledbox"}, {0x25A1, "H22073"}, {0x25AA, "H18543"}, {0x25AB, "H18551"}, {0x25AC, "filledrect"}, {0x25B2, "triagup"}, {0x25BA, "triagrt"}, {0x25BC, "triagdn"}, {0x25C4, "triaglf"}, {0x25CA, "lozenge"}, {0x25CB, "circle"}, {0x25CF, "H18533"}, {0x25D8, "invbullet"}, {0x25D9, "invcircle"}, {0x25E6, "openbullet"}, {0x263A, "smileface"}, {0x263B, "invsmileface"}, {0x263C, "sun"}, {0x2640, "female"}, {0x2642, "male"}, {0x2660, "spade"}, {0x2663, "club"}, {0x2665, "heart"}, {0x2666, "diamond"}, {0x266A, "musicalnote"}, {0x266B, "musicalnotedbl"}, {0xF6BE, "dotlessj"}, {0xF6BF, "LL"}, {0xF6C0, "ll"}, {0xF6C1, "Scedilla"}, {0xF6C2, "scedilla"}, {0xF6C3, "commaaccent"}, {0xF6C4, "afii10063"}, {0xF6C5, "afii10064"}, {0xF6C6, "afii10192"}, {0xF6C7, "afii10831"}, {0xF6C8, "afii10832"}, {0xF6C9, "Acute"}, {0xF6CA, "Caron"}, {0xF6CB, "Dieresis"}, {0xF6CC, "DieresisAcute"}, {0xF6CD, "DieresisGrave"}, {0xF6CE, "Grave"}, {0xF6CF, "Hungarumlaut"}, {0xF6D0, "Macron"}, {0xF6D1, "cyrBreve"}, {0xF6D2, "cyrFlex"}, {0xF6D3, "dblGrave"}, {0xF6D4, "cyrbreve"}, {0xF6D5, "cyrflex"}, {0xF6D6, "dblgrave"}, {0xF6D7, "dieresisacute"}, {0xF6D8, "dieresisgrave"}, {0xF6D9, "copyrightserif"}, {0xF6DA, "registerserif"}, {0xF6DB, "trademarkserif"}, {0xF6DC, "onefitted"}, {0xF6DD, "rupiah"}, {0xF6DE, "threequartersemdash"}, {0xF6DF, "centinferior"}, {0xF6E0, "centsuperior"}, {0xF6E1, "commainferior"}, {0xF6E2, "commasuperior"}, {0xF6E3, "dollarinferior"}, {0xF6E4, "dollarsuperior"}, {0xF6E5, "hypheninferior"}, {0xF6E6, "hyphensuperior"}, {0xF6E7, "periodinferior"}, {0xF6E8, "periodsuperior"}, {0xF6E9, "asuperior"}, {0xF6EA, "bsuperior"}, {0xF6EB, "dsuperior"}, {0xF6EC, "esuperior"}, {0xF6ED, "isuperior"}, {0xF6EE, "lsuperior"}, {0xF6EF, "msuperior"}, {0xF6F0, "osuperior"}, {0xF6F1, "rsuperior"}, {0xF6F2, "ssuperior"}, {0xF6F3, "tsuperior"}, {0xF6F4, "Brevesmall"}, {0xF6F5, "Caronsmall"}, {0xF6F6, "Circumflexsmall"}, {0xF6F7, "Dotaccentsmall"}, {0xF6F8, "Hungarumlautsmall"}, {0xF6F9, "Lslashsmall"}, {0xF6FA, "OEsmall"}, {0xF6FB, "Ogoneksmall"}, {0xF6FC, "Ringsmall"}, {0xF6FD, "Scaronsmall"}, {0xF6FE, "Tildesmall"}, {0xF6FF, "Zcaronsmall"}, {0xF721, "exclamsmall"}, {0xF724, "dollaroldstyle"}, {0xF726, "ampersandsmall"}, {0xF730, "zerooldstyle"}, {0xF731, "oneoldstyle"}, {0xF732, "twooldstyle"}, {0xF733, "threeoldstyle"}, {0xF734, "fouroldstyle"}, {0xF735, "fiveoldstyle"}, {0xF736, "sixoldstyle"}, {0xF737, "sevenoldstyle"}, {0xF738, "eightoldstyle"}, {0xF739, "nineoldstyle"}, {0xF73F, "questionsmall"}, {0xF760, "Gravesmall"}, {0xF761, "Asmall"}, {0xF762, "Bsmall"}, {0xF763, "Csmall"}, {0xF764, "Dsmall"}, {0xF765, "Esmall"}, {0xF766, "Fsmall"}, {0xF767, "Gsmall"}, {0xF768, "Hsmall"}, {0xF769, "Ismall"}, {0xF76A, "Jsmall"}, {0xF76B, "Ksmall"}, {0xF76C, "Lsmall"}, {0xF76D, "Msmall"}, {0xF76E, "Nsmall"}, {0xF76F, "Osmall"}, {0xF770, "Psmall"}, {0xF771, "Qsmall"}, {0xF772, "Rsmall"}, {0xF773, "Ssmall"}, {0xF774, "Tsmall"}, {0xF775, "Usmall"}, {0xF776, "Vsmall"}, {0xF777, "Wsmall"}, {0xF778, "Xsmall"}, {0xF779, "Ysmall"}, {0xF77A, "Zsmall"}, {0xF7A1, "exclamdownsmall"}, {0xF7A2, "centoldstyle"}, {0xF7A8, "Dieresissmall"}, {0xF7AF, "Macronsmall"}, {0xF7B4, "Acutesmall"}, {0xF7B8, "Cedillasmall"}, {0xF7BF, "questiondownsmall"}, {0xF7E0, "Agravesmall"}, {0xF7E1, "Aacutesmall"}, {0xF7E2, "Acircumflexsmall"}, {0xF7E3, "Atildesmall"}, {0xF7E4, "Adieresissmall"}, {0xF7E5, "Aringsmall"}, {0xF7E6, "AEsmall"}, {0xF7E7, "Ccedillasmall"}, {0xF7E8, "Egravesmall"}, {0xF7E9, "Eacutesmall"}, {0xF7EA, "Ecircumflexsmall"}, {0xF7EB, "Edieresissmall"}, {0xF7EC, "Igravesmall"}, {0xF7ED, "Iacutesmall"}, {0xF7EE, "Icircumflexsmall"}, {0xF7EF, "Idieresissmall"}, {0xF7F0, "Ethsmall"}, {0xF7F1, "Ntildesmall"}, {0xF7F2, "Ogravesmall"}, {0xF7F3, "Oacutesmall"}, {0xF7F4, "Ocircumflexsmall"}, {0xF7F5, "Otildesmall"}, {0xF7F6, "Odieresissmall"}, {0xF7F8, "Oslashsmall"}, {0xF7F9, "Ugravesmall"}, {0xF7FA, "Uacutesmall"}, {0xF7FB, "Ucircumflexsmall"}, {0xF7FC, "Udieresissmall"}, {0xF7FD, "Yacutesmall"}, {0xF7FE, "Thornsmall"}, {0xF7FF, "Ydieresissmall"}, {0xF8E5, "radicalex"}, {0xF8E6, "arrowvertex"}, {0xF8E7, "arrowhorizex"}, {0xF8E8, "registersans"}, {0xF8E9, "copyrightsans"}, {0xF8EA, "trademarksans"}, {0xF8EB, "parenlefttp"}, {0xF8EC, "parenleftex"}, {0xF8ED, "parenleftbt"}, {0xF8EE, "bracketlefttp"}, {0xF8EF, "bracketleftex"}, {0xF8F0, "bracketleftbt"}, {0xF8F1, "bracelefttp"}, {0xF8F2, "braceleftmid"}, {0xF8F3, "braceleftbt"}, {0xF8F4, "braceex"}, {0xF8F5, "integralex"}, {0xF8F6, "parenrighttp"}, {0xF8F7, "parenrightex"}, {0xF8F8, "parenrightbt"}, {0xF8F9, "bracketrighttp"}, {0xF8FA, "bracketrightex"}, {0xF8FB, "bracketrightbt"}, {0xF8FC, "bracerighttp"}, {0xF8FD, "bracerightmid"}, {0xF8FE, "bracerightbt"}, {0xFB00, "ff"}, {0xFB01, "fi"}, {0xFB02, "fl"}, {0xFB03, "ffi"}, {0xFB04, "ffl"}, {0xFB1F, "afii57705"}, {0xFB2A, "afii57694"}, {0xFB2B, "afii57695"}, {0xFB35, "afii57723"}, {0xFB4B, "afii57700"}, {0xFFFF, NULL} }; PdfEncodingDifference::PdfEncodingDifference() { } PdfEncodingDifference::PdfEncodingDifference( const PdfEncodingDifference & rhs ) { this->operator=( rhs ); } const PdfEncodingDifference & PdfEncodingDifference::operator=( const PdfEncodingDifference & rhs ) { m_vecDifferences = rhs.m_vecDifferences; return *this; } void PdfEncodingDifference::AddDifference( int nCode, pdf_utf16be unicodeValue ) { pdf_utf16be inCodePoint = unicodeValue; #ifdef PODOFO_IS_LITTLE_ENDIAN inCodePoint = ((inCodePoint & 0xff00) >> 8) | ((inCodePoint & 0xff) << 8); #endif // PODOFO_IS_LITTLE_ENDIAN this->AddDifference( nCode, unicodeValue, PdfDifferenceEncoding::UnicodeIDToName( inCodePoint ) ); } void PdfEncodingDifference::AddDifference( int nCode, pdf_utf16be unicodeValue, const PdfName & rName, bool bExplicitNames ) { if( nCode > 255 || nCode < 0 ) { PODOFO_RAISE_ERROR( ePdfError_ValueOutOfRange ); } TDifference dif; dif.nCode = nCode; dif.name = rName; // In type3 fonts, glyph names are explicit keys from the font's CharProcs // dictionary, therefore they have no meaning. // By setting unicodeValue to nCode, we keep PdfEncodingDifference::Contains // from calling PdfDifferenceEncoding::NameToUnicodeID, which would return 0 // after looking it up in the unicode tables. This allows us, provided the // font's encoding is unicode-compatible, to preserve the characters' codes // in the process. This seems to be Adobe Reader's behaviour as well. if (bExplicitNames) { #ifdef PODOFO_IS_LITTLE_ENDIAN dif.unicodeValue = ((nCode & 0xff00) >> 8) | ((nCode & 0xff) << 8); #else dif.unicodeValue = nCode; #endif // PODOFO_IS_LITTLE_ENDIAN } else { dif.unicodeValue = unicodeValue; } std::pair it = std::equal_range( m_vecDifferences.begin(), m_vecDifferences.end(), dif, DifferenceComparatorPredicate() ); if( it.first != it.second ) { // replace existing object *(it.first) = dif; } else { m_vecDifferences.insert( it.first, dif ); } } bool PdfEncodingDifference::Contains( int nCode, PdfName & rName, pdf_utf16be & rValue ) const { TDifference dif; dif.nCode = nCode; std::pair it = std::equal_range( const_cast(this)->m_vecDifferences.begin(), const_cast(this)->m_vecDifferences.end(), dif, DifferenceComparatorPredicate() ); if( it.first != it.second ) { rName = (*(it.first)).name; if( !(*(it.first)).unicodeValue ) // Field is not yet initialized, // initialize it now, so that we only // compute the value if it is needed. (*(it.first)).unicodeValue = PdfDifferenceEncoding::NameToUnicodeID( rName ); rValue = (*(it.first)).unicodeValue; return true; } return false; } bool PdfEncodingDifference::ContainsUnicodeValue( pdf_utf16be unicodeValue, char &rValue ) const { #ifdef PODOFO_IS_LITTLE_ENDIAN unicodeValue = ((unicodeValue & 0xff00) >> 8) | ((unicodeValue & 0xff) << 8); #endif // PODOFO_IS_LITTLE_ENDIAN TCIVecDifferences it, end = m_vecDifferences.end(); for (it = m_vecDifferences.begin(); it != end; it++) { pdf_utf16be uv = it->unicodeValue; if (uv == unicodeValue) { rValue = it->nCode; return true; } } return false; } void PdfEncodingDifference::ToArray( PdfArray & rArray ) { pdf_int64 nLastCode = -2; rArray.Clear(); TCIVecDifferences it = m_vecDifferences.begin(); while( it != m_vecDifferences.end() ) { if( (*it).nCode != nLastCode + 1 ) { nLastCode = (*it).nCode; rArray.push_back( nLastCode ); rArray.push_back( (*it).name ); } else { ++nLastCode; rArray.push_back( (*it).name ); } ++it; } } // ----------------------------------------------------- // PdfDifferenceEncoding // ----------------------------------------------------- PdfDifferenceEncoding::PdfDifferenceEncoding( const PdfEncodingDifference & rDifference, PdfDocument* pParent, bool bAutoDelete ) : PdfEncoding( 0x00, 0xff ), PdfElement( "Encoding", pParent ), m_differences( rDifference ), m_bAutoDelete( bAutoDelete ), m_baseEncoding( eBaseEncoding_Font ) { Init(); } PdfDifferenceEncoding::PdfDifferenceEncoding( const PdfEncodingDifference & rDifference, PdfVecObjects* pParent, bool bAutoDelete ) : PdfEncoding( 0x00, 0xff ), PdfElement( "Encoding", pParent ), m_differences( rDifference ), m_bAutoDelete( bAutoDelete ), m_baseEncoding( eBaseEncoding_Font ) { Init(); } PdfDifferenceEncoding::PdfDifferenceEncoding( const PdfEncodingDifference & rDifference, EBaseEncoding eBaseEncoding, PdfDocument* pParent, bool bAutoDelete ) : PdfEncoding( 0x00, 0xff ), PdfElement( "Encoding", pParent ), m_differences( rDifference ), m_bAutoDelete( bAutoDelete ), m_baseEncoding( eBaseEncoding ) { Init(); } PdfDifferenceEncoding::PdfDifferenceEncoding( const PdfEncodingDifference & rDifference, EBaseEncoding eBaseEncoding, PdfVecObjects* pParent, bool bAutoDelete ) : PdfEncoding( 0x00, 0xff ), PdfElement( "Encoding", pParent ), m_differences( rDifference ), m_bAutoDelete( bAutoDelete ), m_baseEncoding( eBaseEncoding ) { Init(); } PdfDifferenceEncoding::PdfDifferenceEncoding( PdfObject* pObject, bool bAutoDelete, bool bExplicitNames ) : PdfEncoding( 0x00, 0xff ), PdfElement( NULL, pObject ), m_bAutoDelete( bAutoDelete ) { CreateID(); m_baseEncoding = eBaseEncoding_WinAnsi; if( this->GetObject()->GetDictionary().HasKey( PdfName("BaseEncoding") ) ) { const PdfName & rBase = this->GetObject()->GetDictionary().GetKey( PdfName("BaseEncoding") )->GetName(); if( rBase == PdfName("WinAnsiEncoding") ) m_baseEncoding = eBaseEncoding_WinAnsi; else if( rBase == PdfName("MacRomanEncoding") ) m_baseEncoding = eBaseEncoding_MacRoman; else if( rBase == PdfName("MacExpertEncoding") ) m_baseEncoding = eBaseEncoding_MacExpert; } // Read the differences key if( this->GetObject()->GetDictionary().HasKey( PdfName("Differences") ) ) { const PdfArray & rDifferences = this->GetObject()->GetIndirectKey( PdfName("Differences") )->GetArray(); PdfArray::const_iterator it = rDifferences.begin(); pdf_int64 curCode = -1; while( it != rDifferences.end() ) { if( (*it).IsNumber() ) curCode = (*it).GetNumber(); else if( (*it).IsName() ) { m_differences.AddDifference( static_cast(curCode), 0, (*it).GetName(), bExplicitNames ); ++curCode; } ++it; } } } void PdfDifferenceEncoding::CreateID() { std::ostringstream oss; oss << "/DifferencesEncoding" << this->GetObject()->Reference().ObjectNumber() << "_" << this->GetObject()->Reference().GenerationNumber(); m_id = PdfName( oss.str() ); } void PdfDifferenceEncoding::Init() { CreateID(); switch( m_baseEncoding ) { case eBaseEncoding_WinAnsi: this->GetObject()->GetDictionary().AddKey( PdfName("BaseEncoding"), PdfName("WinAnsiEncoding") ); break; case eBaseEncoding_MacRoman: this->GetObject()->GetDictionary().AddKey( PdfName("BaseEncoding"), PdfName("MacRomanEncoding") ); break; case eBaseEncoding_MacExpert: this->GetObject()->GetDictionary().AddKey( PdfName("BaseEncoding"), PdfName("MacExpertEncoding") ); break; case eBaseEncoding_Font: default: break; } if( m_differences.GetCount() ) { PdfArray differences; m_differences.ToArray( differences ); this->GetObject()->GetDictionary().AddKey( PdfName("Differences"), differences ); } } void PdfDifferenceEncoding::AddToDictionary( PdfDictionary & rDictionary ) const { rDictionary.AddKey( PdfName("Encoding"), this->GetObject()->Reference() ); } pdf_utf16be PdfDifferenceEncoding::GetCharCode( int nIndex ) const { if( nIndex < this->GetFirstChar() || nIndex > this->GetLastChar() ) { PODOFO_RAISE_ERROR( ePdfError_ValueOutOfRange ); } PdfName name; pdf_utf16be value; if( m_differences.Contains( nIndex, name, value ) ) { return value; } else { const PdfEncoding* pEncoding = this->GetBaseEncoding(); return pEncoding->GetCharCode( nIndex ); } } pdf_utf16be PdfDifferenceEncoding::NameToUnicodeID( const PdfName & rName ) { const char* pszName = rName.GetName().c_str(); for( int i = 0; nameToUnicodeTab[i].name; ++i) { if ( strcmp( nameToUnicodeTab[i].name, pszName ) == 0 ) #ifdef PODOFO_IS_LITTLE_ENDIAN return ((nameToUnicodeTab[i].u & 0xff00) >> 8) | ((nameToUnicodeTab[i].u & 0xff) << 8); #else return nameToUnicodeTab[i].u; #endif // PODOFO_IS_LITTLE_ENDIAN } // if we get here, then we might be looking up an undefined codepoint // so try looking for our special format.. if( strncmp( "uni", pszName, 3 ) == 0 ) { pszName += 3; // remove "uni" size_t length = strlen( pszName ); // force base16 IF it's 4 characters line pdf_utf16be val = static_cast(strtol( pszName, NULL, (length == 4 ? 16 : 10) )); #ifdef PODOFO_IS_LITTLE_ENDIAN return val = ((val & 0xff00) >> 8) | ((val & 0xff) << 8); #else return val; #endif // PODOFO_IS_LITTLE_ENDIAN } return 0; } PdfName PdfDifferenceEncoding::UnicodeIDToName( pdf_utf16be inCodePoint ) { #ifdef PODOFO_IS_LITTLE_ENDIAN inCodePoint = ((inCodePoint & 0xff00) >> 8) | ((inCodePoint & 0xff) << 8); #endif // PODOFO_IS_LITTLE_ENDIAN int i; for( i = 0; UnicodeToNameTab[i].name; ++i) { if ( UnicodeToNameTab[i].u == inCodePoint ) return PdfName( UnicodeToNameTab[i].name ); } // if we can't find in the canonical list, look in the complete list for ( i = 0; nameToUnicodeTab[i].name; ++i) { if ( nameToUnicodeTab[i].u == inCodePoint ) return PdfName( UnicodeToNameTab[i].name ); } // if we get here, then we are looking up an undefined codepoint // so we'll just give it SOME name.. const int BUFFER_LEN = 8; char buffer[BUFFER_LEN]; snprintf( buffer, BUFFER_LEN, "uni%04x", inCodePoint ); return PdfName( buffer ); //return PdfName(".notdef"); } PdfString PdfDifferenceEncoding::ConvertToUnicode( const PdfString & rEncodedString, const PdfFont* pFont ) const { const PdfEncoding* pEncoding = GetBaseEncoding(); PdfString str = pEncoding->ConvertToUnicode( rEncodedString, pFont ); pdf_long lLen = str.GetCharacterLength(); pdf_utf16be* pszUtf16 = static_cast(malloc(sizeof(pdf_utf16be)*lLen)); if( !pszUtf16 ) { PODOFO_RAISE_ERROR( ePdfError_OutOfMemory ); } memcpy( pszUtf16, str.GetUnicode(), lLen * sizeof(pdf_utf16be) ); for( pdf_long i=0;i> 8) | ((val & 0xff) << 8); #endif // PODOFO_IS_LITTLE_ENDIAN PdfName name; pdf_utf16be value; if( m_differences.Contains( static_cast(val), name, value ) ) pszUtf16[i] = value; } PdfString ret( pszUtf16, lLen ); free( pszUtf16 ); return ret; } PdfRefCountedBuffer PdfDifferenceEncoding::ConvertToEncoding( const PdfString & rString, const PdfFont* /*pFont*/ ) const { const PdfEncoding* pEncoding = GetBaseEncoding(); pdf_utf16be* pszUtf16 = NULL; pdf_long lLen = 0; if( rString.IsUnicode() ) { lLen = rString.GetCharacterLength(); if( !lLen ) return PdfRefCountedBuffer(); pszUtf16 = static_cast(malloc(sizeof(pdf_utf16be)*lLen)); if( !pszUtf16 ) { PODOFO_RAISE_ERROR( ePdfError_OutOfMemory ); } memcpy( pszUtf16, rString.GetUnicode(), lLen * sizeof(pdf_utf16be) ); } else { // Only do a copy if we really have to PdfString str = rString.ToUnicode(); lLen = str.GetCharacterLength(); if( !lLen ) return PdfRefCountedBuffer(); pszUtf16 = static_cast(malloc(sizeof(pdf_utf16be)*lLen)); if( !pszUtf16 ) { PODOFO_RAISE_ERROR( ePdfError_OutOfMemory ); } memcpy( pszUtf16, str.GetUnicode(), lLen * sizeof(pdf_utf16be) ); } char* pDest = static_cast(malloc( sizeof(char) * (lLen + 1) )); if( !pDest ) { PODOFO_RAISE_ERROR( ePdfError_OutOfMemory ); } char *pCur = pDest; long lNewLen = 0L; for( int i=0;i(pEncoding)->GetUnicodeCharCode(val); if( *pCur) // ignore 0 characters, as they cannot be converted to the current encoding { ++pCur; ++lNewLen; } } *pCur = '\0'; PdfRefCountedBuffer cDest( lNewLen ); memcpy( cDest.GetBuffer(), pDest, lNewLen ); free( pDest ); free( pszUtf16 ); return cDest; } const PdfEncoding* PdfDifferenceEncoding::GetBaseEncoding() const { const PdfEncoding* pEncoding = NULL; switch( m_baseEncoding ) { case eBaseEncoding_WinAnsi: pEncoding = PdfEncodingFactory::GlobalWinAnsiEncodingInstance(); break; case eBaseEncoding_MacRoman: pEncoding = PdfEncodingFactory::GlobalMacRomanEncodingInstance(); break; case eBaseEncoding_MacExpert: case eBaseEncoding_Font: default: break; } if( !pEncoding ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } return pEncoding; } }; /* PoDoFo */ podofo-0.9.3/src/doc/podofo-doc.rc0000664000175000017500000000503312347271543016605 0ustar dominikdominik#define PODOFO_COMPILE_RC #include "base/podofoapi.h" #include "base/PdfDefines.h" #include "base/PdfVersion.h" #include "WinResrc.h" #undef PODOFO_COMPILE_RC #define VER_PRODUCTVERSION PODOFO_MAJOR,PODOFO_MINOR,PODOFO_REVISION,0 #define VER_PRODUCTVERSION_STR PODOFO_VERSION_STRING #define VER_FILEVERSION VER_PRODUCTVERSION #define VER_FILEVERSION_STR VER_PRODUCTVERSION_STR #define VER_PRIVATEBUILD_STR "Custom Build\0" #ifndef DEBUG #define VER_DEBUG 0 #else #define VER_DEBUG VS_FF_DEBUG #endif #if defined(COMPILING_SHARED_PODOFO) #define VER_FILETYPE VFT_DLL #define VER_FILEDESCRIPTION_STR "PoDoFo Dynamic Link Library\0" #define VER_ORIGINALFILENAME_STR "podofo.dll\0" #else #define VER_FILETYPE VFT_STATIC_LIB #define VER_FILEDESCRIPTION_STR "PoDoFo Static Library\0" #define VER_ORIGINALFILENAME_STR "podofo.lib\0" #endif #if 1 #define VER_PRERELEASE VS_FF_PRERELEASE #else #define VER_PRERELEASE 0L #endif VS_VERSION_INFO VERSIONINFO FILEVERSION VER_FILEVERSION PRODUCTVERSION VER_PRODUCTVERSION FILEFLAGSMASK VS_FFI_FILEFLAGSMASK FILEFLAGS (VS_FF_PRIVATEBUILD|VER_PRERELEASE|VER_DEBUG) FILEOS VOS__WINDOWS32 FILETYPE VER_FILETYPE FILESUBTYPE VFT2_UNKNOWN BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904E4" BEGIN VALUE "FileVersion", VER_FILEVERSION VALUE "ProductVersion", VER_PRODUCTVERSION VALUE "Comments", "PoDoFo Doc PDF Library\0" VALUE "CompanyName", "PoDoFo\0" VALUE "InternalName", "podofo\0" VALUE "ProductName", "PoDoFo\0" VALUE "LegalCopyright", "Copyright (C) 2010 Dominik Seichter, Craig Ringer, The PoDoFo Developers\0" VALUE "FileDescription", VER_FILEDESCRIPTION_STR VALUE "OriginalFilename", VER_ORIGINALFILENAME_STR VALUE "PrivateBuild", VER_PRIVATEBUILD_STR END END BLOCK "VarFileInfo" BEGIN /* The following line should only be modified for localized versions. */ /* It consists of any number of WORD,WORD pairs, with each pair */ /* describing a language,codepage combination supported by the file. */ /* */ /* For example, a file might have values "0x409,1252" indicating that it */ /* supports English language (0x409) in the Windows ANSI codepage (1252). */ VALUE "Translation", 0x409, 1252 END END podofo-0.9.3/src/doc/PdfShadingPattern.h0000664000175000017500000003051512347301431017735 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2007 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_SHADING_PATTERN_H_ #define _PDF_SHADING_PATTERN_H_ #include "podofo/base/PdfDefines.h" #include "podofo/base/PdfName.h" #include "PdfElement.h" namespace PoDoFo { class PdfColor; class PdfObject; class PdfPage; class PdfWriter; enum EPdfShadingPatternType { ePdfShadingPatternType_FunctionBase = 1, ePdfShadingPatternType_Axial = 2, ePdfShadingPatternType_Radial = 3, ePdfShadingPatternType_FreeForm = 4, ePdfShadingPatternType_LatticeForm = 5, ePdfShadingPatternType_CoonsPatch = 6, ePdfShadingPatternType_TensorProduct = 7 }; /** * This class defined a shading pattern which can be used * to fill abitrary shapes with a pattern using PdfPainter. */ class PODOFO_DOC_API PdfShadingPattern : public PdfElement { public: virtual ~PdfShadingPattern(); /** Returns the identifier of this ShadingPattern how it is known * in the pages resource dictionary. * \returns PdfName containing the identifier (e.g. /Sh13) */ inline const PdfName & GetIdentifier() const; protected: /** Create a new PdfShadingPattern object which will introduce itself * automatically to every page object it is used on. * * \param pParent parent vector of objects * \param eShadingType the type of this shading pattern * */ PdfShadingPattern( EPdfShadingPatternType eShadingType, PdfVecObjects* pParent ); /** Create a new PdfShadingPattern object which will introduce itself * automatically to every page object it is used on. * * \param pParent parent document * \param eShadingType the type of this shading pattern * */ PdfShadingPattern( EPdfShadingPatternType eShadingType, PdfDocument* pParent ); private: /** Initialize the object * * \param eShadingType the type of this shading pattern */ void Init( EPdfShadingPatternType eShadingType ); private: PdfName m_Identifier; }; // ----------------------------------------------------- // // ----------------------------------------------------- const PdfName & PdfShadingPattern::GetIdentifier() const { return m_Identifier; } /** A shading pattern that is a simple axial * shading between two colors. */ class PODOFO_DOC_API PdfAxialShadingPattern : public PdfShadingPattern { public: /** Create an axial shading pattern * * \param dX0 the starting x coordinate * \param dY0 the starting y coordinate * \param dX1 the ending x coordinate * \param dY1 the ending y coordinate * \param rStart the starting color * \param rEnd the ending color * \param pParent the parent */ PdfAxialShadingPattern( double dX0, double dY0, double dX1, double dY1, const PdfColor & rStart, const PdfColor & rEnd, PdfVecObjects* pParent ); /** Create an axial shading pattern * * \param dX0 the starting x coordinate * \param dY0 the starting y coordinate * \param dX1 the ending x coordinate * \param dY1 the ending y coordinate * \param rStart the starting color * \param rEnd the ending color * \param pParent the parent */ PdfAxialShadingPattern( double dX0, double dY0, double dX1, double dY1, const PdfColor & rStart, const PdfColor & rEnd, PdfDocument* pParent ); private: /** Initialize an axial shading pattern * * \param dX0 the starting x coordinate * \param dY0 the starting y coordinate * \param dX1 the ending x coordinate * \param dY1 the ending y coordinate * \param rStart the starting color * \param rEnd the ending color */ void Init( double dX0, double dY0, double dX1, double dY1, const PdfColor & rStart, const PdfColor & rEnd ); }; /** A shading pattern that is an 2D * shading between four colors. */ class PODOFO_DOC_API PdfFunctionBaseShadingPattern : public PdfShadingPattern { public: /** Create an 2D shading pattern * * \param rLL the color on lower left corner * \param rUL the color on upper left corner * \param rLR the color on lower right corner * \param rUR the color on upper right corner * \param rMatrix the transformation matrix mapping the coordinate space * specified by the Domain entry into the shadings target coordinate space * \param pParent the parent */ PdfFunctionBaseShadingPattern( const PdfColor & rLL, const PdfColor & rUL, const PdfColor & rLR, const PdfColor & rUR, const PdfArray & rMatrix, PdfVecObjects* pParent ); /** Create an 2D shading pattern * * \param rLL the color on lower left corner * \param rUL the color on upper left corner * \param rLR the color on lower right corner * \param rUR the color on upper right corner * \param rMatrix the transformation matrix mapping the coordinate space * specified by the Domain entry into the shading's target coordinate space * \param pParent the parent */ PdfFunctionBaseShadingPattern( const PdfColor & rLL, const PdfColor & rUL, const PdfColor & rLR, const PdfColor & rUR, const PdfArray & rMatrix, PdfDocument* pParent ); private: /** Initialize an 2D shading pattern * * \param rLL the color on lower left corner * \param rUL the color on upper left corner * \param rLR the color on lower right corner * \param rUR the color on upper right corner * \param rMatrix the transformation matrix mapping the coordinate space * specified by the Domain entry into the shading's target coordinate space */ void Init( const PdfColor & rLL, const PdfColor & rUL, const PdfColor & rLR, const PdfColor & rUR, const PdfArray & rMatrix ); }; /** A shading pattern that is a simple radial * shading between two colors. */ class PODOFO_DOC_API PdfRadialShadingPattern : public PdfShadingPattern { public: /** Create an radial shading pattern * * \param dX0 the inner circles x coordinate * \param dY0 the inner circles y coordinate * \param dR0 the inner circles radius * \param dX1 the outer circles x coordinate * \param dY1 the outer circles y coordinate * \param dR1 the outer circles radius * \param rStart the starting color * \param rEnd the ending color * \param pParent the parent */ PdfRadialShadingPattern( double dX0, double dY0, double dR0, double dX1, double dY1, double dR1, const PdfColor & rStart, const PdfColor & rEnd, PdfVecObjects* pParent ); /** Create an radial shading pattern * * \param dX0 the inner circles x coordinate * \param dY0 the inner circles y coordinate * \param dR0 the inner circles radius * \param dX1 the outer circles x coordinate * \param dY1 the outer circles y coordinate * \param dR1 the outer circles radius * \param rStart the starting color * \param rEnd the ending color * \param pParent the parent */ PdfRadialShadingPattern( double dX0, double dY0, double dR0, double dX1, double dY1, double dR1, const PdfColor & rStart, const PdfColor & rEnd, PdfDocument* pParent ); private: /** Initialize an radial shading pattern * * \param dX0 the inner circles x coordinate * \param dY0 the inner circles y coordinate * \param dR0 the inner circles radius * \param dX1 the outer circles x coordinate * \param dY1 the outer circles y coordinate * \param dR1 the outer circles radius * \param rStart the starting color * \param rEnd the ending color */ void Init( double dX0, double dY0, double dR0, double dX1, double dY1, double dR1, const PdfColor & rStart, const PdfColor & rEnd ); }; /** A shading pattern that is a simple triangle * shading between three colors. It's a single-triangle * simplified variation of a FreeForm shadding pattern. */ class PODOFO_DOC_API PdfTriangleShadingPattern : public PdfShadingPattern { public: /** Create a triangle shading pattern * * \param dX0 triangle x coordinate of point 0 * \param dY0 triangle y coordinate of point 0 * \param color0 color of point 0 * \param dX1 triangle x coordinate of point 1 * \param dY1 triangle y coordinate of point 1 * \param color1 color of point 1 * \param dX2 triangle x coordinate of point 2 * \param dY2 triangle y coordinate of point 2 * \param color2 color of point 2 * \param pParent the parent */ PdfTriangleShadingPattern( double dX0, double dY0, const PdfColor &color0, double dX1, double dY1, const PdfColor &color1, double dX2, double dY2, const PdfColor &color2, PdfVecObjects* pParent ); /** Create a triangle shading pattern * * \param dX0 triangle x coordinate of point 0 * \param dY0 triangle y coordinate of point 0 * \param color0 color of point 0 * \param dX1 triangle x coordinate of point 1 * \param dY1 triangle y coordinate of point 1 * \param color1 color of point 1 * \param dX2 triangle x coordinate of point 2 * \param dY2 triangle y coordinate of point 2 * \param color2 color of point 2 * \param pParent the parent */ PdfTriangleShadingPattern( double dX0, double dY0, const PdfColor &color0, double dX1, double dY1, const PdfColor &color1, double dX2, double dY2, const PdfColor &color2, PdfDocument* pParent ); private: /** Initialize a triangle shading pattern * * \param dX0 triangle x coordinate of point 0 * \param dY0 triangle y coordinate of point 0 * \param color0 color of point 0 * \param dX1 triangle x coordinate of point 1 * \param dY1 triangle y coordinate of point 1 * \param color1 color of point 1 * \param dX2 triangle x coordinate of point 2 * \param dY2 triangle y coordinate of point 2 * \param color2 color of point 2 */ void Init( double dX0, double dY0, const PdfColor &color0, double dX1, double dY1, const PdfColor &color1, double dX2, double dY2, const PdfColor &color2 ); }; }; #endif // _PDF_SHADING_PATTERN_H_ podofo-0.9.3/src/doc/PdfPainter.h0000664000175000017500000010610412347317126016432 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2005 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_PAINTER_H_ #define _PDF_PAINTER_H_ #include "podofo/base/PdfDefines.h" #include "podofo/base/PdfRect.h" #include "podofo/base/PdfColor.h" #include namespace PoDoFo { class PdfCanvas; class PdfExtGState; class PdfFont; class PdfImage; class PdfMemDocument; class PdfName; class PdfObject; class PdfReference; class PdfShadingPattern; class PdfStream; class PdfString; class PdfTilingPattern; class PdfXObject; struct TLineElement { TLineElement() : pszStart( NULL ), lLen( 0L ) { } const char* pszStart; pdf_long lLen; }; /** * This class provides an easy to use painter object which allows you to draw on a PDF page * object. * * During all drawing operations, you are still able to access the stream of the object you are * drawing on directly. * * All functions that take coordinates expect these to be in PDF User Units. Keep in mind that PDF has * its coordinate system origin at the bottom left corner. */ class PODOFO_DOC_API PdfPainter { public: /** Create a new PdfPainter object. */ PdfPainter(); virtual ~PdfPainter(); /** Set the page on which the painter should draw. * The painter will draw of course on the pages * contents object. * * Calls FinishPage() on the last page if it was not yet called. * * \param pPage a PdfCanvas object (most likely a PdfPage or PdfXObject). * * \see PdfPage \see PdfXObject * \see FinishPage() * \see GetPage() */ void SetPage( PdfCanvas* pPage ); /** Return the current page that is that on the painter. * * \returns the current page of the painter or NULL if none is set */ inline PdfCanvas* GetPage() const; /** Return the current page canvas stream that is set on the painter. * * \returns the current page canvas stream of the painter or NULL if none is set */ inline PdfStream* GetCanvas() const; /** Finish drawing onto a page. * * This has to be called whenever a page has been drawn complete. */ void FinishPage(); /** Set the color for all following stroking operations * in grayscale colorspace. This operation used the 'G' * PDF operator. * \param g gray scale value in the range 0.0 - 1.0 */ void SetStrokingGray( double g ); /** Set the color for all following non-stroking operations * in grayscale colorspace. This operation used the 'g' * PDF operator. * \param g gray scale value in the range 0.0 - 1.0 */ void SetGray( double g ); /** Set the color for all following stroking operations * in rgb colorspace. This operation used the 'RG' * PDF operator. * \param r red value in the range 0.0 - 1.0 * \param g green value in the range 0.0 - 1.0 * \param b blue value in the range 0.0 - 1.0 */ void SetStrokingColor( double r, double g, double b ); /** Set the color for all following non-stroking operations * in rgb colorspace. This operation used the 'rg' * PDF operator. * * This color is also used when drawing text. * * \param r red value in the range 0.0 - 1.0 * \param g green value in the range 0.0 - 1.0 * \param b blue value in the range 0.0 - 1.0 */ void SetColor( double r, double g, double b ); /** Set the color for all following stroking operations * in cmyk colorspace. This operation used the 'K' * PDF operator. * \param c cyan value in the range 0.0 - 1.0 * \param m magenta value in the range 0.0 - 1.0 * \param y yellow value in the range 0.0 - 1.0 * \param k black value in the range 0.0 - 1.0 */ void SetStrokingColorCMYK( double c, double m, double y, double k ); /** Set the color for all following non-stroking operations * in cmyk colorspace. This operation used the 'k' * PDF operator. * \param c cyan value in the range 0.0 - 1.0 * \param m magenta value in the range 0.0 - 1.0 * \param y yellow value in the range 0.0 - 1.0 * \param k black value in the range 0.0 - 1.0 */ void SetColorCMYK( double c, double m, double y, double k ); /** Set the shading pattern for all following stroking operations. * This operation uses the 'SCN' PDF operator. * * \param rPattern a shading pattern */ void SetStrokingShadingPattern( const PdfShadingPattern & rPattern ); /** Set the shading pattern for all following non-stroking operations. * This operation uses the 'scn' PDF operator. * * \param rPattern a shading pattern */ void SetShadingPattern( const PdfShadingPattern & rPattern ); /** Set the tiling pattern for all following stroking operations. * This operation uses the 'SCN' PDF operator. * * \param rPattern a tiling pattern */ void SetStrokingTilingPattern( const PdfTilingPattern & rPattern ); /** Set the tiling pattern for all following stroking operations by pattern name, * Use when it's already in resources. * This operation uses the 'SCN' PDF operator. * * \param rPatternName a tiling pattern name */ void SetStrokingTilingPattern( const std::string &rPatternName ); /** Set the tiling pattern for all following non-stroking operations. * This operation uses the 'scn' PDF operator. * * \param rPattern a tiling pattern */ void SetTilingPattern( const PdfTilingPattern & rPattern ); /** Set the tiling pattern for all following non-stroking operations by pattern name. * Use when it's already in resources. * This operation uses the 'scn' PDF operator. * * \param rPattern a tiling pattern */ void SetTilingPattern( const std::string & rPatternName ); /** Set the color for all following stroking operations. * * \param rColor a PdfColor object */ void SetStrokingColor( const PdfColor & rColor ); /** Set the color for all following non-stroking operations. * * \param rColor a PdfColor object */ void SetColor( const PdfColor & rColor ); /** Set the line width for all stroking operations. * \param dWidth in PDF User Units. */ void SetStrokeWidth( double dWidth ); /** Set the stoke style for all stroking operations. * \param eStyle style of the stroking operations * \param pszCustom a custom stroking style which is used when * eStyle == ePdfStrokeStyle_Custom. * \param inverted inverted dash style (gaps for drawn spaces), * it is ignored for None, Solid and Custom styles * \param scale scale factor of the stroke style * it is ignored for None, Solid and Custom styles * \param subtractJoinCap if true, subtracts scaled width on filled parts, * thus the line capability still draws into the cell; * is used only if scale is not 1.0 * * Possible values: * ePdfStrokeStyle_None * ePdfStrokeStyle_Solid * ePdfStrokeStyle_Dash * ePdfStrokeStyle_Dot * ePdfStrokeStyle_DashDot * ePdfStrokeStyle_DashDotDot * ePdfStrokeStyle_Custom * */ void SetStrokeStyle( EPdfStrokeStyle eStyle, const char* pszCustom = NULL, bool inverted = false, double scale = 1.0, bool subtractJoinCap = false ); /** Set the line cap style for all stroking operations. * \param eCapStyle the cap style. * * Possible values: * ePdfLineCapStyle_Butt, * ePdfLineCapStyle_Round, * ePdfLineCapStyle_Square */ void SetLineCapStyle( EPdfLineCapStyle eCapStyle ); /** Set the line join style for all stroking operations. * \param eJoinStyle the join style. * * Possible values: * ePdfLineJoinStyle_Miter * ePdfLineJoinStyle_Round * ePdfLineJoinStyle_Bevel */ void SetLineJoinStyle( EPdfLineJoinStyle eJoinStyle ); /** Set the font for all text drawing operations * \param pFont a handle to a valid PdfFont object * * \see DrawText */ void SetFont( PdfFont* pFont ); /** Set the text rendering mode * \param mode What text rendering mode to use. * * Possible values: * ePdfTextRenderingMode_Fill (default mode) * ePdfTextRenderingMode_Stroke * ePdfTextRenderingMode_FillAndStroke * ePdfTextRenderingMode_Invisible * ePdfTextRenderingMode_FillToClipPath * ePdfTextRenderingMode_StrokeToClipPath * ePdfTextRenderingMode_FillAndStrokeToClipPath * ePdfTextRenderingMode_ToClipPath */ void SetTextRenderingMode( EPdfTextRenderingMode mode ); /** Gets current text rendering mode. * Default mode is ePdfTextRenderingMode_Fill. */ inline EPdfTextRenderingMode GetTextRenderingMode(void) const; /** Get the current font: * \returns a font object or NULL if no font was set. */ inline PdfFont* GetFont() const; /** Set a clipping rectangle * * \param dX x coordinate of the rectangle (left coordinate) * \param dY y coordinate of the rectangle (bottom coordinate) * \param dWidth width of the rectangle * \param dHeight absolute height of the rectangle */ void SetClipRect( double dX, double dY, double dWidth, double dHeight ); /** Set a clipping rectangle * * \param rRect rectangle */ inline void SetClipRect( const PdfRect & rRect ); /** Set miter limit. */ void SetMiterLimit(double value); /** Draw a line with the current color and line settings. * \param dStartX x coordinate of the starting point * \param dStartY y coordinate of the starting point * \param dEndX x coordinate of the ending point * \param dEndY y coordinate of the ending point */ void DrawLine( double dStartX, double dStartY, double dEndX, double dEndY ); /** Add a rectangle into the current path * \param dX x coordinate of the rectangle (left coordinate) * \param dY y coordinate of the rectangle (bottom coordinate) * \param dWidth width of the rectangle * \param dHeight absolute height of the rectangle * \param dRoundX rounding factor, x direction * \param dRoundY rounding factor, y direction */ void Rectangle( double dX, double dY, double dWidth, double dHeight, double dRoundX=0.0, double dRoundY=0.0 ); /** Add a rectangle into the current path * * \param rRect the rectangle area * \param dRoundX rounding factor, x direction * \param dRoundY rounding factor, y direction * * \see DrawRect */ inline void Rectangle( const PdfRect & rRect, double dRoundX=0.0, double dRoundY=0.0 ); /** Add an ellipse into the current path * \param dX x coordinate of the ellipse (left coordinate) * \param dY y coordinate of the ellipse (top coordinate) * \param dWidth width of the ellipse * \param dHeight absolute height of the ellipse */ void Ellipse( double dX, double dY, double dWidth, double dHeight ); /** Add a circle into the current path * \param dX x center coordinate of the circle * \param dY y coordinate of the circle * \param dRadius radius of the circle */ void Circle( double dX, double dY, double dRadius ); /** Draw a single-line text string on a page using a given font object. * You have to call SetFont before calling this function. * \param dX the x coordinate * \param dY the y coordinate * \param sText the text string which should be printed * * \see SetFont() */ void DrawText( double dX, double dY, const PdfString & sText); /** Draw a single-line text string on a page using a given font object. * You have to call SetFont before calling this function. * \param dX the x coordinate * \param dY the y coordinate * \param sText the text string which should be printed (is not allowed to be NULL!) * \param lLen draw only lLen characters of pszText * * \see SetFont() */ void DrawText( double dX, double dY, const PdfString & sText, long lLen ); /** Draw multiline text into a rectangle doing automatic wordwrapping. * The current font is used and SetFont has to be called at least once * before using this function * * \param dX the x coordinate of the text area (left) * \param dY the y coordinate of the text area (bottom) * \param dWidth width of the text area * \param dHeight height of the text area * \param rsText the text which should be drawn * \param eAlignment alignment of the individual text lines in the given bounding box * \param eVertical vertical alignment of the text in the given bounding box * \param bClip set the clipping rectangle to the given rRect, otherwise no clipping is performed */ void DrawMultiLineText( double dX, double dY, double dWidth, double dHeight, const PdfString & rsText, EPdfAlignment eAlignment = ePdfAlignment_Left, EPdfVerticalAlignment eVertical = ePdfVerticalAlignment_Top, bool bClip = true ); /** Draw multiline text into a rectangle doing automatic wordwrapping. * The current font is used and SetFont has to be called at least once * before using this function * * \param rRect bounding rectangle of the text * \param rsText the text which should be drawn * \param eAlignment alignment of the individual text lines in the given bounding box * \param eVertical vertical alignment of the text in the given bounding box * \param bClip set the clipping rectangle to the given rRect, otherwise no clipping is performed */ inline void DrawMultiLineText( const PdfRect & rRect, const PdfString & rsText, EPdfAlignment eAlignment = ePdfAlignment_Left, EPdfVerticalAlignment eVertical = ePdfVerticalAlignment_Top, bool bClip = true ); /** Gets the text divided into individual lines, using the current font and clipping rectangle. * * \param dWidth width of the text area * \param rsText the text which should be drawn */ std::vector GetMultiLineTextAsLines( double dWidth, const PdfString & rsText); /** Draw a single line of text horizontally aligned. * \param dX the x coordinate of the text line * \param dY the y coordinate of the text line * \param dWidth the width of the text line * \param rsText the text to draw * \param eAlignment alignment of the text line */ void DrawTextAligned( double dX, double dY, double dWidth, const PdfString & rsText, EPdfAlignment eAlignment ); /** Begin drawing multiple text strings on a page using a given font object. * You have to call SetFont before calling this function. * * If you want more simpler text output and do not need * the advanced text position features of MoveTextPos * use DrawText which is easier. * * \param dX the x coordinate * \param dY the y coordinate * * \see SetFont() * \see AddText() * \see MoveTextPos() * \see EndText() */ void BeginText( double dX, double dY ); /** Draw a string on a page. * You have to call BeginText before the first call of this function * and EndText after the last call. * * If you want more simpler text output and do not need * the advanced text position features of MoveTextPos * use DrawText which is easier. * * \param sText the text string which should be printed * * \see SetFont() * \see MoveTextPos() * \see EndText() */ void AddText( const PdfString & sText ); /** Draw a string on a page. * You have to call BeginText before the first call of this function * and EndText after the last call. * * If you want more simpler text output and do not need * the advanced text position features of MoveTextPos * use DrawText which is easier. * * \param sText the text string which should be printed * \param lStringLen draw only lLen characters of pszText * * \see SetFont() * \see MoveTextPos() * \see EndText() */ void AddText( const PdfString & sText, pdf_long lStringLen ); /** Move position for text drawing on a page. * You have to call BeginText before calling this function * * If you want more simpler text output and do not need * the advanced text position features of MoveTextPos * use DrawText which is easier. * * \param dX the x offset relative to pos of BeginText or last MoveTextPos * \param dY the y offset relative to pos of BeginText or last MoveTextPos * * \see BeginText() * \see AddText() * \see EndText() */ void MoveTextPos( double dX, double dY ); /** End drawing multiple text strings on a page * * If you want more simpler text output and do not need * the advanced text position features of MoveTextPos * use DrawText which is easier. * * \see BeginText() * \see AddText() * \see MoveTextPos() */ void EndText(); /** Draw a single glyph on a page using a given font object. * \param pDocument pointer to the document, needed to generate a copy of the current font * \param dX the x coordinate * \param dY the y coordinate * \param pszGlyphname the name of the glyph which should be printed * * \see SetFont() */ void DrawGlyph( PdfMemDocument* pDocument, double dX, double dY, const char * pszGlyphname ); /** Draw an image on the current page. * \param dX the x coordinate (bottom left position of the image) * \param dY the y coordinate (bottom position of the image) * \param pObject an PdfXObject * \param dScaleX option scaling factor in x direction * \param dScaleY option scaling factor in y direction */ void DrawImage( double dX, double dY, PdfImage* pObject, double dScaleX = 1.0, double dScaleY = 1.0); /** Draw an XObject on the current page. For PdfImage use DrawImage. * * \param dX the x coordinate (bottom left position of the XObject) * \param dY the y coordinate (bottom position of the XObject) * \param pObject an PdfXObject * \param dScaleX option scaling factor in x direction * \param dScaleY option scaling factor in y direction * * \see DrawImage */ void DrawXObject( double dX, double dY, PdfXObject* pObject, double dScaleX = 1.0, double dScaleY = 1.0); /** Closes the current path by drawing a line from the current point * to the starting point of the path. Matches the PDF 'h' operator. * This function is useful to construct an own path * for drawing or clipping. */ void ClosePath(); /** Append a line segment to the current path. Matches the PDF 'l' operator. * This function is useful to construct an own path * for drawing or clipping. * \param dX x position * \param dY y position */ void LineTo( double dX, double dY ); /** Begin a new path. Matches the PDF 'm' operator. * This function is useful to construct an own path * for drawing or clipping. * \param dX x position * \param dY y position */ void MoveTo( double dX, double dY ); /** Append a cubic bezier curve to the current path * Matches the PDF 'c' operator. * * \param dX1 x coordinate of the first control point * \param dY1 y coordinate of the first control point * \param dX2 x coordinate of the second control point * \param dY2 y coordinate of the second control point * \param dX3 x coordinate of the end point, which is the new current point * \param dY3 y coordinate of the end point, which is the new current point */ void CubicBezierTo( double dX1, double dY1, double dX2, double dY2, double dX3, double dY3 ); /** Append a horizontal line to the current path * Matches the SVG 'H' operator * * \param dX x coordinate to draw the line to */ void HorizontalLineTo( double dX ); /** Append a vertical line to the current path * Matches the SVG 'V' operator * * \param dY y coordinate to draw the line to */ void VerticalLineTo( double dY ); /** Append a smooth bezier curve to the current path * Matches the SVG 'S' operator. * * \param dX2 x coordinate of the second control point * \param dY2 y coordinate of the second control point * \param dX3 x coordinate of the end point, which is the new current point * \param dY3 y coordinate of the end point, which is the new current point */ void SmoothCurveTo( double dX2, double dY2, double dX3, double dY3 ); /** Append a quadratic bezier curve to the current path * Matches the SVG 'Q' operator. * * \param dX1 x coordinate of the first control point * \param dY1 y coordinate of the first control point * \param dX3 x coordinate of the end point, which is the new current point * \param dY3 y coordinate of the end point, which is the new current point */ void QuadCurveTo( double dX1, double dY1, double dX3, double dY3 ); /** Append a smooth quadratic bezier curve to the current path * Matches the SVG 'T' operator. * * \param dX3 x coordinate of the end point, which is the new current point * \param dY3 y coordinate of the end point, which is the new current point */ void SmoothQuadCurveTo( double dX3, double dY3 ); /** Append a Arc to the current path * Matches the SVG 'A' operator. * * \param dX x coordinate of the start point * \param dY y coordinate of the start point * \param dRadiusX x coordinate of the end point, which is the new current point * \param dRadiusY y coordinate of the end point, which is the new current point * \param dRotation degree of rotation in radians * \param bLarge large or small portion of the arc * \param bSweep sweep? */ void ArcTo( double dX, double dY, double dRadiusX, double dRadiusY, double dRotation, bool bLarge, bool bSweep); // Peter Petrov 5 January 2009 was delivered from libHaru /** */ bool Arc(double dX, double dY, double dRadius, double dAngle1, double dAngle2); /** Close the current path. Matches the PDF 'h' operator. */ void Close(); /** Stroke the current path. Matches the PDF 'S' operator. * This function is useful to construct an own path * for drawing or clipping. */ void Stroke(); /** Fill the current path. Matches the PDF 'f' operator. * This function is useful to construct an own path * for drawing or clipping. * * \param useEvenOddRule select even-odd rule instead of nonzero winding number rule */ void Fill(bool useEvenOddRule = false); /** Fill then stroke the current path. Matches the PDF 'B' operator. * * \param useEvenOddRule select even-odd rule instead of nonzero winding number rule */ void FillAndStroke(bool useEvenOddRule = false); /** Clip the current path. Matches the PDF 'W' operator. * This function is useful to construct an own path * for drawing or clipping. * * \param useEvenOddRule select even-odd rule instead of nonzero winding number rule */ void Clip( bool useEvenOddRule = false); /** End current pathm without filling or stroking it. * Matches the PDF 'n' operator. */ void EndPath(void); /** Save the current graphics settings onto the graphics * stack. Operator 'q' in PDF. * This call has to be balanced with a corresponding call * to Restore()! * * \see Restore */ void Save(); /** Restore the current graphics settings from the graphics * stack. Operator 'Q' in PDF. * This call has to be balanced with a corresponding call * to Save()! * * \see Save */ void Restore(); /** Set the transformation matrix for the current coordinate system * See the operator 'cm' in PDF. * * The six parameters are a standard 3x3 transformation matrix * where the 3 left parameters are 0 0 1. * * \param a scale in x direction * \param b rotation * \param c rotation * \param d scale in y direction * \param e translate in x direction * \param f translate in y direction * * \see Save() * \see Restore() */ void SetTransformationMatrix( double a, double b, double c, double d, double e, double f ); /** Sets a specific PdfExtGState as being active * \param inGState the specific ExtGState to set */ void SetExtGState( PdfExtGState* inGState ); /** Sets a specific rendering intent * \param intent the specific intent to set */ void SetRenderingIntent( char* intent ); /** Set the tab width for the DrawText operation. * Every tab '\\t' is replaced with nTabWidth * spaces before drawing text. Default is a value of 4 * * \param nTabWidth replace every tabulator by this much spaces * * \see DrawText * \see TabWidth */ inline void SetTabWidth( unsigned short nTabWidth ); /** Get the currently set tab width * \returns by how many spaces a tabulator will be replaced * * \see DrawText * \see TabWidth */ inline unsigned short GetTabWidth() const; /** Set the floating point precision. * * \param inPrec write this many decimal places */ inline void SetPrecision( unsigned short inPrec ); /** Get the currently set floating point precision * \returns how many decimal places will be written out for any floating point value */ inline unsigned short GetPrecision() const; /** Get current path string stream. * Stroke/Fill commands clear current path. * \returns std::ostringstream representing current path */ inline std::ostringstream &GetCurrentPath(void); private: /** Coverts a rectangle to an array of points which can be used * to draw an ellipse using 4 bezier curves. * * The arrays plPointX and plPointY need space for at least 12 longs * to be stored. * * \param dX x position of the bounding rectangle * \param dY y position of the bounding rectangle * \param dWidth width of the bounding rectangle * \param dHeight height of the bounding rectangle * \param pdPointX pointer to an array were the x coordinates * of the resulting points will be stored * \param pdPointY pointer to an array were the y coordinates * of the resulting points will be stored */ void ConvertRectToBezier( double dX, double dY, double dWidth, double dHeight, double pdPointX[], double pdPointY[] ); protected: /** Register an object in the resource dictionary of this page * so that it can be used for any following drawing operations. * * \param rIdentifier identifier of this object, e.g. /Ft0 * \param rRef reference to the object you want to register * \param rName register under this key in the resource dictionary */ virtual void AddToPageResources( const PdfName & rIdentifier, const PdfReference & rRef, const PdfName & rName ); /** Sets the color that was last set by the user as the current stroking color. * You should always enclose this function by Save() and Restore() * * \see Save() \see Restore() */ void SetCurrentStrokingColor(); bool InternalArc( double x, double y, double ray, double ang1, double ang2, bool cont_flg); /** Expand all tab characters in a string * using spaces. * * \param rsString expand all tabs in this string using spaces * \param lLen use only lLen characters of rsString * \returns an expanded copy of the passed string * \see SetTabWidth */ PdfString ExpandTabs( const PdfString & rsString, pdf_long lLen ) const; #if defined(_MSC_VER) && _MSC_VER <= 1200 // MSC 6.0 has a template-bug PdfString ExpandTabs_char( const char* pszText, long lStringLen, int nTabCnt, const char cTab, const char cSpace ) const; PdfString ExpandTabs_pdf_utf16be( const pdf_utf16be* pszText, long lStringLen, int nTabCnt, const pdf_utf16be cTab, const pdf_utf16be cSpace ) const; #else template PdfString ExpandTabsPrivate( const C* pszText, pdf_long lStringLen, int nTabCnt, const C cTab, const C cSpace ) const; #endif protected: /** All drawing operations work on this stream. * This object may not be NULL. If it is NULL any function accessing it should * return ERROR_PDF_INVALID_HANDLE */ PdfStream* m_pCanvas; /** The page object is needed so that fonts etc. can be added * to the page resource dictionary as appropriate. */ PdfCanvas* m_pPage; /** Font for all drawing operations */ PdfFont* m_pFont; /** Every tab '\\t' is replaced with m_nTabWidth * spaces before drawing text. Default is a value of 4 */ unsigned short m_nTabWidth; /** Save the current color for non stroking colors */ PdfColor m_curColor; /** Is between BT and ET */ bool m_isTextOpen; /** temporary stream buffer */ std::ostringstream m_oss; /** current path */ std::ostringstream m_curPath; EPdfTextRenderingMode currentTextRenderingMode; void SetCurrentTextRenderingMode( void ); double lpx, lpy, lpx2, lpy2, lpx3, lpy3, // points for this operation lcx, lcy, // last "current" point lrx, lry; // "reflect points" }; // ----------------------------------------------------- // // ----------------------------------------------------- PdfCanvas* PdfPainter::GetPage() const { return m_pPage; } // ----------------------------------------------------- // // ----------------------------------------------------- PdfStream* PdfPainter::GetCanvas() const { return m_pCanvas; } // ----------------------------------------------------- // // ----------------------------------------------------- EPdfTextRenderingMode PdfPainter::GetTextRenderingMode(void) const { return currentTextRenderingMode; } // ----------------------------------------------------- // // ----------------------------------------------------- PdfFont* PdfPainter::GetFont() const { return m_pFont; } // ----------------------------------------------------- // // ----------------------------------------------------- void PdfPainter::SetTabWidth( unsigned short nTabWidth ) { m_nTabWidth = nTabWidth; } // ----------------------------------------------------- // // ----------------------------------------------------- unsigned short PdfPainter::GetTabWidth() const { return m_nTabWidth; } // ----------------------------------------------------- // // ----------------------------------------------------- void PdfPainter::SetPrecision( unsigned short inPrec ) { m_oss.precision( inPrec ); } // ----------------------------------------------------- // // ----------------------------------------------------- unsigned short PdfPainter::GetPrecision() const { return static_cast(m_oss.precision()); } // ----------------------------------------------------- // // ----------------------------------------------------- inline std::ostringstream &PdfPainter::GetCurrentPath(void) { return m_curPath; } // ----------------------------------------------------- // // ----------------------------------------------------- void PdfPainter::SetClipRect( const PdfRect & rRect ) { this->SetClipRect( rRect.GetLeft(), rRect.GetBottom(), rRect.GetWidth(), rRect.GetHeight() ); } // ----------------------------------------------------- // // ----------------------------------------------------- void PdfPainter::Rectangle( const PdfRect & rRect, double dRoundX, double dRoundY ) { this->Rectangle( rRect.GetLeft(), rRect.GetBottom(), rRect.GetWidth(), rRect.GetHeight(), dRoundX, dRoundY ); } // ----------------------------------------------------- // // ----------------------------------------------------- void PdfPainter::DrawMultiLineText( const PdfRect & rRect, const PdfString & rsText, EPdfAlignment eAlignment, EPdfVerticalAlignment eVertical, bool bClip) { this->DrawMultiLineText( rRect.GetLeft(), rRect.GetBottom(), rRect.GetWidth(), rRect.GetHeight(), rsText, eAlignment, eVertical, bClip ); } }; #endif // _PDF_PAINTER_H_ podofo-0.9.3/src/doc/PdfPage.h0000664000175000017500000003061112262234754015704 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2005 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_PAGE_H_ #define _PDF_PAGE_H_ #include "podofo/base/PdfDefines.h" #include "podofo/base/PdfArray.h" #include "podofo/base/PdfCanvas.h" #include "podofo/base/PdfRect.h" #include "PdfAnnotation.h" #include "PdfContents.h" #include "PdfElement.h" #include "PdfField.h" namespace PoDoFo { class PdfDocument; class PdfDictionary; class PdfVecObjects; typedef std::map TMapAnnotation; typedef TMapAnnotation::iterator TIMapAnnotation; typedef TMapAnnotation::const_iterator TCIMapAnnotation; /** PdfPage is one page in the pdf document. * It is possible to draw on a page using a PdfPainter object. * Every document needs at least one page. */ class PODOFO_DOC_API PdfPage : public PdfElement, public PdfCanvas { public: /** Create a new PdfPage object. * \param rSize a PdfRect specifying the size of the page (i.e the /MediaBox key) in PDF units * \param pParent add the page to this parent */ PdfPage( const PdfRect & rSize, PdfDocument* pParent ); /** Create a new PdfPage object. * \param rSize a PdfRect specifying the size of the page (i.e the /MediaBox key) in PDF units * \param pParent add the page to this parent */ PdfPage( const PdfRect & rSize, PdfVecObjects* pParent ); /** Create a PdfPage based on an existing PdfObject * \param pObject an existing PdfObject * \param listOfParents a list of PdfObjects that are * parents of this page and can be * queried for inherited attributes. * The last object in the list is the * most direct parent of this page. */ PdfPage( PdfObject* pObject, const std::deque & listOfParents ); virtual ~PdfPage(); /** Get the current page size in PDF Units * \returns a PdfRect containing the page size available for drawing */ inline virtual const PdfRect GetPageSize() const; // added by Petr P. Petrov 21 Febrary 2010 /** Set the current page width in PDF Units * * \returns true if successfull, false otherwise * */ bool SetPageWidth(int newWidth); // added by Petr P. Petrov 21 Febrary 2010 /** Set the current page height in PDF Units * * \returns true if successfull, false otherwise * */ bool SetPageHeight(int newHeight); /** Set the trimbox in PDF Units * \param rSize a PdfRect specifying the trimbox of the page (i.e the /TrimBox key) in PDF units */ void SetTrimBox( const PdfRect & rSize ); /** Page number inside of the document. The first page * has the number 1, the last page has the number * PdfPagesTree:GetTotalNumberOfPages() * * \returns the number of the page inside of the document * * \see PdfPagesTree:GetTotalNumberOfPages() */ unsigned int GetPageNumber() const; /** Creates a PdfRect with the page size as values which is needed to create a PdfPage object * from an enum which are defined for a few standard page sizes. * * \param ePageSize the page size you want * \param bLandscape create a landscape pagesize instead of portrait (by exchanging width and height) * \returns a PdfRect object which can be passed to the PdfPage constructor */ static PdfRect CreateStandardPageSize( const EPdfPageSize ePageSize, bool bLandscape = false ); /** Get access to the contents object of this page. * If you want to draw onto the page, you have to add * drawing commands to the stream of the Contents object. * \returns a contents object */ virtual PdfObject* GetContents() const; /** Get access an object that you can use to ADD drawing to. * If you want to draw onto the page, you have to add * drawing commands to the stream of the Contents object. * \returns a contents object */ virtual PdfObject* GetContentsForAppending() const; /** Get access to the resources object of this page. * This is most likely an internal object. * \returns a resources object */ inline virtual PdfObject* GetResources() const; /** Get the current MediaBox (physical page size) in PDF units. * \returns PdfRect the page box */ virtual const PdfRect GetMediaBox() const { return GetPageBox( "MediaBox" ); } /** Get the current CropBox (visible page size) in PDF units. * \returns PdfRect the page box */ virtual const PdfRect GetCropBox() const { return GetPageBox( "CropBox" ); } /** Get the current TrimBox (cut area) in PDF units. * \returns PdfRect the page box */ virtual const PdfRect GetTrimBox() const { return GetPageBox( "TrimBox" ); } /** Get the current BleedBox (extra area for printing purposes) in PDF units. * \returns PdfRect the page box */ virtual const PdfRect GetBleedBox() const { return GetPageBox( "BleedBox" ); } /** Get the current ArtBox in PDF units. * \returns PdfRect the page box */ virtual const PdfRect GetArtBox() const { return GetPageBox( "ArtBox" ); } /** Get the current page rotation (if any). * \returns int 0, 90, 180 or 270 */ virtual int GetRotation() const; /** Set the current page rotation. * \param iRotation Rotation to set to the page. Valid value are 0, 90, 180, 270. */ virtual void SetRotation(int nRotation); /** Get the number of annotations associated with this page * \ returns int number of annotations */ virtual int GetNumAnnots() const; /** Create a new annotation to this page. * \param eType the type of the annotation * \param rRect rectangle of the annotation on the page * * \returns the annotation object which is owned by the PdfPage */ PdfAnnotation* CreateAnnotation( EPdfAnnotation eType, const PdfRect & rRect ); /** Get the annotation with index index of the current page. * \param index the index of the annotation to retrieve * * \returns a annotation object. The annotation object is owned by the PdfPage. * * \see GetNumAnnots */ PdfAnnotation* GetAnnotation( int index ); /** Delete the annotation with index index from this page. * \param index the index of the annotation to delete * * \see GetNumAnnots */ void DeleteAnnotation( int index ); /** Delete the annotation object with reference ref from this page. * \param ref the reference of an annotation object of this page. * * \see GetNumAnnots */ void DeleteAnnotation( const PdfReference & ref ); /** * \returns the number of PdfFields on this page. */ int GetNumFields() const; /** Get a PdfField with a certain index. * \param index of the PdfField (must be smaller than GetNumFields() ) * * \see GetNumFields * * \returns a PdfField */ PdfField GetField( int index ); /** Get a PdfField with a certain index. * \param index of the PdfField (must be smaller than GetNumFields() ) * * \see GetNumFields * * \returns a constP dfField */ const PdfField GetField( int index ) const; /** Get an element from the pages resources dictionary, * using a type (category) and a key. * * \param rType the type of resource to fetch (e.g. /Font, or /XObject) * \param rKey the key of the resource * * \returns the object of the resource or NULL if it was not found */ PdfObject* GetFromResources( const PdfName & rType, const PdfName & rKey ); /** Method for getting a value that can be inherited * Possible names that can be inherited according to * the PDF specification are: Resources, MediaBox, CropBox and Rotate * * \returns PdfObject - the result of the key fetching or NULL */ inline const PdfObject* GetInheritedKey( const PdfName & rName ) const; PdfObject* GetOwnAnnotationsArray( bool bCreate, PdfDocument *pDocument); private: /** * Initialize a new page object. * m_pContents must be initialized before calling this! * * @param rSize page size */ void InitNewPage( const PdfRect & rSize ); /** * Create the internal PdfContents object. * Call this before accessing m_pContents as * the object is only created if needed. */ void CreateContents(); /** Get the bounds of a specified page box in PDF units. * This function is internal, since there are wrappers for all standard boxes * \returns PdfRect the page box */ const PdfRect GetPageBox( const char* inBox ) const; /** Method for getting a key value that could be inherited (such as the boxes, resources, etc.) * \returns PdfObject - the result of the key fetching or NULL */ const PdfObject* GetInheritedKeyFromObject( const char* inKey, const PdfObject* inObject ) const; /** Get the annotations array. * \param bCreate if true the annotations array is created * if it does not exist. * \returns the annotations array or NULL if none exists. */ PdfObject* GetAnnotationsArray( bool bCreate = false ) const; private: PdfContents* m_pContents; PdfObject* m_pResources; TMapAnnotation m_mapAnnotations; }; // ----------------------------------------------------- // // ----------------------------------------------------- inline PdfObject* PdfPage::GetResources() const { return m_pResources; } // ----------------------------------------------------- // // ----------------------------------------------------- inline const PdfRect PdfPage::GetPageSize() const { return this->GetMediaBox(); } // ----------------------------------------------------- // // ----------------------------------------------------- inline const PdfObject* PdfPage::GetInheritedKey( const PdfName & rName ) const { return this->GetInheritedKeyFromObject( rName.GetName().c_str(), this->GetObject() ); } }; #endif // _PDF_PAGE_H_ podofo-0.9.3/src/doc/PdfSignatureField.cpp0000664000175000017500000001406412344436402020267 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2011 by Dominik Seichter * * domseichter@web.de * * by Petr Pytelka * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfSignatureField.h" #include "../base/PdfDictionary.h" #include "../base/PdfData.h" #include "PdfXObject.h" #include namespace PoDoFo { PdfSignatureField::PdfSignatureField( PdfPage* pPage, const PdfRect & rRect, PdfDocument* pDoc ) :PdfField(PoDoFo::ePdfField_Signature, pPage, rRect, pDoc) { m_pSignatureObj = NULL; Init(); } //begin L.K PdfSignatureField::PdfSignatureField( PdfAnnotation* pWidget, PdfAcroForm* pParent, PdfDocument* pDoc) :PdfField(PoDoFo::ePdfField_Signature, pWidget, pParent, pDoc) { m_pSignatureObj = NULL; Init(); } void PdfSignatureField::SetAppearanceStream( PdfXObject* pObject ) { if( !pObject ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } if( !m_pObject->GetDictionary().HasKey( PdfName("AP") ) ) m_pObject->GetDictionary().AddKey( PdfName("AP"), PdfDictionary() ); if( m_pObject->GetDictionary().GetKey( PdfName("AP") )->GetDictionary().HasKey( PdfName("N") ) ) m_pObject->GetDictionary().GetKey( PdfName("AP") )->GetDictionary().RemoveKey(PdfName("N")); m_pObject->GetDictionary().GetKey( PdfName("AP") )->GetDictionary().AddKey( PdfName("N"), pObject->GetObject()->Reference() ); this->GetAppearanceCharacteristics(true); } //end L.K void PdfSignatureField::Init() { m_pSignatureObj = this->GetFieldObject()->GetOwner()->CreateObject( "Sig" ); if( !m_pSignatureObj ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } GetFieldObject()->GetDictionary().AddKey("V", m_pSignatureObj->Reference()); PdfDictionary &dict = m_pSignatureObj->GetDictionary(); dict.AddKey(PdfName::KeyFilter, PdfName("Adobe.PPKLite") ); dict.AddKey("SubFilter", PdfName("adbe.pkcs7.detached") ); } void PdfSignatureField::SetSignatureReason(const PdfString & rsText) { if( !m_pSignatureObj ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } if(m_pSignatureObj->GetDictionary().HasKey(PdfName("Reason"))) { m_pSignatureObj->GetDictionary().RemoveKey(PdfName("Reason")); } m_pSignatureObj->GetDictionary().AddKey(PdfName("Reason"), rsText); } void PdfSignatureField::SetSignatureDate(const PdfDate &sigDate) { if( !m_pSignatureObj ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } if(m_pSignatureObj->GetDictionary().HasKey(PdfName("M"))) { m_pSignatureObj->GetDictionary().RemoveKey(PdfName("M")); } PdfString sDate; sigDate.ToString(sDate); m_pSignatureObj->GetDictionary().AddKey(PdfName("M"), sDate); } void PdfSignatureField::SetSignature(const PdfData &sSignatureData) { // Prepare source data size_t lSigLen = sSignatureData.data().size(); char* pData = static_cast(malloc(lSigLen+2)); pData[0]='<'; pData[lSigLen+1]='>'; memcpy(pData+1, sSignatureData.data().c_str(), lSigLen); PdfData signatureData(pData, lSigLen+2); free(pData); // Content of the signature if( !m_pSignatureObj ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } // Remove old data if(m_pSignatureObj->GetDictionary().HasKey("ByteRange")) { m_pSignatureObj->GetDictionary().RemoveKey("ByteRange"); } if(m_pSignatureObj->GetDictionary().HasKey(PdfName::KeyContents)) { m_pSignatureObj->GetDictionary().RemoveKey(PdfName::KeyContents); } // Byte range PdfData rangeData("[ 0 1234567890 1234567890 1234567890]"); m_pSignatureObj->GetDictionary().AddKey("ByteRange", PdfVariant(rangeData) ); m_pSignatureObj->GetDictionary().AddKey(PdfName::KeyContents, PdfVariant(signatureData) ); } } podofo-0.9.3/src/doc/PdfHintStream.h0000664000175000017500000000713612344436402017107 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2006 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_HINT_STREAM_H_ #define _PDF_HINT_STREAM_H_ #include "podofo/base/PdfDefines.h" #include "podofo/base/PdfWriter.h" #include "PdfElement.h" namespace PoDoFo { class PdfPagesTree; namespace NonPublic { // PdfHintStream is not part of the public API and is NOT exported as part of // the DLL/shared library interface. Do not rely on it. class PdfHintStream : public PdfElement { public: PdfHintStream( PdfVecObjects* pParent, PdfPagesTree* pPagesTree ); ~PdfHintStream(); /** Create the hint stream * \param pXRef pointer to a valid XREF table structure */ //void Create( TVecXRefTable* pXRef ); /** Write a pdf_uint16 to the stream in big endian format. * \param val the value to write to the stream */ void WriteUInt16( pdf_uint16 val ); /** Write a pdf_uint32 to the stream in big endian format. * \param val the value to write to the stream */ void WriteUInt32( pdf_uint32 ); private: //void CreatePageHintTable( TVecXRefTable* pXRef ); void CreateSharedObjectHintTable(); private: PdfPagesTree* m_pPagesTree; }; }; // end namespace NonPublic }; // end namespace PoDoFo #endif /* _PDF_HINT_STREAM_H_ */ podofo-0.9.3/src/doc/PdfPainter.cpp0000664000175000017500000016661412347317126017001 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2005 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #if defined(_MSC_VER) && _MSC_VER <= 1200 #pragma warning(disable: 4786) #endif #include #include #include #include "PdfPainter.h" #include "base/PdfDefinesPrivate.h" #include "base/PdfColor.h" #include "base/PdfDictionary.h" #include "base/PdfFilter.h" #include "base/PdfName.h" #include "base/PdfRect.h" #include "base/PdfStream.h" #include "base/PdfString.h" #include "base/PdfLocale.h" #include "PdfContents.h" #include "PdfExtGState.h" #include "PdfFont.h" #include "PdfFontMetrics.h" #include "PdfImage.h" #include "PdfMemDocument.h" #include "PdfShadingPattern.h" #include "PdfTilingPattern.h" #include "PdfXObject.h" #include #define BEZIER_POINTS 13 /* 4/3 * (1-cos 45,A0(B)/sin 45,A0(B = 4/3 * sqrt(2) - 1 */ #define ARC_MAGIC 0.552284749f #define PI 3.141592654f namespace PoDoFo { static const long clPainterHighPrecision = 15L; static const long clPainterDefaultPrecision = 3L; static inline void CheckDoubleRange( double val, double min, double max ) { if( val < min || val > max ) { PODOFO_RAISE_ERROR( ePdfError_ValueOutOfRange ); } } static inline unsigned short SwapBytes(unsigned short val) { return ((val & 0x00FF) << 8) | ((val & 0xFF00) >> 8); } static inline unsigned short SwapCharBytesIfRequired(pdf_utf16be ch) { #ifdef PODOFO_IS_LITTLE_ENDIAN return SwapBytes(ch); #else return ch; #endif } static inline bool IsNewLineChar(pdf_utf16be ch) { return SwapCharBytesIfRequired(ch) == '\n'; } static inline bool IsSpaceChar(pdf_utf16be ch) { return isspace( SwapCharBytesIfRequired(ch) & 0x00FF ) != 0; } PdfPainter::PdfPainter() : m_pCanvas( NULL ), m_pPage( NULL ), m_pFont( NULL ), m_nTabWidth( 4 ), m_curColor( PdfColor( 0.0, 0.0, 0.0 ) ), m_isTextOpen( false ), m_oss(), m_curPath() { m_oss.flags( std::ios_base::fixed ); m_oss.precision( clPainterDefaultPrecision ); PdfLocaleImbue(m_oss); m_curPath.flags( std::ios_base::fixed ); m_curPath.precision( clPainterDefaultPrecision ); PdfLocaleImbue(m_curPath); lpx = lpy = lpx2 = lpy2 = lpx3 = lpy3 = lcx = lcy = lrx = lry = 0.0; currentTextRenderingMode = ePdfTextRenderingMode_Fill; } PdfPainter::~PdfPainter() { // Throwing exceptions in C++ destructors is not allowed. // Just log the error. // PODOFO_RAISE_LOGIC_IF( m_pCanvas, "FinishPage() has to be called after a page is completed!" ); // Note that we can't do this for the user, since FinishPage() might // throw and we can't safely have that in a dtor. That also means // we can't throw here, but must abort. if( m_pCanvas ) PdfError::LogMessage( eLogSeverity_Error, "PdfPainter::~PdfPainter(): FinishPage() has to be called after a page is completed!" ); assert(!m_pCanvas); } void PdfPainter::SetPage( PdfCanvas* pPage ) { // Ignore setting the same page twice if( m_pPage == pPage ) return; if( m_pCanvas ) m_pCanvas->EndAppend(); m_pPage = pPage; m_pCanvas = pPage ? pPage->GetContentsForAppending()->GetStream() : NULL; if ( m_pCanvas ) { // GetLength() must be called before BeginAppend() if ( m_pCanvas->GetLength() ) { m_pCanvas->BeginAppend( false ); // there is already content here - so let's assume we are appending // as such, we MUST put in a "space" to separate whatever we do. m_pCanvas->Append( " " ); } else m_pCanvas->BeginAppend( false ); currentTextRenderingMode = ePdfTextRenderingMode_Fill; } else { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } } void PdfPainter::FinishPage() { try { if( m_pCanvas ) m_pCanvas->EndAppend(); } catch( const PdfError & e ) { // clean up, even in case of error m_pCanvas = NULL; m_pPage = NULL; throw e; } m_pCanvas = NULL; m_pPage = NULL; currentTextRenderingMode = ePdfTextRenderingMode_Fill; } void PdfPainter::SetStrokingGray( double g ) { PODOFO_RAISE_LOGIC_IF( !m_pCanvas, "Call SetPage() first before doing drawing operations." ); CheckDoubleRange( g, 0.0, 1.0 ); this->SetStrokingColor( PdfColor( g ) ); } void PdfPainter::SetGray( double g ) { PODOFO_RAISE_LOGIC_IF( !m_pCanvas, "Call SetPage() first before doing drawing operations." ); CheckDoubleRange( g, 0.0, 1.0 ); this->SetColor( PdfColor( g ) ); } void PdfPainter::SetStrokingColor( double r, double g, double b ) { PODOFO_RAISE_LOGIC_IF( !m_pCanvas, "Call SetPage() first before doing drawing operations." ); CheckDoubleRange( r, 0.0, 1.0 ); CheckDoubleRange( g, 0.0, 1.0 ); CheckDoubleRange( b, 0.0, 1.0 ); this->SetStrokingColor( PdfColor( r, g, b ) ); } void PdfPainter::SetColor( double r, double g, double b ) { PODOFO_RAISE_LOGIC_IF( !m_pCanvas, "Call SetPage() first before doing drawing operations." ); CheckDoubleRange( r, 0.0, 1.0 ); CheckDoubleRange( g, 0.0, 1.0 ); CheckDoubleRange( b, 0.0, 1.0 ); this->SetColor( PdfColor( r, g, b ) ); } void PdfPainter::SetStrokingColorCMYK( double c, double m, double y, double k ) { PODOFO_RAISE_LOGIC_IF( !m_pCanvas, "Call SetPage() first before doing drawing operations." ); CheckDoubleRange( c, 0.0, 1.0 ); CheckDoubleRange( m, 0.0, 1.0 ); CheckDoubleRange( y, 0.0, 1.0 ); CheckDoubleRange( k, 0.0, 1.0 ); this->SetStrokingColor( PdfColor( c, m, y, k ) ); } void PdfPainter::SetColorCMYK( double c, double m, double y, double k ) { PODOFO_RAISE_LOGIC_IF( !m_pCanvas, "Call SetPage() first before doing drawing operations." ); CheckDoubleRange( c, 0.0, 1.0 ); CheckDoubleRange( m, 0.0, 1.0 ); CheckDoubleRange( y, 0.0, 1.0 ); CheckDoubleRange( k, 0.0, 1.0 ); this->SetColor( PdfColor( c, m, y, k ) ); } void PdfPainter::SetStrokingShadingPattern( const PdfShadingPattern & rPattern ) { PODOFO_RAISE_LOGIC_IF( !m_pCanvas, "Call SetPage() first before doing drawing operations." ); this->AddToPageResources( rPattern.GetIdentifier(), rPattern.GetObject()->Reference(), PdfName("Pattern") ); m_oss.str(""); m_oss << "/Pattern CS /" << rPattern.GetIdentifier().GetName() << " SCN" << std::endl; m_pCanvas->Append( m_oss.str() ); } void PdfPainter::SetShadingPattern( const PdfShadingPattern & rPattern ) { PODOFO_RAISE_LOGIC_IF( !m_pCanvas, "Call SetPage() first before doing drawing operations." ); this->AddToPageResources( rPattern.GetIdentifier(), rPattern.GetObject()->Reference(), PdfName("Pattern") ); m_oss.str(""); m_oss << "/Pattern cs /" << rPattern.GetIdentifier().GetName() << " scn" << std::endl; m_pCanvas->Append( m_oss.str() ); } void PdfPainter::SetStrokingTilingPattern( const PdfTilingPattern & rPattern ) { PODOFO_RAISE_LOGIC_IF( !m_pCanvas, "Call SetPage() first before doing drawing operations." ); this->AddToPageResources( rPattern.GetIdentifier(), rPattern.GetObject()->Reference(), PdfName("Pattern") ); m_oss.str(""); m_oss << "/Pattern CS /" << rPattern.GetIdentifier().GetName() << " SCN" << std::endl; m_pCanvas->Append( m_oss.str() ); } void PdfPainter::SetStrokingTilingPattern( const std::string &rPatternName ) { PODOFO_RAISE_LOGIC_IF( !m_pCanvas, "Call SetPage() first before doing drawing operations." ); m_oss.str(""); m_oss << "/Pattern CS /" << rPatternName << " SCN" << std::endl; m_pCanvas->Append( m_oss.str() ); } void PdfPainter::SetTilingPattern( const PdfTilingPattern & rPattern ) { PODOFO_RAISE_LOGIC_IF( !m_pCanvas, "Call SetPage() first before doing drawing operations." ); this->AddToPageResources( rPattern.GetIdentifier(), rPattern.GetObject()->Reference(), PdfName("Pattern") ); m_oss.str(""); m_oss << "/Pattern cs /" << rPattern.GetIdentifier().GetName() << " scn" << std::endl; m_pCanvas->Append( m_oss.str() ); } void PdfPainter::SetTilingPattern( const std::string &rPatternName ) { PODOFO_RAISE_LOGIC_IF( !m_pCanvas, "Call SetPage() first before doing drawing operations." ); m_oss.str(""); m_oss << "/Pattern cs /" << rPatternName << " scn" << std::endl; m_pCanvas->Append( m_oss.str() ); } void PdfPainter::SetStrokingColor( const PdfColor & rColor ) { PODOFO_RAISE_LOGIC_IF( !m_pCanvas, "Call SetPage() first before doing drawing operations." ); m_oss.str(""); switch( rColor.GetColorSpace() ) { default: case ePdfColorSpace_DeviceRGB: m_oss << rColor.GetRed() << " " << rColor.GetGreen() << " " << rColor.GetBlue() << " RG" << std::endl; break; case ePdfColorSpace_DeviceCMYK: m_oss << rColor.GetCyan() << " " << rColor.GetMagenta() << " " << rColor.GetYellow() << " " << rColor.GetBlack() << " K" << std::endl; break; case ePdfColorSpace_DeviceGray: m_oss << rColor.GetGrayScale() << " G" << std::endl; break; case ePdfColorSpace_Separation: m_pPage->AddColorResource( rColor ); m_oss << "/ColorSpace" << PdfName( rColor.GetName() ).GetEscapedName() << " CS " << rColor.GetDensity() << " SCN" << std::endl; break; case ePdfColorSpace_CieLab: m_pPage->AddColorResource( rColor ); m_oss << "/ColorSpaceCieLab" << " CS " << rColor.GetCieL() << " " << rColor.GetCieA() << " " << rColor.GetCieB() << " SCN" << std::endl; break; case ePdfColorSpace_Unknown: case ePdfColorSpace_Indexed: { PODOFO_RAISE_ERROR( ePdfError_CannotConvertColor ); } } m_pCanvas->Append( m_oss.str() ); } void PdfPainter::SetColor( const PdfColor & rColor ) { PODOFO_RAISE_LOGIC_IF( !m_pCanvas, "Call SetPage() first before doing drawing operations." ); m_oss.str(""); m_curColor = rColor; switch( rColor.GetColorSpace() ) { default: case ePdfColorSpace_DeviceRGB: m_oss << rColor.GetRed() << " " << rColor.GetGreen() << " " << rColor.GetBlue() << " rg" << std::endl; break; case ePdfColorSpace_DeviceCMYK: m_oss << rColor.GetCyan() << " " << rColor.GetMagenta() << " " << rColor.GetYellow() << " " << rColor.GetBlack() << " k" << std::endl; break; case ePdfColorSpace_DeviceGray: m_oss << rColor.GetGrayScale() << " g" << std::endl; break; case ePdfColorSpace_Separation: m_pPage->AddColorResource( rColor ); m_oss << "/ColorSpace" << PdfName( rColor.GetName() ).GetEscapedName() << " cs " << rColor.GetDensity() << " scn" << std::endl; break; case ePdfColorSpace_CieLab: m_pPage->AddColorResource( rColor ); m_oss << "/ColorSpaceCieLab" << " cs " << rColor.GetCieL() << " " << rColor.GetCieA() << " " << rColor.GetCieB() << " scn" << std::endl; break; case ePdfColorSpace_Unknown: case ePdfColorSpace_Indexed: { PODOFO_RAISE_ERROR( ePdfError_CannotConvertColor ); } } m_pCanvas->Append( m_oss.str() ); } void PdfPainter::SetStrokeWidth( double dWidth ) { PODOFO_RAISE_LOGIC_IF( !m_pCanvas, "Call SetPage() first before doing drawing operations." ); m_oss.str(""); m_oss << dWidth << " w" << std::endl; m_pCanvas->Append( m_oss.str() ); } void PdfPainter::SetStrokeStyle( EPdfStrokeStyle eStyle, const char* pszCustom, bool inverted, double scale, bool subtractJoinCap) { bool have = false; PODOFO_RAISE_LOGIC_IF( !m_pCanvas, "Call SetPage() first before doing drawing operations." ); m_oss.str(""); if (eStyle != ePdfStrokeStyle_Custom) { m_oss << "["; } if (inverted && eStyle != ePdfStrokeStyle_Solid && eStyle != ePdfStrokeStyle_Custom) { m_oss << "0 "; } switch( eStyle ) { case ePdfStrokeStyle_Solid: have = true; break; case ePdfStrokeStyle_Dash: have = true; if (scale >= 1.0 - 1e-5 && scale <= 1.0 + 1e-5) { m_oss << "6 2"; } else { if (subtractJoinCap) { m_oss << scale * 2.0 << " " << scale * 2.0; } else { m_oss << scale * 3.0 << " " << scale * 1.0; } } break; case ePdfStrokeStyle_Dot: have = true; if (scale >= 1.0 - 1e-5 && scale <= 1.0 + 1e-5) { m_oss << "2 2"; } else { if (subtractJoinCap) { // zero length segments are drawn anyway here m_oss << 0.001 << " " << 2.0 * scale << " " << 0 << " " << 2.0 * scale; } else { m_oss << scale * 1.0 << " " << scale * 1.0; } } break; case ePdfStrokeStyle_DashDot: have = true; if (scale >= 1.0 - 1e-5 && scale <= 1.0 + 1e-5) { m_oss << "3 2 1 2"; } else { if (subtractJoinCap) { // zero length segments are drawn anyway here m_oss << scale * 2.0 << " " << scale * 2.0 << " " << 0 << " " << scale * 2.0; } else { m_oss << scale * 3.0 << " " << scale * 1.0 << " " << scale * 1.0 << " " << scale * 1.0; } } break; case ePdfStrokeStyle_DashDotDot: have = true; if (scale >= 1.0 - 1e-5 && scale <= 1.0 + 1e-5) { m_oss << "3 1 1 1 1 1"; } else { if (subtractJoinCap) { // zero length segments are drawn anyway here m_oss << scale * 2.0 << " " << scale * 2.0 << " " << 0 << " " << scale * 2.0 << " " << 0 << " " << scale * 2.0; } else { m_oss << scale * 3.0 << " " << scale * 1.0 << " " << scale * 1.0 << " " << scale * 1.0 << " " << scale * 1.0 << " " << scale * 1.0; } } break; case ePdfStrokeStyle_Custom: have = pszCustom != NULL; if (have) m_oss << pszCustom; break; default: { PODOFO_RAISE_ERROR( ePdfError_InvalidStrokeStyle ); } } if( !have ) { PODOFO_RAISE_ERROR( ePdfError_InvalidStrokeStyle ); } if (inverted && eStyle != ePdfStrokeStyle_Solid && eStyle != ePdfStrokeStyle_Custom) { m_oss << " 0"; } if (eStyle != ePdfStrokeStyle_Custom) { m_oss << "] 0"; } m_oss << " d" << std::endl; m_pCanvas->Append( m_oss.str() ); } void PdfPainter::SetLineCapStyle( EPdfLineCapStyle eCapStyle ) { PODOFO_RAISE_LOGIC_IF( !m_pCanvas, "Call SetPage() first before doing drawing operations." ); m_oss.str(""); m_oss << static_cast(eCapStyle) << " J" << std::endl; m_pCanvas->Append( m_oss.str() ); } void PdfPainter::SetLineJoinStyle( EPdfLineJoinStyle eJoinStyle ) { PODOFO_RAISE_LOGIC_IF( !m_pCanvas, "Call SetPage() first before doing drawing operations." ); m_oss.str(""); m_oss << static_cast(eJoinStyle) << " j" << std::endl; m_pCanvas->Append( m_oss.str() ); } void PdfPainter::SetFont( PdfFont* pFont ) { PODOFO_RAISE_LOGIC_IF( !m_pCanvas, "Call SetPage() first before doing drawing operations." ); if( !pFont ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } m_pFont = pFont; } void PdfPainter::SetTextRenderingMode( EPdfTextRenderingMode mode ) { PODOFO_RAISE_LOGIC_IF( !m_pCanvas, "Call SetPage() first before doing drawing operations." ); if (mode == currentTextRenderingMode) { return; } currentTextRenderingMode = mode; if (m_isTextOpen) SetCurrentTextRenderingMode(); } void PdfPainter::SetCurrentTextRenderingMode( void ) { PODOFO_RAISE_LOGIC_IF( !m_pCanvas, "Call SetPage() first before doing drawing operations." ); m_oss << (int) currentTextRenderingMode << " Tr" << std::endl; } void PdfPainter::SetClipRect( double dX, double dY, double dWidth, double dHeight ) { PODOFO_RAISE_LOGIC_IF( !m_pCanvas, "Call SetPage() first before doing drawing operations." ); m_oss.str(""); m_oss << dX << " " << dY << " " << dWidth << " " << dHeight << " re W n" << std::endl; m_pCanvas->Append( m_oss.str() ); m_curPath << dX << " " << dY << " " << dWidth << " " << dHeight << " re W n" << std::endl; } void PdfPainter::SetMiterLimit(double value) { PODOFO_RAISE_LOGIC_IF( !m_pCanvas, "Call SetPage() first before doing drawing operations." ); m_oss.str(""); m_oss << value << " M" << std::endl; m_pCanvas->Append( m_oss.str() ); } void PdfPainter::DrawLine( double dStartX, double dStartY, double dEndX, double dEndY ) { PODOFO_RAISE_LOGIC_IF( !m_pCanvas, "Call SetPage() first before doing drawing operations." ); m_curPath.str(""); m_curPath << dStartX << " " << dStartY << " m " << dEndX << " " << dEndY << " l" << std::endl; m_oss.str(""); m_oss << dStartX << " " << dStartY << " m " << dEndX << " " << dEndY << " l S" << std::endl; m_pCanvas->Append( m_oss.str() ); } void PdfPainter::Rectangle( double dX, double dY, double dWidth, double dHeight, double dRoundX, double dRoundY ) { PODOFO_RAISE_LOGIC_IF( !m_pCanvas, "Call SetPage() first before doing drawing operations." ); if ( static_cast(dRoundX) || static_cast(dRoundY) ) { double x = dX, y = dY, w = dWidth, h = dHeight, rx= dRoundX, ry = dRoundY; double b = 0.4477f; MoveTo(x + rx, y); LineTo(x + w - rx, y); CubicBezierTo(x + w - rx * b, y, x + w, y + ry * b, x + w, y + ry); LineTo(x + w, y + h - ry); CubicBezierTo(x + w, y + h - ry * b, x + w - rx * b, y + h, x + w - rx, y + h); LineTo(x + rx, y + h); CubicBezierTo(x + rx * b, y + h, x, y + h - ry * b, x, y + h - ry); LineTo(x, y + ry); CubicBezierTo(x, y + ry * b, x + rx * b, y, x + rx, y); } else { m_curPath << dX << " " << dY << " " << dWidth << " " << dHeight << " re" << std::endl; m_oss.str(""); m_oss << dX << " " << dY << " " << dWidth << " " << dHeight << " re" << std::endl; m_pCanvas->Append( m_oss.str() ); } } void PdfPainter::Ellipse( double dX, double dY, double dWidth, double dHeight ) { double dPointX[BEZIER_POINTS]; double dPointY[BEZIER_POINTS]; int i; PODOFO_RAISE_LOGIC_IF( !m_pCanvas, "Call SetPage() first before doing drawing operations." ); ConvertRectToBezier( dX, dY, dWidth, dHeight, dPointX, dPointY ); m_curPath << dPointX[0] << " " << dPointY[0] << " m" << std::endl; m_oss.str(""); m_oss << dPointX[0] << " " << dPointY[0] << " m" << std::endl; for( i=1;iAppend( m_oss.str() ); } void PdfPainter::Circle( double dX, double dY, double dRadius ) { if( !m_pCanvas ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } /* draw four Bezier curves to approximate a circle */ MoveTo( dX + dRadius, dY ); CubicBezierTo( dX + dRadius, dY + dRadius*ARC_MAGIC, dX + dRadius*ARC_MAGIC, dY + dRadius, dX, dY + dRadius ); CubicBezierTo( dX - dRadius*ARC_MAGIC, dY + dRadius, dX - dRadius, dY + dRadius*ARC_MAGIC, dX - dRadius, dY ); CubicBezierTo( dX - dRadius, dY - dRadius*ARC_MAGIC, dX - dRadius*ARC_MAGIC, dY - dRadius, dX, dY - dRadius ); CubicBezierTo( dX + dRadius*ARC_MAGIC, dY - dRadius, dX + dRadius, dY - dRadius*ARC_MAGIC, dX + dRadius, dY ); Close(); } void PdfPainter::DrawText( double dX, double dY, const PdfString & sText ) { this->DrawText( dX, dY, sText, static_cast(sText.GetCharacterLength()) ); } void PdfPainter::DrawText( double dX, double dY, const PdfString & sText, long lStringLen ) { PODOFO_RAISE_LOGIC_IF( !m_pCanvas, "Call SetPage() first before doing drawing operations." ); if( !m_pFont || !m_pPage || !sText.IsValid() ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } // Peter Petrov 25 September 2008 //m_pFont->EmbedFont(); PdfString sString = this->ExpandTabs( sText, lStringLen ); this->AddToPageResources( m_pFont->GetIdentifier(), m_pFont->GetObject()->Reference(), PdfName("Font") ); if( m_pFont->IsSubsetting() ) { m_pFont->AddUsedSubsettingGlyphs( sText, lStringLen ); } if( m_pFont->IsUnderlined() || m_pFont->IsStrikeOut()) { this->Save(); this->SetCurrentStrokingColor(); // Draw underline this->SetStrokeWidth( m_pFont->GetFontMetrics()->GetUnderlineThickness() ); if( m_pFont->IsUnderlined() ) { if (sString.IsUnicode()) this->DrawLine( dX, dY + m_pFont->GetFontMetrics()->GetUnderlinePosition(), dX + m_pFont->GetFontMetrics()->StringWidth( sString.GetUnicode() ), dY + m_pFont->GetFontMetrics()->GetUnderlinePosition() ); else this->DrawLine( dX, dY + m_pFont->GetFontMetrics()->GetUnderlinePosition(), dX + m_pFont->GetFontMetrics()->StringWidth( sString.GetString() ), dY + m_pFont->GetFontMetrics()->GetUnderlinePosition() ); } // Draw strikeout this->SetStrokeWidth( m_pFont->GetFontMetrics()->GetStrikeoutThickness() ); if( m_pFont->IsStrikeOut() ) { if (sString.IsUnicode()) this->DrawLine( dX, dY + m_pFont->GetFontMetrics()->GetStrikeOutPosition(), dX + m_pFont->GetFontMetrics()->StringWidth( sString.GetUnicode() ), dY + m_pFont->GetFontMetrics()->GetStrikeOutPosition() ); else this->DrawLine( dX, dY + m_pFont->GetFontMetrics()->GetStrikeOutPosition(), dX + m_pFont->GetFontMetrics()->StringWidth( sString.GetString() ), dY + m_pFont->GetFontMetrics()->GetStrikeOutPosition() ); } this->Restore(); } m_oss.str(""); m_oss << "BT" << std::endl << "/" << m_pFont->GetIdentifier().GetName() << " " << m_pFont->GetFontSize() << " Tf" << std::endl; if (currentTextRenderingMode != ePdfTextRenderingMode_Fill) { SetCurrentTextRenderingMode(); } //if( m_pFont->GetFontScale() != 100.0F ) - this value is kept between text blocks m_oss << m_pFont->GetFontScale() << " Tz" << std::endl; //if( m_pFont->GetFontCharSpace() != 0.0F ) - this value is kept between text blocks m_oss << m_pFont->GetFontCharSpace() * m_pFont->GetFontSize() / 100.0 << " Tc" << std::endl; m_oss << dX << std::endl << dY << std::endl << "Td "; m_pCanvas->Append( m_oss.str() ); m_pFont->WriteStringToStream( sString, m_pCanvas ); /* char* pBuffer; std::auto_ptr pFilter = PdfFilterFactory::Create( ePdfFilter_ASCIIHexDecode ); pFilter->Encode( sString.GetString(), sString.GetLength(), &pBuffer, &lLen ); m_pCanvas->Append( pBuffer, lLen ); free( pBuffer ); */ m_pCanvas->Append( " Tj\nET\n" ); } void PdfPainter::BeginText( double dX, double dY ) { PODOFO_RAISE_LOGIC_IF( !m_pCanvas, "Call SetPage() first before doing drawing operations." ); if( !m_pFont || !m_pPage || m_isTextOpen) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } this->AddToPageResources( m_pFont->GetIdentifier(), m_pFont->GetObject()->Reference(), PdfName("Font") ); m_oss.str(""); m_oss << "BT" << std::endl << "/" << m_pFont->GetIdentifier().GetName() << " " << m_pFont->GetFontSize() << " Tf" << std::endl; if (currentTextRenderingMode != ePdfTextRenderingMode_Fill) { SetCurrentTextRenderingMode(); } //if( m_pFont->GetFontScale() != 100.0F ) - this value is kept between text blocks m_oss << m_pFont->GetFontScale() << " Tz" << std::endl; //if( m_pFont->GetFontCharSpace() != 0.0F ) - this value is kept between text blocks m_oss << m_pFont->GetFontCharSpace() * m_pFont->GetFontSize() / 100.0 << " Tc" << std::endl; m_oss << dX << " " << dY << " Td" << std::endl ; m_pCanvas->Append( m_oss.str() ); m_isTextOpen = true; } void PdfPainter::MoveTextPos( double dX, double dY ) { PODOFO_RAISE_LOGIC_IF( !m_pCanvas, "Call SetPage() first before doing drawing operations." ); if( !m_pFont || !m_pPage || !m_isTextOpen ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } m_oss.str(""); m_oss << dX << " " << dY << " Td" << std::endl ; m_pCanvas->Append( m_oss.str() ); } void PdfPainter::AddText( const PdfString & sText ) { AddText( sText, sText.GetCharacterLength() ); } void PdfPainter::AddText( const PdfString & sText, pdf_long lStringLen ) { PODOFO_RAISE_LOGIC_IF( !m_pCanvas, "Call SetPage() first before doing drawing operations." ); if( !m_pFont || !m_pPage || !sText.IsValid() || !m_isTextOpen ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } PdfString sString = this->ExpandTabs( sText, lStringLen ); if( m_pFont->IsSubsetting() ) { m_pFont->AddUsedSubsettingGlyphs( sText, lStringLen ); } // TODO: Underline and Strikeout not yet supported m_pFont->WriteStringToStream( sString, m_pCanvas ); m_pCanvas->Append( " Tj\n" ); } void PdfPainter::EndText() { PODOFO_RAISE_LOGIC_IF( !m_pCanvas, "Call SetPage() first before doing drawing operations." ); if( !m_pFont || !m_pPage || !m_isTextOpen ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } m_pCanvas->Append( "ET\n" ); m_isTextOpen = false; } void PdfPainter::DrawMultiLineText( double dX, double dY, double dWidth, double dHeight, const PdfString & rsText, EPdfAlignment eAlignment, EPdfVerticalAlignment eVertical, bool bClip ) { PODOFO_RAISE_LOGIC_IF( !m_pCanvas, "Call SetPage() first before doing drawing operations." ); if( !m_pFont || !m_pPage || !rsText.IsValid() ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } // Peter Petrov 25 September 2008 //m_pFont->EmbedFont(); if( dWidth <= 0.0 || dHeight <= 0.0 ) // nonsense arguments return; this->Save(); if( bClip ) { this->SetClipRect( dX, dY, dWidth, dHeight ); } PdfString sString = this->ExpandTabs( rsText, rsText.GetCharacterLength() ); std::vector vecLines = GetMultiLineTextAsLines(dWidth, sString); // Do vertical alignment switch( eVertical ) { default: case ePdfVerticalAlignment_Top: dY += dHeight; break; case ePdfVerticalAlignment_Bottom: dY += m_pFont->GetFontMetrics()->GetLineSpacing() * vecLines.size(); break; case ePdfVerticalAlignment_Center: dY += (dHeight - ((dHeight - (m_pFont->GetFontMetrics()->GetLineSpacing() * vecLines.size()))/2.0)); break; } std::vector::const_iterator it = vecLines.begin(); while( it != vecLines.end() ) { dY -= m_pFont->GetFontMetrics()->GetLineSpacing(); if( (*it).GetCharacterLength() ) this->DrawTextAligned( dX, dY, dWidth, *it, eAlignment ); ++it; } this->Restore(); } std::vector PdfPainter::GetMultiLineTextAsLines( double dWidth, const PdfString & rsText) { PODOFO_RAISE_LOGIC_IF( !m_pCanvas, "Call SetPage() first before doing drawing operations." ); if( !m_pFont || !m_pPage || !rsText.IsValid() ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } if( dWidth <= 0.0 ) // nonsense arguments return std::vector(); if( rsText.GetCharacterLength() == 0 ) // empty string return std::vector(1, rsText); // We will work with utf16 encoded string because it allows us // fast and easy individual characters access const std::string& stringUtf8 = rsText.GetStringUtf8(); std::vector stringUtf16(stringUtf8.length() + 1, 0); assert(stringUtf16.size() > 0); const pdf_long converted = PdfString::ConvertUTF8toUTF16( reinterpret_cast(stringUtf8.c_str()), &stringUtf16[0], stringUtf16.size()); //const pdf_long len = rsText.GetCharacterLength(); assert( converted == (rsText.GetCharacterLength() + 1) ); const pdf_utf16be* const stringUtf16Begin = &stringUtf16[0]; const pdf_utf16be* pszLineBegin = stringUtf16Begin; const pdf_utf16be* pszCurrentCharacter = stringUtf16Begin; const pdf_utf16be* pszStartOfCurrentWord = stringUtf16Begin; bool startOfWord = true; double dCurWidthOfLine = 0.0; std::vector vecLines; // do simple word wrapping while( *pszCurrentCharacter ) { if( IsNewLineChar( *pszCurrentCharacter ) ) // hard-break! { vecLines.push_back( PdfString( pszLineBegin, pszCurrentCharacter - pszLineBegin ) ); ++pszCurrentCharacter; // skip the line feed pszLineBegin = pszCurrentCharacter; startOfWord = true; dCurWidthOfLine = 0.0; } else if( IsSpaceChar( *pszCurrentCharacter ) ) { if( dCurWidthOfLine > dWidth ) { // The previous word does not fit in the current line. // -> Move it to the next one. vecLines.push_back( PdfString( pszLineBegin, pszStartOfCurrentWord - pszLineBegin ) ); pszLineBegin = pszStartOfCurrentWord; if (!startOfWord) { dCurWidthOfLine = m_pFont->GetFontMetrics()->StringWidth( pszStartOfCurrentWord, pszCurrentCharacter - pszStartOfCurrentWord ); } else { dCurWidthOfLine = 0.0; } } else { dCurWidthOfLine += m_pFont->GetFontMetrics()->UnicodeCharWidth( SwapCharBytesIfRequired( *pszCurrentCharacter ) ); } startOfWord = true; } else { if (startOfWord) { pszStartOfCurrentWord = pszCurrentCharacter; startOfWord = false; } //else do nothing if ((dCurWidthOfLine + m_pFont->GetFontMetrics()->UnicodeCharWidth( SwapCharBytesIfRequired( *pszCurrentCharacter ))) > dWidth) { if ( pszLineBegin == pszStartOfCurrentWord ) { // This word takes up the whole line. // Put as much as possible on this line. vecLines.push_back( PdfString( pszLineBegin, pszCurrentCharacter - pszLineBegin ) ); pszLineBegin = pszCurrentCharacter; pszStartOfCurrentWord = pszCurrentCharacter; dCurWidthOfLine = m_pFont->GetFontMetrics()->UnicodeCharWidth( SwapCharBytesIfRequired( *pszCurrentCharacter ) ); } else { // The current word does not fit in the current line. // -> Move it to the next one. vecLines.push_back( PdfString( pszLineBegin, pszStartOfCurrentWord - pszLineBegin ) ); pszLineBegin = pszStartOfCurrentWord; dCurWidthOfLine = m_pFont->GetFontMetrics()->StringWidth( pszStartOfCurrentWord, (pszCurrentCharacter-pszStartOfCurrentWord) + 1 ); } } else { dCurWidthOfLine += m_pFont->GetFontMetrics()->UnicodeCharWidth( SwapCharBytesIfRequired( *pszCurrentCharacter ) ); } } ++pszCurrentCharacter; } if( (pszCurrentCharacter - pszLineBegin) > 0 ) { if( dCurWidthOfLine > dWidth ) { // The previous word does not fit in the current line. // -> Move it to the next one. vecLines.push_back( PdfString( pszLineBegin, pszStartOfCurrentWord - pszLineBegin) ); pszLineBegin = pszStartOfCurrentWord; } //else do nothing if( pszCurrentCharacter - pszLineBegin > 0 ) { vecLines.push_back( PdfString( pszLineBegin, pszCurrentCharacter - pszLineBegin) ); } //else do nothing } return vecLines; } void PdfPainter::DrawTextAligned( double dX, double dY, double dWidth, const PdfString & rsText, EPdfAlignment eAlignment ) { PODOFO_RAISE_LOGIC_IF( !m_pCanvas, "Call SetPage() first before doing drawing operations." ); if( !m_pFont || !m_pPage || !rsText.IsValid() ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } // Peter Petrov 25 Septemer 2008 //m_pFont->EmbedFont(); if( dWidth <= 0.0 ) // nonsense arguments return; switch( eAlignment ) { default: case ePdfAlignment_Left: break; case ePdfAlignment_Center: dX += (dWidth - m_pFont->GetFontMetrics()->StringWidth( rsText ) ) / 2.0; break; case ePdfAlignment_Right: dX += (dWidth - m_pFont->GetFontMetrics()->StringWidth( rsText ) ); break; } this->DrawText( dX, dY, rsText ); } void PdfPainter::DrawGlyph( PdfMemDocument* pDocument, double dX, double dY, const char* pszGlyphname) { PODOFO_RAISE_LOGIC_IF( !m_pCanvas, "Call SetPage() first before doing drawing operations." ); if( !m_pFont || !m_pPage || !pszGlyphname ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } // search for a copy of this font to enter difference-encoding, create a new one if not found PdfFont* pGlyphFont = pDocument->CreateDuplicateFontType1( m_pFont, "Glyph1" ); // select identical sizes pGlyphFont->SetFontSize( m_pFont->GetFontSize() ); pGlyphFont->SetFontCharSpace( m_pFont->GetFontCharSpace() ); pGlyphFont->SetFontScale( m_pFont->GetFontScale() ); PdfObject* pGlyphFontObj = pGlyphFont->GetObject(); // get width of glyph int width = static_cast(pGlyphFont->GetFontMetrics()->GetGlyphWidth( pszGlyphname ) ); // change encoding to difference-encoding and adapt width PdfObject* pEncoding = pGlyphFontObj->GetDictionary().GetKey( "Encoding" ); int code = 32; if ( pEncoding == NULL || pEncoding->IsReference() == false ) { // first time: create difference-encoding as reference, enter glyph pEncoding = pDocument->GetObjects().CreateObject( "Encoding" ); code++; PdfArray diffs; diffs.push_back( PdfVariant( static_cast( code ) ) ); diffs.push_back( PdfName( pszGlyphname ) ); pEncoding->GetDictionary().AddKey( "Differences", diffs ); pGlyphFontObj->GetDictionary().AddKey("Encoding", pEncoding->Reference() ); // clear Widths-array and enter width of this glyph PdfObject* pWidthObj = pGlyphFontObj->GetIndirectKey( "Widths" ); PdfArray & rWidthArr = pWidthObj->GetArray(); for ( unsigned int i = 0; i < rWidthArr.size(); i++ ) { rWidthArr[i] = PdfVariant( static_cast( 0 ) ); } rWidthArr[code] = PdfVariant( static_cast( width ) ); } else { // search glyph in existing Encoding/Difference, create if not found pEncoding = pDocument->GetObjects().GetObject( pEncoding->GetReference() ); PODOFO_ASSERT( pEncoding != NULL ); // paranoia PdfArray diffs; diffs = pEncoding->GetDictionary().GetKey( "Differences" )->GetArray(); bool foundIt = false; TCIVariantList it = diffs.begin(); while( it != diffs.end() ) { if( (*it).GetDataType() == ePdfDataType_Name ) { code++; if ( (*it).GetName().GetName() == pszGlyphname ) { foundIt = true; break; } } ++it; } // TODO: if code exceeds 255, create a new font-copy and start again with code 33 PODOFO_ASSERT( code <= 255 ); if ( foundIt == false ) { code++; diffs.push_back( PdfName( pszGlyphname ) ); pEncoding->GetDictionary().AddKey( "Differences", diffs ); // enter width of glyph PdfObject* pWidthObj = pGlyphFontObj->GetIndirectKey( "Widths" ); PdfArray & rWidthArr = pWidthObj->GetArray(); rWidthArr[code] = PdfVariant( static_cast( width ) ); } } // mark glyph as used in basefont (needed for subsetting) m_pFont->AddUsedGlyphname( pszGlyphname ); // output SetFont( pGlyphFont ); char temp[2]; temp[0] = code; temp[1] = '\0'; DrawText( dX, dY, PdfString( temp ) ); SetFont( m_pFont ); } void PdfPainter::DrawImage( double dX, double dY, PdfImage* pObject, double dScaleX, double dScaleY ) { this->DrawXObject( dX, dY, reinterpret_cast(pObject), dScaleX * pObject->GetPageSize().GetWidth(), dScaleY * pObject->GetPageSize().GetHeight() ); } void PdfPainter::DrawXObject( double dX, double dY, PdfXObject* pObject, double dScaleX, double dScaleY ) { PODOFO_RAISE_LOGIC_IF( !m_pCanvas, "Call SetPage() first before doing drawing operations." ); if( !pObject ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } // use OriginalReference() as the XObject might have been written to disk // already and is not in memory anymore in this case. this->AddToPageResources( pObject->GetIdentifier(), pObject->GetObjectReference(), "XObject" ); std::streamsize oldPrecision = m_oss.precision(clPainterHighPrecision); m_oss.str(""); m_oss << "q" << std::endl << dScaleX << " 0 0 " << dScaleY << " " << dX << " " << dY << " cm" << std::endl << "/" << pObject->GetIdentifier().GetName() << " Do" << std::endl << "Q" << std::endl; m_oss.precision(oldPrecision); m_pCanvas->Append( m_oss.str() ); } void PdfPainter::ClosePath() { PODOFO_RAISE_LOGIC_IF( !m_pCanvas, "Call SetPage() first before doing drawing operations." ); m_curPath << "h" << std::endl; m_pCanvas->Append( "h\n" ); } void PdfPainter::LineTo( double dX, double dY ) { PODOFO_RAISE_LOGIC_IF( !m_pCanvas, "Call SetPage() first before doing drawing operations." ); m_curPath << dX << " " << dY << " l" << std::endl; m_oss.str(""); m_oss << dX << " " << dY << " l" << std::endl; m_pCanvas->Append( m_oss.str() ); } void PdfPainter::MoveTo( double dX, double dY ) { PODOFO_RAISE_LOGIC_IF( !m_pCanvas, "Call SetPage() first before doing drawing operations." ); m_curPath << dX << " " << dY << " m" << std::endl; m_oss.str(""); m_oss << dX << " " << dY << " m" << std::endl; m_pCanvas->Append( m_oss.str() ); } void PdfPainter::CubicBezierTo( double dX1, double dY1, double dX2, double dY2, double dX3, double dY3 ) { PODOFO_RAISE_LOGIC_IF( !m_pCanvas, "Call SetPage() first before doing drawing operations." ); m_curPath << dX1 << " " << dY1 << " " << dX2 << " " << dY2 << " " << dX3 << " " << dY3 << " c" << std::endl; m_oss.str(""); m_oss << dX1 << " " << dY1 << " " << dX2 << " " << dY2 << " " << dX3 << " " << dY3 << " c" << std::endl; m_pCanvas->Append( m_oss.str() ); } void PdfPainter::HorizontalLineTo( double inX ) { LineTo( inX, lpy3 ); } void PdfPainter::VerticalLineTo( double inY ) { LineTo( lpx3, inY ); } void PdfPainter::SmoothCurveTo( double inX2, double inY2, double inX3, double inY3 ) { double px, py, px2 = inX2, py2 = inY2, px3 = inX3, py3 = inY3; // compute the reflective points (thanks Raph!) px = 2 * lcx - lrx; py = 2 * lcy - lry; lpx = px; lpy = py; lpx2 = px2; lpy2 = py2; lpx3 = px3; lpy3 = py3; lcx = px3; lcy = py3; lrx = px2; lry = py2; // thanks Raph! CubicBezierTo( px, py, px2, py2, px3, py3 ); } void PdfPainter::QuadCurveTo( double inX1, double inY1, double inX3, double inY3 ) { double px = inX1, py = inY1, px2, py2, px3 = inX3, py3 = inY3; /* raise quadratic bezier to cubic - thanks Raph! http://www.icce.rug.nl/erikjan/bluefuzz/beziers/beziers/beziers.html */ px = (lcx + 2 * px) * (1.0 / 3.0); py = (lcy + 2 * py) * (1.0 / 3.0); px2 = (px3 + 2 * px) * (1.0 / 3.0); py2 = (py3 + 2 * py) * (1.0 / 3.0); lpx = px; lpy = py; lpx2 = px2; lpy2 = py2; lpx3 = px3; lpy3 = py3; lcx = px3; lcy = py3; lrx = px2; lry = py2; // thanks Raph! CubicBezierTo( px, py, px2, py2, px3, py3 ); } void PdfPainter::SmoothQuadCurveTo( double inX3, double inY3 ) { double px, py, px2, py2, px3 = inX3, py3 = inY3; double xc, yc; /* quadratic control point */ xc = 2 * lcx - lrx; yc = 2 * lcy - lry; /* generate a quadratic bezier with control point = xc, yc */ px = (lcx + 2 * xc) * (1.0 / 3.0); py = (lcy + 2 * yc) * (1.0 / 3.0); px2 = (px3 + 2 * xc) * (1.0 / 3.0); py2 = (py3 + 2 * yc) * (1.0 / 3.0); lpx = px; lpy = py; lpx2 = px2; lpy2 = py2; lpx3 = px3; lpy3 = py3; lcx = px3; lcy = py3; lrx = xc; lry = yc; // thanks Raph! CubicBezierTo( px, py, px2, py2, px3, py3 ); } void PdfPainter::ArcTo( double inX, double inY, double inRadiusX, double inRadiusY, double inRotation, bool inLarge, bool inSweep) { double px = inX, py = inY; double rx = inRadiusX, ry = inRadiusY, rot = inRotation; int large = ( inLarge ? 1 : 0 ), sweep = ( inSweep ? 1 : 0 ); double sin_th, cos_th; double a00, a01, a10, a11; double x0, y0, x1, y1, xc, yc; double d, sfactor, sfactor_sq; double th0, th1, th_arc; int i, n_segs; sin_th = sin (rot * (PI / 180.0)); cos_th = cos (rot * (PI / 180.0)); a00 = cos_th / rx; a01 = sin_th / rx; a10 = -sin_th / ry; a11 = cos_th / ry; x0 = a00 * lcx + a01 * lcy; y0 = a10 * lcx + a11 * lcy; x1 = a00 * px + a01 * py; y1 = a10 * px + a11 * py; /* (x0, y0) is current point in transformed coordinate space. (x1, y1) is new point in transformed coordinate space. The arc fits a unit-radius circle in this space. */ d = (x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0); sfactor_sq = 1.0 / d - 0.25; if (sfactor_sq < 0) sfactor_sq = 0; sfactor = sqrt (sfactor_sq); if (sweep == large) sfactor = -sfactor; xc = 0.5 * (x0 + x1) - sfactor * (y1 - y0); yc = 0.5 * (y0 + y1) + sfactor * (x1 - x0); /* (xc, yc) is center of the circle. */ th0 = atan2 (y0 - yc, x0 - xc); th1 = atan2 (y1 - yc, x1 - xc); th_arc = th1 - th0; if (th_arc < 0 && sweep) th_arc += 2 * PI; else if (th_arc > 0 && !sweep) th_arc -= 2 * PI; n_segs = static_cast(ceil (fabs (th_arc / (PI * 0.5 + 0.001)))); for (i = 0; i < n_segs; i++) { double nth0 = th0 + static_cast(i) * th_arc / n_segs, nth1 = th0 + static_cast(i + 1) * th_arc / n_segs; double nsin_th = 0.0, ncos_th = 0.0; double na00 = 0.0, na01 = 0.0, na10 = 0.0, na11 = 0.0; double nx1 = 0.0, ny1 = 0.0, nx2 = 0.0, ny2 = 0.0, nx3 = 0.0, ny3 = 0.0; double t = 0.0; double th_half = 0.0; nsin_th = sin (rot * (PI / 180.0)); ncos_th = cos (rot * (PI / 180.0)); /* inverse transform compared with rsvg_path_arc */ na00 = ncos_th * rx; na01 = -nsin_th * ry; na10 = nsin_th * rx; na11 = ncos_th * ry; th_half = 0.5 * (nth1 - nth0); t = (8.0 / 3.0) * sin (th_half * 0.5) * sin (th_half * 0.5) / sin (th_half); nx1 = xc + cos (nth0) - t * sin (nth0); ny1 = yc + sin (nth0) + t * cos (nth0); nx3 = xc + cos (nth1); ny3 = yc + sin (nth1); nx2 = nx3 + t * sin (nth1); ny2 = ny3 - t * cos (nth1); nx1 = na00 * nx1 + na01 * ny1; ny1 = na10 * nx1 + na11 * ny1; nx2 = na00 * nx2 + na01 * ny2; ny2 = na10 * nx2 + na11 * ny2; nx3 = na00 * nx3 + na01 * ny3; ny3 = na10 * nx3 + na11 * ny3; CubicBezierTo( nx1, ny1, nx2, ny2, nx3, ny3 ); } lpx = lpx2 = lpx3 = px; lpy = lpy2 = lpy3 = py; lcx = px; lcy = py; lrx = px; lry = py; // thanks Raph! } // Peter Petrov 5 January 2009 was delivered from libHaru bool PdfPainter::Arc(double dX, double dY, double dRadius, double dAngle1, double dAngle2) { bool cont_flg = false; bool ret = true; if (dAngle1 >= dAngle2 || (dAngle2 - dAngle1) >= 360.0f) return false; while (dAngle1 < 0.0f || dAngle2 < 0.0f) { dAngle1 = dAngle1 + 360.0f; dAngle2 = dAngle2 + 360.0f; } for (;;) { if (dAngle2 - dAngle1 <= 90.0f) return InternalArc (dX, dY, dRadius, dAngle1, dAngle2, cont_flg); else { double tmp_ang = dAngle1 + 90.0f; ret = InternalArc (dX, dY, dRadius, dAngle1, tmp_ang, cont_flg); if (!ret) return ret; dAngle1 = tmp_ang; } if (dAngle1 >= dAngle2) break; cont_flg = true; } return true; } bool PdfPainter::InternalArc( double x, double y, double ray, double ang1, double ang2, bool cont_flg) { bool ret = true; double rx0, ry0, rx1, ry1, rx2, ry2, rx3, ry3; double x0, y0, x1, y1, x2, y2, x3, y3; double delta_angle = (90.0f - static_cast(ang1 + ang2) / 2.0f) / 180.0f * PI; double new_angle = static_cast(ang2 - ang1) / 2.0f / 180.0f * PI; rx0 = ray * cos (new_angle); ry0 = ray * sin (new_angle); rx2 = (ray * 4.0f - rx0) / 3.0f; ry2 = ((ray * 1.0f - rx0) * (rx0 - ray * 3.0f)) / (3.0 * ry0); rx1 = rx2; ry1 = -ry2; rx3 = rx0; ry3 = -ry0; x0 = rx0 * cos (delta_angle) - ry0 * sin (delta_angle) + x; y0 = rx0 * sin (delta_angle) + ry0 * cos (delta_angle) + y; x1 = rx1 * cos (delta_angle) - ry1 * sin (delta_angle) + x; y1 = rx1 * sin (delta_angle) + ry1 * cos (delta_angle) + y; x2 = rx2 * cos (delta_angle) - ry2 * sin (delta_angle) + x; y2 = rx2 * sin (delta_angle) + ry2 * cos (delta_angle) + y; x3 = rx3 * cos (delta_angle) - ry3 * sin (delta_angle) + x; y3 = rx3 * sin (delta_angle) + ry3 * cos (delta_angle) + y; if (!cont_flg) { MoveTo(x0,y0); } CubicBezierTo( x1, y1, x2, y2, x3, y3 ); //attr->cur_pos.x = (HPDF_REAL)x3; //attr->cur_pos.y = (HPDF_REAL)y3; lcx = x3; lcy = y3; lpx = lpx2 = lpx3 = x3; lpy = lpy2 = lpy3 = y3; lcx = x3; lcy = y3; lrx = x3; lry = y3; return ret; } void PdfPainter::Close() { PODOFO_RAISE_LOGIC_IF( !m_pCanvas, "Call SetPage() first before doing drawing operations." ); m_curPath << "h" << std::endl; m_pCanvas->Append( "h\n" ); } void PdfPainter::Stroke() { PODOFO_RAISE_LOGIC_IF( !m_pCanvas, "Call SetPage() first before doing drawing operations." ); m_curPath.str(""); m_pCanvas->Append( "S\n" ); } void PdfPainter::Fill(bool useEvenOddRule) { PODOFO_RAISE_LOGIC_IF( !m_pCanvas, "Call SetPage() first before doing drawing operations." ); m_curPath.str(""); if (useEvenOddRule) m_pCanvas->Append( "f*\n" ); else m_pCanvas->Append( "f\n" ); } void PdfPainter::FillAndStroke(bool useEvenOddRule) { PODOFO_RAISE_LOGIC_IF( !m_pCanvas, "Call SetPage() first before doing drawing operations." ); m_curPath.str(""); if (useEvenOddRule) m_pCanvas->Append( "B*\n" ); else m_pCanvas->Append( "B\n" ); } void PdfPainter::Clip( bool useEvenOddRule ) { PODOFO_RAISE_LOGIC_IF( !m_pCanvas, "Call SetPage() first before doing drawing operations." ); if ( useEvenOddRule ) m_pCanvas->Append( "W* n\n" ); else m_pCanvas->Append( "W n\n" ); } void PdfPainter::EndPath(void) { PODOFO_RAISE_LOGIC_IF( !m_pCanvas, "Call SetPage() first before doing drawing operations." ); m_curPath << "n" << std::endl; m_pCanvas->Append( "n\n" ); } void PdfPainter::Save() { PODOFO_RAISE_LOGIC_IF( !m_pCanvas, "Call SetPage() first before doing drawing operations." ); m_pCanvas->Append( "q\n" ); } void PdfPainter::Restore() { PODOFO_RAISE_LOGIC_IF( !m_pCanvas, "Call SetPage() first before doing drawing operations." ); m_pCanvas->Append( "Q\n" ); } void PdfPainter::AddToPageResources( const PdfName & rIdentifier, const PdfReference & rRef, const PdfName & rName ) { if( !m_pPage ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } m_pPage->AddResource( rIdentifier, rRef, rName ); } void PdfPainter::ConvertRectToBezier( double dX, double dY, double dWidth, double dHeight, double pdPointX[], double pdPointY[] ) { // this function is based on code from: // http://www.codeguru.com/Cpp/G-M/gdi/article.php/c131/ // (Llew Goodstadt) // MAGICAL CONSTANT to map ellipse to beziers // 2/3*(sqrt(2)-1) const double dConvert = 0.2761423749154; double dOffX = dWidth * dConvert; double dOffY = dHeight * dConvert; double dCenterX = dX + (dWidth / 2.0); double dCenterY = dY + (dHeight / 2.0); pdPointX[0] = //------------------------// pdPointX[1] = // // pdPointX[11] = // 2___3___4 // pdPointX[12] = dX; // 1 5 // pdPointX[5] = // | | // pdPointX[6] = // | | // pdPointX[7] = dX + dWidth; // 0,12 6 // pdPointX[2] = // | | // pdPointX[10] = dCenterX - dOffX; // | | // pdPointX[4] = // 11 7 // pdPointX[8] = dCenterX + dOffX; // 10___9___8 // pdPointX[3] = // // pdPointX[9] = dCenterX; //------------------------// pdPointY[2] = pdPointY[3] = pdPointY[4] = dY; pdPointY[8] = pdPointY[9] = pdPointY[10] = dY + dHeight; pdPointY[7] = pdPointY[11] = dCenterY + dOffY; pdPointY[1] = pdPointY[5] = dCenterY - dOffY; pdPointY[0] = pdPointY[12] = pdPointY[6] = dCenterY; } void PdfPainter::SetCurrentStrokingColor() { SetStrokingColor( m_curColor ); } void PdfPainter::SetTransformationMatrix( double a, double b, double c, double d, double e, double f ) { PODOFO_RAISE_LOGIC_IF( !m_pCanvas, "Call SetPage() first before doing drawing operations." ); // Need more precision for transformation-matrix !! std::streamsize oldPrecision = m_oss.precision(clPainterHighPrecision); m_oss.str(""); m_oss << a << " " << b << " " << c << " " << d << " " << e << " " << f << " cm" << std::endl; m_oss.precision(oldPrecision); m_pCanvas->Append( m_oss.str() ); } void PdfPainter::SetExtGState( PdfExtGState* inGState ) { PODOFO_RAISE_LOGIC_IF( !m_pCanvas, "Call SetPage() first before doing drawing operations." ); this->AddToPageResources( inGState->GetIdentifier(), inGState->GetObject()->Reference(), PdfName("ExtGState") ); m_oss.str(""); m_oss << "/" << inGState->GetIdentifier().GetName() << " gs" << std::endl; m_pCanvas->Append( m_oss.str() ); } void PdfPainter::SetRenderingIntent( char* intent ) { PODOFO_RAISE_LOGIC_IF( !m_pCanvas, "Call SetPage() first before doing drawing operations." ); m_oss.str(""); m_oss << "/" << intent << " ri" << std::endl; m_pCanvas->Append( m_oss.str() ); } #if defined(_MSC_VER) && _MSC_VER <= 1200 // MSC 6.0 has a template-bug PdfString PdfPainter::ExpandTabs_char( const char* pszText, long lStringLen, int nTabCnt, const char cTab, const char cSpace ) const { long lLen = lStringLen + nTabCnt*(m_nTabWidth-1) + sizeof(char); char* pszTab = static_cast(malloc( sizeof( char ) * lLen )); if( !pszTab ) { PODOFO_RAISE_ERROR( ePdfError_OutOfMemory ); } int i = 0; while( lStringLen-- ) { if( *pszText == cTab ) { for( int z=0;z(malloc( sizeof( pdf_utf16be ) * lLen )); if( !pszTab ) { PODOFO_RAISE_ERROR( ePdfError_OutOfMemory ); } int i = 0; while( lStringLen-- ) { if( *pszText == cTab ) { for( int z=0;z PdfString PdfPainter::ExpandTabsPrivate( const C* pszText, pdf_long lStringLen, int nTabCnt, const C cTab, const C cSpace ) const { pdf_long lLen = lStringLen + nTabCnt*(m_nTabWidth-1) + sizeof(C); C* pszTab = static_cast(malloc( sizeof( C ) * lLen )); if( !pszTab ) { PODOFO_RAISE_ERROR( ePdfError_OutOfMemory ); } int i = 0; while( lStringLen-- ) { if( *pszText == cTab ) { for( int z=0;z( rsString.GetUnicode(), lStringLen, nTabCnt, cTab, cSpace ); else return ExpandTabsPrivate( rsString.GetString(), lStringLen, nTabCnt, '\t', ' ' ); #endif } } /* namespace PoDoFo */ podofo-0.9.3/src/doc/PdfFontTTFSubset.cpp0000664000175000017500000007134712347315357020053 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2008 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfFontTTFSubset.h" #include "base/PdfDefinesPrivate.h" #include "base/PdfInputDevice.h" #include "base/PdfOutputDevice.h" #include #include #include namespace PoDoFo { static const unsigned int __LENGTH_HEADER12 = 12; static const unsigned int __LENGTH_OFFSETTABLE16 = 16; static const unsigned int __LENGTH_DWORD = 4; static const unsigned int __LENGTH_WORD = 2; //Big-endian to little-endian or little-endian to big endian. #ifdef PODOFO_IS_LITTLE_ENDIAN #ifdef PODOFO_IS_LITTLE_ENDIAN inline unsigned long Big2Little(unsigned long big) { return ((big << 24) & 0xFF000000) | ((big << 8) & 0x00FF0000) | ((big >> 8) & 0x0000FF00) | ((big >> 24) & 0x000000FF) ; } inline unsigned short Big2Little(unsigned short big) { return ((big << 8) & 0xFF00) | ((big >> 8) & 0x00FF); } inline short Big2Little(short big) { return ((big << 8) & 0xFF00) | ((big >> 8) & 0x00FF); } #endif // PODOFO_IS_LITTLE_ENDIAN #else #define Big2Little( x ) x #endif // PODOFO_IS_LITTLE_ENDIAN //Get the number of bytes to pad the ul, because of 4-byte-alignment. unsigned int GetPadding(unsigned long ul); PdfFontTTFSubset::PdfFontTTFSubset( const char* pszFontFileName, PdfFontMetrics* pMetrics, unsigned short nFaceIndex ) : m_pMetrics( pMetrics ), m_faceIndex( nFaceIndex ), m_bOwnDevice( true ) { //File type is now distinguished by ext, which might cause problems. const char* pname = pszFontFileName; const char* ext = pname + strlen(pname) - 3; if (PoDoFo::compat::strcasecmp(ext,"ttf") == 0) { m_eFontFileType = eFontFileType_TTF; } else if (PoDoFo::compat::strcasecmp(ext,"ttc") == 0) { m_eFontFileType = eFontFileType_TTC; } else if (PoDoFo::compat::strcasecmp(ext,"otf") == 0) { m_eFontFileType = eFontFileType_OTF; } else { m_eFontFileType = eFontFileType_Unknown; } m_pDevice = new PdfInputDevice( pszFontFileName ); // For any fonts, assume that glyph 0 is needed. m_vGlyphIndice.push_back(0); } PdfFontTTFSubset::PdfFontTTFSubset( PdfInputDevice* pDevice, PdfFontMetrics* pMetrics, EFontFileType eType, unsigned short nFaceIndex ) : m_pMetrics( pMetrics ), m_eFontFileType( eType ), m_faceIndex(nFaceIndex), m_pDevice( pDevice ), m_bOwnDevice( false ) { // For any fonts, assume that glyph 0 is needed. m_vGlyphIndice.push_back(0); } PdfFontTTFSubset::~PdfFontTTFSubset() { if( m_bOwnDevice ) { delete m_pDevice; m_pDevice = NULL; } } void PdfFontTTFSubset::AddGlyph( unsigned short nGlyphIndex ) { // Do a sorted insert std::pair::iterator, std::vector::const_iterator> it = std::equal_range( m_vGlyphIndice.begin(), m_vGlyphIndice.end(), nGlyphIndex ); if( it.first == it.second ) { m_vGlyphIndice.insert( it.first, nGlyphIndex ); } } void PdfFontTTFSubset::Init() { GetStartOfTTFOffsets(); GetNumberOfTables(); InitTables(); GetNumberOfGlyphs(); SeeIfLongLocaOrNot(); } unsigned long PdfFontTTFSubset::GetTableOffset( const char* pszTableName ) { std::vector::const_iterator it = m_vTable.begin(); for (; it != m_vTable.end(); it++) { if (it->m_strTableName == pszTableName) return it->m_offset; } return 0L; } void PdfFontTTFSubset::GetNumberOfGlyphs() { unsigned long ulMaxpOffset = GetTableOffset( "maxp" ); GetData( ulMaxpOffset+__LENGTH_DWORD*1,&m_numGlyphs,__LENGTH_DWORD); m_numGlyphs = Big2Little(m_numGlyphs); //std::cout << "Number of Glyphs: "<< m_numGlyphs << std::endl; } void PdfFontTTFSubset::InitTables() { for (int i=0; i < m_numTables; i++) { TTrueTypeTable tbl; //Name of each table: GetData( m_ulStartOfTTFOffsets+__LENGTH_HEADER12+__LENGTH_OFFSETTABLE16*i, tbl.m_tableName, __LENGTH_DWORD ); //String name of each table: tbl.m_strTableName.assign( reinterpret_cast(tbl.m_tableName), __LENGTH_DWORD ); //Checksum of each table: GetData( m_ulStartOfTTFOffsets+__LENGTH_HEADER12+__LENGTH_OFFSETTABLE16*i+__LENGTH_DWORD*1,&tbl.m_checksum,__LENGTH_DWORD); tbl.m_checksum = Big2Little(tbl.m_checksum); //Offset of each table: GetData( m_ulStartOfTTFOffsets+__LENGTH_HEADER12+__LENGTH_OFFSETTABLE16*i+__LENGTH_DWORD*2,&tbl.m_offset,__LENGTH_DWORD); tbl.m_offset = Big2Little(tbl.m_offset); //Length of each table: GetData( m_ulStartOfTTFOffsets+__LENGTH_HEADER12+__LENGTH_OFFSETTABLE16*i+__LENGTH_DWORD*3,&tbl.m_length,__LENGTH_DWORD); tbl.m_length = Big2Little(tbl.m_length); //It seems that the EBDT, EBLC, EBSC table can be erased. if (PoDoFo::compat::strcasecmp(tbl.m_strTableName.c_str(), "EBDT") == 0 /*|| PoDoFo::compat::strcasecmp(tbl.m_strTableName.c_str(), "EBLC") == 0 || PoDoFo::compat::strcasecmp(tbl.m_strTableName.c_str(), "EBSC") == 0*/ || PoDoFo::compat::strcasecmp(tbl.m_strTableName.c_str(), "DSIG") == 0 || PoDoFo::compat::strcasecmp(tbl.m_strTableName.c_str(), "LTSH") == 0 || PoDoFo::compat::strcasecmp(tbl.m_strTableName.c_str(), "VDMX") == 0 || PoDoFo::compat::strcasecmp(tbl.m_strTableName.c_str(), "HDMX") == 0) { continue; } m_vTable.push_back(tbl); } m_numTables = static_cast(m_vTable.size()); } void PdfFontTTFSubset::GetStartOfTTFOffsets() { switch (m_eFontFileType) { case eFontFileType_TTF: case eFontFileType_OTF: m_ulStartOfTTFOffsets = 0x0; break; case eFontFileType_TTC: { unsigned long ulnumFace; GetData( 8,&ulnumFace,4); ulnumFace = Big2Little(ulnumFace); GetData( (3+m_faceIndex)*__LENGTH_DWORD,&m_ulStartOfTTFOffsets,__LENGTH_DWORD); m_ulStartOfTTFOffsets = Big2Little(m_ulStartOfTTFOffsets); } break; case eFontFileType_Unknown: break; default: return; } } void PdfFontTTFSubset::GetNumberOfTables() { GetData( m_ulStartOfTTFOffsets+1*__LENGTH_DWORD,&m_numTables,__LENGTH_WORD); m_numTables = Big2Little(m_numTables); } void PdfFontTTFSubset::SeeIfLongLocaOrNot() { unsigned short usIsLong; //1 for long unsigned long ulHeadOffset = GetTableOffset("head"); GetData( ulHeadOffset+50,&usIsLong,__LENGTH_WORD); usIsLong = Big2Little(usIsLong); m_bIsLongLoca = (usIsLong == 0 ? false : true); } void PdfFontTTFSubset::BuildFont( PdfOutputDevice* pOutputDevice ) { Init(); // Not necessary as we do a sorted insert //std::sort(m_vGlyphIndice.begin(),m_vGlyphIndice.end()); //Find the font offset table: unsigned long ulStartOfTTFOffsets = m_ulStartOfTTFOffsets; // Deal with glyph indeces which are // not part of this font. Remove any // glyph that cannot be embedded therefore std::vector::iterator itGlyphIndice = m_vGlyphIndice.begin(); for (; itGlyphIndice != m_vGlyphIndice.end();) { if (*itGlyphIndice > m_numGlyphs) { itGlyphIndice = m_vGlyphIndice.erase(itGlyphIndice); } else { itGlyphIndice++; } } //============================================================================== // Make a new font: // Make the glyf table be the last table, just for convenience: long i; for (i = 0; i < m_numTables; i++) { if (m_vTable[i].m_strTableName == "glyf") { TTrueTypeTable tmpTbl = m_vTable.back(); m_vTable.back() = m_vTable[i]; m_vTable[i] = tmpTbl; break; } } unsigned long ulGlyfTableOffset = GetTableOffset("glyf"); unsigned long ulLocaTableOffset = GetTableOffset("loca"); std::vector vOldTable = m_vTable; //vOldTable will be used later. //Print the old table information: // for ( i = 0; i < m_numTables; i++) // { // std::cout << "OldTable:\t" << m_vTable[i].m_strTableName << std::endl; // std::cout << "\tOffSet:\t" << m_vTable[i].m_offset << std::endl; // std::cout << "\t\tLength:\t"< vGD; TGlyphData gd; unsigned long ulNextGlyphAddress; //Deal with the composite glyphs: //Sometimes glyph A will use glyph B, so glyph B must be embeded also, but whether glyph B is using another glyph has not been taken into account. std::vector vGlyphIndice = m_vGlyphIndice; //Temp vGlyphIndice. for ( i = 0; i < static_cast(vGlyphIndice.size()); i++) { gd.glyphIndex = vGlyphIndice[i]; GetData( ulLocaTableOffset+__LENGTH_DWORD*gd.glyphIndex,&gd.glyphOldAddress,__LENGTH_DWORD); gd.glyphOldAddress = Big2Little(gd.glyphOldAddress); short sIsComp; GetData( ulGlyfTableOffset+gd.glyphOldAddress,&sIsComp,__LENGTH_WORD); sIsComp = Big2Little(sIsComp); if (sIsComp >= 0) { continue; } else { unsigned long lOffset = ulGlyfTableOffset+gd.glyphOldAddress+10; const int ARG_1_AND_2_ARE_WORDS = 0x01; const int MORE_COMPONENTS = 0x20; unsigned short flags; unsigned short glyphIndex; do { GetData( lOffset, &flags,__LENGTH_WORD); lOffset += __LENGTH_WORD; GetData( lOffset, &glyphIndex,__LENGTH_WORD); lOffset += __LENGTH_WORD; flags = Big2Little( flags ); if( flags & ARG_1_AND_2_ARE_WORDS) { // Skip two args lOffset += (2*__LENGTH_WORD); } else { // Skip one arg lOffset += __LENGTH_WORD; } glyphIndex = Big2Little( glyphIndex ); this->AddGlyph( glyphIndex ); } while ( flags & MORE_COMPONENTS ); /* unsigned short usNewGlyphIndex; GetData( ulGlyfTableOffset+gd.glyphOldAddress+12,&usNewGlyphIndex,__LENGTH_WORD); usNewGlyphIndex = Big2Little(usNewGlyphIndex); this->AddGlyph( usNewGlyphIndex ); */ } } // Let us assume that the first glyphindex in the vector is always 0: for ( i = 0; i < static_cast(m_vGlyphIndice.size()); i++) { gd.glyphIndex = m_vGlyphIndice[i]; GetData( ulLocaTableOffset+__LENGTH_DWORD*gd.glyphIndex,&gd.glyphOldAddress,__LENGTH_DWORD); gd.glyphOldAddress = Big2Little(gd.glyphOldAddress); GetData( ulLocaTableOffset+__LENGTH_DWORD*(gd.glyphIndex+1),&ulNextGlyphAddress,__LENGTH_DWORD); ulNextGlyphAddress = Big2Little(ulNextGlyphAddress); gd.glyphLength = ulNextGlyphAddress-gd.glyphOldAddress; vGD.push_back(gd); } //The last glyph, whose index seems not needed. ulNextGlyphAddress = m_vTable.back().m_length; GetData( ulLocaTableOffset+(m_numGlyphs)*__LENGTH_DWORD,&gd.glyphOldAddress,__LENGTH_DWORD); //? gd.glyphOldAddress = Big2Little(gd.glyphOldAddress); gd.glyphLength = ulNextGlyphAddress-gd.glyphOldAddress; vGD.push_back(gd); vGD[0].glyphNewAddress = 0x0; for ( i = 1; i < static_cast(vGD.size()); i++) { vGD[i].glyphNewAddress = vGD[i-1].glyphNewAddress+vGD[i-1].glyphLength; } //New glyf table length: unsigned long ulNewGlyfTableLength = vGD.back().glyphNewAddress+vGD.back().glyphLength; m_vTable.back().m_length = ulNewGlyfTableLength; //Writing the header: unsigned char* buf = new unsigned char[3*__LENGTH_DWORD]; GetData( ulStartOfTTFOffsets,buf,3*__LENGTH_DWORD); pOutputDevice->Write( reinterpret_cast(buf), 3*__LENGTH_DWORD ); delete[] buf; buf = new unsigned char[m_numTables*__LENGTH_DWORD*4]; for ( i = 0; i < m_numTables; i++) { //The table name: for (int j(0); j < static_cast(__LENGTH_DWORD); j++) { buf[i*__LENGTH_DWORD*4 + j] = m_vTable[i].m_tableName[j]; } //The checksum: unsigned long ultemp = Big2Little(m_vTable[i].m_checksum); for (int k(0); k < static_cast(__LENGTH_DWORD); k++) { unsigned char ch = static_cast(ultemp%256); buf[i*__LENGTH_DWORD*4 + 4 + k] = ch; ultemp /= 256; } //The offset: ultemp = Big2Little(m_vTable[i].m_offset); for (int m(0); m < static_cast(__LENGTH_DWORD); m++) { unsigned char ch = static_cast(ultemp%256); buf[i*__LENGTH_DWORD*4 + 8 + m] = ch; ultemp /= 256; } //The length: ultemp = Big2Little(m_vTable[i].m_length); for (int n(0); n < static_cast(__LENGTH_DWORD); n++) { unsigned char ch = static_cast(ultemp%256); buf[i*__LENGTH_DWORD*4 + 12 + n] = ch; ultemp /= 256; } } pOutputDevice->Write( reinterpret_cast(buf), m_numTables*__LENGTH_DWORD*4 ); delete[] buf; //Writing new tables: vGD.back().glyphIndex = m_numGlyphs; for ( i = 0; i < m_numTables-1; i++) { if (m_vTable[i].m_strTableName != "loca") { //string str = m_vTable[i].m_strTableName; //unsigned long length = m_vTable[i].m_length; //unsigned long offset = m_vTable[i].m_offset; //unsigned long x = m_vTable[i].m_length; char *buf = new char[m_vTable[i].m_length]; //unsigned long olength = vOldTable[i].m_length; //unsigned long ooffset = vOldTable[i].m_offset; GetData( vOldTable[i].m_offset,buf,vOldTable[i].m_length); pOutputDevice->Write( reinterpret_cast(buf), vOldTable[i].m_length ); delete[] buf; buf = 0; } else { //The loca table: for (unsigned long j(0); j < vGD.size()-1; j++) { unsigned long ultemp = vGD[j].glyphNewAddress; ultemp = Big2Little(ultemp); buf = new unsigned char[__LENGTH_DWORD]; for (int k(0); k < static_cast(__LENGTH_DWORD); k++) { unsigned char ch = static_cast(ultemp%256); buf[k] = ch; ultemp /= 256; } pOutputDevice->Write( reinterpret_cast(buf), __LENGTH_DWORD ); ultemp = vGD[j+1].glyphNewAddress; ultemp = Big2Little(ultemp); for (int n(0); n < static_cast(__LENGTH_DWORD); n++) { unsigned char ch = static_cast(ultemp%256); buf[n] = ch; ultemp /= 256; } for (unsigned long m(vGD[j].glyphIndex+1); m < vGD[j+1].glyphIndex; m++) { pOutputDevice->Write( reinterpret_cast(buf), __LENGTH_DWORD ); } delete[] buf; } //The last glyph address: buf = new unsigned char[__LENGTH_DWORD]; unsigned long ultemp = vGD.back().glyphNewAddress; ultemp = Big2Little(ultemp); for (int n(0); n < static_cast(__LENGTH_DWORD); n++) { unsigned char ch = static_cast(ultemp%256); buf[n] = ch; ultemp /= 256; } pOutputDevice->Write( reinterpret_cast(buf), __LENGTH_DWORD ); delete[] buf; } //Paddings: unsigned pad = GetPadding(m_vTable[i].m_length); if (pad != 0) { buf = new unsigned char[pad]; pOutputDevice->Write( reinterpret_cast(buf), pad ); delete[] buf; } } //Writing the last table, glyf: for ( i = 0; i < static_cast(vGD.size()); i++) { buf = new unsigned char[vGD[i].glyphLength]; GetData( ulGlyfTableOffset+vGD[i].glyphOldAddress,buf,vGD[i].glyphLength); pOutputDevice->Write( reinterpret_cast(buf), vGD[i].glyphLength ); delete[] buf; } } else { std::vector vsGD; TGlyphDataShort gd; unsigned short usNextGlyphAddress; unsigned long usNextGlyphAddressLong; //Deal with the composite glyphs: //Temp vGlyphIndice: std::vector vGlyphIndice = m_vGlyphIndice; for ( i = 0; i < static_cast(vGlyphIndice.size()); i++) { gd.glyphIndex = vGlyphIndice[i]; GetData( ulLocaTableOffset+__LENGTH_WORD*gd.glyphIndex,&gd.glyphOldAddress,__LENGTH_WORD); gd.glyphOldAddress = Big2Little(gd.glyphOldAddress); gd.glyphOldAddressLong = gd.glyphOldAddress*2; short sIsComp; GetData( ulGlyfTableOffset+gd.glyphOldAddressLong,&sIsComp,__LENGTH_WORD); sIsComp = Big2Little(sIsComp); if (sIsComp >= 0) { continue; } else { unsigned short usNewGlyphIndex; GetData( ulGlyfTableOffset+gd.glyphOldAddressLong+12,&usNewGlyphIndex,__LENGTH_WORD); usNewGlyphIndex = Big2Little(usNewGlyphIndex); this->AddGlyph( usNewGlyphIndex ); } } //Let us assume that the first glyphindex in the vector is always 0: for ( i = 0; i < static_cast(m_vGlyphIndice.size()); i++) { gd.glyphIndex = m_vGlyphIndice[i]; GetData( ulLocaTableOffset+__LENGTH_WORD*gd.glyphIndex,&gd.glyphOldAddress,__LENGTH_WORD); gd.glyphOldAddress = Big2Little(gd.glyphOldAddress); gd.glyphOldAddressLong = gd.glyphOldAddress*2; GetData( ulLocaTableOffset+__LENGTH_WORD*(gd.glyphIndex+1),&usNextGlyphAddress,__LENGTH_WORD); usNextGlyphAddress = Big2Little(usNextGlyphAddress); usNextGlyphAddressLong = usNextGlyphAddress*2; gd.glyphLength = static_cast(usNextGlyphAddressLong-gd.glyphOldAddressLong); vsGD.push_back(gd); } //The last glyph, glyph index seems not needed. usNextGlyphAddressLong = m_vTable.back().m_length; GetData( ulLocaTableOffset+(m_numGlyphs)*__LENGTH_WORD,&gd.glyphOldAddress,__LENGTH_WORD); //? gd.glyphOldAddress = Big2Little(gd.glyphOldAddress); gd.glyphOldAddressLong = gd.glyphOldAddress*2; gd.glyphLength = static_cast(usNextGlyphAddressLong-gd.glyphOldAddressLong); vsGD.push_back(gd); vsGD[0].glyphNewAddress = 0x0; vsGD[0].glyphNewAddressLong = 0x0; for ( i = 1; i < static_cast(vsGD.size()); i++) { vsGD[i].glyphNewAddressLong = vsGD[i-1].glyphNewAddressLong+vsGD[i-1].glyphLength; vsGD[i].glyphNewAddress = static_cast(vsGD[i].glyphNewAddressLong/2); } //New glyf table length: unsigned long usNewGlyfTableLength = vsGD.back().glyphNewAddressLong+vsGD.back().glyphLength; m_vTable.back().m_length = usNewGlyfTableLength; //Writing the header: unsigned char* buf = new unsigned char[3*__LENGTH_DWORD]; GetData( ulStartOfTTFOffsets,buf,3*__LENGTH_DWORD); pOutputDevice->Write( reinterpret_cast(buf), 3*__LENGTH_DWORD ); delete[] buf; buf = new unsigned char[m_numTables*__LENGTH_DWORD*4]; for ( i = 0; i < m_numTables; i++) { //The table name: for (int j(0); j < static_cast(__LENGTH_DWORD); j++) { buf[i*__LENGTH_DWORD*4 + j] = m_vTable[i].m_tableName[j]; } //The checksum: unsigned long ultemp = Big2Little(m_vTable[i].m_checksum); for (int k(0); k < static_cast(__LENGTH_DWORD); k++) { unsigned char ch = static_cast(ultemp%256); buf[i*__LENGTH_DWORD*4 + 4 + k] = ch; ultemp /= 256; } //The offset: ultemp = Big2Little(m_vTable[i].m_offset); for (int m(0); m < static_cast(__LENGTH_DWORD); m++) { unsigned char ch = static_cast(ultemp%256); buf[i*__LENGTH_DWORD*4 + 8 + m] = ch; ultemp /= 256; } //The length: ultemp = Big2Little(m_vTable[i].m_length); for (int n(0); n < static_cast(__LENGTH_DWORD); n++) { unsigned char ch = static_cast(ultemp%256); buf[i*__LENGTH_DWORD*4 + 12 + n] = ch; ultemp /= 256; } } pOutputDevice->Write( reinterpret_cast(buf), m_numTables*__LENGTH_DWORD*4 ); delete[] buf; //Writing new tables: vsGD.back().glyphIndex = m_numGlyphs; for ( i = 0; i < m_numTables-1; i++) { if (m_vTable[i].m_strTableName != "loca") { //string str = m_vTable[i].m_strTableName; //unsigned long length = m_vTable[i].m_length; //unsigned long offset = m_vTable[i].m_offset; char *buf = new char[m_vTable[i].m_length]; //unsigned long olength = vOldTable[i].m_length; //unsigned long ooffset = vOldTable[i].m_offset; GetData( vOldTable[i].m_offset,buf,vOldTable[i].m_length); pOutputDevice->Write( reinterpret_cast(buf), vOldTable[i].m_length ); delete[] buf; buf = 0; } else { //The loca table: for (unsigned long j(0); j < vsGD.size()-1; j++) { unsigned short ustemp = vsGD[j].glyphNewAddress; ustemp = Big2Little(ustemp); buf = new unsigned char[__LENGTH_WORD]; for (int k(0); k < static_cast(__LENGTH_WORD); k++) { unsigned char ch = ustemp%256; buf[k] = ch; ustemp /= 256; } pOutputDevice->Write( reinterpret_cast(buf), __LENGTH_WORD ); ustemp = vsGD[j+1].glyphNewAddress; ustemp = Big2Little(ustemp); for (int n(0); n < static_cast(__LENGTH_WORD); n++) { unsigned char ch = ustemp%256; buf[n] = ch; ustemp /= 256; } for (unsigned long m(vsGD[j].glyphIndex+1); m < vsGD[j+1].glyphIndex; m++) { pOutputDevice->Write( reinterpret_cast(buf), __LENGTH_WORD ); } delete[] buf; } //The last glyph address: buf = new unsigned char[__LENGTH_WORD]; unsigned short ustemp = vsGD.back().glyphNewAddress; ustemp = Big2Little(ustemp); for (int n(0); n < static_cast(__LENGTH_WORD); n++) { unsigned char ch = ustemp%256; buf[n] = ch; ustemp /= 256; } //vsGD.back().glyphLength = 0; pOutputDevice->Write( reinterpret_cast(buf), __LENGTH_WORD ); delete[] buf; } //Paddings: unsigned pad = GetPadding(m_vTable[i].m_length); if (pad != 0) { buf = new unsigned char[pad]; pOutputDevice->Write( reinterpret_cast(buf), pad ); delete[] buf; } } //Writing the last table, glyf: for ( i = 0; i < static_cast(vsGD.size()); i++) { buf = new unsigned char[vsGD[i].glyphLength]; GetData( ulGlyfTableOffset+vsGD[i].glyphOldAddressLong,buf,vsGD[i].glyphLength); pOutputDevice->Write( reinterpret_cast(buf), vsGD[i].glyphLength ); delete[] buf; } } } void PdfFontTTFSubset::GetData(unsigned long offset, void* address, unsigned long sz) { m_pDevice->Seek( offset ); m_pDevice->Read( static_cast(address), sz ); } // ----------------------------------------------------- // // ----------------------------------------------------- unsigned int GetPadding(unsigned long ul) { ul %= 4; if (ul != 0) { ul = 4-ul; } return ul; } }; /* PoDoFo */ podofo-0.9.3/src/doc/PdfFontType3.h0000664000175000017500000001040612344436554016666 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2007 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_FONT_TYPE3_H_ #define _PDF_FONT_TYPE3_H_ #include "podofo/base/PdfDefines.h" #include "PdfFontSimple.h" namespace PoDoFo { /** A PdfFont implementation that can be used * to embedd type3 fonts into a PDF file * or to draw with type3 fonts. * * Type3 fonts are always embedded. */ class PdfFontType3 : public PdfFontSimple { public: /** Create a new Type3 font. * * It will get embedded automatically. * * \param pMetrics pointer to a font metrics object. The font in the PDF * file will match this fontmetrics object. The metrics object is * deleted along with the font. * \param pEncoding the encoding of this font. The font will take ownership of this object * depending on pEncoding->IsAutoDelete() * \param pParent parent of the font object * \param bEmbed if true the font will get embedded. * */ PdfFontType3( PdfFontMetrics* pMetrics, const PdfEncoding* const pEncoding, PdfVecObjects* pParent, bool bEmbed ); /** Create a PdfFont based on an existing PdfObject * \param pMetrics pointer to a font metrics object. The font in the PDF * file will match this fontmetrics object. The metrics object is * deleted along with the font. * \param pEncoding the encoding of this font. The font will take ownership of this object * depending on pEncoding->IsAutoDelete() * \param pObject an existing PdfObject */ PdfFontType3( PdfFontMetrics* pMetrics, const PdfEncoding* const pEncoding, PdfObject* pObject ); private: /** Embed the font file directly into the PDF file. * * \param pDescriptor font descriptor object */ void EmbedFontFile( PdfObject* pDescriptor ); }; }; #endif // _PDF_FONT_TYPE3_H_ podofo-0.9.3/src/podofo.h0000664000175000017500000001112312347301431015103 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2006 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PODOFO_H_ #define _PODOFO_H_ /** * This file can be used in client applications to include * all files required by PoDoFo at once. * * Some symbols may be declared in the PoDoFo::NonPublic namespace. * Client applications must never rely on or use these symbols directly. * On supporting platforms they will be excluded from the DLL interface, * and they are not guaranteed to continue to exist. */ #include "podofo-base.h" // Include files from PoDoFo-doc #include "doc/PdfAcroForm.h" #include "doc/PdfAction.h" #include "doc/PdfAnnotation.h" #include "doc/PdfCMapEncoding.h" #include "doc/PdfContents.h" #include "doc/PdfDestination.h" #include "doc/PdfDifferenceEncoding.h" #include "doc/PdfDocument.h" #include "doc/PdfElement.h" #include "doc/PdfEncodingObjectFactory.h" #include "doc/PdfExtGState.h" #include "doc/PdfField.h" #include "doc/PdfFileSpec.h" #include "doc/PdfFontCache.h" #include "doc/PdfFontCID.h" #include "doc/PdfFontConfigWrapper.h" #include "doc/PdfFontFactoryBase14Data.h" #include "doc/PdfFontFactory.h" #include "doc/PdfFont.h" #include "doc/PdfFontMetricsBase14.h" #include "doc/PdfFontMetricsFreetype.h" #include "doc/PdfFontMetrics.h" #include "doc/PdfFontMetricsObject.h" #include "doc/PdfFontSimple.h" #include "doc/PdfFontTrueType.h" #include "doc/PdfFontTTFSubset.h" #include "doc/PdfFontType1Base14.h" #include "doc/PdfFontType1.h" #include "doc/PdfFontType3.h" #include "doc/PdfFunction.h" #include "doc/PdfHintStream.h" #include "doc/PdfIdentityEncoding.h" #include "doc/PdfImage.h" #include "doc/PdfInfo.h" #include "doc/PdfMemDocument.h" #include "doc/PdfNamesTree.h" #include "doc/PdfOutlines.h" #include "doc/PdfPage.h" #include "doc/PdfPagesTreeCache.h" #include "doc/PdfPagesTree.h" #include "doc/PdfPainter.h" #include "doc/PdfPainterMM.h" #include "doc/PdfShadingPattern.h" #include "doc/PdfSigIncMemDocument.h" #include "doc/PdfSigIncPainter.h" #include "doc/PdfSignatureField.h" #include "doc/PdfSignOutputDevice.h" #include "doc/PdfStreamedDocument.h" #include "doc/PdfTable.h" #include "doc/PdfTilingPattern.h" #include "doc/PdfXObject.h" #ifdef _PODOFO_NO_NAMESPACE_ using namespace PoDoFo; #endif /* _PODOFO_NO_NAMESPACE_ */ #endif /* _PODOFO_H_ */ podofo-0.9.3/src/CMakeLists.txt0000664000175000017500000002207112347301431016210 0ustar dominikdominikcmake_minimum_required(VERSION 2.6) IF(NOT PODOFO_MAIN_CMAKELISTS_READ) MESSAGE(FATAL_ERROR "Run cmake on the CMakeLists.txt in the project root, not the one in the 'src' directory. You will need to delete CMakeCache.txt from the current directory.") ENDIF(NOT PODOFO_MAIN_CMAKELISTS_READ) SET(PODOFO_BASE_DEPEND_TARGET CACHE INTERNAL "Which PoDoFo library target to depend on when building tools and tests") SET(PODOFO_DEPEND_TARGET CACHE INTERNAL "Which PoDoFo library target to depend on when building tools and tests") SET(PODOFO_BASE_SOURCES base/PdfArray.cpp base/PdfCanvas.cpp base/PdfColor.cpp base/PdfContentsTokenizer.cpp base/PdfData.cpp base/PdfDataType.cpp base/PdfDate.cpp base/PdfDictionary.cpp base/PdfEncoding.cpp base/PdfEncodingFactory.cpp base/PdfEncrypt.cpp base/PdfError.cpp base/PdfFileStream.cpp base/PdfFilter.cpp base/PdfFiltersPrivate.cpp base/PdfImmediateWriter.cpp base/PdfInputDevice.cpp base/PdfInputStream.cpp base/PdfLocale.cpp base/PdfMemStream.cpp base/PdfMemoryManagement.cpp base/PdfName.cpp base/PdfObject.cpp base/PdfObjectStreamParserObject.cpp base/PdfOutputDevice.cpp base/PdfOutputStream.cpp base/PdfParser.cpp base/PdfParserObject.cpp base/PdfRect.cpp base/PdfRefCountedBuffer.cpp base/PdfRefCountedInputDevice.cpp base/PdfReference.cpp base/PdfSigIncWriter.cpp base/PdfStream.cpp base/PdfString.cpp base/PdfTokenizer.cpp base/PdfVariant.cpp base/PdfVecObjects.cpp base/PdfWriter.cpp base/PdfXRef.cpp base/PdfXRefStream.cpp base/PdfXRefStreamParserObject.cpp ) SET(PODOFO_DOC_SOURCES doc/PdfAcroForm.cpp doc/PdfAction.cpp doc/PdfAnnotation.cpp doc/PdfCMapEncoding.cpp doc/PdfContents.cpp doc/PdfDestination.cpp doc/PdfDifferenceEncoding.cpp doc/PdfDocument.cpp doc/PdfElement.cpp doc/PdfEncodingObjectFactory.cpp doc/PdfExtGState.cpp doc/PdfField.cpp doc/PdfFileSpec.cpp doc/PdfFont.cpp doc/PdfFontCID.cpp doc/PdfFontCache.cpp doc/PdfFontConfigWrapper.cpp doc/PdfFontFactory.cpp doc/PdfFontMetrics.cpp doc/PdfFontMetricsBase14.cpp doc/PdfFontMetricsFreetype.cpp doc/PdfFontMetricsObject.cpp doc/PdfFontSimple.cpp doc/PdfFontTTFSubset.cpp doc/PdfFontTrueType.cpp doc/PdfFontType1.cpp doc/PdfFontType3.cpp doc/PdfFontType1Base14.cpp doc/PdfFunction.cpp doc/PdfHintStream.cpp doc/PdfIdentityEncoding.cpp doc/PdfImage.cpp doc/PdfInfo.cpp doc/PdfMemDocument.cpp doc/PdfNamesTree.cpp doc/PdfOutlines.cpp doc/PdfPage.cpp doc/PdfPagesTree.cpp doc/PdfPagesTreeCache.cpp doc/PdfPainter.cpp doc/PdfPainterMM.cpp doc/PdfShadingPattern.cpp doc/PdfSigIncMemDocument.cpp doc/PdfSigIncPainter.cpp doc/PdfSigIncSignatureField.cpp doc/PdfSignOutputDevice.cpp doc/PdfSignatureField.cpp doc/PdfStreamedDocument.cpp doc/PdfTable.cpp doc/PdfTilingPattern.cpp doc/PdfXObject.cpp ) IF(WIN32) # If we build for windows systems, we also include the resource file SET(PODOFO_DOC_SOURCES ${PODOFO_DOC_SOURCES} doc/podofo-doc.rc) ENDIF(WIN32) SET(PODOFO_HEADERS podofo-base.h podofo.h) SET(PODOFO_BASE_HEADERS ${PoDoFo_BINARY_DIR}/podofo_config.h base/Pdf3rdPtyForwardDecl.h base/PdfArray.h base/PdfCanvas.h base/PdfColor.h base/PdfCompilerCompat.h base/PdfCompilerCompatPrivate.h base/PdfContentsTokenizer.h base/PdfData.h base/PdfDataType.h base/PdfDate.h base/PdfDefines.h base/PdfDefinesPrivate.h base/PdfDictionary.h base/PdfEncoding.h base/PdfEncodingFactory.h base/PdfEncrypt.h base/PdfExtension.h base/PdfError.h base/PdfFileStream.h base/PdfFilter.h base/PdfFiltersPrivate.h base/PdfImmediateWriter.h base/PdfInputDevice.h base/PdfInputStream.h base/PdfLocale.h base/PdfMemStream.h base/PdfMemoryManagement.h base/PdfName.h base/PdfObject.h base/PdfObjectStreamParserObject.h base/PdfOutputDevice.h base/PdfOutputStream.h base/PdfParser.h base/PdfParserObject.h base/PdfRect.h base/PdfRefCountedBuffer.h base/PdfRefCountedInputDevice.h base/PdfReference.h base/PdfSigIncWriter.h base/PdfStream.h base/PdfString.h base/PdfTokenizer.h base/PdfVariant.h base/PdfVecObjects.h base/PdfVersion.h base/PdfWriter.h base/PdfXRef.h base/PdfXRefStream.h base/PdfXRefStreamParserObject.h base/podofoapi.h ) SET(PODOFO_BASE_HEADERS2 base/util/PdfMutex.h base/util/PdfMutexImpl_noop.h base/util/PdfMutexImpl_win32.h base/util/PdfMutexImpl_pthread.h base/util/PdfMutexWrapper.h ) SET(PODOFO_DOC_HEADERS doc/PdfAcroForm.h doc/PdfAction.h doc/PdfAnnotation.h doc/PdfCMapEncoding.h doc/PdfContents.h doc/PdfDestination.h doc/PdfDifferenceEncoding.h doc/PdfDocument.h doc/PdfElement.h doc/PdfEncodingObjectFactory.h doc/PdfExtGState.h doc/PdfField.h doc/PdfFileSpec.h doc/PdfFont.h doc/PdfFontCID.h doc/PdfFontCache.h doc/PdfFontConfigWrapper.h doc/PdfFontFactory.h doc/PdfFontFactoryBase14Data.h doc/PdfFontMetrics.h doc/PdfFontMetricsBase14.h doc/PdfFontMetricsFreetype.h doc/PdfFontMetricsObject.h doc/PdfFontSimple.h doc/PdfFontTTFSubset.h doc/PdfFontTrueType.h doc/PdfFontType1.h doc/PdfFontType3.h doc/PdfFontType1Base14.h doc/PdfFunction.h doc/PdfHintStream.h doc/PdfIdentityEncoding.h doc/PdfImage.h doc/PdfInfo.h doc/PdfMemDocument.h doc/PdfNamesTree.h doc/PdfOutlines.h doc/PdfPage.h doc/PdfPagesTree.h doc/PdfPagesTreeCache.h doc/PdfPainter.h doc/PdfPainterMM.h doc/PdfShadingPattern.h doc/PdfSigIncMemDocument.h doc/PdfSigIncPainter.h doc/PdfSigIncSignatureField.h doc/PdfSignOutputDevice.h doc/PdfSignatureField.h doc/PdfStreamedDocument.h doc/PdfTable.h doc/PdfTilingPattern.h doc/PdfXObject.h ) # Create a Source Group for Visual Studio # so that headers are listed in the folder view # and are easier accessible SOURCE_GROUP(Headers FILES ${PODOFO_HEADERS} ${PODOFO_BASE_HEADERS} ${PODOFO_BASE_HEADERS2} ${PODOFO_DOC_HEADERS}) INSTALL(FILES ${PODOFO_HEADERS} DESTINATION "include/podofo" ) INSTALL(FILES ${PODOFO_BASE_HEADERS} DESTINATION "include/podofo/base" ) INSTALL(FILES ${PODOFO_BASE_HEADERS2} DESTINATION "include/podofo/base/util" ) INSTALL(FILES ${PODOFO_DOC_HEADERS} DESTINATION "include/podofo/doc" ) IF(NOT PODOFO_BUILD_SHARED AND NOT PODOFO_BUILD_STATIC) MESSAGE(FATAL_ERROR "At least one of PODOFO_BUILD_SHARED and PODOF_BUILD_STATIC must be set") ENDIF(NOT PODOFO_BUILD_SHARED AND NOT PODOFO_BUILD_STATIC) IF(PODOFO_BUILD_STATIC) MESSAGE("Building static PoDoFo library") ADD_LIBRARY(podofo_static STATIC ${PODOFO_BASE_SOURCES} ${PODOFO_DOC_SOURCES}) TARGET_LINK_LIBRARIES(podofo_static ${PODOFO_LIB_DEPENDS}) SET_TARGET_PROPERTIES(podofo_static PROPERTIES VERSION "${PODOFO_LIBVERSION}" SOVERSION "${PODOFO_SOVERSION}" CLEAN_DIRECT_OUTPUT 1 OUTPUT_NAME "podofo" COMPILE_FLAGS "-DBUILDING_PODOFO" ) SET(PODOFO_DEPEND_TARGET podofo_static CACHE INTERNAL "Which PoDoFo library variant to depend on") SET(USING_SHARED_PODOFO FALSE) INSTALL(TARGETS podofo_static RUNTIME DESTINATION "bin" LIBRARY DESTINATION "${LIBDIRNAME}" ARCHIVE DESTINATION "${LIBDIRNAME}" ) ENDIF(PODOFO_BUILD_STATIC) IF(PODOFO_BUILD_SHARED) MESSAGE("Building shared PoDoFo library") ADD_LIBRARY(podofo_shared SHARED ${PODOFO_BASE_SOURCES} ${PODOFO_DOC_SOURCES}) TARGET_LINK_LIBRARIES(podofo_shared ${PODOFO_LIB_DEPENDS}) # TODO: set /wd4251 flag if we're doing a debug build with # Visual Studio, since it produces invalid warnings about STL # use. SET_TARGET_PROPERTIES(podofo_shared PROPERTIES VERSION "${PODOFO_LIBVERSION}" SOVERSION "${PODOFO_SOVERSION}" CLEAN_DIRECT_OUTPUT 1 OUTPUT_NAME "podofo" COMPILE_FLAGS "-DBUILDING_PODOFO" ) # Since we're building a shared podofo, prefer to depend on this one for # tests and tools over the static library (if built). SET(PODOFO_DEPEND_TARGET podofo_shared CACHE INTERNAL "Which PoDoFo library variant to depend on") SET(USING_SHARED_PODOFO TRUE) INSTALL(TARGETS podofo_shared RUNTIME DESTINATION "bin" LIBRARY DESTINATION "${LIBDIRNAME}" ARCHIVE DESTINATION "${LIBDIRNAME}" ) ENDIF(PODOFO_BUILD_SHARED) # Use these flags when compiling code that includes PoDoFo headers. # Failure to do so will result in compilation or link-time errors # on some platforms, and can even cause undefined results at runtime. IF(WIN32 AND USING_SHARED_PODOFO) SET(PODOFO_CFLAGS "-DUSING_SHARED_PODOFO" CACHE INTERNAL "Extra flags required when linking to PoDoFo") ELSE(WIN32 AND USING_SHARED_PODOFO) SET(PODOFO_CFLAGS "" CACHE INTERNAL "Extra flags required when linking to PoDoFo") ENDIF(WIN32 AND USING_SHARED_PODOFO) # Write the cflags and depend target to the config file FILE(APPEND "${PoDoFo_BINARY_DIR}/PoDoFoConfig.cmake" "SET(PODOFO_CFLAGS ${PODOFO_CFLAGS})\n" ) FILE(APPEND "${PoDoFo_BINARY_DIR}/PoDoFoConfig.cmake" "SET(PODOFO_DEPEND_TARGET ${PODOFO_DEPEND_TARGET})\n" ) podofo-0.9.3/src/base/0000775000175000017500000000000012356565167014402 5ustar dominikdominikpodofo-0.9.3/src/base/PdfDictionary.h0000664000175000017500000002645212347271543017313 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2006 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_DICTIONARY_H_ #define _PDF_DICTIONARY_H_ #include "PdfDefines.h" #include "PdfDataType.h" #include "PdfName.h" #include "PdfObject.h" /** * PODOFO_USE_UNORDERED_MAP * * If you set this define, PoDoFo * will use std::tr1::unordered_map instead * of std::map for PdfDictionary. * * Some benchmarking tests using callgrind have shown * that unordered_map is a little faster for writing and AddKey * but of course slower for GetKey and HasKey. As PdfDictionaries * are usually very small the difference for GetKey and HasKey is * not very large and should therefore be rarely noticeable. * * By default this define is not set and std::map will be used. */ #ifdef PODOFO_USE_UNORDERED_MAP #include #endif // PODOFO_USE_ORDERED_MAP namespace PoDoFo { #ifdef PODOFO_USE_UNORDERED_MAP class PdfNameHash : public std::unary_function { public: size_t operator()( const PdfName& v ) const { std::tr1::hash hasher; return hasher( v.GetName() ); } }; typedef std::tr1::unordered_map TKeyMap; #else typedef std::map TKeyMap; #endif // PODOFO_USE_UNORDERED_MAP typedef TKeyMap::iterator TIKeyMap; typedef TKeyMap::const_iterator TCIKeyMap; class PdfOutputDevice; class PODOFO_API PdfDictionary : public PdfDataType { public: /** Create a new, empty dictionary */ PdfDictionary(); /** Deep copy a dictionary * \param rhs the PdfDictionary to copy */ PdfDictionary( const PdfDictionary & rhs ); /** Destructor */ virtual ~PdfDictionary(); /** Asignment operator. * Asign another PdfDictionary to this dictionary. This is a deep copy; * all elements of the source dictionary are duplicated. * * \param rhs the PdfDictionary to copy. * * \return this PdfDictionary * * This will set the dirty flag of this object. * \see IsDirty */ const PdfDictionary & operator=( const PdfDictionary & rhs ); /** * Comparison operator. If this dictionary contains all the same keys * as the other dictionary, and for each key the values compare equal, * the dictionaries are considered equal. */ bool operator==( const PdfDictionary& rhs ) const; /** * \see operator== */ inline bool operator!=( const PdfDictionary& rhs ) const; /** Removes all keys from the dictionary */ void Clear(); /** Add a key to the dictionary. If an existing key of this name exists, its * value is replaced and the old value object will be deleted. The passed * object is copied. * * \param identifier the key is identified by this name in the dictionary * \param rObject a variant object containing the data. The object is copied. * * This will set the dirty flag of this object. * \see IsDirty */ void AddKey( const PdfName & identifier, const PdfObject & rObject ); /** Add a key to the dictionary. If an existing key of this name exists, * its value is replaced and the old value object will be deleted. The * passed object is copied. * * This is an overloaded member function. * * \param identifier the key is identified by this name in the dictionary * \param rObject a variant object containing the data. The object is copied. * * This will set the dirty flag of this object. * \see IsDirty */ void AddKey( const PdfName & identifier, const PdfObject* pObject ); /** Get the keys value out of the dictionary. * * The returned value is a pointer to the internal object in the dictionary * so it MUST not be deleted. * * \param key look for the key names pszKey in the dictionary * * \returns pointer to the found value or 0 if the key was not found. */ const PdfObject* GetKey( const PdfName & key ) const; /** Get the keys value out of the dictionary. This is an overloaded member * function. * * The returned value is a pointer to the internal object in the dictionary. * It may be modified but is still owned by the dictionary so it MUST not * be deleted. * * \param key look for the key named key in the dictionary * * \returns the found value or 0 if the key was not found. */ PdfObject* GetKey( const PdfName & key ); pdf_int64 GetKeyAsLong( const PdfName & key, pdf_int64 lDefault = 0 ) const; double GetKeyAsReal( const PdfName & key, double dDefault = 0.0 ) const; bool GetKeyAsBool( const PdfName & key, bool bDefault = false ) const; PdfName GetKeyAsName( const PdfName & key ) const; /** Allows to check if a dictionary contains a certain key. \param key * look for the key named key.Name() in the dictionary * * \returns true if the key is part of the dictionary, otherwise false. */ bool HasKey( const PdfName & key ) const; /** Remove a key from this dictionary. If the key does not exists, this * function does nothing. * * \param identifier the name of the key to delete * * \returns true if the key was found in the object and was removed if * there was is no key with this name, false is returned. * * This will set the dirty flag of this object. * \see IsDirty */ bool RemoveKey( const PdfName & identifier ); /** Write the complete dictionary to a file. \param pDevice write the * object to this device \returns ErrOk on success * * \param pDevice write the object to this device * \param eWriteMode additional options for writing this object * \param pEncrypt an encryption object which is used to encrypt this object * or NULL to not encrypt this object */ inline void Write( PdfOutputDevice* pDevice, EPdfWriteMode eWriteMode, const PdfEncrypt* pEncrypt = NULL ) const; /** Write the complete dictionary to a file. \param pDevice write the * object to this device \param keyStop if not KeyNull and a key == keyStop * is found writing will stop right before this key! \returns ErrOk on * success * * \param pDevice write the object to this device * \param eWriteMode additional options for writing this object * \param pEncrypt an encryption object which is used to encrypt this object * or NULL to not encrypt this object * \param keyStop if not KeyNull and a key == keyStop is found * writing will stop right before this key! */ void Write( PdfOutputDevice* pDevice, EPdfWriteMode eWriteMode, const PdfEncrypt* pEncrypt, const PdfName & keyStop = PdfName::KeyNull ) const; /** Get access to the internal map of keys. * * \returns all keys of this dictionary */ inline const TKeyMap & GetKeys() const; /** Get access to the internal map of keys. \returns all keys of this * dictionary */ inline TKeyMap & GetKeys(); /** The dirty flag is set if this variant * has been modified after construction. * * Usually the dirty flag is also set * if you call any non-const member function * as we cannot determine if you actually changed * something or not. * * \returns true if the value is dirty and has been * modified since construction */ virtual bool IsDirty() const; /** Sets the dirty flag of this PdfVariant * * \param bDirty true if this PdfVariant has been * modified from the outside * * \see IsDirty */ virtual void SetDirty( bool bDirty ); private: TKeyMap m_mapKeys; bool m_bDirty; ///< Indicates if this object was modified after construction }; typedef std::vector TVecDictionaries; typedef TVecDictionaries::iterator TIVecDictionaries; typedef TVecDictionaries::const_iterator TCIVecDictionaries; // ----------------------------------------------------- // // ----------------------------------------------------- const TKeyMap & PdfDictionary::GetKeys() const { return m_mapKeys; } // ----------------------------------------------------- // // ----------------------------------------------------- TKeyMap & PdfDictionary::GetKeys() { return m_mapKeys; } // ----------------------------------------------------- // // ----------------------------------------------------- void PdfDictionary::Write( PdfOutputDevice* pDevice, EPdfWriteMode eWriteMode, const PdfEncrypt* pEncrypt ) const { this->Write( pDevice, eWriteMode, pEncrypt, PdfName::KeyNull ); } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfDictionary::operator!=( const PdfDictionary& rhs ) const { return !(*this == rhs); } }; #endif // _PDF_DICTIONARY_H_ podofo-0.9.3/src/base/PdfVecObjects.cpp0000664000175000017500000004244712344436402017564 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2005 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfVecObjects.h" #include "PdfArray.h" #include "PdfDictionary.h" #include "PdfMemStream.h" #include "PdfObject.h" #include "PdfReference.h" #include "PdfStream.h" #include "PdfDefinesPrivate.h" #include namespace { inline bool ObjectLittle( const PoDoFo::PdfObject* p1, const PoDoFo::PdfObject* p2 ) { return *p1 < *p2; } }; namespace PoDoFo { struct ObjectComparatorPredicate { public: inline bool operator()( const PdfObject* const & pObj, const PdfObject* const & pObj2 ) const { return pObj->Reference() < pObj2->Reference(); } /* inline bool operator()( PdfObject* const & pObj, const PdfReference & ref ) const { return pObj->Reference() < ref; } inline bool operator()( const PdfReference & ref, PdfObject* const & pObj ) const { return ref < pObj->Reference(); } */ }; struct ReferenceComparatorPredicate { public: inline bool operator()( const PdfReference & pObj, const PdfReference & pObj2 ) const { return pObj < pObj2; } }; //RG: 1) Should this class not be moved to the header file class ObjectsComparator { public: ObjectsComparator( const PdfReference & ref ) : m_ref( ref ) { } bool operator()(const PdfObject* p1) const { return p1 ? (p1->Reference() == m_ref ) : false; } private: /** default constructor, not implemented */ ObjectsComparator(void); /** copy constructor, not implemented */ ObjectsComparator(const ObjectsComparator& rhs); /** assignment operator, not implemented */ ObjectsComparator& operator=(const ObjectsComparator& rhs); const PdfReference m_ref; }; PdfVecObjects::PdfVecObjects() : m_bAutoDelete( false ), m_nObjectCount( 1 ), m_bSorted( true ), m_pDocument( NULL ), m_pStreamFactory( NULL ) { } PdfVecObjects::~PdfVecObjects() { this->Clear(); } void PdfVecObjects::Clear() { // always work on a copy of the vector // in case a child invalidates our iterators // with a call to attach or detach. TVecObservers copy( m_vecObservers ); TIVecObservers itObservers = copy.begin(); while( itObservers != copy.end() ) { (*itObservers)->ParentDestructed(); ++itObservers; } if( m_bAutoDelete ) { TIVecObjects it = this->begin(); while( it != this->end() ) { delete *it; ++it; } } m_vector.clear(); m_bAutoDelete = false; m_nObjectCount = 1; m_bSorted = true; // an emtpy vector is sorted m_pDocument = NULL; m_pStreamFactory = NULL; } PdfObject* PdfVecObjects::GetObject( const PdfReference & ref ) const { if( !m_bSorted ) const_cast(this)->Sort(); PdfObject refObj( ref, NULL ); std::pair it = std::equal_range( m_vector.begin(), m_vector.end(), &refObj, ObjectComparatorPredicate() ); if( it.first != it.second ) return *(it.first); /* const TCIVecObjects it ( std::find_if( this->begin(), this->end(), ObjectsComparator( ref ) ) ); if( it != this->end() ) return (*it); */ return NULL; } size_t PdfVecObjects::GetIndex( const PdfReference & ref ) const { if( !m_bSorted ) const_cast(this)->Sort(); PdfObject refObj( ref, NULL ); std::pair it = std::equal_range( m_vector.begin(), m_vector.end(), &refObj, ObjectComparatorPredicate() ); if( it.first == it.second ) { PODOFO_RAISE_ERROR( ePdfError_NoObject ); } return (it.first - this->begin()); } PdfObject* PdfVecObjects::RemoveObject( const PdfReference & ref, bool bMarkAsFree ) { if( !m_bSorted ) this->Sort(); PdfObject* pObj; PdfObject refObj( ref, NULL ); std::pair it = std::equal_range( m_vector.begin(), m_vector.end(), &refObj, ObjectComparatorPredicate() ); if( it.first != it.second ) { pObj = *(it.first); if( bMarkAsFree ) this->AddFreeObject( pObj->Reference() ); m_vector.erase( it.first ); return pObj; } return NULL; } PdfObject* PdfVecObjects::RemoveObject( const TIVecObjects & it ) { PdfObject* pObj = *it; m_vector.erase( it ); return pObj; } void PdfVecObjects::CollectGarbage( PdfObject* pTrailer ) { // We do not have any objects that have // to be on the top, like in a linearized PDF. // So we just use an empty list. TPdfReferenceSet setLinearizedGroup; this->RenumberObjects( pTrailer, &setLinearizedGroup, true ); } PdfReference PdfVecObjects::GetNextFreeObject() { PdfReference ref( static_cast(m_nObjectCount), 0 ); if( !m_lstFreeObjects.empty() ) { ref = m_lstFreeObjects.front(); m_lstFreeObjects.pop_front(); } return ref; } PdfObject* PdfVecObjects::CreateObject( const char* pszType ) { PdfReference ref = this->GetNextFreeObject(); PdfObject* pObj = new PdfObject( ref, pszType ); pObj->SetOwner( this ); this->push_back( pObj ); return pObj; } PdfObject* PdfVecObjects::CreateObject( const PdfVariant & rVariant ) { PdfReference ref = this->GetNextFreeObject(); PdfObject* pObj = new PdfObject( ref, rVariant ); pObj->SetOwner( this ); this->push_back( pObj ); return pObj; } void PdfVecObjects::AddFreeObject( const PdfReference & rReference ) { std::pair it = std::equal_range( m_lstFreeObjects.begin(), m_lstFreeObjects.end(), rReference, ReferenceComparatorPredicate() ); if( it.first != it.second && !m_lstFreeObjects.empty() ) { // Be sure that no reference is added twice to free list PdfError::DebugMessage( "Adding %d to freelist, is already contained !!", rReference.ObjectNumber() ); return; } else { // When append free objects from external doc we need plus one number objects SetObjectCount( rReference ); // Insert so that list stays sorted m_lstFreeObjects.insert( it.first, rReference ); } } void PdfVecObjects::push_back( PdfObject* pObj ) { insert_sorted( pObj ); } void PdfVecObjects::insert_sorted( PdfObject* pObj ) { SetObjectCount( pObj->Reference() ); pObj->SetOwner( this ); if( m_bSorted && !m_vector.empty() && pObj->Reference() < m_vector.back()->Reference() ) { TVecObjects::iterator i_pos = std::lower_bound(m_vector.begin(),m_vector.end(),pObj,ObjectLittle); m_vector.insert(i_pos, pObj ); } else { m_vector.push_back( pObj ); } } void PdfVecObjects::RenumberObjects( PdfObject* pTrailer, TPdfReferenceSet* pNotDelete, bool bDoGarbageCollection ) { TVecReferencePointerList list; TIVecReferencePointerList it; TIReferencePointerList itList; int i = 0; m_lstFreeObjects.clear(); if( !m_bSorted ) const_cast(this)->Sort(); // The following call slows everything down // optimization welcome BuildReferenceCountVector( &list ); InsertReferencesIntoVector( pTrailer, &list ); if( bDoGarbageCollection ) { GarbageCollection( &list, pTrailer, pNotDelete ); } it = list.begin(); while( it != list.end() ) { PdfReference ref( i+1, 0 ); m_vector[i]->m_reference = ref; itList = (*it).begin(); while( itList != (*it).end() ) { *(*itList) = ref; ++itList; } ++i; ++it; } } void PdfVecObjects::InsertOneReferenceIntoVector( const PdfObject* pObj, TVecReferencePointerList* pList ) { size_t index; PODOFO_RAISE_LOGIC_IF( !m_bSorted, "PdfVecObjects must be sorted before calling PdfVecObjects::InsertOneReferenceIntoVector!" ); // we asume that pObj is a reference - no checking here because of speed std::pair it = std::equal_range( m_vector.begin(), m_vector.end(), pObj, ObjectComparatorPredicate() ); if( it.first != it.second ) { // ignore this reference return; //PODOFO_RAISE_ERROR( ePdfError_NoObject ); } index = (it.first - this->begin()); (*pList)[index].push_back( const_cast(&(pObj->GetReference() )) ); } void PdfVecObjects::InsertReferencesIntoVector( const PdfObject* pObj, TVecReferencePointerList* pList ) { PdfArray::const_iterator itArray; TCIKeyMap itKeys; if( pObj->IsReference() ) { InsertOneReferenceIntoVector( pObj, pList ); } else if( pObj->IsArray() ) { itArray = pObj->GetArray().begin(); while( itArray != pObj->GetArray().end() ) { if( (*itArray).IsReference() ) InsertOneReferenceIntoVector( &(*itArray), pList ); else if( (*itArray).IsArray() || (*itArray).IsDictionary() ) InsertReferencesIntoVector( &(*itArray), pList ); ++itArray; } } else if( pObj->IsDictionary() ) { itKeys = pObj->GetDictionary().GetKeys().begin(); while( itKeys != pObj->GetDictionary().GetKeys().end() ) { if( (*itKeys).second->IsReference() ) InsertOneReferenceIntoVector( (*itKeys).second, pList ); // optimization as this is really slow: // Call only for dictionaries, references and arrays else if( (*itKeys).second->IsArray() || (*itKeys).second->IsDictionary() ) InsertReferencesIntoVector( (*itKeys).second, pList ); ++itKeys; } } } void PdfVecObjects::GetObjectDependencies( const PdfObject* pObj, TPdfReferenceList* pList ) const { PdfArray::const_iterator itArray; TCIKeyMap itKeys; if( pObj->IsReference() ) { std::pair itEqualRange = std::equal_range( pList->begin(), pList->end(), pObj->GetReference() ); if( itEqualRange.first == itEqualRange.second ) { pList->insert(itEqualRange.first, pObj->GetReference() ); const PdfObject* referencedObject = this->GetObject(pObj->GetReference()); if( referencedObject != NULL ) { this->GetObjectDependencies( referencedObject, pList ); } } } else if( pObj->IsArray() ) { itArray = pObj->GetArray().begin(); while( itArray != pObj->GetArray().end() ) { if( (*itArray).IsArray() || (*itArray).IsDictionary() || (*itArray).IsReference() ) GetObjectDependencies( &(*itArray), pList ); ++itArray; } } else if( pObj->IsDictionary() ) { itKeys = pObj->GetDictionary().GetKeys().begin(); while( itKeys != pObj->GetDictionary().GetKeys().end() ) { // optimization as this is really slow: // Call only for dictionaries, references and arrays if( (*itKeys).second->IsArray() || (*itKeys).second->IsDictionary() || (*itKeys).second->IsReference() ) GetObjectDependencies( (*itKeys).second, pList ); ++itKeys; } } } void PdfVecObjects::BuildReferenceCountVector( TVecReferencePointerList* pList ) { TCIVecObjects it = this->begin(); pList->clear(); pList->resize( !m_vector.empty() ); while( it != this->end() ) { if( (*it)->IsReference() ) InsertOneReferenceIntoVector( *it, pList ); // optimization as this is really slow: // Call only for dictionaries, references and arrays else if( (*it)->IsArray() || (*it)->IsDictionary() ) InsertReferencesIntoVector( *it, pList ); ++it; } } void PdfVecObjects::Sort() { if( !m_bSorted ) { std::sort( this->begin(), this->end(), ObjectLittle ); m_bSorted = true; } } void PdfVecObjects::GarbageCollection( TVecReferencePointerList* pList, PdfObject*, TPdfReferenceSet* pNotDelete ) { TIVecReferencePointerList it = pList->begin(); int pos = 0; bool bContains = false; while( it != pList->end() ) { bContains = pNotDelete ? ( pNotDelete->find( m_vector[pos]->Reference() ) != pNotDelete->end() ) : false; if( !(*it).size() && !bContains ) { m_vector.erase( this->begin() + pos ); } ++pos; ++it; } m_nObjectCount = ++pos; } void PdfVecObjects::Detach( Observer* pObserver ) { TIVecObservers it = m_vecObservers.begin(); while( it != m_vecObservers.end() ) { if( *it == pObserver ) { m_vecObservers.erase( it ); break; } else ++it; } } PdfStream* PdfVecObjects::CreateStream( PdfObject* pParent ) { PdfStream* pStream = m_pStreamFactory ? m_pStreamFactory->CreateStream( pParent ) : new PdfMemStream( pParent ); return pStream; } void PdfVecObjects::WriteObject( PdfObject* pObject ) { // Tell any observers that there are new objects to write TIVecObservers itObservers = m_vecObservers.begin(); while( itObservers != m_vecObservers.end() ) { (*itObservers)->WriteObject( pObject ); ++itObservers; } } PdfStream* PdfVecObjects::CreateStream( const PdfStream & ) { return NULL; } void PdfVecObjects::Finish() { // always work on a copy of the vector // in case a child invalidates our iterators // with a call to attach or detach. TVecObservers copy( m_vecObservers ); TIVecObservers itObservers = copy.begin(); while( itObservers != copy.end() ) { (*itObservers)->Finish(); ++itObservers; } } void PdfVecObjects::BeginAppendStream( const PdfStream* pStream ) { TIVecObservers itObservers = m_vecObservers.begin(); while( itObservers != m_vecObservers.end() ) { (*itObservers)->BeginAppendStream( pStream ); ++itObservers; } } void PdfVecObjects::EndAppendStream( const PdfStream* pStream ) { TIVecObservers itObservers = m_vecObservers.begin(); while( itObservers != m_vecObservers.end() ) { (*itObservers)->EndAppendStream( pStream ); ++itObservers; } } std::string PdfVecObjects::GetNextSubsetPrefix() { if ( m_sSubsetPrefix == "" ) { m_sSubsetPrefix = "AAAAAA+"; } else { PODOFO_ASSERT( m_sSubsetPrefix.length() == 7 ); PODOFO_ASSERT( m_sSubsetPrefix[6] = '+' ); for ( int i = 5; i >= 0; i-- ) { if ( m_sSubsetPrefix[i] < 'Z' ) { m_sSubsetPrefix[i]++; break; } m_sSubsetPrefix[i] = 'A'; } } return m_sSubsetPrefix; } }; podofo-0.9.3/src/base/PdfName.h0000664000175000017500000002225112344436402016051 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2006 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_NAME_H_ #define _PDF_NAME_H_ #include "PdfDefines.h" #include "PdfDataType.h" namespace PoDoFo { class PdfOutputDevice; class PdfName; //std::size_t hash_value(PdfName const& name); /** This class represents a PdfName. * Whenever a key is required you have to use a PdfName object. * * PdfName are required as keys in PdfObject and PdfVariant objects. * * PdfName may have a maximum length of 127 characters. * * \see PdfObject \see PdfVariant */ class PODOFO_API PdfName : public PdfDataType { public: /** Constructor to create NULL strings. * use PdfName::KeyNull instead of this constructor */ PdfName() : PdfDataType(), m_Data("") { } /** Create a new PdfName object. * \param sName the unescaped value of this name. Please specify * the name without the leading '/'. */ PdfName( const std::string& sName ) : PdfDataType(), m_Data(sName) { } /** Create a new PdfName object. * \param pszName the unescaped value of this name. Please specify * the name without the leading '/'. * Has to be a zero terminated string. */ PdfName( const char* pszName ) : PdfDataType() { if (pszName) m_Data.assign( pszName ); } /** Create a new PdfName object. * \param pszName the unescaped value of this name. Please specify * the name without the leading '/'. * \param lLen length of the name */ PdfName( const char* pszName, long lLen ) : PdfDataType() { if( pszName ) m_Data.assign( pszName, lLen ); } /** Create a new PdfName object from a string containing an escaped * name string without the leading / . * * \param sName A string containing the escaped name * \return A new PdfName */ static PdfName FromEscaped( const std::string& sName ); /** Create a new PdfName object from a string containing an escaped * name string without the leading / . * \param pszName A string containing the escaped name * \param ilength length of the escaped string data. If a length * of 0 is passed, the string data is expected to * be a zero terminated string. * \return A new PdfName */ static PdfName FromEscaped( const char * pszName, pdf_long ilength = 0 ); /** \return an escaped representation of this name * without the leading / . * * There is no corresponding GetEscapedLength(), since * generating the return value is somewhat expensive. */ std::string GetEscapedName() const; /** Create a copy of an existing PdfName object. * \param rhs another PdfName object */ PdfName( const PdfName & rhs ) : PdfDataType(), m_Data(rhs.m_Data) { } virtual ~PdfName(); /** Write the name to an output device in PDF format. * This is an overloaded member function. * * \param pDevice write the object to this device * \param eWriteMode additional options for writing this object * \param pEncrypt an encryption object which is used to encrypt this object * or NULL to not encrypt this object */ void Write( PdfOutputDevice* pDevice, EPdfWriteMode eWriteMode, const PdfEncrypt* pEncrypt = NULL) const; /** \returns the unescaped value of this name object * without the leading slash */ PODOFO_NOTHROW inline const std::string& GetName() const; /** \returns the unescaped length of this * name object */ PODOFO_NOTHROW inline size_t GetLength() const; /** Assign another name to this object * \param rhs another PdfName object */ PODOFO_NOTHROW inline const PdfName& operator=( const PdfName & rhs ); /** compare to PdfName objects. * \returns true if both PdfNames have the same value. */ PODOFO_NOTHROW inline bool operator==( const PdfName & rhs ) const; /** overloaded operator for convinience * * The string argument is treated as an unescaped name. * * \param rhs a name * \returns true if this objects name is equal to pszName */ bool operator==( const char* rhs ) const; /** overloaded operator for convinience * * The string argument is treated as an unescaped name. * * \param rhs a name * \returns true if this objects name is equal to pszName */ PODOFO_NOTHROW inline bool operator==( const std::string& rhs ) const; /** compare two PdfName objects. * \returns true if both PdfNames have different values. */ PODOFO_NOTHROW inline bool operator!=( const PdfName & rhs ) const; /** overloaded operator for convinience * * The string argument is treated as an unescaped name. * * \param rhs a name * \returns true if this objects name is not equal to pszName */ inline bool operator!=( const char* rhs ) const; /** compare two PdfName objects. * Used for sorting in lists * \returns true if this object is smaller than rhs */ PODOFO_NOTHROW inline bool operator<( const PdfName & rhs ) const; static const PdfName KeyContents; static const PdfName KeyFlags; static const PdfName KeyLength; static const PdfName KeyNull; static const PdfName KeyRect; static const PdfName KeySize; static const PdfName KeySubtype; static const PdfName KeyType; static const PdfName KeyFilter; private: // The _unescaped_ name, without leading / std::string m_Data; }; // ----------------------------------------------------- // // ----------------------------------------------------- const std::string & PdfName::GetName() const { return m_Data; } // ----------------------------------------------------- // // ----------------------------------------------------- size_t PdfName::GetLength() const { return m_Data.length(); } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfName::operator!=( const PdfName & rhs ) const { return !this->operator==( rhs ); } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfName::operator!=( const char* rhs ) const { return !this->operator==( rhs ); } bool PdfName::operator<( const PdfName & rhs ) const { return m_Data < rhs.m_Data; } bool PdfName::operator==( const PdfName & rhs ) const { return ( m_Data == rhs.m_Data ); } bool PdfName::operator==( const std::string & rhs ) const { return ( m_Data == rhs ); } const PdfName& PdfName::operator=( const PdfName & rhs ) { m_Data = rhs.m_Data; return *this; } }; #endif /* _PDF_NAME_H_ */ podofo-0.9.3/src/base/PdfContentsTokenizer.cpp0000664000175000017500000002362112347271543021224 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2007 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfContentsTokenizer.h" #include "PdfCanvas.h" #include "PdfInputDevice.h" #include "PdfOutputStream.h" #include "PdfStream.h" #include "PdfVecObjects.h" #include "PdfData.h" #include "PdfDefinesPrivate.h" #include namespace PoDoFo { PdfContentsTokenizer::PdfContentsTokenizer( PdfCanvas* pCanvas ) : PdfTokenizer(), m_readingInlineImgData(false) { if( !pCanvas ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } PdfObject* pContents = pCanvas->GetContents(); if( pContents && pContents->IsArray() ) { PdfArray& a = pContents->GetArray(); for ( PdfArray::iterator it = a.begin(); it != a.end() ; ++it ) { if ( !(*it).IsReference() ) { PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidDataType, "/Contents array contained non-references" ); } m_lstContents.push_back( pContents->GetOwner()->GetObject( (*it).GetReference() ) ); } } else if ( pContents && pContents->HasStream() ) { m_lstContents.push_back( pContents ); } else if ( pContents && pContents->IsDictionary() ) { m_lstContents.push_back( pContents ); PdfError::LogMessage(eLogSeverity_Information, "PdfContentsTokenizer: found canvas-dictionary without stream => empty page"); // OC 18.09.2010 BugFix: Found an empty page in a PDF document: // 103 0 obj // << // /Type /Page // /MediaBox [ 0 0 595 842 ] // /Parent 3 0 R // /Resources << // /ProcSet [ /PDF ] // >> // /Rotate 0 // >> // endobj } else { PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidDataType, "Page /Contents not stream or array of streams" ); } if( m_lstContents.size() ) { SetCurrentContentsStream( m_lstContents.front() ); m_lstContents.pop_front(); } } void PdfContentsTokenizer::SetCurrentContentsStream( PdfObject* pObject ) { PODOFO_RAISE_LOGIC_IF( pObject == NULL, "Content stream object == NULL!" ); PdfStream* pStream = pObject->GetStream(); PdfRefCountedBuffer buffer; PdfBufferOutputStream stream( &buffer ); pStream->GetFilteredCopy( &stream ); m_device = PdfRefCountedInputDevice( buffer.GetBuffer(), buffer.GetSize() ); } bool PdfContentsTokenizer::GetNextToken( const char*& pszToken , EPdfTokenType* peType ) { bool result = PdfTokenizer::GetNextToken(pszToken, peType); while (!result) { if( !m_lstContents.size() ) return false; SetCurrentContentsStream( m_lstContents.front() ); m_lstContents.pop_front(); result = PdfTokenizer::GetNextToken(pszToken, peType); } return result; } bool PdfContentsTokenizer::ReadNext( EPdfContentsType& reType, const char*& rpszKeyword, PdfVariant & rVariant ) { if (m_readingInlineImgData) return ReadInlineImgData(reType, rpszKeyword, rVariant); EPdfTokenType eTokenType; EPdfDataType eDataType; const char* pszToken; // While officially the keyword pointer is undefined if not needed, it // costs us practically nothing to zero it (in case someone fails to check // the return value and/or reType). Do so. We won't nullify the variant // since that has a real cost. //rpszKeyword = 0; // If we've run out of data in this stream and there's another one to read, // switch to reading the next stream. //if( m_device.Device() && m_device.Device()->Eof() && m_lstContents.size() ) //{ // SetCurrentContentsStream( m_lstContents.front() ); // m_lstContents.pop_front(); //} bool gotToken = this->GetNextToken( pszToken, &eTokenType ); if ( !gotToken ) { if ( m_lstContents.size() ) { // We ran out of tokens in this stream. Switch to the next stream // and try again. SetCurrentContentsStream( m_lstContents.front() ); m_lstContents.pop_front(); return ReadNext( reType, rpszKeyword, rVariant ); } else { // No more content stream tokens to read. return false; } } eDataType = this->DetermineDataType( pszToken, eTokenType, rVariant ); // asume we read a variant unless we discover otherwise later. reType = ePdfContentsType_Variant; switch( eDataType ) { case ePdfDataType_Null: case ePdfDataType_Bool: case ePdfDataType_Number: case ePdfDataType_Real: // the data was already read into rVariant by the DetermineDataType function break; case ePdfDataType_Reference: { // references are invalid in content streams PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidDataType, "references are invalid in content streams" ); break; } case ePdfDataType_Dictionary: this->ReadDictionary( rVariant, NULL ); break; case ePdfDataType_Array: this->ReadArray( rVariant, NULL ); break; case ePdfDataType_String: this->ReadString( rVariant, NULL ); break; case ePdfDataType_HexString: this->ReadHexString( rVariant, NULL ); break; case ePdfDataType_Name: this->ReadName( rVariant ); break; case ePdfDataType_Unknown: case ePdfDataType_RawData: default: // Assume we have a keyword reType = ePdfContentsType_Keyword; rpszKeyword = pszToken; break; } std::string idKW ("ID"); if ((reType == ePdfContentsType_Keyword) && (idKW.compare(rpszKeyword) == 0) ) m_readingInlineImgData = true; return true; } bool PdfContentsTokenizer::ReadInlineImgData( EPdfContentsType& reType, const char*&, PdfVariant & rVariant ) { int c; pdf_int64 counter = 0; if( !m_device.Device() ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } // consume the only whitespace between ID and data c = m_device.Device()->Look(); if( PdfTokenizer::IsWhitespace( c ) ) { c = m_device.Device()->GetChar(); } while((c = m_device.Device()->Look()) != EOF) { c = m_device.Device()->GetChar(); if (c=='E' && m_device.Device()->Look()=='I') { // Consume character m_device.Device()->GetChar(); int w = m_device.Device()->Look(); if (w==EOF || PdfTokenizer::IsWhitespace(w)) { // EI is followed by whitespace => stop m_device.Device()->Seek(-2, std::ios::cur); // put back "EI" m_buffer.GetBuffer()[counter] = '\0'; rVariant = PdfData(m_buffer.GetBuffer(), static_cast(counter)); reType = ePdfContentsType_ImageData; m_readingInlineImgData = false; return true; } else { // no whitespace after EI => do not stop m_device.Device()->Seek(-1, std::ios::cur); // put back "I" m_buffer.GetBuffer()[counter] = c; ++counter; } } else { m_buffer.GetBuffer()[counter] = c; ++counter; } if (counter == static_cast(m_buffer.GetSize())) { // image is larger than buffer => resize buffer m_buffer.Resize(m_buffer.GetSize()*2); } } return false; } }; podofo-0.9.3/src/base/PdfInputStream.cpp0000664000175000017500000001145012344436402017776 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2007 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfInputStream.h" #include "PdfInputDevice.h" #include "PdfDefinesPrivate.h" #include #include #include namespace PoDoFo { PdfFileInputStream::PdfFileInputStream( const char* pszFilename ) { m_hFile = fopen( pszFilename, "rb" ); if( !m_hFile ) { PODOFO_RAISE_ERROR_INFO( ePdfError_FileNotFound, pszFilename ); } } #ifdef _WIN32 PdfFileInputStream::PdfFileInputStream( const wchar_t* pszFilename ) { m_hFile = _wfopen( pszFilename, L"rb" ); if( !m_hFile ) { PdfError e( ePdfError_FileNotFound, __FILE__, __LINE__ ); e.SetErrorInformation( pszFilename ); throw e; } } #endif // _WIN32 PdfFileInputStream::~PdfFileInputStream() { if( m_hFile ) fclose( m_hFile ); } pdf_long PdfFileInputStream::Read( char* pBuffer, pdf_long lLen, pdf_long* ) { if( !pBuffer ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } // return zero if EOF is reached if( feof( m_hFile ) ) return 0; // return the number of bytes read and read the data // into pBuffer return fread( pBuffer, sizeof(char), lLen, m_hFile ); } pdf_long PdfFileInputStream::GetFileLength() { pdf_long lOffset = ftello( m_hFile ); pdf_long lLen; fseeko( m_hFile, 0L, SEEK_END ); lLen = ftello( m_hFile ); fseeko( m_hFile, lOffset, SEEK_SET ); return lLen; } FILE* PdfFileInputStream::GetHandle() { return m_hFile; } PdfMemoryInputStream::PdfMemoryInputStream( const char* pBuffer, pdf_long lBufferLen ) : m_pBuffer( pBuffer ), m_pCur( pBuffer ), m_lBufferLen( lBufferLen ) { } PdfMemoryInputStream::~PdfMemoryInputStream() { } pdf_long PdfMemoryInputStream::Read( char* pBuffer, pdf_long lLen, pdf_long* ) { if( !pBuffer ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } pdf_long lRead = m_pCur - m_pBuffer; // return zero if EOF is reached if( lRead == m_lBufferLen ) return 0; lLen = ( lRead + lLen <= m_lBufferLen ? lLen : m_lBufferLen - lRead ); memcpy( pBuffer, m_pCur, lLen ); m_pCur += lLen; return lLen; } PdfDeviceInputStream::PdfDeviceInputStream( PdfInputDevice* pDevice ) : m_pDevice( pDevice ) { } PdfDeviceInputStream::~PdfDeviceInputStream() { } pdf_long PdfDeviceInputStream::Read( char* pBuffer, pdf_long lLen, pdf_long* ) { return m_pDevice->Read( pBuffer, lLen ); } }; podofo-0.9.3/src/base/PdfImmediateWriter.cpp0000664000175000017500000001565412344436402020630 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2007 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfImmediateWriter.h" #include "PdfFileStream.h" #include "PdfMemStream.h" #include "PdfObject.h" #include "PdfXRef.h" #include "PdfXRefStream.h" #include "PdfDefinesPrivate.h" namespace PoDoFo { PdfImmediateWriter::PdfImmediateWriter( PdfOutputDevice* pDevice, PdfVecObjects* pVecObjects, const PdfObject* pTrailer, EPdfVersion eVersion, PdfEncrypt* pEncrypt, EPdfWriteMode eWriteMode ) : PdfWriter( pVecObjects ), m_pParent( pVecObjects ), m_pDevice( pDevice ), m_pLast( NULL ), m_bOpenStream( false ) { if( m_pTrailer ) delete m_pTrailer; m_pTrailer = new PdfObject( *pTrailer ); // register as observer for PdfVecObjects m_pParent->Attach( this ); // register as stream factory for PdfVecObjects m_pParent->SetStreamFactory( this ); this->CreateFileIdentifier( m_identifier, m_pTrailer ); // setup encryption if( pEncrypt ) { this->SetEncrypted( *pEncrypt ); m_pEncrypt->GenerateEncryptionKey( m_identifier ); } // start with writing the header this->SetPdfVersion( eVersion ); this->SetWriteMode( eWriteMode ); this->WritePdfHeader( m_pDevice ); m_pXRef = m_bXRefStream ? new PdfXRefStream( m_vecObjects, this ) : new PdfXRef(); } PdfImmediateWriter::~PdfImmediateWriter() { if( m_pParent ) m_pParent->Detach( this ); delete m_pXRef; } void PdfImmediateWriter::WriteObject( const PdfObject* pObject ) { const int endObjLenght = 7; this->FinishLastObject(); m_pXRef->AddObject( pObject->Reference(), m_pDevice->Tell(), true ); pObject->WriteObject( m_pDevice, this->GetWriteMode(), m_pEncrypt ); // Make sure, no one will add keys now to the object const_cast(pObject)->SetImmutable(true); // Let's cheat a bit: // pObject has written an "endobj\n" as last data to the file. // we simply overwrite this string with "stream\n" which // has excatly the same length. m_pDevice->Seek( m_pDevice->Tell() - endObjLenght ); m_pDevice->Print( "stream\n" ); m_pLast = const_cast(pObject); } void PdfImmediateWriter::ParentDestructed() { m_pParent = NULL; } void PdfImmediateWriter::Finish() { // write all objects which are still in RAM this->FinishLastObject(); // setup encrypt dictionary if( m_pEncrypt ) { // Add our own Encryption dictionary m_pEncryptObj = m_vecObjects->CreateObject(); m_pEncrypt->CreateEncryptionDictionary( m_pEncryptObj->GetDictionary() ); } this->WritePdfObjects( m_pDevice, *m_pParent, m_pXRef ); // write the XRef pdf_long lXRefOffset = m_pDevice->Tell(); m_pXRef->Write( m_pDevice ); // XRef streams contain the trailer in the XRef if( !m_bXRefStream ) { PdfObject trailer; // if we have a dummy offset we write also a prev entry to the trailer FillTrailerObject( &trailer, m_pXRef->GetSize(), false, false ); m_pDevice->Print("trailer\n"); trailer.WriteObject( m_pDevice, this->GetWriteMode(), NULL ); } m_pDevice->Print( "startxref\n%li\n%%%%EOF\n", lXRefOffset ); m_pDevice->Flush(); // we are done now m_pParent->Detach( this ); m_pParent = NULL; } PdfStream* PdfImmediateWriter::CreateStream( PdfObject* pParent ) { return m_bOpenStream ? static_cast(new PdfMemStream( pParent )) : static_cast(new PdfFileStream( pParent, m_pDevice )); } void PdfImmediateWriter::FinishLastObject() { if( m_pLast ) { m_pDevice->Print( "\nendstream\n" ); m_pDevice->Print( "endobj\n" ); delete m_pParent->RemoveObject( m_pLast->Reference(), false ); m_pLast = NULL; } } void PdfImmediateWriter::BeginAppendStream( const PdfStream* pStream ) { const PdfFileStream* pFileStream = dynamic_cast(pStream ); if( pFileStream ) { // Only one open file stream is allowed at a time assert( !m_bOpenStream ); m_bOpenStream = true; if( m_pEncrypt ) const_cast(pFileStream)->SetEncrypted( m_pEncrypt ); } } void PdfImmediateWriter::EndAppendStream( const PdfStream* pStream ) { const PdfFileStream* pFileStream = dynamic_cast(pStream ); if( pFileStream ) { // A PdfFileStream has to be opened before assert( m_bOpenStream ); m_bOpenStream = false; } } }; podofo-0.9.3/src/base/PdfXRefStreamParserObject.cpp0000664000175000017500000002275612347347566022101 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2009 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfXRefStreamParserObject.h" #include "PdfArray.h" #include "PdfDictionary.h" #include "PdfStream.h" #include "PdfVariant.h" #include namespace PoDoFo { PdfXRefStreamParserObject::PdfXRefStreamParserObject(PdfVecObjects* pCreator, const PdfRefCountedInputDevice & rDevice, const PdfRefCountedBuffer & rBuffer, PdfParser::TVecOffsets* pOffsets ) : PdfParserObject( pCreator, rDevice, rBuffer ), m_lNextOffset(-1L), m_pOffsets( pOffsets ) { } PdfXRefStreamParserObject::~PdfXRefStreamParserObject() { } void PdfXRefStreamParserObject::Parse() { // Ignore the encryption in the XREF as the XREF stream must no be encrypted (see PDF Reference 3.4.7) this->ParseFile( NULL ); // Do some very basic error checking if( !this->GetDictionary().HasKey( PdfName::KeyType ) ) { PODOFO_RAISE_ERROR( ePdfError_NoXRef ); } PdfObject* pObj = this->GetDictionary().GetKey( PdfName::KeyType ); if( !pObj->IsName() || ( pObj->GetName() != "XRef" ) ) { PODOFO_RAISE_ERROR( ePdfError_NoXRef ); } if( !this->GetDictionary().HasKey( PdfName::KeySize ) || !this->GetDictionary().HasKey( "W" ) ) { PODOFO_RAISE_ERROR( ePdfError_NoXRef ); } if( !this->HasStreamToParse() ) { PODOFO_RAISE_ERROR( ePdfError_NoXRef ); } if( this->GetDictionary().HasKey("Prev") ) { m_lNextOffset = static_cast(this->GetDictionary().GetKeyAsLong( "Prev", 0 )); } } void PdfXRefStreamParserObject::ReadXRefTable() { pdf_int64 lSize = this->GetDictionary().GetKeyAsLong( PdfName::KeySize, 0 ); PdfVariant vWArray = *(this->GetDictionary().GetKey( "W" )); // The pdf reference states that W is always an array with 3 entries // all of them have to be integers if( !vWArray.IsArray() || vWArray.GetArray().size() != 3 ) { PODOFO_RAISE_ERROR( ePdfError_NoXRef ); } pdf_int64 nW[W_ARRAY_SIZE] = { 0, 0, 0 }; for( int i=0;i(vWArray.GetArray()[i].GetNumber()); } std::vector vecIndeces; GetIndeces( vecIndeces, static_cast(lSize) ); ParseStream( nW, vecIndeces ); } void PdfXRefStreamParserObject::ParseStream( const pdf_int64 nW[W_ARRAY_SIZE], const std::vector & rvecIndeces ) { char* pBuffer; pdf_long lBufferLen; const size_t entryLen = static_cast(nW[0] + nW[1] + nW[2]); this->GetStream()->GetFilteredCopy( &pBuffer, &lBufferLen ); std::vector::const_iterator it = rvecIndeces.begin(); char* const pStart = pBuffer; while( it != rvecIndeces.end() ) { pdf_int64 nFirstObj = *it; ++it; pdf_int64 nCount = *it; ++it; //pdf_int64 nFirstObjOrg = nFirstObj; //pdf_int64 nCountOrg = nCount; //printf("\n"); //printf("nFirstObj=%i\n", static_cast(nFirstObj)); //printf("nCount=%i\n", static_cast(nCount)); while( nCount > 0 ) { if( (pBuffer - pStart) >= lBufferLen ) { PODOFO_RAISE_ERROR_INFO( ePdfError_NoXRef, "Invalid count in XRef stream" ); } //printf("nCount=%i ", static_cast(nCount)); //printf("pBuffer=%li ", (long)(pBuffer - pStart)); //printf("pEnd=%li ", lBufferLen); if ( nFirstObj >= 0 && nFirstObj < static_cast(m_pOffsets->size()) && ! (*m_pOffsets)[static_cast(nFirstObj)].bParsed) { ReadXRefStreamEntry( pBuffer, lBufferLen, nW, static_cast(nFirstObj) ); } nFirstObj++ ; pBuffer += entryLen; --nCount; } //printf("Exp: nFirstObj=%i nFirstObjOrg + nCount=%i\n", nFirstObj - 1, nFirstObjOrg + nCountOrg - 1 ); //printf("===\n"); } podofo_free( pStart ); } void PdfXRefStreamParserObject::GetIndeces( std::vector & rvecIndeces, pdf_int64 size ) { // get the first object number in this crossref stream. // it is not required to have an index key though. if( this->GetDictionary().HasKey( "Index" ) ) { PdfVariant array = *(this->GetDictionary().GetKey( "Index" )); if( !array.IsArray() ) { PODOFO_RAISE_ERROR( ePdfError_NoXRef ); } TCIVariantList it = array.GetArray().begin(); while ( it != array.GetArray().end() ) { rvecIndeces.push_back( (*it).GetNumber() ); ++it; } } else { // Default rvecIndeces.push_back( static_cast(0) ); rvecIndeces.push_back( size ); } // vecIndeces must be a multiple of 2 if( rvecIndeces.size() % 2 != 0) { PODOFO_RAISE_ERROR( ePdfError_NoXRef ); } } void PdfXRefStreamParserObject::ReadXRefStreamEntry( char* pBuffer, pdf_long, const pdf_int64 lW[W_ARRAY_SIZE], int nObjNo ) { int i; pdf_int64 z; unsigned long nData[W_ARRAY_SIZE]; for( i=0;i W_MAX_BYTES ) { PdfError::LogMessage( eLogSeverity_Error, "The XRef stream dictionary has an entry in /W of size %i.\nThe maximum supported value is %i.\n", lW[i], W_MAX_BYTES ); PODOFO_RAISE_ERROR( ePdfError_InvalidXRefStream ); } nData[i] = 0; for( z=W_MAX_BYTES-lW[i];z(*pBuffer); ++pBuffer; } } //printf("OBJ=%i nData = [ %i %i %i ]\n", nObjNo, static_cast(nData[0]), static_cast(nData[1]), static_cast(nData[2]) ); (*m_pOffsets)[nObjNo].bParsed = true; switch( nData[0] ) // nData[0] contains the type information of this entry { case 0: // a free object (*m_pOffsets)[nObjNo].lOffset = nData[1]; (*m_pOffsets)[nObjNo].lGeneration = nData[2]; (*m_pOffsets)[nObjNo].cUsed = 'f'; break; case 1: // normal uncompressed object (*m_pOffsets)[nObjNo].lOffset = nData[1]; (*m_pOffsets)[nObjNo].lGeneration = nData[2]; (*m_pOffsets)[nObjNo].cUsed = 'n'; break; case 2: // object that is part of an object stream (*m_pOffsets)[nObjNo].lOffset = nData[2]; // index in the object stream (*m_pOffsets)[nObjNo].lGeneration = nData[1]; // object number of the stream (*m_pOffsets)[nObjNo].cUsed = 's'; // mark as stream break; default: { PODOFO_RAISE_ERROR( ePdfError_InvalidXRefType ); } } //printf("m_offsets = [ %i %i %c ]\n", (*m_pOffsets)[nObjNo].lOffset, (*m_pOffsets)[nObjNo].lGeneration, (*m_pOffsets)[nObjNo].cUsed ); } }; podofo-0.9.3/src/base/PdfLocale.cpp0000664000175000017500000000150211460071654016721 0ustar dominikdominik#include "PdfDefines.h" #include "PdfLocale.h" #include "PdfError.h" #include "PdfDefinesPrivate.h" #include #include #include namespace PoDoFo { void PdfLocaleImbue(std::ios_base& s) { #if USE_CXX_LOCALE static const std::locale cachedLocale( PdfIOLocale ); try { s.imbue( cachedLocale ); } catch (const std::runtime_error & e) { std::ostringstream s; s << "Failed to set safe locale on stream being used for PDF I/O."; s << "Locale set was: \"" << PdfIOLocale << "\"."; s << "Error reported by STL std::locale: \"" << e.what() << "\""; // The info string is copied by PdfError so we're ok to just: PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidDeviceOperation, s.str().c_str() ); } #endif } }; podofo-0.9.3/src/base/PdfXRefStream.h0000664000175000017500000001332112344436402017207 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2007 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_XREF_STREAM_H_ #define _PDF_XREF_STREAM_H_ #include "PdfDefines.h" #include "PdfArray.h" #include "PdfXRef.h" namespace PoDoFo { class PdfOutputDevice; class PdfVecObjects; class PdfWriter; /** * Creates an XRef table that is a stream object. * Requires at least PDF 1.5. XRef streams are more * compact than normal XRef tables. * * This is an internal class of PoDoFo used by PdfWriter. */ class PdfXRefStream : public PdfXRef { public: /** Create a new XRef table * * \param pParent a vector of PdfObject is required * to create a PdfObject for the XRef * \param pWriter is needed to fill the trailer directory * correctly which is included into the XRef */ PdfXRefStream( PdfVecObjects* pParent, PdfWriter* pWriter ); /** Destruct the XRef table */ virtual ~PdfXRefStream(); /** * \returns the offset in the file at which the XRef table * starts after it was written */ inline virtual pdf_uint64 GetOffset() const; protected: /** Called at the start of writing the XRef table. * This method can be overwritten in subclasses * to write a general header for the XRef table. * * @param pDevice the output device to which the XRef table * should be written. */ virtual void BeginWrite( PdfOutputDevice* pDevice ); /** Begin an XRef subsection. * All following calls of WriteXRefEntry belong to this XRef subsection. * * @param pDevice the output device to which the XRef table * should be written. * @param nFirst the object number of the first object in this subsection * @param nCount the number of entries in this subsection */ virtual void WriteSubSection( PdfOutputDevice* pDevice, pdf_objnum nFirst, pdf_uint32 nCount ); /** Write a single entry to the XRef table * * @param pDevice the output device to which the XRef table * should be written. * @param offset the offset of the object * @param generation the generation number * @param cMode the mode 'n' for object and 'f' for free objects * @param objectNumber the object number of the currently written object if cMode = 'n' * otherwise undefined */ virtual void WriteXRefEntry( PdfOutputDevice* pDevice, pdf_uint64 offset, pdf_gennum generation, char cMode, pdf_objnum objectNumber = 0 ); /** Called at the end of writing the XRef table. * Sub classes can overload this method to finish a XRef table. * * @param pDevice the output device to which the XRef table * should be written. */ virtual void EndWrite( PdfOutputDevice* pDevice ); private: PdfVecObjects* m_pParent; PdfWriter* m_pWriter; PdfObject* m_pObject; PdfArray m_indeces; size_t m_bufferLen; ///< The length of the internal buffer for one XRef entry pdf_uint64 m_offset; ///< Offset of the XRefStream object }; // ----------------------------------------------------- // // ----------------------------------------------------- inline pdf_uint64 PdfXRefStream::GetOffset() const { return m_offset; } }; #endif /* _PDF_XREF_H_ */ podofo-0.9.3/src/base/PdfXRef.h0000664000175000017500000002034512262234754016044 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2007 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_XREF_H_ #define _PDF_XREF_H_ #include "PdfDefines.h" #include "PdfReference.h" namespace PoDoFo { #define EMPTY_OBJECT_OFFSET 65535 class PdfOutputDevice; /** * Creates an XRef table. * * This is an internal class of PoDoFo used by PdfWriter. */ class PdfXRef { protected: struct TXRefItem{ TXRefItem( const PdfReference & rRef, const pdf_uint64 & off ) : reference( rRef ), offset( off ) { } PdfReference reference; pdf_uint64 offset; bool operator<( const TXRefItem & rhs ) const { return this->reference < rhs.reference; } }; typedef std::vector TVecXRefItems; typedef TVecXRefItems::iterator TIVecXRefItems; typedef TVecXRefItems::const_iterator TCIVecXRefItems; typedef std::vector TVecReferences; typedef TVecReferences::iterator TIVecReferences; typedef TVecReferences::const_iterator TCIVecReferences; class PdfXRefBlock { public: PdfXRefBlock() : m_nFirst( 0 ), m_nCount( 0 ) { } PdfXRefBlock( const PdfXRefBlock & rhs ) : m_nFirst( 0 ), m_nCount( 0 ) { this->operator=( rhs ); } bool InsertItem( const TXRefItem & rItem, bool bUsed ); bool operator<( const PdfXRefBlock & rhs ) const { return m_nFirst < rhs.m_nFirst; } const PdfXRefBlock & operator=( const PdfXRefBlock & rhs ) { m_nFirst = rhs.m_nFirst; m_nCount = rhs.m_nCount; items = rhs.items; freeItems = rhs.freeItems; return *this; } pdf_objnum m_nFirst; pdf_uint32 m_nCount; TVecXRefItems items; TVecReferences freeItems; }; typedef std::vector TVecXRefBlock; typedef TVecXRefBlock::iterator TIVecXRefBlock; typedef TVecXRefBlock::const_iterator TCIVecXRefBlock; public: /** Create a new XRef table */ PdfXRef(); /** Destruct the XRef table */ virtual ~PdfXRef(); /** Add an object to the XRef table. * The object should have been written to an output device already. * * \param rRef reference of this object * \param offset the offset where on the device the object was written * \param bUsed specifies wether this is an used or free object. * Set this value to true for all normal objects and to false * for free object references. */ void AddObject( const PdfReference & rRef, pdf_uint64 offset, bool bUsed ); /** Write the XRef table to an output device. * * \param pDevice an output device (usually a PDF file) * */ void Write( PdfOutputDevice* pDevice ); /** Get the size of the XRef table. * I.e. the highest object number + 1. * * \returns the size of the xref table */ pdf_uint32 GetSize() const; /** * \returns the offset in the file at which the XRef table * starts after it was written */ inline virtual pdf_uint64 GetOffset() const; /** * Mark as empty block. */ void SetFirstEmptyBlock(); protected: /** Called at the start of writing the XRef table. * This method can be overwritten in subclasses * to write a general header for the XRef table. * * @param pDevice the output device to which the XRef table * should be written. */ virtual void BeginWrite( PdfOutputDevice* pDevice ); /** Begin an XRef subsection. * All following calls of WriteXRefEntry belong to this XRef subsection. * * @param pDevice the output device to which the XRef table * should be written. * @param nFirst the object number of the first object in this subsection * @param nCount the number of entries in this subsection */ virtual void WriteSubSection( PdfOutputDevice* pDevice, pdf_objnum nFirst, pdf_uint32 nCount ); /** Write a single entry to the XRef table * * @param pDevice the output device to which the XRef table * should be written. * @param offset the offset of the object * @param generation the generation number * @param cMode the mode 'n' for object and 'f' for free objects * @param objectNumber the object number of the currently written object if cMode = 'n' * otherwise undefined */ virtual void WriteXRefEntry( PdfOutputDevice* pDevice, pdf_uint64 offset, pdf_gennum generation, char cMode, pdf_objnum objectNumber = 0 ); /** Called at the end of writing the XRef table. * Sub classes can overload this method to finish a XRef table. * * @param pDevice the output device to which the XRef table * should be written. */ virtual void EndWrite( PdfOutputDevice* pDevice ); private: const PdfReference* GetFirstFreeObject( PdfXRef::TCIVecXRefBlock itBlock, PdfXRef::TCIVecReferences itFree ) const; const PdfReference* GetNextFreeObject( PdfXRef::TCIVecXRefBlock itBlock, PdfXRef::TCIVecReferences itFree ) const; /** Merge all xref blocks that follow immediately after each other * into a single block. * * This results in slitely smaller PDF files which are easier to parse * for other applications. */ void MergeBlocks(); private: pdf_uint64 m_offset; protected: TVecXRefBlock m_vecBlocks; }; // ----------------------------------------------------- // // ----------------------------------------------------- inline pdf_uint64 PdfXRef::GetOffset() const { return m_offset; } }; #endif /* _PDF_XREF_H_ */ podofo-0.9.3/src/base/PdfCanvas.cpp0000664000175000017500000001327412347347566016763 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2006 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfCanvas.h" #include "PdfDictionary.h" #include "PdfName.h" #include "PdfColor.h" #include "PdfStream.h" #include "PdfDefinesPrivate.h" namespace PoDoFo { PdfArray PdfCanvas::s_procset; const PdfArray & PdfCanvas::GetProcSet() { if( s_procset.empty() ) { s_procset.push_back( PdfName( "PDF" ) ); s_procset.push_back( PdfName( "Text" ) ); s_procset.push_back( PdfName( "ImageB" ) ); s_procset.push_back( PdfName( "ImageC" ) ); s_procset.push_back( PdfName( "ImageI" ) ); } return s_procset; } void PdfCanvas::AddColorResource( const PdfColor & rColor ) { PdfObject* pResource = GetResources(); if( !pResource ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } switch( rColor.GetColorSpace() ) { case ePdfColorSpace_Separation: { std::string csPrefix( "ColorSpace" ); std::string csName = rColor.GetName(); std::string temp( csPrefix + csName ); if ( ! pResource->GetDictionary().HasKey( "ColorSpace" ) || ! pResource->GetDictionary().GetKey( "ColorSpace" )->GetDictionary().HasKey( csPrefix + csName ) ) { // Build color-spaces for separation PdfObject* csp = rColor.BuildColorSpace( GetContents()->GetOwner() ); AddResource( csPrefix + csName, csp->Reference(), PdfName("ColorSpace") ); } } break; case ePdfColorSpace_CieLab: { if ( ! pResource->GetDictionary().HasKey( "ColorSpace" ) || ! pResource->GetDictionary().GetKey( "ColorSpace" )->GetDictionary().HasKey( "ColorSpaceLab" ) ) { // Build color-spaces for CIE-lab PdfObject* csp = rColor.BuildColorSpace( GetContents()->GetOwner() ); AddResource( "ColorSpaceCieLab", csp->Reference(), PdfName("ColorSpace") ); } } break; case ePdfColorSpace_DeviceGray: case ePdfColorSpace_DeviceRGB: case ePdfColorSpace_DeviceCMYK: case ePdfColorSpace_Indexed: // No colorspace needed case ePdfColorSpace_Unknown: default: break; } } void PdfCanvas::AddResource( const PdfName & rIdentifier, const PdfReference & rRef, const PdfName & rName ) { if( !rName.GetLength() || !rIdentifier.GetLength() ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } PdfObject* pResource = this->GetResources(); if( !pResource ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } if( !pResource->GetDictionary().HasKey( rName ) ) { pResource->GetDictionary().AddKey( rName, PdfDictionary() ); } // Peter Petrov: 18 December 2008. Bug fix if (ePdfDataType_Reference == pResource->GetDictionary().GetKey( rName )->GetDataType()) { PdfObject *directObject = pResource->GetOwner()->GetObject(pResource->GetDictionary().GetKey( rName )->GetReference()); if (0 == directObject) { PODOFO_RAISE_ERROR( ePdfError_NoObject ); } if( !directObject->GetDictionary().HasKey( rIdentifier ) ) directObject->GetDictionary().AddKey( rIdentifier, rRef ); }else { if( !pResource->GetDictionary().GetKey( rName )->GetDictionary().HasKey( rIdentifier ) ) pResource->GetDictionary().GetKey( rName )->GetDictionary().AddKey( rIdentifier, rRef ); } } }; podofo-0.9.3/src/base/PdfVariant.cpp0000664000175000017500000003410612347275256017145 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2005 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfVariant.h" #include "PdfArray.h" #include "PdfData.h" #include "PdfDictionary.h" #include "PdfOutputDevice.h" #include "PdfParserObject.h" #include "PdfDefinesPrivate.h" #include #include namespace PoDoFo { using namespace std; PdfVariant PdfVariant::NullValue; // Do one-off initialization that should not be repeated // in the Clear() method. Mostly useful for internal sanity checks. inline void PdfVariant::Init() { // DS: These members will be set in ::Clear() // which is called by every constructor. // m_bDelayedLoadDone = true; // m_bDirty = false; // Has to be done in Init so that Clear() works // and can delete data if necessary memset( &m_Data, 0, sizeof( UVariant ) ); // Has to be set as Clear() depends on it m_eDataType = ePdfDataType_Null; m_bImmutable = false; #if defined(PODOFO_EXTRA_CHECKS) m_bDelayedLoadInProgress=false; #endif } PdfVariant::PdfVariant() { Init(); Clear(); m_eDataType = ePdfDataType_Null; } PdfVariant::PdfVariant( bool b ) { Init(); Clear(); m_eDataType = ePdfDataType_Bool; m_Data.bBoolValue = b; } PdfVariant::PdfVariant( pdf_int64 l ) { Init(); Clear(); m_eDataType = ePdfDataType_Number; m_Data.nNumber = l; } PdfVariant::PdfVariant( double d ) { Init(); Clear(); m_eDataType = ePdfDataType_Real; m_Data.dNumber = d; } PdfVariant::PdfVariant( const PdfString & rsString ) { Init(); Clear(); m_eDataType = rsString.IsHex() ? ePdfDataType_HexString : ePdfDataType_String; m_Data.pData = new PdfString( rsString ); } PdfVariant::PdfVariant( const PdfName & rName ) { Init(); Clear(); m_eDataType = ePdfDataType_Name; m_Data.pData = new PdfName( rName ); } PdfVariant::PdfVariant( const PdfReference & rRef ) { Init(); Clear(); m_eDataType = ePdfDataType_Reference; m_Data.pData = new PdfReference( rRef ); } PdfVariant::PdfVariant( const PdfArray & rArray ) { Init(); Clear(); m_eDataType = ePdfDataType_Array; m_Data.pData = new PdfArray( rArray ); } PdfVariant::PdfVariant( const PdfDictionary & rObj ) { Init(); Clear(); m_eDataType = ePdfDataType_Dictionary; m_Data.pData = new PdfDictionary( rObj ); } PdfVariant::PdfVariant( const PdfData & rData ) { Init(); Clear(); m_eDataType = ePdfDataType_RawData; m_Data.pData = new PdfData( rData ); } PdfVariant::PdfVariant( const PdfVariant & rhs ) { Init(); this->operator=(rhs); SetDirty( false ); } PdfVariant::~PdfVariant() { m_bImmutable = false; // Destructor may change things, i.e. delete Clear(); } void PdfVariant::Clear() { switch( m_eDataType ) { case ePdfDataType_Array: case ePdfDataType_Reference: case ePdfDataType_Dictionary: case ePdfDataType_Name: case ePdfDataType_String: case ePdfDataType_HexString: case ePdfDataType_RawData: { if( m_Data.pData ) delete m_Data.pData; break; } case ePdfDataType_Bool: case ePdfDataType_Null: case ePdfDataType_Number: case ePdfDataType_Real: case ePdfDataType_Unknown: default: break; } m_bDelayedLoadDone = true; #if defined(PODOFO_EXTRA_CHECKS) m_bDelayedLoadInProgress = false; #endif m_bDirty = false; m_eDataType = ePdfDataType_Null; m_bImmutable = false; memset( &m_Data, 0, sizeof( UVariant ) ); } void PdfVariant::Write( PdfOutputDevice* pDevice, EPdfWriteMode eWriteMode, const PdfEncrypt* pEncrypt ) const { this->Write( pDevice, eWriteMode, pEncrypt, PdfName::KeyNull ); } void PdfVariant::Write( PdfOutputDevice* pDevice, EPdfWriteMode eWriteMode, const PdfEncrypt* pEncrypt, const PdfName & keyStop ) const { DelayedLoad(); /* Check all handles first */ if( (m_eDataType == ePdfDataType_HexString || m_eDataType == ePdfDataType_String || m_eDataType == ePdfDataType_Array || m_eDataType == ePdfDataType_Dictionary || m_eDataType == ePdfDataType_Name || m_eDataType == ePdfDataType_RawData ) && !m_Data.pData ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } switch( m_eDataType ) { case ePdfDataType_Bool: { if( (eWriteMode & ePdfWriteMode_Compact) == ePdfWriteMode_Compact ) { pDevice->Write( " ", 1 ); // Write space before true or false } if( m_Data.bBoolValue ) pDevice->Write( "true", 4 ); else pDevice->Write( "false", 5 ); break; } case ePdfDataType_Number: { if( (eWriteMode & ePdfWriteMode_Compact) == ePdfWriteMode_Compact ) { pDevice->Write( " ", 1 ); // Write space before numbers } #ifdef _WIN64 pDevice->Print( "%" PDF_FORMAT_INT64, m_Data.nNumber ); #else pDevice->Print( "%" PDF_FORMAT_INT64, m_Data.nNumber ); #endif break; } case ePdfDataType_Real: //pDevice->Print( "%g", m_Data.dNumber ); // DominikS: %g precision might write floating points // numbers in exponential form (with e) // which is not supported in PDF. // %f fixes this but might loose precision as // it defaults to a precision of 6 // pDevice->Print( "%f", m_Data.dNumber ); { if( (eWriteMode & ePdfWriteMode_Compact) == ePdfWriteMode_Compact ) { pDevice->Write( " ", 1 ); // Write space before numbers } // Use ostringstream, so that locale does not matter std::ostringstream oss; PdfLocaleImbue(oss); oss << std::fixed << m_Data.dNumber; std::string copy = oss.str(); size_t len = copy.size(); if( (eWriteMode & ePdfWriteMode_Compact) == ePdfWriteMode_Compact && copy.find('.') != string::npos ) { const char *str = copy.c_str(); while( str[len - 1] == '0' ) --len; if( str[len - 1] == '.' ) --len; if( len == 0 ) { pDevice->Write( "0", 1 ); break; } } pDevice->Write( copy.c_str(), len ); break; } case ePdfDataType_HexString: case ePdfDataType_String: case ePdfDataType_Name: case ePdfDataType_Array: case ePdfDataType_Reference: case ePdfDataType_RawData: m_Data.pData->Write( pDevice, eWriteMode, pEncrypt ); break; case ePdfDataType_Dictionary: static_cast(m_Data.pData)->Write( pDevice, eWriteMode, pEncrypt, keyStop ); break; case ePdfDataType_Null: { if( (eWriteMode & ePdfWriteMode_Compact) == ePdfWriteMode_Compact ) { pDevice->Write( " ", 1 ); // Write space before null } pDevice->Print( "null" ); break; } case ePdfDataType_Unknown: default: { PODOFO_RAISE_ERROR( ePdfError_InvalidDataType ); break; } }; } void PdfVariant::ToString( std::string & rsData, EPdfWriteMode eWriteMode ) const { ostringstream out; // We don't need to this stream with the safe PDF locale because // PdfOutputDevice will do so for us. PdfOutputDevice device( &out ); this->Write( &device, eWriteMode, NULL ); rsData = out.str(); } const PdfVariant & PdfVariant::operator=( const PdfVariant & rhs ) { Clear(); rhs.DelayedLoad(); m_eDataType = rhs.m_eDataType; switch( m_eDataType ) { case ePdfDataType_Array: { if( rhs.m_Data.pData ) m_Data.pData = new PdfArray( *(static_cast(rhs.m_Data.pData)) ); break; } case ePdfDataType_Reference: { if( rhs.m_Data.pData ) m_Data.pData = new PdfReference( *(static_cast(rhs.m_Data.pData)) ); break; } case ePdfDataType_Dictionary: { if( rhs.m_Data.pData ) m_Data.pData = new PdfDictionary( *(static_cast(rhs.m_Data.pData)) ); break; } case ePdfDataType_Name: { if( rhs.m_Data.pData ) m_Data.pData = new PdfName( *(static_cast(rhs.m_Data.pData)) ); break; } case ePdfDataType_String: case ePdfDataType_HexString: { if( rhs.m_Data.pData ) m_Data.pData = new PdfString( *(static_cast(rhs.m_Data.pData)) ); break; } case ePdfDataType_RawData: { if( rhs.m_Data.pData ) m_Data.pData = new PdfData( *(static_cast(rhs.m_Data.pData)) ); break; } case ePdfDataType_Bool: case ePdfDataType_Null: case ePdfDataType_Number: case ePdfDataType_Real: m_Data = rhs.m_Data; break; case ePdfDataType_Unknown: default: break; }; SetDirty( true ); return (*this); } const char * PdfVariant::GetDataTypeString() const { switch(GetDataType()) { case ePdfDataType_Bool: return "Bool"; case ePdfDataType_Number: return "Number"; case ePdfDataType_Real: return "Real"; case ePdfDataType_String: return "String"; case ePdfDataType_HexString: return "HexString"; case ePdfDataType_Name: return "Name"; case ePdfDataType_Array: return "Array"; case ePdfDataType_Dictionary: return "Dictionary"; case ePdfDataType_Null: return "Null"; case ePdfDataType_Reference: return "Reference"; case ePdfDataType_RawData: return "RawData"; case ePdfDataType_Unknown: return "Unknown"; } return "INVALID_TYPE_ENUM"; } // // This is rather slow: // - We set up to catch an exception // - We throw & catch an exception whenever there's a type mismatch // bool PdfVariant::operator==( const PdfVariant & rhs ) const { DelayedLoad(); try { switch (m_eDataType) { case ePdfDataType_Bool: return GetBool() == rhs.GetBool(); case ePdfDataType_Number: return GetNumber() == rhs.GetNumber(); case ePdfDataType_Real: return GetReal() == rhs.GetReal(); case ePdfDataType_String: return GetString() == rhs.GetString(); case ePdfDataType_HexString: return GetString() == rhs.GetString(); case ePdfDataType_Name: return GetName() == rhs.GetName(); case ePdfDataType_Array: return GetArray() == rhs.GetArray(); case ePdfDataType_Dictionary: return GetDictionary() == rhs.GetDictionary(); case ePdfDataType_Null: return rhs.IsNull(); case ePdfDataType_Reference: return GetReference() == rhs.GetReference(); case ePdfDataType_RawData: /* fall through to end of func */ break; case ePdfDataType_Unknown: /* fall through to end of func */ break; } } catch ( PdfError& e ) { if (e.GetError() == ePdfError_InvalidDataType) return false; else throw e; } PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidDataType, "Tried to compare unknown/raw variant" ); } }; podofo-0.9.3/src/base/PdfInputStream.h0000664000175000017500000001452112344436402017445 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2007 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_INPUT_STREAM_H_ #define _PDF_INPUT_STREAM_H_ #include "PdfDefines.h" namespace PoDoFo { class PdfInputDevice; /** An interface for reading blocks of data from an * a data source. */ class PODOFO_API PdfInputStream { public: virtual ~PdfInputStream() { }; /** Read data from the input stream * * \param pBuffer the data will be stored into this buffer * \param lLen the size of the buffer and number of bytes * that will be read * \param pTotalLeft total bytes left (needed for AES IV and padding) * * \returns the number of bytes read, -1 if an error ocurred * and zero if no more bytes are available for reading. */ virtual pdf_long Read( char* pBuffer, pdf_long lLen, pdf_long *pTotalLeft = 0 ) = 0; }; /** An input stream that reads data from a file */ class PODOFO_API PdfFileInputStream : public PdfInputStream { public: /** Open a file for reading data * * \param pszFilename the filename of the file to read */ PdfFileInputStream( const char* pszFilename ); #ifdef _WIN32 /** Open a file for reading data * * \param pszFilename the filename of the file to read * * This is an overloaded member function to allow working * with unicode characters. On Unix systes you can also path * UTF-8 to the const char* overload. */ PdfFileInputStream( const wchar_t* pszFilename ); #endif // _WIN32 ~PdfFileInputStream(); /** Read data from the input stream * * \param pBuffer the data will be stored into this buffer * \param lLen the size of the buffer and number of bytes * that will be read * * \returns the number of bytes read, -1 if an error ocurred * and zero if no more bytes are available for reading. */ virtual pdf_long Read( char* pBuffer, pdf_long lLen, pdf_long* = 0 ); /** Get the length of the file. * \return the file length */ pdf_long GetFileLength(); /** Get the internal FILE handle. * \return the internal FILE handle */ FILE* GetHandle(); private: FILE* m_hFile; }; /** An input stream that reads data from a memory buffer */ class PODOFO_API PdfMemoryInputStream : public PdfInputStream { public: /** Open a file for reading data * * \param pBuffer buffer to read from * \param lBufferLen length of the buffer */ PdfMemoryInputStream( const char* pBuffer, pdf_long lBufferLen ); ~PdfMemoryInputStream(); /** Read data from the input stream * * \param pBuffer the data will be stored into this buffer * \param lLen the size of the buffer and number of bytes * that will be read * * \returns the number of bytes read, -1 if an error ocurred * and zero if no more bytes are available for reading. */ virtual pdf_long Read( char* pBuffer, pdf_long lLen, pdf_long* ); private: const char* m_pBuffer; const char* m_pCur; pdf_long m_lBufferLen; }; /** An input stream that reads data from an input device */ class PODOFO_API PdfDeviceInputStream : public PdfInputStream { public: /** * Read from an alread opened input device * * \param pDevice an input device */ PdfDeviceInputStream( PdfInputDevice* pDevice ); ~PdfDeviceInputStream(); /** Read data from the input stream * * \param pBuffer the data will be stored into this buffer * \param lLen the size of the buffer and number of bytes * that will be read * * \returns the number of bytes read, -1 if an error ocurred * and zero if no more bytes are available for reading. */ virtual pdf_long Read( char* pBuffer, pdf_long lLen, pdf_long* ); private: PdfInputDevice* m_pDevice; }; }; #endif // _PDF_INPUT_STREAM_H_ podofo-0.9.3/src/base/PdfContentsTokenizer.h0000664000175000017500000001432312344436402020662 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2007 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_CONTENTS_TOKENIZER_H_ #define _PDF_CONTENTS_TOKENIZER_H_ #include "PdfDefines.h" #include "PdfTokenizer.h" #include "PdfVariant.h" #include namespace PoDoFo { class PdfDocument; class PdfCanvas; class PdfObject; /** An enum describing the type of a read token */ enum EPdfContentsType { ePdfContentsType_Keyword, /**< The token is a PDF keyword. */ ePdfContentsType_Variant, /**< The token is a PDF variant. A variant is usually a parameter to a keyword */ ePdfContentsType_ImageData /**< The "token" is raw inline image data found between ID and EI tags (see PDF ref section 4.8.6) */ }; /** This class is a parser for content streams in PDF documents. * * The parsed content stream can be used and modified in various ways. * * This class is currently work in progress and subject to change! */ class PODOFO_API PdfContentsTokenizer : public PdfTokenizer { public: /** Construct a PdfContentsTokenizer from an existing buffer. * Usually a stream from a PdfPage. * * \param pBuffer pointer to a buffer * \param lLen length of the buffer */ PdfContentsTokenizer( const char* pBuffer, long lLen ) : PoDoFo::PdfTokenizer( pBuffer, lLen ), m_readingInlineImgData(false) { } /** Construct a PdfContentsTokenizer from a PdfCanvas * (i.e. PdfPage or a PdfXObject). * * This is more convinient as you do not have * to care about buffers yourself. * * \param pCanvas an object that hold a PDF contents stream */ PdfContentsTokenizer( PdfCanvas* pCanvas ); virtual ~PdfContentsTokenizer() { } /** Read the next keyword or variant, returning true and setting reType if something was read. * Either rpszKeyword or rVariant, but never both, have defined and usable values on * true return, with which being controlled by the value of eType. * * If EOF is encountered, returns false and leaves eType, pszKeyword and * rVariant undefined. * * As a special case, reType may be set to ePdfContentsType_ImageData. In * this case rpszzKeyword is undefined, and rVariant contains a PdfData * variant containing the byte sequence between the ID and BI keywords * sans the one byte of leading- and trailing- white space. No filter * decoding is performed. * * \param[out] reType will be set to either keyword or variant if true is returned. Undefined * if false is returned. * * \param[out] rpszKeyword if pType is set to ePdfContentsType_Keyword this will point to the keyword, * otherwise the value is undefined. If set, the value points to memory owned by the * PdfContentsTokenizer and must not be freed. The value is invalidated when ReadNext * is next called or when the PdfContentsTokenizer is destroyed. * * \param[out] rVariant if pType is set to ePdfContentsType_Variant or ePdfContentsType_ImageData * this will be set to the read variant, otherwise the value is undefined. * */ bool ReadNext( EPdfContentsType& reType, const char*& rpszKeyword, PoDoFo::PdfVariant & rVariant ); bool GetNextToken( const char *& pszToken, EPdfTokenType* peType = NULL); private: /** Set another objects stream as the current stream for parsing * * \param pObject use the stream of this object for parsing */ void SetCurrentContentsStream( PdfObject* pObject ); bool ReadInlineImgData(EPdfContentsType& reType, const char*& rpszKeyword, PoDoFo::PdfVariant & rVariant); private: std::list m_lstContents; ///< A list containing pointers to all contents objects bool m_readingInlineImgData; ///< A state of reading inline image data }; }; #endif // _PDF_CONTENTS_TOKENIZER_H_ podofo-0.9.3/src/base/PdfDataType.h0000664000175000017500000001313212344436402016702 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2006 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_DATATYPE_H_ #define _PDF_DATATYPE_H_ #include "PdfDefines.h" namespace PoDoFo { class PdfEncrypt; class PdfOutputDevice; /** An interface for all PDF datatype classes. * * * \see PdfName \see PdfArray \see PdfReference * \see PdfVariant \see PdfDictionary \see PdfString */ class PODOFO_API PdfDataType { protected: /** Create a new PdfDataType. * Can only be called by subclasses */ PdfDataType(); public: virtual ~PdfDataType(); /** Write the complete datatype to a file. * \param pDevice write the object to this device * \param eWriteMode additional options for writing this object * \param pEncrypt an encryption object which is used to encrypt this object * or NULL to not encrypt this object */ virtual void Write( PdfOutputDevice* pDevice, EPdfWriteMode eWriteMode, const PdfEncrypt* pEncrypt = NULL ) const = 0; /** The dirty flag is set if this variant * has been modified after construction. * * Usually the dirty flag is also set * if you call any non-const member function * as we cannot determine if you actually changed * something or not. * * \returns true if the value is dirty and has been * modified since construction */ virtual bool IsDirty() const; /** Sets the dirty flag of this PdfVariant * * \param bDirty true if this PdfVariant has been * modified from the outside * * \see IsDirty */ virtual void SetDirty( bool bDirty ); /** * Sets this object to immutable, * so that no keys can be edited or changed. * * @param bImmutable if true set the object to be immutable * * This is used by PdfImmediateWriter and PdfStreamedDocument so * that no keys can be added to an object after setting stream data on it. * */ inline void SetImmutable(bool bImmutable); /** * Retrieve if an object is immutable. * * This is used by PdfImmediateWriter and PdfStreamedDocument so * that no keys can be added to an object after setting stream data on it. * * @returns true if the object is immutable */ inline bool GetImmutable() const; protected: /** * Will throw an exception if called on an immutable object, * so this should be called before actually changing a value! * */ inline void AssertMutable() const; private: bool m_bImmutable; }; // ----------------------------------------------------- // // ----------------------------------------------------- inline void PdfDataType::SetImmutable(bool bImmutable) { m_bImmutable = bImmutable; } // ----------------------------------------------------- // // ----------------------------------------------------- inline bool PdfDataType::GetImmutable() const { return m_bImmutable; } // ----------------------------------------------------- // // ----------------------------------------------------- inline void PdfDataType::AssertMutable() const { if(m_bImmutable) { throw PdfError( ePdfError_ChangeOnImmutable ); } } }; // namespace PoDoFo #endif /* _PDF_DATATYPE_H_ */ podofo-0.9.3/src/base/PdfOutputStream.cpp0000664000175000017500000001167712344436402020212 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2007 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfOutputStream.h" #include "PdfOutputDevice.h" #include "PdfRefCountedBuffer.h" #include "PdfDefinesPrivate.h" #include #include namespace PoDoFo { PdfFileOutputStream::PdfFileOutputStream( const char* pszFilename ) { m_hFile = fopen( pszFilename, "wb" ); if( !m_hFile ) { PODOFO_RAISE_ERROR_INFO( ePdfError_FileNotFound, pszFilename ); } } pdf_long PdfFileOutputStream::Write( const char* pBuffer, pdf_long lLen ) { return fwrite( pBuffer, sizeof(char), lLen, m_hFile ); } void PdfFileOutputStream::Close() { if( m_hFile ) fclose( m_hFile ); } PdfMemoryOutputStream::PdfMemoryOutputStream( pdf_long lInitial ) : m_lLen( 0 ), m_bOwnBuffer( true ) { m_lSize = lInitial; m_pBuffer = static_cast(podofo_malloc( m_lSize * sizeof(char) )); if( !m_pBuffer ) { PODOFO_RAISE_ERROR( ePdfError_OutOfMemory ); } } PdfMemoryOutputStream::PdfMemoryOutputStream( char* pBuffer, pdf_long lLen ) : m_lLen( 0 ), m_bOwnBuffer( false ) { m_lSize = lLen; m_pBuffer = pBuffer; } PdfMemoryOutputStream::~PdfMemoryOutputStream() { if( m_bOwnBuffer ) podofo_free( m_pBuffer ); } pdf_long PdfMemoryOutputStream::Write( const char* pBuffer, pdf_long lLen ) { if( !m_pBuffer ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } if( m_lLen + lLen > m_lSize ) { if( m_bOwnBuffer ) { // a reallocation is required m_lSize = PDF_MAX( (m_lLen + lLen), (m_lSize << 1 ) ); m_pBuffer = static_cast(podofo_realloc( m_pBuffer, m_lSize )); if( !m_pBuffer ) { PODOFO_RAISE_ERROR( ePdfError_OutOfMemory ); } } else { PODOFO_RAISE_ERROR( ePdfError_OutOfMemory ); } } memcpy( m_pBuffer + m_lLen, pBuffer, lLen ); m_lLen += lLen; return lLen; } PdfDeviceOutputStream::PdfDeviceOutputStream( PdfOutputDevice* pDevice ) : m_pDevice( pDevice ) { } pdf_long PdfDeviceOutputStream::Write( const char* pBuffer, pdf_long lLen ) { pdf_long lTell = m_pDevice->Tell(); m_pDevice->Write( pBuffer, lLen ); return m_pDevice->Tell() - lTell; } pdf_long PdfBufferOutputStream::Write( const char* pBuffer, pdf_long lLen ) { if( m_lLength + lLen >= static_cast(m_pBuffer->GetSize()) ) m_pBuffer->Resize( m_lLength + lLen ); memcpy( m_pBuffer->GetBuffer() + m_lLength, pBuffer, lLen ); m_lLength += lLen; return lLen; } }; podofo-0.9.3/src/base/PdfFileStream.h0000664000175000017500000001553412344436402017232 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2007 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_FILE_STREAM_H_ #define _PDF_FILE_STREAM_H_ #include "PdfDefines.h" #include "PdfStream.h" namespace PoDoFo { class PdfOutputStream; /** A PDF stream can be appended to any PdfObject * and can contain arbitrary data. * * Most of the time it will contain either drawing commands * to draw onto a page or binary data like a font or an image. * * A PdfFileStream writes all data directly to an output device * without keeping it in memory. * PdfFileStream is used automatically when creating PDF files * using PdfImmediateWriter. * * \see PdfVecObjects * \see PdfStream * \see PdfMemoryStream * \see PdfFileStream */ class PODOFO_API PdfFileStream : public PdfStream { public: /** Create a new PdfFileStream object which has a parent PdfObject. * The stream will be deleted along with the parent. * This constructor will be called by PdfObject::Stream() for you. * * \param pParent parent object * \param pDevice output device */ PdfFileStream( PdfObject* pParent, PdfOutputDevice* pDevice ); virtual ~PdfFileStream(); /** Set an encryption object which is used to encrypt * all data written to this stream. * * \param pEncrypt an encryption object or NULL if no encryption should be done */ void SetEncrypted( PdfEncrypt* pEncrypt ); /** Write the stream to an output device * \param pDevice write to this outputdevice. * \param pEncrypt encrypt stream data using this object */ virtual void Write( PdfOutputDevice* pDevice, PdfEncrypt* pEncrypt = NULL ); /** Get a malloced buffer of the current stream. * No filters will be applied to the buffer, so * if the stream is Flate compressed the compressed copy * will be returned. * * The caller has to free() the buffer. * * This is currently not implemented for PdfFileStreams * and will raise an ePdfError_InternalLogic exception * * \param pBuffer pointer to the buffer * \param lLen pointer to the buffer length * \returns ErrOk on success. */ virtual void GetCopy( char** pBuffer, pdf_long* lLen ) const; /** Get a copy of a the stream and write it to a PdfOutputStream * * \param pStream data is written to this stream. */ virtual void GetCopy( PdfOutputStream* pStream ) const; /** Get the streams length with all filters applied (eg the compressed * length of a Flate compressed stream). * * \returns the length of the stream with all filters applied */ inline virtual pdf_long GetLength() const; protected: /** Required for the GetFilteredCopy implementation * \returns a handle to the internal buffer */ inline virtual const char* GetInternalBuffer() const; /** Required for the GetFilteredCopy implementation * \returns the size of the internal buffer */ inline virtual pdf_long GetInternalBufferSize() const; /** Begin appending data to this stream. * Clears the current stream contents. * * \param vecFilters use this filters to encode any data written to the stream. */ virtual void BeginAppendImpl( const TVecFilters & vecFilters ); /** Append a binary buffer to the current stream contents. * * \param pszString a buffer * \param lLen length of the buffer * * \see BeginAppend * \see Append * \see EndAppend */ virtual void AppendImpl( const char* pszString, size_t lLen ); /** Finish appending data to the stream */ virtual void EndAppendImpl(); private: PdfOutputDevice* m_pDevice; PdfOutputStream* m_pStream; PdfOutputStream* m_pDeviceStream; PdfOutputStream* m_pEncryptStream; pdf_long m_lLenInitial; pdf_long m_lLength; PdfObject* m_pLength; PdfEncrypt* m_pCurEncrypt; }; // ----------------------------------------------------- // // ----------------------------------------------------- pdf_long PdfFileStream::GetLength() const { return m_lLength; } // ----------------------------------------------------- // // ----------------------------------------------------- const char* PdfFileStream::GetInternalBuffer() const { return NULL; } // ----------------------------------------------------- // // ----------------------------------------------------- pdf_long PdfFileStream::GetInternalBufferSize() const { return 0; } }; #endif // _PDF_FILE_STREAM_H_ podofo-0.9.3/src/base/Pdf3rdPtyForwardDecl.h0000664000175000017500000000217711641323033020472 0ustar dominikdominik#ifndef PDF_FT_FORWARD_DECL #define PDF_FT_FORWARD_DECL /** * \page Pdf3rdPartyForwardDecl.h * * Forward declare some types that we use in our public API but don't want to * include the headers for directly. We can't do a nice simple forward * declaration because most of these libraries have typedefs everywhere. * * We don't want to include things like freetype directly in our public headers * because: * * - They dump a huge amount of cruft into the top level namespace * * - Programs that haven't gone through the apallingly convoluted process required * to add freetype's header path can't include podofo's headers even if they have no * intention of using any freetype-related font features. */ #ifdef __cplusplus extern "C" { #endif // Provide access to FT_Library struct FT_LibraryRec_; typedef struct FT_LibraryRec_ *FT_Library; // Provide access to FT_Face struct FT_FaceRec_; typedef struct FT_FaceRec_* FT_Face; #if defined(PODOFO_HAVE_FONTCONFIG) // Fontconfig struct _FcConfig; typedef struct _FcConfig FcConfig; #endif #ifdef __cplusplus }; // end extern "C" #endif // end PDF_FT_FORWARD_DECL #endif podofo-0.9.3/src/base/PdfObject.h0000664000175000017500000004035412344436402016403 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2005 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_OBJECT_H_ #define _PDF_OBJECT_H_ #include "PdfDefines.h" #include "PdfName.h" #include "PdfParser.h" #include "PdfReference.h" #include "PdfString.h" #include "PdfVariant.h" namespace PoDoFo { class PdfEncrypt; class PdfObject; class PdfOutputDevice; class PdfStream; class PdfVecObjects; /** * This class represents a PDF indirect Object in memory * * It is possible to manipulate the stream which can be appended to the object * (if the object is of underlying type dictionary). A PdfObject is uniquely * identified by an object number and a generation number which has to be * passed to the constructor. * * The object can be written to a file easily using the WriteObject() function. * * \see WriteObject() */ class PODOFO_API PdfObject : public PdfVariant { friend class PdfVecObjects; public: /** Create a PDF object with object and generation number -1 * and the value of being an empty PdfDictionary. */ PdfObject(); /** Construct a new PDF object of type PdfDictionary. * * \param rRef reference of this object * \param pszType if type is not null a key "/Type" will be added to the dictionary with * the value of type. */ PdfObject( const PdfReference & rRef, const char* pszType); /** Construct a new PDF object. * \param rRef reference of this object * \param rVariant the value of the PdfObject (which is copied) */ PdfObject( const PdfReference & rRef, const PdfVariant & rVariant ); /** Create a PDF object with object and generation number -1 * and the value of the passed variant. * * \param var the value of the object */ PdfObject( const PdfVariant & var ); /** Construct a PdfObject with object and generation number -1 * and a bool as value. * * \param b the boolean value of this PdfObject */ PdfObject( bool b ); /** Construct a PdfObject with object and generation number -1 * and a pdf_int64 as value. * * \param l the pdf_int64 value of this PdfObject */ PdfObject( pdf_int64 l ); /** Construct a PdfObject with object and generation number -1 * and a double as value. * * \param d the double value of this PdfObject */ PdfObject( double d ); /** Construct a PdfObject with object and generation number -1 * and a PdfString as value. * * \param rsString the string value of this PdfObject */ PdfObject( const PdfString & rsString ); /** Construct a PdfObject with object and generation number -1 * and a PdfName as value. * * \param rName the value of this PdfObject */ PdfObject( const PdfName & rName ); /** Construct a PdfObject with object and generation number -1 * and a PdfReference as value. * * \param rRef the value of the this PdfObject */ PdfObject( const PdfReference & rRef ); /** Construct a PdfObject with object and generation number -1 * and a PdfArray as value. * * \param tList the value of the this PdfObject */ PdfObject( const PdfArray & tList ); /** Construct a PdfObject with object and generation number -1 * and a PdfDictionary as value. * * \param rDict the value of the this PdfObject */ PdfObject( const PdfDictionary & rDict ); /** Creates a copy of an existing PdfObject * All assosiated objects and streams will be copied along with the PdfObject * \param rhs PdfObject to clone */ PdfObject( const PdfObject & rhs ); virtual ~PdfObject(); /** Get the keys value out of the dictionary. If the key is a reference, * the reference is resolved and the object pointed to by the reference is returned. * * \param key look for the key named key in the dictionary * * \returns the found value or NULL if the value is not in the * dictionary or if this object is no dictionary */ PdfObject* GetIndirectKey( const PdfName & key ) const; /** * MustGetIndirectKey() wraps GetIndirectKey to throw on null return. * This makes it MUCH more readable to look up deep chains of linked keys * with the cost that it's not easy to tell at which point a missing key/object * was encountered. * * \returns the found value, which is never null * \throws PdfError(ePdfError_NoObject) . */ inline PdfObject* MustGetIndirectKey( const PdfName & key ) const; /** Write the complete object to a file. * \param pDevice write the object to this device * \param pEncrypt an encryption object which is used to encrypt this object * or NULL to not encrypt this object * \param eWriteMode additional options for writing the object * \param keyStop if not KeyNull and a key == keyStop is found * writing will stop right before this key! */ void WriteObject( PdfOutputDevice* pDevice, EPdfWriteMode eWriteMode, PdfEncrypt* pEncrypt, const PdfName & keyStop = PdfName::KeyNull ) const; /** Get the length of the object in bytes if it was written to disk now. * \param eWriteMode additional options for writing the object * \returns the length of the object */ pdf_long GetObjectLength( EPdfWriteMode eWriteMode ); /** Get a indirect reference to this object * \returns a PdfReference pointing to this object. */ inline const PdfReference & Reference() const; /** Get a handle to a PDF stream object * If the PDF object does not have a stream, * one will be created. * \returns a PdfStream object * * This will set the dirty flag of this object. * \see IsDirty */ PdfStream* GetStream(); /** Get a handle to a const PDF stream object * If the PDF object does not have a stream, * null is returned * \returns a PdfStream object or null */ const PdfStream* GetStream() const; /** Check if this object has a PdfStream object * appended. * * \returns true if the object has a stream */ inline bool HasStream() const; /** This operator is required for sorting a list of * PdfObjects. It compares the objectnumber. If objectnumbers * are equal, the generation number is compared. */ PODOFO_NOTHROW inline bool operator<( const PdfObject & rhs ) const; /** Comperasion operator. * Compares two PDF object only based on their object and generation number */ PODOFO_NOTHROW inline bool operator==( const PdfObject & rhs ) const; /** Set the owner of this object, i.e. the PdfVecObjects to which * this object belongs. * * \param pVecObjects a vector of pdf objects */ inline void SetOwner( PdfVecObjects* pVecObjects ); /** Get the owner of this object. * \return the creator of this object */ inline PdfVecObjects* GetOwner() const; /** Creates a copy of an existing PdfObject * All assosiated objects and streams will be copied along with the PdfObject * \param rhs PdfObject to clone * \returns a reference to this object */ const PdfObject & operator=( const PdfObject & rhs ); /** This function compresses any currently set stream * using the FlateDecode algorithm. JPEG compressed streams * will not be compressed again using this function. * Entries to the filter dictionary will be added if necessary. */ void FlateCompressStream(); /** Calculate the byte offset of the key pszKey from the start of the object * if the object was written to disk at the moment of calling this function. * * This function is very calculation intensive! * * \param pszKey key to calculate the byte offset * \param eWriteMode additional options for writing the PDF * \returns the offset of the key */ pdf_long GetByteOffset( const char* pszKey, EPdfWriteMode eWriteMode ); /** * Dynamically load this object and any associated stream from a PDF file * by calling the virtual method DelayedStreamLoadImpl if the stream is not * already loaded. Will call DelayedLoad() first if it is required. * * Call graph: * * DelayedStreamLoad ---> DelayedLoad() --> DelayedLoadImpl() * | * --> DelayedStreamLoadImpl() * * For objects complete created in memory this function does nothing. */ inline void DelayedStreamLoad() const; protected: /** Flag any stream associated with the object as incompletely loaded, * so that DelayedStreamLoad() will be called when needed. * * All constructors initialize a PdfObject with delayed loading of streams * disabled . If you want delayed loading of streams you must ask for it. * If you do so, call this method early in your ctor and be sure to * override DelayedStreamLoadImpl() * * Note that it is quite possible to have a PdfObject that requires a * delayed-load of its stream but does an immediate load of the PdfVariant * base. If you want to delay loading of that too, make sure to call * EnableDelayedLoading(). */ inline void EnableDelayedStreamLoading(); /** Load the stream of the object if it has one and if delayed loading is enabled. * * You should override this to control deferred stream loading in your subclass. * * Never call this method directly; use DelayedStreamLoad() instead. */ inline virtual void DelayedStreamLoadImpl(); /** Same as GetStream() but won't trigger a delayed load, so it's safe * for use while a delayed load is in progress. * * This will set the dirty flag of this object. * \see IsDirty */ PdfStream* GetStream_NoDL(); protected: PdfReference m_reference; PdfStream* m_pStream; PdfVecObjects* m_pOwner; PODOFO_NOTHROW inline bool DelayedStreamLoadDone() const; private: /* See PdfVariant.h for a detailed explanation of this member, which is * here to prevent accidental construction of a PdfObject of integer type * when passing a pointer. */ template PdfObject(T*); // Shared initialization between all the ctors void InitPdfObject(); // No touchy. Only for manipulation by PdfObject private routines. // Tracks whether deferred loading is still pending (in which case it'll be // false). If true, deferred loading is not requried or has been completed. mutable bool m_bDelayedStreamLoadDone; #if defined(PODOFO_EXTRA_CHECKS) protected: PODOFO_NOTHROW bool DelayedStreamLoadInProgress() const { return m_bDelayedStreamLoadInProgress; } private: mutable bool m_bDelayedStreamLoadInProgress; #endif }; // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfObject::DelayedStreamLoadDone() const { return m_bDelayedStreamLoadDone; } // ----------------------------------------------------- // // ----------------------------------------------------- void PdfObject::EnableDelayedStreamLoading() { m_bDelayedStreamLoadDone = false; } // ----------------------------------------------------- // // ----------------------------------------------------- const PdfReference & PdfObject::Reference() const { return m_reference; } // ----------------------------------------------------- // // ----------------------------------------------------- inline void PdfObject::SetOwner( PdfVecObjects* pVecObjects ) { m_pOwner = pVecObjects; } // ----------------------------------------------------- // // ----------------------------------------------------- inline PdfVecObjects* PdfObject::GetOwner() const { return m_pOwner; } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfObject::operator<( const PdfObject & rhs ) const { return m_reference < rhs.m_reference; } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfObject::operator==( const PdfObject & rhs ) const { return (m_reference == rhs.m_reference); } // ----------------------------------------------------- // // ----------------------------------------------------- inline bool PdfObject::HasStream() const { DelayedStreamLoad(); return ( m_pStream != NULL ); } // ----------------------------------------------------- // // ----------------------------------------------------- PdfObject* PdfObject::MustGetIndirectKey( const PdfName & key ) const { PdfObject* obj = GetIndirectKey(key); if (!obj) PODOFO_RAISE_ERROR( ePdfError_NoObject ); return obj; } // ----------------------------------------------------- // // ----------------------------------------------------- // Default implementation of virtual void DelayedStreamLoadImpl() // throws, since delayed loading of steams should not be enabled // except by types that support it. inline void PdfObject::DelayedStreamLoadImpl() { PODOFO_RAISE_ERROR( ePdfError_InternalLogic ); } inline void PdfObject::DelayedStreamLoad() const { DelayedLoad(); #if defined(PODOFO_EXTRA_CHECKS) if( m_bDelayedStreamLoadInProgress ) PODOFO_RAISE_ERROR_INFO( ePdfError_InternalLogic, "Recursive DelayedStreamLoad() detected" ); #endif if( !m_bDelayedStreamLoadDone ) { #if defined(PODOFO_EXTRA_CHECKS) m_bDelayedStreamLoadInProgress = true; #endif const_cast(this)->DelayedStreamLoadImpl(); // Nothing was thrown, so if the implementer of DelayedstreamLoadImpl() is // following the rules we're done. m_bDelayedStreamLoadDone = true; #if defined(PODOFO_EXTRA_CHECKS) m_bDelayedStreamLoadInProgress = false; #endif } } }; #endif // _PDF_OBJECT_H_ podofo-0.9.3/src/base/PdfTokenizer.h0000664000175000017500000003025712344436402017150 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2006 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_TOKENIZER_H_ #define _PDF_TOKENIZER_H_ #include "PdfDefines.h" #include "PdfRefCountedBuffer.h" #include "PdfRefCountedInputDevice.h" #include #include namespace PoDoFo { class PdfEncrypt; class PdfVariant; enum EPdfTokenType { ePdfTokenType_Delimiter, ePdfTokenType_Token, ePdfTokenType_Unknown = 0xFF }; typedef std::pair TTokenizerPair; typedef std::deque TTokenizerQueque; typedef TTokenizerQueque::iterator TITokenizerQueque; typedef TTokenizerQueque::const_iterator TCITokenizerQueque; /** * A simple tokenizer for PDF files and PDF content streams */ class PODOFO_API PdfTokenizer { public: PdfTokenizer(); PdfTokenizer( const char* pBuffer, size_t lLen ); PdfTokenizer( const PdfRefCountedInputDevice & rDevice, const PdfRefCountedBuffer & rBuffer ); virtual ~PdfTokenizer(); /** Reads the next token from the current file position * ignoring all comments. * * \param[out] pszToken On true return, set to a pointer to the read * token (a NULL-terminated C string). The pointer is * to memory owned by PdfTokenizer and must NOT be * freed. The contents are invalidated on the next * call to GetNextToken(..) and by the destruction of * the PdfTokenizer. Undefined on false return. * * \param[out] peType On true return, if not NULL the type of the read token * will be stored into this parameter. Undefined on false * return. * * \returns True if a token was read, false if there are no * more tokens to read. * * \see GetBuffer */ virtual bool GetNextToken( const char *& pszToken, EPdfTokenType* peType = NULL); /** Reads the next token from the current file position * ignoring all comments and compare the passed token * to the read token. * * If there is no next token available, throws UnexpectedEOF. * * \param pszToken a token that is compared to the * read token * * \returns true if the read token equals the passed token. */ bool IsNextToken( const char* pszToken ); /** Read the next number from the current file position * ignoring all comments. * * Raises NoNumber exception if the next token is no number, and * UnexpectedEOF if no token could be read. No token is consumed if * NoNumber is thrown. * * \returns a number read from the input device. */ pdf_long GetNextNumber(); /** Read the next variant from the current file position * ignoring all comments. * * Raises an UnexpectedEOF exception if there is no variant left in the * file. * * \param rVariant write the read variant to this value * \param pEncrypt an encryption object which is used to decrypt strings during parsing */ void GetNextVariant( PdfVariant& rVariant, PdfEncrypt* pEncrypt ); /** Returns true if the given character is a whitespace * according to the pdf reference * * \returns true if it is a whitespace character otherwise false */ PODOFO_NOTHROW inline static bool IsWhitespace(const unsigned char ch); /** Returns true if the given character is a delimiter * according to the pdf reference * * \returns true if it is a delimiter character otherwise false */ PODOFO_NOTHROW inline static bool IsDelimiter(const unsigned char ch); /** * True if the passed character is a regular character according to the PDF * reference (Section 3.1.1, Character Set); ie it is neither a white-space * nor a delimeter character. */ PODOFO_NOTHROW inline static bool IsRegular(const unsigned char ch); /** * True if the passed character is within the generally accepted "printable" * ASCII range. */ PODOFO_NOTHROW inline static bool IsPrintable(const unsigned char ch); /** * Get the hex value from a static map of a given hex character (0-9, A-F, a-f). * * \param ch hex character * * \returns hex value or HEX_NOT_FOUND if invalid * * \see HEX_NOT_FOUND */ PODOFO_NOTHROW inline static int GetHexValue(const unsigned char ch); /** * Constant which is returned for invalid hex values. */ static const unsigned int HEX_NOT_FOUND; protected: /** Read the next variant from the current file position * ignoring all comments. * * Raises an exception if there is no variant left in the file. * * \param pszToken a token that has already been read * \param eType type of the passed token * \param rVariant write the read variant to this value * \param pEncrypt an encryption object which is used to decrypt strings during parsing */ void GetNextVariant( const char* pszToken, EPdfTokenType eType, PdfVariant& rVariant, PdfEncrypt* pEncrypt ); /** Determine the possible datatype of a token. * Numbers, reals, bools or NULL values are parsed directly by this function * and saved to a variant. * * \returns the expected datatype */ EPdfDataType DetermineDataType( const char* pszToken, EPdfTokenType eType, PdfVariant& rVariant ); void ReadDataType( EPdfDataType eDataType, PdfVariant& rVariant, PdfEncrypt* pEncrypt ); /** Read a dictionary from the input device * and store it into a variant. * * \param rVariant store the dictionary into this variable * \param pEncrypt an encryption object which is used to decrypt strings during parsing */ void ReadDictionary( PdfVariant& rVariant, PdfEncrypt* pEncrypt ); /** Read an array from the input device * and store it into a variant. * * \param rVariant store the array into this variable * \param pEncrypt an encryption object which is used to decrypt strings during parsing */ void ReadArray( PdfVariant& rVariant, PdfEncrypt* pEncrypt ); /** Read a string from the input device * and store it into a variant. * * \param rVariant store the string into this variable * \param pEncrypt an encryption object which is used to decrypt strings during parsing */ void ReadString( PdfVariant& rVariant, PdfEncrypt* pEncrypt ); /** Read a hex string from the input device * and store it into a variant. * * \param rVariant store the hex string into this variable * \param pEncrypt an encryption object which is used to decrypt strings during parsing */ void ReadHexString( PdfVariant& rVariant, PdfEncrypt* pEncrypt ); /** Read a name from the input device * and store it into a variant. * * Throws UnexpectedEOF if there is nothing to read. * * \param rVariant store the name into this variable */ void ReadName( PdfVariant& rVariant ); /** Add a token to the queque of tokens. * GetNextToken() will return all quequed tokens first before * reading new tokens from the input device. * * \param pszToken string of the token * \param eType type of the token * * \see GetNextToken */ void QuequeToken( const char* pszToken, EPdfTokenType eType ); protected: PdfRefCountedInputDevice m_device; PdfRefCountedBuffer m_buffer; private: // 256-byte array mapping character ordinal values to a truth value // indicating whether or not they are whitespace according to the PDF // standard. static const char * const s_delimiterMap; static const char * const s_whitespaceMap; static const char s_octMap[]; ///< Map of bool values, if a certain char ///< is a valid octal digit static const char * const s_escMap; ///< Mapping of escape sequences to there value static const char * const s_hexMap; ///< Mapping of hex characters to there value TTokenizerQueque m_deqQueque; // A vector which is used as a buffer to read strings. // It is a member of the class to avoid reallocations while parsing. std::vector m_vecBuffer; // we use a vector instead of a string // because we might read a unicode // string which is allowed to contain 0 bytes. /// An istringstream which is used /// to read double values instead of strtod /// which is locale depend. std::istringstream m_doubleParser; }; // ----------------------------------------------------- // // ----------------------------------------------------- inline bool PdfTokenizer::IsWhitespace(const unsigned char ch) { return ( PdfTokenizer::s_whitespaceMap[static_cast(ch)] != 0 ); } // ----------------------------------------------------- // // ----------------------------------------------------- inline bool PdfTokenizer::IsDelimiter(const unsigned char ch) { return ( PdfTokenizer::s_delimiterMap[ch] != 0 ); } // ----------------------------------------------------- // // ----------------------------------------------------- inline bool PdfTokenizer::IsRegular(const unsigned char ch) { return !IsWhitespace(ch) && !IsDelimiter(static_cast(ch)); } // ----------------------------------------------------- // // ----------------------------------------------------- inline bool PdfTokenizer::IsPrintable(const unsigned char ch) { return ((ch > 32U) && (ch < 125U)); } // ----------------------------------------------------- // // ----------------------------------------------------- inline int PdfTokenizer::GetHexValue(const unsigned char ch) { return PdfTokenizer::s_hexMap[static_cast(ch)]; } }; #endif // _PDF_TOKENIZER_H_ podofo-0.9.3/src/base/PdfXRefStreamParserObject.h0000664000175000017500000001172612344436402021522 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2009 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_XREF_STREAM_PARSER_OBJECT_H_ #define _PDF_XREF_STREAM_PARSER_OBJECT_H_ #include "PdfDefines.h" #include "PdfParserObject.h" #define W_ARRAY_SIZE 3 #define W_MAX_BYTES 4 namespace PoDoFo { /** * A utility class for PdfParser that can parse * an XRef stream object. * * It is mainly here to make PdfParser more modular. */ class PdfXRefStreamParserObject : public PdfParserObject { public: /** Parse the object data from the given file handle starting at * the current position. * \param pCreator pointer to a PdfVecObjects to resolve object references * \param rDevice an open reference counted input device which is positioned in * front of the object which is going to be parsed. * \param rBuffer buffer to use for parsing to avoid reallocations * \param pOffsets XRef entries are stored into this array */ PdfXRefStreamParserObject(PdfVecObjects* pCreator, const PdfRefCountedInputDevice & rDevice, const PdfRefCountedBuffer & rBuffer, PdfParser::TVecOffsets* pOffsets ); ~PdfXRefStreamParserObject(); void Parse(); void ReadXRefTable(); /** * \returns true if there is a previous XRefStream */ inline bool HasPrevious(); /** * \returns the offset of the previous XRef table */ inline pdf_long GetPreviousOffset(); private: /** * Read the /Index key from the current dictionary * and write uit to a vector. * * \param rvecIndeces store the indeces hare * \param size default value from /Size key */ void GetIndeces( std::vector & rvecIndeces, pdf_int64 size ); /** * Parse the stream contents * * \param nW /W key * \param rvecIndeces indeces as filled by GetIndeces * * \see GetIndeces */ void ParseStream( const pdf_int64 nW[W_ARRAY_SIZE], const std::vector & rvecIndeces ); void ReadXRefStreamEntry( char* pBuffer, pdf_long, const pdf_int64 lW[W_ARRAY_SIZE], int nObjNo ); private: pdf_long m_lNextOffset; PdfParser::TVecOffsets* m_pOffsets; }; // ----------------------------------------------------- // // ----------------------------------------------------- inline bool PdfXRefStreamParserObject::HasPrevious() { return (m_lNextOffset != -1); } // ----------------------------------------------------- // // ----------------------------------------------------- inline pdf_long PdfXRefStreamParserObject::GetPreviousOffset() { return m_lNextOffset; } }; #endif // _PDF_XREF_STREAM_PARSER_OBJECT_H_ podofo-0.9.3/src/base/PdfRect.h0000664000175000017500000001471412344436402016073 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2006 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_RECT_H_ #define _PDF_RECT_H_ #include "PdfDefines.h" namespace PoDoFo { class PdfArray; class PdfPage; class PdfVariant; /** A rectangle as defined by the PDF reference */ class PODOFO_API PdfRect { public: /** Create an empty rectangle with bottom=left=with=height=0 */ PdfRect(); /** Create a rectangle with a given size and position * All values are in PDF units * NOTE: since PDF is bottom-left origined, we pass the bottom instead of the top */ PdfRect( double left, double bottom, double width, double height ); /** Create a rectangle from an array * All values are in PDF units */ PdfRect( const PdfArray& inArray ); /** Copy constructor */ PdfRect( const PdfRect & rhs ); /** Converts the rectangle into an array * based on PDF units and adds the array into an variant. * \param var the variant to store the Rect */ void ToVariant( PdfVariant & var ) const; /** Returns a string representation of the PdfRect * \returns std::string representation as [ left bottom right top ] */ std::string ToString() const; /** Assigns the values of this PdfRect from the 4 values in the array * \param inArray the array to load the values from */ void FromArray( const PdfArray& inArray ); /** Intersect with another rect * \param rRect the rect to intersect with */ void Intersect( const PdfRect & rRect ); /** Get the bottom coordinate of the rectangle * \returns bottom */ inline double GetBottom() const; /** Set the bottom coordinate of the rectangle * \param dBottom */ inline void SetBottom( double dBottom ); /** Get the left coordinate of the rectangle * \returns left in PDF units */ inline double GetLeft() const; /** Set the left coordinate of the rectangle * \param lLeft in PDF units */ inline void SetLeft( double lLeft ); /** Get the width of the rectangle * \returns width in PDF units */ inline double GetWidth() const; /** Set the width of the rectangle * \param lWidth in PDF units */ inline void SetWidth( double lWidth ); /** Get the height of the rectangle * \returns height in PDF units */ inline double GetHeight() const; /** Set the height of the rectangle * \param lHeight in PDF units */ inline void SetHeight( double lHeight ); PdfRect & operator=( const PdfRect & rhs ); private: double m_dLeft; double m_dBottom; double m_dWidth; double m_dHeight; }; // ----------------------------------------------------- // // ----------------------------------------------------- double PdfRect::GetBottom() const { return m_dBottom; } // ----------------------------------------------------- // // ----------------------------------------------------- void PdfRect::SetBottom( double dBottom ) { m_dBottom = dBottom; } // ----------------------------------------------------- // // ----------------------------------------------------- double PdfRect::GetLeft() const { return m_dLeft; } // ----------------------------------------------------- // // ----------------------------------------------------- void PdfRect::SetLeft( double dLeft ) { m_dLeft = dLeft; } // ----------------------------------------------------- // // ----------------------------------------------------- double PdfRect::GetWidth() const { return m_dWidth; } // ----------------------------------------------------- // // ----------------------------------------------------- void PdfRect::SetWidth( double dWidth ) { m_dWidth = dWidth; } // ----------------------------------------------------- // // ----------------------------------------------------- double PdfRect::GetHeight() const { return m_dHeight; } // ----------------------------------------------------- // // ----------------------------------------------------- void PdfRect::SetHeight( double dHeight ) { m_dHeight = dHeight; } }; #endif /* _PDF_RECT_H_ */ podofo-0.9.3/src/base/PdfEncoding.cpp0000664000175000017500000021053012347314771017260 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2007 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfEncoding.h" #include "PdfDictionary.h" #include "PdfLocale.h" #include "util/PdfMutexWrapper.h" #include "PdfDefinesPrivate.h" #include #include #include namespace PoDoFo { PdfEncoding::PdfEncoding( int nFirstChar, int nLastChar ) : m_nFirstChar( nFirstChar ), m_nLastChar( nLastChar ) { if( !(m_nFirstChar < m_nLastChar) ) { PODOFO_RAISE_ERROR_INFO( ePdfError_ValueOutOfRange, "PdfEncoding: nFirstChar must be smaller than nLastChar" ); } } PdfEncoding::~PdfEncoding() { } // ----------------------------------------------------- // PdfSimpleEncoding // ----------------------------------------------------- PdfSimpleEncoding::PdfSimpleEncoding( const PdfName & rName ) : PdfEncoding( 0, 255 ), m_mutex( new PoDoFo::Util::PdfMutex() ), m_name( rName ), m_pEncodingTable( NULL ) { } PdfSimpleEncoding::~PdfSimpleEncoding() { free( m_pEncodingTable ); delete m_mutex; } void PdfSimpleEncoding::InitEncodingTable() { Util::PdfMutexWrapper wrapper( *m_mutex ); const long lTableLength = 0xffff; const pdf_utf16be* cpUnicodeTable = this->GetToUnicodeTable(); if( !m_pEncodingTable ) // double check { m_pEncodingTable = static_cast(malloc(sizeof(char)*lTableLength)); // fill the table with 0 memset( m_pEncodingTable, 0, lTableLength * sizeof(char) ); // fill the table with data for( size_t i=0; i<256; i++ ) { m_pEncodingTable[ static_cast(cpUnicodeTable[i]) ] = static_cast(i); } } } void PdfSimpleEncoding::AddToDictionary( PdfDictionary & rDictionary ) const { rDictionary.AddKey( PdfName("Encoding"), m_name ); } pdf_utf16be PdfSimpleEncoding::GetCharCode( int nIndex ) const { if( nIndex < this->GetFirstChar() || nIndex > this->GetLastChar() ) { PODOFO_RAISE_ERROR( ePdfError_ValueOutOfRange ); } const pdf_utf16be* cpUnicodeTable = this->GetToUnicodeTable(); #ifdef PODOFO_IS_LITTLE_ENDIAN return ((cpUnicodeTable[nIndex] & 0xff00) >> 8) | ((cpUnicodeTable[nIndex] & 0xff) << 8); #else return cpUnicodeTable[nIndex]; #endif // PODOFO_IS_LITTLE_ENDIAN } PdfString PdfSimpleEncoding::ConvertToUnicode( const PdfString & rEncodedString, const PdfFont* ) const { const pdf_utf16be* cpUnicodeTable = this->GetToUnicodeTable(); pdf_long lLen = rEncodedString.GetLength(); if( lLen <= 0 ) return PdfString(""); pdf_utf16be* pszStringUtf16 = static_cast(malloc(sizeof(pdf_utf16be) * (lLen + 1)) ); if( !pszStringUtf16 ) { PODOFO_RAISE_ERROR( ePdfError_OutOfMemory ); } const char* pszString = rEncodedString.GetString(); for( int i=0;i(*pszString) ]; #else pszStringUtf16[i] = ((( cpUnicodeTable[ static_cast(*pszString) ] << 8 ) & 0xff00) | (( cpUnicodeTable[ static_cast(*pszString) ] >> 8 ) & 0x00ff)); #endif // PODOFO_IS_BIG_ENDIAN ++pszString; } pszStringUtf16[lLen] = 0; PdfString sStr( pszStringUtf16 ); free( pszStringUtf16 ); return sStr; } PdfRefCountedBuffer PdfSimpleEncoding::ConvertToEncoding( const PdfString & rString, const PdfFont* ) const { if( !m_pEncodingTable ) const_cast(this)->InitEncodingTable(); PdfString sSrc = rString.ToUnicode(); // make sure the string is unicode and not PdfDocEncoding! pdf_long lLen = sSrc.GetCharacterLength(); if( !lLen ) return PdfRefCountedBuffer(); char* pDest = static_cast(malloc( sizeof(char) * (lLen + 1) )); if( !pDest ) { PODOFO_RAISE_ERROR( ePdfError_OutOfMemory ); } const pdf_utf16be* pszUtf16 = sSrc.GetUnicode(); char* pCur = pDest; long lNewLen = 0L; for( int i=0;i> 8) | ((val & 0xff) << 8); #endif // PODOFO_IS_LITTLE_ENDIAN *pCur = m_pEncodingTable[val]; if( *pCur ) // ignore 0 characters, as they cannot be converted to the current encoding { ++pCur; ++lNewLen; } } *pCur = '\0'; PdfRefCountedBuffer cDest( lNewLen ); memcpy( cDest.GetBuffer(), pDest, lNewLen ); free( pDest ); return cDest; } char PdfSimpleEncoding::GetUnicodeCharCode(pdf_utf16be unicodeValue) const { if( !m_pEncodingTable ) const_cast(this)->InitEncodingTable(); #ifdef PODOFO_IS_LITTLE_ENDIAN unicodeValue = ((unicodeValue & 0xff00) >> 8) | ((unicodeValue & 0xff) << 8); #endif // PODOFO_IS_LITTLE_ENDIAN return m_pEncodingTable[unicodeValue]; } // ----------------------------------------------------- // PdfDocEncoding // ----------------------------------------------------- // ----------------------------------------------------- // // ----------------------------------------------------- const pdf_utf16be* PdfDocEncoding::GetToUnicodeTable() const { return PdfDocEncoding::s_cEncoding; } const pdf_utf16be PdfDocEncoding::s_cEncoding[256] = { 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0017, 0x0017, 0x02D8, 0x02C7, // dec 25 0x02C6, 0x02D9, 0x02DD, 0x02DB, 0x02DA, 0x02DC, 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, // dec 57 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F, 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, // 89 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F, 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, //121 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x0000, // Undefined 0x2022, 0x2020, 0x2021, 0x2026, 0x2014, 0x2013, 0x0192, 0x2044, 0x2039, 0x203A, 0x2212, 0x2030, 0x201E, 0x201C, 0x201D, 0x2018, 0x2019, 0x201A, 0x2122, 0xFB01, // dec147 0xFB02, 0x0141, 0x0152, 0x0160, 0x0178, 0x017D, 0x0131, 0x0142, 0x0153, 0x0161, 0x017E, 0x0000, // Undefined 0x20AC, // Euro 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x0000, // Undefined 0x00AE, 0x00AF, 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, 0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF, 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF }; // ----------------------------------------------------- // PdfWinAnsiEncoding // See: http://www.microsoft.com/globaldev/reference/sbcs/1252.mspx // ----------------------------------------------------- // ----------------------------------------------------- // // ----------------------------------------------------- const pdf_utf16be* PdfWinAnsiEncoding::GetToUnicodeTable() const { return PdfWinAnsiEncoding::s_cEncoding; } const pdf_utf16be PdfWinAnsiEncoding::s_cEncoding[256] = { 0x0000, // NULL 0x0001, // START OF HEADING 0x0002, // START OF TEXT 0x0003, // END OF TEXT 0x0004, // END OF TRANSMISSION 0x0005, // ENQUIRY 0x0006, // ACKNOWLEDGE 0x0007, // BELL 0x0008, // BACKSPACE 0x0009, // HORIZONTAL TABULATION 0x000A, // LINE FEED 0x000B, // VERTICAL TABULATION 0x000C, // FORM FEED 0x000D, // CARRIAGE RETURN 0x000E, // SHIFT OUT 0x000F, // SHIFT IN 0x0010, // DATA LINK ESCAPE 0x0011, // DEVICE CONTROL ONE 0x0012, // DEVICE CONTROL TWO 0x0013, // DEVICE CONTROL THREE 0x0014, // DEVICE CONTROL FOUR 0x0015, // NEGATIVE ACKNOWLEDGE 0x0016, // SYNCHRONOUS IDLE 0x0017, // END OF TRANSMISSION BLOCK 0x0018, // CANCEL 0x0019, // END OF MEDIUM 0x001A, // SUBSTITUTE 0x001B, // ESCAPE 0x001C, // FILE SEPARATOR 0x001D, // GROUP SEPARATOR 0x001E, // RECORD SEPARATOR 0x001F, // UNIT SEPARATOR 0x0020, // SPACE 0x0021, // EXCLAMATION MARK 0x0022, // QUOTATION MARK 0x0023, // NUMBER SIGN 0x0024, // DOLLAR SIGN 0x0025, // PERCENT SIGN 0x0026, // AMPERSAND 0x0027, // APOSTROPHE 0x0028, // LEFT PARENTHESIS 0x0029, // RIGHT PARENTHESIS 0x002A, // ASTERISK 0x002B, // PLUS SIGN 0x002C, // COMMA 0x002D, // HYPHEN-MINUS 0x002E, // FULL STOP 0x002F, // SOLIDUS 0x0030, // DIGIT ZERO 0x0031, // DIGIT ONE 0x0032, // DIGIT TWO 0x0033, // DIGIT THREE 0x0034, // DIGIT FOUR 0x0035, // DIGIT FIVE 0x0036, // DIGIT SIX 0x0037, // DIGIT SEVEN 0x0038, // DIGIT EIGHT 0x0039, // DIGIT NINE 0x003A, // COLON 0x003B, // SEMICOLON 0x003C, // LESS-THAN SIGN 0x003D, // EQUALS SIGN 0x003E, // GREATER-THAN SIGN 0x003F, // QUESTION MARK 0x0040, // COMMERCIAL AT 0x0041, // LATIN CAPITAL LETTER A 0x0042, // LATIN CAPITAL LETTER B 0x0043, // LATIN CAPITAL LETTER C 0x0044, // LATIN CAPITAL LETTER D 0x0045, // LATIN CAPITAL LETTER E 0x0046, // LATIN CAPITAL LETTER F 0x0047, // LATIN CAPITAL LETTER G 0x0048, // LATIN CAPITAL LETTER H 0x0049, // LATIN CAPITAL LETTER I 0x004A, // LATIN CAPITAL LETTER J 0x004B, // LATIN CAPITAL LETTER K 0x004C, // LATIN CAPITAL LETTER L 0x004D, // LATIN CAPITAL LETTER M 0x004E, // LATIN CAPITAL LETTER N 0x004F, // LATIN CAPITAL LETTER O 0x0050, // LATIN CAPITAL LETTER P 0x0051, // LATIN CAPITAL LETTER Q 0x0052, // LATIN CAPITAL LETTER R 0x0053, // LATIN CAPITAL LETTER S 0x0054, // LATIN CAPITAL LETTER T 0x0055, // LATIN CAPITAL LETTER U 0x0056, // LATIN CAPITAL LETTER V 0x0057, // LATIN CAPITAL LETTER W 0x0058, // LATIN CAPITAL LETTER X 0x0059, // LATIN CAPITAL LETTER Y 0x005A, // LATIN CAPITAL LETTER Z 0x005B, // LEFT SQUARE BRACKET 0x005C, // REVERSE SOLIDUS 0x005D, // RIGHT SQUARE BRACKET 0x005E, // CIRCUMFLEX ACCENT 0x005F, // LOW LINE 0x0060, // GRAVE ACCENT 0x0061, // LATIN SMALL LETTER A 0x0062, // LATIN SMALL LETTER B 0x0063, // LATIN SMALL LETTER C 0x0064, // LATIN SMALL LETTER D 0x0065, // LATIN SMALL LETTER E 0x0066, // LATIN SMALL LETTER F 0x0067, // LATIN SMALL LETTER G 0x0068, // LATIN SMALL LETTER H 0x0069, // LATIN SMALL LETTER I 0x006A, // LATIN SMALL LETTER J 0x006B, // LATIN SMALL LETTER K 0x006C, // LATIN SMALL LETTER L 0x006D, // LATIN SMALL LETTER M 0x006E, // LATIN SMALL LETTER N 0x006F, // LATIN SMALL LETTER O 0x0070, // LATIN SMALL LETTER P 0x0071, // LATIN SMALL LETTER Q 0x0072, // LATIN SMALL LETTER R 0x0073, // LATIN SMALL LETTER S 0x0074, // LATIN SMALL LETTER T 0x0075, // LATIN SMALL LETTER U 0x0076, // LATIN SMALL LETTER V 0x0077, // LATIN SMALL LETTER W 0x0078, // LATIN SMALL LETTER X 0x0079, // LATIN SMALL LETTER Y 0x007A, // LATIN SMALL LETTER Z 0x007B, // LEFT CURLY BRACKET 0x007C, // VERTICAL LINE 0x007D, // RIGHT CURLY BRACKET 0x007E, // TILDE 0x007F, // DELETE 0x20AC, // EURO SIGN 0x0000, 0x201A, // SINGLE LOW-9 QUOTATION MARK 0x0192, // LATIN SMALL LETTER F WITH HOOK 0x201E, // DOUBLE LOW-9 QUOTATION MARK 0x2026, // HORIZONTAL ELLIPSIS 0x2020, // DAGGER 0x2021, // DOUBLE DAGGER 0x02C6, // MODIFIER LETTER CIRCUMFLEX ACCENT 0x2030, // PER MILLE SIGN 0x0160, // LATIN CAPITAL LETTER S WITH CARON 0x2039, // SINGLE LEFT-POINTING ANGLE QUOTATION MARK 0x0152, // LATIN CAPITAL LIGATURE OE 0x0000, 0x017D, // LATIN CAPITAL LETTER Z WITH CARON 0x0000, 0x0000, 0x2018, // LEFT SINGLE QUOTATION MARK 0x2019, // RIGHT SINGLE QUOTATION MARK 0x201C, // LEFT DOUBLE QUOTATION MARK 0x201D, // RIGHT DOUBLE QUOTATION MARK 0x2022, // BULLET 0x2013, // EN DASH 0x2014, // EM DASH 0x02DC, // SMALL TILDE 0x2122, // TRADE MARK SIGN 0x0161, // LATIN SMALL LETTER S WITH CARON 0x203A, // SINGLE RIGHT-POINTING ANGLE QUOTATION MARK 0x0153, // LATIN SMALL LIGATURE OE 0x0000, 0x017E, // LATIN SMALL LETTER Z WITH CARON 0x0178, // LATIN CAPITAL LETTER Y WITH DIAERESIS 0x00A0, // NO-BREAK SPACE 0x00A1, // INVERTED EXCLAMATION MARK 0x00A2, // CENT SIGN 0x00A3, // POUND SIGN 0x00A4, // CURRENCY SIGN 0x00A5, // YEN SIGN 0x00A6, // BROKEN BAR 0x00A7, // SECTION SIGN 0x00A8, // DIAERESIS 0x00A9, // COPYRIGHT SIGN 0x00AA, // FEMININE ORDINAL INDICATOR 0x00AB, // LEFT-POINTING DOUBLE ANGLE QUOTATION MARK 0x00AC, // NOT SIGN 0x00AD, // SOFT HYPHEN 0x00AE, // REGISTERED SIGN 0x00AF, // MACRON 0x00B0, // DEGREE SIGN 0x00B1, // PLUS-MINUS SIGN 0x00B2, // SUPERSCRIPT TWO 0x00B3, // SUPERSCRIPT THREE 0x00B4, // ACUTE ACCENT 0x00B5, // MICRO SIGN 0x00B6, // PILCROW SIGN 0x00B7, // MIDDLE DOT 0x00B8, // CEDILLA 0x00B9, // SUPERSCRIPT ONE 0x00BA, // MASCULINE ORDINAL INDICATOR 0x00BB, // RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK 0x00BC, // VULGAR FRACTION ONE QUARTER 0x00BD, // VULGAR FRACTION ONE HALF 0x00BE, // VULGAR FRACTION THREE QUARTERS 0x00BF, // INVERTED QUESTION MARK 0x00C0, // LATIN CAPITAL LETTER A WITH GRAVE 0x00C1, // LATIN CAPITAL LETTER A WITH ACUTE 0x00C2, // LATIN CAPITAL LETTER A WITH CIRCUMFLEX 0x00C3, // LATIN CAPITAL LETTER A WITH TILDE 0x00C4, // LATIN CAPITAL LETTER A WITH DIAERESIS 0x00C5, // LATIN CAPITAL LETTER A WITH RING ABOVE 0x00C6, // LATIN CAPITAL LETTER AE 0x00C7, // LATIN CAPITAL LETTER C WITH CEDILLA 0x00C8, // LATIN CAPITAL LETTER E WITH GRAVE 0x00C9, // LATIN CAPITAL LETTER E WITH ACUTE 0x00CA, // LATIN CAPITAL LETTER E WITH CIRCUMFLEX 0x00CB, // LATIN CAPITAL LETTER E WITH DIAERESIS 0x00CC, // LATIN CAPITAL LETTER I WITH GRAVE 0x00CD, // LATIN CAPITAL LETTER I WITH ACUTE 0x00CE, // LATIN CAPITAL LETTER I WITH CIRCUMFLEX 0x00CF, // LATIN CAPITAL LETTER I WITH DIAERESIS 0x00D0, // LATIN CAPITAL LETTER ETH 0x00D1, // LATIN CAPITAL LETTER N WITH TILDE 0x00D2, // LATIN CAPITAL LETTER O WITH GRAVE 0x00D3, // LATIN CAPITAL LETTER O WITH ACUTE 0x00D4, // LATIN CAPITAL LETTER O WITH CIRCUMFLEX 0x00D5, // LATIN CAPITAL LETTER O WITH TILDE 0x00D6, // LATIN CAPITAL LETTER O WITH DIAERESIS 0x00D7, // MULTIPLICATION SIGN 0x00D8, // LATIN CAPITAL LETTER O WITH STROKE 0x00D9, // LATIN CAPITAL LETTER U WITH GRAVE 0x00DA, // LATIN CAPITAL LETTER U WITH ACUTE 0x00DB, // LATIN CAPITAL LETTER U WITH CIRCUMFLEX 0x00DC, // LATIN CAPITAL LETTER U WITH DIAERESIS 0x00DD, // LATIN CAPITAL LETTER Y WITH ACUTE 0x00DE, // LATIN CAPITAL LETTER THORN 0x00DF, // LATIN SMALL LETTER SHARP S 0x00E0, // LATIN SMALL LETTER A WITH GRAVE 0x00E1, // LATIN SMALL LETTER A WITH ACUTE 0x00E2, // LATIN SMALL LETTER A WITH CIRCUMFLEX 0x00E3, // LATIN SMALL LETTER A WITH TILDE 0x00E4, // LATIN SMALL LETTER A WITH DIAERESIS 0x00E5, // LATIN SMALL LETTER A WITH RING ABOVE 0x00E6, // LATIN SMALL LETTER AE 0x00E7, // LATIN SMALL LETTER C WITH CEDILLA 0x00E8, // LATIN SMALL LETTER E WITH GRAVE 0x00E9, // LATIN SMALL LETTER E WITH ACUTE 0x00EA, // LATIN SMALL LETTER E WITH CIRCUMFLEX 0x00EB, // LATIN SMALL LETTER E WITH DIAERESIS 0x00EC, // LATIN SMALL LETTER I WITH GRAVE 0x00ED, // LATIN SMALL LETTER I WITH ACUTE 0x00EE, // LATIN SMALL LETTER I WITH CIRCUMFLEX 0x00EF, // LATIN SMALL LETTER I WITH DIAERESIS 0x00F0, // LATIN SMALL LETTER ETH 0x00F1, // LATIN SMALL LETTER N WITH TILDE 0x00F2, // LATIN SMALL LETTER O WITH GRAVE 0x00F3, // LATIN SMALL LETTER O WITH ACUTE 0x00F4, // LATIN SMALL LETTER O WITH CIRCUMFLEX 0x00F5, // LATIN SMALL LETTER O WITH TILDE 0x00F6, // LATIN SMALL LETTER O WITH DIAERESIS 0x00F7, // DIVISION SIGN 0x00F8, // LATIN SMALL LETTER O WITH STROKE 0x00F9, // LATIN SMALL LETTER U WITH GRAVE 0x00FA, // LATIN SMALL LETTER U WITH ACUTE 0x00FB, // LATIN SMALL LETTER U WITH CIRCUMFLEX 0x00FC, // LATIN SMALL LETTER U WITH DIAERESIS 0x00FD, // LATIN SMALL LETTER Y WITH ACUTE 0x00FE, // LATIN SMALL LETTER THORN 0x00FF, // LATIN SMALL LETTER Y WITH DIAERESIS }; // ----------------------------------------------------- // PdfMacRomanEncoding // ----------------------------------------------------- // ----------------------------------------------------- // // ----------------------------------------------------- const pdf_utf16be* PdfMacRomanEncoding::GetToUnicodeTable() const { return PdfMacRomanEncoding::s_cEncoding; } const pdf_utf16be PdfMacRomanEncoding::s_cEncoding[256] = { 0x0000, // NULL 0x0001, // START OF HEADING 0x0002, // START OF TEXT 0x0003, // END OF TEXT 0x0004, // END OF TRANSMISSION 0x0005, // ENQUIRY 0x0006, // ACKNOWLEDGE 0x0007, // BELL 0x0008, // BACKSPACE 0x0009, // HORIZONTAL TABULATION 0x000A, // LINE FEED 0x000B, // VERTICAL TABULATION 0x000C, // FORM FEED 0x000D, // CARRIAGE RETURN 0x000E, // SHIFT OUT 0x000F, // SHIFT IN 0x0010, // DATA LINK ESCAPE 0x0011, // DEVICE CONTROL ONE 0x0012, // DEVICE CONTROL TWO 0x0013, // DEVICE CONTROL THREE 0x0014, // DEVICE CONTROL FOUR 0x0015, // NEGATIVE ACKNOWLEDGE 0x0016, // SYNCHRONOUS IDLE 0x0017, // END OF TRANSMISSION BLOCK 0x0018, // CANCEL 0x0019, // END OF MEDIUM 0x001A, // SUBSTITUTE 0x001B, // ESCAPE 0x001C, // FILE SEPARATOR 0x001D, // GROUP SEPARATOR 0x001E, // RECORD SEPARATOR 0x001F, // UNIT SEPARATOR 0x0020, // SPACE 0x0021, // EXCLAMATION MARK 0x0022, // QUOTATION MARK 0x0023, // NUMBER SIGN 0x0024, // DOLLAR SIGN 0x0025, // PERCENT SIGN 0x0026, // AMPERSAND 0x0027, // APOSTROPHE 0x0028, // LEFT PARENTHESIS 0x0029, // RIGHT PARENTHESIS 0x002A, // ASTERISK 0x002B, // PLUS SIGN 0x002C, // COMMA 0x002D, // HYPHEN-MINUS 0x002E, // FULL STOP 0x002F, // SOLIDUS 0x0030, // DIGIT ZERO 0x0031, // DIGIT ONE 0x0032, // DIGIT TWO 0x0033, // DIGIT THREE 0x0034, // DIGIT FOUR 0x0035, // DIGIT FIVE 0x0036, // DIGIT SIX 0x0037, // DIGIT SEVEN 0x0038, // DIGIT EIGHT 0x0039, // DIGIT NINE 0x003A, // COLON 0x003B, // SEMICOLON 0x003C, // LESS-THAN SIGN 0x003D, // EQUALS SIGN 0x003E, // GREATER-THAN SIGN 0x003F, // QUESTION MARK 0x0040, // COMMERCIAL AT 0x0041, // LATIN CAPITAL LETTER A 0x0042, // LATIN CAPITAL LETTER B 0x0043, // LATIN CAPITAL LETTER C 0x0044, // LATIN CAPITAL LETTER D 0x0045, // LATIN CAPITAL LETTER E 0x0046, // LATIN CAPITAL LETTER F 0x0047, // LATIN CAPITAL LETTER G 0x0048, // LATIN CAPITAL LETTER H 0x0049, // LATIN CAPITAL LETTER I 0x004A, // LATIN CAPITAL LETTER J 0x004B, // LATIN CAPITAL LETTER K 0x004C, // LATIN CAPITAL LETTER L 0x004D, // LATIN CAPITAL LETTER M 0x004E, // LATIN CAPITAL LETTER N 0x004F, // LATIN CAPITAL LETTER O 0x0050, // LATIN CAPITAL LETTER P 0x0051, // LATIN CAPITAL LETTER Q 0x0052, // LATIN CAPITAL LETTER R 0x0053, // LATIN CAPITAL LETTER S 0x0054, // LATIN CAPITAL LETTER T 0x0055, // LATIN CAPITAL LETTER U 0x0056, // LATIN CAPITAL LETTER V 0x0057, // LATIN CAPITAL LETTER W 0x0058, // LATIN CAPITAL LETTER X 0x0059, // LATIN CAPITAL LETTER Y 0x005A, // LATIN CAPITAL LETTER Z 0x005B, // LEFT SQUARE BRACKET 0x005C, // REVERSE SOLIDUS 0x005D, // RIGHT SQUARE BRACKET 0x005E, // CIRCUMFLEX ACCENT 0x005F, // LOW LINE 0x0060, // GRAVE ACCENT 0x0061, // LATIN SMALL LETTER A 0x0062, // LATIN SMALL LETTER B 0x0063, // LATIN SMALL LETTER C 0x0064, // LATIN SMALL LETTER D 0x0065, // LATIN SMALL LETTER E 0x0066, // LATIN SMALL LETTER F 0x0067, // LATIN SMALL LETTER G 0x0068, // LATIN SMALL LETTER H 0x0069, // LATIN SMALL LETTER I 0x006A, // LATIN SMALL LETTER J 0x006B, // LATIN SMALL LETTER K 0x006C, // LATIN SMALL LETTER L 0x006D, // LATIN SMALL LETTER M 0x006E, // LATIN SMALL LETTER N 0x006F, // LATIN SMALL LETTER O 0x0070, // LATIN SMALL LETTER P 0x0071, // LATIN SMALL LETTER Q 0x0072, // LATIN SMALL LETTER R 0x0073, // LATIN SMALL LETTER S 0x0074, // LATIN SMALL LETTER T 0x0075, // LATIN SMALL LETTER U 0x0076, // LATIN SMALL LETTER V 0x0077, // LATIN SMALL LETTER W 0x0078, // LATIN SMALL LETTER X 0x0079, // LATIN SMALL LETTER Y 0x007A, // LATIN SMALL LETTER Z 0x007B, // LEFT CURLY BRACKET 0x007C, // VERTICAL LINE 0x007D, // RIGHT CURLY BRACKET 0x007E, // TILDE 0x007F, // DEL 0x00C4, // LATIN CAPITAL LETTER A WITH DIAERESIS 0x00C5, // LATIN CAPITAL LETTER A WITH RING ABOVE 0x00C7, // LATIN CAPITAL LETTER C WITH CEDILLA 0x00C9, // LATIN CAPITAL LETTER E WITH ACUTE 0x00D1, // LATIN CAPITAL LETTER N WITH TILDE 0x00D6, // LATIN CAPITAL LETTER O WITH DIAERESIS 0x00DC, // LATIN CAPITAL LETTER U WITH DIAERESIS 0x00E1, // LATIN SMALL LETTER A WITH ACUTE 0x00E0, // LATIN SMALL LETTER A WITH GRAVE 0x00E2, // LATIN SMALL LETTER A WITH CIRCUMFLEX 0x00E4, // LATIN SMALL LETTER A WITH DIAERESIS 0x00E3, // LATIN SMALL LETTER A WITH TILDE 0x00E5, // LATIN SMALL LETTER A WITH RING ABOVE 0x00E7, // LATIN SMALL LETTER C WITH CEDILLA 0x00E9, // LATIN SMALL LETTER E WITH ACUTE 0x00E8, // LATIN SMALL LETTER E WITH GRAVE 0x00EA, // LATIN SMALL LETTER E WITH CIRCUMFLEX 0x00EB, // LATIN SMALL LETTER E WITH DIAERESIS 0x00ED, // LATIN SMALL LETTER I WITH ACUTE 0x00EC, // LATIN SMALL LETTER I WITH GRAVE 0x00EE, // LATIN SMALL LETTER I WITH CIRCUMFLEX 0x00EF, // LATIN SMALL LETTER I WITH DIAERESIS 0x00F1, // LATIN SMALL LETTER N WITH TILDE 0x00F3, // LATIN SMALL LETTER O WITH ACUTE 0x00F2, // LATIN SMALL LETTER O WITH GRAVE 0x00F4, // LATIN SMALL LETTER O WITH CIRCUMFLEX 0x00F6, // LATIN SMALL LETTER O WITH DIAERESIS 0x00F5, // LATIN SMALL LETTER O WITH TILDE 0x00FA, // LATIN SMALL LETTER U WITH ACUTE 0x00F9, // LATIN SMALL LETTER U WITH GRAVE 0x00FB, // LATIN SMALL LETTER U WITH CIRCUMFLEX 0x00FC, // LATIN SMALL LETTER U WITH DIAERESIS 0x2020, // DAGGER 0x00B0, // DEGREE SIGN 0x00A2, // CENT SIGN 0x00A3, // POUND SIGN 0x00A7, // SECTION SIGN 0x2022, // BULLET 0x00B6, // PILCROW SIGN 0x00DF, // LATIN SMALL LETTER SHARP S 0x00AE, // REGISTERED SIGN 0x00A9, // COPYRIGHT SIGN 0x2122, // TRADE MARK SIGN 0x00B4, // ACUTE ACCENT 0x00A8, // DIAERESIS 0x2260, // NOT EQUAL TO 0x00C6, // LATIN CAPITAL LETTER AE 0x00D8, // LATIN CAPITAL LETTER O WITH STROKE 0x221E, // INFINITY 0x00B1, // PLUS-MINUS SIGN 0x2264, // LESS-THAN OR EQUAL TO 0x2265, // GREATER-THAN OR EQUAL TO 0x00A5, // YEN SIGN 0x00B5, // MICRO SIGN 0x2202, // PARTIAL DIFFERENTIAL 0x2211, // N-ARY SUMMATION 0x220F, // N-ARY PRODUCT 0x03C0, // GREEK SMALL LETTER PI 0x222B, // INTEGRAL 0x00AA, // FEMININE ORDINAL INDICATOR 0x00BA, // MASCULINE ORDINAL INDICATOR 0x03A9, // GREEK CAPITAL LETTER OMEGA 0x00E6, // LATIN SMALL LETTER AE 0x00F8, // LATIN SMALL LETTER O WITH STROKE 0x00BF, // INVERTED QUESTION MARK 0x00A1, // INVERTED EXCLAMATION MARK 0x00AC, // NOT SIGN 0x221A, // SQUARE ROOT 0x0192, // LATIN SMALL LETTER F WITH HOOK 0x2248, // ALMOST EQUAL TO 0x2206, // INCREMENT 0x00AB, // LEFT-POINTING DOUBLE ANGLE QUOTATION MARK 0x00BB, // RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK 0x2026, // HORIZONTAL ELLIPSIS 0x00A0, // NO-BREAK SPACE 0x00C0, // LATIN CAPITAL LETTER A WITH GRAVE 0x00C3, // LATIN CAPITAL LETTER A WITH TILDE 0x00D5, // LATIN CAPITAL LETTER O WITH TILDE 0x0152, // LATIN CAPITAL LIGATURE OE 0x0153, // LATIN SMALL LIGATURE OE 0x2013, // EN DASH 0x2014, // EM DASH 0x201C, // LEFT DOUBLE QUOTATION MARK 0x201D, // RIGHT DOUBLE QUOTATION MARK 0x2018, // LEFT SINGLE QUOTATION MARK 0x2019, // RIGHT SINGLE QUOTATION MARK 0x00F7, // DIVISION SIGN 0x25CA, // LOZENGE 0x00FF, // LATIN SMALL LETTER Y WITH DIAERESIS 0x0178, // LATIN CAPITAL LETTER Y WITH DIAERESIS 0x2044, // FRACTION SLASH 0x20AC, // EURO SIGN 0x2039, // SINGLE LEFT-POINTING ANGLE QUOTATION MARK 0x203A, // SINGLE RIGHT-POINTING ANGLE QUOTATION MARK 0xFB01, // LATIN SMALL LIGATURE FI 0xFB02, // LATIN SMALL LIGATURE FL 0x2021, // DOUBLE DAGGER 0x00B7, // MIDDLE DOT 0x201A, // SINGLE LOW-9 QUOTATION MARK 0x201E, // DOUBLE LOW-9 QUOTATION MARK 0x2030, // PER MILLE SIGN 0x00C2, // LATIN CAPITAL LETTER A WITH CIRCUMFLEX 0x00CA, // LATIN CAPITAL LETTER E WITH CIRCUMFLEX 0x00C1, // LATIN CAPITAL LETTER A WITH ACUTE 0x00CB, // LATIN CAPITAL LETTER E WITH DIAERESIS 0x00C8, // LATIN CAPITAL LETTER E WITH GRAVE 0x00CD, // LATIN CAPITAL LETTER I WITH ACUTE 0x00CE, // LATIN CAPITAL LETTER I WITH CIRCUMFLEX 0x00CF, // LATIN CAPITAL LETTER I WITH DIAERESIS 0x00CC, // LATIN CAPITAL LETTER I WITH GRAVE 0x00D3, // LATIN CAPITAL LETTER O WITH ACUTE 0x00D4, // LATIN CAPITAL LETTER O WITH CIRCUMFLEX 0xF8FF, // Apple logo 0x00D2, // LATIN CAPITAL LETTER O WITH GRAVE 0x00DA, // LATIN CAPITAL LETTER U WITH ACUTE 0x00DB, // LATIN CAPITAL LETTER U WITH CIRCUMFLEX 0x00D9, // LATIN CAPITAL LETTER U WITH GRAVE 0x0131, // LATIN SMALL LETTER DOTLESS I 0x02C6, // MODIFIER LETTER CIRCUMFLEX ACCENT 0x02DC, // SMALL TILDE 0x00AF, // MACRON 0x02D8, // BREVE 0x02D9, // DOT ABOVE 0x02DA, // RING ABOVE 0x00B8, // CEDILLA 0x02DD, // DOUBLE ACUTE ACCENT 0x02DB, // OGONEK 0x02C7, // CARON }; // OC 13.08.2010 New: PdfMacExpertEncoding // ----------------------------------------------------- // PdfMacExpertEncoding // See: ghostscript-8.71/Resource/Init/gs_mex_e.ps // --> array of 256 glyphs for MacExpertEncoding // See: http://www.adobe.com/devnet/opentype/archives/glyphlist.txt // --> glyphs to unicodes // ----------------------------------------------------- // ----------------------------------------------------- // // ----------------------------------------------------- const pdf_utf16be* PdfMacExpertEncoding::GetToUnicodeTable() const { return PdfMacExpertEncoding::s_cEncoding; } const pdf_utf16be PdfMacExpertEncoding::s_cEncoding[256] = { // \00x 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // \04x 0x0020, 0xF721, 0xF6F8, 0xF7A2, 0xF724, 0xF6E4, 0xF726, 0xF7B4, 0x207D, 0x207E, 0x2025, 0x2024, 0x002C, 0x002D, 0x002E, 0x2044, 0xF730, 0xF731, 0xF732, 0xF733, 0xF734, 0xF735, 0xF736, 0xF737, 0xF738, 0xF739, 0x003A, 0x003B, 0x0000, 0xF6DE, 0x0000, 0xF73F, // \10x 0x0000, 0x0000, 0x0000, 0x0000, 0xF7F0, 0x0000, 0x0000, 0x00BC, 0x00BD, 0x00BE, 0x215B, 0x215C, 0x215D, 0x215E, 0x2153, 0x2154, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFB00, 0xFB01, 0xFB02, 0xFB03, 0xFB04, 0x208D, 0x0000, 0x208E, 0xF6F6, 0xF6E5, // \14x 0xF760, 0xF761, 0xF762, 0xF763, 0xF764, 0xF765, 0xF766, 0xF767, 0xF768, 0xF769, 0xF76A, 0xF76B, 0xF76C, 0xF76D, 0xF76E, 0xF76F, 0xF770, 0xF771, 0xF772, 0xF773, 0xF774, 0xF775, 0xF776, 0xF777, 0xF778, 0xF779, 0xF77A, 0x20A1, 0xF6DC, 0xF6DD, 0xF6FE, 0x0000, // \20x 0x0000, 0xF6E9, 0xF6E0, 0x0000, 0x0000, 0x0000, 0x0000, 0xF7E1, 0xF7E0, 0xF7E2, 0xF7E4, 0xF7E3, 0xF7E5, 0xF7E7, 0xF7E9, 0xF7E8, 0xF7EA, 0xF7EB, 0xF7ED, 0xF7EC, 0xF7EE, 0xF7EF, 0xF7F1, 0xF7F3, 0xF7F2, 0xF7F4, 0xF7F6, 0xF7F5, 0xF7FA, 0xF7F9, 0xF7FB, 0xF7FC, // \24x 0x0000, 0x2078, 0x2084, 0x2083, 0x2086, 0x2088, 0x2087, 0xF6FD, 0x0000, 0xF6DF, 0x2082, 0x0000, 0xF7A8, 0x0000, 0xF6F5, 0xF6F0, 0x2085, 0x0000, 0xF6E1, 0xF6E7, 0xF7FD, 0x0000, 0xF6E3, 0x0000, 0x0000, 0xF7FE, 0x0000, 0x2089, 0x2080, 0xF6FF, 0xF7E6, 0xF7F8, // \30x 0xF7BF, 0x2081, 0xF6F9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xF7B8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xF6FA, 0x2012, 0xF6E6, 0x0000, 0x0000, 0x0000, 0x0000, 0xF7A1, 0x0000, 0xF7FF, 0x0000, 0x00B9, 0x00B2, 0x00B3, 0x2074, 0x2075, 0x2076, // \34x 0x2077, 0x2079, 0x2070, 0x0000, 0xF6EC, 0xF6F1, 0xF6F3, 0x0000, 0x0000, 0xF6ED, 0xF6F2, 0xF6EB, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xF6EE, 0xF6FB, 0xF6F4, 0xF7AF, 0xF6EA, 0x207F, 0xF6EF, 0xF6E2, 0xF6E8, 0xF6F7, 0xF6FC, 0x0000, 0x0000, 0x0000, 0x0000 }; // OC 13.08.2010 New: PdfStandardEncoding // ----------------------------------------------------- // PdfStandardEncoding // See: http://unicode.org/Public/MAPPINGS/VENDORS/ADOBE/stdenc.txt // ----------------------------------------------------- // ----------------------------------------------------- // // ----------------------------------------------------- const pdf_utf16be* PdfStandardEncoding::GetToUnicodeTable() const { return PdfStandardEncoding::s_cEncoding; } const pdf_utf16be PdfStandardEncoding::s_cEncoding[256] = { //0, // uncomment to check compiler error cause of 257 members // 0x00..0x1f undefined: 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0020, // 20 # SPACE # space // Duplicated char, commented out // 0x00A0, // 20 # NO-BREAK SPACE # space 0x0021, // 21 # EXCLAMATION MARK # exclam 0x0022, // 22 # QUOTATION MARK # quotedbl 0x0023, // 23 # NUMBER SIGN # numbersign 0x0024, // 24 # DOLLAR SIGN # dollar 0x0025, // 25 # PERCENT SIGN # percent 0x0026, // 26 # AMPERSAND # ampersand 0x2019, // 27 # RIGHT SINGLE QUOTATION MARK # quoteright 0x0028, // 28 # LEFT PARENTHESIS # parenleft 0x0029, // 29 # RIGHT PARENTHESIS # parenright 0x002A, // 2A # ASTERISK # asterisk 0x002B, // 2B # PLUS SIGN # plus 0x002C, // 2C # COMMA # comma 0x002D, // 2D # HYPHEN-MINUS # hyphen // Duplicated char, commented out // 0x00AD, // 2D # SOFT HYPHEN # hyphen 0x002E, // 2E # FULL STOP # period 0x002F, // 2F # SOLIDUS # slash 0x0030, // 30 # DIGIT ZERO # zero 0x0031, // 31 # DIGIT ONE # one 0x0032, // 32 # DIGIT TWO # two 0x0033, // 33 # DIGIT THREE # three 0x0034, // 34 # DIGIT FOUR # four 0x0035, // 35 # DIGIT FIVE # five 0x0036, // 36 # DIGIT SIX # six 0x0037, // 37 # DIGIT SEVEN # seven 0x0038, // 38 # DIGIT EIGHT # eight 0x0039, // 39 # DIGIT NINE # nine 0x003A, // 3A # COLON # colon 0x003B, // 3B # SEMICOLON # semicolon 0x003C, // 3C # LESS-THAN SIGN # less 0x003D, // 3D # EQUALS SIGN # equal 0x003E, // 3E # GREATER-THAN SIGN # greater 0x003F, // 3F # QUESTION MARK # question 0x0040, // 40 # COMMERCIAL AT # at 0x0041, // 41 # LATIN CAPITAL LETTER A # A 0x0042, // 42 # LATIN CAPITAL LETTER B # B 0x0043, // 43 # LATIN CAPITAL LETTER C # C 0x0044, // 44 # LATIN CAPITAL LETTER D # D 0x0045, // 45 # LATIN CAPITAL LETTER E # E 0x0046, // 46 # LATIN CAPITAL LETTER F # F 0x0047, // 47 # LATIN CAPITAL LETTER G # G 0x0048, // 48 # LATIN CAPITAL LETTER H # H 0x0049, // 49 # LATIN CAPITAL LETTER I # I 0x004A, // 4A # LATIN CAPITAL LETTER J # J 0x004B, // 4B # LATIN CAPITAL LETTER K # K 0x004C, // 4C # LATIN CAPITAL LETTER L # L 0x004D, // 4D # LATIN CAPITAL LETTER M # M 0x004E, // 4E # LATIN CAPITAL LETTER N # N 0x004F, // 4F # LATIN CAPITAL LETTER O # O 0x0050, // 50 # LATIN CAPITAL LETTER P # P 0x0051, // 51 # LATIN CAPITAL LETTER Q # Q 0x0052, // 52 # LATIN CAPITAL LETTER R # R 0x0053, // 53 # LATIN CAPITAL LETTER S # S 0x0054, // 54 # LATIN CAPITAL LETTER T # T 0x0055, // 55 # LATIN CAPITAL LETTER U # U 0x0056, // 56 # LATIN CAPITAL LETTER V # V 0x0057, // 57 # LATIN CAPITAL LETTER W # W 0x0058, // 58 # LATIN CAPITAL LETTER X # X 0x0059, // 59 # LATIN CAPITAL LETTER Y # Y 0x005A, // 5A # LATIN CAPITAL LETTER Z # Z 0x005B, // 5B # LEFT SQUARE BRACKET # bracketleft 0x005C, // 5C # REVERSE SOLIDUS # backslash 0x005D, // 5D # RIGHT SQUARE BRACKET # bracketright 0x005E, // 5E # CIRCUMFLEX ACCENT # asciicircum 0x005F, // 5F # LOW LINE # underscore #if 1 0x0060, // 60 # GRAVE ACCENT #else // OC 13.08.2010: See http://unicode.org/Public/MAPPINGS/VENDORS/ADOBE/stdenc.txt // The following unicode char should be encoded here. // But i keep the identity ascii 7bit sign. 0x2018, // 60 # LEFT SINGLE QUOTATION MARK # quoteleft #endif 0x0061, // 61 # LATIN SMALL LETTER A # a 0x0062, // 62 # LATIN SMALL LETTER B # b 0x0063, // 63 # LATIN SMALL LETTER C # c 0x0064, // 64 # LATIN SMALL LETTER D # d 0x0065, // 65 # LATIN SMALL LETTER E # e 0x0066, // 66 # LATIN SMALL LETTER F # f 0x0067, // 67 # LATIN SMALL LETTER G # g 0x0068, // 68 # LATIN SMALL LETTER H # h 0x0069, // 69 # LATIN SMALL LETTER I # i 0x006A, // 6A # LATIN SMALL LETTER J # j 0x006B, // 6B # LATIN SMALL LETTER K # k 0x006C, // 6C # LATIN SMALL LETTER L # l 0x006D, // 6D # LATIN SMALL LETTER M # m 0x006E, // 6E # LATIN SMALL LETTER N # n 0x006F, // 6F # LATIN SMALL LETTER O # o 0x0070, // 70 # LATIN SMALL LETTER P # p 0x0071, // 71 # LATIN SMALL LETTER Q # q 0x0072, // 72 # LATIN SMALL LETTER R # r 0x0073, // 73 # LATIN SMALL LETTER S # s 0x0074, // 74 # LATIN SMALL LETTER T # t 0x0075, // 75 # LATIN SMALL LETTER U # u 0x0076, // 76 # LATIN SMALL LETTER V # v 0x0077, // 77 # LATIN SMALL LETTER W # w 0x0078, // 78 # LATIN SMALL LETTER X # x 0x0079, // 79 # LATIN SMALL LETTER Y # y 0x007A, // 7A # LATIN SMALL LETTER Z # z 0x007B, // 7B # LEFT CURLY BRACKET # braceleft 0x007C, // 7C # VERTICAL LINE # bar 0x007D, // 7D # RIGHT CURLY BRACKET # braceright 0x007E, // 7E # TILDE # asciitilde // 0x7f..0xA0 undefined: 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x00A1, // A1 # INVERTED EXCLAMATION MARK # exclamdown 0x00A2, // A2 # CENT SIGN # cent 0x00A3, // A3 # POUND SIGN # sterling 0x2044, // A4 # FRACTION SLASH # fraction // Duplicated char, commented out // 0x2215, // A4 # DIVISION SLASH # fraction 0x00A5, // A5 # YEN SIGN # yen 0x0192, // A6 # LATIN SMALL LETTER F WITH HOOK # florin 0x00A7, // A7 # SECTION SIGN # section 0x00A4, // A8 # CURRENCY SIGN # currency 0x0027, // A9 # APOSTROPHE # quotesingle 0x201C, // AA # LEFT DOUBLE QUOTATION MARK # quotedblleft 0x00AB, // AB # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK # guillemotleft 0x2039, // AC # SINGLE LEFT-POINTING ANGLE QUOTATION MARK # guilsinglleft 0x203A, // AD # SINGLE RIGHT-POINTING ANGLE QUOTATION MARK # guilsinglright 0xFB01, // AE # LATIN SMALL LIGATURE FI # fi 0xFB02, // AF # LATIN SMALL LIGATURE FL # fl 0x0000, // B0 undefined 0x2013, // B1 # EN DASH # endash 0x2020, // B2 # DAGGER # dagger 0x2021, // B3 # DOUBLE DAGGER # daggerdbl 0x00B7, // B4 # MIDDLE DOT # periodcentered // 0x2219, // B4 # BULLET OPERATOR # periodcentered 0x0000, // B5 undefined 0x00B6, // B6 # PILCROW SIGN # paragraph 0x2022, // B7 # BULLET # bullet 0x201A, // B8 # SINGLE LOW-9 QUOTATION MARK # quotesinglbase 0x201E, // B9 # DOUBLE LOW-9 QUOTATION MARK # quotedblbase 0x201D, // BA # RIGHT DOUBLE QUOTATION MARK # quotedblright 0x00BB, // BB # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK # guillemotright 0x2026, // BC # HORIZONTAL ELLIPSIS # ellipsis 0x2030, // BD # PER MILLE SIGN # perthousand 0x0000, // BE undefined 0x00BF, // BF # INVERTED QUESTION MARK # questiondown 0x0000, // C0 undefined 0x0060, // C1 # GRAVE ACCENT # grave 0x00B4, // C2 # ACUTE ACCENT # acute 0x02C6, // C3 # MODIFIER LETTER CIRCUMFLEX ACCENT # circumflex 0x02DC, // C4 # SMALL TILDE # tilde 0x00AF, // C5 # MACRON # macron // Duplicated char, commented out //0x02C9, // C5 # MODIFIER LETTER MACRON # macron 0x02D8, // C6 # BREVE # breve 0x02D9, // C7 # DOT ABOVE # dotaccent 0x00A8, // C8 # DIAERESIS # dieresis 0x0000, // C9 undefined 0x02DA, // CA # RING ABOVE # ring 0x00B8, // CB # CEDILLA # cedilla 0x02DD, // CD # DOUBLE ACUTE ACCENT # hungarumlaut 0x02DB, // CE # OGONEK # ogonek 0x02C7, // CF # CARON # caron 0x2014, // D0 # EM DASH # emdash 0x0000, // D1 undefined 0x0000, // D2 undefined 0x0000, // D3 undefined 0x0000, // D4 undefined 0x0000, // D5 undefined 0x0000, // D6 undefined 0x0000, // D7 undefined 0x0000, // D8 undefined 0x0000, // D9 undefined 0x0000, // DA undefined 0x0000, // DB undefined 0x0000, // DC undefined 0x0000, // DD undefined 0x0000, // DE undefined 0x0000, // DF undefined 0x0000, // E0 undefined 0x00C6, // E1 # LATIN CAPITAL LETTER AE # AE 0x0000, // E2 undefined 0x00AA, // E3 # FEMININE ORDINAL INDICATOR # ordfeminine 0x0000, // E4 undefined 0x0000, // E5 undefined 0x0000, // E6 undefined 0x0000, // E7 undefined 0x0141, // E8 # LATIN CAPITAL LETTER L WITH STROKE # Lslash 0x00D8, // E9 # LATIN CAPITAL LETTER O WITH STROKE # Oslash 0x0152, // EA # LATIN CAPITAL LIGATURE OE # OE 0x00BA, // EB # MASCULINE ORDINAL INDICATOR # ordmasculine 0x0000, // EC undefined 0x0000, // ED undefined 0x0000, // EE undefined 0x0000, // EF undefined 0x0000, // F0 undefined 0x00E6, // F1 # LATIN SMALL LETTER AE # ae 0x0000, // F2 undefined 0x0000, // F3 undefined 0x0000, // F4 undefined 0x0131, // F5 # LATIN SMALL LETTER DOTLESS I # dotlessi 0x0000, // F6 undefined 0x0000, // F7 undefined 0x0142, // F8 # LATIN SMALL LETTER L WITH STROKE # lslash 0x00F8, // F9 # LATIN SMALL LETTER O WITH STROKE # oslash 0x0153, // FA # LATIN SMALL LIGATURE OE # oe 0x00DF, // FB # LATIN SMALL LETTER SHARP S # germandbls 0x0000, // FC undefined 0x0000, // FD undefined 0x0000, // FE undefined 0x0000 // FF undefined }; // OC 13.08.2010 New: PdfSymbolEncoding // ----------------------------------------------------- // PdfSymbolEncoding // See: http://unicode.org/Public/MAPPINGS/VENDORS/ADOBE/symbol.txt // ----------------------------------------------------- // ----------------------------------------------------- // // ----------------------------------------------------- const pdf_utf16be* PdfSymbolEncoding::GetToUnicodeTable() const { return PdfSymbolEncoding::s_cEncoding; } const pdf_utf16be PdfSymbolEncoding::s_cEncoding[256] = { //0, // uncomment to check compiler error cause of 257 members // 0x00..0x1f undefined: 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0020, // 20 # SPACE # space // 0x00A0, // 20 # NO-BREAK SPACE # space 0x0021, // 21 # EXCLAMATION MARK # exclam 0x2200, // 22 # FOR ALL # universal 0x0023, // 23 # NUMBER SIGN # numbersign 0x2203, // 24 # THERE EXISTS # existential 0x0025, // 25 # PERCENT SIGN # percent 0x0026, // 26 # AMPERSAND # ampersand 0x220B, // 27 # CONTAINS AS MEMBER # suchthat 0x0028, // 28 # LEFT PARENTHESIS # parenleft 0x0029, // 29 # RIGHT PARENTHESIS # parenright 0x2217, // 2A # ASTERISK OPERATOR # asteriskmath 0x002B, // 2B # PLUS SIGN # plus 0x002C, // 2C # COMMA # comma 0x2212, // 2D # MINUS SIGN # minus 0x002E, // 2E # FULL STOP # period 0x002F, // 2F # SOLIDUS # slash 0x0030, // 30 # DIGIT ZERO # zero 0x0031, // 31 # DIGIT ONE # one 0x0032, // 32 # DIGIT TWO # two 0x0033, // 33 # DIGIT THREE # three 0x0034, // 34 # DIGIT FOUR # four 0x0035, // 35 # DIGIT FIVE # five 0x0036, // 36 # DIGIT SIX # six 0x0037, // 37 # DIGIT SEVEN # seven 0x0038, // 38 # DIGIT EIGHT # eight 0x0039, // 39 # DIGIT NINE # nine 0x003A, // 3A # COLON # colon 0x003B, // 3B # SEMICOLON # semicolon 0x003C, // 3C # LESS-THAN SIGN # less 0x003D, // 3D # EQUALS SIGN # equal 0x003E, // 3E # GREATER-THAN SIGN # greater 0x003F, // 3F # QUESTION MARK # question 0x2245, // 40 # APPROXIMATELY EQUAL TO # congruent 0x0391, // 41 # GREEK CAPITAL LETTER ALPHA # Alpha 0x0392, // 42 # GREEK CAPITAL LETTER BETA # Beta 0x03A7, // 43 # GREEK CAPITAL LETTER CHI # Chi 0x0394, // 44 # GREEK CAPITAL LETTER DELTA # Delta // 0x2206, // 44 # INCREMENT # Delta 0x0395, // 45 # GREEK CAPITAL LETTER EPSILON # Epsilon 0x03A6, // 46 # GREEK CAPITAL LETTER PHI # Phi 0x0393, // 47 # GREEK CAPITAL LETTER GAMMA # Gamma 0x0397, // 48 # GREEK CAPITAL LETTER ETA # Eta 0x0399, // 49 # GREEK CAPITAL LETTER IOTA # Iota 0x03D1, // 4A # GREEK THETA SYMBOL # theta1 0x039A, // 4B # GREEK CAPITAL LETTER KAPPA # Kappa 0x039B, // 4C # GREEK CAPITAL LETTER LAMDA # Lambda 0x039C, // 4D # GREEK CAPITAL LETTER MU # Mu 0x039D, // 4E # GREEK CAPITAL LETTER NU # Nu 0x039F, // 4F # GREEK CAPITAL LETTER OMICRON # Omicron 0x03A0, // 50 # GREEK CAPITAL LETTER PI # Pi 0x0398, // 51 # GREEK CAPITAL LETTER THETA # Theta 0x03A1, // 52 # GREEK CAPITAL LETTER RHO # Rho 0x03A3, // 53 # GREEK CAPITAL LETTER SIGMA # Sigma 0x03A4, // 54 # GREEK CAPITAL LETTER TAU # Tau 0x03A5, // 55 # GREEK CAPITAL LETTER UPSILON # Upsilon 0x03C2, // 56 # GREEK SMALL LETTER FINAL SIGMA # sigma1 0x03A9, // 57 # GREEK CAPITAL LETTER OMEGA # Omega // 0x2126, // 57 # OHM SIGN # Omega 0x039E, // 58 # GREEK CAPITAL LETTER XI # Xi 0x03A8, // 59 # GREEK CAPITAL LETTER PSI # Psi 0x0396, // 5A # GREEK CAPITAL LETTER ZETA # Zeta 0x005B, // 5B # LEFT SQUARE BRACKET # bracketleft 0x2234, // 5C # THEREFORE # therefore 0x005D, // 5D # RIGHT SQUARE BRACKET # bracketright 0x22A5, // 5E # UP TACK # perpendicular 0x005F, // 5F # LOW LINE # underscore 0xF8E5, // 60 # RADICAL EXTENDER # radicalex (CUS) 0x03B1, // 61 # GREEK SMALL LETTER ALPHA # alpha 0x03B2, // 62 # GREEK SMALL LETTER BETA # beta 0x03C7, // 63 # GREEK SMALL LETTER CHI # chi 0x03B4, // 64 # GREEK SMALL LETTER DELTA # delta 0x03B5, // 65 # GREEK SMALL LETTER EPSILON # epsilon 0x03C6, // 66 # GREEK SMALL LETTER PHI # phi 0x03B3, // 67 # GREEK SMALL LETTER GAMMA # gamma 0x03B7, // 68 # GREEK SMALL LETTER ETA # eta 0x03B9, // 69 # GREEK SMALL LETTER IOTA # iota 0x03D5, // 6A # GREEK PHI SYMBOL # phi1 0x03BA, // 6B # GREEK SMALL LETTER KAPPA # kappa 0x03BB, // 6C # GREEK SMALL LETTER LAMDA # lambda // 0x00B5, // 6D # MICRO SIGN # mu 0x03BC, // 6D # GREEK SMALL LETTER MU # mu 0x03BD, // 6E # GREEK SMALL LETTER NU # nu 0x03BF, // 6F # GREEK SMALL LETTER OMICRON # omicron 0x03C0, // 70 # GREEK SMALL LETTER PI # pi 0x03B8, // 71 # GREEK SMALL LETTER THETA # theta 0x03C1, // 72 # GREEK SMALL LETTER RHO # rho 0x03C3, // 73 # GREEK SMALL LETTER SIGMA # sigma 0x03C4, // 74 # GREEK SMALL LETTER TAU # tau 0x03C5, // 75 # GREEK SMALL LETTER UPSILON # upsilon 0x03D6, // 76 # GREEK PI SYMBOL # omega1 0x03C9, // 77 # GREEK SMALL LETTER OMEGA # omega 0x03BE, // 78 # GREEK SMALL LETTER XI # xi 0x03C8, // 79 # GREEK SMALL LETTER PSI # psi 0x03B6, // 7A # GREEK SMALL LETTER ZETA # zeta 0x007B, // 7B # LEFT CURLY BRACKET # braceleft 0x007C, // 7C # VERTICAL LINE # bar 0x007D, // 7D # RIGHT CURLY BRACKET # braceright 0x223C, // 7E # TILDE OPERATOR # similar // 0x7f..0x9F undefined: 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x20AC, // A0 # EURO SIGN # Euro 0x03D2, // A1 # GREEK UPSILON WITH HOOK SYMBOL # Upsilon1 0x2032, // A2 # PRIME # minute 0x2264, // A3 # LESS-THAN OR EQUAL TO # lessequal 0x2044, // A4 # FRACTION SLASH # fraction // 0x2215, // A4 # DIVISION SLASH # fraction 0x221E, // A5 # INFINITY # infinity 0x0192, // A6 # LATIN SMALL LETTER F WITH HOOK # florin 0x2663, // A7 # BLACK CLUB SUIT # club 0x2666, // A8 # BLACK DIAMOND SUIT # diamond 0x2665, // A9 # BLACK HEART SUIT # heart 0x2660, // AA # BLACK SPADE SUIT # spade 0x2194, // AB # LEFT RIGHT ARROW # arrowboth 0x2190, // AC # LEFTWARDS ARROW # arrowleft 0x2191, // AD # UPWARDS ARROW # arrowup 0x2192, // AE # RIGHTWARDS ARROW # arrowright 0x2193, // AF # DOWNWARDS ARROW # arrowdown 0x00B0, // B0 # DEGREE SIGN # degree 0x00B1, // B1 # PLUS-MINUS SIGN # plusminus 0x2033, // B2 # DOUBLE PRIME # second 0x2265, // B3 # GREATER-THAN OR EQUAL TO # greaterequal 0x00D7, // B4 # MULTIPLICATION SIGN # multiply 0x221D, // B5 # PROPORTIONAL TO # proportional 0x2202, // B6 # PARTIAL DIFFERENTIAL # partialdiff 0x2022, // B7 # BULLET # bullet 0x00F7, // B8 # DIVISION SIGN # divide 0x2260, // B9 # NOT EQUAL TO # notequal 0x2261, // BA # IDENTICAL TO # equivalence 0x2248, // BB # ALMOST EQUAL TO # approxequal 0x2026, // BC # HORIZONTAL ELLIPSIS # ellipsis 0xF8E6, // BD # VERTICAL ARROW EXTENDER # arrowvertex (CUS) 0xF8E7, // BE # HORIZONTAL ARROW EXTENDER # arrowhorizex (CUS) 0x21B5, // BF # DOWNWARDS ARROW WITH CORNER LEFTWARDS # carriagereturn 0x2135, // C0 # ALEF SYMBOL # aleph 0x2111, // C1 # BLACK-LETTER CAPITAL I # Ifraktur 0x211C, // C2 # BLACK-LETTER CAPITAL R # Rfraktur 0x2118, // C3 # SCRIPT CAPITAL P # weierstrass 0x2297, // C4 # CIRCLED TIMES # circlemultiply 0x2295, // C5 # CIRCLED PLUS # circleplus 0x2205, // C6 # EMPTY SET # emptyset 0x2229, // C7 # INTERSECTION # intersection 0x222A, // C8 # UNION # union 0x2283, // C9 # SUPERSET OF # propersuperset 0x2287, // CA # SUPERSET OF OR EQUAL TO # reflexsuperset 0x2284, // CB # NOT A SUBSET OF # notsubset 0x2282, // CC # SUBSET OF # propersubset 0x2286, // CD # SUBSET OF OR EQUAL TO # reflexsubset 0x2208, // CE # ELEMENT OF # element 0x2209, // CF # NOT AN ELEMENT OF # notelement 0x2220, // D0 # ANGLE # angle 0x2207, // D1 # NABLA # gradient 0xF6DA, // D2 # REGISTERED SIGN SERIF # registerserif (CUS) 0xF6D9, // D3 # COPYRIGHT SIGN SERIF # copyrightserif (CUS) 0xF6DB, // D4 # TRADE MARK SIGN SERIF # trademarkserif (CUS) 0x220F, // D5 # N-ARY PRODUCT # product 0x221A, // D6 # SQUARE ROOT # radical 0x22C5, // D7 # DOT OPERATOR # dotmath 0x00AC, // D8 # NOT SIGN # logicalnot 0x2227, // D9 # LOGICAL AND # logicaland 0x2228, // DA # LOGICAL OR # logicalor 0x21D4, // DB # LEFT RIGHT DOUBLE ARROW # arrowdblboth 0x21D0, // DC # LEFTWARDS DOUBLE ARROW # arrowdblleft 0x21D1, // DD # UPWARDS DOUBLE ARROW # arrowdblup 0x21D2, // DE # RIGHTWARDS DOUBLE ARROW # arrowdblright 0x21D3, // DF # DOWNWARDS DOUBLE ARROW # arrowdbldown 0x25CA, // E0 # LOZENGE # lozenge 0x2329, // E1 # LEFT-POINTING ANGLE BRACKET # angleleft 0xF8E8, // E2 # REGISTERED SIGN SANS SERIF # registersans (CUS) 0xF8E9, // E3 # COPYRIGHT SIGN SANS SERIF # copyrightsans (CUS) 0xF8EA, // E4 # TRADE MARK SIGN SANS SERIF # trademarksans (CUS) 0x2211, // E5 # N-ARY SUMMATION # summation 0xF8EB, // E6 # LEFT PAREN TOP # parenlefttp (CUS) 0xF8EC, // E7 # LEFT PAREN EXTENDER # parenleftex (CUS) 0xF8ED, // E8 # LEFT PAREN BOTTOM # parenleftbt (CUS) 0xF8EE, // E9 # LEFT SQUARE BRACKET TOP # bracketlefttp (CUS) 0xF8EF, // EA # LEFT SQUARE BRACKET EXTENDER # bracketleftex (CUS) 0xF8F0, // EB # LEFT SQUARE BRACKET BOTTOM # bracketleftbt (CUS) 0xF8F1, // EC # LEFT CURLY BRACKET TOP # bracelefttp (CUS) 0xF8F2, // ED # LEFT CURLY BRACKET MID # braceleftmid (CUS) 0xF8F3, // EE # LEFT CURLY BRACKET BOTTOM # braceleftbt (CUS) 0xF8F4, // EF # CURLY BRACKET EXTENDER # braceex (CUS) 0x0000, // F0 undefined 0x232A, // F1 # RIGHT-POINTING ANGLE BRACKET # angleright 0x222B, // F2 # INTEGRAL # integral 0x2320, // F3 # TOP HALF INTEGRAL # integraltp 0xF8F5, // F4 # INTEGRAL EXTENDER # integralex (CUS) 0x2321, // F5 # BOTTOM HALF INTEGRAL # integralbt 0xF8F6, // F6 # RIGHT PAREN TOP # parenrighttp (CUS) 0xF8F7, // F7 # RIGHT PAREN EXTENDER # parenrightex (CUS) 0xF8F8, // F8 # RIGHT PAREN BOTTOM # parenrightbt (CUS) 0xF8F9, // F9 # RIGHT SQUARE BRACKET TOP # bracketrighttp (CUS) 0xF8FA, // FA # RIGHT SQUARE BRACKET EXTENDER # bracketrightex (CUS) 0xF8FB, // FB # RIGHT SQUARE BRACKET BOTTOM # bracketrightbt (CUS) 0xF8FC, // FC # RIGHT CURLY BRACKET TOP # bracerighttp (CUS) 0xF8FD, // FD # RIGHT CURLY BRACKET MID # bracerightmid (CUS) 0xF8FE, // FE # RIGHT CURLY BRACKET BOTTOM # bracerightbt (CUS) 0x0000 // FF undefined }; // OC 13.08.2010 New: PdfZapfDingbatsEncoding // ----------------------------------------------------- // PdfZapfDingbatsEncoding // See: http://unicode.org/Public/MAPPINGS/VENDORS/ADOBE/zdingbat.txt // ----------------------------------------------------- // ----------------------------------------------------- // // ----------------------------------------------------- const pdf_utf16be* PdfZapfDingbatsEncoding::GetToUnicodeTable() const { return PdfZapfDingbatsEncoding::s_cEncoding; } const pdf_utf16be PdfZapfDingbatsEncoding::s_cEncoding[256] = { //0, // uncomment to check compiler error cause of 257 members // 0x00..0x1f undefined: 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0020, // 20 # SPACE # space // 0x00A0, // 20 # NO-BREAK SPACE # space 0x2701, // 21 # UPPER BLADE SCISSORS # a1 0x2702, // 22 # BLACK SCISSORS # a2 0x2703, // 23 # LOWER BLADE SCISSORS # a202 0x2704, // 24 # WHITE SCISSORS # a3 0x260E, // 25 # BLACK TELEPHONE # a4 0x2706, // 26 # TELEPHONE LOCATION SIGN # a5 0x2707, // 27 # TAPE DRIVE # a119 0x2708, // 28 # AIRPLANE # a118 0x2709, // 29 # ENVELOPE # a117 0x261B, // 2A # BLACK RIGHT POINTING INDEX # a11 0x261E, // 2B # WHITE RIGHT POINTING INDEX # a12 0x270C, // 2C # VICTORY HAND # a13 0x270D, // 2D # WRITING HAND # a14 0x270E, // 2E # LOWER RIGHT PENCIL # a15 0x270F, // 2F # PENCIL # a16 0x2710, // 30 # UPPER RIGHT PENCIL # a105 0x2711, // 31 # WHITE NIB # a17 0x2712, // 32 # BLACK NIB # a18 0x2713, // 33 # CHECK MARK # a19 0x2714, // 34 # HEAVY CHECK MARK # a20 0x2715, // 35 # MULTIPLICATION X # a21 0x2716, // 36 # HEAVY MULTIPLICATION X # a22 0x2717, // 37 # BALLOT X # a23 0x2718, // 38 # HEAVY BALLOT X # a24 0x2719, // 39 # OUTLINED GREEK CROSS # a25 0x271A, // 3A # HEAVY GREEK CROSS # a26 0x271B, // 3B # OPEN CENTRE CROSS # a27 0x271C, // 3C # HEAVY OPEN CENTRE CROSS # a28 0x271D, // 3D # LATIN CROSS # a6 0x271E, // 3E # SHADOWED WHITE LATIN CROSS # a7 0x271F, // 3F # OUTLINED LATIN CROSS # a8 0x2720, // 40 # MALTESE CROSS # a9 0x2721, // 41 # STAR OF DAVID # a10 0x2722, // 42 # FOUR TEARDROP-SPOKED ASTERISK # a29 0x2723, // 43 # FOUR BALLOON-SPOKED ASTERISK # a30 0x2724, // 44 # HEAVY FOUR BALLOON-SPOKED ASTERISK # a31 0x2725, // 45 # FOUR CLUB-SPOKED ASTERISK # a32 0x2726, // 46 # BLACK FOUR POINTED STAR # a33 0x2727, // 47 # WHITE FOUR POINTED STAR # a34 0x2605, // 48 # BLACK STAR # a35 0x2729, // 49 # STRESS OUTLINED WHITE STAR # a36 0x272A, // 4A # CIRCLED WHITE STAR # a37 0x272B, // 4B # OPEN CENTRE BLACK STAR # a38 0x272C, // 4C # BLACK CENTRE WHITE STAR # a39 0x272D, // 4D # OUTLINED BLACK STAR # a40 0x272E, // 4E # HEAVY OUTLINED BLACK STAR # a41 0x272F, // 4F # PINWHEEL STAR # a42 0x2730, // 50 # SHADOWED WHITE STAR # a43 0x2731, // 51 # HEAVY ASTERISK # a44 0x2732, // 52 # OPEN CENTRE ASTERISK # a45 0x2733, // 53 # EIGHT SPOKED ASTERISK # a46 0x2734, // 54 # EIGHT POINTED BLACK STAR # a47 0x2735, // 55 # EIGHT POINTED PINWHEEL STAR # a48 0x2736, // 56 # SIX POINTED BLACK STAR # a49 0x2737, // 57 # EIGHT POINTED RECTILINEAR BLACK STAR # a50 0x2738, // 58 # HEAVY EIGHT POINTED RECTILINEAR BLACK STAR # a51 0x2739, // 59 # TWELVE POINTED BLACK STAR # a52 0x273A, // 5A # SIXTEEN POINTED ASTERISK # a53 0x273B, // 5B # TEARDROP-SPOKED ASTERISK # a54 0x273C, // 5C # OPEN CENTRE TEARDROP-SPOKED ASTERISK # a55 0x273D, // 5D # HEAVY TEARDROP-SPOKED ASTERISK # a56 0x273E, // 5E # SIX PETALLED BLACK AND WHITE FLORETTE # a57 0x273F, // 5F # BLACK FLORETTE # a58 0x2740, // 60 # WHITE FLORETTE # a59 0x2741, // 61 # EIGHT PETALLED OUTLINED BLACK FLORETTE # a60 0x2742, // 62 # CIRCLED OPEN CENTRE EIGHT POINTED STAR # a61 0x2743, // 63 # HEAVY TEARDROP-SPOKED PINWHEEL ASTERISK # a62 0x2744, // 64 # SNOWFLAKE # a63 0x2745, // 65 # TIGHT TRIFOLIATE SNOWFLAKE # a64 0x2746, // 66 # HEAVY CHEVRON SNOWFLAKE # a65 0x2747, // 67 # SPARKLE # a66 0x2748, // 68 # HEAVY SPARKLE # a67 0x2749, // 69 # BALLOON-SPOKED ASTERISK # a68 0x274A, // 6A # EIGHT TEARDROP-SPOKED PROPELLER ASTERISK # a69 0x274B, // 6B # HEAVY EIGHT TEARDROP-SPOKED PROPELLER ASTERISK # a70 0x25CF, // 6C # BLACK CIRCLE # a71 0x274D, // 6D # SHADOWED WHITE CIRCLE # a72 0x25A0, // 6E # BLACK SQUARE # a73 0x274F, // 6F # LOWER RIGHT DROP-SHADOWED WHITE SQUARE # a74 0x2750, // 70 # UPPER RIGHT DROP-SHADOWED WHITE SQUARE # a203 0x2751, // 71 # LOWER RIGHT SHADOWED WHITE SQUARE # a75 0x2752, // 72 # UPPER RIGHT SHADOWED WHITE SQUARE # a204 0x25B2, // 73 # BLACK UP-POINTING TRIANGLE # a76 0x25BC, // 74 # BLACK DOWN-POINTING TRIANGLE # a77 0x25C6, // 75 # BLACK DIAMOND # a78 0x2756, // 76 # BLACK DIAMOND MINUS WHITE X # a79 0x25D7, // 77 # RIGHT HALF BLACK CIRCLE # a81 0x2758, // 78 # LIGHT VERTICAL BAR # a82 0x2759, // 79 # MEDIUM VERTICAL BAR # a83 0x275A, // 7A # HEAVY VERTICAL BAR # a84 0x275B, // 7B # HEAVY SINGLE TURNED COMMA QUOTATION MARK ORNAMENT # a97 0x275C, // 7C # HEAVY SINGLE COMMA QUOTATION MARK ORNAMENT # a98 0x275D, // 7D # HEAVY DOUBLE TURNED COMMA QUOTATION MARK ORNAMENT # a99 0x275E, // 7E # HEAVY DOUBLE COMMA QUOTATION MARK ORNAMENT # a100 0x0000, // 7F undefined 0xF8D7, // 80 # MEDIUM LEFT PARENTHESIS ORNAMENT # a89 (CUS) 0xF8D8, // 81 # MEDIUM RIGHT PARENTHESIS ORNAMENT # a90 (CUS) 0xF8D9, // 82 # MEDIUM FLATTENED LEFT PARENTHESIS ORNAMENT # a93 (CUS) 0xF8DA, // 83 # MEDIUM FLATTENED RIGHT PARENTHESIS ORNAMENT # a94 (CUS) 0xF8DB, // 84 # MEDIUM LEFT-POINTING ANGLE BRACKET ORNAMENT # a91 (CUS) 0xF8DC, // 85 # MEDIUM RIGHT-POINTING ANGLE BRACKET ORNAMENT # a92 (CUS) 0xF8DD, // 86 # HEAVY LEFT-POINTING ANGLE QUOTATION MARK ORNAMENT # a205 (CUS) 0xF8DE, // 87 # HEAVY RIGHT-POINTING ANGLE QUOTATION MARK ORNAMENT # a85 (CUS) 0xF8DF, // 88 # HEAVY LEFT-POINTING ANGLE BRACKET ORNAMENT # a206 (CUS) 0xF8E0, // 89 # HEAVY RIGHT-POINTING ANGLE BRACKET ORNAMENT # a86 (CUS) 0xF8E1, // 8A # LIGHT LEFT TORTOISE SHELL BRACKET ORNAMENT # a87 (CUS) 0xF8E2, // 8B # LIGHT RIGHT TORTOISE SHELL BRACKET ORNAMENT # a88 (CUS) 0xF8E3, // 8C # MEDIUM LEFT CURLY BRACKET ORNAMENT # a95 (CUS) 0xF8E4, // 8D # MEDIUM RIGHT CURLY BRACKET ORNAMENT # a96 (CUS) // 0x8E..0xA0 undefined: 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2761, // A1 # CURVED STEM PARAGRAPH SIGN ORNAMENT # a101 0x2762, // A2 # HEAVY EXCLAMATION MARK ORNAMENT # a102 0x2763, // A3 # HEAVY HEART EXCLAMATION MARK ORNAMENT # a103 0x2764, // A4 # HEAVY BLACK HEART # a104 0x2765, // A5 # ROTATED HEAVY BLACK HEART BULLET # a106 0x2766, // A6 # FLORAL HEART # a107 0x2767, // A7 # ROTATED FLORAL HEART BULLET # a108 0x2663, // A8 # BLACK CLUB SUIT # a112 0x2666, // A9 # BLACK DIAMOND SUIT # a111 0x2665, // AA # BLACK HEART SUIT # a110 0x2660, // AB # BLACK SPADE SUIT # a109 0x2460, // AC # CIRCLED DIGIT ONE # a120 0x2461, // AD # CIRCLED DIGIT TWO # a121 0x2462, // AE # CIRCLED DIGIT THREE # a122 0x2463, // AF # CIRCLED DIGIT FOUR # a123 0x2464, // B0 # CIRCLED DIGIT FIVE # a124 0x2465, // B1 # CIRCLED DIGIT SIX # a125 0x2466, // B2 # CIRCLED DIGIT SEVEN # a126 0x2467, // B3 # CIRCLED DIGIT EIGHT # a127 0x2468, // B4 # CIRCLED DIGIT NINE # a128 0x2469, // B5 # CIRCLED NUMBER TEN # a129 0x2776, // B6 # DINGBAT NEGATIVE CIRCLED DIGIT ONE # a130 0x2777, // B7 # DINGBAT NEGATIVE CIRCLED DIGIT TWO # a131 0x2778, // B8 # DINGBAT NEGATIVE CIRCLED DIGIT THREE # a132 0x2779, // B9 # DINGBAT NEGATIVE CIRCLED DIGIT FOUR # a133 0x277A, // BA # DINGBAT NEGATIVE CIRCLED DIGIT FIVE # a134 0x277B, // BB # DINGBAT NEGATIVE CIRCLED DIGIT SIX # a135 0x277C, // BC # DINGBAT NEGATIVE CIRCLED DIGIT SEVEN # a136 0x277D, // BD # DINGBAT NEGATIVE CIRCLED DIGIT EIGHT # a137 0x277E, // BE # DINGBAT NEGATIVE CIRCLED DIGIT NINE # a138 0x277F, // BF # DINGBAT NEGATIVE CIRCLED NUMBER TEN # a139 0x2780, // C0 # DINGBAT CIRCLED SANS-SERIF DIGIT ONE # a140 0x2781, // C1 # DINGBAT CIRCLED SANS-SERIF DIGIT TWO # a141 0x2782, // C2 # DINGBAT CIRCLED SANS-SERIF DIGIT THREE # a142 0x2783, // C3 # DINGBAT CIRCLED SANS-SERIF DIGIT FOUR # a143 0x2784, // C4 # DINGBAT CIRCLED SANS-SERIF DIGIT FIVE # a144 0x2785, // C5 # DINGBAT CIRCLED SANS-SERIF DIGIT SIX # a145 0x2786, // C6 # DINGBAT CIRCLED SANS-SERIF DIGIT SEVEN # a146 0x2787, // C7 # DINGBAT CIRCLED SANS-SERIF DIGIT EIGHT # a147 0x2788, // C8 # DINGBAT CIRCLED SANS-SERIF DIGIT NINE # a148 0x2789, // C9 # DINGBAT CIRCLED SANS-SERIF NUMBER TEN # a149 0x278A, // CA # DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT ONE # a150 0x278B, // CB # DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT TWO # a151 0x278C, // CC # DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT THREE # a152 0x278D, // CD # DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT FOUR # a153 0x278E, // CE # DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT FIVE # a154 0x278F, // CF # DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT SIX # a155 0x2790, // D0 # DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT SEVEN # a156 0x2791, // D1 # DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT EIGHT # a157 0x2792, // D2 # DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT NINE # a158 0x2793, // D3 # DINGBAT NEGATIVE CIRCLED SANS-SERIF NUMBER TEN # a159 0x2794, // D4 # HEAVY WIDE-HEADED RIGHTWARDS ARROW # a160 0x2192, // D5 # RIGHTWARDS ARROW # a161 0x2194, // D6 # LEFT RIGHT ARROW # a163 0x2195, // D7 # UP DOWN ARROW # a164 0x2798, // D8 # HEAVY SOUTH EAST ARROW # a196 0x2799, // D9 # HEAVY RIGHTWARDS ARROW # a165 0x279A, // DA # HEAVY NORTH EAST ARROW # a192 0x279B, // DB # DRAFTING POINT RIGHTWARDS ARROW # a166 0x279C, // DC # HEAVY ROUND-TIPPED RIGHTWARDS ARROW # a167 0x279D, // DD # TRIANGLE-HEADED RIGHTWARDS ARROW # a168 0x279E, // DE # HEAVY TRIANGLE-HEADED RIGHTWARDS ARROW # a169 0x279F, // DF # DASHED TRIANGLE-HEADED RIGHTWARDS ARROW # a170 0x27A0, // E0 # HEAVY DASHED TRIANGLE-HEADED RIGHTWARDS ARROW # a171 0x27A1, // E1 # BLACK RIGHTWARDS ARROW # a172 0x27A2, // E2 # THREE-D TOP-LIGHTED RIGHTWARDS ARROWHEAD # a173 0x27A3, // E3 # THREE-D BOTTOM-LIGHTED RIGHTWARDS ARROWHEAD # a162 0x27A4, // E4 # BLACK RIGHTWARDS ARROWHEAD # a174 0x27A5, // E5 # HEAVY BLACK CURVED DOWNWARDS AND RIGHTWARDS ARROW # a175 0x27A6, // E6 # HEAVY BLACK CURVED UPWARDS AND RIGHTWARDS ARROW # a176 0x27A7, // E7 # SQUAT BLACK RIGHTWARDS ARROW # a177 0x27A8, // E8 # HEAVY CONCAVE-POINTED BLACK RIGHTWARDS ARROW # a178 0x27A9, // E9 # RIGHT-SHADED WHITE RIGHTWARDS ARROW # a179 0x27AA, // EA # LEFT-SHADED WHITE RIGHTWARDS ARROW # a193 0x27AB, // EB # BACK-TILTED SHADOWED WHITE RIGHTWARDS ARROW # a180 0x27AC, // EC # FRONT-TILTED SHADOWED WHITE RIGHTWARDS ARROW # a199 0x27AD, // ED # HEAVY LOWER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW # a181 0x27AE, // EE # HEAVY UPPER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW # a200 0x27AF, // EF # NOTCHED LOWER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW # a182 0x0000, // F0 undefined 0x27B1, // F1 # NOTCHED UPPER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW # a201 0x27B2, // F2 # CIRCLED HEAVY WHITE RIGHTWARDS ARROW # a183 0x27B3, // F3 # WHITE-FEATHERED RIGHTWARDS ARROW # a184 0x27B4, // F4 # BLACK-FEATHERED SOUTH EAST ARROW # a197 0x27B5, // F5 # BLACK-FEATHERED RIGHTWARDS ARROW # a185 0x27B6, // F6 # BLACK-FEATHERED NORTH EAST ARROW # a194 0x27B7, // F7 # HEAVY BLACK-FEATHERED SOUTH EAST ARROW # a198 0x27B8, // F8 # HEAVY BLACK-FEATHERED RIGHTWARDS ARROW # a186 0x27B9, // F9 # HEAVY BLACK-FEATHERED NORTH EAST ARROW # a195 0x27BA, // FA # TEARDROP-BARBED RIGHTWARDS ARROW # a187 0x27BB, // FB # HEAVY TEARDROP-SHANKED RIGHTWARDS ARROW # a188 0x27BC, // FC # WEDGE-TAILED RIGHTWARDS ARROW # a189 0x27BD, // FD # HEAVY WEDGE-TAILED RIGHTWARDS ARROW # a190 0x27BE, // FE # OPEN-OUTLINED RIGHTWARDS ARROW # a191 0x0000 // FF undefined }; }; /* namespace PoDoFo */ podofo-0.9.3/src/base/PdfSigIncWriter.h0000664000175000017500000000545612262234754017557 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2014 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_SIGWRITER_H_ #define _PDF_SIGWRITER_H_ #include "PdfWriter.h" namespace PoDoFo { class PdfWriter; class PODOFO_API PdfSigIncWriter: public PdfWriter { public: PdfSigIncWriter( PdfVecObjects* pVecObjects, const PdfObject* pTrailer ); virtual ~PdfSigIncWriter(); void Write( PdfOutputDevice* pDevice, pdf_int64 prevOffset); }; }; #endif // _PDF_SIGWRITER_H_ podofo-0.9.3/src/base/PdfVecObjects.h0000664000175000017500000005026012262234754017226 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2005 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_VEC_OBJECTS_H_ #define _PDF_VEC_OBJECTS_H_ #include "PdfDefines.h" #include "PdfReference.h" #include namespace PoDoFo { class PdfDocument; class PdfObject; class PdfStream; class PdfVariant; // Use deque as many insertions are here way faster than with using std::list // This is especially useful for PDFs like PDFReference17.pdf with // lot's of free objects. typedef std::deque TPdfReferenceList; typedef TPdfReferenceList::iterator TIPdfReferenceList; typedef TPdfReferenceList::const_iterator TCIPdfReferenceList; typedef std::set TPdfReferenceSet; typedef TPdfReferenceSet::iterator TIPdfReferenceSet; typedef TPdfReferenceSet::const_iterator TCIPdfReferenceSet; typedef std::list TReferencePointerList; typedef TReferencePointerList::iterator TIReferencePointerList; typedef TReferencePointerList::const_iterator TCIReferencePointerList; typedef std::vector TVecReferencePointerList; typedef TVecReferencePointerList::iterator TIVecReferencePointerList; typedef TVecReferencePointerList::const_iterator TCIVecReferencePointerList; /* typedef std::vector TVecObjects; typedef TVecObjects::iterator TIVecObjects; typedef TVecObjects::const_iterator TCIVecObjects; */ typedef std::vector TVecObjects; typedef TVecObjects::iterator TIVecObjects; typedef TVecObjects::const_iterator TCIVecObjects; /** A STL vector of PdfObjects. I.e. a list of PdfObject classes. * The PdfParser will read the PdfFile into memory and create * a PdfVecObjects of all dictionaries found in the PDF file. * * The PdfWriter class contrary creates a PdfVecObjects internally * and writes it to a PDF file later with an appropriate table of * contents. * * These class contains also advanced funtions for searching of PdfObject's * in a PdfVecObject. */ class PODOFO_API PdfVecObjects { friend class PdfWriter; public: // An incomplete set of container typedefs, just enough to handle // the begin() and end() methods we wrap from the internal vector. // TODO: proper wrapper iterator class. typedef TVecObjects::iterator iterator; typedef TVecObjects::const_iterator const_iterator; /** Every observer of PdfVecObjects has to implement this interface. */ class PODOFO_API Observer { friend class PdfVecObjects; public: virtual ~Observer() { } virtual void WriteObject( const PdfObject* pObject ) = 0; /** * This method is called when the observed PdfVecObjects is delted. * * No more method may be called on the observable * after this method was called on the observer. */ virtual void ParentDestructed() = 0; /** Called whenever appending to a stream is started. * \param pStream the stream object the user currently writes to. */ virtual void BeginAppendStream( const PdfStream* pStream ) = 0; /** Called whenever appending to a stream has ended. * \param pStream the stream object the user currently writes to. */ virtual void EndAppendStream( const PdfStream* pStream ) = 0; virtual void Finish() = 0; }; /** This class is used to implement stream factories in PoDoFo. */ class PODOFO_API StreamFactory { public: virtual ~StreamFactory() { } /** Creates a stream object * * \param pParent parent object * * \returns a new stream object */ virtual PdfStream* CreateStream( PdfObject* pParent ) = 0; }; private: typedef std::vector TVecObservers; typedef TVecObservers::iterator TIVecObservers; typedef TVecObservers::const_iterator TCIVecObservers; public: /** Default constuctor */ PdfVecObjects(); virtual ~PdfVecObjects(); /** \returns a pointer to a PdfDocument that is the * parent of this vector. * Might be NULL if the vector has no parent. */ inline PdfDocument* GetParentDocument() const; /** Sets a parent document of this vector * \param pDocument the parent of this vector */ inline void SetParentDocument( PdfDocument* pDocument ); /** Enable/disable auto deletion. * By default auto deletion is disabled. * * \param bAutoDelete if true all objects will be deleted when the PdfVecObjects is * deleted. */ inline void SetAutoDelete( bool bAutoDelete ); /** * \returns if autodeletion is enabled and all objects will be deleted when the PdfVecObjects is * deleted. */ inline bool AutoDelete() const; /** Removes all objects from the vector * and resets it to the default state. * * If SetAutoDelete is true all objects are deleted. * All observers are removed from the vector. * * \see SetAutoDelete * \see AutoDelete */ void Clear(); /** * \returns the size of the internal vector */ inline size_t GetSize() const; /** * \returns the highest object number in the vector */ size_t GetObjectCount() const { return m_nObjectCount; } /** Finds the object with the given reference in m_vecOffsets * and returns a pointer to it if it is found. * \param ref the object to be found * \returns the found object or NULL if no object was found. */ PdfObject* GetObject( const PdfReference & ref ) const; /** Finds the object with the given reference in m_vecOffsets * and returns the index to it. * \param ref the object to be found * \returns the found object or NULL if no object was found. */ size_t GetIndex( const PdfReference & ref ) const; /** Remove the object with the given object and generation number from the list * of objects. * The object is returned if it was found. Otherwise NULL is returned. * The caller has to delete the object by hisself. * * \param ref the object to be found * \param bMarkAsFree if true the removed object reference is marked as free object * you will always want to have this true * as invalid PDF files can be generated otherwise * \returns The removed object. */ PdfObject* RemoveObject( const PdfReference & ref, bool bMarkAsFree = true ); /** Remove the object with the iterator it from the vector and return it * \param it the object to remove * \returns the removed object */ PdfObject* RemoveObject( const TIVecObjects & it ); /** Creates a new object and inserts it into the vector. * This function assigns the next free object number to the PdfObject. * * \param pszType optionall value of the /Type key of the object * \returns PdfObject pointer to the new PdfObject */ PdfObject* CreateObject( const char* pszType = NULL ); /** Creates a new object (of type rVariants) and inserts it into the vector. * This function assigns the next free object number to the PdfObject. * * \param rVariant value of the PdfObject * \returns PdfObject pointer to the new PdfObject */ PdfObject* CreateObject( const PdfVariant & rVariant ); /** Mark a reference as unused so that it can be reused for new objects. * \param rReference the reference to reuse */ void AddFreeObject( const PdfReference & rReference ); /** \returns a list of free references in this vector */ inline const TPdfReferenceList & GetFreeObjects() const; /** * Renumbers all objects according to there current position in the vector. * All references remain intact. * Warning! This function is _very_ calculation intensive. * * \param pTrailer the trailer object * \param pNotDelete a list of object which must not be deleted * \param bDoGarbageCollection enable garbage collection, which deletes * all objects that are not reachable from the trailer. This might be slow! * * \see CollectGarbage */ void RenumberObjects( PdfObject* pTrailer, TPdfReferenceSet* pNotDelete = NULL, bool bDoGarbageCollection = false ); /** * \see insert_sorted * * Simple forward to insert sorted, as PdfVecObjects is always sorted. */ void push_back( PdfObject* pObj ); /** Insert an object into this vector so that * the vector remains sorted w.r.t. * the ordering based on object and generation numbers * m_bObjectCount will be increased for the object. * * \param pObj pointer to the object you want to insert */ void insert_sorted( PdfObject *pObj ); /** * Sort the objects in the vector based on their object and generation numbers */ void Sort(); /** * Causes the internal vector to reserve space for size elements. * \param size reserve space for that much elements in the internal vector */ inline void Reserve( size_t size ); /** Get a set with all references of objects that the passed object * depends on. * \param pObj the object to calculate all dependencies for * \param pList write the list of dependencies to this list * */ void GetObjectDependencies( const PdfObject* pObj, TPdfReferenceList* pList ) const; /** Attach a new observer * \param pObserver to attach */ inline void Attach( Observer* pObserver ); /** Detach an observer. * * \param pObserver observer to detach */ void Detach( Observer* pObserver ); /** Sets a StreamFactory which is used whenever CreateStream is called. * * \param pFactory a stream factory or NULL to reset to the default factory */ inline void SetStreamFactory( StreamFactory* pFactory ); /** Creates a stream object * This method is a factory for PdfStream objects. * * \param pParent parent object * * \returns a new stream object */ PdfStream* CreateStream( PdfObject* pParent ); /** Creates a stream object by copying an existing stream * * \param rhs copy this stream * * \returns a new stream object */ PdfStream* CreateStream( const PdfStream & rhs ); /** Can be called to force objects to be written to disk. * * \param pObject a PdfObject that should be written to disk. */ void WriteObject( PdfObject* pObject ); /** Call whenever a document is finished */ void Finish(); /** Every stream implementation has to call this in BeginAppend * \param pStream the stream object that is calling */ void BeginAppendStream( const PdfStream* pStream ); /** Every stream implementation has to call this in EndAppend * \param pStream the stream object that is calling */ void EndAppendStream( const PdfStream* pStream ); /** Iterator pointing at the begining of the vector * \returns beginning iterator */ inline TIVecObjects begin(); /** Iterator pointing at the begining of the vector * \returns beginning iterator */ inline TCIVecObjects begin() const; /** Iterator pointing at the end of the vector * \returns ending iterator */ inline TIVecObjects end(); /** Iterator pointing at the end of the vector * \returns ending iterator */ inline TCIVecObjects end() const; inline PdfObject*& operator[](size_t index); /** Get the last object in the vector * \returns the last object in the vector or NULL * if the vector is emtpy. */ inline PdfObject* GetBack(); /** * Deletes all objects that are not references by other objects * besides the trailer (which references the root dictionary, which in * turn should reference all other objects). * * \param pTrailer trailer object of the PDF * * Warning this might be slow! */ void CollectGarbage( PdfObject* pTrailer ); /** Get next unique subset-prefix * * \returns a string to use as subset-prefix. */ std::string GetNextSubsetPrefix(); /** * Set the object count so that the object described this reference * is contained in the object count. * * \param rRef reference of newly added object */ void SetObjectCount( const PdfReference & rRef ); private: /** * \returns the next free object reference */ PdfReference GetNextFreeObject(); /** * Create a list of all references that point to the object * for each object in this vector. * \param pList write all references to this list */ void BuildReferenceCountVector( TVecReferencePointerList* pList ); void InsertReferencesIntoVector( const PdfObject* pObj, TVecReferencePointerList* pList ); /** Assumes that the PdfVecObjects is sorted */ void InsertOneReferenceIntoVector( const PdfObject* pObj, TVecReferencePointerList* pList ); /** Delete all objects from the vector which do not have references to them selves * \param pList must be a list created by BuildReferenceCountVector * \param pTrailer must be the trailer object so that it is not deleted * \param pNotDelete a list of object which must not be deleted * \see BuildReferenceCountVector */ void GarbageCollection( TVecReferencePointerList* pList, PdfObject* pTrailer, TPdfReferenceSet* pNotDelete = NULL ); private: bool m_bAutoDelete; size_t m_nObjectCount; bool m_bSorted; TVecObjects m_vector; TVecObservers m_vecObservers; TPdfReferenceList m_lstFreeObjects; PdfDocument* m_pDocument; StreamFactory* m_pStreamFactory; std::string m_sSubsetPrefix; ///< Prefix for BaseFont and FontName of subsetted font }; // ----------------------------------------------------- // // ----------------------------------------------------- inline size_t PdfVecObjects::GetSize() const { return m_vector.size(); } // ----------------------------------------------------- // // ----------------------------------------------------- inline void PdfVecObjects::Reserve( size_t size ) { m_vector.reserve( size ); } // ----------------------------------------------------- // // ----------------------------------------------------- inline PdfDocument* PdfVecObjects::GetParentDocument() const { return m_pDocument; } // ----------------------------------------------------- // // ----------------------------------------------------- inline void PdfVecObjects::SetParentDocument( PdfDocument* pDocument ) { m_pDocument = pDocument; } // ----------------------------------------------------- // // ----------------------------------------------------- inline void PdfVecObjects::SetAutoDelete( bool bAutoDelete ) { m_bAutoDelete = bAutoDelete; } // ----------------------------------------------------- // // ----------------------------------------------------- inline bool PdfVecObjects::AutoDelete() const { return m_bAutoDelete; } // ----------------------------------------------------- // // ----------------------------------------------------- inline const TPdfReferenceList & PdfVecObjects::GetFreeObjects() const { return m_lstFreeObjects; } // ----------------------------------------------------- // // ----------------------------------------------------- inline void PdfVecObjects::Attach( Observer* pObserver ) { m_vecObservers.push_back( pObserver ); } // ----------------------------------------------------- // // ----------------------------------------------------- inline void PdfVecObjects::SetStreamFactory( StreamFactory* pFactory ) { m_pStreamFactory = pFactory; } // ----------------------------------------------------- // // ----------------------------------------------------- inline TIVecObjects PdfVecObjects::begin() { return m_vector.begin(); } // ----------------------------------------------------- // // ----------------------------------------------------- inline TCIVecObjects PdfVecObjects::begin() const { return m_vector.begin(); } // ----------------------------------------------------- // // ----------------------------------------------------- inline TIVecObjects PdfVecObjects::end() { return m_vector.end(); } // ----------------------------------------------------- // // ----------------------------------------------------- inline TCIVecObjects PdfVecObjects::end() const { return m_vector.end(); } // ----------------------------------------------------- // // ----------------------------------------------------- inline PdfObject* PdfVecObjects::GetBack() { return m_vector.back(); } // ----------------------------------------------------- // // ----------------------------------------------------- inline void PdfVecObjects::SetObjectCount( const PdfReference & rRef ) { if( rRef.ObjectNumber() >= m_nObjectCount ) // Peter Petrov 18 September 2008 { // This was a bug. //++m_nObjectCount; // In fact "m_bObjectCount" is used for the next free object number. // We need to use the greatest object number + 1 for the next free object number. // Otherwise, object number overlap would have occurred. m_nObjectCount = rRef.ObjectNumber() + 1; } } // ----------------------------------------------------- // // ----------------------------------------------------- inline PdfObject*& PdfVecObjects::operator[](size_t index) { return m_vector[index]; } //inline PdfObject const * & PdfVecObjects::operator[](int index) const { return m_vector[index]; } }; #endif // _PDF_VEC_OBJECTS_H_ podofo-0.9.3/src/base/PdfTokenizer.cpp0000664000175000017500000006441512347271543017514 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2006 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfTokenizer.h" #include "PdfArray.h" #include "PdfDictionary.h" #include "PdfEncrypt.h" #include "PdfInputDevice.h" #include "PdfName.h" #include "PdfString.h" #include "PdfReference.h" #include "PdfVariant.h" #include "PdfDefinesPrivate.h" #include #include #include #include #define PDF_BUFFER 4096 #define DICT_SEP_LENGTH 2 #define NULL_LENGTH 4 #define TRUE_LENGTH 4 #define FALSE_LENGTH 5 namespace PoDoFo { namespace PdfTokenizerNameSpace{ static const int g_MapAllocLen = 256; static char g_DelMap[g_MapAllocLen] = { 0 }; static char g_WsMap[g_MapAllocLen] = { 0 }; static char g_EscMap[g_MapAllocLen] = { 0 }; static char g_hexMap[g_MapAllocLen] = { 0 }; // Generate the delimiter character map at runtime // so that it can be derived from the more easily // maintainable structures in PdfDefines.h const char * genDelMap() { char* map = static_cast(g_DelMap); memset( map, 0, sizeof(char) * g_MapAllocLen ); for (int i = 0; i < PoDoFo::s_nNumDelimiters; ++i) { map[static_cast(PoDoFo::s_cDelimiters[i])] = 1; } return map; } // Generate the whitespace character map at runtime // so that it can be derived from the more easily // maintainable structures in PdfDefines.h const char * genWsMap() { char* map = static_cast(g_WsMap); memset( map, 0, sizeof(char) * g_MapAllocLen ); for (int i = 0; i < PoDoFo::s_nNumWhiteSpaces; ++i) { map[static_cast(PoDoFo::s_cWhiteSpaces[i])] = 1; } return map; } // Generate the escape character map at runtime const char* genEscMap() { char* map = static_cast(g_EscMap); memset( map, 0, sizeof(char) * g_MapAllocLen ); map[static_cast('n')] = '\n'; // Line feed (LF) map[static_cast('r')] = '\r'; // Carriage return (CR) map[static_cast('t')] = '\t'; // Horizontal tab (HT) map[static_cast('b')] = '\b'; // Backspace (BS) map[static_cast('f')] = '\f'; // Form feed (FF) map[static_cast(')')] = ')'; map[static_cast('(')] = '('; map[static_cast('\\')] = '\\'; return map; } // Generate the hex character map at runtime const char* genHexMap() { char* map = static_cast(g_hexMap); memset( map, PdfTokenizer::HEX_NOT_FOUND, sizeof(char) * g_MapAllocLen ); map[static_cast('0')] = 0x0; map[static_cast('1')] = 0x1; map[static_cast('2')] = 0x2; map[static_cast('3')] = 0x3; map[static_cast('4')] = 0x4; map[static_cast('5')] = 0x5; map[static_cast('6')] = 0x6; map[static_cast('7')] = 0x7; map[static_cast('8')] = 0x8; map[static_cast('9')] = 0x9; map[static_cast('a')] = 0xA; map[static_cast('b')] = 0xB; map[static_cast('c')] = 0xC; map[static_cast('d')] = 0xD; map[static_cast('e')] = 0xE; map[static_cast('f')] = 0xF; map[static_cast('A')] = 0xA; map[static_cast('B')] = 0xB; map[static_cast('C')] = 0xC; map[static_cast('D')] = 0xD; map[static_cast('E')] = 0xE; map[static_cast('F')] = 0xF; return map; } }; const unsigned int PdfTokenizer::HEX_NOT_FOUND = std::numeric_limits::max(); const char * const PdfTokenizer::s_delimiterMap = PdfTokenizerNameSpace::genDelMap(); const char * const PdfTokenizer::s_whitespaceMap = PdfTokenizerNameSpace::genWsMap(); const char * const PdfTokenizer::s_escMap = PdfTokenizerNameSpace::genEscMap(); const char * const PdfTokenizer::s_hexMap = PdfTokenizerNameSpace::genHexMap(); const char PdfTokenizer::s_octMap[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; PdfTokenizer::PdfTokenizer() : m_buffer( PDF_BUFFER ) { PdfLocaleImbue(m_doubleParser); } PdfTokenizer::PdfTokenizer( const char* pBuffer, size_t lLen ) : m_device( pBuffer, lLen ), m_buffer( PDF_BUFFER ) { PdfLocaleImbue(m_doubleParser); } PdfTokenizer::PdfTokenizer( const PdfRefCountedInputDevice & rDevice, const PdfRefCountedBuffer & rBuffer ) : m_device( rDevice ), m_buffer( rBuffer ) { PdfLocaleImbue(m_doubleParser); } PdfTokenizer::~PdfTokenizer() { } bool PdfTokenizer::GetNextToken( const char*& pszToken , EPdfTokenType* peType ) { int c; pdf_int64 counter = 0; // check first if there are quequed tokens and return them first if( m_deqQueque.size() ) { TTokenizerPair pair = m_deqQueque.front(); m_deqQueque.pop_front(); if( peType ) *peType = pair.second; strcpy( m_buffer.GetBuffer(), pair.first.c_str() ); pszToken = m_buffer.GetBuffer(); return true; } if( !m_device.Device() ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } if( peType ) *peType = ePdfTokenType_Token; while( (c = m_device.Device()->Look()) != EOF && counter < static_cast(m_buffer.GetSize()) ) { // ignore leading whitespaces if( !counter && IsWhitespace( c ) ) { // Consume the whitespace character c = m_device.Device()->GetChar(); continue; } // ignore comments else if( c == '%' ) { // Consume all characters before the next line break // 2011-04-19 Ulrich Arnold: accept 0x0D, 0x0A and oX0D 0x0A as one EOL do { c = m_device.Device()->GetChar(); } while( c != EOF && c != 0x0D && c != 0x0A ); if ( c == 0x0D ) { if ( m_device.Device()->Look() == 0x0A ) c = m_device.Device()->GetChar(); } // If we've already read one or more chars of a token, return them, since // comments are treated as token-delimiting whitespace. Otherwise keep reading // at the start of the next line. if (counter) break; } // special handling for << and >> tokens else if( !counter && (c == '<' || c == '>' ) ) { if( peType ) *peType = ePdfTokenType_Delimiter; // retrieve c really from stream c = m_device.Device()->GetChar(); m_buffer.GetBuffer()[counter] = c; ++counter; char n = m_device.Device()->Look(); // Is n another < or > , ie are we opening/closing a dictionary? // If so, consume that character too. if( n == c ) { n = m_device.Device()->GetChar(); m_buffer.GetBuffer()[counter] = n; ++counter; } // `m_buffer' contains one of < , > , << or >> ; we're done . break; } else if( counter && (IsWhitespace( c ) || IsDelimiter( c )) ) { // Next (unconsumed) character is a token-terminating char, so // we have a complete token and can return it. break; } else { // Consume the next character and add it to the token we're building. c = m_device.Device()->GetChar(); m_buffer.GetBuffer()[counter] = c; ++counter; if( IsDelimiter( c ) ) { // All delimeters except << and >> (handled above) are // one-character tokens, so if we hit one we can just return it // immediately. if( peType ) *peType = ePdfTokenType_Delimiter; break; } } } m_buffer.GetBuffer()[counter] = '\0'; if( c == EOF && !counter ) { // No characters were read before EOF, so we're out of data. // Ensure the buffer points to NULL in case someone fails to check the return value. pszToken = 0; return false; } pszToken = m_buffer.GetBuffer(); return true; } bool PdfTokenizer::IsNextToken( const char* pszToken ) { if( !pszToken ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } const char* pszRead; bool gotToken = this->GetNextToken( pszRead, NULL ); if (!gotToken) { PODOFO_RAISE_ERROR( ePdfError_UnexpectedEOF ); } return (strcmp( pszToken, pszRead ) == 0); } pdf_long PdfTokenizer::GetNextNumber() { EPdfTokenType eType; const char* pszRead; bool gotToken = this->GetNextToken( pszRead, &eType ); if( !gotToken ) { PODOFO_RAISE_ERROR_INFO( ePdfError_UnexpectedEOF, "Expected number" ); } char* end; #ifdef _WIN64 pdf_long l = _strtoui64( pszRead, &end, 10 ); #else pdf_long l = strtol( pszRead, &end, 10 ); #endif if( end == pszRead ) { // Don't consume the token this->QuequeToken( pszRead, eType ); PODOFO_RAISE_ERROR_INFO( ePdfError_NoNumber, pszRead ); } return l; } void PdfTokenizer::GetNextVariant( PdfVariant& rVariant, PdfEncrypt* pEncrypt ) { EPdfTokenType eTokenType; const char* pszRead; bool gotToken = this->GetNextToken( pszRead, &eTokenType ); if (!gotToken) { PODOFO_RAISE_ERROR_INFO( ePdfError_UnexpectedEOF, "Expected variant." ); } this->GetNextVariant( pszRead, eTokenType, rVariant, pEncrypt ); } void PdfTokenizer::GetNextVariant( const char* pszToken, EPdfTokenType eType, PdfVariant& rVariant, PdfEncrypt* pEncrypt ) { EPdfDataType eDataType = this->DetermineDataType( pszToken, eType, rVariant ); if( eDataType == ePdfDataType_Null || eDataType == ePdfDataType_Bool || eDataType == ePdfDataType_Number || eDataType == ePdfDataType_Real || eDataType == ePdfDataType_Reference ) { // the data was already read into rVariant by the DetermineDataType function return; } this->ReadDataType( eDataType, rVariant, pEncrypt ); } EPdfDataType PdfTokenizer::DetermineDataType( const char* pszToken, EPdfTokenType eTokenType, PdfVariant& rVariant ) { if( eTokenType == ePdfTokenType_Token ) { // check for the two special datatypes // null and boolean. // check for numbers if( strncmp( "null", pszToken, NULL_LENGTH ) == 0 ) { rVariant = PdfVariant(); return ePdfDataType_Null; } else if( strncmp( "true", pszToken, TRUE_LENGTH ) == 0 ) { rVariant = PdfVariant( true ); return ePdfDataType_Bool; } else if( strncmp( "false", pszToken, FALSE_LENGTH ) == 0 ) { rVariant = PdfVariant( false ); return ePdfDataType_Bool; } EPdfDataType eDataType = ePdfDataType_Number; const char* pszStart = pszToken; while( *pszStart ) { if( *pszStart == '.' ) eDataType = ePdfDataType_Real; else if( !(isdigit( static_cast(*pszStart) ) || *pszStart == '-' || *pszStart == '+' ) ) { eDataType = ePdfDataType_Unknown; break; } ++pszStart; } if( eDataType == ePdfDataType_Real ) { // DOM: strtod is locale dependend, // do not use it //double dVal = strtod( pszToken, NULL ); double dVal; m_doubleParser.clear(); // clear error state m_doubleParser.str( pszToken ); if( !(m_doubleParser >> dVal) ) { m_doubleParser.clear(); // clear error state PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidDataType, pszToken ); } rVariant = PdfVariant( dVal ); return ePdfDataType_Real; } else if( eDataType == ePdfDataType_Number ) { #ifdef _WIN64 rVariant = PdfVariant( static_cast(_strtoui64( pszToken, NULL, 10 )) ); #else rVariant = PdfVariant( static_cast(strtol( pszToken, NULL, 10 )) ); #endif // read another two tokens to see if it is a reference // we cannot be sure that there is another token // on the input device, so if we hit EOF just return // ePdfDataType_Number . EPdfTokenType eSecondTokenType; bool gotToken = this->GetNextToken( pszToken, &eSecondTokenType ); if (!gotToken) // No next token, so it can't be a reference return eDataType; if( eSecondTokenType != ePdfTokenType_Token ) { this->QuequeToken( pszToken, eSecondTokenType ); return eDataType; } pszStart = pszToken; #ifdef _WIN64 pdf_long l = _strtoui64( pszStart, const_cast(&pszToken), 10 ); #else long l = strtol( pszStart, const_cast(&pszToken), 10 ); #endif if( pszToken == pszStart ) { this->QuequeToken( pszStart, eSecondTokenType ); return eDataType; } std::string backup( pszStart ); EPdfTokenType eThirdTokenType; gotToken = this->GetNextToken( pszToken, &eThirdTokenType ); if (!gotToken) // No third token, so it can't be a reference return eDataType; if( eThirdTokenType == ePdfTokenType_Token && pszToken[0] == 'R' && pszToken[1] == '\0' ) { rVariant = PdfReference( static_cast(rVariant.GetNumber()), static_cast(l) ); return ePdfDataType_Reference; } else { this->QuequeToken( backup.c_str(), eSecondTokenType ); this->QuequeToken( pszToken, eThirdTokenType ); return eDataType; } } } else if( eTokenType == ePdfTokenType_Delimiter ) { if( strncmp( "<<", pszToken, DICT_SEP_LENGTH ) == 0 ) return ePdfDataType_Dictionary; else if( pszToken[0] == '[' ) return ePdfDataType_Array; else if( pszToken[0] == '(' ) return ePdfDataType_String; else if( pszToken[0] == '<' ) return ePdfDataType_HexString; else if( pszToken[0] == '/' ) return ePdfDataType_Name; } if( false ) { std::ostringstream ss; #if defined(_MSC_VER) && _MSC_VER <= 1200 ss << "Got unexpected PDF data in" << __FILE__ << ", line " << __LINE__ #else ss << "Got unexpected PDF data in" << PODOFO__FUNCTION__ #endif << ": \"" << pszToken << "\". Current read offset is " << m_device.Device()->Tell() << " which should be around the problem.\n"; PdfError::DebugMessage(ss.str().c_str()); } return ePdfDataType_Unknown; } void PdfTokenizer::ReadDataType( EPdfDataType eDataType, PdfVariant& rVariant, PdfEncrypt* pEncrypt ) { switch( eDataType ) { case ePdfDataType_Dictionary: this->ReadDictionary( rVariant, pEncrypt ); break; case ePdfDataType_Array: this->ReadArray( rVariant, pEncrypt ); break; case ePdfDataType_String: this->ReadString( rVariant, pEncrypt ); break; case ePdfDataType_HexString: this->ReadHexString( rVariant, pEncrypt ); break; case ePdfDataType_Name: this->ReadName( rVariant ); break; // The following datatypes are not handled by read datatype // but are already parsed by DetermineDatatype case ePdfDataType_Null: case ePdfDataType_Bool: case ePdfDataType_Number: case ePdfDataType_Real: case ePdfDataType_Reference: case ePdfDataType_Unknown: case ePdfDataType_RawData: default: { PdfError::LogMessage( eLogSeverity_Debug, "Got Datatype: %i\n", eDataType ); PODOFO_RAISE_ERROR( ePdfError_InvalidDataType ); } } } void PdfTokenizer::ReadDictionary( PdfVariant& rVariant, PdfEncrypt* pEncrypt ) { PdfVariant val; PdfName key; PdfDictionary dict; EPdfTokenType eType; const char * pszToken; for( ;; ) { bool gotToken = this->GetNextToken( pszToken, &eType ); if (!gotToken) { PODOFO_RAISE_ERROR_INFO(ePdfError_UnexpectedEOF, "Expected dictionary key name or >> delim."); } if( eType == ePdfTokenType_Delimiter && strncmp( ">>", pszToken, DICT_SEP_LENGTH ) == 0 ) break; this->GetNextVariant( pszToken, eType, val, pEncrypt ); // Convert the read variant to a name; throws InvalidDataType if not a name. key = val.GetName(); // Get the next variant. If there isn't one, it'll throw UnexpectedEOF. this->GetNextVariant( val, pEncrypt ); dict.AddKey( key, val ); } rVariant = dict; } void PdfTokenizer::ReadArray( PdfVariant& rVariant, PdfEncrypt* pEncrypt ) { const char* pszToken; EPdfTokenType eType; PdfVariant var; PdfArray array; for( ;; ) { bool gotToken = this->GetNextToken( pszToken, &eType ); if (!gotToken) { PODOFO_RAISE_ERROR_INFO(ePdfError_UnexpectedEOF, "Expected array item or ] delim."); } if( eType == ePdfTokenType_Delimiter && pszToken[0] == ']' ) break; this->GetNextVariant( pszToken, eType, var, pEncrypt ); array.push_back( var ); } rVariant = array; } void PdfTokenizer::ReadString( PdfVariant& rVariant, PdfEncrypt* pEncrypt ) { int c; bool bEscape = false; bool bOctEscape = false; int nOctCount = 0; char cOctValue = 0; int nBalanceCount = 0; // Balanced parathesis do not have to be escaped in strings m_vecBuffer.clear(); while( (c = m_device.Device()->Look()) != EOF ) { // end of stream reached if( !bEscape ) { // Handle raw characters c = m_device.Device()->GetChar(); if( !nBalanceCount && c == ')' ) break; if( c == '(' ) ++nBalanceCount; else if( c == ')' ) --nBalanceCount; bEscape = (c == '\\'); if( !bEscape ) m_vecBuffer.push_back( static_cast(c) ); } else { // Handle escape sequences if( bOctEscape || s_octMap[c & 0xff] ) // The last character we have read was a '\\', // so we check now for a digit to find stuff like \005 bOctEscape = true; if( bOctEscape ) { // Handle octal escape sequences ++nOctCount; if( !s_octMap[c & 0xff] ) { // No octal character anymore, // so the octal sequence must be ended // and the character has to be treated as normal character! m_vecBuffer.push_back ( cOctValue ); bEscape = false; bOctEscape = false; nOctCount = 0; cOctValue = 0; continue; } c = m_device.Device()->GetChar(); cOctValue <<= 3; cOctValue |= ((c-'0') & 0x07); if( nOctCount > 2 ) { m_vecBuffer.push_back ( cOctValue ); bEscape = false; bOctEscape = false; nOctCount = 0; cOctValue = 0; } } else { // Handle plain escape sequences const char & code = s_escMap[m_device.Device()->GetChar() & 0xff]; if( code ) m_vecBuffer.push_back( code ); bEscape = false; } } } // In case the string ends with a octal escape sequence if( bOctEscape ) m_vecBuffer.push_back ( cOctValue ); if( m_vecBuffer.size() ) { if( pEncrypt ) { pdf_long outLen = m_vecBuffer.size() - pEncrypt->CalculateStreamOffset(); char * outBuffer = new char[outLen + 16 - (outLen % 16)]; pEncrypt->Decrypt( reinterpret_cast(&(m_vecBuffer[0])), static_cast(m_vecBuffer.size()), reinterpret_cast(outBuffer), outLen); rVariant = PdfString( outBuffer, outLen ); delete[] outBuffer; } else { rVariant = PdfString( &(m_vecBuffer[0]), m_vecBuffer.size() ); } } else { rVariant = PdfString(""); } } void PdfTokenizer::ReadHexString( PdfVariant& rVariant, PdfEncrypt* pEncrypt ) { int c; m_vecBuffer.clear(); while( (c = m_device.Device()->GetChar()) != EOF ) { // end of stream reached if( c == '>' ) break; // only a hex digits if( isdigit( c ) || ( c >= 'A' && c <= 'F') || ( c >= 'a' && c <= 'f')) m_vecBuffer.push_back( c ); } // pad to an even length if necessary if( m_vecBuffer.size() % 2 ) m_vecBuffer.push_back( '0' ); PdfString string; string.SetHexData( m_vecBuffer.size() ? &(m_vecBuffer[0]) : "", m_vecBuffer.size(), pEncrypt ); rVariant = string; } void PdfTokenizer::ReadName( PdfVariant& rVariant ) { EPdfTokenType eType; const char* pszToken; // Do special checking for empty names // as GetNextToken will ignore white spaces // and we have to take care for stuff like: // 10 0 obj / endobj // which stupid but legal PDF int c = m_device.Device()->Look(); if( IsWhitespace( c ) ) // Delimeters are handled correctly by GetNextToken { // We are an empty PdfName rVariant = PdfName(); return; } bool gotToken = this->GetNextToken( pszToken, &eType ); if( !gotToken || eType != ePdfTokenType_Token ) { // We got an empty name which is legal according to the PDF specification // Some weird PDFs even use them. rVariant = PdfName(); // Queque the token again if( gotToken ) QuequeToken( pszToken, eType ); } else rVariant = PdfName::FromEscaped( pszToken ); } void PdfTokenizer::QuequeToken( const char* pszToken, EPdfTokenType eType ) { m_deqQueque.push_back( TTokenizerPair( std::string( pszToken ), eType ) ); } }; podofo-0.9.3/src/base/PdfObjectStreamParserObject.h0000664000175000017500000000756712347271543022102 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2010 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_OBJECT_STREAM_PARSER_OBJECT_H_ #define _PDF_OBJECT_STREAM_PARSER_OBJECT_H_ #include "PdfDefines.h" #include "PdfRefCountedBuffer.h" namespace PoDoFo { class PdfEncrypt; class PdfParserObject; class PdfVecObjects; /** * A utility class for PdfParser that can parse * an object stream object. * * It is mainly here to make PdfParser more modular. */ class PdfObjectStreamParserObject { public: typedef std::vector ObjectIdList; /** * Create a new PdfObjectStreamParserObject from an existing * PdfParserObject. The PdfParserObject will be removed and deleted. * All objects from the object stream will be read into memory. * * \param pParser PdfParserObject for an object stream * \param pVecObjects add loaded objecs to this vector of objects * \param rBuffer use this allocated buffer for caching * \param pEncrypt encryption object used to decrypt streams */ PdfObjectStreamParserObject(PdfParserObject* pParser, PdfVecObjects* pVecObjects, const PdfRefCountedBuffer & rBuffer, PdfEncrypt* pEncrypt ); ~PdfObjectStreamParserObject(); void Parse(ObjectIdList const &); private: void ReadObjectsFromStream( char* pBuffer, pdf_long lBufferLen, pdf_int64 lNum, pdf_int64 lFirst, ObjectIdList const &); private: PdfParserObject* m_pParser; PdfVecObjects* m_vecObjects; PdfRefCountedBuffer m_buffer; PdfEncrypt* m_pEncrypt; }; }; #endif // _PDF_OBJECT_STREAM_PARSER_OBJECT_H_ podofo-0.9.3/src/base/PdfOutputDevice.h0000664000175000017500000002074412344436402017616 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2006 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_OUTPUT_DEVICE_H_ #define _PDF_OUTPUT_DEVICE_H_ #include #include #include "PdfDefines.h" #include "PdfLocale.h" #include "PdfRefCountedBuffer.h" namespace PoDoFo { /** This class provides an output device which operates * either on a file or on a buffer in memory. * Additionally it can count the bytes written to the device. * * This class is suitable for inheritance to provide output * devices of your own for PoDoFo. * Just overide the required virtual methods. */ class PODOFO_API PdfOutputDevice { public: /** Construct a new PdfOutputDevice that does not write any data. Only the length * of the data is counted. * */ PdfOutputDevice(); /** Construct a new PdfOutputDevice that writes all data to a file. * * \param pszFilename path to a file that will be opened and all data * is written to this file. */ PdfOutputDevice( const char* pszFilename ); #ifdef _WIN32 /** Construct a new PdfOutputDevice that writes all data to a file. * * \param pszFilename path to a file that will be opened and all data * is written to this file. * * This is an overloaded member function to allow working * with unicode characters. On Unix systes you can also path * UTF-8 to the const char* overload. */ PdfOutputDevice( const wchar_t* pszFilename ); #endif // _WIN32 /** Construct a new PdfOutputDevice that writes all data to a memory buffer. * The buffer will not be owned by this object and has to be allocated before. * * \param pBuffer a buffer in memory * \param lLen the length of the buffer in memory */ PdfOutputDevice( char* pBuffer, size_t lLen ); /** Construct a new PdfOutputDevice that writes all data to a std::ostream. * * WARNING: PoDoFo will change the stream's locale. It will be restored when * the PdfOutputStream controlling the stream is destroyed. * * \param pOutStream write to this std::ostream */ PdfOutputDevice( const std::ostream* pOutStream ); /** Construct a new PdfOutputDevice that writes all data to a PdfRefCountedBuffer. * This output device has the advantage that the PdfRefCountedBuffer will resize itself * if more memory is needed to hold all data. * * \param pOutBuffer write to this PdfRefCountedBuffer * * \see PdfRefCountedBuffer */ PdfOutputDevice( PdfRefCountedBuffer* pOutBuffer ); /** Destruct the PdfOutputDevice object and close any open files. */ virtual ~PdfOutputDevice(); /** The number of bytes written to this object. * \returns the number of bytes written to this object. * * \see Init */ virtual inline size_t GetLength() const; /** Write to the PdfOutputDevice. Usage is as the usage of printf. * * WARNING: Do not use this for doubles or floating point values * as the output might depend on the current locale. * * \param pszFormat a format string as you would use it with printf * \returns ErrOk on success * * \see Write */ virtual void Print( const char* pszFormat, ... ); /** Write to the PdfOutputDevice. Usage is as the usage of printf. * * WARNING: Do not use this for doubles or floating point values * as the output might depend on the current locale. * * \param pszFormat a format string as you would use it with printf * \param lBytes length of the format string in bytes when written * \param argptr variable argument list * \returns ErrOk on success * * \see Write */ virtual void PrintV( const char* pszFormat, long lBytes, va_list argptr ); /** * Determine the length of a format string in bytes * when written using PrintV * * \param pszFormat format string * \param args variable argument list * * \returns length in bytes * \see PrintV */ long PrintVLen( const char* pszFormat, va_list args ); /** Write data to the buffer. Use this call instead of Print if you * want to write binary data to the PdfOutputDevice. * * \param pBuffer a pointer to the data buffer * \param lLen write lLen bytes of pBuffer to the PdfOutputDevice * \returns ErrOk on success * * \see Print */ virtual void Write( const char* pBuffer, size_t lLen ); /** Read data from the device * \param pBuffer a pointer to the data buffer * \param lLen length of the output buffer * \returns Number of read bytes. Return 0 if EOF */ virtual size_t Read( char* pBuffer, size_t lLen ); /** Seek the device to the position offset from the begining * \param offset from the beginning of the file */ virtual void Seek( size_t offset ); /** Get the current offset from the beginning of the file. * \return the offset form the beginning of the file. */ virtual inline size_t Tell() const; /** Flush the output files buffer to disk if this devices * operates on a disk. */ virtual void Flush(); private: /** Initialize all private members */ void Init(); protected: size_t m_ulLength; private: FILE* m_hFile; char* m_pBuffer; size_t m_lBufferLen; std::ostream* m_pStream; std::istream* m_pReadStream; bool m_pStreamOwned; #if USE_CXX_LOCALE std::locale m_pStreamSavedLocale; #endif PdfRefCountedBuffer* m_pRefCountedBuffer; size_t m_ulPosition; PdfRefCountedBuffer m_printBuffer; }; // ----------------------------------------------------- // // ----------------------------------------------------- size_t PdfOutputDevice::GetLength() const { return m_ulLength; } // ----------------------------------------------------- // // ----------------------------------------------------- size_t PdfOutputDevice::Tell() const { return m_ulPosition; } }; #endif // _PDF_OUTPUT_DEVICE_H_ podofo-0.9.3/src/base/podofoapi.h0000664000175000017500000001344111536441063016521 0ustar dominikdominik#ifndef PODOFO_API_H_20061017 #define PODOFO_API_H_20061017 /* * This header provides a macro to handle correct symbol imports/exports * on platforms that require explicit instructions to make symbols public, * or differentiate between exported and imported symbols. * * Win32 compilers use this information, and gcc4 can use it on *nix * to reduce the size of the export symbol table and get faster runtime * linking. * * All declarations of public API should be marked with the PODOFO_API macro. * Separate definitions need not be annotated, even in headers. * * Usage examples: * * class PODOFO_API PdfArray : public PdfDataType { * ... * }; * * bool PODOFO_API doThatThing(void); * * For an exception type that may be thrown across a DSO boundary, you must * use: * * class PODOFO_EXCEPTION_API(PODOFO_API) MyException * { * ... * }; * * PODOFO_LOCAL can be used on members of a class exported with PODOFO_API * to omit some members from the symbol table on supporting platforms. This * helps keep the exported API cleaner and the symbol table smaller. * * To hide a given method in an otherwise exported class: * * class PODOFO_API Myclass * { * // blah blah * private: * void privateHelper() PODOFO_LOCAL; * }; * * For information on the gcc visibility support see: * http://gcc.gnu.org/wiki/Visibility * http://people.redhat.com/drepper/dsohowto.pdf * * * * * Note that gcc has some other useful attributes: * http://gcc.gnu.org/onlinedocs/gcc-4.0.0/gcc/Function-Attributes.html * http://gcc.gnu.org/onlinedocs/gcc-4.0.0/gcc/Variable-Attributes.html * http://gcc.gnu.org/onlinedocs/gcc-4.0.0/gcc/Type-Attributes.html * * including __attribute__((deprecated)) for deprecating old interfaces. * (available as PODOFO_DEPRECATED) * * __attribute__((pure)) for functions w/o side effects * (available as PODOFO_PURE_FUNCTION) * */ // Peter Petrov 26 April 2008 /* Automatically defined by CMake when building a shared library */ #if defined (podofo_EXPORTS) #define COMPILING_SHARED_PODOFO #undef USING_SHARED_PODOFO #if defined(podofo_EXPORTS) #define COMPILING_SHARED_PODOFO_BASE #define COMPILING_SHARED_PODOFO_DOC #endif #endif /* Automatically defined by CMake when building a shared library */ //#if defined(podofo_shared_EXPORTS) #if defined(podofo_shared_EXPORTS) #define COMPILING_SHARED_PODOFO #undef USING_SHARED_PODOFO #endif /* Sanity check - can't be both compiling and using shared podofo */ #if defined(COMPILING_SHARED_PODOFO) && defined(USING_SHARED_PODOFO) #error "Both COMPILING_SHARED_PODOFO and USING_SHARED_PODOFO defined!" #endif /* * Define COMPILING_SHARED_PODOFO when building the PoDoFo library as a * DLL. When building code that uses that DLL, define USING_SHARED_PODOFO. * * Building or linking to a static library does not require either * preprocessor symbol. */ #if defined(_WIN32) #if defined(COMPILING_SHARED_PODOFO) #define PODOFO_API __declspec(dllexport) #define PODOFO_DOC_API __declspec(dllexport) #elif defined(USING_SHARED_PODOFO) #define PODOFO_API __declspec(dllimport) #define PODOFO_DOC_API __declspec(dllimport) #else #define PODOFO_API #define PODOFO_DOC_API #endif /* PODOFO_LOCAL doesn't mean anything on win32, it's to exclude * symbols from the export table with gcc4. */ #define PODOFO_LOCAL #else #if defined(PODOFO_HAVE_GCC_SYMBOL_VISIBILITY) /* Forces inclusion of a symbol in the symbol table, so software outside the current library can use it. */ #define PODOFO_API __attribute__ ((visibility("default"))) #define PODOFO_DOC_API __attribute__ ((visibility("default"))) /* Within a section exported with PODOFO_API, forces a symbol to be private to the library / app. Good for private members. */ #define PODOFO_LOCAL __attribute__ ((visibility("hidden"))) /* Forces even stricter hiding of methods/functions. The function must * absolutely never be called from outside the module even via a function * pointer.*/ #define PODOFO_INTERNAL __attribute__ ((visibility("internal"))) #else #define PODOFO_API #define PODOFO_DOC_API #define PODOFO_LOCAL #define PODOFO_INTERNAL #endif #endif /* Throwable classes must always be exported by all binaries when * using gcc. Marking exception classes with PODOFO_EXCEPTION_API * ensures this. */ #ifdef _WIN32 #define PODOFO_EXCEPTION_API(api) api #elif defined(PODOFO_HAVE_GCC_SYMBOL_VISIBILITY) #define PODOFO_EXCEPTION_API(api) PODOFO_API #else #define PODOFO_EXCEPTION_API(api) #endif /* Set up some other compiler-specific but not platform-specific macros */ #if defined(__GNUC__) /* gcc will issue a warning if a function or variable so annotated is used */ #define PODOFO_DEPRECATED __attribute__((deprecated)) /* gcc can do some additional optimisations on functions annotated as pure. * See the documentation on __attribute__((pure)) in the gcc docs. */ #define PODOFO_PURE_FUNCTION __attribute__((pure)) /* PODOFO_NOTHROW can be used to tell the compiler the annotated function is * guaranteed not to throw. If it does throw, undefined behaviour will result, * so be VERY careful with this. This is NOT the same as the PODOFO_NOTHROW qualifier * (see CODINGSTYLE.txt) .*/ #define PODOFO_NOTHROW __attribute__((nothrow)) #else #define PODOFO_DEPRECATED #define PODOFO_PURE_FUNCTION #define PODOFO_NOTHROW __declspec(nothrow) #endif // Peter Petrov 27 April 2008 // Disable warnings #if defined(_WIN32) && defined(_MSC_VER) #pragma warning(disable: 4251) #pragma warning(disable: 4309) #endif // _WIN32 #endif // PODOFO_API_H podofo-0.9.3/src/base/PdfWriter.cpp0000664000175000017500000005360412262234754017013 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2005 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfWriter.h" #include "PdfData.h" #include "PdfDate.h" #include "PdfDictionary.h" //#include "PdfHintStream.h" #include "PdfObject.h" #include "PdfParser.h" #include "PdfStream.h" #include "PdfVariant.h" #include "PdfXRef.h" #include "PdfXRefStream.h" #include "PdfDefinesPrivate.h" //#define PDF_MAGIC "%\n" //"%\0x25\0xe2\0xe3\0xcf\0xd3\0x0d" #define PDF_MAGIC "\xe2\xe3\xcf\xd3\n" // 10 spaces #define LINEARIZATION_PADDING " " #include #include namespace PoDoFo { PdfWriter::PdfWriter( PdfParser* pParser ) : m_bXRefStream( false ), m_pEncrypt( NULL ), m_pEncryptObj( NULL ), m_eWriteMode( ePdfWriteMode_Compact ), m_bLinearized( false ), m_lFirstInXRef( 0 ) { if( !(pParser && pParser->GetTrailer()) ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } m_eVersion = pParser->GetPdfVersion(); m_pTrailer = new PdfObject( *(pParser->GetTrailer()) ); m_vecObjects = pParser->m_vecObjects; } PdfWriter::PdfWriter( PdfVecObjects* pVecObjects, const PdfObject* pTrailer ) : m_bXRefStream( false ), m_pEncrypt( NULL ), m_pEncryptObj( NULL ), m_eWriteMode( ePdfWriteMode_Compact ), m_bLinearized( false ), m_lFirstInXRef( 0 ) { if( !pVecObjects || !pTrailer ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } m_eVersion = ePdfVersion_Default; m_pTrailer = new PdfObject( *pTrailer ); m_vecObjects = pVecObjects; } PdfWriter::PdfWriter( PdfVecObjects* pVecObjects ) : m_bXRefStream( false ), m_pEncrypt( NULL ), m_pEncryptObj( NULL ), m_eWriteMode( ePdfWriteMode_Compact ), m_bLinearized( false ), m_lFirstInXRef( 0 ) { m_eVersion = ePdfVersion_Default; m_pTrailer = new PdfObject(); m_vecObjects = pVecObjects; } PdfWriter::~PdfWriter() { delete m_pTrailer; delete m_pEncrypt; m_pTrailer = NULL; m_vecObjects = NULL; } void PdfWriter::Write( const char* pszFilename ) { PdfOutputDevice device( pszFilename ); this->Write( &device ); } #ifdef _WIN32 void PdfWriter::Write( const wchar_t* pszFilename ) { PdfOutputDevice device( pszFilename ); this->Write( &device ); } #endif // _WIN32 void PdfWriter::Write( PdfOutputDevice* pDevice ) { CreateFileIdentifier( m_identifier, m_pTrailer ); if( !pDevice ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } // setup encrypt dictionary if( m_pEncrypt ) { m_pEncrypt->GenerateEncryptionKey( m_identifier ); // Add our own Encryption dictionary m_pEncryptObj = m_vecObjects->CreateObject(); m_pEncrypt->CreateEncryptionDictionary( m_pEncryptObj->GetDictionary() ); } if( m_bLinearized ) { this->WriteLinearized( pDevice ); } else { PdfXRef* pXRef = m_bXRefStream ? new PdfXRefStream( m_vecObjects, this ) : new PdfXRef(); try { WritePdfHeader ( pDevice ); WritePdfObjects ( pDevice, *m_vecObjects, pXRef ); pXRef->Write( pDevice ); // XRef streams contain the trailer in the XRef if( !m_bXRefStream ) { PdfObject trailer; // if we have a dummy offset we write also a prev entry to the trailer FillTrailerObject( &trailer, pXRef->GetSize(), false, false ); pDevice->Print("trailer\n"); trailer.WriteObject( pDevice, m_eWriteMode, NULL ); // Do not encrypt the trailer dicionary!!! } pDevice->Print( "startxref\n%li\n%%%%EOF\n", pXRef->GetOffset() ); delete pXRef; } catch( PdfError & e ) { // Make sure pXRef is always deleted delete pXRef; // P.Zent: Delete Encryption dictionary (cannot be reused) if(m_pEncryptObj) { m_vecObjects->RemoveObject(m_pEncryptObj->Reference()); delete m_pEncryptObj; } e.AddToCallstack( __FILE__, __LINE__ ); throw e; } } // P.Zent: Delete Encryption dictionary (cannot be reused) if(m_pEncryptObj) { m_vecObjects->RemoveObject(m_pEncryptObj->Reference()); delete m_pEncryptObj; } } void PdfWriter::WriteLinearized( PdfOutputDevice* /* pDevice */ ) { /* PdfObject* pLinearize = NULL; PdfPage* pPage; PdfObject* pLast; NonPublic::PdfHintStream* pHint; PdfOutputDevice length; TVecXRefTable vecXRef; TVecXRefOffset vecXRefOffset; TIVecOffsets it; // prepare the document for linearization this->FetchPagesTree(); pPage = m_pPagesTree->GetPage( 0 ); pLinearize = CreateLinearizationDictionary(); pHint = new NonPublic::PdfHintStream( m_vecObjects, m_pPagesTree ); this->ReorderObjectsLinearized( pLinearize, pHint, pPage, &pLast ); // The file is prepared for linearization, // so write it now. WritePdfHeader( pDevice ); m_lLinearizedOffset = pDevice->GetLength(); pLinearize->WriteObject( pDevice ); // fill the XRef table with the objects { // Use nested scope and stack local for PdfOutputDevice // rather than using a temporary to stop gcc's whining. PdfOutputDevice o; WritePdfObjects(&o, m_vecLinearized, &vecXRef ); } // prepend the linearization dictionary to the XRef table TXRefEntry entry; entry.lOffset = m_lLinearizedOffset; entry.lGeneration = pLinearize->Reference().GenerationNumber(); entry.cUsed = 'n'; vecXRef[0].nCount++; vecXRef[0].nFirst--; vecXRef[0].vecOffsets.insert( vecXRef[0].vecOffsets.begin(), entry ); // Calculate the length of the xref table WritePdfTableOfContents( &vecXRef, &length, &vecXRefOffset, true, false ); it = vecXRef[0].vecOffsets.begin(); it++; // skip the linearization dictionary, as it was written before the XRef table // and does already have a correct offset while( it != vecXRef[0].vecOffsets.end() ) { (*it).lOffset += pDevice->GetLength() + length.GetLength(); m_lLinearizedLastOffset = (*it).lOffset; ++it; } vecXRefOffset.clear(); WritePdfTableOfContents( &vecXRef, pDevice, &vecXRefOffset, true, false ); vecXRef.clear(); WritePdfObjects( pDevice, m_vecLinearized, &vecXRef ); vecXRef.clear(); WritePdfObjects( pDevice, *m_vecObjects, &vecXRef ); if( m_bXRefStream ) WriteXRefStream( &vecXRef, pDevice ); else WritePdfTableOfContents( &vecXRef, pDevice, &vecXRefOffset, false, m_bLinearized ); this->FillLinearizationDictionary( pLinearize, pDevice, pPage, pLast, pHint, &vecXRefOffset ); */ } void PdfWriter::WritePdfHeader( PdfOutputDevice* pDevice ) { pDevice->Print( "%s\n%%%s", s_szPdfVersions[static_cast(m_eVersion)], PDF_MAGIC ); } void PdfWriter::WritePdfObjects( PdfOutputDevice* pDevice, const PdfVecObjects& vecObjects, PdfXRef* pXref ) { TCIVecObjects itObjects = vecObjects.begin(); TCIPdfReferenceList itFree = vecObjects.GetFreeObjects().begin(); while( itObjects != vecObjects.end() ) { pXref->AddObject( (*itObjects)->Reference(), pDevice->Tell(), true ); // Make sure that we do not encrypt the encryption dictionary! (*itObjects)->WriteObject( pDevice, m_eWriteMode, ((*itObjects) == m_pEncryptObj ? NULL : m_pEncrypt) ); ++itObjects; } while( itFree != vecObjects.GetFreeObjects().end() ) { pXref->AddObject( *itFree, 0, false ); ++itFree; } } void PdfWriter::GetByteOffset( PdfObject* pObject, pdf_long* pulOffset ) { TCIVecObjects it = m_vecObjects->begin(); PdfOutputDevice deviceHeader; if( !pObject || !pulOffset ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } this->WritePdfHeader( &deviceHeader ); *pulOffset = deviceHeader.GetLength(); while( it != m_vecObjects->end() ) { if( (*it) == pObject ) break; *pulOffset += (*it)->GetObjectLength( m_eWriteMode ); ++it; } } void PdfWriter::WriteToBuffer( char** ppBuffer, pdf_long* pulLen ) { PdfOutputDevice device; if( !pulLen ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } this->Write( &device ); *pulLen = device.GetLength(); *ppBuffer = static_cast(malloc( *pulLen * sizeof(char) )); if( !*ppBuffer ) { PODOFO_RAISE_ERROR( ePdfError_OutOfMemory ); } PdfOutputDevice memDevice( *ppBuffer, *pulLen ); this->Write( &memDevice ); } /* PdfObject* PdfWriter::CreateLinearizationDictionary() { PdfObject* pLinearize = m_vecObjects->CreateObject(); // This will be overwritten later with valid data! PdfVariant place_holder( PdfData( LINEARIZATION_PADDING ) ); PdfArray array; array.push_back( place_holder ); array.push_back( place_holder ); pLinearize->GetDictionary().AddKey( "Linearized", 1.0 ); // Version pLinearize->GetDictionary().AddKey( "L", place_holder ); // File length pLinearize->GetDictionary().AddKey( "H", array ); // Hint stream offset and length as PdfArray pLinearize->GetDictionary().AddKey( "E", place_holder ); // Offset of end of first page pLinearize->GetDictionary().AddKey( "N", // Number of pages in the document static_cast(m_pPagesTree->GetTotalNumberOfPages()) ); pLinearize->GetDictionary().AddKey( "O", place_holder ); // Object number of the first page pLinearize->GetDictionary().AddKey( "T", place_holder ); // Offset of first entry in main cross reference table return pLinearize; }*/ /* void PdfWriter::ReorderObjectsLinearized( PdfObject* pLinearize, NonPublic::PdfHintStream* pHint, PdfPage* pPage, PdfObject** ppLast ) { TPdfReferenceList lstLinearizedGroup; TPdfReferenceSet setLinearizedGroup; TCIPdfReferenceList it; TIVecObjects itObjects; PdfObject* pRoot; PdfObject* pTmp = NULL; size_t index, i; // get the dependend objects that are required to display // the first page. I.e. get all objects that have to be written // at the start of the file. // Add all depencies to lstLinearizedGroup m_vecObjects->GetObjectDependencies( pPage->GetObject(), &lstLinearizedGroup ); // get the root dictionary, it has to be written at the top of the file too. pRoot = m_vecObjects->GetObject( m_pTrailer->GetDictionary().GetKey( "Root" )->GetReference() ); // add the root dictionary lstLinearizedGroup.push_back( pRoot->Reference() ); // add the first page itself lstLinearizedGroup.push_back( pPage->GetObject()->Reference() ); // add several dependencies of the root dictionary this->FindCatalogDependencies( pRoot, "ViewerPreferences", &lstLinearizedGroup, true ); this->FindCatalogDependencies( pRoot, "PageMode", &lstLinearizedGroup, true ); this->FindCatalogDependencies( pRoot, "Threads", &lstLinearizedGroup, false ); this->FindCatalogDependencies( pRoot, "OpenAction", &lstLinearizedGroup, true ); this->FindCatalogDependencies( pRoot, "AcroForm", &lstLinearizedGroup, false ); this->FindCatalogDependencies( pRoot, "Encrypt", &lstLinearizedGroup, true ); // add the hint stream lstLinearizedGroup.push_back( pHint->GetObject()->Reference() ); // add the linearization dictionary lstLinearizedGroup.push_back( pLinearize->Reference() ); // move all objects which are required to display the first page // at the front of the vector of objects. // We only swap objects inside of the vector to avoid reallocations. // This is a fast operation therefore i = m_vecObjects->GetSize()-1; it = lstLinearizedGroup.begin(); while( it != lstLinearizedGroup.end() ) { index = m_vecObjects->GetIndex( *it ); if( index < i ) { pTmp = (*m_vecObjects)[index]; (*m_vecObjects)[index] = (*m_vecObjects)[i]; (*m_vecObjects)[i] = pTmp; } i--; ++it; } // Renumber all objects according to their position in the vector. // This is the slowest (only slow) operation when creating a // linearized PDF file. Garbage collection goes along with this step. std::copy( lstLinearizedGroup.begin(), lstLinearizedGroup.end(), std::inserter(setLinearizedGroup, setLinearizedGroup.begin()) ); m_vecObjects->RenumberObjects( m_pTrailer, &setLinearizedGroup ); // reorder the objects in the file itObjects = m_vecObjects->begin(); itObjects += m_vecObjects->GetSize() - setLinearizedGroup.size(); m_vecObjects->RemoveObject( itObjects ); while( itObjects != m_vecObjects->end() ) { m_vecLinearized.push_back( *itObjects ); // reset the owner (*itObjects)->SetOwner( m_vecObjects ); m_vecObjects->RemoveObject( itObjects ); } *ppLast = m_vecLinearized.GetBack(); }*/ /* void PdfWriter::FindCatalogDependencies( PdfObject* pCatalog, const PdfName & rName, TPdfReferenceList* pList, bool bWithDependencies ) { if( pCatalog->GetDictionary().HasKey( rName ) && pCatalog->GetDictionary().GetKey( rName )->IsReference() ) { if( bWithDependencies ) m_vecObjects->GetObjectDependencies( pCatalog->GetIndirectKey( rName ), pList ); else pList->push_back( pCatalog->GetIndirectKey( rName )->Reference() ); } }*/ void PdfWriter::FillTrailerObject( PdfObject* pTrailer, pdf_long lSize, bool bPrevEntry, bool bOnlySizeKey ) const { // this will be overwritten later with valid data PdfVariant place_holder( PdfData( LINEARIZATION_PADDING ) ); pTrailer->GetDictionary().AddKey( PdfName::KeySize, static_cast(lSize) ); if( !bOnlySizeKey ) { if( m_pTrailer->GetDictionary().HasKey( "Root" ) ) pTrailer->GetDictionary().AddKey( "Root", m_pTrailer->GetDictionary().GetKey( "Root" ) ); /* DominikS: It makes no sense to simple copy an encryption key Either we have no encryption or we encrypt again by ourselves if( m_pTrailer->GetDictionary().HasKey( "Encrypt" ) ) pTrailer->GetDictionary().AddKey( "Encrypt", m_pTrailer->GetDictionary().GetKey( "Encrypt" ) ); */ if( m_pTrailer->GetDictionary().HasKey( "Info" ) ) pTrailer->GetDictionary().AddKey( "Info", m_pTrailer->GetDictionary().GetKey( "Info" ) ); if( m_pEncryptObj ) pTrailer->GetDictionary().AddKey( PdfName("Encrypt"), m_pEncryptObj->Reference() ); // maybe only call this function if bPrevEntry is false PdfArray array; // The ID is the same unless the PDF was incrementally updated array.push_back( m_identifier ); array.push_back( m_identifier ); // finally add the key to the trailer dictionary pTrailer->GetDictionary().AddKey( "ID", array ); if( bPrevEntry ) { pTrailer->GetDictionary().AddKey( "Prev", place_holder ); } } } /* void PdfWriter::FetchPagesTree() { if( !m_pPagesTree ) { // try to find the pages tree PdfObject* pRoot = m_pTrailer->GetDictionary().GetKey( "Root" ); if( !pRoot || !pRoot->IsReference() ) { PODOFO_RAISE_ERROR( ePdfError_InvalidDataType ); } //printf("Fetching: %lu\n", pRoot->GetReference().ObjectNumber() ); //printf("Size : %i\n", static_cast(m_vecObjects->GetSize()) ); pRoot = m_vecObjects->GetObject( pRoot->GetReference() ); if( !pRoot ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } m_pPagesTree = new PdfPagesTree( pRoot->GetIndirectKey( "Pages" ) ); } } */ /* void PdfWriter::FillLinearizationDictionary( PdfObject* pLinearize, PdfOutputDevice* pDevice, PdfPage* pPage, PdfObject* pLast, NonPublic::PdfHintStream* pHint, TVecXRefOffset* pVecXRefOffset ) { long lFileSize = pDevice->GetLength(); PdfVariant value( 0l ); PdfArray hints; PdfObject trailer; value.SetPaddingLength( LINEARIZATION_PADDING ); value.SetNumber( lFileSize ); pLinearize->GetDictionary().AddKey( "L", value ); value.SetNumber( pPage->GetObject()->Reference().ObjectNumber() ); pLinearize->GetDictionary().AddKey( "O", value ); value.SetNumber( m_lFirstInXRef ); pLinearize->GetDictionary().AddKey( "T", value ); value.SetNumber( m_lLinearizedLastOffset + pLast->GetObjectLength() ); pLinearize->GetDictionary().AddKey( "E", value ); value.SetNumber( m_lLinearizedOffset + pLinearize->GetObjectLength() ); hints.push_back( value ); value.SetNumber( pHint->GetObject()->GetObjectLength() ); hints.push_back( value ); pLinearize->GetDictionary().AddKey( "H", hints ); pDevice->Seek( m_lLinearizedOffset ); pLinearize->WriteObject( pDevice ); pDevice->Seek( lFileSize ); value.SetNumber( pVecXRefOffset->back() ); FillTrailerObject( &trailer, pLast->Reference().ObjectNumber()+1, true, false ); trailer.GetDictionary().AddKey("Prev", value ); pDevice->Seek( m_lTrailerOffset ); trailer.WriteObject( pDevice ); pDevice->Seek( lFileSize ); } */ void PdfWriter::CreateFileIdentifier( PdfString & identifier, const PdfObject* pTrailer ) const { PdfOutputDevice length; PdfObject* pInfo; char* pBuffer; // create a dictionary with some unique information. // This dictionary is based on the PDF files information // dictionary if it exists. if( pTrailer->GetDictionary().HasKey("Info") ) { const PdfReference & rRef = pTrailer->GetDictionary().GetKey( "Info" )->GetReference(); const PdfObject* pObj = m_vecObjects->GetObject( rRef ); if( pObj ) { pInfo = new PdfObject( *pObj ); } else { std::ostringstream oss; oss << "Error while retrieving info dictionary: " << rRef.ObjectNumber() << " " << rRef.GenerationNumber() << " R" << std::endl; PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidHandle, oss.str().c_str() ); } } else { PdfDate date; PdfString dateString; date.ToString( dateString ); pInfo = new PdfObject(); pInfo->GetDictionary().AddKey( "CreationDate", dateString ); pInfo->GetDictionary().AddKey( "Creator", PdfString("PoDoFo") ); pInfo->GetDictionary().AddKey( "Producer", PdfString("PoDoFo") ); } pInfo->GetDictionary().AddKey( "Location", PdfString("SOMEFILENAME") ); pInfo->WriteObject( &length, m_eWriteMode, NULL ); pBuffer = static_cast(malloc( sizeof(char) * length.GetLength() )); if( !pBuffer ) { delete pInfo; PODOFO_RAISE_ERROR( ePdfError_OutOfMemory ); } PdfOutputDevice device( pBuffer, length.GetLength() ); pInfo->WriteObject( &device, m_eWriteMode, NULL ); // calculate the MD5 Sum identifier = PdfEncryptMD5Base::GetMD5String( reinterpret_cast(pBuffer), static_cast(length.GetLength()) ); free( pBuffer ); delete pInfo; } void PdfWriter::SetEncrypted( const PdfEncrypt & rEncrypt ) { delete m_pEncrypt; m_pEncrypt = PdfEncrypt::CreatePdfEncrypt( rEncrypt ); } }; podofo-0.9.3/src/base/PdfColor.cpp0000664000175000017500000013001212347347566016614 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2007 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfColor.h" #include "PdfArray.h" #include "PdfDictionary.h" #include "PdfLocale.h" #include "PdfStream.h" #include "PdfTokenizer.h" #include "PdfVariant.h" #include "PdfDefinesPrivate.h" #include #include namespace PoDoFo { /** A PdfNamedColor holds * a PdfColor object and a name. */ class PdfNamedColor { public: /** Create a PdfNamedColor object. * * \param pszName the name. The string must be allocated as static memory somewhere * The string data will not be copied! * \param rColor a PdfColor object */ PdfNamedColor( const char* pszName, const PdfColor & rColor ) : m_pszName( pszName ), m_color( rColor ) { } /** Create a PdfNamedColor object. * * \param pszName the name. The string must be allocated as static memory somewhere * The string data will not be copied! * \param rColorName RGB hex value (e.g. #FFABCD) */ PdfNamedColor( const char* pszName, const char* rColorName ) : m_pszName( pszName ), m_color( FromRGBString(rColorName) ) { } /** Copy constructor */ PdfNamedColor(const PdfNamedColor& rhs) : m_pszName( rhs.m_pszName ), m_color( rhs.m_color ) { } /** Class destructor. */ ~PdfNamedColor() { } /** Compare this color object to a name * The comparison is case insensitive! * \returns true if the passed string is smaller than the name * of this color object. */ inline bool operator<( const char* pszName ) const { return pszName ? PoDoFo::compat::strcasecmp( m_pszName, pszName ) < 0 : true; } /** Compare this color object to a PdfNamedColor comparing only the name. * The comparison is case insensitive! * \returns true if the passed string is smaller than the name * of this color object. */ inline bool operator<( const PdfNamedColor & rhs ) const { return rhs.GetName() ? PoDoFo::compat::strcasecmp( m_pszName, rhs.GetName() ) < 0 : true; } /** Compare this color object to a name * The comparison is case insensitive! * \returns true if the passed string is the name * of this color object. */ inline bool operator==( const char* pszName ) const { return pszName ? PoDoFo::compat::strcasecmp( m_pszName, pszName ) == 0 : false; } /** * \returns a reference to the internal color object */ inline const PdfColor & GetColor() const { return m_color; } /** * \returns a pointer to the name of the color */ inline const char* GetName() const { return m_pszName; } private: /** default constructor, not implemented */ PdfNamedColor(); /** copy assignment operator, not implemented */ PdfNamedColor& operator=(const PdfNamedColor&); /** Creates a color object from a RGB string. * * \param pszName a string describing a color. * * Supported values are: * - hex values (e.g. #FF002A (RGB)) * * \returns a PdfColor object */ static PdfColor FromRGBString( const char* pszName ) { //This method cannot use PdfTokenizer::GetHexValue() as static values used there have //not been initialised yet. This function should used only during program startup //and the only purpose is use at s_NamedColors table. size_t lLen = strlen( pszName ); if ( (lLen == 7) && (pszName[0] == '#') && isxdigit(pszName[1]) ) { const unsigned long NAME_CONVERTED_TO_LONG_HEX = static_cast(strtol(&pszName[1], 0, 16)); const unsigned long R = (NAME_CONVERTED_TO_LONG_HEX & 0x00FF0000) >> 16; const unsigned long G = (NAME_CONVERTED_TO_LONG_HEX & 0x0000FF00) >> 8; const unsigned long B = (NAME_CONVERTED_TO_LONG_HEX & 0x000000FF); return PdfColor( static_cast(R)/255.0, static_cast(G)/255.0, static_cast(B)/255.0 ); } else { PODOFO_RAISE_ERROR( ePdfError_CannotConvertColor ); } } const char* m_pszName; PdfColor m_color; }; /** * Predicate to allow binary search in the list * of PdfNamedColor's using for example std::equal_range. */ class NamedColorComparatorPredicate { public: NamedColorComparatorPredicate() { } inline bool operator()( const PdfNamedColor & rNamedColor1, const PdfNamedColor & rNamedColor2 ) const { return rNamedColor1 < rNamedColor2; } }; // Table based on http://cvsweb.xfree86.org/cvsweb/xc/programs/rgb/rgb.txt?rev=1.2 // Hex values have been copied from http://en.wikipedia.org/wiki/X11_color_names (21/11/2010) static const size_t s_nNumNamedColors = 148; static const PdfNamedColor s_NamedColors[s_nNumNamedColors] = { PdfNamedColor( "aliceblue", "#F0F8FF" ) , PdfNamedColor( "antiquewhite", "#FAEBD7" ) , PdfNamedColor( "aqua", "#00FFFF" ) , PdfNamedColor( "aquamarine", "#7FFFD4" ) , PdfNamedColor( "azure", "#F0FFFF" ) , PdfNamedColor( "beige", "#F5F5DC" ) , PdfNamedColor( "bisque", "#FFE4C4" ) , PdfNamedColor( "black", "#000000" ) , PdfNamedColor( "blanchedalmond","#FFEBCD" ) , PdfNamedColor( "blue", "#0000FF" ) , PdfNamedColor( "blueviolet", "#8A2BE2" ) , PdfNamedColor( "brown", "#A52A2A" ) , PdfNamedColor( "burlywood", "#DEB887" ) , PdfNamedColor( "cadetblue", "#5F9EA0" ) , PdfNamedColor( "chartreuse", "#7FFF00" ) , PdfNamedColor( "chocolate", "#D2691E" ) , PdfNamedColor( "coral", "#FF7F50" ) , PdfNamedColor( "cornflowerblue","#6495ED" ) , PdfNamedColor( "cornsilk", "#FFF8DC" ) , PdfNamedColor( "crimson", "#DC143C" ) , PdfNamedColor( "cyan", "#00FFFF" ) , PdfNamedColor( "darkblue", "#00008B" ) , PdfNamedColor( "darkcyan", "#008B8B" ) , PdfNamedColor( "darkgoldenrod", "#B8860B" ) , PdfNamedColor( "darkgray", "#A9A9A9" ) , PdfNamedColor( "darkgreen", "#006400" ) , PdfNamedColor( "darkgrey", "#A9A9A9" ) , PdfNamedColor( "darkkhaki", "#BDB76B" ) , PdfNamedColor( "darkmagenta", "#8B008B" ) , PdfNamedColor( "darkolivegreen","#556B2F" ) , PdfNamedColor( "darkorange", "#FF8C00" ) , PdfNamedColor( "darkorchid", "#9932CC" ) , PdfNamedColor( "darkred", "#8B0000" ) , PdfNamedColor( "darksalmon", "#E9967A" ) , PdfNamedColor( "darkseagreen", "#8FBC8F" ) , PdfNamedColor( "darkslateblue", "#483D8B" ) , PdfNamedColor( "darkslategray", "#2F4F4F" ) , PdfNamedColor( "darkslategrey", "#2F4F4F" ) , PdfNamedColor( "darkturquoise", "#00CED1" ) , PdfNamedColor( "darkviolet", "#9400D3" ) , PdfNamedColor( "deeppink", "#FF1493" ) , PdfNamedColor( "deepskyblue", "#00BFFF" ) , PdfNamedColor( "dimgray", "#696969" ) , PdfNamedColor( "dimgrey", "#696969" ) , PdfNamedColor( "dodgerblue", "#1E90FF" ) , PdfNamedColor( "firebrick", "#B22222" ) , PdfNamedColor( "floralwhite", "#FFFAF0" ) , PdfNamedColor( "forestgreen", "#228B22" ) , PdfNamedColor( "fuchsia", "#FF00FF" ) , PdfNamedColor( "gainsboro", "#DCDCDC" ) , PdfNamedColor( "ghostwhite", "#F8F8FF" ) , PdfNamedColor( "gold", "#FFD700" ) , PdfNamedColor( "goldenrod", "#DAA520" ) , PdfNamedColor( "gray", "#BEBEBE" ) , //RG changed from W3C to X11 value PdfNamedColor( "green", "#00FF00" ) , PdfNamedColor( "greenyellow", "#ADFF2F" ) , PdfNamedColor( "grey", "#BEBEBE" ) , //RG changed from W3C to X11 value PdfNamedColor( "honeydew", "#F0FFF0" ) , PdfNamedColor( "hotpink", "#FF69B4" ) , PdfNamedColor( "indianred", "#CD5C5C" ) , PdfNamedColor( "indigo", "#4B0082" ) , PdfNamedColor( "ivory", "#FFFFF0" ) , PdfNamedColor( "khaki", "#F0E68C" ) , PdfNamedColor( "lavender", "#E6E6FA" ) , PdfNamedColor( "lavenderblush", "#FFF0F5" ) , PdfNamedColor( "lawngreen", "#7CFC00" ) , PdfNamedColor( "lemonchiffon", "#FFFACD" ) , PdfNamedColor( "lightblue", "#ADD8E6" ) , PdfNamedColor( "lightcoral", "#F08080" ) , PdfNamedColor( "lightcyan", "#E0FFFF" ) , PdfNamedColor( "lightgoldenrod", "#EEDD82" ) , PdfNamedColor( "lightgoldenrodyellow", "#FAFAD2" ) , PdfNamedColor( "lightgray", "#D3D3D3" ) , PdfNamedColor( "lightgreen", "#90EE90" ) , PdfNamedColor( "lightgrey", "#D3D3D3" ) , PdfNamedColor( "lightpink", "#FFB6C1" ) , PdfNamedColor( "lightsalmon", "#FFA07A" ) , PdfNamedColor( "lightseagreen", "#20B2AA" ) , PdfNamedColor( "lightskyblue", "#87CEFA" ) , PdfNamedColor( "lightslategray","#778899" ) , PdfNamedColor( "lightslategrey","#778899" ) , PdfNamedColor( "lightsteelblue","#B0C4DE" ) , PdfNamedColor( "lightyellow", "#FFFFE0" ) , PdfNamedColor( "lime", "#00FF00" ) , PdfNamedColor( "limegreen", "#32CD32" ) , PdfNamedColor( "linen", "#FAF0E6" ) , PdfNamedColor( "magenta", "#FF00FF" ) , PdfNamedColor( "maroon", "#B03060" ) , //RG changed from W3C to X11 value PdfNamedColor( "mediumaquamarine", "#66CDAA" ) , PdfNamedColor( "mediumblue", "#0000CD" ) , PdfNamedColor( "mediumorchid", "#BA55D3" ) , PdfNamedColor( "mediumpurple", "#9370DB" ) , PdfNamedColor( "mediumseagreen","#3CB371" ) , PdfNamedColor( "mediumslateblue", "#7B68EE" ) , PdfNamedColor( "mediumspringgreen", "#00FA9A" ) , PdfNamedColor( "mediumturquoise", "#48D1CC" ) , PdfNamedColor( "mediumvioletred", "#C71585" ) , PdfNamedColor( "midnightblue", "#191970" ) , PdfNamedColor( "mintcream", "#F5FFFA" ) , PdfNamedColor( "mistyrose", "#FFE4E1" ) , PdfNamedColor( "moccasin", "#FFE4B5" ) , PdfNamedColor( "navajowhite", "#FFDEAD" ) , PdfNamedColor( "navy", "#000080" ) , PdfNamedColor( "oldlace", "#FDF5E6" ) , PdfNamedColor( "olive", "#808000" ) , PdfNamedColor( "olivedrab", "#6B8E23" ) , PdfNamedColor( "orange", "#FFA500" ) , PdfNamedColor( "orangered", "#FF4500" ) , PdfNamedColor( "orchid", "#DA70D6" ) , PdfNamedColor( "palegoldenrod", "#EEE8AA" ) , PdfNamedColor( "palegreen", "#98FB98" ) , PdfNamedColor( "paleturquoise", "#AFEEEE" ) , PdfNamedColor( "palevioletred", "#DB7093" ) , PdfNamedColor( "papayawhip", "#FFEFD5" ) , PdfNamedColor( "peachpuff", "#FFDAB9" ) , PdfNamedColor( "peru", "#CD853F" ) , PdfNamedColor( "pink", "#FFC0CB" ) , PdfNamedColor( "plum", "#DDA0DD" ) , PdfNamedColor( "powderblue", "#B0E0E6" ) , PdfNamedColor( "purple", "#A020F0" ) , //RG changed from W3C to X11 value PdfNamedColor( "red", "#FF0000" ) , PdfNamedColor( "rosybrown", "#BC8F8F" ) , PdfNamedColor( "royalblue", "#4169E1" ) , PdfNamedColor( "saddlebrown", "#8B4513" ) , PdfNamedColor( "salmon", "#FA8072" ) , PdfNamedColor( "sandybrown", "#F4A460" ) , PdfNamedColor( "seagreen", "#2E8B57" ) , PdfNamedColor( "seashell", "#FFF5EE" ) , PdfNamedColor( "sienna", "#A0522D" ) , PdfNamedColor( "silver", "#C0C0C0" ) , PdfNamedColor( "skyblue", "#87CEEB" ) , PdfNamedColor( "slateblue", "#6A5ACD" ) , PdfNamedColor( "slategray", "#708090" ) , PdfNamedColor( "slategrey", "#708090" ) , PdfNamedColor( "snow", "#FFFAFA" ) , PdfNamedColor( "springgreen", "#00FF7F" ) , PdfNamedColor( "steelblue", "#4682B4" ) , PdfNamedColor( "tan", "#D2B48C" ) , PdfNamedColor( "teal", "#008080" ) , PdfNamedColor( "thistle", "#D8BFD8" ) , PdfNamedColor( "tomato", "#FF6347" ) , PdfNamedColor( "turquoise", "#40E0D0" ) , PdfNamedColor( "violet", "#EE82EE" ) , PdfNamedColor( "wheat", "#F5DEB3" ) , PdfNamedColor( "white", "#FFFFFF" ) , PdfNamedColor( "whitesmoke", "#F5F5F5" ) , PdfNamedColor( "yellow", "#FFFF00" ) , PdfNamedColor( "yellowgreen", "#9ACD32" ) }; inline void CheckDoubleRange( double val, double min, double max ) { if( (val < min) || (val > max) ) { PODOFO_RAISE_ERROR( ePdfError_ValueOutOfRange ); } } PdfColor::PdfColor() : m_uColor(), m_separationName(), m_separationDensity(0.0), m_eColorSpace(ePdfColorSpace_Unknown), m_eAlternateColorSpace(ePdfColorSpace_Unknown) { m_uColor.rgb[0] = 0.0; m_uColor.rgb[1] = 0.0; m_uColor.rgb[2] = 0.0; } PdfColor::PdfColor( double dGray ) : m_uColor(), m_separationName(), m_separationDensity(0.0), m_eColorSpace(ePdfColorSpace_DeviceGray), m_eAlternateColorSpace(ePdfColorSpace_Unknown) { CheckDoubleRange( dGray, 0.0, 1.0 ); m_uColor.gray = dGray; } PdfColor::PdfColor( double dRed, double dGreen, double dBlue ) : m_uColor(), m_separationName(), m_separationDensity(0.0), m_eColorSpace(ePdfColorSpace_DeviceRGB), m_eAlternateColorSpace(ePdfColorSpace_Unknown) { CheckDoubleRange( dRed, 0.0, 1.0 ); CheckDoubleRange( dGreen, 0.0, 1.0 ); CheckDoubleRange( dBlue, 0.0, 1.0 ); m_uColor.rgb[0] = dRed; m_uColor.rgb[1] = dGreen; m_uColor.rgb[2] = dBlue; } PdfColor::PdfColor( double dCyan, double dMagenta, double dYellow, double dBlack ) : m_uColor(), m_separationName(), m_separationDensity(0.0), m_eColorSpace( ePdfColorSpace_DeviceCMYK ), m_eAlternateColorSpace(ePdfColorSpace_Unknown) { CheckDoubleRange( dCyan, 0.0, 1.0 ); CheckDoubleRange( dMagenta, 0.0, 1.0 ); CheckDoubleRange( dYellow, 0.0, 1.0 ); CheckDoubleRange( dBlack, 0.0, 1.0 ); m_uColor.cmyk[0] = dCyan; m_uColor.cmyk[1] = dMagenta; m_uColor.cmyk[2] = dYellow; m_uColor.cmyk[3] = dBlack; } PdfColor::PdfColor( const PdfColor & rhs ) : m_uColor(), m_separationName(rhs.m_separationName), m_separationDensity(rhs.m_separationDensity), m_eColorSpace(rhs.m_eColorSpace), m_eAlternateColorSpace(rhs.m_eAlternateColorSpace) { memcpy( &m_uColor, &rhs.m_uColor, sizeof(m_uColor) ); } PdfColor::~PdfColor() { } PdfColorGray::PdfColorGray( double dGray ) : PdfColor( dGray ) { } PdfColorGray::~PdfColorGray() { } PdfColorRGB::PdfColorRGB( double dRed, double dGreen, double dBlue ) : PdfColor( dRed, dGreen, dBlue ) { } PdfColorRGB::~PdfColorRGB() { } PdfColorCMYK::PdfColorCMYK( double dCyan, double dMagenta, double dYellow, double dBlack ) : PdfColor( dCyan, dMagenta, dYellow, dBlack ) { } PdfColorCMYK::~PdfColorCMYK() { } PdfColorCieLab::PdfColorCieLab( double dCieL, double dCieA, double dCieB ) : PdfColor() { CheckDoubleRange( dCieL, 0.0, 100.0 ); CheckDoubleRange( dCieA, -128.0, 127.0 ); CheckDoubleRange( dCieB, -128.0, 127.0 ); m_eColorSpace = ePdfColorSpace_CieLab; m_uColor.lab[0] = dCieL; m_uColor.lab[1] = dCieA; m_uColor.lab[2] = dCieB; } PdfColorCieLab::~PdfColorCieLab() { } PdfColorSeparationAll::PdfColorSeparationAll() : PdfColor() { m_eColorSpace = ePdfColorSpace_Separation; m_separationName = "All"; m_separationDensity = 1.0; m_eAlternateColorSpace = ePdfColorSpace_DeviceCMYK; m_uColor.cmyk[0] = 1.0; m_uColor.cmyk[1] = 1.0; m_uColor.cmyk[2] = 1.0; m_uColor.cmyk[3] = 1.0; } PdfColorSeparationAll::~PdfColorSeparationAll() { } PdfColorSeparationNone::PdfColorSeparationNone() : PdfColor() { m_eColorSpace = ePdfColorSpace_Separation; m_separationName = "None"; m_separationDensity = 0.0; m_eAlternateColorSpace = ePdfColorSpace_DeviceCMYK; m_uColor.cmyk[0] = 0.0; m_uColor.cmyk[1] = 0.0; m_uColor.cmyk[2] = 0.0; m_uColor.cmyk[3] = 0.0; } PdfColorSeparationNone::~PdfColorSeparationNone() { } PdfColorSeparation::PdfColorSeparation( const std::string & sName, double dDensity, const PdfColor & alternateColor ) : PdfColor() { m_eAlternateColorSpace = alternateColor.GetColorSpace(); switch( m_eAlternateColorSpace ) { case ePdfColorSpace_DeviceGray: { m_uColor.gray = alternateColor.GetGrayScale(); break; } case ePdfColorSpace_DeviceRGB: { m_uColor.rgb[0] = alternateColor.GetRed(); m_uColor.rgb[1] = alternateColor.GetGreen(); m_uColor.rgb[2] = alternateColor.GetBlue(); break; } case ePdfColorSpace_DeviceCMYK: { m_uColor.cmyk[0] = alternateColor.GetCyan(); m_uColor.cmyk[1] = alternateColor.GetMagenta(); m_uColor.cmyk[2] = alternateColor.GetYellow(); m_uColor.cmyk[3] = alternateColor.GetBlack(); break; } case ePdfColorSpace_CieLab: { m_uColor.lab[0] = alternateColor.GetCieL(); m_uColor.lab[1] = alternateColor.GetCieA(); m_uColor.lab[2] = alternateColor.GetCieB(); break; } case ePdfColorSpace_Separation: { PODOFO_RAISE_LOGIC_IF( true, "PdfColor::PdfColorSeparation alternateColor must be Gray, RGB, CMYK or CieLab!"); break; } case ePdfColorSpace_Unknown: case ePdfColorSpace_Indexed: default: { PODOFO_RAISE_ERROR( ePdfError_InvalidEnumValue ); break; } } m_eColorSpace = ePdfColorSpace_Separation; m_separationName = sName; m_separationDensity = dDensity; } PdfColorSeparation::~PdfColorSeparation() { } const PdfColor & PdfColor::operator=( const PdfColor & rhs ) { if (this != &rhs) { memcpy( &m_uColor, &rhs.m_uColor, sizeof(m_uColor) ); m_separationName = rhs.m_separationName; m_separationDensity = rhs.m_separationDensity; m_eColorSpace = rhs.m_eColorSpace; m_eAlternateColorSpace = rhs.m_eAlternateColorSpace; } else { //do nothing } return *this; } PdfColor PdfColor::ConvertToGrayScale() const { switch(m_eColorSpace) { case ePdfColorSpace_DeviceGray: { return *this; } case ePdfColorSpace_DeviceRGB: { return PdfColor( 0.299*m_uColor.rgb[0] + 0.587*m_uColor.rgb[1] + 0.114*m_uColor.rgb[2] ); } case ePdfColorSpace_DeviceCMYK: { return ConvertToRGB().ConvertToGrayScale(); } case ePdfColorSpace_Separation: { if ( m_eAlternateColorSpace == ePdfColorSpace_DeviceCMYK ) { double dCyan = m_uColor.cmyk[0]; double dMagenta = m_uColor.cmyk[1]; double dYellow = m_uColor.cmyk[2]; double dBlack = m_uColor.cmyk[3]; double dRed = dCyan * (1.0 - dBlack) + dBlack; double dGreen = dMagenta * (1.0 - dBlack) + dBlack; double dBlue = dYellow * (1.0 - dBlack) + dBlack; return PdfColor( 1.0 - dRed, 1.0 - dGreen, 1.0 - dBlue ); } else { PODOFO_RAISE_ERROR( ePdfError_NotImplemented ); } break; } case ePdfColorSpace_CieLab: case ePdfColorSpace_Indexed: case ePdfColorSpace_Unknown: { PODOFO_RAISE_ERROR( ePdfError_CannotConvertColor ); break; } default: { PODOFO_RAISE_ERROR( ePdfError_InvalidEnumValue ); break; } }; return PdfColor(); } PdfColor PdfColor::ConvertToRGB() const { switch(m_eColorSpace) { case ePdfColorSpace_DeviceGray: { return PdfColor( m_uColor.gray, m_uColor.gray, m_uColor.gray ); } case ePdfColorSpace_DeviceRGB: { return *this; } case ePdfColorSpace_DeviceCMYK: { double dCyan = m_uColor.cmyk[0]; double dMagenta = m_uColor.cmyk[1]; double dYellow = m_uColor.cmyk[2]; double dBlack = m_uColor.cmyk[3]; double dRed = dCyan * (1.0 - dBlack) + dBlack; double dGreen = dMagenta * (1.0 - dBlack) + dBlack; double dBlue = dYellow * (1.0 - dBlack) + dBlack; return PdfColor( 1.0 - dRed, 1.0 - dGreen, 1.0 - dBlue ); } case ePdfColorSpace_Separation: { if ( m_eAlternateColorSpace == ePdfColorSpace_DeviceCMYK ) { double dCyan = m_uColor.cmyk[0]; double dMagenta = m_uColor.cmyk[1]; double dYellow = m_uColor.cmyk[2]; double dBlack = m_uColor.cmyk[3]; double dRed = dCyan * (1.0 - dBlack) + dBlack; double dGreen = dMagenta * (1.0 - dBlack) + dBlack; double dBlue = dYellow * (1.0 - dBlack) + dBlack; return PdfColor( 1.0 - dRed, 1.0 - dGreen, 1.0 - dBlue ); } else { PODOFO_RAISE_ERROR( ePdfError_NotImplemented ); } break; } case ePdfColorSpace_CieLab: case ePdfColorSpace_Indexed: case ePdfColorSpace_Unknown: { PODOFO_RAISE_ERROR( ePdfError_CannotConvertColor ); break; } default: { PODOFO_RAISE_ERROR( ePdfError_InvalidEnumValue ); break; } }; return PdfColor(); } PdfColor PdfColor::ConvertToCMYK() const { switch(m_eColorSpace) { case ePdfColorSpace_DeviceGray: { return ConvertToRGB().ConvertToCMYK(); } case ePdfColorSpace_DeviceRGB: { double dRed = m_uColor.rgb[0]; double dGreen = m_uColor.rgb[1]; double dBlue = m_uColor.rgb[2]; double dBlack = PDF_MIN( 1.0-dRed, PDF_MIN( 1.0-dGreen, 1.0-dBlue ) ); double dCyan = 0.0; double dMagenta = 0.0; double dYellow = 0.0; if (dBlack < 1.0) { dCyan = (1.0 - dRed - dBlack) / (1.0 - dBlack); dMagenta = (1.0 - dGreen - dBlack) / (1.0 - dBlack); dYellow = (1.0 - dBlue - dBlack) / (1.0 - dBlack); } //else do nothing return PdfColor( dCyan, dMagenta, dYellow, dBlack ); } case ePdfColorSpace_DeviceCMYK: { return *this; } case ePdfColorSpace_Separation: case ePdfColorSpace_CieLab: case ePdfColorSpace_Indexed: case ePdfColorSpace_Unknown: { PODOFO_RAISE_ERROR( ePdfError_CannotConvertColor ); break; } default: { PODOFO_RAISE_ERROR( ePdfError_InvalidEnumValue ); break; } }; } PdfArray PdfColor::ToArray() const { PdfArray array; switch(m_eColorSpace) { case ePdfColorSpace_DeviceGray: { array.push_back( m_uColor.gray ); break; } case ePdfColorSpace_DeviceRGB: { array.push_back( m_uColor.rgb[0] ); array.push_back( m_uColor.rgb[1] ); array.push_back( m_uColor.rgb[2] ); break; } case ePdfColorSpace_DeviceCMYK: { array.push_back( m_uColor.cmyk[0] ); array.push_back( m_uColor.cmyk[1] ); array.push_back( m_uColor.cmyk[2] ); array.push_back( m_uColor.cmyk[3] ); break; } case ePdfColorSpace_CieLab: { array.push_back( m_uColor.lab[0] ); array.push_back( m_uColor.lab[1] ); array.push_back( m_uColor.lab[2] ); break; } case ePdfColorSpace_Separation: { array.push_back( m_separationDensity ); break; } case ePdfColorSpace_Indexed: case ePdfColorSpace_Unknown: { PODOFO_RAISE_ERROR( ePdfError_CannotConvertColor ); break; } default: { PODOFO_RAISE_ERROR( ePdfError_InvalidEnumValue ); break; } }; return array; } PdfColor PdfColor::FromString( const char* pszName ) { if( pszName ) { size_t lLen = strlen( pszName ); // first see if it's a single number - if so, that's a single gray value if( isdigit( pszName[0] ) || (pszName[0] == '.') ) { double dGrayVal = 0.0; std::istringstream stream( pszName ); PdfLocaleImbue(stream); if( !(stream >> dGrayVal) ) { PODOFO_RAISE_ERROR( ePdfError_CannotConvertColor ); } else { return PdfColor( dGrayVal ); } } // now check for a hex value (#xxxxxx or #xxxxxxxx) else if( pszName[0] == '#' ) { ++pszName; if( lLen == 7 ) // RGB { const unsigned int R_HI = static_cast(PdfTokenizer::GetHexValue( *pszName++ )); const unsigned int R_LO = static_cast(PdfTokenizer::GetHexValue( *pszName++ )); const unsigned int R = (R_HI << 4) | R_LO; const unsigned int G_HI = static_cast(PdfTokenizer::GetHexValue( *pszName++ )); const unsigned int G_LO = static_cast(PdfTokenizer::GetHexValue( *pszName++ )); const unsigned int G = (G_HI << 4) | G_LO; const unsigned int B_HI = static_cast(PdfTokenizer::GetHexValue( *pszName++ )); const unsigned int B_LO = static_cast(PdfTokenizer::GetHexValue( *pszName++ )); const unsigned int B = (B_HI << 4) | B_LO; if ( (R_HI != PdfTokenizer::HEX_NOT_FOUND) && (R_LO != PdfTokenizer::HEX_NOT_FOUND) && (G_HI != PdfTokenizer::HEX_NOT_FOUND) && (G_LO != PdfTokenizer::HEX_NOT_FOUND) && (B_HI != PdfTokenizer::HEX_NOT_FOUND) && (B_LO != PdfTokenizer::HEX_NOT_FOUND) ) { return PdfColor( static_cast(R)/255.0, static_cast(G)/255.0, static_cast(B)/255.0 ); } else { PODOFO_RAISE_ERROR( ePdfError_CannotConvertColor ); } } else if( lLen == 9 ) // CMYK { const unsigned int C_HI = static_cast(PdfTokenizer::GetHexValue( *pszName++ )); const unsigned int C_LO = static_cast(PdfTokenizer::GetHexValue( *pszName++ )); const unsigned int C = (C_HI << 4) | C_LO; const unsigned int M_HI = static_cast(PdfTokenizer::GetHexValue( *pszName++ )); const unsigned int M_LO = static_cast(PdfTokenizer::GetHexValue( *pszName++ )); const unsigned int M = (M_HI << 4) | M_LO; const unsigned int Y_HI = static_cast(PdfTokenizer::GetHexValue( *pszName++ )); const unsigned int Y_LO = static_cast(PdfTokenizer::GetHexValue( *pszName++ )); const unsigned int Y = (Y_HI << 4) | Y_LO; const unsigned int K_HI = static_cast(PdfTokenizer::GetHexValue( *pszName++ )); const unsigned int K_LO = static_cast(PdfTokenizer::GetHexValue( *pszName++ )); const unsigned int K = (K_HI << 4) | K_LO; if ( (C_HI != PdfTokenizer::HEX_NOT_FOUND) && (C_LO != PdfTokenizer::HEX_NOT_FOUND) && (M_HI != PdfTokenizer::HEX_NOT_FOUND) && (M_LO != PdfTokenizer::HEX_NOT_FOUND) && (Y_HI != PdfTokenizer::HEX_NOT_FOUND) && (Y_LO != PdfTokenizer::HEX_NOT_FOUND) && (K_HI != PdfTokenizer::HEX_NOT_FOUND) && (K_LO != PdfTokenizer::HEX_NOT_FOUND) ) { return PdfColor( static_cast(C)/255.0, static_cast(M)/255.0, static_cast(Y)/255.0, static_cast(K)/255.0 ); } else { PODOFO_RAISE_ERROR( ePdfError_CannotConvertColor ); } } } // PdfArray else if( pszName[0] == '[' ) { PdfTokenizer tokenizer( pszName, lLen ); PdfVariant var; tokenizer.GetNextVariant( var, NULL ); // No encryption... if( var.IsArray() ) return PdfColor::FromArray( var.GetArray() ); } // it must be a named RGB color else { std::pair iterators = std::equal_range( &(s_NamedColors[0]), s_NamedColors + s_nNumNamedColors, PdfNamedColor( pszName, PdfColor() ), NamedColorComparatorPredicate() ); if( iterators.first != iterators.second ) { return (*(iterators.first)).GetColor(); } } } return PdfColor(); } PdfColor PdfColor::FromArray( const PdfArray & rArray ) { if( rArray.GetSize() == 1 ) // grayscale return PdfColor( rArray[0].GetReal() ); else if( rArray.GetSize() == 3 ) // RGB or spot return PdfColor( rArray[0].GetReal(), rArray[1].GetReal(), rArray[2].GetReal() ); else if( rArray.GetSize() == 4 ) // CMYK return PdfColor( rArray[0].GetReal(), rArray[1].GetReal(), rArray[2].GetReal(), rArray[3].GetReal() ); PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidDataType, "PdfColor::FromArray supports only GrayScale, RGB and CMYK colors." ); } PdfObject* PdfColor::BuildColorSpace( PdfVecObjects* pOwner ) const { switch( m_eColorSpace ) { case ePdfColorSpace_Separation: { // Build color-spaces for separation PdfObject* csTintFunc = pOwner->CreateObject(); csTintFunc->GetDictionary().AddKey( "BitsPerSample", static_cast(8) ); PdfArray decode; decode.push_back( static_cast(0) ); decode.push_back( static_cast(1) ); decode.push_back( static_cast(0) ); decode.push_back( static_cast(1) ); decode.push_back( static_cast(0) ); decode.push_back( static_cast(1) ); decode.push_back( static_cast(0) ); decode.push_back( static_cast(1) ); csTintFunc->GetDictionary().AddKey( "Decode", decode ); PdfArray domain; domain.push_back( static_cast(0) ); domain.push_back( static_cast(1) ); csTintFunc->GetDictionary().AddKey( "Domain", domain ); PdfArray encode; encode.push_back( static_cast(0) ); encode.push_back( static_cast(1) ); csTintFunc->GetDictionary().AddKey( "Encode", encode ); csTintFunc->GetDictionary().AddKey( "Filter", PdfName( "FlateDecode" ) ); csTintFunc->GetDictionary().AddKey( "FunctionType", PdfVariant( static_cast(0L) ) ); //csTintFunc->GetDictionary().AddKey( "FunctionType", // PdfVariant( static_cast(ePdfFunctionType_Sampled) ) ); switch ( m_eAlternateColorSpace ) { case ePdfColorSpace_DeviceGray: { char data[1*2]; data[0] = 0; data[1] = static_cast (m_uColor.gray); PdfArray range; range.push_back( static_cast(0) ); range.push_back( static_cast(1) ); csTintFunc->GetDictionary().AddKey( "Range", range ); PdfArray size; size.push_back( static_cast(2) ); csTintFunc->GetDictionary().AddKey( "Size", size ); PdfMemoryInputStream stream( data, 1*2 ); csTintFunc->GetStream()->Set( &stream ); PdfArray csArr; csArr.push_back( PdfName("Separation") ); csArr.push_back( PdfName( m_separationName ) ); csArr.push_back( PdfName("DeviceGray") ); csArr.push_back( csTintFunc->Reference() ); PdfObject* csp = pOwner->CreateObject( csArr ); return csp; } break; case ePdfColorSpace_DeviceRGB: { char data[3*2]; data[0] = data[1] = data[2] = 0; data[3] = static_cast (m_uColor.rgb[0] * 255); data[4] = static_cast (m_uColor.rgb[1] * 255); data[5] = static_cast (m_uColor.rgb[2] * 255); PdfArray range; range.push_back( static_cast(0) ); range.push_back( static_cast(1) ); range.push_back( static_cast(0) ); range.push_back( static_cast(1) ); range.push_back( static_cast(0) ); range.push_back( static_cast(1) ); csTintFunc->GetDictionary().AddKey( "Range", range ); PdfArray size; size.push_back( static_cast(2) ); csTintFunc->GetDictionary().AddKey( "Size", size ); PdfMemoryInputStream stream( data, 3*2 ); csTintFunc->GetStream()->Set( &stream ); PdfArray csArr; csArr.push_back( PdfName("Separation") ); csArr.push_back( PdfName( m_separationName ) ); csArr.push_back( PdfName("DeviceRGB") ); csArr.push_back( csTintFunc->Reference() ); PdfObject* csp = pOwner->CreateObject( csArr ); return csp; } break; case ePdfColorSpace_DeviceCMYK: { char data[4*2]; data[0] = data[1] = data[2] = data[3] = 0; data[4] = static_cast (m_uColor.cmyk[0] * 255); data[5] = static_cast (m_uColor.cmyk[1] * 255); data[6] = static_cast (m_uColor.cmyk[2] * 255); data[7] = static_cast (m_uColor.cmyk[3] * 255); PdfArray range; range.push_back( static_cast(0) ); range.push_back( static_cast(1) ); range.push_back( static_cast(0) ); range.push_back( static_cast(1) ); range.push_back( static_cast(0) ); range.push_back( static_cast(1) ); range.push_back( static_cast(0) ); range.push_back( static_cast(1) ); csTintFunc->GetDictionary().AddKey( "Range", range ); PdfArray size; size.push_back( static_cast(2) ); csTintFunc->GetDictionary().AddKey( "Size", size ); PdfArray csArr; csArr.push_back( PdfName("Separation") ); csArr.push_back( PdfName( m_separationName ) ); csArr.push_back( PdfName("DeviceCMYK") ); csArr.push_back( csTintFunc->Reference() ); PdfMemoryInputStream stream( data, 4*2 ); csTintFunc->GetStream()->Set( &stream ); // set stream as last, so that it will work with PdfStreamedDocument PdfObject* csp = pOwner->CreateObject( csArr ); return csp; } break; case ePdfColorSpace_CieLab: { char data[3*2]; data[0] = data[1] = data[2] = 0; data[3] = static_cast (m_uColor.lab[0] * 255); data[4] = static_cast (m_uColor.lab[1] * 255); data[5] = static_cast (m_uColor.lab[2] * 255); PdfArray range; range.push_back( static_cast(0) ); range.push_back( static_cast(1) ); range.push_back( static_cast(0) ); range.push_back( static_cast(1) ); range.push_back( static_cast(0) ); range.push_back( static_cast(1) ); csTintFunc->GetDictionary().AddKey( "Range", range ); PdfArray size; size.push_back( static_cast(2) ); csTintFunc->GetDictionary().AddKey( "Size", size ); PdfMemoryInputStream stream( data, 3*2 ); csTintFunc->GetStream()->Set( &stream ); PdfArray csArr; csArr.push_back( PdfName("Separation") ); csArr.push_back( PdfName( m_separationName ) ); csArr.push_back( PdfName("Lab") ); csArr.push_back( csTintFunc->Reference() ); PdfObject* csp = pOwner->CreateObject( csArr ); return csp; } break; case ePdfColorSpace_Separation: case ePdfColorSpace_Indexed: { break; } case ePdfColorSpace_Unknown: default: { PODOFO_RAISE_ERROR( ePdfError_InvalidEnumValue ); break; } } } break; case ePdfColorSpace_CieLab: { // Build color-spaces for CIE-lab PdfDictionary labDict; // D65-whitepoint PdfArray wpArr; wpArr.push_back( 0.9505 ); wpArr.push_back( 1.0000 ); wpArr.push_back( 1.0890 ); labDict.AddKey( PdfName("WhitePoint" ), wpArr ); // Range for A,B, L is implicit 0..100 PdfArray rangeArr; rangeArr.push_back( static_cast(-128) ); rangeArr.push_back( static_cast(127) ); rangeArr.push_back( static_cast(-128) ); rangeArr.push_back( static_cast(127) ); labDict.AddKey( PdfName("Range" ), rangeArr ); PdfArray labArr; labArr.push_back( PdfName("Lab") ); labArr.push_back( labDict ); PdfObject* labp = pOwner->CreateObject( labArr ); return labp; } break; case ePdfColorSpace_DeviceGray: case ePdfColorSpace_DeviceRGB: case ePdfColorSpace_DeviceCMYK: case ePdfColorSpace_Indexed: { break; } case ePdfColorSpace_Unknown: default: { PODOFO_RAISE_ERROR( ePdfError_InvalidEnumValue ); break; } } return NULL; } EPdfColorSpace PdfColor::GetColorSpaceForName( const PdfName & rName ) { EPdfColorSpace ePdfColorSpace = ePdfColorSpace_Unknown; if( PdfName("DeviceGray") == rName ) { ePdfColorSpace = ePdfColorSpace_DeviceGray; } else if( PdfName("DeviceRGB") == rName ) { ePdfColorSpace = ePdfColorSpace_DeviceRGB; } else if( PdfName("DeviceCMYK") == rName ) { ePdfColorSpace = ePdfColorSpace_DeviceCMYK; } else if( PdfName("Indexed") == rName ) { ePdfColorSpace = ePdfColorSpace_Indexed; } else { // TODO: other are not supported at the moment PdfError::LogMessage( eLogSeverity_Information, "Unsupported colorspace name: %s", rName.GetName().c_str() ); } return ePdfColorSpace; } PdfName PdfColor::GetNameForColorSpace( EPdfColorSpace eColorSpace ) { switch( eColorSpace ) { case ePdfColorSpace_DeviceGray: return PdfName("DeviceGray"); case ePdfColorSpace_DeviceRGB: return PdfName("DeviceRGB"); case ePdfColorSpace_DeviceCMYK: return PdfName("DeviceCMYK"); case ePdfColorSpace_Separation: return PdfName("Separation"); case ePdfColorSpace_CieLab: return PdfName("Lab"); case ePdfColorSpace_Indexed: return PdfName("Indexed"); case ePdfColorSpace_Unknown: default: PdfError::LogMessage( eLogSeverity_Information, "Unsupported colorspace enum: %i", eColorSpace ); return PdfName(); } } }; podofo-0.9.3/src/base/PdfFiltersPrivate.cpp0000664000175000017500000010363412344436402020474 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2007 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfDefines.h" #include "PdfFiltersPrivate.h" #include "PdfDictionary.h" #include "PdfOutputDevice.h" #include "PdfOutputStream.h" #include "PdfTokenizer.h" #include "PdfDefinesPrivate.h" #ifdef PODOFO_HAVE_JPEG_LIB extern "C" { #include "jerror.h" } #endif // PODOFO_HAVE_JPEG_LIB #include #include #ifdef PODOFO_HAVE_TIFF_LIB extern "C" { #ifdef _WIN32 // For O_RDONLY // TODO: DS #else #include #include #include #endif } #endif // PODOFO_HAVE_TIFF_LIB #define LZW_TABLE_SIZE 4096 namespace { // Private data for PdfAscii85Filter. This will be optimised // by the compiler through compile-time constant expression // evaluation. const unsigned long sPowers85[] = { 85*85*85*85, 85*85*85, 85*85, 85, 1 }; } // end anonymous namespace namespace PoDoFo { /** * This structur contains all necessary values * for a FlateDecode and LZWDecode Predictor. * These values are normally stored in the /DecodeParams * key of a PDF dictionary. */ class PdfPredictorDecoder { public: PdfPredictorDecoder( const PdfDictionary* pDecodeParms ) { m_nPredictor = static_cast(pDecodeParms->GetKeyAsLong( "Predictor", 1L )); m_nColors = static_cast(pDecodeParms->GetKeyAsLong( "Colors", 1L )); m_nBPC = static_cast(pDecodeParms->GetKeyAsLong( "BitsPerComponent", 8L )); m_nColumns = static_cast(pDecodeParms->GetKeyAsLong( "Columns", 1L )); m_nEarlyChange = static_cast(pDecodeParms->GetKeyAsLong( "EarlyChange", 1L )); if( m_nPredictor >= 10) { m_bNextByteIsPredictor = true; m_nCurPredictor = -1; } else { m_bNextByteIsPredictor = false; m_nCurPredictor = m_nPredictor; } m_nCurRowIndex = 0; m_nBpp = (m_nBPC * m_nColors) >> 3; m_nRows = (m_nColumns * m_nColors * m_nBPC) >> 3; m_pPrev = static_cast(malloc( sizeof(char) * m_nRows)); if( !m_pPrev ) { PODOFO_RAISE_ERROR( ePdfError_OutOfMemory ); } memset( m_pPrev, 0, sizeof(char) * m_nRows ); }; ~PdfPredictorDecoder() { free( m_pPrev ); } void Decode( const char* pBuffer, pdf_long lLen, PdfOutputStream* pStream ) { if( m_nPredictor == 1 ) { pStream->Write( pBuffer, lLen ); return; } while( lLen-- ) { if( m_bNextByteIsPredictor ) { m_nCurPredictor = *pBuffer + 10; m_bNextByteIsPredictor = false; } else { switch( m_nCurPredictor ) { case 2: // Tiff Predictor { if(m_nBPC == 8) { // Same as png sub int prev = (m_nCurRowIndex - m_nBpp < 0 ? 0 : m_pPrev[m_nCurRowIndex - m_nBpp]); m_pPrev[m_nCurRowIndex] = *pBuffer + prev; break; } // TODO: implement tiff predictor for other than 8 BPC PODOFO_RAISE_ERROR( ePdfError_InvalidPredictor ); break; } case 10: // png none { m_pPrev[m_nCurRowIndex] = *pBuffer; break; } case 11: // png sub { int prev = (m_nCurRowIndex - m_nBpp < 0 ? 0 : m_pPrev[m_nCurRowIndex - m_nBpp]); m_pPrev[m_nCurRowIndex] = *pBuffer + prev; break; } case 12: // png up { m_pPrev[m_nCurRowIndex] += *pBuffer; break; } case 13: // png average { int prev = (m_nCurRowIndex - m_nBpp < 0 ? 0 : m_pPrev[m_nCurRowIndex - m_nBpp]); m_pPrev[m_nCurRowIndex] = ((prev + m_pPrev[m_nCurRowIndex]) >> 1) + *pBuffer; break; } case 14: // png paeth case 15: // png optimum PODOFO_RAISE_ERROR( ePdfError_InvalidPredictor ); break; default: { //PODOFO_RAISE_ERROR( ePdfError_InvalidPredictor ); break; } } ++m_nCurRowIndex; } ++pBuffer; if( m_nCurRowIndex >= m_nRows ) { // One line finished m_nCurRowIndex = 0; m_bNextByteIsPredictor = (m_nCurPredictor >= 10); pStream->Write( m_pPrev, m_nRows ); } } } private: int m_nPredictor; int m_nColors; int m_nBPC; //< Bytes per component int m_nColumns; int m_nEarlyChange; int m_nBpp; ///< Bytes per pixel int m_nCurPredictor; int m_nCurRowIndex; int m_nRows; bool m_bNextByteIsPredictor; char* m_pPrev; }; // ------------------------------------------------------- // Hex // ------------------------------------------------------- void PdfHexFilter::EncodeBlockImpl( const char* pBuffer, pdf_long lLen ) { char data[2]; while( lLen-- ) { data[0] = (*pBuffer & 0xF0) >> 4; data[0] += (data[0] > 9 ? 'A' - 10 : '0'); data[1] = (*pBuffer & 0x0F); data[1] += (data[1] > 9 ? 'A' - 10 : '0'); GetStream()->Write( data, 2 ); ++pBuffer; } } void PdfHexFilter::BeginDecodeImpl( const PdfDictionary* ) { m_cDecodedByte = 0; m_bLow = true; } void PdfHexFilter::DecodeBlockImpl( const char* pBuffer, pdf_long lLen ) { char val; while( lLen-- ) { if( PdfTokenizer::IsWhitespace( *pBuffer ) ) { ++pBuffer; continue; } val = PdfTokenizer::GetHexValue( *pBuffer ); if( m_bLow ) { m_cDecodedByte = (val & 0x0F); m_bLow = false; } else { m_cDecodedByte = ((m_cDecodedByte << 4) | val); m_bLow = true; GetStream()->Write( &m_cDecodedByte, 1 ); } ++pBuffer; } } void PdfHexFilter::EndDecodeImpl() { if( !m_bLow ) { // an odd number of bytes was read, // so the last byte is 0 GetStream()->Write( &m_cDecodedByte, 1 ); } } // ------------------------------------------------------- // Ascii 85 // // based on public domain software from: // Paul Haahr - http://www.webcom.com/~haahr/ // ------------------------------------------------------- void PdfAscii85Filter::EncodeTuple( unsigned long tuple, int count ) { int i = 5; int z = 0; char buf[5]; char out[5]; char* start = buf;; do { *start++ = static_cast(tuple % 85); tuple /= 85; } while (--i > 0); i = count; do { out[z++] = static_cast(*--start) + '!'; } while (i-- > 0); GetStream()->Write( out, z ); } void PdfAscii85Filter::BeginEncodeImpl() { m_count = 0; m_tuple = 0; } void PdfAscii85Filter::EncodeBlockImpl( const char* pBuffer, pdf_long lLen ) { unsigned int c; const char* z = "z"; while( lLen ) { c = *pBuffer & 0xff; switch (m_count++) { case 0: m_tuple |= ( c << 24); break; case 1: m_tuple |= ( c << 16); break; case 2: m_tuple |= ( c << 8); break; case 3: m_tuple |= c; if( 0 == m_tuple ) { GetStream()->Write( z, 1 ); } else { this->EncodeTuple( m_tuple, m_count ); } m_tuple = 0; m_count = 0; break; } --lLen; ++pBuffer; } } void PdfAscii85Filter::EndEncodeImpl() { if( m_count > 0 ) this->EncodeTuple( m_tuple, m_count ); //GetStream()->Write( "~>", 2 ); } void PdfAscii85Filter::BeginDecodeImpl( const PdfDictionary* ) { m_count = 0; m_tuple = 0; } void PdfAscii85Filter::DecodeBlockImpl( const char* pBuffer, pdf_long lLen ) { bool foundEndMarker = false; while( lLen && !foundEndMarker ) { switch ( *pBuffer ) { default: if ( *pBuffer < '!' || *pBuffer > 'u') { PODOFO_RAISE_ERROR( ePdfError_ValueOutOfRange ); } m_tuple += ( *pBuffer - '!') * sPowers85[m_count++]; if( m_count == 5 ) { WidePut( m_tuple, 4 ); m_count = 0; m_tuple = 0; } break; case 'z': if (m_count != 0 ) { PODOFO_RAISE_ERROR( ePdfError_ValueOutOfRange ); } this->WidePut( 0, 4 ); break; case '~': ++pBuffer; --lLen; if( lLen && *pBuffer != '>' ) { PODOFO_RAISE_ERROR( ePdfError_ValueOutOfRange ); } foundEndMarker = true; break; case '\n': case '\r': case '\t': case ' ': case '\0': case '\f': case '\b': case 0177: break; } --lLen; ++pBuffer; } } void PdfAscii85Filter::EndDecodeImpl() { if( m_count > 0 ) { m_count--; m_tuple += sPowers85[m_count]; WidePut( m_tuple, m_count ); } } void PdfAscii85Filter::WidePut( unsigned long tuple, int bytes ) const { char data[4]; switch( bytes ) { case 4: data[0] = static_cast(tuple >> 24); data[1] = static_cast(tuple >> 16); data[2] = static_cast(tuple >> 8); data[3] = static_cast(tuple); break; case 3: data[0] = static_cast(tuple >> 24); data[1] = static_cast(tuple >> 16); data[2] = static_cast(tuple >> 8); break; case 2: data[0] = static_cast(tuple >> 24); data[1] = static_cast(tuple >> 16); break; case 1: data[0] = static_cast(tuple >> 24); break; } GetStream()->Write( data, bytes ); } // ------------------------------------------------------- // Flate // ------------------------------------------------------- PdfFlateFilter::PdfFlateFilter() : m_pPredictor( 0 ) { } PdfFlateFilter::~PdfFlateFilter() { delete m_pPredictor; } void PdfFlateFilter::BeginEncodeImpl() { m_stream.zalloc = Z_NULL; m_stream.zfree = Z_NULL; m_stream.opaque = Z_NULL; if( deflateInit( &m_stream, Z_DEFAULT_COMPRESSION ) ) { PODOFO_RAISE_ERROR( ePdfError_Flate ); } } void PdfFlateFilter::EncodeBlockImpl( const char* pBuffer, pdf_long lLen ) { this->EncodeBlockInternal( pBuffer, lLen, Z_NO_FLUSH ); } void PdfFlateFilter::EncodeBlockInternal( const char* pBuffer, pdf_long lLen, int nMode ) { int nWrittenData = 0; m_stream.avail_in = static_cast(lLen); m_stream.next_in = reinterpret_cast(const_cast(pBuffer)); do { m_stream.avail_out = PODOFO_FILTER_INTERNAL_BUFFER_SIZE; m_stream.next_out = m_buffer; if( deflate( &m_stream, nMode) == Z_STREAM_ERROR ) { FailEncodeDecode(); PODOFO_RAISE_ERROR( ePdfError_Flate ); } nWrittenData = PODOFO_FILTER_INTERNAL_BUFFER_SIZE - m_stream.avail_out; try { if( nWrittenData > 0 ) { GetStream()->Write( reinterpret_cast(m_buffer), nWrittenData ); } } catch( PdfError & e ) { // clean up after any output stream errors FailEncodeDecode(); e.AddToCallstack( __FILE__, __LINE__ ); throw e; } } while( m_stream.avail_out == 0 ); } void PdfFlateFilter::EndEncodeImpl() { this->EncodeBlockInternal( NULL, 0, Z_FINISH ); deflateEnd( &m_stream ); } // -- void PdfFlateFilter::BeginDecodeImpl( const PdfDictionary* pDecodeParms ) { m_stream.zalloc = Z_NULL; m_stream.zfree = Z_NULL; m_stream.opaque = Z_NULL; m_pPredictor = pDecodeParms ? new PdfPredictorDecoder( pDecodeParms ) : NULL; if( inflateInit( &m_stream ) != Z_OK ) { PODOFO_RAISE_ERROR( ePdfError_Flate ); } } void PdfFlateFilter::DecodeBlockImpl( const char* pBuffer, pdf_long lLen ) { int flateErr; int nWrittenData; m_stream.avail_in = static_cast(lLen); m_stream.next_in = reinterpret_cast(const_cast(pBuffer)); do { m_stream.avail_out = PODOFO_FILTER_INTERNAL_BUFFER_SIZE; m_stream.next_out = m_buffer; switch( (flateErr = inflate(&m_stream, Z_NO_FLUSH)) ) { case Z_NEED_DICT: case Z_DATA_ERROR: case Z_MEM_ERROR: { PdfError::LogMessage( eLogSeverity_Error, "Flate Decoding Error from ZLib: %i\n", flateErr ); (void)inflateEnd(&m_stream); FailEncodeDecode(); PODOFO_RAISE_ERROR( ePdfError_Flate ); } default: break; } nWrittenData = PODOFO_FILTER_INTERNAL_BUFFER_SIZE - m_stream.avail_out; try { if( m_pPredictor ) m_pPredictor->Decode( reinterpret_cast(m_buffer), nWrittenData, GetStream() ); else GetStream()->Write( reinterpret_cast(m_buffer), nWrittenData ); } catch( PdfError & e ) { // clean up after any output stream errors FailEncodeDecode(); e.AddToCallstack( __FILE__, __LINE__ ); throw e; } } while( m_stream.avail_out == 0 ); } void PdfFlateFilter::EndDecodeImpl() { delete m_pPredictor; m_pPredictor = NULL; (void)inflateEnd(&m_stream); } // ------------------------------------------------------- // RLE // ------------------------------------------------------- void PdfRLEFilter::BeginEncodeImpl() { PODOFO_RAISE_ERROR( ePdfError_UnsupportedFilter ); } void PdfRLEFilter::EncodeBlockImpl( const char*, pdf_long ) { PODOFO_RAISE_ERROR( ePdfError_UnsupportedFilter ); } void PdfRLEFilter::EndEncodeImpl() { PODOFO_RAISE_ERROR( ePdfError_UnsupportedFilter ); } void PdfRLEFilter::BeginDecodeImpl( const PdfDictionary* ) { m_nCodeLen = 0; } void PdfRLEFilter::DecodeBlockImpl( const char* pBuffer, pdf_long lLen ) { while( lLen-- ) { if( !m_nCodeLen ) { m_nCodeLen = static_cast(*pBuffer); } else if( m_nCodeLen == 128 ) break; else if( m_nCodeLen <= 127 ) { GetStream()->Write( pBuffer, 1 ); m_nCodeLen--; } else if( m_nCodeLen >= 129 ) { m_nCodeLen = 257 - m_nCodeLen; while( m_nCodeLen-- ) GetStream()->Write( pBuffer, 1 ); } ++pBuffer; } } // ------------------------------------------------------- // LZW // ------------------------------------------------------- const unsigned short PdfLZWFilter::s_masks[] = { 0x01FF, 0x03FF, 0x07FF, 0x0FFF }; const unsigned short PdfLZWFilter::s_clear = 0x0100; // clear table const unsigned short PdfLZWFilter::s_eod = 0x0101; // end of data PdfLZWFilter::PdfLZWFilter() : m_pPredictor( 0 ) { } PdfLZWFilter::~PdfLZWFilter() { delete m_pPredictor; } void PdfLZWFilter::BeginEncodeImpl() { PODOFO_RAISE_ERROR( ePdfError_UnsupportedFilter ); } void PdfLZWFilter::EncodeBlockImpl( const char*, pdf_long ) { PODOFO_RAISE_ERROR( ePdfError_UnsupportedFilter ); } void PdfLZWFilter::EndEncodeImpl() { PODOFO_RAISE_ERROR( ePdfError_UnsupportedFilter ); } void PdfLZWFilter::BeginDecodeImpl( const PdfDictionary* pDecodeParms ) { m_mask = 0; m_code_len = 9; m_character = 0; m_bFirst = true; m_pPredictor = pDecodeParms ? new PdfPredictorDecoder( pDecodeParms ) : NULL; InitTable(); } void PdfLZWFilter::DecodeBlockImpl( const char* pBuffer, pdf_long lLen ) { unsigned int buffer_size = 0; const unsigned int buffer_max = 24; pdf_uint32 old = 0; pdf_uint32 code = 0; pdf_uint32 buffer = 0; TLzwItem item; std::vector data; if( m_bFirst ) { m_character = *pBuffer; m_bFirst = false; } while( lLen ) { // Fill the buffer while( buffer_size <= (buffer_max-8) && lLen ) { buffer <<= 8; buffer |= static_cast(static_cast(*pBuffer)); buffer_size += 8; ++pBuffer; lLen--; } // read from the buffer while( buffer_size >= m_code_len ) { code = (buffer >> (buffer_size - m_code_len)) & PdfLZWFilter::s_masks[m_mask]; buffer_size -= m_code_len; if( code == PdfLZWFilter::s_clear ) { m_mask = 0; m_code_len = 9; InitTable(); } else if( code == PdfLZWFilter::s_eod ) { lLen = 0; break; } else { if( code >= m_table.size() ) { if (old >= m_table.size()) { PODOFO_RAISE_ERROR( ePdfError_ValueOutOfRange ); } data = m_table[old].value; data.push_back( m_character ); } else data = m_table[code].value; // Write data to the output device if( m_pPredictor ) m_pPredictor->Decode( reinterpret_cast(&(data[0])), data.size(), GetStream() ); else GetStream()->Write( reinterpret_cast(&(data[0])), data.size()); m_character = data[0]; if( old < m_table.size() ) // fix the first loop data = m_table[old].value; data.push_back( m_character ); item.value = data; m_table.push_back( item ); old = code; switch( m_table.size() ) { case 511: case 1023: case 2047: ++m_code_len; ++m_mask; default: break; } } } } } void PdfLZWFilter::EndDecodeImpl() { delete m_pPredictor; m_pPredictor = NULL; } void PdfLZWFilter::InitTable() { int i; TLzwItem item; m_table.clear(); m_table.reserve( LZW_TABLE_SIZE ); for( i=0;i<=255;i++ ) { item.value.clear(); item.value.push_back( static_cast(i) ); m_table.push_back( item ); } // Add dummy entry, which is never used by decoder item.value.clear(); m_table.push_back( item ); } // ------------------------------------------------------- // DCTDecode // ------------------------------------------------------- #ifdef PODOFO_HAVE_JPEG_LIB /* * The actual filter implementation */ PdfDCTFilter::PdfDCTFilter() : m_pDevice( NULL ) { } PdfDCTFilter::~PdfDCTFilter() { } void PdfDCTFilter::BeginEncodeImpl() { PODOFO_RAISE_ERROR( ePdfError_UnsupportedFilter ); } void PdfDCTFilter::EncodeBlockImpl( const char*, pdf_long ) { PODOFO_RAISE_ERROR( ePdfError_UnsupportedFilter ); } void PdfDCTFilter::EndEncodeImpl() { PODOFO_RAISE_ERROR( ePdfError_UnsupportedFilter ); } void PdfDCTFilter::BeginDecodeImpl( const PdfDictionary* ) { // Setup variables for JPEGLib m_cinfo.err = jpeg_std_error( &m_jerr ); jpeg_create_decompress( &m_cinfo ); m_pDevice = new PdfOutputDevice( &m_buffer ); } void PdfDCTFilter::DecodeBlockImpl( const char* pBuffer, pdf_long lLen ) { m_pDevice->Write( pBuffer, lLen ); } void PdfDCTFilter::EndDecodeImpl() { delete m_pDevice; m_pDevice = NULL; jpeg_memory_src ( &m_cinfo, reinterpret_cast(m_buffer.GetBuffer()), m_buffer.GetSize() ); if( jpeg_read_header(&m_cinfo, TRUE) <= 0 ) { (void) jpeg_destroy_decompress(&m_cinfo); PODOFO_RAISE_ERROR( ePdfError_UnexpectedEOF ); } jpeg_start_decompress(&m_cinfo); char* pOutBuffer; JSAMPARRAY pBuffer; long lRowBytes = m_cinfo.output_width * m_cinfo.output_components; const int iComponents = m_cinfo.output_components; // pBuffer will be deleted by jpeg_destroy_decompress pBuffer = (*m_cinfo.mem->alloc_sarray)( reinterpret_cast( &m_cinfo ), JPOOL_IMAGE, lRowBytes, 1); pOutBuffer = static_cast(malloc( lRowBytes * sizeof(char)) ); while( m_cinfo.output_scanline < m_cinfo.output_height ) { jpeg_read_scanlines(&m_cinfo, pBuffer, 1); if( iComponents == 4 ) { for( unsigned int i=0, c=0; i < m_cinfo.output_width; i++, c+=4 ) { pOutBuffer[c] = pBuffer[0][i*4]; pOutBuffer[c+1] = pBuffer[0][i*4+1]; pOutBuffer[c+2] = pBuffer[0][i*4+2]; pOutBuffer[c+3] = pBuffer[0][i*4+3]; } } else if( iComponents == 3 ) { for( unsigned int i=0, c=0; i < m_cinfo.output_width; i++, c+=3 ) { pOutBuffer[c] = pBuffer[0][i*3]; pOutBuffer[c+1] = pBuffer[0][i*3+1]; pOutBuffer[c+2] = pBuffer[0][i*3+2]; } } else if( iComponents == 1 ) { memcpy( pOutBuffer, pBuffer[0], m_cinfo.output_width ); } else { PODOFO_RAISE_ERROR_INFO( ePdfError_InternalLogic, "DCTDecode unknown components" ); } GetStream()->Write( reinterpret_cast(pOutBuffer), lRowBytes ); } free( pOutBuffer ); (void) jpeg_destroy_decompress( &m_cinfo ); } // ------------------------------------------------------- // memsrc.c // ------------------------------------------------------- /* * memsrc.c * * Copyright (C) 1994-1996, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains decompression data source routines for the case of * reading JPEG data from a memory buffer that is preloaded with the entire * JPEG file. This would not seem especially useful at first sight, but * a number of people have asked for it. * This is really just a stripped-down version of jdatasrc.c. Comparison * of this code with jdatasrc.c may be helpful in seeing how to make * custom source managers for other purposes. */ /* Expanded data source object for memory input */ typedef struct { struct jpeg_source_mgr pub; /* public fields */ JOCTET eoi_buffer[2]; /* a place to put a dummy EOI */ } my_source_mgr; typedef my_source_mgr * my_src_ptr; /* * Initialize source --- called by jpeg_read_header * before any data is actually read. */ METHODDEF(void) init_source (j_decompress_ptr) { /* No work, since jpeg_memory_src set up the buffer pointer and count. * Indeed, if we want to read multiple JPEG images from one buffer, * this *must* not do anything to the pointer. */ } /* * Fill the input buffer --- called whenever buffer is emptied. * * In this application, this routine should never be called; if it is called, * the decompressor has overrun the end of the input buffer, implying we * supplied an incomplete or corrupt JPEG datastream. A simple error exit * might be the most appropriate response. * * But what we choose to do in this code is to supply dummy EOI markers * in order to force the decompressor to finish processing and supply * some sort of output image, no matter how corrupted. */ METHODDEF(boolean) fill_input_buffer (j_decompress_ptr cinfo) { my_src_ptr src = reinterpret_cast(cinfo->src); WARNMS(cinfo, JWRN_JPEG_EOF); /* Create a fake EOI marker */ src->eoi_buffer[0] = static_cast(0xFF); src->eoi_buffer[1] = static_cast(JPEG_EOI); src->pub.next_input_byte = src->eoi_buffer; src->pub.bytes_in_buffer = 2; return TRUE; } /* * Skip data --- used to skip over a potentially large amount of * uninteresting data (such as an APPn marker). * * If we overrun the end of the buffer, we let fill_input_buffer deal with * it. An extremely large skip could cause some time-wasting here, but * it really isn't supposed to happen ... and the decompressor will never * skip more than 64K anyway. */ METHODDEF(void) skip_input_data (j_decompress_ptr cinfo, long num_bytes) { my_src_ptr src = reinterpret_cast(cinfo->src); if (num_bytes > 0) { while (num_bytes > static_cast(src->pub.bytes_in_buffer) ) { num_bytes -= static_cast(src->pub.bytes_in_buffer); fill_input_buffer(cinfo); /* note we assume that fill_input_buffer will never return FALSE, * so suspension need not be handled. */ } src->pub.next_input_byte += static_cast(num_bytes); src->pub.bytes_in_buffer -= static_cast(num_bytes); } } /* * An additional method that can be provided by data source modules is the * resync_to_restart method for error recovery in the presence of RST markers. * For the moment, this source module just uses the default resync method * provided by the JPEG library. That method assumes that no backtracking * is possible. */ /* * Terminate source --- called by jpeg_finish_decompress * after all data has been read. Often a no-op. * * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding * application must deal with any cleanup that should happen even * for error exit. */ METHODDEF(void) term_source (j_decompress_ptr) { /* no work necessary here */ } /* * Prepare for input from a memory buffer. */ GLOBAL(void) jpeg_memory_src (j_decompress_ptr cinfo, const JOCTET * buffer, size_t bufsize) { my_src_ptr src; /* The source object is made permanent so that a series of JPEG images * can be read from a single buffer by calling jpeg_memory_src * only before the first one. * This makes it unsafe to use this manager and a different source * manager serially with the same JPEG object. Caveat programmer. */ if (cinfo->src == NULL) { /* first time for this JPEG object? */ cinfo->src = static_cast( (*cinfo->mem->alloc_small) ( reinterpret_cast(cinfo), JPOOL_PERMANENT, sizeof(my_source_mgr))); } src = reinterpret_cast(cinfo->src); src->pub.init_source = init_source; src->pub.fill_input_buffer = fill_input_buffer; src->pub.skip_input_data = skip_input_data; src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */ src->pub.term_source = term_source; src->pub.next_input_byte = buffer; src->pub.bytes_in_buffer = bufsize; } #endif // PODOFO_HAVE_JPEG_LIB #ifdef PODOFO_HAVE_TIFF_LIB #ifdef DS_CCITT_DEVELOPMENT_CODE // ------------------------------------------------------- // // ------------------------------------------------------- static tsize_t dummy_read(thandle_t, tdata_t, tsize_t) { return 0; } // ------------------------------------------------------- // // ------------------------------------------------------- static tsize_t dummy_write(thandle_t, tdata_t, tsize_t size) { return size; } // ------------------------------------------------------- // // ------------------------------------------------------- static toff_t dummy_seek(thandle_t, toff_t, int) { } // ------------------------------------------------------- // // ------------------------------------------------------- static int dummy_close(thandle_t) { } // ------------------------------------------------------- // // ------------------------------------------------------- static toff_t dummy_size(thandle_t) { } #endif // ------------------------------------------------------- // Actual filter code below // ------------------------------------------------------- PdfCCITTFilter::PdfCCITTFilter() : m_tiff( NULL ) { } PdfCCITTFilter::~PdfCCITTFilter() { } void PdfCCITTFilter::BeginEncodeImpl() { PODOFO_RAISE_ERROR( ePdfError_UnsupportedFilter ); } void PdfCCITTFilter::EncodeBlockImpl( const char*, pdf_long ) { PODOFO_RAISE_ERROR( ePdfError_UnsupportedFilter ); } void PdfCCITTFilter::EndEncodeImpl() { PODOFO_RAISE_ERROR( ePdfError_UnsupportedFilter ); } #ifndef _MSC_VER #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-parameter" #endif void PdfCCITTFilter::BeginDecodeImpl( const PdfDictionary* pDict ) { #ifdef DS_CCITT_DEVELOPMENT_CODE if( !pDict ) { PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidHandle, "PdfCCITTFilter required a DecodeParms dictionary" ); } m_tiff = TIFFClientOpen("podofo", "w", reinterpret_cast(-1), dummy_read, dummy_write, dummy_seek, dummy_close, dummy_size, NULL, NULL); if( !m_tiff ) { PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidHandle, "TIFFClientOpen failed" ); } m_tiff->tif_mode = O_RDONLY; TIFFSetField(m_tiff, TIFFTAG_IMAGEWIDTH, pDict->GetKeyAsLong( PdfName("Columns"), 1728 )->GetNumber() ); TIFFSetField(m_tiff, TIFFTAG_SAMPLESPERPIXEL, 1); TIFFSetField(m_tiff, TIFFTAG_BITSPERSAMPLE, 1); TIFFSetField(m_tiff, TIFFTAG_FILLORDER, FILLORDER_LSB2MSB); TIFFSetField(m_tiff, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); TIFFSetField(m_tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISWHITE); TIFFSetField(m_tiff, TIFFTAG_YRESOLUTION, 196.); TIFFSetField(m_tiff, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH); /* m_tiff->tif_scanlinesize = TIFFSetField(m_tiff ); if( pDict ) { long lEncoding = pDict->GetKeyAsLong( PdfName("K"), 0 ); if( lEncoding == 0 ) // pure 1D encoding, Group3 1D { TIFFSetField(faxTIFF,TIFFTAG_GROUP3OPTIONS, GROUP3OPT_1DENCODING); } else if( lEncoding < 0 ) // pure 2D encoding, Group4 { TIFFSetField(faxTIFF,TIFFTAG_GROUP4OPTIONS, GROUP4OPT_2DENCODING); } else //if( lEncoding > 0 ) // mixed, Group3 2D { TIFFSetField(faxTIFF,TIFFTAG_GROUP3OPTIONS, GROUP3OPT_2DENCODING); } } */ #endif // DS_CCITT_DEVELOPMENT_CODE } #ifndef _MSC_VER #pragma GCC diagnostic pop #endif void PdfCCITTFilter::DecodeBlockImpl( const char*, pdf_long ) { } void PdfCCITTFilter::EndDecodeImpl() { } #endif // PODOFO_HAVE_TIFF_LIB }; podofo-0.9.3/src/base/PdfInputDevice.h0000664000175000017500000001617512347311233017415 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2006 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_INPUT_DEVICE_H_ #define _PDF_INPUT_DEVICE_H_ #include #include #include "PdfDefines.h" #include "PdfLocale.h" namespace PoDoFo { /** This class provides an Input device which operates * either on a file, a buffer in memory or any arbitrary std::istream * * This class is suitable for inheritance to provide input * devices of your own for PoDoFo. * Just overide the required virtual methods. */ class PODOFO_API PdfInputDevice { public: /** Construct a new PdfInputDevice that reads all data from a file. * * \param pszFilename path to a file that will be opened and all data * is read from this file. */ PdfInputDevice( const char* pszFilename ); #ifdef _WIN32 /** Construct a new PdfInputDevice that reads all data from a file. * * \param pszFilename path to a file that will be opened and all data * is read from this file. * * This is an overloaded member function to allow working * with unicode characters. On Unix systes you can also path * UTF-8 to the const char* overload. */ PdfInputDevice( const wchar_t* pszFilename ); #endif // _WIN32 /** Construct a new PdfInputDevice that reads all data from a memory buffer. * The buffer will not be owned by this object - it is COPIED. * * \param pBuffer a buffer in memory * \param lLen the length of the buffer in memory */ PdfInputDevice( const char* pBuffer, size_t lLen ); /** Construct a new PdfInputDevice that reads all data from a std::istream. * * \param pInStream read from this std::istream */ PdfInputDevice( const std::istream* pInStream ); /** Destruct the PdfInputDevice object and close any open files. */ virtual ~PdfInputDevice(); /** Close the input device. * No further operations may be performed on this device * after calling this function. */ virtual void Close(); /** Get the current position in file. * /returns the current position in the file */ virtual std::streamoff Tell() const; /** Get next char from stream. * \returns the next character from the stream */ virtual int GetChar() const; /** Peek at next char in stream. * /returns the next char in the stream */ virtual int Look() const; /** Seek the device to the position offset from the begining * \param off from the beginning of the file * \param dir where to start (start, cur, end) * * A non-seekable input device will throw an InvalidDeviceOperation. */ virtual void Seek( std::streamoff off, std::ios_base::seekdir dir = std::ios_base::beg ); /** Read a certain number of bytes from the input device. * * \param pBuffer store bytes in this buffer. * The buffer has to be large enough. * \param lLen number of bytes to read. * \returns the number of bytes that have been read. * If reading was successfull the number of read bytes * is equal to lLen. */ virtual std::streamoff Read( char* pBuffer, std::streamsize lLen ); /** * \return True if the stream is at EOF */ PODOFO_NOTHROW inline virtual bool Eof() const; /** * \return True if there was an error in an I/O operation */ PODOFO_NOTHROW inline virtual bool Bad() const; /** * Set the stream error state. By default, clears badbit, eofbit * and failbit. */ PODOFO_NOTHROW inline virtual void Clear( std::ios_base::iostate state = std::ios_base::goodbit) const; /** * \return True if the stream is seekable. Subclasses can control * this value with SetIsSeekable(bool) . */ PODOFO_NOTHROW inline bool IsSeekable() const; protected: /** * Control whether or or not this stream is flagged * seekable. */ PODOFO_NOTHROW inline void SetSeekable(bool bIsSeekable); /** CAN NOT Construct a new PdfInputDevice without an input source. * However subclasses may well need to do just that. */ PdfInputDevice(); private: /** Initialize all private members */ void Init(); private: std::istream* m_pStream; FILE * m_pFile; bool m_StreamOwned; bool m_bIsSeekable; }; bool PdfInputDevice::IsSeekable() const { return m_bIsSeekable; } void PdfInputDevice::SetSeekable(bool bIsSeekable) { m_bIsSeekable = bIsSeekable; } bool PdfInputDevice::Bad() const { return m_pStream->bad(); } bool PdfInputDevice::Eof() const { return m_pStream->eof(); } void PdfInputDevice::Clear(std::ios_base::iostate state) const { m_pStream->clear(state); } }; #endif // _PDF_INPUT_DEVICE_H_ podofo-0.9.3/src/base/PdfInputDevice.cpp0000664000175000017500000001543112347311233017742 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2006 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfInputDevice.h" #include #include #include #include "PdfDefinesPrivate.h" namespace PoDoFo { PdfInputDevice::PdfInputDevice() { this->Init(); } PdfInputDevice::PdfInputDevice( const char* pszFilename ) { this->Init(); if( !pszFilename ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } try { m_pFile = fopen(pszFilename, "rb"); //m_pStream = new std::ifstream( pszFilename, std::ios::binary ); if( !m_pFile) { PODOFO_RAISE_ERROR_INFO( ePdfError_FileNotFound, pszFilename ); } m_StreamOwned = true; } catch(...) { // should probably check the exact error, but for now it's a good error PODOFO_RAISE_ERROR_INFO( ePdfError_FileNotFound, pszFilename ); } //PdfLocaleImbue(*m_pStream); } #ifdef _WIN32 PdfInputDevice::PdfInputDevice( const wchar_t* pszFilename ) { this->Init(); if( !pszFilename ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } try { // James McGill 16.02.2011 Fix wide character filename loading in windows m_pFile = _wfopen(pszFilename, L"rb"); if( !m_pFile) { PdfError e( ePdfError_FileNotFound, __FILE__, __LINE__ ); e.SetErrorInformation( pszFilename ); throw e; } m_StreamOwned = true; } catch(...) { // should probably check the exact error, but for now it's a good error PdfError e( ePdfError_FileNotFound, __FILE__, __LINE__ ); e.SetErrorInformation( pszFilename ); throw e; } } #endif // _WIN32 PdfInputDevice::PdfInputDevice( const char* pBuffer, size_t lLen ) { this->Init(); if( !pBuffer ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } try { m_pStream = static_cast< std::istream* >( new std::istringstream( std::string( pBuffer, lLen ), std::ios::binary ) ); if( !m_pStream || !m_pStream->good() ) { PODOFO_RAISE_ERROR( ePdfError_FileNotFound ); } m_StreamOwned = true; } catch(...) { // should probably check the exact error, but for now it's a good error PODOFO_RAISE_ERROR( ePdfError_FileNotFound ); } PdfLocaleImbue(*m_pStream); } PdfInputDevice::PdfInputDevice( const std::istream* pInStream ) { this->Init(); m_pStream = const_cast< std::istream* >( pInStream ); if( !m_pStream->good() ) { PODOFO_RAISE_ERROR( ePdfError_FileNotFound ); } PdfLocaleImbue(*m_pStream); } PdfInputDevice::~PdfInputDevice() { this->Close(); if ( m_StreamOwned ) { if (m_pStream) delete m_pStream; if (m_pFile) fclose(m_pFile); } } void PdfInputDevice::Init() { m_pStream = NULL; m_pFile = 0; m_StreamOwned = false; m_bIsSeekable = true; } void PdfInputDevice::Close() { // nothing to do here, but maybe necessary for inheriting classes } int PdfInputDevice::GetChar() const { if (m_pStream) return m_pStream->get(); if (m_pFile) return fgetc(m_pFile); return 0; } int PdfInputDevice::Look() const { if (m_pStream) return m_pStream->peek(); if (m_pFile) { pdf_long lOffset = ftello( m_pFile ); int ch = GetChar(); fseeko( m_pFile, lOffset, SEEK_SET ); return ch; } return 0; } std::streamoff PdfInputDevice::Tell() const { if (m_pStream) return m_pStream->tellg(); if (m_pFile) return ftello(m_pFile); return 0; } /* void PdfInputDevice::Seek( std::streamoff off, std::ios_base::seekdir dir ) { if (m_bIsSeekable) m_pStream->seekg( off, dir ); else PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidDeviceOperation, "Tried to seek an unseekable input device." ); } */ void PdfInputDevice::Seek( std::streamoff off, std::ios_base::seekdir dir ) { if (m_bIsSeekable) { if (m_pStream) { m_pStream->seekg( off, dir ); } if (m_pFile) { fseeko( m_pFile, off, dir ); } } else { PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidDeviceOperation, "Tried to seek an unseekable input device." ); } } std::streamoff PdfInputDevice::Read( char* pBuffer, std::streamsize lLen ) { if (m_pStream) { m_pStream->read( pBuffer, lLen ); return m_pStream->gcount(); } else { return fread(pBuffer, 1, lLen, m_pFile); } } }; // namespace PoDoFo podofo-0.9.3/src/base/PdfLocale.h0000664000175000017500000000225712312006110016354 0ustar dominikdominik#ifndef PODOFO_PDFLOCALE_H #define PODOFO_PDFLOCALE_H #include namespace PoDoFo { /** * The locale to use for PDF I/O . See PoDoFo::PdfLocaleImbue() . */ static const char PdfIOLocale[] = "C"; /** * Imbue the passed stream with a locale that will be safe to do * I/O of the low level PDF format with. * * PDF document structure I/O is done with the C++ standard library * IOStreams code. By default, this will adapt to the current locale. * That's not good at all when doing I/O of PDF data structures, which * follow POSIX/english locale conventions irrespective of runtime locale. * Make sure to to call this function on any stream you intend to use for * PDF I/O. Avoid using this stream for anything that should be done in the * regional locale. * * \warning This method may throw ePdfError_InvalidDeviceOperation * if your STL does not support the locale string in PdfIOLocale . * * If you fail to call this on a stream you use for PDF I/O you will encounter * problems like German and other European users getting numbers in the format * "10110,4" or even "10.110,4" instead of "10110.4" . */ void PODOFO_API PdfLocaleImbue(std::ios_base&); }; #endif podofo-0.9.3/src/base/PdfXRef.cpp0000664000175000017500000002613312262234754016400 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2007 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfXRef.h" #include "PdfOutputDevice.h" #include "PdfDefinesPrivate.h" #include namespace PoDoFo { bool PdfXRef::PdfXRefBlock::InsertItem( const TXRefItem & rItem, bool bUsed ) { if( rItem.reference.ObjectNumber() == m_nFirst + m_nCount ) { // Insert at back m_nCount++; if( bUsed ) items.push_back( rItem ); else freeItems.push_back( rItem.reference ); return true; // no sorting required } else if( rItem.reference.ObjectNumber() == m_nFirst - 1 ) { // Insert at front m_nFirst--; m_nCount++; // This is known to be slow, but should not occur actually if( bUsed ) items.insert( items.begin(), rItem ); else freeItems.insert( freeItems.begin(), rItem.reference ); return true; // no sorting required } else if( rItem.reference.ObjectNumber() > m_nFirst - 1 && rItem.reference.ObjectNumber() < m_nFirst + m_nCount ) { // Insert at back m_nCount++; if( bUsed ) { items.push_back( rItem ); std::sort( items.begin(), items.end() ); } else { freeItems.push_back( rItem.reference ); std::sort( freeItems.begin(), freeItems.end() ); } return true; } return false; } PdfXRef::PdfXRef() { } PdfXRef::~PdfXRef() { } void PdfXRef::AddObject( const PdfReference & rRef, pdf_uint64 offset, bool bUsed ) { TIVecXRefBlock it = m_vecBlocks.begin(); PdfXRef::TXRefItem item( rRef, offset ); bool bInsertDone = false; while( it != m_vecBlocks.end() ) { if( (*it).InsertItem( item, bUsed ) ) { bInsertDone = true; break; } ++it; } if( !bInsertDone ) { PdfXRefBlock block; block.m_nFirst = rRef.ObjectNumber(); block.m_nCount = 1; if( bUsed ) block.items.push_back( item ); else block.freeItems.push_back( rRef ); m_vecBlocks.push_back( block ); std::sort( m_vecBlocks.begin(), m_vecBlocks.end() ); } } void PdfXRef::Write( PdfOutputDevice* pDevice ) { PdfXRef::TCIVecXRefBlock it = m_vecBlocks.begin(); PdfXRef::TCIVecXRefItems itItems; PdfXRef::TCIVecReferences itFree; const PdfReference* pNextFree = NULL; pdf_objnum nFirst = 0; pdf_uint32 nCount = 0; MergeBlocks(); m_offset = pDevice->Tell(); this->BeginWrite( pDevice ); while( it != m_vecBlocks.end() ) { nCount = (*it).m_nCount; nFirst = (*it).m_nFirst; itFree = (*it).freeItems.begin(); itItems = (*it).items.begin(); if( nFirst == 1 ) { --nFirst; ++nCount; } // when there is only one, then we need to start with 0 and the bogus object... this->WriteSubSection( pDevice, nFirst, nCount ); if( !nFirst ) { const PdfReference* pFirstFree = this->GetFirstFreeObject( it, itFree ); this->WriteXRefEntry( pDevice, pFirstFree ? pFirstFree->ObjectNumber() : 0, EMPTY_OBJECT_OFFSET, 'f' ); } while( itItems != (*it).items.end() ) { // check if there is a free object at the current position while( itFree != (*it).freeItems.end() && *itFree < (*itItems).reference ) { pdf_gennum nGen = (*itFree).GenerationNumber(); // get a pointer to the next free object pNextFree = this->GetNextFreeObject( it, itFree ); // write free object this->WriteXRefEntry( pDevice, pNextFree ? pNextFree->ObjectNumber() : 0, nGen, 'f' ); ++itFree; } this->WriteXRefEntry( pDevice, (*itItems).offset, (*itItems).reference.GenerationNumber(), 'n', (*itItems).reference.ObjectNumber() ); ++itItems; } // Check if there are any free objects left! while( itFree != (*it).freeItems.end() ) { pdf_gennum nGen = (*itFree).GenerationNumber(); // get a pointer to the next free object pNextFree = this->GetNextFreeObject( it, itFree ); // write free object this->WriteXRefEntry( pDevice, pNextFree ? pNextFree->ObjectNumber() : 0, nGen, 'f' ); ++itFree; } ++it; } this->EndWrite( pDevice ); } const PdfReference* PdfXRef::GetFirstFreeObject( PdfXRef::TCIVecXRefBlock itBlock, PdfXRef::TCIVecReferences itFree ) const { const PdfReference* pRef = NULL; // find the next free object while( itBlock != m_vecBlocks.end() ) { if( itFree != (*itBlock).freeItems.end() ) break; // got a free object ++itBlock; if(itBlock != m_vecBlocks.end()) itFree = (*itBlock).freeItems.begin(); } // if there is another free object, return it if( itBlock != m_vecBlocks.end() && itFree != (*itBlock).freeItems.end() ) { pRef = &(*itFree); return pRef; } return pRef; } const PdfReference* PdfXRef::GetNextFreeObject( PdfXRef::TCIVecXRefBlock itBlock, PdfXRef::TCIVecReferences itFree ) const { const PdfReference* pRef = NULL; // check if itFree points to a valid free object at the moment if( itFree != (*itBlock).freeItems.end() ) ++itFree; // we currently have a free object, so go to the next one // find the next free object while( itBlock != m_vecBlocks.end() ) { if( itFree != (*itBlock).freeItems.end() ) break; // got a free object ++itBlock; if( itBlock != m_vecBlocks.end() ) itFree = (*itBlock).freeItems.begin(); } // if there is another free object, return it if( itBlock != m_vecBlocks.end() && itFree != (*itBlock).freeItems.end() ) { pRef = &(*itFree); return pRef; } return pRef; } pdf_uint32 PdfXRef::GetSize() const { pdf_uint32 nCount = 0; PdfXRef::TCIVecXRefBlock it = m_vecBlocks.begin(); while( it != m_vecBlocks.end() ) { nCount += (*it).m_nCount; ++it; } //return nCount; if( !m_vecBlocks.size() ) return 0; const PdfXRefBlock& lastBlock = m_vecBlocks.back(); pdf_objnum highObj = lastBlock.items.size() ? lastBlock.items.back().reference.ObjectNumber() : 0; pdf_objnum highFree = lastBlock.freeItems.size() ? lastBlock.freeItems.back().ObjectNumber() : 0; pdf_uint32 max = PDF_MAX( highObj, highFree ); // From the PdfReference: /Size's value is 1 greater than the highes object number used in the file. return max+1; } void PdfXRef::MergeBlocks() { PdfXRef::TIVecXRefBlock it = m_vecBlocks.begin(); PdfXRef::TIVecXRefBlock itNext = it+1; // Do not crash in case we have no blocks at all if( it == m_vecBlocks.end() ) { PODOFO_RAISE_ERROR( ePdfError_NoXRef ); } while( itNext != m_vecBlocks.end() ) { if( (*itNext).m_nFirst == (*it).m_nFirst + (*it).m_nCount ) { // merge the two (*it).m_nCount += (*itNext).m_nCount; (*it).items.reserve( (*it).items.size() + (*itNext).items.size() ); (*it).items.insert( (*it).items.end(), (*itNext).items.begin(), (*itNext).items.end() ); (*it).freeItems.reserve( (*it).freeItems.size() + (*itNext).freeItems.size() ); (*it).freeItems.insert( (*it).freeItems.end(), (*itNext).freeItems.begin(), (*itNext).freeItems.end() ); itNext = m_vecBlocks.erase( itNext ); it = itNext - 1; } else it = itNext++; } } void PdfXRef::BeginWrite( PdfOutputDevice* pDevice ) { pDevice->Print( "xref\n" ); } void PdfXRef::WriteSubSection( PdfOutputDevice* pDevice, pdf_objnum nFirst, pdf_uint32 nCount ) { #ifdef DEBUG PdfError::DebugMessage("Writing XRef section: %u %u\n", nFirst, nCount ); #endif // DEBUG pDevice->Print( "%u %u\n", nFirst, nCount ); } void PdfXRef::WriteXRefEntry( PdfOutputDevice* pDevice, pdf_uint64 offset, pdf_gennum generation, char cMode, pdf_objnum ) { pDevice->Print( "%0.10" PDF_FORMAT_UINT64 " %0.5hu %c \n", offset, generation, cMode ); } void PdfXRef::EndWrite( PdfOutputDevice* ) { } void PdfXRef::SetFirstEmptyBlock() { PdfXRefBlock block; block.m_nFirst = 0; block.m_nCount = 1; m_vecBlocks.insert(m_vecBlocks.begin(), block ); } }; podofo-0.9.3/src/base/PdfParserObject.cpp0000664000175000017500000003620212347271543020116 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2005 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfParserObject.h" #include "PdfArray.h" #include "PdfDictionary.h" #include "PdfEncrypt.h" #include "PdfInputDevice.h" #include "PdfInputStream.h" #include "PdfParser.h" #include "PdfStream.h" #include "PdfVariant.h" #include "PdfDefinesPrivate.h" #include #include #include namespace PoDoFo { using namespace std; static const int s_nLenEndObj = 6; // strlen("endobj"); static const int s_nLenStream = 6; // strlen("stream"); //static const int s_nLenEndStream = 9; // strlen("endstream"); PdfParserObject::PdfParserObject( PdfVecObjects* pCreator, const PdfRefCountedInputDevice & rDevice, const PdfRefCountedBuffer & rBuffer, pdf_long lOffset ) : PdfObject( PdfVariant::NullValue ), PdfTokenizer( rDevice, rBuffer ), m_pEncrypt( NULL ) { m_pOwner = pCreator; InitPdfParserObject(); m_lOffset = lOffset == -1 ? m_device.Device()->Tell() : lOffset; } PdfParserObject::PdfParserObject( const PdfRefCountedBuffer & rBuffer ) : PdfObject( PdfVariant::NullValue ), PdfTokenizer( PdfRefCountedInputDevice(), rBuffer ), m_pEncrypt( NULL ) { InitPdfParserObject(); } PdfParserObject::~PdfParserObject() { } void PdfParserObject::InitPdfParserObject() { m_bIsTrailer = false; // Whether or not demand loading is disabled we still don't load // anything in the ctor. This just controls whether ::ParseFile(...) // forces an immediate demand load, or lets it genuinely happen // on demand. m_bLoadOnDemand = false; // We rely heavily on the demand loading infrastructure whether or not // we *actually* delay loading. EnableDelayedLoading(); EnableDelayedStreamLoading(); m_lOffset = -1; m_bStream = false; m_lStreamOffset = 0; } void PdfParserObject::ReadObjectNumber() { try { pdf_long obj = this->GetNextNumber(); pdf_long gen = this->GetNextNumber(); m_reference = PdfReference( static_cast(obj), static_cast(gen) ); } catch( PdfError & e ) { e.AddToCallstack( __FILE__, __LINE__, "Object and generation number cannot be read." ); throw e; } if( !this->IsNextToken( "obj" )) { std::ostringstream oss; oss << "Error while reading object " << m_reference.ObjectNumber() << " " << m_reference.GenerationNumber() << ": Next token is not 'obj'." << std::endl; PODOFO_RAISE_ERROR_INFO( ePdfError_NoObject, oss.str().c_str() ); } } void PdfParserObject::ParseFile( PdfEncrypt* pEncrypt, bool bIsTrailer ) { if( !m_device.Device() ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } if( m_lOffset > -1 ) m_device.Device()->Seek( m_lOffset ); if( !bIsTrailer ) ReadObjectNumber(); #if defined(PODOFO_VERBOSE_DEBUG) std::cerr << "Parsing object number: " << m_reference.ObjectNumber() << " " << m_reference.GenerationNumber() << " obj" << " " << m_lOffset << " offset" << " (DL: " << ( m_bLoadOnDemand ? "on" : "off" ) << ")" << endl; #endif // PODOFO_VERBOSE_DEBUG m_lOffset = m_device.Device()->Tell(); m_pEncrypt = pEncrypt; m_bIsTrailer = bIsTrailer; if( !m_bLoadOnDemand ) { // Force immediate loading of the object. We need to do this through // the deferred loading machinery to avoid getting the object into an // inconsistent state. // We can't do a full DelayedStreamLoad() because the stream might use // an indirect /Length or /Length1 key that hasn't been read yet. DelayedLoad(); // TODO: support immediate loading of the stream here too. For that, we need // to be able to trigger the reading of not-yet-parsed indirect objects // such as might appear in a /Length key with an indirect reference. #if defined(PODOFO_EXTRA_CHECKS) // Sanity check - the variant base must be fully loaded now if (!DelayedLoadDone() ) { // We don't know what went wrong, but the internal state is // broken or the API rules aren't being followed and we // can't carry on. PODOFO_RAISE_ERROR( ePdfError_InternalLogic ); } #endif // PODOF_EXTRA_CHECKS } } // Only called via the demand loading mechanism // Be very careful to avoid recursive demand loads via PdfVariant // or PdfObject method calls here. void PdfParserObject::ParseFileComplete( bool bIsTrailer ) { #if defined(PODOFO_EXTRA_CHECKS) assert(DelayedLoadInProgress()); assert(!DelayedLoadDone()); #endif const char* pszToken; m_device.Device()->Seek( m_lOffset ); if( m_pEncrypt ) m_pEncrypt->SetCurrentReference( m_reference ); // Do not call GetNextVariant directly, // but GetNextToken, to handle empty objects like: // 13 0 obj // endobj EPdfTokenType eTokenType; bool gotToken = this->GetNextToken( pszToken, &eTokenType ); if (!gotToken) { PODOFO_RAISE_ERROR_INFO( ePdfError_UnexpectedEOF, "Expected variant." ); } // Check if we have an empty object or data if( strncmp( pszToken, "endobj", s_nLenEndObj ) != 0 ) { this->GetNextVariant( pszToken, eTokenType, *this, m_pEncrypt ); this->SetDirty( false ); if( !bIsTrailer ) { bool gotToken = this->GetNextToken( pszToken ); if (!gotToken) { PODOFO_RAISE_ERROR_INFO( ePdfError_UnexpectedEOF, "Expected 'endobj' or (if dict) 'stream', got EOF." ); } if( strncmp( pszToken, "endobj", s_nLenEndObj ) == 0 ) ; // nothing to do, just validate that the PDF is correct // If it's a dictionary, it might have a stream, so check for that else if( this->IsDictionary() && strncmp( pszToken, "stream", s_nLenStream ) == 0 ) { m_bStream = true; m_lStreamOffset = m_device.Device()->Tell(); // NOTE: whitespace after "stream" handle in stream parser! // Most of the code relies on PdfObjects that are dictionaries // to have the datatype ePdfDataType_Dictionary and not Stream. // Please use PdfObject::HasStream to check wether it has a stream. // // Commenting this out is right now easier than fixing all code to check // either for ePdfDataType_Stream or ePdfDataType_Dictionary // //eDataType = ePdfDataType_Stream; // reset the object type to stream! } else { PODOFO_RAISE_ERROR_INFO( ePdfError_NoObject, pszToken ); } } } } // Only called during delayed loading. Must be careful to avoid // triggering recursive delay loading due to use of accessors of // PdfVariant or PdfObject. void PdfParserObject::ParseStream() { #if defined(PODOFO_EXTRA_CHECKS) assert(DelayedLoadDone()); assert(DelayedStreamLoadInProgress()); assert(!DelayedStreamLoadDone()); #endif pdf_int64 lLen = -1; int c; if( !m_device.Device() || !m_pOwner ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } m_device.Device()->Seek( m_lStreamOffset ); // From the PDF Reference manual // The keyword stream that follows // the stream dictionary should be followed by an end-of-line marker consisting of // either a carriage return and a line feed or just a line feed, and not by a carriage re- // turn alone. c = m_device.Device()->Look(); if( PdfTokenizer::IsWhitespace( c ) ) { c = m_device.Device()->GetChar(); if( c == '\r' ) { c = m_device.Device()->Look(); if( c == '\n' ) { c = m_device.Device()->GetChar(); } } } pdf_long fLoc = m_device.Device()->Tell(); // we need to save this, since loading the Length key could disturb it! PdfObject* pObj = this->GetDictionary_NoDL().GetKey( PdfName::KeyLength ); if( pObj && pObj->IsNumber() ) { lLen = pObj->GetNumber(); } else if( pObj && pObj->IsReference() ) { pObj = m_pOwner->GetObject( pObj->GetReference() ); if( !pObj ) { PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidHandle, "/Length key referenced indirect object that could not be loaded" ); } /*PdfError::LogMessage(eLogSeverity_Information, "Reading object %i 0 R with type: %s\n", pObj->Reference().ObjectNumber(), pObj->GetDataTypeString());*/ if( !pObj->IsNumber() ) { PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidStreamLength, "/Length key for stream referenced non-number" ); } lLen = pObj->GetNumber(); // DS: This code makes no sense, // as empty streams with length 0 are valid, too. //if( !lLen ) //{ // PODOFO_RAISE_ERROR( ePdfError_InvalidStreamLength ); //} // we do not use indirect references for the length of the document // DS: Even though do not remove the length key, // as 2 or more object might use the same object for key lengths. // Deleting the length object of the first object will make // all other objects non readable. // If you want those length object to be removed, // run the garbage collection of PdfVecObjects over your PDF. //delete m_pOwner->RemoveObject( pObj->Reference() ); } else { PODOFO_RAISE_ERROR( ePdfError_InvalidStreamLength ); } m_device.Device()->Seek( fLoc ); // reset it before reading! PdfDeviceInputStream reader( m_device.Device() ); if( m_pEncrypt && !m_pEncrypt->IsMetadataEncrypted() ) { // If metadata is not encrypted the Filter is set to "Crypt" PdfObject* pFilterObj = this->GetDictionary_NoDL().GetKey( PdfName::KeyFilter ); if( pFilterObj && pFilterObj->IsArray() ) { PdfArray filters = pFilterObj->GetArray(); for(PdfArray::iterator it = filters.begin(); it != filters.end(); it++) { if( (*it).IsName() ) if( (*it).GetName() == "Crypt" ) m_pEncrypt = 0; } } } if( m_pEncrypt ) { m_pEncrypt->SetCurrentReference( m_reference ); PdfInputStream* pInput = m_pEncrypt->CreateEncryptionInputStream( &reader ); this->GetStream_NoDL()->SetRawData( pInput, static_cast(lLen) ); delete pInput; } else this->GetStream_NoDL()->SetRawData( &reader, static_cast(lLen) ); this->SetDirty( false ); /* SAFE_OP( GetNextStringFromFile( ) ); if( strncmp( m_buffer.Buffer(), "endstream", s_nLenEndStream ) != 0 ) return ERROR_PDF_MISSING_ENDSTREAM; */ } void PdfParserObject::DelayedLoadImpl() { #if defined(PODOFO_EXTRA_CHECKS) // DelayedLoadImpl() should only ever be called via DelayedLoad(), // which ensures that it is never called repeatedly. assert(!DelayedLoadDone()); assert(DelayedLoadInProgress()); #endif ParseFileComplete( m_bIsTrailer ); // If we complete without throwing DelayedLoadDone will be set // for us. } void PdfParserObject::DelayedStreamLoadImpl() { #if defined(PODOFO_EXTRA_CHECKS) // DelayedLoad() must've been called, either directly earlier // or via DelayedStreamLoad. DelayedLoad() will throw if the load // failed, so if we're being called this condition must be true. assert(DelayedLoadDone()); // Similarly, we should not be being called unless the stream isn't // already loaded. assert(!DelayedStreamLoadDone()); assert(DelayedStreamLoadInProgress()); #endif // Note: we can't use HasStream() here because it'll call DelayedStreamLoad() // causing a nasty loop. test m_pStream directly instead. if( this->HasStreamToParse() && !m_pStream ) { try { this->ParseStream(); } catch( PdfError & e ) { // TODO: track object ptr in error info so we don't have to do this memory-intensive // formatting here. std::ostringstream s; s << "Unable to parse the stream for object " << Reference().ObjectNumber() << ' ' << Reference().GenerationNumber() << " obj ."; e.AddToCallstack( __FILE__, __LINE__, s.str().c_str()); throw e; } } // If we complete without throwing the stream will be flagged as loaded. } void PdfParserObject::FreeObjectMemory( bool bForce ) { if( this->IsLoadOnDemand() && (bForce || !this->IsDirty()) ) { PdfVariant::Clear(); delete m_pStream; m_pStream = NULL; EnableDelayedLoading(); EnableDelayedStreamLoading(); } } }; podofo-0.9.3/src/base/PdfMemoryManagement.cpp0000664000175000017500000001036412347271543021001 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2009 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfMemoryManagement.h" #include "PdfDefinesPrivate.h" namespace PoDoFo { bool podofo_is_little_endian() { int _p = 1; return ((reinterpret_cast(&_p))[0] == 1); } void* podofo_malloc( size_t size ) { return malloc( size ); } void* podofo_realloc( void* buffer, size_t size ) { return realloc( buffer, size ); } void podofo_free( void* buffer ) { free( buffer ); } }; // OC 17.08.2010: Activate showing the correct source for Memory Leak Detection in Visual Studio: // See: looking for _AFX_NO_DEBUG_CRT // // Annotation: // defining the new and delete operators and initializeDebugHeap // have to be done inside the dll if podofo is compiled as dll. // // If podofo is compiled as static library // the main program is responsible for theese definitions and initialisations. // Specially the new operator may be implemented completely different // and may not be redefined here. #ifdef _MSC_VER #ifdef DEBUG_NEW // #if defined(_DEBUG) && defined(DEFINE_NEW_DEBUG_NEW) #if defined(COMPILING_SHARED_PODOFO) || defined(podofo_shared_EXPORTS) #undef new void* operator new(size_t ai_NewSize, const char* ac_File_, int ai_Line) { return ::operator new(ai_NewSize, _NORMAL_BLOCK, ac_File_, ai_Line); } void operator delete(void* av_Ptr_, const char* ac_File_, int ai_Line) { ::operator delete(av_Ptr_); } #define new DEBUG_NEW static int initializeDebugHeap() { _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); // _CRTDBG_CHECK_ALWAYS_DF|_CRTDBG_DELAY_FREE_MEM_DF // test if the memory leak detection works: static const char leakdata[] = "*** test memory leak ***"; char* memleak = new char[sizeof(leakdata)]; memcpy(memleak, leakdata, sizeof(leakdata)); return 1; } int isDebugHeapInitialized = initializeDebugHeap(); #endif // podofo_shared_EXPORTS #endif // DEBUG_NEW #endif // _MSC_VER podofo-0.9.3/src/base/PdfDate.cpp0000664000175000017500000001604712344436402016407 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2005 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfDate.h" #include "PdfDefinesPrivate.h" #include #include namespace PoDoFo { PdfDate::PdfDate() : m_bValid( false ) { m_time = time( &m_time ); CreateStringRepresentation(); } PdfDate::PdfDate( const time_t & t ) : m_bValid( false ) { m_time = t; CreateStringRepresentation(); } PdfDate::PdfDate( const PdfString & sDate ) : m_bValid( false ) { if ( !sDate.IsValid() ) { m_szDate[0] = 0; return; } strncpy(m_szDate,sDate.GetString(),PDF_DATE_BUFFER_SIZE); struct tm _tm; memset( &_tm, 0, sizeof(_tm) ); int nZoneShift = 0; int nZoneHour = 0; int nZoneMin = 0; const char * pszDate = sDate.GetString(); if ( pszDate == NULL ) return; if ( *pszDate == 'D' ) { pszDate++; if ( *pszDate++ != ':' ) return; } if ( ParseFixLenNumber(pszDate,4,0,9999,_tm.tm_year) == false ) return; _tm.tm_year -= 1900; if ( *pszDate != '\0' ) { if ( ParseFixLenNumber(pszDate,2,1,12,_tm.tm_mon) == false ) return; _tm.tm_mon--; if ( *pszDate != '\0' ) { if ( ParseFixLenNumber(pszDate,2,1,31,_tm.tm_mday) == false ) return; if ( *pszDate != '\0' ) { if ( ParseFixLenNumber(pszDate,2,0,23,_tm.tm_hour) == false ) return; if ( *pszDate != '\0' ) { if ( ParseFixLenNumber(pszDate,2,0,59,_tm.tm_min) == false ) return; if ( *pszDate != '\0' ) { if ( ParseFixLenNumber(pszDate,2,0,59,_tm.tm_sec) == false ) return; if ( *pszDate != '\0' ) { switch(*pszDate++) { case '+': nZoneShift = -1; break; case '-': nZoneShift = 1; break; case 'Z': nZoneShift = 0; break; default: return; } if ( ParseFixLenNumber(pszDate,2,0,59,nZoneHour) == false ) return; if ( *pszDate == '\'' ) { pszDate++; if ( ParseFixLenNumber(pszDate,2,0,59,nZoneMin) == false ) return; if ( *pszDate != '\'' ) return; pszDate++; } } } } } } } if ( *pszDate != '\0' ) { return; } // convert to m_time = mktime(&_tm); if ( m_time == -1 ) { return; } m_time += nZoneShift*(nZoneHour*3600 + nZoneMin*60); m_bValid = true; } PdfDate::~PdfDate() { } void PdfDate::CreateStringRepresentation() { const int ZONE_STRING_SIZE = 6; const char* INVALIDDATE = "INVALIDDATE"; char szZone[ZONE_STRING_SIZE]; char szDate[PDF_DATE_BUFFER_SIZE]; struct tm* stm = localtime( &m_time ); #ifdef _WIN32 // On win32, strftime with %z returns a verbose time zone name // like "W. Australia Standard time". We use tzset and timezone // instead. _tzset(); snprintf( szZone, ZONE_STRING_SIZE, "%+03d", -_timezone/3600 ); #else if( strftime( szZone, ZONE_STRING_SIZE, "%z", stm ) == 0 ) { std::ostringstream ss; ss << "Generated invalid date from time_t value " << m_time << " (couldn't determine time zone)\n"; PdfError::DebugMessage( ss.str().c_str() ); strcpy( m_szDate, INVALIDDATE ); return; } #endif // only the first 3 characters are important for the pdf date representation // e.g. +01 instead off +0100 szZone[3] = '\0'; if( strftime( szDate, PDF_DATE_BUFFER_SIZE, "D:%Y%m%d%H%M%S", stm ) == 0 ) { std::ostringstream ss; ss << "Generated invalid date from time_t value " << m_time << "\n"; PdfError::DebugMessage( ss.str().c_str() ); strcpy( m_szDate, INVALIDDATE ); return; } snprintf( m_szDate, PDF_DATE_BUFFER_SIZE, "%s%s'00'", szDate, szZone ); m_bValid = true; } bool PdfDate::ParseFixLenNumber(const char *&in, unsigned int length, int min, int max, int &ret) { ret = 0; for(unsigned int i=0;i max ) return false; return true; } }; podofo-0.9.3/src/base/PdfData.cpp0000664000175000017500000000524212344436402016376 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2007 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfData.h" #include "PdfOutputDevice.h" #include "PdfDefinesPrivate.h" namespace PoDoFo { void PdfData::Write( PdfOutputDevice* pDevice, EPdfWriteMode, const PdfEncrypt* ) const { pDevice->Write( m_sData.c_str(), m_sData.length() ); } }; podofo-0.9.3/src/base/PdfFileStream.cpp0000664000175000017500000001236112347271543017566 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2007 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfFileStream.h" #include "PdfEncrypt.h" #include "PdfFilter.h" #include "PdfOutputDevice.h" #include "PdfOutputStream.h" #include "PdfDefinesPrivate.h" namespace PoDoFo { PdfFileStream::PdfFileStream( PdfObject* pParent, PdfOutputDevice* pDevice ) : PdfStream( pParent ), m_pDevice( pDevice ), m_pStream( NULL ), m_pDeviceStream( NULL ), m_pEncryptStream( NULL ), m_lLenInitial( 0 ), m_lLength( 0 ), m_pCurEncrypt( NULL ) { m_pLength = pParent->GetOwner()->CreateObject( PdfVariant(static_cast(PODOFO_LL_LITERAL(0))) ); m_pParent->GetDictionary().AddKey( PdfName::KeyLength, m_pLength->Reference() ); } PdfFileStream::~PdfFileStream() { } void PdfFileStream::Write( PdfOutputDevice*, PdfEncrypt* ) { } void PdfFileStream::BeginAppendImpl( const TVecFilters & vecFilters ) { m_pParent->GetOwner()->WriteObject( m_pParent ); m_lLenInitial = m_pDevice->GetLength(); if( vecFilters.size() ) { m_pDeviceStream = new PdfDeviceOutputStream( m_pDevice ); if( m_pCurEncrypt ) { m_pEncryptStream = m_pCurEncrypt->CreateEncryptionOutputStream( m_pDeviceStream ); m_pStream = PdfFilterFactory::CreateEncodeStream( vecFilters, m_pEncryptStream ); } else m_pStream = PdfFilterFactory::CreateEncodeStream( vecFilters, m_pDeviceStream ); } else { if( m_pCurEncrypt ) { m_pDeviceStream = new PdfDeviceOutputStream( m_pDevice ); m_pStream = m_pCurEncrypt->CreateEncryptionOutputStream( m_pDeviceStream ); } else m_pStream = new PdfDeviceOutputStream( m_pDevice ); } } void PdfFileStream::AppendImpl( const char* pszString, size_t lLen ) { m_pStream->Write( pszString, static_cast(lLen) ); } void PdfFileStream::EndAppendImpl() { if( m_pStream ) { m_pStream->Close(); delete m_pStream; m_pStream = NULL; } if( m_pEncryptStream ) { m_pEncryptStream->Close(); delete m_pEncryptStream; m_pEncryptStream = NULL; } if( m_pDeviceStream ) { m_pDeviceStream->Close(); delete m_pDeviceStream; m_pDeviceStream = NULL; } m_lLength = m_pDevice->GetLength() - m_lLenInitial; if( m_pCurEncrypt ) { m_lLength = m_pCurEncrypt->CalculateStreamLength(m_lLength); } m_pLength->SetNumber( static_cast(m_lLength) ); } void PdfFileStream::GetCopy( char**, pdf_long* ) const { PODOFO_RAISE_ERROR( ePdfError_InternalLogic ); } void PdfFileStream::GetCopy(PdfOutputStream*) const { PODOFO_RAISE_ERROR( ePdfError_InternalLogic ); } void PdfFileStream::SetEncrypted( PdfEncrypt* pEncrypt ) { m_pCurEncrypt = pEncrypt; if( m_pCurEncrypt ) m_pCurEncrypt->SetCurrentReference( m_pParent->Reference() ); } }; podofo-0.9.3/src/base/PdfVersion.h0000664000175000017500000000036411460071654016621 0ustar dominikdominik#ifndef PODOFO_PDFVERSION_H #define PODOFO_PDFVERSION_H #define PODOFO_MAJOR PODOFO_VERSION_MAJOR #define PODOFO_MINOR PODOFO_VERSION_MINOR #define PODOFO_REVISION PODOFO_VERSION_PATCH #define PODOFO_VERSION_STRING PODOFO_VERSION_STR #endif podofo-0.9.3/src/base/PdfImmediateWriter.h0000664000175000017500000001430012344436402020260 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2007 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_IMMEDIATE_WRITER_H_ #define _PDF_IMMEDIATE_WRITER_H_ #include "PdfDefines.h" #include "PdfVecObjects.h" #include "PdfWriter.h" namespace PoDoFo { class PdfEncrypt; class PdfOutputDevice; class PdfXRef; class PODOFO_API PdfImmediateWriter : private PdfWriter, private PdfVecObjects::Observer, private PdfVecObjects::StreamFactory { public: /** Create a new PdfWriter that writes objects with streams immediately to a PdfOutputDevice * * This has the advantage that large documents can be created without * having to keep the whole document in memory. * * @param pDevice all stream streams are immediately written to this output device * while the document is created. * @param pVecObjects a vector of objects containing the objects which are written to disk * @param pTrailer the trailer object * @param eVersion the PDF version of the document to write. * The PDF version can only be set in the constructor * as it is the first item written to the document on disk. * @param pEncrypt pointer to an encryption object or NULL. If not NULL * the PdfEncrypt object will be copied and used to encrypt the * created document. * @param eWriteMode additional options for writing the pdf */ PdfImmediateWriter( PdfOutputDevice* pDevice, PdfVecObjects* pVecObjects, const PdfObject* pTrailer, EPdfVersion eVersion = ePdfVersion_1_5, PdfEncrypt* pEncrypt = NULL, EPdfWriteMode eWriteMode = ePdfWriteMode_Default ); ~PdfImmediateWriter(); /** Get the write mode used for wirting the PDF * \returns the write mode */ inline EPdfWriteMode GetWriteMode() const; /** Get the PDF version of the document * The PDF version can only be set in the constructor * as it is the first item written to the document on disk * * \returns EPdfVersion version of the pdf document */ inline EPdfVersion GetPdfVersion() const; private: void WriteObject( const PdfObject* pObject ); /** Called when the PdfVecObjects we observer is deleted. */ void ParentDestructed(); /** Finish the PDF file. * I.e. write the XRef and close the output device. */ void Finish(); /** Called whenever appending to a stream is started. * \param pStream the stream object the user currently writes to. */ void BeginAppendStream( const PdfStream* pStream ); /** Called whenever appending to a stream has ended. * \param pStream the stream object the user currently writes to. */ void EndAppendStream( const PdfStream* pStream ); /** Creates a stream object * * \param pParent parent object * * \returns a new stream object */ PdfStream* CreateStream( PdfObject* pParent ); /** Assume the stream for the last object has * been written complete. * Therefore close the stream of the object * now so that the next object can be written * to disk */ void FinishLastObject(); private: PdfVecObjects* m_pParent; PdfOutputDevice* m_pDevice; PdfXRef* m_pXRef; PdfObject* m_pLast; bool m_bOpenStream; }; // ----------------------------------------------------- // // ----------------------------------------------------- inline EPdfWriteMode PdfImmediateWriter::GetWriteMode() const { return PdfWriter::GetWriteMode(); } // ----------------------------------------------------- // // ----------------------------------------------------- inline EPdfVersion PdfImmediateWriter::GetPdfVersion() const { return PdfWriter::GetPdfVersion(); } }; #endif /* _PDF_IMMEDIATE_WRITER_H_ */ podofo-0.9.3/src/base/PdfOutputStream.h0000664000175000017500000002125112344436402017644 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2007 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_OUTPUT_STREAM_H_ #define _PDF_OUTPUT_STREAM_H_ #include "PdfDefines.h" #include "PdfRefCountedBuffer.h" #include namespace PoDoFo { #define INITIAL_SIZE 4096 class PdfOutputDevice; /** An interface for writing blocks of data to * a data source. */ class PODOFO_API PdfOutputStream { public: virtual ~PdfOutputStream() { }; /** Write data to the output stream * * \param pBuffer the data is read from this buffer * \param lLen the size of the buffer * * \returns the number of bytes written, -1 if an error ocurred */ virtual pdf_long Write( const char* pBuffer, pdf_long lLen ) = 0; /** * Helper that writes a string via Write(const char*,long) */ inline pdf_long Write( const std::string & s ); /** Close the PdfOutputStream. * This method may throw exceptions and has to be called * before the descructor to end writing. * * No more data may be written to the output device * after calling close. */ virtual void Close() = 0; }; inline pdf_long PdfOutputStream::Write( const std::string & s ) { return this->Write( s.data(), s.size() ); } /** An output stream that writes data to a file */ class PODOFO_API PdfFileOutputStream : public PdfOutputStream { public: /** Open a file for writing data * * \param pszFilename the filename of the file to read */ PdfFileOutputStream( const char* pszFilename ); /** Write data to the output stream * * \param pBuffer the data is read from this buffer * \param lLen the size of the buffer * * \returns the number of bytes written, -1 if an error ocurred */ virtual pdf_long Write( const char* pBuffer, pdf_long lLen ); /** Close the PdfOutputStream. * This method may throw exceptions and has to be called * before the descructor to end writing. * * No more data may be written to the output device * after calling close. */ virtual void Close(); private: FILE* m_hFile; }; /** An output stream that writes data to a memory buffer * If the buffer is to small, it will be enlarged automatically. * * DS: TODO: remove in favour of PdfBufferOutputStream. */ class PODOFO_API PdfMemoryOutputStream : public PdfOutputStream { public: /** * Construct a new PdfMemoryOutputStream * \param lInitial initial size of the buffer */ PdfMemoryOutputStream( pdf_long lInitial = INITIAL_SIZE); /** * Construct a new PdfMemoryOutputStream that writes to an existing buffer * \param pBuffer handle to the buffer * \param lLen length of the buffer */ PdfMemoryOutputStream( char* pBuffer, pdf_long lLen ); ~PdfMemoryOutputStream(); /** Write data to the output stream * * \param pBuffer the data is read from this buffer * \param lLen the size of the buffer * * \returns the number of bytes written, -1 if an error ocurred */ virtual pdf_long Write( const char* pBuffer, pdf_long lLen ); /** Close the PdfOutputStream. * This method may throw exceptions and has to be called * before the descructor to end writing. * * No more data may be written to the output device * after calling close. */ virtual void Close() { } /** \returns the length of the written data */ inline pdf_long GetLength() const; /** * \returns a handle to the internal buffer. * * The internal buffer is now owned by the caller * and will not be deleted by PdfMemoryOutputStream. * Further calls to write are not allowed. * * The caller has to free the returned malloc'ed buffer! */ inline char* TakeBuffer(); private: char* m_pBuffer; pdf_long m_lLen; pdf_long m_lSize; bool m_bOwnBuffer; }; // ----------------------------------------------------- // // ----------------------------------------------------- inline pdf_long PdfMemoryOutputStream::GetLength() const { return m_lLen; } // ----------------------------------------------------- // // ----------------------------------------------------- inline char* PdfMemoryOutputStream::TakeBuffer() { char* pBuffer = m_pBuffer; m_pBuffer = NULL; return pBuffer; } /** An output stream that writes to a PdfOutputDevice */ class PODOFO_API PdfDeviceOutputStream : public PdfOutputStream { public: /** * Write to an already opened input device * * \param pDevice an output device */ PdfDeviceOutputStream( PdfOutputDevice* pDevice ); /** Write data to the output stream * * \param pBuffer the data is read from this buffer * \param lLen the size of the buffer * * \returns the number of bytes written, -1 if an error ocurred */ virtual pdf_long Write( const char* pBuffer, pdf_long lLen ); /** Close the PdfOutputStream. * This method may throw exceptions and has to be called * before the descructor to end writing. * * No more data may be written to the output device * after calling close. */ virtual void Close() {} private: PdfOutputDevice* m_pDevice; }; /** An output stream that writes to a PdfRefCountedBuffer. * * The PdfRefCountedBuffer is resized automatically if necessary. */ class PODOFO_API PdfBufferOutputStream : public PdfOutputStream { public: /** * Write to an already opened input device * * \param pBuffer data is written to this buffer */ PdfBufferOutputStream( PdfRefCountedBuffer* pBuffer ) : m_pBuffer( pBuffer ), m_lLength( pBuffer->GetSize() ) { } /** Write data to the output stream * * \param pBuffer the data is read from this buffer * \param lLen the size of the buffer * * \returns the number of bytes written, -1 if an error ocurred */ virtual pdf_long Write( const char* pBuffer, pdf_long lLen ); virtual void Close() { } /** * \returns the length of the buffers contents */ inline pdf_long GetLength() const { return m_lLength; } private: PdfRefCountedBuffer* m_pBuffer; pdf_long m_lLength; }; }; #endif // _PDF_OUTPUT_STREAM_H_ podofo-0.9.3/src/base/PdfParser.h0000664000175000017500000006167112347271543016444 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2005 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_PARSER_H_ #define _PDF_PARSER_H_ #include "PdfDefines.h" #include "PdfTokenizer.h" #include "PdfVecObjects.h" #define W_ARRAY_SIZE 3 #define W_MAX_BYTES 4 namespace PoDoFo { typedef std::map TMapObjects; typedef TMapObjects::iterator TIMapObjects; typedef TMapObjects::const_iterator TCIMapObjects; class PdfEncrypt; class PdfString; /** * PdfParser reads a PDF file into memory. * The file can be modified in memory and written back using * the PdfWriter class. * Most PDF features are supported */ class PODOFO_API PdfParser : public PdfTokenizer { friend class PdfDocument; friend class PdfWriter; public: struct TXRefEntry { inline TXRefEntry() : lOffset(0), lGeneration(0), cUsed('\x00'), bParsed(false) { } pdf_long lOffset; long lGeneration; char cUsed; bool bParsed; }; typedef std::vector TVecOffsets; typedef TVecOffsets::iterator TIVecOffsets; typedef TVecOffsets::const_iterator TCIVecOffsets; /** Create a new PdfParser object * You have to open a PDF file using ParseFile later. * \param pVecObjects vector to write the parsed PdfObjects to * * \see ParseFile */ PdfParser( PdfVecObjects* pVecObjects ); /** Create a new PdfParser object and open a PDF file and parse * it into memory. * * \param pVecObjects vector to write the parsed PdfObjects to * \param pszFilename filename of the file which is going to be parsed * \param bLoadOnDemand If true all objects will be read from the file at * the time they are accesed first. * If false all objects will be read immediately. * This is faster if you do not need the complete PDF * file in memory. * * This might throw a PdfError( ePdfError_InvalidPassword ) exception * if a password is required to read this PDF. * Call SetPassword with the correct password in this case. * * \see SetPassword */ PdfParser( PdfVecObjects* pVecObjects, const char* pszFilename, bool bLoadOnDemand = true ); #ifdef _WIN32 #if defined(_MSC_VER) && _MSC_VER <= 1200 // nicht fr Visualstudio 6 #else /** Create a new PdfParser object and open a PDF file and parse * it into memory. * * \param pVecObjects vector to write the parsed PdfObjects to * \param pszFilename filename of the file which is going to be parsed * \param bLoadOnDemand If true all objects will be read from the file at * the time they are accesed first. * If false all objects will be read immediately. * This is faster if you do not need the complete PDF * file in memory. * * This might throw a PdfError( ePdfError_InvalidPassword ) exception * if a password is required to read this PDF. * Call SetPassword with the correct password in this case. * * This is an overloaded member function to allow working * with unicode characters. On Unix systes you can also path * UTF-8 to the const char* overload. * * \see SetPassword */ PdfParser( PdfVecObjects* pVecObjects, const wchar_t* pszFilename, bool bLoadOnDemand = true ); #endif #endif // _WIN32 /** Create a new PdfParser object and open a PDF file and parse * it into memory. * * \param pVecObjects vector to write the parsed PdfObjects to * \param pBuffer buffer containing a PDF file in memory * \param lLen length of the buffer containing the PDF file * \param bLoadOnDemand If true all objects will be read from the file at * the time they are accesed first. * If false all objects will be read immediately. * This is faster if you do not need the complete PDF * file in memory. * * This might throw a PdfError( ePdfError_InvalidPassword ) exception * if a password is required to read this PDF. * Call SetPassword with the correct password in this case. * * \see SetPassword */ PdfParser( PdfVecObjects* pVecObjects, const char* pBuffer, long lLen, bool bLoadOnDemand = true ); /** Create a new PdfParser object and open a PDF file and parse * it into memory. * * \param pVecObjects vector to write the parsed PdfObjects to * \param rDevice read from this PdfRefCountedInputDevice * \param bLoadOnDemand If true all objects will be read from the file at * the time they are accesed first. * If false all objects will be read immediately. * This is faster if you do not need the complete PDF * file in memory. * * This might throw a PdfError( ePdfError_InvalidPassword ) exception * if a password is required to read this PDF. * Call SetPassword with the correct password in this case. * * \see SetPassword */ PdfParser( PdfVecObjects* pVecObjects, const PdfRefCountedInputDevice & rDevice, bool bLoadOnDemand = true ); /** Delete the PdfParser and all PdfObjects */ virtual ~PdfParser(); /** Open a PDF file and parse it. * * \param pszFilename filename of the file which is going to be parsed * \param bLoadOnDemand If true all objects will be read from the file at * the time they are accesed first. * If false all objects will be read immediately. * This is faster if you do not need the complete PDF * file in memory. * * * This might throw a PdfError( ePdfError_InvalidPassword ) exception * if a password is required to read this PDF. * Call SetPassword with the correct password in this case. * * \see SetPassword */ void ParseFile( const char* pszFilename, bool bLoadOnDemand = true ); #ifdef _WIN32 /** Open a PDF file and parse it. * * \param pszFilename filename of the file which is going to be parsed * \param bLoadOnDemand If true all objects will be read from the file at * the time they are accesed first. * If false all objects will be read immediately. * This is faster if you do not need the complete PDF * file in memory. * * * This might throw a PdfError( ePdfError_InvalidPassword ) exception * if a password is required to read this PDF. * Call SetPassword with the correct password in this case. * * This is an overloaded member function to allow working * with unicode characters. On Unix systes you can also path * UTF-8 to the const char* overload. * * \see SetPassword */ void ParseFile( const wchar_t* pszFilename, bool bLoadOnDemand = true ); #endif // _WIN32 /** Open a PDF file and parse it. * * \param pBuffer buffer containing a PDF file in memory * \param lLen length of the buffer containing the PDF file * \param bLoadOnDemand If true all objects will be read from the file at * the time they are accesed first. * If false all objects will be read immediately. * This is faster if you do not need the complete PDF * file in memory. * * * This might throw a PdfError( ePdfError_InvalidPassword ) exception * if a password is required to read this PDF. * Call SetPassword with the correct password in this case. * * \see SetPassword */ void ParseFile( const char* pBuffer, long lLen, bool bLoadOnDemand = true ); /** Open a PDF file and parse it. * * \param rDevice the input device to read from * \param bLoadOnDemand If true all objects will be read from the file at * the time they are accesed first. * If false all objects will be read immediately. * This is faster if you do not need the complete PDF * file in memory. * * * This might throw a PdfError( ePdfError_InvalidPassword ) exception * if a password is required to read this PDF. * Call SetPassword with the correct password in this case. * * \see SetPassword */ void ParseFile( const PdfRefCountedInputDevice & rDevice, bool bLoadOnDemand = true ); /** Quick method to detect secured PDF files, i.e. * a PDF with an /Encrypt key in the trailer directory. * * \returns true if document is secured, false otherwise */ bool QuickEncryptedCheck( const char* pszFilename ); /** * Retrieve the number of incremental updates that * have been applied to the last parsed PDF file. * * 0 means no update has been applied. * * \returns the number of incremental updates to the parsed PDF. */ inline int GetNumberOfIncrementalUpdates() const; /** Get a reference to the sorted internal objects vector. * \returns the internal objects vector. */ inline const PdfVecObjects* GetObjects() const; /** Get the file format version of the pdf * \returns the file format version as enum */ inline EPdfVersion GetPdfVersion() const; /** Get the file format version of the pdf * \returns the file format version as string */ const char* GetPdfVersionString() const; /** Get the trailer dictionary * which can be written unmodified to a pdf file. */ inline const PdfObject* GetTrailer() const; /** \returns true if this PdfParser loads all objects on demand at * the time they are accessed for the first time. * The default is to load all object immediately. * In this case false is returned. */ inline bool GetLoadOnDemand() const; /** \returns whether the parsed document contains linearization tables */ bool IsLinearized() const { return m_pLinearization != NULL; } /** \returns the length of the file */ size_t GetFileSize() const { return m_nFileSize; } /** * \returns true if this PdfWriter creates an encrypted PDF file */ bool GetEncrypted() const { return (m_pEncrypt != NULL); } /** * \returns the parsers encryption object or NULL if the read PDF file was not encrypted */ const PdfEncrypt* GetEncrypt() const { return m_pEncrypt; } /** * Takes the encryption object fro mthe parser. The internal handle will be set * to NULL and the ownership of the object is given to the caller. * * Only call this if you need access to the encryption object * before deleting the parser. * * \returns the parsers encryption object or NULL if the read PDF file was not encrypted */ inline PdfEncrypt* TakeEncrypt(); /** If you try to open an encrypted PDF file, which requires * a password to open, PoDoFo will throw a PdfError( ePdfError_InvalidPassword ) * exception. * * If you got such an exception, you have to set a password * which should be used for opening the PDF. * * The usual way will be to ask the user for the password * and set the password using this method. * * PdfParser will immediately continue to read the PDF file. * * \param sPassword a user or owner password which can be used to open an encrypted PDF file * If the password is invalid, a PdfError( ePdfError_InvalidPassword ) exception is thrown! */ void SetPassword( const std::string & sPassword ); /** * \returns true if strict parsing mode is enabled * * \see SetStringParsing */ inline bool IsStrictParsing() const; /** * Enable/disable strict parsing mode. * Strict parsing is by default disabled. * * If you enable strict parsing, PoDoFo will fail * on a few more common PDF failures. Please not * that PoDoFo's parser is by default very strict * already and does not recover from e.g. wrong XREF * tables. * * \param bStrict new setting for strict parsing mode. */ inline void SetStrictParsing( bool bStrict ); /** * \return if broken objects are ignored while parsing */ inline bool GetIgnoreBrokenObjects(); /** * Specify if the parser should ignore broken * objects, i.e. XRef entries that do not point * to valid objects. * * Default is to not ignore broken objects and * throw an exception if one is found. * * \param bBroken if true broken objects will be ignored */ inline void SetIgnoreBrokenObjects( bool bBroken ); /** * \return maximum object count to read (default is LONG_MAX * which means no limit) */ inline static long GetMaxObjectCount(); /** * Specify the maximum number of objects the parser should * read. An exception is thrown if document contains more * objects than this. Use to avoid problems with very large * documents with millions of objects, which use 500MB of * working set and spend 15 mins in Load() before throwing * an out of memory exception. * * \param nMaxObjects set max number of objects */ inline static void SetMaxObjectCount( long nMaxObjects ); inline pdf_long GetXRefOffset(void); bool HasXRefStream(); protected: /** Searches backwards from the end of the file * and tries to find a token. * The current file is positioned right after the token. * * \param pszToken a token to find * \param lRange range in bytes in which to search * begining at the end of the file */ void FindToken( const char* pszToken, const long lRange ); // Peter Petrov 23 December 2008 /** Searches backwards from the specified position of the file * and tries to find a token. * The current file is positioned right after the token. * * \param pszToken a token to find * \param lRange range in bytes in which to search * begining at the specified position of the file * \param searchEnd specifies position */ void FindToken2( const char* pszToken, const long lRange, size_t searchEnd ); /** Reads the xref sections and the trailers of the file * in the correct order in the memory * and takes care for linearized pdf files. */ void ReadDocumentStructure(); /** Checks wether this pdf is linearized or not. * Initializes the linearization directory on sucess. */ void HasLinearizationDict(); /** Merge the information of this trailer object * in the parsers main trailer object. * \param pTrailer take the keys to merge from this dictionary. */ void MergeTrailer( const PdfObject* pTrailer ); /** Read the trailer directory at the end of the file. */ void ReadTrailer(); /** Looks for a startxref entry at the current file position * and saves its byteoffset to pXRefOffset. * \param pXRefOffset store the byte offset of the xref section into this variable. */ void ReadXRef( pdf_long* pXRefOffset ); /** Reads the xref table from a pdf file. * If there is no xref table, ReadXRefStreamContents() is called. * \param lOffset read the table from this offset * \param bPositionAtEnd if true the xref table is not read, but the * file stream is positioned directly * after the table, which allows reading * a following trailer dictionary. */ void ReadXRefContents( pdf_long lOffset, bool bPositionAtEnd = false ); /** Read a xref subsection * * Throws ePdfError_NoXref if the number of objects read was not * the number specified by the subsection header (as passed in * `nNumObjects'). * * \param nFirstObject object number of the first object * \param nNumObjects how many objects should be read from this section */ void ReadXRefSubsection( pdf_int64 & nFirstObject, pdf_int64 & nNumObjects ); /** Reads a xref stream contens object * \param lOffset read the stream from this offset * \param bReadOnlyTrailer only the trailer is skipped over, the contents * of the xref stream are not parsed */ void ReadXRefStreamContents( pdf_long lOffset, bool bReadOnlyTrailer ); /** Reads all objects from the pdf into memory * from the offsets listed in m_vecOffsets. * * If required an encryption object is setup first. * * The actual reading happens in ReadObjectsInternal() * either if no encryption is required or a correct * encryption object was initialized from SetPassword. */ void ReadObjects(); /** Reads all objects from the pdf into memory * from the offsets listed in m_vecOffsets. * * Requires a correctly setup PdfEncrypt object * with correct password. * * This method is called from ReadObjects * or SetPassword. * * \see ReadObjects * \see SetPassword */ void ReadObjectsInternal(); /** Read the object with index nIndex from the object stream nObjNo * and push it on the objects vector m_vecOffsets. * * All objects are read from this stream and the stream object * is free'd from memory. Further calls who try to read from the * same stream simply do nothing. * * \param nObjNo object number of the stream object * \param nIndex index of the object which should be parsed * */ void ReadObjectFromStream( int nObjNo, int nIndex ); /** Checks the magic number at the start of the pdf file * and sets the m_ePdfVersion member to the correct version * of the pdf file. * * \returns true if this is a pdf file, otherwise false */ bool IsPdfFile(); void ReadNextTrailer(); /** Checks for the existence of the %%EOF marker at the end of the file * When strict mode is off it will also attempt to setup the parser to ignore * any garbage after the last %%EOF marker * Simply raises an error if there is a problem with the marker * */ void CheckEOFMarker(); private: /** Free all internal data structures */ void Clear(); /** Initializes all private members * with their initial values. */ void Init(); /** Small helper method to retrieve the document id from the trailer * * \returns the document id of this PDF document */ const PdfString & GetDocumentId(); /** Determines the correct version of the PDF * from the document catalog (if available). * as, PDF > 1.4 allows updating the version. * * If no catalog dictionary is present or no /Version * key is available, the version from the file header will * be used. */ void UpdateDocumentVersion(); private: EPdfVersion m_ePdfVersion; bool m_bLoadOnDemand; pdf_long m_nXRefOffset; long m_nFirstObject; long m_nNumObjects; pdf_long m_nXRefLinearizedOffset; size_t m_nFileSize; pdf_long m_lLastEOFOffset; TVecOffsets m_offsets; PdfVecObjects* m_vecObjects; PdfObject* m_pTrailer; PdfObject* m_pLinearization; PdfEncrypt* m_pEncrypt; bool m_xrefSizeUnknown; std::set m_setObjectStreams; bool m_bStrictParsing; bool m_bIgnoreBrokenObjects; int m_nIncrementalUpdates; int m_nReadNextTrailerLevel; static long s_nMaxObjects; }; // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfParser::GetLoadOnDemand() const { return m_bLoadOnDemand; } // ----------------------------------------------------- // // ----------------------------------------------------- EPdfVersion PdfParser::GetPdfVersion() const { return m_ePdfVersion; } // ----------------------------------------------------- // // ----------------------------------------------------- int PdfParser::GetNumberOfIncrementalUpdates() const { return m_nIncrementalUpdates; } // ----------------------------------------------------- // // ----------------------------------------------------- const PdfVecObjects* PdfParser::GetObjects() const { return m_vecObjects; } // ----------------------------------------------------- // // ----------------------------------------------------- const PdfObject* PdfParser::GetTrailer() const { return m_pTrailer; } // ----------------------------------------------------- // // ----------------------------------------------------- PdfEncrypt* PdfParser::TakeEncrypt() { PdfEncrypt* pEncrypt = m_pEncrypt; m_pEncrypt = NULL; return pEncrypt; } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfParser::IsStrictParsing() const { return m_bStrictParsing; } // ----------------------------------------------------- // // ----------------------------------------------------- void PdfParser::SetStrictParsing( bool bStrict ) { m_bStrictParsing = bStrict; } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfParser::GetIgnoreBrokenObjects() { return m_bIgnoreBrokenObjects; } // ----------------------------------------------------- // // ----------------------------------------------------- void PdfParser::SetIgnoreBrokenObjects( bool bBroken ) { m_bIgnoreBrokenObjects = bBroken; } // ----------------------------------------------------- // // ----------------------------------------------------- long PdfParser::GetMaxObjectCount() { return PdfParser::s_nMaxObjects; } // ----------------------------------------------------- // // ----------------------------------------------------- void PdfParser::SetMaxObjectCount( long nMaxObjects ) { PdfParser::s_nMaxObjects = nMaxObjects; } // ----------------------------------------------------- // // ----------------------------------------------------- pdf_long PdfParser::GetXRefOffset() { return m_nXRefOffset; } }; #endif // _PDF_PARSER_H_ podofo-0.9.3/src/base/PdfReference.h0000664000175000017500000002134212347503635017075 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2006 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_REFERENCE_H_ #define _PDF_REFERENCE_H_ #include "PdfDefines.h" #include "PdfDataType.h" namespace PoDoFo { typedef pdf_uint32 pdf_objnum; /* Technically a generation number must be able to represent 99999 so 65535 isn't good enough. * In practice Adobe's implementation notes suggest that they use a uint16 internally, and PDFs * with greater object numbers won't work on many viewers. So we'll stick with uint16. * * If you change this you'll need to change PdfReference::Write(...) to use the apppropriate * format, too. */ typedef pdf_uint16 pdf_gennum; class PdfOutputDevice; /** * A reference is a pointer to a object in the PDF file of the form * "4 0 R", where 4 is the object number and 0 is the generation number. * Every object in the PDF file can be identified this way. * * This class is a indirect reference in a PDF file. */ class PODOFO_API PdfReference : public PdfDataType { public: /** * Create a PdfReference with object number and generation number * initialized to 0. */ PdfReference() : m_nObjectNo( 0 ), m_nGenerationNo( 0 ) { } /** * Create a PdfReference to an object with a given object and generation number. * * \param nObjectNo the object number * \param nGenerationNo the generation number */ PdfReference( const pdf_objnum nObjectNo, const pdf_gennum nGenerationNo ) : m_nObjectNo( nObjectNo ), m_nGenerationNo( nGenerationNo ) { } /** * Create a copy of an existing PdfReference. * * \param rhs the object to copy */ PdfReference( const PdfReference & rhs ) : PdfDataType() { this->operator=( rhs ); } PODOFO_NOTHROW virtual ~PdfReference() { } /** Convert the reference to a string. * \returns a string representation of the object. * * \see PdfVariant::ToString */ const std::string ToString() const; /** * Assign the value of another object to this PdfReference. * * \param rhs the object to copy */ PODOFO_NOTHROW inline const PdfReference & operator=( const PdfReference & rhs ); /** Write the complete variant to an output device. * This is an overloaded member function. * * \param pDevice write the object to this device * \param eWriteMode additional options for writing this object * \param pEncrypt an encryption object which is used to encrypt this object * or NULL to not encrypt this object */ void Write( PdfOutputDevice* pDevice, EPdfWriteMode eWriteMode, const PdfEncrypt* pEncrypt = NULL ) const; /** * Compare to PdfReference objects. * \returns true if both reference the same object */ PODOFO_NOTHROW inline bool operator==( const PdfReference & rhs ) const; /** * Compare to PdfReference objects. * \returns false if both reference the same object */ PODOFO_NOTHROW inline bool operator!=( const PdfReference & rhs ) const; /** * Compare to PdfReference objects. * \returns true if this reference has a smaller object and generation number */ PODOFO_NOTHROW inline bool operator<( const PdfReference & rhs ) const; /** Set the object number of this object * \param o the new object number */ PODOFO_NOTHROW inline void SetObjectNumber( pdf_objnum o ); /** Get the object number. * \returns the object number of this PdfReference */ PODOFO_NOTHROW inline pdf_objnum ObjectNumber() const; /** Set the generation number of this object * \param g the new generation number */ PODOFO_NOTHROW inline void SetGenerationNumber( const pdf_gennum g ); /** Get the generation number. * \returns the generation number of this PdfReference */ PODOFO_NOTHROW inline pdf_gennum GenerationNumber() const; /** Allows to check if a reference points to an indirect * object. * * A reference is indirect if object number and generation * number are both not equal 0. * * \returns true if this reference is the reference of * an indirect object. */ PODOFO_NOTHROW inline bool IsIndirect() const; private: pdf_objnum m_nObjectNo; pdf_gennum m_nGenerationNo; }; // ----------------------------------------------------- // // ----------------------------------------------------- const PdfReference & PdfReference::operator=( const PdfReference & rhs ) { m_nObjectNo = rhs.m_nObjectNo; m_nGenerationNo = rhs.m_nGenerationNo; return *this; } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfReference::operator<( const PdfReference & rhs ) const { return m_nObjectNo == rhs.m_nObjectNo ? m_nGenerationNo < rhs.m_nGenerationNo : m_nObjectNo < rhs.m_nObjectNo; } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfReference::operator==( const PdfReference & rhs ) const { return ( m_nObjectNo == rhs.m_nObjectNo && m_nGenerationNo == rhs.m_nGenerationNo); } // ----------------------------------------------------- // // ----------------------------------------------------- inline bool PdfReference::operator!=( const PdfReference & rhs ) const { return !this->operator==( rhs ); } // ----------------------------------------------------- // // ----------------------------------------------------- void PdfReference::SetObjectNumber( pdf_objnum o ) { m_nObjectNo = o; } // ----------------------------------------------------- // // ----------------------------------------------------- pdf_objnum PdfReference::ObjectNumber() const { return m_nObjectNo; } // ----------------------------------------------------- // // ----------------------------------------------------- void PdfReference::SetGenerationNumber( pdf_gennum g ) { m_nGenerationNo = g; } // ----------------------------------------------------- // // ----------------------------------------------------- pdf_gennum PdfReference::GenerationNumber() const { return m_nGenerationNo; } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfReference::IsIndirect() const { return !( !m_nObjectNo && !m_nGenerationNo ); } }; #endif // _PDF_REFERENCE_H_ podofo-0.9.3/src/base/PdfReference.cpp0000664000175000017500000000612312344436402017422 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2006 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfReference.h" #include "PdfOutputDevice.h" #include "PdfDefinesPrivate.h" #include namespace PoDoFo { void PdfReference::Write( PdfOutputDevice* pDevice, EPdfWriteMode eWriteMode, const PdfEncrypt* ) const { if( (eWriteMode & ePdfWriteMode_Compact) == ePdfWriteMode_Compact ) { // Write space before the reference pDevice->Print( " %i %hi R", m_nObjectNo, m_nGenerationNo ); } else { pDevice->Print( "%i %hi R", m_nObjectNo, m_nGenerationNo ); } } const std::string PdfReference::ToString() const { std::ostringstream out; out << m_nObjectNo << " " << m_nGenerationNo << " R"; return out.str(); } }; podofo-0.9.3/src/base/PdfObject.cpp0000664000175000017500000002340412344436402016733 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2005 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfObject.h" #include "PdfArray.h" #include "PdfDictionary.h" #include "PdfEncrypt.h" #include "PdfFileStream.h" #include "PdfOutputDevice.h" #include "PdfStream.h" #include "PdfVariant.h" #include "PdfDefinesPrivate.h" #include #include #include #include using namespace std; namespace PoDoFo { PdfObject::PdfObject() : PdfVariant( PdfDictionary() ) { InitPdfObject(); } PdfObject::PdfObject( const PdfReference & rRef, const char* pszType ) : PdfVariant( PdfDictionary() ), m_reference( rRef ) { InitPdfObject(); if( pszType ) this->GetDictionary().AddKey( PdfName::KeyType, PdfName( pszType ) ); } PdfObject::PdfObject( const PdfReference & rRef, const PdfVariant & rVariant ) : PdfVariant( rVariant ), m_reference( rRef ) { InitPdfObject(); } PdfObject::PdfObject( const PdfVariant & var ) : PdfVariant( var ) { InitPdfObject(); } PdfObject::PdfObject( bool b ) : PdfVariant( b ) { InitPdfObject(); } PdfObject::PdfObject( pdf_int64 l ) : PdfVariant( l ) { InitPdfObject(); } PdfObject::PdfObject( double d ) : PdfVariant( d ) { InitPdfObject(); } PdfObject::PdfObject( const PdfString & rsString ) : PdfVariant( rsString ) { InitPdfObject(); } PdfObject::PdfObject( const PdfName & rName ) : PdfVariant( rName ) { InitPdfObject(); } PdfObject::PdfObject( const PdfReference & rRef ) : PdfVariant( rRef ) { InitPdfObject(); } PdfObject::PdfObject( const PdfArray & tList ) : PdfVariant( tList ) { InitPdfObject(); } PdfObject::PdfObject( const PdfDictionary & rDict ) : PdfVariant( rDict ) { InitPdfObject(); } PdfObject::PdfObject( const PdfObject & rhs ) : PdfVariant( rhs ), m_reference( rhs.m_reference ) { InitPdfObject(); // DS: If you change this code, also change the assignment operator. // As the copy constructor is called very often, // it contains a copy of parts of the assignment code to be faster. const_cast(&rhs)->DelayedStreamLoad(); m_bDelayedStreamLoadDone = rhs.DelayedStreamLoadDone(); if( rhs.m_pStream ) m_pStream = m_pOwner->CreateStream( *(rhs.m_pStream) ); #if defined(PODOFO_EXTRA_CHECKS) // Must've been demand loaded or already done assert(DelayedLoadDone()); assert(DelayedStreamLoadDone()); #endif } PdfObject::~PdfObject() { delete m_pStream; m_pStream = NULL; } void PdfObject::InitPdfObject() { m_pStream = NULL; m_pOwner = NULL; m_bDelayedStreamLoadDone = true; #if defined(PODOFO_EXTRA_CHECKS) m_bDelayedStreamLoadInProgress = false; #endif } void PdfObject::WriteObject( PdfOutputDevice* pDevice, EPdfWriteMode eWriteMode, PdfEncrypt* pEncrypt, const PdfName & keyStop ) const { DelayedStreamLoad(); if( !pDevice ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } if( m_reference.IsIndirect() ) { if( (eWriteMode & ePdfWriteMode_Clean) == ePdfWriteMode_Clean ) { pDevice->Print( "%i %i obj\n", m_reference.ObjectNumber(), m_reference.GenerationNumber() ); } else { pDevice->Print( "%i %i obj", m_reference.ObjectNumber(), m_reference.GenerationNumber() ); } } if( pEncrypt ) { pEncrypt->SetCurrentReference( m_reference ); } if( pEncrypt && m_pStream ) { // Set length if it is a key PdfFileStream* pFileStream = dynamic_cast(m_pStream); if( !pFileStream ) { // PdfFileStream handles encryption internally pdf_long lLength = pEncrypt->CalculateStreamLength(m_pStream->GetLength()); PdfVariant varLength = static_cast(lLength); *(const_cast(this)->GetIndirectKey( PdfName::KeyLength )) = varLength; } } this->Write( pDevice, eWriteMode, pEncrypt, keyStop ); pDevice->Print( "\n" ); if( m_pStream ) { m_pStream->Write( pDevice, pEncrypt ); } if( m_reference.IsIndirect() ) { pDevice->Print( "endobj\n" ); } } PdfObject* PdfObject::GetIndirectKey( const PdfName & key ) const { const PdfObject* pObj = NULL; if( this->IsDictionary() && this->GetDictionary().HasKey( key ) ) { pObj = this->GetDictionary().GetKey( key ); if( pObj->IsReference() ) { if( !m_pOwner ) { PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidHandle, "Object is a reference but does not have an owner!" ); } pObj = m_pOwner->GetObject( pObj->GetReference() ); } else const_cast(pObj)->SetOwner( GetOwner() );// even directs might want an owner... } // DominikS: TODO Remove const on GetIndirectKey return const_cast(pObj); } pdf_long PdfObject::GetObjectLength( EPdfWriteMode eWriteMode ) { PdfOutputDevice device; this->WriteObject( &device, eWriteMode, NULL ); return device.GetLength(); } PdfStream* PdfObject::GetStream() { DelayedStreamLoad(); return GetStream_NoDL(); } PdfStream* PdfObject::GetStream_NoDL() { if( !m_pStream ) { if ( GetDataType() != ePdfDataType_Dictionary ) { PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidDataType, "Tried to get stream of non-dictionary object"); } if ( !m_reference.IsIndirect() ) { PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidDataType, "Tried to get stream of non-indirect PdfObject"); } if( !m_pOwner ) { PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidHandle, "Tried to create stream on PdfObject lacking owning document/PdfVecObjects" ); } m_pStream = m_pOwner->CreateStream( this ); } SetDirty( true ); return m_pStream; } const PdfStream* PdfObject::GetStream() const { DelayedStreamLoad(); return m_pStream; } void PdfObject::FlateCompressStream() { // TODO: If the stream isn't already in memory, defer loading and compression until first read of the stream to save some memory. DelayedStreamLoad(); /* if( m_pStream ) m_pStream->FlateCompress(); */ } const PdfObject & PdfObject::operator=( const PdfObject & rhs ) { // DS: If you change this code, also change the copy constructor. // As the copy constructor is called very often, // it contains a copy of parts of this code to be faster. delete m_pStream; const_cast(&rhs)->DelayedStreamLoad(); m_reference = rhs.m_reference; m_pOwner = rhs.m_pOwner; PdfVariant::operator=( rhs ); m_bDelayedStreamLoadDone = rhs.DelayedStreamLoadDone(); if( rhs.m_pStream ) m_pStream = m_pOwner->CreateStream( *(rhs.m_pStream) ); #if defined(PODOFO_EXTRA_CHECKS) // Must've been demand loaded or already done assert(DelayedLoadDone()); assert(DelayedStreamLoadDone()); #endif return *this; } pdf_long PdfObject::GetByteOffset( const char* pszKey, EPdfWriteMode eWriteMode ) { PdfOutputDevice device; if( !pszKey ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } if( !this->GetDictionary().HasKey( pszKey ) ) { PODOFO_RAISE_ERROR( ePdfError_InvalidKey ); } this->Write( &device, eWriteMode, NULL, pszKey ); return device.GetLength(); } }; podofo-0.9.3/src/base/PdfDataType.cpp0000664000175000017500000000527612344436402017247 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2006 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfDataType.h" #include "PdfDefinesPrivate.h" namespace PoDoFo { PdfDataType::PdfDataType() : m_bImmutable(false) { } PdfDataType::~PdfDataType() { } bool PdfDataType::IsDirty() const { return false; } void PdfDataType::SetDirty( bool ) { // Ignore } }; podofo-0.9.3/src/base/PdfCompilerCompatPrivate.h0000664000175000017500000001515711641323033021443 0ustar dominikdominik#ifndef _PDF_COMPILERCOMPAT_PRIVATE_H #define _PDF_COMPILERCOMPAT_PRIVATE_H #ifndef _PDF_DEFINES_PRIVATE_H_ #error Include PdfDefinesPrivate.h instead #endif #if defined(__BORLANDC__) || defined( __TURBOC__) // Borland Turbo C has a broken "" but provides a usable "math.h" // and it needs a bunch of other includes # include # include # include # include # include #else // We can use the ISO C++ headers with other compilers # include # include # include # include # include #endif #if PODOFO_HAVE_WINSOCK2_H # ifdef PODOFO_MULTI_THREAD # if defined(_WIN32) || defined(_WIN64) # ifndef _WIN32_WINNT # define _WIN32_WINNT 0x0400 // Make the TryEnterCriticalSection method available # include // This will include windows.h, so we have to define _WIN32_WINNT // if we want to use threads later. # undef _WIN32_WINNT # else # include # endif // _WIN32_WINNT # endif // _WIN32 || _WIN64 # else # include # endif // PODOFO_MULTI_THREAD #endif #if PODOFO_HAVE_ARPA_INET_H # include #endif #ifdef PODOFO_MULTI_THREAD # if defined(_WIN32) || defined(_WIN64) # if defined(_MSC_VER) && !defined(_WINSOCK2API_) # error must be included before , config problem? # endif # ifndef _WIN32_WINNT # define _WIN32_WINNT 0x0400 // Make the TryEnterCriticalSection method available # include # undef _WIN32_WINNT # else # include # endif // _WIN32_WINNT # else # include # endif // _WIN32 #endif // PODOFO_MULTI_THREAD #if defined(_WIN32) || defined(_WIN64) # if defined(GetObject) # undef GetObject // Horrible windows.h macro definition that breaks things # endif # if defined(DrawText) # undef DrawText // Horrible windows.h macro definition that breaks things # endif # if defined(CreateFont) # undef CreateFont # endif #endif namespace PoDoFo { namespace compat { // Case-insensitive string compare functions aren't very portable, and we must account // for several flavours. inline static int strcasecmp( const char * s1, const char * s2) { #if defined(_WIN32) || defined (_WIN64) # if defined(_MSC_VER) // MSVC++ return ::_stricmp(s1, s2); # else return ::stricmp(s1, s2); # endif #else // POSIX.1-2001 return ::strcasecmp(s1, s2); #endif } inline static int strncasecmp( const char * s1, const char * s2, size_t n) { #if defined(_WIN32) || defined(_WIN64) # if defined(_MSC_VER) // MSVC++ return ::_strnicmp(s1, s2, n); # else return ::strnicmp(s1, s2, n); # endif #else // POSIX.1-2001 return ::strncasecmp(s1, s2, n); #endif } inline static double logb(double x) { #if defined(_WIN32) || defined(_WIN64) return ::log(x); #else return ::logb(x); #endif } /* * We define inline wrappers for htons and friends here so that * any issues with integer types can be contained to just this * source file. * * These functions are defined to do NOTHING when * host byte order == network byte order (ie: on big endian hosts) * so you do NOT need to #ifdef them. They'll be inlined and * then optimized out with any sane compiler and C library. */ inline static pdf_uint32 podofo_ntohl(pdf_uint32 i) { #if defined(_WIN32) && defined(_MSC_VER) return (pdf_uint32)( ntohl( i ) ); #else return static_cast( ntohl( i ) ); #endif // _WIN32 } inline static pdf_uint16 podofo_ntohs(pdf_uint16 i) { #if defined(_WIN32) && defined(_MSC_VER) return (pdf_uint16)( ntohs( i ) ); #else return static_cast( ntohs( i ) ); #endif // _WIN32 } inline static pdf_uint32 podofo_htonl(pdf_uint32 i) { #if defined(_WIN32) && defined(_MSC_VER) return (pdf_uint32)( htonl( i ) ); #else return static_cast( htonl( i ) ); #endif // _WIN32 } inline static pdf_uint16 podofo_htons(pdf_uint16 i) { #if defined(_WIN32) && defined(_MSC_VER) return (pdf_uint16)( htons( i ) ); #else return static_cast( htons( i ) ); #endif // _WIN32 } };}; // end namespace PoDoFo::compat /* * This is needed to enable compilation with VC++ on Windows, which likes to prefix * many functions with underscores. * * TODO: These should probably be inline wrappers instead, and we need to consolidate * hacks from the rest of the code where other _underscore_prefixed_names are checked * for here. */ #ifdef _MSC_VER #define snprintf _snprintf #define vsnprintf _vsnprintf #endif #if defined(_WIN64) #define fseeko _fseeki64 #define ftello _ftelli64 #else #define fseeko fseek #define ftello ftell #endif /** * \def PODOFO_UNUSED( x ) * Make a certain variable to be unused * in the code, without getting a compiler * warning. */ #ifndef _WIN32 template inline void podofo_unused(T &t) { (void)t; } #define PODOFO_UNUSED( x ) podofo_unused( x ); #else #define PODOFO_UNUSED( x ) (void)x; #endif // _WIN32 // OC 17.08.2010: Activate showing the correct source for Memory Leak Detection in Visual Studio: // See: looking for _AFX_NO_DEBUG_CRT #ifdef _MSC_VER #if defined(_DEBUG) && defined(DEFINE_NEW_DEBUG_NEW) // fuer crtdbg.h und malloc.h #define _CRTDBG_MAP_ALLOC #include #include void* operator new(size_t ai_NewSize, const char* ac_File_, int ai_Line); void operator delete(void* av_Ptr_, const char* ac_File_, int ai_Line); #define DEBUG_NEW new(__FILE__, __LINE__) #define new DEBUG_NEW // doesnt work: // // _NEW_CRT is defined in // // #define new _NEW_CRT #endif // _DEBUG #endif // _MSC_VER /** * \page PoDoFo PdfCompilerCompatPrivate Header * * PdfCompilerCompatPrivate.h gathers up nastyness required for various * compiler compatibility into a central place. All compiler-specific defines, * wrappers, and the like should be included here and (if necessary) in * PdfCompilerCompatPrivate.cpp. If the must be visible to library users * they're put in PdfCompilerCompat.{cpp,h} instead. * * PdfCompilerCompatPrivate.h is private to PoDoFo's build process. It is not * used by library clients, the tools, or the unit tests. It is not installed * with PoDoFo and must never be visible in the public headers. * * Include PdfCompilerCompatPrivate.h in your .cpp sources, preferably after * including other PoDoFo headers. * * Please NEVER use symbols from this header or the PoDoFo::compat namespace in * a "using" directive. Always explicitly reference names so it's clear that * you're pulling them from the compat cruft. */ #endif podofo-0.9.3/src/base/PdfRefCountedBuffer.h0000664000175000017500000002653412344436402020371 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2006 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_REF_COUNTED_BUFFER_H_ #define _PDF_REF_COUNTED_BUFFER_H_ #include "PdfDefines.h" namespace PoDoFo { /** * A reference counted buffer object * which is deleted as soon as the last * object having access to it is delteted. * * The attached memory object can be resized. */ class PODOFO_API PdfRefCountedBuffer { public: /** Created an empty reference counted buffer * The buffer will be initialize to NULL */ inline PdfRefCountedBuffer(); /** Created an reference counted buffer and use an exiting buffer * The buffer will be owned by this object. * * \param pBuffer a pointer to an allocated buffer * \param lSize size of the allocated buffer * * \see SetTakePossesion */ PdfRefCountedBuffer( char* pBuffer, size_t lSize ); /** Create a new PdfRefCountedBuffer. * \param lSize buffer size */ inline PdfRefCountedBuffer( size_t lSize ); /** Copy an existing PdfRefCountedBuffer and increase * the reference count * \param rhs the PdfRefCountedBuffer to copy */ inline PdfRefCountedBuffer( const PdfRefCountedBuffer & rhs ); /** Decrease the reference count and delete the buffer * if this is the last owner */ inline ~PdfRefCountedBuffer(); /* !Non-Doxygen comment because constructor is disabled! * Append to the current buffers contents. * If the buffer is referenced by another PdfRefCountedBuffer * this object detaches from this buffer and allocates an own * buffer. Otherwise the internal buffer is used and resized if * necessary. * * \param pszString a buffer * \param lLen length of the buffer */ //void Append( const char* pszString, long lLen ); /** Get access to the buffer * \returns the buffer */ inline char* GetBuffer() const; /** Return the buffer size. * * \returns the buffer size */ inline size_t GetSize() const; /** Resize the buffer to hold at least * lSize bytes. * * \param lSize the size of bytes the buffer can at least hold * * If the buffer is larger no operation is performed. */ inline void Resize( size_t lSize ); /** Copy an existing PdfRefCountedBuffer and increase * the reference count * \param rhs the PdfRefCountedBuffer to copy * \returns the copied object */ const PdfRefCountedBuffer & operator=( const PdfRefCountedBuffer & rhs ); /** If the PdfRefCountedBuffer has no possesion on its buffer, * it won't delete the buffer. By default the buffer is owned * and deleted by the PdfRefCountedBuffer object. * * \param bTakePossession if false the buffer will not be deleted. */ inline void SetTakePossesion( bool bTakePossession ); /** * \returns true if the buffer is owned by the PdfRefCountedBuffer * and is deleted along with it. */ inline bool TakePossesion() const; /** Compare to buffers. * \param rhs compare to this buffer * \returns true if both buffers contain the same contents */ bool operator==( const PdfRefCountedBuffer & rhs ) const; /** Compare to buffers. * \param rhs compare to this buffer * \returns true if this buffer is lexically littler than rhs */ bool operator<( const PdfRefCountedBuffer & rhs ) const; /** Compare to buffers. * \param rhs compare to this buffer * \returns true if this buffer is lexically greater than rhs */ bool operator>( const PdfRefCountedBuffer & rhs ) const; private: /** * Indicate that the buffer is no longer being used, freeing it if there * are no further users. The buffer becomes inaccessible to this * PdfRefCountedBuffer in either case. */ inline void DerefBuffer(); /** * Free a buffer if the refcount is zero. Internal method used by DerefBuffer. */ void FreeBuffer(); /** Detach from a shared buffer or do nothing if we are the only * one referencing the buffer. * * Call this function before any operation modifiying the buffer! * * \param lLen an additional parameter specifiying extra bytes * to be allocated to optimize allocations of a new buffer. */ inline void Detach( size_t lExtraLen = 0 ); /** * Called by Detach() to do the work if action is actually required. * \see Detach */ void ReallyDetach( size_t lExtraLen ); /** * Do the hard work of resizing the buffer if it turns out not to already be big enough. * \see Resize */ void ReallyResize( size_t lSize ); private: struct TRefCountedBuffer { enum { INTERNAL_BUFSIZE = 32 }; // Convenience inline for buffer switching PODOFO_NOTHROW inline char * GetRealBuffer() { return m_bOnHeap? m_pHeapBuffer : &(m_sInternalBuffer[0]); } // size in bytes of the buffer. If and only if this is strictly >INTERNAL_BUFSIZE, // this buffer is on the heap in memory pointed to by m_pHeapBuffer . If it is <=INTERNAL_BUFSIZE, // the buffer is in the in-object buffer m_sInternalBuffer. size_t m_lBufferSize; // Size in bytes of m_pBuffer that should be reported to clients. We // over-allocate on the heap for efficiency and have a minimum 32 byte // size, but this extra should NEVER be visible to a client. size_t m_lVisibleSize; long m_lRefCount; char* m_pHeapBuffer; char m_sInternalBuffer[INTERNAL_BUFSIZE]; bool m_bPossesion; // Are we using the heap-allocated buffer in place of our small internal one? bool m_bOnHeap; }; TRefCountedBuffer* m_pBuffer; }; // ----------------------------------------------------- // // ----------------------------------------------------- PdfRefCountedBuffer::PdfRefCountedBuffer() : m_pBuffer( NULL ) { } // ----------------------------------------------------- // // ----------------------------------------------------- PdfRefCountedBuffer::PdfRefCountedBuffer( size_t lSize ) : m_pBuffer( NULL ) { this->Resize( lSize ); } // ----------------------------------------------------- // // ----------------------------------------------------- // We define the copy ctor separately to the assignment // operator since it's a *LOT* faster this way. PdfRefCountedBuffer::PdfRefCountedBuffer( const PdfRefCountedBuffer & rhs ) : m_pBuffer( rhs.m_pBuffer ) { if (m_pBuffer) ++(m_pBuffer->m_lRefCount); } // ----------------------------------------------------- // // ----------------------------------------------------- PdfRefCountedBuffer::~PdfRefCountedBuffer() { DerefBuffer(); } // ----------------------------------------------------- // // ----------------------------------------------------- inline char* PdfRefCountedBuffer::GetBuffer() const { if (!m_pBuffer) return NULL; return m_pBuffer->GetRealBuffer(); } // ----------------------------------------------------- // // ----------------------------------------------------- inline size_t PdfRefCountedBuffer::GetSize() const { return m_pBuffer ? m_pBuffer->m_lVisibleSize : 0; } // ----------------------------------------------------- // // ----------------------------------------------------- inline void PdfRefCountedBuffer::SetTakePossesion( bool bTakePossession ) { if( m_pBuffer ) m_pBuffer->m_bPossesion = bTakePossession; } // ----------------------------------------------------- // // ----------------------------------------------------- inline bool PdfRefCountedBuffer::TakePossesion() const { return m_pBuffer ? m_pBuffer->m_bPossesion : false; } // ----------------------------------------------------- // // ----------------------------------------------------- inline void PdfRefCountedBuffer::Detach( size_t lExtraLen ) { if (m_pBuffer && m_pBuffer->m_lRefCount > 1L) ReallyDetach(lExtraLen); } // ----------------------------------------------------- // // ----------------------------------------------------- inline void PdfRefCountedBuffer::Resize( size_t lSize ) { if (m_pBuffer && m_pBuffer->m_lRefCount == 1L && static_cast(m_pBuffer->m_lBufferSize) >= lSize) { // We have a solely owned buffer the right size already; no need to // waste any time detaching or resizing it. Just let the client see // more of it (or less if they're shrinking their view). m_pBuffer->m_lVisibleSize = lSize; } else { ReallyResize( lSize ); } } // ----------------------------------------------------- // // ----------------------------------------------------- inline void PdfRefCountedBuffer::DerefBuffer() { if ( m_pBuffer && !(--m_pBuffer->m_lRefCount) ) FreeBuffer(); // Whether or not it still exists, we no longer have anything to do with // the buffer we just released our claim on. m_pBuffer = NULL; } }; #endif // _PDF_REF_COUNTED_BUFFER_H_ podofo-0.9.3/src/base/PdfEncrypt.h0000664000175000017500000010311112344436402016610 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2006 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDFENCRYPT_H_ #define _PDFENCRYPT_H_ #include "PdfDefines.h" #include "PdfString.h" #include "PdfReference.h" namespace PoDoFo { class PdfDictionary; class PdfInputStream; class PdfObject; class PdfOutputStream; class AESCryptoEngine; class RC4CryptoEngine; /// Class representing PDF encryption methods. (For internal use only) /// Based on code from Ulrich Telle: http://wxcode.sourceforge.net/components/wxpdfdoc/ /// Original Copyright header: /////////////////////////////////////////////////////////////////////////////// // Name: pdfencrypt.h // Purpose: // Author: Ulrich Telle // Modified by: // Created: 2005-08-16 // Copyright: (c) Ulrich Telle // Licence: wxWindows licence /////////////////////////////////////////////////////////////////////////////// /** A class that is used to encrypt a PDF file and * set document permisions on the PDF file. * * As a user of this class, you have only to instanciate a * object of this class and pass it to PdfWriter, PdfMemDocument, * PdfStreamedDocument or PdfImmediateWriter. * You do not have to call any other method of this class. The above * classes know how to handle encryption using Pdfencrypt. * */ class PODOFO_API PdfEncrypt { public: /** A enum specifying a valid keylength for a PDF encryption key. * Keys must be in the range 40 to 128 bit and have to be a * multiple of 8. * * Adobe Reader supports only keys with 40, 128 or 256 bits! */ typedef enum { ePdfKeyLength_40 = 40, ePdfKeyLength_56 = 56, ePdfKeyLength_80 = 80, ePdfKeyLength_96 = 96, ePdfKeyLength_128 = 128 #ifdef PODOFO_HAVE_LIBIDN ,ePdfKeyLength_256 = 256 #endif //PODOFO_HAVE_LIBIDN } EPdfKeyLength; /** Set user permissions/restrictions on a document */ typedef enum { ePdfPermissions_Print = 0x00000004, ///< Allow printing the document ePdfPermissions_Edit = 0x00000008, ///< Allow modifying the document besides annotations, form fields or chaning pages ePdfPermissions_Copy = 0x00000010, ///< Allow text and graphic extraction ePdfPermissions_EditNotes = 0x00000020, ///< Add or modify text annoations or form fields (if ePdfPermissions_Edit is set also allow to create interactive form fields including signature) ePdfPermissions_FillAndSign = 0x00000100, ///< Fill in existing form or signature fields ePdfPermissions_Accessible = 0x00000200, ///< Extract text and graphics to support user with disabillities ePdfPermissions_DocAssembly = 0x00000400, ///< Assemble the document: insert, create, rotate delete pages or add bookmarks ePdfPermissions_HighPrint = 0x00000800 ///< Print a high resolution version of the document } EPdfPermissions; /** * The encryption algorithm. */ typedef enum { ePdfEncryptAlgorithm_RC4V1 = 1, ///< RC4 Version 1 encryption using a 40bit key ePdfEncryptAlgorithm_RC4V2 = 2, ///< RC4 Version 2 encryption using a key with 40-128bit ePdfEncryptAlgorithm_AESV2 = 4 ///< AES encryption with a 128 bit key (PDF1.6) #ifdef PODOFO_HAVE_LIBIDN ,ePdfEncryptAlgorithm_AESV3 = 8 ///< AES encryption with a 256 bit key (PDF1.7 extension 3) - Support added by P. Zent #endif //PODOFO_HAVE_LIBIDN } EPdfEncryptAlgorithm; /** Create a PdfEncrypt object which can be used to encrypt a PDF file. * * \param userPassword the user password (if empty the user does not have * to enter a password to open the document) * \param ownerPassword the owner password * \param protection several EPdfPermissions values or'ed together to set * the users permissions for this document * \param eAlgorithm the revision of the encryption algorithm to be used * \param eKeyLength the length of the encryption key ranging from 40 to 128 bits * (only used if eAlgorithm == ePdfEncryptAlgorithm_RC4V2) * * \see GenerateEncryptionKey with the documentID to generate the real * encryption key using this information */ static PdfEncrypt * CreatePdfEncrypt( const std::string & userPassword, const std::string & ownerPassword, int protection = ePdfPermissions_Print | ePdfPermissions_Edit | ePdfPermissions_Copy | ePdfPermissions_EditNotes | ePdfPermissions_FillAndSign | ePdfPermissions_Accessible | ePdfPermissions_DocAssembly | ePdfPermissions_HighPrint, EPdfEncryptAlgorithm eAlgorithm = ePdfEncryptAlgorithm_RC4V1, EPdfKeyLength eKeyLength = ePdfKeyLength_40 ); /** Initialize a PdfEncrypt object from an encryption dictionary in a PDF file. * * This is required for encrypting a PDF file, but handled internally in PdfParser * for you. * * Will use only encrypting algorithms that are enabled. * * \param pObject a PDF encryption dictionary * * \see GetEnabledEncryptionAlgorithms */ static PdfEncrypt * CreatePdfEncrypt( const PdfObject* pObject ); /** Copy constructor * * \param rhs another PdfEncrypt object which is copied */ static PdfEncrypt * CreatePdfEncrypt( const PdfEncrypt & rhs ); /** * Retrieve the list of encryption algorithms that are used * when loading a PDF document. * * By default all alogrithms are enabled. * * \see IsEncryptionEnabled * \see SetEnabledEncryptionAlgorithms * * \return an or'ed together list of all enabled encryption algorithms */ static int GetEnabledEncryptionAlgorithms(); /** * Specify the list of encryption algorithms that should be used by PoDoFo * when loading a PDF document. * * This can be used to disable for example AES encryption/decryption * which is unstable in certain cases. * * \see GetEnabledEncryptionAlgorithms * \see IsEncryptionEnabled */ static void SetEnabledEncryptionAlgorithms(int nEncryptionAlgorithms); /** * Test if a certain encryption algorithm is enabled for loading PDF documents. * * \returns ture if the encryption algorithm is enabled * \see GetEnabledEncryptionAlgorithms * \see SetEnabledEncryptionAlgorithms */ static bool IsEncryptionEnabled(EPdfEncryptAlgorithm eAlgorithm); /** Destruct the PdfEncrypt object */ virtual ~PdfEncrypt() = 0; /** Generate encryption key from user and owner passwords and protection key * * \param documentId the documentId of the current document */ virtual void GenerateEncryptionKey(const PdfString & documentId) = 0; /** Fill all keys into a encryption dictionary. * This dictionary is usually added to the PDF files trailer * under the /Encryption key. * * \param rDictionary an empty dictionary which is filled with information about * the used encryption algorithm */ virtual void CreateEncryptionDictionary( PdfDictionary & rDictionary ) const = 0; /** Create a PdfOutputStream that encrypts all data written to * it using the current settings of the PdfEncrypt object. * * Warning: Currently only RC4 based encryption is supported using output streams! * * \param pOutputStream the created PdfOutputStream writes all encrypted * data to this output stream. * * \returns a PdfOutputStream that encryts all data. */ virtual PdfOutputStream* CreateEncryptionOutputStream( PdfOutputStream* pOutputStream ) = 0; /** Create a PdfInputStream that decrypts all data read from * it using the current settings of the PdfEncrypt object. * * Warning: Currently only RC4 based encryption is supported using output streams! * * \param pInputStream the created PdfInputStream reads all decrypted * data to this input stream. * * \returns a PdfInputStream that decrypts all data. */ virtual PdfInputStream* CreateEncryptionInputStream( PdfInputStream* pInputStream ) = 0; /** * Tries to authenticate a user using either the user or owner password * * \param password owner or user password * \param documentId the documentId of the PDF file * * \returns true if either the owner or user password matches password */ virtual bool Authenticate( const std::string & password, const PdfString & documentId ) = 0; /** Get the encryption algorithm of this object. * \returns the EPdfEncryptAlgorithm of this object */ inline EPdfEncryptAlgorithm GetEncryptAlgorithm() const; /** Checks if printing this document is allowed. * Every PDF consuming applications has to adhere this value! * * \returns true if you are allowed to print this document * * \see PdfEncrypt to set own document permissions. */ inline bool IsPrintAllowed() const; /** Checks if modifiying this document (besides annotations, form fields or changing pages) is allowed. * Every PDF consuming applications has to adhere this value! * * \returns true if you are allowed to modfiy this document * * \see PdfEncrypt to set own document permissions. */ inline bool IsEditAllowed() const; /** Checks if text and graphics extraction is allowed. * Every PDF consuming applications has to adhere this value! * * \returns true if you are allowed to extract text and graphics from this document * * \see PdfEncrypt to set own document permissions. */ inline bool IsCopyAllowed() const; /** Checks if it is allowed to add or modify annotations or form fields * Every PDF consuming applications has to adhere this value! * * \returns true if you are allowed to add or modify annotations or form fields * * \see PdfEncrypt to set own document permissions. */ inline bool IsEditNotesAllowed() const; /** Checks if it is allowed to fill in existing form or signature fields * Every PDF consuming applications has to adhere this value! * * \returns true if you are allowed to fill in existing form or signature fields * * \see PdfEncrypt to set own document permissions. */ inline bool IsFillAndSignAllowed() const; /** Checks if it is allowed to extract text and graphics to support users with disabillities * Every PDF consuming applications has to adhere this value! * * \returns true if you are allowed to extract text and graphics to support users with disabillities * * \see PdfEncrypt to set own document permissions. */ inline bool IsAccessibilityAllowed() const; /** Checks if it is allowed to insert, create, rotate, delete pages or add bookmarks * Every PDF consuming applications has to adhere this value! * * \returns true if you are allowed to insert, create, rotate, delete pages or add bookmarks * * \see PdfEncrypt to set own document permissions. */ inline bool IsDocAssemblyAllowed() const; /** Checks if it is allowed to print a high quality version of this document * Every PDF consuming applications has to adhere this value! * * \returns true if you are allowed to print a high quality version of this document * * \see PdfEncrypt to set own document permissions. */ inline bool IsHighPrintAllowed() const; /// Get the U object value (user) const unsigned char* GetUValue() const { return m_uValue; } /// Get the O object value (owner) const unsigned char* GetOValue() const { return m_oValue; } /// Get the encryption key value (owner) const unsigned char* GetEncryptionKey() const { return m_encryptionKey; } /// Get the P object value (protection) pdf_int32 GetPValue() const { return m_pValue; } /// Get the revision number of the encryption method int GetRevision() const { return m_rValue; } /// Get the key length of the encryption key in bits int GetKeyLength() const { return m_keyLength*8; } /// Is metadata encrypted bool IsMetadataEncrypted() const { return m_bEncryptMetadata; } /// Encrypt a wxString //void Encrypt( std::string & str, pdf_long inputLen ) const; /// Encrypt a character string // inStr: the input buffer // inLen: length of the input buffer // outStr: the output buffer // outLen: length of the output buffer virtual void Encrypt(const unsigned char* inStr, pdf_long inLen, unsigned char* outStr, pdf_long outLen) const = 0; /// Decrypt a character string // inStr: the input buffer // inLen: length of the input buffer // outStr: the output buffer // outLen: length of the output buffer virtual void Decrypt(const unsigned char* inStr, pdf_long inLen, unsigned char* outStr, pdf_long &outLen) const = 0; /// Calculate stream size virtual pdf_long CalculateStreamLength(pdf_long length) const = 0; /// Calculate stream offset virtual pdf_long CalculateStreamOffset() const = 0; /** Set the reference of the object that is currently encrypted. * * This value will be used in following calls of Encrypt * to encrypt the object. * * \see Encrypt */ inline void SetCurrentReference( const PdfReference & rRef ); protected: PdfEncrypt() : m_bEncryptMetadata(true) {}; PdfEncrypt( const PdfEncrypt & rhs ); /// Check two keys for equality bool CheckKey(unsigned char key1[32], unsigned char key2[32]); EPdfEncryptAlgorithm m_eAlgorithm; ///< The used encryption algorithm int m_keyLength; ///< Length of encryption key int m_rValue; ///< Revision pdf_int32 m_pValue; ///< P entry in pdf document EPdfKeyLength m_eKeyLength; ///< The key length std::string m_userPass; ///< User password std::string m_ownerPass; ///< Owner password unsigned char m_uValue[48]; ///< U entry in pdf document unsigned char m_oValue[48]; ///< O entry in pdf document unsigned char m_encryptionKey[32]; ///< Encryption key PdfReference m_curReference; ///< Reference of the current PdfObject std::string m_documentId; ///< DocumentID of the current document bool m_bEncryptMetadata; ///< Is metadata encrypted private: static int s_nEnabledEncryptionAlgorithms; ///< Or'ed int containing the enabled encryption algorithms }; #ifdef PODOFO_HAVE_LIBIDN /** A pure virtual class that is used to encrypt a PDF file (AES-256) * This class is the base for classes that implement algorithms based on SHA hashes * * Client code is working only with PdfEncrypt class and knows nothing * about PdfEncrypt*, it is created through CreatePdfEncrypt factory method * */ class PdfEncryptSHABase : public PdfEncrypt { public: PdfEncryptSHABase() {}; // copy constructor PdfEncryptSHABase(const PdfEncrypt &rhs); /* * Destruct PdfEncryptAESV2 object */ virtual ~PdfEncryptSHABase() {}; virtual PdfInputStream* CreateEncryptionInputStream( PdfInputStream* pInputStream ) = 0; virtual PdfOutputStream* CreateEncryptionOutputStream( PdfOutputStream* pOutputStream ) = 0; virtual void CreateEncryptionDictionary( PdfDictionary & rDictionary ) const; virtual bool Authenticate( const std::string & password, const PdfString & documentId ) = 0; /// Encrypt a character string virtual void Encrypt(const unsigned char* inStr, pdf_long inLen, unsigned char* outStr, pdf_long outLen) const = 0; virtual void GenerateEncryptionKey(const PdfString & documentId) = 0; /// Get the UE object value (user) const unsigned char* GetUEValue() const { return m_ueValue; } /// Get the OE object value (owner) const unsigned char* GetOEValue() const { return m_oeValue; } /// Get the Perms object value (encrypted protection) const unsigned char* GetPermsValue() const { return m_permsValue; } virtual pdf_long CalculateStreamOffset() const = 0; virtual pdf_long CalculateStreamLength(pdf_long length) const = 0; bool Authenticate(const std::string & documentID, const std::string & password, const std::string & uValue, const std::string & ueValue, const std::string & oValue, const std::string & oeValue, int pValue, const std::string & permsValue, int lengthValue, int rValue); protected: /// Generate initial vector virtual void GenerateInitialVector(unsigned char iv[16]); /// Compute encryption key to be used with AES-256 void ComputeEncryptionKey(); /// Generate the U and UE entries void ComputeUserKey(const unsigned char * userpswd, int len); /// Generate the O and OE entries void ComputeOwnerKey(const unsigned char * userpswd, int len); /// Preprocess password for use in EAS-256 Algorithm /// outBuf needs to be at least 127 bytes long void PreprocessPassword( const std::string &password, unsigned char* outBuf, int &len); unsigned char m_ueValue[32]; ///< UE entry in pdf document unsigned char m_oeValue[32]; ///< OE entry in pdf document unsigned char m_permsValue[16]; ///< Perms entry in pdf document }; /** A pure virtual class that is used to encrypt a PDF file (RC4, AES-128) * This class is the base for classes that implement algorithms based on MD5 hashes * * Client code is working only with PdfEncrypt class and knows nothing * about PdfEncrypt*, it is created through CreatePdfEncrypt factory method * */ #endif // PODOFO_HAVE_LIBIDN /** A pure virtual class that is used to encrypt a PDF file (AES-128/256) * This class is the base for classes that implement algorithms based on AES * * Client code is working only with PdfEncrypt class and knows nothing * about PdfEncrypt*, it is created through CreatePdfEncrypt factory method * */ class PdfEncryptAESBase { public: ~PdfEncryptAESBase(); protected: PdfEncryptAESBase(); void BaseDecrypt(const unsigned char* key, int keylen, const unsigned char* iv, const unsigned char* textin, pdf_long textlen, unsigned char* textout, pdf_long &textoutlen); void BaseEncrypt(const unsigned char* key, int keylen, const unsigned char* iv, const unsigned char* textin, pdf_long textlen, unsigned char* textout, pdf_long textoutlen); AESCryptoEngine* m_aes; ///< AES encryptor }; /** A pure virtual class that is used to encrypt a PDF file (RC4-40..128) * This class is the base for classes that implement algorithms based on RC4 * * Client code is working only with PdfEncrypt class and knows nothing * about PdfEncrypt*, it is created through CreatePdfEncrypt factory method * */ class PdfEncryptRC4Base { public: ~PdfEncryptRC4Base(); protected: PdfEncryptRC4Base(); /// AES encryption void RC4(const unsigned char* key, int keylen, const unsigned char* textin, pdf_long textlen, unsigned char* textout, pdf_long textoutlen); RC4CryptoEngine* m_rc4; ///< AES encryptor }; class PdfEncryptMD5Base : public PdfEncrypt, public PdfEncryptRC4Base { public: PdfEncryptMD5Base() {}; // copy constructor PdfEncryptMD5Base(const PdfEncrypt &rhs); /* * Destruct PdfEncryptAESV2 object */ virtual ~PdfEncryptMD5Base() {}; virtual PdfInputStream* CreateEncryptionInputStream( PdfInputStream* pInputStream ) = 0; virtual PdfOutputStream* CreateEncryptionOutputStream( PdfOutputStream* pOutputStream ) = 0; virtual void CreateEncryptionDictionary( PdfDictionary & rDictionary ) const; virtual bool Authenticate( const std::string & password, const PdfString & documentId ) = 0; /// Encrypt a character string virtual void Encrypt(const unsigned char* inStr, pdf_long inLen, unsigned char* outStr, pdf_long outLen) const = 0; virtual void GenerateEncryptionKey(const PdfString & documentId) = 0; /** Create a PdfString of MD5 data generated from a buffer in memory. * \param pBuffer the buffer of which to calculate the MD5 sum * \param nLength the length of the buffer * * \returns an MD5 sum as PdfString */ static PdfString GetMD5String( const unsigned char* pBuffer, int nLength ); virtual pdf_long CalculateStreamOffset() const = 0; virtual pdf_long CalculateStreamLength(pdf_long length) const = 0; /// Calculate the binary MD5 message digest of the given data static void GetMD5Binary(const unsigned char* data, int length, unsigned char* digest); bool Authenticate(const std::string & documentID, const std::string & password, const std::string & uValue, const std::string & oValue, int pValue, int lengthValue, int rValue); protected: /// Generate initial vector virtual void GenerateInitialVector(unsigned char iv[16]); /// Compute owner key void ComputeOwnerKey(unsigned char userPad[32], unsigned char ownerPad[32], int keylength, int revision, bool authenticate, unsigned char ownerKey[32]); /// Pad a password to 32 characters void PadPassword(const std::string& password, unsigned char pswd[32]); /// Compute encryption key and user key void ComputeEncryptionKey(const std::string & documentID, unsigned char userPad[32], unsigned char ownerKey[32], int pValue, int keyLength, int revision, unsigned char userKey[32], bool bEncryptMetadata); /** Create the encryption key for the current object. * * \param objkey pointer to an array of at least MD5_HASHBYTES (=16) bytes length * \param pnKeyLen pointer to an integer where the actual keylength is stored. */ virtual void CreateObjKey( unsigned char objkey[16], int* pnKeyLen ) const; unsigned char m_rc4key[16]; ///< last RC4 key unsigned char m_rc4last[256]; ///< last RC4 state table }; /** A class that is used to encrypt a PDF file (AES-128) * * Client code is working only with PdfEncrypt class and knows nothing * about PdfEncryptAES*, it is created through CreatePdfEncrypt factory method * */ class PdfEncryptAESV2 : public PdfEncryptMD5Base, public PdfEncryptAESBase { public: /* * Constructors of PdfEncryptAESV2 */ PdfEncryptAESV2(PdfString oValue, PdfString uValue, int pValue, bool bEncryptMetadata); PdfEncryptAESV2( const PdfEncrypt & rhs ) : PdfEncryptMD5Base(rhs) {} PdfEncryptAESV2( const std::string & userPassword, const std::string & ownerPassword, int protection = ePdfPermissions_Print | ePdfPermissions_Edit | ePdfPermissions_Copy | ePdfPermissions_EditNotes | ePdfPermissions_FillAndSign | ePdfPermissions_Accessible | ePdfPermissions_DocAssembly | ePdfPermissions_HighPrint ); /* * Destruct PdfEncryptAESV2 object */ virtual ~PdfEncryptAESV2() {}; virtual PdfInputStream* CreateEncryptionInputStream( PdfInputStream* pInputStream ); virtual PdfOutputStream* CreateEncryptionOutputStream( PdfOutputStream* pOutputStream ); virtual bool Authenticate( const std::string & password, const PdfString & documentId ); /// Encrypt a character string virtual void Encrypt(const unsigned char* inStr, pdf_long inLen, unsigned char* outStr, pdf_long outLen) const; virtual void Decrypt(const unsigned char* inStr, pdf_long inLen, unsigned char* outStr, pdf_long &outLen) const; virtual void GenerateEncryptionKey(const PdfString & documentId); virtual pdf_long CalculateStreamOffset() const; virtual pdf_long CalculateStreamLength(pdf_long length) const; }; #ifdef PODOFO_HAVE_LIBIDN /** A class that is used to encrypt a PDF file (AES-256) * * Client code is working only with PdfEncrypt class and knows nothing * about PdfEncryptAES*, it is created through CreatePdfEncrypt factory method * */ class PdfEncryptAESV3 : public PdfEncryptSHABase, public PdfEncryptAESBase { public: /* * Constructors of PdfEncryptAESV3 */ PdfEncryptAESV3(PdfString oValue, PdfString oeValue, PdfString uValue, PdfString ueValue, int pValue, PdfString permsValue); PdfEncryptAESV3( const PdfEncrypt & rhs ) : PdfEncryptSHABase(rhs) {} PdfEncryptAESV3( const std::string & userPassword, const std::string & ownerPassword, int protection = ePdfPermissions_Print | ePdfPermissions_Edit | ePdfPermissions_Copy | ePdfPermissions_EditNotes | ePdfPermissions_FillAndSign | ePdfPermissions_Accessible | ePdfPermissions_DocAssembly | ePdfPermissions_HighPrint ); /* * Destruct PdfEncryptAESV3 object */ virtual ~PdfEncryptAESV3() {}; virtual PdfInputStream* CreateEncryptionInputStream( PdfInputStream* pInputStream ); virtual PdfOutputStream* CreateEncryptionOutputStream( PdfOutputStream* pOutputStream ); virtual bool Authenticate( const std::string & password, const PdfString & documentId ); /// Encrypt a character string virtual void Encrypt(const unsigned char* inStr, pdf_long inLen, unsigned char* outStr, pdf_long outLen) const; virtual void Decrypt(const unsigned char* inStr, pdf_long inLen, unsigned char* outStr, pdf_long &outLen) const; virtual void GenerateEncryptionKey(const PdfString & documentId); virtual pdf_long CalculateStreamOffset() const; virtual pdf_long CalculateStreamLength(pdf_long length) const; }; #endif // PODOFO_HAVE_LIBIDN /** A class that is used to encrypt a PDF file (RC4 40-bit and 128-bit) * * Client code is working only with PdfEncrypt class and knows nothing * about PdfEncryptRC4, it is created through CreatePdfEncrypt factory method * */ class PdfEncryptRC4 : public PdfEncryptMD5Base { public: /* * Constructors of PdfEncryptRC4 objects */ PdfEncryptRC4(PdfString oValue, PdfString uValue, int pValue, int rValue, EPdfEncryptAlgorithm eAlgorithm, long length, bool bEncryptMetadata); PdfEncryptRC4( const PdfEncrypt & rhs ) : PdfEncryptMD5Base(rhs) {} PdfEncryptRC4( const std::string & userPassword, const std::string & ownerPassword, int protection = ePdfPermissions_Print | ePdfPermissions_Edit | ePdfPermissions_Copy | ePdfPermissions_EditNotes | ePdfPermissions_FillAndSign | ePdfPermissions_Accessible | ePdfPermissions_DocAssembly | ePdfPermissions_HighPrint, EPdfEncryptAlgorithm eAlgorithm = ePdfEncryptAlgorithm_RC4V1, EPdfKeyLength eKeyLength = ePdfKeyLength_40 ); /* * Destruct PdfEncryptRC4 object */ virtual ~PdfEncryptRC4() {} virtual bool Authenticate( const std::string & password, const PdfString & documentId ); /// Encrypt a character string virtual void Encrypt(const unsigned char* inStr, pdf_long inLen, unsigned char* outStr, pdf_long outLen) const; virtual void Decrypt(const unsigned char* inStr, pdf_long inLen, unsigned char* outStr, pdf_long &outLen) const; virtual PdfInputStream* CreateEncryptionInputStream( PdfInputStream* pInputStream ); virtual PdfOutputStream* CreateEncryptionOutputStream( PdfOutputStream* pOutputStream ); virtual void GenerateEncryptionKey(const PdfString & documentId); virtual pdf_long CalculateStreamOffset() const; virtual pdf_long CalculateStreamLength(pdf_long length) const; }; // ----------------------------------------------------- // // ----------------------------------------------------- PdfEncrypt::EPdfEncryptAlgorithm PdfEncrypt::GetEncryptAlgorithm() const { return m_eAlgorithm; } // ----------------------------------------------------- // // ----------------------------------------------------- void PdfEncrypt::SetCurrentReference( const PdfReference & rRef ) { m_curReference = rRef; } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfEncrypt::IsPrintAllowed() const { return (m_pValue & ePdfPermissions_Print) == ePdfPermissions_Print; } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfEncrypt::IsEditAllowed() const { return (m_pValue & ePdfPermissions_Edit) == ePdfPermissions_Edit; } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfEncrypt::IsCopyAllowed() const { return (m_pValue & ePdfPermissions_Copy) == ePdfPermissions_Copy; } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfEncrypt::IsEditNotesAllowed() const { return (m_pValue & ePdfPermissions_EditNotes) == ePdfPermissions_EditNotes; } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfEncrypt::IsFillAndSignAllowed() const { return (m_pValue & ePdfPermissions_FillAndSign) == ePdfPermissions_FillAndSign; } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfEncrypt::IsAccessibilityAllowed() const { return (m_pValue & ePdfPermissions_Accessible) == ePdfPermissions_Accessible; } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfEncrypt::IsDocAssemblyAllowed() const { return (m_pValue & ePdfPermissions_DocAssembly) == ePdfPermissions_DocAssembly; } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfEncrypt::IsHighPrintAllowed() const { return (m_pValue & ePdfPermissions_HighPrint) == ePdfPermissions_HighPrint; } } //end namespace PoDoFo #endif podofo-0.9.3/src/base/PdfMemoryManagement.h0000664000175000017500000000637012344436402020442 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2009 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_MEMORY_MANAGEMENT_H_ #define _PDF_MEMORY_MANAGEMENT_H_ #include "PdfDefines.h" #include namespace PoDoFo { /** * Wrapper around malloc of the c-library used by PoDoFo. * * Is used to allocate buffers inside of PoDoFo. */ PODOFO_API void* podofo_malloc( size_t size ); /** * Wrapper around realloc of the c-library used by PoDoFo. */ PODOFO_API void* podofo_realloc( void* buffer, size_t size ); /** * Wrapper around free of the c-library used by PoDoFo. * * Use this to free memory allocated inside of PoDoFo * with podofo_malloc. */ PODOFO_API void podofo_free( void* buffer ); /** * Check during runtime if the current architecture is big- or little-endian. * \returns true if the architecture is little-endian */ PODOFO_API bool podofo_is_little_endian(); }; #endif // _PDF_XREF_STREAM_PARSER_OBJECT_H_ podofo-0.9.3/src/base/PdfArray.h0000664000175000017500000004046712347271543016266 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2006 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_ARRAY_H_ #define _PDF_ARRAY_H_ #ifdef _WIN32 #ifdef _MSC_VER // IC: VS2008 suppress dll warning #pragma warning(disable: 4275) #endif // _MSC_VER #endif // _WIN32 #include "PdfDefines.h" #include "PdfDataType.h" #include "PdfObject.h" namespace PoDoFo { /** This class represents a PdfArray * Use it for all arrays that are written to a PDF file. * * A PdfArray can hold any PdfVariant. * * \see PdfVariant */ typedef std::vector PdfArrayBaseClass; class PODOFO_API PdfArray : private PdfArrayBaseClass, public PdfDataType { public: typedef PdfArrayBaseClass::iterator iterator; typedef PdfArrayBaseClass::const_iterator const_iterator; typedef PdfArrayBaseClass::reverse_iterator reverse_iterator; typedef PdfArrayBaseClass::const_reverse_iterator const_reverse_iterator; /** Create an empty array */ PdfArray(); /** Create an array and add one value to it. * The value is copied. * * \param var add this object to the array. */ explicit PdfArray( const PdfObject & var ); /** Deep copy an existing PdfArray * * \param rhs the array to copy */ PdfArray( const PdfArray & rhs ); virtual ~PdfArray(); /** assignment operator * * \param rhs the array to assign */ PdfArray& operator=(const PdfArray& rhs); /** * \returns the size of the array */ inline size_t GetSize() const; /** Remove all elements from the array */ inline void Clear(); /** Write the array to an output device. * This is an overloaded member function. * * \param pDevice write the object to this device * \param eWriteMode additional options for writing this object * \param pEncrypt an encryption object which is used to encrypt this object * or NULL to not encrypt this object */ virtual void Write( PdfOutputDevice* pDevice, EPdfWriteMode eWriteMode, const PdfEncrypt* pEncrypt = NULL ) const; /** Utility method to determine if the array contains * contains any objects of ePdfDataType_String whose * value is the passed string. * \param cmpString the string to compare against * \returns true if success, false if not */ bool ContainsString( const std::string& cmpString ) const; /** Utility method to return the actual index in the * array which contains an object of ePdfDataType_String whose * value is the passed string. * \param cmpString the string to compare against * \returns true if success, false if not */ size_t GetStringIndex( const std::string& cmpString ) const; /** Adds a PdfObject to the array * * \param var add a PdfObject to the array * * This will set the dirty flag of this object. * \see IsDirty */ inline void push_back( const PdfObject & var ); /** * \returns the size of the array */ inline size_t size() const; /** * \returns true if the array is empty. */ inline bool empty() const; inline PdfObject & operator[](size_type __n); inline const PdfObject & operator[](size_type __n) const; /** * Resize the internal vector. * \param __n new size */ inline void resize(size_t __n, value_type __x = PdfArrayBaseClass::value_type()); /** * Returns a read/write iterator that points to the first * element in the array. Iteration is done in ordinary * element order. */ inline iterator begin(); /** * Returns a read-only (constant) iterator that points to the * first element in the array. Iteration is done in ordinary * element order. */ inline const_iterator begin() const; /** * Returns a read/write iterator that points one past the last * element in the array. Iteration is done in ordinary * element order. */ inline iterator end(); /** * Returns a read-only (constant) iterator that points one past * the last element in the array. Iteration is done in * ordinary element order. */ inline const_iterator end() const; /** * Returns a read/write reverse iterator that points to the * last element in the array. Iteration is done in reverse * element order. */ inline reverse_iterator rbegin(); /** * Returns a read-only (constant) reverse iterator that points * to the last element in the array. Iteration is done in * reverse element order. */ inline const_reverse_iterator rbegin() const; /** * Returns a read/write reverse iterator that points to one * before the first element in the array. Iteration is done * in reverse element order. */ inline reverse_iterator rend(); /** * Returns a read-only (constant) reverse iterator that points * to one before the first element in the array. Iteration * is done in reverse element order. */ inline const_reverse_iterator rend() const; #if defined(_MSC_VER) && _MSC_VER <= 1200 // workaround template-error in Visualstudio 6 inline void insert(iterator __position, iterator __first, iterator __last); #else template void insert(const iterator& __position, const _InputIterator& __first, const _InputIterator& __last); #endif inline PdfArray::iterator insert(const iterator& __position, const PdfObject & val ); inline void erase( const iterator& pos ); inline void erase( const iterator& first, const iterator& last ); inline void reserve(size_type __n); /** * \returns a read/write reference to the data at the first * element of the array. */ inline reference front(); /** * \returns a read-only (constant) reference to the data at the first * element of the array. */ inline const_reference front() const; /** * \returns a read/write reference to the data at the last * element of the array. */ inline reference back(); /** * \returns a read-only (constant) reference to the data at the * last element of the array. */ inline const_reference back() const; inline bool operator==( const PdfArray & rhs ) const; inline bool operator!=( const PdfArray & rhs ) const; /** The dirty flag is set if this variant * has been modified after construction. * * Usually the dirty flag is also set * if you call any non-const member function * as we cannot determine if you actually changed * something or not. * * \returns true if the value is dirty and has been * modified since construction */ virtual bool IsDirty() const; /** Sets the dirty flag of this PdfVariant * * \param bDirty true if this PdfVariant has been * modified from the outside * * \see IsDirty */ virtual void SetDirty( bool bDirty ); private: bool m_bDirty; ///< Indicates if this object was modified after construction }; // ----------------------------------------------------- // // ----------------------------------------------------- void PdfArray::Clear() { AssertMutable(); this->clear(); } // ----------------------------------------------------- // // ----------------------------------------------------- size_t PdfArray::GetSize() const { return this->size(); } // ----------------------------------------------------- // // ----------------------------------------------------- void PdfArray::push_back( const PdfObject & var ) { AssertMutable(); PdfArrayBaseClass::push_back( var ); m_bDirty = true; } // ----------------------------------------------------- // // ----------------------------------------------------- size_t PdfArray::size() const { return PdfArrayBaseClass::size(); } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfArray::empty() const { return PdfArrayBaseClass::empty(); } // ----------------------------------------------------- // // ----------------------------------------------------- PdfObject& PdfArray::operator[](size_type __n) { AssertMutable(); m_bDirty = true; return PdfArrayBaseClass::operator[](__n); } // ----------------------------------------------------- // // ----------------------------------------------------- const PdfObject& PdfArray::operator[](size_type __n) const { return PdfArrayBaseClass::operator[](__n); } // ----------------------------------------------------- // // ----------------------------------------------------- void PdfArray::resize(size_t __n, value_type __x) { PdfArrayBaseClass::resize(__n, __x); } // ----------------------------------------------------- // // ----------------------------------------------------- PdfArray::iterator PdfArray::begin() { return PdfArrayBaseClass::begin(); } // ----------------------------------------------------- // // ----------------------------------------------------- PdfArray::const_iterator PdfArray::begin() const { return PdfArrayBaseClass::begin(); } // ----------------------------------------------------- // // ----------------------------------------------------- PdfArray::iterator PdfArray::end() { return PdfArrayBaseClass::end(); } // ----------------------------------------------------- // // ----------------------------------------------------- PdfArray::const_iterator PdfArray::end() const { return PdfArrayBaseClass::end(); } // ----------------------------------------------------- // // ----------------------------------------------------- PdfArray::reverse_iterator PdfArray::rbegin() { return PdfArrayBaseClass::rbegin(); } // ----------------------------------------------------- // // ----------------------------------------------------- PdfArray::const_reverse_iterator PdfArray::rbegin() const { return PdfArrayBaseClass::rbegin(); } // ----------------------------------------------------- // // ----------------------------------------------------- PdfArray::reverse_iterator PdfArray::rend() { return PdfArrayBaseClass::rend(); } // ----------------------------------------------------- // // ----------------------------------------------------- PdfArray::const_reverse_iterator PdfArray::rend() const { return PdfArrayBaseClass::rend(); } // ----------------------------------------------------- // // ----------------------------------------------------- #if defined(_MSC_VER) && _MSC_VER <= 1200 // workaround template-error in Visualstudio 6 void PdfArray::insert(PdfArray::iterator __position, PdfArray::iterator __first, PdfArray::iterator __last) #else template void PdfArray::insert(const PdfArray::iterator& __position, const _InputIterator& __first, const _InputIterator& __last) #endif { AssertMutable(); PdfArrayBaseClass::insert( __position, __first, __last ); m_bDirty = true; } // ----------------------------------------------------- // // ----------------------------------------------------- PdfArray::iterator PdfArray::insert(const iterator& __position, const PdfObject & val ) { AssertMutable(); m_bDirty = true; return PdfArrayBaseClass::insert( __position, val ); } // ----------------------------------------------------- // // ----------------------------------------------------- void PdfArray::erase( const iterator& pos ) { AssertMutable(); PdfArrayBaseClass::erase( pos ); m_bDirty = true; } // ----------------------------------------------------- // // ----------------------------------------------------- void PdfArray::erase( const iterator& first, const iterator& last ) { AssertMutable(); PdfArrayBaseClass::erase( first, last ); m_bDirty = true; } // ----------------------------------------------------- // // ----------------------------------------------------- void PdfArray::reserve(size_type __n) { PdfArrayBaseClass::reserve( __n ); } // ----------------------------------------------------- // // ----------------------------------------------------- PdfObject & PdfArray::front() { return PdfArrayBaseClass::front(); } // ----------------------------------------------------- // // ----------------------------------------------------- const PdfObject & PdfArray::front() const { return PdfArrayBaseClass::front(); } // ----------------------------------------------------- // // ----------------------------------------------------- PdfObject & PdfArray::back() { return PdfArrayBaseClass::back(); } // ----------------------------------------------------- // // ----------------------------------------------------- const PdfObject & PdfArray::back() const { return PdfArrayBaseClass::back(); } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfArray::operator==( const PdfArray & rhs ) const { //TODO: This operator does not check for m_bDirty. Add comparison or add explanation why it should not be there return (static_cast< PdfArrayBaseClass >(*this) == static_cast< PdfArrayBaseClass >(rhs) ); } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfArray::operator!=( const PdfArray & rhs ) const { //TODO: This operator does not check for m_bDirty. Add comparison or add explanation why it should not be there return (static_cast< PdfArrayBaseClass >(*this) != static_cast< PdfArrayBaseClass >(rhs) ); } typedef PdfArray TVariantList; typedef PdfArray::iterator TIVariantList; typedef PdfArray::const_iterator TCIVariantList; }; #endif // _PDF_ARRAY_H_ podofo-0.9.3/src/base/PdfEncodingFactory.h0000664000175000017500000001614312347275540020261 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2008 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_ENCODING_FACTORY_H_ #define _PDF_ENCODING_FACTORY_H_ #include "PdfDefines.h" #include "util/PdfMutex.h" #include "string.h" namespace PoDoFo { class PdfEncoding; class PdfDocEncoding; class PdfMacRomanEncoding; class PdfObject; class PdfWinAnsiEncoding; class PdfStandardEncoding; // OC 13.08.2010 class PdfMacExpertEncoding; // OC 13.08.2010 class PdfSymbolEncoding; // OC 13.08.2010 class PdfZapfDingbatsEncoding; // OC 13.08.2010 class PdfIdentityEncoding; /** This factory creates a PdfEncoding * from an existing object in the PDF. */ class PODOFO_API PdfEncodingFactory { public: /** Singleton method which returns a global instance * of PdfDocEncoding. * * \returns global instance of PdfDocEncoding */ static const PdfEncoding* GlobalPdfDocEncodingInstance(); /** Singleton method which returns a global instance * of WinAnsiEncoding. * * \returns global instance of WinAnsiEncoding */ static const PdfEncoding* GlobalWinAnsiEncodingInstance(); /** Singleton method which returns a global instance * of MacRomanEncoding. * * \returns global instance of MacRomanEncoding */ static const PdfEncoding* GlobalMacRomanEncodingInstance(); // OC 13.08.2010: /** Singleton method which returns a global instance * of StandardEncoding. * * \returns global instance of StandardEncoding */ static const PdfEncoding* GlobalStandardEncodingInstance(); // OC 13.08.2010: /** Singleton method which returns a global instance * of MacExpertEncoding. * * \returns global instance of MacExpertEncoding */ static const PdfEncoding* GlobalMacExpertEncodingInstance(); // OC 13.08.2010: /** Singleton method which returns a global instance * of SymbolEncoding. * * \returns global instance of SymbolEncoding */ static const PdfEncoding* GlobalSymbolEncodingInstance(); // OC 13.08.2010: /** Singleton method which returns a global instance * of ZapfDingbatsEncoding. * * \returns global instance of ZapfDingbatsEncoding */ static const PdfEncoding* GlobalZapfDingbatsEncodingInstance(); /** Singleton method which returns a global instance * of IndentityEncoding useful for writing direct UTF8 strings. * * \returns global instance of IdentityEncoding */ static const PdfEncoding* GlobalIdentityEncodingInstance(); /** Free's the memory allocated by * the global encoding instancess in this singleton. * * PoDoFo will reallocated these encodings as soon * as they are needed again. * * Only call this method if no other class * of PoDoFo exists anymore, as PdfString etc * contain pointers to the global instances. * */ static void FreeGlobalEncodingInstances(); static void PoDoFoClientAttached(); private: /** Always use this static declaration, * if you need an instance of PdfDocEncoding * as heap allocation is expensive for PdfDocEncoding. */ static const PdfDocEncoding* s_pDocEncoding; /** Always use this static declaration, * if you need an instance of PdfWinAnsiEncoding * as heap allocation is expensive for PdfWinAnsiEncoding. */ static const PdfWinAnsiEncoding* s_pWinAnsiEncoding; /** Always use this static declaration, * if you need an instance of PdfWinAnsiEncoding * as heap allocation is expensive for PdfWinAnsiEncoding. */ static const PdfMacRomanEncoding* s_pMacRomanEncoding; // OC 13.08.2010: /** Always use this static declaration, * if you need an instance of StandardEncoding * as heap allocation is expensive for PdfStandardEncoding. */ static const PdfStandardEncoding* s_pStandardEncoding; // OC 13.08.2010: /** Always use this static declaration, * if you need an instance of MacExpertEncoding * as heap allocation is expensive for PdfMacExpertEncoding. */ static const PdfMacExpertEncoding* s_pMacExpertEncoding; // OC 13.08.2010: /** Always use this static declaration, * if you need an instance of SymbolEncoding * as heap allocation is expensive for PdfSymbolEncoding. */ static const PdfSymbolEncoding* s_pSymbolEncoding; // OC 13.08.2010: /** Always use this static declaration, * if you need an instance of ZapfDingbatsEncoding * as heap allocation is expensive for PdfZapfDingbatsEncoding. */ static const PdfZapfDingbatsEncoding* s_pZapfDingbatsEncoding; static const PdfIdentityEncoding *s_pIdentityEncoding; static Util::PdfMutex s_mutex; }; }; /* namespace PoDoFo */ #endif // _PDF_ENCODING_FACTORY_H__ podofo-0.9.3/src/base/PdfFilter.h0000664000175000017500000004660112344436402016423 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2006 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_FILTER_H_ #define _PDF_FILTER_H_ #include #include #include "PdfDefines.h" #include "PdfInputStream.h" #include "PdfOutputStream.h" namespace PoDoFo { class PdfDictionary; class PdfName; class PdfObject; class PdfOutputStream; typedef std::vector TVecFilters; typedef TVecFilters::iterator TIVecFilters; typedef TVecFilters::const_iterator TCIVecFilters; /** Every filter in PoDoFo has to implement this interface. * * The two methods Encode and Decode have to be implemented * for every filter. * * The output buffers are malloc'ed in the functions and have * to be free'd by the caller. */ class PODOFO_API PdfFilter { public: /** Construct and initialize a new filter */ PdfFilter(); /** All classes with virtual functions need a virtual destructor */ inline virtual ~PdfFilter(); /** Check wether encoding is implemented for this filter. * * \returns true if the filter is able to encode data */ virtual bool CanEncode() const = 0; /** Encodes a buffer using a filter. The buffer will malloc'ed and * has to be free'd by the caller. * * This function uses BeginEncode()/EncodeBlock()/EndEncode() * internally, so it's not safe to use when progressive encoding * is in progress. * * \param pInBuffer input buffer * \param lInLen length of the input buffer * \param ppOutBuffer pointer to the buffer of the encoded data * \param plOutLen pointer to the length of the output buffer */ void Encode( const char* pInBuffer, pdf_long lInLen, char** ppOutBuffer, pdf_long* plOutLen ) const; /** Begin progressively encoding data using this filter. * * This method sets the filter's output stream and may * perform other operations defined by particular filter * implementations. It calls BeginEncodeImpl(). * * \param pOutput encoded data will be written to this stream. * * Call EncodeBlock() to encode blocks of data and use EndEncode * to finish the encoding process. * * \see EncodeBlock * \see EndEncode */ inline void BeginEncode( PdfOutputStream* pOutput ); /** Encode a block of data and write it to the PdfOutputStream * specified by BeginEncode. Ownership of the block is not taken * and remains with the caller. * * The filter implementation need not immediately process the buffer, * and might internally buffer some or all of it. However, if it does * this the buffer's contents will be copied, so it is guaranteed to be * safe to free the passed buffer after this call returns. * * This method is a wrapper around EncodeBlockImpl(). * * BeginEncode() must be called before this function. * * \param pBuffer pointer to a buffer with data to encode * \param lLen length of data to encode. * * Call EndEncode() after all data has been encoded * * \see BeginEncode * \see EndEncode */ inline void EncodeBlock( const char* pBuffer, pdf_long lLen ); /** * Finish encoding of data and reset the stream's state. * * \see BeginEncode * \see EncodeBlock */ inline void EndEncode(); /** Check wether the decoding is implemented for this filter. * * \returns true if the filter is able to decode data */ virtual bool CanDecode() const = 0; /** Decodes a buffer using a filter. The buffer will malloc'ed and * has to be free'd by the caller. * * \param pInBuffer input buffer * \param lInLen length of the input buffer * \param ppOutBuffer pointer to the buffer of the decoded data * \param plOutLen pointer to the length of the output buffer * \param pDecodeParms optional pointer to an decode parameters dictionary * containing additional information to decode the data. * This pointer must be NULL if no decode parameter dictionary * is available. */ void Decode( const char* pInBuffer, pdf_long lInLen, char** ppOutBuffer, pdf_long* plOutLen, const PdfDictionary* pDecodeParms = NULL ) const; /** Begin progressively decoding data using this filter. * * This method sets the filter's output stream and may * perform other operations defined by particular filter * implementations. It calls BeginDecodeImpl(). * * \param pOutput decoded data will be written to this stream. * \param pDecodeParms a dictionary containing addiational information for decoding * * Call DecodeBlock() to decode blocks of data and use EndDecode * to finish the decoding process. * * \see DecodeBlock * \see EndDecode */ inline void BeginDecode( PdfOutputStream* pOutput, const PdfDictionary* pDecodeParms = NULL ); /** Decode a block of data and write it to the PdfOutputStream * specified by BeginDecode. Ownership of the block is not taken * and remains with the caller. * * The filter implementation need not immediately process the buffer, * and might internally buffer some or all of it. However, if it does * this the buffer's contents will be copied, so it is guaranteed to be * safe to free the passed buffer after this call returns. * * This method is a wrapper around DecodeBlockImpl(). * * BeginDecode() must be called before this function. * * \param pBuffer pointer to a buffer with data to encode * \param lLen length of data to encode. * * Call EndDecode() after all data has been decoded * * \see BeginDecode * \see EndDecode */ inline void DecodeBlock( const char* pBuffer, pdf_long lLen ); /** * Finish decoding of data and reset the stream's state. * * \see BeginDecode * \see DecodeBlock */ inline void EndDecode(); /** Type of this filter. * \returns the type of this filter */ virtual EPdfFilter GetType() const = 0; PODOFO_NOTHROW inline PdfOutputStream* GetStream() const { return m_pOutputStream; } protected: /** * Indicate that the filter has failed, and will be non-functional until BeginEncode() * or BeginDecode() is next called. Call this instead of EndEncode() or EndDecode if * something went wrong. It clears the stream output but otherwise does nothing. * * After this method is called futher calls to EncodeBlock(), DecodeBlock(), EndDecode() and * EndEncode() before the next BeginEncode() or BeginDecode() are guaranteed to throw * without calling their virtual implementations. */ PODOFO_NOTHROW inline void FailEncodeDecode(); /** Real implementation of `BeginEncode()'. NEVER call this method directly. * * By default this function does nothing. If your filter needs to do setup for encoding, * you should override this method. * * PdfFilter ensures that a valid stream is available when this method is called, and * that EndEncode() was called since the last BeginEncode()/EncodeBlock(). * * \see BeginEncode */ virtual void BeginEncodeImpl( ) { } /** Real implementation of `EncodeBlock()'. NEVER call this method directly. * * You must override this method to encode the buffer passed by the caller. * * You are not obliged to immediately process any or all of the data in * the passed buffer, but you must ensure that you have processed it and * written it out by the end of EndEncodeImpl(). You must copy the buffer * if you're going to store it, as ownership is not transferred to the * filter and the caller may free the buffer at any time. * * PdfFilter ensures that a valid stream is available when this method is * called, ensures that BeginEncode() has been called, and ensures that * EndEncode() has not been called since the last BeginEncode(). * * \see EncodeBlock */ virtual void EncodeBlockImpl( const char* pBuffer, pdf_long lLen ) = 0; /** Real implementation of `EndEncode()'. NEVER call this method directly. * * By the time this method returns, all filtered data must be written to the stream * and the filter must be in a state where BeginEncode() can be safely called. * * PdfFilter ensures that a valid stream is available when this method is * called, and ensures that BeginEncodeImpl() has been called. * * \see EndEncode */ virtual void EndEncodeImpl() { } /** Real implementation of `BeginDecode()'. NEVER call this method directly. * * By default this function does nothing. If your filter needs to do setup for decoding, * you should override this method. * * PdfFilter ensures that a valid stream is available when this method is called, and * that EndDecode() was called since the last BeginDecode()/DecodeBlock(). * * \see BeginDecode */ virtual void BeginDecodeImpl( const PdfDictionary* ) { } /** Real implementation of `DecodeBlock()'. NEVER call this method directly. * * You must override this method to decode the buffer passed by the caller. * * You are not obliged to immediately process any or all of the data in * the passed buffer, but you must ensure that you have processed it and * written it out by the end of EndDecodeImpl(). You must copy the buffer * if you're going to store it, as ownership is not transferred to the * filter and the caller may free the buffer at any time. * * PdfFilter ensures that a valid stream is available when this method is * called, ensures that BeginDecode() has been called, and ensures that * EndDecode() has not been called since the last BeginDecode(). * * \see DecodeBlock */ virtual void DecodeBlockImpl( const char* pBuffer, pdf_long lLen ) = 0; /** Real implementation of `EndDecode()'. NEVER call this method directly. * * By the time this method returns, all filtered data must be written to the stream * and the filter must be in a state where BeginDecode() can be safely called. * * PdfFilter ensures that a valid stream is available when this method is * called, and ensures that BeginDecodeImpl() has been called. * * \see EndDecode */ virtual void EndDecodeImpl() { } private: PdfOutputStream* m_pOutputStream; }; // ----------------------------------------------------- // // ----------------------------------------------------- void PdfFilter::BeginEncode( PdfOutputStream* pOutput ) { PODOFO_RAISE_LOGIC_IF( m_pOutputStream, "BeginEncode() on failed filter or without EndEncode()" ); m_pOutputStream = pOutput; try { BeginEncodeImpl(); } catch( const PdfError & e ) { // Clean up and close stream this->FailEncodeDecode(); throw e; } } // ----------------------------------------------------- // // ----------------------------------------------------- void PdfFilter::EncodeBlock( const char* pBuffer, pdf_long lLen ) { PODOFO_RAISE_LOGIC_IF( !m_pOutputStream, "EncodeBlock() without BeginEncode() or on failed filter" ); try { EncodeBlockImpl(pBuffer, lLen); } catch( const PdfError & e ) { // Clean up and close stream this->FailEncodeDecode(); throw e; } } // ----------------------------------------------------- // // ----------------------------------------------------- void PdfFilter::EndEncode() { PODOFO_RAISE_LOGIC_IF( !m_pOutputStream, "EndEncode() without BeginEncode() or on failed filter" ); try { EndEncodeImpl(); } catch( const PdfError & e ) { // Clean up and close stream this->FailEncodeDecode(); throw e; } m_pOutputStream->Close(); m_pOutputStream = NULL; } // ----------------------------------------------------- // // ----------------------------------------------------- void PdfFilter::BeginDecode( PdfOutputStream* pOutput, const PdfDictionary* pDecodeParms ) { PODOFO_RAISE_LOGIC_IF( m_pOutputStream, "BeginDecode() on failed filter or without EndDecode()" ); m_pOutputStream = pOutput; try { BeginDecodeImpl( pDecodeParms ); } catch( const PdfError & e ) { // Clean up and close stream this->FailEncodeDecode(); throw e; } } // ----------------------------------------------------- // // ----------------------------------------------------- void PdfFilter::DecodeBlock( const char* pBuffer, pdf_long lLen ) { PODOFO_RAISE_LOGIC_IF( !m_pOutputStream, "DecodeBlock() without BeginDecode() or on failed filter" ) try { DecodeBlockImpl(pBuffer, lLen); } catch( const PdfError & e ) { // Clean up and close stream this->FailEncodeDecode(); throw e; } } // ----------------------------------------------------- // // ----------------------------------------------------- void PdfFilter::EndDecode() { PODOFO_RAISE_LOGIC_IF( !m_pOutputStream, "EndDecode() without BeginDecode() or on failed filter" ) try { EndDecodeImpl(); } catch( const PdfError & e ) { // Clean up and close stream this->FailEncodeDecode(); throw e; } if( m_pOutputStream ) { m_pOutputStream->Close(); m_pOutputStream = NULL; } } // ----------------------------------------------------- // // ----------------------------------------------------- void PdfFilter::FailEncodeDecode() { if ( m_pOutputStream != NULL ) // OC 19.08.2010 BugFix: Sometimes FailEncodeDecode() is called twice m_pOutputStream->Close(); m_pOutputStream = NULL; } // ----------------------------------------------------- // // ----------------------------------------------------- PdfFilter::~PdfFilter() { // Whoops! Didn't call EndEncode() before destroying the filter! // Note that we can't do this for the user, since EndEncode() might // throw and we can't safely have that in a dtor. That also means // we can't throw here, but must abort. assert(!m_pOutputStream); } /** A factory to create a filter object for a filter GetType from the EPdfFilter enum. * * All filters should be created using this factory. */ class PODOFO_API PdfFilterFactory { public: /** Create a filter from an enum. * * Ownership is transferred to the caller, who should let the auto_ptr the * filter is returned in take care of freeing it when they're done with * it. * * \param eFilter the GetType of filter that should be created. * * \returns a new PdfFilter allocated using new or NULL if no * filter is available for this type. */ static std::auto_ptr Create( const EPdfFilter eFilter ); /** Create a PdfOutputStream that applies a list of filters * on all data written to it. * * \param filters a list of filters * \param pStream write all data to this PdfOutputStream after it has been encoded. * \returns a new PdfOutputStream that has to be deleted by the caller. * * \see PdfFilterFactory::CreateFilterList */ static PdfOutputStream* CreateEncodeStream( const TVecFilters & filters, PdfOutputStream* pStream ); /** Create a PdfOutputStream that applies a list of filters * on all data written to it. * * \param filters a list of filters * \param pStream write all data to this PdfOutputStream after it has been decoded. * \param pDictionary pointer to a dictionary that might contain additional parameters * for decoding the stream. * CreateDecodeStream will look for a key named DecodeParms in this dictionary * and pass the information found in this dictionary to the filters. * * \returns a new PdfOutputStream that has to be deleted by the caller. * * \see PdfFilterFactory::CreateFilterList */ static PdfOutputStream* CreateDecodeStream( const TVecFilters & filters, PdfOutputStream* pStream, const PdfDictionary* pDictionary = NULL ); /** Converts a filter name to the corresponding enum * \param name of the filter without leading * \param bSupportShortNames the PDF Reference supports several * short names for filters (e.g. AHx for AsciiHexDecode), if true * support for these short names will be enabled. * This is often used in inline images. * \returns the filter as enum */ static EPdfFilter FilterNameToType( const PdfName & name, bool bSupportShortNames = true ); /** Converts a filter type enum to the corresponding PdfName * \param eFilter a filter type * \returns the filter as name */ static const char* FilterTypeToName( EPdfFilter eFilter ); /** The passed PdfObject has to be a dictionary with a Filters key, * an array of filter names or a filter name. * * \param pObject must define a list of filters. * * \returns a list of filters */ static TVecFilters CreateFilterList( const PdfObject* pObject ); }; }; #endif /* _PDF_FILTER_H_ */ podofo-0.9.3/src/base/PdfObjectStreamParserObject.cpp0000664000175000017500000001352012347271543022417 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2010 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfObjectStreamParserObject.h" #include "PdfDictionary.h" #include "PdfEncrypt.h" #include "PdfInputDevice.h" #include "PdfParserObject.h" #include "PdfStream.h" #include "PdfVecObjects.h" #include #if defined(PODOFO_VERBOSE_DEBUG) #include #endif namespace PoDoFo { PdfObjectStreamParserObject::PdfObjectStreamParserObject(PdfParserObject* pParser, PdfVecObjects* pVecObjects, const PdfRefCountedBuffer & rBuffer, PdfEncrypt* pEncrypt ) : m_pParser( pParser ), m_vecObjects( pVecObjects ), m_buffer( rBuffer ), m_pEncrypt( pEncrypt ) { } PdfObjectStreamParserObject::~PdfObjectStreamParserObject() { } void PdfObjectStreamParserObject::Parse(ObjectIdList const & list) { pdf_int64 lNum = m_pParser->GetDictionary().GetKeyAsLong( "N", 0 ); pdf_int64 lFirst = m_pParser->GetDictionary().GetKeyAsLong( "First", 0 ); char* pBuffer; pdf_long lBufferLen; m_pParser->GetStream()->GetFilteredCopy( &pBuffer, &lBufferLen ); try { this->ReadObjectsFromStream( pBuffer, lBufferLen, lNum, lFirst, list ); free( pBuffer ); // the object stream is not needed anymore in the final PDF delete m_vecObjects->RemoveObject( m_pParser->Reference() ); m_pParser = NULL; } catch( const PdfError & rError ) { free( pBuffer ); throw rError; } } void PdfObjectStreamParserObject::ReadObjectsFromStream( char* pBuffer, pdf_long lBufferLen, pdf_int64 lNum, pdf_int64 lFirst, ObjectIdList const & list) { PdfRefCountedInputDevice device( pBuffer, lBufferLen ); PdfTokenizer tokenizer( device, m_buffer ); PdfVariant var; int i = 0; while( static_cast(i) < lNum ) { const pdf_int64 lObj = tokenizer.GetNextNumber(); const pdf_int64 lOff = tokenizer.GetNextNumber(); const std::streamoff pos = device.Device()->Tell(); // move to the position of the object in the stream device.Device()->Seek( static_cast(lFirst + lOff) ); // use a second tokenizer here so that anything that gets dequeued isn't left in the tokenizer that reads the offsets and lengths PdfTokenizer variantTokenizer( device, m_buffer ); if( m_pEncrypt && m_pEncrypt->GetEncryptAlgorithm() == PdfEncrypt::ePdfEncryptAlgorithm_AESV2 ) variantTokenizer.GetNextVariant( var, 0 ); // Stream is already decrypted else variantTokenizer.GetNextVariant( var, m_pEncrypt ); bool should_read = std::find(list.begin(), list.end(), lObj) != list.end(); #if defined(PODOFO_VERBOSE_DEBUG) std::cerr << "ReadObjectsFromStream STREAM=" << m_pParser->Reference().ToString() << ", OBJ=" << lObj << ", " << (should_read ? "read" : "skipped") << std::endl; #endif if (should_read) { if(m_vecObjects->GetObject(PdfReference( static_cast(lObj), PODOFO_LL_LITERAL(0) ))) { PdfError::LogMessage( eLogSeverity_Warning, "Object: %li 0 R will be deleted and loaded again.\n", lObj ); delete m_vecObjects->RemoveObject(PdfReference( static_cast(lObj), PODOFO_LL_LITERAL(0) ),false); } m_vecObjects->insert_sorted( new PdfObject( PdfReference( static_cast(lObj), PODOFO_LL_LITERAL(0) ), var ) ); } // move back to the position inside of the table of contents device.Device()->Clear(); device.Device()->Seek( pos ); ++i; } } }; podofo-0.9.3/src/base/PdfExtension.h0000664000175000017500000000630512340213643017143 0ustar dominikdominik/************************************************************************** * Copyright (C) 2006 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_EXTENSION_H_ #define _PDF_EXTENSION_H_ #include "podofo/base/PdfDefines.h" namespace PoDoFo { /** PdfExtension is a simple class that describes a vendor-specific extension to * the official specifications. */ class PODOFO_DOC_API PdfExtension { public: PdfExtension(const char* ns, EPdfVersion baseVersion, pdf_int64 level): _ns(ns), _baseVersion(baseVersion), _level(level) {} const std::string& getNamespace() const { return _ns; } EPdfVersion getBaseVersion() const { return _baseVersion; } pdf_int64 getLevel() const { return _level; } private: std::string _ns; EPdfVersion _baseVersion; pdf_int64 _level; }; } #endif // _PDF_EXTENSION_H_ podofo-0.9.3/src/base/PdfMemStream.cpp0000664000175000017500000002176712344436402017431 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2007 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfMemStream.h" #include "PdfArray.h" #include "PdfEncrypt.h" #include "PdfFilter.h" #include "PdfObject.h" #include "PdfOutputDevice.h" #include "PdfOutputStream.h" #include "PdfVariant.h" #include "PdfDefinesPrivate.h" #include namespace PoDoFo { PdfMemStream::PdfMemStream( PdfObject* pParent ) : PdfStream( pParent ), m_pStream( NULL ), m_pBufferStream( NULL ), m_lLength( 0 ) { } PdfMemStream::PdfMemStream( const PdfMemStream & rhs ) : PdfStream( NULL ), m_pStream( NULL ), m_pBufferStream( NULL ), m_lLength( 0 ) { operator=(rhs); } PdfMemStream::~PdfMemStream() { } void PdfMemStream::BeginAppendImpl( const TVecFilters & vecFilters ) { m_buffer = PdfRefCountedBuffer(); m_lLength = 0; if( vecFilters.size() ) { m_pBufferStream = new PdfBufferOutputStream( &m_buffer ); m_pStream = PdfFilterFactory::CreateEncodeStream( vecFilters, m_pBufferStream ); } else m_pStream = new PdfBufferOutputStream( &m_buffer ); } void PdfMemStream::AppendImpl( const char* pszString, size_t lLen ) { m_pStream->Write( pszString, lLen ); } void PdfMemStream::EndAppendImpl() { if( m_pStream ) { m_pStream->Close(); if( !m_pBufferStream ) m_lLength = dynamic_cast(m_pStream)->GetLength(); delete m_pStream; m_pStream = NULL; } if( m_pBufferStream ) { m_pBufferStream->Close(); m_lLength = m_pBufferStream->GetLength(); delete m_pBufferStream; m_pBufferStream = NULL; } if( m_pParent ) m_pParent->GetDictionary().AddKey( PdfName::KeyLength, PdfVariant(static_cast(m_lLength) ) ); } void PdfMemStream::GetCopy( char** pBuffer, pdf_long* lLen ) const { if( !pBuffer || !lLen ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } *pBuffer = static_cast(malloc( sizeof( char ) * m_lLength )); *lLen = m_lLength; if( !*pBuffer ) { PODOFO_RAISE_ERROR( ePdfError_OutOfMemory ); } memcpy( *pBuffer, m_buffer.GetBuffer(), m_lLength ); } void PdfMemStream::GetCopy(PdfOutputStream * pStream) const { if( !pStream) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } pStream->Write(m_buffer.GetBuffer(), m_lLength); } void PdfMemStream::FlateCompress() { PdfObject* pObj; PdfVariant vFilter( PdfName("FlateDecode" ) ); PdfVariant vFilterList; PdfArray tFilters; PdfArray::const_iterator tciFilters; if( !m_lLength ) return; // ePdfError_ErrOk // TODO: Handle DecodeParms if( m_pParent->GetDictionary().HasKey( "Filter" ) ) { pObj = m_pParent->GetIndirectKey( "Filter" ); if( pObj->IsName() ) { if( pObj->GetName() != "DCTDecode" && pObj->GetName() != "FlateDecode" ) { tFilters.push_back( vFilter ); tFilters.push_back( *pObj ); } } else if( pObj->IsArray() ) { tciFilters = pObj->GetArray().begin(); while( tciFilters != pObj->GetArray().end() ) { if( (*tciFilters).IsName() ) { // do not compress DCTDecoded are already FlateDecoded streams again if( (*tciFilters).GetName() == "DCTDecode" || (*tciFilters).GetName() == "FlateDecode" ) { return; } } ++tciFilters; } tFilters.push_back( vFilter ); tciFilters = pObj->GetArray().begin(); while( tciFilters != pObj->GetArray().end() ) { tFilters.push_back( (*tciFilters) ); ++tciFilters; } } else return; vFilterList = PdfVariant( tFilters ); m_pParent->GetDictionary().AddKey( "Filter", vFilterList ); FlateCompressStreamData(); // throws an exception on error } else { m_pParent->GetDictionary().AddKey( "Filter", PdfName( "FlateDecode" ) ); FlateCompressStreamData(); } } void PdfMemStream::Uncompress() { pdf_long lLen; char* pBuffer = NULL; TVecFilters vecEmpty; if( m_pParent && m_pParent->IsDictionary() && m_pParent->GetDictionary().HasKey( "Filter" ) && m_lLength ) { try { this->GetFilteredCopy( &pBuffer, &lLen ); } catch( PdfError & e ) { if( pBuffer ) free( pBuffer ); throw e; } this->Set( pBuffer, lLen, vecEmpty ); // free the memory allocated by GetFilteredCopy again. podofo_free( pBuffer ); m_pParent->GetDictionary().RemoveKey( "Filter" ); if( m_pParent->GetDictionary().HasKey( "DecodeParms" ) ) { m_pParent->GetDictionary().RemoveKey( "DecodeParms" ); } } } void PdfMemStream::FlateCompressStreamData() { char* pBuffer; pdf_long lLen; if( !m_lLength ) return; std::auto_ptr pFilter = PdfFilterFactory::Create( ePdfFilter_FlateDecode ); if( pFilter.get() ) { pFilter->Encode( m_buffer.GetBuffer(), m_buffer.GetSize(), &pBuffer, &lLen ); this->Set( pBuffer, lLen ); } else { PODOFO_RAISE_ERROR( ePdfError_UnsupportedFilter ); } } const PdfStream & PdfMemStream::operator=( const PdfStream & rhs ) { const PdfMemStream* pStream = dynamic_cast(&rhs); if( pStream ) m_buffer = pStream->m_buffer; else return PdfStream::operator=( rhs ); m_lLength = rhs.GetLength(); if( m_pParent ) m_pParent->GetDictionary().AddKey( PdfName::KeyLength, PdfVariant( static_cast(m_lLength) ) ); return *this; } void PdfMemStream::Write( PdfOutputDevice* pDevice, PdfEncrypt* pEncrypt ) { pDevice->Print( "stream\n" ); if( pEncrypt ) { pdf_long lLen = this->GetLength(); pdf_long nOutputLen = pEncrypt->CalculateStreamLength(lLen); char *pOutputBuffer = new char[nOutputLen]; pEncrypt->Encrypt( reinterpret_cast(this->Get()), lLen, reinterpret_cast(pOutputBuffer), nOutputLen); pDevice->Write( pOutputBuffer, nOutputLen ); delete[] pOutputBuffer; } else { pDevice->Write( this->Get(), this->GetLength() ); } pDevice->Print( "\nendstream\n" ); } pdf_long PdfMemStream::GetLength() const { return m_lLength; } }; podofo-0.9.3/src/base/PdfError.cpp0000664000175000017500000005202512354340617016622 0ustar dominikdominik/************************************************************************** * Copyright (C) 2006 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ // PdfError.h doesn't, and can't, include PdfDefines.h so we do so here. // PdfDefines.h will include PdfError.h for us. #include "PdfDefines.h" #include "PdfDefinesPrivate.h" #include #include namespace PoDoFo { bool PdfError::s_DgbEnabled = true; bool PdfError::s_LogEnabled = true; // OC 17.08.2010 New to optionally replace stderr output by a callback: PdfError::LogMessageCallback* PdfError::m_fLogMessageCallback = NULL; //static PdfError::LogMessageCallback* PdfError::SetLogMessageCallback(LogMessageCallback* fLogMessageCallback) { PdfError::LogMessageCallback* old_fLogMessageCallback = m_fLogMessageCallback; m_fLogMessageCallback = fLogMessageCallback; return old_fLogMessageCallback; } PdfErrorInfo::PdfErrorInfo() : m_nLine( -1 ) { } PdfErrorInfo::PdfErrorInfo( int line, const char* pszFile, const char* pszInfo ) : m_nLine( line ), m_sFile( pszFile ? pszFile : "" ), m_sInfo( pszInfo ? pszInfo : "" ) { } PdfErrorInfo::PdfErrorInfo( int line, const char* pszFile, const wchar_t* pszInfo ) : m_nLine( line ), m_sFile( pszFile ? pszFile : "" ), m_swInfo( pszInfo ? pszInfo : L"" ) { } PdfErrorInfo::PdfErrorInfo( const PdfErrorInfo & rhs ) { this->operator=( rhs ); } const PdfErrorInfo & PdfErrorInfo::operator=( const PdfErrorInfo & rhs ) { m_nLine = rhs.m_nLine; m_sFile = rhs.m_sFile; m_sInfo = rhs.m_sInfo; m_swInfo = rhs.m_swInfo; return *this; } // ----------------------------------------------------- // // ----------------------------------------------------- PdfError::PdfError() { m_error = ePdfError_ErrOk; } PdfError::PdfError( const EPdfError & eCode, const char* pszFile, int line, const char* pszInformation ) { this->SetError( eCode, pszFile, line, pszInformation ); } PdfError::PdfError( const PdfError & rhs ) { this->operator=( rhs ); } PdfError::~PdfError() throw() { } const PdfError & PdfError::operator=( const PdfError & rhs ) { m_error = rhs.m_error; m_callStack = rhs.m_callStack; return *this; } const PdfError & PdfError::operator=( const EPdfError & eCode ) { m_error = eCode; m_callStack.clear(); return *this; } bool PdfError::operator==( const PdfError & rhs ) { return this->operator==( rhs.m_error ); } bool PdfError::operator==( const EPdfError & eCode ) { return m_error == eCode; } bool PdfError::operator!=( const PdfError & rhs ) { return this->operator!=( rhs.m_error ); } bool PdfError::operator!=( const EPdfError & eCode ) { return !this->operator==( eCode ); } void PdfError::PrintErrorMsg() const { TCIDequeErrorInfo it = m_callStack.begin(); const char* pszMsg = PdfError::ErrorMessage( m_error ); const char* pszName = PdfError::ErrorName( m_error ); int i = 0; PdfError::LogErrorMessage( eLogSeverity_Error, "\n\nPoDoFo encounter an error. Error: %i %s\n", m_error, pszName ? pszName : "" ); if( pszMsg ) PdfError::LogErrorMessage( eLogSeverity_Error, "\tError Description: %s\n", pszMsg ); if( m_callStack.size() ) PdfError::LogErrorMessage( eLogSeverity_Error, "\tCallstack:\n" ); while( it != m_callStack.end() ) { if( !(*it).GetFilename().empty() ) PdfError::LogErrorMessage( eLogSeverity_Error, "\t#%i Error Source: %s:%i\n", i, (*it).GetFilename().c_str(), (*it).GetLine() ); if( !(*it).GetInformation().empty() ) PdfError::LogErrorMessage( eLogSeverity_Error, "\t\tInformation: %s\n", (*it).GetInformation().c_str() ); if( !(*it).GetInformationW().empty() ) PdfError::LogErrorMessage( eLogSeverity_Error, L"\t\tInformation: %s\n", (*it).GetInformationW().c_str() ); ++i; ++it; } PdfError::LogErrorMessage( eLogSeverity_Error, "\n\n" ); } const char* PdfError::what() const { return PdfError::ErrorName( m_error ); } const char* PdfError::ErrorName( EPdfError eCode ) { const char* pszMsg = NULL; switch( eCode ) { case ePdfError_ErrOk: pszMsg = "ePdfError_ErrOk"; break; case ePdfError_TestFailed: pszMsg = "ePdfError_TestFailed"; break; case ePdfError_InvalidHandle: pszMsg = "ePdfError_InvalidHandle"; break; case ePdfError_FileNotFound: pszMsg = "ePdfError_FileNotFound"; break; case ePdfError_InvalidDeviceOperation: pszMsg = "ePdfError_InvalidDeviceOperation"; break; case ePdfError_UnexpectedEOF: pszMsg = "ePdfError_UnexpectedEOF"; break; case ePdfError_OutOfMemory: pszMsg = "ePdfError_OutOfMemory"; break; case ePdfError_ValueOutOfRange: pszMsg = "ePdfError_ValueOutOfRange"; break; case ePdfError_InternalLogic: pszMsg = "ePdfError_InternalLogic"; break; case ePdfError_InvalidEnumValue: pszMsg = "ePdfError_InvalidEnumValue"; break; case ePdfError_PageNotFound: pszMsg = "ePdfError_PageNotFound"; break; case ePdfError_NoPdfFile: pszMsg = "ePdfError_NoPdfFile"; break; case ePdfError_NoXRef: pszMsg = "ePdfError_NoXRef"; break; case ePdfError_NoTrailer: pszMsg = "ePdfError_NoTrailer"; break; case ePdfError_NoNumber: pszMsg = "ePdfError_NoNumber"; break; case ePdfError_NoObject: pszMsg = "ePdfError_NoObject"; break; case ePdfError_NoEOFToken: pszMsg = "ePdfError_NoEOFToken"; break; case ePdfError_InvalidTrailerSize: pszMsg = "ePdfError_InvalidTrailerSize"; break; case ePdfError_InvalidLinearization: pszMsg = "ePdfError_InvalidLinearization"; break; case ePdfError_InvalidDataType: pszMsg = "ePdfError_InvalidDataType"; break; case ePdfError_InvalidXRef: pszMsg = "ePdfError_InvalidXRef"; break; case ePdfError_InvalidXRefStream: pszMsg = "ePdfError_InvalidXRefStream"; break; case ePdfError_InvalidXRefType: pszMsg = "ePdfError_InvalidXRefType"; break; case ePdfError_InvalidPredictor: pszMsg = "ePdfError_InvalidPredictor"; break; case ePdfError_InvalidStrokeStyle: pszMsg = "ePdfError_InvalidStrokeStyle"; break; case ePdfError_InvalidHexString: pszMsg = "ePdfError_InvalidHexString"; break; case ePdfError_InvalidStream: pszMsg = "ePdfError_InvalidStream"; break; case ePdfError_InvalidStreamLength: pszMsg = "ePdfError_InvalidStream"; break; case ePdfError_InvalidKey: pszMsg = "ePdfError_InvalidKey"; break; case ePdfError_InvalidName: pszMsg = "ePdfError_InvalidName"; break; case ePdfError_InvalidEncryptionDict: pszMsg = "ePdfError_InvalidEncryptionDict"; /**< The encryption dictionary is invalid or misses a required key */ break; case ePdfError_InvalidPassword: /**< The password used to open the PDF file was invalid */ pszMsg = "ePdfError_InvalidPassword"; break; case ePdfError_InvalidFontFile: pszMsg = "ePdfError_InvalidFontFile"; break; case ePdfError_InvalidContentStream: pszMsg = "ePdfError_InvalidContentStream"; break; case ePdfError_UnsupportedFilter: pszMsg = "ePdfError_UnsupportedFilter"; break; case ePdfError_UnsupportedFontFormat: /**< This font format is not supported by PoDoFO. */ pszMsg = "ePdfError_UnsupportedFontFormat"; break; case ePdfError_ActionAlreadyPresent: pszMsg = "ePdfError_ActionAlreadyPresent"; break; case ePdfError_WrongDestinationType: pszMsg = "ePdfError_WrongDestinationType"; break; case ePdfError_MissingEndStream: pszMsg = "ePdfError_MissingEndStream"; break; case ePdfError_Date: pszMsg = "ePdfError_Date"; break; case ePdfError_Flate: pszMsg = "ePdfError_Flate"; break; case ePdfError_FreeType: pszMsg = "ePdfError_FreeType"; break; case ePdfError_SignatureError: pszMsg = "ePdfError_SignatureError"; break; case ePdfError_MutexError: pszMsg = "ePdfError_MutexError"; break; case ePdfError_UnsupportedImageFormat: /**< This image format is not supported by PoDoFO. */ pszMsg = "ePdfError_UnsupportedImageFormat"; break; case ePdfError_CannotConvertColor: /**< This color format cannot be converted. */ pszMsg = "ePdfError_CannotConvertColor"; break; case ePdfError_NotImplemented: pszMsg = "ePdfError_NotImplemented"; break; case ePdfError_NotCompiled: pszMsg = "ePdfError_NotCompiled"; break; case ePdfError_DestinationAlreadyPresent: pszMsg = "ePdfError_DestinationAlreadyPresent"; break; case ePdfError_ChangeOnImmutable: pszMsg = "ePdfError_ChangeOnImmutable"; break; case ePdfError_Unknown: pszMsg = "ePdfError_Unknown"; break; default: break; } return pszMsg; } const char* PdfError::ErrorMessage( EPdfError eCode ) { const char* pszMsg = NULL; switch( eCode ) { case ePdfError_ErrOk: pszMsg = "No error during execution."; break; case ePdfError_TestFailed: pszMsg = "An error curred in an automatic test included in PoDoFo."; break; case ePdfError_InvalidHandle: pszMsg = "A NULL handle was passed, but initialized data was expected."; break; case ePdfError_FileNotFound: pszMsg = "The specified file was not found."; break; case ePdfError_InvalidDeviceOperation: pszMsg = "Tried to do something unsupported to an I/O device like seek a non-seekable input device"; break; case ePdfError_UnexpectedEOF: pszMsg = "End of file was reached unxexpectedly."; break; case ePdfError_OutOfMemory: pszMsg = "PoDoFo is out of memory."; break; case ePdfError_ValueOutOfRange: pszMsg = "The passed value is out of range."; break; case ePdfError_InternalLogic: pszMsg = "An internal error occurred."; break; case ePdfError_InvalidEnumValue: pszMsg = "An invalid enum value was specified."; break; case ePdfError_PageNotFound: pszMsg = "The requested page could not be found in the PDF."; break; case ePdfError_NoPdfFile: pszMsg = "This is not a PDF file."; break; case ePdfError_NoXRef: pszMsg = "No XRef table was found in the PDF file."; break; case ePdfError_NoTrailer: pszMsg = "No trailer was found in the PDF file."; break; case ePdfError_NoNumber: pszMsg = "A number was expected but not found."; break; case ePdfError_NoObject: pszMsg = "A object was expected but not found."; break; case ePdfError_NoEOFToken: pszMsg = "No EOF Marker was found in the PDF file."; break; case ePdfError_InvalidTrailerSize: case ePdfError_InvalidLinearization: case ePdfError_InvalidDataType: case ePdfError_InvalidXRef: case ePdfError_InvalidXRefStream: case ePdfError_InvalidXRefType: case ePdfError_InvalidPredictor: case ePdfError_InvalidStrokeStyle: case ePdfError_InvalidHexString: case ePdfError_InvalidStream: case ePdfError_InvalidStreamLength: case ePdfError_InvalidKey: case ePdfError_InvalidName: break; case ePdfError_InvalidEncryptionDict: pszMsg = "The encryption dictionary is invalid or misses a required key."; break; case ePdfError_InvalidPassword: pszMsg = "The password used to open the PDF file was invalid."; break; case ePdfError_InvalidFontFile: pszMsg = "The font file is invalid."; break; case ePdfError_InvalidContentStream: pszMsg = "The content stream is invalid due to mismatched context pairing or other problems."; break; case ePdfError_UnsupportedFilter: break; case ePdfError_UnsupportedFontFormat: pszMsg = "This font format is not supported by PoDoFO."; break; case ePdfError_DestinationAlreadyPresent: case ePdfError_ActionAlreadyPresent: pszMsg = "Outlines can have either destinations or actions."; break; case ePdfError_WrongDestinationType: pszMsg = "The requested field is not available for the given destination type"; break; case ePdfError_MissingEndStream: case ePdfError_Date: break; case ePdfError_Flate: pszMsg = "ZLib returned an error."; break; case ePdfError_FreeType: pszMsg = "FreeType returned an error."; break; case ePdfError_SignatureError: pszMsg = "The signature contains an error."; break; case ePdfError_MutexError: pszMsg = "Error during a mutex operation."; break; case ePdfError_UnsupportedImageFormat: pszMsg = "This image format is not supported by PoDoFO."; break; case ePdfError_CannotConvertColor: pszMsg = "This color format cannot be converted."; break; case ePdfError_ChangeOnImmutable: pszMsg = "Changing values on immutable objects is not allowed."; break; case ePdfError_NotImplemented: pszMsg = "This feature is currently not implemented."; break; case ePdfError_NotCompiled: pszMsg = "This feature was disabled during compile time."; break; case ePdfError_Unknown: pszMsg = "Error code unknown."; break; default: break; } return pszMsg; } void PdfError::LogMessage( ELogSeverity eLogSeverity, const char* pszMsg, ... ) { if(!PdfError::LoggingEnabled()) return; #ifdef DEBUG const ELogSeverity eMinSeverity = eLogSeverity_Debug; #else const ELogSeverity eMinSeverity = eLogSeverity_Information; #endif // DEBUG // OC 17.08.2010 BugFix: Higher level is lower value // if( eLogSeverity < eMinSeverity ) if( eLogSeverity > eMinSeverity ) return; va_list args; va_start( args, pszMsg ); LogMessageInternal( eLogSeverity, pszMsg, args ); va_end( args ); } void PdfError::LogErrorMessage( ELogSeverity eLogSeverity, const char* pszMsg, ... ) { va_list args; va_start( args, pszMsg ); LogMessageInternal( eLogSeverity, pszMsg, args ); va_end( args ); } void PdfError::LogMessageInternal( ELogSeverity eLogSeverity, const char* pszMsg, va_list & args ) { const char* pszPrefix = NULL; switch( eLogSeverity ) { case eLogSeverity_Error: break; case eLogSeverity_Critical: pszPrefix = "CRITICAL: "; break; case eLogSeverity_Warning: pszPrefix = "WARNING: "; break; case eLogSeverity_Information: break; case eLogSeverity_Debug: pszPrefix = "DEBUG: "; break; case eLogSeverity_None: case eLogSeverity_Unknown: default: break; } // OC 17.08.2010 New to optionally replace stderr output by a callback: if ( m_fLogMessageCallback != NULL ) { m_fLogMessageCallback->LogMessage(eLogSeverity, pszPrefix, pszMsg, args); return; } if( pszPrefix ) fprintf( stderr, "%s", pszPrefix ); vfprintf( stderr, pszMsg, args ); } void PdfError::LogMessage( ELogSeverity eLogSeverity, const wchar_t* pszMsg, ... ) { if(!PdfError::LoggingEnabled()) return; #ifdef DEBUG const ELogSeverity eMinSeverity = eLogSeverity_Debug; #else const ELogSeverity eMinSeverity = eLogSeverity_Information; #endif // DEBUG // OC 17.08.2010 BugFix: Higher level is lower value // if( eLogSeverity < eMinSeverity ) if( eLogSeverity > eMinSeverity ) return; va_list args; va_start( args, pszMsg ); LogMessageInternal( eLogSeverity, pszMsg, args ); va_end( args ); } void PdfError::LogErrorMessage( ELogSeverity eLogSeverity, const wchar_t* pszMsg, ... ) { va_list args; va_start( args, pszMsg ); LogMessageInternal( eLogSeverity, pszMsg, args ); va_end( args ); } void PdfError::LogMessageInternal( ELogSeverity eLogSeverity, const wchar_t* pszMsg, va_list & args ) { const wchar_t* pszPrefix = NULL; switch( eLogSeverity ) { case eLogSeverity_Error: break; case eLogSeverity_Critical: pszPrefix = L"CRITICAL: "; break; case eLogSeverity_Warning: pszPrefix = L"WARNING: "; break; case eLogSeverity_Information: break; case eLogSeverity_Debug: pszPrefix = L"DEBUG: "; break; case eLogSeverity_None: case eLogSeverity_Unknown: default: break; } // OC 17.08.2010 New to optionally replace stderr output by a callback: if ( m_fLogMessageCallback != NULL ) { m_fLogMessageCallback->LogMessage(eLogSeverity, pszPrefix, pszMsg, args); return; } if( pszPrefix ) fwprintf( stderr, pszPrefix ); vfwprintf( stderr, pszMsg, args ); } void PdfError::DebugMessage( const char* pszMsg, ... ) { if ( !PdfError::DebugEnabled() ) return; const char* pszPrefix = "DEBUG: "; va_list args; va_start( args, pszMsg ); // OC 17.08.2010 New to optionally replace stderr output by a callback: if ( m_fLogMessageCallback != NULL ) { m_fLogMessageCallback->LogMessage(eLogSeverity_Debug, pszPrefix, pszMsg, args); return; } if( pszPrefix ) fprintf( stderr, "%s", pszPrefix ); vfprintf( stderr, pszMsg, args ); va_end( args ); } }; podofo-0.9.3/src/base/PdfArray.cpp0000664000175000017500000001252312344436402016603 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2006 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfArray.h" #include "PdfOutputDevice.h" #include "PdfDefinesPrivate.h" #include namespace PoDoFo { PdfArray::PdfArray() : PdfArrayBaseClass(), PdfDataType(), m_bDirty( false ) { } PdfArray::~PdfArray() { } PdfArray::PdfArray( const PdfObject & var ) : PdfArrayBaseClass(), PdfDataType(), m_bDirty( false ) { this->push_back( var ); } PdfArray::PdfArray( const PdfArray & rhs ) : PdfArrayBaseClass(rhs), PdfDataType(rhs), m_bDirty(rhs.m_bDirty) { this->operator=( rhs ); } PdfArray& PdfArray::operator=(const PdfArray& rhs) { if (this != &rhs) { m_bDirty = rhs.m_bDirty; PdfArrayBaseClass::operator=( rhs ); } else { //do nothing } return *this; } void PdfArray::Write( PdfOutputDevice* pDevice, EPdfWriteMode eWriteMode, const PdfEncrypt* pEncrypt ) const { PdfArray::const_iterator it = this->begin(); int count = 1; if( (eWriteMode & ePdfWriteMode_Clean) == ePdfWriteMode_Clean ) { pDevice->Print( "[ " ); } else { pDevice->Print( "[" ); } while( it != this->end() ) { (*it).Write( pDevice, eWriteMode, pEncrypt ); if( (eWriteMode & ePdfWriteMode_Clean) == ePdfWriteMode_Clean ) { pDevice->Print( (count % 10 == 0) ? "\n" : " " ); } ++it; ++count; } pDevice->Print( "]" ); } bool PdfArray::ContainsString( const std::string& cmpString ) const { bool foundIt = false; TCIVariantList it(this->begin()); while( it != this->end() ) { if( (*it).GetDataType() == ePdfDataType_String ) { if ( (*it).GetString().GetString() == cmpString ) { foundIt = true; break; } } ++it; } return foundIt; } size_t PdfArray::GetStringIndex( const std::string& cmpString ) const { size_t foundIdx = std::numeric_limits::max(); for ( size_t i=0; isize(); i++ ) { if( (*this)[i].GetDataType() == ePdfDataType_String ) { if ( (*this)[i].GetString().GetString() == cmpString ) { foundIdx = i; break; } } } return foundIdx; } bool PdfArray::IsDirty() const { // If the array itself is dirty // return immediately // otherwise check all children. if( m_bDirty ) return m_bDirty; PdfArray::const_iterator it(this->begin()); while( it != this->end() ) { if( (*it).IsDirty() ) return true; ++it; } return false; } void PdfArray::SetDirty( bool bDirty ) { m_bDirty = bDirty; if( !m_bDirty ) { // Propagate state to all subclasses PdfArray::iterator it(this->begin()); while( it != this->end() ) { (*it).SetDirty( m_bDirty ); ++it; } } } }; podofo-0.9.3/src/base/PdfDefines.h0000664000175000017500000004522612350106026016546 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2005 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_DEFINES_H_ #define _PDF_DEFINES_H_ /** \file PdfDefines.h * This file should be included as the FIRST file in every header of * PoDoFo lib. It includes all standard files, defines some useful * macros, some datatypes and all important enumeration types. On * supporting platforms it will be precompiled to speed compilation. */ #include "PdfCompilerCompat.h" /** * PoDoFo version - 24-bit integer representation. * Version is 0xMMmmpp where M is major, m is minor and p is patch * eg 0.7.0 is represented as 0x000700 * eg 0.7.99 is represented as 0x000763 * * Note that the PoDoFo version is available in parts as individual 8-bit * integer literals in PODOFO_VERSION_MAJOR, PODOFO_VERSION_MINOR and * PODOFO_VERSION_PATCH . */ #define PODOFO_MAKE_VERSION_REAL(M,m,p) ( (M<<16)+(m<<8)+(p) ) #define PODOFO_MAKE_VERSION(M,m,p) PODOFO_MAKE_VERSION_REAL(M,m,p) #define PODOFO_VERSION PODOFO_MAKE_VERSION(PODOFO_VERSION_MAJOR, PODOFO_VERSION_MINOR, PODOFO_VERSION_PATCH) /** * PoDoFo version represented as a string literal, eg '0.7.99' */ #define PODOFO_MAKE_VERSION_STR_REAL(M,m,p) ("\"" #M "." #m "." #p "\"") #define PODOFO_MAKE_VERSION_STR(M,m,p) PODOFO_MAKE_VERSION_STR_REAL(M,m,p) #define PODOFO_VERSION_STR PODOFO_MAKE_VERSION_STR(PODOFO_VERSION_MAJOR, PODOFO_VERSION_MINOR, PODOFO_VERSION_PATCH) #ifndef PODOFO_COMPILE_RC // Include common system files // (most are now pulled in my PdfCompilerCompat.h) #include // Include common STL files #include #include #include #include // Include common BOOST settings #ifdef PODOFO_HAVE_BOOST #include #endif // PODOFO_HAVE_BOOST /** \def PODOFO_VERBOSE_DEBUG * Debug define. Enable it, if you need * more debuf output to the commandline from PoDoFo * * Setting PDF_VERBOSE_DEBUG will make PoDoFo * EXTREMELY slow and verbose, so it's not practical * even for regular debuggin. */ #ifndef PODOFO_VERBOSE_DEBUG //#define PODOFO_VERBOSE_DEBUG #endif //PODOFO_VERBOSE_DEBUG #ifdef DEBUG #include #define PODOFO_ASSERT( x ) assert( x ); #else #define PODOFO_ASSERT( x ) #endif // DEBUG // Should we do lots of extra (expensive) sanity checking? You should not // define this on production builds because of the runtime cost and because it // might cause the library to abort() if it notices something nasty. // It may also change the size of some objects, and is thus not binary // compatible. // // If you don't know you need this, avoid it. // #ifndef PODOFO_EXTRA_CHECKS //#define PODOFO_EXTRA_CHECKS #endif //PODOFO_EXTRA_CHECKS // Error Handling Defines #include "PdfError.h" // Memory management #include "PdfMemoryManagement.h" // Include API macro definitions #include "podofoapi.h" // By default, PoDoFo will use C++ locale support to ensure that // it doesn't write bad PDF data - particularly floating point numbers. // If your standard library does not support locales this won't work, but // your STL probably writes all data in a POSIX-like way irrespective of // locale. If you set this to 0, you MUST use some other method to ensure // that streams used by PoDoFo will write data in a POSIX locale like manner. #ifndef USE_CXX_LOCALE #define USE_CXX_LOCALE 1 #endif /** * \namespace PoDoFo * * All classes, functions, types and enums of PoDoFo * are members of these namespace. * * If you use PoDoFo, you might want to add the line: * using namespace PoDoFo; * to your application. */ namespace PoDoFo { /* Explicitly big-endian short, suitable for unicode text */ typedef pdf_uint16 pdf_utf16be; /* Typedef to indicate utf-8 encoded data */ typedef unsigned char pdf_utf8; // Enums /** * Enum to identify diferent versions of the PDF file format */ enum EPdfVersion { ePdfVersion_1_0 = 0, /**< PDF 1.0 */ ePdfVersion_1_1, /**< PDF 1.1 */ ePdfVersion_1_2, /**< PDF 1.2 */ ePdfVersion_1_3, /**< PDF 1.3 */ ePdfVersion_1_4, /**< PDF 1.4 */ ePdfVersion_1_5, /**< PDF 1.5 */ ePdfVersion_1_6, /**< PDF 1.6 */ ePdfVersion_1_7 /**< PDF 1.7 */ }; /** The default PDF Version used by new PDF documents * in PoDoFo. */ const EPdfVersion ePdfVersion_Default = ePdfVersion_1_3; /** * Specify additional options for writing the PDF. */ enum EPdfWriteMode { ePdfWriteMode_Compact = 0x01, ///< Try to write the PDF as compact as possible (Default) ePdfWriteMode_Clean = 0x02, ///< Create a PDF that is readable in a text editor, i.e. insert spaces and linebreaks between tokens }; const EPdfWriteMode ePdfWriteMode_Default = ePdfWriteMode_Compact; /** * Every PDF datatype that can occur in a PDF file * is referenced by an own enum (e.g. Bool or String). * * \see PdfVariant * * Remember to update PdfVariant::GetDataTypeString() when adding members here. */ enum EPdfDataType { ePdfDataType_Bool, /**< Boolean datatype: Accepts the values "true" and "false" */ ePdfDataType_Number, /**< Number datatype for integer values */ ePdfDataType_Real, /**< Real datatype for floating point numbers */ ePdfDataType_String, /**< String datatype in PDF file. Strings have the form (Hallo World!) in PDF files. \see PdfString */ ePdfDataType_HexString, /**< HexString datatype in PDF file. Hex encoded strings have the form <AF00BE> in PDF files. \see PdfString */ ePdfDataType_Name, /**< Name datatype. Names are used as keys in dictionary to reference values. \see PdfName */ ePdfDataType_Array, /**< An array of other PDF data types. */ ePdfDataType_Dictionary, /**< A dictionary associates keys with values. A key can have another dictionary as value. */ //ePdfDataType_Stream, /**< A stream can be attached to a dictionary and contain additional data. \see PdfStream */ ePdfDataType_Null, /**< The null datatype is always null. */ ePdfDataType_Reference, /**< The reference datatype contains references to PDF objects in the PDF file of the form 4 0 R. \see PdfObject */ ePdfDataType_RawData, /**< Raw PDF data */ ePdfDataType_Unknown /**< The Datatype is unknown */ }; /** * Every filter that can be used to encode a stream * in a PDF file is referenced by an own enum value. * Common filters are ePdfFilter_FlateDecode (i.e. Zip) or * ePdfFilter_ASCIIHexDecode */ enum EPdfFilter { ePdfFilter_ASCIIHexDecode, /**< Converts data from and to hexadecimal. Increases size of the data by a factor of 2! \see PdfHexFilter */ ePdfFilter_ASCII85Decode, /**< Converts to and from Ascii85 encoding. \see PdfAscii85Filter */ ePdfFilter_LZWDecode, ePdfFilter_FlateDecode, /**< Compress data using the Flate algorithm of ZLib. This filter is recommended to be used always. \see PdfFlateFilter */ ePdfFilter_RunLengthDecode, /**< Run length decode data. \see PdfRLEFilter */ ePdfFilter_CCITTFaxDecode, ePdfFilter_JBIG2Decode, ePdfFilter_DCTDecode, ePdfFilter_JPXDecode, ePdfFilter_Crypt }; /** * Enum for the different font formats supported by PoDoFo */ enum EPdfFontType { ePdfFontType_TrueType, ePdfFontType_Type1Pfa, ePdfFontType_Type1Pfb, ePdfFontType_Type1Base14, ePdfFontType_Type3, ePdfFontType_Unknown = 0xff }; /** * Enum for the colorspaces supported * by PDF. */ enum EPdfColorSpace { ePdfColorSpace_DeviceGray, /**< Gray */ ePdfColorSpace_DeviceRGB, /**< RGB */ ePdfColorSpace_DeviceCMYK, /**< CMYK */ ePdfColorSpace_Separation, /**< Separation */ ePdfColorSpace_CieLab, /**< CIE-Lab */ ePdfColorSpace_Indexed, /**< Indexed */ ePdfColorSpace_Unknown = 0xff }; /** * Enum for text rendering mode (Tr) */ enum EPdfTextRenderingMode { ePdfTextRenderingMode_Fill = 0, /**< Default mode, fill text */ ePdfTextRenderingMode_Stroke, /**< Stroke text */ ePdfTextRenderingMode_FillAndStroke, /**< Fill, then stroke text */ ePdfTextRenderingMode_Invisible, /**< Neither fill nor stroke text (invisible) */ ePdfTextRenderingMode_FillToClipPath, /**< Fill text and add to path for clipping */ ePdfTextRenderingMode_StrokeToClipPath, /**< Stroke text and add to path for clipping */ ePdfTextRenderingMode_FillAndStrokeToClipPath, /**< Fill, then stroke text and add to path for clipping */ ePdfTextRenderingMode_ToClipPath, /**< Add text to path for clipping */ ePdfTextRenderingMode_Unknown = 0xff }; /** * Enum for the different stroke styles that can be set * when drawing to a PDF file (mostly for line drawing). */ enum EPdfStrokeStyle { ePdfStrokeStyle_Solid, ePdfStrokeStyle_Dash, ePdfStrokeStyle_Dot, ePdfStrokeStyle_DashDot, ePdfStrokeStyle_DashDotDot, ePdfStrokeStyle_Custom }; /** * Enum for predefined tiling patterns. */ enum EPdfTilingPatternType { ePdfTilingPatternType_BDiagonal = 1, ePdfTilingPatternType_Cross, ePdfTilingPatternType_DiagCross, ePdfTilingPatternType_FDiagonal, ePdfTilingPatternType_Horizontal, ePdfTilingPatternType_Vertical, ePdfTilingPatternType_Image }; /** * Enum for line cap styles when drawing. */ enum EPdfLineCapStyle { ePdfLineCapStyle_Butt = 0, ePdfLineCapStyle_Round = 1, ePdfLineCapStyle_Square = 2 }; /** * Enum for line join styles when drawing. */ enum EPdfLineJoinStyle { ePdfLineJoinStyle_Miter = 0, ePdfLineJoinStyle_Round = 1, ePdfLineJoinStyle_Bevel = 2 }; /** * Enum for vertical text alignment */ enum EPdfVerticalAlignment { ePdfVerticalAlignment_Top = 0, ePdfVerticalAlignment_Center = 1, ePdfVerticalAlignment_Bottom = 2 }; /** * Enum for text alignment */ enum EPdfAlignment { ePdfAlignment_Left = 0, ePdfAlignment_Center = 1, ePdfAlignment_Right = 2 }; /** * List of defined Rendering intents */ #define ePdfRenderingIntent_AbsoluteColorimetric "AbsoluteColorimetric" #define ePdfRenderingIntent_RelativeColorimetric "RelativeColorimetric" #define ePdfRenderingIntent_Perceptual "Perceptual" #define ePdfRenderingIntent_Saturation "Saturation" /** * List of defined transparency blending modes */ #define ePdfBlendMode_Normal "Normal" #define ePdfBlendMode_Multiply "Multiply" #define ePdfBlendMode_Screen "Screen" #define ePdfBlendMode_Overlay "Overlay" #define ePdfBlendMode_Darken "Darken" #define ePdfBlendMode_Lighten "Lighten" #define ePdfBlendMode_ColorDodge "ColorDodge" #define ePdfBlendMode_ColorBurn "ColorBurn" #define ePdfBlendMode_HardLight "HardLight" #define ePdfBlendMode_SoftLight "SoftLight" #define ePdfBlendMode_Difference "Difference" #define ePdfBlendMode_Exclusion "Exclusion" #define ePdfBlendMode_Hue "Hue" #define ePdfBlendMode_Saturation "Saturation" #define ePdfBlendMode_Color "Color" #define ePdfBlendMode_Luminosity "Luminosity" /** * Enum holding the supported page sizes by PoDoFo. * Can be used to construct a PdfRect structure with * measurements of a page object. * * \see PdfPage */ enum EPdfPageSize { ePdfPageSize_A0, /**< DIN A0 */ ePdfPageSize_A1, /**< DIN A1 */ ePdfPageSize_A2, /**< DIN A2 */ ePdfPageSize_A3, /**< DIN A3 */ ePdfPageSize_A4, /**< DIN A4 */ ePdfPageSize_A5, /**< DIN A5 */ ePdfPageSize_A6, /**< DIN A6 */ ePdfPageSize_Letter, /**< Letter */ ePdfPageSize_Legal, /**< Legal */ ePdfPageSize_Tabloid /**< Tabloid */ }; /** * Enum holding the supported of types of "PageModes" * that define which (if any) of the "panels" are opened * in Acrobat when the document is opened. * * \see PdfDocument */ enum EPdfPageMode { ePdfPageModeDontCare, ePdfPageModeUseNone, ePdfPageModeUseThumbs, ePdfPageModeUseBookmarks, ePdfPageModeFullScreen, ePdfPageModeUseOC, ePdfPageModeUseAttachments }; /** * Enum holding the supported of types of "PageLayouts" * that define how Acrobat will display the pages in * relation to each other * * \see PdfDocument */ enum EPdfPageLayout { ePdfPageLayoutIgnore, ePdfPageLayoutDefault, ePdfPageLayoutSinglePage, ePdfPageLayoutOneColumn, ePdfPageLayoutTwoColumnLeft, ePdfPageLayoutTwoColumnRight, ePdfPageLayoutTwoPageLeft, ePdfPageLayoutTwoPageRight }; /** */ const bool ePdfCreateObject = true; const bool ePdfDontCreateObject = false; // character constants #define MAX_PDF_VERSION_STRING_INDEX 7 // We use fixed bounds two dimensional arrays here so that // they go into the const data section of the library. static const char s_szPdfVersions[][9] = { "%PDF-1.0", "%PDF-1.1", "%PDF-1.2", "%PDF-1.3", "%PDF-1.4", "%PDF-1.5", "%PDF-1.6", "%PDF-1.7" }; static const char s_szPdfVersionNums[][4] = { "1.0", "1.1", "1.2", "1.3", "1.4", "1.5", "1.6", "1.7" }; /// PDF Reference, Section 3.1.1, Table 3.1, White-space characters const int s_nNumWhiteSpaces = 6; const char s_cWhiteSpaces[] = { 0x00, // NULL 0x09, // TAB 0x0A, // Line Feed 0x0C, // Form Feed 0x0D, // Carriage Return 0x20, // White Space 0x00 // end marker }; /// PDF Reference, Section 3.1.1, Character Set static const int s_nNumDelimiters = 10; static const char s_cDelimiters[] = { '(', ')', '<', '>', '[', ']', '{', '}', '/', '%', '\0' // end marker }; /** * PDF_MAX(x,y) * * \returns the maximum of x and y */ // Not actually a macro, because function-like macros are evil and // prone to nasty issues with double-evaluation of arguments. template const T PDF_MAX ( const T a, const T b ) { return (b const T PDF_MIN ( const T a, const T b ) { return (aPoDoFo is a library to work with the PDF file format and includes also a few * tools. The name comes from the first letter of PDF (Portable Document * Format). * * The PoDoFo library is a free portable C++ library which includes * classes to parse a PDF file and modify its contents into memory. The changes * can be written back to disk easily. The parser could also be used to write a * PDF viewer. Besides parsing PoDoFo includes also very simple classes to create * your own PDF files. All classes are documented so it is easy to start writing * your own application using PoDoFo. * * The PoDoFo tools are simple tools build around the PoDoFo library. These tools * are first of all examples on how to use the PoDoFo library in your own * projects. But secondly they offer also features for working with PDF * files. More tools will come with future release and the existing tools will * gain more features. Currently there are two tools: podofoimgextract (which * extracts all jpeg images from a given PDF file) and podofouncompress (which * removes all compression filters from a PDF file - this is useful for debugging * existing PDF files). * * Additionally there is the external tool PoDoFoBrowser which is not included in * this package, but can be downloaded from the PoDoFo webpage. PoDoFoBrowser is * a Qt application for browsing the objects in a PDF file and modifying their * keys easily. It is very useful if you want to look on the internal structure * of PDF files. * * As of now PoDoFo is available for Unix, Mac OS X and Windows platforms. * * More information can be found at: http://podofo.sourceforge.net * * PoDoFo is created by Dominik Seichter , * Leonard Rosenthol and Craig Ringer * * \page Codingstyle (Codingstyle) * \verbinclude CODINGSTYLE.txt * */ #endif // !PODOFO_COMPILE_RC #endif // _PDF_DEFINES_H_ podofo-0.9.3/src/base/PdfSigIncWriter.cpp0000664000175000017500000001440612277220550020100 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2014 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfSigIncWriter.h" #include "PdfData.h" #include "PdfDate.h" #include "PdfDictionary.h" #include "PdfObject.h" #include "PdfParser.h" #include "PdfStream.h" #include "PdfVariant.h" #include "PdfXRef.h" #include "PdfXRefStream.h" #include "PdfDefinesPrivate.h" #include #include namespace PoDoFo { PdfSigIncWriter::PdfSigIncWriter( PdfVecObjects* pVecObjects, const PdfObject* pTrailer ) : PdfWriter(pVecObjects, pTrailer) { } PdfSigIncWriter::~PdfSigIncWriter() { } void PdfSigIncWriter::Write( PdfOutputDevice* pDevice, pdf_int64 prevOffset) { //CreateFileIdentifier( m_identifier, m_pTrailer ); if( m_pTrailer->GetDictionary().HasKey( "ID" ) ) { PdfObject *idObj = m_pTrailer->GetDictionary().GetKey("ID"); TCIVariantList it = idObj->GetArray().begin(); while( it != idObj->GetArray().end() ) { if( (*it).GetDataType() == ePdfDataType_HexString ) { PdfVariant var = (*it); m_identifier = var.GetString(); } ++it; } } else { PdfDate date; PdfString dateString; PdfObject* pInfo; PdfOutputDevice length; date.ToString( dateString ); pInfo = new PdfObject(); pInfo->GetDictionary().AddKey( "CreationDate", dateString ); pInfo->GetDictionary().AddKey( "Creator", PdfString("PoDoFo") ); pInfo->GetDictionary().AddKey( "Producer", PdfString("PoDoFo") ); pInfo->GetDictionary().AddKey( "Location", PdfString("SOMEFILENAME") ); pInfo->WriteObject( &length, ePdfWriteMode_Clean, NULL ); char *pBuffer = static_cast(malloc( sizeof(char) * length.GetLength() )); if( !pBuffer ) { delete pInfo; PODOFO_RAISE_ERROR( ePdfError_OutOfMemory ); } PdfOutputDevice device( pBuffer, length.GetLength() ); pInfo->WriteObject( &device, ePdfWriteMode_Clean, NULL ); // calculate the MD5 Sum m_identifier = PdfEncryptMD5Base::GetMD5String( reinterpret_cast(pBuffer), static_cast(length.GetLength()) ); free( pBuffer ); delete pInfo; } if( !pDevice ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } // setup encrypt dictionary if( m_pEncrypt ) { m_pEncrypt->GenerateEncryptionKey( m_identifier ); // Add our own Encryption dictionary m_pEncryptObj = m_vecObjects->CreateObject(); m_pEncrypt->CreateEncryptionDictionary( m_pEncryptObj->GetDictionary() ); } if( GetLinearized() ) { this->WriteLinearized( pDevice ); } else { PdfXRef* pXRef = m_bXRefStream ? new PdfXRefStream( m_vecObjects, this ) : new PdfXRef(); try { // WritePdfHeader ( pDevice ); WritePdfObjects ( pDevice, *m_vecObjects, pXRef ); pXRef->SetFirstEmptyBlock(); pXRef->Write( pDevice ); // XRef streams contain the trailer in the XRef if( !m_bXRefStream ) { PdfObject trailer; // if we have a dummy offset we write also a prev entry to the trailer FillTrailerObject( &trailer, pXRef->GetSize(), false, false ); PdfObject prevOffsetObj(prevOffset); trailer.GetDictionary().AddKey( "Prev", prevOffsetObj); pDevice->Print("trailer\n"); trailer.WriteObject( pDevice, ePdfWriteMode_Clean, NULL ); // Do not encrypt the trailer dicionary!!! } pDevice->Print( "startxref\n%li\n%%%%EOF\n", pXRef->GetOffset()); delete pXRef; } catch( PdfError & e ) { // Make sure pXRef is always deleted delete pXRef; e.AddToCallstack( __FILE__, __LINE__ ); throw e; } } } }; podofo-0.9.3/src/base/PdfData.h0000664000175000017500000001213212344436402016037 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2007 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_DATA_H_ #define _PDF_DATA_H_ #include "PdfDefines.h" #include "PdfDataType.h" namespace PoDoFo { class PdfOutputDevice; /** A datatype that allows to write abitrary data * to a PDF file. * The user of this class has to ensure that the data * written to the PDF file using this class is valid data * for a PDF file! * * This class is used in PoDoFo to pad PdfVariants. * */ class PODOFO_API PdfData : public PdfDataType { public: /** * Create a new PdfData object with valid PdfData * * The contained data has to be a valid value in a PDF file. * It will be written directly to the PDF file. * * \param pszData a null-terminated string to be copied. */ PdfData( const char* pszData ) : PdfDataType(), m_sData( pszData ) { } /** * Create a new PdfData object with valid PdfData. * * \param pszData a char * buffer to be copied. * \param dataSize size of buffer */ PdfData( const char* pszData, size_t dataSize ) : PdfDataType(), m_sData( pszData, dataSize ) { } /** Copy an existing PdfData * \param rhs another PdfData to copy */ PdfData( const PdfData & rhs ) : PdfDataType() { this->operator=( rhs ); } /** Write the complete datatype to a file. * \param pDevice write the object to this device * \param eWriteMode additional options for writing this object * \param pEncrypt an encryption object which is used to encrypt this object * or NULL to not encrypt this object * * PdfData cannot do any encryption for you. So the encryption object will * be ignored as it is also the case for the write mode! */ void Write( PdfOutputDevice* pDevice, EPdfWriteMode eWriteMode, const PdfEncrypt* pEncrypt = NULL ) const; /** Copy an existing PdfData * \param rhs another PdfData to copy * \returns this object */ inline const PdfData & operator=( const PdfData & rhs ); /** * Access the data as a std::string * \returns a const reference to the contained data */ inline const std::string & data() const; private: std::string m_sData; }; // ----------------------------------------------------- // // ----------------------------------------------------- const PdfData & PdfData::operator=( const PdfData & rhs ) { m_sData = rhs.m_sData; return (*this); } // ----------------------------------------------------- // // ----------------------------------------------------- const std::string & PdfData::data() const { return m_sData; } }; // namespace PoDoFo #endif /* _PDF_DATATYPE_H_ */ podofo-0.9.3/src/base/util/0000775000175000017500000000000012356565166015356 5ustar dominikdominikpodofo-0.9.3/src/base/util/PdfMutexImpl_pthread.h0000664000175000017500000001042212344436402021576 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2008 by Dominik Seichter, Craig Ringer * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "../PdfDefines.h" #include "../PdfDefinesPrivate.h" #if ! defined(PODOFO_MULTI_THREAD) #error "Not a multi-thread build. PdfMutex_null.h should be used instead" #endif #if defined(_WIN32) #error "win32 build. PdfMutex_win32.h should be used instead" #endif #include #include namespace PoDoFo { namespace Util { /** * A platform independent reentrant mutex, pthread implementation. * * PdfMutex is *NOT* part of PoDoFo's public API. * * This is the pthread implementation, which is * entirely inline. */ class PdfMutexImpl { pthread_mutex_t m_mutex; public: inline PdfMutexImpl(); inline ~PdfMutexImpl(); inline void Init( const pthread_mutexattr_t *attr ); /** * Lock the mutex */ inline void Lock(); /** * Try locking the mutex. * * \returns true if the mutex was locked * \returns false if the mutex is already locked * by some other thread */ inline bool TryLock(); /** * Unlock the mutex */ inline void UnLock(); }; PdfMutexImpl::PdfMutexImpl() { pthread_mutexattr_t attr; pthread_mutexattr_init(&attr); pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); pthread_mutex_init( &m_mutex, &attr ); } PdfMutexImpl::~PdfMutexImpl() { pthread_mutex_destroy( &m_mutex ); } void PdfMutexImpl::Lock() { if( pthread_mutex_lock( &m_mutex ) != 0 ) { PODOFO_RAISE_ERROR( ePdfError_MutexError ); } } bool PdfMutexImpl::TryLock() { int nRet = pthread_mutex_trylock( &m_mutex ); if( nRet == 0 ) return true; else if( nRet == EBUSY ) return false; else { PODOFO_RAISE_ERROR( ePdfError_MutexError ); } } void PdfMutexImpl::UnLock() { if( pthread_mutex_unlock( &m_mutex ) != 0 ) { PODOFO_RAISE_ERROR( ePdfError_MutexError ); } } }; // Util }; // PoDoFo podofo-0.9.3/src/base/util/PdfMutex.h0000664000175000017500000000761612344436402017260 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2008 by Dominik Seichter, Craig Ringer * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef PDF_PDFMUTEX_H #define PDF_PDFMUTEX_H #if defined(BUILDING_PODOFO) /* Import the platform-specific implementation of PdfMutex */ #if defined(PODOFO_MULTI_THREAD) # if defined(_WIN32) # include "PdfMutexImpl_win32.h" # else # include "PdfMutexImpl_pthread.h" # endif #else # include "PdfMutexImpl_noop.h" #endif namespace PoDoFo { namespace Util { /** * Reentrant mutex implemented by win32 CRITICAL_SECTION or pthread recursive mutex. * * If PODOFO_MULTI_THREAD is not set, all operations are no-ops and always succeed. * * A held (locked) PdfMutex may not be acquired (locked) by a thread other than * the thread that currently holds it. * * The thread holding a PdfMutex may acquire it repeatedly. Every acquision must be matched * by a release. * * When a PdfMutex is not held by any thread (ie it is newly allocated or has been released) * then exactly one thread attempting to acquire it will succeed. If there is more than one * thread trying to acquire a PdfMutex, which thread will succeed is undefined. * */ class PdfMutex : public PdfMutexImpl { // This wrapper/extension class is provided so we can add platform-independent // functionality and helpers if desired. public: PdfMutex() { } ~PdfMutex() { } }; };}; #else // BUILDING_PODOFO // Only a forward-declaration is available for PdfMutex for sources outside the // PoDoFo library build its self. PdfMutex is not public API. namespace PoDoFo { namespace Util { class PdfMutex; }; }; #endif #endif podofo-0.9.3/src/base/util/PdfMutexImpl_win32.h0000664000175000017500000000725312344436402021121 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2008 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "../PdfDefines.h" #include "../PdfDefinesPrivate.h" #if ! defined(PODOFO_MULTI_THREAD) #error "Not a multi-thread build. PdfMutex_null.h should be used instead" #endif #if !defined(_WIN32) #error "Wrong PdfMutex implementation included!" #endif namespace PoDoFo { namespace Util { /** * A platform independent reentrant mutex, win32 implementation. */ class PdfMutexImpl { public: /** Construct a new mutex */ inline PdfMutexImpl(); inline ~PdfMutexImpl(); /** * Lock the mutex */ inline void Lock(); /** * Try locking the mutex. * * \returns true if the mutex was locked * \returns false if the mutex is already locked * by some other thread */ inline bool TryLock(); /** * Unlock the mutex */ inline void UnLock(); private: CRITICAL_SECTION m_cs; }; PdfMutexImpl::PdfMutexImpl() { InitializeCriticalSection( &m_cs ); } PdfMutexImpl::~PdfMutexImpl() { DeleteCriticalSection( &m_cs ); } void PdfMutexImpl::Lock() { EnterCriticalSection( &m_cs ); } bool PdfMutexImpl::TryLock() { return (TryEnterCriticalSection( &m_cs ) ? true : false); } void PdfMutexImpl::UnLock() { LeaveCriticalSection( &m_cs ); } }; // Util }; // PoDoFo podofo-0.9.3/src/base/util/PdfMutexImpl_noop.h0000664000175000017500000000654112344436402021131 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2008 by Dominik Seichter, Craig Ringer * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "../PdfDefines.h" #include "../PdfDefinesPrivate.h" #if defined(PODOFO_MULTI_THREAD) #error "Multi-thread build, a real PdfMutex implementation should be used instead" #endif namespace PoDoFo { namespace Util { /** * A platform independent non-reentrant mutex, no-op implementation. * This version is used if PoDoFo is built without threading support. * * PdfMutex is *NOT* part of PoDoFo's public API. */ class PdfMutexImpl { public: /** Construct a new mutex */ inline PdfMutexImpl() { } inline ~PdfMutexImpl() { } /** * Lock the mutex */ inline void Lock() { } /** * Try locking the mutex. * * \returns true if the mutex was locked * \returns false if the mutex is already locked * by some other thread */ inline bool TryLock() { return true; } /** * Unlock the mutex */ inline void UnLock() { } }; }; // Util }; // PoDoFo podofo-0.9.3/src/base/util/PdfMutexWrapper.h0000664000175000017500000000747712344436402020626 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2008 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_MUTEX_WRAPPER_H_ #define _PDF_MUTEX_WRAPPER_H_ #include "../PdfDefines.h" #include "PdfMutex.h" namespace PoDoFo { namespace Util { /** * A wrapper around PdfMutex. * The mutex is locked in the constructor * and unlocked in the destructor. * * In debug builds all exceptions thrown by the mutex implementation * are caught and logged before being rethrown. * * Note that PdfMutexWrapper is *not* part of PoDoFo's public API. */ class PdfMutexWrapper { public: /** Lock a mutex. * * \param rMutex the mutex to be locked. */ PODOFO_NOTHROW inline PdfMutexWrapper( PdfMutex & rMutex ); /** Unlocks the mutex on destruction */ inline ~PdfMutexWrapper(); private: /** default constructor, not implemented */ PdfMutexWrapper(void); /** copy constructor, not implemented */ PdfMutexWrapper(const PdfMutexWrapper& rhs); /** assignment operator, not implemented */ PdfMutexWrapper& operator=(const PdfMutexWrapper& rhs); PdfMutex& m_rMutex; }; PdfMutexWrapper::PdfMutexWrapper( PdfMutex & rMutex ) : m_rMutex( rMutex ) { m_rMutex.Lock(); } PdfMutexWrapper::~PdfMutexWrapper() { #if defined(DEBUG) try { m_rMutex.UnLock(); } catch( const PdfError & rError ) { rError.PrintErrorMsg(); throw rError; } #else m_rMutex.UnLock(); #endif } }; // Util }; // PoDoFo #endif // _PDF_MUTEX_H_ podofo-0.9.3/src/base/PdfFiltersPrivate.h0000664000175000017500000007617412344436402020151 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2007 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_FILTERS_PRIVATE_H_ #define _PDF_FILTERS_PRIVATE_H_ /** * \file PdfFiltersPrivate.h * * Provides implementations of various PDF stream filters. * * This is an internal header. It should not be included in podofo.h, and * should not be included directly by client applications. These filters should * only be accessed through the factory interface in PdfFilters.h . */ #include "PdfDefines.h" #include "PdfDefinesPrivate.h" #include "PdfFilter.h" #include "PdfRefCountedBuffer.h" #include #ifdef PODOFO_HAVE_JPEG_LIB extern "C" { #ifdef _WIN32 // Collision between win and jpeg-headers #define XMD_H #undef FAR #endif #include "jpeglib.h" } #endif // PODOFO_HAVE_JPEG_LIB #ifdef PODOFO_HAVE_TIFF_LIB extern "C" { #include "tiffio.h" #ifdef _WIN32 // Collision between tiff and jpeg-headers #define XMD_H #undef FAR #endif } #endif // PODOFO_HAVE_TIFF_LIB namespace PoDoFo { #define PODOFO_FILTER_INTERNAL_BUFFER_SIZE 4096 class PdfPredictorDecoder; class PdfOutputDevice; /** The ascii hex filter. */ class PdfHexFilter : public PdfFilter { public: virtual ~PdfHexFilter() { } /** Check wether the encoding is implemented for this filter. * * \returns true if the filter is able to encode data */ inline virtual bool CanEncode() const; /** Encode a block of data and write it to the PdfOutputStream * specified by BeginEncodeImpl. * * BeginEncodeImpl() has to be called before this function. * * \param pBuffer pointer to a buffer with data to encode * \param lLen length of data to encode. * * Call EndEncodeImpl() after all data has been encoded * * * \see BeginEncodeImpl * \see EndEncodeImpl */ virtual void EncodeBlockImpl( const char* pBuffer, pdf_long lLen ); /** Check wether the decoding is implemented for this filter. * * \returns true if the filter is able to decode data */ inline virtual bool CanDecode() const; /** Real implementation of `BeginDecode()'. NEVER call this method directly. * * By default this function does nothing. If your filter needs to do setup for decoding, * you should override this method. * * PdfFilter ensures that a valid stream is available when this method is called, and * that EndDecode() was called since the last BeginDecode()/DecodeBlock(). * * \see BeginDecode */ virtual void BeginDecodeImpl( const PdfDictionary* ); /** Real implementation of `DecodeBlock()'. NEVER call this method directly. * * You must override this method to decode the buffer passed by the caller. * * You are not obliged to immediately process any or all of the data in * the passed buffer, but you must ensure that you have processed it and * written it out by the end of EndDecodeImpl(). You must copy the buffer * if you're going to store it, as ownership is not transferred to the * filter and the caller may free the buffer at any time. * * PdfFilter ensures that a valid stream is available when this method is * called, ensures that BeginDecode() has been called, and ensures that * EndDecode() has not been called since the last BeginDecode(). * * \see DecodeBlock */ virtual void DecodeBlockImpl( const char* pBuffer, pdf_long lLen ); /** Real implementation of `EndDecode()'. NEVER call this method directly. * * By the time this method returns, all filtered data must be written to the stream * and the filter must be in a state where BeginDecode() can be safely called. * * PdfFilter ensures that a valid stream is available when this method is * called, and ensures that BeginDecodeImpl() has been called. * * \see EndDecode */ virtual void EndDecodeImpl(); /** GetType of this filter. * \returns the GetType of this filter */ inline virtual EPdfFilter GetType() const; private: char m_cDecodedByte; bool m_bLow; }; // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfHexFilter::CanEncode() const { return true; } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfHexFilter::CanDecode() const { return true; } // ----------------------------------------------------- // // ----------------------------------------------------- EPdfFilter PdfHexFilter::GetType() const { return ePdfFilter_ASCIIHexDecode; } /** The Ascii85 filter. */ class PdfAscii85Filter : public PdfFilter { public: virtual ~PdfAscii85Filter() { } /** Check wether the encoding is implemented for this filter. * * \returns true if the filter is able to encode data */ inline virtual bool CanEncode() const; /** Begin encoding data using this filter. Called by PdfFilter::BeginEncode. * * \see EncodeBlockImpl * \see EndEncodeImpl * \see PdfFilter::BeginEncode */ virtual void BeginEncodeImpl(); /** Encode a block of data and write it to the PdfOutputStream * specified by BeginEncodeImpl. * * BeginEncodeImpl() has to be called before this function. * * \param pBuffer pointer to a buffer with data to encode * \param lLen length of data to encode. * * Call EndEncodeImpl() after all data has been encoded * * * \see BeginEncodeImpl * \see EndEncodeImpl */ virtual void EncodeBlockImpl( const char* pBuffer, pdf_long lLen ); /** * Finish encoding of data. * * \see BeginEncodeImpl * \see EncodeBlockImpl */ virtual void EndEncodeImpl(); /** Check wether the decoding is implemented for this filter. * * \returns true if the filter is able to decode data */ inline virtual bool CanDecode() const; /** Real implementation of `BeginDecode()'. NEVER call this method directly. * * By default this function does nothing. If your filter needs to do setup for decoding, * you should override this method. * * PdfFilter ensures that a valid stream is available when this method is called, and * that EndDecode() was called since the last BeginDecode()/DecodeBlock(). * * \see BeginDecode */ virtual void BeginDecodeImpl( const PdfDictionary* ); /** Real implementation of `DecodeBlock()'. NEVER call this method directly. * * You must override this method to decode the buffer passed by the caller. * * You are not obliged to immediately process any or all of the data in * the passed buffer, but you must ensure that you have processed it and * written it out by the end of EndDecodeImpl(). You must copy the buffer * if you're going to store it, as ownership is not transferred to the * filter and the caller may free the buffer at any time. * * PdfFilter ensures that a valid stream is available when this method is * called, ensures that BeginDecode() has been called, and ensures that * EndDecode() has not been called since the last BeginDecode(). * * \see DecodeBlock */ virtual void DecodeBlockImpl( const char* pBuffer, pdf_long lLen ); /** Real implementation of `EndDecode()'. NEVER call this method directly. * * By the time this method returns, all filtered data must be written to the stream * and the filter must be in a state where BeginDecode() can be safely called. * * PdfFilter ensures that a valid stream is available when this method is * called, and ensures that BeginDecodeImpl() has been called. * * \see EndDecode */ virtual void EndDecodeImpl(); /** GetType of this filter. * \returns the GetType of this filter */ inline virtual EPdfFilter GetType() const; private: void EncodeTuple ( unsigned long tuple, int bytes ); void WidePut( unsigned long tuple, int bytes ) const; private: int m_count; unsigned long m_tuple; }; // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfAscii85Filter::CanEncode() const { return true; } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfAscii85Filter::CanDecode() const { return true; } // ----------------------------------------------------- // // ----------------------------------------------------- EPdfFilter PdfAscii85Filter::GetType() const { return ePdfFilter_ASCII85Decode; } /** The flate filter. */ class PdfFlateFilter : public PdfFilter { public: PdfFlateFilter(); virtual ~PdfFlateFilter(); /** Check wether the encoding is implemented for this filter. * * \returns true if the filter is able to encode data */ inline virtual bool CanEncode() const; /** Begin encoding data using this filter. Called by PdfFilter::BeginEncode. * * \see EncodeBlockImpl * \see EndEncodeImpl * \see PdfFilter::BeginEncode */ virtual void BeginEncodeImpl(); /** Encode a block of data and write it to the PdfOutputStream * specified by BeginEncodeImpl. * * BeginEncodeImpl() has to be called before this function. * * \param pBuffer pointer to a buffer with data to encode * \param lLen length of data to encode. * * Call EndEncodeImpl() after all data has been encoded * * * \see BeginEncodeImpl * \see EndEncodeImpl */ virtual void EncodeBlockImpl( const char* pBuffer, pdf_long lLen ); /** * Finish encoding of data. * * \see BeginEncodeImpl * \see EncodeBlockImpl */ virtual void EndEncodeImpl(); /** Check wether the decoding is implemented for this filter. * * \returns true if the filter is able to decode data */ inline virtual bool CanDecode() const; /** Real implementation of `BeginDecode()'. NEVER call this method directly. * * By default this function does nothing. If your filter needs to do setup for decoding, * you should override this method. * * PdfFilter ensures that a valid stream is available when this method is called, and * that EndDecode() was called since the last BeginDecode()/DecodeBlock(). * * \param pDecodeParms additional parameters for decoding data * * \see BeginDecode */ virtual void BeginDecodeImpl( const PdfDictionary* pDecodeParms ); /** Real implementation of `DecodeBlock()'. NEVER call this method directly. * * You must override this method to decode the buffer passed by the caller. * * You are not obliged to immediately process any or all of the data in * the passed buffer, but you must ensure that you have processed it and * written it out by the end of EndDecodeImpl(). You must copy the buffer * if you're going to store it, as ownership is not transferred to the * filter and the caller may free the buffer at any time. * * PdfFilter ensures that a valid stream is available when this method is * called, ensures that BeginDecode() has been called, and ensures that * EndDecode() has not been called since the last BeginDecode(). * * \see DecodeBlock */ virtual void DecodeBlockImpl( const char* pBuffer, pdf_long lLen ); /** Real implementation of `EndDecode()'. NEVER call this method directly. * * By the time this method returns, all filtered data must be written to the stream * and the filter must be in a state where BeginDecode() can be safely called. * * PdfFilter ensures that a valid stream is available when this method is * called, and ensures that BeginDecodeImpl() has been called. * * \see EndDecode */ virtual void EndDecodeImpl(); /** GetType of this filter. * \returns the GetType of this filter */ inline virtual EPdfFilter GetType() const; private: void EncodeBlockInternal( const char* pBuffer, pdf_long lLen, int nMode ); private: unsigned char m_buffer[PODOFO_FILTER_INTERNAL_BUFFER_SIZE]; z_stream m_stream; PdfPredictorDecoder* m_pPredictor; }; // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfFlateFilter::CanEncode() const { return true; } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfFlateFilter::CanDecode() const { return true; } // ----------------------------------------------------- // // ----------------------------------------------------- EPdfFilter PdfFlateFilter::GetType() const { return ePdfFilter_FlateDecode; } /** The RLE filter. */ class PdfRLEFilter : public PdfFilter { public: virtual ~PdfRLEFilter() {} /** Check wether the encoding is implemented for this filter. * * \returns true if the filter is able to encode data */ inline virtual bool CanEncode() const; virtual void BeginEncodeImpl(); /** Encode a block of data and write it to the PdfOutputStream * specified by BeginEncodeImpl. * * BeginEncodeImpl() has to be called before this function. * * \param pBuffer pointer to a buffer with data to encode * \param lLen length of data to encode. * * Call EndEncodeImpl() after all data has been encoded * * * \see BeginEncodeImpl * \see EndEncodeImpl */ virtual void EncodeBlockImpl( const char* pBuffer, pdf_long lLen ); /** * Finish encoding of data. * * \see BeginEncodeImpl * \see EncodeBlockImpl */ virtual void EndEncodeImpl(); /** Check wether the decoding is implemented for this filter. * * \returns true if the filter is able to decode data */ inline virtual bool CanDecode() const; /** Real implementation of `BeginDecode()'. NEVER call this method directly. * * By default this function does nothing. If your filter needs to do setup for decoding, * you should override this method. * * PdfFilter ensures that a valid stream is available when this method is called, and * that EndDecode() was called since the last BeginDecode()/DecodeBlock(). * * \see BeginDecode */ virtual void BeginDecodeImpl( const PdfDictionary* ); /** Real implementation of `DecodeBlock()'. NEVER call this method directly. * * You must override this method to decode the buffer passed by the caller. * * You are not obliged to immediately process any or all of the data in * the passed buffer, but you must ensure that you have processed it and * written it out by the end of EndDecodeImpl(). You must copy the buffer * if you're going to store it, as ownership is not transferred to the * filter and the caller may free the buffer at any time. * * PdfFilter ensures that a valid stream is available when this method is * called, ensures that BeginDecode() has been called, and ensures that * EndDecode() has not been called since the last BeginDecode(). * * \see DecodeBlock */ virtual void DecodeBlockImpl( const char* pBuffer, pdf_long lLen ); /** GetType of this filter. * \returns the GetType of this filter */ inline virtual EPdfFilter GetType() const; private: int m_nCodeLen; }; // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfRLEFilter::CanEncode() const { return false; } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfRLEFilter::CanDecode() const { return true; } // ----------------------------------------------------- // // ----------------------------------------------------- EPdfFilter PdfRLEFilter::GetType() const { return ePdfFilter_RunLengthDecode; } /** The LZW filter. */ class PdfLZWFilter : public PdfFilter { struct TLzwItem { std::vector value; }; typedef std::vector TLzwTable; typedef TLzwTable::iterator TILzwTable; typedef TLzwTable::const_iterator TCILzwTable; public: PdfLZWFilter(); virtual ~PdfLZWFilter(); /** Check wether the encoding is implemented for this filter. * * \returns true if the filter is able to encode data */ inline virtual bool CanEncode() const; /** Begin encoding data using this filter. Called by PdfFilter::BeginEncode. * * \see EncodeBlockImpl * \see EndEncodeImpl * \see PdfFilter::BeginEncode */ virtual void BeginEncodeImpl(); /** Encode a block of data and write it to the PdfOutputStream * specified by BeginEncodeImpl. * * BeginEncodeImpl() has to be called before this function. * * \param pBuffer pointer to a buffer with data to encode * \param lLen length of data to encode. * * Call EndEncodeImpl() after all data has been encoded * * * \see BeginEncodeImpl * \see EndEncodeImpl */ virtual void EncodeBlockImpl( const char* pBuffer, pdf_long lLen ); /** * Finish encoding of data. * * \see BeginEncodeImpl * \see EncodeBlockImpl */ virtual void EndEncodeImpl(); /** Check wether the decoding is implemented for this filter. * * \returns true if the filter is able to decode data */ inline virtual bool CanDecode() const; /** Real implementation of `BeginDecode()'. NEVER call this method directly. * * By default this function does nothing. If your filter needs to do setup for decoding, * you should override this method. * * PdfFilter ensures that a valid stream is available when this method is called, and * that EndDecode() was called since the last BeginDecode()/DecodeBlock(). * * \see BeginDecode */ virtual void BeginDecodeImpl( const PdfDictionary* ); /** Real implementation of `DecodeBlock()'. NEVER call this method directly. * * You must override this method to decode the buffer passed by the caller. * * You are not obliged to immediately process any or all of the data in * the passed buffer, but you must ensure that you have processed it and * written it out by the end of EndDecodeImpl(). You must copy the buffer * if you're going to store it, as ownership is not transferred to the * filter and the caller may free the buffer at any time. * * PdfFilter ensures that a valid stream is available when this method is * called, ensures that BeginDecode() has been called, and ensures that * EndDecode() has not been called since the last BeginDecode(). * * \see DecodeBlock */ virtual void DecodeBlockImpl( const char* pBuffer, pdf_long lLen ); /** Real implementation of `EndDecode()'. NEVER call this method directly. * * By the time this method returns, all filtered data must be written to the stream * and the filter must be in a state where BeginDecode() can be safely called. * * PdfFilter ensures that a valid stream is available when this method is * called, and ensures that BeginDecodeImpl() has been called. * * \see EndDecode */ virtual void EndDecodeImpl(); /** GetType of this filter. * \returns the GetType of this filter */ inline virtual EPdfFilter GetType() const; private: /** Initialize an lzw table. */ void InitTable(); private: static const unsigned short s_masks[4]; static const unsigned short s_clear; static const unsigned short s_eod; TLzwTable m_table; unsigned int m_mask; unsigned int m_code_len; unsigned char m_character; bool m_bFirst; PdfPredictorDecoder* m_pPredictor; }; // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfLZWFilter::CanEncode() const { return false; } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfLZWFilter::CanDecode() const { return true; } // ----------------------------------------------------- // // ----------------------------------------------------- EPdfFilter PdfLZWFilter::GetType() const { return ePdfFilter_LZWDecode; } #ifdef PODOFO_HAVE_JPEG_LIB void PODOFO_API jpeg_memory_src (j_decompress_ptr cinfo, const JOCTET * buffer, size_t bufsize); /** The DCT filter can decoded JPEG compressed data. * * This filter requires JPEG lib to be available */ class PdfDCTFilter : public PdfFilter { public: PdfDCTFilter(); virtual ~PdfDCTFilter(); /** Check wether the encoding is implemented for this filter. * * \returns true if the filter is able to encode data */ inline virtual bool CanEncode() const; /** Begin encoding data using this filter. Called by PdfFilter::BeginEncode. * * \see EncodeBlockImpl * \see EndEncodeImpl * \see PdfFilter::BeginEncode */ virtual void BeginEncodeImpl(); /** Encode a block of data and write it to the PdfOutputStream * specified by BeginEncodeImpl. * * BeginEncodeImpl() has to be called before this function. * * \param pBuffer pointer to a buffer with data to encode * \param lLen length of data to encode. * * Call EndEncodeImpl() after all data has been encoded * * * \see BeginEncodeImpl * \see EndEncodeImpl */ virtual void EncodeBlockImpl( const char* pBuffer, pdf_long lLen ); /** * Finish encoding of data. * * \see BeginEncodeImpl * \see EncodeBlockImpl */ virtual void EndEncodeImpl(); /** Check wether the decoding is implemented for this filter. * * \returns true if the filter is able to decode data */ inline virtual bool CanDecode() const; /** Real implementation of `BeginDecode()'. NEVER call this method directly. * * By default this function does nothing. If your filter needs to do setup for decoding, * you should override this method. * * PdfFilter ensures that a valid stream is available when this method is called, and * that EndDecode() was called since the last BeginDecode()/DecodeBlock(). * * \see BeginDecode */ virtual void BeginDecodeImpl( const PdfDictionary* ); /** Real implementation of `DecodeBlock()'. NEVER call this method directly. * * You must override this method to decode the buffer passed by the caller. * * You are not obliged to immediately process any or all of the data in * the passed buffer, but you must ensure that you have processed it and * written it out by the end of EndDecodeImpl(). You must copy the buffer * if you're going to store it, as ownership is not transferred to the * filter and the caller may free the buffer at any time. * * PdfFilter ensures that a valid stream is available when this method is * called, ensures that BeginDecode() has been called, and ensures that * EndDecode() has not been called since the last BeginDecode(). * * \see DecodeBlock */ virtual void DecodeBlockImpl( const char* pBuffer, pdf_long lLen ); /** Real implementation of `EndDecode()'. NEVER call this method directly. * * By the time this method returns, all filtered data must be written to the stream * and the filter must be in a state where BeginDecode() can be safely called. * * PdfFilter ensures that a valid stream is available when this method is * called, and ensures that BeginDecodeImpl() has been called. * * \see EndDecode */ virtual void EndDecodeImpl(); /** GetType of this filter. * \returns the GetType of this filter */ inline virtual EPdfFilter GetType() const; private: struct jpeg_decompress_struct m_cinfo; struct jpeg_error_mgr m_jerr; PdfRefCountedBuffer m_buffer; PdfOutputDevice* m_pDevice; }; // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfDCTFilter::CanEncode() const { return false; } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfDCTFilter::CanDecode() const { return true; } // ----------------------------------------------------- // // ----------------------------------------------------- EPdfFilter PdfDCTFilter::GetType() const { return ePdfFilter_DCTDecode; } #endif // PODOFO_HAVE_JPEG_LIB #ifdef PODOFO_HAVE_TIFF_LIB /** The CCITT filter can decoded CCITTFaxDecode compressed data. * * This filter requires TIFFlib to be available */ class PdfCCITTFilter : public PdfFilter { public: PdfCCITTFilter(); virtual ~PdfCCITTFilter(); /** Check wether the encoding is implemented for this filter. * * \returns true if the filter is able to encode data */ inline virtual bool CanEncode() const; /** Begin encoding data using this filter. Called by PdfFilter::BeginEncode. * * \see EncodeBlockImpl * \see EndEncodeImpl * \see PdfFilter::BeginEncode */ virtual void BeginEncodeImpl(); /** Encode a block of data and write it to the PdfOutputStream * specified by BeginEncodeImpl. * * BeginEncodeImpl() has to be called before this function. * * \param pBuffer pointer to a buffer with data to encode * \param lLen length of data to encode. * * Call EndEncodeImpl() after all data has been encoded * * * \see BeginEncodeImpl * \see EndEncodeImpl */ virtual void EncodeBlockImpl( const char* pBuffer, pdf_long lLen ); /** * Finish encoding of data. * * \see BeginEncodeImpl * \see EncodeBlockImpl */ virtual void EndEncodeImpl(); /** Check wether the decoding is implemented for this filter. * * \returns true if the filter is able to decode data */ inline virtual bool CanDecode() const; /** Real implementation of `BeginDecode()'. NEVER call this method directly. * * By default this function does nothing. If your filter needs to do setup for decoding, * you should override this method. * * PdfFilter ensures that a valid stream is available when this method is called, and * that EndDecode() was called since the last BeginDecode()/DecodeBlock(). * * \see BeginDecode */ virtual void BeginDecodeImpl( const PdfDictionary* ); /** Real implementation of `DecodeBlock()'. NEVER call this method directly. * * You must override this method to decode the buffer passed by the caller. * * You are not obliged to immediately process any or all of the data in * the passed buffer, but you must ensure that you have processed it and * written it out by the end of EndDecodeImpl(). You must copy the buffer * if you're going to store it, as ownership is not transferred to the * filter and the caller may free the buffer at any time. * * PdfFilter ensures that a valid stream is available when this method is * called, ensures that BeginDecode() has been called, and ensures that * EndDecode() has not been called since the last BeginDecode(). * * \see DecodeBlock */ virtual void DecodeBlockImpl( const char* pBuffer, pdf_long lLen ); /** Real implementation of `EndDecode()'. NEVER call this method directly. * * By the time this method returns, all filtered data must be written to the stream * and the filter must be in a state where BeginDecode() can be safely called. * * PdfFilter ensures that a valid stream is available when this method is * called, and ensures that BeginDecodeImpl() has been called. * * \see EndDecode */ virtual void EndDecodeImpl(); /** GetType of this filter. * \returns the GetType of this filter */ inline virtual EPdfFilter GetType() const; private: TIFF* m_tiff; }; // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfCCITTFilter::CanEncode() const { return false; } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfCCITTFilter::CanDecode() const { return true; } // ----------------------------------------------------- // // ----------------------------------------------------- EPdfFilter PdfCCITTFilter::GetType() const { return ePdfFilter_CCITTFaxDecode; } #endif // PODOFO_HAVE_TIFF_LIB }; #endif /* _PDF_FILTERS_PRIVATE_H_ */ podofo-0.9.3/src/base/PdfOutputDevice.cpp0000664000175000017500000002533512347271543020160 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2006 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfOutputDevice.h" #include "PdfRefCountedBuffer.h" #include "PdfDefinesPrivate.h" #include #include namespace PoDoFo { PdfOutputDevice::PdfOutputDevice() { this->Init(); } PdfOutputDevice::PdfOutputDevice( const char* pszFilename ) { this->Init(); if( !pszFilename ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } std::fstream *pStream = new std::fstream(pszFilename, std::fstream::binary|std::ios_base::in | std::ios_base::out | std::ios_base::trunc); if(pStream->fail()) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } m_pStream = pStream; m_pReadStream = pStream; PdfLocaleImbue(*m_pStream); /* m_hFile = fopen( pszFilename, "wb" ); if( !m_hFile ) { PODOFO_RAISE_ERROR_INFO( ePdfError_FileNotFound, pszFilename ); } */ } #ifdef _WIN32 PdfOutputDevice::PdfOutputDevice( const wchar_t* pszFilename ) { this->Init(); if( !pszFilename ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } m_hFile = _wfopen( pszFilename, L"w+b" ); if( !m_hFile ) { PdfError e( ePdfError_FileNotFound, __FILE__, __LINE__ ); e.SetErrorInformation( pszFilename ); throw e; } } #endif // _WIN32 PdfOutputDevice::PdfOutputDevice( char* pBuffer, size_t lLen ) { this->Init(); if( !pBuffer ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } m_lBufferLen = lLen; m_pBuffer = pBuffer; } PdfOutputDevice::PdfOutputDevice( const std::ostream* pOutStream ) { this->Init(); m_pStream = const_cast< std::ostream* >( pOutStream ); m_pStreamOwned = false; #if USE_CXX_LOCALE m_pStreamSavedLocale = m_pStream->getloc(); PdfLocaleImbue(*m_pStream); #endif } PdfOutputDevice::PdfOutputDevice( PdfRefCountedBuffer* pOutBuffer ) { this->Init(); m_pRefCountedBuffer = pOutBuffer; } PdfOutputDevice::~PdfOutputDevice() { if( m_pStreamOwned ) // remember, deleting a null pointer is safe delete m_pStream; // will call close #if USE_CXX_LOCALE if( !m_pStreamOwned ) m_pStream->imbue(m_pStreamSavedLocale); #endif if( m_hFile ) fclose( m_hFile ); } void PdfOutputDevice::Init() { m_ulLength = 0; m_hFile = NULL; m_pBuffer = NULL; m_pStream = NULL; m_pReadStream = NULL; m_pRefCountedBuffer = NULL; m_lBufferLen = 0; m_ulPosition = 0; m_pStreamOwned = true; } void PdfOutputDevice::Print( const char* pszFormat, ... ) { va_list args; long lBytes; va_start( args, pszFormat ); lBytes = PrintVLen(pszFormat, args); va_end( args ); va_start( args, pszFormat ); PrintV(pszFormat, lBytes, args); va_end( args ); } long PdfOutputDevice::PrintVLen( const char* pszFormat, va_list args ) { long lBytes; if( !pszFormat ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } if( m_hFile ) { if( (lBytes = vfprintf( m_hFile, pszFormat, args )) < 0 ) { perror( NULL ); PODOFO_RAISE_ERROR( ePdfError_UnexpectedEOF ); } } else { // OC 17.08.2010: Use new function _vscprintf to get the number of characters: // visual c++ 8.0 == 1400 (Visual Studio 2005) // i am not shure if 1300 is ok here, but who cares this cruel compiler version #if (defined _MSC_VER && _MSC_VER >= 1400 ) lBytes = _vscprintf( pszFormat, args ); #elif (defined _MSC_VER || defined __hpux) // vsnprintf without buffer does not work with MS-VC or HPUX int len = 1024; do { char * temp = new char[len+1]; // OC 17.08.2010 BugFix: +1 avoids corrupted heap lBytes = vsnprintf( temp, len+1, pszFormat, args ); delete[] temp; len *= 2; } while (lBytes < 0 ); #else lBytes = vsnprintf( NULL, 0, pszFormat, args ); #endif } return lBytes; } void PdfOutputDevice::PrintV( const char* pszFormat, long lBytes, va_list args ) { if( !pszFormat ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } if( m_pBuffer ) { if( m_ulPosition + lBytes <= m_lBufferLen ) { vsnprintf( m_pBuffer + m_ulPosition, m_lBufferLen - m_ulPosition, pszFormat, args ); } else { PODOFO_RAISE_ERROR( ePdfError_OutOfMemory ); } } else if( m_pStream || m_pRefCountedBuffer ) { ++lBytes; m_printBuffer.Resize( lBytes ); char* data = m_printBuffer.GetBuffer(); if( !data ) { PODOFO_RAISE_ERROR( ePdfError_OutOfMemory ); } vsnprintf( data, lBytes, pszFormat, args ); if( lBytes ) --lBytes; if( m_pStream ) { std::string str; str.assign( data, lBytes ); *m_pStream << str; } else // if( m_pRefCountedBuffer ) { if( m_ulPosition + lBytes > static_cast(m_pRefCountedBuffer->GetSize()) ) { m_pRefCountedBuffer->Resize( m_ulPosition + lBytes ); } memcpy( m_pRefCountedBuffer->GetBuffer() + m_ulPosition, data, lBytes ); } } m_ulPosition += static_cast(lBytes); if(m_ulPosition>m_ulLength) { m_ulLength = m_ulPosition; } } size_t PdfOutputDevice::Read( char* pBuffer, size_t lLen ) { size_t numRead = 0; if( m_hFile ) { numRead = fread( pBuffer, sizeof(char), lLen, m_hFile ); if(ferror(m_hFile)!=0) { PODOFO_RAISE_ERROR( ePdfError_InvalidDeviceOperation ); } } else if( m_pBuffer ) { if( m_ulPosition <= m_ulLength ) { numRead = PODOFO_MIN(lLen, m_ulLength-m_ulPosition); memcpy( pBuffer, m_pBuffer + m_ulPosition, numRead); } } else if( m_pReadStream ) { size_t iPos = m_pReadStream->tellg(); m_pReadStream->read( pBuffer, lLen ); if(m_pReadStream->fail()&&!m_pReadStream->eof()) { PODOFO_RAISE_ERROR( ePdfError_InvalidDeviceOperation ); } numRead = m_pReadStream->tellg(); numRead -= iPos; } else if( m_pRefCountedBuffer ) { if( m_ulPosition <= m_ulLength ) { numRead = PODOFO_MIN(lLen, m_ulLength-m_ulPosition); memcpy( pBuffer, m_pRefCountedBuffer->GetBuffer() + m_ulPosition, numRead ); } } m_ulPosition += static_cast(numRead); return numRead; } void PdfOutputDevice::Write( const char* pBuffer, size_t lLen ) { if( m_hFile ) { if( fwrite( pBuffer, sizeof(char), lLen, m_hFile ) != static_cast(lLen) ) { PODOFO_RAISE_ERROR( ePdfError_UnexpectedEOF ); } } else if( m_pBuffer ) { if( m_ulPosition + lLen <= m_lBufferLen ) { memcpy( m_pBuffer + m_ulPosition, pBuffer, lLen ); } else { PODOFO_RAISE_ERROR_INFO( ePdfError_OutOfMemory, "Allocated buffer to small for PdfOutputDevice. Cannot write!" ); } } else if( m_pStream ) { m_pStream->write( pBuffer, lLen ); } else if( m_pRefCountedBuffer ) { if( m_ulPosition + lLen > m_pRefCountedBuffer->GetSize() ) m_pRefCountedBuffer->Resize( m_ulPosition + lLen ); memcpy( m_pRefCountedBuffer->GetBuffer() + m_ulPosition, pBuffer, lLen ); } m_ulPosition += static_cast(lLen); if(m_ulPosition>m_ulLength) m_ulLength = m_ulPosition; } void PdfOutputDevice::Seek( size_t offset ) { if( m_hFile ) { if( fseeko( m_hFile, offset, SEEK_SET ) == -1 ) { PODOFO_RAISE_ERROR( ePdfError_ValueOutOfRange ); } } else if( m_pBuffer ) { if( offset >= m_lBufferLen ) { PODOFO_RAISE_ERROR( ePdfError_ValueOutOfRange ); } } else if( m_pStream ) { m_pStream->seekp( offset, std::ios_base::beg ); } else if( m_pRefCountedBuffer ) { m_ulPosition = offset; } m_ulPosition = offset; // Seek should not change the length of the device // m_ulLength = offset; } void PdfOutputDevice::Flush() { if( m_hFile ) { if( fflush( m_hFile ) ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } } else if( m_pStream ) { m_pStream->flush(); } } }; podofo-0.9.3/src/base/PdfParser.cpp0000664000175000017500000014107412355520733016770 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2005 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfParser.h" #include "PdfArray.h" #include "PdfDefinesPrivate.h" #include "PdfDictionary.h" #include "PdfEncrypt.h" #include "PdfInputDevice.h" #include "PdfMemStream.h" #include "PdfObjectStreamParserObject.h" #include "PdfOutputDevice.h" #include "PdfParserObject.h" #include "PdfStream.h" #include "PdfVariant.h" #include "PdfXRefStreamParserObject.h" #include #include #include #include #include #include using std::cerr; using std::endl; using std::flush; #define PDF_MAGIC_LEN 8 #define PDF_XREF_ENTRY_SIZE 20 #define PDF_XREF_BUF 512 namespace PoDoFo { long PdfParser::s_nMaxObjects = std::numeric_limits::max(); PdfParser::PdfParser( PdfVecObjects* pVecObjects ) : PdfTokenizer(), m_vecObjects( pVecObjects ) { this->Init(); } PdfParser::PdfParser( PdfVecObjects* pVecObjects, const char* pszFilename, bool bLoadOnDemand ) : PdfTokenizer(), m_vecObjects( pVecObjects ) { this->Init(); this->ParseFile( pszFilename, bLoadOnDemand ); } #ifdef _WIN32 #if defined(_MSC_VER) && _MSC_VER <= 1200 // nicht fr Visualstudio 6 #else PdfParser::PdfParser( PdfVecObjects* pVecObjects, const wchar_t* pszFilename, bool bLoadOnDemand ) : PdfTokenizer(), m_vecObjects( pVecObjects ) { this->Init(); this->ParseFile( pszFilename, bLoadOnDemand ); } #endif #endif // _WIN32 PdfParser::PdfParser( PdfVecObjects* pVecObjects, const char* pBuffer, long lLen, bool bLoadOnDemand ) : PdfTokenizer(), m_vecObjects( pVecObjects ) { this->Init(); this->ParseFile( pBuffer, lLen, bLoadOnDemand ); } PdfParser::PdfParser( PdfVecObjects* pVecObjects, const PdfRefCountedInputDevice & rDevice, bool bLoadOnDemand ) : PdfTokenizer(), m_vecObjects( pVecObjects ) { this->Init(); if( !rDevice.Device() ) { PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidHandle, "Cannot create PdfRefCountedInputDevice." ); } this->ParseFile( rDevice, bLoadOnDemand ); } PdfParser::~PdfParser() { Clear(); } void PdfParser::Init() { m_bLoadOnDemand = false; m_device = PdfRefCountedInputDevice(); m_pTrailer = NULL; m_pLinearization = NULL; m_offsets.clear(); m_pEncrypt = NULL; m_ePdfVersion = ePdfVersion_Default; m_nXRefOffset = 0; m_nFirstObject = 0; m_nNumObjects = 0; m_nXRefLinearizedOffset = 0; m_lLastEOFOffset = 0; m_bStrictParsing = false; m_bIgnoreBrokenObjects = false; m_nIncrementalUpdates = 0; m_nReadNextTrailerLevel = 0; } void PdfParser::ParseFile( const char* pszFilename, bool bLoadOnDemand ) { if( !pszFilename || !pszFilename[0] ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } PdfRefCountedInputDevice device( pszFilename, "rb" ); if( !device.Device() ) { PODOFO_RAISE_ERROR_INFO( ePdfError_FileNotFound, pszFilename ); } this->ParseFile( device, bLoadOnDemand ); } #ifdef _WIN32 #if defined(_MSC_VER) && _MSC_VER <= 1200 // nicht fr Visualstudio 6 #else void PdfParser::ParseFile( const wchar_t* pszFilename, bool bLoadOnDemand ) { if( !pszFilename || !pszFilename[0] ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } PdfRefCountedInputDevice device( pszFilename, "rb" ); if( !device.Device() ) { PdfError e( ePdfError_FileNotFound, __FILE__, __LINE__ ); e.SetErrorInformation( pszFilename ); throw e; } this->ParseFile( device, bLoadOnDemand ); } #endif #endif // _WIN32 void PdfParser::ParseFile( const char* pBuffer, long lLen, bool bLoadOnDemand ) { if( !pBuffer || !lLen ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } PdfRefCountedInputDevice device( pBuffer, lLen ); if( !device.Device() ) { PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidHandle, "Cannot create PdfParser from buffer." ); } this->ParseFile( device, bLoadOnDemand ); } void PdfParser::ParseFile( const PdfRefCountedInputDevice & rDevice, bool bLoadOnDemand ) { Clear(); m_device = rDevice; m_bLoadOnDemand = bLoadOnDemand; try { if( !IsPdfFile() ) { PODOFO_RAISE_ERROR( ePdfError_NoPdfFile ); } ReadDocumentStructure(); ReadObjects(); } catch( PdfError & e ) { if( e.GetError() == ePdfError_InvalidPassword ) { // Do not clean up, expect user to call ParseFile again throw e; } // If this is being called from a constructor then the // destructor will not be called. // Clean up here Clear(); e.AddToCallstack( __FILE__, __LINE__, "Unable to load objects from file." ); throw e; } } void PdfParser::Clear() { m_setObjectStreams.clear(); m_offsets.clear(); m_device = PdfRefCountedInputDevice(); delete m_pTrailer; m_pTrailer = NULL; delete m_pLinearization; m_pLinearization = NULL; delete m_pEncrypt; m_pEncrypt = NULL; this->Init(); } void PdfParser::ReadDocumentStructure() { // Ulrich Arnold 8.9.2009, deactivated because of problems during reading xref's //begin L.K - na test povoleno HasLinearizationDict(); //begin L.K // position at the end of the file to search the xref table. m_device.Device()->Seek( 0, std::ios_base::end ); m_nFileSize = m_device.Device()->Tell(); // James McGill 18.02.2011, validate the eof marker and when not in strict mode accept garbage after it try { CheckEOFMarker(); } catch( PdfError & e ) { e.AddToCallstack( __FILE__, __LINE__, "EOF marker could not be found." ); throw e; } try { ReadXRef( &m_nXRefOffset ); } catch( PdfError & e ) { e.AddToCallstack( __FILE__, __LINE__, "Unable to find startxref entry in file." ); throw e; } try { ReadTrailer(); } catch( PdfError & e ) { e.AddToCallstack( __FILE__, __LINE__, "Unable to find trailer in file." ); throw e; } if( m_pLinearization ) { try { ReadXRefContents( m_nXRefOffset, true ); } catch( PdfError & e ) { e.AddToCallstack( __FILE__, __LINE__, "Unable to skip xref dictionary." ); throw e; } // another trailer directory is to follow right after this XRef section try { ReadNextTrailer(); } catch( PdfError & e ) { if( e != ePdfError_NoTrailer ) throw e; } } if( m_pTrailer->IsDictionary() && m_pTrailer->GetDictionary().HasKey( PdfName::KeySize ) ) { m_nNumObjects = static_cast(m_pTrailer->GetDictionary().GetKeyAsLong( PdfName::KeySize )); } else { PdfError::LogMessage( eLogSeverity_Warning, "PDF Standard Violation: No /Size key was specified in the trailer directory. Will attempt to recover." ); // Treat the xref size as unknown, and expand the xref dynamically as we read it. m_nNumObjects = 0; } // allow caller to specify a max object count to avoid very slow load times on large documents if (s_nMaxObjects != std::numeric_limits::max() && m_nNumObjects > s_nMaxObjects) PODOFO_RAISE_ERROR_INFO( ePdfError_ValueOutOfRange, "m_nNumObjects is greater than m_nMaxObjects." ); if (m_nNumObjects > 0) m_offsets.resize(m_nNumObjects); if( m_pLinearization ) { try { ReadXRefContents( m_nXRefLinearizedOffset ); } catch( PdfError & e ) { e.AddToCallstack( __FILE__, __LINE__, "Unable to read linearized XRef section." ); throw e; } } try { ReadXRefContents( m_nXRefOffset ); } catch( PdfError & e ) { e.AddToCallstack( __FILE__, __LINE__, "Unable to load xref entries." ); throw e; } } bool PdfParser::IsPdfFile() { const char* szPdfMagicStart = "%PDF-"; int i; if( m_device.Device()->Read( m_buffer.GetBuffer(), PDF_MAGIC_LEN ) != PDF_MAGIC_LEN ) return false; if( strncmp( m_buffer.GetBuffer(), szPdfMagicStart, strlen( szPdfMagicStart ) ) != 0 ) return false; // try to determine the excact PDF version of the file for( i=0;i<=MAX_PDF_VERSION_STRING_INDEX;i++ ) { if( strncmp( m_buffer.GetBuffer(), s_szPdfVersions[i], PDF_MAGIC_LEN ) == 0 ) { m_ePdfVersion = static_cast(i); break; } } return true; } void PdfParser::HasLinearizationDict() { if (m_pLinearization) { PODOFO_RAISE_ERROR_INFO( ePdfError_InternalLogic, "HasLinarizationDict() called twice on one object"); } m_device.Device()->Seek( 0 ); // The linearization dictionary must be in the first 1024 // bytes of the PDF, our buffer might be larger so. // Therefore read only the first 1024 byte. // Normally we should jump to the end of the file, to determine // it's filesize and read the min(1024, filesize) to not fail // on smaller files, but jumping to the end is against the idea // of linearized PDF. Therefore just check if we read anything. const std::streamoff MAX_READ = 1024; PdfRefCountedBuffer linearizeBuffer( MAX_READ ); std::streamoff size = m_device.Device()->Read( linearizeBuffer.GetBuffer(), linearizeBuffer.GetSize() ); // Only fail if we read nothing, to allow files smaller than MAX_READ if( static_cast(size) <= 0 ) { // Clear the error state from the bad read m_device.Device()->Clear(); return; // Ignore Error Code: ERROR_PDF_NO_TRAILER; } //begin L.K //char * pszObj = strstr( m_buffer.GetBuffer(), "obj" ); char * pszObj = strstr( linearizeBuffer.GetBuffer(), "obj" ); //end L.K if( !pszObj ) // strange that there is no obj in the first 1024 bytes, // but ignore it return; --pszObj; // *pszObj == 'o', so the while would fail without decrement while( *pszObj && (PdfTokenizer::IsWhitespace( *pszObj ) || (*pszObj >= '0' && *pszObj <= '9')) ) --pszObj; m_pLinearization = new PdfParserObject( m_vecObjects, m_device, linearizeBuffer, pszObj - linearizeBuffer.GetBuffer() + 2 ); try { // Do not care for encryption here, as the linearization dictionary does not contain strings or streams // ... hint streams do, but we do not load the hintstream. static_cast(m_pLinearization)->ParseFile( NULL ); if (! (m_pLinearization->IsDictionary() && m_pLinearization->GetDictionary().HasKey( "Linearized" ) ) ) { delete m_pLinearization; m_pLinearization = NULL; return; } } catch( PdfError & e ) { PdfError::LogMessage( eLogSeverity_Warning, e.ErrorName(e.GetError()) ); delete m_pLinearization; m_pLinearization = NULL; return; } pdf_int64 lXRef = -1; lXRef = m_pLinearization->GetDictionary().GetKeyAsLong( "T", lXRef ); if( lXRef == -1 ) { PODOFO_RAISE_ERROR( ePdfError_InvalidLinearization ); } // avoid moving to a negative file position here m_device.Device()->Seek( (static_cast(lXRef-PDF_XREF_BUF) > 0 ? static_cast(lXRef-PDF_XREF_BUF) : PDF_XREF_BUF) ); m_nXRefLinearizedOffset = m_device.Device()->Tell(); if( m_device.Device()->Read( m_buffer.GetBuffer(), PDF_XREF_BUF ) != PDF_XREF_BUF ) { PODOFO_RAISE_ERROR( ePdfError_InvalidLinearization ); } m_buffer.GetBuffer()[PDF_XREF_BUF] = '\0'; // search backwards in the buffer in case the buffer contains null bytes // because it is right after a stream (can't use strstr for this reason) const int XREF_LEN = 4; // strlen( "xref" ); int i = 0; char* pszStart = NULL; for( i = PDF_XREF_BUF - XREF_LEN; i >= 0; i-- ) if( strncmp( m_buffer.GetBuffer()+i, "xref", XREF_LEN ) == 0 ) { pszStart = m_buffer.GetBuffer()+i; break; } m_nXRefLinearizedOffset += i; if( !pszStart ) { if( m_ePdfVersion < ePdfVersion_1_5 ) { PdfError::LogMessage( eLogSeverity_Warning, "Linearization dictionaries are only supported with PDF version 1.5. This is 1.%i. Trying to continue.\n", static_cast(m_ePdfVersion) ); // PODOFO_RAISE_ERROR( ePdfError_InvalidLinearization ); } { m_nXRefLinearizedOffset = static_cast(lXRef); /* eCode = ReadXRefStreamContents(); i = 0; */ } } } void PdfParser::MergeTrailer( const PdfObject* pTrailer ) { PdfVariant cVar; if( !pTrailer || !m_pTrailer ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } // Only update keys, if not already present if( pTrailer->GetDictionary().HasKey( PdfName::KeySize ) && !m_pTrailer->GetDictionary().HasKey( PdfName::KeySize ) ) m_pTrailer->GetDictionary().AddKey( PdfName::KeySize, *(pTrailer->GetDictionary().GetKey( PdfName::KeySize )) ); if( pTrailer->GetDictionary().HasKey( "Root" ) && !m_pTrailer->GetDictionary().HasKey( "Root" )) m_pTrailer->GetDictionary().AddKey( "Root", *(pTrailer->GetDictionary().GetKey( "Root" )) ); if( pTrailer->GetDictionary().HasKey( "Encrypt" ) && !m_pTrailer->GetDictionary().HasKey( "Encrypt" ) ) m_pTrailer->GetDictionary().AddKey( "Encrypt", *(pTrailer->GetDictionary().GetKey( "Encrypt" )) ); if( pTrailer->GetDictionary().HasKey( "Info" ) && !m_pTrailer->GetDictionary().HasKey( "Info" ) ) m_pTrailer->GetDictionary().AddKey( "Info", *(pTrailer->GetDictionary().GetKey( "Info" )) ); if( pTrailer->GetDictionary().HasKey( "ID" ) && !m_pTrailer->GetDictionary().HasKey( "ID" ) ) m_pTrailer->GetDictionary().AddKey( "ID", *(pTrailer->GetDictionary().GetKey( "ID" )) ); } void PdfParser::ReadNextTrailer() { // be careful changing this limit - overflow limits depend on the OS, linker settings, and how much stack space compiler allocates // 500 limit prevents overflow on Win7 with VC++ 2005 with default linker stack size (1000 caused overflow with same compiler/OS) const int maxReadNextTrailerLevel = 500; ++m_nReadNextTrailerLevel; if ( m_nReadNextTrailerLevel > maxReadNextTrailerLevel ) { // avoid stack overflow on documents that have circular cross references in trailer PODOFO_RAISE_ERROR( ePdfError_InvalidXRef ); } // ReadXRefcontents has read the first 't' from "trailer" so just check for "railer" if( this->IsNextToken( "trailer" ) ) //if( strcmp( m_buffer.GetBuffer(), "railer" ) == 0 ) { PdfParserObject trailer( m_vecObjects, m_device, m_buffer ); try { // Ignore the encryption in the trailer as the trailer may not be encrypted trailer.ParseFile( NULL, true ); } catch( PdfError & e ) { e.AddToCallstack( __FILE__, __LINE__, "The linearized trailer was found in the file, but contains errors." ); throw e; } // now merge the information of this trailer with the main documents trailer MergeTrailer( &trailer ); if( trailer.GetDictionary().HasKey( "XRefStm" ) ) { // Whenever we read a XRefStm key, // we know that the file was updated. if( !trailer.GetDictionary().HasKey( "Prev" ) ) m_nIncrementalUpdates++; try { ReadXRefStreamContents( static_cast(trailer.GetDictionary().GetKeyAsLong( "XRefStm", 0 )), false ); } catch( PdfError & e ) { e.AddToCallstack( __FILE__, __LINE__, "Unable to load /XRefStm xref stream." ); throw e; } } if( trailer.GetDictionary().HasKey( "Prev" ) ) { // Whenever we read a Prev key, // we know that the file was updated. m_nIncrementalUpdates++; try { ReadXRefContents( static_cast(trailer.GetDictionary().GetKeyAsLong( "Prev", 0 )) ); } catch( PdfError & e ) { e.AddToCallstack( __FILE__, __LINE__, "Unable to load /Prev xref entries." ); throw e; } } } else // OC 13.08.2010 BugFix: else belongs to IsNextToken( "trailer" ) and not to HasKey( "Prev" ) { PODOFO_RAISE_ERROR( ePdfError_NoTrailer ); } --m_nReadNextTrailerLevel; } void PdfParser::ReadTrailer() { FindToken( "trailer", PDF_XREF_BUF ); if( !this->IsNextToken( "trailer" ) ) { // if( m_ePdfVersion < ePdfVersion_1_5 ) // Ulrich Arnold 19.10.2009, found linearized 1.3-pdf's with trailer-info in xref-stream if( m_ePdfVersion < ePdfVersion_1_3 ) { PODOFO_RAISE_ERROR( ePdfError_NoTrailer ); } else { // Since PDF 1.5 trailer information can also be found // in the crossreference stream object // and a trailer dictionary is not required m_device.Device()->Seek( m_nXRefOffset ); m_pTrailer = new PdfParserObject( m_vecObjects, m_device, m_buffer ); static_cast(m_pTrailer)->ParseFile( NULL, false ); return; } } else { m_pTrailer = new PdfParserObject( m_vecObjects, m_device, m_buffer ); try { // Ignore the encryption in the trailer as the trailer may not be encrypted static_cast(m_pTrailer)->ParseFile( NULL, true ); } catch( PdfError & e ) { e.AddToCallstack( __FILE__, __LINE__, "The trailer was found in the file, but contains errors." ); throw e; } #ifdef PODOFO_VERBOSE_DEBUG PdfError::DebugMessage("Size=%li\n", m_pTrailer->GetDictionary().GetKeyAsLong( PdfName::KeySize, 0 ) ); #endif // PODOFO_VERBOSE_DEBUG } } void PdfParser::ReadXRef( pdf_long* pXRefOffset ) { FindToken( "startxref", PDF_XREF_BUF ); if( !this->IsNextToken( "startxref" ) ) { // Could be non-standard startref if(!m_bStrictParsing) { FindToken( "startref", PDF_XREF_BUF ); if( !this->IsNextToken( "startref" ) ) { PODOFO_RAISE_ERROR( ePdfError_NoXRef ); } } else { PODOFO_RAISE_ERROR( ePdfError_NoXRef ); } } *pXRefOffset = this->GetNextNumber(); } void PdfParser::ReadXRefContents( pdf_long lOffset, bool bPositionAtEnd ) { pdf_int64 nFirstObject = 0; pdf_int64 nNumObjects = 0; size_t curPosition = m_device.Device()->Tell(); m_device.Device()->Seek(0,std::ios_base::end); std::streamoff fileSize = m_device.Device()->Tell(); m_device.Device()->Seek(curPosition,std::ios_base::beg); if (lOffset > fileSize) { // Invalid "startxref" Peter Petrov 23 December 2008 // ignore returned value and get offset from the device ReadXRef( &lOffset ); lOffset = m_device.Device()->Tell(); // TODO: hard coded value "4" m_buffer.Resize(PDF_XREF_BUF*4); FindToken2("xref", PDF_XREF_BUF*4,lOffset); m_buffer.Resize(PDF_XREF_BUF); lOffset = m_device.Device()->Tell(); m_nXRefOffset = lOffset; } else { m_device.Device()->Seek( lOffset ); } if( !this->IsNextToken( "xref" ) ) { // if( m_ePdfVersion < ePdfVersion_1_5 ) // Ulrich Arnold 19.10.2009, found linearized 1.3-pdf's with trailer-info in xref-stream if( m_ePdfVersion < ePdfVersion_1_3 ) { PODOFO_RAISE_ERROR( ePdfError_NoXRef ); } else { ReadXRefStreamContents( lOffset, bPositionAtEnd ); return; } } // read all xref subsections // OC 13.08.2010: Avoid exception to terminate endless loop for( int nXrefSection = 0; ; ++nXrefSection ) { try { // OC 13.08.2010: Avoid exception to terminate endless loop if ( nXrefSection > 0 ) { // something like PeekNextToken() EPdfTokenType eType; const char* pszRead; bool gotToken = this->GetNextToken( pszRead, &eType ); if( gotToken ) { this->QuequeToken( pszRead, eType ); if ( strcmp( "trailer", pszRead ) == 0 ) break; } } nFirstObject = this->GetNextNumber(); nNumObjects = this->GetNextNumber(); #ifdef PODOFO_VERBOSE_DEBUG PdfError::DebugMessage("Reading numbers: %" PDF_FORMAT_INT64 " %" PDF_FORMAT_INT64 "\n", nFirstObject, nNumObjects ); #endif // PODOFO_VERBOSE_DEBUG if( bPositionAtEnd ) { #ifdef _WIN32 m_device.Device()->Seek( static_cast(nNumObjects* PDF_XREF_ENTRY_SIZE), std::ios_base::cur ); #else m_device.Device()->Seek( nNumObjects* PDF_XREF_ENTRY_SIZE, std::ios_base::cur ); #endif // _WIN32 } else { ReadXRefSubsection( nFirstObject, nNumObjects ); } } catch( PdfError & e ) { if( e == ePdfError_NoNumber || e == ePdfError_InvalidXRef || e == ePdfError_UnexpectedEOF ) break; else { e.AddToCallstack( __FILE__, __LINE__ ); throw e; } } } try { ReadNextTrailer(); } catch( PdfError & e ) { if( e != ePdfError_NoTrailer ) { e.AddToCallstack( __FILE__, __LINE__ ); throw e; } } } void PdfParser::ReadXRefSubsection( pdf_int64 & nFirstObject, pdf_int64 & nNumObjects ) { int count = 0; #ifdef PODOFO_VERBOSE_DEBUG PdfError::DebugMessage("Reading XRef Section: %" PDF_FORMAT_INT64 " with %" PDF_FORMAT_INT64 " Objects.\n", nFirstObject, nNumObjects ); #endif // PODOFO_VERBOSE_DEBUG if ( nFirstObject + nNumObjects > m_nNumObjects ) { // Total number of xref entries to read is greater than the /Size // specified in the trailer if any. That's an error unless we're trying // to recover from a missing /Size entry. PdfError::LogMessage( eLogSeverity_Warning, "There are more objects (%" PDF_FORMAT_INT64 ") in this XRef table than " "specified in the size key of the trailer directory (%" PDF_FORMAT_INT64 ")!\n", nFirstObject + nNumObjects, m_nNumObjects ); #ifdef _WIN32 m_nNumObjects = static_cast(nFirstObject + nNumObjects); m_offsets.resize(static_cast(nFirstObject+nNumObjects)); #else m_nNumObjects = nFirstObject + nNumObjects; m_offsets.resize(nFirstObject+nNumObjects); #endif // _WIN32 } // consume all whitespaces int charcode; while( this->IsWhitespace((charcode = m_device.Device()->Look())) ) { m_device.Device()->GetChar(); } while( count < nNumObjects && m_device.Device()->Read( m_buffer.GetBuffer(), PDF_XREF_ENTRY_SIZE ) == PDF_XREF_ENTRY_SIZE ) { char empty1; char empty2; m_buffer.GetBuffer()[PDF_XREF_ENTRY_SIZE] = '\0'; #ifdef _WIN32 const int objID = static_cast(nFirstObject+count); #else const int objID = nFirstObject+count; #endif // _WIN32 if( !m_offsets[objID].bParsed ) { m_offsets[objID].bParsed = true; #if defined(_WIN64) && defined(_MSC_VER) sscanf( m_buffer.GetBuffer(), "%10" PDF_FORMAT_INT64 " %5ld %c%c%c", &(m_offsets[objID].lOffset), &(m_offsets[objID].lGeneration), &(m_offsets[objID].cUsed), &empty1, &empty2 ); #else pdf_int64 tmp1; pdf_int64 tmp2; sscanf( m_buffer.GetBuffer(), "%10" PDF_FORMAT_INT64 " %5ld %c%c%c", &tmp1, &tmp2, &(m_offsets[objID].cUsed), &empty1, &empty2 ); m_offsets[objID].lOffset = static_cast(tmp1); m_offsets[objID].lGeneration = static_cast(tmp2); #endif } ++count; } if( count != nNumObjects ) { PdfError::LogMessage( eLogSeverity_Warning, "Count of readobject is %i. Expected %" PDF_FORMAT_INT64 ".\n", count, nNumObjects ); PODOFO_RAISE_ERROR( ePdfError_NoXRef ); } } void PdfParser::ReadXRefStreamContents( pdf_long lOffset, bool bReadOnlyTrailer ) { m_device.Device()->Seek( lOffset ); PdfXRefStreamParserObject xrefObject( m_vecObjects, m_device, m_buffer, &m_offsets ); xrefObject.Parse(); if( !m_pTrailer ) m_pTrailer = new PdfParserObject( m_vecObjects, m_device, m_buffer ); MergeTrailer( &xrefObject ); if( bReadOnlyTrailer ) return; xrefObject.ReadXRefTable(); // Check for a previous XRef stream if(xrefObject.HasPrevious()) { try { m_nIncrementalUpdates++; this->ReadXRefStreamContents( xrefObject.GetPreviousOffset(), bReadOnlyTrailer ); } catch(PdfError &e) { /* Be forgiving, the error happens when an entry in XRef stream points to a wrong place (offset) in the PDF file. */ if( e != ePdfError_NoNumber ) { e.AddToCallstack( __FILE__, __LINE__ ); throw e; } } } } bool PdfParser::QuickEncryptedCheck( const char* pszFilename ) { bool bEncryptStatus = false; bool bOldLoadOnDemand = m_bLoadOnDemand; Init(); Clear(); m_bLoadOnDemand = true; // maybe will be quicker if true? if( !pszFilename || !pszFilename[0] ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } m_device = PdfRefCountedInputDevice( pszFilename, "rb" ); if( !m_device.Device() ) { //PODOFO_RAISE_ERROR_INFO( ePdfError_FileNotFound, pszFilename ); // If we can not open PDF file // then file does not exist return false; } if( !IsPdfFile() ) { //PODOFO_RAISE_ERROR( ePdfError_NoPdfFile ); return false; } ReadDocumentStructure(); try { m_vecObjects->Reserve( m_nNumObjects ); // Check for encryption and make sure that the encryption object // is loaded before all other objects const PdfObject * encObj = m_pTrailer->GetDictionary().GetKey( PdfName("Encrypt") ); if( encObj && ! encObj->IsNull() ) { bEncryptStatus = true; } } catch( PdfError & e ) { m_bLoadOnDemand = bOldLoadOnDemand; // Restore load on demand behaviour e.AddToCallstack( __FILE__, __LINE__, "Unable to load objects from file." ); throw e; } m_bLoadOnDemand = bOldLoadOnDemand; // Restore load on demand behaviour return bEncryptStatus; } void PdfParser::ReadObjects() { int i = 0; PdfParserObject* pObject = NULL; m_vecObjects->Reserve( m_nNumObjects ); // Check for encryption and make sure that the encryption object // is loaded before all other objects PdfObject* pEncrypt = m_pTrailer->GetDictionary().GetKey( PdfName("Encrypt") ); if( pEncrypt && !pEncrypt->IsNull() ) { #ifdef PODOFO_VERBOSE_DEBUG PdfError::DebugMessage("The PDF file is encrypted.\n" ); #endif // PODOFO_VERBOSE_DEBUG if( pEncrypt->IsReference() ) { i = pEncrypt->GetReference().ObjectNumber(); pObject = new PdfParserObject( m_vecObjects, m_device, m_buffer, m_offsets[i].lOffset ); pObject->SetLoadOnDemand( false ); // Never load this on demand, as we will use it immediately try { pObject->ParseFile( NULL ); // The encryption dictionary is not encrypted :) // Never add the encryption dictionary to m_vecObjects // we create a new one, if we need it for writing // m_vecObjects->push_back( pObject ); m_offsets[i].bParsed = false; m_pEncrypt = PdfEncrypt::CreatePdfEncrypt( pObject ); delete pObject; } catch( PdfError & e ) { std::ostringstream oss; if( pObject ) { oss << "Error while loading object " << pObject->Reference().ObjectNumber() << " " << pObject->Reference().GenerationNumber() << std::endl; delete pObject; } e.AddToCallstack( __FILE__, __LINE__, oss.str().c_str() ); throw e; } } else if( pEncrypt->IsDictionary() ) { m_pEncrypt = PdfEncrypt::CreatePdfEncrypt( pEncrypt ); } else { PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidEncryptionDict, "The encryption entry in the trailer is neither an object nor a reference." ); } // Generate encryption keys // Set user password, try first with an empty password bool bAuthenticate = m_pEncrypt->Authenticate( "", this->GetDocumentId() ); #ifdef PODOFO_VERBOSE_DEBUG PdfError::DebugMessage("Authentication with empty password: %i.\n", bAuthenticate ); #endif // PODOFO_VERBOSE_DEBUG if( !bAuthenticate ) { // authentication failed so we need a password from the user. // The user can set the password using PdfParser::SetPassword PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidPassword, "A password is required to read this PDF file."); } } ReadObjectsInternal(); } void PdfParser::ReadObjectsInternal() { int i = 0; int nLast = 0; PdfParserObject* pObject = NULL; // Read objects for( i=0; i < m_nNumObjects; i++ ) { #ifdef PODOFO_VERBOSE_DEBUG std::cerr << "ReadObjectsInteral\t" << i << " " << (m_offsets[i].bParsed ? "parsed" : "unparsed") << " " << m_offsets[i].cUsed << " " << m_offsets[i].lOffset << " " << m_offsets[i].lGeneration << std::endl; #endif if( m_offsets[i].bParsed && m_offsets[i].cUsed == 'n' && m_offsets[i].lOffset > 0 ) { //printf("Reading object %i 0 R from %li\n", i, m_offsets[i].lOffset ); pObject = new PdfParserObject( m_vecObjects, m_device, m_buffer, m_offsets[i].lOffset ); pObject->SetLoadOnDemand( m_bLoadOnDemand ); try { pObject->ParseFile( m_pEncrypt ); if (m_pEncrypt && pObject->IsDictionary()) { PdfObject* pObjType = pObject->GetDictionary().GetKey( PdfName::KeyType ); if( pObjType && pObjType->IsName() && pObjType->GetName() == "XRef" ) { // XRef is never encrypted delete pObject; pObject = new PdfParserObject( m_vecObjects, m_device, m_buffer, m_offsets[i].lOffset ); pObject->SetLoadOnDemand( m_bLoadOnDemand ); pObject->ParseFile( NULL ); } } nLast = pObject->Reference().ObjectNumber(); /* if( i != pObject->Reference().ObjectNumber() ) { printf("Expected %i got %i\n", i, pObject->Reference().ObjectNumber()); } if( pObject->Reference().ObjectNumber() != i ) { printf("EXPECTED: %i got %i\n", i, pObject->Reference().ObjectNumber() ); abort(); } */ // final pdf should not contain a linerization dictionary as it contents are invalid // as we change some objects and the final xref table if( m_pLinearization && nLast == static_cast(m_pLinearization->Reference().ObjectNumber()) ) { m_vecObjects->AddFreeObject( pObject->Reference() ); delete pObject; } else m_vecObjects->push_back( pObject ); } catch( PdfError & e ) { std::ostringstream oss; if( pObject ) { oss << "Error while loading object " << pObject->Reference().ObjectNumber() << " " << pObject->Reference().GenerationNumber() << " Offset = " << m_offsets[i].lOffset << " Index = " << i << std::endl; delete pObject; } if( m_bIgnoreBrokenObjects ) { PdfError::LogMessage( eLogSeverity_Error, oss.str().c_str() ); m_vecObjects->AddFreeObject( PdfReference( i, 0 ) ); } else { e.AddToCallstack( __FILE__, __LINE__, oss.str().c_str() ); throw e; } } } else if( m_offsets[i].bParsed && m_offsets[i].cUsed == 'n' && (m_offsets[i].lOffset == 0) ) { // There are broken PDFs which add objects with 'n' // and 0 offset and 0 generation number // to the xref table instead of using free objects // treating them as free objects if( m_bStrictParsing ) { PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidXRef, "Found object with 0 offset which should be 'f' instead of 'n'." ); } else { PdfError::LogMessage( eLogSeverity_Warning, "Treating object %i 0 R as a free object." ); m_vecObjects->AddFreeObject( PdfReference( i, PODOFO_LL_LITERAL(1) ) ); } } // Ulrich Arnold 30.7.2009: the linked free list in the xref section is not always correct in pdf's // (especially Illustrator) but Acrobat still accepts them. I've seen XRefs // where some object-numbers are alltogether missing and multiple XRefs where // the link list is broken. // Because PdfVecObjects relies on a unbroken range, fill the free list more // robustly from all places which are either free or unparsed // else if( m_offsets[i].bParsed && m_offsets[i].cUsed == 'f' && m_offsets[i].lOffset ) // { // m_vecObjects->AddFreeObject( PdfReference( static_cast(m_offsets[i].lOffset), PODOFO_LL_LITERAL(1) ) ); // TODO: do not hard code // } else if( (!m_offsets[i].bParsed || m_offsets[i].cUsed == 'f') && i != 0 ) { m_vecObjects->AddFreeObject( PdfReference( static_cast(i), PODOFO_LL_LITERAL(1) ) ); // TODO: do not hard code generation number } } // all normal objects including object streams are available now, // we can parse the object streams safely now. // // Note that even if demand loading is enabled we still currently read all // objects from the stream into memory then free the stream. // for( i = 0; i < m_nNumObjects; i++ ) { if( m_offsets[i].bParsed && m_offsets[i].cUsed == 's' ) // we have an object stream { #if defined(PODOFO_VERBOSE_DEBUG) if (m_bLoadOnDemand) cerr << "Demand loading on, but can't demand-load from object stream." << endl; #endif ReadObjectFromStream( static_cast(m_offsets[i].lGeneration), static_cast(m_offsets[i].lOffset) ); } } if( !m_bLoadOnDemand ) { // Force loading of streams. We can't do this during the initial // run that populates m_vecObjects because a stream might have a /Length // key that references an object we haven't yet read. So we must do it here // in a second pass, or (if demand loading is enabled) defer it for later. for (TCIVecObjects itObjects = m_vecObjects->begin(); itObjects != m_vecObjects->end(); ++itObjects) { pObject = dynamic_cast(*itObjects); // only parse streams for objects that have not yet parsed // their streams if( pObject && pObject->HasStreamToParse() && !pObject->HasStream() ) pObject->GetStream(); } } // Now sort the list of objects m_vecObjects->Sort(); UpdateDocumentVersion(); } void PdfParser::SetPassword( const std::string & sPassword ) { if( !m_pEncrypt ) { PODOFO_RAISE_ERROR_INFO( ePdfError_InternalLogic, "Cannot set password for unencrypted PDF." ); } bool bAuthenticate = m_pEncrypt->Authenticate( sPassword, this->GetDocumentId() ); if( !bAuthenticate ) { #ifdef PODOFO_VERBOSE_DEBUG PdfError::DebugMessage("Authentication with user password failed\n" ); #endif // PODOFO_VERBOSE_DEBUG PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidPassword, "Authentication with user specified password failed."); } ReadObjectsInternal(); } void PdfParser::ReadObjectFromStream( int nObjNo, int ) { // check if we already have read all objects // from this stream if( m_setObjectStreams.find( nObjNo ) != m_setObjectStreams.end() ) { return; } else m_setObjectStreams.insert( nObjNo ); // generation number of object streams is always 0 PdfParserObject* pStream = dynamic_cast(m_vecObjects->GetObject( PdfReference( nObjNo, 0 ) ) ); if( !pStream ) { std::ostringstream oss; oss << "Loading of object " << nObjNo << " 0 R failed!" << std::endl; PODOFO_RAISE_ERROR_INFO( ePdfError_NoObject, oss.str().c_str() ); } PdfObjectStreamParserObject::ObjectIdList list; for( int i = 0; i < m_nNumObjects; i++ ) { if( m_offsets[i].bParsed && m_offsets[i].cUsed == 's' && m_offsets[i].lGeneration == nObjNo) { list.push_back(static_cast(i)); } } PdfObjectStreamParserObject pParserObject( pStream, m_vecObjects, m_buffer, m_pEncrypt ); pParserObject.Parse( list ); } const char* PdfParser::GetPdfVersionString() const { return s_szPdfVersions[static_cast(m_ePdfVersion)]; } void PdfParser::FindToken( const char* pszToken, const long lRange ) { // James McGill 18.02.2011, offset read position to the EOF marker if it is not the last thing in the file m_device.Device()->Seek( -m_lLastEOFOffset, std::ios_base::end ); std::streamoff nFileSize = m_device.Device()->Tell(); if (nFileSize == -1) { PODOFO_RAISE_ERROR_INFO( ePdfError_NoXRef, "Failed to seek to EOF when looking for xref"); } pdf_long lXRefBuf = PDF_MIN( static_cast(nFileSize), static_cast(lRange) ); size_t nTokenLen = strlen( pszToken ); m_device.Device()->Seek( -lXRefBuf, std::ios_base::cur ); if( m_device.Device()->Read( m_buffer.GetBuffer(), lXRefBuf ) != lXRefBuf && !m_device.Device()->Eof() ) { PODOFO_RAISE_ERROR( ePdfError_NoXRef ); } m_buffer.GetBuffer()[lXRefBuf] = '\0'; int i; // Do not make this unsigned, this will cause infinte loops in files without trailer // search backwards in the buffer in case the buffer contains null bytes // because it is right after a stream (can't use strstr for this reason) for( i = lXRefBuf - nTokenLen; i >= 0; i-- ) { if( strncmp( m_buffer.GetBuffer()+i, pszToken, nTokenLen ) == 0 ) { break; } } if( !i ) { PODOFO_RAISE_ERROR( ePdfError_InternalLogic ); } // James McGill 18.02.2011, offset read position to the EOF marker if it is not the last thing in the file m_device.Device()->Seek( ((lXRefBuf-i)*-1)-m_lLastEOFOffset, std::ios_base::end ); } // Peter Petrov 23 December 2008 void PdfParser::FindToken2( const char* pszToken, const long lRange, size_t searchEnd ) { m_device.Device()->Seek( searchEnd, std::ios_base::beg ); std::streamoff nFileSize = m_device.Device()->Tell(); if (nFileSize == -1) { PODOFO_RAISE_ERROR_INFO( ePdfError_NoXRef, "Failed to seek to EOF when looking for xref"); } pdf_long lXRefBuf = PDF_MIN( static_cast(nFileSize), static_cast(lRange) ); size_t nTokenLen = strlen( pszToken ); m_device.Device()->Seek( -lXRefBuf, std::ios_base::cur ); if( m_device.Device()->Read( m_buffer.GetBuffer(), lXRefBuf ) != lXRefBuf && !m_device.Device()->Eof() ) { PODOFO_RAISE_ERROR( ePdfError_NoXRef ); } m_buffer.GetBuffer()[lXRefBuf] = '\0'; // search backwards in the buffer in case the buffer contains null bytes // because it is right after a stream (can't use strstr for this reason) int i; // Do not use an unsigned variable here for( i = lXRefBuf - nTokenLen; i >= 0; i-- ) if( strncmp( m_buffer.GetBuffer()+i, pszToken, nTokenLen ) == 0 ) { break; } if( !i ) { PODOFO_RAISE_ERROR( ePdfError_InternalLogic ); } m_device.Device()->Seek( searchEnd + (lXRefBuf-i)*-1, std::ios_base::beg ); } const PdfString & PdfParser::GetDocumentId() { if( !m_pTrailer->GetDictionary().HasKey( PdfName("ID") ) ) { PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidEncryptionDict, "No document ID found in trailer."); } return m_pTrailer->GetDictionary().GetKey( PdfName("ID") )->GetArray()[0].GetString(); } void PdfParser::UpdateDocumentVersion() { if( m_pTrailer->IsDictionary() && m_pTrailer->GetDictionary().HasKey( PdfName("Root") ) ) { PdfObject* pCatalog = m_pTrailer->GetDictionary().GetKey( PdfName("Root") ); if( pCatalog->IsReference() ) { pCatalog = m_vecObjects->GetObject( pCatalog->GetReference() ); } if( pCatalog && pCatalog->IsDictionary() && pCatalog->GetDictionary().HasKey( PdfName("Version" ) ) ) { PdfObject* pVersion = pCatalog->GetDictionary().GetKey( PdfName( "Version" ) ); for(int i=0;i<=MAX_PDF_VERSION_STRING_INDEX;i++) { if(pVersion->GetName().GetName() == s_szPdfVersionNums[i]) { PdfError::LogMessage( eLogSeverity_Information, "Updating version from %s to %s\n", s_szPdfVersionNums[static_cast(m_ePdfVersion)], s_szPdfVersionNums[i] ); m_ePdfVersion = static_cast(i); break; } } } } } void PdfParser::CheckEOFMarker() { // Check for the existence of the EOF marker m_lLastEOFOffset = 0; const char* pszEOFToken = "%%EOF"; const size_t nEOFTokenLen = 5; char pszBuff[nEOFTokenLen+1]; m_device.Device()->Seek(-static_cast(nEOFTokenLen), std::ios_base::end ); if( IsStrictParsing() ) { // For strict mode EOF marker must be at the very end of the file if( static_cast(m_device.Device()->Read( pszBuff, nEOFTokenLen )) != nEOFTokenLen && !m_device.Device()->Eof() ) PODOFO_RAISE_ERROR( ePdfError_NoEOFToken ); if (strncmp( pszBuff, pszEOFToken, nEOFTokenLen) != 0) PODOFO_RAISE_ERROR( ePdfError_NoEOFToken ); } else { // Search for the Marker from the end of the file pdf_long lCurrentPos = m_device.Device()->Tell(); bool bFound = false; while (lCurrentPos>=0) { m_device.Device()->Seek( lCurrentPos, std::ios_base::beg ); if( static_cast(m_device.Device()->Read( pszBuff, nEOFTokenLen )) != nEOFTokenLen && !m_device.Device()->Eof() ) { PODOFO_RAISE_ERROR( ePdfError_NoEOFToken ); } if (strncmp( pszBuff, pszEOFToken, nEOFTokenLen) == 0) { bFound = true; break; } --lCurrentPos; } // Try and deal with garbage by offsetting the buffer reads in PdfParser from now on if (bFound) m_lLastEOFOffset = (m_nFileSize - (m_device.Device()->Tell()-1)) + nEOFTokenLen; else PODOFO_RAISE_ERROR( ePdfError_NoEOFToken ); } } bool PdfParser::HasXRefStream() { m_device.Device()->Tell(); m_device.Device()->Seek( m_nXRefOffset ); if( !this->IsNextToken( "xref" ) ) { // if( m_ePdfVersion < ePdfVersion_1_5 ) // Ulrich Arnold 19.10.2009, found linearized 1.3-pdf's with trailer-info in xref-stream if( m_ePdfVersion < ePdfVersion_1_3 ) { return false; } else { return true; } } return false; } }; podofo-0.9.3/src/base/PdfColor.h0000664000175000017500000006774212344436402016265 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2007 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_COLOR_H_ #define _PDF_COLOR_H_ #include "PdfDefines.h" #include "PdfName.h" namespace PoDoFo { class PdfArray; class PdfObject; class PdfVecObjects; /** A color object can represent either a grayscale * value, a RGB color, a CMYK color, a separation color or * a CieLab color. * * All drawing functions in PoDoFo accept a PdfColor object * to specify a drawing color in one of these colorspaces. * * Derived classes PdfColorGray, PdfColorRGB, PdfColorCMYK, PdfColorSeparation * and PdfColorCieLab are available for easy construction */ class PODOFO_API PdfColor { public: /** Create a PdfColor object that is RGB black. */ PdfColor(); /** Create a new PdfColor object with * a grayscale value. * * \param dGray a grayscalue value between 0.0 and 1.0 */ explicit PdfColor( double dGray ); /** Create a new PdfColor object with * a RGB color * * \param dRed the value of the red component, must be between 0.0 and 1.0 * \param dGreen the value of the green component, must be between 0.0 and 1.0 * \param dBlue the value of the blue component, must be between 0.0 and 1.0 */ PdfColor( double dRed, double dGreen, double dBlue ); /** Create a new PdfColor object with * a CMYK color * * \param dCyan the value of the cyan component, must be between 0.0 and 1.0 * \param dMagenta the value of the magenta component, must be between 0.0 and 1.0 * \param dYellow the value of the yellow component, must be between 0.0 and 1.0 * \param dBlack the value of the black component, must be between 0.0 and 1.0 */ PdfColor( double dCyan, double dMagenta, double dYellow, double dBlack ); /** Copy constructor * * \param rhs copy rhs into this object */ PdfColor( const PdfColor & rhs ); /** Destructor */ virtual ~PdfColor(); /** Assignment operator * * \param rhs copy rhs into this object * * \returns a reference to this color object */ const PdfColor & operator=( const PdfColor & rhs ); /** Test for equality of colors. * * \param rhs color to compare ro * * \returns true if object color is equal to rhs */ inline bool operator==( const PdfColor & rhs ) const; /** Test for inequality of colors. * * \param rhs color to compare ro * * \returns true if object color is not equal to rhs */ inline bool operator!=( const PdfColor & rhs ) const; /** Test if this is a grayscale color. * * \returns true if this is a grayscale PdfColor object */ inline bool IsGrayScale() const; /** Test if this is a RGB color. * * \returns true if this is a RGB PdfColor object */ inline bool IsRGB() const; /** Test if this is a CMYK color. * * \returns true if this is a CMYK PdfColor object */ inline bool IsCMYK() const; /** Test if this is a separation color. * * \returns true if this is a separation PdfColor object */ inline bool IsSeparation() const; /** Test if this is a CIE-Lab color. * * \returns true if this is a lab Color object */ inline bool IsCieLab() const; /** Get the colorspace of this PdfColor object * * \returns the colorspace of this PdfColor object */ inline EPdfColorSpace GetColorSpace() const; /** Get the alternate colorspace of this PdfColor object * * \returns the colorspace of this PdfColor object (must be separation) */ inline EPdfColorSpace GetAlternateColorSpace() const; /** Get the grayscale color value * of this object. * * Throws an exception if this is no grayscale color object. * * \returns the grayscale color value of this object (between 0.0 and 1.0) * * \see IsGrayScale */ inline double GetGrayScale() const; /** Get the red color value * of this object. * * Throws an exception if this is no RGB color object. * * \returns the red color value of this object (between 0.0 and 1.0) * * \see IsRGB */ inline double GetRed() const; /** Get the green color value * of this object. * * Throws an exception if this is no RGB color object. * * \returns the green color value of this object (between 0.0 and 1.0) * * \see IsRGB */ inline double GetGreen() const; /** Get the blue color value * of this object. * * Throws an exception if this is no RGB color object. * * \returns the blue color value of this object (between 0.0 and 1.0) * * \see IsRGB */ inline double GetBlue() const; /** Get the cyan color value * of this object. * * Throws an exception if this is no CMYK or separation color object. * * \returns the cyan color value of this object (between 0.0 and 1.0) * * \see IsCMYK */ inline double GetCyan() const; /** Get the magenta color value * of this object. * * Throws an exception if this is no CMYK or separation color object. * * \returns the magenta color value of this object (between 0.0 and 1.0) * * \see IsCMYK */ inline double GetMagenta() const; /** Get the yellow color value * of this object. * * Throws an exception if this is no CMYK or separation color object. * * \returns the yellow color value of this object (between 0.0 and 1.0) * * \see IsCMYK */ inline double GetYellow() const; /** Get the black color value * of this object. * * Throws an exception if this is no CMYK or separation color object. * * \returns the black color value of this object (between 0.0 and 1.0) * * \see IsCMYK */ inline double GetBlack() const; /** Get the separation name of this object. * * Throws an exception if this is no separation color object. * * \returns the name of this object * * \see IsSeparation */ inline const std::string GetName() const; /** Get the density color value * of this object. * * Throws an exception if this is no separation color object. * * \returns the density value of this object (between 0.0 and 1.0) * * \see IsSeparation */ inline double GetDensity() const; /** Get the L color value * of this object. * * Throws an exception if this is no CIE-Lab color object. * * \returns the L color value of this object (between 0.0 and 100.0) * * \see IsCieLab */ inline double GetCieL() const; /** Get the A color value * of this object. * * Throws an exception if this is no CIE-Lab color object. * * \returns the A color value of this object (between -128.0 and 127.0) * * \see IsCieLab */ inline double GetCieA() const; /** Get the B color value * of this object. * * Throws an exception if this is no CIE-Lab color object. * * \returns the B color value of this object (between -128.0 and 127.0) * * \see IsCieLab */ inline double GetCieB() const; /** Converts the color object into a grayscale * color object. * * This is only a convinience function. It might be useful * for on screen display but is in NO WAY suitable to * professional printing! * * \returns a grayscale color object * \see IsGrayScale() */ PdfColor ConvertToGrayScale() const; /** Converts the color object into a RGB * color object. * * This is only a convinience function. It might be useful * for on screen display but is in NO WAY suitable to * professional printing! * * \returns a RGB color object * \see IsRGB() */ PdfColor ConvertToRGB() const; /** Converts the color object into a CMYK * color object. * * This is only a convinience function. It might be useful * for on screen display but is in NO WAY suitable to * professional printing! * * \returns a CMYK color object * \see IsCMYK() */ PdfColor ConvertToCMYK() const; /** Creates a PdfArray which represents a color from a color. * \returns a PdfArray object */ PdfArray ToArray() const; /** Creates a color object from a string. * * \param pszName a string describing a color. * * Supported values are: * - single gray values as string (e.g. '0.5') * - a named color (e.g. 'auquamarine' or 'magenta') * - hex values (e.g. #FF002A (RGB) or #FF12AB3D (CMYK)) * - PdfArray's * * \returns a PdfColor object */ static PdfColor FromString( const char* pszName ); /** Creates a color object from a PdfArray which represents a color. * * Raises an exception if this is no PdfColor! * * \param rArray an array that must be a color PdfArray * \returns a PdfColor object */ static PdfColor FromArray( const PdfArray & rArray ); /** * Convert a name into a colorspace enum. * @param rName name representing a colorspace such as DeviceGray * @returns colorspace enum or ePdfColorSpace_Unknown if name is unknown * @see GetNameForColorSpace */ static EPdfColorSpace GetColorSpaceForName( const PdfName & rName ); /** * Convert a colorspace enum value into a name such as DeviceRGB * @param eColorSpace a colorspace * @returns a name * @see GetColorSpaceForName */ static PdfName GetNameForColorSpace( EPdfColorSpace eColorSpace ); /** Creates a colorspace object from a color to insert into resources. * * \param pOwner a pointer to the owner of the generated object * \returns a PdfObject pointer, which can be insert into resources, NULL if not needed */ PdfObject* BuildColorSpace( PdfVecObjects* pOwner ) const; protected: union { double cmyk[4]; double rgb[3]; double lab[3]; double gray; } m_uColor; std::string m_separationName; double m_separationDensity; EPdfColorSpace m_eColorSpace; EPdfColorSpace m_eAlternateColorSpace; private: static const unsigned int* const m_hexDigitMap; ///< Mapping of hex sequences to int value }; class PODOFO_API PdfColorGray : public PdfColor { public: /** Create a new PdfColor object with * a grayscale value. * * \param dGray a grayscalue value between 0.0 and 1.0 */ explicit PdfColorGray( double dGray ); /** Class destructor. */ virtual ~PdfColorGray(); private: /** Default constructor, not implemented */ PdfColorGray(); /** Copy constructor, not implemented */ PdfColorGray(const PdfColorGray& ); /** Copy assignment operator, not implemented */ PdfColorGray& operator=(const PdfColorGray&); }; class PODOFO_API PdfColorRGB : public PdfColor { public: /** Create a new PdfColor object with * a RGB color * * \param dRed the value of the red component, must be between 0.0 and 1.0 * \param dGreen the value of the green component, must be between 0.0 and 1.0 * \param dBlue the value of the blue component, must be between 0.0 and 1.0 */ PdfColorRGB( double dRed, double dGreen, double dBlue ); /** Class destructor. */ virtual ~PdfColorRGB(); private: /** Default constructor, not implemented */ PdfColorRGB(); /** Copy constructor, not implemented */ PdfColorRGB(const PdfColorRGB& ); /** Copy assignment operator, not implemented */ PdfColorRGB& operator=(const PdfColorRGB&); }; class PODOFO_API PdfColorCMYK : public PdfColor { public: /** Create a new PdfColor object with * a CMYK color * * \param dCyan the value of the cyan component, must be between 0.0 and 1.0 * \param dMagenta the value of the magenta component, must be between 0.0 and 1.0 * \param dYellow the value of the yellow component, must be between 0.0 and 1.0 * \param dBlack the value of the black component, must be between 0.0 and 1.0 */ PdfColorCMYK( double dCyan, double dMagenta, double dYellow, double dBlack ); /** Class destructor. */ virtual ~PdfColorCMYK(); private: /** Default constructor, not implemented */ PdfColorCMYK(); /** Copy constructor, not implemented */ PdfColorCMYK(const PdfColorCMYK& ); /** Copy assignment operator, not implemented */ PdfColorCMYK& operator=(const PdfColorCMYK&); }; class PODOFO_API PdfColorSeparationAll : public PdfColor { public: /** Create a new PdfColor object with * Separation color All. * */ PdfColorSeparationAll(); /** Class destructor. */ virtual ~PdfColorSeparationAll(); private: /** Copy constructor, not implemented */ PdfColorSeparationAll(const PdfColorSeparationAll& ); /** Copy assignment operator, not implemented */ PdfColorSeparationAll& operator=(const PdfColorSeparationAll&); }; class PODOFO_API PdfColorSeparationNone : public PdfColor { public: /** Create a new PdfColor object with * Separation color None. * */ PdfColorSeparationNone(); /** Class destructor. */ virtual ~PdfColorSeparationNone(); private: /** Copy constructor, not implemented */ PdfColorSeparationNone(const PdfColorSeparationNone& ); /** Copy assignment operator, not implemented */ PdfColorSeparationNone& operator=(const PdfColorSeparationNone&); }; class PODOFO_API PdfColorSeparation : public PdfColor { public: /** Create a new PdfColor object with * a separation-name and an equivalent color * * \param sName Name of the separation color * \param sDensity the density value of the separation color * \param alternateColor the alternate color, must be of typ gray, rgb, cmyk or cie */ PdfColorSeparation( const std::string & sName, double dDensity, const PdfColor & alternateColor ); /** Class destructor. */ virtual ~PdfColorSeparation(); private: /** Default constructor, not implemented */ PdfColorSeparation(); /** Copy constructor, not implemented */ PdfColorSeparation(const PdfColorSeparation& ); /** Copy assignment operator, not implemented */ PdfColorSeparation& operator=(const PdfColorSeparation&); }; class PODOFO_API PdfColorCieLab : public PdfColor { public: /** Create a new PdfColor object with * a CIE-LAB-values * * \param dCieL the value of the L component, must be between 0.0 and 100.0 * \param dCieA the value of the A component, must be between -128.0 and 127.0 * \param dCieB the value of the B component, must be between -128.0 and 127.0 */ PdfColorCieLab( double dCieL, double dCieA, double dCieB ); /** Class destructor. */ virtual ~PdfColorCieLab(); private: /** Default constructor, not implemented */ PdfColorCieLab(); /** Copy constructor, not implemented */ PdfColorCieLab(const PdfColorCieLab& ); /** Copy assignment operator, not implemented */ PdfColorCieLab& operator=(const PdfColorCieLab&); }; // ----------------------------------------------------- // // ----------------------------------------------------- inline bool PdfColor::operator==( const PdfColor & rhs ) const { if ( m_eColorSpace == rhs.m_eColorSpace ) { if ( (m_eColorSpace == ePdfColorSpace_DeviceGray) && (m_uColor.gray == rhs.m_uColor.gray) ) return true; if ( (m_eColorSpace == ePdfColorSpace_DeviceRGB) && (m_uColor.rgb[0] == rhs.m_uColor.rgb[0]) && (m_uColor.rgb[1] == rhs.m_uColor.rgb[1]) && (m_uColor.rgb[2] == rhs.m_uColor.rgb[2]) ) return true; if ( (m_eColorSpace == ePdfColorSpace_DeviceCMYK) && (m_uColor.cmyk[0] == rhs.m_uColor.cmyk[0]) && (m_uColor.cmyk[1] == rhs.m_uColor.cmyk[1]) && (m_uColor.cmyk[2] == rhs.m_uColor.cmyk[2]) && (m_uColor.cmyk[3] == rhs.m_uColor.cmyk[3]) ) return true; if ( (m_eColorSpace == ePdfColorSpace_CieLab) && (m_uColor.lab[0] == rhs.m_uColor.lab[0]) && (m_uColor.lab[1] == rhs.m_uColor.lab[1]) && (m_uColor.lab[2] == rhs.m_uColor.lab[2]) ) return true; if ( (m_eColorSpace == ePdfColorSpace_Separation) && (m_separationDensity == rhs.m_separationDensity) && (m_separationName == rhs.m_separationName) && (m_eAlternateColorSpace == rhs.m_eAlternateColorSpace) && ( ( (m_eAlternateColorSpace == ePdfColorSpace_DeviceGray) && (m_uColor.gray == rhs.m_uColor.gray) ) || ( (m_eAlternateColorSpace == ePdfColorSpace_DeviceRGB) && (m_uColor.rgb[0] == rhs.m_uColor.rgb[0]) && (m_uColor.rgb[1] == rhs.m_uColor.rgb[1]) && (m_uColor.rgb[2] == rhs.m_uColor.rgb[2]) ) || ( (m_eAlternateColorSpace == ePdfColorSpace_DeviceCMYK) && (m_uColor.cmyk[0] == rhs.m_uColor.cmyk[0]) && (m_uColor.cmyk[1] == rhs.m_uColor.cmyk[1]) && (m_uColor.cmyk[2] == rhs.m_uColor.cmyk[2]) && (m_uColor.cmyk[3] == rhs.m_uColor.cmyk[3]) ) || ( (m_eAlternateColorSpace == ePdfColorSpace_CieLab) && (m_uColor.lab[0] == rhs.m_uColor.lab[0]) && (m_uColor.lab[1] == rhs.m_uColor.lab[1]) && (m_uColor.lab[2] == rhs.m_uColor.lab[2]) ) ) ) return true; if (m_eColorSpace == ePdfColorSpace_Unknown) return true; } return false; } // ----------------------------------------------------- // // ----------------------------------------------------- inline bool PdfColor::operator!=( const PdfColor & rhs ) const { return ! (*this == rhs); } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfColor::IsGrayScale() const { return (m_eColorSpace == ePdfColorSpace_DeviceGray); } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfColor::IsRGB() const { return (m_eColorSpace == ePdfColorSpace_DeviceRGB); } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfColor::IsCMYK() const { return (m_eColorSpace == ePdfColorSpace_DeviceCMYK); } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfColor::IsSeparation() const { return (m_eColorSpace == ePdfColorSpace_Separation); } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfColor::IsCieLab() const { return (m_eColorSpace == ePdfColorSpace_CieLab); } // ----------------------------------------------------- // // ----------------------------------------------------- EPdfColorSpace PdfColor::GetColorSpace() const { return m_eColorSpace; } // ----------------------------------------------------- // // ----------------------------------------------------- EPdfColorSpace PdfColor::GetAlternateColorSpace() const { PODOFO_RAISE_LOGIC_IF( !this->IsSeparation(), "PdfColor::GetAlternateColorSpace cannot be called on non separation color objects!"); return m_eAlternateColorSpace; } // ----------------------------------------------------- // // ----------------------------------------------------- double PdfColor::GetGrayScale() const { PODOFO_RAISE_LOGIC_IF( !this->IsGrayScale() && !(this->IsSeparation() && (this->m_eAlternateColorSpace == ePdfColorSpace_DeviceGray)), "PdfColor::GetGrayScale cannot be called on non grayscale color objects!"); return m_uColor.gray; } // ----------------------------------------------------- // // ----------------------------------------------------- double PdfColor::GetRed() const { PODOFO_RAISE_LOGIC_IF( !this->IsRGB() && !(this->IsSeparation() && (this->m_eAlternateColorSpace == ePdfColorSpace_DeviceRGB)), "PdfColor::GetRed cannot be called on non RGB color objects!"); return m_uColor.rgb[0]; } // ----------------------------------------------------- // // ----------------------------------------------------- double PdfColor::GetGreen() const { PODOFO_RAISE_LOGIC_IF( !this->IsRGB() && !(this->IsSeparation() && (this->m_eAlternateColorSpace == ePdfColorSpace_DeviceRGB)), "PdfColor::GetGreen cannot be called on non RGB color objects!"); return m_uColor.rgb[1]; } // ----------------------------------------------------- // // ----------------------------------------------------- double PdfColor::GetBlue() const { PODOFO_RAISE_LOGIC_IF( !this->IsRGB() && !(this->IsSeparation() && (this->m_eAlternateColorSpace == ePdfColorSpace_DeviceRGB)), "PdfColor::GetBlue cannot be called on non RGB color objects!"); return m_uColor.rgb[2]; } // ----------------------------------------------------- // // ----------------------------------------------------- double PdfColor::GetCyan() const { PODOFO_RAISE_LOGIC_IF( !this->IsCMYK() && !(this->IsSeparation() && (this->m_eAlternateColorSpace == ePdfColorSpace_DeviceCMYK)), "PdfColor::GetCyan cannot be called on non CMYK color objects!"); return m_uColor.cmyk[0]; } // ----------------------------------------------------- // // ----------------------------------------------------- double PdfColor::GetMagenta() const { PODOFO_RAISE_LOGIC_IF( !this->IsCMYK() && !(this->IsSeparation() && (this->m_eAlternateColorSpace == ePdfColorSpace_DeviceCMYK)), "PdfColor::GetMagenta cannot be called on non CMYK color objects!"); return m_uColor.cmyk[1]; } // ----------------------------------------------------- // // ----------------------------------------------------- double PdfColor::GetYellow() const { PODOFO_RAISE_LOGIC_IF( !this->IsCMYK() && !(this->IsSeparation() && (this->m_eAlternateColorSpace == ePdfColorSpace_DeviceCMYK)), "PdfColor::GetYellow cannot be called on non CMYK color objects!"); return m_uColor.cmyk[2]; } // ----------------------------------------------------- // // ----------------------------------------------------- double PdfColor::GetBlack() const { PODOFO_RAISE_LOGIC_IF( !this->IsCMYK() && !(this->IsSeparation() && (this->m_eAlternateColorSpace == ePdfColorSpace_DeviceCMYK)), "PdfColor::GetBlack cannot be called on non CMYK color objects!"); return m_uColor.cmyk[3]; } // ----------------------------------------------------- // // ----------------------------------------------------- const std::string PdfColor::GetName() const { PODOFO_RAISE_LOGIC_IF( !this->IsSeparation(), "PdfColor::GetName cannot be called on non separation color objects!"); return m_separationName; } // ----------------------------------------------------- // // ----------------------------------------------------- double PdfColor::GetDensity() const { PODOFO_RAISE_LOGIC_IF( !this->IsSeparation(), "PdfColor::GetDensity cannot be called on non separation color objects!"); return m_separationDensity; } // ----------------------------------------------------- // // ----------------------------------------------------- double PdfColor::GetCieL() const { PODOFO_RAISE_LOGIC_IF( !this->IsCieLab() && !(this->IsSeparation() && (this->m_eAlternateColorSpace == ePdfColorSpace_CieLab)), "PdfColor::GetCieL cannot be called on non CIE-Lab color objects!"); return m_uColor.lab[0]; } // ----------------------------------------------------- // // ----------------------------------------------------- double PdfColor::GetCieA() const { PODOFO_RAISE_LOGIC_IF( !this->IsCieLab() && !(this->IsSeparation() && (this->m_eAlternateColorSpace == ePdfColorSpace_CieLab)), "PdfColor::GetCieA cannot be called on non CIE-Lab color objects!"); return m_uColor.lab[1]; } // ----------------------------------------------------- // // ----------------------------------------------------- double PdfColor::GetCieB() const { PODOFO_RAISE_LOGIC_IF( !this->IsCieLab() && !(this->IsSeparation() && (this->m_eAlternateColorSpace == ePdfColorSpace_CieLab)), "PdfColor::GetCieB cannot be called on non CIE-Lab color objects!"); return m_uColor.lab[2]; } }; #endif // _PDF_COLOR_H_ podofo-0.9.3/src/base/PdfParserObject.h0000664000175000017500000002155612344436402017563 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2005 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_PARSER_OBJECT_H_ #define _PDF_PARSER_OBJECT_H_ #include "PdfDefines.h" #include "PdfObject.h" #include "PdfTokenizer.h" namespace PoDoFo { class PdfEncrypt; class PdfParser; /** * A PdfParserObject constructs a PdfObject from a PDF file. * Parsing starts always at the current file position. */ class PODOFO_API PdfParserObject : public PdfObject, public PdfTokenizer { public: /** Parse the object data from the given file handle starting at * the current position. * \param pCreator pointer to a PdfVecObjects to resolve object references * \param rDevice an open reference counted input device which is positioned in * front of the object which is going to be parsed. * \param rBuffer buffer to use for parsing to avoid reallocations * \param lOffset the position in the device from which the object shall be read * if lOffset = -1, the object will be read from the current * position in the file. */ PdfParserObject( PdfVecObjects* pCreator, const PdfRefCountedInputDevice & rDevice, const PdfRefCountedBuffer & rBuffer, pdf_long lOffset = -1 ); /** Parse the object data for an internal object. * You have to call ParseDictionaryKeys as next function call. * * The following two parameters are used to avoid allocation of a new * buffer in PdfSimpleParser. * * \warning This constructor is for internal usage only! * * \param rBuffer buffer to use for parsing to avoid reallocations */ explicit PdfParserObject( const PdfRefCountedBuffer & rBuffer ); virtual ~PdfParserObject(); /** Parse the object data from the given file handle * If delayed loading is enabled, only the object and generation number * is read now and everything else is read later. * * \param pEncrypt an encryption dictionary which is used to decrypt * strings and streams during parsing or NULL if the PDF * file was not encrypted * \param bIsTrailer wether this is a trailer dictionary or not. * trailer dictionaries do not have a object number etc. */ void ParseFile( PdfEncrypt* pEncrypt, bool bIsTrailer = false ); /** Returns if this object has a stream object appended. * which has to be parsed. * \returns true if there is a stream */ inline bool HasStreamToParse() const; /** \returns true if this PdfParser loads all objects at * the time they are accessed for the first time. * The default is to load all object immediately. * In this case false is returned. */ inline bool IsLoadOnDemand() const; /** Sets wether this object shall be loaded on demand * when it's data is accessed for the first time. * \param bDelayed if true the object is loaded delayed. */ inline void SetLoadOnDemand( bool bDelayed ); /** Set the object number of this object. * It is almost never necessary to use this call. * It is only included for usage in the PdfParser. * * \param nObjNo the new object number of this object */ inline void SetObjectNumber( unsigned int nObjNo ); /** Tries to free all memory allocated by this * PdfObject (variables and streams) and reads * it from disk again if it is requested another time. * * This will only work if load on demand is used. * If the object is dirty if will not be free'd. * * \param bForce if true the object will be free'd * even if IsDirty() returns true. * So you will loose any changes made * to this object. * * \see IsLoadOnDemand * \see IsDirty */ void FreeObjectMemory( bool bForce = false ); protected: /** Load all data of the object if load object on demand is enabled. * Reimplemented from PdfVariant. Do not call this directly, use * DelayedLoad(). */ virtual void DelayedLoadImpl(); /** Load the stream of the object if it has one and if loading on demand is enabled. * Reimplemented from PdfObject. Do not call this directly, use * DelayedStreamLoad(). */ virtual void DelayedStreamLoadImpl(); /** Starts reading at the file position m_lStreamOffset and interprets all bytes * as contents of the objects stream. * It is assumed that the dictionary has a valid /Length key already. * * Called from DelayedStreamLoadImpl(). Do not call directly. */ void ParseStream(); private: /** Initialize private members in this object with their default values */ void InitPdfParserObject(); /** Parse the object data from the given file handle * \param bIsTrailer wether this is a trailer dictionary or not. * trailer dictionaries do not have a object number etc. */ void ParseFileComplete( bool bIsTrailer ); void ReadObjectNumber(); private: PdfEncrypt* m_pEncrypt; bool m_bIsTrailer; // Should the object try to defer loading of its contents until needed? // If false, object contents will be loaded during ParseFile(...). Note that // this still uses the delayed loading infrastructure. // If true, loading will be triggered the first time the information is needed by // an external caller. // Outside callers should not be able to tell the difference between the two modes // of operation. bool m_bLoadOnDemand; pdf_long m_lOffset; bool m_bStream; pdf_long m_lStreamOffset; }; // ----------------------------------------------------- // // ----------------------------------------------------- void PdfParserObject::SetObjectNumber( unsigned int nObjNo ) { m_reference.SetObjectNumber( nObjNo ); } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfParserObject::IsLoadOnDemand() const { return m_bLoadOnDemand; } // ----------------------------------------------------- // // ----------------------------------------------------- void PdfParserObject::SetLoadOnDemand( bool bDelayed ) { m_bLoadOnDemand = bDelayed; } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfParserObject::HasStreamToParse() const { return m_bStream; } }; #endif // _PDF_PARSER_OBJECT_H_ podofo-0.9.3/src/base/PdfEncoding.h0000664000175000017500000005302412347314771016730 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2007 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_ENCODING_H_ #define _PDF_ENCODING_H_ #include "PdfDefines.h" #include "PdfName.h" #include "PdfString.h" #include "util/PdfMutex.h" #include namespace PoDoFo { class PdfDictionary; class PdfFont; /** * A PdfEncoding is in PdfFont to transform a text string * into a representation so that it can be displayed in a * PDF file. * * PdfEncoding can also be used to convert strings from a * PDF file back into a PdfString. */ class PODOFO_API PdfEncoding { protected: /** * Create a new PdfEncoding. * * \param nFirstChar the first supported character code * (either a byte value in the current encoding or a unicode value) * \param nLastChar the last supported character code, must be larger than nFirstChar - * (either a byte value in the current encoding or a unicode value) * */ PdfEncoding( int nFirstChar, int nLastChar ); /** Get a unique ID for this encoding * which can used for comparisons! * * \returns a unique id for this encoding! */ virtual const PdfName & GetID() const = 0; public: #if defined(_MSC_VER) && _MSC_VER <= 1200 // ab Visualstudio 6 class PODOFO_API const_iterator : public std::iterator< std::forward_iterator_tag, int, ptrdiff_t> { #else class PODOFO_API const_iterator : public std::iterator< std::forward_iterator_tag, int, std::ptrdiff_t, const int *, const int &> { #endif public: const_iterator( const PdfEncoding* pEncoding, int nCur ) : m_pEncoding( pEncoding ), m_nCur( nCur ) { } const_iterator( const const_iterator & rhs ) { this->operator=(rhs); } const const_iterator & operator=( const const_iterator & rhs ) { m_nCur = rhs.m_nCur; m_pEncoding = rhs.m_pEncoding; return *this; } inline bool operator==( const const_iterator & rhs ) const { return (m_nCur == rhs.m_nCur); } inline bool operator!=( const const_iterator & rhs ) const { return (m_nCur != rhs.m_nCur); } inline pdf_utf16be operator*() const { return m_pEncoding->GetCharCode( m_nCur ); } inline const_iterator & operator++() { m_nCur++; return *this; } private: const PdfEncoding* m_pEncoding; int m_nCur; }; virtual ~PdfEncoding(); /** Comparison operator. * * \param rhs the PdfEncoding to which this encoding should be compared * * \returns true if both encodings are the same. */ inline bool operator==( const PdfEncoding & rhs ) const; /** Comparison operator. * * \param rhs the PdfEncoding to which this encoding should be compared * * \returns true if this encoding is less than the specified. */ inline bool operator<( const PdfEncoding & rhs ) const; /** Add this encoding object to a dictionary * usually be adding an /Encoding key in font dictionaries. * * \param rDictionary add the encoding to this dictionary */ virtual void AddToDictionary( PdfDictionary & rDictionary ) const = 0; /** Convert a string that is encoded with this encoding * to an unicode PdfString. * * \param rEncodedString a string encoded by this encoding. * Usually this string was read from a content stream. * \param pFont the font for which this string is converted * * \returns an unicode PdfString. */ virtual PdfString ConvertToUnicode( const PdfString & rEncodedString, const PdfFont* pFont ) const = 0; /** Convert a unicode PdfString to a string encoded with this encoding. * * \param rString an unicode PdfString. * \param pFont the font for which this string is converted * * \returns an encoded PdfRefCountedBuffer. The PdfRefCountedBuffer is treated as a series of bytes * and is allowed to have 0 bytes. The returned buffer must not be a unicode string. */ virtual PdfRefCountedBuffer ConvertToEncoding( const PdfString & rString, const PdfFont* pFont ) const = 0; virtual bool IsAutoDelete() const = 0; virtual bool IsSingleByteEncoding() const = 0; /** * \returns the first character code that is defined for this encoding */ inline int GetFirstChar() const; /** * \returns the last character code that is defined for this encoding */ inline int GetLastChar() const; /** Iterate over all unicode character points in this * encoding, beginning with the first. * * \returns iterator pointing to the first defined unicode character */ inline const_iterator begin() const; /** Iterate over all unicode character points in this * encoding, beginning with the first. * * \returns iterator pointing at the end */ inline const_iterator end() const; /** Get the unicode character code for this encoding * at the position nIndex. nIndex is a position between * GetFirstChar() and GetLastChar() * * \param nIndex character code at position index * \returns unicode character code * * \see GetFirstChar * \see GetLastChar * * Will throw an exception if nIndex is out of range. */ virtual pdf_utf16be GetCharCode( int nIndex ) const = 0; private: int m_nFirstChar; ///< The first defined character code int m_nLastChar; ///< The last defined character code }; // ----------------------------------------------------- // // ----------------------------------------------------- inline bool PdfEncoding::operator<( const PdfEncoding & rhs ) const { return (this->GetID() < rhs.GetID()); } // ----------------------------------------------------- // // ----------------------------------------------------- inline bool PdfEncoding::operator==( const PdfEncoding & rhs ) const { return (this->GetID() == rhs.GetID()); } // ----------------------------------------------------- // // ----------------------------------------------------- inline int PdfEncoding::GetFirstChar() const { return m_nFirstChar; } // ----------------------------------------------------- // // ----------------------------------------------------- inline int PdfEncoding::GetLastChar() const { return m_nLastChar; } // ----------------------------------------------------- // // ----------------------------------------------------- inline PdfEncoding::const_iterator PdfEncoding::begin() const { return PdfEncoding::const_iterator( this, this->GetFirstChar() ); } // ----------------------------------------------------- // // ----------------------------------------------------- inline PdfEncoding::const_iterator PdfEncoding::end() const { return PdfEncoding::const_iterator( this, this->GetLastChar() + 1 ); } /** * A common base class for standard PdfEncoding which are * known by name. * * - PdfDocEncoding (only use this for strings which are not printed * in the document. This is for meta data in the PDF). * - MacRomanEncoding * - WinAnsiEncoding * - MacExpertEncoding * - StandardEncoding * - SymbolEncoding * - ZapfDingbatsEncoding * * \see PdfWinAnsiEncoding * \see PdfMacRomanEncoding * \see PdfMacExportEncoding *..\see PdfStandardEncoding * \see PdfSymbolEncoding * \see PdfZapfDingbatsEncoding * */ class PODOFO_API PdfSimpleEncoding : public PdfEncoding { public: /* * Create a new simple PdfEncoding which uses 1 byte. * * \param rName the name of a standard PdfEncoding * * As of now possible values for rName are: * - MacRomanEncoding * - WinAnsiEncoding * - MacExpertEncoding * - StandardEncoding * - SymbolEncoding * - ZapfDingbatsEncoding * * \see PdfWinAnsiEncoding * \see PdfMacRomanEncoding * \see PdfMacExportEncoding * \see PdfStandardEncoding * \see PdfSymbolEncoding * \see PdfZapfDingbatsEncoding * * This will allocate a table of 65535 short values * to make conversion from unicode to encoded strings * faster. As this requires a lot of memory, make sure that * only one object of a certain encoding exists at one * time, which is no problem as all methods are const anyways! * */ PdfSimpleEncoding( const PdfName & rName ); ~PdfSimpleEncoding(); /** Add this encoding object to a dictionary * usually be adding an /Encoding key in font dictionaries. * * \param rDictionary add the encoding to this dictionary */ virtual void AddToDictionary( PdfDictionary & rDictionary ) const; /** Convert a string that is encoded with this encoding * to an unicode PdfString. * * \param rEncodedString a string encoded by this encoding. * Usually this string was read from a content stream. * \param pFont the font for which this string is converted * * \returns an unicode PdfString. */ virtual PdfString ConvertToUnicode( const PdfString & rEncodedString, const PdfFont* pFont ) const; /** Convert a unicode PdfString to a string encoded with this encoding. * * \param rString an unicode PdfString. * \param pFont the font for which this string is converted * * \returns an encoded PdfRefCountedBuffer. The PdfRefCountedBuffer is treated as a series of bytes * and is allowed to have 0 bytes. The returned buffer must not be a unicode string. */ virtual PdfRefCountedBuffer ConvertToEncoding( const PdfString & rString, const PdfFont* pFont ) const; /** * PdfSimpleEncoding subclasses are usuylla not auto-deleted, as * they are allocated statically only once. * * \returns true if this encoding should be deleted automatically with the * font. * * \see PdfFont::WinAnsiEncoding * \see PdfFont::MacRomanEncoding */ virtual bool IsAutoDelete() const; /** * \returns true if this is a single byte encoding with a maximum of 256 values. */ inline virtual bool IsSingleByteEncoding() const; /** Get the name of this encoding. * * \returns the name of this encoding. */ inline const PdfName & GetName() const; /** Get the unicode character code for this encoding * at the position nIndex. nIndex is a position between * GetFirstChar() and GetLastChar() * * \param nIndex character code at position index * \returns unicode character code * * \see GetFirstChar * \see GetLastChar * * Will throw an exception if nIndex is out of range. */ virtual pdf_utf16be GetCharCode( int nIndex ) const; char GetUnicodeCharCode(pdf_utf16be unicodeValue) const; private: /** Initialize the internal table of mappings from unicode code points * to encoded byte values. */ void InitEncodingTable(); protected: /** Get a unique ID for this encoding * which can used for comparisons! * * \returns a unique id for this encoding! */ inline virtual const PdfName & GetID() const; /** Gets a table of 256 short values which are the * big endian unicode code points that are assigned * to the 256 values of this encoding. * * This table is used internally to convert an encoded * string of this encoding to and from unicode. * * \returns an array of 256 big endian unicode code points */ virtual const pdf_utf16be* GetToUnicodeTable() const = 0; protected: Util::PdfMutex * m_mutex; ///< Mutex for the creation of the encoding table private: PdfName m_name; ///< The name of the encoding char* m_pEncodingTable; ///< The helper table for conversions into this encoding }; // ----------------------------------------------------- // // ----------------------------------------------------- inline const PdfName & PdfSimpleEncoding::GetID() const { return m_name; } // ----------------------------------------------------- // // ----------------------------------------------------- inline bool PdfSimpleEncoding::IsAutoDelete() const { return false; } // ----------------------------------------------------- // // ----------------------------------------------------- inline bool PdfSimpleEncoding::IsSingleByteEncoding() const { return true; } // ----------------------------------------------------- // // ----------------------------------------------------- inline const PdfName & PdfSimpleEncoding::GetName() const { return m_name; } /** * The PdfDocEncoding is the default encoding for * all strings in PoDoFo which are data in the PDF * file. * * Do not allocate this class yourself, as allocations * might be expensive. Try using PdfFont::DocEncoding. * * \see PdfFont::DocEncoding */ class PODOFO_API PdfDocEncoding : public PdfSimpleEncoding { public: /** Create a new PdfDocEncoding */ PdfDocEncoding() : PdfSimpleEncoding( PdfName("PdfDocEncoding") ) { } protected: /** Gets a table of 256 short values which are the * big endian unicode code points that are assigned * to the 256 values of this encoding. * * This table is used internally to convert an encoded * string of this encoding to and from unicode. * * \returns an array of 256 big endian unicode code points */ virtual const pdf_utf16be* GetToUnicodeTable() const; private: static const pdf_utf16be s_cEncoding[256]; ///< conversion table from DocEncoding to UTF16 }; /** * The WinAnsi Encoding is the default encoding in PoDoFo for * contents on PDF pages. * * It is also called CP-1252 encoding. * * Do not allocate this class yourself, as allocations * might be expensive. Try using PdfFont::WinAnsiEncoding. * * \see PdfFont::WinAnsiEncoding */ class PODOFO_API PdfWinAnsiEncoding : public PdfSimpleEncoding { public: /** Create a new PdfWinAnsiEncoding */ PdfWinAnsiEncoding() : PdfSimpleEncoding( PdfName("WinAnsiEncoding") ) { } protected: /** Gets a table of 256 short values which are the * big endian unicode code points that are assigned * to the 256 values of this encoding. * * This table is used internally to convert an encoded * string of this encoding to and from unicode. * * \returns an array of 256 big endian unicode code points */ virtual const pdf_utf16be* GetToUnicodeTable() const; private: static const pdf_utf16be s_cEncoding[256]; ///< conversion table from WinAnsiEncoding to UTF16 }; /** * Do not allocate this class yourself, as allocations * might be expensive. Try using PdfFont::MacRomanEncoding. * * \see PdfFont::MacRomanEncoding */ class PODOFO_API PdfMacRomanEncoding : public PdfSimpleEncoding { public: /** Create a new PdfMacRomanEncoding */ PdfMacRomanEncoding() : PdfSimpleEncoding( PdfName("MacRomanEncoding") ) { } protected: /** Gets a table of 256 short values which are the * big endian unicode code points that are assigned * to the 256 values of this encoding. * * This table is used internally to convert an encoded * string of this encoding to and from unicode. * * \returns an array of 256 big endian unicode code points */ virtual const pdf_utf16be* GetToUnicodeTable() const; private: static const pdf_utf16be s_cEncoding[256]; ///< conversion table from MacRomanEncoding to UTF16 }; /** */ class PODOFO_API PdfMacExpertEncoding : public PdfSimpleEncoding { public: /** Create a new PdfMacExpertEncoding */ inline PdfMacExpertEncoding() : PdfSimpleEncoding( PdfName("MacExpertEncoding") ) { } protected: /** Gets a table of 256 short values which are the * big endian unicode code points that are assigned * to the 256 values of this encoding. * * This table is used internally to convert an encoded * string of this encoding to and from unicode. * * \returns an array of 256 big endian unicode code points */ virtual const pdf_utf16be* GetToUnicodeTable() const; private: static const pdf_utf16be s_cEncoding[256]; ///< conversion table from MacExpertEncoding to UTF16 }; // OC 13.08.2010 Neu: StandardEncoding /** * Do not allocate this class yourself, as allocations * might be expensive. Try using PdfFont::StandardEncoding. * * \see PdfFont::StandardEncoding */ class PODOFO_API PdfStandardEncoding : public PdfSimpleEncoding { public: /** Create a new PdfStandardEncoding */ PdfStandardEncoding() : PdfSimpleEncoding( PdfName("StandardEncoding") ) { } protected: /** Gets a table of 256 short values which are the * big endian unicode code points that are assigned * to the 256 values of this encoding. * * This table is used internally to convert an encoded * string of this encoding to and from unicode. * * \returns an array of 256 big endian unicode code points */ virtual const pdf_utf16be* GetToUnicodeTable() const; private: static const pdf_utf16be s_cEncoding[256]; ///< conversion table from StandardEncoding to UTF16 }; // OC 13.08.2010 Neu: SymbolEncoding /** * Do not allocate this class yourself, as allocations * might be expensive. Try using PdfFont::SymbolEncoding. * * \see PdfFont::SymbolEncoding */ class PODOFO_API PdfSymbolEncoding : public PdfSimpleEncoding { public: /** Create a new PdfSymbolEncoding */ PdfSymbolEncoding() : PdfSimpleEncoding( PdfName("SymbolEncoding") ) { } protected: /** Gets a table of 256 short values which are the * big endian unicode code points that are assigned * to the 256 values of this encoding. * * This table is used internally to convert an encoded * string of this encoding to and from unicode. * * \returns an array of 256 big endian unicode code points */ virtual const pdf_utf16be* GetToUnicodeTable() const; private: static const pdf_utf16be s_cEncoding[256]; ///< conversion table from SymbolEncoding to UTF16 }; // OC 13.08.2010 Neu: ZapfDingbatsEncoding /** * Do not allocate this class yourself, as allocations * might be expensive. Try using PdfFont::ZapfDingbats. * * \see PdfFont::ZapfDingbatsEncoding */ class PODOFO_API PdfZapfDingbatsEncoding : public PdfSimpleEncoding { public: /** Create a new PdfZapfDingbatsEncoding */ PdfZapfDingbatsEncoding() : PdfSimpleEncoding( PdfName("ZapfDingbatsEncoding") ) { } protected: /** Gets a table of 256 short values which are the * big endian unicode code points that are assigned * to the 256 values of this encoding. * * This table is used internally to convert an encoded * string of this encoding to and from unicode. * * \returns an array of 256 big endian unicode code points */ virtual const pdf_utf16be* GetToUnicodeTable() const; private: static const pdf_utf16be s_cEncoding[256]; ///< conversion table from ZapfDingbatsEncoding to UTF16 }; }; /* namespace PoDoFo */ #endif // _PDF_ENCODING_H_ podofo-0.9.3/src/base/PdfCanvas.h0000664000175000017500000001146112344436402016405 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2006 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_CANVAS_H_ #define _PDF_CANVAS_H_ #include "PdfDefines.h" #include "PdfArray.h" namespace PoDoFo { class PdfDictionary; class PdfObject; class PdfRect; class PdfColor; /** A interface that provides the necessary features * for a painter to draw onto a PdfObject. */ class PODOFO_API PdfCanvas { public: /** Virtual destructor * to avoid compiler warnings */ virtual ~PdfCanvas() {}; /** Get access to the contents object of this page. * If you want to draw onto the page, you have to add * drawing commands to the stream of the Contents object. * \returns a contents object */ virtual PdfObject* GetContents() const = 0; /** Get access an object that you can use to ADD drawing to. * If you want to draw onto the page, you have to add * drawing commands to the stream of the Contents object. * \returns a contents object */ virtual PdfObject* GetContentsForAppending() const = 0; /** Get access to the resources object of this page. * This is most likely an internal object. * \returns a resources object */ virtual PdfObject* GetResources() const = 0; /** Get the current page size in PDF Units * \returns a PdfRect containing the page size available for drawing */ virtual const PdfRect GetPageSize() const = 0; /** Get a reference to a static procset PdfArray. * \returns a reference to a static procset PdfArray */ static const PdfArray & GetProcSet(); /** Register a colourspace for a (separation) colour in the resource dictionary * of this page or XObbject so that it can be used for any following drawing * operations. * * \param rColor reference to the PdfColor */ void AddColorResource( const PdfColor & rColor ); /** Register an object in the resource dictionary of this page or XObbject * so that it can be used for any following drawing operations. * * \param rIdentifier identifier of this object, e.g. /Ft0 * \param rRef reference to the object you want to register * \param rName register under this key in the resource dictionary */ void AddResource( const PdfName & rIdentifier, const PdfReference & rRef, const PdfName & rName ); private: /** The procset is the same for all * PdfContents objects */ static PdfArray s_procset; }; }; #endif /* _PDF_CANVAS_H_ */ podofo-0.9.3/src/base/PdfRefCountedBuffer.cpp0000664000175000017500000002535712344436402020726 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2006 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfRefCountedBuffer.h" #include "PdfDefinesPrivate.h" #include #include namespace PoDoFo { PdfRefCountedBuffer::PdfRefCountedBuffer( char* pBuffer, size_t lSize ) : m_pBuffer( NULL ) { if( pBuffer && lSize ) { m_pBuffer = new TRefCountedBuffer(); m_pBuffer->m_lRefCount = 1; m_pBuffer->m_pHeapBuffer = pBuffer; m_pBuffer->m_bOnHeap = true; m_pBuffer->m_lBufferSize = lSize; m_pBuffer->m_lVisibleSize = lSize; m_pBuffer->m_bPossesion = true; } } void PdfRefCountedBuffer::FreeBuffer() { PODOFO_RAISE_LOGIC_IF( !m_pBuffer || m_pBuffer->m_lRefCount, "Tried to free in-use buffer" ); // last owner of the file! if( m_pBuffer->m_bOnHeap && m_pBuffer->m_bPossesion ) free( m_pBuffer->m_pHeapBuffer ); delete m_pBuffer; } void PdfRefCountedBuffer::ReallyDetach( size_t lExtraLen ) { PODOFO_RAISE_LOGIC_IF( m_pBuffer && m_pBuffer->m_lRefCount == 1, "Use Detach() rather than calling ReallyDetach() directly." ) size_t lSize = m_pBuffer->m_lBufferSize + lExtraLen; TRefCountedBuffer* pBuffer = new TRefCountedBuffer(); pBuffer->m_lRefCount = 1; pBuffer->m_bOnHeap = (lSize > TRefCountedBuffer::INTERNAL_BUFSIZE); if ( pBuffer->m_bOnHeap ) pBuffer->m_pHeapBuffer = static_cast(malloc( sizeof(char)*lSize )); else pBuffer->m_pHeapBuffer = 0; pBuffer->m_lBufferSize = PDF_MAX( lSize, static_cast(+TRefCountedBuffer::INTERNAL_BUFSIZE) ); pBuffer->m_bPossesion = true; if( pBuffer->m_bOnHeap && !pBuffer->m_pHeapBuffer ) { delete pBuffer; pBuffer = NULL; PODOFO_RAISE_ERROR( ePdfError_OutOfMemory ); } memcpy( pBuffer->GetRealBuffer(), this->GetBuffer(), this->GetSize() ); // Detaching the buffer should have NO visible effect to clients, so the // visible size must not change. pBuffer->m_lVisibleSize = m_pBuffer->m_lVisibleSize; // Now that we've copied the data, release our claim on the old buffer, // deleting it if needed, and link up the new one. DerefBuffer(); m_pBuffer = pBuffer; } void PdfRefCountedBuffer::ReallyResize( const size_t lSize ) { if( m_pBuffer ) { // Resizing the buffer counts as altering it, so detach as per copy on write behaviour. If the detach // actually has to do anything it'll reallocate the buffer at the new desired size. this->Detach( static_cast(m_pBuffer->m_lBufferSize) < lSize ? lSize - static_cast(m_pBuffer->m_lBufferSize) : 0 ); // We might have pre-allocated enough to service the request already if( static_cast(m_pBuffer->m_lBufferSize) < lSize ) { // Allocate more space, since we need it. We over-allocate so that clients can efficiently // request lots of small resizes if they want, but these over allocations are not visible // to clients. // const size_t lAllocSize = PDF_MAX(lSize, m_pBuffer->m_lBufferSize) << 1; if ( m_pBuffer->m_bPossesion && m_pBuffer->m_bOnHeap ) { // We have an existing on-heap buffer that we own. Realloc() // it, potentially saving us a memcpy and free(). void* temp = realloc( m_pBuffer->m_pHeapBuffer, lAllocSize ); if (!temp) { PODOFO_RAISE_ERROR_INFO( ePdfError_OutOfMemory, "PdfRefCountedBuffer::Resize failed!" ); } m_pBuffer->m_pHeapBuffer = static_cast(temp); m_pBuffer->m_lBufferSize = lAllocSize; } else { // Either we don't own the buffer or it's a local static buffer that's no longer big enough. // Either way, it's time to move to a heap-allocated buffer we own. char* pBuffer = static_cast(malloc( sizeof(char) * lAllocSize )); if( !pBuffer ) { PODOFO_RAISE_ERROR_INFO( ePdfError_OutOfMemory, "PdfRefCountedBuffer::Resize failed!" ); } // Only bother copying the visible portion of the buffer. It's completely incorrect // to rely on anything more than that, and not copying it will help catch those errors. memcpy( pBuffer, m_pBuffer->GetRealBuffer(), m_pBuffer->m_lVisibleSize ); // Record the newly allocated buffer's details. The visible size gets updated later. m_pBuffer->m_lBufferSize = lAllocSize; m_pBuffer->m_pHeapBuffer = pBuffer; m_pBuffer->m_bOnHeap = true; } } else { // Allocated buffer is large enough, do nothing } } else { // No buffer was allocated at all, so we need to make one. m_pBuffer = new TRefCountedBuffer(); m_pBuffer->m_lRefCount = 1; m_pBuffer->m_bOnHeap = (lSize > TRefCountedBuffer::INTERNAL_BUFSIZE); if ( m_pBuffer->m_bOnHeap ) { m_pBuffer->m_pHeapBuffer = static_cast(malloc( sizeof(char)*lSize )); } else { m_pBuffer->m_pHeapBuffer = 0; } m_pBuffer->m_lBufferSize = PDF_MAX( lSize, static_cast(+TRefCountedBuffer::INTERNAL_BUFSIZE) ); m_pBuffer->m_bPossesion = true; if( m_pBuffer->m_bOnHeap && !m_pBuffer->m_pHeapBuffer ) { delete m_pBuffer; m_pBuffer = NULL; PODOFO_RAISE_ERROR( ePdfError_OutOfMemory ); } } m_pBuffer->m_lVisibleSize = lSize; PODOFO_RAISE_LOGIC_IF ( m_pBuffer->m_lVisibleSize > m_pBuffer->m_lBufferSize, "Buffer improperly allocated/resized"); } const PdfRefCountedBuffer & PdfRefCountedBuffer::operator=( const PdfRefCountedBuffer & rhs ) { // Self assignment is a no-op if (this == &rhs) return rhs; DerefBuffer(); m_pBuffer = rhs.m_pBuffer; if( m_pBuffer ) m_pBuffer->m_lRefCount++; return *this; } bool PdfRefCountedBuffer::operator==( const PdfRefCountedBuffer & rhs ) const { if( m_pBuffer != rhs.m_pBuffer ) { if( m_pBuffer && rhs.m_pBuffer ) { if ( m_pBuffer->m_lVisibleSize != rhs.m_pBuffer->m_lVisibleSize ) // Unequal buffer sizes cannot be equal buffers return false; // Test for byte-for-byte equality since lengths match return (memcmp( m_pBuffer->GetRealBuffer(), rhs.m_pBuffer->GetRealBuffer(), m_pBuffer->m_lVisibleSize ) == 0 ); } else // Cannot be equal if only one object has a real data buffer return false; } return true; } bool PdfRefCountedBuffer::operator<( const PdfRefCountedBuffer & rhs ) const { // equal buffers are neither smaller nor greater if( m_pBuffer == rhs.m_pBuffer ) return false; if( !m_pBuffer && rhs.m_pBuffer ) return true; else if( m_pBuffer && !rhs.m_pBuffer ) return false; else { int cmp = memcmp( m_pBuffer->GetRealBuffer(), rhs.m_pBuffer->GetRealBuffer(), PDF_MIN( m_pBuffer->m_lVisibleSize, rhs.m_pBuffer->m_lVisibleSize ) ); if (cmp == 0) // If one is a prefix of the other, ie they compare equal for the length of the shortest but one is longer, // the longer buffer is the greater one. return m_pBuffer->m_lVisibleSize < rhs.m_pBuffer->m_lVisibleSize; else return cmp < 0; } } bool PdfRefCountedBuffer::operator>( const PdfRefCountedBuffer & rhs ) const { // equal buffers are neither smaller nor greater if( m_pBuffer == rhs.m_pBuffer ) return false; if( !m_pBuffer && rhs.m_pBuffer ) return false; else if( m_pBuffer && !rhs.m_pBuffer ) return true; else { int cmp = memcmp( m_pBuffer->GetRealBuffer(), rhs.m_pBuffer->GetRealBuffer(), PDF_MIN( m_pBuffer->m_lVisibleSize, rhs.m_pBuffer->m_lVisibleSize ) ); if (cmp == 0) // If one is a prefix of the other, ie they compare equal for the length of the shortest but one is longer, // the longer buffer is the greater one. return m_pBuffer->m_lVisibleSize > rhs.m_pBuffer->m_lVisibleSize; else return cmp > 0; } } }; podofo-0.9.3/src/base/PdfString.h0000664000175000017500000004610712347313527016452 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2006 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_STRING_H_ #define _PDF_STRING_H_ #include "PdfDefines.h" #include "PdfDataType.h" #include "PdfRefCountedBuffer.h" namespace PoDoFo { #define PDF_STRING_BUFFER_SIZE 24 class PdfEncoding; class PdfOutputDevice; enum EPdfStringConversion { ePdfStringConversion_Strict, ePdfStringConversion_Lenient }; /** A string that can be written to a PDF document. * If it contains binary data it is automatically * converted into a hex string, otherwise a normal PDF * string is written to the document. * * PdfStrings representing text are either in PDFDocEncoding * (ISO Latin1) encoded or UTF-16BE encoded. * * PoDoFo contains methods to convert between these * encodings. For convinience conversion to UTF-8 * is possible to. Please not that strings are * always stored as UTF-16BE or ISO Latin1 (PdfDocEncoding) * in the PDF file. * * UTF-16BE strings have to start with the byts 0xFE 0xFF * to be recognized by PoDoFo as unicode strings. * * * PdfStrings is an implicitly shared class. As a reason * it is very fast to copy PdfString objects. * * The internal string buffer is guaranteed to be always terminated * by 2 zeros. */ class PODOFO_API PdfString : public PdfDataType{ public: /** Create an empty and invalid string */ PdfString(); /** Construct a new PdfString from a std::string. * The input string will be copied. * If the first to bytes of the string are 0xFE and 0xFF * this string is treated as UTF-16BE encoded unicode string. * * \param sString the string to copy * \param pEncoding the encoding of this string, if it is no unicode string. * This is ignored for unicode strings. If NULL PdfDocEncoding will be used as a default. */ PdfString( const std::string& sString, const PdfEncoding * const pEncoding = NULL ); /** Construct a new PdfString from a 0 terminated * string. * The input string will be copied. * * \param pszString the string to copy * \param pEncoding the encoding of this string, if it is no unicode string. * This is ignored for unicode strings. If NULL PdfDocEncoding will be used as a default. */ PdfString( const char* pszString, const PdfEncoding * const pEncoding = NULL ); /** Construct a new PdfString from a 0 terminated * string. * The input string will be copied. * * \param pszString the string to copy */ #if defined(_MSC_VER) && _MSC_VER <= 1200 // nicht fr Visualstudio 6 #else PdfString( const wchar_t* pszString, pdf_long lLen = -1 ); #endif void setFromWchar_t( const wchar_t* pszString, pdf_long lLen = -1 ); /** Construct a new PdfString from a string. * The input string will be copied. * If the first to bytes of the string are 0xFE and 0xFF * this string is treated as UTF-16BE encoded unicode string. * * \param pszString the string to copy * \param lLen length of the string data to encode * \param bHex if true the data will be * hex encoded during writeout of the string and IsHex() will return true. * \param pEncoding the encoding of this string, if it is no unicode string. * This is ignored for unicode strings. If NULL PdfDocEncoding will be used as a default. */ PdfString( const char* pszString, pdf_long lLen, bool bHex = false, const PdfEncoding * const pEncoding = NULL ); /** Construct a new PdfString from an UTF-8 encoded string. * * The string is converted to UTF-16BE internally. * * \param pszStringUtf8 a UTF-8 encoded string. */ PdfString( const pdf_utf8* pszStringUtf8 ); /** Construct a new PdfString from an UTF-16be encoded zero terminated string. * * \param pszStringUtf16 a UTF-16BE encoded string. */ PdfString( const pdf_utf16be* pszStringUtf16 ); /** Construct a new PdfString from an UTF-8 encoded string. * * The string is converted to UTF-16BE internally. * * \param pszStringUtf8 a UTF-8 encoded string. * \param lLen number of bytes to convert */ PdfString( const pdf_utf8* pszStringUtf8, pdf_long lLen ); /** Construct a new PdfString from an UTF-16be encoded zero terminated string. * * \param pszStringUtf16 a UTF-16BE encoded string. * \param lLen number of words to convert */ PdfString( const pdf_utf16be* pszStringUtf16, pdf_long lLen ); /** Copy an existing PdfString * \param rhs another PdfString to copy */ PdfString( const PdfString & rhs ); ~PdfString(); /** Set hex encoded data as the strings data. * \param pszHex must be hex encoded data. * \param lLen length of the hex encoded data. * if lLen == -1 then strlen( pszHex ) will * be used as length of the hex data. * pszHex has to be zero terminated in this case. * \param pEncrypt if !NULL assume the hex data is encrypted and should be decrypted after hexdecoding */ void SetHexData( const char* pszHex, pdf_long lLen = -1, PdfEncrypt* pEncrypt = NULL ); /** The string is valid if no error in the constructor has occurred. * If it is valid it is safe to call all the other member functions. * \returns true if this is a valid initialized PdfString */ inline bool IsValid() const; /** Check if this is a hex string. * * If true the data will be hex encoded when the string is written to * a PDF file. * * \returns true if this is a hex string. * \see GetString() will return the raw string contents (not hex encoded) */ inline bool IsHex () const; /** * PdfStrings are either Latin1 encoded or UTF-16BE * encoded unicode strings. * This functions returns true if this is a unicode * string object. * * \returns true if this is a unicode string. */ inline bool IsUnicode () const; /** The contents of the strings can be read * by this function. * * The returned data is never hex encoded may contain 0 bytes. * * if IsUnicode() returns true, the return value * points to a UTF-16BE string buffer with Length() * characters. Better use GetUnicode() in this case. * * \returns the strings contents which is guaranteed to be zero terminated * but might also contain 0 bytes in the string. * \see IsHex * \see IsUnicode * \see Length */ inline const char* GetString() const; /** The contents of the strings can be read * by this function. * * The returned data is never hex encoded any maycontain 0 bytes. * * if IsUnicode() returns true, the return value * points to a UTF-16BE string buffer with Length() * characters. Better use GetUnicode() in this case. * * \returns the strings contents which is guaranteed to be zero terminated * but might also contain 0 bytes in the string. * * \see IsHex * \see IsUnicode * \see Length */ inline const pdf_utf16be* GetUnicode() const; /** The contents of the string as UTF8 string. * * The strings contents are always returned as * UTF8 by this function. Works for unicode strings * and for non unicode strings. * * This is the prefered way to access the strings contents. * * \returns the string contents always as UTF8. */ inline const std::string & GetStringUtf8() const; #ifdef _WIN32 /** The contents of the string as wide character string. * * \returns the string contents as wide character string. */ const std::wstring GetStringW() const; #endif // _WIN32 /** The length of the string data returned by GetString() * in bytes not including terminating zeros. * * \returns the length of the string. * * \see GetCharacterLength to determine the number of characters in the string */ inline pdf_long GetLength() const; /** The length of the string data returned by GetUnicode() * in characters not including the terminating zero * * \returns the length of the string. * * \see GetCharacterLength to determine the number of characters in the string */ inline pdf_long GetUnicodeLength() const; /** Get the number of characters in the string. * * This function returns the correct number of characters in the string * for unicode and ansi strings. Always use this method if you want to * know the number of characters in the string * as GetLength() will returns the number of bytes used for unicode strings! * * * \returns the number of characters in the string */ inline pdf_long GetCharacterLength() const; /** Write this PdfString in PDF format to a PdfOutputDevice * * \param pDevice the output device. * \param eWriteMode additional options for writing this object * \param pEncrypt an encryption object which is used to encrypt this object * or NULL to not encrypt this object */ void Write ( PdfOutputDevice* pDevice, EPdfWriteMode eWriteMode, const PdfEncrypt* pEncrypt = NULL ) const; /** Copy an existing PdfString * \param rhs another PdfString to copy * \returns this object */ const PdfString & operator=( const PdfString & rhs ); /** Compare two PdfString objects * \param rhs another PdfString to compare * \returns this object */ bool operator>( const PdfString & rhs ) const; /** Compare two PdfString objects * \param rhs another PdfString to compare * \returns this object */ bool operator<( const PdfString & rhs ) const; /** Comparison operator * * UTF-8 and UTF-16BE encoded strings of the same data compare equal. Whether * the string will be written out as hex is not considered - only the real "text" * is tested for equality. * * \param rhs compare to this string object * \returns true if both strings have the same contents */ bool operator==( const PdfString & rhs ) const; /** Comparison operator * \param rhs compare to this string object * \returns true if strings have different contents */ bool operator!=(const PdfString& rhs) const { return !operator==(rhs); } /** Converts this string to a hex encoded string. * * If IsHex returns true, a copy of this string is returned * otherwise the strings data is hex encoded and returned. * * \returns a hex encoded version of this string or this string * if it is already hex ecoded. * * \see IsHex */ //PdfString HexEncode() const; /** Converts this string to a ascii string (not hex encoded) * * If IsHex returns false, a copy of this string is returned * otherwise the strings data is hex decoded and returned. * * \returns a plain version of this string which is not hex encoded * or this string if it is already a plain not hex encoded string. * * \see IsHex */ //PdfString HexDecode() const; /** Converts this string to a unicode string * * If IsUnicode() returns true a copy of this string is returned * otherwise the string data is converted to UTF-16be and returned. * * \returns a unicode version of this string */ PdfString ToUnicode() const; /** Returns internal buffer; do not free it, it's owned by the PdfString * * \returns internal buffer; do not free it, it's owned by the PdfString */ PdfRefCountedBuffer &GetBuffer(void); static const PdfString StringNull; static pdf_long ConvertUTF8toUTF16( const pdf_utf8* pszUtf8, pdf_utf16be* pszUtf16, pdf_long lLenUtf16 ); static pdf_long ConvertUTF8toUTF16( const pdf_utf8* pszUtf8, pdf_long lLenUtf8, pdf_utf16be* pszUtf16, pdf_long lLenUtf16, EPdfStringConversion eConversion = ePdfStringConversion_Strict ); static pdf_long ConvertUTF16toUTF8( const pdf_utf16be* pszUtf16, pdf_utf8* pszUtf8, pdf_long lLenUtf8 ); static pdf_long ConvertUTF16toUTF8( const pdf_utf16be* pszUtf16, pdf_long lLenUtf16, pdf_utf8* pszUtf8, pdf_long lLenUtf8, EPdfStringConversion eConversion = ePdfStringConversion_Strict ); private: /** Allocate m_lLen data for m_pszData if data * does not fit into m_pBuffer. * Otherwise m_pszData is set to point to * m_pBuffer. */ void Allocate(); /** Frees the internal buffer * if it was allocated using malloc */ void FreeBuffer(); /** Construct a new PdfString from a 0 terminated * string. * The input string will be copied. * if m_bhex is true the copied data will be hex encoded. * * \param pszString the string to copy, must not be NULL * \param lLen length of the string data to copy * */ void Init( const char* pszString, pdf_long lLen ); /** Construct a new PdfString from a UTF8 * string. * The input string will be copied and converted to UTF-16be. * * \param pszStringUtf8 the string to copy, ust not be NULL * \param lLen number of bytes of the string data to copy * */ void InitFromUtf8( const pdf_utf8* pszStringUtf8, pdf_long lLen ); /** Swap the bytes in the buffer (UTF16be -> UTF16le) * \param pBuf buffer * \param lLen length of buffer */ static void SwapBytes( char* pBuf, pdf_long lLen ); /** Initialise the data member containing a * UTF8 version of this string. * * This is only done once and only if necessary. */ void InitUtf8(); private: static const char s_pszUnicodeMarker[]; ///< The unicode marker used to indicate unicode strings in PDF static const char* s_pszUnicodeMarkerHex; ///< The unicode marker converted to HEX static const pdf_utf16be s_cPdfDocEncoding[256]; ///< conversion table from PDFDocEncoding to UTF16 static const char * const m_escMap; ///< Mapping of escape sequences to there value private: PdfRefCountedBuffer m_buffer; ///< String data (always binary), may contain 0 bytes bool m_bHex; ///< This string is converted to hex during write out bool m_bUnicode; ///< This string contains unicode data std::string m_sUtf8; ///< The UTF8 version of the strings contents. const PdfEncoding* m_pEncoding; ///< Encoding for non Unicode strings. NULL for unicode strings. }; // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfString::IsValid() const { return (m_buffer.GetBuffer() != NULL); } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfString::IsHex () const { return m_bHex; } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfString::IsUnicode () const { return m_bUnicode; } // ----------------------------------------------------- // // ----------------------------------------------------- const char* PdfString::GetString() const { return m_buffer.GetBuffer(); } // ----------------------------------------------------- // // ----------------------------------------------------- const pdf_utf16be* PdfString::GetUnicode() const { return reinterpret_cast(m_buffer.GetBuffer()); } // ----------------------------------------------------- // // ----------------------------------------------------- const std::string & PdfString::GetStringUtf8() const { if( this->IsValid() && !m_sUtf8.length() && m_buffer.GetSize() - 2) const_cast(this)->InitUtf8(); return m_sUtf8; } // ----------------------------------------------------- // // ----------------------------------------------------- pdf_long PdfString::GetLength() const { return m_buffer.GetSize() - 2; } // ----------------------------------------------------- // // ----------------------------------------------------- pdf_long PdfString::GetCharacterLength() const { return this->IsUnicode() ? this->GetUnicodeLength() : this->GetLength(); } // ----------------------------------------------------- // // ----------------------------------------------------- pdf_long PdfString::GetUnicodeLength() const { return (m_buffer.GetSize() / sizeof(pdf_utf16be)) - 1; } }; #endif // _PDF_STRING_H_ podofo-0.9.3/src/base/PdfCompilerCompat.h0000664000175000017500000001362312350106026020103 0ustar dominikdominik#ifndef _PDF_COMPILERCOMPAT_H #define _PDF_COMPILERCOMPAT_H // // *** THIS HEADER IS INCLUDED BY PdfDefines.h *** // *** DO NOT INCLUDE DIRECTLY *** #ifndef _PDF_DEFINES_H_ #error Please include PdfDefines.h instead #endif #include "podofo_config.h" #ifndef PODOFO_COMPILE_RC // Silence some annoying warnings from Visual Studio #ifdef _MSC_VER #if _MSC_VER <= 1200 // Visual Studio 6 #pragma warning(disable: 4786) #pragma warning(disable: 4251) #elif _MSC_VER <= 1400 // Visual Studio 2005 #pragma warning(disable: 4251) #pragma warning(disable: 4275) #endif // _MSC_VER #endif // _MSC_VER // Make sure that DEBUG is defined // for debug builds on Windows // as Visual Studio defines only _DEBUG #ifdef _DEBUG #ifndef DEBUG #define DEBUG 1 #endif // DEBUG #endif // _DEBUG #if defined(__BORLANDC__) || defined( __TURBOC__) # include #else # include #endif #if defined(TEST_BIG) # define PODOFO_IS_BIG_ENDIAN #else # define PODOFO_IS_LITTLE_ENDIAN #endif #if PODOFO_HAVE_STDINT_H #include #endif #if PODOFO_HAVE_BASETSD_H #include #endif #if PODOFO_HAVE_SYS_TYPES_H #include #endif #if PODOFO_HAVE_MEM_H #include #endif #if PODOFO_HAVE_CTYPE_H #include #endif #if PODOFO_HAVE_STRINGS_H #include #endif // alloca() is defined only in on Mac OS X, // only in on win32, and in both on Linux. #if defined(_WIN32) #include #endif // Disable usage of min() and max() macros #if defined(_WIN32) && !defined(__MINGW32__) #define NOMINMAX #endif // Integer types - fixed size types guaranteed to work anywhere // because we detect the right underlying type name to use with // CMake. Use typedefs rather than macros for saner error messages // etc. namespace PoDoFo { typedef PDF_INT8_TYPENAME pdf_int8; typedef PDF_INT16_TYPENAME pdf_int16; typedef PDF_INT32_TYPENAME pdf_int32; typedef PDF_INT64_TYPENAME pdf_int64; typedef PDF_UINT8_TYPENAME pdf_uint8; typedef PDF_UINT16_TYPENAME pdf_uint16; typedef PDF_UINT32_TYPENAME pdf_uint32; typedef PDF_UINT64_TYPENAME pdf_uint64; }; #undef PDF_INT8_TYPENAME #undef PDF_INT16_TYPENAME #undef PDF_INT32_TYPENAME #undef PDF_INT64_TYPENAME #undef PDF_UINT8_TYPENAME #undef PDF_UINT16_TYPENAME #undef PDF_UINT32_TYPENAME #undef PDF_UINT64_TYPENAME /* * Some elderly compilers, notably VC6, don't support LL literals. * In those cases we can use the oversized literal without any suffix. */ #if defined(_MSC_VER) && _MSC_VER <= 1200 // Visual Studio 6 # define PODOFO_LL_LITERAL(x) x # define PODOFO_ULL_LITERAL(x) x #else #if defined(PODOFO_COMPILER_LACKS_LL_LITERALS) # define PODOFO_LL_LITERAL(x) x # define PODOFO_ULL_LITERAL(x) x #else # define PODOFO_LL_LITERAL(x) x##LL # define PODOFO_ULL_LITERAL(x) x##ULL #endif #endif #if defined(_MSC_VER) && _MSC_VER <= 1200 // Visual Studio 6 # define PODOFO_MIN(_a, _b) ((_a) < (_b) ? (_a) : (_b)) #else # define PODOFO_MIN(_a, _b) (std::min((_a), (_b))) #endif // pdf_long is defined as ptrdiff_t . It's a pointer-sized signed quantity // used throughout the code for a variety of purposes. // // pdf_long is DEPRECATED. Please use one of the explicitly sized types // instead, or define a typedef that meaningfully describes what it's for. // Good choices in many cases include size_t (string and buffer sizes) and // ptrdiff_t (offsets and pointer arithmetic). // // pdf_long should not be used in new code. // namespace PoDoFo { typedef ptrdiff_t pdf_long; }; // Different compilers use different format specifiers for 64-bit integers // (yay!). Use these macros with C's automatic string concatenation to handle // that ghastly quirk. // // for example: printf("Value of signed 64-bit integer: %"PDF_FORMAT_INT64" (more blah)", 128LL) // #if defined(_MSC_VER) # define PDF_FORMAT_INT64 "I64d" # define PDF_FORMAT_UINT64 "I64u" #elif defined(SZ_INT64) && defined(SZ_LONG) && SZ_INT64 == SZ_LONG # define PDF_FORMAT_INT64 "ld" # define PDF_FORMAT_UINT64 "lu" #else # define PDF_FORMAT_INT64 "lld" # define PDF_FORMAT_UINT64 "llu" #endif // Different compilers express __FUNC__ in different ways and with different // capabilities. Try to find the best option. // // Note that __LINE__ and __FILE__ are *NOT* included. // Further note that you can't use compile-time string concatenation on __FUNC__ and friends // on many compilers as they're defined to behave as if they were a: // static const char* __func__ = 'nameoffunction'; // just after the opening brace of each function. // #if (defined(_MSC_VER) && _MSC_VER <= 1200) # define PODOFO__FUNCTION__ __FUNCTION__ #elif defined(__BORLANDC__) || defined(__TURBOC__) # define PODOFO__FUNCTION__ __FUNC__ #elif defined(__GNUC__) # define PODOFO__FUNCTION__ __PRETTY_FUNCTION__ #else # define PODOFO__FUNCTION__ __FUNCTION__ #endif #if defined(_WIN32) // Undefined stuff which windows does define that breaks the build // e.g. GetObject is defined to either GetObjectA or GetObjectW #ifdef GetObject #undef GetObject #endif // GetObject #ifdef CreateFont #undef CreateFont #endif // CreateFont #ifdef DrawText #undef DrawText #endif // DrawText #endif // defined(_WIN32) /** * \page PoDoFo PdfCompilerCompat Header * * PdfCompilerCompat.h gathers up nastyness required for various * compiler compatibility into a central place. All compiler-specific defines, * wrappers, and the like should be included here and (if necessary) in * PdfCompilerCompat.cpp if they must be visible to public users of the library. * * If the nasty platform and compiler specific hacks can be kept to PoDoFo's * build and need not be visible to users of the library, put them in * PdfCompilerCompatPrivate.{cpp,h} instead. * * Please NEVER use symbols from this header or the PoDoFo::compat namespace in * a "using" directive. Always explicitly reference names so it's clear that * you're pulling them from the compat cruft. */ #endif // !PODOFO_COMPILE_RC #endif podofo-0.9.3/src/base/PdfDate.h0000664000175000017500000001320312344436402016043 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2005 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_DATE_H_ #define _PDF_DATE_H_ #include "PdfDefines.h" #include "PdfString.h" #include // a PDF date has a maximum of 26 bytes incuding the terminating \0 #define PDF_DATE_BUFFER_SIZE 26 namespace PoDoFo { /** This class is a date datatype as specified in the PDF * reference. You can easily convert from Unix time_t to * the PDF time representation and back. Dates like these * are used for example in the PDF info dictionary for the * creation time and date of the PDF file. * * PdfDate objects are immutable. * * From the PDF reference: * * PDF defines a standard date format, which closely follows * that of the international standard ASN.1 (Abstract Syntax * Notation One), defined in ISO/IEC 8824 (see the Bibliography). * A date is a string of the form * (D:YYYYMMDDHHmmSSOHH'mm') */ class PODOFO_API PdfDate { public: /** Create a PdfDate object with the current date and time. */ PdfDate(); /** Create a PdfDate with a specified date and time * \param t the date and time of this object * * Use IsValid to check wether the time_t could be * converted to a valid PdfDate object. * * \see IsValid() */ PdfDate( const time_t & t ); /** Create a PdfDate with a specified date and time * \param szDate the date and time of this object * in PDF format. It has to be a string of * the format (D:YYYYMMDDHHmmSSOHH'mm'). * Otherwise IsValid will return false. * * Use IsValid to check wether the string could be * converted to a valid PdfDate object. * * \see IsValid() */ PdfDate( const PdfString & sDate ); /** Delete the PdfDate object */ virtual ~PdfDate(); /** You can use this function to check wether the date * you passed to the constructor could be converted to * a valid pdf date string or a valid time_t. * * \returns true if the PdfDate object is valid */ inline bool IsValid() const; /** \returns the date and time of this PdfDate in * seconds since epoch. */ inline const time_t & GetTime() const; /** The value returned by this function can be used in any PdfObject * where a date is needed. * * \param rsString write the date to a PdfString */ inline void ToString( PdfString & rsString ) const; private: /** Creates the internal string representation from * a time_t value and writes it to m_szDate. */ void CreateStringRepresentation(); /** Parse fixed length number from string * \param in string to read number from * \param length of number to read * \param min minimal value of number * \param max maximal value of number * \param ret parsed number */ bool ParseFixLenNumber(const char *&in, unsigned int length, int min, int max, int &ret); private: time_t m_time; char m_szDate[PDF_DATE_BUFFER_SIZE]; bool m_bValid; }; const time_t & PdfDate::GetTime() const { return m_time; } void PdfDate::ToString( PdfString & rsString ) const { rsString = PdfString( m_szDate ); } bool PdfDate::IsValid() const { return m_bValid; } }; #endif // _PDF_DATE_H_ podofo-0.9.3/src/base/PdfVariant.h0000664000175000017500000010112012351603162016563 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2005 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_VARIANT_H_ #define _PDF_VARIANT_H_ #if defined(__BORLANDC__) || defined( __TURBOC__) #include #else #include #endif #include "PdfDefines.h" #include "PdfRefCountedBuffer.h" #include "PdfString.h" namespace PoDoFo { class PdfArray; class PdfData; class PdfDataType; class PdfDictionary; class PdfEncrypt; class PdfName; class PdfOutputDevice; class PdfString; class PdfReference; /** * A variant data type which supports all data types supported by the PDF standard. * The data can be parsed directly from a string or set by one of the members. * One can also convert the variant back to a string after setting the values. * * \warning All methods not marked otherwise may trigger a deferred load. This means * that they are unsafe to call while a deferred load is already in progress * (as recursion will occurr). * * TODO: domseichter: Make this class implicitly shared */ class PODOFO_API PdfVariant { friend class PdfArray; friend class PdfDictionary; public: static PdfVariant NullValue; /** Construct an empty variant type * IsNull() will return true. */ PdfVariant(); /** Construct a PdfVariant that is a bool. * \param b the boolean value of this PdfVariant */ PdfVariant( bool b ); /** Construct a PdfVariant that is a number. * \param l the value of the number. */ PdfVariant( pdf_int64 l ); /** Construct a PdfVariant that is a real number. * \param d the value of the real number. */ PdfVariant( double d ); /** Construct a PdfVariant that is a string. The argument * string will be escaped where necessary, so it should be * passed in unescaped form. * * \param rsString the value of the string */ PdfVariant( const PdfString & rsString ); /** Construct a PdfVariant that is a name. * \param rName the value of the name */ PdfVariant( const PdfName & rName ); /** Construct a PdfVariant that is a name. * \param rRef the value of the name */ PdfVariant( const PdfReference & rRef ); /** Initalize a PdfVariant object with array data. * The variant will automatically get the datatype * ePdfDataType_Array. This Init call is the fastest * way to create a new PdfVariant that is an array. * * \param tList a list of variants * * \returns ErrOk on sucess */ PdfVariant( const PdfArray & tList ); /** Construct a PdfVariant that is a dictionary. * \param rDict the value of the dictionary. */ PdfVariant( const PdfDictionary & rDict ); /** Construct a PdfVariant that contains raw PDF data. * \param rData raw and valid PDF data. */ PdfVariant( const PdfData & rData ); /** Constructs a new PdfVariant which has the same * contents as rhs. * \param rhs an existing variant which is copied. */ PdfVariant( const PdfVariant & rhs ); virtual ~PdfVariant(); /** \returns true if this PdfVariant is empty. * i.e. m_eDataType == ePdfDataType_Null */ inline bool IsEmpty() const; /** Clear all internal member variables and free the memory * they have allocated. * Sets the datatype to ePdfDataType_Null * * This will reset the dirty flag of this object to be clean. * \see IsDirty */ void Clear(); /** \returns the datatype of this object or ePdfDataType_Unknown * if it does not have a value. */ inline EPdfDataType GetDataType() const; /** \returns a human readable string representation of GetDataType() * The returned string must not be free'd. */ const char * GetDataTypeString() const; /** \returns true if this variant is a bool (i.e. GetDataType() == ePdfDataType_Bool) */ inline bool IsBool() const { return GetDataType() == ePdfDataType_Bool; } /** \returns true if this variant is a number (i.e. GetDataType() == ePdfDataType_Number) */ inline bool IsNumber() const { return GetDataType() == ePdfDataType_Number; } /** \returns true if this variant is a real (i.e. GetDataType() == ePdfDataType_Real) */ inline bool IsReal() const { return GetDataType() == ePdfDataType_Real; } /** \returns true if this variant is a string (i.e. GetDataType() == ePdfDataType_String) */ inline bool IsString() const { return GetDataType() == ePdfDataType_String; } /** \returns true if this variant is a hex-string (i.e. GetDataType() == ePdfDataType_HexString) */ inline bool IsHexString() const { return GetDataType() == ePdfDataType_HexString; } /** \returns true if this variant is a name (i.e. GetDataType() == ePdfDataType_Name) */ inline bool IsName() const { return GetDataType() == ePdfDataType_Name; } /** \returns true if this variant is an array (i.e. GetDataType() == ePdfDataType_Array) */ inline bool IsArray() const { return GetDataType() == ePdfDataType_Array; } /** \returns true if this variant is a dictionary (i.e. GetDataType() == ePdfDataType_Dictionary) */ inline bool IsDictionary() const { return GetDataType() == ePdfDataType_Dictionary; } /** \returns true if this variant is raw data (i.e. GetDataType() == ePdfDataType_RawData */ inline bool IsRawData() const { return GetDataType() == ePdfDataType_RawData; } /** \returns true if this variant is null (i.e. GetDataType() == ePdfDataType_Null) */ inline bool IsNull() const { return GetDataType() == ePdfDataType_Null; } /** \returns true if this variant is a reference (i.e. GetDataType() == ePdfDataType_Reference) */ inline bool IsReference() const { return GetDataType() == ePdfDataType_Reference; } /** Write the complete variant to an output device. * This is an overloaded member function. * * \param pDevice write the object to this device * \param eWriteMode additional options for writing this object * \param pEncrypt an encryption object which is used to encrypt this object * or NULL to not encrypt this object */ void Write( PdfOutputDevice* pDevice, EPdfWriteMode eWriteMode, const PdfEncrypt* pEncrypt = NULL ) const; /** Write the complete variant to an output device. * \param pDevice write the object to this device * \param eWriteMode additional options for writing this object * \param pEncrypt an encryption object which is used to encrypt this object * or NULL to not encrypt this object * \param keyStop if not KeyNull and a key == keyStop is found * writing will stop right before this key! * if IsDictionary returns true. */ virtual void Write( PdfOutputDevice* pDevice, EPdfWriteMode eWriteMode, const PdfEncrypt* pEncrypt, const PdfName & keyStop ) const; /** Converts the current object into a string representation * which can be written directly to a PDF file on disc. * \param rsData the object string is returned in this object. * \param eWriteMode additional options for writing to a string */ void ToString( std::string & rsData, EPdfWriteMode eWriteMode = ePdfWriteMode_Clean ) const; /** Set the value of this object as bool * \param b the value as bool. * * This will set the dirty flag of this object. * \see IsDirty */ inline void SetBool( bool b ); /** Get the value if this object is a bool. * \returns the bool value. */ inline bool GetBool() const; /** Set the value of this object as long * \param l the value as long. * * This will set the dirty flag of this object. * \see IsDirty */ inline void SetNumber( long l ); /** Get the value of the object as long. * \return the value of the number */ inline pdf_int64 GetNumber() const; /** Set the value of this object as double * \param d the value as double. * * This will set the dirty flag of this object. * \see IsDirty */ inline void SetReal( double d ); /** Get the value of the object as double. * \return the value of the number */ inline double GetReal() const; /** \returns the value of the object as string. */ inline const PdfString & GetString() const; /** \returns the value of the object as name */ inline const PdfName & GetName() const; /** Returns the value of the object as array * \returns a array */ inline const PdfArray & GetArray() const; /** Returns the value of the object as array * \returns a array */ inline PdfArray & GetArray(); /** Returns the dictionary value of this object * \returns a PdfDictionary */ inline const PdfDictionary & GetDictionary() const; /** Returns the dictionary value of this object * \returns a PdfDictionary */ inline PdfDictionary & GetDictionary(); /** Get the reference values of this object. * \returns a PdfReference */ inline const PdfReference & GetReference() const; /** Get the reference values of this object. * \returns a reference to the PdfData instance. */ inline const PdfData & GetRawData() const; /** Get the reference values of this object. * \returns a reference to the PdfData instance. */ inline PdfData & GetRawData(); /** Assign the values of another PdfVariant to this one. * \param rhs an existing variant which is copied. * * This will set the dirty flag of this object. * \see IsDirty */ const PdfVariant & operator=( const PdfVariant & rhs ); /** * Test to see if the value contained by this variant is the same * as the value of the other variant. */ bool operator==( const PdfVariant & rhs ) const; /** * \see operator== */ inline bool operator!=( const PdfVariant & rhs) const; /** The dirty flag is set if this variant * has been modified after construction. * * Usually the dirty flag is also set * if you call any non-const member function * (e.g. GetDictionary()) as PdfVariant cannot * determine if you actually changed the dictionary * or not. * * \returns true if the value is dirty and has been * modified since construction */ inline bool IsDirty() const; /** * Sets this object to immutable, * so that no keys can be edited or changed. * * @param bImmutable if true set the object to be immutable * * This is used by PdfImmediateWriter and PdfStreamedDocument so * that no keys can be added to an object after setting stream data on it. * */ inline void SetImmutable(bool bImmutable); /** * Retrieve if an object is immutable. * * This is used by PdfImmediateWriter and PdfStreamedDocument so * that no keys can be added to an object after setting stream data on it. * * @returns true if the object is immutable */ inline bool GetImmutable() const; protected: /** * Will throw an exception if called on an immutable object, * so this should be called before actually changing a value! * */ inline void AssertMutable() const; /** Sets the dirty flag of this PdfVariant * * \param bDirty true if this PdfVariant has been * modified from the outside * * \see IsDirty */ inline void SetDirty( bool bDirty ); /** * Dynamically load the contents of this object from a PDF file by calling * the virtual method DelayedLoadImpl() if the object is not already loaded. * * For objects complete created in memory and those that do not support * deferred loading this function does nothing, since deferred loading * will not be enabled. */ inline void DelayedLoad() const; /** Flag the object incompletely loaded. DelayedLoad() will be called * when any method that requires more information than is currently * available is loaded. * * All constructors initialize a PdfVariant with delayed loading disabled . * If you want delayed loading you must ask for it. If you do so, call * this method early in your ctor and be sure to override DelayedLoadImpl(). */ inline void EnableDelayedLoading(); /** Load all data of the object if delayed loading is enabled. * * Never call this method directly; use DelayedLoad() instead. * * You should override this to control deferred loading in your subclass. * Note that this method should not load any associated streams, just the * base object. * * The default implementation throws. It should never be called, since * objects that do not support delayed loading should not enable it. * * While this method is not `const' it may be called from a const context, * so be careful what you mess with. */ inline virtual void DelayedLoadImpl(); /** * Returns true if delayed loading is disabled, or if it is enabled * and loading has completed. External callers should never need to * see this, it's an internal state flag only. */ PODOFO_NOTHROW inline bool DelayedLoadDone() const; // Rather than having deferred load triggering disabled while deferred // loading is in progress, causing public methods to potentially return // invalid data, we provide special methods that won't trigger a deferred // load for use during deferred loading. They're not for general use and // not available for use except by subclasses. // /** Version of GetDictionary() that doesn't trigger a delayed load * \returns a PdfDictionary */ inline const PdfDictionary & GetDictionary_NoDL() const; /** Version of GetDictionary() that doesn't trigger a delayed load * \returns a PdfDictionary */ inline PdfDictionary & GetDictionary_NoDL(); /** Version of GetArray() that doesn't trigger a delayed load * \returns a array */ inline const PdfArray & GetArray_NoDL() const; /** Version of GetArray() that doesn't trigger a delayed load. * \returns a array */ inline PdfArray & GetArray_NoDL(); private: /** * It's an easy mistake to pass a pointer to a PdfVariant when trying to * copy a PdfVariant, especially with heap allocators like `new'. This can * produce confusing and unexpected results like getting a PdfVariant(bool). * * A similar issue can arise when the user passes a `char*' and expects a PdfName * or PdfString based variant to be created. We can't know which they wanted, so * we should fail, especially since the compiler tends to convert pointers to bool * for extra confusion value. * * We provide this overload so that such attempts will fail with an error about * a private ctor. If you're reading this, you wrote: * * PdfVariant( my_ptr_to_something ) * *... not ... * * PdfVariant( *my_ptr_to_something ) * * If you need to modify PdfVariant to legitimately take a pointer in the future, * you can do so by providing a template specialization, or by removing this check * and replacing it with a couple of overloads specific to PdfObject*, PdfVariant*, * and char* (at least). */ template PdfVariant(T*); /** To reduce memory usage of this very often used class, * we use a union here, as there is always only * one of those members used. */ typedef union { /** Holds references, strings, * names, dictionaries and arrays */ PdfDataType* pData; bool bBoolValue; double dNumber; pdf_int64 nNumber; } UVariant; UVariant m_Data; bool m_bDirty; ///< Indicates if this object was modified after construction bool m_bImmutable; ///< Indicates if this object maybe modified /** Datatype of the variant. * required to access the correct member of * the union UVariant. */ EPdfDataType m_eDataType; // No touchy. Only for use by PdfVariant's internal tracking of the delayed // loading state. Use DelayedLoadDone() to test this if you need to. mutable bool m_bDelayedLoadDone; // Helper for ctor PODOFO_NOTHROW void Init(); #if defined(PODOFO_EXTRA_CHECKS) protected: PODOFO_NOTHROW bool DelayedLoadInProgress() const { return m_bDelayedLoadInProgress; } private: mutable bool m_bDelayedLoadInProgress; #endif }; // ----------------------------------------------------- // // ----------------------------------------------------- inline void PdfVariant::DelayedLoad() const { #if defined(PODOFO_EXTRA_CHECKS) // Whoops! Delayed loading triggered during delayed loading. Someone probably // used a public method that calls DelayedLoad() from a delayed load. if (m_bDelayedLoadInProgress) PODOFO_RAISE_ERROR_INFO( ePdfError_InternalLogic, "Recursive DelayedLoad() detected" ); #endif if( !m_bDelayedLoadDone) { #if defined(PODOFO_EXTRA_CHECKS) m_bDelayedLoadInProgress = true; #endif const_cast(this)->DelayedLoadImpl(); // Nothing was thrown, so if the implementer of DelayedLoadImpl() // following the rules we're done. m_bDelayedLoadDone = true; #if defined(PODOFO_EXTRA_CHECKS) m_bDelayedLoadInProgress = false; #endif } } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfVariant::IsEmpty() const { DelayedLoad(); return (m_eDataType == ePdfDataType_Null); } // ----------------------------------------------------- // // ----------------------------------------------------- EPdfDataType PdfVariant::GetDataType() const { DelayedLoad(); return m_eDataType; } // ----------------------------------------------------- // // ----------------------------------------------------- void PdfVariant::SetBool( bool b ) { DelayedLoad(); if( !IsBool() ) { PODOFO_RAISE_ERROR( ePdfError_InvalidDataType ); } AssertMutable(); m_Data.bBoolValue = b; SetDirty( true ); } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfVariant::GetBool() const { DelayedLoad(); if( !IsBool() ) { PODOFO_RAISE_ERROR( ePdfError_InvalidDataType ); } return m_Data.bBoolValue; } // ----------------------------------------------------- // // ----------------------------------------------------- void PdfVariant::SetNumber( long l ) { DelayedLoad(); if( !IsReal() && !IsNumber() ) { PODOFO_RAISE_ERROR( ePdfError_InvalidDataType ); } AssertMutable(); if ( IsReal() ) m_Data.dNumber = static_cast(l); else m_Data.nNumber = l; SetDirty( true ); } // ----------------------------------------------------- // // ----------------------------------------------------- pdf_int64 PdfVariant::GetNumber() const { DelayedLoad(); if( !IsReal() && !IsNumber() ) { PODOFO_RAISE_ERROR( ePdfError_InvalidDataType ); } if ( IsReal() ) return static_cast(floor( m_Data.dNumber )); else return m_Data.nNumber; } // ----------------------------------------------------- // // ----------------------------------------------------- void PdfVariant::SetReal( double d ) { DelayedLoad(); if( !IsReal() && !IsNumber() ) { PODOFO_RAISE_ERROR( ePdfError_InvalidDataType ); } AssertMutable(); if ( IsReal() ) m_Data.dNumber = d; else m_Data.nNumber = static_cast(floor( d )); SetDirty( true ); } // ----------------------------------------------------- // // ----------------------------------------------------- double PdfVariant::GetReal() const { DelayedLoad(); if( !IsReal() && !IsNumber() ) { PODOFO_RAISE_ERROR( ePdfError_InvalidDataType ); } if ( IsReal() ) return m_Data.dNumber; else return static_cast(m_Data.nNumber); } // ----------------------------------------------------- // // ----------------------------------------------------- #ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wold-style-cast" #endif // __GNUC__ const PdfData & PdfVariant::GetRawData() const { DelayedLoad(); if( !IsRawData() ) { PODOFO_RAISE_ERROR( ePdfError_InvalidDataType ); } // Do not change this to an reinterpret_cast // We need a c-style casts here to avoid crashes // because a reinterpret_cast might point to a different position. return *((PdfData*)m_Data.pData); } #ifdef __GNUC__ #pragma GCC diagnostic pop #endif // __GNUC__ PdfData & PdfVariant::GetRawData() { DelayedLoad(); if( !IsRawData() ) { PODOFO_RAISE_ERROR( ePdfError_InvalidDataType ); } // Do not change this to an reinterpret_cast // We need a c-style casts here to avoid crashes // because a reinterpret_cast might point to a different position. return *((PdfData*)m_Data.pData); } // ----------------------------------------------------- // // ----------------------------------------------------- const PdfString & PdfVariant::GetString() const { DelayedLoad(); if( !IsString() && !IsHexString() ) { PODOFO_RAISE_ERROR( ePdfError_InvalidDataType ); } // Do not change this to an reinterpret_cast // We need a c-style casts here to avoid crashes // because a reinterpret_cast might point to a different position. return *((PdfString*)m_Data.pData); } // ----------------------------------------------------- // // ----------------------------------------------------- const PdfName & PdfVariant::GetName() const { DelayedLoad(); if( !IsName() ) { PODOFO_RAISE_ERROR( ePdfError_InvalidDataType ); } // Do not change this to an reinterpret_cast // We need a c-style casts here to avoid crashes // because a reinterpret_cast might point to a different position. return *((PdfName*)m_Data.pData); } // ----------------------------------------------------- // // ----------------------------------------------------- const PdfArray & PdfVariant::GetArray() const { DelayedLoad(); return GetArray_NoDL(); } // ----------------------------------------------------- // // ----------------------------------------------------- const PdfArray & PdfVariant::GetArray_NoDL() const { // Test against eDataType directly not GetDataType() since // we don't want to trigger a delayed load (and if required one has // already been triggered). if( m_eDataType != ePdfDataType_Array ) { PODOFO_RAISE_ERROR( ePdfError_InvalidDataType ); } // Do not change this to an reinterpret_cast // We need a c-style casts here to avoid crashes // because a reinterpret_cast might point to a different position. return *((PdfArray*)m_Data.pData); } // ----------------------------------------------------- // // ----------------------------------------------------- PdfArray & PdfVariant::GetArray() { DelayedLoad(); return GetArray_NoDL(); } // ----------------------------------------------------- // // ----------------------------------------------------- PdfArray & PdfVariant::GetArray_NoDL() { // Test against eDataType directly not GetDataType() since // we don't want to trigger a delayed load (and if required one has // already been triggered). if( m_eDataType != ePdfDataType_Array ) { PODOFO_RAISE_ERROR( ePdfError_InvalidDataType ); } // Do not change this to an reinterpret_cast // We need a c-style casts here to avoid crashes // because a reinterpret_cast might point to a different position. return *((PdfArray*)m_Data.pData); } // ----------------------------------------------------- // // ----------------------------------------------------- const PdfDictionary & PdfVariant::GetDictionary() const { DelayedLoad(); return GetDictionary_NoDL(); } // ----------------------------------------------------- // // ----------------------------------------------------- const PdfDictionary & PdfVariant::GetDictionary_NoDL() const { // Test against eDataType directly not GetDataType() since // we don't want to trigger a delayed load (and if required one has // already been triggered). if( m_eDataType != ePdfDataType_Dictionary ) { PODOFO_RAISE_ERROR( ePdfError_InvalidDataType ); } // Do not change this to an reinterpret_cast // We need a c-style casts here to avoid crashes // because a reinterpret_cast might point to a different position. return *((PdfDictionary*)m_Data.pData); } // ----------------------------------------------------- // // ----------------------------------------------------- PdfDictionary & PdfVariant::GetDictionary() { DelayedLoad(); return GetDictionary_NoDL(); } // ----------------------------------------------------- // // ----------------------------------------------------- PdfDictionary & PdfVariant::GetDictionary_NoDL() { // Test against eDataType directly not GetDataType() since // we don't want to trigger a delayed load (and if required one has // already been triggered). if( m_eDataType != ePdfDataType_Dictionary ) { PODOFO_RAISE_ERROR( ePdfError_InvalidDataType ); } // Do not change this to an reinterpret_cast // We need a c-style casts here to avoid crashes // because a reinterpret_cast might point to a different position. return *((PdfDictionary*)m_Data.pData); } // ----------------------------------------------------- // // ----------------------------------------------------- const PdfReference & PdfVariant::GetReference() const { DelayedLoad(); if( !IsReference() ) { PODOFO_RAISE_ERROR( ePdfError_InvalidDataType ); } // Do not change this to an reinterpret_cast // We need a c-style casts here to avoid crashes // because a reinterpret_cast might point to a different position. return *((PdfReference*)m_Data.pData); } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfVariant::DelayedLoadDone() const { return m_bDelayedLoadDone; } // ----------------------------------------------------- // // ----------------------------------------------------- void PdfVariant::EnableDelayedLoading() { m_bDelayedLoadDone = false; } // ----------------------------------------------------- // // ----------------------------------------------------- void PdfVariant::DelayedLoadImpl() { // Default implementation of virtual void DelayedLoadImpl() throws, since delayed // loading should not be enabled except by types that support it. PODOFO_RAISE_ERROR( ePdfError_InternalLogic ); } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfVariant::operator!=( const PdfVariant & rhs) const { return !(*this == rhs); } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfVariant::IsDirty() const { // If this is a object with // stream, the streams dirty // flag might be set. if( m_bDirty ) return m_bDirty; switch( m_eDataType ) { case ePdfDataType_Array: case ePdfDataType_Dictionary: // Arrays and Dictionaries // handle dirty status by themselfes return m_Data.pData->IsDirty(); case ePdfDataType_Bool: case ePdfDataType_Number: case ePdfDataType_Real: case ePdfDataType_HexString: case ePdfDataType_String: case ePdfDataType_Name: case ePdfDataType_RawData: case ePdfDataType_Reference: case ePdfDataType_Null: case ePdfDataType_Unknown: default: return m_bDirty; }; } // ----------------------------------------------------- // // ----------------------------------------------------- void PdfVariant::SetDirty( bool bDirty ) { m_bDirty = bDirty; if( !m_bDirty ) { // Propogate new dirty state to subclasses switch( m_eDataType ) { case ePdfDataType_Array: case ePdfDataType_Dictionary: // Arrays and Dictionaries // handle dirty status by themselfes m_Data.pData->SetDirty( m_bDirty ); case ePdfDataType_Bool: case ePdfDataType_Number: case ePdfDataType_Real: case ePdfDataType_HexString: case ePdfDataType_String: case ePdfDataType_Name: case ePdfDataType_RawData: case ePdfDataType_Reference: case ePdfDataType_Null: case ePdfDataType_Unknown: default: break; }; } } // ----------------------------------------------------- // // ----------------------------------------------------- inline void PdfVariant::SetImmutable(bool bImmutable) { m_bImmutable = bImmutable; switch( m_eDataType ) { case ePdfDataType_Array: case ePdfDataType_Dictionary: // Arrays and Dictionaries // handle dirty status by themselfes m_Data.pData->SetImmutable( m_bImmutable ); case ePdfDataType_Bool: case ePdfDataType_Number: case ePdfDataType_Real: case ePdfDataType_HexString: case ePdfDataType_String: case ePdfDataType_Name: case ePdfDataType_RawData: case ePdfDataType_Reference: case ePdfDataType_Null: case ePdfDataType_Unknown: default: break; }; } // ----------------------------------------------------- // // ----------------------------------------------------- inline bool PdfVariant::GetImmutable() const { return m_bImmutable; } // ----------------------------------------------------- // // ----------------------------------------------------- inline void PdfVariant::AssertMutable() const { if(m_bImmutable) { throw PdfError( ePdfError_ChangeOnImmutable ); } } }; #endif // _PDF_VARIANT_H_ podofo-0.9.3/src/base/PdfFilter.cpp0000664000175000017500000003276412344436402016763 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2006 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfDefines.h" #include "PdfFilter.h" #include "PdfArray.h" #include "PdfDictionary.h" #include "PdfFiltersPrivate.h" #include "PdfOutputStream.h" #include "PdfDefinesPrivate.h" namespace PoDoFo { // All known filters static const char* aszFilters[] = { "ASCIIHexDecode", "ASCII85Decode", "LZWDecode", "FlateDecode", "RunLengthDecode", "CCITTFaxDecode", "JBIG2Decode", "DCTDecode", "JPXDecode", "Crypt", NULL }; static const char* aszShortFilters[] = { "AHx", "A85", "LZW", "Fl", "RL", "CCF", "", ///< There is no shortname for JBIG2Decode "DCT", "", ///< There is no shortname for JPXDecode "", ///< There is no shortname for Crypt NULL }; /** Create a filter that is a PdfOutputStream. * * All data written to this stream is encoded using a * filter and written to another PdfOutputStream. * * The passed output stream is owned by this PdfOutputStream * and deleted along with it. */ class PdfFilteredEncodeStream : public PdfOutputStream{ public: /** Create a filtered output stream. * * All data written to this stream is encoded using the passed filter type * and written to the passed output stream which will be deleted * by this PdfFilteredEncodeStream. * * \param pOutputStream write all data to this output stream after encoding the data. * \param eFilter use this filter for encoding. * \param bOwnStream if true pOutputStream will be deleted along with this filter */ PdfFilteredEncodeStream( PdfOutputStream* pOutputStream, const EPdfFilter eFilter, bool bOwnStream ) : m_pOutputStream( pOutputStream ) { m_filter = PdfFilterFactory::Create( eFilter ); if( !m_filter.get() ) { PODOFO_RAISE_ERROR( ePdfError_UnsupportedFilter ); } m_filter->BeginEncode( pOutputStream ); if( !bOwnStream ) m_pOutputStream = NULL; } virtual ~PdfFilteredEncodeStream() { delete m_pOutputStream; } /** Write data to the output stream * * \param pBuffer the data is read from this buffer * \param lLen the size of the buffer */ virtual pdf_long Write( const char* pBuffer, pdf_long lLen ) { m_filter->EncodeBlock( pBuffer, lLen ); return 0; } virtual void Close() { m_filter->EndEncode(); } private: PdfOutputStream* m_pOutputStream; std::auto_ptr m_filter; }; /** Create a filter that is a PdfOutputStream. * * All data written to this stream is decoded using a * filter and written to another PdfOutputStream. * * The passed output stream is owned by this PdfOutputStream * and deleted along with it. */ class PdfFilteredDecodeStream : public PdfOutputStream { public: /** Create a filtered output stream. * * All data written to this stream is decoded using the passed filter type * and written to the passed output stream which will be deleted * by this PdfFilteredEncodeStream. * * \param pOutputStream write all data to this output stream after decoding the data. * The PdfOutputStream is deleted along with this object. * \param eFilter use this filter for decoding. * \param bOwnStream if true pOutputStream will be deleted along with this filter * \param pDecodeParms additional parameters for decoding */ PdfFilteredDecodeStream( PdfOutputStream* pOutputStream, const EPdfFilter eFilter, bool bOwnStream, const PdfDictionary* pDecodeParms = NULL ) : m_pOutputStream( pOutputStream ), m_bFilterFailed( false ) { m_filter = PdfFilterFactory::Create( eFilter ); if( !m_filter.get() ) { PODOFO_RAISE_ERROR( ePdfError_UnsupportedFilter ); } m_filter->BeginDecode( pOutputStream, pDecodeParms ); if( !bOwnStream ) m_pOutputStream = NULL; } virtual ~PdfFilteredDecodeStream() { delete m_pOutputStream; } /** Write data to the output stream * * \param pBuffer the data is read from this buffer * \param lLen the size of the buffer */ virtual pdf_long Write( const char* pBuffer, pdf_long lLen ) { try { m_filter->DecodeBlock( pBuffer, lLen ); } catch( const PdfError & e ) { m_bFilterFailed = true; throw e; } return 0; } virtual void Close() { if( !m_bFilterFailed ) { m_filter->EndDecode(); } } private: PdfOutputStream* m_pOutputStream; std::auto_ptr m_filter; bool m_bFilterFailed; }; // ----------------------------------------------------- // Actual PdfFilter code // ----------------------------------------------------- PdfFilter::PdfFilter() : m_pOutputStream( NULL ) { } void PdfFilter::Encode( const char* pInBuffer, pdf_long lInLen, char** ppOutBuffer, pdf_long* plOutLen ) const { if( !this->CanEncode() ) { PODOFO_RAISE_ERROR( ePdfError_UnsupportedFilter ); } PdfMemoryOutputStream stream; const_cast(this)->BeginEncode( &stream ); const_cast(this)->EncodeBlock( pInBuffer, lInLen ); const_cast(this)->EndEncode(); *ppOutBuffer = stream.TakeBuffer(); *plOutLen = stream.GetLength(); } void PdfFilter::Decode( const char* pInBuffer, pdf_long lInLen, char** ppOutBuffer, pdf_long* plOutLen, const PdfDictionary* pDecodeParms ) const { if( !this->CanDecode() ) { PODOFO_RAISE_ERROR( ePdfError_UnsupportedFilter ); } PdfMemoryOutputStream stream; const_cast(this)->BeginDecode( &stream, pDecodeParms ); const_cast(this)->DecodeBlock( pInBuffer, lInLen ); const_cast(this)->EndDecode(); *ppOutBuffer = stream.TakeBuffer(); *plOutLen = stream.GetLength(); } // ----------------------------------------------------- // PdfFilterFactory code // ----------------------------------------------------- std::auto_ptr PdfFilterFactory::Create( const EPdfFilter eFilter ) { PdfFilter* pFilter = NULL; switch( eFilter ) { case ePdfFilter_ASCIIHexDecode: pFilter = new PdfHexFilter(); break; case ePdfFilter_ASCII85Decode: pFilter = new PdfAscii85Filter(); break; case ePdfFilter_LZWDecode: pFilter = new PdfLZWFilter(); break; case ePdfFilter_FlateDecode: pFilter = new PdfFlateFilter(); break; case ePdfFilter_RunLengthDecode: pFilter = new PdfRLEFilter(); break; case ePdfFilter_DCTDecode: #ifdef PODOFO_HAVE_JPEG_LIB pFilter = new PdfDCTFilter(); break; #else break; #endif // PODOFO_HAVE_JPEG_LIB case ePdfFilter_CCITTFaxDecode: #ifdef PODOFO_HAVE_TIFF_LIB pFilter = new PdfCCITTFilter(); break; #else break; #endif // PODOFO_HAVE_TIFF_LIB case ePdfFilter_JBIG2Decode: case ePdfFilter_JPXDecode: case ePdfFilter_Crypt: default: break; } return std::auto_ptr(pFilter); } PdfOutputStream* PdfFilterFactory::CreateEncodeStream( const TVecFilters & filters, PdfOutputStream* pStream ) { TVecFilters::const_iterator it = filters.begin(); PODOFO_RAISE_LOGIC_IF( !filters.size(), "Cannot create an EncodeStream from an empty list of filters" ); PdfFilteredEncodeStream* pFilter = new PdfFilteredEncodeStream( pStream, *it, false ); ++it; while( it != filters.end() ) { pFilter = new PdfFilteredEncodeStream( pFilter, *it, true ); ++it; } return pFilter; } PdfOutputStream* PdfFilterFactory::CreateDecodeStream( const TVecFilters & filters, PdfOutputStream* pStream, const PdfDictionary* pDictionary ) { TVecFilters::const_reverse_iterator it = filters.rbegin(); PODOFO_RAISE_LOGIC_IF( !filters.size(), "Cannot create an DecodeStream from an empty list of filters" ); // TODO: support arrays and indirect objects here and the short name /DP if( pDictionary && pDictionary->HasKey( "DecodeParms" ) && pDictionary->GetKey( "DecodeParms" )->IsDictionary() ) pDictionary = &(pDictionary->GetKey( "DecodeParms" )->GetDictionary()); PdfFilteredDecodeStream* pFilter = new PdfFilteredDecodeStream( pStream, *it, false, pDictionary ); ++it; while( it != filters.rend() ) { pFilter = new PdfFilteredDecodeStream( pFilter, *it, true, pDictionary ); ++it; } return pFilter; } EPdfFilter PdfFilterFactory::FilterNameToType( const PdfName & name, bool bSupportShortNames ) { int i = 0; while( aszFilters[i] ) { if( name == aszFilters[i] ) return static_cast(i); ++i; } if( bSupportShortNames ) { i = 0; while( aszShortFilters[i] ) { if( name == aszShortFilters[i] ) return static_cast(i); ++i; } } PODOFO_RAISE_ERROR_INFO( ePdfError_UnsupportedFilter, name.GetName().c_str() ); } const char* PdfFilterFactory::FilterTypeToName( EPdfFilter eFilter ) { return aszFilters[static_cast(eFilter)]; } TVecFilters PdfFilterFactory::CreateFilterList( const PdfObject* pObject ) { TVecFilters filters; const PdfObject* pObj = NULL; if( pObject->IsDictionary() && pObject->GetDictionary().HasKey( "Filter" ) ) pObj = pObject->GetDictionary().GetKey( "Filter" ); else if( pObject->IsArray() ) pObj = pObject; else if( pObject->IsName() ) pObj = pObject; if (!pObj) // Object had no /Filter key . Return a null filter list. return filters; if( pObj->IsName() ) filters.push_back( PdfFilterFactory::FilterNameToType( pObj->GetName() ) ); else if( pObj->IsArray() ) { TCIVariantList it = pObj->GetArray().begin(); while( it != pObj->GetArray().end() ) { if ( (*it).IsName() ) { filters.push_back( PdfFilterFactory::FilterNameToType( (*it).GetName() ) ); } else if ( (*it).IsReference() ) { PdfObject* pFilter = pObject->GetOwner()->GetObject( (*it).GetReference() ); if( pFilter == NULL ) { PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidDataType, "Filter array contained unexpected reference" ); } filters.push_back( PdfFilterFactory::FilterNameToType( pFilter->GetName() ) ); } else { PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidDataType, "Filter array contained unexpected non-name type" ); } ++it; } } return filters; } }; podofo-0.9.3/src/base/PdfRefCountedInputDevice.cpp0000664000175000017500000001132312347311233021715 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2006 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfRefCountedInputDevice.h" #include "PdfInputDevice.h" #include "PdfDefinesPrivate.h" namespace PoDoFo { PdfRefCountedInputDevice::PdfRefCountedInputDevice() : m_pDevice( NULL ) { } PdfRefCountedInputDevice::PdfRefCountedInputDevice( const char* pszFilename, const char* ) : m_pDevice( NULL ) { m_pDevice = new TRefCountedInputDevice(); m_pDevice->m_lRefCount = 1; try { m_pDevice->m_pDevice = new PdfInputDevice( pszFilename ); } catch( const PdfError & rError ) { delete m_pDevice; throw rError; } } #ifdef _WIN32 PdfRefCountedInputDevice::PdfRefCountedInputDevice( const wchar_t* pszFilename, const char* ) : m_pDevice( NULL ) { m_pDevice = new TRefCountedInputDevice(); m_pDevice->m_lRefCount = 1; try { m_pDevice->m_pDevice = new PdfInputDevice( pszFilename ); } catch( const PdfError & rError ) { delete m_pDevice; throw rError; } } #endif // _WIN32 PdfRefCountedInputDevice::PdfRefCountedInputDevice( const char* pBuffer, size_t lLen ) : m_pDevice( NULL ) { m_pDevice = new TRefCountedInputDevice(); m_pDevice->m_lRefCount = 1; try { m_pDevice->m_pDevice = new PdfInputDevice( pBuffer, lLen ); } catch( const PdfError & rError ) { delete m_pDevice; throw rError; } } PdfRefCountedInputDevice::PdfRefCountedInputDevice( PdfInputDevice* pDevice ) : m_pDevice( NULL ) { m_pDevice = new TRefCountedInputDevice(); m_pDevice->m_lRefCount = 1; m_pDevice->m_pDevice = pDevice; } PdfRefCountedInputDevice::PdfRefCountedInputDevice( const PdfRefCountedInputDevice & rhs ) : m_pDevice( NULL ) { this->operator=( rhs ); } PdfRefCountedInputDevice::~PdfRefCountedInputDevice() { Detach(); } void PdfRefCountedInputDevice::Detach() { if( m_pDevice && !--m_pDevice->m_lRefCount ) { // last owner of the file! m_pDevice->m_pDevice->Close(); delete m_pDevice->m_pDevice; delete m_pDevice; m_pDevice = NULL; } } const PdfRefCountedInputDevice & PdfRefCountedInputDevice::operator=( const PdfRefCountedInputDevice & rhs ) { Detach(); m_pDevice = rhs.m_pDevice; if( m_pDevice ) m_pDevice->m_lRefCount++; return *this; } }; podofo-0.9.3/src/base/PdfEncodingFactory.cpp0000664000175000017500000001756212347275540020622 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2008 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfEncodingFactory.h" #include "PdfEncoding.h" #include "util/PdfMutexWrapper.h" #include "PdfName.h" #include "PdfObject.h" #include "PdfDefinesPrivate.h" #include "doc/PdfIdentityEncoding.h" namespace PoDoFo { const PdfDocEncoding* PdfEncodingFactory::s_pDocEncoding = NULL; const PdfWinAnsiEncoding* PdfEncodingFactory::s_pWinAnsiEncoding = NULL; const PdfMacRomanEncoding* PdfEncodingFactory::s_pMacRomanEncoding = NULL; const PdfStandardEncoding* PdfEncodingFactory::s_pStandardEncoding = NULL; // OC 13.08.2010 New. const PdfMacExpertEncoding* PdfEncodingFactory::s_pMacExpertEncoding = NULL; // OC 13.08.2010 New. const PdfSymbolEncoding* PdfEncodingFactory::s_pSymbolEncoding = NULL; // OC 13.08.2010 New. const PdfZapfDingbatsEncoding* PdfEncodingFactory::s_pZapfDingbatsEncoding = NULL; // OC 13.08.2010 New. const PdfIdentityEncoding * PdfEncodingFactory::s_pIdentityEncoding = NULL; Util::PdfMutex PdfEncodingFactory::s_mutex; const PdfEncoding* PdfEncodingFactory::GlobalPdfDocEncodingInstance() { if(!s_pDocEncoding) // First check { Util::PdfMutexWrapper wrapper( PdfEncodingFactory::s_mutex ); if(!s_pDocEncoding) // Double check s_pDocEncoding = new PdfDocEncoding(); } return s_pDocEncoding; } const PdfEncoding* PdfEncodingFactory::GlobalWinAnsiEncodingInstance() { if(!s_pWinAnsiEncoding) // First check { Util::PdfMutexWrapper wrapper( PdfEncodingFactory::s_mutex ); if(!s_pWinAnsiEncoding) // Double check s_pWinAnsiEncoding = new PdfWinAnsiEncoding(); } return s_pWinAnsiEncoding; } const PdfEncoding* PdfEncodingFactory::GlobalMacRomanEncodingInstance() { if(!s_pMacRomanEncoding) // First check { Util::PdfMutexWrapper wrapper( PdfEncodingFactory::s_mutex ); if(!s_pMacRomanEncoding) // Double check s_pMacRomanEncoding = new PdfMacRomanEncoding(); } return s_pMacRomanEncoding; } // OC 13.08.2010: const PdfEncoding* PdfEncodingFactory::GlobalStandardEncodingInstance() { if(!s_pStandardEncoding) // First check { Util::PdfMutexWrapper wrapper( PdfEncodingFactory::s_mutex ); if(!s_pStandardEncoding) // Double check s_pStandardEncoding = new PdfStandardEncoding(); } return s_pStandardEncoding; } // OC 13.08.2010: const PdfEncoding* PdfEncodingFactory::GlobalMacExpertEncodingInstance() { if(!s_pMacExpertEncoding) // First check { Util::PdfMutexWrapper wrapper( PdfEncodingFactory::s_mutex ); if(!s_pMacExpertEncoding) // Double check s_pMacExpertEncoding = new PdfMacExpertEncoding(); } return s_pMacExpertEncoding; } // OC 13.08.2010: const PdfEncoding* PdfEncodingFactory::GlobalSymbolEncodingInstance() { if(!s_pSymbolEncoding) // First check { Util::PdfMutexWrapper wrapper( PdfEncodingFactory::s_mutex ); if(!s_pSymbolEncoding) // Double check s_pSymbolEncoding = new PdfSymbolEncoding(); } return s_pSymbolEncoding; } // OC 13.08.2010: const PdfEncoding* PdfEncodingFactory::GlobalZapfDingbatsEncodingInstance() { if(!s_pZapfDingbatsEncoding) // First check { Util::PdfMutexWrapper wrapper( PdfEncodingFactory::s_mutex ); if(!s_pZapfDingbatsEncoding) // Double check s_pZapfDingbatsEncoding = new PdfZapfDingbatsEncoding(); } return s_pZapfDingbatsEncoding; } const PdfEncoding* PdfEncodingFactory::GlobalIdentityEncodingInstance() { if(!s_pIdentityEncoding) // First check { Util::PdfMutexWrapper wrapper( PdfEncodingFactory::s_mutex ); if(!s_pIdentityEncoding) // Double check s_pIdentityEncoding = new PdfIdentityEncoding( 0, 0xffff, false ); } return s_pIdentityEncoding; } int podofo_number_of_clients = 0; void PdfEncodingFactory::FreeGlobalEncodingInstances() { Util::PdfMutexWrapper wrapper( PdfEncodingFactory::s_mutex ); podofo_number_of_clients--; if (podofo_number_of_clients <= 0) { Util::PdfMutexWrapper wrapper( PdfEncodingFactory::s_mutex ); if (NULL != s_pMacRomanEncoding) { delete s_pMacRomanEncoding; } if (NULL != s_pWinAnsiEncoding) { delete s_pWinAnsiEncoding; } if (NULL != s_pDocEncoding) { delete s_pDocEncoding; } if (NULL != s_pStandardEncoding) // OC 13.08.2010 { delete s_pStandardEncoding; } if (NULL != s_pMacExpertEncoding) // OC 13.08.2010 { delete s_pMacExpertEncoding; } if (NULL != s_pSymbolEncoding) // OC 13.08.2010 { delete s_pSymbolEncoding; } if (NULL != s_pZapfDingbatsEncoding) // OC 13.08.2010 { delete s_pZapfDingbatsEncoding; } if (NULL != s_pIdentityEncoding) { delete s_pIdentityEncoding; } s_pMacRomanEncoding = NULL; s_pWinAnsiEncoding = NULL; s_pDocEncoding = NULL; s_pStandardEncoding = NULL; // OC 13.08.2010 s_pMacExpertEncoding = NULL; // OC 13.08.2010 s_pSymbolEncoding = NULL; // OC 13.08.2010 s_pZapfDingbatsEncoding = NULL; // OC 13.08.2010 s_pIdentityEncoding = NULL; } } void PdfEncodingFactory::PoDoFoClientAttached() { podofo_number_of_clients++; } }; podofo-0.9.3/src/base/PdfStream.cpp0000664000175000017500000002143412344436402016761 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2005 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfStream.h" #include "PdfArray.h" #include "PdfFilter.h" #include "PdfInputStream.h" #include "PdfOutputStream.h" #include "PdfOutputDevice.h" #include "PdfDefinesPrivate.h" #include #include using namespace std; namespace PoDoFo { PdfStream::PdfStream( PdfObject* pParent ) : m_pParent( pParent ), m_bAppend( false ) { } PdfStream::~PdfStream() { } void PdfStream::GetFilteredCopy( PdfOutputStream* pStream ) const { TVecFilters vecFilters = PdfFilterFactory::CreateFilterList( m_pParent ); if( vecFilters.size() ) { PdfOutputStream* pDecodeStream = PdfFilterFactory::CreateDecodeStream( vecFilters, pStream, m_pParent ? &(m_pParent->GetDictionary()) : NULL ); try { pDecodeStream->Write( const_cast(this->GetInternalBuffer()), this->GetInternalBufferSize() ); pDecodeStream->Close(); } catch( const PdfError & e ) { delete pDecodeStream; throw e; } delete pDecodeStream; } else { // Also work on unencoded streams pStream->Write( const_cast(this->GetInternalBuffer()), this->GetInternalBufferSize() ); } } void PdfStream::GetFilteredCopy( char** ppBuffer, pdf_long* lLen ) const { TVecFilters vecFilters = PdfFilterFactory::CreateFilterList( m_pParent ); PdfMemoryOutputStream stream; if( vecFilters.size() ) { // Use std::auto_ptr so that pDecodeStream is deleted // even in the case of an exception std::auto_ptr pDecodeStream( PdfFilterFactory::CreateDecodeStream( vecFilters, &stream, m_pParent ? &(m_pParent->GetDictionary()) : NULL ) ); pDecodeStream->Write( this->GetInternalBuffer(), this->GetInternalBufferSize() ); pDecodeStream->Close(); } else { // Also work on unencoded streams stream.Write( const_cast(this->GetInternalBuffer()), this->GetInternalBufferSize() ); stream.Close(); } *lLen = stream.GetLength(); *ppBuffer = stream.TakeBuffer(); } const PdfStream & PdfStream::operator=( const PdfStream & rhs ) { PdfMemoryInputStream stream( rhs.GetInternalBuffer(), rhs.GetInternalBufferSize() ); this->SetRawData( &stream ); if( m_pParent ) m_pParent->GetDictionary().AddKey( PdfName::KeyLength, PdfVariant(static_cast(rhs.GetInternalBufferSize()))); return (*this); } void PdfStream::Set( const char* szBuffer, pdf_long lLen, const TVecFilters & vecFilters ) { this->BeginAppend( vecFilters ); this->Append( szBuffer, lLen ); this->EndAppend(); } void PdfStream::Set( const char* szBuffer, pdf_long lLen ) { this->BeginAppend(); this->Append( szBuffer, lLen ); this->EndAppend(); } void PdfStream::Set( PdfInputStream* pStream ) { TVecFilters vecFilters; vecFilters.push_back( ePdfFilter_FlateDecode ); this->Set( pStream, vecFilters ); } void PdfStream::Set( PdfInputStream* pStream, const TVecFilters & vecFilters ) { const int BUFFER_SIZE = 4096; pdf_long lLen = 0; char buffer[BUFFER_SIZE]; this->BeginAppend( vecFilters ); do { lLen = pStream->Read( buffer, BUFFER_SIZE ); this->Append( buffer, lLen ); } while( lLen == BUFFER_SIZE ); this->EndAppend(); } void PdfStream::SetRawData( PdfInputStream* pStream, pdf_long lLen ) { const pdf_long BUFFER_SIZE = 4096; char buffer[BUFFER_SIZE]; pdf_long lRead; TVecFilters vecEmpty; // TODO: DS, give begin append a size hint so that it knows // how many data has to be allocated this->BeginAppend( vecEmpty, true, false ); if( lLen == -1 ) { do { lRead = pStream->Read( buffer, BUFFER_SIZE ); this->Append( buffer, lRead ); } while( lRead > 0 ); } else { do { lRead = pStream->Read( buffer, PDF_MIN( BUFFER_SIZE, lLen ), &lLen ); lLen -= lRead; this->Append( buffer, lRead ); } while( lLen && lRead > 0 ); } this->EndAppend(); } void PdfStream::BeginAppend( bool bClearExisting ) { TVecFilters vecFilters; vecFilters.push_back( ePdfFilter_FlateDecode ); this->BeginAppend( vecFilters, bClearExisting ); } void PdfStream::BeginAppend( const TVecFilters & vecFilters, bool bClearExisting, bool bDeleteFilters ) { char* pBuffer = NULL; pdf_long lLen = 0; //RG: TODO Should this variable be initialised with 0 (line 225 may fall through without initialisation!) PODOFO_RAISE_LOGIC_IF( m_bAppend, "BeginAppend() failed because EndAppend() was not yet called!" ); if( m_pParent && m_pParent->GetOwner() ) m_pParent->GetOwner()->BeginAppendStream( this ); if( !bClearExisting && this->GetLength() ) this->GetFilteredCopy( &pBuffer, &lLen ); if( !vecFilters.size() && bDeleteFilters ) { m_pParent->GetDictionary().RemoveKey( PdfName::KeyFilter ); } if( vecFilters.size() == 1 ) { m_pParent->GetDictionary().AddKey( PdfName::KeyFilter, PdfName( PdfFilterFactory::FilterTypeToName( vecFilters.front() ) ) ); } else if( vecFilters.size() > 1 ) { PdfArray filters; TCIVecFilters it = vecFilters.begin(); while( it != vecFilters.end() ) { filters.push_back( PdfName( PdfFilterFactory::FilterTypeToName( *it ) ) ); ++it; } m_pParent->GetDictionary().AddKey( PdfName::KeyFilter, filters ); } this->BeginAppendImpl( vecFilters ); m_bAppend = true; if( pBuffer ) { this->Append( pBuffer, lLen ); free( pBuffer ); } } void PdfStream::EndAppend() { PODOFO_RAISE_LOGIC_IF( !m_bAppend, "EndAppend() failed because BeginAppend() was not yet called!" ); m_bAppend = false; this->EndAppendImpl(); if( m_pParent && m_pParent->GetOwner() ) m_pParent->GetOwner()->EndAppendStream( this ); } }; podofo-0.9.3/src/base/PdfStream.h0000664000175000017500000003112012344436402016417 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2005 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_STREAM_H_ #define _PDF_STREAM_H_ #include "PdfDefines.h" #include "PdfDictionary.h" #include "PdfFilter.h" #include "PdfRefCountedBuffer.h" #include namespace PoDoFo { class PdfInputStream; class PdfName; class PdfObject; class PdfOutputStream; /** A PDF stream can be appended to any PdfObject * and can contain arbitrary data. * * Most of the time it will contain either drawing commands * to draw onto a page or binary data like a font or an image. * * You have to use a concrete implementation of a stream, * which can be retrieved from a StreamFactory. * \see PdfVecObjects * \see PdfMemoryStream * \see PdfFileStream */ class PODOFO_API PdfStream { public: /** Create a new PdfStream object which has a parent PdfObject. * The stream will be deleted along with the parent. * This constructor will be called by PdfObject::Stream() for you. * \param pParent parent object */ PdfStream( PdfObject* pParent ); virtual ~PdfStream(); /** Write the stream to an output device * \param pDevice write to this outputdevice. * \param pEncrypt encrypt stream data using this object */ virtual void Write( PdfOutputDevice* pDevice, PdfEncrypt* pEncrypt = NULL ) = 0; /** Set a binary buffer as stream data. * * Use PdfFilterFactory::CreateFilterList if you want to use the contents * of the stream dictionary's existing filter key. * * \param szBuffer buffer containing the stream data * \param lLen length of the buffer * \param vecFilters a list of filters to use when appending data */ void Set( const char* szBuffer, pdf_long lLen, const TVecFilters & vecFilters ); /** Set a binary buffer as stream data. * All data will be flate encoded. * * \param szBuffer buffer containing the stream data * \param lLen length of the buffer */ void Set( const char* szBuffer, pdf_long lLen ); /** Set a binary buffer whose contents are read from a PdfInputStream * All data will be flate encoded. * * \param pStream read stream contents from this PdfInputStream */ void Set( PdfInputStream* pStream ); /** Set a binary buffer whose contents are read from a PdfInputStream * * Use PdfFilterFactory::CreateFilterList if you want to use the contents * of the stream dictionary's existing filter key. * * \param pStream read stream contents from this PdfInputStream * \param vecFilters a list of filters to use when appending data */ void Set( PdfInputStream* pStream, const TVecFilters & vecFilters ); /** Set a null-terminated char* buffer as the streams contents. * * The string will be copied into a newly allocated buffer. * \param pszString a zero terminated string buffer containing only ASCII text data */ inline void Set( const char* pszString ); /** Sets raw data for this filter which is read from an input stream. * This method does neither encode nor decode the read data. * The filters of the object are not modified and the data is expected to be * encoded as stated by the /Filters key in the streams object. * * \param pStream read data from this input stream * \param lLen read excactly lLen bytes from the input stream * if lLen = -1 read until the end of the input stream was reached. */ void SetRawData( PdfInputStream* pStream, pdf_long lLen = -1 ); /** Start appending data to this stream. * * This method has to be called before any of the append methods. * All appended data will be flate decoded! * * \param bClearExisting if true any existing stream contents will be * cleared. * * \see Append * \see EndAppend */ void BeginAppend( bool bClearExisting = true ); /** Start appending data to this stream. * This method has to be called before any of the append methods. * * Use PdfFilterFactory::CreateFilterList if you want to use the contents * of the stream dictionary's existing filter key. * * \param vecFilters a list of filters to use when appending data * \param bClearExisting if true any existing stream contents will be cleared. * \param bDeleteFilters if true existing filter keys are deleted if an * empty list of filters is passed (required for SetRawData) * * \see Append * \see EndAppend */ void BeginAppend( const TVecFilters & vecFilters, bool bClearExisting = true, bool bDeleteFilters = true ); /** Append a binary buffer to the current stream contents. * * Make sure BeginAppend has been called before. * * \param pszString a buffer * \param lLen length of the buffer * * \see BeginAppend * \see EndAppend */ inline void Append( const char* pszString, size_t lLen ); /** Append a null-terminated string to the current stream contents. * * Make sure BeginAppend has been called before. * * \param pszString a zero terminated string buffer containing only ASCII text data * * \see BeginAppend * \see EndAppend */ inline void Append( const char* pszString ); /** Append to the current stream contents. * * Make sure BeginAppend has been called before. * * \param sString a std::string containing ASCII text data * * \see BeginAppend * \see EndAppend */ inline void Append( const std::string& sString ); /** Finish appending data to this stream. * BeginAppend() has to be called before this method. * * \see BeginAppend * \see Append */ void EndAppend(); /** * \returns true if code is between BeginAppend() * and EndAppend() at the moment. I.e. * it is save to call EndAppend now. * * \see BeginAppend * \see Append */ inline bool IsAppending() const; /** Get the stream's length with all filters applied (eg if the stream is * Flate compressed, the length of the compressed data stream). * * \returns the length of the internal buffer */ virtual pdf_long GetLength() const = 0; /** Get a malloced buffer of the current stream. * No filters will be applied to the buffer, so * if the stream is Flate compressed the compressed copy * will be returned. * * The caller has to free() the buffer. * * \param pBuffer pointer to the buffer * \param lLen pointer to the buffer length */ virtual void GetCopy( char** pBuffer, pdf_long* lLen ) const = 0; /** Get a copy of a the stream and write it to a PdfOutputStream * * \param pStream data is written to this stream. */ virtual void GetCopy( PdfOutputStream* pStream ) const = 0; /** Get a malloced buffer of the current stream which has been * filtered by all filters as specified in the dictionary's * /Filter key. For example, if the stream is Flate compressed, * the buffer returned from this method will have been decompressed. * * The caller has to free() the buffer. * * \param pBuffer pointer to the buffer * \param lLen pointer to the buffer length */ void GetFilteredCopy( char** pBuffer, pdf_long* lLen ) const; /** Get a filtered copy of a the stream and write it to a PdfOutputStream * * \param pStream filtered data is written to this stream. */ void GetFilteredCopy( PdfOutputStream* pStream ) const; /** Create a copy of a PdfStream object * \param rhs the object to clone * \returns a reference to this object */ const PdfStream & operator=( const PdfStream & rhs ); protected: /** Required for the GetFilteredCopy implementation * \returns a handle to the internal buffer */ virtual const char* GetInternalBuffer() const = 0; /** Required for the GetFilteredCopy implementation * \returns the size of the internal buffer */ virtual pdf_long GetInternalBufferSize() const = 0; /** Begin appending data to this stream. * Clears the current stream contents. * * Use PdfFilterFactory::CreateFilterList if you want to use the contents * of the stream dictionary's existing filter key. * * \param vecFilters use this filters to encode any data written to the stream. */ virtual void BeginAppendImpl( const TVecFilters & vecFilters ) = 0; /** Append a binary buffer to the current stream contents. * * \param pszString a buffer * \param lLen length of the buffer * * \see BeginAppend * \see Append * \see EndAppend */ virtual void AppendImpl( const char* pszString, size_t lLen ) = 0; /** Finish appending data to the stream */ virtual void EndAppendImpl() = 0; protected: PdfObject* m_pParent; bool m_bAppend; }; // ----------------------------------------------------- // // ----------------------------------------------------- void PdfStream::Set( const char* pszString ) { if( pszString ) Set( const_cast(pszString), strlen( pszString ) ); } // ----------------------------------------------------- // // ----------------------------------------------------- void PdfStream::Append( const char* pszString, size_t lLen ) { PODOFO_RAISE_LOGIC_IF( !m_bAppend, "Append() failed because BeginAppend() was not yet called!" ); this->AppendImpl( pszString, lLen ); } // ----------------------------------------------------- // // ----------------------------------------------------- void PdfStream::Append( const char* pszString ) { if( pszString ) Append( pszString, strlen( pszString ) ); } // ----------------------------------------------------- // // ----------------------------------------------------- void PdfStream::Append( const std::string& sString ) { Append( sString.c_str(), sString.length() ); } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfStream::IsAppending() const { return m_bAppend; } }; #endif // _PDF_STREAM_H_ podofo-0.9.3/src/base/PdfEncrypt.cpp0000664000175000017500000021520012347271543017154 0ustar dominikdominik/* ********************************************************************** ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. ** ** ** ** License to copy and use this software is granted provided that ** ** it is identified as the "RSA Data Security, Inc. MD5 Message ** ** Digest Algorithm" in all material mentioning or referencing this ** ** software or this function. ** ** ** ** License is also granted to make and use derivative works ** ** provided that such works are identified as "derived from the RSA ** ** Data Security, Inc. MD5 Message Digest Algorithm" in all ** ** material mentioning or referencing the derived work. ** ** ** ** RSA Data Security, Inc. makes no representations concerning ** ** either the merchantability of this software or the suitability ** ** of this software for any particular purpose. It is provided "as ** ** is" without express or implied warranty of any kind. ** ** ** ** These notices must be retained in any copies of any part of this ** ** documentation and/or software. ** ********************************************************************** */ // includes #include "PdfEncrypt.h" #include "PdfDictionary.h" #include "PdfFilter.h" #include "PdfDefinesPrivate.h" #include #include #include #ifdef PODOFO_HAVE_OPENSSL // SHA-256 #ifdef PODOFO_HAVE_LIBIDN // AES-256 dependencies : // SASL #include #include #endif // PODOFO_HAVE_LIBIDN #include #include #endif //PODOFO_HAVE_OPENSSL namespace { //RG: TODO Could we name literal 256 and use the literal name e.g. //const size_t KEY_SIZE = 256; } namespace PoDoFo { #ifdef PODOFO_HAVE_LIBIDN int PdfEncrypt::s_nEnabledEncryptionAlgorithms = ePdfEncryptAlgorithm_RC4V1 | ePdfEncryptAlgorithm_RC4V2 | ePdfEncryptAlgorithm_AESV2 | ePdfEncryptAlgorithm_AESV3; #else // PODOFO_HAVE_LIBIDN int PdfEncrypt::s_nEnabledEncryptionAlgorithms = ePdfEncryptAlgorithm_RC4V1 | ePdfEncryptAlgorithm_RC4V2 | ePdfEncryptAlgorithm_AESV2; #endif // PODOFO_HAVE_LIBIDN #ifdef PODOFO_HAVE_OPENSSL // Default value for P (permissions) = no permission #define PERMS_DEFAULT 0xFFFFF0C0 #define AES_IV_LENGTH 16 // A class that holds the AES Crypto object class AESCryptoEngine { public: AESCryptoEngine() { EVP_CIPHER_CTX_init(&aes); } EVP_CIPHER_CTX* getEngine() {return &aes;} ~AESCryptoEngine() { EVP_CIPHER_CTX_cleanup(&aes); } private: EVP_CIPHER_CTX aes; }; // A class that holds the RC4 Crypto object // Either CCCrpytor or EVP_CIPHER_CTX class RC4CryptoEngine { public: RC4CryptoEngine() { EVP_CIPHER_CTX_init(&rc4); } EVP_CIPHER_CTX* getEngine() {return &rc4;} ~RC4CryptoEngine() { EVP_CIPHER_CTX_cleanup(&rc4); } private: EVP_CIPHER_CTX rc4; }; /** A class that can encrypt/decrpyt streamed data block wise * This is used in the input and output stream encryption implementation. * Only the RC4 encryption algorithm is supported */ class PdfRC4Stream { public: PdfRC4Stream( unsigned char rc4key[256], unsigned char rc4last[256], unsigned char* key, const size_t keylen ) : m_a( 0 ), m_b( 0 ) { size_t i; size_t j; size_t t; if (memcmp(key,rc4key,keylen) != 0) { for (i = 0; i < 256; i++) m_rc4[i] = static_cast(i); j = 0; for (i = 0; i < 256; i++) { t = static_cast(m_rc4[i]); j = (j + t + static_cast(key[i % keylen])) % 256; m_rc4[i] = m_rc4[j]; m_rc4[j] = static_cast(t); } memcpy(rc4key, key, keylen); memcpy(rc4last, m_rc4, 256); } else { memcpy(m_rc4, rc4last, 256); } } ~PdfRC4Stream() { } /** Encrypt or decrypt a block * * \param pBuffer the input/output buffer. Data is read from this buffer and also stored here * \param lLen the size of the buffer */ pdf_long Encrypt( char* pBuffer, pdf_long lLen ) { unsigned char k; pdf_long t, i; // Do not encode data with no length if( !lLen ) return lLen; for (i = 0; i < lLen; i++ ) { m_a = (m_a + 1) % 256; t = m_rc4[m_a]; m_b = (m_b + t) % 256; m_rc4[m_a] = m_rc4[m_b]; m_rc4[m_b] = static_cast(t); k = m_rc4[(m_rc4[m_a] + m_rc4[m_b]) % 256]; pBuffer[i] = pBuffer[i] ^ k; } return lLen; } private: unsigned char m_rc4[256]; int m_a; int m_b; }; /** A PdfOutputStream that encrypt all data written * using the RC4 encryption algorithm */ class PdfRC4OutputStream : public PdfOutputStream { public: PdfRC4OutputStream( PdfOutputStream* pOutputStream, unsigned char rc4key[256], unsigned char rc4last[256], unsigned char* key, int keylen ) : m_pOutputStream( pOutputStream ), m_stream( rc4key, rc4last, key, keylen ) { } virtual ~PdfRC4OutputStream() { } /** Write data to the output stream * * \param pBuffer the data is read from this buffer * \param lLen the size of the buffer */ virtual pdf_long Write( const char* pBuffer, pdf_long lLen ) { // Do not encode data with no length if( !lLen ) return lLen; char* pOutputBuffer = static_cast(malloc( sizeof(char) * lLen )); if( !pOutputBuffer ) { PODOFO_RAISE_ERROR( ePdfError_OutOfMemory ); } memcpy(pOutputBuffer, pBuffer, lLen); m_stream.Encrypt( pOutputBuffer, lLen ); m_pOutputStream->Write( pOutputBuffer, lLen ); free( pOutputBuffer ); return lLen; } /** Close the PdfOutputStream. * This method may throw exceptions and has to be called * before the descructor to end writing. * * No more data may be written to the output device * after calling close. */ virtual void Close() { } private: PdfOutputStream* m_pOutputStream; PdfRC4Stream m_stream; }; /** A PdfInputStream that decrypts all data read * using the RC4 encryption algorithm */ class PdfRC4InputStream : public PdfInputStream { public: PdfRC4InputStream( PdfInputStream* pInputStream, unsigned char rc4key[256], unsigned char rc4last[256], unsigned char* key, int keylen ) : m_pInputStream( pInputStream ), m_stream( rc4key, rc4last, key, keylen ) { } virtual ~PdfRC4InputStream() { } /** Read data from the input stream * * \param pBuffer the data will be stored into this buffer * \param lLen the size of the buffer and number of bytes * that will be read * * \returns the number of bytes read, -1 if an error ocurred * and zero if no more bytes are available for reading. */ virtual pdf_long Read( char* pBuffer, pdf_long lLen, pdf_long* ) { // Do not encode data with no length if( !lLen ) return lLen; m_pInputStream->Read( pBuffer, lLen ); m_stream.Encrypt( pBuffer, lLen ); return lLen; } private: PdfInputStream* m_pInputStream; PdfRC4Stream m_stream; }; /** A class that can encrypt/decrpyt streamed data block wise * This is used in the input and output stream encryption implementation. */ class PdfAESStream : public PdfEncryptAESBase { public: PdfAESStream( unsigned char* key, const size_t keylen ) : keyLen( keylen ), bFirstRead( true ), bOnlyFinalLeft( false ) { memcpy( this->key, key, keylen ); } ~PdfAESStream() {} /** Decrypt a block * * \param pBuffer the input/output buffer. Data is read from this buffer and also stored here * \param lLen the size of the buffer * \param pTotalLeft total bytes left (needed for AES IV and padding) */ pdf_long Decrypt( unsigned char* pBuffer, pdf_long lLen, pdf_long* pTotalLeft ) { if (pTotalLeft == 0) PODOFO_RAISE_ERROR_INFO( ePdfError_InternalLogic, "Error AES-decryption needs pTotalLeft" ); if( lLen % 16 != 0 ) PODOFO_RAISE_ERROR_INFO( ePdfError_InternalLogic, "Error AES-decryption data length not a multiple of 16" ); EVP_CIPHER_CTX* aes = m_aes->getEngine(); int lOutLen = 0, lStepOutLen; int status = 1; if( bFirstRead ) { bFirstRead = false; if( keyLen == PdfEncrypt::ePdfKeyLength_128/8 ) { status = EVP_DecryptInit_ex( aes, EVP_aes_128_cbc(), NULL, key, pBuffer ); #ifdef PODOFO_HAVE_LIBIDN } else if( keyLen == PdfEncrypt::ePdfKeyLength_256/8 ) { status = EVP_DecryptInit_ex( aes, EVP_aes_256_cbc(), NULL, key, pBuffer ); #endif } else { PODOFO_RAISE_ERROR_INFO( ePdfError_InternalLogic, "Invalid AES key length" ); } if(status != 1) PODOFO_RAISE_ERROR_INFO( ePdfError_InternalLogic, "Error initializing AES encryption engine" ); status = EVP_DecryptUpdate( aes, pBuffer, &lOutLen, pBuffer + AES_IV_LENGTH, lLen - AES_IV_LENGTH ); } else if( !bOnlyFinalLeft ) { // Quote openssl.org: "the decrypted data buffer out passed to EVP_DecryptUpdate() should have sufficient room // for (inl + cipher_block_size) bytes unless the cipher block size is 1 in which case inl bytes is sufficient." // So we need to create a buffer that is bigger than lLen. unsigned char* tempBuffer = new unsigned char[lLen + 16]; status = EVP_DecryptUpdate( aes, tempBuffer, &lOutLen, pBuffer, lLen ); memcpy( pBuffer, tempBuffer, lOutLen ); delete[] tempBuffer; } if( status != 1 ) PODOFO_RAISE_ERROR_INFO( ePdfError_InternalLogic, "Error AES-decryption data" ); if( lLen == *pTotalLeft ) { // Last chunk of the stream if( lLen == lOutLen ) { // Buffer is full, so we need an other round for EVP_DecryptFinal_ex. bOnlyFinalLeft = true; *pTotalLeft += 16; } else { status = EVP_DecryptFinal_ex( aes, pBuffer + lOutLen, &lStepOutLen ); if( status != 1 ) PODOFO_RAISE_ERROR_INFO( ePdfError_InternalLogic, "Error AES-decryption data padding" ); lOutLen += lStepOutLen; } } *pTotalLeft -= lLen - lOutLen; // AES makes the resulting buffer shorter (IV and padding) return lOutLen; } private: unsigned char key[32]; const size_t keyLen; bool bFirstRead; bool bOnlyFinalLeft; }; /** A PdfAESInputStream that decrypts all data read * using the AES encryption algorithm */ class PdfAESInputStream : public PdfInputStream { public: PdfAESInputStream( PdfInputStream* pInputStream, unsigned char* key, int keylen ) : m_pInputStream( pInputStream ), m_stream( key, keylen ) { } virtual ~PdfAESInputStream() { } /** Read data from the input stream * * \param pBuffer the data will be stored into this buffer * \param lLen the size of the buffer and number of bytes * that will be read * \param pTotalLeft total bytes left (needed for AES IV and padding) * * \returns the number of bytes read, -1 if an error ocurred * and zero if no more bytes are available for reading. */ virtual pdf_long Read( char* pBuffer, pdf_long lLen, pdf_long *pTotalLeft ) { // Do not encode data with no length if( !lLen ) return lLen; m_pInputStream->Read( pBuffer, lLen ); return m_stream.Decrypt( (unsigned char*)pBuffer, lLen, pTotalLeft ); } private: PdfInputStream* m_pInputStream; PdfAESStream m_stream; }; /*************************************************************************** * Copyright (C) 2006 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ // --------------------------- // PdfEncrypt implementation // Based on code from Ulrich Telle: http://wxcode.sourceforge.net/components/wxpdfdoc/ // --------------------------- static unsigned char padding[] = "\x28\xBF\x4E\x5E\x4E\x75\x8A\x41\x64\x00\x4E\x56\xFF\xFA\x01\x08\x2E\x2E\x00\xB6\xD0\x68\x3E\x80\x2F\x0C\xA9\xFE\x64\x53\x69\x7A"; PdfEncrypt * PdfEncrypt::CreatePdfEncrypt( const std::string & userPassword, const std::string & ownerPassword, int protection, EPdfEncryptAlgorithm eAlgorithm, EPdfKeyLength eKeyLength ) { PdfEncrypt *pdfEncrypt = NULL; switch (eAlgorithm) { case ePdfEncryptAlgorithm_AESV2: pdfEncrypt = new PdfEncryptAESV2(userPassword, ownerPassword, protection); break; #ifdef PODOFO_HAVE_LIBIDN case ePdfEncryptAlgorithm_AESV3: pdfEncrypt = new PdfEncryptAESV3(userPassword, ownerPassword, protection); break; #endif // PODOFO_HAVE_LIBIDN case ePdfEncryptAlgorithm_RC4V2: case ePdfEncryptAlgorithm_RC4V1: default: pdfEncrypt = new PdfEncryptRC4(userPassword, ownerPassword, protection, eAlgorithm, eKeyLength); break; } return pdfEncrypt; } PdfEncrypt* PdfEncrypt::CreatePdfEncrypt( const PdfObject* pObject ) { PdfEncrypt* pdfEncrypt = NULL; if( !pObject->GetDictionary().HasKey( PdfName("Filter") ) || pObject->GetDictionary().GetKey( PdfName("Filter" ) )->GetName() != PdfName("Standard") ) { std::ostringstream oss; if( pObject->GetDictionary().HasKey( PdfName("Filter") ) ) { oss << "Unsupported encryption filter: " << pObject->GetDictionary().GetKey( PdfName("Filter" ) )->GetName().GetName(); } else { oss << "Encryption dictionary does not have a key /Filter."; } PODOFO_RAISE_ERROR_INFO( ePdfError_UnsupportedFilter, oss.str().c_str() ); } long lV; pdf_int64 lLength; int rValue; int pValue; PdfString oValue; PdfString uValue; PdfName cfmName; bool encryptMetadata = true; try { PdfString sTmp; lV = static_cast(pObject->GetDictionary().GetKey( PdfName("V") )->GetNumber()); rValue = static_cast(pObject->GetDictionary().GetKey( PdfName("R") )->GetNumber()); pValue = static_cast(pObject->GetDictionary().GetKey( PdfName("P") )->GetNumber()); oValue = pObject->GetDictionary().GetKey( PdfName("O") )->GetString(); uValue = pObject->GetDictionary().GetKey( PdfName("U") )->GetString(); if( pObject->GetDictionary().HasKey( PdfName("Length") ) ) { lLength = pObject->GetDictionary().GetKey( PdfName("Length") )->GetNumber(); } else { lLength = 0; } const PdfObject *encryptMetadataObj = pObject->GetDictionary().GetKey( PdfName("EncryptMetadata") ); if( encryptMetadataObj && encryptMetadataObj->IsBool() ) encryptMetadata = encryptMetadataObj->GetBool(); const PdfObject *stmfObj = pObject->GetDictionary().GetKey( PdfName("StmF") ); if( stmfObj && stmfObj->IsName() ) { const PdfObject *obj = pObject->GetDictionary().GetKey( PdfName("CF") ); if( obj && obj->IsDictionary() ) { obj = obj->GetDictionary().GetKey( stmfObj->GetName() ); if( obj && obj->IsDictionary() ) { obj = obj->GetDictionary().GetKey( PdfName("CFM") ); if( obj && obj->IsName() ) cfmName = obj->GetName(); } } } } catch( PdfError & e ) { e.AddToCallstack( __FILE__, __LINE__, "Invalid key in encryption dictionary" ); throw e; } if( (lV == 1L) && (rValue == 2L || rValue == 3L) && PdfEncrypt::IsEncryptionEnabled( ePdfEncryptAlgorithm_RC4V1 ) ) { pdfEncrypt = new PdfEncryptRC4(oValue, uValue, pValue, rValue, ePdfEncryptAlgorithm_RC4V1, 40, encryptMetadata); } else if( (((lV == 2L) && (rValue == 3L)) || cfmName == "V2") && PdfEncrypt::IsEncryptionEnabled( ePdfEncryptAlgorithm_RC4V2 ) ) { // [Alexey] - lLength is pdf_int64. Please make changes in encryption algorithms pdfEncrypt = new PdfEncryptRC4(oValue, uValue, pValue, rValue, ePdfEncryptAlgorithm_RC4V2, static_cast(lLength), encryptMetadata); } else if( (lV == 4L) && (rValue == 4L) && PdfEncrypt::IsEncryptionEnabled( ePdfEncryptAlgorithm_AESV2 ) ) { pdfEncrypt = new PdfEncryptAESV2(oValue, uValue, pValue, encryptMetadata); } #ifdef PODOFO_HAVE_LIBIDN else if( (lV == 5L) && (rValue == 5L) && PdfEncrypt::IsEncryptionEnabled( ePdfEncryptAlgorithm_AESV3 ) ) { PdfString permsValue = pObject->GetDictionary().GetKey( PdfName("Perms") )->GetString(); PdfString oeValue = pObject->GetDictionary().GetKey( PdfName("OE") )->GetString(); PdfString ueValue = pObject->GetDictionary().GetKey( PdfName("UE") )->GetString(); pdfEncrypt = new PdfEncryptAESV3(oValue, oeValue, uValue, ueValue, pValue, permsValue); } #endif // PODOFO_HAVE_LIBIDN else { std::ostringstream oss; oss << "Unsupported encryption method Version=" << lV << " Revision=" << rValue; PODOFO_RAISE_ERROR_INFO( ePdfError_UnsupportedFilter, oss.str().c_str() ); } return pdfEncrypt; } PdfEncrypt * PdfEncrypt::CreatePdfEncrypt(const PdfEncrypt & rhs ) { PdfEncrypt *pdfEncrypt = NULL; if (rhs.m_eAlgorithm == ePdfEncryptAlgorithm_AESV2) pdfEncrypt = new PdfEncryptAESV2(rhs); #ifdef PODOFO_HAVE_LIBIDN else if (rhs.m_eAlgorithm == ePdfEncryptAlgorithm_AESV3) pdfEncrypt = new PdfEncryptAESV3(rhs); #endif // PODOFO_HAVE_LIBIDN else pdfEncrypt = new PdfEncryptRC4(rhs); return pdfEncrypt; } PdfEncrypt::~PdfEncrypt() { } int PdfEncrypt::GetEnabledEncryptionAlgorithms() { return PdfEncrypt::s_nEnabledEncryptionAlgorithms; } void PdfEncrypt::SetEnabledEncryptionAlgorithms(int nEncryptionAlgorithms) { PdfEncrypt::s_nEnabledEncryptionAlgorithms = nEncryptionAlgorithms; } bool PdfEncrypt::IsEncryptionEnabled(EPdfEncryptAlgorithm eAlgorithm) { return (PdfEncrypt::s_nEnabledEncryptionAlgorithms & eAlgorithm) != 0; } PdfEncrypt::PdfEncrypt( const PdfEncrypt & rhs ) { m_eAlgorithm = rhs.m_eAlgorithm; m_eKeyLength = rhs.m_eKeyLength; m_pValue = rhs.m_pValue; m_rValue = rhs.m_rValue; m_keyLength = rhs.m_keyLength; m_curReference = rhs.m_curReference; m_documentId = rhs.m_documentId; m_userPass = rhs.m_userPass; m_ownerPass = rhs.m_ownerPass; m_bEncryptMetadata = rhs.m_bEncryptMetadata; } bool PdfEncrypt::CheckKey(unsigned char key1[32], unsigned char key2[32]) { // Check whether the right password had been given bool ok = true; int k; for (k = 0; ok && k < m_keyLength; k++) { ok = ok && (key1[k] == key2[k]); } return ok; } PdfEncryptMD5Base::PdfEncryptMD5Base( const PdfEncrypt & rhs ) : PdfEncrypt(rhs) { const PdfEncrypt* ptr = &rhs; memcpy( m_uValue, rhs.GetUValue(), sizeof(unsigned char) * 32 ); memcpy( m_oValue, rhs.GetOValue(), sizeof(unsigned char) * 32 ); memcpy( m_encryptionKey, rhs.GetEncryptionKey(), sizeof(unsigned char) * 16 ); memcpy( m_rc4key, static_cast(ptr)->m_rc4key, sizeof(unsigned char) * 16 ); memcpy( m_rc4last, static_cast(ptr)->m_rc4last, sizeof(unsigned char) * 256 ); m_bEncryptMetadata = static_cast(ptr)->m_bEncryptMetadata; } void PdfEncryptMD5Base::PadPassword(const std::string& password, unsigned char pswd[32]) { size_t m = password.length(); if (m > 32) m = 32; size_t j; size_t p = 0; for (j = 0; j < m; j++) { pswd[p++] = static_cast( password[j] ); } for (j = 0; p < 32 && j < 32; j++) { pswd[p++] = padding[j]; } } bool PdfEncryptMD5Base::Authenticate(const std::string& documentID, const std::string& password, const std::string& uValue, const std::string& oValue, int pValue, int lengthValue, int rValue) { m_pValue = pValue; m_keyLength = lengthValue / 8; m_rValue = rValue; memcpy(m_uValue, uValue.c_str(), 32); memcpy(m_oValue, oValue.c_str(), 32); return Authenticate(password, documentID); } void PdfEncryptMD5Base::ComputeOwnerKey(unsigned char userPad[32], unsigned char ownerPad[32], int keyLength, int revision, bool authenticate, unsigned char ownerKey[32]) { unsigned char mkey[MD5_DIGEST_LENGTH]; unsigned char digest[MD5_DIGEST_LENGTH]; MD5_CTX ctx; int status = MD5_Init(&ctx); if(status != 1) PODOFO_RAISE_ERROR_INFO( ePdfError_InternalLogic, "Error initializing MD5 hashing engine" ); status = MD5_Update(&ctx, ownerPad, 32); if(status != 1) PODOFO_RAISE_ERROR_INFO( ePdfError_InternalLogic, "Error MD5-hashing data" ); status = MD5_Final(digest,&ctx); if(status != 1) PODOFO_RAISE_ERROR_INFO( ePdfError_InternalLogic, "Error MD5-hashing data" ); if ((revision == 3) || (revision == 4)) { // only use for the input as many bit as the key consists of for (int k = 0; k < 50; ++k) { status = MD5_Init(&ctx); if(status != 1) PODOFO_RAISE_ERROR_INFO( ePdfError_InternalLogic, "Error initializing MD5 hashing engine" ); status = MD5_Update(&ctx, digest, keyLength); if(status != 1) PODOFO_RAISE_ERROR_INFO( ePdfError_InternalLogic, "Error MD5-hashing data" ); status = MD5_Final(digest,&ctx); if(status != 1) PODOFO_RAISE_ERROR_INFO( ePdfError_InternalLogic, "Error MD5-hashing data" ); } memcpy(ownerKey, userPad, 32); for (unsigned int i = 0; i < 20; ++i) { for (int j = 0; j < keyLength ; ++j) { if (authenticate) mkey[j] = static_cast(static_cast(digest[j] ^ (19-i))); else mkey[j] = static_cast(static_cast(digest[j] ^ i)); } RC4(mkey, keyLength, ownerKey, 32, ownerKey, 32); } } else { RC4(digest, 5, userPad, 32, ownerKey, 32); } } void PdfEncryptMD5Base::ComputeEncryptionKey(const std::string& documentId, unsigned char userPad[32], unsigned char ownerKey[32], int pValue, int keyLength, int revision, unsigned char userKey[32], bool encryptMetadata) { int j; int k; m_keyLength = keyLength / 8; MD5_CTX ctx; int status = MD5_Init(&ctx); if(status != 1) PODOFO_RAISE_ERROR_INFO( ePdfError_InternalLogic, "Error initializing MD5 hashing engine" ); status = MD5_Update(&ctx, userPad, 32); if(status != 1) PODOFO_RAISE_ERROR_INFO( ePdfError_InternalLogic, "Error MD5-hashing data" ); status = MD5_Update(&ctx, ownerKey, 32); if(status != 1) PODOFO_RAISE_ERROR_INFO( ePdfError_InternalLogic, "Error MD5-hashing data" ); unsigned char ext[4]; ext[0] = static_cast ( pValue & 0xff); ext[1] = static_cast ((pValue >> 8) & 0xff); ext[2] = static_cast ((pValue >> 16) & 0xff); ext[3] = static_cast ((pValue >> 24) & 0xff); status = MD5_Update(&ctx, ext, 4); if(status != 1) PODOFO_RAISE_ERROR_INFO( ePdfError_InternalLogic, "Error MD5-hashing data" ); unsigned int docIdLength = static_cast(documentId.length()); unsigned char* docId = NULL; if (docIdLength > 0) { docId = new unsigned char[docIdLength]; size_t j; for (j = 0; j < docIdLength; j++) { docId[j] = static_cast( documentId[j] ); } status = MD5_Update(&ctx, docId, docIdLength); if(status != 1) PODOFO_RAISE_ERROR_INFO( ePdfError_InternalLogic, "Error MD5-hashing data" ); } // If document metadata is not being encrypted, // pass 4 bytes with the value 0xFFFFFFFF to the MD5 hash function. if( !encryptMetadata ) { unsigned char noMetaAddition[4] = { 0xff, 0xff, 0xff, 0xff }; status = MD5_Update(&ctx, noMetaAddition, 4); } unsigned char digest[MD5_DIGEST_LENGTH]; status = MD5_Final(digest,&ctx); if(status != 1) PODOFO_RAISE_ERROR_INFO( ePdfError_InternalLogic, "Error MD5-hashing data" ); // only use the really needed bits as input for the hash if (revision == 3 || revision == 4) { for (k = 0; k < 50; ++k) { status = MD5_Init(&ctx); if(status != 1) PODOFO_RAISE_ERROR_INFO( ePdfError_InternalLogic, "Error initializing MD5 hashing engine" ); status = MD5_Update(&ctx, digest, m_keyLength); if(status != 1) PODOFO_RAISE_ERROR_INFO( ePdfError_InternalLogic, "Error MD5-hashing data" ); status = MD5_Final(digest, &ctx); if(status != 1) PODOFO_RAISE_ERROR_INFO( ePdfError_InternalLogic, "Error MD5-hashing data" ); } } memcpy(m_encryptionKey, digest, m_keyLength); // Setup user key if (revision == 3 || revision == 4) { status = MD5_Init(&ctx); if(status != 1) PODOFO_RAISE_ERROR_INFO( ePdfError_InternalLogic, "Error initializing MD5 hashing engine" ); status = MD5_Update(&ctx, padding, 32); if(status != 1) PODOFO_RAISE_ERROR_INFO( ePdfError_InternalLogic, "Error MD5-hashing data" ); if (docId != NULL) { status = MD5_Update(&ctx, docId, docIdLength); if(status != 1) PODOFO_RAISE_ERROR_INFO( ePdfError_InternalLogic, "Error MD5-hashing data" ); } status = MD5_Final(digest, &ctx); if(status != 1) PODOFO_RAISE_ERROR_INFO( ePdfError_InternalLogic, "Error MD5-hashing data" ); memcpy(userKey, digest, 16); for (k = 16; k < 32; ++k) { userKey[k] = 0; } for (k = 0; k < 20; k++) { for (j = 0; j < m_keyLength; ++j) { digest[j] = static_cast(m_encryptionKey[j] ^ k); } RC4(digest, m_keyLength, userKey, 16, userKey, 16); } } else { RC4(m_encryptionKey, m_keyLength, padding, 32, userKey, 32); } if (docId != NULL) { delete [] docId; } } void PdfEncryptMD5Base::CreateObjKey( unsigned char objkey[16], int* pnKeyLen ) const { const unsigned int n = static_cast(m_curReference.ObjectNumber()); const unsigned int g = static_cast(m_curReference.GenerationNumber()); unsigned char nkey[MD5_DIGEST_LENGTH+5+4]; int nkeylen = m_keyLength + 5; const size_t KEY_LENGTH_SIZE_T = static_cast(m_keyLength); for (size_t j = 0; j < KEY_LENGTH_SIZE_T; j++) { nkey[j] = m_encryptionKey[j]; } nkey[m_keyLength+0] = static_cast(0xff & n); nkey[m_keyLength+1] = static_cast(0xff & (n >> 8)); nkey[m_keyLength+2] = static_cast(0xff & (n >> 16)); nkey[m_keyLength+3] = static_cast(0xff & g); nkey[m_keyLength+4] = static_cast(0xff & (g >> 8)); if (m_eAlgorithm == ePdfEncryptAlgorithm_AESV2) { // AES encryption needs some 'salt' nkeylen += 4; nkey[m_keyLength+5] = 0x73; nkey[m_keyLength+6] = 0x41; nkey[m_keyLength+7] = 0x6c; nkey[m_keyLength+8] = 0x54; } GetMD5Binary(nkey, nkeylen, objkey); *pnKeyLen = (m_keyLength <= 11) ? m_keyLength+5 : 16; } PdfEncryptRC4Base::PdfEncryptRC4Base() { m_rc4 = new RC4CryptoEngine(); } PdfEncryptRC4Base::~PdfEncryptRC4Base() { delete m_rc4; } /** * RC4 is the standard encryption algorithm used in PDF format */ void PdfEncryptRC4Base::RC4(const unsigned char* key, int keylen, const unsigned char* textin, pdf_long textlen, unsigned char* textout, pdf_long textoutlen) { EVP_CIPHER_CTX* rc4 = m_rc4->getEngine(); if(textlen != textoutlen) PODOFO_RAISE_ERROR_INFO( ePdfError_InternalLogic, "Error initializing RC4 encryption engine" ); // Don't set the key because we will modify the parameters int status = EVP_EncryptInit_ex(rc4, EVP_rc4(), NULL, NULL, NULL); if(status != 1) PODOFO_RAISE_ERROR_INFO( ePdfError_InternalLogic, "Error initializing RC4 encryption engine" ); status = EVP_CIPHER_CTX_set_key_length(rc4, keylen); if(status != 1) PODOFO_RAISE_ERROR_INFO( ePdfError_InternalLogic, "Error initializing RC4 encryption engine" ); // We finished modifying parameters so now we can set the key status = EVP_EncryptInit_ex(rc4, NULL, NULL, key, NULL); if(status != 1) PODOFO_RAISE_ERROR_INFO( ePdfError_InternalLogic, "Error initializing RC4 encryption engine" ); int dataOutMoved; status = EVP_EncryptUpdate(rc4, textout, &dataOutMoved, textin, textlen); if(status != 1) PODOFO_RAISE_ERROR_INFO( ePdfError_InternalLogic, "Error RC4-encrypting data" ); status = EVP_EncryptFinal_ex(rc4, &textout[dataOutMoved], &dataOutMoved); if(status != 1) PODOFO_RAISE_ERROR_INFO( ePdfError_InternalLogic, "Error RC4-encrypting data" ); } void PdfEncryptMD5Base::GetMD5Binary(const unsigned char* data, int length, unsigned char* digest) { int status; MD5_CTX ctx; status = MD5_Init(&ctx); if(status != 1) PODOFO_RAISE_ERROR_INFO( ePdfError_InternalLogic, "Error initializing MD5 hashing engine" ); status = MD5_Update(&ctx, data, length); if(status != 1) PODOFO_RAISE_ERROR_INFO( ePdfError_InternalLogic, "Error MD5-hashing data" ); status = MD5_Final(digest,&ctx); if(status != 1) PODOFO_RAISE_ERROR_INFO( ePdfError_InternalLogic, "Error MD5-hashing data" ); } void PdfEncryptMD5Base::GenerateInitialVector(unsigned char iv[AES_IV_LENGTH]) { GetMD5Binary(reinterpret_cast(m_documentId.c_str()), static_cast(m_documentId.length()), iv); } PdfString PdfEncryptMD5Base::GetMD5String( const unsigned char* pBuffer, int nLength ) { char data[MD5_DIGEST_LENGTH]; GetMD5Binary( pBuffer, nLength, reinterpret_cast(data) ); return PdfString( data, MD5_DIGEST_LENGTH, true ); } void PdfEncryptMD5Base::CreateEncryptionDictionary( PdfDictionary & rDictionary ) const { rDictionary.AddKey( PdfName("Filter"), PdfName("Standard") ); if(m_eAlgorithm == ePdfEncryptAlgorithm_AESV2 || !m_bEncryptMetadata) { PdfDictionary cf; PdfDictionary stdCf; if(m_eAlgorithm == ePdfEncryptAlgorithm_RC4V2) stdCf.AddKey( PdfName("CFM"), PdfName("V2") ); else stdCf.AddKey( PdfName("CFM"), PdfName("AESV2") ); stdCf.AddKey( PdfName("Length"), static_cast(PODOFO_LL_LITERAL(16)) ); rDictionary.AddKey( PdfName("O"), PdfString( reinterpret_cast(this->GetOValue()), 32, true ) ); rDictionary.AddKey( PdfName("U"), PdfString( reinterpret_cast(this->GetUValue()), 32, true ) ); stdCf.AddKey( PdfName("AuthEvent"), PdfName("DocOpen") ); cf.AddKey( PdfName("StdCF"), stdCf ); rDictionary.AddKey( PdfName("CF"), cf ); rDictionary.AddKey( PdfName("StrF"), PdfName("StdCF") ); rDictionary.AddKey( PdfName("StmF"), PdfName("StdCF") ); rDictionary.AddKey( PdfName("V"), static_cast(PODOFO_LL_LITERAL(4)) ); rDictionary.AddKey( PdfName("R"), static_cast(PODOFO_LL_LITERAL(4)) ); rDictionary.AddKey( PdfName("Length"), static_cast(PODOFO_LL_LITERAL(128)) ); if(!m_bEncryptMetadata) rDictionary.AddKey( PdfName("EncryptMetadata"), PdfVariant( false ) ); } else if(m_eAlgorithm == ePdfEncryptAlgorithm_RC4V1) { rDictionary.AddKey( PdfName("V"), static_cast(PODOFO_LL_LITERAL(1)) ); // Can be 2 or 3 rDictionary.AddKey( PdfName("R"), static_cast(m_rValue) ); } else if(m_eAlgorithm == ePdfEncryptAlgorithm_RC4V2) { rDictionary.AddKey( PdfName("V"), static_cast(PODOFO_LL_LITERAL(2)) ); rDictionary.AddKey( PdfName("R"), static_cast(PODOFO_LL_LITERAL(3)) ); rDictionary.AddKey( PdfName("Length"), PdfVariant( static_cast(m_eKeyLength) ) ); } rDictionary.AddKey( PdfName("O"), PdfString( reinterpret_cast(this->GetOValue()), 32, true ) ); rDictionary.AddKey( PdfName("U"), PdfString( reinterpret_cast(this->GetUValue()), 32, true ) ); rDictionary.AddKey( PdfName("P"), PdfVariant( static_cast(this->GetPValue()) ) ); } void PdfEncryptRC4::GenerateEncryptionKey(const PdfString & documentId) { unsigned char userpswd[32]; unsigned char ownerpswd[32]; // Pad passwords PadPassword( m_userPass, userpswd ); PadPassword( m_ownerPass, ownerpswd ); // Compute O value ComputeOwnerKey(userpswd, ownerpswd, m_keyLength, m_rValue, false, m_oValue); // Compute encryption key and U value m_documentId = std::string( documentId.GetString(), documentId.GetLength() ); ComputeEncryptionKey(m_documentId, userpswd, m_oValue, m_pValue, m_eKeyLength, m_rValue, m_uValue, m_bEncryptMetadata); } bool PdfEncryptRC4::Authenticate( const std::string & password, const PdfString & documentId ) { bool ok = false; m_documentId = std::string( documentId.GetString(), documentId.GetLength() ); // Pad password unsigned char userKey[32]; unsigned char pswd[32]; PadPassword( password, pswd ); // Check password: 1) as user password, 2) as owner password ComputeEncryptionKey(m_documentId, pswd, m_oValue, m_pValue, m_eKeyLength, m_rValue, userKey, m_bEncryptMetadata); ok = CheckKey(userKey, m_uValue); if (!ok) { unsigned char userpswd[32]; ComputeOwnerKey( m_oValue, pswd, m_keyLength, m_rValue, true, userpswd ); ComputeEncryptionKey( m_documentId, userpswd, m_oValue, m_pValue, m_eKeyLength, m_rValue, userKey, m_bEncryptMetadata ); ok = CheckKey( userKey, m_uValue ); if( ok ) m_ownerPass = password; } else m_userPass = password; return ok; } pdf_long PdfEncryptRC4::CalculateStreamOffset() const { return 0; } pdf_long PdfEncryptRC4::CalculateStreamLength(pdf_long length) const { return length; } void PdfEncryptRC4::Encrypt(const unsigned char* inStr, pdf_long inLen, unsigned char* outStr, pdf_long outLen) const { unsigned char objkey[MD5_DIGEST_LENGTH]; int keylen; CreateObjKey( objkey, &keylen ); const_cast(this)->RC4(objkey, keylen, inStr, inLen, outStr, outLen); } void PdfEncryptRC4::Decrypt(const unsigned char* inStr, pdf_long inLen, unsigned char* outStr, pdf_long &outLen) const { Encrypt(inStr, inLen, outStr, outLen); } PdfInputStream* PdfEncryptRC4::CreateEncryptionInputStream( PdfInputStream* pInputStream ) { unsigned char objkey[MD5_DIGEST_LENGTH]; int keylen; this->CreateObjKey( objkey, &keylen ); return new PdfRC4InputStream( pInputStream, m_rc4key, m_rc4last, objkey, keylen ); } PdfEncryptRC4::PdfEncryptRC4(PdfString oValue, PdfString uValue, int pValue, int rValue, EPdfEncryptAlgorithm eAlgorithm, long length, bool encryptMetadata) { m_pValue = pValue; m_rValue = rValue; m_eAlgorithm = eAlgorithm; m_eKeyLength = static_cast(length); m_keyLength = length/8; m_bEncryptMetadata = encryptMetadata; memcpy( m_oValue, oValue.GetString(), 32 ); memcpy( m_uValue, uValue.GetString(), 32 ); // Init buffers memset(m_rc4key, 0, 16); memset(m_rc4last, 0, 256); memset(m_encryptionKey, 0, 32); } PdfEncryptRC4::PdfEncryptRC4( const std::string & userPassword, const std::string & ownerPassword, int protection, EPdfEncryptAlgorithm eAlgorithm, EPdfKeyLength eKeyLength ) { // setup object int keyLength = static_cast(eKeyLength); m_userPass = userPassword; m_ownerPass = ownerPassword; m_eAlgorithm = eAlgorithm; m_eKeyLength = eKeyLength; switch (eAlgorithm) { case ePdfEncryptAlgorithm_RC4V2: keyLength = keyLength - keyLength % 8; keyLength = (keyLength >= 40) ? ((keyLength <= 128) ? keyLength : 128) : 40; m_rValue = 3; m_keyLength = keyLength / 8; break; case ePdfEncryptAlgorithm_RC4V1: default: m_rValue = 2; m_keyLength = 40 / 8; break; case ePdfEncryptAlgorithm_AESV2: #ifdef PODOFO_HAVE_LIBIDN case ePdfEncryptAlgorithm_AESV3: #endif // PODOFO_HAVE_LIBIDN break; } // Init buffers memset(m_rc4key, 0, 16); memset(m_oValue, 0, 48); memset(m_uValue, 0, 48); memset(m_rc4last, 0, 256); memset(m_encryptionKey, 0, 32); // Compute P value m_pValue = PERMS_DEFAULT | protection; } PdfOutputStream* PdfEncryptRC4::CreateEncryptionOutputStream( PdfOutputStream* pOutputStream ) { unsigned char objkey[MD5_DIGEST_LENGTH]; int keylen; this->CreateObjKey( objkey, &keylen ); return new PdfRC4OutputStream( pOutputStream, m_rc4key, m_rc4last, objkey, keylen ); } PdfEncryptAESBase::PdfEncryptAESBase() { m_aes = new AESCryptoEngine(); } PdfEncryptAESBase::~PdfEncryptAESBase() { delete m_aes; } void PdfEncryptAESBase::BaseDecrypt(const unsigned char* key, int keyLen, const unsigned char* iv, const unsigned char* textin, pdf_long textlen, unsigned char* textout, pdf_long &outLen ) { if ((textlen % 16) != 0) PODOFO_RAISE_ERROR_INFO( ePdfError_InternalLogic, "Error AES-decryption data length not a multiple of 16" ); EVP_CIPHER_CTX* aes = m_aes->getEngine(); int status; if(keyLen == PdfEncrypt::ePdfKeyLength_128/8) status = EVP_DecryptInit_ex(aes, EVP_aes_128_cbc(), NULL, key, iv); #ifdef PODOFO_HAVE_LIBIDN else if (keyLen == PdfEncrypt::ePdfKeyLength_256/8) status = EVP_DecryptInit_ex(aes, EVP_aes_256_cbc(), NULL, key, iv); #endif else PODOFO_RAISE_ERROR_INFO( ePdfError_InternalLogic, "Invalid AES key length" ); if(status != 1) PODOFO_RAISE_ERROR_INFO( ePdfError_InternalLogic, "Error initializing AES decryption engine" ); int dataOutMoved; status = EVP_DecryptUpdate(aes, textout, &dataOutMoved, textin, textlen); outLen = dataOutMoved; if(status != 1) PODOFO_RAISE_ERROR_INFO( ePdfError_InternalLogic, "Error AES-decryption data" ); status = EVP_DecryptFinal_ex(aes, textout + outLen, &dataOutMoved); outLen += dataOutMoved; if(status != 1) PODOFO_RAISE_ERROR_INFO( ePdfError_InternalLogic, "Error AES-decryption data final" ); } void PdfEncryptAESBase::BaseEncrypt(const unsigned char* key, int keyLen, const unsigned char* iv, const unsigned char* textin, pdf_long textlen, unsigned char* textout, pdf_long ) // To avoid Wunused-parameter { EVP_CIPHER_CTX* aes = m_aes->getEngine(); int status; if(keyLen == PdfEncrypt::ePdfKeyLength_128/8) status = EVP_EncryptInit_ex(aes, EVP_aes_128_cbc(), NULL, key, iv); #ifdef PODOFO_HAVE_LIBIDN else if (keyLen == PdfEncrypt::ePdfKeyLength_256/8) status = EVP_EncryptInit_ex(aes, EVP_aes_256_cbc(), NULL, key, iv); #endif else PODOFO_RAISE_ERROR_INFO( ePdfError_InternalLogic, "Invalid AES key length" ); if(status != 1) PODOFO_RAISE_ERROR_INFO( ePdfError_InternalLogic, "Error initializing AES encryption engine" ); int dataOutMoved; status = EVP_EncryptUpdate(aes, textout, &dataOutMoved, textin, textlen); if(status != 1) PODOFO_RAISE_ERROR_INFO( ePdfError_InternalLogic, "Error AES-encrypting data" ); status = EVP_EncryptFinal_ex(aes, &textout[dataOutMoved], &dataOutMoved); if(status != 1) PODOFO_RAISE_ERROR_INFO( ePdfError_InternalLogic, "Error AES-encrypting data" ); } void PdfEncryptAESV2::GenerateEncryptionKey(const PdfString & documentId) { unsigned char userpswd[32]; unsigned char ownerpswd[32]; // Pad passwords PadPassword( m_userPass, userpswd ); PadPassword( m_ownerPass, ownerpswd ); // Compute O value ComputeOwnerKey(userpswd, ownerpswd, m_keyLength, m_rValue, false, m_oValue); // Compute encryption key and U value m_documentId = std::string( documentId.GetString(), documentId.GetLength() ); ComputeEncryptionKey(m_documentId, userpswd, m_oValue, m_pValue, m_eKeyLength, m_rValue, m_uValue, m_bEncryptMetadata); } bool PdfEncryptAESV2::Authenticate( const std::string & password, const PdfString & documentId ) { bool ok = false; m_documentId = std::string( documentId.GetString(), documentId.GetLength() ); // Pad password unsigned char userKey[32]; unsigned char pswd[32]; PadPassword( password, pswd ); // Check password: 1) as user password, 2) as owner password ComputeEncryptionKey(m_documentId, pswd, m_oValue, m_pValue, m_eKeyLength, m_rValue, userKey, m_bEncryptMetadata); ok = CheckKey(userKey, m_uValue); if (!ok) { unsigned char userpswd[32]; ComputeOwnerKey( m_oValue, pswd, m_keyLength, m_rValue, true, userpswd ); ComputeEncryptionKey( m_documentId, userpswd, m_oValue, m_pValue, m_eKeyLength, m_rValue, userKey, m_bEncryptMetadata ); ok = CheckKey( userKey, m_uValue ); if( ok ) m_ownerPass = password; } else m_userPass = password; return ok; } pdf_long PdfEncryptAESV2::CalculateStreamOffset() const { return AES_IV_LENGTH; } void PdfEncryptAESV2::Encrypt(const unsigned char* inStr, pdf_long inLen, unsigned char* outStr, pdf_long outLen) const { unsigned char objkey[MD5_DIGEST_LENGTH]; int keylen; CreateObjKey( objkey, &keylen ); pdf_long offset = CalculateStreamOffset(); const_cast(this)->GenerateInitialVector(outStr); const_cast(this)->BaseEncrypt(objkey, keylen, outStr, inStr, inLen, &outStr[offset], outLen-offset); } void PdfEncryptAESV2::Decrypt(const unsigned char* inStr, pdf_long inLen, unsigned char* outStr, pdf_long &outLen) const { unsigned char objkey[MD5_DIGEST_LENGTH]; int keylen; CreateObjKey( objkey, &keylen ); pdf_long offset = CalculateStreamOffset(); if( inLen <= offset ) { // Is empty outLen = 0; return; } const_cast(this)->BaseDecrypt(objkey, keylen, inStr, &inStr[offset], inLen-offset, outStr, outLen); } PdfEncryptAESV2::PdfEncryptAESV2( const std::string & userPassword, const std::string & ownerPassword, int protection) : PdfEncryptAESBase() { // setup object m_userPass = userPassword; m_ownerPass = ownerPassword; m_eAlgorithm = ePdfEncryptAlgorithm_AESV2; m_rValue = 4; m_eKeyLength = ePdfKeyLength_128; m_keyLength = ePdfKeyLength_128 / 8; // Init buffers memset(m_rc4key, 0 ,16); memset(m_rc4last, 0 ,256); memset(m_oValue, 0 ,48); memset(m_uValue, 0 ,48); memset(m_encryptionKey, 0 ,32); // Compute P value m_pValue = PERMS_DEFAULT | protection; } PdfEncryptAESV2::PdfEncryptAESV2(PdfString oValue, PdfString uValue, int pValue, bool encryptMetadata) : PdfEncryptAESBase() { m_pValue = pValue; m_eAlgorithm = ePdfEncryptAlgorithm_AESV2; m_eKeyLength = ePdfKeyLength_128; m_keyLength = ePdfKeyLength_128 / 8; m_rValue = 4; m_bEncryptMetadata = encryptMetadata; memcpy( m_oValue, oValue.GetString(), 32 ); memcpy( m_uValue, uValue.GetString(), 32 ); // Init buffers memset(m_rc4key, 0 ,16); memset(m_rc4last, 0 ,256); memset(m_encryptionKey, 0 ,32); } pdf_long PdfEncryptAESV2::CalculateStreamLength(pdf_long length) const { pdf_long realLength = ((length + 15) & ~15) + AES_IV_LENGTH; if (length % 16 == 0) { realLength += 16; } return realLength; } PdfInputStream* PdfEncryptAESV2::CreateEncryptionInputStream( PdfInputStream* pInputStream ) { unsigned char objkey[MD5_DIGEST_LENGTH]; int keylen; this->CreateObjKey( objkey, &keylen ); return new PdfAESInputStream( pInputStream, objkey, keylen ); } PdfOutputStream* PdfEncryptAESV2::CreateEncryptionOutputStream( PdfOutputStream* ) { /*unsigned char objkey[MD5_DIGEST_LENGTH]; int keylen; this->CreateObjKey( objkey, &keylen );*/ PODOFO_RAISE_ERROR_INFO( ePdfError_InternalLogic, "CreateEncryptionOutputStream does not yet support AESV2" ); } #ifdef PODOFO_HAVE_LIBIDN PdfEncryptSHABase::PdfEncryptSHABase( const PdfEncrypt & rhs ) : PdfEncrypt(rhs) { const PdfEncrypt* ptr = &rhs; memcpy( m_uValue, rhs.GetUValue(), sizeof(unsigned char) * 48 ); memcpy( m_oValue, rhs.GetOValue(), sizeof(unsigned char) * 48 ); memcpy( m_encryptionKey, rhs.GetEncryptionKey(), sizeof(unsigned char) * 32 ); memcpy( m_permsValue, static_cast(ptr)->m_permsValue, sizeof(unsigned char) * 16 ); memcpy( m_ueValue, static_cast(ptr)->m_ueValue, sizeof(unsigned char) * 32 ); memcpy( m_oeValue, static_cast(ptr)->m_oeValue, sizeof(unsigned char) * 32 ); } void PdfEncryptSHABase::ComputeUserKey(const unsigned char * userpswd, int len) { // Generate User Salts unsigned char vSalt[8]; unsigned char kSalt[8]; for(int i=0; i< 8 ; i++) { vSalt[i] = rand()%255; kSalt[i] = rand()%255; } // Generate hash for U unsigned char hashValue[32]; SHA256_CTX context; SHA256_Init(&context); SHA256_Update(&context, userpswd, len); SHA256_Update(&context, vSalt, 8); SHA256_Final(hashValue, &context); // U = hash + validation salt + key salt memcpy(m_uValue, hashValue, 32); memcpy(m_uValue+32, vSalt, 8); memcpy(m_uValue+32+8, kSalt, 8); // Generate hash for UE SHA256_Init(&context); SHA256_Update(&context, userpswd, len); SHA256_Update(&context, kSalt, 8); SHA256_Final(hashValue, &context); // UE = AES-256 encoded file encryption key with key=hash // CBC mode, no padding, init vector=0 EVP_CIPHER_CTX aes; EVP_CIPHER_CTX_init(&aes); int status = EVP_EncryptInit_ex(&aes, EVP_aes_256_cbc(), NULL, hashValue, NULL); if(status != 1) PODOFO_RAISE_ERROR_INFO( ePdfError_InternalLogic, "Error initializing AES encryption engine" ); EVP_CIPHER_CTX_set_padding(&aes, 0); // disable padding int dataOutMoved; status = EVP_EncryptUpdate(&aes, m_ueValue, &dataOutMoved, m_encryptionKey, m_keyLength); if(status != 1) PODOFO_RAISE_ERROR_INFO( ePdfError_InternalLogic, "Error AES-encrypting data" ); status = EVP_EncryptFinal_ex(&aes, &m_ueValue[dataOutMoved], &dataOutMoved); if(status != 1) PODOFO_RAISE_ERROR_INFO( ePdfError_InternalLogic, "Error AES-encrypting data" ); EVP_CIPHER_CTX_cleanup(&aes); } void PdfEncryptSHABase::ComputeOwnerKey(const unsigned char * ownerpswd, int len) { // Generate User Salts unsigned char vSalt[8]; unsigned char kSalt[8]; for(int i=0; i< 8 ; i++) { vSalt[i] = rand()%255; kSalt[i] = rand()%255; } // Generate hash for O unsigned char hashValue[32]; SHA256_CTX context; SHA256_Init(&context); SHA256_Update(&context, ownerpswd, len); SHA256_Update(&context, vSalt, 8); SHA256_Update(&context, m_uValue, 48); SHA256_Final(hashValue, &context); // O = hash + validation salt + key salt memcpy(m_oValue, hashValue, 32); memcpy(m_oValue+32, vSalt, 8); memcpy(m_oValue+32+8, kSalt, 8); // Generate hash for OE SHA256_Init(&context); SHA256_Update(&context, ownerpswd, len); SHA256_Update(&context, kSalt, 8); SHA256_Update(&context, m_uValue, 48); SHA256_Final(hashValue, &context); // OE = AES-256 encoded file encryption key with key=hash // CBC mode, no padding, init vector=0 EVP_CIPHER_CTX aes; EVP_CIPHER_CTX_init(&aes); int status = EVP_EncryptInit_ex(&aes, EVP_aes_256_cbc(), NULL, hashValue, NULL); if(status != 1) PODOFO_RAISE_ERROR_INFO( ePdfError_InternalLogic, "Error initializing AES encryption engine" ); EVP_CIPHER_CTX_set_padding(&aes, 0); // disable padding int dataOutMoved; status = EVP_EncryptUpdate(&aes, m_oeValue, &dataOutMoved, m_encryptionKey, m_keyLength); if(status != 1) PODOFO_RAISE_ERROR_INFO( ePdfError_InternalLogic, "Error AES-encrypting data" ); status = EVP_EncryptFinal_ex(&aes, &m_oeValue[dataOutMoved], &dataOutMoved); if(status != 1) PODOFO_RAISE_ERROR_INFO( ePdfError_InternalLogic, "Error AES-encrypting data" ); EVP_CIPHER_CTX_cleanup(&aes); } void PdfEncryptSHABase::PreprocessPassword( const std::string &password, unsigned char* outBuf, int &len) { char* password_sasl; if (stringprep_profile(password.c_str(), &password_sasl, "SASLprep", STRINGPREP_NO_UNASSIGNED) != STRINGPREP_OK) { PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidPassword, "Error processing password through SASLprep" ); } int l = strlen(password_sasl); len = l > 127 ? 127 : l; memcpy(outBuf, password_sasl, len); free(password_sasl); } void PdfEncryptSHABase::ComputeEncryptionKey() { // Seed once for all srand ( time(NULL) ); for(int i=0; i< m_keyLength ; i++) m_encryptionKey[i] = rand()%255; } bool PdfEncryptSHABase::Authenticate(const std::string& documentID, const std::string& password, const std::string& uValue, const std::string& ueValue, const std::string& oValue, const std::string& oeValue, int pValue, const std::string& permsValue, int lengthValue, int rValue) { m_pValue = pValue; m_keyLength = lengthValue / 8; m_rValue = rValue; memcpy(m_uValue, uValue.c_str(), 48); memcpy(m_ueValue, ueValue.c_str(), 32); memcpy(m_oValue, oValue.c_str(), 48); memcpy(m_oeValue, oeValue.c_str(), 32); memcpy(m_permsValue, permsValue.c_str(), 16); return Authenticate(password, documentID); } void PdfEncryptSHABase::GenerateInitialVector(unsigned char iv[AES_IV_LENGTH]) { for (int i=0; i(PODOFO_LL_LITERAL(5)) ); rDictionary.AddKey( PdfName("R"), static_cast(PODOFO_LL_LITERAL(5)) ); rDictionary.AddKey( PdfName("Length"), static_cast(PODOFO_LL_LITERAL(256)) ); stdCf.AddKey( PdfName("CFM"), PdfName("AESV3") ); stdCf.AddKey( PdfName("Length"), static_cast(PODOFO_LL_LITERAL(32)) ); rDictionary.AddKey( PdfName("O"), PdfString( reinterpret_cast(this->GetOValue()), 48, true ) ); rDictionary.AddKey( PdfName("OE"), PdfString( reinterpret_cast(this->GetOEValue()), 32, true ) ); rDictionary.AddKey( PdfName("U"), PdfString( reinterpret_cast(this->GetUValue()), 48, true ) ); rDictionary.AddKey( PdfName("UE"), PdfString( reinterpret_cast(this->GetUEValue()), 32, true ) ); rDictionary.AddKey( PdfName("Perms"), PdfString( reinterpret_cast(this->GetPermsValue()), 16, true ) ); stdCf.AddKey( PdfName("AuthEvent"), PdfName("DocOpen") ); cf.AddKey( PdfName("StdCF"), stdCf ); rDictionary.AddKey( PdfName("CF"), cf ); rDictionary.AddKey( PdfName("StrF"), PdfName("StdCF") ); rDictionary.AddKey( PdfName("StmF"), PdfName("StdCF") ); rDictionary.AddKey( PdfName("P"), PdfVariant( static_cast(this->GetPValue()) ) ); } void PdfEncryptAESV3::GenerateEncryptionKey(const PdfString &) { // Prepare passwords unsigned char userpswd[127]; unsigned char ownerpswd[127]; int userpswdLen; int ownerpswdLen; PreprocessPassword(m_userPass, userpswd, userpswdLen); PreprocessPassword(m_ownerPass, ownerpswd, ownerpswdLen); // Compute encryption key ComputeEncryptionKey(); // Compute U and UE values ComputeUserKey(userpswd, userpswdLen); // Compute O and OE value ComputeOwnerKey(ownerpswd, ownerpswdLen); // Compute Perms value unsigned char perms[16]; // First 4 bytes = 32bits permissions perms[3] = (m_pValue >> 24) & 0xff; perms[2] = (m_pValue >> 16) & 0xff; perms[1] = (m_pValue >> 8) & 0xff; perms[0] = m_pValue & 0xff; // Placeholder for future versions that may need 64-bit permissions perms[4] = 0xff; perms[5] = 0xff; perms[6] = 0xff; perms[7] = 0xff; // if EncryptMetadata is false, this value should be set to 'F' perms[8] = m_bEncryptMetadata ? 'T' : 'F'; // Next 3 bytes are mandatory perms[9] = 'a'; perms[10] = 'd'; perms[11] = 'b'; // Next 4 bytes are ignored perms[12] = 0; perms[13] = 0; perms[14] = 0; perms[15] = 0; // Encrypt Perms value EVP_CIPHER_CTX aes; EVP_CIPHER_CTX_init(&aes); int status = EVP_EncryptInit_ex(&aes, EVP_aes_256_ecb(), NULL, m_encryptionKey, NULL); if(status != 1) PODOFO_RAISE_ERROR_INFO( ePdfError_InternalLogic, "Error initializing AES encryption engine" ); EVP_CIPHER_CTX_set_padding(&aes, 0); // disable padding int dataOutMoved; status = EVP_EncryptUpdate(&aes, m_permsValue, &dataOutMoved, perms, 16); if(status != 1) PODOFO_RAISE_ERROR_INFO( ePdfError_InternalLogic, "Error AES-encrypting data" ); status = EVP_EncryptFinal_ex(&aes, &m_permsValue[dataOutMoved], &dataOutMoved); if(status != 1) PODOFO_RAISE_ERROR_INFO( ePdfError_InternalLogic, "Error AES-encrypting data" ); EVP_CIPHER_CTX_cleanup(&aes); } bool PdfEncryptAESV3::Authenticate( const std::string & password, const PdfString & ) { bool ok = false; // Prepare password unsigned char pswd_sasl[127]; int pswdLen; PreprocessPassword(password, pswd_sasl, pswdLen); // Test 1: is it the user key ? unsigned char hashValue[32]; SHA256_CTX context; SHA256_Init(&context); SHA256_Update(&context, pswd_sasl, pswdLen); // password SHA256_Update(&context, m_uValue + 32, 8); // user Validation Salt SHA256_Final(hashValue, &context); ok = CheckKey(hashValue, m_uValue); if(!ok) { // Test 2: is it the owner key ? SHA256_Init(&context); SHA256_Update(&context, pswd_sasl, pswdLen); // password SHA256_Update(&context, m_oValue + 32, 8); // owner Validation Salt SHA256_Update(&context, m_uValue, 48); // U string SHA256_Final(hashValue, &context); ok = CheckKey(hashValue, m_oValue); if(ok) { m_ownerPass = password; // ISO 32000: "Compute an intermediate owner key by computing the SHA-256 hash of // the UTF-8 password concatenated with the 8 bytes of owner Key Salt, concatenated with the 48-byte U string." SHA256_Init(&context); SHA256_Update(&context, pswd_sasl, pswdLen); // password SHA256_Update(&context, m_oValue + 40, 8); // owner Key Salt SHA256_Update(&context, m_uValue, 48); // U string SHA256_Final(hashValue, &context); // ISO 32000: "The 32-byte result is the key used to decrypt the 32-byte OE string using // AES-256 in CBC mode with no padding and an initialization vector of zero. // The 32-byte result is the file encryption key" EVP_CIPHER_CTX* aes = m_aes->getEngine(); EVP_DecryptInit_ex( aes, EVP_aes_256_cbc(), NULL, hashValue, 0 ); // iv zero EVP_CIPHER_CTX_set_padding( aes, 0 ); // no padding int lOutLen; EVP_DecryptUpdate( aes, m_encryptionKey, &lOutLen, m_oeValue, 32 ); } } else { m_userPass = password; // ISO 32000: "Compute an intermediate user key by computing the SHA-256 hash of // the UTF-8 password concatenated with the 8 bytes of user Key Salt" SHA256_Init(&context); SHA256_Update(&context, pswd_sasl, pswdLen); // password SHA256_Update(&context, m_uValue + 40, 8); // user Key Salt SHA256_Final(hashValue, &context); // ISO 32000: "The 32-byte result is the key used to decrypt the 32-byte UE string using // AES-256 in CBC mode with no padding and an initialization vector of zero. // The 32-byte result is the file encryption key" EVP_CIPHER_CTX* aes = m_aes->getEngine(); EVP_DecryptInit_ex( aes, EVP_aes_256_cbc(), NULL, hashValue, 0 ); // iv zero EVP_CIPHER_CTX_set_padding( aes, 0 ); // no padding int lOutLen; EVP_DecryptUpdate( aes, m_encryptionKey, &lOutLen, m_ueValue, 32 ); } // TODO Validate permissions (or not...) return ok; } pdf_long PdfEncryptAESV3::CalculateStreamOffset() const { return AES_IV_LENGTH; } void PdfEncryptAESV3::Encrypt(const unsigned char* inStr, pdf_long inLen, unsigned char* outStr, pdf_long outLen) const { pdf_long offset = CalculateStreamOffset(); const_cast(this)->GenerateInitialVector(outStr); const_cast(this)->BaseEncrypt(const_cast(m_encryptionKey), m_keyLength, outStr, inStr, inLen, &outStr[offset], outLen-offset); } void PdfEncryptAESV3::Decrypt(const unsigned char* inStr, pdf_long inLen, unsigned char* outStr, pdf_long &outLen) const { pdf_long offset = CalculateStreamOffset(); const_cast(this)->BaseDecrypt(const_cast(m_encryptionKey), m_keyLength, inStr, &inStr[offset], inLen-offset, outStr, outLen); } PdfEncryptAESV3::PdfEncryptAESV3( const std::string & userPassword, const std::string & ownerPassword, int protection) : PdfEncryptAESBase() { // setup object m_userPass = userPassword; m_ownerPass = ownerPassword; m_eAlgorithm = ePdfEncryptAlgorithm_AESV3; m_rValue = 5; m_eKeyLength = ePdfKeyLength_256; m_keyLength = ePdfKeyLength_256 / 8; // Init buffers memset(m_oValue, 0 ,48); memset(m_uValue, 0 ,48); memset(m_encryptionKey, 0 ,32); memset(m_ueValue, 0 ,32); memset(m_oeValue, 0 ,32); // Compute P value m_pValue = PERMS_DEFAULT | protection; } PdfEncryptAESV3::PdfEncryptAESV3(PdfString oValue,PdfString oeValue, PdfString uValue, PdfString ueValue, int pValue, PdfString permsValue) : PdfEncryptAESBase() { m_pValue = pValue; m_eAlgorithm = ePdfEncryptAlgorithm_AESV3; m_eKeyLength = ePdfKeyLength_256; m_keyLength = ePdfKeyLength_256 / 8; m_rValue = 5; memcpy( m_oValue, oValue.GetString(), 48 ); memcpy( m_oeValue, oeValue.GetString(), 32 ); memcpy( m_uValue, uValue.GetString(), 48 ); memcpy( m_ueValue, ueValue.GetString(), 32 ); memcpy( m_permsValue, permsValue.GetString(), 16 ); memset(m_encryptionKey, 0 ,32); } pdf_long PdfEncryptAESV3::CalculateStreamLength(pdf_long length) const { pdf_long realLength = ((length + 15) & ~15) + AES_IV_LENGTH; if (length % 16 == 0) { realLength += 16; } return realLength; } PdfInputStream* PdfEncryptAESV3::CreateEncryptionInputStream( PdfInputStream* pInputStream ) { return new PdfAESInputStream( pInputStream, m_encryptionKey, 32 ); } PdfOutputStream* PdfEncryptAESV3::CreateEncryptionOutputStream( PdfOutputStream* ) { PODOFO_RAISE_ERROR_INFO( ePdfError_InternalLogic, "CreateEncryptionOutputStream does not yet support AESV3" ); } #endif // PODOFO_HAVE_LIBIDN #else // PODOFO_HAVE_OPENSSL // ---------------- // MD5 by RSA // ---------------- // C headers for MD5 #include #include #include #include #define MD5_HASHBYTES 16 /// Structure representing an MD5 context while ecrypting. (For internal use only) typedef struct MD5Context { unsigned int buf[4]; unsigned int bits[2]; unsigned char in[64]; } MD5_CTX; static void MD5Init(MD5_CTX *context); static void MD5Update(MD5_CTX *context, unsigned char const *buf, unsigned len); static void MD5Final(unsigned char digest[MD5_HASHBYTES], MD5_CTX *context); static void MD5Transform(unsigned int buf[4], unsigned int const in[16]); /* * Final wrapup - pad to 64-byte boundary with the bit pattern * 1 0* (64-bit count of bits processed, MSB-first) */ static void MD5Final(unsigned char digest[MD5_HASHBYTES], MD5_CTX *ctx) { unsigned count; unsigned char *p; /* Compute number of bytes mod 64 */ count = (ctx->bits[0] >> 3) & 0x3F; /* Set the first char of padding to 0x80. This is safe since there is always at least one byte free */ p = ctx->in + count; *p++ = 0x80; /* Bytes of padding needed to make 64 bytes */ count = 64 - 1 - count; /* Pad out to 56 mod 64 */ if (count < 8) { /* Two lots of padding: Pad the first block to 64 bytes */ memset(p, 0, count); MD5Transform(ctx->buf, reinterpret_cast(ctx->in)); /* Now fill the next block with 56 bytes */ memset(ctx->in, 0, 56); } else { /* Pad block to 56 bytes */ memset(p, 0, count - 8); } /* Append length in bits and transform */ reinterpret_cast(ctx->in)[14] = ctx->bits[0]; reinterpret_cast(ctx->in)[15] = ctx->bits[1]; MD5Transform(ctx->buf, reinterpret_cast(ctx->in)); memcpy(digest, ctx->buf, MD5_HASHBYTES); memset( reinterpret_cast(ctx), 0, sizeof(ctx)); /* In case it's sensitive */ } static void MD5Init(MD5_CTX *ctx) { ctx->buf[0] = 0x67452301; ctx->buf[1] = 0xefcdab89; ctx->buf[2] = 0x98badcfe; ctx->buf[3] = 0x10325476; ctx->bits[0] = 0; ctx->bits[1] = 0; } static void MD5Update(MD5_CTX *ctx, unsigned char const *buf, unsigned len) { unsigned int t; /* Update bitcount */ t = ctx->bits[0]; if ((ctx->bits[0] = t + ( static_cast(len) << 3)) < t) { ctx->bits[1]++; /* Carry from low to high */ } ctx->bits[1] += len >> 29; t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ /* Handle any leading odd-sized chunks */ if (t) { unsigned char *p = static_cast(ctx->in) + t; t = 64 - t; if (len < t) { memcpy(p, buf, len); return; } memcpy(p, buf, t); MD5Transform(ctx->buf, reinterpret_cast(ctx->in)); buf += t; len -= t; } /* Process data in 64-byte chunks */ while (len >= 64) { memcpy(ctx->in, buf, 64); MD5Transform(ctx->buf, reinterpret_cast(ctx->in)); buf += 64; len -= 64; } /* Handle any remaining bytes of data. */ memcpy(ctx->in, buf, len); } /* #define F1(x, y, z) (x & y | ~x & z) */ #define F1(x, y, z) (z ^ (x & (y ^ z))) #define F2(x, y, z) F1(z, x, y) #define F3(x, y, z) (x ^ y ^ z) #define F4(x, y, z) (y ^ (x | ~z)) /* This is the central step in the MD5 algorithm. */ #define MD5STEP(f, w, x, y, z, data, s) \ ( w += f(x, y, z) + data, w = w<>(32-s), w += x ) /* * The core of the MD5 algorithm, this alters an existing MD5 hash to * reflect the addition of 16 longwords of new data. MD5Update blocks * the data and converts bytes into longwords for this routine. */ static void MD5Transform(unsigned int buf[4], unsigned int const in[16]) { register unsigned int a, b, c, d; a = buf[0]; b = buf[1]; c = buf[2]; d = buf[3]; MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); buf[0] += a; buf[1] += b; buf[2] += c; buf[3] += d; } PdfEncrypt * PdfEncrypt::CreatePdfEncrypt( const std::string & userPassword, const std::string & ownerPassword, int protection, EPdfEncryptAlgorithm eAlgorithm, EPdfKeyLength eKeyLength ) { PODOFO_RAISE_ERROR_INFO( ePdfError_NotCompiled, "PdfEncrypt::CreatePdfEncrypt: Encryption support was disabled during compile time" ); return NULL; } PdfEncrypt* PdfEncrypt::CreatePdfEncrypt( const PdfObject* pObject ) { PODOFO_RAISE_ERROR_INFO( ePdfError_NotCompiled, "PdfEncrypt::CreatePdfEncrypt: Encryption support was disabled during compile time" ); return NULL; } PdfEncrypt * PdfEncrypt::CreatePdfEncrypt(const PdfEncrypt & rhs ) { PODOFO_RAISE_ERROR_INFO( ePdfError_NotCompiled, "PdfEncrypt::CreatePdfEncrypt: Encryption support was disabled during compile time" ); return NULL; } PdfEncrypt::~PdfEncrypt() { } void PdfEncryptMD5Base::GetMD5Binary(const unsigned char* data, int length, unsigned char* digest) { MD5_CTX ctx; MD5Init(&ctx); MD5Update(&ctx, data, length); MD5Final(digest,&ctx); } PdfString PdfEncryptMD5Base::GetMD5String( const unsigned char* pBuffer, int nLength ) { // Will be called by PdfWriter::CreateFileIdentifier, even without encryption, // so implement it with above c-functions char data[MD5_HASHBYTES]; PdfEncryptMD5Base::GetMD5Binary( pBuffer, nLength, reinterpret_cast(data) ); return PdfString( data, MD5_HASHBYTES, true ); } #endif // PODOFO_HAVE_OPENSSL } podofo-0.9.3/src/base/PdfString.cpp0000664000175000017500000011054112347313527016777 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2006 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfString.h" #include "PdfEncrypt.h" #include "PdfEncoding.h" #include "PdfEncodingFactory.h" #include "PdfFilter.h" #include "PdfTokenizer.h" #include "PdfOutputDevice.h" #include "PdfDefinesPrivate.h" #if defined(_AIX) || defined(__sun) #include #elif defined(__APPLE__) || defined(__linux) #include #elif defined(_WIN32) #include #endif #include #include #include namespace PoDoFo { namespace PdfStringNameSpace { static char g_StrEscMap[256] = { 0 }; // Generate the escape character map at runtime static const char* genStrEscMap() { const long lAllocLen = 256; char* map = static_cast(g_StrEscMap); memset( map, 0, sizeof(char) * lAllocLen ); map[static_cast('\n')] = 'n'; // Line feed (LF) map[static_cast('\r')] = 'r'; // Carriage return (CR) map[static_cast('\t')] = 't'; // Horizontal tab (HT) map[static_cast('\b')] = 'b'; // Backspace (BS) map[static_cast('\f')] = 'f'; // Form feed (FF) map[static_cast(')')] = ')'; map[static_cast('(')] = '('; map[static_cast('\\')] = '\\'; return map; } }; const char * const PdfString::m_escMap = PdfStringNameSpace::genStrEscMap(); const PdfString PdfString::StringNull = PdfString(); #ifdef _MSC_VER const char PdfString::s_pszUnicodeMarker[] = { static_cast(0xFE), static_cast(0xFF) }; #else const char PdfString::s_pszUnicodeMarker[] = { static_cast(0xFE), static_cast(0xFF) }; #endif const char* PdfString::s_pszUnicodeMarkerHex = "FEFF"; PdfString::PdfString() : m_bHex( false ), m_bUnicode( false ), m_pEncoding( NULL ) { } PdfString::PdfString( const std::string& sString, const PdfEncoding * const pEncoding ) : m_bHex( false ), m_bUnicode( false ), m_pEncoding( pEncoding ) { Init( sString.c_str(), sString.length() ); } PdfString::PdfString( const char* pszString, const PdfEncoding * const pEncoding ) : m_bHex( false ), m_bUnicode( false ), m_pEncoding( pEncoding ) { if( pszString ) Init( pszString, strlen( pszString ) ); } #if defined(_MSC_VER) && _MSC_VER <= 1200 // nicht fr Visualstudio 6 #else PdfString::PdfString( const wchar_t* pszString, pdf_long lLen ) { setFromWchar_t(pszString, lLen); } #endif void PdfString::setFromWchar_t(const wchar_t* pszString, pdf_long lLen ) { m_bHex = false; m_bUnicode = true; m_pEncoding = NULL; if( pszString ) { if (lLen == -1) { lLen = wcslen( pszString ); } if( sizeof(wchar_t) == 2 ) { // We have UTF16 lLen *= sizeof(wchar_t); m_buffer = PdfRefCountedBuffer( lLen + 2 ); memcpy( m_buffer.GetBuffer(), pszString, lLen ); m_buffer.GetBuffer()[lLen] = '\0'; m_buffer.GetBuffer()[lLen+1] = '\0'; // if the buffer is a UTF-16LE string // convert it to UTF-16BE #ifdef PODOFO_IS_LITTLE_ENDIAN SwapBytes( m_buffer.GetBuffer(), lLen ); #endif // PODOFO_IS_LITTLE_ENDIA } else { // Try to convert to UTF8 pdf_long lDest = 5 * lLen; // At max 5 bytes per UTF8 char char* pDest = static_cast(malloc( lDest )); size_t cnt = wcstombs(pDest, pszString, lDest); if( cnt != static_cast(-1) ) { // No error InitFromUtf8( reinterpret_cast(pDest), cnt ); free( pDest ); } else { free( pDest ); PdfError e( ePdfError_InternalLogic, __FILE__, __LINE__ ); e.SetErrorInformation( pszString ); throw e; } } } } PdfString::PdfString( const char* pszString, pdf_long lLen, bool bHex, const PdfEncoding * const pEncoding ) : m_bHex( bHex ), m_bUnicode( false ), m_pEncoding( pEncoding ) { if( pszString ) Init( pszString, lLen ); } PdfString::PdfString( const pdf_utf8* pszStringUtf8 ) : m_bHex( false ), m_bUnicode( true ), m_pEncoding( NULL ) { InitFromUtf8( pszStringUtf8, strlen( reinterpret_cast(pszStringUtf8) ) ); m_sUtf8 = reinterpret_cast(pszStringUtf8); } PdfString::PdfString( const pdf_utf8* pszStringUtf8, pdf_long lLen ) : m_bHex( false ), m_bUnicode( true ), m_pEncoding( NULL ) { InitFromUtf8( pszStringUtf8, lLen ); m_sUtf8.assign( reinterpret_cast(pszStringUtf8), lLen ); } PdfString::PdfString( const pdf_utf16be* pszStringUtf16 ) : m_bHex( false ), m_bUnicode( true ), m_pEncoding( NULL ) { pdf_long lBufLen = 0; const pdf_utf16be* pszCnt = pszStringUtf16; while( *pszCnt ) { ++pszCnt; ++lBufLen; } lBufLen *= sizeof(pdf_utf16be); m_buffer = PdfRefCountedBuffer( lBufLen + sizeof(pdf_utf16be) ); memcpy( m_buffer.GetBuffer(), reinterpret_cast(pszStringUtf16), lBufLen ); m_buffer.GetBuffer()[lBufLen] = '\0'; m_buffer.GetBuffer()[lBufLen+1] = '\0'; } PdfString::PdfString( const pdf_utf16be* pszStringUtf16, pdf_long lLen ) : m_bHex( false ), m_bUnicode( true ), m_pEncoding( NULL ) { pdf_long lBufLen = 0; const pdf_utf16be* pszCnt = pszStringUtf16; while( lLen-- ) { ++pszCnt; ++lBufLen; } lBufLen *= sizeof(pdf_utf16be); m_buffer = PdfRefCountedBuffer( lBufLen + sizeof(pdf_utf16be) ); memcpy( m_buffer.GetBuffer(), reinterpret_cast(pszStringUtf16), lBufLen ); m_buffer.GetBuffer()[lBufLen] = '\0'; m_buffer.GetBuffer()[lBufLen+1] = '\0'; } PdfString::PdfString( const PdfString & rhs ) : PdfDataType(), m_bHex( false ), m_bUnicode( false ), m_pEncoding( NULL ) { this->operator=( rhs ); } PdfString::~PdfString() { } void PdfString::SetHexData( const char* pszHex, pdf_long lLen, PdfEncrypt* pEncrypt ) { AssertMutable(); if( !pszHex ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } if( lLen == -1 ) lLen = strlen( pszHex ); // Allocate a buffer large enough for the hex decoded data // and the 2 terminating zeros m_buffer = PdfRefCountedBuffer( lLen % 2 ? ((lLen + 1) >> 1) + 2 : (lLen >> 1) + 2 ); m_bHex = true; char* pBuffer = m_buffer.GetBuffer(); char val; char cDecodedByte = 0; bool bLow = true; while( lLen-- ) { if( PdfTokenizer::IsWhitespace( *pszHex ) ) { ++pszHex; continue; } val = PdfTokenizer::GetHexValue( *pszHex ); if( bLow ) { cDecodedByte = (val & 0x0F); bLow = false; } else { cDecodedByte = ((cDecodedByte << 4) | val); bLow = true; *pBuffer++ = cDecodedByte; } ++pszHex; } if( !bLow ) { // an odd number of bytes was read, // so the last byte is 0 *pBuffer++ = cDecodedByte; } *pBuffer++ = '\0'; *pBuffer++ = '\0'; // If the allocated internal buffer is too big (e.g. because of whitespaces in the data) // copy to a smaller buffer so that PdfString::GetLength() will be correct lLen = pBuffer - m_buffer.GetBuffer(); if( static_cast(lLen) != m_buffer.GetSize() ) { PdfRefCountedBuffer temp( lLen ); memcpy( temp.GetBuffer(), m_buffer.GetBuffer(), lLen ); m_buffer = temp; } if( pEncrypt ) { pdf_long outBufferLen = m_buffer.GetSize() - 2 - pEncrypt->CalculateStreamOffset(); PdfRefCountedBuffer outBuffer(outBufferLen + 16 - (outBufferLen % 16)); pEncrypt->Decrypt( reinterpret_cast(m_buffer.GetBuffer()), static_cast(m_buffer.GetSize()-2), reinterpret_cast(outBuffer.GetBuffer()), outBufferLen); outBuffer.Resize(outBufferLen); // Replace buffer with decrypted value m_buffer = outBuffer; } // Now check for the first two bytes, to see if we got a unicode string if( m_buffer.GetSize() > 4 ) { m_bUnicode = (m_buffer.GetBuffer()[0] == static_cast(0xFE) && m_buffer.GetBuffer()[1] == static_cast(0xFF)); if( m_bUnicode ) { PdfRefCountedBuffer temp( m_buffer.GetSize() - 2 ); memcpy( temp.GetBuffer(), m_buffer.GetBuffer() + 2, m_buffer.GetSize() - 2 ); m_buffer = temp; } } } void PdfString::Write ( PdfOutputDevice* pDevice, EPdfWriteMode eWriteMode, const PdfEncrypt* pEncrypt ) const { // Strings in PDF documents may contain \0 especially if they are encrypted // this case has to be handled! // Peter Petrov: 17 May 2008 // Added check - m_buffer.GetSize() // Now we are not encrypting the empty strings (was access violation)! if( pEncrypt && m_buffer.GetSize()) { pdf_long nInputBufferLen = m_buffer.GetSize(); pdf_long nUnicodeMarkerOffet = sizeof( PdfString::s_pszUnicodeMarker ); if( m_bUnicode ) nInputBufferLen += nUnicodeMarkerOffet; char * pInputBuffer = new char[nInputBufferLen]; if( m_bUnicode ) { memcpy(pInputBuffer, PdfString::s_pszUnicodeMarker, nUnicodeMarkerOffet); memcpy(&pInputBuffer[nUnicodeMarkerOffet], m_buffer.GetBuffer(), m_buffer.GetSize()); } else memcpy(pInputBuffer, m_buffer.GetBuffer(), m_buffer.GetSize()); pdf_long nOutputBufferLen = pEncrypt->CalculateStreamLength(nInputBufferLen); char* pOutputBuffer = new char [nOutputBufferLen]; pEncrypt->Encrypt(reinterpret_cast(pInputBuffer), nInputBufferLen, reinterpret_cast(pOutputBuffer), nOutputBufferLen); PdfString str( pOutputBuffer, nOutputBufferLen, true ); str.Write( pDevice, eWriteMode, NULL ); delete[] pInputBuffer; delete[] pOutputBuffer; return; } pDevice->Print( m_bHex ? "<" : "(" ); if( m_buffer.GetSize() ) { char* pBuf = m_buffer.GetBuffer(); pdf_long lLen = m_buffer.GetSize() - 2; if( m_bHex ) { if( m_bUnicode ) pDevice->Write( PdfString::s_pszUnicodeMarkerHex, 4 ); char data[2]; while( lLen-- ) { data[0] = (*pBuf & 0xF0) >> 4; data[0] += (data[0] > 9 ? 'A' - 10 : '0'); data[1] = (*pBuf & 0x0F); data[1] += (data[1] > 9 ? 'A' - 10 : '0'); pDevice->Write( data, 2 ); ++pBuf; } } else { if( m_bUnicode ) { pDevice->Write( PdfString::s_pszUnicodeMarker, sizeof( PdfString::s_pszUnicodeMarker ) ); } while( lLen-- ) { const char & cEsc = m_escMap[static_cast(*pBuf)]; if( cEsc != 0 ) { pDevice->Write( "\\", 1 ); pDevice->Write( &cEsc, 1 ); } else { pDevice->Write( &*pBuf, 1 ); } ++pBuf; } } } pDevice->Print( m_bHex ? ">" : ")" ); } const PdfString & PdfString::operator=( const PdfString & rhs ) { this->m_bHex = rhs.m_bHex; this->m_bUnicode = rhs.m_bUnicode; this->m_buffer = rhs.m_buffer; this->m_sUtf8 = rhs.m_sUtf8; this->m_pEncoding = rhs.m_pEncoding; return *this; } bool PdfString::operator>( const PdfString & rhs ) const { const PdfString & str1 = *this; const PdfString & str2 = rhs; if( m_bUnicode || rhs.m_bUnicode ) { #ifdef _WIN32 std::wstring sWide_1 = str1.GetStringW(); std::wstring sWide_2 = str2.GetStringW(); return sWide_1 > sWide_2; #else std::string sUtf8_1 = str1.GetStringUtf8(); std::string sUtf8_2 = str2.GetStringUtf8(); return sUtf8_1 > sUtf8_2; #endif // _WIN32 } return (strcmp( str1.GetString(), str2.GetString() ) > 0); } bool PdfString::operator<( const PdfString & rhs ) const { const PdfString & str1 = *this; const PdfString & str2 = rhs; if( m_bUnicode || rhs.m_bUnicode ) { #ifdef _WIN32 std::wstring sWide_1 = str1.GetStringW(); std::wstring sWide_2 = str2.GetStringW(); return sWide_1 < sWide_2; #else std::string sUtf8_1 = str1.GetStringUtf8(); std::string sUtf8_2 = str2.GetStringUtf8(); return sUtf8_1 < sUtf8_2; #endif // _WIN32 } return (strcmp( str1.GetString(), str2.GetString() ) < 0); } bool PdfString::operator==( const PdfString & rhs ) const { PdfString str1 = *this; PdfString str2 = rhs; if( m_bUnicode || rhs.m_bUnicode ) { // one or both strings are unicode: // make sure both are unicode so that // we do not loose information str1 = str1.ToUnicode(); str2 = str2.ToUnicode(); } return str1.m_buffer == str2.m_buffer; } void PdfString::Init( const char* pszString, pdf_long lLen ) { if( !pszString ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } bool bUft16LE = false; // check if it is a unicode string (UTF-16BE) // UTF-16BE strings have to start with 0xFE 0xFF if( lLen >= 2 ) { m_bUnicode = (pszString[0] == PdfString::s_pszUnicodeMarker[0] && pszString[1] == PdfString::s_pszUnicodeMarker[1]); // Check also for UTF-16LE if( !m_bUnicode && (pszString[0] == PdfString::s_pszUnicodeMarker[1] && pszString[1] == PdfString::s_pszUnicodeMarker[0]) ) { bUft16LE = true; } } // skip the first two bytes if( m_bUnicode ) { lLen -= 2; pszString += 2; } m_buffer = PdfRefCountedBuffer( lLen + 2 ); memcpy( m_buffer.GetBuffer(), pszString, lLen ); m_buffer.GetBuffer()[lLen] = '\0'; m_buffer.GetBuffer()[lLen+1] = '\0'; // if the buffer is a UTF-16LE string // convert it to UTF-16BE if( bUft16LE ) { SwapBytes( m_buffer.GetBuffer(), lLen ); } } void PdfString::InitFromUtf8( const pdf_utf8* pszStringUtf8, pdf_long lLen ) { if( !pszStringUtf8 ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } pdf_long lBufLen = (lLen << 1) + sizeof(wchar_t); // twice as large buffer should always be enough pdf_utf16be *pBuffer = static_cast(alloca(lBufLen)); lBufLen = PdfString::ConvertUTF8toUTF16( pszStringUtf8, lLen, pBuffer, lBufLen ); lBufLen = (lBufLen-1) << 1; // lBufLen is the number of characters, we need the number of bytes now! m_buffer = PdfRefCountedBuffer( lBufLen + sizeof(pdf_utf16be) ); memcpy( m_buffer.GetBuffer(), reinterpret_cast(pBuffer), lBufLen ); m_buffer.GetBuffer()[lBufLen] = '\0'; m_buffer.GetBuffer()[lBufLen+1] = '\0'; } void PdfString::InitUtf8() { if( this->IsUnicode() ) { // we can convert UTF16 to UTF8 // UTF8 is at maximum 5 * characterlenght. pdf_long lBufferLen = (5*this->GetUnicodeLength())+2; char* pBuffer = static_cast(malloc(sizeof(char)*lBufferLen)); if( !pBuffer ) { PODOFO_RAISE_ERROR( ePdfError_OutOfMemory ); } pdf_long lUtf8 = PdfString::ConvertUTF16toUTF8( reinterpret_cast(m_buffer.GetBuffer()), this->GetUnicodeLength(), reinterpret_cast(pBuffer), lBufferLen, ePdfStringConversion_Lenient ); pBuffer[lUtf8-1] = '\0'; pBuffer[lUtf8] = '\0'; m_sUtf8 = pBuffer; free( pBuffer ); } else { PdfString sTmp = this->ToUnicode(); m_sUtf8 = sTmp.GetStringUtf8(); } } #ifdef _WIN32 const std::wstring PdfString::GetStringW() const { if( !this->IsUnicode() ) { return this->ToUnicode().GetStringW(); } PdfRefCountedBuffer buffer( m_buffer.GetSize() ); memcpy( buffer.GetBuffer(), m_buffer.GetBuffer(), m_buffer.GetSize() ); #ifdef PODOFO_IS_LITTLE_ENDIAN SwapBytes( buffer.GetBuffer(), buffer.GetSize() ); #endif // PODOFO_IS_LITTLE_ENDIA std::wstring wstr( reinterpret_cast(buffer.GetBuffer()) ); return wstr; } #endif // _WIN32 /* PdfString PdfString::HexEncode() const { if( this->IsHex() ) return *this; else { std::auto_ptr pFilter; pdf_long lLen = (m_buffer.GetSize() - 1) << 1; PdfString str; PdfRefCountedBuffer buffer( lLen + 1 ); PdfMemoryOutputStream stream( buffer.GetBuffer(), lLen ); pFilter = PdfFilterFactory::Create( ePdfFilter_ASCIIHexDecode ); pFilter->BeginEncode( &stream ); pFilter->EncodeBlock( m_buffer.GetBuffer(), (m_buffer.GetSize() - 1) ); pFilter->EndEncode(); buffer.GetBuffer()[buffer.GetSize()-1] = '\0'; str.m_buffer = buffer; str.m_bHex = true; str.m_bUnicode = m_bUnicode; return str; } } // TODO: REMOVE PdfString PdfString::HexDecode() const { if( !this->IsHex() ) return *this; else { std::auto_ptr pFilter; pdf_long lLen = m_buffer.GetSize() >> 1; PdfString str; PdfRefCountedBuffer buffer( lLen ); PdfMemoryOutputStream stream( buffer.GetBuffer(), lLen ); pFilter = PdfFilterFactory::Create( ePdfFilter_ASCIIHexDecode ); pFilter->BeginDecode( &stream ); pFilter->DecodeBlock( m_buffer.GetBuffer(), m_buffer.GetSize() ); pFilter->EndDecode(); str.m_buffer = buffer; str.m_bHex = false; str.m_bUnicode = m_bUnicode; return str; } } */ PdfString PdfString::ToUnicode() const { if( this->IsUnicode() ) return *this; else { const PdfEncoding* const pEncoding = (m_pEncoding ? m_pEncoding : PdfEncodingFactory::GlobalPdfDocEncodingInstance()); return pEncoding->ConvertToUnicode( *this, NULL ); } } void PdfString::SwapBytes( char* pBuf, pdf_long lLen ) { char cSwap; while( lLen > 1 ) { cSwap = *pBuf; *pBuf = *(pBuf+1); *(++pBuf) = cSwap; ++pBuf; lLen -= 2; } } /* * The disclaimer below applies to the Unicode conversion * functions below. The functions where adapted for use in PoDoFo. * * The original can be found at: * http://www.unicode.org/Public/PROGRAMS/CVTUTF/ */ /* * Copyright 2001-2004 Unicode, Inc. * * Disclaimer * * This source code is provided as is by Unicode, Inc. No claims are * made as to fitness for any particular purpose. No warranties of any * kind are expressed or implied. The recipient agrees to determine * applicability of information provided. If this file has been * purchased on magnetic or optical media from Unicode, Inc., the * sole remedy for any claim will be exchange of defective media * within 90 days of receipt. * * Limitations on Rights to Redistribute This Code * * Unicode, Inc. hereby grants the right to freely use the information * supplied in this file in the creation of products supporting the * Unicode Standard, and to make copies of this file in any form * for internal or external distribution as long as this notice * remains attached. */ /* --------------------------------------------------------------------- Conversions between UTF32, UTF-16, and UTF-8. Source code file. Author: Mark E. Davis, 1994. Rev History: Rick McGowan, fixes & updates May 2001. Sept 2001: fixed const & error conditions per mods suggested by S. Parent & A. Lillich. June 2002: Tim Dodd added detection and handling of incomplete source sequences, enhanced error detection, added casts to eliminate compiler warnings. July 2003: slight mods to back out aggressive FFFE detection. Jan 2004: updated switches in from-UTF8 conversions. Oct 2004: updated to use UNI_MAX_LEGAL_UTF32 in UTF-32 conversions. See the header file "ConvertUTF.h" for complete documentation. ------------------------------------------------------------------------ */ /* --------------------------------------------------------------------- */ /* Some fundamental constants */ #define UNI_REPLACEMENT_CHAR static_cast(0x0000FFFD) #define UNI_MAX_BMP static_cast(0x0000FFFF) #define UNI_MAX_UTF16 static_cast(0x0010FFFF) #define UNI_SUR_HIGH_START static_cast(0xD800) #define UNI_SUR_HIGH_END static_cast(0xDBFF) #define UNI_SUR_LOW_START static_cast(0xDC00) #define UNI_SUR_LOW_END static_cast(0xDFFF) static const int halfShift = 10; /* used for shifting by 10 bits */ static const unsigned long halfBase = 0x0010000UL; static const unsigned long halfMask = 0x3FFUL; /* --------------------------------------------------------------------- */ /* * Index into the table below with the first byte of a UTF-8 sequence to * get the number of trailing bytes that are supposed to follow it. * Note that *legal* UTF-8 values can't have 4 or 5-bytes. The table is * left as-is for anyone who may want to do such conversion, which was * allowed in earlier algorithms. */ static const char trailingBytesForUTF8[256] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 }; /* * Magic values subtracted from a buffer value during UTF8 conversion. * This table contains as many values as there might be trailing bytes * in a UTF-8 sequence. */ static const unsigned long offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL, 0x03C82080UL, 0xFA082080UL, 0x82082080UL }; /* * Once the bits are split out into bytes of UTF-8, this is a mask OR-ed * into the first byte, depending on how many bytes follow. There are * as many entries in this table as there are UTF-8 sequence types. * (I.e., one byte sequence, two byte... etc.). Remember that sequencs * for *legal* UTF-8 will be 4 or fewer bytes total. */ static const pdf_utf8 firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; /* --------------------------------------------------------------------- */ /* * Utility routine to tell whether a sequence of bytes is legal UTF-8. * This must be called with the length pre-determined by the first byte. * If not calling this from ConvertUTF8to*, then the length can be set by: * length = trailingBytesForUTF8[*source]+1; * and the sequence is illegal right away if there aren't that many bytes * available. * If presented with a length > 4, this returns false. The Unicode * definition of UTF-8 goes up to 4-byte sequences. */ static bool isLegalUTF8(const pdf_utf8 *source, int length) { pdf_utf8 a; const pdf_utf8 *srcptr = source+length; switch (length) { default: return false; /* Everything else falls through when "true"... */ case 4: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false; case 3: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false; case 2: if ((a = (*--srcptr)) > 0xBF) return false; switch (*source) { /* no fall-through in this inner switch */ case 0xE0: if (a < 0xA0) return false; break; case 0xED: if (a > 0x9F) return false; break; case 0xF0: if (a < 0x90) return false; break; case 0xF4: if (a > 0x8F) return false; break; default: if (a < 0x80) return false; } case 1: if (*source >= 0x80 && *source < 0xC2) return false; } if (*source > 0xF4) return false; return true; } /* --------------------------------------------------------------------- */ /* * Exported function to return whether a UTF-8 sequence is legal or not. * This is not used here; it's just exported. */ bool isLegalUTF8Sequence(const pdf_utf8 *source, const pdf_utf8 *sourceEnd) { int length = trailingBytesForUTF8[*source]+1; if (source+length > sourceEnd) { return false; } return isLegalUTF8(source, length); } pdf_long PdfString::ConvertUTF8toUTF16( const pdf_utf8* pszUtf8, pdf_utf16be* pszUtf16, pdf_long lLenUtf16 ) { return pszUtf8 ? PdfString::ConvertUTF8toUTF16( pszUtf8, strlen( reinterpret_cast(pszUtf8) ), pszUtf16, lLenUtf16 ) : 0; } pdf_long PdfString::ConvertUTF8toUTF16( const pdf_utf8* pszUtf8, pdf_long lLenUtf8, pdf_utf16be* pszUtf16, pdf_long lLenUtf16, EPdfStringConversion eConversion ) { const pdf_utf8* source = pszUtf8; const pdf_utf8* sourceEnd = pszUtf8 + lLenUtf8 + 1; // point after the last element pdf_utf16be* target = pszUtf16; pdf_utf16be* targetEnd = pszUtf16 + lLenUtf16; while (source < sourceEnd) { unsigned long ch = 0; unsigned short extraBytesToRead = trailingBytesForUTF8[*source]; if (source + extraBytesToRead >= sourceEnd) { PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidDataType, "The UTF8 string was to short while converting from UTF8 to UTF16." ); } // Do this check whether lenient or strict if (! isLegalUTF8(source, extraBytesToRead+1)) { PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidDataType, "The UTF8 string was invalid while from UTF8 to UTF16." ); } /* * The cases all fall through. See "Note A" below. */ switch (extraBytesToRead) { case 5: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */ case 4: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */ case 3: ch += *source++; ch <<= 6; case 2: ch += *source++; ch <<= 6; case 1: ch += *source++; ch <<= 6; case 0: ch += *source++; } ch -= offsetsFromUTF8[extraBytesToRead]; if (target >= targetEnd) { source -= (extraBytesToRead+1); /* Back up source pointer! */ PODOFO_RAISE_ERROR( ePdfError_OutOfMemory ); } if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */ /* UTF-16 surrogate values are illegal in UTF-32 */ if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { if (eConversion == ePdfStringConversion_Strict) { source -= (extraBytesToRead+1); /* return to the illegal value itself */ PODOFO_RAISE_ERROR( ePdfError_InvalidDataType ); break; } else { *target++ = UNI_REPLACEMENT_CHAR; } } else { *target++ = static_cast(ch); /* normal case */ } } else if (ch > UNI_MAX_UTF16) { if (eConversion == ePdfStringConversion_Strict) { PODOFO_RAISE_ERROR( ePdfError_InvalidDataType ); //RG: TODO My compiler says that this is unreachable code! source -= (extraBytesToRead+1); /* return to the start */ break; /* Bail out; shouldn't continue */ } else { *target++ = UNI_REPLACEMENT_CHAR; } } else { /* target is a character in range 0xFFFF - 0x10FFFF. */ if (target + 1 >= targetEnd) { source -= (extraBytesToRead+1); /* Back up source pointer! */ PODOFO_RAISE_ERROR( ePdfError_OutOfMemory ); } ch -= halfBase; *target++ = static_cast((ch >> halfShift) + UNI_SUR_HIGH_START); *target++ = static_cast((ch & halfMask) + UNI_SUR_LOW_START); } } // swap to UTF-16be on LE systems #ifdef PODOFO_IS_LITTLE_ENDIAN PdfString::SwapBytes( reinterpret_cast(pszUtf16), static_cast(target - pszUtf16) << 1 ); #endif // PODOFO_IS_LITTLE_ENDIAN // return characters written return target - pszUtf16; } pdf_long PdfString::ConvertUTF16toUTF8( const pdf_utf16be* pszUtf16, pdf_utf8* pszUtf8, pdf_long lLenUtf8 ) { pdf_long lLen = 0; const pdf_utf16be* pszStart = pszUtf16; while( *pszStart ) ++lLen; return ConvertUTF16toUTF8( pszUtf16, lLen, pszUtf8, lLenUtf8 ); } pdf_long PdfString::ConvertUTF16toUTF8( const pdf_utf16be* pszUtf16, pdf_long lLenUtf16, pdf_utf8* pszUtf8, pdf_long lLenUtf8, EPdfStringConversion eConversion ) { bool bOwnBuf = false; const pdf_utf16be* source = pszUtf16; const pdf_utf16be* sourceEnd = pszUtf16 + lLenUtf16 + 1; // point after the last element pdf_utf8* target = pszUtf8; pdf_utf8* targetEnd = pszUtf8 + lLenUtf8; // swap to UTF-16be on LE systems #ifdef PODOFO_IS_LITTLE_ENDIAN bOwnBuf = true; source = new pdf_utf16be[lLenUtf16+1]; if( !source ) { PODOFO_RAISE_ERROR( ePdfError_OutOfMemory ); } memcpy( const_cast(source), pszUtf16, lLenUtf16 * sizeof(pdf_utf16be) ); PdfString::SwapBytes( reinterpret_cast(const_cast(source)), lLenUtf16 * sizeof(pdf_utf16be) ); pszUtf16 = source; const_cast(source)[lLenUtf16] = 0; sourceEnd = pszUtf16 + lLenUtf16 + 1; // point after the last element #endif // PODOFO_IS_LITTLE_ENDIAN try { while (source < sourceEnd) { unsigned long ch; unsigned short bytesToWrite = 0; const unsigned long byteMask = 0xBF; const unsigned long byteMark = 0x80; const pdf_utf16be* oldSource = source; /* In case we have to back up because of target overflow. */ ch = *source++; /* If we have a surrogate pair, convert to UTF32 first. */ if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) { /* If the 16 bits following the high surrogate are in the source buffer... */ if (source < sourceEnd) { unsigned long ch2 = *source; /* If it's a low surrogate, convert to UTF32. */ if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) { ch = ((ch - UNI_SUR_HIGH_START) << halfShift) + (ch2 - UNI_SUR_LOW_START) + halfBase; ++source; } else if (eConversion == ePdfStringConversion_Strict) { /* it's an unpaired high surrogate */ --source; /* return to the illegal value itself */ PODOFO_RAISE_ERROR( ePdfError_InvalidDataType ); break; } } else { /* We don't have the 16 bits following the high surrogate. */ --source; /* return to the high surrogate */ PODOFO_RAISE_ERROR( ePdfError_OutOfMemory ); break; } } else if (eConversion == ePdfStringConversion_Strict) { /* UTF-16 surrogate values are illegal in UTF-32 */ if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) { --source; /* return to the illegal value itself */ PODOFO_RAISE_ERROR( ePdfError_InvalidDataType ); break; } } /* Figure out how many bytes the result will require */ if (ch < static_cast(0x80)) { bytesToWrite = 1; } else if (ch < static_cast(0x800)) { bytesToWrite = 2; } else if (ch < static_cast(0x10000)) { bytesToWrite = 3; } else if (ch < static_cast(0x110000)) { bytesToWrite = 4; } else { bytesToWrite = 3; ch = UNI_REPLACEMENT_CHAR; } target += bytesToWrite; if (target > targetEnd) { source = oldSource; /* Back up source pointer! */ target -= bytesToWrite; PODOFO_RAISE_ERROR( ePdfError_OutOfMemory ); break; } switch (bytesToWrite) { /* note: everything falls through. */ case 4: *--target = static_cast((ch | byteMark) & byteMask); ch >>= 6; case 3: *--target = static_cast((ch | byteMark) & byteMask); ch >>= 6; case 2: *--target = static_cast((ch | byteMark) & byteMask); ch >>= 6; case 1: *--target = static_cast(ch | firstByteMark[bytesToWrite]); } target += bytesToWrite; } } catch( const PdfError & e ) { if( bOwnBuf ) delete[] const_cast(pszUtf16); throw e; } if( bOwnBuf ) delete[] const_cast(pszUtf16); // return bytes written return target - pszUtf8; } PdfRefCountedBuffer &PdfString::GetBuffer(void) { return m_buffer; } /* --------------------------------------------------------------------- Note A. The fall-through switches in UTF-8 reading code save a temp variable, some decrements & conditionals. The switches are equivalent to the following loop: { int tmpBytesToRead = extraBytesToRead+1; do { ch += *source++; --tmpBytesToRead; if (tmpBytesToRead) ch <<= 6; } while (tmpBytesToRead > 0); } In UTF-8 writing code, the switches on "bytesToWrite" are similarly unrolled loops. --------------------------------------------------------------------- */ }; podofo-0.9.3/src/base/PdfRefCountedInputDevice.h0000664000175000017500000001275212347311233021371 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2006 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_REF_COUNTED_INPUT_DEVICE_H_ #define _PDF_REF_COUNTED_INPUT_DEVICE_H_ #include "PdfDefines.h" namespace PoDoFo { class PdfInputDevice; /** * A reference counted input device object * which is closed as soon as the last * object having access to it is deleted. */ class PODOFO_API PdfRefCountedInputDevice { public: /** Created an empty reference counted input device object * The input device will be initialize to NULL */ PdfRefCountedInputDevice(); /** Create a new PdfRefCountedInputDevice which reads from a file. * The file is opened using fopen() * \param pszFilename a filename to be passed to fopen * \param pszMode a mode string that can be passed to fopen */ PdfRefCountedInputDevice( const char* pszFilename, const char* pszMode ); #ifdef _WIN32 /** Create a new PdfRefCountedInputDevice which reads from a file. * The file is opened using fopen() * \param pszFilename a filename to be passed to fopen * \param pszMode a mode string that can be passed to fopen * * This is an overloaded member function to allow working * with unicode characters. On Unix systes you can also path * UTF-8 to the const char* overload. * */ PdfRefCountedInputDevice( const wchar_t* pszFilename, const char* pszMode ); #endif // _WIN32 /** Create a new PdfRefCountedInputDevice which operates on a in memory buffer * * \param pBuffer pointer to the buffer * \param lLen length of the buffer */ PdfRefCountedInputDevice( const char* pBuffer, size_t lLen ); /** Create a new PdfRefCountedInputDevice from an PdfInputDevice * * \param pDevice the input device. It will be owned and deleted by this object. */ PdfRefCountedInputDevice( PdfInputDevice* pDevice ); /** Copy an existing PdfRefCountedFile and increase * the reference count * \param rhs the PdfRefCountedFile to copy */ PdfRefCountedInputDevice( const PdfRefCountedInputDevice & rhs ); /** Decrease the reference count and close the file * if this is the last owner */ ~PdfRefCountedInputDevice(); /** Get access to the file handle * \returns the file handle */ PODOFO_NOTHROW inline PdfInputDevice* Device() const; /** Copy an existing PdfRefCountedFile and increase * the reference count * \param rhs the PdfRefCountedFile to copy * \returns the copied object */ const PdfRefCountedInputDevice & operator=( const PdfRefCountedInputDevice & rhs ); private: /** Detach from the reference counted file */ void Detach(); private: typedef struct { PdfInputDevice* m_pDevice; long m_lRefCount; } TRefCountedInputDevice; TRefCountedInputDevice* m_pDevice; }; // ----------------------------------------------------- // // ----------------------------------------------------- inline PdfInputDevice* PdfRefCountedInputDevice::Device() const { return m_pDevice ? m_pDevice->m_pDevice : NULL; } }; #endif // _PDF_REF_COUNTED_INPUT_DEVICE_H_ podofo-0.9.3/src/base/PdfXRefStream.cpp0000664000175000017500000001157612331014616017547 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2007 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfXRefStream.h" #include "PdfObject.h" #include "PdfStream.h" #include "PdfWriter.h" #include "PdfDefinesPrivate.h" #if defined(_AIX) || defined(__sun) #include #elif defined(__APPLE__) || defined(__linux) #include #elif defined(_WIN32) #include #endif namespace PoDoFo { PdfXRefStream::PdfXRefStream( PdfVecObjects* pParent, PdfWriter* pWriter ) : m_pParent( pParent ), m_pWriter( pWriter ), m_pObject( NULL ) { m_bufferLen = 2 + sizeof( pdf_uint32 ); m_pObject = pParent->CreateObject( "XRef" ); m_offset = 0; } PdfXRefStream::~PdfXRefStream() { } void PdfXRefStream::BeginWrite( PdfOutputDevice* ) { m_pObject->GetStream()->BeginAppend(); } void PdfXRefStream::WriteSubSection( PdfOutputDevice*, pdf_objnum first, pdf_uint32 count ) { PdfError::DebugMessage("Writing XRef section: %u %u\n", first, count ); m_indeces.push_back( static_cast(first) ); m_indeces.push_back( static_cast(count) ); } void PdfXRefStream::WriteXRefEntry( PdfOutputDevice*, pdf_uint64 offset, pdf_gennum generation, char cMode, pdf_objnum objectNumber ) { char * buffer = reinterpret_cast(alloca(m_bufferLen)); if( cMode == 'n' && objectNumber == m_pObject->Reference().ObjectNumber() ) m_offset = offset; buffer[0] = static_cast( cMode == 'n' ? 1 : 0 ); buffer[m_bufferLen-1] = static_cast( cMode == 'n' ? 0 : generation ); const pdf_uint32 offset_be = ::PoDoFo::compat::podofo_htonl(static_cast(offset)); memcpy( &buffer[1], reinterpret_cast(&offset_be), sizeof(pdf_uint32) ); m_pObject->GetStream()->Append( buffer, m_bufferLen ); } void PdfXRefStream::EndWrite( PdfOutputDevice* pDevice ) { PdfArray w; w.push_back( static_cast(1) ); w.push_back( static_cast(sizeof(pdf_uint32)) ); w.push_back( static_cast(1) ); // Add our self to the XRef table this->WriteXRefEntry( pDevice, pDevice->Tell(), 0, 'n' ); m_pObject->GetStream()->EndAppend(); m_pWriter->FillTrailerObject( m_pObject, this->GetSize(), false, false ); m_pObject->GetDictionary().AddKey( "Index", m_indeces ); m_pObject->GetDictionary().AddKey( "W", w ); pDevice->Seek( static_cast(m_offset) ); m_pObject->WriteObject( pDevice, m_pWriter->GetWriteMode(), NULL ); // DominikS: Requires encryption info?? m_indeces.Clear(); } }; podofo-0.9.3/src/base/PdfMemStream.h0000664000175000017500000001753712344436402017076 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2007 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_MEM_STREAM_H_ #define _PDF_MEM_STREAM_H_ #include "PdfDefines.h" #include "PdfStream.h" #include "PdfDictionary.h" #include "PdfRefCountedBuffer.h" namespace PoDoFo { class PdfBufferOutputStream; class PdfName; class PdfObject; /** A PDF stream can be appended to any PdfObject * and can contain abitrary data. * * A PDF memory stream is held completely in memory. * * Most of the time it will contain either drawing commands * to draw onto a page or binary data like a font or an image. * * A PdfMemStream is implicitly shared and can therefore be copied very quickly. */ class PODOFO_API PdfMemStream : public PdfStream { friend class PdfVecObjects; public: /** Create a new PdfStream object which has a parent PdfObject. * The stream will be deleted along with the parent. * This constructor will be called by PdfObject::Stream() for you. * \param pParent parent object */ PdfMemStream( PdfObject* pParent ); /** Create a shallow copy of a PdfStream object * * \param rhs the object to clone */ PdfMemStream( const PdfMemStream & rhs ); ~PdfMemStream(); /** Write the stream to an output device * \param pDevice write to this outputdevice. * \param pEncrypt encrypt stream data using this object */ virtual void Write( PdfOutputDevice* pDevice, PdfEncrypt* pEncrypt = NULL ); /** Get a malloced buffer of the current stream. * No filters will be applied to the buffer, so * if the stream is Flate compressed the compressed copy * will be returned. * * The caller has to free() the buffer. * * \param pBuffer pointer to the buffer * \param lLen pointer to the buffer length * \returns ErrOk on success. */ virtual void GetCopy( char** pBuffer, pdf_long* lLen ) const; /** Get a copy of a the stream and write it to a PdfOutputStream * * \param pStream data is written to this stream. */ virtual void GetCopy( PdfOutputStream* pStream ) const; /** Get a read-only handle to the current stream data. * The data will not be filtered before being returned, so (eg) calling * Get() on a Flate compressed stream will return a pointer to the * Flate-compressed buffer. * * \warning Do not retain pointers to the stream's internal buffer, * as it may be reallocated with any non-const operation. * * \returns a read-only handle to the streams data */ inline const char* Get() const; /** Get the stream's length. The length is that of the internal * stream buffer, so (eg) for a Flate-compressed stream it will be * the length of the compressed data. * * \returns the length of the internal buffer * \see Get() */ virtual pdf_long GetLength() const; /** This function compresses any currently set stream * using the FlateDecode(ZIP) algorithm. JPEG compressed streams * will not be compressed again using this function. * Entries to the filter dictionary will be added if necessary. */ void FlateCompress(); /** This method removes all filters from the stream */ void Uncompress(); /** Empty's the stream and set the streams buffer size to 0 */ void Empty(); /** Create a copy of a PdfStream object * * \param rhs the object to clone * \returns a reference to this object */ const PdfStream & operator=( const PdfStream & rhs ); protected: /** Required for the GetFilteredCopy implementation * \returns a handle to the internal buffer */ inline virtual const char* GetInternalBuffer() const; /** Required for the GetFilteredCopy implementation * \returns the size of the internal buffer */ inline virtual pdf_long GetInternalBufferSize() const; /** Begin appending data to this stream. * Clears the current stream contents. * * \param vecFilters use this filters to encode any data written to the stream. */ virtual void BeginAppendImpl( const TVecFilters & vecFilters ); /** Append a binary buffer to the current stream contents. * * \param pszString a buffer * \param lLen length of the buffer * * \see BeginAppend * \see Append * \see EndAppend */ virtual void AppendImpl( const char* pszString, size_t lLen ); /** Finish appending data to the stream */ virtual void EndAppendImpl(); private: /** Compress the current data using the FlateDecode(ZIP) algorithm * Expects that all filters are setup correctly. * \returns ErrOk on success */ void FlateCompressStreamData(); private: PdfRefCountedBuffer m_buffer; PdfOutputStream* m_pStream; PdfBufferOutputStream* m_pBufferStream; pdf_long m_lLength; }; // ----------------------------------------------------- // // ----------------------------------------------------- const char* PdfMemStream::Get() const { return m_buffer.GetBuffer(); } // ----------------------------------------------------- // // ----------------------------------------------------- const char* PdfMemStream::GetInternalBuffer() const { return m_buffer.GetBuffer(); } // ----------------------------------------------------- // // ----------------------------------------------------- pdf_long PdfMemStream::GetInternalBufferSize() const { return m_lLength; } }; #endif // _PDF_MEM_STREAM_H_ podofo-0.9.3/src/base/PdfName.cpp0000664000175000017500000001766412344436402016420 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2006 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfName.h" #include "PdfOutputDevice.h" #include "PdfTokenizer.h" #include "PdfDefinesPrivate.h" #include using PoDoFo::ePdfError_InvalidName; namespace { /** * This function writes a hex encoded representation of the character * `ch' to `buf', advancing the iterator by two steps. * * \warning no buffer length checking is performed, so MAKE SURE * you have enough room for the two characters that * will be written to the buffer. * * \param ch The character to write a hex representation of * \param buf An iterator (eg a char* or std::string::iterator) to write the * characters to. Must support the postfix ++, operator=(char) and * dereference operators. */ template inline void hexchr(const unsigned char ch, T & it) { *(it++) = "0123456789ABCDEF"[ch / 16]; *(it++) = "0123456789ABCDEF"[ch % 16]; } /** Escape the input string according to the PDF name * escaping rules and return the result. * * \param it Iterator referring to the start of the input string * ( eg a `const char *' or a `std::string::iterator' ) * \param length Length of input string * \returns Escaped string */ template static std::string EscapeName(T it, size_t length) { // Scan the input string once to find out how much memory we need // to reserve for the encoded result string. We could do this in one // pass using a std::ostringstream instead, but it's a LOT slower. T it2(it); unsigned int outchars = 0; for (size_t i = 0; i < length; ++i) { // Null chars are illegal in names, even escaped if (*it2 == '\0') { PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidName, "Null byte in PDF name is illegal"); } else { // Leave room for either just the char, or a #xx escape of it. outchars += (::PoDoFo::PdfTokenizer::IsRegular(*it2) && ::PoDoFo::PdfTokenizer::IsPrintable(*it2) && (*it2 != '#')) ? 1 : 3; } ++it2; } // Reserve it. We can't use reserve() because the GNU STL doesn't seem to // do it correctly; the memory never seems to get allocated. std::string buf; buf.resize(outchars); // and generate the encoded string std::string::iterator bufIt(buf.begin()); for (size_t z = 0; z < length; ++z) { if (::PoDoFo::PdfTokenizer::IsRegular(*it) && ::PoDoFo::PdfTokenizer::IsPrintable(*it) && (*it != '#') ) *(bufIt++) = *it; else { *(bufIt++) = '#'; hexchr(static_cast(*it), bufIt); } ++it; } return buf; } /** Interpret the passed string as an escaped PDF name * and return the unescaped form. * * \param it Iterator referring to the start of the input string * ( eg a `const char *' or a `std::string::iterator' ) * \param length Length of input string * \returns Unescaped string */ template static std::string UnescapeName(T it, size_t length) { // We know the decoded string can be AT MOST // the same length as the encoded one, so: std::string buf; buf.resize(length); unsigned int incount = 0, outcount = 0; while (incount++ < length) { if (*it == '#') { unsigned char hi = static_cast(*(++it)); ++incount; unsigned char low = static_cast(*(++it)); ++incount; hi -= ( hi < 'A' ? '0' : 'A'-10 ); low -= ( low < 'A' ? '0' : 'A'-10 ); buf[outcount++] = (hi << 4) | (low & 0x0F); } else buf[outcount++] = *it; ++it; } // Chop buffer off at number of decoded bytes buf.resize(outcount); return buf; } }; // End anonymous namespace namespace PoDoFo { const PdfName PdfName::KeyContents = PdfName( "Contents" ); const PdfName PdfName::KeyFlags = PdfName( "Flags" ); const PdfName PdfName::KeyLength = PdfName( "Length" ); const PdfName PdfName::KeyNull = PdfName(); const PdfName PdfName::KeyRect = PdfName( "Rect" ); const PdfName PdfName::KeySize = PdfName( "Size" ); const PdfName PdfName::KeySubtype = PdfName( "Subtype" ); const PdfName PdfName::KeyType = PdfName( "Type" ); const PdfName PdfName::KeyFilter = PdfName( "Filter" ); PdfName::~PdfName() { } PdfName PdfName::FromEscaped( const std::string & sName ) { return PdfName(UnescapeName(sName.begin(), sName.length())); } PdfName PdfName::FromEscaped( const char * pszName, pdf_long ilen ) { if( !ilen && pszName ) ilen = strlen( pszName ); return PdfName(UnescapeName(pszName, ilen)); } void PdfName::Write( PdfOutputDevice* pDevice, EPdfWriteMode, const PdfEncrypt* ) const { // Allow empty names, which are legal according to the PDF specification pDevice->Print( "/" ); if( m_Data.length() ) { std::string escaped( EscapeName(m_Data.begin(), m_Data.length()) ); pDevice->Write( escaped.c_str(), escaped.length() ); } } std::string PdfName::GetEscapedName() const { return EscapeName(m_Data.begin(), m_Data.length()); } bool PdfName::operator==( const char* rhs ) const { /* If the string is empty and you pass NULL - that's equivalent If the string is NOT empty and you pass NULL - that's not equal Otherwise, compare them */ if( m_Data.empty() && !rhs ) return true; else if( !m_Data.empty() && !rhs ) return false; else return ( m_Data == std::string( rhs ) ); } }; podofo-0.9.3/src/base/PdfError.h0000664000175000017500000005322112354340617016266 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2006 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_ERROR_H_ #define _PDF_ERROR_H_ // PdfError.h should not include PdfDefines.h, since it is included by it. // It should avoid depending on anything defined in PdfDefines.h . #include "podofoapi.h" #include #include #include #if defined(_MSC_VER) && _MSC_VER <= 1200 // same pragma as in PdfDefines.h which we cannot include here #pragma warning(disable: 4251) #pragma warning(disable: 4275) #endif /** \file PdfError.h * Error information and logging is implemented in this file. */ namespace PoDoFo { /** Error Code defines which are used in PdfError to describe the error. * * If you add an error code to this enum, please also add it to PdfError::ErrorName * and PdfError::ErrorMessage. * * \see PdfError */ enum EPdfError { ePdfError_ErrOk = 0, /**< The default value indicating no error. */ ePdfError_TestFailed, /**< Used in PoDoFo tests, to indicate that a test failed for some reason. */ ePdfError_InvalidHandle, /**< Null pointer was passed, but null pointer is not allowed. */ ePdfError_FileNotFound, /**< A file was not found or cannot be opened. */ ePdfError_InvalidDeviceOperation, /**< Tried to do something unsupported to an I/O device like seek a non-seekable input device */ ePdfError_UnexpectedEOF, /**< End of file was reached but data was expected. */ ePdfError_OutOfMemory, /**< Not enough memory to complete an operation. */ ePdfError_ValueOutOfRange, /**< The specified memory is out of the allowed range. */ ePdfError_InternalLogic, /**< An internal sanity check or assertion failed. */ ePdfError_InvalidEnumValue, /**< An invalid enum value was specified. */ ePdfError_PageNotFound, /**< The requested page could not be found in the PDF. */ ePdfError_NoPdfFile, /**< The file is no PDF file. */ ePdfError_NoXRef, /**< The PDF file has no or an invalid XRef table. */ ePdfError_NoTrailer, /**< The PDF file has no or an invalid trailer. */ ePdfError_NoNumber, /**< A number was expected in the PDF file, but the read string is no number. */ ePdfError_NoObject, /**< A object was expected and non was found. */ ePdfError_NoEOFToken, /**< The PDF file has no or an invalid EOF marker. */ ePdfError_InvalidTrailerSize, /**< The trailer size is invalid. */ ePdfError_InvalidLinearization, /**< The linearization directory of a web-optimized PDF file is invalid. */ ePdfError_InvalidDataType, /**< The passed datatype is invalid or was not recognized */ ePdfError_InvalidXRef, /**< The XRef table is invalid */ ePdfError_InvalidXRefStream, /**< A XRef steam is invalid */ ePdfError_InvalidXRefType, /**< The XRef type is invalid or was not found */ ePdfError_InvalidPredictor, /**< Invalid or unimplemented predictor */ ePdfError_InvalidStrokeStyle, /**< Invalid stroke style during drawing */ ePdfError_InvalidHexString, /**< Invalid hex string */ ePdfError_InvalidStream, /**< The stream is invalid */ ePdfError_InvalidStreamLength, /**< The stream length is invlaid */ ePdfError_InvalidKey, /**< The specified key is invalid */ ePdfError_InvalidName, /**< The specified Name is not valid in this context */ ePdfError_InvalidEncryptionDict, /**< The encryption dictionary is invalid or misses a required key */ ePdfError_InvalidPassword, /**< The password used to open the PDF file was invalid */ ePdfError_InvalidFontFile, /**< The font file is invalid */ ePdfError_InvalidContentStream, /**< The content stream is invalid due to mismatched context pairing or other problems */ ePdfError_UnsupportedFilter, /**< The requested filter is not yet implemented. */ ePdfError_UnsupportedFontFormat, /**< This font format is not supported by PoDoFO. */ ePdfError_ActionAlreadyPresent, /**< An Action was already present when trying to add a Destination */ ePdfError_WrongDestinationType, /**< The requested field is not available for the given destination type */ ePdfError_MissingEndStream, /**< The required token endstream was not found. */ ePdfError_Date, /**< Date/time error */ ePdfError_Flate, /**< Error in zlib */ ePdfError_FreeType, /**< Error in FreeType */ ePdfError_SignatureError, /**< Error in signature */ ePdfError_MutexError, /**< Error during a mutex operation */ ePdfError_UnsupportedImageFormat, /**< This image format is not supported by PoDoFO. */ ePdfError_CannotConvertColor, /**< This color format cannot be converted. */ ePdfError_NotImplemented, /**< This feature is currently not implemented. */ ePdfError_DestinationAlreadyPresent,/**< An destination was already present when trying to add a Action */ ePdfError_ChangeOnImmutable, /**< Changing values on immutable objects is not allowed. */ ePdfError_NotCompiled, /**< This feature was disabled during compile time. */ ePdfError_Unknown = 0xffff /**< Unknown error */ }; /** * Used in PdfError::LogMessage to specify the log level. * * \see PdfError::LogMessage */ enum ELogSeverity { eLogSeverity_Critical, /**< Critical unexpected error */ eLogSeverity_Error, /**< Error */ eLogSeverity_Warning, /**< Warning */ eLogSeverity_Information, /**< Information message */ eLogSeverity_Debug, /**< Debug information */ eLogSeverity_None, /**< No specified level */ eLogSeverity_Unknown = 0xffff /**< Unknown log level */ }; /** \def PODOFO_RAISE_ERROR( x ) * * Set the value of the variable eCode (which has to exist in the current function) to x * and return the eCode. */ #define PODOFO_RAISE_ERROR( x ) throw ::PoDoFo::PdfError( x, __FILE__, __LINE__ ); /** \def PODOFO_RAISE_ERROR_INFO( x, y ) * * Set the value of the variable eCode (which has to exist in the current function) to x * and return the eCode. Additionally additional information on the error y is set. y has * to be an c-string. */ #define PODOFO_RAISE_ERROR_INFO( x, y ) throw ::PoDoFo::PdfError( x, __FILE__, __LINE__, y ); /** \def PODOFO_RAISE_LOGIC_IF( x, y ) * * Evaluate `x' as a binary predicate and if it is true, raise a logic error with the * info string `y' . * * This macro will be undefined when NDEBUG is set, so it's compiled out for release * builds. Use it for expensive or extremely frequent sanity checking. * * We define it then UNDEF it to help out doxygen. */ #ifndef NDEBUG // Woo for double-negatives. We define PODOFO_RAISE_LOGIC_IF unless we've been told not to by NDEBUG. #define PODOFO_RAISE_LOGIC_IF( x, y ) { if (x) throw ::PoDoFo::PdfError( ePdfError_InternalLogic, __FILE__, __LINE__, y ); }; #else #define PODOFO_RAISE_LOGIC_IF( x, y ) {}; #endif class PODOFO_API PdfErrorInfo { public: PdfErrorInfo(); PdfErrorInfo( int line, const char* pszFile, const char* pszInfo ); PdfErrorInfo( int line, const char* pszFile, const wchar_t* pszInfo ); PdfErrorInfo( const PdfErrorInfo & rhs ); const PdfErrorInfo & operator=( const PdfErrorInfo & rhs ); inline int GetLine() const { return m_nLine; } inline const std::string & GetFilename() const { return m_sFile; } inline const std::string & GetInformation() const { return m_sInfo; } inline const std::wstring & GetInformationW() const { return m_swInfo; } inline void SetInformation( const char* pszInfo ) { m_sInfo = pszInfo ? pszInfo : ""; } inline void SetInformation( const wchar_t* pszInfo ) { m_swInfo = pszInfo ? pszInfo : L""; } private: int m_nLine; std::string m_sFile; std::string m_sInfo; std::wstring m_swInfo; }; typedef std::deque TDequeErrorInfo; typedef TDequeErrorInfo::iterator TIDequeErrorInfo; typedef TDequeErrorInfo::const_iterator TCIDequeErrorInfo; // This is required to generate the documentation with Doxygen. // Without this define doxygen thinks we have a class called PODOFO_EXCEPTION_API(PODOFO_API) ... #define PODOFO_EXCEPTION_API_DOXYGEN PODOFO_EXCEPTION_API(PODOFO_API) /** The error handling class of PoDoFo lib. * Whenever a function encounters an error * a PdfError object is returned. * * A PdfError with Error() == ErrOk means * successfull execution. * * This class provides also meaningfull * error descriptions. */ class PODOFO_EXCEPTION_API_DOXYGEN PdfError { public: // OC 17.08.2010 New to optionally replace stderr output by a callback: class LogMessageCallback { public: virtual ~LogMessageCallback() {} // every class with virtual methods needs a virtual destructor virtual void LogMessage( ELogSeverity eLogSeverity, const char* pszPrefix, const char* pszMsg, va_list & args ) = 0; virtual void LogMessage( ELogSeverity eLogSeverity, const wchar_t* pszPrefix, const wchar_t* pszMsg, va_list & args ) = 0; }; /** Set a global static LogMessageCallback functor to repleace stderr output in LogMessageInternal * \param fLogMessageCallback the pointer to the new callback functor object * \returns the pointer to the previous callback functor object */ static LogMessageCallback* SetLogMessageCallback(LogMessageCallback* fLogMessageCallback); /** Create a PdfError object initialized to ErrOk */ PdfError(); /** Create a PdfError object with a given error code. * \param eCode the error code of this object * \param pszFile the file in which the error has occured. * Use the compiler macro __FILE__ to initialize the field. * \param line the line in which the error has occured. * Use the compiler macro __LINE__ to initialize the field. * \param pszInformation additional information on this error which mayy * be formatted like printf */ PdfError( const EPdfError & eCode, const char* pszFile = NULL, int line = 0, const char* pszInformation = NULL ); /** Copy constructor * \param rhs copy the contents of rhs into this object */ PdfError( const PdfError & rhs ); virtual ~PdfError() throw(); /** Assignment operator * \param rhs another PdfError object * \returns this object */ const PdfError & operator=( const PdfError & rhs ); /** Overloaded assignment operator * \param eCode a EPdfError code * \returns this object */ const PdfError & operator=( const EPdfError & eCode ); /** Comparison operator compares 2 PdfError objects * \param rhs another PdfError object * \returns true if both objects have the same error code. */ bool operator==( const PdfError & rhs ); /** Overloaded comparison operator compares 2 PdfError objects * \param eCode an erroce code * \returns true if this object has the same error code. */ bool operator==( const EPdfError & eCode ); /** Comparison operator compares 2 PdfError objects * \param rhs another PdfError object * \returns true if both objects have the different error code. */ bool operator!=( const PdfError & rhs ); /** Overloaded comparison operator compares 2 PdfError objects * \param eCode an erroce code * \returns true if this object has different error code. */ bool operator!=( const EPdfError & eCode ); /** Return the error code of this object * \returns the error code of this object */ inline EPdfError GetError() const; /** Get access to the internal callstack of this error * \return the callstack */ inline const TDequeErrorInfo & GetCallstack() const; /** Set the error code of this object. * \param eCode the error code of this object * \param pszFile the filename of the source file causing * the error or NULL. Typically you will use * the gcc macro __FILE__ here. * \param line the line of source causing the error * or 0. Typically you will use the gcc * macro __LINE__ here. * \param pszInformation additional information on the error. * e.g. how to fix the error. This string is intended to * be shown to the user. */ inline void SetError( const EPdfError & eCode, const char* pszFile = NULL, int line = 0, const char* pszInformation = NULL ); /** Set additional error informatiom * \param pszInformation additional information on the error. * e.g. how to fix the error. This string is intended to * be shown to the user. */ inline void SetErrorInformation( const char* pszInformation ); /** Set additional error informatiom * \param pszInformation additional information on the error. * e.g. how to fix the error. This string is intended to * be shown to the user. */ inline void SetErrorInformation( const wchar_t* pszInformation ); /** Add callstack information to an error object. Always call this function * if you get an error object but do not handle the error but throw it again. * * \param pszFile the filename of the source file causing * the error or NULL. Typically you will use * the gcc macro __FILE__ here. * \param line the line of source causing the error * or 0. Typically you will use the gcc * macro __LINE__ here. * \param pszInformation additional information on the error. * e.g. how to fix the error. This string is intended to * be shown to the user. */ inline void AddToCallstack( const char* pszFile = NULL, int line = 0, const char* pszInformation = NULL ); /** \returns true if an error code was set * and false if the error code is ePdfError_ErrOk */ inline bool IsError() const; /** Print an error message to stderr */ void PrintErrorMsg() const; /** Obtain error description. * \returns a c string describing the error. */ const char* what() const; /** Get the name for a certain error code. * \returns the name or NULL if no name for the specified * error code is available. */ PODOFO_NOTHROW static const char* ErrorName( EPdfError eCode ); /** Get the error message for a certain error code. * \returns the error message or NULL if no error * message for the specified error code * is available. */ static const char* ErrorMessage( EPdfError eCode ); /** Log a message to the logging system defined for PoDoFo. * \param eLogSeverity the sevirity of the log message * \param pszMsg the message to be logged */ static void LogMessage( ELogSeverity eLogSeverity, const char* pszMsg, ... ); /** Log a message to the logging system defined for PoDoFo. * \param eLogSeverity the sevirity of the log message * \param pszMsg the message to be logged */ static void LogMessage( ELogSeverity eLogSeverity, const wchar_t* pszMsg, ... ); /** Enable or disable Logging * \param bEnable enable (true) or disable (false) */ static void EnableLogging( bool bEnable ) { PdfError::s_LogEnabled = bEnable; } /** Is the display of debugging messages enabled or not? */ static bool LoggingEnabled() { return PdfError::s_LogEnabled; } /** Log a message to the logging system defined for PoDoFo for debugging * \param pszMsg the message to be logged */ static void DebugMessage( const char* pszMsg, ... ); /** Enable or disable the display of debugging messages * \param bEnable enable (true) or disable (false) */ static void EnableDebug( bool bEnable ) { PdfError::s_DgbEnabled = bEnable; } /** Is the display of debugging messages enabled or not? */ static bool DebugEnabled() { return PdfError::s_DgbEnabled; } private: /** Log a message to the logging system defined for PoDoFo. * * This call does not check if logging is enabled and always * prints the error message * * \param eLogSeverity the sevirity of the log message * \param pszMsg the message to be logged */ static void LogErrorMessage( ELogSeverity eLogSeverity, const char* pszMsg, ... ); /** Log a message to the logging system defined for PoDoFo. * * This call does not check if logging is enabled and always * prints the error message * * \param eLogSeverity the sevirity of the log message * \param pszMsg the message to be logged */ static void LogErrorMessage( ELogSeverity eLogSeverity, const wchar_t* pszMsg, ... ); static void LogMessageInternal( ELogSeverity eLogSeverity, const char* pszMsg, va_list & args ); static void LogMessageInternal( ELogSeverity eLogSeverity, const wchar_t* pszMsg, va_list & args ); private: EPdfError m_error; TDequeErrorInfo m_callStack; static bool s_DgbEnabled; static bool s_LogEnabled; // OC 17.08.2010 New to optionally replace stderr output by a callback: static LogMessageCallback* m_fLogMessageCallback; }; // ----------------------------------------------------- // // ----------------------------------------------------- EPdfError PdfError::GetError() const { return m_error; } // ----------------------------------------------------- // // ----------------------------------------------------- const TDequeErrorInfo & PdfError::GetCallstack() const { return m_callStack; } // ----------------------------------------------------- // // ----------------------------------------------------- void PdfError::SetError( const EPdfError & eCode, const char* pszFile, int line, const char* pszInformation ) { m_error = eCode; this->AddToCallstack( pszFile, line, pszInformation ); } // ----------------------------------------------------- // // ----------------------------------------------------- void PdfError::AddToCallstack( const char* pszFile, int line, const char* pszInformation ) { m_callStack.push_front( PdfErrorInfo( line, pszFile, pszInformation ) ); } // ----------------------------------------------------- // // ----------------------------------------------------- void PdfError::SetErrorInformation( const char* pszInformation ) { if( m_callStack.size() ) m_callStack.front().SetInformation( pszInformation ? pszInformation : "" ); } // ----------------------------------------------------- // // ----------------------------------------------------- void PdfError::SetErrorInformation( const wchar_t* pszInformation ) { if( m_callStack.size() ) m_callStack.front().SetInformation( pszInformation ? pszInformation : L"" ); } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfError::IsError() const { return (m_error != ePdfError_ErrOk); } }; #endif /* _PDF_ERROR_H_ */ podofo-0.9.3/src/base/PdfRect.cpp0000664000175000017500000001201212344436402016413 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2006 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfRect.h" #include "PdfArray.h" #include "PdfVariant.h" #include "PdfDefinesPrivate.h" #include #include #include namespace PoDoFo { PdfRect::PdfRect() { m_dBottom = m_dLeft = m_dWidth = m_dHeight = 0; } PdfRect::PdfRect( double dLeft, double dBottom, double dWidth, double dHeight ) { m_dBottom = dBottom; m_dLeft = dLeft; m_dWidth = dWidth; m_dHeight = dHeight; } PdfRect::PdfRect( const PdfArray& inArray ) { m_dBottom = m_dLeft = m_dWidth = m_dHeight = 0; FromArray( inArray ); } PdfRect::PdfRect( const PdfRect & rhs ) { this->operator=( rhs ); } void PdfRect::ToVariant( PdfVariant & var ) const { PdfArray array; array.push_back( PdfVariant( m_dLeft ) ); array.push_back( PdfVariant( m_dBottom ) ); array.push_back( PdfVariant( (m_dWidth+m_dLeft) ) ); array.push_back( PdfVariant( (m_dHeight+m_dBottom) ) ); var = array; } std::string PdfRect::ToString() const { PdfVariant var; std::string str; this->ToVariant( var ); var.ToString( str ); return str; /* std::ostringstream oStr; oStr << "[ "; oStr << std::setprecision( 3 ) << m_dLeft << " "; oStr << std::setprecision( 3 ) << m_dBottom << " "; oStr << std::setprecision( 3 ) << m_dWidth + m_dLeft << " "; oStr << std::setprecision( 3 ) << m_dHeight - m_dBottom << " ]"; return oStr.str(); */ } void PdfRect::FromArray( const PdfArray& inArray ) { if ( inArray.size() == 4 ) { m_dLeft = inArray[0].GetReal(); m_dBottom = inArray[1].GetReal(); m_dWidth = inArray[2].GetReal() - m_dLeft; m_dHeight = inArray[3].GetReal() - m_dBottom; } else { PODOFO_RAISE_ERROR( ePdfError_ValueOutOfRange ); } } void PdfRect::Intersect( const PdfRect & rRect ) { if( rRect.GetBottom() != 0 || rRect.GetHeight() != 0 || rRect.GetLeft() != 0 || rRect.GetWidth() != 0 ) { double diff; diff = rRect.m_dLeft - m_dLeft; if ( diff > 0.0 ) { m_dLeft += diff; m_dWidth -= diff; } diff = (m_dLeft + m_dWidth) - (rRect.m_dLeft + rRect.m_dWidth); if ( diff > 0.0 ) { m_dWidth -= diff; } diff = rRect.m_dBottom - m_dBottom; if ( diff > 0.0 ) { m_dBottom += diff; m_dHeight -= diff; } diff = (m_dBottom + m_dHeight) - (rRect.m_dBottom + rRect.m_dHeight); if ( diff > 0.0 ) { m_dHeight -= diff; } } } PdfRect & PdfRect::operator=( const PdfRect & rhs ) { this->m_dBottom = rhs.m_dBottom; this->m_dLeft = rhs.m_dLeft; this->m_dWidth = rhs.m_dWidth; this->m_dHeight = rhs.m_dHeight; return *this; } }; podofo-0.9.3/src/base/PdfDefinesPrivate.h0000664000175000017500000000145111641323033020072 0ustar dominikdominik#ifndef _PDF_DEFINES_PRIVATE_H_ #define _PDF_DEFINES_PRIVATE_H_ #ifndef BUILDING_PODOFO #error PdfDefinesPrivate.h is only available for use in the core PoDoFo src/ build .cpp files #endif // Right now, just pulls in the private parts of the compiler compat hacks. #include "PdfCompilerCompatPrivate.h" /** * \page * * PdfDefinesPrivate.h contains preprocessor definitions, inline functions, templates, * compile-time const variables, and other things that must be visible across the entirety of * the PoDoFo library code base but should not be visible to users of the library's headers. * * This header is private to the library build. It is not installed with PoDoFo and must not be * referenced in any way from any public, installed header. */ #endif podofo-0.9.3/src/base/PdfDictionary.cpp0000664000175000017500000002372212347271543017643 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2006 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #include "PdfDictionary.h" #include "PdfOutputDevice.h" #include "PdfDefinesPrivate.h" namespace PoDoFo { PdfDictionary::PdfDictionary() : m_bDirty( false ) { } PdfDictionary::PdfDictionary( const PdfDictionary & rhs ) : PdfDataType() { this->operator=( rhs ); m_bDirty = false; } PdfDictionary::~PdfDictionary() { this->SetImmutable(false); // Destructor may change things, i.e. delete this->Clear(); } const PdfDictionary & PdfDictionary::operator=( const PdfDictionary & rhs ) { TCIKeyMap it; this->Clear(); it = rhs.m_mapKeys.begin(); while( it != rhs.m_mapKeys.end() ) { m_mapKeys[(*it).first] = new PdfObject( *(*it).second ); ++it; } m_bDirty = true; return *this; } bool PdfDictionary::operator==( const PdfDictionary& rhs ) const { if (this == &rhs) return true; if ( m_mapKeys.size() != rhs.m_mapKeys.size() ) return false; // It's not enough to test that our internal maps are equal, because // we store variants by pointer not value. However, since a dictionary's // keys are stored in a SORTED map, and there may be only one instance of // every key, we can do lockstep iteration and compare that way. const TCIKeyMap thisIt = m_mapKeys.begin(); const TCIKeyMap thisEnd = m_mapKeys.end(); const TCIKeyMap rhsIt = rhs.m_mapKeys.begin(); const TCIKeyMap rhsEnd = rhs.m_mapKeys.end(); while ( thisIt != thisEnd && rhsIt != rhsEnd ) { if ( (*thisIt).first != (*rhsIt).first ) // Name mismatch. Since the keys are sorted that means that there's a key present // in one dictionary but not the other. return false; if ( *(*thisIt).second != *(*rhsIt).second ) // Value mismatch on same-named keys. return false; } // BOTH dictionaries must now be on their end iterators - since we checked that they were // the same size initially, we know they should run out of keys at the same time. PODOFO_RAISE_LOGIC_IF( thisIt != thisEnd || rhsIt != rhsEnd, "Dictionary compare error" ); // We didn't find any mismatches return true; } void PdfDictionary::Clear() { AssertMutable(); if( !m_mapKeys.empty() ) { TIKeyMap it; it = m_mapKeys.begin(); while( it != m_mapKeys.end() ) { delete (*it).second; ++it; } m_mapKeys.clear(); } } void PdfDictionary::AddKey( const PdfName & identifier, const PdfObject & rObject ) { AssertMutable(); // Empty PdfNames are legal according to the PDF specification // weird but true. As a reason we cannot throw an error here /* if( !identifier.GetLength() ) { PODOFO_RAISE_ERROR( ePdfError_InvalidDataType ); } */ if( m_mapKeys.find( identifier ) != m_mapKeys.end() ) { delete m_mapKeys[identifier]; m_mapKeys.erase( identifier ); } m_mapKeys[identifier] = new PdfObject( rObject ); m_bDirty = true; } void PdfDictionary::AddKey( const PdfName & identifier, const PdfObject* pObject ) { this->AddKey( identifier, *pObject ); } const PdfObject* PdfDictionary::GetKey( const PdfName & key ) const { TCIKeyMap it; if( HasKey( key ) ) { it = m_mapKeys.find( key ); return (*it).second; } return NULL; } PdfObject* PdfDictionary::GetKey( const PdfName & key ) { TIKeyMap it; if( HasKey( key ) ) { it = m_mapKeys.find( key ); return (*it).second; } return NULL; } pdf_int64 PdfDictionary::GetKeyAsLong( const PdfName & key, pdf_int64 lDefault ) const { const PdfObject* pObject = GetKey( key ); if( pObject && pObject->GetDataType() == ePdfDataType_Number ) { return pObject->GetNumber(); } return lDefault; } double PdfDictionary::GetKeyAsReal( const PdfName & key, double dDefault ) const { const PdfObject* pObject = GetKey( key ); if( pObject && ( pObject->GetDataType() == ePdfDataType_Real || pObject->GetDataType() == ePdfDataType_Number)) { return pObject->GetReal(); } return dDefault; } bool PdfDictionary::GetKeyAsBool( const PdfName & key, bool bDefault ) const { const PdfObject* pObject = GetKey( key ); if( pObject && pObject->GetDataType() == ePdfDataType_Bool ) { return pObject->GetBool(); } return bDefault; } PdfName PdfDictionary::GetKeyAsName( const PdfName & key ) const { const PdfObject* pObject = GetKey( key ); if( pObject && pObject->GetDataType() == ePdfDataType_Name ) { return pObject->GetName(); } return PdfName(""); // return an empty name } bool PdfDictionary::HasKey( const PdfName & key ) const { if( !key.GetLength() ) return false; return ( m_mapKeys.find( key ) != m_mapKeys.end() ); } bool PdfDictionary::RemoveKey( const PdfName & identifier ) { if( HasKey( identifier ) ) { AssertMutable(); delete m_mapKeys[identifier]; m_mapKeys.erase( identifier ); m_bDirty = true; return true; } return false; } void PdfDictionary::Write( PdfOutputDevice* pDevice, EPdfWriteMode eWriteMode, const PdfEncrypt* pEncrypt, const PdfName & keyStop ) const { TCIKeyMap itKeys; if( (eWriteMode & ePdfWriteMode_Clean) == ePdfWriteMode_Clean ) { pDevice->Print( "<<\n" ); } else { pDevice->Print( "<<" ); } itKeys = m_mapKeys.begin(); if( keyStop != PdfName::KeyNull && keyStop.GetLength() && keyStop == PdfName::KeyType ) return; if( this->HasKey( PdfName::KeyType ) ) { // Type has to be the first key in any dictionary if( (eWriteMode & ePdfWriteMode_Clean) == ePdfWriteMode_Clean ) { pDevice->Print( "/Type " ); } else { pDevice->Print( "/Type" ); } this->GetKey( PdfName::KeyType )->Write( pDevice, eWriteMode, pEncrypt ); if( (eWriteMode & ePdfWriteMode_Clean) == ePdfWriteMode_Clean ) { pDevice->Print( "\n" ); } } while( itKeys != m_mapKeys.end() ) { if( (*itKeys).first != PdfName::KeyType ) { if( keyStop != PdfName::KeyNull && keyStop.GetLength() && (*itKeys).first == keyStop ) return; (*itKeys).first.Write( pDevice, eWriteMode ); if( (eWriteMode & ePdfWriteMode_Clean) == ePdfWriteMode_Clean ) { pDevice->Write( " ", 1 ); // write a separator } (*itKeys).second->Write( pDevice, eWriteMode, pEncrypt ); if( (eWriteMode & ePdfWriteMode_Clean) == ePdfWriteMode_Clean ) { pDevice->Write( "\n", 1 ); } } ++itKeys; } pDevice->Print( ">>" ); } bool PdfDictionary::IsDirty() const { // If the dictionary itself is dirty // return immediately // otherwise check all children. if( m_bDirty ) return m_bDirty; TKeyMap::const_iterator it = this->GetKeys().begin(); while( it != this->GetKeys().end() ) { if( (*it).second->IsDirty() ) return true; ++it; } return false; } void PdfDictionary::SetDirty( bool bDirty ) { m_bDirty = bDirty; if( !m_bDirty ) { // Propagate state to all subclasses TKeyMap::iterator it = this->GetKeys().begin(); while( it != this->GetKeys().end() ) { (*it).second->SetDirty( m_bDirty ); ++it; } } } }; podofo-0.9.3/src/base/PdfWriter.h0000664000175000017500000003063112262234754016453 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2005 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PDF_WRITER_H_ #define _PDF_WRITER_H_ #include "PdfDefines.h" #include "PdfOutputDevice.h" #include "PdfVecObjects.h" #include "PdfEncrypt.h" namespace PoDoFo { class PdfDictionary; class PdfName; class PdfObject; class PdfPage; class PdfPagesTree; class PdfParser; class PdfVecObjects; class PdfXRef; namespace NonPublic { class PdfHintStream; } /** The PdfWriter class writes a list of PdfObjects as PDF file. * The XRef section (which is the required table of contents for any * PDF file) is created automatically. * * It does not know about pages but only about PdfObjects. * * Most users will want to use PdfDocument. */ class PODOFO_API PdfWriter { public: /** Create a PdfWriter object from a PdfParser object * \param pParser a pdf parser object */ PdfWriter( PdfParser* pParser ); /** Create a new pdf file, from an vector of PdfObjects * and a trailer object. * \param pVecObjects the vector of objects * \param pTrailer a valid trailer object */ PdfWriter( PdfVecObjects* pVecObjects, const PdfObject* pTrailer ); virtual ~PdfWriter(); /** Writes the complete document to a PDF file. * * \param pszFilename filename of a PDF file. */ void Write( const char* pszFilename ); #ifdef _WIN32 /** Writes the complete document to a PDF file. * * \param pszFilename filename of a PDF file. * * This is an overloaded member function to allow working * with unicode characters. On Unix systes you can also path * UTF-8 to the const char* overload. */ void Write( const wchar_t* pszFilename ); #endif // _WIN32 /** Writes the complete document to a PdfOutputDevice * * \param pDevice write to the specified device */ void Write( PdfOutputDevice* pDevice ); /** Set the write mode to use when writing the PDF. * \param eWriteMode write mode */ void SetWriteMode( EPdfWriteMode eWriteMode ) { m_eWriteMode = eWriteMode; } /** Get the write mode used for wirting the PDF * \returns the write mode */ EPdfWriteMode GetWriteMode() const { return m_eWriteMode; } /** Set the PDF Version of the document. Has to be called before Write() to * have an effect. * \param eVersion version of the pdf document */ void SetPdfVersion( EPdfVersion eVersion ) { m_eVersion = eVersion; } /** Get the PDF version of the document * \returns EPdfVersion version of the pdf document */ EPdfVersion GetPdfVersion() const { return m_eVersion; } /** Enabled linearization for this document. * I.e. optimize it for web usage. Default is false. * \param bLinearize if true create a web optimized PDF file */ inline void SetLinearized( bool bLinearize ); /** * \returns true if this PDF file is web optimized. */ inline bool GetLinearized() const; /** Create a XRef stream which is in some case * more compact but requires at least PDF 1.5 * Default is false. * \param bStream if true a XRef stream object will be created */ inline void SetUseXRefStream( bool bStream ); /** * \returns wether a XRef stream is used or not */ inline bool GetUseXRefStream() const; /** Get the file format version of the pdf * \returns the file format version as string */ const char* GetPdfVersionString() const { return s_szPdfVersionNums[static_cast(m_eVersion)]; } /** Set the written document to be encrypted using a PdfEncrypt object * * \param rEncrypt an encryption object which is used to encrypt the written PDF file */ void SetEncrypted( const PdfEncrypt & rEncrypt ); /** * \returns true if this PdfWriter creates an encrypted PDF file */ bool GetEncrypted() const { return (m_pEncrypt != NULL); } /** Calculate the byte offset of the object pObject in the PDF file * if the file was written to disk at the moment of calling this function. * * This function is very calculation intensive! * * \param pObject object to calculate the byte offset (has to be a * child of this PdfWriter) * \param pulOffset pointer to an unsigned long to save the offset */ void GetByteOffset( PdfObject* pObject, pdf_long* pulOffset ); /** Write the whole document to a buffer in memory. * * Better use a PdfOutputDevice that writes to a PdfRefCountedBuffer. * * \param ppBuffer will be malloc'ed and the document * will be written to this buffer. * \param pulLen the length of the buffer will be returned in this parameter * \returns ErrOk on success * * \see Write */ void WriteToBuffer( char** ppBuffer, pdf_long* pulLen ); /** Add required keys to a trailer object * \param pTrailer add keys to this object * \param lSize number of objects in the PDF file * \param bPrevEntry if true a prev entry is added to the trailer object with a value of 0 * \param bOnlySizeKey write only the size key */ void FillTrailerObject( PdfObject* pTrailer, pdf_long lSize, bool bPrevEntry, bool bOnlySizeKey ) const; protected: /** * Create a PdfWriter from a PdfVecObjects */ PdfWriter( PdfVecObjects* pVecObjects ); /** Writes the pdf header to the current file. * \param pDevice write to this output device */ void PODOFO_LOCAL WritePdfHeader( PdfOutputDevice* pDevice ); /** Write pdf objects to file * \param pDevice write to this output device * \param vecObjects write all objects in this vector to the file * \param pXref add all written objects to this XRefTable */ void WritePdfObjects( PdfOutputDevice* pDevice, const PdfVecObjects& vecObjects, PdfXRef* pXref ) PODOFO_LOCAL; /** Creates a file identifier which is required in several * PDF workflows. * All values from the files document information dictionary are * used to create a unique MD5 key which is added to the trailer dictionary. * * \param identifier write the identifier to this string * \param pTrailer trailer object */ void CreateFileIdentifier( PdfString & identifier, const PdfObject* pTrailer ) const PODOFO_LOCAL; protected: /** Writes a linearized PDF file * \param pDevice write to this output device */ void PODOFO_LOCAL WriteLinearized( PdfOutputDevice* pDevice ); /** Create a linearization dictionary for the current * document and return a pointer to it after inserting * it into the vector of PdfObjects * * \returns a pointer to the linearization dictionary */ PdfObject* CreateLinearizationDictionary() PODOFO_LOCAL; /** Reorder and renumber all object as required for linearized PDF files. * This function is very slow. * * \param pLinearize linearization dictionary * \param pHint primary hint stream dictionary * \param pPage first page to display in the document * \param ppLast the pointer will be initialized to the last object * belonging to the first page */ //void ReorderObjectsLinearized( PdfObject* pLinearize, NonPublic::PdfHintStream* pHint, PdfPage* pPage, PdfObject** ppLast ) PODOFO_LOCAL; /** Initialize m_pPagesTree with its correct value * Always call this function befre accessing the pages tree. */ //void FetchPagesTree(); /** Find dependencies required for creating a linearized PDF of the catalog dictionary. */ //void FindCatalogDependencies( PdfObject* pCatalog, const PdfName & rName, TPdfReferenceList* pList, bool bWithDependencies ) PODOFO_LOCAL; /** Fill all keys in the linearization dictionary with their values * \param pLinearize a linearization dictionary * \param pHint the hint stream * \param pPage the first page in the linerarized PDF file * \param pLast pointer of the last object belonging to the first page * \param pVecXRefOffset xref table entries for previous entry */ // void FillLinearizationDictionary( PdfObject* pLinearize, PdfOutputDevice* pDevice, PdfPage* pPage, PdfObject* pLast, NonPublic::PdfHintStream* pHint, TVecXRefOffset* pVecXRefOffset ) PODOFO_LOCAL; protected: PdfVecObjects* m_vecObjects; PdfObject* m_pTrailer; bool m_bXRefStream; PdfEncrypt* m_pEncrypt; ///< If not NULL encrypt all strings and streams and create an encryption dictionary in the trailer PdfObject* m_pEncryptObj; ///< Used to temporarly store the encryption dictionary PdfString m_identifier; private: EPdfWriteMode m_eWriteMode; EPdfVersion m_eVersion; bool m_bLinearized; /** * This value is required when writing * a linearized PDF file. * It represents the offset of the whitespace * character before the first line in the XRef * section. */ size_t m_lFirstInXRef; size_t m_lLinearizedOffset; size_t m_lLinearizedLastOffset; size_t m_lTrailerOffset; PdfVecObjects m_vecLinearized; }; // ----------------------------------------------------- // // ----------------------------------------------------- void PdfWriter::SetLinearized( bool bLinearize ) { m_bLinearized = bLinearize; } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfWriter::GetLinearized() const { return m_bLinearized; } // ----------------------------------------------------- // // ----------------------------------------------------- void PdfWriter::SetUseXRefStream( bool bStream ) { if( bStream && this->GetPdfVersion() < ePdfVersion_1_5 ) this->SetPdfVersion( ePdfVersion_1_5 ); m_bXRefStream = bStream; } // ----------------------------------------------------- // // ----------------------------------------------------- bool PdfWriter::GetUseXRefStream() const { return m_bXRefStream; } }; #endif // _PDF_WRITER_H_ podofo-0.9.3/src/podofo-base.h0000664000175000017500000000764312320241722016024 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2010 by Dominik Seichter * * domseichter@web.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library 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 Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * * In addition, as a special exception, the copyright holders give * * permission to link the code of portions of this program with the * * OpenSSL library under certain conditions as described in each * * individual source file, and distribute linked combinations * * including the two. * * You must obey the GNU General Public License in all respects * * for all of the code used other than OpenSSL. If you modify * * file(s) with this exception, you may extend this exception to your * * version of the file(s), but you are not obligated to do so. If you * * do not wish to do so, delete this exception statement from your * * version. If you delete this exception statement from all source * * files in the program, then also delete it here. * ***************************************************************************/ #ifndef _PODOFO_BASE_H_ #define _PODOFO_BASE_H_ // Include files from PoDoFo-base #include "base/PdfVersion.h" #include "base/PdfDefines.h" #include "base/Pdf3rdPtyForwardDecl.h" #include "base/PdfArray.h" #include "base/PdfCanvas.h" #include "base/PdfColor.h" #include "base/PdfContentsTokenizer.h" #include "base/PdfData.h" #include "base/PdfDataType.h" #include "base/PdfDate.h" #include "base/PdfDictionary.h" #include "base/PdfEncodingFactory.h" #include "base/PdfEncoding.h" #include "base/PdfEncrypt.h" #include "base/PdfError.h" #include "base/PdfExtension.h" #include "base/PdfFileStream.h" #include "base/PdfFilter.h" #include "base/PdfImmediateWriter.h" #include "base/PdfInputDevice.h" #include "base/PdfInputStream.h" #include "base/PdfLocale.h" #include "base/PdfMemoryManagement.h" #include "base/PdfMemStream.h" #include "base/PdfName.h" #include "base/PdfObject.h" #include "base/PdfObjectStreamParserObject.h" #include "base/PdfOutputDevice.h" #include "base/PdfOutputStream.h" #include "base/PdfParser.h" #include "base/PdfParserObject.h" #include "base/PdfRect.h" #include "base/PdfRefCountedBuffer.h" #include "base/PdfRefCountedInputDevice.h" #include "base/PdfReference.h" #include "base/PdfSigIncWriter.h" #include "base/PdfStream.h" #include "base/PdfString.h" #include "base/PdfTokenizer.h" #include "base/PdfVariant.h" #include "base/PdfVecObjects.h" #include "base/PdfWriter.h" #include "base/PdfXRef.h" #include "base/PdfXRefStream.h" #include "base/PdfXRefStreamParserObject.h" #endif // _PODOFO_BASE_H_ podofo-0.9.3/README.html0000664000175000017500000010472111725624277014526 0ustar dominikdominik PoDoFo Readme

PoDoFo

What is PoDoFo?

PoDoFo is a library to work with the PDF file format and includes also a few tools. The name comes from the first two letters of PDF (Portable Document Format).

The PoDoFo library is a free portable C++ library which includes classes to parse a PDF file and modify its contents into memory. The changes can be written back to disk easily. PoDoFo is designed to avoid loading large PDF objects into memory until they are required and can write large streams immediately to disk, so it is possible to manipulate quite large files with it. PoDoFo uses and relies on exceptions, so it must be built with them enabled.

Besides PDF parsing and writing PoDoFo includes also very simple classes to create your own PDF files. All classes are documented so it is easy to start writing your own application using PoDoFo.

PoDoFo is primarily useful for applications that wish to do lower level manipulation of PDF, such as extracting content or merging files. It's also useful if your application has specific requirements for it's PDF output that more general output-oriented libraries like Cairo cannot satisfy. Canvas/drawing support is currently very limited in PoDoFo, so for pure output tasks a library like Cairo will be more suitable. PoDoFo cannot render PDF, so you should look at a library like Poppler for that.

See:

The PoDoFo tools are simple tools build around the PoDoFo library. These tools are first of all examples on how to use the PoDoFo library in your own projects. But secondly they offer also features for working with PDF files. More tools will come with future release and the existing tools will gain more features. The following tools are currently available:

  • podofoencrypt - Encrypts any PDF and allows to set PDF permissions..
  • podofoimgextract - Extracts all images from a given PDF file.
  • podofoimpose - A powerful PDF imposition tool. It places pages from one or more source PDFs onto pages of a new PDF, applying scaling and positioning. If you have lua5.1 development libraries installed, it will be built with support for Lua plan files, which allow for mighty PDF transformations.
  • podofomerge - Merges two PDF files into onw.
  • podofopdfinfo - Provides some basic info about a PDF - metadata, page details, etc.
  • podofotxt2pdf - Converts a text file to a PDF
  • podofotxtextract - A tool that extracts all text from a PDF file. Works only for simple PDFs at the moment.
  • podofouncompress - Removes all compression filters from a PDF file. This is useful for debugging existing PDF files. You might also find PoDoFoBrowser, distributed separately, to be useful if you're using this tool a lot.

Additionally there is the external tool PoDoFoBrowser which is not included in this package, but can be downloaded from the PoDoFo webpage. PoDoFoBrowser is a Qt application for browsing and modifying the objects in a PDF file, examining the structure of PDF files, and manipulating PDF streams. It is very useful if you want to look on the internal structure of PDF files.

As of version 0.7 PoDoFo is available for Unix, Mac OS X and Windows platforms.

Where can I can get it?

PoDoFo is available on the internet: podofo.sf.net

Requirements

To build PoDoFo lib you need a working toolchain and a c++ compiler as well as the following libraries:

  • zlib
  • freetype2
  • fontconfig (Unix & Mac OS X only)
  • libjpeg (optional)
  • libtiff (optional)
  • libidn (optional)
  • libCrypto++ (optional)

See Installation with CMake for a list of tested platforms and compilers. In general, any reasonably well behaved C++ compiler should work.

A list of known -dev / -devel packages required for various Linux distros is maintained in the required Linux packages appendix.

See also Using PoDoFo.

Installation

Rather than using binary packages, you should usually build PoDoFo yourself. This ensures that it will be built with the same compiler and settings as your program. Because most platforms have no consistent C++ ABI or runtime libraries, this is important to ensure that you get a compatible STL, correct memory management between podofo and your app, etc.

PoDoFo is built and installed using CMake. The autotools build, Visual Studio project and XCode project were dropped as maintaining three unrelated and incompatible build systems that are exclusive to three different platforms consumes a lot of resources which can be spend better on improving PoDoFo itself. Even if you've never used CMake before, you'll find it pretty easy.

Unix users should generate Unix Makefiles with CMake, though it's also possible to produce a KDevelop project. See CMake builds on Linux/UNIX

If your application or library uses Visual Studio, CMake can be used to build a Visual Studio project you can use. Alternately, if you are using MinGW for your existing code, CMake can make you a MinGW makefile to build a mingw compatible version of PoDoFo. You must build PoDoFo with the same compiler as your application. See CMake builds on Windows

Mac OS X users will need to use CMake to generate a conventional UNIX build with Makefiles, or may generate an XCode project with CMake. See the Mac OS X section below, and the generic instructions for cmake builds

STLPort support

Don't know what STLPort is? Ignore it and skip this section. Packagers should not enable STLPort.

If your project uses STLPort rather than your platform/toolset's native STL, you must configure PoDoFo to use STLPort as well. Use the -DUSE_STLPORT=1 argument to configure. Do not enable STLPort for podofo unless you use it in your project; you will get an incompatible C++ STL leading to link errors, runtime crashes, or other problems.

It is unnecessary and unwise to build PoDoFo against STLPort on any current major platform unless you have a specific reason to do so.

Boost support

PoDoFo can make limited use of the Boost libraries if they are available. There is no need to use them, but some things may work more smoothly, and more use is expected in the future. If PoDoFo is built to use Boost, your application must also have Boost's headers (boost graph libraries) on its search path. Set -DWANT_BOOST:BOOL=1 to enable Boost support.

Packagers should not currently build PoDoFo with boost support.

Installation with CMake

PoDoFo has support for builds using CMake on all supported platforms. The CMake build has been tested on:

  • Visual C++ 9 Express Edition [Win32] ("Visual Studio 9 2008" target)
  • Visual C++ 8 Express Edition [Win32] ("Visual Studio 8 2005" target) (needs additional setup)
  • Visual C++ 8 Express +NMake [Win32] ("NMake Makefiles" target) (needs additional setup)
  • MinGW with GCC 3.4.2 [Win32] ("MinGW Makefiles" target)
  • gcc 3.3.5 [Linux: Debian 3.1] ("Unix Makefiles" target)
  • gcc 4.0, 4.1, 4.2 [Linux: Debian 4.0] ("Unix Makefiles" target)
  • gcc 4.0 [Mac OS X 10.4.10] ("Unix Makefiles" target)

PoDoFo is also known to build with Visual C++ 6 using CMake, though it is not regularly tested by the team so you might need to do some work to use a recent svn build.

You can use the CMake variable CMAKE_BUILD_TYPE to control the type of build. The main values supported are DEBUG and RELEASE. The default is DEBUG. Set the build type with the CMake argument:
  -DCMAKE_BUILD_TYPE=DEBUG
   or
  -DCMAKE_BUILD_TYPE=RELEASE
as appropriate.

You can control where the files are installed with `make install' with -DCMAKE_INSTALL_PREFIX=/path/to/install/dir

All instructons below use out-of-tree builds (recommended). To clean up an out-of-tree build, just delete the build directory, as no files are touched within the source directory.

On all Makefile-style builds, set the VERBOSE flag to 1 on the make command line to see all compiler commands etc, eg: make VERBOSE=1

CMake builds on Linux/UNIX

Linux and UNIX users should be able to build PoDoFo by cd'ing into the PoDoFo checkout or unpacked tarball directory (here assumed to be named "podofo-src") then running the build commands shown below. The CMake command below will install into $HOME/podofo to avoid needing root priveleges for installation, but you can change the destination to wherever you want or remove the install prefix setting to use the default.

To build and install:

mkdir ../podofo-build
cd ../podofo-build
cmake -G "Unix Makefiles" -DCMAKE_INSTALL_PREFIX="$HOME/podofo" ../podofo-src
make
make install

To see detailed compiler output, use:

make VERBOSE=1

If you're working on a 64 bit linux that has a /usr/lib64 directory, add -DWANT_LIB64:BOOL=TRUE to the CMake command line.

If you need to specify additional paths to search for libraries, set the CMAKE_INCLUDE_PATH and CMAKE_LIBRARY_PATH environment variables or set them on the command line:

cmake -G "Unix Makefiles" ../podofo-src \
	-DCMAKE_INCLUDE_PATH=/usr/sfw/include \
	-DCMAKE_LIBRARY_PATH=/usr/sfw/lib

If you wish to generate only a static library or only a shared library, set the PODOFO_BUILD_SHARED and/or PODOFO_BUILD_STATIC flags:

cmake -G "Unix Makefiles" ../podofo-src \
	-DCMAKE_INCLUDE_PATH=/usr/sfw/include \
	-DCMAKE_LIBRARY_PATH=/usr/sfw/lib \
	-DPODOFO_BUILD_SHARED:BOOL=TRUE \
	-DPODOFO_BUILD_STATIC:BOOL=FALSE

By default, with CMake 2.6.x all supported library types will be built where possible. Only the shared library will be built by default using 2.4.x because of a CMake limitation; you can build a static library instead with -DPODOFO_BUILD_STATIC:BOOL=TRUE, or upgrade to CMake 2.6.x .

Note that the instructions above run an out-of-tree build. CMake does support in-tree builds, but the use of out-of-tree builds is very strongly recommended.

If your system has gcc 4, PoDoFo will tell gcc to make symbols hidden by default using the -fvisibility=hidden flag to gcc. Only symbols explicitly exported by PoDoFo will be exported. You can explicitly enable or disable this behaviour with the boolean flag: -DPODOFO_USE_VISIBILITY=1 (or 0 for off). Enabling default hidden visibility reduces the PoDoFo binary size dramatically and improves link times. It also helps prevent accidental use of symbols that are not part of PoDoFo's public API. PoDoFo developers will also find this useful, as it will cause some mistakes to be reported as link errors that would otherwise go undetected and break the win32 builds.

CMake builds on Mac OS X

Mac OS X users can build PoDoFo using CMake either by generating conventional UNIX Makefiles (the "Unix Makefiles" CMake target) or generating an XCode project (the "Xcode" target). In either case the following applies.

You will need freetype and fontconfig. It's possible to omit the use of libjpeg (see the platform-independent documentation) but by default libjpeg will also be required. If you have these libraries already (say, from fink or DarwinPorts) you can skip the following section and update the CMAKE_INCLUDE_PATH and CMAKE_LIBRARY_PATH arguments appropriately.

Dependencies

I'll assume you're installing podofo and any required libraries into $HOME/libs . Adjust to taste, but keep it consistent.

The easiest way to get any required libraries is to use MacPorts to install the libjpeg, fontconfig, and freetype libraries. Once you've installed MacPorts, just run:

/opt/local/bin/port install fontconfig freetype jpeg tiff lua

MacPorts will automatically build the libraries and their dependencies, installing them in /opt/local.

If you want to distribute the libraries with your application, all you'll need to do is use install_name_tool to set appropriate relative paths for their linkage and include them in your application bundle - just like you do with any other libraries.

PoDoFo its self

You should be able to configure and install podofo on Mac OS X using:

	cmake -G "Unix Makefiles" \
		-DWANT_FONTCONFIG:BOOL=TRUE \
		-DCMAKE_INSTALL_PREFIX=/opt/podofo \
		-DCMAKE_INCLUDE_PATH=/opt/local/include \
		-DCMAKE_LIBRARY_PATH=/opt/local/lib \
		../podofo
	make
	sudo mkdir /opt/podofo
	sudo chown $USER /opt/podofo
	make install

change "Unix Makefiles" to "Xcode" if you want to build an XCode project instead, then instead of running `make' and `make install' just open the project file and work as normal

Homebrew builds on Mac OS X

For Homebrew (package manager for Mac OS X) it is quite simple to install podofo. Freetype2 and zlib should be installed on Mac OS X by default.

brew install fontconfig
brew install libjpeg
brew install libtiff
cd ((directory of podofo))
cmake -G "Unix Makefiles"
make
make install

CMake builds on Windows

Windows Dependencies

PoDoFo requires a couple of other open source libraries to work. At minimum it needs zlib and libjpeg. Additional functionality is enabled if libtiff and/or openssl are available.

zlib

Both MinGW and Visual Studio users should use the standard precompiled zlib dll from zlib.org. There is no need to compile your own.

Remember that you must ship zlib1.dll with your application. During testing it must be in the same directory as the PoDoFo-using executable or the directory containing it must be on your system PATH.

libjpeg

MinGW users can download the latest libjpeg installer from GnuWin32

.

For Visual Studio you will need to build libjpeg with your version of Visual Studio. Download the libjpeg sources from http://www.ijg.org/ and unpack them into a working directory. I'll assume you've used C:\Developer\jpeg. Once the sources are unpacked, start a visual studio command prompt and cd into c:\developer\jpeg then run copy jconfig.vc jconfig.h then nmake /f makefile.vc /a

.

If you use a DLL build of libjpeg remember that you must ship the DLL with your application. During testing the libjpeg dll must be in the same directory as the PoDoFo-using executable or the directory containing it must be on your system PATH. These requirements do not apply to the (recommended) static library libjpeg.

Building PoDoFo on Windows

Building PoDoFo on Windows can be done using MinGW (a minimalist gcc-based compliler environment for Windows) or Visual Studio. Other methods may work but have not been tested.

CMake 2.6.x is required for Windows. You can download it from cmake.org

.

Because the C++ ABIs of most of the win32 compilers are incompatible, you must build PoDoFo with the same compiler and version that you will use to build the programs linked to PoDoFo. Failure to follow this restriction will result in link errors at best, and bizarre runtime failures at worst.

On Windows, if you are linking against a shared (DLL) build of PoDoFo you MUST define the preprocessor macro USING_SHARED_PODOFO when including any podofo headers. Failure to do so will result in link time and/or runtime errors. Similarly, defining it when linking with a static PoDoFo can cause problems.

On Windows, PoDoFo may be built as either a shared or static library. Building both is not supported. By default only the shared library will be built. If you want a static library, just disable generation of the shared library with the extra argument to cmake:

	-DPODOFO_BUILD_SHARED=FALSE

PoDoFo will generally work correctly if you download pre-built libraries, such as those published by the GnuWin32 project, even if they were built with a different compiler. The primary exception is freetype, which should if at all possible be built using your compiler. Freetype provides a VC++ project file and is very easy to build. Make sure to build both the debug multi-threaded and release multi-threaded versions.

For release you should generally build your own copy of these libraries unless there is a well known and high quality pre-built version, like there is for zlib. If you have built your own libjpeg you can improve PoDoFo's use of it a bit by passing -DJPEG_COMPATIBLE_RUNTIME to CMake to tell PoDoFo it's safe not to use its' workarounds for incompatible runtimes.

Handling library naming on win32

Especially on Windows it is also common for custom built libraries to have different names to those you might download as pre-built copies. CMake won't be able to find them if they're called something else unless you tell it. Use these variables to tell CMake what names to look for a library under:

  • FREETYPE_LIBRARY_NAMES_DEBUG, FREETYPE_LIBRARY_NAMES_RELEASE and FREETYPE_LIBRARY_NAMES
  • TIFF_LIBRARY_NAMES_DEBUG, TIFF_LIBRARY_NAMES_RELEASE and TIFF_LIBRARY_NAMES
  • LIBJPEG_LIBRARY_NAMES_DEBUG, LIBJPEG_LIBRARY_NAMES_RELEASE and LIBJPEG_LIBRARY_NAMES
  • ZLIB_LIBRARY_NAMES_DEBUG, ZLIB_LIBRARY_NAMES_RELEASE, ZLIB_LIBRARY_NAMES

For example, a cmake command line might include -DFREETYPE_LIBRARY_NAMES_DEBUG=freetype239MT_D -DFREETYPE_LIBRARY_NAMES_RELEASE=freetype239MT . If you only have the release library, just use -DFREETYPE_LIBRARY_NAMES . Telling CMake which are debug and release libraries helps it ensure you link to the right libraries depending on build type, but that does no good if you don't have a debug library.

CMake builds on Windows with MinGW

To build PoDoFo with MinGW, you'll naturally need MinGW. The author recommends installing Qt 4 from Trolltech, which has a well packaged version of MinGW and is also useful for some PoDoFo tools like PoDoFoBrowser.

Once MinGW is set up, make sure that the MinGW "bin" directory is on your PATH, and be sure to set CMAKE_INCLUDE_PATH and CMAKE_LIBRARY_PATH such that CMake can find the headers and .lib files for the libraries PoDoFo requires. The GnuWin32 library packages from http://gnuwin32.sf.net/ are known to work with PoDoFo, so installing zlib, freetype, and libjpeg from there should do the trick.

To configure and build PoDoFo with a default GnuWin32 install and with MinGW already on your PATH:

md ..\podofo-debug
cd ..\podofo-debug
cmake -G "MinGW Makefiles" ..\podofo-src -DCMAKE_INCLUDE_PATH=c:\progra~1\gnuwin32\include -DCMAKE_LIBRARY_PATH=c:\progra~1\gnuwin32\lib -DPODOFO_BUILD_SHARED:BOOL=FALSE
mingw32-make

It is extremely strongly recommended that you build PoDoFo only as a static library if you are using MinGW by setting the -DPODOFO_BUILD_SHARED:BOOL=FALSE flag to cmake. libstdc++ on MinGW at the time of writing was not a shared library, causing serious issues with memory allocation and deallocation when C++ objects like std::string are passed by value across DLL boundaries or are otherwise deleted in a different DLL to where they were allocated. Of course, this will cause you problems if you intend to use PoDoFo across DLL boundaries, but until libstd++ is made shared on MinGW there's not much to be done. VC++ does not suffer from this issue.

CMake builds on Windows with Visual Studio

A Visual Studio build requires that Microsoft Visual Studio be installed. Visual Studio 9 2008 Express Edition is known to work, and is a free download from Microsoft. You should get zlib from zlib.org. If you want JPEG support, build your own libjpeg from sources or use the version from GnuWin32 (which will work OK, if a bit slower, despite being built with gcc). It is preferable to build your own copies of freetype, libjpeg and libtiff with your own compiler and bundle those copies.

You'll also need CMake 2.6.

If you're using Visual Studio you really should build your own freetype. With recent VC++ versions the GnuWin32 version of freetype is unlikely to work reliably. Download the sources from http://download.savannah.gnu.org/releases/freetype/ - you want something like ft245.zip . Unpack them and open builds\win32\visualc\freetype.sln in VC++, upgrading it if required. Build it in both debug multithreaded and release multithreaded modes. You should now see some .lib files in a subdirectory of the objs\win32\ directory. The following instructions will assume they're named freetype239MT.lib and freetype239MT_D.lib and are found in objs\win32\vc2008, so adjust if yours are different.

If you built a debug freetype, you will also need to copy vc90.pdb (assuming you're using VC++ 9, otherwise the name will vary) from objs\debug_mt\vc90.pdb to objs\win32\vc2008\ so that VC++ can find Freetype's debug info.

The visual studio build of PoDoFo has two stages - first, CMake is used to generate a Visual Studio solution, then the solution is built in VC++. I prefer to create a short build.cmd file for the CMake command since on Windows it tends to get rather long. Here's an example that assumes the build.cmd file is in an empty directory with ..\podofo-src being the relative path to the PoDoFo sources.

del cmakecache.txt
set FTDIR=C:\developer\freetype-2.3.5
set FTLIBDIR=C:\developer\freetype-2.3.5\objs\win32\vc2008
set JPEGDIR=C:\Developer\jpeg
set ZLIBDIR=C:\developer\zlib123-dll
cmake -G "Visual Studio 9 2008" ..\podofo-src -DCMAKE_INCLUDE_PATH="%FTDIR%\include;%JPEGDIR%\include;%JPEGDIR%;%ZLIBDIR%\include" -DCMAKE_LIBRARY_PATH="%FTLIBDIR%;%FTDIR%\lib;%JPEGDIR%\lib;%JPEGDIR%;%ZLIBDIR%\lib" -DPODOFO_BUILD_SHARED:BOOL=FALSE -DFREETYPE_LIBRARY_NAMES_DEBUG=freetype239MT_D -DFREETYPE_LIBRARY_NAMES_RELEASE=freetype239MT

Run the saved build.cmd from a cmd.exe window. If all goes well, you can open and build the generated podofo.sln in Visual Studio and build it.

Note that CMake should automatically find your Visual Studio install, so you shouldn't need any special settings unless you have an unusual setup or more than copy of the same version of Visual Studio installed.

You can download the free Visual C++ Express Edition 9 from Microsoft.

PROBLEMS?

If you have problems, try deleting your build directory then re-running the commands above after running:

set PATH=%SystemRoot%;%SystemRoot%\SYSTEM32

in the cmd.exe window you are using. If you do this you'll have to copy jpeg62.dll, freetype6.dll, and zlib.dll (names may vary; make sure they're the ones that match the LIB files you linked to) to the same folder as the .exe you are trying to run. This should resolve any issues caused by incompatible DLLs with the same names being present earlier on your PATH - a rather common issue if you have lots of open source software installed. Do this if you get unexplained crashes or errors about missing/mismatched ordinals.

CMake builds on Windows with NMake

PoDoFo can also be built with NMake. The build procedure is essentially the same as described for MinGW or Visual Studio, but you must use the target name "NMake Makefiles" and run "nmake" after CMake completes. Remember to run everything from within a Visual Studio environment shell or to run vcvarsall.bat before running CMake.

With Visual C++ Express Edition 8, you must also separately run setenv.cmd from the Win32 SDK. This is not required for Express Edition 9.

Using PoDoFo in Your Application

A simple example that uses PoDoFo can be found in examples/helloworld . You will also find the tests and tools shipped with PoDoFo informative when learning to use the library. Reading the documentation on PdfMemDocument, PdfStreamedDocument, PdfObject and PdfVariant may also be useful.

UNSTABLE API (IMPORTANT)

It is very important to understand that PoDoFo's 0.x's API is not stable from release to release. As such, rather than relying on a particular version of PoDoFo being shipped by the OS/distro that you are targeting, consider building and linking to your own private copy of PoDoFo. (Win32 developers will do this anyway). For example, between PoDoFo 0.5.0 and early PoDoFo 0.6.0svn, PdfDocument changed from being a concrete class to an abstract parent of PdfMemDocument and PdfStreamedDocument, thus breaking code that instantiates PdfDocument .

A good way to handle maintaining your own private copy if you use Subversion for your project is to use the svn:externals mechanism to automatically reference a specific revision of PoDoFo from podofo svn, or a particular tag . This permits you to control when you update to a new version and lets you make sure your code is updated for any API changes, without forcing users to go and find a specific version of PoDoFo. Alternately, you can just check the tree into your own revision control system and do periodic code drops. Have a look at PoDoFoBrowser for an example of the svn:externals approach.

If you statically link to podofo, that'll prevent any unexpected problems with linker paths. Another option on most platforms is to use rpath linking to ensure that a specific copy of the podofo library is preferred by the linker. CMake takes care of this automatically if you're using it for your project.

When PoDoFo reaches 1.x versions it is expected that API changes will be less frequent. At this point, though, they're an unavoidable part of improving and completing the library.

If you are using CMake in your project and you choose to bundle a copy of the PoDoFo sources, with svn:externals or otherwise, you can quite easily build a private copy of PoDoFo as part of your app's normal build process. Have a look at FindLIBPODOFO.cmake from PoDoFoBrowser to see how to do that, or just copy that file.

Compiling and Linking Against PoDoFo

PoDoFo's headers are designed to avoid exposing its library dependencies, so you do not need the headers for Freetype etc on the include path. However, you MUST link your application to podofo's required libraries on most platforms, eg on UNIX:

    -lpodofo -lfreetype -lfontconfig -ljpeg -lz

is generally appropriate. Win32 users must also ensure that they link to gdi32 and ws_win32.

Handling Exceptions

When working with PoDoFo it is important to remember that the library makes use of exceptions. Your code must be built with exception support and must be exception safe in areas that call PoDoFo. gcc users may not build with -fno-exceptions. If you have non-exception-safe code or code (such as pure C code) that cannot propagate exceptions your podofo-using code must catch all exceptions before they propagate to such unsafe sections. PoDoFo will throw a PdfError& for PoDoFo-specific exceptions. It may also propagate STL/runtime generated exceptions like std::bad_alloc, though it'll never throw them directly. PoDoFo cannot be built without exceptions.

More general information about exception handling is in the FAQ.

Preprocessor defines used in PoDoFo

Several preprocessor defines are used inside PoDoFo. This section tries to document all of them. These defines are set automatically by the CMake build system, so usually you do not have to worry about them.

Define Meaning
DEBUG Indicates a debug build of PoDoFo.
PODOFO_EXTRA_CHECKS Should we do lots of extra (expensive) sanity checking? You should not define this on production builds because of the runtime cost and because it might cause the library to abort() if it notices something nasty. It may also change the size of some objects, and is thus not binary compatible.
PODOFO_IS_LITTLE_ENDIAN This define is set on all little endian system and required on these systems for PoDoFo to work properly.
PODOFO_IS_BIG_ENDIAN This define is set on all big endian system and required on these systems for PoDoFo to work properly.
PODOFO_MULTI_THREAD Will compile PoDoFo with threading support, e.g. mutex that lock global variables.
PODOFO_VERBOSE_DEBUG This will cause PoDoFo to write even more debug output to the commandline.
HAVE_BOOST If defined PoDoFo is compiled with Boost support.
PODOFO_HAVE_JPEG_LIB If defined PoDoFo will use libJpeg to read and decode JPEG images.
PODOFO_HAVE_TIFF_LIB If defined PoDoFo will use libTiff to read and decode TIFF images.
PODOFO_HAVE_LUA If defined PoDoFoImpose will be built with Lua support for plan files.

Structure of the library

PoDoFo is structured into two libraries podofo-base and podofo-doc, where most users want to use podofo-doc which includes all the PoDoFo features and dependends on the podofo-base library.

If you only need basic PDF editing features and are not afraid of working with the object in a PDF file directly (see PdfObject), podofo-base is the right choice for you. It has only a few dependencies (zlib and libjpeg for compression). Contrary, podofo-doc provides you with a much richer and easier to use interface, but has some more dependencies to handle fonts and images. The image below shows the dependencies of each of the two libraries.

Architecture

Contact

If you have questions on PoDoFo or bug reports, feature requests you can email our mailinglist <podofo-users@lists.sf.net>. Sign up details are available on the podofo support page.

Licensing

The library is licensed under the LGPL (i.e. you may even use the shared library in closed sourced applications). The tests and tools which are included in PoDoFo are licensed under the GPL. See the files COPYING and COPYING.LIB for details. More detailed explanations are in the FAQ on the website, but the licenses have the final say.

Appendices

Required Linux Packages

Linux distros love to name their packages in various weird ways. Here are commands to install the required -dev or -devel packages for PoDoFo for various distros. Please send additions for reasonably recent distros to the PoDoFo mailing list.

  • Ubuntu (also generally applies to recent Debian)
    • 8.10 and most others: sudo aptitude install build-essential g++ cmake libz-dev libtiff-dev libjpeg-dev libfreetype6-dev libfontconfig-dev
podofo-0.9.3/INSTALL0000664000175000017500000000012310625114670013710 0ustar dominikdominikPlease see the file README for instruction on howto install PoDoFo on your system. podofo-0.9.3/tools/0000775000175000017500000000000012356565167014041 5ustar dominikdominikpodofo-0.9.3/tools/podofoimgextract/0000775000175000017500000000000012356565167017417 5ustar dominikdominikpodofo-0.9.3/tools/podofoimgextract/podofoimgextract.vcproj0000664000175000017500000000714610475170454024221 0ustar dominikdominik podofo-0.9.3/tools/podofoimgextract/CMakeLists.txt0000664000175000017500000000051310517314571022142 0ustar dominikdominikADD_EXECUTABLE(podofoimgextract ImageExtractor.cpp podofoimgextract.cpp) TARGET_LINK_LIBRARIES(podofoimgextract ${PODOFO_LIB}) SET_TARGET_PROPERTIES(podofoimgextract PROPERTIES COMPILE_FLAGS "${PODOFO_CFLAGS}") ADD_DEPENDENCIES(podofoimgextract ${PODOFO_DEPEND_TARGET}) INSTALL(TARGETS podofoimgextract RUNTIME DESTINATION "bin") podofo-0.9.3/tools/podofoimgextract/podofoimgextract.cpp0000664000175000017500000000451311306221052023454 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2005 by Dominik Seichter * * domseichter@web.de * * * * 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., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "ImageExtractor.h" #include #include #ifdef _HAVE_CONFIG #include #endif // _HAVE_CONFIG void print_help() { printf("Usage: podofoimgextract [inputfile] [outputdirectory]\n\n"); printf("\nPoDoFo Version: %s\n\n", PODOFO_VERSION_STRING); } int main( int argc, char* argv[] ) { char* pszInput; char* pszOutput; int nNum = 0; ImageExtractor extractor; if( argc != 3 ) { print_help(); exit( -1 ); } pszInput = argv[1]; pszOutput = argv[2]; try { extractor.Init( pszInput, pszOutput, &nNum ); } catch( PdfError & e ) { fprintf( stderr, "Error: An error %i ocurred during processing the pdf file.\n", e.GetError() ); e.PrintErrorMsg(); return e.GetError(); } nNum = extractor.GetNumImagesExtracted(); printf("Extracted %i images sucessfully from the PDF file.\n", nNum ); return 0; } podofo-0.9.3/tools/podofoimgextract/ImageExtractor.cpp0000664000175000017500000001231511336327135023027 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2005 by Dominik Seichter * * domseichter@web.de * * * * 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., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "ImageExtractor.h" #include #include #include #ifdef _MSC_VER #define snprintf _snprintf #endif ImageExtractor::ImageExtractor() : m_pszOutputDirectory( NULL ), m_nSuccess( 0 ), m_nCount( 0 ) { } ImageExtractor::~ImageExtractor() { } void ImageExtractor::Init( const char* pszInput, const char* pszOutput, int* pnNum ) { PdfObject* pObj = NULL; if( !pszInput || !pszOutput ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } PdfMemDocument document( pszInput ); m_pszOutputDirectory = const_cast(pszOutput); TCIVecObjects it = document.GetObjects().begin(); if( pnNum ) *pnNum = 0; while( it != document.GetObjects().end() ) { if( (*it)->IsDictionary() ) { PdfObject* pObjType = (*it)->GetDictionary().GetKey( PdfName::KeyType ); PdfObject* pObjSubType = (*it)->GetDictionary().GetKey( PdfName::KeySubtype ); if( ( pObjType && pObjType->IsName() && ( pObjType->GetName().GetName() == "XObject" ) ) || ( pObjSubType && pObjSubType->IsName() && ( pObjSubType->GetName().GetName() == "Image" ) ) ) { pObj = (*it)->GetDictionary().GetKey( PdfName::KeyFilter ); if( pObj && pObj->IsArray() && pObj->GetArray().GetSize() == 1 && pObj->GetArray()[0].IsName() && (pObj->GetArray()[0].GetName().GetName() == "DCTDecode") ) pObj = &pObj->GetArray()[0]; if( pObj && pObj->IsName() && ( pObj->GetName().GetName() == "DCTDecode" ) ) { // The only filter is JPEG -> create a JPEG file ExtractImage( *it, true ); } else { ExtractImage( *it, false ); } document.FreeObjectMemory( *it ); } } ++it; } } void ImageExtractor::ExtractImage( PdfObject* pObject, bool bJpeg ) { FILE* hFile = NULL; const char* pszExtension = bJpeg ? "jpg" : "ppm"; // Do not overwrite existing files: do { snprintf( m_szBuffer, MAX_PATH, "%s/pdfimage_%04i.%s", m_pszOutputDirectory, m_nCount++, pszExtension ); } while( FileExists( m_szBuffer ) ); hFile = fopen( m_szBuffer, "wb" ); if( !hFile ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } printf("-> Writing image object %s to the file: %s\n", pObject->Reference().ToString().c_str(), m_szBuffer); if( bJpeg ) { PdfMemStream* pStream = dynamic_cast(pObject->GetStream()); fwrite( pStream->Get(), pStream->GetLength(), sizeof(char), hFile ); } else { //long lBitsPerComponent = pObject->GetDictionary().GetKey( PdfName("BitsPerComponent" ) )->GetNumber(); // TODO: Handle colorspaces // Create a ppm image const char* pszPpmHeader = "P6\n# Image extracted by PoDoFo\n%li %li\n%li\n"; fprintf( hFile, pszPpmHeader, pObject->GetDictionary().GetKey( PdfName("Width" ) )->GetNumber(), pObject->GetDictionary().GetKey( PdfName("Height" ) )->GetNumber(), 255 ); char* pBuffer; pdf_long lLen; pObject->GetStream()->GetFilteredCopy( &pBuffer, &lLen ); fwrite( pBuffer, lLen, sizeof(char), hFile ); free( pBuffer ); } fclose( hFile ); ++m_nSuccess; } bool ImageExtractor::FileExists( const char* pszFilename ) { bool result = true; // if there is an error, it's probably because the file doesn't yet exist struct stat stBuf; if ( stat( pszFilename, &stBuf ) == -1 ) result = false; return result; } podofo-0.9.3/tools/podofoimgextract/ImageExtractor.h0000664000175000017500000000576011066250055022476 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2005 by Dominik Seichter * * domseichter@web.de * * * * 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., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #ifndef _IMAGE_EXTRACTOR_H_ #define _IMAGE_EXTRACTOR_H_ #include using namespace PoDoFo; #ifndef MAX_PATH #define MAX_PATH 512 #endif // MAX_PATH /** This class uses the PoDoFo lib to parse * a PDF file and to write all images it finds * in this PDF document to a given directory. */ class ImageExtractor { public: ImageExtractor(); virtual ~ImageExtractor(); /** * \param pnNum pointer to an integer were * the number of processed images can be stored * or null if you do not want this information. */ void Init( const char* pszInput, const char* pszOutput, int* pnNum = NULL ); /** * \returns the number of succesfully extracted images */ inline int GetNumImagesExtracted() const; private: /** Extracts the image form the given PdfObject * which has to be an XObject with Subtype "Image" * \param pObject a handle to a PDF object * \param bJpeg if true extract as a jpeg, otherwise create a ppm * \returns ErrOk on success */ void ExtractImage( PoDoFo::PdfObject* pObject, bool bJpeg ); /** This function checks wether a file with the * given filename does exist. * \returns true if the file exists otherwise false */ bool FileExists( const char* pszFilename ); private: char* m_pszOutputDirectory; unsigned int m_nSuccess; unsigned int m_nCount; char m_szBuffer[MAX_PATH]; }; inline int ImageExtractor::GetNumImagesExtracted() const { return m_nSuccess; } #endif // _IMAGE_EXTRACTOR_H_ podofo-0.9.3/tools/podofogc/0000775000175000017500000000000012356565167015641 5ustar dominikdominikpodofo-0.9.3/tools/podofogc/CMakeLists.txt0000664000175000017500000000041111515123365020357 0ustar dominikdominikADD_EXECUTABLE(podofogc podofogc.cpp) TARGET_LINK_LIBRARIES(podofogc ${PODOFO_LIB}) SET_TARGET_PROPERTIES(podofogc PROPERTIES COMPILE_FLAGS "${PODOFO_CFLAGS}") ADD_DEPENDENCIES(podofogc ${PODOFO_DEPEND_TARGET}) INSTALL(TARGETS podofogc RUNTIME DESTINATION "bin") podofo-0.9.3/tools/podofogc/podofogc.cpp0000664000175000017500000000675011515123365020137 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2010 by Ian Ashley * * Ian Ashley * * * * 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., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include #include #include using namespace std; using namespace PoDoFo; int main (int argc, char *argv[]) { PdfError::EnableLogging(true); PdfError::EnableDebug(true); PdfVecObjects objects; PdfParser parser( &objects ); objects.SetAutoDelete( true ); if( argc != 3 ) { cerr << "Usage: podofogc \n" << " Performs garbage collection on a PDF file.\n" << " All objects that are not reachable from within\n" << " the trailer are deleted.\n" << flush; return 0; } try { cerr << "Parsing " << argv[1] << " ... (this might take a while)" << flush; bool bIncorrectPw = false; std::string pw; do { try { if( !bIncorrectPw ) parser.ParseFile( argv[1], false ); else parser.SetPassword( pw ); bIncorrectPw = false; } catch( const PdfError & e ) { if( e.GetError() == ePdfError_InvalidPassword ) { cout << endl << "Password :"; std::getline( cin, pw ); cout << endl; // try to continue with the new password bIncorrectPw = true; } else throw e; } } while( bIncorrectPw ); cerr << " done" << endl; cerr << "Writing..." << flush; PdfWriter writer( &parser ); writer.SetPdfVersion( parser.GetPdfVersion() ); if( parser.GetEncrypted() ) { writer.SetEncrypted( *(parser.GetEncrypt()) ); } writer.Write( argv[2] ); cerr << " done" << endl; } catch( PdfError & e ) { e.PrintErrorMsg(); return e.GetError(); } cerr << "Parsed and wrote successfully" << endl; return EXIT_SUCCESS; } podofo-0.9.3/tools/podofotxt2pdf/0000775000175000017500000000000012356565167016643 5ustar dominikdominikpodofo-0.9.3/tools/podofotxt2pdf/podofotxt2pdf.vcproj0000664000175000017500000000673110475170454022670 0ustar dominikdominik podofo-0.9.3/tools/podofotxt2pdf/CMakeLists.txt0000664000175000017500000000044610517314571021373 0ustar dominikdominikADD_EXECUTABLE(podofotxt2pdf podofotxt2pdf.cpp) TARGET_LINK_LIBRARIES(podofotxt2pdf ${PODOFO_LIB}) SET_TARGET_PROPERTIES(podofotxt2pdf PROPERTIES COMPILE_FLAGS "${PODOFO_CFLAGS}") ADD_DEPENDENCIES(podofotxt2pdf ${PODOFO_DEPEND_TARGET}) INSTALL(TARGETS podofotxt2pdf RUNTIME DESTINATION "bin") podofo-0.9.3/tools/podofotxt2pdf/podofotxt2pdf.cpp0000664000175000017500000001367312347303775022156 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2005 by Dominik Seichter * * domseichter@web.de * * * * 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., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include #include #include using namespace PoDoFo; #ifdef _HAVE_CONFIG #include #endif // _HAVE_CONFIG #define BORDER_TOP 10000 * CONVERSION_CONSTANT #define BORDER_LEFT 10000 * CONVERSION_CONSTANT #define FONT_SIZE 12.0 #define DEFAULT_FONT "Arial" void print_help() { printf("Usage: podofotxt2pdf [inputfile] [outputfile]\n\n"); printf("Optional parameters:\n"); printf("\t-fontname [name]\t Use the font [name]\n"); printf("\t-utf8\t that specifies that the input text\n"); printf("\t\tis UTF8 encoded instead of Windows ANSI encoding.\n"); printf("\nPoDoFo Version: %s\n\n", PODOFO_VERSION_STRING); } void draw( char* pszBuffer, PdfDocument* pDocument, bool bUtf8, const char* pszFontName ) { PdfPage* pPage; PdfPainter painter; PdfFont* pFont; PdfRect size; const PdfEncoding* pEncoding; double dX = BORDER_LEFT; double dY = BORDER_TOP; char* pszStart = pszBuffer; if( bUtf8 ) { pEncoding = new PdfIdentityEncoding(); } else { pEncoding = PdfEncodingFactory::GlobalWinAnsiEncodingInstance(); } size = PdfPage::CreateStandardPageSize( ePdfPageSize_A4 ); pFont = pDocument->CreateFont( pszFontName, false, pEncoding ); pPage = pDocument->CreatePage( size ); dY = size.GetHeight() - dY; if( !pFont ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } pFont->SetFontSize( FONT_SIZE ); painter.SetPage( pPage ); painter.SetFont( pFont ); while( *pszBuffer ) { if( *pszBuffer == '\n' ) { if( bUtf8 ) { painter.DrawText( dX, dY, PdfString( reinterpret_cast(pszStart), pszBuffer-pszStart ) ); } else { painter.DrawText( dX, dY, pszStart, pszBuffer-pszStart ); } pszStart = (++pszBuffer); dY -= pFont->GetFontMetrics()->GetLineSpacing(); if( dY < BORDER_TOP ) { pPage = pDocument->CreatePage( size ); painter.SetPage( pPage ); dY = size.GetHeight() - dY; } } else ++pszBuffer; } painter.FinishPage(); } void init( const char* pszInput, const char* pszOutput, bool bUtf8, const char* pszFontName ) { FILE* hFile; PdfStreamedDocument doc( pszOutput ); char* pszBuf; size_t lSize; hFile = fopen( pszInput, "rb" ); // read it as binary if we are going to compare sizes! if( !hFile ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } fseek( hFile, 0x00, SEEK_END ); lSize = ftell( hFile ); pszBuf = static_cast(malloc( sizeof( char ) * (lSize+1) )); fseek( hFile, 0x00, SEEK_SET ); if( !pszBuf ) { PODOFO_RAISE_ERROR( ePdfError_OutOfMemory ); } // read the whole file into memory at once. // this not very efficient, but as this is // a library demonstration I do not care. // If anyone wants to improve this: Go for it! if( fread( pszBuf, sizeof(char), lSize, hFile ) != lSize ) { free( pszBuf ); PODOFO_RAISE_ERROR( ePdfError_UnexpectedEOF ); } fclose( hFile ); pszBuf[lSize] = '\0'; draw( pszBuf, &doc, bUtf8, pszFontName ); doc.GetInfo()->SetCreator( PdfString("podofotxt2pdf") ); doc.GetInfo()->SetTitle( PdfString("Converted to PDF from a text file") ); doc.Close(); free( pszBuf ); } int main( int argc, char* argv[] ) { const char* pszInput = NULL; const char* pszOutput = NULL; const char* pszFontName = DEFAULT_FONT; bool bUtf8 = false; if( argc < 3 ) { print_help(); exit( -1 ); } for(int i=1;i #include #include #include #ifdef _WIN32 # include # ifdef GetObject # undef GetObject # endif #else # include # include # include #endif // _WIN32 using namespace PoDoFo; #ifdef _HAVE_CONFIG #include #endif // _HAVE_CONFIG void print_help() { printf("Usage: podofocrop input.pdf output.pdf\n"); printf(" This tool will crop all pages.\n"); printf(" It requires ghostscript to be in your PATH\n"); printf("\nPoDoFo Version: %s\n\n", PODOFO_VERSION_STRING); } void crop_page( PdfPage* pPage, const PdfRect & rCropBox ) { PdfVariant var; /* printf("%f %f %f %f\n", rCropBox.GetLeft(), rCropBox.GetBottom(), rCropBox.GetWidth(), rCropBox.GetHeight()); */ rCropBox.ToVariant( var ); pPage->GetObject()->GetDictionary().AddKey( PdfName("MediaBox"), var ); } std::string get_ghostscript_output( const char* pszInput ) { std::string sOutput; const int lBufferLen = 256; char buffer[lBufferLen]; #ifdef _WIN32 DWORD count; char cmd[lBufferLen]; STARTUPINFO si; PROCESS_INFORMATION pi; ZeroMemory( &si, sizeof(si) ); si.cb = sizeof(si); ZeroMemory( &pi, sizeof(pi) ); // Fenster nicht sichtbar si.dwFlags=STARTF_USESHOWWINDOW; si.wShowWindow=SW_HIDE; // Ausgabe umleiten HANDLE pipe; CreatePipe(&pipe, 0, 0, 0 ); si.dwFlags|=STARTF_USESTDHANDLES; //si.hStdOutput=pipe_wr; si.hStdError = pipe; _snprintf(cmd, lBufferLen, "gs -dSAFER -sDEVICE=bbox -sNOPAUSE -q %s -c quit", pszInput); printf("Running %s\n", cmd ); if( !CreateProcess( NULL, cmd, NULL, NULL, TRUE, CREATE_DEFAULT_ERROR_MODE, NULL, NULL, &si, &pi ) ) { printf("CreateProcess failed."); exit(1); } while( ReadFile(pipe,buffer,lBufferLen,&count,NULL) && GetLastError() != ERROR_BROKEN_PIPE && count > 0) { printf("%s",buffer); sOutput.append( buffer, count ); } // eigenes Handle schliessen CloseHandle(pipe); CloseHandle( pi.hProcess ); CloseHandle( pi.hThread ); #else pid_t pid; int p[2]; int count; pipe( p ); if( (pid = fork()) == 0 ) { // Child, launch ghostscript close( p[0] ); // Close unused read end dup2(p[1], 2); // redirect stderr to stdout dup2(p[1], 1); //printf("HELLO\n"); execlp( "gs", "gs", "-dSAFER", "-sDEVICE=bbox", "-sNOPAUSE", "-q", pszInput, "-c", "quit", NULL ); printf("Fatal error, cannot launch ghostscript\n"); exit(0); } else { close( p[1] ); // Close unused write end while( (count = read( p[0], buffer, lBufferLen )) > 0 ) { sOutput.append( buffer, count ); } wait(NULL); } #endif // _WIN32 return sOutput; } std::vector get_crop_boxes( const char* pszInput ) { std::vector rects; std::string sOutput = get_ghostscript_output( pszInput ); std::stringstream ss(sOutput); std::string sLine; PdfRect curRect; bool bHaveRect = false; while(std::getline(ss, sLine)) { if( strncmp( "%%BoundingBox: ", sLine.c_str(), 15 ) == 0 ) { int x, y, w, h; sscanf(sLine.c_str()+15, "%i %i %i %i\n", &x, &y, &w, &h); curRect = PdfRect( static_cast(x), static_cast(y), static_cast(w-x), static_cast(h-y) ); bHaveRect = true; } else if( strncmp( "%%HiResBoundingBox: ", sLine.c_str(), 17 ) == 0 ) { if( bHaveRect ) { // I have no idea, while gs writes BoundingBoxes twice to stdout .. printf("Using bounding box: [ %f %f %f %f ]\n", curRect.GetLeft(), curRect.GetBottom(), curRect.GetWidth(), curRect.GetHeight()); rects.push_back( curRect ); bHaveRect = false; } } } return rects; } int main( int argc, char* argv[] ) { PdfError::EnableDebug( false ); if( argc != 3 ) { print_help(); exit( -1 ); } const char* pszInput = argv[1]; const char* pszOutput = argv[2]; try { printf("Cropping file:\t%s\n", pszInput); printf("Writing to :\t%s\n", pszOutput); std::vector cropBoxes = get_crop_boxes( pszInput ); PdfMemDocument doc; doc.Load( pszInput ); if( static_cast(cropBoxes.size()) != doc.GetPageCount() ) { printf("Number of cropboxes obtained form ghostscript does not match with page count (%i, %i)\n", static_cast(cropBoxes.size()), doc.GetPageCount() ); PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } for( int i=0;i Lua is parsing page:", n + 1) end function end_page (n) -- Do nothing end function start_xobjext () -- Do nothing end function end_xobject () -- Do nothing end -- This method is called whenever a gray stroking color is set -- using the 'G' PDF command. -- -- @param a grayscale color object -- @returns a new color which should be set instead (any colorspace) function set_stroking_color_gray (g) -- Convert all gray values to RGB red local a = { 1.0,0.0,0.0 } return a end -- This method is called whenever a rgb stroking color is set -- using the 'RG' PDF command. -- -- @param a rgb color object -- @returns a new color which should be set instead (any colorspace) function set_stroking_color_rgb (r,g,b) -- convert all black rgb values to cmyk, -- leave other as they are if r == 0 and g == 0 and b == 0 then return { 0.0, 0.0, 0.0, 1.0 } else return { r,g,b } end end -- This method is called whenever a cmyk stroking color is set -- using the 'K' PDF command. -- -- @param a cmyk color object -- @returns a new color which should be set instead (any colorspace) function set_stroking_color_cmyk (c,m,y,k) -- do not change color, -- just return input values again return { c,m,y,k } end -- This method is called whenever a gray non-stroking color is set -- using the 'g' PDF command. -- -- @param a grayscale color object -- @returns a new color which should be set instead (any colorspace) function set_non_stroking_color_gray (g) -- do not change color, -- just return input values again return { g } end -- This method is called whenever a rgb stroking color is set -- using the 'rg' PDF command. -- -- @param a rgb color object -- @returns a new color which should be set instead (any colorspace) function set_non_stroking_color_rgb (r,g,b) -- Handle stroking and non-stroking rgb values in the same way local c = set_stroking_color_rgb (r,g,b) return c end -- This method is called whenever a cmyk non-stroking color is set -- using the 'k' PDF command. -- -- @param a cmyk color object -- @returns a new color which should be set instead (any colorspace) function set_non_stroking_color_cmyk (c,m,y,k) -- do not change color, -- just return input values again return { c,m,y,k } end -- This method converts a given RGB color to CMYK -- The conversion is like a maximal -- under color removal -- http://en.wikipedia.org/wiki/Under_color_removal -- according to PoDoFo PdfColor::ConvertToCMYK() -- -- @param a rgb color object -- @returns the new CMYK color function ConvertRGBtoCMYK(r,g,b) -- local k = math.min( 1.0-r, math.min( 1.0-g, 1.0-b ) ) local k = math.min( 1.0-r, 1.0-g, 1.0-b ) local c = 0.0 local m = 0.0 local y = 0.0 if k < 1.0 then c = (1.0 - r - k) / (1.0 - k) m = (1.0 - g - k) / (1.0 - k) y = (1.0 - b - k) / (1.0 - k) end return { c, m, y, k } end -- This method converts a given RGB color to Gray -- according to PoDoFo PdfColor::ConvertToGrayScale() -- -- @param a rgb color object -- @returns the new GrayScale color function ConvertRGBtoGrayScale(r,g,b) return { 0.299*r + 0.587*g + 0.114*b } end -- Check if the given Color is nearly Gray -- IsNearlyGray(0.126,0.127,0.128, 0.002) = true -- IsNearlyGray(0.125,0.127,0.128, 0.002) = false -- -- @param a rgb color object plus a tolerance-value -- @returns true or false function IsNearlyGray(r,g,b,t) local min = math.min( r,g,b ) local max = math.max( r,g,b ) if max - min <= t and max - min >= -t then return true else return false end end -- Check if the given RGB Color1 is nearly RGB Color2 -- -- @param two rgb colors plus a tolerance-value -- @returns true or false function IsNearlyTheSameRGB(r1,g1,b1, r2,g2,b2, t) local rMin = math.min( r1,r2 ) local rMax = math.max( r1,r2 ) local rSame = false local gMin = math.min( g1,g2 ) local gMax = math.max( g1,g2 ) local gSame = false local bMin = math.min( b1,b2 ) local bMax = math.max( b1,b2 ) local bSame = false if rMax - rMin <= t and rMax - rMin >= -t then rSame = true end if gMax - gMin <= t and gMax - gMin >= -t then gSame = true end if bMax - bMin <= t and bMax - bMin >= -t then bSame = true end if rSame and gSame and bSame then return true else return false end end podofo-0.9.3/tools/podofocolor/lua_compat.h0000664000175000017500000000225212205457547020657 0ustar dominikdominikextern "C" { #include "lua.h" // Note: If you're missing these, you're using lua 5.0 and haven't installed // the extension libraries. #include "lualib.h" #include "lauxlib.h" } #if !defined(LUA_VERSION_NUM) // Old lua without numeric version #define LUA_VERSION_NUM 0 #endif // Handle an API difference in the lua_open call between // Lua 5.1 and Lua 5.2. #if LUA_VERSION_NUM >= 502 inline lua_State* imp_lua_open(void) { return luaL_newstate(); } inline size_t imp_lua_objlen(lua_State *L, int index) { return lua_rawlen(L, index); } #else inline lua_State* imp_lua_open(void) { return lua_open(); } inline size_t imp_lua_objlen(lua_State *L, int index) { return lua_objlen(L, index); } #endif // Handle an API difference in the dofile and getn calls between // Lua 5.0 and Lua 5.1. #if LUA_VERSION_NUM >= 501 inline int imp_lua_dofile(lua_State* L, const char * path) { return luaL_dofile(L, path); } inline int imp_lua_getn(lua_State *L, int t) { return imp_lua_objlen(L, t); } #else inline int imp_lua_dofile(lua_State* L, const char * path) { return lua_dofile(L, path); } inline int imp_lua_getn(lua_State *L, int t) { return luaL_getn(L, t); } #endif podofo-0.9.3/tools/podofocolor/podofocolor.cpp0000664000175000017500000000746711506672210021415 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2010 by Dominik Seichter * * domseichter@web.de * * * * 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., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "podofo.h" #include #include #include #include "podofo_config.h" #include "colorchanger.h" #include "dummyconverter.h" #include "grayscaleconverter.h" #ifdef PODOFO_HAVE_LUA #include "luaconverter.h" #endif // PODOFO_HAVE_LUA static void print_help() { std::cerr << "Usage: podofocolor [converter] [inputfile] [outpufile]\n"; #ifdef PODOFO_HAVE_LUA std::cerr << "\t[converter] can be one of: dummy|grayscale|lua [planfile]\n"; #else std::cerr << "\t[converter] can be one of: dummy|grayscale\n"; #endif // PODOFO_HAVE_LUA std::cerr << "\tpodofocolor is a tool to change all colors in a PDF file based on a predefined or Lua description.\n"; std::cerr << "\nPoDoFo Version: "<< PODOFO_VERSION_STRING <<"\n\n"; } /** * @return a converter implementation or NULL if unknown */ static IConverter* ConverterForName( const std::string & converter, const std::string & lua ) { IConverter* pConverter = NULL; if( converter == "dummy" ) { pConverter = new DummyConverter(); } else if( converter == "grayscale" ) { pConverter = new GrayscaleConverter(); } #ifdef PODOFO_HAVE_LUA else if( converter == "lua" ) { pConverter = new LuaConverter( lua ); } #endif // PODOFO_HAVE_LUA return pConverter; } int main( int argc, char* argv[] ) { if( !(argc == 4 || argc == 5) ) { print_help(); exit( -1 ); } std::string converter = argv[1]; std::string input = argv[2]; std::string output = argv[3]; std::string lua; if( argc == 4 && converter != "lua" ) { input = argv[2]; output = argv[3]; } #ifdef PODOFO_HAVE_LUA else if( argc == 5 && converter == "lua" ) { lua = argv[2]; input = argv[3]; output = argv[4]; } #endif // PODOFO_HAVE_LUA else { print_help(); exit( -3 ); } IConverter* pConverter = ConverterForName( converter, lua ); if( !pConverter ) { std::cerr << "Aborting! Unknown converter: " << converter << std::endl; print_help(); exit( -2 ); } try { ColorChanger cc(pConverter, input, output); cc.start(); } catch( PoDoFo::PdfError & e ) { std::cerr << "Error: An error "<< e.GetError() <<" ocurred during processing the pdf file\n"; e.PrintErrorMsg(); return e.GetError(); } delete pConverter; return 0; } podofo-0.9.3/tools/podofocolor/CMakeLists.txt0000664000175000017500000000114611511141604021102 0ustar dominikdominikSET(color_srcs podofocolor.cpp colorchanger.cpp colorspace.cpp graphicsstack.cpp iconverter.cpp dummyconverter.cpp grayscaleconverter.cpp ) SET(color_extra_libs) IF(LUA_FOUND) SET(color_extra_libs ${LUA_LIBRARIES}) SET(color_srcs ${color_srcs} luaconverter.cpp) ENDIF(LUA_FOUND) ADD_EXECUTABLE(podofocolor ${color_srcs} ) TARGET_LINK_LIBRARIES(podofocolor ${PODOFO_LIB} ${color_extra_libs} ) SET_TARGET_PROPERTIES(podofocolor PROPERTIES COMPILE_FLAGS "${PODOFO_CFLAGS}") ADD_DEPENDENCIES(podofocolor ${PODOFO_DEPEND_TARGET}) INSTALL(TARGETS podofocolor RUNTIME DESTINATION "bin") podofo-0.9.3/tools/podofocolor/grayscaleconverter.h0000664000175000017500000000675511506670673022451 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2010 by Dominik Seichter * * domseichter@web.de * * * * 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., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #ifndef _GRAYSCALE_CONVERTER_H_ #define _GRAYSCALE_CONVERTER_H_ #include "iconverter.h" /** * A converter which converts every color to its grayscale value. */ class GrayscaleConverter : public IConverter { public: GrayscaleConverter(); virtual ~GrayscaleConverter(); /** * A helper method that is called to inform the converter * when a new page is analyzed. * * @param pPage page object * @param nPageIndex index of the page in the document */ virtual void StartPage( PoDoFo::PdfPage* pPage, int nPageIndex ); /** * A helper method that is called to inform the converter * when a new page has been analyzed completely. * * @param pPage page object * @param nPageIndex index of the page in the document */ virtual void EndPage( PoDoFo::PdfPage* pPage, int nPageIndex ); /** * A helper method that is called to inform the converter * when a new xobjext is analyzed. * * @param pObj the xobject */ virtual void StartXObject( PoDoFo::PdfXObject* pObj ); /** * A helper method that is called to inform the converter * when a xobjext has been analyzed. * * @param pObj the xobject */ virtual void EndXObject( PoDoFo::PdfXObject* pObj ); /** * This method is called whenever a gray stroking color is set * using the 'G' PDF command. * * @param a grayscale color object * @returns a new color which should be set instead (any colorspace) */ virtual PoDoFo::PdfColor SetStrokingColorGray( const PoDoFo::PdfColor & rColor ); virtual PoDoFo::PdfColor SetStrokingColorRGB( const PoDoFo::PdfColor & rColor ); virtual PoDoFo::PdfColor SetStrokingColorCMYK( const PoDoFo::PdfColor & rColor ); virtual PoDoFo::PdfColor SetNonStrokingColorGray( const PoDoFo::PdfColor & rColor ); virtual PoDoFo::PdfColor SetNonStrokingColorRGB( const PoDoFo::PdfColor & rColor ); virtual PoDoFo::PdfColor SetNonStrokingColorCMYK( const PoDoFo::PdfColor & rColor ); }; #endif // _GRAYSCALE_CONVERTER_H_ podofo-0.9.3/tools/podofocolor/luaconverter.cpp0000664000175000017500000001752712205457547021612 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2010 by Dominik Seichter * * domseichter@web.de * * * * 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., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "luaconverter.h" // Note: this is *not* lua.hpp shipped with lua 5.1, it's a wrapper // header we use to handle version differences between lua 5.1 and lua // 5.0 . #include "lua_compat.h" #include #include using namespace PoDoFo; #define FUNCTION_START_PAGE "start_page" #define FUNCTION_END_PAGE "end_page" #define FUNCTION_START_XOBJECT "start_xobject" #define FUNCTION_END_XOBJECT "end_xobject" #define FUNCTION_SET_STROKING_GRAY "set_stroking_color_gray" #define FUNCTION_SET_STROKING_RGB "set_stroking_color_rgb" #define FUNCTION_SET_STROKING_CMYK "set_stroking_color_cmyk" #define FUNCTION_SET_NON_STROKING_GRAY "set_non_stroking_color_gray" #define FUNCTION_SET_NON_STROKING_RGB "set_non_stroking_color_rgb" #define FUNCTION_SET_NON_STROKING_CMYK "set_non_stroking_color_cmyk" LuaMachina::LuaMachina() { /* Init the Lua interpreter */ L = imp_lua_open(); if (!L) { throw std::runtime_error("Whoops! Failed to open lua!"); } /* Init the Lua libraries we want users to have access to. * Note that the `os' and `io' libraries MUST NOT be included, * as providing access to those libraries to the user would * make running plan files unsafe. */ luaopen_base(L); luaopen_table(L); luaopen_string(L); luaopen_math(L); } LuaMachina::~LuaMachina() { lua_close(L); } LuaConverter::LuaConverter( const std::string & sLuaScript ) : IConverter() { if( imp_lua_dofile(m_machina.State(), sLuaScript.c_str()) ) { std::cerr << "Unable to process Lua script:\"" << lua_tostring(m_machina.State(), -1)<<"\"" << std::endl; } } LuaConverter::~LuaConverter() { } void LuaConverter::StartPage( PdfPage*, int nPageNumber ) { lua_getglobal( m_machina.State(), FUNCTION_START_PAGE ); lua_pushnumber( m_machina.State(), static_cast(nPageNumber) ); // Lua 5.1 only //lua_pushinteger( m_machina.State(), nPageNumber ); lua_call( m_machina.State(), 1, 0 ); } void LuaConverter::EndPage( PdfPage*, int nPageNumber ) { lua_getglobal( m_machina.State(), FUNCTION_END_PAGE ); lua_pushnumber( m_machina.State(), static_cast(nPageNumber) ); // Lua 5.1 only //lua_pushinteger( m_machina.State(), nPageNumber ); lua_call( m_machina.State(), 1, 0 ); } void LuaConverter::StartXObject( PdfXObject* ) { lua_getglobal( m_machina.State(), FUNCTION_START_XOBJECT ); lua_call( m_machina.State(), 0, 0 ); } void LuaConverter::EndXObject( PdfXObject* ) { lua_getglobal( m_machina.State(), FUNCTION_END_XOBJECT ); lua_call( m_machina.State(), 0, 0 ); } PdfColor LuaConverter::GetColorFromReturnValue(const char* pszFunctionName) { int top; double value; std::vector colors; size_t len; luaL_checktype(m_machina.State(), 1, LUA_TTABLE); len = imp_lua_getn( m_machina.State(), -1 ); // Lua 5.1 only //len = lua_objlen( m_machina.State(), -1 ); for( int i = 1; i <= static_cast(len); i++ ) { lua_rawgeti( m_machina.State(), -1, i ); top = lua_gettop( m_machina.State() ); value = static_cast(lua_tonumber(m_machina.State(), top)); lua_pop(m_machina.State(), 1); colors.push_back( value ); } switch( len ) { case 1: return PdfColor( colors[0] ); case 3: return PdfColor( colors[0], colors[1], colors[2] ); case 4: return PdfColor( colors[0], colors[1], colors[2], colors[3] ); default: { PdfError::LogMessage( eLogSeverity_Error, "Array length is %i returned by %s.\n", len, pszFunctionName ); PODOFO_RAISE_ERROR_INFO( ePdfError_CannotConvertColor, "Arrays returned from Lua must be { g }, { r,g,b } or { c,m,y,k }!" ); break; } } return PdfColor(); } PdfColor LuaConverter::SetStrokingColorGray( const PdfColor & rColor ) { lua_getglobal( m_machina.State(), FUNCTION_SET_STROKING_GRAY ); lua_pushnumber( m_machina.State(), rColor.GetGrayScale() ); lua_call( m_machina.State(), 1, 1 ); return this->GetColorFromReturnValue( FUNCTION_SET_STROKING_GRAY ); } PdfColor LuaConverter::SetStrokingColorRGB( const PdfColor & rColor ) { lua_getglobal( m_machina.State(), FUNCTION_SET_STROKING_RGB ); lua_pushnumber( m_machina.State(), rColor.GetRed() ); lua_pushnumber( m_machina.State(), rColor.GetGreen() ); lua_pushnumber( m_machina.State(), rColor.GetBlue() ); lua_call( m_machina.State(), 3, 1 ); return this->GetColorFromReturnValue( FUNCTION_SET_STROKING_RGB ); } PdfColor LuaConverter::SetStrokingColorCMYK( const PdfColor & rColor ) { lua_getglobal( m_machina.State(), FUNCTION_SET_STROKING_CMYK ); lua_pushnumber( m_machina.State(), rColor.GetCyan() ); lua_pushnumber( m_machina.State(), rColor.GetMagenta() ); lua_pushnumber( m_machina.State(), rColor.GetYellow() ); lua_pushnumber( m_machina.State(), rColor.GetBlack() ); lua_call( m_machina.State(), 4, 1 ); return this->GetColorFromReturnValue( FUNCTION_SET_STROKING_CMYK ); } PdfColor LuaConverter::SetNonStrokingColorGray( const PdfColor & rColor ) { lua_getglobal( m_machina.State(), FUNCTION_SET_NON_STROKING_GRAY ); lua_pushnumber( m_machina.State(), rColor.GetGrayScale() ); lua_call( m_machina.State(), 1, 1 ); return this->GetColorFromReturnValue( FUNCTION_SET_NON_STROKING_GRAY ); } PdfColor LuaConverter::SetNonStrokingColorRGB( const PdfColor & rColor ) { lua_getglobal( m_machina.State(), FUNCTION_SET_NON_STROKING_RGB ); lua_pushnumber( m_machina.State(), rColor.GetRed() ); lua_pushnumber( m_machina.State(), rColor.GetGreen() ); lua_pushnumber( m_machina.State(), rColor.GetBlue() ); lua_call( m_machina.State(), 3, 1 ); return this->GetColorFromReturnValue( FUNCTION_SET_NON_STROKING_RGB ); } PdfColor LuaConverter::SetNonStrokingColorCMYK( const PdfColor & rColor ) { lua_getglobal( m_machina.State(), FUNCTION_SET_NON_STROKING_CMYK ); lua_pushnumber( m_machina.State(), rColor.GetCyan() ); lua_pushnumber( m_machina.State(), rColor.GetMagenta() ); lua_pushnumber( m_machina.State(), rColor.GetYellow() ); lua_pushnumber( m_machina.State(), rColor.GetBlack() ); lua_call( m_machina.State(), 4, 1 ); return this->GetColorFromReturnValue( FUNCTION_SET_NON_STROKING_CMYK ); } podofo-0.9.3/tools/podofocolor/colorspace.cpp0000664000175000017500000000444011511141604021200 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2010 by Dominik Seichter * * domseichter@web.de * * * * 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., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "colorspace.h" using namespace PoDoFo; ColorSpace::ColorSpace() : m_name("DeviceGray") { } ColorSpace::ColorSpace(const PdfName & rName) : m_name(rName) { } ColorSpace::ColorSpace(const ColorSpace & rhs) { this->operator=(rhs); } ColorSpace::~ColorSpace() { } const ColorSpace & ColorSpace::operator=(const ColorSpace & rhs) { m_name = rhs.m_name; return *this; } bool ColorSpace::IsSimpleColorSpace() const { EPdfColorSpace eColorSpace = this->ConvertToPdfColorSpace(); if( eColorSpace == ePdfColorSpace_DeviceGray || eColorSpace == ePdfColorSpace_DeviceRGB || eColorSpace == ePdfColorSpace_DeviceCMYK ) { return true; } else { return false; } } EPdfColorSpace ColorSpace::ConvertToPdfColorSpace() const { return PdfColor::GetColorSpaceForName(m_name); } podofo-0.9.3/tools/podofocolor/graphicsstack.h0000664000175000017500000001153411506670673021364 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2010 by Dominik Seichter * * domseichter@web.de * * * * 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., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #ifndef _GRAPHICSSTACK_H_ #define _GRAPHICSSTACK_H_ #include #include class GraphicsStack { class TGraphicsStackElement { public: TGraphicsStackElement() : m_strokingColor( PoDoFo::PdfColor( 0.0 ) ), m_nonStrokingColor( PoDoFo::PdfColor( 0.0 ) ), m_eColorSpaceStroking( PoDoFo::ePdfColorSpace_DeviceGray ), m_eColorSpaceNonStroking( PoDoFo::ePdfColorSpace_DeviceGray ) { } TGraphicsStackElement( const TGraphicsStackElement & rhs ) { this->operator=(rhs); } const TGraphicsStackElement & operator=( const TGraphicsStackElement & rhs ) { m_strokingColor = rhs.m_strokingColor; m_nonStrokingColor = rhs.m_nonStrokingColor; m_eColorSpaceStroking = rhs.m_eColorSpaceStroking; m_eColorSpaceNonStroking = rhs.m_eColorSpaceNonStroking; return *this; } inline const PoDoFo::PdfColor & GetStrokingColor() { return m_strokingColor; } inline const PoDoFo::PdfColor & GetNonStrokingColor() { return m_nonStrokingColor; } inline PoDoFo::EPdfColorSpace GetStrokingColorSpace() { return m_eColorSpaceStroking; } inline PoDoFo::EPdfColorSpace GetNonStrokingColorSpace() { return m_eColorSpaceNonStroking; } inline void SetStrokingColor( const PoDoFo::PdfColor & c ) { m_strokingColor = c; } inline void SetNonStrokingColor( const PoDoFo::PdfColor & c ) { m_nonStrokingColor = c; } inline void SetStrokingColorSpace( PoDoFo::EPdfColorSpace eCS ) { m_eColorSpaceStroking = eCS; } inline void SetNonStrokingColorSpace( PoDoFo::EPdfColorSpace eCS ) { m_eColorSpaceNonStroking = eCS; } private: PoDoFo::PdfColor m_strokingColor; PoDoFo::PdfColor m_nonStrokingColor; PoDoFo::EPdfColorSpace m_eColorSpaceStroking; PoDoFo::EPdfColorSpace m_eColorSpaceNonStroking; }; public: GraphicsStack(); ~GraphicsStack(); void Push(); void Pop(); inline const PoDoFo::PdfColor & GetStrokingColor() { return GetCurrentGraphicsState().GetStrokingColor(); } inline const PoDoFo::PdfColor & GetNonStrokingColor() { return GetCurrentGraphicsState().GetNonStrokingColor(); } inline PoDoFo::EPdfColorSpace GetStrokingColorSpace() { return GetCurrentGraphicsState().GetStrokingColorSpace(); } inline PoDoFo::EPdfColorSpace GetNonStrokingColorSpace() { return GetCurrentGraphicsState().GetNonStrokingColorSpace(); } inline void SetStrokingColor( const PoDoFo::PdfColor & c ) { GetCurrentGraphicsState().SetStrokingColor( c ); } inline void SetNonStrokingColor( const PoDoFo::PdfColor & c ) { GetCurrentGraphicsState().SetNonStrokingColor( c ); } inline void SetStrokingColorSpace( PoDoFo::EPdfColorSpace eCS ) { GetCurrentGraphicsState().SetStrokingColorSpace( eCS ); } inline void SetNonStrokingColorSpace( PoDoFo::EPdfColorSpace eCS ) { GetCurrentGraphicsState().SetNonStrokingColorSpace( eCS ); } private: TGraphicsStackElement & GetCurrentGraphicsState(); private: std::stack m_stack; }; #endif // _GRAPHICSSTACK_H_ podofo-0.9.3/tools/podofocolor/iconverter.h0000664000175000017500000001122711506670673020715 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2010 by Dominik Seichter * * domseichter@web.de * * * * 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., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #ifndef _ICONVERTER_H_ #define _ICONVERTER_H_ #include /** * Interface for a converter that can be used * together with a ColorChanger object * to convert colors in a PDF file. */ class IConverter { public: IConverter(); virtual ~IConverter(); /** * A helper method that is called to inform the converter * when a new page is analyzed. * * @param pPage page object * @param nPageIndex index of the page in the document */ virtual void StartPage( PoDoFo::PdfPage* pPage, int nPageIndex ) = 0; /** * A helper method that is called to inform the converter * when a new page has been analyzed completely. * * @param pPage page object * @param nPageIndex index of the page in the document */ virtual void EndPage( PoDoFo::PdfPage* pPage, int nPageIndex ) = 0; /** * A helper method that is called to inform the converter * when a new xobjext is analyzed. * * @param pObj the xobject */ virtual void StartXObject( PoDoFo::PdfXObject* pObj ) = 0; /** * A helper method that is called to inform the converter * when a xobjext has been analyzed. * * @param pObj the xobject */ virtual void EndXObject( PoDoFo::PdfXObject* pObj ) = 0; /** * This method is called whenever a gray stroking color is set * using the 'G' PDF command. * * @param a grayscale color object * @returns a new color which should be set instead (any colorspace) */ virtual PoDoFo::PdfColor SetStrokingColorGray( const PoDoFo::PdfColor & rColor ) = 0; /** * This method is called whenever a RGB stroking color is set * using the 'RG' PDF command. * * @param a RGB color object * @returns a new color which should be set instead (any colorspace) */ virtual PoDoFo::PdfColor SetStrokingColorRGB( const PoDoFo::PdfColor & rColor ) = 0; /** * This method is called whenever a CMYK stroking color is set * using the 'K' PDF command. * * @param a CMYK color object * @returns a new color which should be set instead (any colorspace) */ virtual PoDoFo::PdfColor SetStrokingColorCMYK( const PoDoFo::PdfColor & rColor ) = 0; /** * This method is called whenever a gray non-stroking color is set * using the 'g' PDF command. * * @param a grayscale color object * @returns a new color which should be set instead (any colorspace) */ virtual PoDoFo::PdfColor SetNonStrokingColorGray( const PoDoFo::PdfColor & rColor ) = 0; /** * This method is called whenever a RGB non-stroking color is set * using the 'rg' PDF command. * * @param a RGB color object * @returns a new color which should be set instead (any colorspace) */ virtual PoDoFo::PdfColor SetNonStrokingColorRGB( const PoDoFo::PdfColor & rColor ) = 0; /** * This method is called whenever a CMYK non-stroking color is set * using the 'k' PDF command. * * @param a CMYK color object * @returns a new color which should be set instead (any colorspace) */ virtual PoDoFo::PdfColor SetNonStrokingColorCMYK( const PoDoFo::PdfColor & rColor ) = 0; }; #endif // _ICONVERTER_H_ podofo-0.9.3/tools/podofocolor/luaconverter.h0000664000175000017500000001221511506674437021246 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2010 by Dominik Seichter * * domseichter@web.de * * * * 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., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #ifndef _LUA_CONVERTER_H_ #define _LUA_CONVERTER_H_ #include "iconverter.h" struct lua_State; class LuaMachina { lua_State *L; public: LuaMachina(); ~LuaMachina(); inline lua_State* State() { return L; } }; /** * Converter that calls a lua script * to do the color conversions. */ class LuaConverter : public IConverter { public: LuaConverter( const std::string & sLuaScript ); virtual ~LuaConverter(); /** * A helper method that is called to inform the converter * when a new page is analyzed. * * @param pPage page object * @param nPageIndex index of the page in the document */ virtual void StartPage( PoDoFo::PdfPage* pPage, int nPageIndex ); /** * A helper method that is called to inform the converter * when a new page has been analyzed completely. * * @param pPage page object * @param nPageIndex index of the page in the document */ virtual void EndPage( PoDoFo::PdfPage* pPage, int nPageIndex ); /** * A helper method that is called to inform the converter * when a new xobjext is analyzed. * * @param pObj the xobject */ virtual void StartXObject( PoDoFo::PdfXObject* pObj ); /** * A helper method that is called to inform the converter * when a xobjext has been analyzed. * * @param pObj the xobject */ virtual void EndXObject( PoDoFo::PdfXObject* pObj ); /** * This method is called whenever a gray stroking color is set * using the 'G' PDF command. * * @param a grayscale color object * @returns a new color which should be set instead (any colorspace) */ virtual PoDoFo::PdfColor SetStrokingColorGray( const PoDoFo::PdfColor & rColor ); /** * This method is called whenever a RGB stroking color is set * using the 'RG' PDF command. * * @param a RGB color object * @returns a new color which should be set instead (any colorspace) */ virtual PoDoFo::PdfColor SetStrokingColorRGB( const PoDoFo::PdfColor & rColor ); /** * This method is called whenever a CMYK stroking color is set * using the 'K' PDF command. * * @param a CMYK color object * @returns a new color which should be set instead (any colorspace) */ virtual PoDoFo::PdfColor SetStrokingColorCMYK( const PoDoFo::PdfColor & rColor ); /** * This method is called whenever a gray non-stroking color is set * using the 'g' PDF command. * * @param a grayscale color object * @returns a new color which should be set instead (any colorspace) */ virtual PoDoFo::PdfColor SetNonStrokingColorGray( const PoDoFo::PdfColor & rColor ); /** * This method is called whenever a RGB non-stroking color is set * using the 'rg' PDF command. * * @param a RGB color object * @returns a new color which should be set instead (any colorspace) */ virtual PoDoFo::PdfColor SetNonStrokingColorRGB( const PoDoFo::PdfColor & rColor ); /** * This method is called whenever a CMYK non-stroking color is set * using the 'k' PDF command. * * @param a CMYK color object * @returns a new color which should be set instead (any colorspace) */ virtual PoDoFo::PdfColor SetNonStrokingColorCMYK( const PoDoFo::PdfColor & rColor ); private: /** * Create a PdfColor from an array returned on the stack * by a Lua function. * @param pszFunctionName name of Lua function for error reporting * @returns a PdfColor or throws a PdfError if color cannot be created */ PoDoFo::PdfColor GetColorFromReturnValue(const char* pszFunctionName); private: LuaMachina m_machina; }; #endif // _LUA_CONVERTER_H_ podofo-0.9.3/tools/podofocolor/colorchanger.h0000664000175000017500000001141011511141604021154 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2010 by Dominik Seichter * * domseichter@web.de * * * * 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., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #ifndef _COLORCHANGER_H_ #define _COLORCHANGER_H_ #include #include #include class IConverter; class GraphicsStack; /** * This class provides a tool to change all colors * in a PDF file. */ class ColorChanger { public: enum EKeywordType { eKeyword_GraphicsStack_Push, eKeyword_GraphicsStack_Pop, eKeyword_SelectGray_Stroking, eKeyword_SelectRGB_Stroking, eKeyword_SelectCMYK_Stroking, eKeyword_SelectGray_NonStroking, eKeyword_SelectRGB_NonStroking, eKeyword_SelectCMYK_NonStroking, eKeyword_SelectColorSpace_Stroking, eKeyword_SelectColorSpace_NonStroking, eKeyword_SelectColor_Stroking, eKeyword_SelectColor_NonStroking, eKeyword_SelectColor_Stroking2, eKeyword_SelectColor_NonStroking2, eKeyword_Undefined = 0xffff }; /** * KWInfo describes a single PDF keyword's characteristics. See kwInfo[] . */ struct KWInfo { ColorChanger::EKeywordType eKeywordType; /// null-terminated keyword text const char pszText[6]; /// Number of arguments int nNumArguments; /// Short description text (optional, set to NULL if undesired). const char* pszDescription; }; /** * Construct a new colorchanger object * @param pConverter a converter which is applied to all color definitions * @param sInput the input PDF file * @param sOutput write output to this filename */ ColorChanger( IConverter* pConvert, const std::string & sInput, const std::string & sOutput ); /** * Start processing the input file. */ void start(); private: /** * Replace all colors in the given page. * @param pPage may not be NULL */ void ReplaceColorsInPage( PoDoFo::PdfCanvas* pPage ); /** * Convert a keyword name to a keyword typee * @param pszKeyword name of a keyword * @return the keyword type or eKeywordType_Undefined if unknown */ const KWInfo* FindKeyWordByName(const char* pszKeyword); PoDoFo::PdfColor GetColorFromStack( int nArgs, std::vector & args ); void PutColorOnStack( const PoDoFo::PdfColor & rColor, std::vector & args ); const char* ProcessColor( EKeywordType eKeywordType, int nNumArgs, std::vector & args, GraphicsStack & rGraphicsStack ); const char* GetKeywordForColor( const PoDoFo::PdfColor & rColor, bool bIsStroking ); /** Write a list of arguments and optionally a keyword * to an output device * * @param rArgs list of arguments which will be written to rDevice (will be cleared afterwards). * @param pszKeyword a keyword or NULL to be written after the arguments * @param rDevice output device */ void WriteArgumentsAndKeyword( std::vector & rArgs, const char* pszKeyword, PoDoFo::PdfOutputDevice & rDevice ); /** * unused */ PoDoFo::EPdfColorSpace GetColorSpaceForName( const PoDoFo::PdfName & rName, PoDoFo::PdfCanvas* pPage ); /** * unused */ PoDoFo::EPdfColorSpace GetColorSpaceForArray( const PoDoFo::PdfArray & rArray, PoDoFo::PdfCanvas* pPage ); private: IConverter* m_pConverter; std::string m_sInput; std::string m_sOutput; }; #endif // _COLORCHANGER_H_ podofo-0.9.3/tools/podofocolor/colorspace.h0000664000175000017500000000520611511141604020646 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2010 by Dominik Seichter * * domseichter@web.de * * * * 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., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #ifndef _COLORSPACE_H_ #define _COLORSPACE_H_ #include /** * A more powerful representation * of a colorspace than EPdfColorSpace. * */ class ColorSpace { public: /** * Construct a DeviceGray ColorSpace */ ColorSpace(); /** * Construct a colorspace from a colorspace name */ ColorSpace(const PoDoFo::PdfName & rName); /** * Copy constructor */ ColorSpace(const ColorSpace & rhs); ~ColorSpace(); const ColorSpace & operator=(const ColorSpace & rhs); /** * Checks if this is a "simple" * colorspace (i.e. DeviceGray, DeviceRGB, DeviceCMYK). * \returns true if this is a simple colospace */ bool IsSimpleColorSpace() const; /** * Convert this object into an EPdfColorSpace * enum. * \returns enum value if possible or ePdfColorSpace_Unknown */ PoDoFo::EPdfColorSpace ConvertToPdfColorSpace() const; /** * Retrieve the internal name. * \return the internal name */ inline const PoDoFo::PdfName & GetName() const; private: PoDoFo::PdfName m_name; }; const PoDoFo::PdfName & ColorSpace::GetName() const { return m_name; } #endif // _COLORSPACE_H_ podofo-0.9.3/tools/podofocolor/grayscaleconverter.cpp0000664000175000017500000000517311506670673022775 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2010 by Dominik Seichter * * domseichter@web.de * * * * 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., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "grayscaleconverter.h" GrayscaleConverter::GrayscaleConverter() : IConverter() { } GrayscaleConverter::~GrayscaleConverter() { } void GrayscaleConverter::StartPage( PoDoFo::PdfPage*, int ) { } void GrayscaleConverter::EndPage( PoDoFo::PdfPage*, int ) { } void GrayscaleConverter::StartXObject( PoDoFo::PdfXObject* ) { } void GrayscaleConverter::EndXObject( PoDoFo::PdfXObject* ) { } PoDoFo::PdfColor GrayscaleConverter::SetStrokingColorGray( const PoDoFo::PdfColor & rColor ) { return rColor; } PoDoFo::PdfColor GrayscaleConverter::SetStrokingColorRGB( const PoDoFo::PdfColor & rColor ) { return rColor.ConvertToGrayScale(); } PoDoFo::PdfColor GrayscaleConverter::SetStrokingColorCMYK( const PoDoFo::PdfColor & rColor ) { return rColor.ConvertToGrayScale(); } PoDoFo::PdfColor GrayscaleConverter::SetNonStrokingColorGray( const PoDoFo::PdfColor & rColor ) { return rColor.ConvertToGrayScale(); } PoDoFo::PdfColor GrayscaleConverter::SetNonStrokingColorRGB( const PoDoFo::PdfColor & rColor ) { return rColor.ConvertToGrayScale(); } PoDoFo::PdfColor GrayscaleConverter::SetNonStrokingColorCMYK( const PoDoFo::PdfColor & rColor ) { return rColor.ConvertToGrayScale(); } podofo-0.9.3/tools/podofocolor/colorchanger.cpp0000664000175000017500000005411212347347566021544 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2010 by Dominik Seichter * * domseichter@web.de * * * * 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., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * x1 ***************************************************************************/ #include "colorchanger.h" #include #include #include #include #include "graphicsstack.h" #include "iconverter.h" using namespace PoDoFo; static const ColorChanger::KWInfo kwInfo[] = { { ColorChanger::eKeyword_GraphicsStack_Push, "q", 0, "Save state" }, { ColorChanger::eKeyword_GraphicsStack_Pop, "Q", 0, "Restore state" }, { ColorChanger::eKeyword_SelectGray_Stroking, "G", 1, "Select gray stroking color" }, { ColorChanger::eKeyword_SelectRGB_Stroking, "RG", 3, "Select RGB stroking color" }, { ColorChanger::eKeyword_SelectCMYK_Stroking, "K", 4, "Select CMYK stroking color" }, { ColorChanger::eKeyword_SelectGray_NonStroking, "g", 1, "Select gray non-stroking color" }, { ColorChanger::eKeyword_SelectRGB_NonStroking, "rg", 3, "Select RGB non-stroking color" }, { ColorChanger::eKeyword_SelectCMYK_NonStroking, "k", 4, "Select CMYK non-stroking color" }, { ColorChanger::eKeyword_SelectColorSpace_Stroking, "CS", 1, "Select colorspace non-stroking color" }, { ColorChanger::eKeyword_SelectColorSpace_NonStroking, "cs", 1, "Select colorspace non-stroking color" }, { ColorChanger::eKeyword_SelectColor_Stroking, "SC", 1, "Select depending on current colorspace" }, { ColorChanger::eKeyword_SelectColor_NonStroking, "sc", 1, "Select depending on current colorspace" }, { ColorChanger::eKeyword_SelectColor_Stroking2, "SCN", 1, "Select depending on current colorspace (extended)" }, { ColorChanger::eKeyword_SelectColor_NonStroking2, "scn", 1, "Select depending on current colorspace (extended)" }, // Sentinel { ColorChanger::eKeyword_Undefined, "\0", 0, NULL } }; // PDF Commands, which modify colors according to PDFReference 1.7 // CS - select colorspace stroking (May need lookup in Colorspace key of resource directory) // cs - select colorspace non-stroking (May need lookup in Colorspace key of resource directory) // SC - select stroking color depending on colorspace // SCN - select stroking color for colorspaces including Separation, DeviceN, ICCBased // sc - select non-stroking color depending on colorspace // scn - select non-stroking color for colorspaces including Separation, DeviceN, ICCBased // G - select gray colorspace and gray stroking color // g - select gray colorspace and gray non stroking color // RG - select RGB colorspace and RGB stroking color // rg - select RGB colorspace and RGB non stroking color // K - select CMYK colorspace and CMYK stroking color // k - select CMYK colorspace and CMYK non stroking color // TODO: Allow to set default color and colorspace when starting a page // ColorSpaces and their default colors // DeviceColorSpaces // DeviceGray 0.0 // DeviceRGB 0.0 // DeviceCMYK 0.0 0.0 0.0 1.0 // CIE Based ColorSpaces // CalGray 0.0 // CalRGB 0.0 // Lab - all values 0.0 or closest according to range // ICCBased - all values 0.0 or closest according to range // Special ColorSpaces // Pattern - the value that causes nothing to be painted // Indexed 0 // Separation - all values 1.0 // DeviceN - all values 1.0 // GraphicsState entries and their default values // ColorSpace - DeviceGray // color stroking - black (see ColorSpace default values) // color non stroking - black (see ColorSpace default values) // Operations // q Push // Q Pop ColorChanger::ColorChanger( IConverter* pConvert, const std::string & sInput, const std::string & sOutput ) : m_pConverter( pConvert ), m_sInput( sInput ), m_sOutput( sOutput ) { if( !m_pConverter ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } } void ColorChanger::start() { PdfMemDocument input( m_sInput.c_str() ); for( int i = 0; i < input.GetPageCount(); i++ ) { std::cout << "Processing page " << std::setw(6) << (i+1) << "..." << std::endl << std::flush; PdfPage* pPage = input.GetPage( i ); PODOFO_RAISE_LOGIC_IF( !pPage, "Got null page pointer within valid page range" ); m_pConverter->StartPage( pPage, i ); this->ReplaceColorsInPage( pPage ); m_pConverter->EndPage( pPage, i ); } // Go through all XObjects PdfVecObjects::iterator it = input.GetObjects().begin(); while( it != input.GetObjects().end() ) { if( (*it)->IsDictionary() && (*it)->GetDictionary().HasKey( "Type") ) { if( PdfName("XObject") == (*it)->GetDictionary().GetKey("Type")->GetName() && (*it)->GetDictionary().HasKey("Subtype") && PdfName("Image") != (*it)->GetDictionary().GetKey("Subtype")->GetName() ) { std::cout << "Processing XObject " << (*it)->Reference().ObjectNumber() << " " << (*it)->Reference().GenerationNumber() << std::endl; PdfXObject xObject( *it ); m_pConverter->StartXObject( &xObject ); this->ReplaceColorsInPage( &xObject ); m_pConverter->EndXObject( &xObject ); } } ++it; } input.Write( m_sOutput.c_str() ); } void ColorChanger::ReplaceColorsInPage( PdfCanvas* pPage ) { EPdfContentsType t; const char* pszKeyword; PdfVariant var; bool bReadToken; GraphicsStack graphicsStack; PdfContentsTokenizer tokenizer( pPage ); std::vector args; PdfRefCountedBuffer buffer; PdfOutputDevice device( &buffer ); while( (bReadToken = tokenizer.ReadNext(t, pszKeyword, var)) ) { if (t == ePdfContentsType_Variant) { // arguments come before operators, but we want to group them up before // their operator. args.push_back(var); } else if (t == ePdfContentsType_ImageData) { // Handle inline images (Internally using PdfData) args.push_back(var); } else if (t == ePdfContentsType_Keyword) { const KWInfo* pInfo = FindKeyWordByName(pszKeyword); PdfColor color, newColor; int nNumArgs = pInfo->nNumArguments; EPdfColorSpace eColorSpace; switch( pInfo->eKeywordType ) { case eKeyword_GraphicsStack_Push: graphicsStack.Push(); break; case eKeyword_GraphicsStack_Pop: graphicsStack.Pop(); break; case eKeyword_SelectColorSpace_Stroking: eColorSpace = this->GetColorSpaceForName( args.back().GetName(), pPage ); eColorSpace = PdfColor::GetColorSpaceForName( args.back().GetName() ); args.pop_back(); graphicsStack.SetStrokingColorSpace( eColorSpace ); break; case eKeyword_SelectColorSpace_NonStroking: eColorSpace = PdfColor::GetColorSpaceForName( args.back().GetName() ); args.pop_back(); graphicsStack.SetNonStrokingColorSpace( eColorSpace ); break; case eKeyword_SelectGray_Stroking: case eKeyword_SelectRGB_Stroking: case eKeyword_SelectCMYK_Stroking: case eKeyword_SelectGray_NonStroking: case eKeyword_SelectRGB_NonStroking: case eKeyword_SelectCMYK_NonStroking: pszKeyword = this->ProcessColor( pInfo->eKeywordType, nNumArgs, args, graphicsStack ); break; case eKeyword_SelectColor_Stroking: case eKeyword_SelectColor_Stroking2: { /* PdfError::LogMessage( eLogSeverity_Information, "SCN called for colorspace: %s\n", PdfColor::GetNameForColorSpace( graphicsStack.GetStrokingColorSpace() ).GetName().c_str() ); */ int nTmpArgs; EKeywordType eTempKeyword; switch( graphicsStack.GetStrokingColorSpace() ) { case ePdfColorSpace_DeviceGray: nTmpArgs = 1; eTempKeyword = eKeyword_SelectGray_Stroking; break; case ePdfColorSpace_DeviceRGB: nTmpArgs = 3; eTempKeyword = eKeyword_SelectRGB_Stroking; break; case ePdfColorSpace_DeviceCMYK: nTmpArgs = 4; eTempKeyword = eKeyword_SelectCMYK_Stroking; break; case ePdfColorSpace_Separation: { PdfError::LogMessage( eLogSeverity_Error, "Separation color space not supported.\n" ); PODOFO_RAISE_ERROR( ePdfError_CannotConvertColor ); break; } case ePdfColorSpace_CieLab: { PdfError::LogMessage( eLogSeverity_Error, "CieLab color space not supported.\n" ); PODOFO_RAISE_ERROR( ePdfError_CannotConvertColor ); break; } case ePdfColorSpace_Indexed: { PdfError::LogMessage( eLogSeverity_Error, "Indexed color space not supported.\n" ); PODOFO_RAISE_ERROR( ePdfError_CannotConvertColor ); break; } case ePdfColorSpace_Unknown: default: { PODOFO_RAISE_ERROR( ePdfError_CannotConvertColor ); } } pszKeyword = this->ProcessColor( eTempKeyword, nTmpArgs, args, graphicsStack ); break; } case eKeyword_SelectColor_NonStroking: case eKeyword_SelectColor_NonStroking2: { /* PdfError::LogMessage( eLogSeverity_Information, "scn called for colorspace: %s\n", PdfColor::GetNameForColorSpace( graphicsStack.GetNonStrokingColorSpace() ).GetName().c_str() );*/ int nTmpArgs; EKeywordType eTempKeyword; switch( graphicsStack.GetNonStrokingColorSpace() ) { case ePdfColorSpace_DeviceGray: nTmpArgs = 1; eTempKeyword = eKeyword_SelectGray_NonStroking; break; case ePdfColorSpace_DeviceRGB: nTmpArgs = 3; eTempKeyword = eKeyword_SelectRGB_NonStroking; break; case ePdfColorSpace_DeviceCMYK: nTmpArgs = 4; eTempKeyword = eKeyword_SelectCMYK_NonStroking; break; case ePdfColorSpace_Separation: case ePdfColorSpace_CieLab: case ePdfColorSpace_Indexed: case ePdfColorSpace_Unknown: default: { PdfError::LogMessage( eLogSeverity_Error, "Unknown color space %i type.\n", graphicsStack.GetNonStrokingColorSpace() ); PODOFO_RAISE_ERROR( ePdfError_CannotConvertColor ); } } pszKeyword = this->ProcessColor( eTempKeyword, nTmpArgs, args, graphicsStack ); break; } case eKeyword_Undefined: //PdfError::LogMessage( eLogSeverity_Error, "Unknown keyword type.\n" ); break; default: break; } WriteArgumentsAndKeyword( args, pszKeyword, device ); } } // Write arguments if there are any left WriteArgumentsAndKeyword( args, NULL, device ); // Set new contents stream pPage->GetContentsForAppending()->GetStream()->Set( buffer.GetBuffer(), buffer.GetSize() ); } void ColorChanger::WriteArgumentsAndKeyword( std::vector & rArgs, const char* pszKeyword, PdfOutputDevice & rDevice ) { std::vector::const_iterator it = rArgs.begin(); while( it != rArgs.end() ) { (*it).Write( &rDevice, ePdfWriteMode_Compact ); ++it; } rArgs.clear(); if( pszKeyword ) { rDevice.Write( " ", 1 ); rDevice.Write( pszKeyword, strlen( pszKeyword ) ); rDevice.Write( "\n", 1 ); } } const ColorChanger::KWInfo* ColorChanger::FindKeyWordByName(const char* pszKeyword) { PODOFO_RAISE_LOGIC_IF( !pszKeyword, "Keyword cannot be NULL."); const KWInfo* pInfo = &(kwInfo[0]); while( pInfo->eKeywordType != eKeyword_Undefined ) { if( strcmp( pInfo->pszText, pszKeyword ) == 0 ) { return pInfo; } ++pInfo; } return pInfo; } void ColorChanger::PutColorOnStack( const PdfColor & rColor, std::vector & args ) { switch( rColor.GetColorSpace() ) { case ePdfColorSpace_DeviceGray: args.push_back( rColor.GetGrayScale() ); break; case ePdfColorSpace_DeviceRGB: args.push_back( rColor.GetRed() ); args.push_back( rColor.GetGreen() ); args.push_back( rColor.GetBlue() ); break; case ePdfColorSpace_DeviceCMYK: args.push_back( rColor.GetCyan() ); args.push_back( rColor.GetMagenta() ); args.push_back( rColor.GetYellow() ); args.push_back( rColor.GetBlack() ); break; case ePdfColorSpace_Separation: case ePdfColorSpace_CieLab: case ePdfColorSpace_Indexed: case ePdfColorSpace_Unknown: default: { PODOFO_RAISE_ERROR( ePdfError_CannotConvertColor ); } } } PdfColor ColorChanger::GetColorFromStack( int nArgs, std::vector & args ) { PdfColor color; double gray = -1.0; double red = -1.0, green = -1.0, blue = -1.0; double cyan = -1.0, magenta = -1.0, yellow = -1.0, black = -1.0; switch( nArgs ) { case 1: gray = args.back().GetReal(); args.pop_back(); color = PdfColor( gray ); break; case 3: blue = args.back().GetReal(); args.pop_back(); green = args.back().GetReal(); args.pop_back(); red = args.back().GetReal(); args.pop_back(); color = PdfColor( red, green, blue ); break; case 4: black = args.back().GetReal(); args.pop_back(); yellow = args.back().GetReal(); args.pop_back(); magenta = args.back().GetReal(); args.pop_back(); cyan = args.back().GetReal(); args.pop_back(); color = PdfColor( cyan, magenta, yellow, black ); break; } return color; } const char* ColorChanger::ProcessColor( EKeywordType eKeywordType, int nNumArgs, std::vector & args, GraphicsStack & rGraphicsStack ) { PdfColor newColor; bool bStroking = false; PdfColor color = this->GetColorFromStack( nNumArgs, args ); switch( eKeywordType ) { case eKeyword_SelectGray_Stroking: bStroking = true; rGraphicsStack.SetStrokingColorSpace( ePdfColorSpace_DeviceGray ); newColor = m_pConverter->SetStrokingColorGray( color ); break; case eKeyword_SelectRGB_Stroking: bStroking = true; rGraphicsStack.SetStrokingColorSpace( ePdfColorSpace_DeviceRGB ); newColor = m_pConverter->SetStrokingColorRGB( color ); break; case eKeyword_SelectCMYK_Stroking: bStroking = true; rGraphicsStack.SetStrokingColorSpace( ePdfColorSpace_DeviceCMYK ); newColor = m_pConverter->SetStrokingColorCMYK( color ); break; case eKeyword_SelectGray_NonStroking: rGraphicsStack.SetNonStrokingColorSpace( ePdfColorSpace_DeviceGray ); newColor = m_pConverter->SetNonStrokingColorGray( color ); break; case eKeyword_SelectRGB_NonStroking: rGraphicsStack.SetNonStrokingColorSpace( ePdfColorSpace_DeviceRGB ); newColor = m_pConverter->SetNonStrokingColorRGB( color ); break; case eKeyword_SelectCMYK_NonStroking: rGraphicsStack.SetNonStrokingColorSpace( ePdfColorSpace_DeviceCMYK ); newColor = m_pConverter->SetNonStrokingColorCMYK( color ); break; case eKeyword_GraphicsStack_Push: case eKeyword_GraphicsStack_Pop: case eKeyword_SelectColorSpace_Stroking: case eKeyword_SelectColorSpace_NonStroking: case eKeyword_SelectColor_Stroking: case eKeyword_SelectColor_Stroking2: case eKeyword_SelectColor_NonStroking: case eKeyword_SelectColor_NonStroking2: case eKeyword_Undefined: default: { PODOFO_RAISE_ERROR( ePdfError_CannotConvertColor ); } } this->PutColorOnStack( newColor, args ); if( bStroking ) { rGraphicsStack.SetStrokingColor( newColor ); } else { rGraphicsStack.SetNonStrokingColor( newColor ); } return this->GetKeywordForColor( newColor, bStroking ); } const char* ColorChanger::GetKeywordForColor( const PdfColor & rColor, bool bIsStroking ) { const char* pszKeyword = NULL; switch( rColor.GetColorSpace() ) { case ePdfColorSpace_DeviceGray: pszKeyword = ( bIsStroking ? "G" : "g" ); break; case ePdfColorSpace_DeviceRGB: pszKeyword = ( bIsStroking ? "RG" : "rg" ); break; case ePdfColorSpace_DeviceCMYK: pszKeyword = ( bIsStroking ? "K" : "k" ); break; case ePdfColorSpace_Separation: case ePdfColorSpace_CieLab: case ePdfColorSpace_Indexed: case ePdfColorSpace_Unknown: default: { PODOFO_RAISE_ERROR( ePdfError_CannotConvertColor ); } } return pszKeyword; } EPdfColorSpace ColorChanger::GetColorSpaceForName( const PdfName & rName, PdfCanvas* pPage ) { EPdfColorSpace eColorSpace = PdfColor::GetColorSpaceForName( rName ); if( eColorSpace == ePdfColorSpace_Unknown ) { // See if we can find it in the resource dictionary of the current page PdfObject* pResources = pPage->GetResources(); if( pResources != NULL && pResources->GetDictionary().HasKey( PdfName("ColorSpace") ) ) { PdfObject* pColorSpaces = pResources->GetIndirectKey( PdfName("ColorSpace") ); if( pColorSpaces != NULL && pColorSpaces->GetDictionary().HasKey( rName ) ) { PdfObject* pCS = pColorSpaces->GetIndirectKey( rName ); if( !pCS ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } else if( pCS->IsName() ) { return this->GetColorSpaceForName( pCS->GetName(), pPage ); } else if( pCS->IsArray() ) { return this->GetColorSpaceForArray( pCS->GetArray(), pPage ); } } } } return eColorSpace; } EPdfColorSpace ColorChanger::GetColorSpaceForArray( const PdfArray &, PdfCanvas* ) { EPdfColorSpace eColorSpace = ePdfColorSpace_Unknown; // CIE Based: [name dictionary] // CalGray // CalRGB // CalLab // ICCBased [name stream] // Special: // Pattern // Indexed [/Indexed base hival lookup] // Separation [/Separation name alternateSpace tintTransform] // DeviceN [/DeviceN names alternateSpace tintTransform] or // [/DeviceN names alternateSpace tintTransform attributes] // return eColorSpace; } podofo-0.9.3/tools/podofocolor/dummyconverter.h0000664000175000017500000000674011506670673021624 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2010 by Dominik Seichter * * domseichter@web.de * * * * 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., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #ifndef _DUMMY_CONVERTER_H_ #define _DUMMY_CONVERTER_H_ #include "iconverter.h" /** * Dummy implementation of a converter, * which sets all colors to RGB red. */ class DummyConverter : public IConverter { public: DummyConverter(); virtual ~DummyConverter(); /** * A helper method that is called to inform the converter * when a new page is analyzed. * * @param pPage page object * @param nPageIndex index of the page in the document */ virtual void StartPage( PoDoFo::PdfPage* pPage, int nPageIndex ); /** * A helper method that is called to inform the converter * when a new page has been analyzed completely. * * @param pPage page object * @param nPageIndex index of the page in the document */ virtual void EndPage( PoDoFo::PdfPage* pPage, int nPageIndex ); /** * A helper method that is called to inform the converter * when a new xobjext is analyzed. * * @param pObj the xobject */ virtual void StartXObject( PoDoFo::PdfXObject* pObj ); /** * A helper method that is called to inform the converter * when a xobjext has been analyzed. * * @param pObj the xobject */ virtual void EndXObject( PoDoFo::PdfXObject* pObj ); /** * This method is called whenever a gray stroking color is set * using the 'G' PDF command. * * @param a grayscale color object * @returns a new color which should be set instead (any colorspace) */ virtual PoDoFo::PdfColor SetStrokingColorGray( const PoDoFo::PdfColor & rColor ); virtual PoDoFo::PdfColor SetStrokingColorRGB( const PoDoFo::PdfColor & rColor ); virtual PoDoFo::PdfColor SetStrokingColorCMYK( const PoDoFo::PdfColor & rColor ); virtual PoDoFo::PdfColor SetNonStrokingColorGray( const PoDoFo::PdfColor & rColor ); virtual PoDoFo::PdfColor SetNonStrokingColorRGB( const PoDoFo::PdfColor & rColor ); virtual PoDoFo::PdfColor SetNonStrokingColorCMYK( const PoDoFo::PdfColor & rColor ); }; #endif // _DUMMY_CONVERTER_H_ podofo-0.9.3/tools/podofomerge/0000775000175000017500000000000012356565167016347 5ustar dominikdominikpodofo-0.9.3/tools/podofomerge/podofomerge.cpp0000664000175000017500000000704311474750735021362 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2006 by Dominik Seichter * * domseichter@web.de * * * * 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., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include #include using namespace PoDoFo; #ifdef _HAVE_CONFIG #include #endif // _HAVE_CONFIG void print_help() { printf("Usage: podofomerge [inputfile1] [inputfile2] [outputfile]\n\n"); printf("\nPoDoFo Version: %s\n\n", PODOFO_VERSION_STRING); } void merge( const char* pszInput1, const char* pszInput2, const char* pszOutput ) { printf("Reading file: %s\n", pszInput1 ); PdfMemDocument input1( pszInput1 ); printf("Reading file: %s\n", pszInput2 ); PdfMemDocument input2( pszInput2 ); // #define TEST_ONLY_SOME_PAGES #ifdef TEST_ONLY_SOME_PAGES input1.InsertPages( input2, 1, 2 ); #else printf("Appending %i pages on a document with %i pages.\n", input2.GetPageCount(), input1.GetPageCount() ); input1.Append( input2 ); #endif // we are going to bookmark the insertions // using destinations - also adding each as a NamedDest /* PdfDestination p1Dest( input1.GetPage(0) ); input1.AddNamedDestination( p1Dest, std::string("Input1") ); PdfOutlines* bMarks = input1.GetOutlines(); PdfOutlineItem* bmRoot = bMarks->CreateRoot( "Merged Document" ); PdfOutlineItem* child1 = bmRoot->CreateChild( pszInput1, p1Dest ); PdfDestination p2Dest( input1.GetPage(pgCount) ); input1.AddNamedDestination( p2Dest, std::string("Input2") ); child1->CreateNext( pszInput2, p2Dest ); */ #ifdef TEST_FULL_SCREEN input1.SetUseFullScreen(); #else input1.SetPageMode( ePdfPageModeUseBookmarks ); input1.SetHideToolbar(); input1.SetPageLayout( ePdfPageLayoutTwoColumnLeft ); #endif printf("Writing file: %s\n", pszOutput ); input1.Write( pszOutput ); } int main( int argc, char* argv[] ) { char* pszInput1; char* pszInput2; char* pszOutput; if( argc != 4 ) { print_help(); exit( -1 ); } pszInput1 = argv[1]; pszInput2 = argv[2]; pszOutput = argv[3]; try { merge( pszInput1, pszInput2, pszOutput ); } catch( PdfError & e ) { fprintf( stderr, "Error %i occurred!\n", e.GetError() ); e.PrintErrorMsg(); return e.GetError(); } return 0; } podofo-0.9.3/tools/podofomerge/CMakeLists.txt0000664000175000017500000000043210517314571021072 0ustar dominikdominikADD_EXECUTABLE(podofomerge podofomerge.cpp) TARGET_LINK_LIBRARIES(podofomerge ${PODOFO_LIB}) SET_TARGET_PROPERTIES(podofomerge PROPERTIES COMPILE_FLAGS "${PODOFO_CFLAGS}") ADD_DEPENDENCIES(podofomerge ${PODOFO_DEPEND_TARGET}) INSTALL(TARGETS podofomerge RUNTIME DESTINATION "bin") podofo-0.9.3/tools/podofomerge/podofomerge.vcproj0000664000175000017500000000671710475170454022104 0ustar dominikdominik podofo-0.9.3/tools/podofocountpages/0000775000175000017500000000000012356565167017420 5ustar dominikdominikpodofo-0.9.3/tools/podofocountpages/countpages.cpp0000664000175000017500000000642111306221052022247 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2009 by Dominik Seichter * * domseichter@web.de * * * * 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., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include #include using namespace PoDoFo; #ifdef _HAVE_CONFIG #include #endif // _HAVE_CONFIG void print_help() { printf("Usage: podofocountpages [-s] [-t] file1.pdf ... \n\n"); printf(" This tool counts the pages in a PDF file.\n"); printf(" -s will enable the short format, which ommites\n"); printf(" printing of the filename in the output.\n"); printf(" -t print the total sum of all pages.\n"); printf("\nPoDoFo Version: %s\n\n", PODOFO_VERSION_STRING); } int count_pages( const char* pszFilename, const bool & bShortFormat ) { PdfMemDocument document; document.Load( pszFilename ); int nPages = document.GetPageCount(); if( bShortFormat ) printf("%i\n", nPages ); else printf("%s:\t%i\n", pszFilename, nPages ); return nPages; } int main( int argc, char* argv[] ) { PdfError::EnableDebug( false ); if( argc <= 1 ) { print_help(); exit( -1 ); } try { bool bTotal = false; bool bShortFormat = false; int sum = 0; for(int i=1;i #include using namespace PoDoFo; #ifndef MAX_PATH #define MAX_PATH 512 #endif // MAX_PATH /** This class uses the PoDoFo lib to parse * a PDF file and to write all text it finds * in this PDF document to stdout. */ class TextExtractor { public: TextExtractor(); virtual ~TextExtractor(); void Init( const char* pszInput ); private: /** Extract all text from the given page * * \param pDocument the owning document * \param pPage extract the text of this page. */ void ExtractText( PdfMemDocument* pDocument, PdfPage* pPage ); /** Adds a text string to a list which can be sorted by * position on the page later, so that the whole structure * of the text including formatting can be reconstructed. * * \param dCurPosX x position of the text * \param dCurPosY y position of the text * \param pCurFont font of the text * \param rString the actual string */ void AddTextElement( double dCurPosX, double dCurPosY, PdfFont* pCurFont, const PdfString & rString ); }; #endif // _TEXT_EXTRACTOR_H_ podofo-0.9.3/tools/podofotxtextract/TextExtractor.cpp0000664000175000017500000001427112347347566023014 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2008 by Dominik Seichter * * domseichter@web.de * * * * 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., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "TextExtractor.h" #include TextExtractor::TextExtractor() { } TextExtractor::~TextExtractor() { } void TextExtractor::Init( const char* pszInput ) { if( !pszInput ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } PdfMemDocument document( pszInput ); int nCount = document.GetPageCount(); for( int i=0; iExtractText( &document, pPage ); } } void TextExtractor::ExtractText( PdfMemDocument* pDocument, PdfPage* pPage ) { const char* pszToken = NULL; PdfVariant var; EPdfContentsType eType; PdfContentsTokenizer tokenizer( pPage ); double dCurPosX = 0.0; double dCurPosY = 0.0; bool bTextBlock = false; PdfFont* pCurFont = NULL; std::stack stack; while( tokenizer.ReadNext( eType, pszToken, var ) ) { if( eType == ePdfContentsType_Keyword ) { // support 'l' and 'm' tokens if( strcmp( pszToken, "l" ) == 0 || strcmp( pszToken, "m" ) == 0 ) { dCurPosX = stack.top().GetReal(); stack.pop(); dCurPosY = stack.top().GetReal(); stack.pop(); } else if( strcmp( pszToken, "BT" ) == 0 ) { bTextBlock = true; // BT does not reset font // pCurFont = NULL; } else if( strcmp( pszToken, "ET" ) == 0 ) { if( !bTextBlock ) fprintf( stderr, "WARNING: Found ET without BT!\n" ); } if( bTextBlock ) { if( strcmp( pszToken, "Tf" ) == 0 ) { stack.pop(); PdfName fontName = stack.top().GetName(); PdfObject* pFont = pPage->GetFromResources( PdfName("Font"), fontName ); if( !pFont ) { PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidHandle, "Cannot create font!" ); } pCurFont = pDocument->GetFont( pFont ); if( !pCurFont ) { fprintf( stderr, "WARNING: Unable to create font for object %i %i R\n", pFont->Reference().ObjectNumber(), pFont->Reference().GenerationNumber() ); } } else if( strcmp( pszToken, "Tj" ) == 0 || strcmp( pszToken, "'" ) == 0 ) { AddTextElement( dCurPosX, dCurPosY, pCurFont, stack.top().GetString() ); stack.pop(); } else if( strcmp( pszToken, "\"" ) == 0 ) { AddTextElement( dCurPosX, dCurPosY, pCurFont, stack.top().GetString() ); stack.pop(); stack.pop(); // remove char spacing from stack stack.pop(); // remove word spacing from stack } else if( strcmp( pszToken, "TJ" ) == 0 ) { PdfArray array = stack.top().GetArray(); stack.pop(); for( int i=0; i(array.GetSize()); i++ ) { if( array[i].IsString() || array[i].IsHexString() ) AddTextElement( dCurPosX, dCurPosY, pCurFont, array[i].GetString() ); } } } } else if ( eType == ePdfContentsType_Variant ) { stack.push( var ); } else { // Impossible; type must be keyword or variant PODOFO_RAISE_ERROR( ePdfError_InternalLogic ); } } } void TextExtractor::AddTextElement( double dCurPosX, double dCurPosY, PdfFont* pCurFont, const PdfString & rString ) { if( !pCurFont ) { fprintf( stderr, "WARNING: Found text but do not have a current font: %s\n", rString.GetString() ); return; } if( !pCurFont->GetEncoding() ) { fprintf( stderr, "WARNING: Found text but do not have a current encoding: %s\n", rString.GetString() ); return; } // For now just write to console PdfString unicode = pCurFont->GetEncoding()->ConvertToUnicode( rString, pCurFont ); const char* pszData = unicode.GetStringUtf8().c_str(); while( *pszData ) { //printf("%02x", static_cast(*pszData) ); ++pszData; } printf("(%.3f,%.3f) %s \n", dCurPosX, dCurPosY, unicode.GetStringUtf8().c_str() ); } podofo-0.9.3/tools/podofotxtextract/CMakeLists.txt0000664000175000017500000000051311025247575022211 0ustar dominikdominikADD_EXECUTABLE(podofotxtextract TextExtractor.cpp podofotxtextract.cpp) TARGET_LINK_LIBRARIES(podofotxtextract ${PODOFO_LIB}) SET_TARGET_PROPERTIES(podofotxtextract PROPERTIES COMPILE_FLAGS "${PODOFO_CFLAGS}") ADD_DEPENDENCIES(podofotxtextract ${PODOFO_DEPEND_TARGET}) INSTALL(TARGETS podofotxtextract RUNTIME DESTINATION "bin") podofo-0.9.3/tools/podofotxtextract/podofotxtextract.cpp0000664000175000017500000000417011306221052023561 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2008 by Dominik Seichter * * domseichter@web.de * * * * 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., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "TextExtractor.h" #include #include #include #ifdef _HAVE_CONFIG #include #endif // _HAVE_CONFIG void print_help() { printf("Usage: podofotxtextract [inputfile]\n\n"); printf("\nPoDoFo Version: %s\n\n", PODOFO_VERSION_STRING); } int main( int argc, char* argv[] ) { char* pszInput; TextExtractor extractor; if( argc != 2 ) { print_help(); exit( -1 ); } pszInput = argv[1]; try { extractor.Init( pszInput ); } catch( PdfError & e ) { fprintf( stderr, "Error: An error %i ocurred during processing the pdf file.\n", e.GetError() ); e.PrintErrorMsg(); return e.GetError(); } return 0; } podofo-0.9.3/tools/podofoencrypt/0000775000175000017500000000000012356565167016734 5ustar dominikdominikpodofo-0.9.3/tools/podofoencrypt/podofoencrypt.cpp0000664000175000017500000002115112062205562022313 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2005 by Dominik Seichter * * domseichter@web.de * * * * 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., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include using namespace PoDoFo; #include #include #ifdef _HAVE_CONFIG #include #endif // _HAVE_CONFIG void encrypt( const char* pszInput, const char* pszOutput, const std::string & userPass, const std::string & ownerPass, const PdfEncrypt::EPdfEncryptAlgorithm eAlgorithm, const int nPermissions ) { PdfVecObjects objects; PdfParser parser( &objects ); objects.SetAutoDelete( true ); parser.ParseFile( pszInput ); PdfEncrypt::EPdfKeyLength eKeyLength; EPdfVersion eVersion; switch( eAlgorithm ) { case PdfEncrypt::ePdfEncryptAlgorithm_RC4V1: eKeyLength = PdfEncrypt::ePdfKeyLength_40; eVersion = ePdfVersion_1_3; break; #ifdef PODOFO_HAVE_LIBIDN case PdfEncrypt::ePdfEncryptAlgorithm_AESV3:; eKeyLength = PdfEncrypt::ePdfKeyLength_256; eVersion = ePdfVersion_1_7; break; #endif // PODOFO_HAVE_LIBIDN case PdfEncrypt::ePdfEncryptAlgorithm_RC4V2: case PdfEncrypt::ePdfEncryptAlgorithm_AESV2: default: eKeyLength = PdfEncrypt::ePdfKeyLength_128; eVersion = ePdfVersion_1_5; break; } PdfWriter writer( &parser ); PdfEncrypt *encrypt = PdfEncrypt::CreatePdfEncrypt( userPass, ownerPass, nPermissions, eAlgorithm, eKeyLength ); writer.SetPdfVersion( eVersion ); writer.SetEncrypted( *encrypt ); writer.Write( pszOutput ); delete encrypt; } void print_help() { printf("Usage: podofoencrypt [--rc4v1] [--rc4v2] [--aesv2] [--aesv3] [-u ]\n"); printf(" -o \n\n"); printf(" This tool encrypts an existing PDF file.\n\n"); printf(" --help Display this help text\n"); printf(" Algorithm:\n"); printf(" --rc4v1 Use rc4v1 encryption\n"); printf(" --rc4v2 Use rc4v2 encryption (Default value)\n"); printf(" --aesv2 Use aes-128 encryption\n"); printf(" --aesv3 Use aes-256 encryption\n"); printf(" Passwords:\n"); printf(" -u An optional userpassword\n"); printf(" -o The required owner password\n"); printf(" Permissions:\n"); printf(" --print Allow printing the document\n"); printf(" --edit Allow modifying the document besides annotations, form fields or chaning pages\n"); printf(" --copy Allow text and graphic extraction\n"); printf(" --editnotes Add or modify text annoations or form fields (if ePdfPermissions_Edit is set also allow to create interactive form fields including signature)\n"); printf(" --fillandsign Fill in existing form or signature fields\n"); printf(" --accessible Extract text and graphics to support user with disabillities\n"); printf(" --assemble Assemble the document: insert, create, rotate delete pages or add bookmarks\n"); printf(" --highprint Print a high resolution version of the document\n"); printf("\n\n"); } int main( int argc, char* argv[] ) { const char* pszInput = NULL; const char* pszOutput = NULL; PdfEncrypt::EPdfEncryptAlgorithm eAlgorithm = PdfEncrypt::ePdfEncryptAlgorithm_RC4V1; int nPerm = 0; std::string userPass; std::string ownerPass; if( argc < 3 ) { print_help(); exit( -1 ); } // Parse the commandline options for( int i=1;i #include class PdfInfo { public: PdfInfo( const std::string& inPathname ); virtual ~PdfInfo(); void OutputDocumentInfo( std::ostream& sOutStream ); void OutputInfoDict( std::ostream& sOutStream ); void OutputPageInfo( std::ostream& sOutStream ); void OutputOutlines( std::ostream& sOutStream, PoDoFo::PdfOutlineItem* pFirst = NULL, int level = 0 ); void OutputNames( std::ostream& sOutStream ); private: PoDoFo::PdfDocument* mDoc; void OutputOneName( std::ostream& sOutStream, PoDoFo::PdfNamesTree* inTreeObj, const std::string& inTitle, const std::string& inKey ); std::string GuessFormat(); }; #endif // _PDFINFO_H podofo-0.9.3/tools/podofopdfinfo/podofopdfinfo.cpp0000664000175000017500000001111711515074452022222 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2005 by Dominik Seichter * * domseichter@web.de * * * * 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., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include "pdfinfo.h" #include #include #ifdef _HAVE_CONFIG #include #endif // _HAVE_CONFIG void print_help() { printf("Usage: podofopdfinfo [DCPON] [inputfile] \n\n"); printf(" This tool displays information about the PDF file\n"); printf(" according to format instruction (if not provided, displays all).\n"); printf(" D displays Document Info.\n"); printf(" C displays Classic Metadata.\n"); printf(" P displays Page Info.\n"); printf(" O displays Outlines.\n"); printf(" N displays Names.\n"); printf("\nPoDoFo Version: %s\n\n", PODOFO_VERSION_STRING); } struct Format { bool document; // D bool classic; // C bool pages; // P bool outlines; // O bool names; // N Format():document(true),classic(true),pages(true),outlines(true),names(true){} }; Format ParseFormat(const std::string& fs) { Format ret; if(fs.find('D') == std::string::npos) ret.document = false; if(fs.find('C') == std::string::npos) ret.classic = false; if(fs.find('P') == std::string::npos) ret.pages = false; if(fs.find('O') == std::string::npos) ret.outlines = false; if(fs.find('N') == std::string::npos) ret.names = false; return ret; } int main( int argc, char* argv[] ) { #if 1 PoDoFo::PdfError::EnableDebug( false ); // turn it off to better view the output from this app! PoDoFo::PdfError::EnableLogging( false ); #endif if( (argc < 2) || (argc > 3) ) { print_help(); return ( -1 ); } char* pszInput = 0; Format format; std::string fName; if(argc == 2) { pszInput = argv[1]; } else if(argc == 3) { pszInput = argv[2]; format = ParseFormat(std::string(argv[1])); } if (pszInput!= NULL) { fName = pszInput; } //else leave empty try { PdfInfo myInfo( fName ); if(format.document) { std::cout << "Document Info" << std::endl; std::cout << "-------------" << std::endl; std::cout << "\tFile: " << fName << std::endl; myInfo.OutputDocumentInfo( std::cout ); std::cout << std::endl; } if(format.classic) { std::cout << "Classic Metadata" << std::endl; std::cout << "----------------" << std::endl; myInfo.OutputInfoDict( std::cout ); std::cout << std::endl; } if(format.pages) { std::cout << "Page Info" << std::endl; std::cout << "---------" << std::endl; myInfo.OutputPageInfo( std::cout ); } if(format.outlines) { std::cout << "Outlines" << std::endl; std::cout << "--------" << std::endl; myInfo.OutputOutlines( std::cout ); } if(format.names) { std::cout << "Names" << std::endl; std::cout << "-----" << std::endl; myInfo.OutputNames( std::cout ); } } catch( PoDoFo::PdfError & e ) { fprintf( stderr, "Error: An error %i ocurred during uncompressing the pdf file.\n", e.GetError() ); e.PrintErrorMsg(); return e.GetError(); } // std::cerr << "All information written sucessfully.\n" << std::endl << std::endl; return 0; } podofo-0.9.3/tools/podofopdfinfo/pdfinfo.cpp0000664000175000017500000002275611515074452021026 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2005 by Dominik Seichter * * domseichter@web.de * * * * 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., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "pdfinfo.h" PdfInfo::PdfInfo( const std::string& inPathname ) { mDoc = new PoDoFo::PdfMemDocument( inPathname.c_str() ); } PdfInfo::~PdfInfo() { if ( mDoc ) { delete mDoc; mDoc = NULL; } } void PdfInfo::OutputDocumentInfo( std::ostream& sOutStream ) { sOutStream << "\tPDF Version: " << PoDoFo::s_szPdfVersionNums[static_cast(mDoc->GetPdfVersion())] << std::endl; sOutStream << "\tPage Count: " << mDoc->GetPageCount() << std::endl; sOutStream << "\tPage Size: " << GuessFormat() << std::endl; sOutStream << std::endl; sOutStream << "\tFast Web View Enabled: " << (mDoc->IsLinearized() ? "Yes" : "No") << std::endl; sOutStream << "\tTagged: " << (static_cast(mDoc)->GetStructTreeRoot() != NULL ? "Yes" : "No") << std::endl; sOutStream << "\tEncrypted: " << (static_cast(mDoc)->GetEncrypted() ? "Yes" : "No") << std::endl; sOutStream << "\tPrinting Allowed: " << (mDoc->IsPrintAllowed() ? "Yes" : "No") << std::endl; sOutStream << "\tModification Allowed: " << (mDoc->IsEditAllowed() ? "Yes" : "No") << std::endl; sOutStream << "\tCopy&Paste Allowed: " << (mDoc->IsCopyAllowed() ? "Yes" : "No") << std::endl; sOutStream << "\tAdd/Modify Annotations Allowed: " << (mDoc->IsEditNotesAllowed() ? "Yes" : "No") << std::endl; sOutStream << "\tFill&Sign Allowed: " << (mDoc->IsFillAndSignAllowed() ? "Yes" : "No") << std::endl; sOutStream << "\tAccessibility Allowed: " << (mDoc->IsAccessibilityAllowed() ? "Yes" : "No") << std::endl; sOutStream << "\tDocument Assembly Allowed: " << (mDoc->IsDocAssemblyAllowed() ? "Yes" : "No") << std::endl; sOutStream << "\tHigh Quality Print Allowed: " << (mDoc->IsHighPrintAllowed() ? "Yes" : "No") << std::endl; } void PdfInfo::OutputInfoDict( std::ostream& sOutStream ) { if( !mDoc->GetInfo() ) sOutStream << "No info dictionary in this PDF file!" << std::endl; else { sOutStream << "\tAuthor: " << mDoc->GetInfo()->GetAuthor().GetStringUtf8() << std::endl; sOutStream << "\tCreator: " << mDoc->GetInfo()->GetCreator().GetStringUtf8() << std::endl; sOutStream << "\tSubject: " << mDoc->GetInfo()->GetSubject().GetStringUtf8() << std::endl; sOutStream << "\tTitle: " << mDoc->GetInfo()->GetTitle().GetStringUtf8() << std::endl; sOutStream << "\tKeywords: " << mDoc->GetInfo()->GetKeywords().GetStringUtf8() << std::endl; sOutStream << "\tTrapped: " << mDoc->GetInfo()->GetTrapped().GetEscapedName() << std::endl; } } void PdfInfo::OutputPageInfo( std::ostream& sOutStream ) { PoDoFo::PdfPage* curPage; PoDoFo::PdfAnnotation* curAnnot; PoDoFo::PdfVariant var; std::string str; int annotCount; int pgCount = mDoc->GetPageCount(); sOutStream << "Page Count: " << pgCount << std::endl; for ( int pg=0; pgGetPage( pg ); sOutStream << "->Internal Number:" << curPage->GetPageNumber() << std::endl; sOutStream << "->Object Number:" << curPage->GetObject()->Reference().ObjectNumber() << " " << curPage->GetObject()->Reference().GenerationNumber() << " R" << std::endl; curPage->GetMediaBox().ToVariant( var ); var.ToString( str ); annotCount = curPage->GetNumAnnots(); sOutStream << "\tMediaBox: " << str << std::endl; sOutStream << "\tRotation: " << curPage->GetRotation() << std::endl; sOutStream << "\t# of Annotations: " << annotCount << std::endl; for( int i=0; i < annotCount; i++ ) { curAnnot = curPage->GetAnnotation( i ); curAnnot->GetRect().ToVariant( var ); var.ToString( str ); sOutStream << std::endl; sOutStream << "\tAnnotation " << i << std::endl; sOutStream << "\t\tType: " << curAnnot->GetType() << std::endl; sOutStream << "\t\tContents: " << curAnnot->GetContents().GetStringUtf8() << std::endl; sOutStream << "\t\tTitle: " << curAnnot->GetTitle().GetStringUtf8() << std::endl; sOutStream << "\t\tFlags: " << curAnnot->GetFlags() << std::endl; sOutStream << "\t\tRect: " << str << std::endl; sOutStream << "\t\tOpen: " << (curAnnot->GetOpen() ? "true" : "false" ) << std::endl; if( curAnnot->GetType() == PoDoFo::ePdfAnnotation_Link ) { sOutStream << "\t\tLink Target: " << curAnnot->GetType() << std::endl; if( curAnnot->HasAction() && curAnnot->GetAction()->HasURI() ) sOutStream << "\t\tAction URI: " << curAnnot->GetAction()->GetURI().GetStringUtf8() << std::endl; } } } } void PdfInfo::OutputOutlines( std::ostream& sOutStream, PoDoFo::PdfOutlineItem* pItem, int level ) { PoDoFo::PdfOutlines* pOutlines; int i; if( !pItem ) { pOutlines = mDoc->GetOutlines( PoDoFo::ePdfDontCreateObject ); if ( !pOutlines || !pOutlines->First() ) { sOutStream << "\tNone Found" << std::endl; return; } pItem = pOutlines->First(); } for( i=0;i" << pItem->GetTitle().GetString(); PoDoFo::PdfDestination* pDest = pItem->GetDestination( mDoc ); if ( pDest ) { // then it's a destination PoDoFo::PdfPage* pPage = pDest->GetPage( mDoc ); if( pPage ) sOutStream << "\tDestination: Page #" << pPage->GetPageNumber(); else sOutStream << "\tDestination: Page #" << "???"; } else { // then it's one or more actions sOutStream << "\tAction: " << "???"; } sOutStream << std::endl; if( pItem->First() ) this->OutputOutlines( sOutStream, pItem->First(), level+1 ); if( pItem->Next() ) this->OutputOutlines( sOutStream, pItem->Next(), level ); } void PdfInfo::OutputOneName( std::ostream& sOutStream, PoDoFo::PdfNamesTree* inTreeObj, const std::string& inTitle, const std::string& inKey ) { sOutStream << "\t" << inTitle << std::endl; PoDoFo::PdfDictionary dict; inTreeObj->ToDictionary( PoDoFo::PdfName( inKey ), dict ); const PoDoFo::TKeyMap& keys = dict.GetKeys(); PoDoFo::TCIKeyMap it = keys.begin(); std::string str; while( it != keys.end() ) { (*it).second->ToString( str ); sOutStream << "\t-> " << (*it).first.GetName().c_str() << "=" << str << std::endl; ++it; } sOutStream << std::endl; } void PdfInfo::OutputNames( std::ostream& sOutStream ) { PoDoFo::PdfNamesTree* namesObj = mDoc->GetNamesTree( PoDoFo::ePdfDontCreateObject ); if ( namesObj ) { OutputOneName( sOutStream, namesObj, "Destinations", "Dests" ); OutputOneName( sOutStream, namesObj, "JavaScripts", "JavaScript" ); OutputOneName( sOutStream, namesObj, "Embedded Files", "EmbeddedFiles" ); } else { sOutStream << "\t\tNone Found" << std::endl; } } std::string PdfInfo::GuessFormat() { typedef std::pair Format; PoDoFo::PdfPage* curPage; int pgCount = mDoc->GetPageCount(); std::map< Format , int > sizes; std::map< Format , int >::iterator sIt; PoDoFo::PdfRect rect; for ( int pg=0; pgGetPage( pg ); rect = curPage->GetMediaBox(); Format s( rect.GetWidth() - rect.GetLeft(), rect.GetHeight() - rect.GetBottom()); sIt = sizes.find(s); if(sIt == sizes.end()) sizes.insert(std::pair(s,1)); else ++(sIt->second); } Format format; std::stringstream ss; if(sizes.size() == 1) { format = sizes.begin()->first; ss << format.first << " x " << format.second << " pts" ; } else { // We’re looking for the most represented format int max=0; for(sIt = sizes.begin();sIt != sizes.end(); ++sIt) { if(sIt->second > max) { max = sIt->second; format = sIt->first; } } ss << format.first << " x " << format.second << " pts "< class BoxSetter { BoxSetter(){} const std::string m_box; const PoDoFo::PdfRect m_rect; void SetBox(PoDoFo::PdfPage * page); bool CompareBox(const PoDoFo::PdfRect& rect1, const PoDoFo::PdfRect& rect2); public: BoxSetter(const std::string& in, const std::string& out, const std::string& box, const PoDoFo::PdfRect& rect); }; #endif // BOXSETTER_H podofo-0.9.3/tools/podofobox/boxsetter.cpp0000664000175000017500000000531512347347566020570 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2010 by Pierre Marchand * * pierre@oep-h.com * * * * 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., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "boxsetter.h" BoxSetter::BoxSetter(const std::string& in, const std::string& out, const std::string& box, const PoDoFo::PdfRect& rect) :m_box(box), m_rect(rect) { PoDoFo::PdfMemDocument* source = new PoDoFo::PdfMemDocument(in.c_str()); int pcount(source->GetPageCount()); for ( int i = 0; i < pcount ; ++i ) { SetBox(source->GetPage ( i )); } source->Write(out.c_str()); } void BoxSetter::SetBox(PoDoFo::PdfPage *page) { if(!page) return; PoDoFo::PdfObject r; m_rect.ToVariant( r ); if(m_box.find("media") != std::string::npos) { page->GetObject()->GetDictionary().AddKey ( PoDoFo::PdfName ( "MediaBox" ), r ); } else if(m_box.find("crop") != std::string::npos) { page->GetObject()->GetDictionary().AddKey ( PoDoFo::PdfName ( "CropBox" ), r ); } else if(m_box.find("bleed") != std::string::npos) { page->GetObject()->GetDictionary().AddKey ( PoDoFo::PdfName ( "BleedBox" ), r ); } else if(m_box.find("trim") != std::string::npos) { page->GetObject()->GetDictionary().AddKey ( PoDoFo::PdfName ( "TrimBox" ), r ); } else if(m_box.find("art") != std::string::npos) { page->GetObject()->GetDictionary().AddKey ( PoDoFo::PdfName ( "ArtBox" ), r ); } // TODO check that box sizes are ordered } bool BoxSetter::CompareBox(const PoDoFo::PdfRect &rect1, const PoDoFo::PdfRect &rect2) { return rect1.ToString() == rect2.ToString(); } podofo-0.9.3/tools/podofobox/podofobox.cpp0000664000175000017500000000466711332333316020536 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2010 by Pierre Marchand * * pierre@oep-h.com * * * * 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., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "podofo.h" #include #include #include #include "boxsetter.h" void print_help() { std::cerr<<"Usage: podofobox [inputfile] [outpufile] [box] [left] [bottom] [width] [height]\n"; std::cerr<<"Box is one of media crop bleed trim art.\n"; std::cerr<<"Give values * 100 as integers (avoid locale headaches with strtod).\n\n"; std::cerr<<"\nPoDoFo Version: "<< PODOFO_VERSION_STRING <<"\n\n"; } int main( int argc, char* argv[] ) { if( argc != 8 ) { print_help(); exit( -1 ); } std::string input = argv[1]; std::string output = argv[2]; std::string box = argv[3]; double left = double(atol(argv[4])) /100.0; double bottom = double(atol(argv[5])) /100.0; double width = double(atol(argv[6])) /100.0; double height = double(atol(argv[7])) /100.0; PoDoFo::PdfRect rect( left , bottom, width, height ); try { BoxSetter bs(input, output, box, rect); } catch( PoDoFo::PdfError & e ) { std::cerr << "Error: An error "<< e.GetError() <<" ocurred during processing the pdf file\n"; e.PrintErrorMsg(); return e.GetError(); } return 0; } podofo-0.9.3/tools/podofobox/CMakeLists.txt0000664000175000017500000000043511332333316020560 0ustar dominikdominikADD_EXECUTABLE(podofobox podofobox.cpp boxsetter.cpp) TARGET_LINK_LIBRARIES(podofobox ${PODOFO_LIB}) SET_TARGET_PROPERTIES(podofobox PROPERTIES COMPILE_FLAGS "${PODOFO_CFLAGS}") ADD_DEPENDENCIES(podofobox ${PODOFO_DEPEND_TARGET}) INSTALL(TARGETS podofobox RUNTIME DESTINATION "bin") podofo-0.9.3/tools/podofoxmp/0000775000175000017500000000000012356565167016054 5ustar dominikdominikpodofo-0.9.3/tools/podofoxmp/CMakeLists.txt0000664000175000017500000000041711430230735020574 0ustar dominikdominikADD_EXECUTABLE(podofoxmp podofoxmp.cpp) TARGET_LINK_LIBRARIES(podofoxmp ${PODOFO_LIB}) SET_TARGET_PROPERTIES(podofoxmp PROPERTIES COMPILE_FLAGS "${PODOFO_CFLAGS}") ADD_DEPENDENCIES(podofoxmp ${PODOFO_DEPEND_TARGET}) INSTALL(TARGETS podofoxmp RUNTIME DESTINATION "bin") podofo-0.9.3/tools/podofoxmp/podofoxmp.cpp0000664000175000017500000000762711763156133020575 0ustar dominikdominik/*************************************************************************** * Copyright (C) 2010 by Ian Ashley * * Ian Ashley * * * * 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., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include #include #include #include #ifdef _MSC_VER #include #include #endif #include using namespace std; int main (int argc, char *argv[]) { PoDoFo::PdfError::EnableDebug(false); if (argc != 2 && argc != 4) { cout << "Syntax" << endl; cout << " " << argv[0] << " - display the XMP in a file (use \"-\" to specify stdin)" << endl; cout << "or" << endl; cout << " " << argv[0] << " <new pdf file> - create a new PDF with the XMP in" << endl; return EXIT_FAILURE; } PoDoFo::PdfMemDocument *doc; if ( string("-") == argv[1] ) { cin >> std::noskipws; #ifdef _MSC_VER _setmode(_fileno(stdin), _O_BINARY); // @TODO: MSVC specific binary setmode -- not sure if other platforms need it cin.sync_with_stdio(); #endif istream_iterator<char> it(std::cin); istream_iterator<char> end; string buffer(it, end); doc = new PoDoFo::PdfMemDocument(); doc->Load( buffer.c_str(), (long)buffer.size() ); } else { doc = new PoDoFo::PdfMemDocument(argv[1]); } if (argc == 2) { PoDoFo::PdfObject *metadata; if ((metadata = doc->GetMetadata()) == NULL) cout << "No metadata" << endl; else { PoDoFo::PdfStream *str = metadata->GetStream(); if (str != NULL) { char *buf; PoDoFo::pdf_long len; str->GetFilteredCopy(&buf, &len); for (PoDoFo::pdf_long i = 0; i < len; ++i) printf("%c", buf[i]); printf("\n"); fflush(stdout); free(buf); } } } if (argc == 4) { char *xmpBuf; FILE *fp; if ((fp = fopen(argv[2], "rb")) == NULL) cout << "Cannot open " << argv[2] << endl; else { fseek(fp, 0, SEEK_END); long xmpLen = ftell(fp); xmpBuf = new char[xmpLen]; fseek(fp, 0, SEEK_SET); fread(xmpBuf, 1, xmpLen, fp); fclose(fp); PoDoFo::PdfObject *metadata; if ((metadata = doc->GetMetadata()) != NULL) metadata->GetStream()->Set(xmpBuf, xmpLen, PoDoFo::TVecFilters()); else { metadata = doc->GetObjects().CreateObject("Metadata"); metadata->GetDictionary().AddKey(PoDoFo::PdfName("Subtype"), PoDoFo::PdfName("XML")); metadata->GetStream()->Set(xmpBuf, xmpLen, PoDoFo::TVecFilters()); doc->GetCatalog()->GetDictionary().AddKey(PoDoFo::PdfName("Metadata"), metadata->Reference()); } delete[] xmpBuf; doc->Write(argv[3]); } } delete doc; return EXIT_SUCCESS; } ���������������������������������������������������������������������������������������������������������podofo-0.9.3/tools/podofoimpose/��������������������������������������������������������������������0000775�0001750�0001750�00000000000�12356565167�016544� 5����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/tools/podofoimpose/charpainter.h�������������������������������������������������������0000664�0001750�0001750�00000005367�10674015620�021211� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*************************************************************************** * Copyright (C) 2007 by Pierre Marchand * * pierre@moulindetouvois.com * * * * 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., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #ifndef CHARPAINTER_H #define CHARPAINTER_H /** @author Pierre Marchand <pierre@moulindetouvois.com> */ #include <ostream> class CharPainter{ public: CharPainter() { } ~CharPainter() { } void paint(std::ostream& s, int n, double size, double x, double y); // call paint() for each digit in the number `n' void multipaint(std::ostream& s, int n, double size, double x, double y); private: // some simple helpers for writing points // TODO: nothrow annotations inline void wdir(std::ostream& s, double x1, double y1, double x2, double y2) const { s << x1 << ' ' << y1 << " m\n" << x2 << ' ' << y2 << " l\n"; } inline void top(std::ostream& s) const { wdir(s, m_x, m_sh, m_sw, m_x); } inline void topright(std::ostream& s) const { wdir(s, m_sw, m_sh, m_sw, m_midh); } inline void bottomright(std::ostream& s) const { wdir(s, m_sw, m_midh, m_sw, m_y); } inline void bottom(std::ostream& s) const { wdir(s, m_x, m_y, m_sw, m_y); } inline void bottomleft(std::ostream&s) const { wdir(s, m_x, m_y, m_x, m_midh); } inline void topleft(std::ostream& s) const { wdir(s, m_x, m_midh, m_x, m_sh); } inline void center(std::ostream& s) const { wdir(s, m_x, m_midh, m_sw, m_midh); } // temporaries used by paint(...) double m_size; double m_x; double m_y; double m_sh; double m_sw; double m_midh; }; #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/tools/podofoimpose/sample.pdf����������������������������������������������������������0000664�0001750�0001750�00000057420�11044703333�020506� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������%PDF-1.4 %쏢 1 0 obj << /Type /Catalog /Outlines 3 0 R /Pages 4 0 R /Dests 5 0 R /AcroForm 6 0 R /Names 7 0 R /Threads 8 0 R /PageLayout /SinglePage /ViewerPreferences << /PageDirection /L2R >> >> endobj 2 0 obj << /Creator (Scribus 1.3.3.13svn) /Producer (Scribus PDF Library 1.3.3.13svn) /Title <> /Author <> /Keywords <> /CreationDate (D:20080801001624) /ModDate (D:20080801001624) /Trapped /False >> endobj 9 0 obj << /Type /XObject /Subtype /Form /FormType 1 /BBox [ 0.03600 -0.33900 0.47800 -1.01100 ] /Resources << /ProcSet [/PDF /Text /ImageB /ImageC /ImageI] >> /Length 188 /Filter /FlateDecode >> stream xڕA 0 yE΅Ik{(rRۅBofZ D1B5B�RT-!�(z`!3m2͹g* WB/!zֹF4SsQ"Gءr9Q"ÇC8@bgӅ \;}MNg'88t endstream endobj 10 0 obj << /Type /XObject /Subtype /Form /FormType 1 /BBox [ 0.10400 -0.35000 0.32100 -1.00000 ] /Resources << /ProcSet [/PDF /Text /ImageB /ImageC /ImageI] >> /Length 110 /Filter /FlateDecode >> stream x} >E {`t_(˓||c.w=SXsmB!%ȡ (R rJw& FG i@ Ro endstream endobj 11 0 obj << /Type /XObject /Subtype /Form /FormType 1 /BBox [ 0.04500 -0.33900 0.46000 -1.00000 ] /Resources << /ProcSet [/PDF /Text /ImageB /ImageC /ImageI] >> /Length 203 /Filter /FlateDecode >> stream x} Dw"sF _!0>q X)�+ X lf!=lzLA<< b {1N^sIr5&HkvV3PjM"":D<2^>N  GfmNކ^4:. q9>�Nˇ.0̎ endstream endobj 12 0 obj << /Type /XObject /Subtype /Form /FormType 1 /BBox [ 0.04200 -0.33900 0.44800 -1.01100 ] /Resources << /ProcSet [/PDF /Text /ImageB /ImageC /ImageI] >> /Length 275 /Filter /FlateDecode >> stream x}Mn 9Ŭ+ 3R;mҴ+Ч@!R/qTk@B N@\MkD liByjU CTHT3!dHzf{0]T&�k ꠁ|f% 5�Zg {k%dX[Z#(GWd^`Qi[SЬ`(<45X0qVS>-G8Ww 4AZCl!y|q endstream endobj 13 0 obj << /Type /XObject /Subtype /Form /FormType 1 /BBox [ 0.01500 -0.35000 0.49100 -1.00000 ] /Resources << /ProcSet [/PDF /Text /ImageB /ImageC /ImageI] >> /Length 203 /Filter /FlateDecode >> stream xڅA =p=ɘByHlvP0B 0{H3\À`^ -!\n&׀LݺxM 4`A!&@XH`ApݶGy]F)}R͂A4J-jpZAle\> G#͔ri-lb' w:LOt2_q~ endstream endobj 14 0 obj << /Type /XObject /Subtype /Form /FormType 1 /BBox [ 0.04200 -0.35000 0.44600 -1.01100 ] /Resources << /ProcSet [/PDF /Text /ImageB /ImageC /ImageI] >> /Length 230 /Filter /FlateDecode >> stream x}10EwsF6Tu:`M;%z>`X8g , f k:@0@Ҽp."*fꊣ&KuPqd :jہ15#�%LfffaR/@ `351#M郠sۋP)@~'!yz+ NUQ6fVe xI~?iO`M^ endstream endobj 15 0 obj << /Type /XObject /Subtype /Form /FormType 1 /BBox [ 0.03400 -0.34000 0.48000 -1.01100 ] /Resources << /ProcSet [/PDF /Text /ImageB /ImageC /ImageI] >> /Length 286 /Filter /FlateDecode >> stream x}9n0 E9Ơ<4-!ٓT$񋆃<_pC[<y2`i&$2jJM} x%:FAw`c1Dhn]~ʼ*KT^t"bv_W0()\B_0$یE?DH.)I"<AĎ:57IԼ{~Y W :73DqZIISL٦kRJDPwH?$`֎na@*F endstream endobj 16 0 obj << /Type /XObject /Subtype /Form /FormType 1 /BBox [ 0.05700 -0.35000 0.46700 -1.00000 ] /Resources << /ProcSet [/PDF /Text /ImageB /ImageC /ImageI] >> /Length 109 /Filter /FlateDecode >> stream x}A ὧp$t#D)Gw?P@ 3\ ܇@4(FiB!hԐb6"w�4x'k}$<7;F͗w�R endstream endobj 17 0 obj << /Type /XObject /Subtype /Form /FormType 1 /BBox [ 0.03700 -0.33900 0.47600 -1.01100 ] /Resources << /ProcSet [/PDF /Text /ImageB /ImageC /ImageI] >> /Length 331 /Filter /FlateDecode >> stream xڕMn09Ŭ+53>HU7vFJDבL:t&(msS?ZLAv ͠^IQe@aZ(PEOS`AabHd(n_5x5E- ^gZC4P.X:mAm([s&>c*ftpZ!,*m|KL(=#Bt@q@նQ~ ;+1/Dfi ] !psA360yyqqy簝b6! Ծ=FyXg`S;�Q endstream endobj 18 0 obj << /Type /XObject /Subtype /Form /FormType 1 /BBox [ 0.04000 -0.33900 0.47800 -1.01100 ] /Resources << /ProcSet [/PDF /Text /ImageB /ImageC /ImageI] >> /Length 302 /Filter /FlateDecode >> stream x}Mn0s+5gRM■mr7< 8)' /8%�4f ?]Tx"8[YCޥU�kQa)EqD>^Qa5] DS0%x^kHu1�_0E]#o�wKj&I[^higfӽ+=&J-+&;g7Y eUIr$o"`̫�ϡ`Z‹,e~m]9$b <m"=zn endstream endobj 19 0 obj << /Type /XObject /Subtype /Form /FormType 1 /BBox [ 0 0 419.52756 595.27559 ] /Resources << /ProcSet [/PDF /Text /ImageB /ImageC /ImageI] >> /Length 95 /Filter /FlateDecode >> stream x=10 w"/- ؀1I,Y@80$rReЋm'B )YZ [зr5+f||p endstream endobj 20 0 obj << /Length 196 /Filter /FlateDecode >> stream xmP 0WnlMAP)x)ՖbV"I}P,d6$BB-`5ٲ [t%ӄy0+@r1DĬWwp$*G6F}U^zh`kHCS{OEܵeY-,r-]vʫ2ku&3?'<Mh Hm endstream endobj 21 0 obj << /S /Transparency /CS /DeviceRGB >> endobj 22 0 obj << /Type /Page /Parent 4 0 R /MediaBox [0 0 419.52756 595.27559] /TrimBox [0 0 419.52756 595.27559] /Rotate 0 /Contents 20 0 R /Group 21 0 R >> endobj 23 0 obj << /Length 196 /Filter /FlateDecode >> stream xmP 0WnlMAP)x)ՖbV"I}P,d6$BB-`5ٲ [t%ӄy0+@r1DĬWwp$*G6F}U^zh`kHCS{OEܵeYcq &\KmLO4?a|S/Z0JHe endstream endobj 24 0 obj << /S /Transparency /CS /DeviceRGB >> endobj 25 0 obj << /Type /Page /Parent 4 0 R /MediaBox [0 0 419.52756 595.27559] /TrimBox [0 0 419.52756 595.27559] /Rotate 0 /Contents 23 0 R /Group 24 0 R >> endobj 26 0 obj << /Length 195 /Filter /FlateDecode >> stream xmPA 0+4&Wы <(jTߛT-EBfL2!$ V)'Ȗoآ+q'&|. XN)S-)&"fڃ P�=1CWy2Ղ! eO=Mn_f,~,K50o+tʼrhM^`Hf endstream endobj 27 0 obj << /S /Transparency /CS /DeviceRGB >> endobj 28 0 obj << /Type /Page /Parent 4 0 R /MediaBox [0 0 419.52756 595.27559] /TrimBox [0 0 419.52756 595.27559] /Rotate 0 /Contents 26 0 R /Group 27 0 R >> endobj 29 0 obj << /Length 196 /Filter /FlateDecode >> stream xmP 0WnlMAP)x)ՖbV"I}P,d6$BB-`5ٲ [t%ӄy0+@r1DĬWwp$*G6F}U^zh`kHCS{OEܵeYc]EM~.;U: hM^`Hg endstream endobj 30 0 obj << /S /Transparency /CS /DeviceRGB >> endobj 31 0 obj << /Type /Page /Parent 4 0 R /MediaBox [0 0 419.52756 595.27559] /TrimBox [0 0 419.52756 595.27559] /Rotate 0 /Contents 29 0 R /Group 30 0 R >> endobj 32 0 obj << /Length 195 /Filter /FlateDecode >> stream xmPA 0+4[ET"R,jTߛh+EBfL2!$ VCN- ߰EWO =M5\@ N*ZSpMD{V0Y #J/QFzl `({~ht,f,1s㸁Ż: H]TO40wԋ_Hh endstream endobj 33 0 obj << /S /Transparency /CS /DeviceRGB >> endobj 34 0 obj << /Type /Page /Parent 4 0 R /MediaBox [0 0 419.52756 595.27559] /TrimBox [0 0 419.52756 595.27559] /Rotate 0 /Contents 32 0 R /Group 33 0 R >> endobj 35 0 obj << /Length 196 /Filter /FlateDecode >> stream xmP 0WnlMAP)x)ՖbV"I}P,d6$BB-`5ٲ [t%ӄy0+@r1DĬWwp$*G6F}U^zh`kHCS{OEܵeYc]EM~.;U: hM^`Hi endstream endobj 36 0 obj << /S /Transparency /CS /DeviceRGB >> endobj 37 0 obj << /Type /Page /Parent 4 0 R /MediaBox [0 0 419.52756 595.27559] /TrimBox [0 0 419.52756 595.27559] /Rotate 0 /Contents 35 0 R /Group 36 0 R >> endobj 38 0 obj << /Length 196 /Filter /FlateDecode >> stream xmP 0WnlMAP)x)ՖbV"I}P,d6$BB-`5ٲ [t%ӄy0+@r1DĬWwp$*G6F}U^zh`kHCS{OEܵeYcq &\KmLO4?a|S/Z0RHj endstream endobj 39 0 obj << /S /Transparency /CS /DeviceRGB >> endobj 40 0 obj << /Type /Page /Parent 4 0 R /MediaBox [0 0 419.52756 595.27559] /TrimBox [0 0 419.52756 595.27559] /Rotate 0 /Contents 38 0 R /Group 39 0 R >> endobj 41 0 obj << /Length 195 /Filter /FlateDecode >> stream xmP 0WnlMAP<jKQjTĿw"f!L&Z.gȞ41T8h _z'Њ,W!nʮUΦ]3 3 e2�9P8vZ[ޑlB%{84iU_wEd&JRXUެudDh7EHk endstream endobj 42 0 obj << /S /Transparency /CS /DeviceRGB >> endobj 43 0 obj << /Type /Page /Parent 4 0 R /MediaBox [0 0 419.52756 595.27559] /TrimBox [0 0 419.52756 595.27559] /Rotate 0 /Contents 41 0 R /Group 42 0 R >> endobj 44 0 obj << /Length 195 /Filter /FlateDecode >> stream xmPA 0+4&Wы <(jTߛ-EBfL2!$ V)'Ȗoآ+q'&. XN)S-)&"f3 zdcTe=ToE[C2ʞ{*>ݾ\3XX8Nq]Q]\oEU\O4ۇ0ԋ_"Hl endstream endobj 45 0 obj << /S /Transparency /CS /DeviceRGB >> endobj 46 0 obj << /Type /Page /Parent 4 0 R /MediaBox [0 0 419.52756 595.27559] /TrimBox [0 0 419.52756 595.27559] /Rotate 0 /Contents 44 0 R /Group 45 0 R >> endobj 47 0 obj << /Length 213 /Filter /FlateDecode >> stream xڥQj1W4NL6e]E-oR< d&y/ !!kdbQ8P@GZQZxWzf񘒪Ucu{8Y H 0vq=ԑbiS Nm;IP9Bo"4/oU/{6|]3+k?P/UȏE].׹NhO!} $~=d endstream endobj 48 0 obj << /S /Transparency /CS /DeviceRGB >> endobj 49 0 obj << /Type /Page /Parent 4 0 R /MediaBox [0 0 419.52756 595.27559] /TrimBox [0 0 419.52756 595.27559] /Rotate 0 /Contents 47 0 R /Group 48 0 R >> endobj 50 0 obj << /Length 210 /Filter /FlateDecode >> stream xڭQˊ1Wdcr DYguG"/ӲiHuRjJL_,jHgX,]?pRY9)Z G >f@8�#s慡=U@J# uG#.a]Vus.{0tͬ1?U-:kSB'h-Z~!N ɥd endstream endobj 51 0 obj << /S /Transparency /CS /DeviceRGB >> endobj 52 0 obj << /Type /Page /Parent 4 0 R /MediaBox [0 0 419.52756 595.27559] /TrimBox [0 0 419.52756 595.27559] /Rotate 0 /Contents 50 0 R /Group 51 0 R >> endobj 53 0 obj << /Length 214 /Filter /FlateDecode >> stream xڥQj1W4;dP" l(RMtwYē@fJL!ŋx 5t @+J `w0 YrSR*Z%̖@hsf衉Ljtg%ޑNz^~öCZ7*i 5_*;TsϪ}WR'Nt-A46fd endstream endobj 54 0 obj << /S /Transparency /CS /DeviceRGB >> endobj 55 0 obj << /Type /Page /Parent 4 0 R /MediaBox [0 0 419.52756 595.27559] /TrimBox [0 0 419.52756 595.27559] /Rotate 0 /Contents 53 0 R /Group 54 0 R >> endobj 56 0 obj << /Length 213 /Filter /FlateDecode >> stream xڥQMk1ϯ?8dPhEȲeQۦ-7Yēf 3{y^ Y{%&EA< t �?GXŻ |݅rQR*ZK el49s顎Ljtg%ޑNz¶ܼiQ2Yokfe}_tjr(P|uU4]-]EC"7Mgd endstream endobj 57 0 obj << /S /Transparency /CS /DeviceRGB >> endobj 58 0 obj << /Type /Page /Parent 4 0 R /MediaBox [0 0 419.52756 595.27559] /TrimBox [0 0 419.52756 595.27559] /Rotate 0 /Contents 56 0 R /Group 57 0 R >> endobj 59 0 obj << /Length 214 /Filter /FlateDecode >> stream xڥQj1W4;dP" l(RMtwYē@fJL!ŋx 5t @+J `w0 YrSR*Z%̖@hsf衉Ljtg%ޑNz^~öCZ7*i 5_?UvN:USԥNh&Zim6d endstream endobj 60 0 obj << /S /Transparency /CS /DeviceRGB >> endobj 61 0 obj << /Type /Page /Parent 4 0 R /MediaBox [0 0 419.52756 595.27559] /TrimBox [0 0 419.52756 595.27559] /Rotate 0 /Contents 59 0 R /Group 60 0 R >> endobj 62 0 obj << /Length 213 /Filter /FlateDecode >> stream xڥQj1W'ٙlr-z+ ,[][oe d&y/ !!kbQ8P #LA+J m`prQR*Z?_ @hs]=txG: s8Gh<jhY7_*I sZ:TCuCylw.uBG"oDoǞd endstream endobj 63 0 obj << /S /Transparency /CS /DeviceRGB >> endobj 64 0 obj << /Type /Page /Parent 4 0 R /MediaBox [0 0 419.52756 595.27559] /TrimBox [0 0 419.52756 595.27559] /Rotate 0 /Contents 62 0 R /Group 63 0 R >> endobj 65 0 obj << /Length 214 /Filter /FlateDecode >> stream xڥQj1W4;dP" l(RMtwYē@fJL!ŋx 5t @+J `w0 YrSR*Z%̖@hsf衉Ljtg%ޑNz^~öCZ7*i 5_*;TsϪ}WR'Nt-A46d endstream endobj 66 0 obj << /S /Transparency /CS /DeviceRGB >> endobj 67 0 obj << /Type /Page /Parent 4 0 R /MediaBox [0 0 419.52756 595.27559] /TrimBox [0 0 419.52756 595.27559] /Rotate 0 /Contents 65 0 R /Group 66 0 R >> endobj 68 0 obj << /Length 214 /Filter /FlateDecode >> stream xڥQj1W4;dP" l(RMtwYē@fJL!ŋx 5t @+J `w0 YrSR*Z%̖@hsf衉Ljtg%ޑNz^~öCZ7*i 5_*;TsϪ}WR'Nt-A46nd endstream endobj 69 0 obj << /S /Transparency /CS /DeviceRGB >> endobj 70 0 obj << /Type /Page /Parent 4 0 R /MediaBox [0 0 419.52756 595.27559] /TrimBox [0 0 419.52756 595.27559] /Rotate 0 /Contents 68 0 R /Group 69 0 R >> endobj 71 0 obj << /Length 214 /Filter /FlateDecode >> stream xڥQj1W4;*z)jz(eQmSKwbUL^ރBBшGbtW܁U'XCy-@>3GlU)Up<8]Bp:cl$YY79/mG02=?Wm>ꮭ庲h"Z>!rAYd endstream endobj 72 0 obj << /S /Transparency /CS /DeviceRGB >> endobj 73 0 obj << /Type /Page /Parent 4 0 R /MediaBox [0 0 419.52756 595.27559] /TrimBox [0 0 419.52756 595.27559] /Rotate 0 /Contents 71 0 R /Group 72 0 R >> endobj 74 0 obj << /Length 214 /Filter /FlateDecode >> stream xڥQAj0+W,]Cs)`ȡ$$q>RSzj]iF30"$d하B,\t Њoxyw;0YrSR*Z?%,J el493Fq榞jruJ#9#=þ-C?[5[CsZ{WTYW>PmSC+?_Mh>d endstream endobj 75 0 obj << /S /Transparency /CS /DeviceRGB >> endobj 76 0 obj << /Type /Page /Parent 4 0 R /MediaBox [0 0 419.52756 595.27559] /TrimBox [0 0 419.52756 595.27559] /Rotate 0 /Contents 74 0 R /Group 75 0 R >> endobj 77 0 obj << /Length 213 /Filter /FlateDecode >> stream xڥQj1W4NL6e]E-oR< d&y/ !!kdbQ8P@GZQZxWzf񘒪Ucu{8Y H 0vq=ԑbiS Nm;IP9Bo"4/oU/NX>箙?F|B~,*o>vuBDK.&+d endstream endobj 78 0 obj << /S /Transparency /CS /DeviceRGB >> endobj 79 0 obj << /Type /Page /Parent 4 0 R /MediaBox [0 0 419.52756 595.27559] /TrimBox [0 0 419.52756 595.27559] /Rotate 0 /Contents 77 0 R /Group 78 0 R >> endobj 80 0 obj << /Length 214 /Filter /FlateDecode >> stream xڥQj1W4;dP" l(RMtwYē@fJL!ŋx 5t @+J `w0 YrSR*Z%̖@hsf衉Ljtg%ޑNz^~öCZ7*ᴅcYYk*;TsϪ}WR'Nt-A46fd endstream endobj 81 0 obj << /S /Transparency /CS /DeviceRGB >> endobj 82 0 obj << /Type /Page /Parent 4 0 R /MediaBox [0 0 419.52756 595.27559] /TrimBox [0 0 419.52756 595.27559] /Rotate 0 /Contents 80 0 R /Group 81 0 R >> endobj 83 0 obj << /Length 207 /Filter /FlateDecode >> stream xڭQ 0WnlLAP<jKQjTĿ7EOb2d&Z:ٱ ;%Nq2Є}HAqfpW>ʶV]HYz LZF_qzӂ% eC ~C_eu 5~.Ƙ̏l>ʬ^3~>կ _Ԉ6�'d endstream endobj 84 0 obj << /S /Transparency /CS /DeviceRGB >> endobj 85 0 obj << /Type /Page /Parent 4 0 R /MediaBox [0 0 419.52756 595.27559] /TrimBox [0 0 419.52756 595.27559] /Rotate 0 /Contents 83 0 R /Group 84 0 R >> endobj 86 0 obj << /Length 209 /Filter /FlateDecode >> stream xڥQ 0W7i6&Wы DJ(j5*ߛE<id&Z:ٱ;p2}#HAqpn̎V'UHXaw )P&`lzw_qzv;K2 9=u|՚ey&U0]j-1ˇ.; H&i~>կ _Ԉ6d endstream endobj 87 0 obj << /S /Transparency /CS /DeviceRGB >> endobj 88 0 obj << /Type /Page /Parent 4 0 R /MediaBox [0 0 419.52756 595.27559] /TrimBox [0 0 419.52756 595.27559] /Rotate 0 /Contents 86 0 R /Group 87 0 R >> endobj 89 0 obj << /Length 209 /Filter /FlateDecode >> stream xڥQ 0WnlLAP<jKQjTĿ7EO&3 !NjAv,}S܁ 0c_n�RP\x<7)EU#RA3H( 0tVEYT8=ӂ%eٜ ~C_eu 5~sZ c_+S}^YXg2-}D_A0md endstream endobj 90 0 obj << /S /Transparency /CS /DeviceRGB >> endobj 91 0 obj << /Type /Page /Parent 4 0 R /MediaBox [0 0 419.52756 595.27559] /TrimBox [0 0 419.52756 595.27559] /Rotate 0 /Contents 89 0 R /Group 90 0 R >> endobj 92 0 obj << /Length 209 /Filter /FlateDecode >> stream xڥQ 0WnlLAP<(jTĿ7EO&3 !NjAv,}S܁ 0c_Vp�)(.lV7)EU#RA3H( 0tV/EYT8=ӂ%eٜ ~n=vk.ƘӇʏg,zd&#%ZV`~}S#(~_d endstream endobj 93 0 obj << /S /Transparency /CS /DeviceRGB >> endobj 94 0 obj << /Type /Page /Parent 4 0 R /MediaBox [0 0 419.52756 595.27559] /TrimBox [0 0 419.52756 595.27559] /Rotate 0 /Contents 92 0 R /Group 93 0 R >> endobj 95 0 obj << /Length 213 /Filter /FlateDecode >> stream xڥQj1W4NL6e]E-oR< d&y/ !!kdbQ8P@GZQZxWzf񘒪Ucu{8Y H 0vq=ԑbiS Nm;IP9Bo"4/oU/NX>箙_|O5:KcQWyu Z-wAt46_d endstream endobj 96 0 obj << /S /Transparency /CS /DeviceRGB >> endobj 97 0 obj << /Type /Page /Parent 4 0 R /MediaBox [0 0 419.52756 595.27559] /TrimBox [0 0 419.52756 595.27559] /Rotate 0 /Contents 95 0 R /Group 96 0 R >> endobj 98 0 obj << /Length 209 /Filter /FlateDecode >> stream xڥQ 0WnlLAP<jKQjTĿ7EO&3 !NjAv,}S܁ 0c_n�RP\x<7)EU#RA3H( 0tVEYT8=ӂ%eٜ ~C_eu 5~sZ c_l>ʬ^3Ɉ~>կ _Ԉ6�/d endstream endobj 99 0 obj << /S /Transparency /CS /DeviceRGB >> endobj 100 0 obj << /Type /Page /Parent 4 0 R /MediaBox [0 0 419.52756 595.27559] /TrimBox [0 0 419.52756 595.27559] /Rotate 0 /Contents 98 0 R /Group 99 0 R >> endobj 101 0 obj << /Length 209 /Filter /FlateDecode >> stream xڥQ 0WnlLAP<jKQjTĿ7EO&3 !NjAv,}S܁ 0c_n�RP\x<7)EU#RA3H( 0tVEYT8=ӂ%eٜ ~C_eu 5~sZ c_+S}^YXg2-}D_A0md endstream endobj 102 0 obj << /S /Transparency /CS /DeviceRGB >> endobj 103 0 obj << /Type /Page /Parent 4 0 R /MediaBox [0 0 419.52756 595.27559] /TrimBox [0 0 419.52756 595.27559] /Rotate 0 /Contents 101 0 R /Group 102 0 R >> endobj 104 0 obj << /Length 209 /Filter /FlateDecode >> stream xڥQ 0W7i6MAP<(jTĿ7EO&3 !NJ ;a`)@/+8^`6w+P͛jauBQՈuк?L7 U@QV=c5N`gIFA`6�WWC_Ey 5~sZ c_?Vʏg,zd&#%ZV`~}S#(~d endstream endobj 105 0 obj << /S /Transparency /CS /DeviceRGB >> endobj 106 0 obj << /Type /Page /Parent 4 0 R /MediaBox [0 0 419.52756 595.27559] /TrimBox [0 0 419.52756 595.27559] /Rotate 0 /Contents 104 0 R /Group 105 0 R >> endobj 107 0 obj << /Length 214 /Filter /FlateDecode >> stream xڥQMk1ϯ?8dԋ "xuY*jR&!Kf oy/JL.ŋx : ЊؼŻޙrQb*\t26 `Dq1Ա8ӳz;҉P:y,MQyzCDs/SZ>N?X~~U8uU4}uXKF&d endstream endobj 108 0 obj << /S /Transparency /CS /DeviceRGB >> endobj 109 0 obj << /Type /Page /Parent 4 0 R /MediaBox [0 0 419.52756 595.27559] /TrimBox [0 0 419.52756 595.27559] /Rotate 0 /Contents 107 0 R /Group 108 0 R >> endobj 110 0 obj << /Length 214 /Filter /FlateDecode >> stream xڥQMk1ϯ?8dPhEȲeQۦ-7Yēf oy/JL.ŋx X&Vc6`wΜUpjK/Q�#s悡-ƙ=ԣg%ޑNz9cir rEU g ݧ}~ɡB]UѬw.ݰF&3Nd endstream endobj 111 0 obj << /S /Transparency /CS /DeviceRGB >> endobj 112 0 obj << /Type /Page /Parent 4 0 R /MediaBox [0 0 419.52756 595.27559] /TrimBox [0 0 419.52756 595.27559] /Rotate 0 /Contents 110 0 R /Group 111 0 R >> endobj 113 0 obj << /Length 209 /Filter /FlateDecode >> stream xڥQM 0 WXӮU"*1:mC<i}iW^ tU cv d(> ŅW/] @ywv:jD:pՃ)@B ZF_eՓ=FD;K2Fg3Y>UkRmYboRkaK1ڻt.|z"TXK̯ojXd endstream endobj 114 0 obj << /S /Transparency /CS /DeviceRGB >> endobj 115 0 obj << /Type /Page /Parent 4 0 R /MediaBox [0 0 419.52756 595.27559] /TrimBox [0 0 419.52756 595.27559] /Rotate 0 /Contents 113 0 R /Group 114 0 R >> endobj 116 0 obj << /ProcSet [/PDF /Text /ImageB /ImageC /ImageI] /XObject << /MyriadPro-Regular48 9 0 R /MyriadPro-Regular49 10 0 R /MyriadPro-Regular50 11 0 R /MyriadPro-Regular51 12 0 R /MyriadPro-Regular52 13 0 R /MyriadPro-Regular53 14 0 R /MyriadPro-Regular54 15 0 R /MyriadPro-Regular55 16 0 R /MyriadPro-Regular56 17 0 R /MyriadPro-Regular57 18 0 R /master_page_obj_1_1 19 0 R >> >> endobj 3 0 obj << /Type /Outlines /Count 0 >> endobj 4 0 obj << /Type /Pages /Kids [22 0 R 25 0 R 28 0 R 31 0 R 34 0 R 37 0 R 40 0 R 43 0 R 46 0 R 49 0 R 52 0 R 55 0 R 58 0 R 61 0 R 64 0 R 67 0 R 70 0 R 73 0 R 76 0 R 79 0 R 82 0 R 85 0 R 88 0 R 91 0 R 94 0 R 97 0 R 100 0 R 103 0 R 106 0 R 109 0 R 112 0 R 115 0 R ] /Count 32 /Resources 116 0 R >> endobj 5 0 obj << >> endobj 6 0 obj << /Fields [ ] >> endobj 7 0 obj << >> endobj 8 0 obj [] endobj xref 0 117 0000000000 65535 f 0000000015 00000 n 0000000207 00000 n 0000021397 00000 n 0000021443 00000 n 0000021745 00000 n 0000021766 00000 n 0000021800 00000 n 0000021822 00000 n 0000000414 00000 n 0000000822 00000 n 0000001153 00000 n 0000001577 00000 n 0000002073 00000 n 0000002497 00000 n 0000002948 00000 n 0000003455 00000 n 0000003785 00000 n 0000004337 00000 n 0000004860 00000 n 0000005165 00000 n 0000005434 00000 n 0000005488 00000 n 0000005648 00000 n 0000005917 00000 n 0000005971 00000 n 0000006131 00000 n 0000006399 00000 n 0000006453 00000 n 0000006613 00000 n 0000006882 00000 n 0000006936 00000 n 0000007096 00000 n 0000007364 00000 n 0000007418 00000 n 0000007578 00000 n 0000007847 00000 n 0000007901 00000 n 0000008061 00000 n 0000008330 00000 n 0000008384 00000 n 0000008544 00000 n 0000008812 00000 n 0000008866 00000 n 0000009026 00000 n 0000009294 00000 n 0000009348 00000 n 0000009508 00000 n 0000009794 00000 n 0000009848 00000 n 0000010008 00000 n 0000010291 00000 n 0000010345 00000 n 0000010505 00000 n 0000010792 00000 n 0000010846 00000 n 0000011006 00000 n 0000011292 00000 n 0000011346 00000 n 0000011506 00000 n 0000011793 00000 n 0000011847 00000 n 0000012007 00000 n 0000012293 00000 n 0000012347 00000 n 0000012507 00000 n 0000012794 00000 n 0000012848 00000 n 0000013008 00000 n 0000013295 00000 n 0000013349 00000 n 0000013509 00000 n 0000013796 00000 n 0000013850 00000 n 0000014010 00000 n 0000014297 00000 n 0000014351 00000 n 0000014511 00000 n 0000014797 00000 n 0000014851 00000 n 0000015011 00000 n 0000015298 00000 n 0000015352 00000 n 0000015512 00000 n 0000015792 00000 n 0000015846 00000 n 0000016006 00000 n 0000016288 00000 n 0000016342 00000 n 0000016502 00000 n 0000016784 00000 n 0000016838 00000 n 0000016998 00000 n 0000017280 00000 n 0000017334 00000 n 0000017494 00000 n 0000017780 00000 n 0000017834 00000 n 0000017994 00000 n 0000018276 00000 n 0000018330 00000 n 0000018491 00000 n 0000018774 00000 n 0000018829 00000 n 0000018992 00000 n 0000019275 00000 n 0000019330 00000 n 0000019493 00000 n 0000019781 00000 n 0000019836 00000 n 0000019999 00000 n 0000020287 00000 n 0000020342 00000 n 0000020505 00000 n 0000020788 00000 n 0000020843 00000 n 0000021006 00000 n trailer << /Size 117 /Root 1 0 R /Info 2 0 R /ID [<0B8271610621E4061F9B76A7DE7D539B><0B8271610621E4061F9B76A7DE7D539B>] >> startxref 21840 %%EOF ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/tools/podofoimpose/pdftranslator.cpp���������������������������������������������������0000664�0001750�0001750�00000036534�11341226006�022121� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*************************************************************************** * Copyright (C) 2007 by Pierre Marchand * * pierre@moulindetouvois.com * * * * 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., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "pdftranslator.h" // #include "charpainter.h" #include "planreader_legacy.h" #ifdef PODOFO_HAVE_LUA #include "planreader_lua.h" #endif #include <fstream> #include <stdexcept> #include <algorithm> #include <cmath> #include <istream> #include <ostream> #include <cstdlib> using std::ostringstream; using std::map; using std::vector; using std::string; using std::ifstream; using std::istream; using std::ostream; using std::endl; using std::runtime_error; #include <iostream> //XXX namespace PoDoFo { namespace Impose { #define MAX_SOURCE_PAGES 5000 #define MAX_RECORD_SIZE 2048 bool PdfTranslator::checkIsPDF ( std::string path ) { ifstream in ( path.c_str(), ifstream::in ); if ( !in.good() ) throw runtime_error ( "setSource() failed to open input file" ); const int magicBufferLen = 5; char magicBuffer[magicBufferLen ]; in.read ( magicBuffer, magicBufferLen ); std::string magic ( magicBuffer , magicBufferLen ); in.close(); if ( magic.find ( "%PDF" ) < 5 ) return true; // throw runtime_error("First bytes of the file tend to indicate it is not a PDF file"); return false; } PdfTranslator::PdfTranslator ( ) { std::cerr<<"PdfTranslator::PdfTranslator"<<std::endl; sourceDoc = 0; targetDoc = 0; extraSpace = 0; scaleFactor = 1.0; } void PdfTranslator::setSource ( const std::string & source ) { int dbg(0); // std::cerr<<"PdfTranslator::setSource "<<source<<std::endl; std::cerr<< ++dbg <<std::endl; if ( checkIsPDF ( source ) ) { // std::cerr << "Appending "<<source<<" to source" << endl; multiSource.push_back ( source ); } else { ifstream in ( source.c_str(), ifstream::in ); if ( !in.good() ) throw runtime_error ( "setSource() failed to open input file" ); char *filenameBuffer = new char[1000]; do { in.getline ( filenameBuffer, 1000 ); std::string ts ( filenameBuffer, in.gcount() ); if ( ts.size() > 4 ) // at least ".pdf" because just test if ts is empty doesn't work. { multiSource.push_back ( ts ); std::cerr << "Appending "<< ts <<" to source" << endl; } } while ( !in.eof() ); in.close(); delete filenameBuffer; } std::cerr<< ++dbg <<std::endl; for ( std::vector<std::string>::const_iterator ms = multiSource.begin(); ms != multiSource.end(); ++ms ) { if ( ms == multiSource.begin() ) { // std::cerr << "First doc is "<< (*ms).c_str() << endl; try{ sourceDoc = new PdfMemDocument ( ( *ms ).c_str() ); } catch(PdfError& e) { std::cerr<<"Unable to create Document: " <<PdfError::ErrorMessage( e. GetError() )<<endl; return; } } else { PdfMemDocument mdoc ( ( *ms ).c_str() ); // std::cerr << "Appending "<< mdoc.GetPageCount() << " page(s) of " << *ms << endl; sourceDoc->InsertPages ( mdoc, 0, mdoc.GetPageCount() ); } } pcount = sourceDoc->GetPageCount(); // std::cerr << "Document has "<< pcount << " page(s) " << endl; if ( pcount > 0 ) // only here to avoid possible segfault, but PDF without page is not conform IIRC { PoDoFo::PdfRect rect ( sourceDoc->GetPage ( 0 )->GetMediaBox() ); // keep in mind it’s just a hint since PDF can have different page sizes in a same doc sourceWidth = rect.GetWidth() - rect.GetLeft(); sourceHeight = rect.GetHeight() - rect.GetBottom() ; } } void PdfTranslator::addToSource ( const std::string & source ) { // std::cerr<<"PdfTranslator::addToSource "<< source<<std::endl; if ( !sourceDoc ) return; PdfMemDocument extraDoc ( source.c_str() ); sourceDoc->InsertPages ( extraDoc, 0, extraDoc.GetPageCount() ); multiSource.push_back ( source ); } PdfObject* PdfTranslator::migrateResource ( PdfObject * obj ) { // std::cerr<<"PdfTranslator::migrateResource"<<std::endl; PdfObject *ret ( 0 ); if ( obj->IsDictionary() ) { ret = targetDoc->GetObjects().CreateObject ( *obj ); TKeyMap resmap = obj->GetDictionary().GetKeys(); for ( TCIKeyMap itres = resmap.begin(); itres != resmap.end(); ++itres ) { PdfObject *o = itres->second; ret->GetDictionary().AddKey ( itres->first , migrateResource ( o ) ); } if ( obj->HasStream() ) { * ( ret->GetStream() ) = * ( obj->GetStream() ); } } else if ( obj->IsArray() ) { PdfArray carray ( obj->GetArray() ); PdfArray narray; for ( unsigned int ci = 0; ci < carray.GetSize(); ++ci ) { PdfObject *co ( migrateResource ( &carray[ci] ) ); narray.push_back ( *co ); } ret = targetDoc->GetObjects().CreateObject ( narray ); } else if ( obj->IsReference() ) { if ( migrateMap.find ( obj->GetReference().ToString() ) != migrateMap.end() ) { return migrateMap[obj->GetReference().ToString() ]; } PdfObject * o ( migrateResource ( sourceDoc->GetObjects().GetObject ( obj->GetReference() ) ) ); ret = new PdfObject ( o->Reference() ) ; } else { ret = new PdfObject ( *obj );//targetDoc->GetObjects().CreateObject(*obj); } migrateMap.insert ( std::pair<std::string, PdfObject*> ( obj->Reference().ToString(), ret ) ); return ret; } PdfObject* PdfTranslator::getInheritedResources ( PdfPage* page ) { // std::cerr<<"PdfTranslator::getInheritedResources"<<std::endl; PdfObject *res ( 0 ); // = new PdfObject; PdfObject *rparent = page->GetObject(); while ( rparent && rparent->IsDictionary() ) { PdfObject *curRes = rparent->GetDictionary().GetKey ( PdfName ( "Resources" ) ); if ( curRes ) { res = migrateResource ( curRes ); } rparent = rparent->GetIndirectKey ( "Parent" ); } return res; } void PdfTranslator::setTarget ( const std::string & target ) { // std::cerr<<"PdfTranslator::setTarget "<<target<<std::endl; if ( !sourceDoc ) throw std::logic_error ( "setTarget() called before setSource()" ); targetDoc = new PdfMemDocument; outFilePath = target; for ( int i = 0; i < pcount ; ++i ) { PdfPage * page = sourceDoc->GetPage ( i ); PdfMemoryOutputStream outMemStream ( 1 ); PdfXObject *xobj = new PdfXObject ( page->GetMediaBox(), targetDoc ); if ( page->GetContents()->HasStream() ) { page->GetContents()->GetStream()->GetFilteredCopy ( &outMemStream ); } else if ( page->GetContents()->IsArray() ) { PdfArray carray ( page->GetContents()->GetArray() ); for ( unsigned int ci = 0; ci < carray.GetSize(); ++ci ) { if ( carray[ci].HasStream() ) { carray[ci].GetStream()->GetFilteredCopy ( &outMemStream ); } else if ( carray[ci].IsReference() ) { PdfObject *co = sourceDoc->GetObjects().GetObject ( carray[ci].GetReference() ); while ( co != NULL ) { if ( co->IsReference() ) { co = sourceDoc->GetObjects().GetObject ( co->GetReference() ); } else if ( co->HasStream() ) { co->GetStream()->GetFilteredCopy ( &outMemStream ); break; } } } } } /// Its time to manage other keys of the page dictionary. std::vector<std::string> pageKeys; std::vector<std::string>::const_iterator itKey; pageKeys.push_back ( "Group" ); for ( itKey = pageKeys.begin(); itKey != pageKeys.end(); ++itKey ) { PoDoFo::PdfName keyname ( *itKey ); if ( page->GetObject()->GetDictionary().HasKey ( keyname ) ) { xobj->GetObject()->GetDictionary().AddKey ( keyname, migrateResource ( page->GetObject()->GetDictionary().GetKey ( keyname ) ) ); } } outMemStream.Close(); PdfMemoryInputStream inStream ( outMemStream.TakeBuffer(),outMemStream.GetLength() ); xobj->GetContents()->GetStream()->Set ( &inStream ); resources[i+1] = getInheritedResources ( page ); xobjects[i+1] = xobj; cropRect[i+1] = page->GetCropBox(); bleedRect[i+1] = page->GetBleedBox(); trimRect[i+1] = page->GetTrimBox(); artRect[i+1] = page->GetArtBox(); } targetDoc->SetPdfVersion ( sourceDoc->GetPdfVersion() ); PdfInfo *sInfo ( sourceDoc->GetInfo() ); PdfInfo *tInfo ( targetDoc->GetInfo() ); if ( sInfo->GetAuthor() != PdfString::StringNull ) tInfo->SetAuthor ( sInfo->GetAuthor() ); if ( sInfo->GetCreator() != PdfString::StringNull ) tInfo->SetCreator ( sInfo->GetCreator() ); if ( sInfo->GetSubject() != PdfString::StringNull ) tInfo->SetSubject ( sInfo->GetSubject() ); if ( sInfo->GetTitle() != PdfString::StringNull ) tInfo->SetTitle ( sInfo->GetTitle() ); if ( sInfo->GetKeywords() != PdfString::StringNull ) tInfo->SetKeywords ( sInfo->GetKeywords() ); if ( sInfo->GetTrapped() != PdfName::KeyNull ) tInfo->SetTrapped ( sInfo->GetTrapped() ); // PdfObject *scat( sourceDoc->GetCatalog() ); // PdfObject *tcat( targetDoc->GetCatalog() ); // TKeyMap catmap = scat->GetDictionary().GetKeys(); // for ( TCIKeyMap itc = catmap.begin(); itc != catmap.end(); ++itc ) // { // if(tcat->GetDictionary().GetKey(itc->first) == 0) // { // PdfObject *o = itc->second; // tcat->GetDictionary().AddKey (itc->first , migrateResource( o ) ); // } // } // delete sourceDoc; } void PdfTranslator::loadPlan ( const std::string & planFile , PoDoFo::Impose::PlanReader loader ) { // std::cerr<< "loadPlan" << planFile<<std::endl; SourceVars sv; sv.PageCount = pcount; sv.PageHeight = sourceHeight; sv.PageWidth = sourceWidth; planImposition = new ImpositionPlan ( sv ); if ( loader == PoDoFo::Impose::Legacy ) { PlanReader_Legacy ( planFile, planImposition ); } #if defined(PODOFO_HAVE_LUA) else if ( loader == PoDoFo::Impose::Lua ) { PlanReader_Lua ( planFile, planImposition ); } #endif if ( !planImposition->valid() ) throw std::runtime_error ( "Unable to build a valid imposition plan" ); destWidth = planImposition->destWidth(); destHeight = planImposition->destHeight(); scaleFactor = planImposition->scale(); boundingBox = planImposition->boundingBox(); // std::cerr <<"Plan completed "<< planImposition.size() <<endl; } void PdfTranslator::impose() { // std::cerr<<"PdfTranslator::impose"<<std::endl; if ( !targetDoc ) throw std::invalid_argument ( "impose() called with empty target" ); // PdfObject trimbox; // PdfRect trim ( 0, 0, destWidth, destHeight ); // trim.ToVariant ( trimbox ); std::map<int, PdfRect>* bbIndex = NULL; if(boundingBox.size() > 0) { if(boundingBox.find("crop") != std::string::npos) { bbIndex = &cropRect; } else if(boundingBox.find("bleed") != std::string::npos) { bbIndex = &bleedRect; } else if(boundingBox.find("trim") != std::string::npos) { bbIndex = &trimRect; } else if(boundingBox.find("art") != std::string::npos) { bbIndex = &artRect; } } typedef map<int, vector<PageRecord> > groups_t; groups_t groups; for ( unsigned int i = 0; i < planImposition->size(); ++i ) { groups[ ( *planImposition ) [i].destPage].push_back ( ( *planImposition ) [i] ); } unsigned int lastPlate(0); groups_t::const_iterator git = groups.begin(); const groups_t::const_iterator gitEnd = groups.end(); while ( git != gitEnd ) { PdfPage * newpage; // Allow "holes" in dest. pages sequence. unsigned int curPlate(git->first); while(lastPlate != curPlate) { newpage = targetDoc->CreatePage ( PdfRect ( 0.0, 0.0, destWidth, destHeight ) ); ++lastPlate; } // newpage->GetObject()->GetDictionary().AddKey ( PdfName ( "TrimBox" ), trimbox ); PdfDictionary xdict; ostringstream buffer; // Scale buffer << std::fixed << scaleFactor <<" 0 0 "<< scaleFactor <<" 0 0 cm\n"; for ( unsigned int i = 0; i < git->second.size(); ++i ) { PageRecord curRecord ( git->second[i] ); // std::cerr<<curRecord.sourcePage<< " " << curRecord.destPage<<std::endl; if(curRecord.sourcePage <= pcount) { double cosR = cos ( curRecord.rotate * 3.14159 / 180.0 ); double sinR = sin ( curRecord.rotate * 3.14159 / 180.0 ); double tx = curRecord.transX ; double ty = curRecord.transY ; int resourceIndex ( /*(curRecord.duplicateOf > 0) ? curRecord.duplicateOf : */curRecord.sourcePage ); PdfXObject *xo = xobjects[resourceIndex]; if(NULL != bbIndex) { PdfObject bb; // DominikS: Fix compilation using Visual Studio on Windows // bbIndex->at(resourceIndex).ToVariant( bb ); ((*bbIndex)[resourceIndex]).ToVariant( bb ); xo->GetObject()->GetDictionary().AddKey ( PdfName ( "BBox" ), bb ); } ostringstream op; op << "OriginalPage" << resourceIndex; xdict.AddKey ( PdfName ( op.str() ) , xo->GetObjectReference() ); if ( resources[resourceIndex] ) { if ( resources[resourceIndex]->IsDictionary() ) { TKeyMap resmap = resources[resourceIndex]->GetDictionary().GetKeys(); TCIKeyMap itres; for ( itres = resmap.begin(); itres != resmap.end(); ++itres ) { xo->GetResources()->GetDictionary().AddKey ( itres->first, itres->second ); } } else if ( resources[resourceIndex]->IsReference() ) { xo->GetObject()->GetDictionary().AddKey ( PdfName ( "Resources" ), resources[resourceIndex] ); } else std::cerr<<"ERROR Unknown type resource "<<resources[resourceIndex]->GetDataTypeString() << std::endl; } // Very primitive but it makes it easy to track down imposition plan into content stream. buffer << "q\n"; buffer << std::fixed << cosR <<" "<< sinR<<" "<<-sinR<<" "<< cosR<<" "<< tx <<" "<< ty << " cm\n"; buffer << "/OriginalPage" << resourceIndex << " Do\n"; buffer << "Q\n"; } } string bufStr = buffer.str(); newpage->GetContentsForAppending()->GetStream()->Set ( bufStr.data(), bufStr.size() ); newpage->GetResources()->GetDictionary().AddKey ( PdfName ( "XObject" ), xdict ); ++git; } targetDoc->Write ( outFilePath.c_str() ); } }; }; // end of namespace ��������������������������������������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/tools/podofoimpose/planreader_legacy.cpp�����������������������������������������������0000664�0001750�0001750�00000015544�11577110632�022705� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// // C++ Implementation: planreader_legacy // // Description: // // // Author: Pierre Marchand <pierremarc@oep-h.com>, (C) 2008 // // Copyright: See COPYING file that comes with this distribution // // #include "planreader_legacy.h" #ifdef PODOFO_HAVE_LUA #include "planreader_lua.h" #endif // PODOFO_HAVE_LUA #include <fstream> #include <stdexcept> #include <algorithm> #include <cmath> #include <istream> #include <ostream> using std::ostringstream; using std::map; using std::vector; using std::string; using std::ifstream; using std::istream; using std::ostream; using std::endl; using std::runtime_error; #include <iostream> //XXX#define MAX_SOURCE_PAGES 5000 #define MAX_RECORD_SIZE 2048 int PlanReader_Legacy::sortLoop(std::vector<std::string>& memfile, int numline) { // std::cerr<<"===================================== "<<numline<<std::endl; //Debug // for(std::map<std::string, double>::iterator dit(localvars.begin());dit!=localvars.end();++dit) // { // std::cerr<<"R "<<dit->first<<" = "<<dit->second<<std::endl; // } // std::map<std::string,std::string> storedvars = I->vars; int startAt(numline); std::string buffer( memfile.at(numline) ); int blen = buffer.length(); std::string iterN; int a(1); char ca(0); for(;a<blen;++a) { ca = buffer.at(a); if(ca == '[') break; else if(ca == 0x20 || ca == 0x9 ) continue; iterN += buffer.at(a); } std::map<std::string, double> increments; std::string tvar; std::string tinc; ++a; bool varside(true); for(;a<blen;++a) { ca = buffer.at(a); // if(ca == 0x20 || ca == 0x9 ) // continue; if( (ca == ']') || (ca == ';') ) // time to commit { if(I->vars.find(tvar) != I->vars.end()) { // std::cerr<< "I " << tvar <<" = "<< tinc <<std::endl; increments.insert(std::pair<std::string, double>( tvar, std::atof(tinc.c_str()))); } tvar.clear(); tinc.clear(); if(ca == ';') varside = true; else break; } else if(ca == '+') { varside = false; continue; } else { if(varside) tvar += ca; else tinc += ca; } } int endOfloopBlock(numline + 1); int openLoop(0); for(unsigned int bolb2 = (numline + 1); bolb2 < memfile.size();++bolb2) { // std::cerr<<"| "<< memfile.at ( bolb2 ) <<" |"<<std::endl; if(memfile.at ( bolb2 ).at( 0 ) == '<') ++openLoop; else if(memfile.at ( bolb2 ).at( 0 ) == '>') { if(openLoop == 0) break; else --openLoop; } else endOfloopBlock = bolb2 + 1; } int maxIter(PoDoFo::Impose::PageRecord::calc(iterN, I->vars)); for(int iter(0); iter < maxIter ; ++iter ) { if(iter != 0) { // we set the vars std::map<std::string, double>::iterator vit; for(vit = increments.begin(); vit != increments.end() ; ++vit) { I->vars[vit->first] = PoDoFo::Impose::Util::dToStr( std::atof(I->vars[vit->first].c_str()) + vit->second ); } } for(int subi(numline + 1);subi < endOfloopBlock ; ++subi) { // std::cerr<< subi <<"/"<< endOfloopBlock <<" - "<<memfile.at(subi) <<std::endl; if(memfile.at ( subi ).at( 0 ) == '<') { subi += sortLoop(memfile , subi); // std::cerr<< "|| " << memfile.at ( subi ) <<std::endl; } else { PoDoFo::Impose::PageRecord p; p.load ( memfile.at(subi), I->vars ) ; if(!p.isValid() || p.sourcePage > I->sourceVars.PageCount) { // std::cerr<< "Error p("<<(p.isValid()?"valid":"invalid")<<") "<< p.sourcePage <<std::endl; continue; } // maxPageDest = std::max ( maxPageDest, p.destPage ); // bool isDup(false); // for(ImpositionPlan::const_iterator ipIt(planImposition.begin());ipIt != planImposition.end(); ++ipIt) // { // if(ipIt->sourcePage == p.sourcePage) // { // isDup = true; // break; // } // } // if ( isDup ) // { // p.duplicateOf = p.sourcePage; // } I->push_back ( p ); } } } // numline = endOfloopBlock; // std::cerr<<"EOL"<<std::endl; int retvalue(endOfloopBlock - startAt + 1); I->vars = storedvars; // std::cerr<<"------------------------------------- "<<retvalue<<std::endl; return retvalue; } PlanReader_Legacy::PlanReader_Legacy(const std::string & plan, PoDoFo::Impose::ImpositionPlan *Imp) :I(Imp) { ifstream in ( plan.c_str(), ifstream::in ); if ( !in.good() ) throw runtime_error ( "Failed to open plan file" ); // duplicate = MAX_SOURCE_PAGES; std::string line; char cbuffer[MAX_RECORD_SIZE]; int blen (0); std::vector<std::string> memfile; do { in.getline ( cbuffer, MAX_RECORD_SIZE ); blen = in.gcount() ; std::string buffer ( cbuffer, blen ); #ifdef PODOFO_HAVE_LUA // This was "supposed" to be a legacy file, but if it starts // with two dashes, it must be a lua file, so process it accordingly: if (buffer.substr(0,2) == "--") { in.close(); PlanReader_Lua(plan, Imp); return; } #endif // PODOFO_HAVE_LUA if ( blen < 2 ) // Nothing continue; PoDoFo::Impose::Util::trimmed_str(buffer); if(buffer.length() < 2) continue; else if ( buffer.at ( 0 ) == '#' ) // Comment continue; else { memfile.push_back(buffer); // std::cerr<<buffer<<std::endl; } } while(!in.eof()); /// PROVIDED I->vars[std::string("$PagesCount")] = PoDoFo::Impose::Util::iToStr( I->sourceVars.PageCount ); I->vars[std::string("$SourceWidth")] = PoDoFo::Impose::Util::dToStr( I->sourceVars.PageWidth ); I->vars[std::string("$SourceHeight")] = PoDoFo::Impose::Util::dToStr( I->sourceVars.PageHeight ); /// END OF PROVIDED for( unsigned int numline = 0; numline < memfile.size() ; ++numline) { std::string buffer( memfile.at(numline) ); if ( buffer.at ( 0 ) == '$' ) // Variable { int sepPos ( buffer.find_first_of ( '=' ) ); std::string key(buffer.substr ( 0,sepPos )); std::string value(buffer.substr ( sepPos + 1 )); { I->vars[key] = value; } } else if( buffer.at ( 0 ) == '<' ) // Loop - experimental { numline += sortLoop( memfile , numline ); } else // Record? We hope! { PoDoFo::Impose::PageRecord p; p.load ( buffer, I->vars ) ; if(!p.isValid() || p.sourcePage > I->sourceVars.PageCount) continue; // maxPageDest = std::max ( maxPageDest, p.destPage ); // if ( pagesIndex.find ( p.sourcePage ) != pagesIndex.end() ) // { // p.duplicateOf = p.sourcePage; // } I->push_back ( p ); } } /// REQUIRED if ( I->vars.find("$PageWidth") == I->vars.end() ) throw runtime_error ( "$PageWidth not set" ); if (I->vars.find("$PageHeight") == I->vars.end() ) throw runtime_error ( "$PageHeight not set" ); I->setDestWidth( PoDoFo::Impose::PageRecord::calc( I->vars["$PageWidth"] , I->vars) ); I->setDestHeight( PoDoFo::Impose::PageRecord::calc( I->vars["$PageHeight"] , I->vars)); /// END OF REQUIRED /// SUPPORTED if ( I->vars.find("$ScaleFactor") != I->vars.end() ) I->setScale( PoDoFo::Impose::PageRecord::calc( I->vars["$ScaleFactor"] , I->vars)); /// END OF SUPPORTED } ������������������������������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/tools/podofoimpose/lua_compat.h��������������������������������������������������������0000664�0001750�0001750�00000001525�12205457547�021037� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������extern "C" { #include "lua.h" // Note: If you're missing these, you're using lua 5.0 and haven't installed // the extension libraries. #include "lualib.h" #include "lauxlib.h" } #if !defined(LUA_VERSION_NUM) // Old lua without numeric version #define LUA_VERSION_NUM 0 #endif // Handle an API difference in the lua_open call between // Lua 5.1 and Lua 5.2. #if LUA_VERSION_NUM >= 502 inline lua_State* imp_lua_open(void) { return luaL_newstate(); } #else inline lua_State* imp_lua_open(void) { return lua_open(); } #endif // Handle an API difference in the dofile and getn calls between // Lua 5.0 and Lua 5.1. #if LUA_VERSION_NUM >= 501 inline int imp_lua_dofile(lua_State* L, const char * path) { return luaL_dofile(L, path); } #else inline int imp_lua_dofile(lua_State* L, const char * path) { return lua_dofile(L, path); } #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/tools/podofoimpose/planreader_lua.cpp��������������������������������������������������0000664�0001750�0001750�00000010600�12205457547�022216� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// // C++ Implementation: planreader_lua // // Description: // // // Author: Pierre Marchand <pierremarc@oep-h.com>, (C) 2008 // // Copyright: See COPYING file that comes with this distribution // // #include "planreader_lua.h" #include <stdexcept> #include <iostream> // Note: this is *not* lua.hpp shipped with lua 5.1, it's a wrapper // header we use to handle version differences between lua 5.1 and lua // 5.0 . #include "lua_compat.h" LuaMachina::LuaMachina() { /* Init the Lua interpreter */ L = imp_lua_open(); if (!L) { throw std::runtime_error("Whoops! Failed to open lua!"); } /* Init the Lua libraries we want users to have access to. * Note that the `os' and `io' libraries MUST NOT be included, * as providing access to those libraries to the user would * make running plan files unsafe. */ luaopen_base(L); luaopen_table(L); luaopen_string(L); luaopen_math(L); } LuaMachina::~LuaMachina() { lua_close(L); } PlanReader_Lua::PlanReader_Lua(const std::string & planfile, PoDoFo::Impose::ImpositionPlan * ip) { // std::cerr<<"PlanReader_Lua::PlanReader_Lua "<< planfile <<std::endl; plan = ip; lua_pushcfunction(L.State(), &PlanReader_Lua::PushRecord); lua_setglobal(L.State(), "PushRecord"); lua_pushlightuserdata(L.State(), static_cast<void*>(this)); lua_setglobal(L.State(), "This"); setNumber("PageCount", plan->sourceVars.PageCount); setNumber("SourceWidth", plan->sourceVars.PageWidth ); setNumber("SourceHeight", plan->sourceVars.PageHeight); // imp_lua_dofile is a wrapper around luaL_dofile for Lua 5.0/5.1 compat. if(imp_lua_dofile(L.State(), planfile.c_str())) { std::cerr<<"Unable to process Lua script:\"" <<lua_tostring(L.State(), -1)<<"\""<<std::endl ; } else // if not reached, the plan remains invalid { if(hasGlobal("PageWidth")) plan->setDestWidth(getNumber("PageWidth")); if(hasGlobal("PageHeight")) plan->setDestHeight(getNumber("PageHeight")); if(hasGlobal("Scale")) plan->setScale(getNumber("Scale")); if(hasGlobal("BoundingBox")) plan->setBoundingBox(getString("BoundingBox")); } } PlanReader_Lua::~ PlanReader_Lua() { } int PlanReader_Lua::PushRecord ( lua_State * L ) { /* TODO: check stack for space! I would be glad to do that, but I don’t know how - pm */ if ( ! ( lua_isnumber ( L, 1 ) && lua_isnumber ( L, 2 ) && lua_isnumber ( L, 3 ) && lua_isnumber ( L, 4 ) && lua_isnumber ( L, 5 ) ) ) { throw std::runtime_error ( "One or more arguments to PushRecord were not numbers" ); } /* Get the instance of the reader which runs the script */ lua_getglobal ( L , "This" ); if ( ! lua_islightuserdata ( L, -1 ) ) throw std::runtime_error ( "\"This\" is not valid" ); // ;-) PlanReader_Lua *that = static_cast<PlanReader_Lua*> ( lua_touserdata ( L, -1 ) ); lua_pop ( L, 1 ); // std::cerr<<"PlanReader_Lua::PushRecord "<<lua_tonumber ( L, 1 )<<" "<<lua_tonumber ( L, 2 )<<" "<<lua_tonumber ( L, 3 )<<" "<<lua_tonumber ( L, 4 )<<" "<<lua_tonumber ( L, 5 )<<std::endl; /* and add a new record to it */ PoDoFo::Impose::PageRecord P( lua_tonumber ( L, 1 ), lua_tonumber ( L, 2 ), lua_tonumber ( L, 3 ), lua_tonumber ( L, 4 ), lua_tonumber ( L, 5 )); if(P.isValid()) that->plan->push_back ( P ); lua_pop ( L, 5 ); return 0; } double PlanReader_Lua::getNumber(const std::string & name) { lua_getglobal(L.State(), name.c_str()); if (!lua_isnumber(L.State(), -1)) { std::string errString = name + " is non-number"; throw std::runtime_error(errString.c_str()); } double d = lua_tonumber(L.State(), -1); lua_pop(L.State(), 1); return d; } void PlanReader_Lua::setNumber(const std::string & name, double value) { lua_pushnumber(L.State(), value); lua_setglobal(L.State(), name.c_str()); /* pops stack */ } bool PlanReader_Lua::hasGlobal(const std::string & name) { bool ret(true); lua_getglobal(L.State(), name.c_str()); if(lua_isnil(L.State(), -1) > 0) { ret = false; } lua_pop(L.State(), 1); return ret; } std::string PlanReader_Lua::getString(const std::string& name) { lua_getglobal(L.State(), name.c_str()); if (!lua_isstring(L.State(), -1)) { std::string errString = name + " is non-string"; throw std::runtime_error(errString.c_str()); } std::string s( lua_tostring(L.State(), -1) ); lua_pop(L.State(), 1); return s; } ��������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/tools/podofoimpose/charpainter.cpp�����������������������������������������������������0000664�0001750�0001750�00000006654�10674015620�021544� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*************************************************************************** * Copyright (C) 2007 by Pierre Marchand * * pierre@moulindetouvois.com * * * * 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., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "charpainter.h" #include <vector> using std::vector; using std::ostream; using std::string; namespace { // write the digits of `n' to `d'. The digits are ordered by increasing // place value. void digits(int n, vector<int> & d) { while ( n > 0 ) { d.push_back(n % 10); n = n / 10; } } }; // end anon namespace using namespace std; void CharPainter::paint(ostream & s, int n, double size, double x, double y) { // update working variables used by topleft() etc m_y = y; m_x = x; m_size = size; m_sh = m_size + m_y; m_midh = (m_size /2.0) + m_y; m_sw = (m_size /2.0) + m_x; switch(n) { case 1 : topright(s); bottomright(s); break; case 2 : top(s); topright(s); center(s); bottomleft(s); bottom(s); break; case 3 : top(s); topright(s); bottomright(s); bottom(s); center(s); break; case 4 : topleft(s); center(s); bottomright(s); topright(s); break; case 5 : top(s); topleft(s); center(s); bottomright(s); bottom(s); break; case 6 : top(s); topleft(s); center(s); bottomright(s); bottom(s); bottomleft(s); break; case 7 : top(s); topright(s); bottomright(s); break; case 8 : top(s); topleft(s); center(s); bottomright(s); bottom(s); bottomleft(s); topright(s); break; case 9 : top(s); topleft(s); center(s); bottomright(s); bottom(s); topright(s); break; case 0 : top(s); topleft(s); bottomright(s); bottom(s); bottomleft(s); topright(s); break; } s << "S\n"; } void CharPainter::multipaint(ostream& s, int n, double size, double x, double y) { vector<int> d; digits(n, d); vector<int>::const_reverse_iterator itEnd = d.rend(); int i = d.size() - 1; for ( vector<int>::const_reverse_iterator it = d.rbegin(); it != itEnd; ++it, --i ) paint(s, *it, size, x + (size * i / 1.6), y ); } ������������������������������������������������������������������������������������podofo-0.9.3/tools/podofoimpose/planreader_legacy.h�������������������������������������������������0000664�0001750�0001750�00000001116�11075367546�022353� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// // C++ Interface: planreader_legacy // // Description: // // // Author: Pierre Marchand <pierremarc@oep-h.com>, (C) 2008 // // Copyright: See COPYING file that comes with this distribution // // #ifndef PLANREADER_LEGACY_H #define PLANREADER_LEGACY_H #include "impositionplan.h" #include <string> #include <vector> class PlanReader_Legacy { public: PlanReader_Legacy(const std::string & plan, PoDoFo::Impose::ImpositionPlan* Imp); ~PlanReader_Legacy(){} private: PoDoFo::Impose::ImpositionPlan* I; int sortLoop(std::vector<std::string>& memfile, int numline); }; #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/tools/podofoimpose/CMakeLists.txt������������������������������������������������������0000664�0001750�0001750�00000001104�11075542173�021265� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# PoDoFoImpose SET(impose_srcs podofoimpose.cpp pdftranslator.cpp impositionplan.cpp planreader_legacy.cpp ) SET(impose_extra_libs) IF(LUA_FOUND) SET(impose_extra_libs ${LUA_LIBRARIES}) SET(impose_srcs ${impose_srcs} planreader_lua.cpp) ENDIF(LUA_FOUND) ADD_EXECUTABLE(podofoimpose ${impose_srcs} ) TARGET_LINK_LIBRARIES(podofoimpose ${PODOFO_LIB} ${impose_extra_libs} ) SET_TARGET_PROPERTIES(podofoimpose PROPERTIES COMPILE_FLAGS "${PODOFO_CFLAGS}") ADD_DEPENDENCIES(podofoimpose ${PODOFO_DEPEND_TARGET}) INSTALL(TARGETS podofoimpose RUNTIME DESTINATION "bin") ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/tools/podofoimpose/README.html���������������������������������������������������������0000664�0001750�0001750�00000021370�11133352773�020357� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>PodofoImpose - some words</title> <meta name="AUTHOR" content="Pierre Marchand"/> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <style type="text/css"> body{ width:360pt; margin:auto; font-family:sans-serif; font-size:11.2pt; } .section{ /* background-color:#ddd; */ border-left:1pt solid #333; padding-left:12pt; } .code-abs{ font-family:mono; font-weight:bold; font-size:9pt; background-color:#eee; color:#222; } .command{ font-family:monospace; font-size:9pt; background-color:#222; color:#eee; padding:6pt; } .file{ border:1pt dotted black; width:90%; margin:12pt auto; } .file .name{ text-align:right; font-family:monospace; font-weight:bold; font-size:8pt; background-color:#eee; } .file .content{ margin:0; padding:0; border:0; white-space:pre; } </style> </head> <body> <h2>PodofoImpose</h2> <div id="intro">PodofoImpose is a utility program which aims to provide a rather simple way to impose PDF documents. Originally written for my own use, it ended up in PoDoFo release as a show-case (don’t rely too much on it). </div> <h3>Plan (built-in)</h3> <div class="section"><!-- Plan own --> PodofoImpose is driven by a PLAN file. This file describes how pages from a source PDF document have to be relayout into a target document. We’ll describe how this file must be formated. <h4>Records</h4> <div> Most of the PLAN file is composed of record lines of the form: <div class="code-abs"> source page; target page; rotation; horizontal translation; vertical translation; </div> Each element of the record can be a numeric value, a constant or an expression involving both numerics and constants. </div> <h4>Constants</h4> <div> Constants can be declared everywhere in the PLAN file except in loops. They are 8 bits char strings (except "=") with a leading "$" character which makes them easy to identify. Their value is always interpreted as a float through std::atof. You can "overload" a constant value by redeclaring it. They are declared in this form: <div class="code-abs"> $MyConstant = 123.456 </div> Note that a PLAN file is valid only if it contains 2 required constants which are "$PageWidth" and "$PageHeight", giving target document dimensions. Now support the "$ScaleFactor" constant -- means that the declared scale factor will be added to the current transformation matrix for each placed page. Constants declarations can hold expressions: <div class="code-abs"> $MyConstant = $AnotherConst * .5; </div> Source document pages count is provided as "$PageCount". Source first page geometry is provided as "$SourceWidth" and "$SourceHeight", reflecting geometry given by the MediaBox. </div> <h4>Expressions</h4> <div> An expression is a set of basic mathematic operations +, -, *,/ and % (operands of modulo will be first rounded). As a convenience, we added the | as "max(a,b)" it’s mainly there to allow user to prevent division by 0. <div class="code-abs"> $ValueA / ( $ValueB | 0.000001 ) </div> Operations are executed from left to right without taking care of any kind of precedance. You can use parenthesis to enclose operations that need to be computed separetly. Example: <div class="code-abs"> 123.456 * ( $ConstantA - ( $ConstantB / 3.14 ) ) </div> </div> <h4>Loops</h4> <div> Loops allow users to programmatically generate records. While the concept itself is familiar to programmers I can imagine that regular users would feel not so easy with it. So let me introduce a simple example to explain the thing. </div> <div> Let say we have a source document, A4 format, which has 1000 pages and we just want to position each page of the first half of the document on the center of an A3 plate. <div class="file"> <div class="name">A4onA3.plan</div> <div class="content">$PageWidth=842.6 $PageHeight=1195.2 ## SourceWidth &#38; SourceHeight $sw=597.6 $sh=842.4 $page=1 &#60;$PageCount/2[$page+1] $page; $page; 0; ($PageWidth-$sw)/2; ($PageHeight-$sh)/2; &#62; </div> </div> The loop is what’s enclosed by "&#60;" and "&#62;"characters, the second just indicates the end of the loop. The first first indicates how many iterations (loops) have to be performed &#8212; 500 here. Then comes the interesting part, constants which appear in parenthesis will be incremented by the value following the "+" (can be a minus one, in that case don’t turn the "+" into a "-", just prefix the value with "-" as in [$foo+-1.23]), which means in this example that at each iteration, $page will see its value increased by 1. </div> <div> Constants (which finally turn into variables ;-)) must be declared before the loop. Many constants can be put in loop declaration, separate them with semicolons. </div> <div> <!-- No, loops can’t be nested! --> There is an experimental support of nested loops. </div> <h4>Running</h4> <div> Once you’ve wrote the PLAN file you can run the program: <div class="command"> podofoimpose source.pdf target.pdf plan.plan </div> Note the source can be either a PDF file or a text file which is a listing of PDF files. In this case, listed files will be first merged in order. </div> </div> <!-- Plan --> <h3>Plan (Lua)</h3> <div class="section"><!-- lua plan --> PoDoFoImpose now supports Lua scripted plan files. Note that, mainly for security reasons, only the following modules are loaded: base, table, string, math. If you need more, just add luaopen_* calls to LuaMachina::LuaMachina(). <h4>Format</h4> <div> Records are pushed with: <div class="command"> PushRecord(source page, target page, rotation, x, y); </div> As for regular plan files, there are a couple of provided informations through global variables, specifically: "SourceWidth", "SourceHeight", "PageCount". You need to set "PageWidth" and "PageHeight". You may alter the global scale factor (from source to target) by setting "Scale". </div> <h4>Running</h4> <div> There is no format detection mechanism, so you need to append "lua" keyword to podofoimpose invocation when you want it to process a Lua script. </div> </div> <!-- lua plan --> <h3>Examples</h3> <div class="section"><!-- Examples --> <div> For Lua scripts, some samples can be found in directory tools/podofoimpose/plans/lua of PoDoFo sources tree. </div> <h5>Add a stamp to a document</h5> Shame on me, don’t even have a real stamp at my "office". So I tried something and it worked! Say you have that official one page A4 doc, named official.pdf, on which you want to add a nice stamp. You have your stamp in the file stamp.pdf. You first have to create two files: <div class="file"> <div class="name"> pdf.list </div> <div class="content">official.pdf stamp.pdf</div> </div> <div class="file"> <div class="name">stamponator.plan</div> <div class="content">$PageWidth=597.6 $PageHeight=842.4 # original page is left unchanged; 1; 1; 0; 0; 0; # positionning stamp is up to you! 2; 1; 0; 350; 100;</div> </div> Now you can run: <div class="command">podofoimpose pdf.list stamped-official.pdf stamponator.plan</div> <h5>Make a tiled poster</h5> <div> Printing a large graphic onto a set of little paper sheets can be handful. Doing it automatically is even better! <!--You can find files used in this example here: <a href="poster.pdf">poster.pdf</a>, <a href="poster_mask.pdf">poster_mask.pdf</a>, <a href="poster.plan">poster.plan</a> and <a href="poster.list">poster.list</a>. Here constants are a bit abbreviated in order to fit in the frame.--> Latest changes allow us to provide you with a quasi all-automatic solution. The only thing that you would want to change (apart from debugging) is the output paper size (here ISO-A4, "Europe oblige !"). <div class="file"> <div class="name">poster.plan</div> <div class="content"> ##POSTER printed on tiled A4 paper sheets. # destination (A4) $PageWidth = 597.6 $PageHeight = 842.4 $sW = $SourceWidth $sH = $SourceHeight # with a little trick to get integers $rows = (($sH / $PageHeight) + 1) % (2 * (($sH / $PageHeight)+1)) $cols = (($sW / $PageWidth) + 1) % (2 * (($sW / $PageWidth )+1)) $hbox = ($sW / ($cols | 1)) $vbox = ($sH/ ($rows | 1)) $hm = ($PageWidth - $hbox ) / 2 $vm = ($PageHeight - $vbox ) / 2 $R = 1 $C = 1 &#60;$rows[$R+1] &#60;$cols[$C+1] 1; (($R - 1)*$cols) + $C; 0; $hm - (($C -1) * $hbox); $vm - (($R-1) * $vbox); &#62; &#62; </div> </div> </div> <div class="command">podofoimpose poster.pdf poster_tiled.pdf poster.plan </div> <div>Etc.</div> </div><!-- Examples --> </body> </html> ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/tools/podofoimpose/impositionplan.h����������������������������������������������������0000664�0001750�0001750�00000005010�11332265042�021734� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// // C++ Interface: impositionplan // // Description: // // // Author: Pierre Marchand <pierremarc@oep-h.com>, (C) 2008 // // Copyright: See COPYING file that comes with this distribution // // #ifndef IMPOSITIONPLAN_H #define IMPOSITIONPLAN_H #include "podofo.h" #include <map> #include <string> #include <vector> #include <cstdio> namespace PoDoFo { namespace Impose { enum PlanReader { Legacy = 0, Lua = 1 }; struct SourceVars { double PageCount; double PageWidth; double PageHeight; }; class Util { public: static void trimmed_str ( std::string& s ) { std::string::iterator si ( s.begin() ); while ( si != s.end() ) { if ( ( *si ) == 0x20 ) si = s.erase ( si ); else if ( ( *si ) == 0x9 ) si = s.erase ( si ); else ++si; } } static std::string dToStr ( double d ) { char buffer [126]; sprintf ( buffer, "%.5f", d ); std::string ret ( buffer ); return ret; } static std::string iToStr ( int i ) { char buffer [126]; sprintf ( buffer, "%d", i ); std::string ret ( buffer ); return ret; } }; /** @author Pierre Marchand <pierre@moulindetouvois.com> */ class PageRecord { public: PageRecord ( int s,int d,double r, double tx, double ty , int du = 0 ); PageRecord( ); ~PageRecord() {}; int sourcePage; int xobjIndex; int destPage; double rotate; double transX; double transY; int duplicateOf; bool isValid() const; /// needed by legacy loader - should be removed soon static double calc ( const std::string& s , const std::map<std::string, std::string>& vars ); static double calc ( const std::vector<std::string>& t ); void load ( const std::string& s, const std::map<std::string, std::string>& vars ); }; class ImpositionPlan : public std::vector<PageRecord> { public: ImpositionPlan(const SourceVars& sv); ~ImpositionPlan(); // legacy std::map<std::string, std::string> vars; const SourceVars sourceVars; private: double m_destWidth; double m_destHeight; double m_scale; std::string m_boundingBox; public: bool valid() const; void setDestWidth ( double theValue ); double destWidth() const{return m_destWidth;} void setDestHeight ( double theValue ); double destHeight() const{return m_destHeight;} void setScale ( double theValue ); double scale() const{return m_scale;} void setBoundingBox( const std::string& theString ); std::string boundingBox()const{return m_boundingBox;} }; };}; // end of namespace #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/tools/podofoimpose/plans/��������������������������������������������������������������0000775�0001750�0001750�00000000000�12356565167�017661� 5����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/tools/podofoimpose/plans/lua/����������������������������������������������������������0000775�0001750�0001750�00000000000�12356565167�020442� 5����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/tools/podofoimpose/plans/lua/Booklet-USletter-top.plan���������������������������������0000664�0001750�0001750�00000014572�11577110115�025252� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������---lua ---imposition plan : Generic Booklet -- US letter paper -- 8.5 x 11 --- ---It is said generic as it will try to determine ---automatically how to fit the booklet onto US letter ---paper sheets, scaling pages if necessary. ---it is well suited for office documents for ---which you do not care too much about resulting ---imposition artefacts since it manages to save ---paper! --- -- print("Booklet") -- We output a booklet on US letter paper -- 8.5 x 11 -- Interface notes ..... ---- Evidently PageCount, SourceWidth, and SourceHeight are ---- passed to us from the C++ program when we are called. ---- Evidently we are required to provide values for ---- PageWidth, PageHeight, and Scale ... which are used by ---- the C++ program after we return. Scale defaults to 1. ---- ---- Note that these Page-related names are unfortunate, ---- because they do *not* correspond to the pages as defined ---- by the source, or to the pages in the final booklet. ---- Really PageHeight should be called SheetHeight and ---- PageWidth should be called SheetWidth or something ---- like that. ---- ---- Note that we calculate our offsets and margins in ----_real_ units, not scaled units. That is significant ---- PushRecord will scale its arguments, so we will need -----to descale the offsets in the call to PushRecord. -- Useful units, measured in local units (i.e. postscript points): inch = 72 mm = inch / 25.4 PageWidth = 8.5*inch PageHeight = 11*inch -- Turn on TopMode if you want to print the top side of each sheet -- Turn on BottomMode if you want to print the bottm side of each sheet -- Turn on TopMode and BottomMode if you want both, as for a duplex printer TopMode = 1 BottomMode = 1 -- Turn on BoStack if your non-duplex printer has the property -- that the first thing printed winds up at the bottom of the -- stack, face up. BoStack = 1 print("PageCount",PageCount) -- Note that we need to distinguish ---- the hw margins need to keep the printer happy ---- the /added/ margins we need to apply here. -- Worst case is when the source -- material bleeds right to the edge of its bounding box. -- Conversely, if the source material has a lot of margin -- already built into it, we may not need any /extra/ margin -- at all, and we could set UsableHeight = PageHeight here. -- Similarly if Ydelta/2 is larger than the hwBottomMargin -- we shouldn't need to add any /add/ margin. hwTopMargin = 0.1*inch hwBottomMargin = 0.5*inch hwLeftMargin = 0.1*inch hwRightMargin = 0.1*inch srcMargin = 0 addTopMargin = math.max(0, hwTopMargin - srcMargin) addBottomMargin = math.max(0, hwBottomMargin - srcMargin) addLeftMargin = math.max(0, hwLeftMargin - srcMargin) addRightMargin = math.max(0, hwRightMargin - srcMargin) -- When calculating wiggle room, assume paper will be used -- symmetrically. This is a nontrivial assumption, since -- e.g. we could use a paper cutter to chop off one edge -- and not the other ... but that would be beyond the -- scope of this analysis. Symmetry means that if we -- apply a margin to the recto page, we must apply the -- same margin to the verso page, even if the hardware -- would not require it. Hence the factors of 2 here: UsableHeight = PageHeight - 2*addTopMargin - 2*addBottomMargin UsableWidth = PageWidth - 2*addLeftMargin - 2*addRightMargin if(SourceWidth <= SourceHeight) then Scale = math.min(UsableHeight / (2*SourceWidth), UsableWidth / SourceHeight) rot = 90 Ywiggle = 0.5 * math.max(0, UsableHeight - 2*SourceWidth*Scale) Xwiggle = math.max(0, UsableWidth - SourceHeight*Scale) fudge = addTopMargin + 2*(addBottomMargin + Ywiggle) -- Apply a factor of /2 to Xwiggle here, -- because we want centering -- (not flush to right of sheet, i.e. bottom of page): -- Do not apply corresponding factor to Ywiggle, because -- we do want flush to top of sheet, i.e. right of page: xof = addLeftMargin + SourceHeight*Scale + Xwiggle/2 yofRtop = SourceWidth*Scale + fudge yofRbot = SourceWidth*Scale + fudge yofVtop = addBottomMargin + Ywiggle yofVbot = addBottomMargin + Ywiggle else Scale = math.min(UsableHeight / (2*SourceHeight), UsableWidth / SourceWidth) rot = 0 Ywiggle = 0.5 * math.max(0, UsableHeight - 2*SourceHeight*Scale) Xwiggle = math.max(0, UsableWidth - SourceWidth*Scale) fudge = addTopMargin + 2*(addBottomMargin + Ywiggle) xof = addLeftMargin + Xwiggle/2 yofRtop = SourceHeight*Scale + fudge yofRbot = SourceHeight*Scale + fudge yofVtop = addBottomMargin + Ywiggle yofVbot = addBottomMargin + Ywiggle end do rest = PageCount % 4 totp = PageCount if rest ~= 0 then totp = totp + ( 4 - rest) end -- "inc" counts input pages skipped as well as pages actually used: inc = 0 -- "outc" counts output pages: outc = 0; count = 0 imax = totp/4 middle = totp/2 while count < imax do -- We assume that podofoimpose will discard invalid records -- such as those with source page greater than PageCount -- print(totp, inc, outc, rot, xof, yofRtop, yofVtop, yofRbot, yofVbot) -- Top of sheet: (8 1) ... (6 3) if TopMode ~= 0 then -- We did all the interesting calculations in real units (above). -- We convert to nasty descaled units at the last moment: PushRecord(totp - inc, outc + 1, rot, xof/Scale, yofVtop/Scale) PushRecord(inc + 1, outc + 1, rot, xof/Scale, yofRtop/Scale) outc = outc + 1 end -- Bottom of sheet: if BottomMode ~= 0 then if BoStack ~= 0 then -- Reversed bottom: (4 5) ... (2 7) PushRecord(middle - inc, outc + 1, rot, xof/Scale, yofVbot/Scale) PushRecord(middle + 1 + inc, outc + 1, rot, xof/Scale, yofRbot/Scale) else -- Normal bottom: (2 7) ... (4 5) PushRecord(inc + 2, outc + 1, rot, xof/Scale, yofVbot/Scale) PushRecord(totp-(inc + 1), outc + 1, rot, xof/Scale, yofRbot/Scale) end outc = outc + 1 end count = count + 1 inc = inc + 2 end end ��������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/tools/podofoimpose/plans/lua/Booklet-USletter-duplex.plan������������������������������0000664�0001750�0001750�00000014572�11577110115�025751� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������---lua ---imposition plan : Generic Booklet -- US letter paper -- 8.5 x 11 --- ---It is said generic as it will try to determine ---automatically how to fit the booklet onto US letter ---paper sheets, scaling pages if necessary. ---it is well suited for office documents for ---which you do not care too much about resulting ---imposition artefacts since it manages to save ---paper! --- -- print("Booklet") -- We output a booklet on US letter paper -- 8.5 x 11 -- Interface notes ..... ---- Evidently PageCount, SourceWidth, and SourceHeight are ---- passed to us from the C++ program when we are called. ---- Evidently we are required to provide values for ---- PageWidth, PageHeight, and Scale ... which are used by ---- the C++ program after we return. Scale defaults to 1. ---- ---- Note that these Page-related names are unfortunate, ---- because they do *not* correspond to the pages as defined ---- by the source, or to the pages in the final booklet. ---- Really PageHeight should be called SheetHeight and ---- PageWidth should be called SheetWidth or something ---- like that. ---- ---- Note that we calculate our offsets and margins in ----_real_ units, not scaled units. That is significant ---- PushRecord will scale its arguments, so we will need -----to descale the offsets in the call to PushRecord. -- Useful units, measured in local units (i.e. postscript points): inch = 72 mm = inch / 25.4 PageWidth = 8.5*inch PageHeight = 11*inch -- Turn on TopMode if you want to print the top side of each sheet -- Turn on BottomMode if you want to print the bottm side of each sheet -- Turn on TopMode and BottomMode if you want both, as for a duplex printer TopMode = 1 BottomMode = 1 -- Turn on BoStack if your non-duplex printer has the property -- that the first thing printed winds up at the bottom of the -- stack, face up. BoStack = 0 print("PageCount",PageCount) -- Note that we need to distinguish ---- the hw margins need to keep the printer happy ---- the /added/ margins we need to apply here. -- Worst case is when the source -- material bleeds right to the edge of its bounding box. -- Conversely, if the source material has a lot of margin -- already built into it, we may not need any /extra/ margin -- at all, and we could set UsableHeight = PageHeight here. -- Similarly if Ydelta/2 is larger than the hwBottomMargin -- we shouldn't need to add any /add/ margin. hwTopMargin = 0.1*inch hwBottomMargin = 0.5*inch hwLeftMargin = 0.1*inch hwRightMargin = 0.1*inch srcMargin = 0 addTopMargin = math.max(0, hwTopMargin - srcMargin) addBottomMargin = math.max(0, hwBottomMargin - srcMargin) addLeftMargin = math.max(0, hwLeftMargin - srcMargin) addRightMargin = math.max(0, hwRightMargin - srcMargin) -- When calculating wiggle room, assume paper will be used -- symmetrically. This is a nontrivial assumption, since -- e.g. we could use a paper cutter to chop off one edge -- and not the other ... but that would be beyond the -- scope of this analysis. Symmetry means that if we -- apply a margin to the recto page, we must apply the -- same margin to the verso page, even if the hardware -- would not require it. Hence the factors of 2 here: UsableHeight = PageHeight - 2*addTopMargin - 2*addBottomMargin UsableWidth = PageWidth - 2*addLeftMargin - 2*addRightMargin if(SourceWidth <= SourceHeight) then Scale = math.min(UsableHeight / (2*SourceWidth), UsableWidth / SourceHeight) rot = 90 Ywiggle = 0.5 * math.max(0, UsableHeight - 2*SourceWidth*Scale) Xwiggle = math.max(0, UsableWidth - SourceHeight*Scale) fudge = addTopMargin + 2*(addBottomMargin + Ywiggle) -- Apply a factor of /2 to Xwiggle here, -- because we want centering -- (not flush to right of sheet, i.e. bottom of page): -- Do not apply corresponding factor to Ywiggle, because -- we do want flush to top of sheet, i.e. right of page: xof = addLeftMargin + SourceHeight*Scale + Xwiggle/2 yofRtop = SourceWidth*Scale + fudge yofRbot = SourceWidth*Scale + fudge yofVtop = addBottomMargin + Ywiggle yofVbot = addBottomMargin + Ywiggle else Scale = math.min(UsableHeight / (2*SourceHeight), UsableWidth / SourceWidth) rot = 0 Ywiggle = 0.5 * math.max(0, UsableHeight - 2*SourceHeight*Scale) Xwiggle = math.max(0, UsableWidth - SourceWidth*Scale) fudge = addTopMargin + 2*(addBottomMargin + Ywiggle) xof = addLeftMargin + Xwiggle/2 yofRtop = SourceHeight*Scale + fudge yofRbot = SourceHeight*Scale + fudge yofVtop = addBottomMargin + Ywiggle yofVbot = addBottomMargin + Ywiggle end do rest = PageCount % 4 totp = PageCount if rest ~= 0 then totp = totp + ( 4 - rest) end -- "inc" counts input pages skipped as well as pages actually used: inc = 0 -- "outc" counts output pages: outc = 0; count = 0 imax = totp/4 middle = totp/2 while count < imax do -- We assume that podofoimpose will discard invalid records -- such as those with source page greater than PageCount -- print(totp, inc, outc, rot, xof, yofRtop, yofVtop, yofRbot, yofVbot) -- Top of sheet: (8 1) ... (6 3) if TopMode ~= 0 then -- We did all the interesting calculations in real units (above). -- We convert to nasty descaled units at the last moment: PushRecord(totp - inc, outc + 1, rot, xof/Scale, yofVtop/Scale) PushRecord(inc + 1, outc + 1, rot, xof/Scale, yofRtop/Scale) outc = outc + 1 end -- Bottom of sheet: if BottomMode ~= 0 then if BoStack ~= 0 then -- Reversed bottom: (4 5) ... (2 7) PushRecord(middle - inc, outc + 1, rot, xof/Scale, yofVbot/Scale) PushRecord(middle + 1 + inc, outc + 1, rot, xof/Scale, yofRbot/Scale) else -- Normal bottom: (2 7) ... (4 5) PushRecord(inc + 2, outc + 1, rot, xof/Scale, yofVbot/Scale) PushRecord(totp-(inc + 1), outc + 1, rot, xof/Scale, yofRbot/Scale) end outc = outc + 1 end count = count + 1 inc = inc + 2 end end ��������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/tools/podofoimpose/plans/lua/Booklet.plan����������������������������������������������0000664�0001750�0001750�00000002237�11133352773�022706� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������-- Booklet print("Booklet") -- We output an A4 booklet PageWidth = 595.27559 PageHeight = 841.88976 print("PageCount",PageCount) -- We assume that H > W -- Argh, we now can do better since we have "if" ;-) -- Scale = PageHeight / (2*SourceWidth) if(SourceWidth <= SourceHeight) then Scale = PageHeight / (2*SourceWidth) rot = 90 xof = SourceHeight yofRA = 0 yofRB = SourceWidth yofVA = 0 yofVB = SourceWidth else Scale = PageHeight / (2*SourceHeight) rot = 0 xof = 0; yofRA = 0 yofRB = SourceHeight yofVA = SourceHeight yofVB = 0 end do rest = PageCount % 4 totp = PageCount if rest ~= 0 then totp = totp + ( 4 - rest) end inc = 0 count = 0 imax = totp/4 while count < imax do -- We assume that podofoimpose will discard invalid records -- such as those with source page greater than PageCount -- print(totp, inc, rot, xof,yofRA, yofRA, yofVA, yofVB) -- Recto PushRecord(totp - inc , inc + 1 , rot, xof , yofRA) PushRecord(inc + 1 , inc + 1 , rot, xof , yofRB) -- Verso PushRecord(inc + 2 , inc + 2 , rot, xof , yofVA) PushRecord(totp-(inc + 1) , inc + 2 , rot, xof, yofVB) count = count + 1 inc = inc + 2 end end�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/tools/podofoimpose/plans/lua/Booklet-A4-duplex.plan������������������������������������0000664�0001750�0001750�00000014544�11577110115�024445� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������---lua ---imposition plan : Generic Booklet -- A4 paper -- 210 x 297 --- ---It is said generic as it will try to determine ---automatically how to fit the booklet onto A4 ---paper sheets, scaling pages if necessary. ---it is well suited for office documents for ---which you do not care too much about resulting ---imposition artefacts since it manages to save ---paper! --- -- print("Booklet") -- We output a booklet on A4 paper -- 210 x 297 -- Interface notes ..... ---- Evidently PageCount, SourceWidth, and SourceHeight are ---- passed to us from the C++ program when we are called. ---- Evidently we are required to provide values for ---- PageWidth, PageHeight, and Scale ... which are used by ---- the C++ program after we return. Scale defaults to 1. ---- ---- Note that these Page-related names are unfortunate, ---- because they do *not* correspond to the pages as defined ---- by the source, or to the pages in the final booklet. ---- Really PageHeight should be called SheetHeight and ---- PageWidth should be called SheetWidth or something ---- like that. ---- ---- Note that we calculate our offsets and margins in ----_real_ units, not scaled units. That is significant ---- PushRecord will scale its arguments, so we will need -----to descale the offsets in the call to PushRecord. -- Useful units, measured in local units (i.e. postscript points): inch = 72 mm = inch / 25.4 PageWidth = 210*mm PageHeight = 297*mm -- Turn on TopMode if you want to print the top side of each sheet -- Turn on BottomMode if you want to print the bottm side of each sheet -- Turn on TopMode and BottomMode if you want both, as for a duplex printer TopMode = 1 BottomMode = 1 -- Turn on BoStack if your non-duplex printer has the property -- that the first thing printed winds up at the bottom of the -- stack, face up. BoStack = 0 print("PageCount",PageCount) -- Note that we need to distinguish ---- the hw margins need to keep the printer happy ---- the /added/ margins we need to apply here. -- Worst case is when the source -- material bleeds right to the edge of its bounding box. -- Conversely, if the source material has a lot of margin -- already built into it, we may not need any /extra/ margin -- at all, and we could set UsableHeight = PageHeight here. -- Similarly if Ydelta/2 is larger than the hwBottomMargin -- we shouldn't need to add any /add/ margin. hwTopMargin = 0.1*inch hwBottomMargin = 0.5*inch hwLeftMargin = 0.1*inch hwRightMargin = 0.1*inch srcMargin = 0 addTopMargin = math.max(0, hwTopMargin - srcMargin) addBottomMargin = math.max(0, hwBottomMargin - srcMargin) addLeftMargin = math.max(0, hwLeftMargin - srcMargin) addRightMargin = math.max(0, hwRightMargin - srcMargin) -- When calculating wiggle room, assume paper will be used -- symmetrically. This is a nontrivial assumption, since -- e.g. we could use a paper cutter to chop off one edge -- and not the other ... but that would be beyond the -- scope of this analysis. Symmetry means that if we -- apply a margin to the recto page, we must apply the -- same margin to the verso page, even if the hardware -- would not require it. Hence the factors of 2 here: UsableHeight = PageHeight - 2*addTopMargin - 2*addBottomMargin UsableWidth = PageWidth - 2*addLeftMargin - 2*addRightMargin if(SourceWidth <= SourceHeight) then Scale = math.min(UsableHeight / (2*SourceWidth), UsableWidth / SourceHeight) rot = 90 Ywiggle = 0.5 * math.max(0, UsableHeight - 2*SourceWidth*Scale) Xwiggle = math.max(0, UsableWidth - SourceHeight*Scale) fudge = addTopMargin + 2*(addBottomMargin + Ywiggle) -- Apply a factor of /2 to Xwiggle here, -- because we want centering -- (not flush to right of sheet, i.e. bottom of page): -- Do not apply corresponding factor to Ywiggle, because -- we do want flush to top of sheet, i.e. right of page: xof = addLeftMargin + SourceHeight*Scale + Xwiggle/2 yofRtop = SourceWidth*Scale + fudge yofRbot = SourceWidth*Scale + fudge yofVtop = addBottomMargin + Ywiggle yofVbot = addBottomMargin + Ywiggle else Scale = math.min(UsableHeight / (2*SourceHeight), UsableWidth / SourceWidth) rot = 0 Ywiggle = 0.5 * math.max(0, UsableHeight - 2*SourceHeight*Scale) Xwiggle = math.max(0, UsableWidth - SourceWidth*Scale) fudge = addTopMargin + 2*(addBottomMargin + Ywiggle) xof = addLeftMargin + Xwiggle/2 yofRtop = SourceHeight*Scale + fudge yofRbot = SourceHeight*Scale + fudge yofVtop = addBottomMargin + Ywiggle yofVbot = addBottomMargin + Ywiggle end do rest = PageCount % 4 totp = PageCount if rest ~= 0 then totp = totp + ( 4 - rest) end -- "inc" counts input pages skipped as well as pages actually used: inc = 0 -- "outc" counts output pages: outc = 0; count = 0 imax = totp/4 middle = totp/2 while count < imax do -- We assume that podofoimpose will discard invalid records -- such as those with source page greater than PageCount -- print(totp, inc, outc, rot, xof, yofRtop, yofVtop, yofRbot, yofVbot) -- Top of sheet: (8 1) ... (6 3) if TopMode ~= 0 then -- We did all the interesting calculations in real units (above). -- We convert to nasty descaled units at the last moment: PushRecord(totp - inc, outc + 1, rot, xof/Scale, yofVtop/Scale) PushRecord(inc + 1, outc + 1, rot, xof/Scale, yofRtop/Scale) outc = outc + 1 end -- Bottom of sheet: if BottomMode ~= 0 then if BoStack ~= 0 then -- Reversed bottom: (4 5) ... (2 7) PushRecord(middle - inc, outc + 1, rot, xof/Scale, yofVbot/Scale) PushRecord(middle + 1 + inc, outc + 1, rot, xof/Scale, yofRbot/Scale) else -- Normal bottom: (2 7) ... (4 5) PushRecord(inc + 2, outc + 1, rot, xof/Scale, yofVbot/Scale) PushRecord(totp-(inc + 1), outc + 1, rot, xof/Scale, yofRbot/Scale) end outc = outc + 1 end count = count + 1 inc = inc + 2 end end ������������������������������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/tools/podofoimpose/plans/lua/In4.plan��������������������������������������������������0000664�0001750�0001750�00000001326�11133352773�021737� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������-- In4 - imposé sur un A4 présentement PageWidth = 595.27559 PageHeight = 841.88976 sw = SourceWidth sh = SourceHeight xoffset = (PageWidth - (2*sw)) / 2; yoffset = (PageHeight - (2*sh)) / 2; print("xo",xoffset ); print("yo",yoffset ); -- sw = sw + xoffset; -- sh = sh + yoffset; i = 0 while i < PageCount do F = i/8 PushRecord(i+ 8,F+ 1, 0, 0, yoffset ) PushRecord(i+ 1,F+ 1, 0, sw, yoffset ) PushRecord(i+ 4,F+ 1, 180, 2*sw, 2*(sh+yoffset) ) PushRecord(i+ 5,F+ 1, 180, sw, 2*(sh+yoffset) ) PushRecord( i+ 2, F+ 2, 0, 0, yoffset ) PushRecord( i+ 7, F+ 2, 0, sw, yoffset ) PushRecord( i+ 6, F+ 2, 180, 2*sw, 2*(sh+yoffset) ) PushRecord( i+ 3, F+ 2, 180, sw, 2*(sh+yoffset) ) i = i + 8 end ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/tools/podofoimpose/plans/lua/Test.plan�������������������������������������������������0000664�0001750�0001750�00000000272�11133352773�022223� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������-- Test PageHeight = SourceHeight PageWidth = SourceWidth print("SourceHeight",SourceHeight); PushRecord(1,1,0,0,0); PushRecord(1,3,0,0,0); PushRecord(1,5,0,0,0); PushRecord(1,7,0,0,0);��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/tools/podofoimpose/plans/lua/Identity.plan���������������������������������������������0000664�0001750�0001750�00000000303�11133352773�023070� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������-- Identity - a test script for podofoimpose -- Required PageWidth = SourceWidth PageHeight = SourceHeight -- Records i = 1 while i <= PageCount do PushRecord( i , i ,0,0,0) i = i + 1 end �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/tools/podofoimpose/plans/lua/Booklet-USlegal-duplex.plan�������������������������������0000664�0001750�0001750�00000014567�11577110115�025542� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������---lua ---imposition plan : Generic Booklet -- US legal paper -- 8.5 x 14 --- ---It is said generic as it will try to determine ---automatically how to fit the booklet onto US legal ---paper sheets, scaling pages if necessary. ---it is well suited for office documents for ---which you do not care too much about resulting ---imposition artefacts since it manages to save ---paper! --- -- print("Booklet") -- We output a booklet on US legal paper -- 8.5 x 14 -- Interface notes ..... ---- Evidently PageCount, SourceWidth, and SourceHeight are ---- passed to us from the C++ program when we are called. ---- Evidently we are required to provide values for ---- PageWidth, PageHeight, and Scale ... which are used by ---- the C++ program after we return. Scale defaults to 1. ---- ---- Note that these Page-related names are unfortunate, ---- because they do *not* correspond to the pages as defined ---- by the source, or to the pages in the final booklet. ---- Really PageHeight should be called SheetHeight and ---- PageWidth should be called SheetWidth or something ---- like that. ---- ---- Note that we calculate our offsets and margins in ----_real_ units, not scaled units. That is significant ---- PushRecord will scale its arguments, so we will need -----to descale the offsets in the call to PushRecord. -- Useful units, measured in local units (i.e. postscript points): inch = 72 mm = inch / 25.4 PageWidth = 8.5*inch PageHeight = 14*inch -- Turn on TopMode if you want to print the top side of each sheet -- Turn on BottomMode if you want to print the bottm side of each sheet -- Turn on TopMode and BottomMode if you want both, as for a duplex printer TopMode = 1 BottomMode = 1 -- Turn on BoStack if your non-duplex printer has the property -- that the first thing printed winds up at the bottom of the -- stack, face up. BoStack = 0 print("PageCount",PageCount) -- Note that we need to distinguish ---- the hw margins need to keep the printer happy ---- the /added/ margins we need to apply here. -- Worst case is when the source -- material bleeds right to the edge of its bounding box. -- Conversely, if the source material has a lot of margin -- already built into it, we may not need any /extra/ margin -- at all, and we could set UsableHeight = PageHeight here. -- Similarly if Ydelta/2 is larger than the hwBottomMargin -- we shouldn't need to add any /add/ margin. hwTopMargin = 0.1*inch hwBottomMargin = 0.5*inch hwLeftMargin = 0.1*inch hwRightMargin = 0.1*inch srcMargin = 0 addTopMargin = math.max(0, hwTopMargin - srcMargin) addBottomMargin = math.max(0, hwBottomMargin - srcMargin) addLeftMargin = math.max(0, hwLeftMargin - srcMargin) addRightMargin = math.max(0, hwRightMargin - srcMargin) -- When calculating wiggle room, assume paper will be used -- symmetrically. This is a nontrivial assumption, since -- e.g. we could use a paper cutter to chop off one edge -- and not the other ... but that would be beyond the -- scope of this analysis. Symmetry means that if we -- apply a margin to the recto page, we must apply the -- same margin to the verso page, even if the hardware -- would not require it. Hence the factors of 2 here: UsableHeight = PageHeight - 2*addTopMargin - 2*addBottomMargin UsableWidth = PageWidth - 2*addLeftMargin - 2*addRightMargin if(SourceWidth <= SourceHeight) then Scale = math.min(UsableHeight / (2*SourceWidth), UsableWidth / SourceHeight) rot = 90 Ywiggle = 0.5 * math.max(0, UsableHeight - 2*SourceWidth*Scale) Xwiggle = math.max(0, UsableWidth - SourceHeight*Scale) fudge = addTopMargin + 2*(addBottomMargin + Ywiggle) -- Apply a factor of /2 to Xwiggle here, -- because we want centering -- (not flush to right of sheet, i.e. bottom of page): -- Do not apply corresponding factor to Ywiggle, because -- we do want flush to top of sheet, i.e. right of page: xof = addLeftMargin + SourceHeight*Scale + Xwiggle/2 yofRtop = SourceWidth*Scale + fudge yofRbot = SourceWidth*Scale + fudge yofVtop = addBottomMargin + Ywiggle yofVbot = addBottomMargin + Ywiggle else Scale = math.min(UsableHeight / (2*SourceHeight), UsableWidth / SourceWidth) rot = 0 Ywiggle = 0.5 * math.max(0, UsableHeight - 2*SourceHeight*Scale) Xwiggle = math.max(0, UsableWidth - SourceWidth*Scale) fudge = addTopMargin + 2*(addBottomMargin + Ywiggle) xof = addLeftMargin + Xwiggle/2 yofRtop = SourceHeight*Scale + fudge yofRbot = SourceHeight*Scale + fudge yofVtop = addBottomMargin + Ywiggle yofVbot = addBottomMargin + Ywiggle end do rest = PageCount % 4 totp = PageCount if rest ~= 0 then totp = totp + ( 4 - rest) end -- "inc" counts input pages skipped as well as pages actually used: inc = 0 -- "outc" counts output pages: outc = 0; count = 0 imax = totp/4 middle = totp/2 while count < imax do -- We assume that podofoimpose will discard invalid records -- such as those with source page greater than PageCount -- print(totp, inc, outc, rot, xof, yofRtop, yofVtop, yofRbot, yofVbot) -- Top of sheet: (8 1) ... (6 3) if TopMode ~= 0 then -- We did all the interesting calculations in real units (above). -- We convert to nasty descaled units at the last moment: PushRecord(totp - inc, outc + 1, rot, xof/Scale, yofVtop/Scale) PushRecord(inc + 1, outc + 1, rot, xof/Scale, yofRtop/Scale) outc = outc + 1 end -- Bottom of sheet: if BottomMode ~= 0 then if BoStack ~= 0 then -- Reversed bottom: (4 5) ... (2 7) PushRecord(middle - inc, outc + 1, rot, xof/Scale, yofVbot/Scale) PushRecord(middle + 1 + inc, outc + 1, rot, xof/Scale, yofRbot/Scale) else -- Normal bottom: (2 7) ... (4 5) PushRecord(inc + 2, outc + 1, rot, xof/Scale, yofVbot/Scale) PushRecord(totp-(inc + 1), outc + 1, rot, xof/Scale, yofRbot/Scale) end outc = outc + 1 end count = count + 1 inc = inc + 2 end end �����������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/tools/podofoimpose/plans/lua/Booklet-USletter-bottom.plan������������������������������0000664�0001750�0001750�00000014572�11577110115�025754� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������---lua ---imposition plan : Generic Booklet -- US letter paper -- 8.5 x 11 --- ---It is said generic as it will try to determine ---automatically how to fit the booklet onto US letter ---paper sheets, scaling pages if necessary. ---it is well suited for office documents for ---which you do not care too much about resulting ---imposition artefacts since it manages to save ---paper! --- -- print("Booklet") -- We output a booklet on US letter paper -- 8.5 x 11 -- Interface notes ..... ---- Evidently PageCount, SourceWidth, and SourceHeight are ---- passed to us from the C++ program when we are called. ---- Evidently we are required to provide values for ---- PageWidth, PageHeight, and Scale ... which are used by ---- the C++ program after we return. Scale defaults to 1. ---- ---- Note that these Page-related names are unfortunate, ---- because they do *not* correspond to the pages as defined ---- by the source, or to the pages in the final booklet. ---- Really PageHeight should be called SheetHeight and ---- PageWidth should be called SheetWidth or something ---- like that. ---- ---- Note that we calculate our offsets and margins in ----_real_ units, not scaled units. That is significant ---- PushRecord will scale its arguments, so we will need -----to descale the offsets in the call to PushRecord. -- Useful units, measured in local units (i.e. postscript points): inch = 72 mm = inch / 25.4 PageWidth = 8.5*inch PageHeight = 11*inch -- Turn on TopMode if you want to print the top side of each sheet -- Turn on BottomMode if you want to print the bottm side of each sheet -- Turn on TopMode and BottomMode if you want both, as for a duplex printer TopMode = 1 BottomMode = 1 -- Turn on BoStack if your non-duplex printer has the property -- that the first thing printed winds up at the bottom of the -- stack, face up. BoStack = 1 print("PageCount",PageCount) -- Note that we need to distinguish ---- the hw margins need to keep the printer happy ---- the /added/ margins we need to apply here. -- Worst case is when the source -- material bleeds right to the edge of its bounding box. -- Conversely, if the source material has a lot of margin -- already built into it, we may not need any /extra/ margin -- at all, and we could set UsableHeight = PageHeight here. -- Similarly if Ydelta/2 is larger than the hwBottomMargin -- we shouldn't need to add any /add/ margin. hwTopMargin = 0.1*inch hwBottomMargin = 0.5*inch hwLeftMargin = 0.1*inch hwRightMargin = 0.1*inch srcMargin = 0 addTopMargin = math.max(0, hwTopMargin - srcMargin) addBottomMargin = math.max(0, hwBottomMargin - srcMargin) addLeftMargin = math.max(0, hwLeftMargin - srcMargin) addRightMargin = math.max(0, hwRightMargin - srcMargin) -- When calculating wiggle room, assume paper will be used -- symmetrically. This is a nontrivial assumption, since -- e.g. we could use a paper cutter to chop off one edge -- and not the other ... but that would be beyond the -- scope of this analysis. Symmetry means that if we -- apply a margin to the recto page, we must apply the -- same margin to the verso page, even if the hardware -- would not require it. Hence the factors of 2 here: UsableHeight = PageHeight - 2*addTopMargin - 2*addBottomMargin UsableWidth = PageWidth - 2*addLeftMargin - 2*addRightMargin if(SourceWidth <= SourceHeight) then Scale = math.min(UsableHeight / (2*SourceWidth), UsableWidth / SourceHeight) rot = 90 Ywiggle = 0.5 * math.max(0, UsableHeight - 2*SourceWidth*Scale) Xwiggle = math.max(0, UsableWidth - SourceHeight*Scale) fudge = addTopMargin + 2*(addBottomMargin + Ywiggle) -- Apply a factor of /2 to Xwiggle here, -- because we want centering -- (not flush to right of sheet, i.e. bottom of page): -- Do not apply corresponding factor to Ywiggle, because -- we do want flush to top of sheet, i.e. right of page: xof = addLeftMargin + SourceHeight*Scale + Xwiggle/2 yofRtop = SourceWidth*Scale + fudge yofRbot = SourceWidth*Scale + fudge yofVtop = addBottomMargin + Ywiggle yofVbot = addBottomMargin + Ywiggle else Scale = math.min(UsableHeight / (2*SourceHeight), UsableWidth / SourceWidth) rot = 0 Ywiggle = 0.5 * math.max(0, UsableHeight - 2*SourceHeight*Scale) Xwiggle = math.max(0, UsableWidth - SourceWidth*Scale) fudge = addTopMargin + 2*(addBottomMargin + Ywiggle) xof = addLeftMargin + Xwiggle/2 yofRtop = SourceHeight*Scale + fudge yofRbot = SourceHeight*Scale + fudge yofVtop = addBottomMargin + Ywiggle yofVbot = addBottomMargin + Ywiggle end do rest = PageCount % 4 totp = PageCount if rest ~= 0 then totp = totp + ( 4 - rest) end -- "inc" counts input pages skipped as well as pages actually used: inc = 0 -- "outc" counts output pages: outc = 0; count = 0 imax = totp/4 middle = totp/2 while count < imax do -- We assume that podofoimpose will discard invalid records -- such as those with source page greater than PageCount -- print(totp, inc, outc, rot, xof, yofRtop, yofVtop, yofRbot, yofVbot) -- Top of sheet: (8 1) ... (6 3) if TopMode ~= 0 then -- We did all the interesting calculations in real units (above). -- We convert to nasty descaled units at the last moment: PushRecord(totp - inc, outc + 1, rot, xof/Scale, yofVtop/Scale) PushRecord(inc + 1, outc + 1, rot, xof/Scale, yofRtop/Scale) outc = outc + 1 end -- Bottom of sheet: if BottomMode ~= 0 then if BoStack ~= 0 then -- Reversed bottom: (4 5) ... (2 7) PushRecord(middle - inc, outc + 1, rot, xof/Scale, yofVbot/Scale) PushRecord(middle + 1 + inc, outc + 1, rot, xof/Scale, yofRbot/Scale) else -- Normal bottom: (2 7) ... (4 5) PushRecord(inc + 2, outc + 1, rot, xof/Scale, yofVbot/Scale) PushRecord(totp-(inc + 1), outc + 1, rot, xof/Scale, yofRbot/Scale) end outc = outc + 1 end count = count + 1 inc = inc + 2 end end ��������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/tools/podofoimpose/sample.plan���������������������������������������������������������0000664�0001750�0001750�00000002715�11044703333�020664� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������##### ISO A2 paper - ISO A5 pages - in16 x 2 ##### ## Here is a sample plan file for podofoimpose ## You should find sample.pdf along this file ## run "podofoimpose sample.pdf sample_imposed.pdf sample.plan" to try it. # $PageWidth & $PageHeight are required # reminder: # source page; destination page; rotation; Tx; Ty; $PageWidth=1190.55 $PageHeight=1683.78 # I’m lazy at typing :) $pw=1190.55 $ph=1683.78 # Plate 1 $plate=1 8; $plate; 270; 0; $ph; 1; $plate; 90; $pw; ($ph/4.0)*3.0; 9; $plate; 270; 0; ($ph/4.0) * 3.0; 16; $plate; 90; $pw; ($ph/4.0)*2.0; 12; $plate; 270; 0; ($ph/4.0)*2.0; 13; $plate; 90; $pw; $ph/4.0; 5; $plate; 270; 0; $ph/4.0; 4; $plate; 90; $pw; 0; # Plate 2 $plate=2 2; $plate; 270; 0; $ph; 7; $plate; 90; $pw; ($ph/4.0)*3.0; 15; $plate; 270; 0; ($ph/4.0)*3.0; 10; $plate; 90; $pw; ($ph/4.0)*2.0; 14; $plate; 270; 0; ($ph/4.0)*2.0; 11; $plate; 90; $pw; $ph/4.0; 3; $plate; 270; 0; $ph/4.0; 6; $plate; 90; $pw; 0; # Plate 3 $plate=3 24; $plate; 270; 0; $ph; 17; $plate; 90; $pw; ($ph/4.0)*3.0; 25; $plate; 270; 0; ($ph/4.0)*3.0; 32; $plate; 90; $pw; ($ph/4.0)*2.0; 28; $plate; 270; 0; ($ph/4.0)*2.0; 29; $plate; 90; $pw; $ph/4.0; 21; $plate; 270; 0; $ph/4.0; 20; $plate; 90; $pw; 0; # Plate 4 $plate=4 18; $plate; 270; 0; $ph; 23; $plate; 90; $pw; ($ph/4.0)*3.0; 31; $plate; 270; 0; ($ph/4.0)*3.0; 26; $plate; 90; $pw; ($ph/4.0)*2.0; 30; $plate; 270; 0; ($ph/4.0)*2.0; 27; $plate; 90; $pw; $ph/4.0; 19; $plate; 270; 0; $ph/4.0; 22; $plate; 90; $pw; 0; ���������������������������������������������������podofo-0.9.3/tools/podofoimpose/podofoimpose.cpp����������������������������������������������������0000664�0001750�0001750�00000007222�11306221052�021726� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*************************************************************************** * Copyright (C) 2007 by Pierre Marchand * * pierre@moulindetouvois.com * * * * 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., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "pdftranslator.h" #include <cstdlib> #include <iostream> #include <string> #include <cstdio> using std::cerr; using std::endl; using std::strtod; using std::string; struct _params { string executablePath; string inFilePath; string outFilePath; string planFilePath; PoDoFo::Impose::PlanReader planReader; } params; void usage() { cerr << "Usage : " << params.executablePath << " Input Output Plan [Interpretor]" << endl; cerr << "***" << endl; cerr << "\tInput is a PDF file or a file which contains a list of PDF file paths" << endl<< endl; cerr << "\tOutput will be a PDF file" << endl<< endl; cerr << "\tPlan is an imposition plan file" <<endl<< endl; cerr << "\t[Interpretor] Can be \"native\" (default value) or \"lua\""<< endl<< endl; cerr << "PoDoFo Version: " << PODOFO_VERSION_STRING << endl << endl; } int parseCommandLine ( int argc, char* argv[] ) { params.executablePath = argv[0]; if ( argc < 4 ) { usage(); return 1; } params.inFilePath = argv[1]; params.outFilePath = argv[2]; params.planFilePath = argv[3]; params.planReader = PoDoFo::Impose::Legacy; if ( argc >= 5 ) { std::string native ( "native" ); std::string lua ( "lua" ); std::string interpretor ( argv[4] ); if ( !interpretor.compare ( native ) ) params.planReader = PoDoFo::Impose::Legacy; else if ( !interpretor.compare ( lua ) ) params.planReader = PoDoFo::Impose::Lua; } return 0; } /** * Return values: * * 0 : success * 1 : bad command line arguments */ int main ( int argc, char *argv[] ) { #if 0 PoDoFo::PdfError::EnableDebug ( false ); PoDoFo::PdfError::EnableLogging ( false ); #endif int ret = parseCommandLine ( argc, argv ); if ( ret ) return ret; std::cerr<<"Source : "<<params.inFilePath<<std::endl; std::cerr<<"Target : "<<params.outFilePath<<std::endl; std::cerr<<"Plan : "<<params.planFilePath<<std::endl; try { PoDoFo::Impose::PdfTranslator *translator = new PoDoFo::Impose::PdfTranslator; translator->setSource ( params.inFilePath ); translator->setTarget ( params.outFilePath ); translator->loadPlan ( params.planFilePath, params.planReader ); translator->impose(); } catch ( PoDoFo::PdfError & e ) { e.GetCallstack(); e.PrintErrorMsg(); return 3; } catch ( std::exception & e ) { cerr << e.what() << endl; } return 0; } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/tools/podofoimpose/planreader_lua.h����������������������������������������������������0000664�0001750�0001750�00000002213�11332265042�021647� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// // C++ Header: planreader_lua // // Description: // // // Author: Pierre Marchand <pierremarc@oep-h.com>, (C) 2008 // // Copyright: See COPYING file that comes with this distribution // // #ifndef PLANREADERLUA_H #define PLANREADERLUA_H #include "impositionplan.h" #include <string> struct lua_State; class LuaMachina { lua_State *L; public: LuaMachina(); ~LuaMachina(); inline lua_State* State() { return L; } }; // could be best to have a base class but we wont develop 36000 // readers after all. class PlanReader_Lua { LuaMachina L; public: PlanReader_Lua(const std::string & planfile, PoDoFo::Impose::ImpositionPlan* ip); ~PlanReader_Lua(); static int PushRecord(lua_State *L); private: PoDoFo::Impose::ImpositionPlan* plan; /** Ask if a variable is available in script global scope */ bool hasGlobal(const std::string& name); /** Get the value of the named global from the Lua environment */ double getNumber(const std::string& name); /** Set a global to the passed value */ void setNumber(const std::string& name, double value); std::string getString(const std::string& name); }; #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/tools/podofoimpose/impositionplan.cpp��������������������������������������������������0000664�0001750�0001750�00000017227�11332265042�022304� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������// // C++ Implementation: impositionplan // // Description: // // // Author: Pierre Marchand <pierremarc@oep-h.com>, (C) 2008 // // Copyright: See COPYING file that comes with this distribution // // #include "impositionplan.h" #include <fstream> #include <stdexcept> #include <algorithm> #include <cmath> #include <istream> #include <ostream> #include <cstdio> using std::ostringstream; using std::map; using std::vector; using std::string; using std::ifstream; using std::istream; using std::ostream; using std::endl; using std::runtime_error; #ifdef _WIN32 #ifdef max #undef max #endif // max #ifdef min #undef min #endif // min #endif // _WIN32 #include <iostream> //XXX namespace PoDoFo { namespace Impose { PageRecord::PageRecord ( int s,int d,double r, double tx, double ty, int du ) : sourcePage ( s ), destPage ( d ), rotate ( r ), transX ( tx ), transY ( ty ), duplicateOf( du ) { }; PageRecord::PageRecord ( ) : sourcePage ( 0 ), destPage ( 0 ), rotate ( 0 ), transX ( 0 ), transY ( 0 ) {}; void PageRecord::load ( const std::string& buffer, const std::map<std::string, std::string>& vars ) { int blen ( buffer.length() ); std::vector<std::string> tokens; std::string ts; for ( int i ( 0 ); i < blen; ++i ) { char ci ( buffer.at ( i ) ); if ( ci == ' ' ) continue; else if ( ci == ';' ) { tokens.push_back ( ts ); ts.clear(); continue; } ts += ci; } if ( tokens.size() != 5 ) { sourcePage = destPage = 0; // will return false for isValid() std::cerr<<"INVALID_RECORD("<< tokens.size() <<") "<<buffer<<std::endl; for ( unsigned int i = 0;i<tokens.size();++i ) std::cerr<<"\t+ "<<tokens.at ( i ) <<std::endl; } sourcePage = static_cast<int>(calc ( tokens.at ( 0 ) , vars)); destPage = static_cast<int>(calc ( tokens.at ( 1 ) , vars)); if ( ( sourcePage < 1 ) || ( destPage < 1 ) ) { sourcePage = destPage = 0; } rotate = calc ( tokens.at ( 2 ) , vars); transX = calc ( tokens.at ( 3 ) , vars); transY = calc ( tokens.at ( 4 ) , vars); std::cerr<<" "<<sourcePage<<" "<<destPage<<" "<<rotate<<" "<<transX<<" "<<transY <<std::endl; } double PageRecord::calc ( const std::string& s , const std::map<std::string, std::string>& vars) { // std::cerr<< s; std::vector<std::string> tokens; int tlen ( s.length() ); std::string ts; for ( int i ( 0 ); i < tlen; ++i ) { char ci ( s.at ( i ) ); // if ( ci == 0x20 || ci == 0x9 )// skip spaces and horizontal tabs // continue; if ( ( ci == '+' ) || ( ci == '-' ) || ( ci == '*' ) || ( ci == '/' ) || ( ci == '%' ) || ( ci == '|' ) || ( ci == '"' ) || ( ci == '(' ) || ( ci == ')' ) ) { // commit current string if ( ts.length() > 0 ) { std::map<std::string, std::string>::const_iterator vit = vars.find ( ts ); if ( vit != vars.end() ) { // std::cerr<<"A Found "<<ts<<" "<< vit->second <<std::endl; tokens.push_back ( Util::dToStr ( calc ( vit->second, vars ) ) ); } else { // std::cerr<<"A Not Found "<<ts<<std::endl; tokens.push_back ( ts ); } } ts.clear(); // append operator ts += ci; tokens.push_back ( ts ); ts.clear(); } else if ( ci > 32 ) { ts += ci; } // else // std::cerr<<"Wrong char : "<< ci <<std::endl; } if ( ts.length() > 0 ) { std::map<std::string, std::string>::const_iterator vit2 = vars.find ( ts ); if ( vit2 != vars.end() ) { // std::cerr<<std::endl<<"Found "<<ts<<std::endl; tokens.push_back ( Util::dToStr ( calc ( vit2->second , vars) ) ); } else { // if((ts.length() > 0) && (ts[0] == '$')) // { // std::cerr<<std::endl<<"Not Found \""; // for(unsigned int c(0);c < ts.length(); ++c) // { // std::cerr<<ts[c]<<"/"; // } // std::cerr<<"\""<<std::endl; // for(std::map<std::string,std::string>::iterator i(PoDoFoImpose::vars.begin());i != PoDoFoImpose::vars.end(); ++i) // { // // std::cerr<<"VA \""<< i->first << "\" => " <<(i->first == ts ? "True" : "False") <<std::endl; // for(unsigned int c(0);c < i->first.length(); ++c) // { // std::cerr<< i->first[c]<<"/"; // } // std::cerr<<std::endl; // } // } tokens.push_back ( ts ); } } double result ( calc ( tokens ) ); // std::cerr<<" = "<<result<<std::endl; return result; } double PageRecord::calc ( const std::vector<std::string>& t ) { // std::cerr<<"C ="; // for(uint i(0);i<t.size();++i) // std::cerr<<" "<< t.at(i) <<" "; // std::cerr<<std::endl; if ( t.size() == 0 ) return 0.0; double ret ( 0.0 ); std::vector<double> values; std::vector<std::string> ops; ops.push_back ( "+" ); for ( unsigned int vi = 0; vi < t.size(); ++vi ) { if ( t.at ( vi ) == "(" ) { std::vector<std::string> tokens; int cdeep ( 0 ); // std::cerr<<"("; for ( ++vi ; vi < t.size(); ++vi ) { // std::cerr<<t.at ( ti ); if ( t.at ( vi ) == ")" ) { if ( cdeep == 0 ) break; else { --cdeep; } } else if ( t.at ( vi ) == "(" ) { ++cdeep; } // std::cerr<<std::endl<<"\t"; tokens.push_back ( t.at ( vi ) ); } // std::cerr<<std::endl; values.push_back ( calc ( tokens ) ); } else if ( t.at ( vi ) == "+" ) ops.push_back ( "+" ); else if ( t.at ( vi ) == "-" ) ops.push_back ( "-" ); else if ( t.at ( vi ) == "*" ) ops.push_back ( "*" ); else if ( t.at ( vi ) == "/" ) ops.push_back ( "/" ); else if ( t.at ( vi ) == "%" ) ops.push_back ( "%" ); else if ( t.at ( vi ) == "|" ) ops.push_back ( "|" ); else if ( t.at ( vi ) == "\"" ) ops.push_back ( "\"" ); else values.push_back ( std::atof ( t.at ( vi ).c_str() ) ); } if ( values.size() == 1 ) ret = values.at ( 0 ); else { for ( unsigned int vi = 0; vi < ops.size(); ++vi ) { // std::cerr<<"OP>> \""<<ret<<"\" " << ops.at ( vi )<<" \""<<values.at( vi ) <<"\" = "; if ( ops.at ( vi ) == "+" ) ret += values.at ( vi ); else if ( ops.at ( vi ) == "-" ) ret -= values.at ( vi ); else if ( ops.at ( vi ) == "*" ) ret *= values.at ( vi ); /// I know it’s not good (tm) /// + http://gcc.gnu.org/ml/gcc/2001-08/msg00853.html else if ( ops.at ( vi ) == "/" ) { if ( values.at ( vi ) == 0.0 ) ret = 0.0; else ret /= values.at ( vi ); } else if ( ops.at ( vi ) == "%" ) { if ( values.at ( vi ) == 0.0 ) ret = 0.0; else ret = static_cast<int> ( ret ) % static_cast<int> ( values.at ( vi ) ); } else if ( ops.at ( vi ) == "|" ) // Stands for max(a,b), easier than true condition, allow to filter division by 0 ret = std::max ( ret , values.at ( vi ) ); else if ( ops.at ( vi ) == "\"" ) // Stands for min(a,b) ret = std::min ( ret , values.at ( vi ) ); // std::cerr<<ret<<std::endl; } } // std::cerr<<" <"<< values.size() <<"> "<<ret<<std::endl; return ret; } bool PageRecord::isValid() const { //TODO if ( !sourcePage || !destPage ) return false; return true; } ImpositionPlan::ImpositionPlan(const SourceVars& sv) : sourceVars(sv), m_destWidth ( 0.0 ), m_destHeight ( 0.0 ), m_scale ( 1.0 ) { } ImpositionPlan::~ ImpositionPlan() { } bool ImpositionPlan::valid() const { if ( destWidth() <= 0.0 ) return false; else if ( destHeight() <= 0.0 ) return false; // else if ( scale() <= 0.0 ) // return false; else if(size() == 0) return false; return true; } void ImpositionPlan::setDestWidth ( double theValue ) { m_destWidth = theValue; } void ImpositionPlan::setDestHeight ( double theValue ) { m_destHeight = theValue; } void ImpositionPlan::setScale ( double theValue ) { m_scale = theValue; } void ImpositionPlan::setBoundingBox( const std::string& theString ) { m_boundingBox = theString; } };}; �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/tools/podofoimpose/pdftranslator.h�����������������������������������������������������0000664�0001750�0001750�00000011335�11332265042�021561� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*************************************************************************** * Copyright (C) 2007 by Pierre Marchand * * pierre@moulindetouvois.com * * * * 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., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #ifndef PDFTRANSLATOR_H #define PDFTRANSLATOR_H #include "podofo.h" #include "impositionplan.h" #include <string> #include <map> #include <vector> #include <sstream> #include <istream> #include <string> // using namespace PoDoFo; namespace PoDoFo { namespace Impose { /** PdfTranslator create a new PDF file which is the imposed version, following the imposition plan provided by the user, of the source PDF file. Pdftranslate does not really create a new PDF doc, it rather works on source doc, getting all page contents as XObjects and put these XObjects on new pages. At the end, it removes original pages from the doc, but since PoDoFo keeps them --- just removing from the pages tree ---, if it happens that you have a lot of content in content stream rather than in resources, you'll get a huge file. Usage is something like : p = new PdfTranslator; p->setSource("mydoc.pdf"); p->setTarget("myimposeddoc.pdf"); p->loadPlan("in4-32p.plan"); p->impose(); p->mailItToMyPrinterShop("job@proprint.com");//Would be great, doesn't it ? */ class PdfTranslator { public: PdfTranslator(); ~PdfTranslator() { } PdfMemDocument *sourceDoc; PdfMemDocument *targetDoc; /** Set the source document(s) to be imposed. Argument source is the path of the PDF file, or the path of a file containing a list of paths of PDF files... */ void setSource ( const std::string & source ); /** Another way to set many files as source document. Note that a source must be set before you call addToSource(). */ void addToSource ( const std::string & source ); /** Set the path of the file where the imposed PDF doc will be save. */ void setTarget ( const std::string & target ); /** Load an imposition plan file of form: widthOfSheet heightOfSheet sourcePage destPage rotation translationX translationY ... ... ... ... ... */ void loadPlan ( const std::string & planFile , PoDoFo::Impose::PlanReader loader ); /** When all is prepared, call it to do the job. */ void impose(); private: std::string inFilePath; std::string outFilePath; PdfReference globalResRef; ImpositionPlan *planImposition; std::map<int, PdfXObject*> xobjects; std::map<int,PdfObject*> resources; std::map<int, PdfRect> cropRect; std::map<int,PdfRect> bleedRect; std::map<int, PdfRect> trimRect; std::map<int,PdfRect> artRect; std::map<int, PdfDictionary*> pDict; std::map<int, int> virtualMap; // int maxPageDest; int duplicate; bool checkIsPDF ( std::string path ); PdfObject* getInheritedResources ( PdfPage* page ); void mergeResKey ( PdfObject *base, PdfName key, PdfObject *tomerge ); PdfObject* migrateResource(PdfObject * obj); void drawLine ( double x, double y, double xx, double yy, std::ostringstream & a ); void signature ( double x , double y, int sheet, const std::vector<int> & pages, std::ostringstream & a ); // An attempt to allow nested loops // returns new position in records list. int sortLoop(std::vector<std::string>& memfile, int numline); std::string useFont; PdfReference useFontRef; double extraSpace; std::vector<std::string> multiSource; std::map<std::string, PdfObject*> migrateMap; public: int pcount; double sourceWidth; double sourceHeight; double destWidth; double destHeight; double scaleFactor; std::string boundingBox; }; };}; // end of namespace #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/tools/podofoincrementalupdates/��������������������������������������������������������0000775�0001750�0001750�00000000000�12356565167�021137� 5����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/tools/podofoincrementalupdates/incrementalupdates.cpp����������������������������������0000664�0001750�0001750�00000006664�12062205562�025526� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*************************************************************************** * Copyright (C) 2009 by Dominik Seichter * * domseichter@web.de * * * * 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., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include <podofo.h> #include <cstdlib> #include <cstdio> using namespace PoDoFo; #ifdef _HAVE_CONFIG #include <config.h> #endif // _HAVE_CONFIG void print_help() { printf("Usage: podofoincrementalupdates [-e N out.pdf] file.pdf\n\n"); printf(" This tool prints information of incremental updates to file.pdf.\n"); printf(" By default the number of incremental updates will be printed.\n"); printf(" -e N out.pdf\n"); printf(" Extract the Nth update from file.pdf and write it to out.pdf.\n"); printf("\nPoDoFo Version: %s\n\n", PODOFO_VERSION_STRING); } int get_info( const char* pszFilename ) { int nUpdates = 0; PdfVecObjects vecObjects; PdfParser parser( &vecObjects, pszFilename, true ); nUpdates = parser.GetNumberOfIncrementalUpdates(); printf( "%s\t=\t%i\t(Number of incremental updates)\n", pszFilename, nUpdates ); return nUpdates; } void extract(const char* pszFilename, int nExtract, const char* pszOutputFilename) { //int nUpdates = 0; PdfVecObjects vecObjects; PdfParser parser( &vecObjects ); //parser.ParseFile( pszOutputFilename, true, nExtract ); // TODO } int main( int argc, char* argv[] ) { PdfError::EnableDebug( false ); if( argc != 2 && argc != 5 ) { print_help(); exit( -1 ); } try { const char* pszFilename; const char* pszOutputFilename; int nExtract = -1; if(argc == 2) { pszFilename = argv[1]; get_info(pszFilename); } else if(argc == 5) { nExtract = strtol(argv[2], NULL, 10); pszOutputFilename = argv[3]; pszFilename = argv[4]; extract(pszFilename, nExtract, pszOutputFilename); } } catch( PdfError & e ) { fprintf( stderr, "Error: An error %i ocurred during counting pages in the pdf file.\n", e.GetError() ); e.PrintErrorMsg(); return e.GetError(); } return 0; } ����������������������������������������������������������������������������podofo-0.9.3/tools/podofoincrementalupdates/CMakeLists.txt������������������������������������������0000664�0001750�0001750�00000000543�11305305023�023651� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������ADD_EXECUTABLE(podofoincrementalupdates incrementalupdates.cpp) TARGET_LINK_LIBRARIES(podofoincrementalupdates ${PODOFO_LIB}) SET_TARGET_PROPERTIES(podofoincrementalupdates PROPERTIES COMPILE_FLAGS "${PODOFO_CFLAGS}") ADD_DEPENDENCIES(podofoincrementalupdates ${PODOFO_DEPEND_TARGET}) INSTALL(TARGETS podofoincrementalupdates RUNTIME DESTINATION "bin") �������������������������������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/tools/podofoimg2pdf/�������������������������������������������������������������������0000775�0001750�0001750�00000000000�12356565167�016600� 5����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/tools/podofoimg2pdf/CMakeLists.txt�����������������������������������������������������0000664�0001750�0001750�00000000471�11331602263�021317� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������ADD_EXECUTABLE(podofoimg2pdf podofoimg2pdf.cpp ImageConverter.cpp) TARGET_LINK_LIBRARIES(podofoimg2pdf ${PODOFO_LIB}) SET_TARGET_PROPERTIES(podofoimg2pdf PROPERTIES COMPILE_FLAGS "${PODOFO_CFLAGS}") ADD_DEPENDENCIES(podofoimg2pdf ${PODOFO_DEPEND_TARGET}) INSTALL(TARGETS podofoimg2pdf RUNTIME DESTINATION "bin") �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/tools/podofoimg2pdf/ImageConverter.h���������������������������������������������������0000664�0001750�0001750�00000004024�11331602263�021640� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*************************************************************************** * Copyright (C) 2010 by Dominik Seichter * * domseichter@web.de * * * * 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., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include <string> #include <vector> class ImageConverter { public: ImageConverter(); ~ImageConverter(); inline void SetOutputFilename( const char* pszFilename ) { m_sOutputFilename = pszFilename; } inline void AddImage( const char* pszImage ) { m_vecImages.push_back( std::string(pszImage) ); } inline void SetUseImageSize( bool bImageSize ) { m_bUseImageSize = bImageSize; } void Work(); private: std::vector<std::string> m_vecImages; std::string m_sOutputFilename; bool m_bUseImageSize; }; ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/tools/podofoimg2pdf/podofoimg2pdf.cpp��������������������������������������������������0000664�0001750�0001750�00000006334�11373224054�022032� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*************************************************************************** * Copyright (C) 2010 by Dominik Seichter * * domseichter@web.de * * * * 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., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include <stdio.h> #include <stdlib.h> #ifdef _HAVE_CONFIG #include <config.h> #endif // _HAVE_CONFIG #include "ImageConverter.h" #include <podofo.h> void print_help() { printf("Usage: podofoimg2pdf [output.pdf] [-useimgsize] [image1 image2 image3 ...]\n\n"); printf("Options:\n"); printf(" -useimgsize Use the imagesize as page size, instead of A4\n"); printf("\nPoDoFo Version: %s\n\n", PODOFO_VERSION_STRING); printf("\n"); printf("This tool will combine any number of images into a single PDF.\n"); printf("This is useful to create a document from scanned images.\n"); printf("Large pages will be scaled to fit the page and imags smaller\n"); printf("than the defined page size, will be centered.\n"); printf("\n"); printf("Supported image formats:\n"); const char** ppszFormats = PoDoFo::PdfImage::GetSupportedFormats(); while( *ppszFormats ) { printf("\t%s\n", *ppszFormats ); ++ppszFormats; } printf("\n"); } int main( int argc, char* argv[] ) { char* pszOutput; if( argc < 3 ) { print_help(); exit( -1 ); } pszOutput = argv[1]; printf("Output filename: %s\n", pszOutput); ImageConverter converter; converter.SetOutputFilename( pszOutput ); for( int i=2;i<argc;i++ ) { std::string sOption = argv[i]; if( sOption == "-useimgsize" ) { converter.SetUseImageSize( true ); } else { printf("Adding image: %s\n", argv[i]); converter.AddImage( argv[i] ); } } try { converter.Work(); } catch( PoDoFo::PdfError & e ) { fprintf( stderr, "Error: An error %i ocurred during processing the pdf file.\n", e.GetError() ); e.PrintErrorMsg(); return e.GetError(); } printf("Wrote PDF successfully: %s.\n", pszOutput ); return 0; } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/tools/podofoimg2pdf/ImageConverter.cpp�������������������������������������������������0000664�0001750�0001750�00000005657�11331602263�022210� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*************************************************************************** * Copyright (C) 2010 by Dominik Seichter * * domseichter@web.de * * * * 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., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "ImageConverter.h" #include <podofo.h> ImageConverter::ImageConverter() : m_bUseImageSize( false ) { } ImageConverter::~ImageConverter() { } void ImageConverter::Work() { PoDoFo::PdfMemDocument document; std::vector<std::string>::const_iterator it = m_vecImages.begin(); PoDoFo::PdfRect size = PoDoFo::PdfPage::CreateStandardPageSize( PoDoFo::ePdfPageSize_A4, false ); PoDoFo::PdfPainter painter; double dScaleX = 1.0; double dScaleY = 1.0; double dScale = 1.0; while( it != m_vecImages.end() ) { PoDoFo::PdfPage* pPage; PoDoFo::PdfImage image( &document ); image.LoadFromFile( (*it).c_str() ); if( m_bUseImageSize ) { size = PoDoFo::PdfRect( 0.0, 0.0, image.GetWidth(), image.GetHeight() ); } pPage = document.CreatePage( size ); dScaleX = size.GetWidth() / image.GetWidth(); dScaleY = size.GetHeight() / image.GetHeight(); dScale = PoDoFo::PDF_MIN( dScaleX, dScaleY ); painter.SetPage( pPage ); if( dScale < 1.0 ) { painter.DrawImage( 0.0, 0.0, &image, dScale, dScale ); } else { // Center Image double dX = (size.GetWidth() - image.GetWidth())/2.0; double dY = (size.GetHeight() - image.GetHeight())/2.0; painter.DrawImage( dX, dY, &image ); } painter.FinishPage(); ++it; } document.Write( m_sOutputFilename.c_str() ); } ���������������������������������������������������������������������������������podofo-0.9.3/tools/podofopages/���������������������������������������������������������������������0000775�0001750�0001750�00000000000�12356565167�016347� 5����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/tools/podofopages/MoveOperation.cpp����������������������������������������������������0000664�0001750�0001750�00000004257�11201067720�021626� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*************************************************************************** * Copyright (C) 2009 by Dominik Seichter * * domseichter@web.de * * * * 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., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "MoveOperation.h" #include <podofo.h> MoveOperation::MoveOperation( int nFrom, int nTo ) : m_nFrom( nFrom ), m_nTo( nTo ) { } void MoveOperation::Perform( PoDoFo::PdfDocument & rDoc ) { PoDoFo::PdfPagesTree* pTree = rDoc.GetPagesTree(); PoDoFo::PdfPage* pPage = pTree->GetPage( m_nFrom ); int from = m_nFrom; pTree->InsertPage( m_nTo, pPage ); if( m_nTo < from ) { // If we inserted the page before the old // position we have to increment the from position from++; } pTree->DeletePage( from ); } std::string MoveOperation::ToString() const { std::ostringstream oss; oss << "Moving page " << m_nFrom << " to " << m_nTo << "." << std::endl; return oss.str(); } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/tools/podofopages/DeleteOperation.h����������������������������������������������������0000664�0001750�0001750�00000003532�11201067720�021562� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*************************************************************************** * Copyright (C) 2009 by Dominik Seichter * * domseichter@web.de * * * * 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., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #ifndef __DELETE_OPERATION__H__ #define __DELETE_OPERATION__H__ #include "Operation.h" namespace PoDoFo { class PdfDocument; } class DeleteOperation : public Operation { public: DeleteOperation( int nPage ); virtual ~DeleteOperation() { } virtual void Perform( PoDoFo::PdfDocument & rDoc ); virtual std::string ToString() const; private: int m_nPage; }; #endif // __DELETE_OPERATION__H__ ����������������������������������������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/tools/podofopages/MoveOperation.h������������������������������������������������������0000664�0001750�0001750�00000003550�11201067720�021266� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*************************************************************************** * Copyright (C) 2009 by Dominik Seichter * * domseichter@web.de * * * * 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., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #ifndef __MOVE_OPERATION__H__ #define __MOVE_OPERATION__H__ #include "Operation.h" namespace PoDoFo { class PdfDocument; } class MoveOperation : public Operation { public: MoveOperation( int nFrom, int nTo ); virtual ~MoveOperation() { } virtual void Perform( PoDoFo::PdfDocument & rDoc ); virtual std::string ToString() const; private: int m_nFrom; int m_nTo; }; #endif // __MOVE_OPERATION__H__ ��������������������������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/tools/podofopages/podofopages.cpp������������������������������������������������������0000664�0001750�0001750�00000012615�11341226006�021341� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*************************************************************************** * Copyright (C) 2009 by Dominik Seichter * * domseichter@web.de * * * * 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., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include <podofo.h> #include <stdlib.h> #include <iostream> #include <iostream> #include <string> #include <stdexcept> #include <vector> #include <cstdio> #include "DeleteOperation.h" #include "MoveOperation.h" using namespace PoDoFo; #ifdef _HAVE_CONFIG #include <config.h> #endif // _HAVE_CONFIG class BadConversion : public std::runtime_error { public: BadConversion(const std::string& s) : std::runtime_error(s) { } }; void print_help() { printf("Usage: podofopages [inputfile] [outputfile]\n"); printf("Options:\n"); printf("\t--delete NUMBER\n"); printf("\tDeletes the page NUMBER (number is 0-based)\n"); printf("\tThe page will not really be deleted from the PDF.\n"); printf("\tIt is only removed from the so called pagestree and\n"); printf("\ttherefore invisible. The content of the page can still\n"); printf("\tbe retrieved from the document though.\n\n"); printf("\t--move FROM TO\n"); printf("\tMoves a page FROM TO in the document (FROM and TO are 0-based)\n\n"); printf("\nPoDoFo Version: %s\n\n", PODOFO_VERSION_STRING); } void work(const char* pszInput, const char* pszOutput, std::vector<Operation*> & rvecOperations) { std::cout << "Input file: " << pszInput << std::endl; std::cout << "Output file: " << pszOutput << std::endl; PdfMemDocument doc(pszInput); int total = rvecOperations.size(); int i = 1; std::vector<Operation*>::iterator it = rvecOperations.begin(); while( it != rvecOperations.end() ) { std::string msg = (*it)->ToString(); std::cout << "Operation " << i << " of " << total << ": " << msg; (*it)->Perform( doc ); ++it; ++i; } std::cout << "Operations done. Writing PDF to disk." << std::endl; doc.Write( pszOutput ); std::cout << "Done." << std::endl; } double convertToInt(const std::string& s) { std::istringstream i(s); int x; if (!(i >> x)) throw BadConversion("convertToInt(\"" + s + "\")"); return x; } int main( int argc, char* argv[] ) { char* pszInput = NULL; char* pszOutput = NULL; if( argc < 3 ) { print_help(); exit( -1 ); } // Fill operations vector std::vector<Operation*> vecOperations; for( int i=1; i < argc; i++ ) { std::string argument = argv[i]; if( argument == "--delete" || argument == "-delete" ) { int page = static_cast<int>(convertToInt( std::string(argv[i+1]) )); vecOperations.push_back( new DeleteOperation( page ) ); ++i; } else if( argument == "--move" || argument == "-move" ) { int from = static_cast<int>(convertToInt( std::string(argv[i+1]) )); int to = static_cast<int>(convertToInt( std::string(argv[i+2]) )); vecOperations.push_back( new MoveOperation( from, to ) ); ++i; ++i; } else { if( pszInput == NULL ) { pszInput = argv[i]; } else if( pszOutput == NULL ) { pszOutput = argv[i]; } else { std::cerr << "Ignoring unknown argument: " << argument << std::endl; } } } if( !pszInput ) { std::cerr << "Please specify an input file." << std::endl; exit( -2 ); } if( !pszOutput ) { std::cerr << "Please specify an output file." << std::endl; exit( -3 ); } if( std::string(pszInput) == std::string(pszOutput) ) { std::cerr << "Input and outpuf file must point to different files." << std::endl; exit( -4 ); } try { work( pszInput, pszOutput, vecOperations ); } catch( PdfError & e ) { std::cerr << "Error: An error " << e.GetError() << " ocurred." << std::endl; e.PrintErrorMsg(); return e.GetError(); } // Delete operations vectore std::vector<Operation*>::iterator it = vecOperations.begin(); while( it != vecOperations.end() ) { delete (*it); ++it; } return 0; } �������������������������������������������������������������������������������������������������������������������podofo-0.9.3/tools/podofopages/CMakeLists.txt�������������������������������������������������������0000664�0001750�0001750�00000000500�11201067720�021056� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������ADD_EXECUTABLE(podofopages podofopages.cpp DeleteOperation.cpp MoveOperation.cpp) TARGET_LINK_LIBRARIES(podofopages ${PODOFO_LIB}) SET_TARGET_PROPERTIES(podofopages PROPERTIES COMPILE_FLAGS "${PODOFO_CFLAGS}") ADD_DEPENDENCIES(podofopages ${PODOFO_DEPEND_TARGET}) INSTALL(TARGETS podofopages RUNTIME DESTINATION "bin") ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/tools/podofopages/Operation.h����������������������������������������������������������0000664�0001750�0001750�00000003503�11201067720�020435� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*************************************************************************** * Copyright (C) 2009 by Dominik Seichter * * domseichter@web.de * * * * 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., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #ifndef __OPERATION__H__ #define __OPERATION__H__ #include <string> namespace PoDoFo { class PdfDocument; } /** * Abstract base class for all operations * the podofopages can perform. * */ class Operation { public: virtual ~Operation() { } virtual void Perform( PoDoFo::PdfDocument & rDoc ) = 0; virtual std::string ToString() const = 0; }; #endif // __OPERATION__H__ ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/tools/podofopages/DeleteOperation.cpp��������������������������������������������������0000664�0001750�0001750�00000003513�11201067720�022114� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*************************************************************************** * Copyright (C) 2009 by Dominik Seichter * * domseichter@web.de * * * * 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., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "DeleteOperation.h" #include <podofo.h> DeleteOperation::DeleteOperation( int nPage ) : m_nPage( nPage ) { } void DeleteOperation::Perform( PoDoFo::PdfDocument & rDoc ) { rDoc.GetPagesTree()->DeletePage( m_nPage ); } std::string DeleteOperation::ToString() const { std::ostringstream oss; oss << "Deleting page: " << m_nPage << "." << std::endl; return oss.str(); } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/tools/podofouncompress/����������������������������������������������������������������0000775�0001750�0001750�00000000000�12356565167�017446� 5����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/tools/podofouncompress/CMakeLists.txt��������������������������������������������������0000664�0001750�0001750�00000000507�10517314571�022174� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������ADD_EXECUTABLE(podofouncompress Uncompress.cpp podofouncompress.cpp) TARGET_LINK_LIBRARIES(podofouncompress ${PODOFO_LIB}) SET_TARGET_PROPERTIES(podofouncompress PROPERTIES COMPILE_FLAGS "${PODOFO_CFLAGS}") ADD_DEPENDENCIES(podofouncompress ${PODOFO_DEPEND_TARGET}) INSTALL(TARGETS podofouncompress RUNTIME DESTINATION "bin") �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/tools/podofouncompress/Uncompress.h����������������������������������������������������0000664�0001750�0001750�00000003411�10646124303�021733� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*************************************************************************** * Copyright (C) 2005 by Dominik Seichter * * domseichter@web.de * * * * 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., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #ifndef _UNCOMPRESS_H_ #define _UNCOMPRESS_H_ #include <podofo.h> using namespace PoDoFo; class UnCompress { public: UnCompress(); ~UnCompress(); void Init( const char* pszInput, const char* pszOutput ); private: void UncompressObjects(); private: PdfMemDocument* m_pDocument; }; #endif // _UNCOMPRESS_H_ �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/tools/podofouncompress/Uncompress.cpp��������������������������������������������������0000664�0001750�0001750�00000006732�11667220150�022300� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*************************************************************************** * Copyright (C) 2005 by Dominik Seichter * * domseichter@web.de * * * * 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., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "Uncompress.h" #include <cstdio> using namespace PoDoFo; UnCompress::UnCompress() : m_pDocument( NULL ) { } UnCompress::~UnCompress() { delete m_pDocument; } void UnCompress::Init( const char* pszInput, const char* pszOutput ) { if( m_pDocument ) delete m_pDocument; m_pDocument = new PdfMemDocument( pszInput ); this->UncompressObjects(); PdfWriter writer( &(m_pDocument->GetObjects()), new PdfObject( *(m_pDocument->GetTrailer() ) ) ); writer.SetWriteMode( ePdfWriteMode_Clean ); writer.Write( pszOutput ); } void UnCompress::UncompressObjects() { TIVecObjects it = m_pDocument->GetObjects().begin(); while( it != m_pDocument->GetObjects().end() ) { printf("Reading %i %i R\n", (*it)->Reference().ObjectNumber(), (*it)->Reference().GenerationNumber() ); if( (*it)->HasStream() ) { try { printf("-> Uncompressing object %i %i\n", (*it)->Reference().ObjectNumber(), (*it)->Reference().GenerationNumber() ); PdfMemStream* pStream = dynamic_cast<PdfMemStream*>((*it)->GetStream()); printf("-> Original Length: %"PDF_FORMAT_INT64"\n", static_cast<pdf_int64>(pStream->GetLength()) ); try { pStream->Uncompress(); } catch( const PdfError & e ) { if( e.GetError() == ePdfError_Flate ) { // Ignore ZLib errors fprintf( stderr, "WARNING: ZLib error ignored for this object.\n"); } else throw e; } printf("-> Uncompressed Length: %"PDF_FORMAT_INT64"\n", static_cast<pdf_int64>(pStream->GetLength()) ); } catch( const PdfError & e ) { e.PrintErrorMsg(); if( e.GetError() != ePdfError_UnsupportedFilter ) throw e; } } ++it; } } ��������������������������������������podofo-0.9.3/tools/podofouncompress/podofouncompress.cpp��������������������������������������������0000664�0001750�0001750�00000004735�11460071654�023554� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*************************************************************************** * Copyright (C) 2005 by Dominik Seichter * * domseichter@web.de * * * * 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., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "Uncompress.h" #include <podofo.h> #include <stdlib.h> #include <cstdio> using namespace PoDoFo; #ifdef _HAVE_CONFIG #include <config.h> #endif // _HAVE_CONFIG void print_help() { printf("Usage: podofouncompress [inputfile] [outputfile]\n\n"); printf(" This tool removes all compression from the PDF file.\n"); printf(" It is useful for debugging errors in PDF files or analysing their structure.\n"); printf("\nPoDoFo Version: %s\n\n", PODOFO_VERSION_STRING); } int main( int argc, char* argv[] ) { char* pszInput; char* pszOutput; UnCompress unc; if( argc != 3 ) { print_help(); exit( -1 ); } pszInput = argv[1]; pszOutput = argv[2]; // try { unc.Init( pszInput, pszOutput ); /* } catch( PdfError & e ) { fprintf( stderr, "Error: An error %i ocurred during uncompressing the pdf file.\n", e.GetError() ); e.PrintErrorMsg(); return e.GetError(); } */ printf("%s was sucessfully uncompressed to: %s\n", pszInput, pszOutput ); return 0; } �����������������������������������podofo-0.9.3/Doxyfile�������������������������������������������������������������������������������0000664�0001750�0001750�00000205406�11641323033�014372� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Doxyfile 1.7.1 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project # # All text after a hash (#) is considered a comment and will be ignored # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" ") #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file # that follow. The default is UTF-8 which is also the encoding used for all # text before the first occurrence of this tag. Doxygen uses libiconv (or the # iconv built into libc) for the transcoding. See # http://www.gnu.org/software/libiconv for the list of possible encodings. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded # by quotes) that should identify the project. PROJECT_NAME = PoDoFo # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = 0.9.1 # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. OUTPUT_DIRECTORY = doc # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 4096 sub-directories (in 2 levels) under the output directory of each output # format and will distribute the generated files over these directories. # Enabling this option can be useful when feeding doxygen a huge amount of # source files, where putting all generated files in the same directory would # otherwise cause performance problems for the file system. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # The default language is English, other supported languages are: # Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, # Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, # Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English # messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, # Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, # Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will # include brief member descriptions after the members that are listed in # the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend # the brief description of a member or function before the detailed description. # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator # that is used to form the text in various listings. Each string # in this list, if found as the leading text of the brief description, will be # stripped from the text and the result after processing the whole list, is # used as the annotated text. Otherwise, the brief description is used as-is. # If left blank, the following values are used ("$name" is automatically # replaced with the name of the entity): "The $name class" "The $name widget" # "The $name file" "is" "provides" "specifies" "contains" # "represents" "a" "an" "the" ABBREVIATE_BRIEF = "The $name class" \ "The $name widget" \ "The $name file" \ is \ provides \ specifies \ contains \ represents \ a \ an \ the # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full # path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = NO # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag # can be used to strip a user-defined part of the path. Stripping is # only done if one of the specified strings matches the left-hand part of # the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the # path to strip. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # the path mentioned in the documentation of a class, which tells # the reader which header file to include in order to use a class. # If left blank only the name of the header file containing the class # definition is used. Otherwise one should specify the include paths that # are normally passed to the compiler using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful is your file systems # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen # will interpret the first line (until the first dot) of a JavaDoc-style # comment as the brief description. If set to NO, the JavaDoc # comments will behave just like regular Qt-style comments # (thus requiring an explicit @brief command for a brief description.) JAVADOC_AUTOBRIEF = NO # If the QT_AUTOBRIEF tag is set to YES then Doxygen will # interpret the first line (until the first dot) of a Qt-style # comment as the brief description. If set to NO, the comments # will behave just like regular Qt-style comments (thus requiring # an explicit \brief command for a brief description.) QT_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen # treat a multi-line C++ special comment block (i.e. a block of //! or /// # comments) as a brief description. This used to be the default behaviour. # The new default is to treat a multi-line C++ comment block as a detailed # description. Set this tag to YES if you prefer the old behaviour instead. MULTILINE_CPP_IS_BRIEF = NO # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented # member inherits the documentation from any documented member that it # re-implements. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce # a new page for each member. If set to NO, the documentation of a member will # be part of the file/class/namespace that contains it. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. TAB_SIZE = 8 # This tag can be used to specify a number of aliases that acts # as commands in the documentation. An alias has the form "name=value". # For example adding "sideeffect=\par Side Effects:\n" will allow you to # put the command \sideeffect (or @sideeffect) in the documentation, which # will result in a user-defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. ALIASES = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C # sources only. Doxygen will then generate output that is more tailored for C. # For instance, some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = NO # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java # sources only. Doxygen will then generate output that is more tailored for # Java. For instance, namespaces will be presented as packages, qualified # scopes will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources only. Doxygen will then generate output that is more tailored for # Fortran. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL # sources. Doxygen will then generate output that is tailored for # VHDL. OPTIMIZE_OUTPUT_VHDL = NO # Doxygen selects the parser to use depending on the extension of the files it # parses. With this tag you can assign which parser to use for a given extension. # Doxygen has a built-in mapping, but you can override or extend it using this # tag. The format is ext=language, where ext is a file extension, and language # is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, # C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make # doxygen treat .inc files as Fortran files (default is PHP), and .f files as C # (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions # you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. EXTENSION_MAPPING = # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should # set this tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); v.s. # func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. BUILTIN_STL_SUPPORT = NO # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. # Doxygen will parse them like normal C++ but will assume all classes use public # instead of private inheritance when no explicit protection keyword is present. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate getter # and setter methods for a property. Setting this option to YES (the default) # will make doxygen to replace the get and set methods by a property in the # documentation. This will only work if the methods are indeed getting or # setting a simple type. If this is not the case, or you want to show the # methods anyway, you should set this option to NO. IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. DISTRIBUTE_GROUP_DOC = NO # Set the SUBGROUPING tag to YES (the default) to allow class member groups of # the same type (for instance a group of public functions) to be put as a # subgroup of that type (e.g. under the Public Functions section). Set it to # NO to prevent subgrouping. Alternatively, this can be done per class using # the \nosubgrouping command. SUBGROUPING = YES # When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum # is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically # be useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. TYPEDEF_HIDES_STRUCT = NO # The SYMBOL_CACHE_SIZE determines the size of the internal cache use to # determine which symbols to keep in memory and which to flush to disk. # When the cache is full, less often used symbols will be written to disk. # For small to medium size projects (<1000 input files) the default value is # probably good enough. For larger projects a too small cache size can cause # doxygen to be busy swapping symbols to and from disk most of the time # causing a significant performance penality. # If the system has enough physical memory increasing the cache will improve the # performance by keeping more symbols in memory. Note that the value works on # a logarithmic scale so increasing the size by one will rougly double the # memory usage. The cache size is given by this formula: # 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, # corresponding to a cache size of 2^16 = 65536 symbols SYMBOL_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. # Private class members and static file members will be hidden unless # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES EXTRACT_ALL = NO # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = NO # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = NO # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. When set to YES local # methods, which are defined in the implementation section but not in # the interface are included in the documentation. # If set to NO (the default) only methods in the interface are included. EXTRACT_LOCAL_METHODS = NO # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base # name of the file that contains the anonymous namespace. By default # anonymous namespace are hidden. EXTRACT_ANON_NSPACES = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members of documented classes, files or namespaces. # If set to NO (the default) these members will be included in the # various overviews, but no documentation section is generated. # This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_MEMBERS = YES # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. # If set to NO (the default) these classes will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = YES # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all # friend (class|struct|union) declarations. # If set to NO (the default) these declarations will be included in the # documentation. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any # documentation blocks found inside the body of a function. # If set to NO (the default) these blocks will be appended to the # function's detailed documentation block. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation # that is typed after a \internal command is included. If the tag is set # to NO (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate # file names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen # will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen # will put a list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = YES # If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen # will list include files with double quotes in the documentation # rather than with sharp brackets. FORCE_LOCAL_INCLUDES = NO # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen # will sort the (detailed) documentation of file and class members # alphabetically by member name. If set to NO the members will appear in # declaration order. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the # brief documentation of file, namespace and class members alphabetically # by member name. If set to NO (the default) the members will appear in # declaration order. SORT_BRIEF_DOCS = NO # If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen # will sort the (brief and detailed) documentation of class members so that # constructors and destructors are listed first. If set to NO (the default) # the constructors will appear in the respective orders defined by # SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. # This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO # and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. SORT_MEMBERS_CTORS_1ST = NO # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the # hierarchy of group names into alphabetical order. If set to NO (the default) # the group names will appear in their defined order. SORT_GROUP_NAMES = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be # sorted by fully-qualified names, including namespaces. If set to # NO (the default), the class list will be sorted only by class name, # not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the # alphabetical list. SORT_BY_SCOPE_NAME = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or # disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or # disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or # disable (NO) the deprecated list. This list is created by putting # \deprecated commands in the documentation. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or define consists of for it to appear in # the documentation. If the initializer consists of more lines than specified # here it will be hidden. Use a value of 0 to hide initializers completely. # The appearance of the initializer of individual variables and defines in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated # at the bottom of the documentation of classes and structs. If set to YES the # list will mention the files that were used to generate the documentation. SHOW_USED_FILES = NO # If the sources in your project are distributed over multiple directories # then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy # in the documentation. The default is NO. SHOW_DIRECTORIES = NO # Set the SHOW_FILES tag to NO to disable the generation of the Files page. # This will remove the Files entry from the Quick Index and from the # Folder Tree View (if specified). The default is YES. SHOW_FILES = YES # Set the SHOW_NAMESPACES tag to NO to disable the generation of the # Namespaces page. # This will remove the Namespaces entry from the Quick Index # and from the Folder Tree View (if specified). The default is YES. SHOW_NAMESPACES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command <command> <input-file>, where <command> is the value of # the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file # provided by doxygen. Whatever the program writes to standard output # is used as the file version. See the manual for examples. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed # by doxygen. The layout file controls the global structure of the generated # output files in an output format independent way. The create the layout file # that represents doxygen's defaults, run doxygen with the -l option. # You can optionally specify a file name after the option, if omitted # DoxygenLayout.xml will be used as the name of the layout file. LAYOUT_FILE = #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings # for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = YES # If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some # parameters in a documented function, or documenting parameters that # don't exist or using markup commands wrongly. WARN_IF_DOC_ERROR = YES # This WARN_NO_PARAMDOC option can be abled to get warnings for # functions that are documented, but have no documentation for their parameters # or return value. If set to NO (the default) doxygen will only warn about # wrong or incomplete parameter documentation, but not about the absence of # documentation. WARN_NO_PARAMDOC = NO # The WARN_FORMAT tag determines the format of the warning messages that # doxygen can produce. The string should contain the $file, $line, and $text # tags, which will be replaced by the file and line number from which the # warning originated and the warning text. Optionally the format may contain # $version, which will be replaced by the version of the file (if it could # be obtained via FILE_VERSION_FILTER) WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning # and error messages should be written. If left blank the output is written # to stderr. WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag can be used to specify the files and/or directories that contain # documented source files. You may enter file names like "myfile.cpp" or # directories like "/usr/src/myproject". Separate the files or directories # with spaces. INPUT = src/ # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is # also the default input encoding. Doxygen uses libiconv (or the iconv built # into libc) for the transcoding. See http://www.gnu.org/software/libiconv for # the list of possible encodings. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx # *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 FILE_PATTERNS = *.cpp \ *.h # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = YES # The EXCLUDE tag can be used to specify files and/or directories that should # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used select whether or not files or # directories that are symbolic links (a Unix filesystem feature) are excluded # from the input. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. Note that the wildcards are matched # against the file with absolute path, so to exclude all test directories # for example use the pattern */test/* EXCLUDE_PATTERNS = # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test EXCLUDE_SYMBOLS = # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see # the \include command). EXAMPLE_PATH = test/ \ ./ # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. EXAMPLE_PATTERNS = * # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude # commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = YES # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command <filter> <input-file>, where <filter> # is the value of the INPUT_FILTER tag, and <input-file> is the name of an # input file. Doxygen will then use the output that the filter program writes # to standard output. # If FILTER_PATTERNS is specified, this tag will be # ignored. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. # Doxygen will compare the file name with each pattern and apply the # filter if there is a match. # The filters are a list of the form: # pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further # info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER # is applied to all files. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will # be generated. Documented entities will be cross-referenced with these sources. # Note: To get rid of all source code in the generated output, make sure also # VERBATIM_HEADERS is set to NO. SOURCE_BROWSER = NO # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code # fragments. Normal C and C++ comments will always remain visible. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = NO # If the REFERENCES_RELATION tag is set to YES # then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = NO # If the REFERENCES_LINK_SOURCE tag is set to YES (the default) # and SOURCE_BROWSER tag is set to YES, then the hyperlinks from # functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will # link to the source code. # Otherwise they will link to the documentation. REFERENCES_LINK_SOURCE = YES # If the USE_HTAGS tag is set to YES then the references to source code # will point to the HTML generated by the htags(1) tool instead of doxygen # built-in source browser. The htags tool is part of GNU's global source # tagging system (see http://www.gnu.org/software/global/global.html). You # will need version 4.8.6 or higher. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen # will generate a verbatim copy of the header file for each class for # which an include is specified. Set to NO to disable this. VERBATIM_HEADERS = NO #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index # of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = YES # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. # The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = Pdf #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for # each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a # standard header. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to # fine-tune the look of the HTML output. If the tag is left blank doxygen # will generate a default style sheet. Note that doxygen will try to copy # the style sheet file to the HTML output directory, so don't put your own # stylesheet in the HTML output directory as well, or it will be erased! HTML_STYLESHEET = # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. # Doxygen will adjust the colors in the stylesheet and background images # according to this color. Hue is specified as an angle on a colorwheel, # see http://en.wikipedia.org/wiki/Hue for more information. # For instance the value 0 represents red, 60 is yellow, 120 is green, # 180 is cyan, 240 is blue, 300 purple, and 360 is red again. # The allowed range is 0 to 359. HTML_COLORSTYLE_HUE = 220 # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of # the colors in the HTML output. For a value of 0 the output will use # grayscales only. A value of 255 will produce the most vivid colors. HTML_COLORSTYLE_SAT = 100 # The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to # the luminance component of the colors in the HTML output. Values below # 100 gradually make the output lighter, whereas values above 100 make # the output darker. The value divided by 100 is the actual gamma applied, # so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, # and 100 does not change the gamma. HTML_COLORSTYLE_GAMMA = 80 # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML # page will contain the date and time when the page was generated. Setting # this to NO can help when comparing the output of multiple runs. HTML_TIMESTAMP = YES # If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, # files or namespaces will be aligned in HTML using tables. If set to # NO a bullet list will be used. HTML_ALIGN_MEMBERS = YES # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. For this to work a browser that supports # JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox # Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). HTML_DYNAMIC_SECTIONS = NO # If the GENERATE_DOCSET tag is set to YES, additional index files # will be generated that can be used as input for Apple's Xcode 3 # integrated development environment, introduced with OSX 10.5 (Leopard). # To create a documentation set, doxygen will generate a Makefile in the # HTML output directory. Running make will produce the docset in that # directory and running "make install" will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find # it at startup. # See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html # for more information. GENERATE_DOCSET = NO # When GENERATE_DOCSET tag is set to YES, this tag determines the name of the # feed. A documentation feed provides an umbrella under which multiple # documentation sets from a single provider (such as a company or product suite) # can be grouped. DOCSET_FEEDNAME = "Doxygen generated docs" # When GENERATE_DOCSET tag is set to YES, this tag specifies a string that # should uniquely identify the documentation set bundle. This should be a # reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen # will append .docset to the name. DOCSET_BUNDLE_ID = org.doxygen.Project # When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify # the documentation publisher. This should be a reverse domain-name style # string, e.g. com.mycompany.MyDocSet.documentation. DOCSET_PUBLISHER_ID = org.doxygen.Publisher # The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. DOCSET_PUBLISHER_NAME = Publisher # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the # Microsoft HTML help workshop to generate a compiled HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can # be used to specify the file name of the resulting .chm file. You # can add a path in front of the file if the result should not be # written to the html output directory. CHM_FILE = # If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can # be used to specify the location (absolute path including file name) of # the HTML help compiler (hhc.exe). If non-empty doxygen will try to run # the HTML help compiler on the generated index.hhp. HHC_LOCATION = # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag # controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING # is used to encode HtmlHelp index (hhk), content (hhc) and project file # content. CHM_INDEX_ENCODING = # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag # controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = NO # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and # QHP_VIRTUAL_FOLDER are set, an additional index file will be generated # that can be used as input for Qt's qhelpgenerator to generate a # Qt Compressed Help (.qch) of the generated HTML documentation. GENERATE_QHP = NO # If the QHG_LOCATION tag is specified, the QCH_FILE tag can # be used to specify the file name of the resulting .qch file. # The path specified is relative to the HTML output folder. QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#namespace QHP_NAMESPACE = org.doxygen.Project # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#virtual-folders QHP_VIRTUAL_FOLDER = doc # If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to # add. For more information please see # http://doc.trolltech.com/qthelpproject.html#custom-filters QHP_CUST_FILTER_NAME = # The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the # custom filter to add. For more information please see # <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters"> # Qt Help Project / Custom Filters</a>. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this # project's # filter section matches. # <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes"> # Qt Help Project / Filter Attributes</a>. QHP_SECT_FILTER_ATTRS = # If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can # be used to specify the location of Qt's qhelpgenerator. # If non-empty doxygen will try to run qhelpgenerator on the generated # .qhp file. QHG_LOCATION = # If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files # will be generated, which together with the HTML files, form an Eclipse help # plugin. To install this plugin and make it available under the help contents # menu in Eclipse, the contents of the directory containing the HTML and XML # files needs to be copied into the plugins directory of eclipse. The name of # the directory within the plugins directory should be the same as # the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before # the help appears. GENERATE_ECLIPSEHELP = NO # A unique identifier for the eclipse help plugin. When installing the plugin # the directory name containing the HTML and XML files should also have # this name. ECLIPSE_DOC_ID = org.doxygen.Project # The DISABLE_INDEX tag can be used to turn on/off the condensed index at # top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. DISABLE_INDEX = NO # This tag can be used to set the number of enum values (range [1..20]) # that doxygen will group on one line in the generated HTML documentation. ENUM_VALUES_PER_LINE = 4 # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. # If the tag value is set to YES, a side panel will be generated # containing a tree-like index structure (just like the one that # is generated for HTML Help). For this to work a browser that supports # JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). # Windows users are probably better off using the HTML help feature. GENERATE_TREEVIEW = NO # By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, # and Class Hierarchy pages using a tree view instead of an ordered list. USE_INLINE_TREES = NO # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 # When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open # links to external symbols imported via tag files in a separate window. EXT_LINKS_IN_WINDOW = NO # Use this tag to change the font size of Latex formulas included # as images in the HTML documentation. The default is 10. Note that # when you change the font size after a successful doxygen run you need # to manually remove any form_*.png images from the HTML output directory # to force them to be regenerated. FORMULA_FONTSIZE = 10 # Use the FORMULA_TRANPARENT tag to determine whether or not the images # generated for formulas are transparent PNGs. Transparent PNGs are # not supported properly for IE 6.0, but are supported on all modern browsers. # Note that when changing this option you need to delete any form_*.png files # in the HTML output before the changes have effect. FORMULA_TRANSPARENT = YES # When the SEARCHENGINE tag is enabled doxygen will generate a search box # for the HTML output. The underlying search engine uses javascript # and DHTML and should work on any modern browser. Note that when using # HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets # (GENERATE_DOCSET) there is already a search function so this one should # typically be disabled. For large projects the javascript based search engine # can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. SEARCHENGINE = NO # When the SERVER_BASED_SEARCH tag is enabled the search engine will be # implemented using a PHP enabled web server instead of at the web client # using Javascript. Doxygen will generate the search PHP script and index # file to put on the web server. The advantage of the server # based approach is that it scales better to large projects and allows # full text search. The disadvances is that it is more difficult to setup # and does not have live searching capabilities. SERVER_BASED_SEARCH = NO #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = YES # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. # Note that when enabling USE_PDFLATEX this option is only used for # generating bitmaps for formulas in the HTML output, but not in the # Makefile that is written to the output directory. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to # generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, a4wide, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = a4 # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = YES # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = YES # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO # If LATEX_HIDE_INDICES is set to YES then doxygen will not # include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = NO # If LATEX_SOURCE_CODE is set to YES then doxygen will include # source code with syntax highlighting in the LaTeX output. # Note that which sources are shown also depends on other settings # such as SOURCE_BROWSER. LATEX_SOURCE_CODE = NO #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output # The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load stylesheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = NO # The MAN_OUTPUT tag is used to specify where the man pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 # If the MAN_LINKS tag is set to YES and Doxygen generates man output, # then it will generate one additional man file for each entity # documented in the real man page(s). These additional files # only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES Doxygen will # generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = NO # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml # The XML_SCHEMA tag can be used to specify an XML schema, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting # and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will # generate an AutoGen Definitions (see autogen.sf.net) file # that captures the structure of the code including all # documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- # If the GENERATE_PERLMOD tag is set to YES Doxygen will # generate a Perl module file that captures the structure of # the code including all documentation. Note that this # feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO # If the PERLMOD_LATEX tag is set to YES Doxygen will generate # the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be # nicely formatted so it can be parsed by a human reader. # This is useful # if you want to understand what is going on. # On the other hand, if this # tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES # The names of the make variables in the generated doxyrules.make file # are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. # This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = NO # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_DEFINED tags. EXPAND_ONLY_PREDEF = NO # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # in the INCLUDE_PATH (see below) will be search if a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # are defined before the preprocessor is started (similar to the -D option of # gcc). The argument of the tag is a list of macros of the form: name # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. To prevent a macro definition from being # undefined via #undef or recursively expanded use the := operator # instead of the = operator. PREDEFINED = # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all function-like macros that are alone # on a line, have an all uppercase name, and do not end with a semicolon. Such # function macros are typically used for boiler-plate code, and will confuse # the parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- # The TAGFILES option can be used to specify one or more tagfiles. # Optionally an initial location of the external documentation # can be added for each tagfile. The format of a tag file without # this location is as follows: # # TAGFILES = file1 file2 ... # Adding location for the tag files is done as follows: # # TAGFILES = file1=loc1 "file2 = loc2" ... # where "loc1" and "loc2" can be relative or absolute paths or # URLs. If a location is present for each tag, the installdox tool # does not have to be run to correct the links. # Note that each tag file must have a unique name # (where the name does NOT include the path) # If a tag file is not located in the directory in which doxygen # is run, you must also specify the path to the tagfile here. TAGFILES = # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. GENERATE_TAGFILE = # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed # in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base # or super classes. Setting the tag to NO turns the diagrams off. Note that # this option is superseded by the HAVE_DOT option below. This is only a # fallback. It is recommended to install and use dot, since it yields more # powerful graphs. CLASS_DIAGRAMS = YES # You can define message sequence charts within doxygen comments using the \msc # command. Doxygen will then run the mscgen tool (see # http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the # documentation. The MSCGEN_PATH tag allows you to specify the directory where # the mscgen tool resides. If left empty the tool is assumed to be found in the # default search path. MSCGEN_PATH = # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = NO # The DOT_NUM_THREADS specifies the number of dot invocations doxygen is # allowed to run in parallel. When set to 0 (the default) doxygen will # base this on the number of processors available in the system. You can set it # explicitly to a value larger than 0 to get control over the balance # between CPU load and processing speed. DOT_NUM_THREADS = 0 # By default doxygen will write a font called FreeSans.ttf to the output # directory and reference it in all dot files that doxygen generates. This # font does not include all possible unicode characters however, so when you need # these (or just want a differently looking font) you can specify the font name # using DOT_FONTNAME. You need need to make sure dot is able to find the font, # which can be done by putting it in a standard location or by setting the # DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory # containing the font. DOT_FONTNAME = FreeSans.ttf # The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. # The default size is 10pt. DOT_FONTSIZE = 10 # By default doxygen will tell dot to use the output directory to look for the # FreeSans.ttf font (which doxygen will put there itself). If you specify a # different font using DOT_FONTNAME you can set the path where dot # can find it using this tag. DOT_FONTPATH = # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # the CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = YES # If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen # will generate a graph for groups, showing the direct groups dependencies GROUP_GRAPHS = YES # If the UML_LOOK tag is set to YES doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = YES # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = NO # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT # tags are set to YES then doxygen will generate a graph for each documented # file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES # If the CALL_GRAPH and HAVE_DOT options are set to YES then # doxygen will generate a call dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable call graphs # for selected functions only using the \callgraph command. CALL_GRAPH = NO # If the CALLER_GRAPH and HAVE_DOT tags are set to YES then # doxygen will generate a caller dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable caller # graphs for selected functions only using the \callergraph command. CALLER_GRAPH = NO # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES # If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES # then doxygen will show the dependencies a directory has on other directories # in a graphical way. The dependency relations are determined by the #include # relations between the files in the directories. DIRECTORY_GRAPH = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are png, jpg, or gif # If left blank png will be used. DOT_IMAGE_FORMAT = png # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found in the path. DOT_PATH = # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). DOTFILE_DIRS = # The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of # nodes that will be shown in the graph. If the number of nodes in a graph # becomes larger than this value, doxygen will truncate the graph, which is # visualized by representing a node as a red box. Note that doxygen if the # number of direct children of the root node in a graph is already larger than # DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note # that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. DOT_GRAPH_MAX_NODES = 50 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the # graphs generated by dot. A depth value of 3 means that only nodes reachable # from the root by following a path via at most 3 edges will be shown. Nodes # that lay further from the root node will be omitted. Note that setting this # option to 1 or 2 may greatly reduce the computation time needed for large # code bases. Also note that the size of a graph can be further restricted by # DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. MAX_DOT_GRAPH_DEPTH = 1000 # Set the DOT_TRANSPARENT tag to YES to generate images with a transparent # background. This is disabled by default, because dot on Windows does not # seem to support this out of the box. Warning: Depending on the platform used, # enabling this option may lead to badly anti-aliased labels on the edges of # a graph (i.e. they become hard to read). DOT_TRANSPARENT = NO # Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output # files in one run (i.e. multiple -o and -T options on the command line). This # makes dot run faster, but since only newer versions of dot (>1.8.10) # support this, this feature is disabled by default. DOT_MULTI_TARGETS = NO # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will # generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/AUTHORS��������������������������������������������������������������������������������0000664�0001750�0001750�00000000476�10674015620�013741� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������PoDoFo library, tools and tests: Dominik Seichter <domseichter@web.de> Leonard Rosenthol <leonardr@pdfsages.com> Craig Ringer <craig@postnewspapers.com.au> PoDoFoImpose: Contributed by Pierre Marchand <pierre@moulindetouvois.com> as `pdfimpose' Qt-to-STL conversion by Craig Ringer <craig@postnewspapers.com.au> ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/debian/��������������������������������������������������������������������������������0000775�0001750�0001750�00000000000�12356565165�014121� 5����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/debian/CMakeLists.txt������������������������������������������������������������������0000664�0001750�0001750�00000000027�11500641065�016640� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� ADD_SUBDIRECTORY(man) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/debian/man/����������������������������������������������������������������������������0000775�0001750�0001750�00000000000�12356565165�014674� 5����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/debian/man/podofocountpages.1����������������������������������������������������������0000664�0001750�0001750�00000002233�11544447143�020326� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.TH "PODOFOCOUNTPAGES" "1" "2010-12-09" "PoDoFo" "podofocountpages" .PP .SH NAME podofocountpages \- count the number of pages in a pdf file .PP .SH SYNOPSIS \fBpodofocountpages\fR [\-s] [\-t] file1.pdf \.\.\. .PP .SH DESCRIPTION .B podofocountpages is one of the command line tools from the PoDoFo library that provide several useful operations to work with PDF files\. It counts the pages in a PDF file\. .PP .SH "OPTIONS" .PP \fB\-s\fR .RS enable the short format, which omits printing of the filename to the output .RE .PP \fB\-t\fR .RS print the total number of pages .PP .SH "SEE ALSO" .BR podofobox (1), .BR podofocolor (1), .BR podofocrop (1), .BR podofoencrypt (1), .BR podofogc (1), .BR podofoimg2pdf (1), .BR podofoimgextract (1), .BR podofoimpose (1), .BR podofoincrementalupdates (1), .BR podofomerge (1), .BR podofopages (1), .BR podofopdfinfo (1), .BR podofotxt2pdf (1), .BR podofotxtextract (1), .BR podofouncompress (1), .BR podofoxmp (1) .PP .SH AUTHOR .PP PoDoFo is written by Dominik Seichter <domseichter@web\.de> and others\. .PP This manual page was written by Oleksandr Moskalenko <malex@debian\.org> for the Debian Project (but may be used by others)\. ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/debian/man/podofocrop.1����������������������������������������������������������������0000664�0001750�0001750�00000001755�11544447143�017131� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.TH "PODOFOCROP" "1" "2010-12-09" "PoDoFo" "podofocrop" .PP .SH NAME podofocrop \- crop all pages .PP .SH SYNOPSIS \fBpodofocrop\fR input\.pdf output\.pdf .PP .SH DESCRIPTION .B podofocrop is one of the command line tools from the PoDoFo library that provide several useful operations to work with PDF files\. It can crop all pages in a PDF file\. It requires ghostscript to be in your PATH\. .PP .SH "SEE ALSO" .BR podofobox (1), .BR podofocolor (1), .BR podofocountpages (1), .BR podofoencrypt (1), .BR podofogc (1), .BR podofoimg2pdf (1), .BR podofoimgextract (1), .BR podofoimpose (1), .BR podofoincrementalupdates (1), .BR podofomerge (1), .BR podofopages (1), .BR podofopdfinfo (1), .BR podofotxt2pdf (1), .BR podofotxtextract (1), .BR podofouncompress (1), .BR podofoxmp (1) .PP .SH AUTHORS .PP PoDoFo is written by Dominik Seichter <domseichter@web\.de> and others\. .PP This manual page was written by Oleksandr Moskalenko <malex@debian\.org> for the Debian Project (but may be used by others)\. �������������������podofo-0.9.3/debian/man/podofoimgextract.1����������������������������������������������������������0000664�0001750�0001750�00000002034�11544447143�020324� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.TH "PODOFOIMGEXTRACT" "1" "2010-12-09" "PoDoFo" "podofoimgextract" .PP .SH NAME podofoimgextract \- Extract all images from a PDF file .PP .SH SYNOPSIS \fBpodofoimgextract\fR [inputfile] [outputdirectory] .PP .SH DESCRIPTION .B podofoimgextract is one of the command line tools from the PoDoFo library that provide several useful operations to work with PDF files\. Itw can extract all images from a PDF file into the specified output directory\. .PP .SH SEE ALSO .BR podofobox (1), .BR podofocolor (1), .BR podofocountpages (1), .BR podofocrop (1), .BR podofoencrypt (1), .BR podofogc (1), .BR podofoimg2pdf (1), .BR podofoincrementalupdates (1), .BR podofoimpose (1), .BR podofomerge (1), .BR podofopages (1), .BR podofopdfinfo (1), .BR podofotxt2pdf (1), .BR podofotxtextract (1), .BR podofouncompress (1), .BR podofoxmp (1) .PP .SH AUTHORS .PP PoDoFo is written by Dominik Seichter <domseichter@web\.de> and others\. .PP This manual page was written by Oleksandr Moskalenko <malex@debian\.org> for the Debian Project (but may be used by others)\. ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/debian/man/podofopdfinfo.1�������������������������������������������������������������0000664�0001750�0001750�00000002604�11544447143�017605� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.TH "PODOFOPDFINFO" "1" "2010-12-09" "PoDoFo" "podofopdfinfo" .PP .SH NAME podofopdfinfo \- provide information about a PDF file .PP .SH SYNOPSIS \fBpodofopdfinfo\fR [DCPON] [inputfile] .PP .SH DESCRIPTION .B podofopdfinfo is one of the command line tools from the PoDoFo library that provide several useful operations to work with PDF files\. It can provide a number of facts about a PDF document according to the formatting instructions. If the instructions are not provided, complete information is shown\. .PP .SH "OPTIONS" .PP \fBD\fR .RS .PP display Document Info\. .RE .PP \fBC\fR .RS .PP display Classic Metadata\. .RE .PP \fBP\fR .RS .PP display Page Info\. .RE .PP \fBO\fR .RS .PP display Outlines\. .RE .PP \fBN\fR .RS .PP display Names\. .RE .PP \fB[inputfile]\fR .RS .PP Input PDF file\. .RE .PP .SH SEE ALSO .BR podofobox (1), .BR podofocolor (1), .BR podofocountpages (1), .BR podofocrop (1), .BR podofoencrypt (1), .BR podofogc (1), .BR podofoimg2pdf (1), .BR podofoimgextract (1), .BR podofoimpose (1), .BR podofoincrementalupdates (1), .BR podofomerge (1), .BR podofopages (1), .BR podofotxt2pdf (1), .BR podofotxtextract (1), .BR podofouncompress (1), .BR podofoxmp (1) .PP .SH AUTHORS .PP PoDoFo is written by Dominik Seichter <domseichter@web\.de> and others\. .PP This manual page was written by Oleksandr Moskalenko <malex@debian\.org> for the Debian Project (but may be used by others)\. ����������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/debian/man/podofobox.1�����������������������������������������������������������������0000664�0001750�0001750�00000003203�11544447143�016744� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.TH "PODOFOCOLOR" "1" "2011-01-06" "PoDoFo" "podofocolor" .PP .SH NAME podofocolor \- modify colors in a PDF file. .PP .SH SYNOPSIS \fBpodofocolor\fR [converter] [inputfile] [outpufile] .PP .SH DESCRIPTION .B podofocolor is one of the command line tools from the PoDoFo library that provide several useful operations to work with colors in PDF files\. It can parse and/or modify all colors or colorspaces in a PDF file\. The modifications can be defined via C++ or a Lua script\. Custom conversions like \fconvert all colors to grayscale\f are included. Please note that only colors of vector objects on pages and in XObjects are affected\. This tool does not transform colos in images at the moment\. .PP .SH CONVERTERS [converter] can be any of .RS dummy - Convert all colors to red\. Just a dummy and test implementation which serves as an example for developers\. grayscale - Convert all colors of vector objects in a PDF to grayscale\. lua - Convert all colors based on a Lua description\. A lua script has to be passed as an additional parameter. .RE .PP .SH "SEE ALSO" .BR podofocolor (1), .BR podofocountpages (1), .BR podofocrop (1), .BR podofoencrypt (1), .BR podofogc (1), .BR podofoimg2pdf (1), .BR podofoimgextract (1), .BR podofoimpose (1), .BR podofomerge (1), .BR podofoincrementalupdates (1), .BR podofopages (1), .BR podofopdfinfo (1), .BR podofotxt2pdf (1), .BR podofotxtextract (1), .BR podofouncompress (1), .BR podofoxmp (1) .PP .SH AUTHOR .PP PoDoFo is written by Dominik Seichter <domseichter@web\.de> and others\. .PP This manual page was written by Dominik Seichter <domseichter@web\.de> for the PoDoFo Project (but may be used by others)\. ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/debian/man/podofogc.1������������������������������������������������������������������0000664�0001750�0001750�00000002055�11544447143�016551� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.TH "PODOFOGC" "1" "2011-03-26" "PoDoFo" "podofogc" .PP .SH NAME podofogc \- Garbage collection in a PDF file\. .PP .SH SYNOPSIS \fBpodofogc \fR [inputfile] [outpufile] .PP .SH DESCRIPTION .B podofogc is one of the command line tools from the PoDoFo library that provide several useful operations to work with PDF files\. It can perform a garbage collection operation on a PDF file. All objects that are not reachable from within the trailer are deleted\. .PP .SH "SEE ALSO" .BR podofobox (1), .BR podofocolor (1), .BR podofocountpages (1), .BR podofocrop (1), .BR podofoencrypt (1), .BR podofoimg2pdf (1), .BR podofoimgextract (1), .BR podofoimpose (1), .BR podofomerge (1), .BR podofoincrementalupdates (1), .BR podofopages (1), .BR podofopdfinfo (1), .BR podofotxt2pdf (1), .BR podofotxtextract (1), .BR podofouncompress (1), .BR podofoxmp (1) .PP .SH AUTHOR .PP PoDoFo is written by Dominik Seichter <domseichter@web\.de> and others\. .PP This manual page was written by Oleksandr Moskalenko <malex@debian\.org> for the Debian Project (but may be used by others)\. �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/debian/man/podofouncompress.1����������������������������������������������������������0000664�0001750�0001750�00000002254�11544447143�020357� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.TH "PODOFOUNCOMPRESS" "1" "2010-12-09" "PoDoFo" "podofouncompress" .PP .SH NAME podofouncompress \- Uncompress PDF files .PP .SH SYNOPSIS \fBpodofouncompress\fR [inputfile] [outputfile] .PP .SH DESCRIPTION .B podofouncompress is one of the command line tools from the PoDoFo library that provide several useful operations to work with PDF files\. It can remove compression from a PDF file\. It is useful for debugging errors in PDF files or analysing their structure\. .PP .SH "OPTIONS" .PP \fB[inputfile]\fR .RS .PP Input PDF file\. .RE .PP \fB[outputfile]\fR .RS .PP Output PDF file\. .RE .PP .SH SEE ALSO .BR podofobox (1), .BR podofocolor (1), .BR podofocountpages (1), .BR podofocrop (1), .BR podofoencrypt (1), .BR podofogc (1), .BR podofoimg2pdf (1), .BR podofoimgextract (1), .BR podofoimpose (1), .BR podofoincrementalupdates (1), .BR podofomerge (1), .BR podofopages (1), .BR podofopdfinfo (1), .BR podofotxt2pdf (1), .BR podofotxtextract (1), .BR podofoxmp (1) .PP .SH AUTHORS .PP PoDoFo is written by Dominik Seichter <domseichter@web\.de> and others\. .PP This manual page was written by Oleksandr Moskalenko <malex@debian\.org> for the Debian Project (but may be used by others)\. ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/debian/man/podofoincrementalupdates.1��������������������������������������������������0000664�0001750�0001750�00000002433�11544447143�022047� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.TH "PODOFOINCREMENTALUPDATES" "1" "2010-12-09" "PoDoFo" "podofoincrementalupdates" .PP .SH NAME podofoincrementalupdates \- Provides information about incremental updates in PDF files .PP .SH SYNOPSIS \fBpodofoincrementalupdates\fR [\-e N out\.pdf] file\.pdf .PP .SH DESCRIPTION .B podofoincrementalupdates is one of the command line tools from the PoDoFo library that provide several useful operations to work with PDF files\. It can print information of incremental updates to file\.pdf\. By default the number of incremental updates will be printed\. .PP .SH "OPTIONS" .PP \fB\-e N\fR .RS Extract the Nth update .RE .PP \fBout\.pdf\fR .RS Output PDF file\. .RE .PP \fBfile\.pdf\fR .RS Input PDF file\. .RE .PP .SH SEE ALSO .BR podofobox (1), .BR podofocolor (1), .BR podofocountpages (1), .BR podofocrop (1), .BR podofoencrypt (1), .BR podofogc (1), .BR podofoimg2pdf (1), .BR podofoimgextract (1), .BR podofoimpose (1), .BR podofomerge (1), .BR podofopages (1), .BR podofopdfinfo (1), .BR podofotxt2pdf (1), .BR podofotxtextract (1), .BR podofouncompress (1), .BR podofoxmp (1) .PP .SH AUTHORS .PP PoDoFo is written by Dominik Seichter <domseichter@web\.de> and others\. .PP This manual page was written by Oleksandr Moskalenko <malex@debian\.org> for the Debian Project (but may be used by others)\. �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/debian/man/CMakeLists.txt��������������������������������������������������������������0000664�0001750�0001750�00000000541�12113724117�017415� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� INSTALL(FILES podofobox.1 podofocolor.1 podofocountpages.1 podofocrop.1 podofogc.1 podofoencrypt.1 podofoimg2pdf.1 podofoimgextract.1 podofoimpose.1 podofoincrementalupdates.1 podofomerge.1 podofopages.1 podofopdfinfo.1 podofotxt2pdf.1 podofotxtextract.1 podofouncompress.1 podofoxmp.1 DESTINATION ${MANDIR}man1 ) ���������������������������������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/debian/man/podofotxt2pdf.1�������������������������������������������������������������0000664�0001750�0001750�00000002465�11544447143�017560� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.TH "PODOFOTXT2PDF" "1" "2010-12-09" "PoDoFo" "podofotxt2pdf" .PP .SH NAME podofotxt2pdf \- convert plain text files into PDF files .PP .SH SYNOPSIS \fBpodofotxt2pdf\fR [\-fontname <name>] [\-utf8] [inputfile] [outputfile] .PP .SH DESCRIPTION .B podofotxt2pdf is one of the command line tools from the PoDoFo library that provide several useful operations to work with PDF files\. It can convert a plain text file into a PDF file. .PP .SH "OPTIONS" .PP \fB\-fontname\fR <name> .RS .PP Use the font <name>\. .RE .PP \fB\-utf8\fR .RS .PP specifies that the input text is UTF8 encoded instead of Windows ANSI encoding\. .RE .PP \fB[inputfile]\fR .RS .PP Input PDF file\. .RE .PP \fB[outputfile]\fR .RS .PP Output PDF file\. .RE .PP .SH SEE ALSO .BR podofobox (1), .BR podofocolor (1), .BR podofocountpages (1), .BR podofocrop (1), .BR podofoencrypt (1), .BR podofogc (1), .BR podofoimg2pdf (1), .BR podofoimgextract (1), .BR podofoimpose (1), .BR podofoincrementalupdates (1), .BR podofomerge (1), .BR podofopages (1), .BR podofopdfinfo (1), .BR podofotxtextract (1), .BR podofouncompress (1), .BR podofoxmp (1) .PP .SH AUTHORS .PP PoDoFo is written by Dominik Seichter <domseichter@web\.de> and others\. .PP This manual page was written by Oleksandr Moskalenko <malex@debian\.org> for the Debian Project (but may be used by others)\. �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/debian/man/podofoimpose.1��������������������������������������������������������������0000664�0001750�0001750�00000002470�11544447143�017455� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.TH "PODOFOIMPOSE" "1" "2010-12-09" "PoDoFo" "podofoimpose" .PP .SH NAME podofoimpose \- A powerful PDF imposition tool .PP .SH SYNOPSIS \fBpodofoimpose\fR Input Output Plan [Interpretor] .PP .SH DESCRIPTION .B podofoimpose is one of the command line tools from the PoDoFo library that provide several useful operations to work with PDF files\. It can do imposition of the final output according to the specified imposition plan. .PP .SH "OPTIONS" .PP \fBInput\fR .RS PDF file or a file which contains a list of PDF file paths\. .RE .PP \fBOutput\fR .RS Resulting PDF file\. .RE .PP \fBPlan\fR .RS Imposition plan file\. .RE .PP \fB[Interpretor]\fR .RS Imposition interpretor\. It can be "native" (default value) or "lua"\. .RE .PP .SH SEE ALSO .BR podofobox (1), .BR podofocolor (1), .BR podofocountpages (1), .BR podofocrop (1), .BR podofoencrypt (1), .BR podofogc (1), .BR podofoimg2pdf (1), .BR podofoimgextract (1), .BR podofomerge (1), .BR podofoincrementalupdates (1), .BR podofopages (1), .BR podofopdfinfo (1), .BR podofotxt2pdf (1), .BR podofotxtextract (1), .BR podofouncompress (1), .BR podofoxmp (1) .PP .SH AUTHORS .PP PoDoFo is written by Dominik Seichter <domseichter@web\.de> and others\. .PP This manual page was written by Oleksandr Moskalenko <malex@debian\.org> for the Debian Project (but may be used by others)\. ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/debian/man/podofocolor.1���������������������������������������������������������������0000664�0001750�0001750�00000003232�11544447143�017274� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.TH "PODOFOCOLOR" "1" "2011-01-06" "PoDoFo" "podofocolor" .PP .SH NAME podofocolor \- modify colors in a PDF file. .PP .SH SYNOPSIS \fBpodofocolor\fR [converter] [inputfile] [outpufile] .PP .SH DESCRIPTION .B podofocolor is one of the command line tools from the PoDoFo library that provide several useful operations to work with colors in PDF files\. It can parse and/or modify all colors or colorspaces in a PDF file\. The modifications can be defined via C++ or a Lua script\. Custom conversions like \fconvert all colors to grayscale\f are included. Please note that only colors of vector objects on pages and in XObjects are affected\. This tool does not transform colos in images at the moment\. .PP .SH CONVERTERS [converter] can be any of .RS dummy - Convert all colors to red\. Just a dummy and test implementation which serves as an example for developers\. .RE .RS grayscale - Convert all colors of vector objects in a PDF to grayscale\. .RE .RS lua [script] - Convert all colors based on a Lua description\. A lua script has to be passed as an additional parameter. .RE .PP .SH "SEE ALSO" .BR podofobox (1), .BR podofocountpages (1), .BR podofocrop (1), .BR podofoencrypt (1), .BR podofogc (1), .BR podofoimg2pdf (1), .BR podofoimgextract (1), .BR podofoimpose (1), .BR podofomerge (1), .BR podofoincrementalupdates (1), .BR podofopages (1), .BR podofopdfinfo (1), .BR podofotxt2pdf (1), .BR podofotxtextract (1), .BR podofouncompress (1), .BR podofoxmp (1) .PP .SH AUTHOR .PP PoDoFo is written by Dominik Seichter <domseichter@web\.de> and others\. .PP This manual page was written by Dominik Seichter <domseichter@web\.de> for the PoDoFo Project (but may be used by others)\. ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/debian/man/podofoimg2pdf.1�������������������������������������������������������������0000664�0001750�0001750�00000002523�11544447143�017510� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.TH "PODOFOIMG2PDF" "1" "2010-12-09" "PoDoFo" "podofoimg2pdf" .PP .SH NAME podofoimg2pdf \- Convert images to PDF files .PP .SH SYNOPSIS \fBpodofoimg2pdf\fR [output\.pdf] [\-useimgsize] [image1 image2 image3 \.\.\.] .PP .SH DESCRIPTION .B podofoimg2pdf is one of the command line tools from the PoDoFo library that provide several useful operations to work with PDF files\. This tool will combine any number of images into a single PDF\. This is useful for creating a document from scanned images\. Large pages will be scaled to fit the page and images smaller than the defined page size will be centered\. .PP Supported image formats: .RS JPEG .br PNG .br TIFF .RE .PP .SH OPTIONS \fB\-useimgsize\fR .RS Use the image size as page size instead of A4 .RE .PP .SH SEE ALSO .BR podofobox (1), .BR podofocolor (1), .BR podofocountpages (1), .BR podofocrop (1), .BR podofoencrypt (1), .BR podofogc (1), .BR podofoimgextract (1), .BR podofoincrementalupdates (1), .BR podofoimpose (1), .BR podofomerge (1), .BR podofopages (1), .BR podofopdfinfo (1), .BR podofotxt2pdf (1), .BR podofotxtextract (1), .BR podofouncompress (1), .BR podofoxmp (1) .PP .SH AUTHORS .PP PoDoFo is written by Dominik Seichter <domseichter@web\.de> and others\. .PP This manual page was written by Oleksandr Moskalenko <malex@debian\.org> for the Debian Project (but may be used by others)\. �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/debian/man/podofotxtextract.1����������������������������������������������������������0000664�0001750�0001750�00000002042�11544447143�020366� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.TH "PODOFOTXTEXTRACT" "1" "2010-12-09" "PoDoFo" "podofotxtextract" .PP .SH NAME podofotxtextract \- Extract all text from a PDF file .PP .SH SYNOPSIS \fBpodofotxtextract\fR [inputfile] .PP .SH DESCRIPTION .B podofotxtextract is one of the command line tools from the PoDoFo library that provide several useful operations to work with PDF files\. It can extract text from a PDF file\. .PP .SH "OPTIONS" .PP \fB[inputfile]\fR .RS .PP Input PDF file\. .RE .PP .SH SEE ALSO .BR podofobox (1), .BR podofocolor (1), .BR podofocountpages (1), .BR podofocrop (1), .BR podofoencrypt (1), .BR podofogc (1), .BR podofoimg2pdf (1), .BR podofoimgextract (1), .BR podofoimpose (1), .BR podofoincrementalupdates (1), .BR podofomerge (1), .BR podofopages (1), .BR podofopdfinfo (1), .BR podofotxt2pdf (1), .BR podofouncompress (1), .BR podofoxmp (1) .PP .SH AUTHORS .PP PoDoFo is written by Dominik Seichter <domseichter@web\.de> and others\. .PP This manual page was written by Oleksandr Moskalenko <malex@debian\.org> for the Debian Project (but may be used by others)\. ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/debian/man/podofoxmp.1�����������������������������������������������������������������0000664�0001750�0001750�00000002573�11544447143�016771� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.TH "PODOFOXMP" "1" "2010-12-09" "PoDoFo" "podofoxmp" .PP .SH NAME podofoxmp \- Modify or extract XMP information from a PDF file .PP .SH SYNOPSIS \fBpodofoxmp\fR [inputfile] [xmpfile outputfile] .PP .SH DESCRIPTION .B podofoxmp is one of the command line tools from the PoDoFo library that provide several useful operations to work with PDF files\. It can extract or modify XMP information in a PDF file\. .PP .SH "OPTIONS" .PP \fB[inputfile]\fR .RS .PP Input PDF file\. This is the only option needed to extract the XMP information from a PDF file\. .RE .PP \fB[xmpfile]\fR .RS .PP Optional file that provides PDF XMP structure\. It must be used in conjuction with an [outputfile]\. .RE .PP \fB[outputfile]\fR .RS .PP Output PDF file\. It is only used in conjuction with an [xmpfile]\. .RE .PP .SH SEE ALSO .BR podofobox (1), .BR podofocolor (1), .BR podofocountpages (1), .BR podofocrop (1), .BR podofoencrypt (1), .BR podofogc (1), .BR podofoimg2pdf (1), .BR podofoimgextract (1), .BR podofoimpose (1), .BR podofoincrementalupdates (1), .BR podofomerge (1), .BR podofopages (1), .BR podofopdfinfo (1), .BR podofotxt2pdf (1), .BR podofotxtextract (1), .BR podofouncompress (1) .PP .SH AUTHORS .PP PoDoFo is written by Dominik Seichter <domseichter@web\.de> and others\. .PP This manual page was written by Oleksandr Moskalenko <malex@debian\.org> for the Debian Project (but may be used by others)\. �������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/debian/man/podofomerge.1���������������������������������������������������������������0000664�0001750�0001750�00000001730�11544447143�017256� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.TH "PODOFOMERGE" "1" "2010-12-09" "PoDoFo" "podofomerge" .PP .SH NAME podofomerge \- merge several PDF files .PP .SH SYNOPSIS \fBpodofomerge\fR [inputfile1] [inputfile2] [outputfile] .PP .SH DESCRIPTION .B podofomerge is one of the command line tools from the PoDoFo library that provide several useful operations to work with PDF files\. It can merge several PDF files\. .PP .SH SEE ALSO .BR podofobox (1), .BR podofocolor (1), .BR podofocountpages (1), .BR podofocrop (1), .BR podofoencrypt (1), .BR podofogc (1), .BR podofoimg2pdf (1), .BR podofoimgextract (1), .BR podofoimpose (1), .BR podofoincrementalupdates (1), .BR podofopages (1), .BR podofopdfinfo (1), .BR podofotxt2pdf (1), .BR podofotxtextract (1), .BR podofouncompress (1), .BR podofoxmp (1) .PP .SH AUTHORS .PP PoDoFo is written by Dominik Seichter <domseichter@web\.de> and others\. .PP This manual page was written by Oleksandr Moskalenko <malex@debian\.org> for the Debian Project (but may be used by others)\. ����������������������������������������podofo-0.9.3/debian/man/podofoencrypt.1�������������������������������������������������������������0000664�0001750�0001750�00000004471�11544447143�017650� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.TH "PODOFOENCRYPT" "1" "2010-12-09" "PoDoFo" "podofoencrypt" .PP .SH NAME podofoencrypt \- encrypt PDF files and set PDF security settings .PP .SH SYNOPSIS \fBpodofoencrypt\fR [\-\-rc4v1] [\-\-rc4v2] [\-\-aes] [\-u <userpassword>] \-o <ownerpassword> <inputfile> <outputfile> .PP .SH DESCRIPTION .B podofoencrypt is one of the command line tools from the PoDoFo library that provide several useful operations to work with PDF files\. It can encrypt PDF files using RC4 or AES encoding and can set PDF security settings\. .PP .SH "OPTIONS" \fB\-\-help\fR .RS Display the help text .RE .PP Algorithm: .PP .RS \fB\-\-rc4v1\fR .RS Use rc4v1 encryption .RE .PP \fB\-\-rc4v2\fR .RS Use rc4v2 encryption (Default value) .RE .PP \fB\-\-aes\fR .RS Use aes encryption (currently not supported) .RE .RE .PP Passwords: .PP .RS \fB\-u <password>\fR .RS An optional user password .RE .PP \fB\-o <password>\fR .RS The required owner password .RE .RE .PP Permissions: .RS .PP \fB\-\-print\fR .RS .PP Allow printing the document .RE .PP \fB\-\-edit\fR .RS .PP Allow modification of the document besides annotations, form fields or changing pages .RE .PP \fB\-\-copy\fR .RS .PP Allow extraction of text and graphics .RE .PP \fB\-\-editnotes\fR .RS .PP Add or modify text annoations or form fields (if ePdfPermissions_Edit is set also allow to create interactive form fields including signature) .RE .PP \fB\-\-fillandsign\fR .RS .PP Fill in existing form or signature fields .RE .PP \fB\-\-accessible\fR .RS .PP Extract text and graphics to support user with disabillities .RE .PP \fB\-\-assemble\fR .RS .PP Assemble the document: insert, create, rotate delete pages or add bookmarks .RE .PP \fB\-\-highprint \fR .RS .PP Print a high resolution version of the document .PP .SH SEE ALSO .BR podofobox (1), .BR podofocolor (1), .BR podofocountpages (1), .BR podofocrop (1), .BR podofogc (1), .BR podofoimg2pdf (1), .BR podofoimgextract (1), .BR podofoincrementalupdates (1), .BR podofoimpose (1), .BR podofomerge (1), .BR podofopages (1), .BR podofopdfinfo (1), .BR podofotxt2pdf (1), .BR podofotxtextract (1), .BR podofouncompress (1), .BR podofoxmp (1) .PP .SH AUTHORS .PP PoDoFo is written by Dominik Seichter <domseichter@web\.de> and others\. .PP This manual page was written by Oleksandr Moskalenko <malex@debian\.org> for the Debian Project (but may be used by others)\. �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/debian/man/podofopages.1���������������������������������������������������������������0000664�0001750�0001750�00000002636�11544447143�017264� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.TH "PODOFOPAGES" "1" "2010-12-09" "PoDoFo" "podofopages" .PP .SH NAME podofopages \- move and delete pages in a PDF document .PP .SH SYNOPSIS \fBpodofopages\fR [\-\-delete] [\-\-move] [inputfile] [outputfile] .PP .SH DESCRIPTION .B podofopages is one of the command line tools from the PoDoFo library that provide several useful operations to work with PDF files\. It can move and delete pages in a PDF document\. .PP .SH "OPTIONS" .PP \fB\-\-delete NUMBER\fR .RS .PP Deletes the page NUMBER (number is 0\-based)\. The page will not really be deleted from the PDF\. It is only removed from the so called pagestree and therefore becomes hidden\. The content of the page can still be retrieved from the document though\. .RE .PP \fB\-\-move FROM TO\fR .RS .PP Moves a page FROM TO in the document (FROM and TO are 0\-based)\. .RE .PP .SH SEE ALSO .BR podofobox (1), .BR podofocolor (1), .BR podofocountpages (1), .BR podofocrop (1), .BR podofoencrypt (1), .BR podofogc (1), .BR podofoimg2pdf (1), .BR podofoimgextract (1), .BR podofoimpose (1), .BR podofoincrementalupdates (1), .BR podofomerge (1), .BR podofopdfinfo (1), .BR podofotxt2pdf (1), .BR podofotxtextract (1), .BR podofouncompress (1), .BR podofoxmp (1) .PP .SH AUTHORS .PP PoDoFo is written by Dominik Seichter <domseichter@web\.de> and others\. .PP This manual page was written by Oleksandr Moskalenko <malex@debian\.org> for the Debian Project (but may be used by others)\. ��������������������������������������������������������������������������������������������������podofo-0.9.3/cmake_uninstall.cmake.in���������������������������������������������������������������0000664�0001750�0001750�00000001444�10653272660�017453� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������IF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") MESSAGE(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"") ENDIF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") FILE(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files) STRING(REGEX REPLACE "\n" ";" files "${files}") FOREACH(file ${files}) MESSAGE(STATUS "Uninstalling \"${file}\"") IF(NOT EXISTS "${file}") MESSAGE(FATAL_ERROR "File \"${file}\" does not exists.") ENDIF(NOT EXISTS "${file}") EXEC_PROGRAM("@CMAKE_COMMAND@" ARGS "-E remove \"${file}\"" OUTPUT_VARIABLE rm_out RETURN_VARIABLE rm_retval) IF("${rm_retval}" GREATER 0) MESSAGE(FATAL_ERROR "Problem when removing \"${file}\"") ENDIF("${rm_retval}" GREATER 0) ENDFOREACH(file)����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/NEWS�����������������������������������������������������������������������������������0000664�0001750�0001750�00000000000�10432364310�013342� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/examples/������������������������������������������������������������������������������0000775�0001750�0001750�00000000000�12356565167�014517� 5����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/examples/helloworld-base14/������������������������������������������������������������0000775�0001750�0001750�00000000000�12356565167�017747� 5����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/examples/helloworld-base14/helloworld-base14.cpp���������������������������������������0000664�0001750�0001750�00000026015�11366377460�023704� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*************************************************************************** * Copyright (C) 2006 by Dominik Seichter * * domseichter@web.de * * * * 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., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ /* * Include the standard headers for cout to write * some output to the console. */ #include <iostream> /* Include appropriate system header for standard integer types */ #ifdef _WIN32 #include <BaseTsd.h> #else #include <stdint.h> #endif /* * Now include all podofo header files, to have access * to all functions of podofo and so that you do not have * to care about the order of includes. * * You should always use podofo.h and not try to include * the required headers on your own. */ #include <podofo.h> /* * All podofo classes are member of the PoDoFo namespace. */ using namespace PoDoFo; void PrintHelp() { std::cout << "This is a example application for the PoDoFo PDF library." << std::endl << "It creates a small PDF file containing the text >Hello World!<" << std::endl << "Please see http://podofo.sf.net for more information" << std::endl << std::endl; std::cout << "Usage:" << std::endl; std::cout << " examplehelloworld [outputfile.pdf]" << std::endl << std::endl; } const char * GetBase14FontName(int i); void DemoBase14Fonts(PdfPainter& painter, PdfPage* pPage, PdfStreamedDocument& document); void HelloWorld( const char* pszFilename ) { /* * PdfStreamedDocument is the class that can actually write a PDF file. * PdfStreamedDocument is much faster than PdfDocument, but it is only * suitable for creating/drawing PDF files and cannot modify existing * PDF documents. * * The document is written directly to pszFilename while being created. */ PdfStreamedDocument document( pszFilename ); /* * PdfPainter is the class which is able to draw text and graphics * directly on a PdfPage object. */ PdfPainter painter; /* * This pointer will hold the page object later. * PdfSimpleWriter can write several PdfPage's to a PDF file. */ PdfPage* pPage; /* * A PdfFont object is required to draw text on a PdfPage using a PdfPainter. * PoDoFo will find the font using fontconfig on your system and embedd truetype * fonts automatically in the PDF file. */ PdfFont* pFont; try { /* * The PdfDocument object can be used to create new PdfPage objects. * The PdfPage object is owned by the PdfDocument will also be deleted automatically * by the PdfDocument object. * * You have to pass only one argument, i.e. the page size of the page to create. * There are predefined enums for some common page sizes. */ pPage = document.CreatePage( PdfPage::CreateStandardPageSize( ePdfPageSize_A4 ) ); /* * If the page cannot be created because of an error (e.g. ePdfError_OutOfMemory ) * a NULL pointer is returned. * We check for a NULL pointer here and throw an exception using the RAISE_ERROR macro. * The raise error macro initializes a PdfError object with a given error code and * the location in the file in which the error ocurred and throws it as an exception. */ if( !pPage ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } /* * Set the page as drawing target for the PdfPainter. * Before the painter can draw, a page has to be set first. */ painter.SetPage( pPage ); /* * Create a PdfFont object using the font "Arial". * The font is found on the system using fontconfig and embedded into the * PDF file. If Arial is not available, a default font will be used. * * The created PdfFont will be deleted by the PdfDocument. */ pFont = document.CreateFont( "Helvetica" ); /* * If the PdfFont object cannot be allocated return an error. */ if( !pFont ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } /* * Set the font size */ pFont->SetFontSize( 18.0 ); /* * Set the font as default font for drawing. * A font has to be set before you can draw text on * a PdfPainter. */ painter.SetFont( pFont ); /* * You could set a different color than black to draw * the text. * * SAFE_OP( painter.SetColor( 1.0, 0.0, 0.0 ) ); */ /* * Actually draw the line "Hello World!" on to the PdfPage at * the position 2cm,2cm from the top left corner. * Please remember that PDF files have their origin at the * bottom left corner. Therefore we substract the y coordinate * from the page height. * * The position specifies the start of the baseline of the text. * * All coordinates in PoDoFo are in PDF units. * You can also use PdfPainterMM which takes coordinates in 1/1000th mm. * */ painter.DrawText( 56.69, pPage->GetPageSize().GetHeight() - 56.69, "Hello World!" ); DemoBase14Fonts(painter, pPage, document); painter.FinishPage(); /* * The last step is to close the document. */ document.Close(); } catch ( const PdfError & e ) { /* * All PoDoFo methods may throw exceptions * make sure that painter.FinishPage() is called * or who will get an assert in its destructor */ try { painter.FinishPage(); } catch( ... ) { /* * Ignore errors this time */ } throw e; } } int main( int argc, char* argv[] ) { /* * Check if a filename was passed as commandline argument. * If more than 1 argument or no argument is passed, * a help message is displayed and the example application * will quit. */ if( argc != 2 ) { PrintHelp(); return -1; } /* * All podofo functions will throw an exception in case of an error. * * You should catch the exception to either fix it or report * back to the user. * * All exceptions podofo throws are objects of the class PdfError. * Thats why we simply catch PdfError objects. */ try { /* * Call the drawing routing which will create a PDF file * with the filename of the output file as argument. */ HelloWorld( argv[1] ); } catch( const PdfError & eCode ) { /* * We have to check if an error has occurred. * If yes, we return and print an error message * to the commandline. */ eCode.PrintErrorMsg(); return eCode.GetError(); } /* * The PDF was created sucessfully. */ std::cout << std::endl << "Created a PDF file containing the line \"Hello World!\": " << argv[1] << std::endl << std::endl; return 0; } // Base14 + other non-Base14 fonts for comparison #define NUM_BASE14_FONTS 17 const char * GetBase14FontName(int i) { const char *base14fonts[NUM_BASE14_FONTS] = { "Courier", "Courier-Bold", "Courier-Oblique", "Courier-BoldOblique", "Helvetica", "Helvetica-Bold", "Helvetica-Oblique", "Helvetica-BoldOblique", "Times-Roman", "Times-Bold", "Times-Italic", "Times-BoldItalic", "Symbol", "ZapfDingbats", "Arial", "Times New Roman", "Verdana" }; if (i >= 0 && i < NUM_BASE14_FONTS) return base14fonts[i]; else return NULL; } void DrawRedFrame(PdfPainter& painter, double x, double y, double width, double height) { // draw red box painter.SetColor(1.0f, 0.0f, 0.0f); painter.SetStrokingColor(1.0f, 0.0f, 0.0f); painter.DrawLine(x, y, x+width, y); if ( height > 0.0f ) { painter.DrawLine(x, y, x, y+height); painter.DrawLine(x+width, y, x+width, y+height); painter.DrawLine(x, y+height, x+width, y+height); } // restore to black painter.SetColor(0.0f, 0.0f, 0.0f); painter.SetStrokingColor(0.0f, 0.0f, 0.0f); } void DemoBase14Fonts(PdfPainter& painter, PdfPage* pPage, PdfStreamedDocument& document) { double x = 56,y = pPage->GetPageSize().GetHeight() - 56.69; char text[255]; const char *demo_text = "abcdefgABCDEFG12345!#$%&+-@? "; double height=0.0f, width=0.0f; int i; // draw sample of all types for(i = 0; i < NUM_BASE14_FONTS; ++i) { x = 56; y = y - 25; strcpy(text, demo_text); strcat(text, GetBase14FontName(i)); PdfFont *pFont = document.CreateFont( GetBase14FontName(i) ); pFont->SetFontSize( 12.0 ); painter.SetFont( pFont ); width = pFont->GetFontMetrics()->StringWidth(text); height = pFont->GetFontMetrics()->GetLineSpacing(); std::cout << GetBase14FontName(i) << " Width = " << width << " Height = " << height << std::endl; // draw red box DrawRedFrame( painter, x, y, width, height); // draw text painter.DrawText( x, y , text); } // draw some individual characters: const char *demo_text2 = " @_1jiPlg .;"; int nChars = strlen(demo_text2); // draw individuals for(i = 0; i < nChars; i++) { x = 56; y = y - 25; if ( i==0 ) { strcpy(text, "Helvetica / Arial Comparison:"); } else { text[0] = demo_text2[i]; text[1] = '\0'; } PdfFont *pFont = document.CreateFont("Helvetica"); painter.SetFont( pFont ); height = pFont->GetFontMetrics()->GetLineSpacing(); width = pFont->GetFontMetrics()->StringWidth(text); // draw red box DrawRedFrame( painter, x, y, width, height); // draw text painter.DrawText( x, y , text); if ( i>0 ) { // draw again, with non-Base14 font PdfFont *pFont2 = document.CreateFont("Arial"); painter.SetFont( pFont2 ); height = pFont2->GetFontMetrics()->GetLineSpacing(); width = pFont2->GetFontMetrics()->StringWidth(text); // draw red box DrawRedFrame( painter, x+100, y, width, height); // draw text painter.DrawText( x+100, y , text); } } } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/examples/helloworld-base14/CMakeLists.txt����������������������������������������������0000664�0001750�0001750�00000001331�11366377460�022502� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This is not a full standalone CMake configuration for the hello world # example. # # To build it outside the PoDoFo source tree, you must set your build system # make the PoDoFo headers available and must link to the PoDoFo library # and any libraries it depends on (see the README, # "5. Using PoDoFo in Your Application") . # # Note that you don't need the headers for PoDoFo's dependencies in your # header search path. ADD_EXECUTABLE(helloworld-base14 helloworld-base14.cpp) TARGET_LINK_LIBRARIES(helloworld-base14 ${PODOFO_LIB}) SET_TARGET_PROPERTIES(helloworld-base14 PROPERTIES COMPILE_FLAGS "${PODOFO_CFLAGS}") ADD_DEPENDENCIES(helloworld-base14 ${PODOFO_DEPEND_TARGET}) INCLUDE_DIRECTORIES(${PoDoFo_SOURCE_DIR}) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/examples/pdfcontentsgraph/�������������������������������������������������������������0000775�0001750�0001750�00000000000�12356565167�020070� 5����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/examples/pdfcontentsgraph/PdfContentsGraph.h�������������������������������������������0000664�0001750�0001750�00000024334�11541741676�023454� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#ifndef _PODOFO_PDFCONTENTSGRAPH_H #define _PODOFO_PDFCONTENTSGRAPH_H #include "podofo/podofo.h" #if defined(PODOFO_HAVE_BOOST) #include <utility> #include <string> #include <boost/graph/graph_traits.hpp> #include <boost/graph/adjacency_list.hpp> #include <boost/variant.hpp> namespace PoDoFo { class PdfInputStream; class PdfOutputStream; class PdfContentsTokenizer; enum PdfContentStreamKeyword { // Special node for undefined/unset value. Should never get used except when default-constructing // a node variant. KW_Undefined = 0, // Normal PDF operators KW_q, KW_Q, KW_ST, KW_ET, KW_BMC, KW_BDC, KW_EMC, KW_m, KW_l, // Special node with no associated keyword, used to identify the root node that anchors // the graph. KW_RootNode = 0xfe, // Value returned by findKwByName(...) when no enum for the keyword is known. KW_Unknown = 0xff }; /** * PdfContentsGraph provides a concrete representation of a content stream as an * in-memory graph. It can be created as a blank structure to be populated by hand, * or from an existing content stream via PdfContentsTokenizer . It can serialize * its state as a PDF content stream. * * This class does not track the resources used by the content stream. \see PdfCanvas . * * This class is only available when the Boost library, specifically the boost graph * library, has been configured for use. */ class PdfContentsGraph { public: /** * The KWType enumeration is used to identify whether a given keyword * should be expected to open or close a new scope (think q/Q pairs) or * whether it's just a plain unscoped operator. */ enum KWType { KT_Undefined = 0, /**< Only used for sentinel */ KT_Standalone, /**< Keyword doesn't open or close a scope. */ KT_Opening, /**< Keyword opens a new scope. */ KT_Closing /**< Keyword closes an open scope. */ }; /** * KWInfo describes a single PDF keyword's characteristics. See kwInfo[] . */ struct KWInfo { /// Keyword type ( ends scope, begins scope, or scope neutral ) KWType kt; /// Keyword ID (enum) PdfContentStreamKeyword kw; /// ID enum of context closing keyword (only to be set if this /// is a context opening keyword), eg KW_Q if kw = KW_q . PdfContentStreamKeyword kwClose; /// null-terminated keyword text const char kwText[6]; /// Short description text (optional, set to NULL if undesired). const char * kwDesc; }; // KWInstance stores a keyword and any associated arguments. The keyword // may be stored as an enumerated ID (if it's known to PoDoFo) or a string // (if it's not). class KWInstance { typedef boost::variant<PdfContentStreamKeyword,std::string> KWVariant; typedef std::vector<PoDoFo::PdfVariant> KWArgs; KWVariant m_keyword; KWArgs m_args; public: /** Construct a default(KW_Undefined) KWInstance */ KWInstance() : m_keyword(KW_Undefined) { } /** Construct a KWInstance from an enum id. \see SetKw */ KWInstance(PdfContentStreamKeyword kw) : m_keyword(kw) { if (kw == KW_Undefined) PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidEnumValue, "Cannot explicitly init KWInstance to KW_Undefined"); } /** Construct a KWInstance from a string. \see SetKw */ KWInstance(const std::string& kwStr) { SetKw(kwStr); } /** True iff this instance is defined. */ bool IsDefined() const { return GetKwId() != KW_Undefined; } /** True iff this is a root node object. */ bool IsRootNode() const { return GetKwId() == KW_RootNode; } /** Return a string representation of the keyword (as it will appear in a content stream). */ std::string GetKwString() const; /** Returns KW_Unknown if we're a string-based KWInstance for an unknown keyword */ PdfContentStreamKeyword GetKwId() const; /** * Returns a reference to the KWInfo structure for this keyword, or the * special kwInfoUnknown structure (kw=KW_Unknown, * kwType=KT_Standalone) if the keyword is not known. If !IsDefined(), * returns a record with kw=KW_Undefined and kwType=KT_Undefined . * * \see findKwById \see findKwByName */ const KWInfo& GetKwInfo() const { return findKwById(GetKwId()); } /** return a reference to the argument array of this keyword */ KWArgs & GetArgs() { return m_args; } /** Return a reference to the argument array of this keyword. */ const KWArgs & GetArgs() const { return m_args; } /** * Set this keyword to the string `str'. If `str' is recognised by PoDoFo, * it'll be converted to a keyword enum. */ inline void SetKw(const std::string& kwStr); /** Set this keyword to the enum value kw */ void SetKw(PdfContentStreamKeyword kw) { m_keyword = kw; } /** Print this keyword and its arguments to the passed stream in proper content stream format. * If the node is of type KW_Undefined this is a no-op, so it's always safe to call on both sides * of a NodeData pair. * An optional whitespace string `szSepStr' may be provided to override the newline that's * normally written after each argument and keyword. The provided length must NOT include the * trailing NULL (if any); */ void PrintToStream(PdfOutputStream& os, const char * szSepStr = " ", long lSepLen = 1L ) const; }; // Each node actually has two values. Internal nodes have both defined, with the first being the // keyword opening the context and the second being the keyword closing the context. Leaf nodes // have only the first defined (the keyword and its arguments) with the second being undefined. typedef std::pair<KWInstance,KWInstance> NodeData; typedef boost::adjacency_list<boost::listS,boost::vecS,boost::directedS,NodeData> Graph; typedef boost::graph_traits<Graph>::vertex_descriptor Vertex; /** * Construct a new, blank PdfContentsGraph */ PdfContentsGraph(); /** * Construct a PdfContentsGraph from a PdfContentsTokenizer's output. */ PdfContentsGraph(PdfContentsTokenizer & contentsTokenizer); /** * Destroy the PdfContentsGraph. */ ~PdfContentsGraph() { } /** * Serialize the PdfContentsGraph to the passed output stream. * The output format is valid PDF content stream data. */ void Write(PdfOutputStream& outStream); /** * For quick and easy debugging, serialize the graph to stderr as * a PDF content stream. */ void WriteToStdErr(); /** * Look up a keyword string and return a reference to the associated * keyword info struct If the keyword string is not known, return * a reference to the special kwInfoUnknown structure that sets: * * kwType = PdfContentsGraph::KT_Standalone * kw = KW_Unknown * * (The rest of the members should not be relied upon). */ static const KWInfo& findKwByName(const std::string & kwText); /** * Look up an operator code and return the associated keyword string. All * defined enums MUST exist in kwIdMap . */ static const KWInfo& findKwById(PdfContentStreamKeyword kw); /** * Provide access to the internal graph used by ContentStreamGraph to * represent the content stream. The caller may safely modify this graph * so long as: * * - No cyclic references are created, ie it remains a simple tree * - The root node is not altered/removed/replaced * - All internal nodes (ie nodes with children) have variant type * KWPair, where the first value in the pair is the PdfContentStreamKeyword * for a valid context opening keyword, and the second in the pair is the * corresponding closing keyword. * - Nodes of variant type PdfContentStreamKeyword must not contain a context * opening or closing keyword. * * You can use the findKwById and findKwByName functions to determine the attributes * of a keyword - for example, whether it's a context opening / closing keyword. * * For many complex operations on PDF content streams you will want to modify this * graph directly or use it as input for one of the Boost Graph Library algorithms * in combination with a custom visitor. To see how this works, have a look at the * implementation of this class's Write(...) method. Another example can be found in * test/ContentsParser. * * \see findKwById \see findKwByName */ PODOFO_NOTHROW Graph & GetGraph() { return m_graph; } /** * Provide access to a read only view of the internal graph. * * \see GetGraph() */ PODOFO_NOTHROW const Graph & GetGraph() const { return m_graph; } /** * Return a string-formatted version of the passed KWInstance. */ static std::string formatVariant( const KWInstance& var ); /** * Make a KWNode from a pair of possible keyword values (each of which may * be a type convertable to std::string or a PdfContentStreamKeyword) */ template<typename T1, typename T2> std::pair<KWInstance,KWInstance> MakeNode( const T1 & kw1, const T2 & kw2 ) { return std::pair<KWInstance,KWInstance>(kw1,kw2); } /** * Make a KWNode from a possible keyword value ( a type convertable to * std::string or a PdfContentStreamKeyword ), with the second part of * the node being KW_Undefined. */ template<typename T1> std::pair<KWInstance,KWInstance> MakeNode( const T1 & kw ) { return std::pair<KWInstance,KWInstance>(kw,KWInstance()); } private: // private member variables Graph m_graph; }; /** * Set this keyword to the string `str'. If `str' is recognised by PoDoFo, * it'll be converted to a keyword enum. */ inline void PdfContentsGraph::KWInstance::SetKw(const std::string& kwStr) { const KWInfo& kwInfo = findKwByName(kwStr); if (kwInfo.kw == KW_Unknown) m_keyword = kwStr; else m_keyword = kwInfo.kw; } } // namespace PoDoFo #endif // defined(PODOFO_HAVE_BOOST) #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/examples/pdfcontentsgraph/README.txt���������������������������������������������������0000664�0001750�0001750�00000002026�11032100623�021532� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������PdfContentsGraph is a demo that uses the Boost::Graph library to construct a graph of the PDF contents stream(s) that can then be operated on with the usual BGL facilities for graph walking and modification. At present the graph code is incomplete; it makes some assumptions about the structure of PDF content streams that the standard does not require to be true, so it may fail to parse some content streams. The test code in main.cpp parses the stream into a graph. It then walks the graph, using PdfContentsTokenizer to read through the original stream and compare each reached node in the graph to the matching token in the stream. If the graph reflects the content stream and is being walked correctly then the sequence of nodes walked in the graph should match the sequence of tokens read from the stream by PdfContentsTokenizer. This isn't exactly an exciting application. It should be possible to build more useful applications, like a PDF contents stream validator, from the same base. -- Craig Ringer <craig@postnewspapers.com.au> ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/examples/pdfcontentsgraph/CMakeLists.txt�����������������������������������������������0000664�0001750�0001750�00000000457�11235544613�022622� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������ADD_EXECUTABLE(pdfcontentsgraph PdfContentsGraph.cpp main.cpp) TARGET_LINK_LIBRARIES(pdfcontentsgraph ${PODOFO_LIB}) SET_TARGET_PROPERTIES(pdfcontentsgraph PROPERTIES COMPILE_FLAGS "${PODOFO_CFLAGS}") ADD_DEPENDENCIES(pdfcontentsgraph ${PODOFO_DEPEND_TARGET}) INCLUDE_DIRECTORIES(${PoDoFo_SOURCE_DIR}) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/examples/pdfcontentsgraph/PdfContentsGraph.cpp�����������������������������������������0000664�0001750�0001750�00000044161�11541741676�024007� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include "PdfContentsGraph.h" #if !defined(PODOFO_HAVE_BOOST) #error This module requires boost::graph #endif #include <cassert> #include <string> #include <iostream> #include <map> #include <stack> #include <list> #include <sstream> #include <boost/graph/depth_first_search.hpp> using namespace std; using namespace boost; using namespace PoDoFo; // Enable some more verbose debugging output #if !defined(DEBUG_CONTENTS_GRAPH) //#define DEBUG_CONTENTS_GRAPH #endif namespace { // // This static structure describes the content stream keywords PoDoFo knows // about. Anything unrecognised will be assumed to be standalone keyword that // doesn't open or close a scope. // // See PDF Reference, table, 4.1, "Operator categories". // static const PdfContentsGraph::KWInfo kwInfo[] = { { PdfContentsGraph::KT_Standalone, KW_m, KW_Undefined, "m", "MoveTo" }, { PdfContentsGraph::KT_Standalone, KW_l, KW_Undefined, "l", "LineTo" }, { PdfContentsGraph::KT_Opening, KW_q, KW_Q, "q", "Save State" }, { PdfContentsGraph::KT_Closing, KW_Q, KW_Undefined, "Q", "Restore State" }, { PdfContentsGraph::KT_Opening, KW_ST, KW_ET, "BT", "Begin Text" }, { PdfContentsGraph::KT_Closing, KW_ET, KW_Undefined, "ET", "End Text" }, { PdfContentsGraph::KT_Opening, KW_BDC, KW_EMC, "BDC", "Begin marked content" }, { PdfContentsGraph::KT_Opening, KW_BMC, KW_EMC, "BMC", "Begin marked content with property list" }, { PdfContentsGraph::KT_Closing, KW_EMC, KW_Undefined, "EMC", "End marked content" }, // Sentinel { PdfContentsGraph::KT_Undefined, KW_Undefined, KW_Undefined, "\0", NULL } }; // // This value is returned when an unknown keyword is encountered. // static const PdfContentsGraph::KWInfo kwInfoUnknown = { PdfContentsGraph::KT_Standalone, KW_Unknown, KW_Undefined, "\0", NULL }; // This function populates kwNameMap at startup, permitting use to look up // KWInfo structures by keyword string value. map<string,const PdfContentsGraph::KWInfo*> generateKWNameMap() { map<string,const PdfContentsGraph::KWInfo*> m; const PdfContentsGraph::KWInfo* ki = &(kwInfo[0]); do { m.insert( pair<string,const PdfContentsGraph::KWInfo*>(ki->kwText,ki) ); ki ++; } while ( ki->kt != PdfContentsGraph::KT_Undefined ); return m; } // This function populates kwIdMap at startup, permitting use to look up KWInfo // structures by keyword enum value. map<PdfContentStreamKeyword,const PdfContentsGraph::KWInfo*> generateKWIdMap() { map<PdfContentStreamKeyword,const PdfContentsGraph::KWInfo*> m; const PdfContentsGraph::KWInfo* ki = &(kwInfo[0]); do { m.insert( pair<PdfContentStreamKeyword,const PdfContentsGraph::KWInfo*>(ki->kw,ki) ); ki ++; } while ( ki->kt != PdfContentsGraph::KT_Undefined ); return m; } // Mapping table from keyword string value to KWInfo static const map<string,const PdfContentsGraph::KWInfo*> kwNameMap = generateKWNameMap(); // Mapping table from keyword enum value to KWInfo static const map<PdfContentStreamKeyword,const PdfContentsGraph::KWInfo*> kwIdMap = generateKWIdMap(); // Visitor used by KWInstance to convert any stored variant to a string. // kw == KW_Unknown indicates that it should be a no-op, ie return "" struct KWIVariantAsStringVisitor : public static_visitor<string> { string operator()(const std::string& s) const { return s; } string operator()(PdfContentStreamKeyword kw) const { if (kw == KW_Undefined) // Variant has no value return string(); PODOFO_RAISE_LOGIC_IF(kw == KW_Unknown, "Variant in invalid state(may not contain KW_Unknown)"); return PdfContentsGraph::findKwById(kw).kwText; } }; // Visitor used by KWInstance to convert any stored variant to a PdfContentStreamKeyword . // If the variant contains a string that's not a keyword known to podofo, returns KW_Unknown. struct KWIVariantAsIdVisitor : public static_visitor<PdfContentStreamKeyword> { PdfContentStreamKeyword operator()(PdfContentStreamKeyword kw) const { return kw; } PdfContentStreamKeyword operator()(const std::string& s) const { return PdfContentsGraph::findKwByName(s).kw; } }; // boost graph depth_first_search visitor that prints each node's keyword and // arguments to the provided stream in proper content stream format. // // The `arriving' param is set to true if the // variant visitor this graph visitor invokes is being called on node discovery // (in which case EV must be boost::on_discover_vertex) // and false if it's being called on node exit // (in which case EV must be boost::on_finish_vertex ). template<typename EV, bool Arriving> class PrintVertexVisitor { PdfOutputStream * m_os; public: PrintVertexVisitor(PdfOutputStream* os) : m_os(os) { } typedef EV event_filter; void operator()(const PdfContentsGraph::Vertex & v, const PdfContentsGraph::Graph & g) { const PdfContentsGraph::KWInstance& i ( Arriving ? g[v].first : g[v].second ); if (!i.IsRootNode()) i.PrintToStream( *m_os ); } }; // This routine is useful in debugging and error reporting. It formats // the values associated with the passed stack of vertices into a // space-separated string, eg "BT g g g" string formatReversedStack( const PdfContentsGraph::Graph & g, stack<PdfContentsGraph::Vertex> s, ostream& os) { vector<PdfContentsGraph::Vertex> l; while ( s.size() > 1 ) { l.push_back(s.top()); s.pop(); } while ( l.size() ) { os << g[l.back()].first.GetKwString() << ' '; l.pop_back(); } return string(); } #if defined(DEBUG_CONTENTS_GRAPH) // // This debuging routine prints the current context stack to stderr. // void PrintStack( const PdfContentsGraph::Graph & g, const stack<PdfContentsGraph::Vertex> & s, const string & prefix) { PdfOutputDevice outDev( &cerr ); PdfDeviceOutputStream outStream( &outDev ); ostringstream ss; ss << prefix << ' ' << (s.size() - 1) << ' '; formatReversedStack(g,s,ss); ss << '\n'; string out = ss.str(); outStream.Write( out.data(), out.size() ); } #else // Do nothing ; this will inline away nicely and avoids the need for debug // ifdefs or ugly macros. inline void PrintStack( const PdfContentsGraph::Graph &, const stack<PdfContentsGraph::Vertex> &, const string &) { } #endif // // Format an error message reporting an open/close operator mismatch error. // std::string formatMismatchError( const PdfContentsGraph::Graph & g, const stack<PdfContentsGraph::Vertex> & s, int tokenNumber, PdfContentStreamKeyword gotKW, PdfContentStreamKeyword expectedKW) { // Didn't find matching opening operator at top of stack. ostringstream err; err << "Found mismatching opening/closing operators at token number " << tokenNumber << ". Got: " << PdfContentsGraph::findKwById(gotKW).kwText << ", expected " << PdfContentsGraph::findKwById(expectedKW).kwText << ". Context stack was: "; formatReversedStack(g,s,err); err << '.'; return err.str(); } // Read ahead to try to find an ordering of close operators that satisfies // the requirements of the standard. bool closeFixup( PdfContentsGraph::Graph & g, stack<PdfContentsGraph::Vertex> & s, PdfContentsTokenizer & contentsTokenizer, const PdfContentsGraph::KWInfo& badKw ) { // For now we only look ahead one operator, since that's good enough // to let use read the PDF references etc. EPdfContentsType t; const char * kwText; PdfVariant var; bool readToken; // Save a copy of the stack so we can put it back how it was if // our readahead fixup fails. stack<PdfContentsGraph::Vertex> s_copy ( s ); // Next item must be a close keyword if ( ( readToken = contentsTokenizer.ReadNext(t, kwText, var) ) ) { if ( t == ePdfContentsType_Keyword ) { const PdfContentsGraph::KWInfo & ki ( PdfContentsGraph::findKwByName(kwText) ); if ( ki.kt == PdfContentsGraph::KT_Closing ) { // We know that the waiting close keyword, badKw, // doesn't match the open keyword on the top of the stack. // If the one we just read does, and badKw matches the // context open outside that, we're OK. PdfContentsGraph::NodeData & n1 ( g[s.top()] ); if ( ki.kw == n1.first.GetKwInfo().kwClose ) { // The keyword we just read was the right one to // close the top context. n1.second.SetKw( ki.kw ); s.pop(); // Leaving us with the newly exposed outer context // node and the old keyword. See if it matches. PdfContentsGraph::NodeData & n2 ( g[s.top()] ); if ( badKw.kw == n2.first.GetKwInfo().kwClose ) { // The old keyword matches the newly exposed // node's close keyword, so everything's OK. n2.second.SetKw( badKw.kw ); s.pop(); // Fixup succeeded return true; } // Whoops, failed. Restore the copied stack // so error reports don't show the effects of the // lookahead. s = s_copy; } } } } // Fixup attempt failed return false; } } // end anon namespace namespace PoDoFo { const PdfContentsGraph::KWInfo& PdfContentsGraph::findKwByName(const string & kwText) { static const map<string,const KWInfo*>::const_iterator itEnd = kwNameMap.end(); map<string,const KWInfo*>::const_iterator it = kwNameMap.find(kwText); if (it == itEnd) return kwInfoUnknown; else return *((*it).second); } const PdfContentsGraph::KWInfo& PdfContentsGraph::findKwById(PdfContentStreamKeyword kw) { if ( kw == KW_RootNode ) { PODOFO_RAISE_ERROR_INFO(ePdfError_InvalidEnumValue, "Cannot get KWInfo for root node"); } static const map<PdfContentStreamKeyword,const KWInfo*>::const_iterator itEnd = kwIdMap.end(); map<PdfContentStreamKeyword,const KWInfo*>::const_iterator it = kwIdMap.find(kw); if ( it == itEnd) { PODOFO_RAISE_ERROR_INFO(ePdfError_InvalidEnumValue, "Bad keyword ID"); } return *((*it).second); } PdfContentsGraph::PdfContentsGraph() : m_graph() { // Init the root node, leaving an otherwise empty graph. Vertex v = add_vertex(m_graph); m_graph[v] = MakeNode(KW_RootNode,KW_RootNode); } PdfContentsGraph::PdfContentsGraph( PdfContentsTokenizer & contentsTokenizer ) : m_graph() { EPdfContentsType t; const char * kwText; PdfVariant var; bool readToken; // Keep a count of the number of tokens read so we can report errors // more usefully. int tokenNumber = 0; // Set up the node stack and initialize the root node stack<Vertex> parentage; parentage.push( add_vertex(m_graph) ); m_graph[parentage.top()] = MakeNode(KW_RootNode,KW_RootNode); // Arguments to be associated with the next keyword found vector<PdfVariant> args; while ( ( readToken = contentsTokenizer.ReadNext(t, kwText, var) ) ) { ++tokenNumber; if (t == ePdfContentsType_Variant) { // arguments come before operators, but we want to group them up before // their operator. args.push_back(var); } else if (t == ePdfContentsType_Keyword) { const KWInfo & ki ( findKwByName(kwText) ); if (ki.kt != KT_Closing) { // We're going to need a new vertex, so make sure we have one ready. Vertex v = add_vertex( m_graph ); // Switch any waiting arguments into the new node's data. m_graph[v].first.GetArgs().swap( args ); assert(!args.size()); if (ki.kw == KW_Unknown) { // No idea what this keyword is. We have to assume it's an ordinary // one, possibly with arguments, and just push it in as a node at the // current level. assert(!m_graph[v].first.IsDefined()); m_graph[v].first.SetKw( string(kwText) ); add_edge( parentage.top(), v, m_graph ); assert( m_graph[v].first.GetKwId() == ki.kw ); assert( m_graph[v].first.GetKwString() == kwText ); } else if (ki.kt == KT_Standalone) { // Plain operator, shove it in the newly reserved vertex (which might already contain // arguments) and add an edge from the top to it. assert(ki.kw != KW_Undefined && ki.kw != KW_Unknown && ki.kw != KW_RootNode ); assert(!m_graph[v].first.IsDefined()); m_graph[v].first.SetKw( ki.kw ); add_edge( parentage.top(), v, m_graph ); assert( m_graph[v].first.GetKwId() == ki.kw ); assert( m_graph[v].first.GetKwString() == kwText ); } else if (ki.kt == KT_Opening) { PrintStack(m_graph, parentage, "OS: "); assert(ki.kw != KW_Undefined && ki.kw != KW_Unknown && ki.kw != KW_RootNode ); assert(!m_graph[v].first.IsDefined()); m_graph[v].first.SetKw( ki.kw ); // add an edge from the current top to it add_edge( parentage.top(), v, m_graph ); // and push it to the top of the parentage stack parentage.push( v ); assert( m_graph[v].first.GetKwId() == ki.kw ); assert( m_graph[v].first.GetKwString() == kwText ); PrintStack(m_graph, parentage, "OF: "); } else { assert(false); } } else if (ki.kt == KT_Closing) { // This keyword closes a context. The top of the parentage tree should // be a node whose KWInstance is the matching opening keyword. We'll check // that, then set the second KWInstance appropriately. PrintStack(m_graph, parentage, "CS: "); assert(ki.kw != KW_Undefined && ki.kw != KW_Unknown && ki.kw != KW_RootNode ); // Get a reference to the node data for the current parent NodeData & n ( m_graph[parentage.top()] ); PODOFO_RAISE_LOGIC_IF( n.second.IsDefined(), "Closing already closed group" ); // Ensure that the opening keyword therein is one that this closing keyword is // a valid match for PdfContentStreamKeyword expectedCloseKw = n.first.GetKwInfo().kwClose; // Ensure there aren't any args to the close kw assert(!args.size()); // and handle the close matching if ( ki.kw != expectedCloseKw ) { // Some PDFs, even Adobe ones, place close operators // in the wrong order. We'll do some lookahead to see // if we can fix things up before we hit a non-close // operator. if ( !closeFixup( m_graph, parentage, contentsTokenizer, ki ) ) { string err = formatMismatchError(m_graph, parentage, tokenNumber, ki.kw, expectedCloseKw); PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidContentStream, err.c_str() ); } } else { n.second.SetKw( ki.kw ); // Our associated operator is now on the top of the // parentage stack. Since its scope has ended, it should // also be popped. parentage.pop(); } PrintStack(m_graph, parentage, "CF: "); } else { assert(false); } } else { assert(false); } } PODOFO_RAISE_LOGIC_IF( args.size(), "Stream ended with unconsumed arguments!" ); PODOFO_RAISE_LOGIC_IF( parentage.size() != 1, "Stream failed to close all levels" ); } void PdfContentsGraph::Write(PdfOutputStream& outStream) { typedef pair<PrintVertexVisitor<on_discover_vertex,true>,PrintVertexVisitor<on_finish_vertex,false> > EVList; dfs_visitor<EVList> vis = make_dfs_visitor( EVList( PrintVertexVisitor<on_discover_vertex,true>(&outStream), PrintVertexVisitor<on_finish_vertex,false>(&outStream) ) ); depth_first_search(m_graph, visitor(vis)); } void PdfContentsGraph::WriteToStdErr() { PdfOutputDevice outDev( &cerr ); PdfDeviceOutputStream outStream( &outDev ); Write(outStream); } string PdfContentsGraph::KWInstance::GetKwString() const { return boost::apply_visitor( KWIVariantAsStringVisitor(), m_keyword ); } PdfContentStreamKeyword PdfContentsGraph::KWInstance::GetKwId() const { return boost::apply_visitor( KWIVariantAsIdVisitor(), m_keyword ); } void PdfContentsGraph::KWInstance::PrintToStream(PdfOutputStream& os, const char * szSepStr, long lStrLen) const { string s; if (m_args.size()) { typedef vector<PdfVariant>::const_iterator Iter; const Iter itEnd = m_args.end(); Iter it = m_args.begin(); while ( it != itEnd ) { (*it).ToString(s); os.Write(s.data(), s.size()); os.Write(szSepStr,lStrLen); ++it; } } s = GetKwString(); os.Write(s.data(), s.size()); os.Write(szSepStr,lStrLen); } }; // namespace PoDoFo ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/examples/pdfcontentsgraph/main.cpp�����������������������������������������������������0000664�0001750�0001750�00000004170�11235544613�021506� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include "podofo.h" #include "PdfContentsGraph.h" #include <iostream> #include <stack> #include <algorithm> #include <string> #include <iomanip> #include <cstdio> using namespace std; using namespace PoDoFo; void usage() { printf("Usage: pdfcontentgraph [-a] input_filename\n"); printf(" -a Process all pages of input, not just first\n"); } int main( int argc, char* argv[] ) { bool all_pages = false; int firstPageNo = 0; string inputFileName; ++argv; --argc; while (argc) { if( argv[0][0] == '-' ) { // Single character flag switch( argv[0][1] ) { case 'a': // Process all pages, not just first page all_pages = true; break; default: usage(); return 1; } } else { // Input filename if (inputFileName.empty()) { inputFileName = argv[0]; } else { usage(); return 1; } } ++argv; --argc; } if (inputFileName.empty()) { usage(); return 1; } try { PdfMemDocument doc( inputFileName.c_str() ); if( !doc.GetPageCount() ) { std::cerr << "This document contains no page!" << std::endl; return 1; } int toPage = all_pages ? doc.GetPageCount() : firstPageNo + 1 ; for ( int i = firstPageNo; i < toPage; ++i ) { cout << "Processing page " << setw(6) << (i+1) << "..." << std::flush; PdfPage* page = doc.GetPage( i ); PODOFO_RAISE_LOGIC_IF( !page, "Got null page pointer within valid page range" ); PdfContentsTokenizer tokenizer( page ); PdfContentsGraph grapher( tokenizer ); cout << " - page ok" << endl; } } catch( const PdfError & e ) { e.PrintErrorMsg(); return e.GetError(); } cout << endl; return 0; } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/examples/helloworld/�������������������������������������������������������������������0000775�0001750�0001750�00000000000�12356565167�016672� 5����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/examples/helloworld/helloworld.cpp�����������������������������������������������������0000664�0001750�0001750�00000020657�12114144122�021533� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*************************************************************************** * Copyright (C) 2006 by Dominik Seichter * * domseichter@web.de * * * * 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., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ /* * Include the standard headers for cout to write * some output to the console. */ #include <iostream> /* * Now include all podofo header files, to have access * to all functions of podofo and so that you do not have * to care about the order of includes. * * You should always use podofo.h and not try to include * the required headers on your own. */ #include <podofo/podofo.h> /* * All podofo classes are member of the PoDoFo namespace. */ using namespace PoDoFo; void PrintHelp() { std::cout << "This is a example application for the PoDoFo PDF library." << std::endl << "It creates a small PDF file containing the text >Hello World!<" << std::endl << "Please see http://podofo.sf.net for more information" << std::endl << std::endl; std::cout << "Usage:" << std::endl; std::cout << " examplehelloworld [outputfile.pdf]" << std::endl << std::endl; } void HelloWorld( const char* pszFilename ) { /* * PdfStreamedDocument is the class that can actually write a PDF file. * PdfStreamedDocument is much faster than PdfDocument, but it is only * suitable for creating/drawing PDF files and cannot modify existing * PDF documents. * * The document is written directly to pszFilename while being created. */ PdfStreamedDocument document( pszFilename ); /* * PdfPainter is the class which is able to draw text and graphics * directly on a PdfPage object. */ PdfPainter painter; /* * This pointer will hold the page object later. * PdfSimpleWriter can write several PdfPage's to a PDF file. */ PdfPage* pPage; /* * A PdfFont object is required to draw text on a PdfPage using a PdfPainter. * PoDoFo will find the font using fontconfig on your system and embedd truetype * fonts automatically in the PDF file. */ PdfFont* pFont; try { /* * The PdfDocument object can be used to create new PdfPage objects. * The PdfPage object is owned by the PdfDocument will also be deleted automatically * by the PdfDocument object. * * You have to pass only one argument, i.e. the page size of the page to create. * There are predefined enums for some common page sizes. */ pPage = document.CreatePage( PdfPage::CreateStandardPageSize( ePdfPageSize_A4 ) ); /* * If the page cannot be created because of an error (e.g. ePdfError_OutOfMemory ) * a NULL pointer is returned. * We check for a NULL pointer here and throw an exception using the RAISE_ERROR macro. * The raise error macro initializes a PdfError object with a given error code and * the location in the file in which the error ocurred and throws it as an exception. */ if( !pPage ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } /* * Set the page as drawing target for the PdfPainter. * Before the painter can draw, a page has to be set first. */ painter.SetPage( pPage ); /* * Create a PdfFont object using the font "Arial". * The font is found on the system using fontconfig and embedded into the * PDF file. If Arial is not available, a default font will be used. * * The created PdfFont will be deleted by the PdfDocument. */ pFont = document.CreateFont( "Arial" ); /* * If the PdfFont object cannot be allocated return an error. */ if( !pFont ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } /* * Set the font size */ pFont->SetFontSize( 18.0 ); /* * Set the font as default font for drawing. * A font has to be set before you can draw text on * a PdfPainter. */ painter.SetFont( pFont ); /* * You could set a different color than black to draw * the text. * * SAFE_OP( painter.SetColor( 1.0, 0.0, 0.0 ) ); */ /* * Actually draw the line "Hello World!" on to the PdfPage at * the position 2cm,2cm from the top left corner. * Please remember that PDF files have their origin at the * bottom left corner. Therefore we substract the y coordinate * from the page height. * * The position specifies the start of the baseline of the text. * * All coordinates in PoDoFo are in PDF units. * You can also use PdfPainterMM which takes coordinates in 1/1000th mm. * */ painter.DrawText( 56.69, pPage->GetPageSize().GetHeight() - 56.69, "Hello World!" ); /* * Tell PoDoFo that the page has been drawn completely. * This required to optimize drawing operations inside in PoDoFo * and has to be done whenever you are done with drawing a page. */ painter.FinishPage(); /* * Set some additional information on the PDF file. */ document.GetInfo()->SetCreator ( PdfString("examplahelloworld - A PoDoFo test application") ); document.GetInfo()->SetAuthor ( PdfString("Dominik Seichter") ); document.GetInfo()->SetTitle ( PdfString("Hello World") ); document.GetInfo()->SetSubject ( PdfString("Testing the PoDoFo PDF Library") ); document.GetInfo()->SetKeywords( PdfString("Test;PDF;Hello World;") ); /* * The last step is to close the document. */ document.Close(); } catch ( const PdfError & e ) { /* * All PoDoFo methods may throw exceptions * make sure that painter.FinishPage() is called * or who will get an assert in its destructor */ try { painter.FinishPage(); } catch( ... ) { /* * Ignore errors this time */ } throw e; } } int main( int argc, char* argv[] ) { /* * Check if a filename was passed as commandline argument. * If more than 1 argument or no argument is passed, * a help message is displayed and the example application * will quit. */ if( argc != 2 ) { PrintHelp(); return -1; } /* * All podofo functions will throw an exception in case of an error. * * You should catch the exception to either fix it or report * back to the user. * * All exceptions podofo throws are objects of the class PdfError. * Thats why we simply catch PdfError objects. */ try { /* * Call the drawing routing which will create a PDF file * with the filename of the output file as argument. */ HelloWorld( argv[1] ); } catch( const PdfError & eCode ) { /* * We have to check if an error has occurred. * If yes, we return and print an error message * to the commandline. */ eCode.PrintErrorMsg(); return eCode.GetError(); } /** * Free global memory allocated by PoDoFo. * This is normally not necessary as memory * will be free'd when the application terminates. * * If you want to free all memory allocated by * PoDoFo you have to call this method. * * PoDoFo will reallocate the memory if necessary. */ PdfEncodingFactory::FreeGlobalEncodingInstances(); /* * The PDF was created sucessfully. */ std::cout << std::endl << "Created a PDF file containing the line \"Hello World!\": " << argv[1] << std::endl << std::endl; return 0; } ���������������������������������������������������������������������������������podofo-0.9.3/examples/helloworld/CMakeLists.txt�����������������������������������������������������0000664�0001750�0001750�00000001266�10653303212�021412� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This is not a full standalone CMake configuration for the hello world # example. # # To build it outside the PoDoFo source tree, you must set your build system # make the PoDoFo headers available and must link to the PoDoFo library # and any libraries it depends on (see the README, # "5. Using PoDoFo in Your Application") . # # Note that you don't need the headers for PoDoFo's dependencies in your # header search path. ADD_EXECUTABLE(helloworld helloworld.cpp) TARGET_LINK_LIBRARIES(helloworld ${PODOFO_LIB}) SET_TARGET_PROPERTIES(helloworld PROPERTIES COMPILE_FLAGS "${PODOFO_CFLAGS}") ADD_DEPENDENCIES(helloworld ${PODOFO_DEPEND_TARGET}) INCLUDE_DIRECTORIES(${PoDoFo_SOURCE_DIR}) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/examples/CMakeLists.txt����������������������������������������������������������������0000664�0001750�0001750�00000000226�11366377460�017254� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������IF(BOOST_FOUND) SET(graph pdfcontentsgraph) ELSE(BOOST_FOUND) SET(graph) ENDIF(BOOST_FOUND) SUBDIRS( helloworld helloworld-base14 ${graph} ) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������podofo-0.9.3/FAQ.html�������������������������������������������������������������������������������0000664�0001750�0001750�00000031504�11236203662�014162� 0����������������������������������������������������������������������������������������������������ustar �dominik�������������������������dominik����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <title>PoDoFo FAQ</title> <style type="text/css"> h1 { font-size: 140%; } h2 { font-variant: small-caps; font-size: 120%; padding-left: 0.5em; } ul p { font-variant: small-caps; font-weight: bold; } .question { font-style: italic; padding-left: 1.5em; font-size: 110%; font-weight: bold; } .answer { padding-left: 1.5em; } </style> </head> <body> <h1>PoDoFo FAQ</h1> <ul> <p><a href="#s_general">General</a></p> <ul> <li><a href="#q_platforms">What platforms are supported by PoDoFo?</a></li> <li><a href="#commercial">Can I use PoDoFo in my commercial application?</a></li> <li><a href="#q_language">What language is PoDoFo written in?</a></li> <li><a href="#q_stability">Does PoDoFo offer a stable API or ABI</a></li> <li><a href="#q_mailinglists">Does PoDoFo have a mailing list?</a></li> <li><a href="#q_contact">My question isn't answered here. Where do I go next?"</a></li> </ul> <p><a href="#s_otherlang">Other Programming Languages</a></p> <ul> <li><a href="#q_c">My program is written in C. Can I use PoDoFo?</a></li> <li><a href="#q_cwrap">Is there a C wrapper for PoDoFo?</a></li> <li><a href="#q_java">I'm a Java developer. Can I use PoDoFo?</a></li> <li><a href="#q_otherlang">Are any other languages supported?</a></li> </ul> <p><a href="#s_troubleshooting">Troubleshooting</a></p> <ul> <li><a href="#q_stdterminate">Sometimes my program crashes in a call to PoDoFo and produces a traceback including a call to <code>std::terminate()</code>. Why?</a></li> <li><a href="#q_sigabrt">Why does my program crash with a SIGABRT (Signal #6) in a call to PoDoFo?</a></li> <li><a href="#q_setlocale">PoDoFo creates invalid PDF files because <b>,</b> is used in floats instead of <b>.</b>?</a></li> </ul> </ul> <a name="s_general"><h2>General</h2></a> <a name="q_platforms"><p class="question">What platforms are supported by PoDoFo?</p></a> <p class="answer">PoDoFo has been tested on Linux, Mac OS X and Windows. It is developed in a way platform independent way so that porting to any other system should be no problem.</p> <a name="q_commercial"><p class="question">Can I use PoDoFo in my commercial application?</p></a> <div class="answer"> <p>Yes, though you must follow the terms of the LGPL license for PoDoFo. The license permits you to use PoDoFo in any commercial application, though the LGTL obliges you to provide source to PoDoFo its self and any changes you made to it under the LGPL. That means that you may link code to PoDoFo that is not GPL or LGPL licensed so long as you follow the LGPL's rules. You need not fear "viral code" here - not unless you start copying chunks of podofo into your own application, of course. The inlining done by the compiler is considered "linking" for the purposes of the license and thus not an issue.</p> <p>The PoDoFo developers would be happy if you would credit them for using PoDoFo in your application, though this is not a license obligation.</p> </div> <a name="q_language"><p class="question">What language is PoDoFo written in?</p></a> <p class="answer">PoDoFo is written entirely in C++ . If you're interested in using it from other languages, see the section <a href="#s_otherlang">below</a>.</p> <a name="q_stability"><p class="question">Does PoDoFo offer a stable API or ABI?</p></a> <div class="answer"> <p>PoDoFo is not presently able to provider either a stable API or ABI. The library is being developed quickly and still requires a lot of changes to its interfaces as it is enhanced.</p> <p>At present the best option for many users will be to target a snapshot of PoDoFo or a particular release. An in-tree copy of the library is not an unreasonable option, though care must be taken to ensure that your copy doesn't end up as an increasingly unmaintainable fork. The <a href="http://svnbook.red-bean.com/en/1.0/ch07s03.html">svn:externals</a> mechanism is probably ideal for projects that use svn, since it lets you specify a particular tag or revision that's versioned along with your project. See PoDoFoBrowser for an example of this.</p> <p>The README offers some more information on how to minimise the impact of API changes on your application.</p> <p>The PoDoFo developers are interested in offering a stable, maintained release at some point, but the library is not yet at a point where that is practical.</p> </div> <a name="q_mailinglists"><p class="question">Does PoDoFo have a mailing list?</p></a> <p class="answer">Yes. See our <a href="http://podofo.sourceforge.net/support.html">support</a> pages. You're very welcome on the lists, and they're not high traffic. If you have a question, make sure to tell us your compiler and version, platform / OS and version, PoDoFo version, where you got PoDoFo / how it was built, and the details of any error messages. If possible, upload a problem PDF somewhere that we can get to it, too.</p> <a name="q_contact"><p class="question">My question isn't answered here. Where do I go next?</p></a> <p class="answer">Your best bet is to email the <a href="http://podofo.sourceforge.net/support.html">podofo-users mailing list</a>.</p> <a name="s_otherlang"><h2>Other Programming Languages</h2></a> <a name="q_c"><p class="question">My program is written in C. Can I use PoDoFo?</p></a> <div class="answer"> <p>PoDoFo can not be used directly from a basic C program, but if you have access to a C++ compiler there are acceptable workarounds.</p> <p>The cleanest approach is probably to write your PoDoFo-using code as C++ and have it expose a pure C interface (using <code>extern "C"</code> and the <code>nothrow()</code> qualifier) that can be used by the rest of your program/library/plugin. With proper care and attention to memory handling and exception safety in the code that works directly with podofo, this approach should work extremely well. You need to be careful not to allow exceptions to unroll past your interface functions and into their pure-C callers, and it's also necessary to be careful to use the C library memory allocator when allocating memory that'll be <code>free()</code>'d in your pure C code (or vice versa).</p> <p>As an alternative, if your program compiles as C++ (most C programs are legal C++), you may simply switch to building it with a C++ compiler. You may then use PoDoFo directly, though you'll still need to pay attention to cleaning up after an exception is thrown to avoid leaking resources or leaving your program in an invalid state. This is a reasonable approach for stand-alone programs, but is unattractive for library authors, plugin writers for C programs, and some other users.</p> </div> <a name="q_cwrap"><p class="question">Is there a C wrapper for PoDoFo?</p></a> <div class="answer"> <p>Not as yet.</p> <p>As PoDoFo does not make heavy use of templates in its general public API, it would be possible to write a fairly full featured C wrapper around PoDoFo's public C++ APIs. Most of what'd be needed would be to:</p> <ul> <li>provide factory functions for PoDoFo objects</li> <li>provide deletion functions for PoDoFo objects</li> <li>write wrappers for methods that take an instance as their first argument (also expanding overloaded methods) and translate thrown exceptions into error codes.</li> </ul> <p>The PoDoFo authors would be interested in hearing about any such effort, but are not working on anything along those lines themselves.</p> </div> <a name="q_java"><p class="question">I'm a Java developer. Can I use PoDoFo?</p></a> <p class="answer">Not with Java, no, though we don't discriminate if you've used it but want to move to another language ;-) . In all seriousness a wrapper for Java may be possible, but nobody has been in touch with the PoDoFo developers to express an interest in writing one. Java users will probably want to look at <a href="http://sourceforge.net/project/showfiles.php?group_id=2435">iText</a>.</p> <a name="q_dotnet"><p class="question">I'm a C# or other .NET develiper. Can I use PoDoFo?</p></a> <p class="answer">Not easily. Since PoDoFo is unmanaged C++ code, you can use it with P/Invoke and a glue layer, but I wouldn't recommend this as a pleasant way to use a library. If writing your PDF output code in C++ is an option, you may well be able to use PoDoFo.</p> <a name="q_otherlang"><p class="question">Are any other languages supported?</p></a> <p class="answer">No. Python bindings would be a fun <a href=http://www.boost.org/libs/python/doc/">Boost::Python</a> project, though.</p> <a name="s_troubleshooting"><h2>Troubleshooting</h2></a> <a name="q_stdterminate"><p class="question">Sometimes my program crashes in a call to PoDoFo and produces a traceback including a call to <code>std::terminate()</code>. Why?</p></a> <div class="answer"> <p>If you're seeing a traceback including a call to <code>std::terminate()</code>, like the (simplified) one shown below, the problem is probably that you're not catching an exception being thrown by podofo.</p> <code> raise()<br/> abort ()<br/> std::set_unexpected ()<br/> <b>std::terminate</b> ()<br/> PoDoFo::SomePoDoFoMethod()<br/> main()<br/> </code> <p>PoDoFo uses exceptions to indicate error conditions to the caller, and your program is not handling an exception that is thrown by PoDoFo. Your program should call all PoDoFo methods that are not annotated `nothrow()' in a try/catch block, or be prepared to handle the exception further up the call chain. Code that calls PoDoFo should also be exception safe.</p> <p>In simplified terms, if you fail to catch an exception and allow it to unroll the stack past your main() function, the runtime will call <code>std::terminate()</code> for you. This in turn will call <code>abort()</code>. On Linux, a <code>SIGABRT</code> (Signal #6) will be generated and your program will be terminated. Windows users may be informed that their program has asked the runtime to terminate it in an unusual way, or may get a crash dialog.</p> </div> <a name="q_sigabrt"><p class="question">Why does my program crash with a SIGABRT (Signal #6) in a call to PoDoFo?</p></a> <p class="answer">You're probably not catching an exception being thrown by podofo. See the answer for std::terminate . Alternately, you might be hitting an internal assertion in PoDoFo, indicating you've found a library bug. If your problem isn't covered by the answer for std::terminate, please report a bug and include the full podofo library version, a backtrace of the crash (this is critical), the code that causes the crash if possible, the PDF that causes the crash if possible, and full information about your platform (OS/distro and version, what the CPU is, etc).</p> <a name="q_unusual_terminate"><p class="question">Why does my program exit with the message "Application has requested runtime to terminate it in an unusual way" ? </p> <p class="answer">This is the Windows equivalent of a crash on a signal. This could easily be an error in your code, or an error from PoDoFo crashing your program. You need to attach a debugger to find out. If you're using MinGW, install GDB from <a href="http://sourceforge.net/project/showfiles.php?group_id=2435">this page under "GNU Source Level Debugger"</a> then run <code>gdb --args myprogram.exe</code>. Visual Studio users should use the integrated debugger. If the crash does appear to come from PoDoFo, make sure that you are correctly catching and handling exceptions thrown by PoDoFo - see the answer to <code>std::terminate</code>.</p> <a name="q_setlocale"><p class="question">PoDoFo creates invalid PDF files because <b>,</b> is used in floats instead of <b>.</b>?</p></a> <p class="answer">PDF files use floating point numbers for almost all drawing operations as coordinates. Those floating point numbers have to be written in the English format with a <b>.</b> (point) as a separator. Some languages like German use a <b>,</b> (comma) instead.<br/> Earlier versions of PoDoFo used the current locale's C++ library formatting operations to output values, causing these issues. Upgrade to a recent PoDoFo, or run in the `C' locale.</p> <a name="q_testsuites"><p class="question">Where can I get test PDF files?</p> <p class="answer"> <ul> <li>Misc PDF test files <ul> <li><a href="http://acroeng.adobe.com/">Adobe - acroeng.adobe.com</a>. Mostly browser-plugin related, plus misc tests.</li> </ul> </li> <li>Colour and ICC: <ul> <li><a href="http://www.eci.org/doku.php?id=en:downloads#altona_test_suite">Altona test suite</a></li> <li><a href="http://www.gwg.org/ghentoutputsuite.phtml">Ghent Output Suite</a></li> </ul> </li> </ul> </p> </body> ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������
  1. What is PoDoFo?
  2. Where can I can get it?
  3. Requirements
  4. Installation
    1. STLPort support
    2. Boost support
    3. Installation with CMake
      1. CMake builds on Linux/UNIX
      2. CMake builds on Mac OS X
      3. Homebrew builds on Mac OS X
      4. CMake builds on Windows
  5. Using PoDoFo in Your Application
  6. Preprocessor defines used in PoDoFo
  7. Structure of the library
  8. Contact
  9. Licensing