Index: lib/build/qdox-1.6.3.jar
===================================================================
--- lib/build/qdox-1.6.3.jar	(revision 1575872)
+++ lib/build/qdox-1.6.3.jar	(working copy)
@@ -1,881 +0,0 @@
-PK
-     [6            	   META-INF/PK
-    [6.tf   |      META-INF/MANIFEST.MFMLK-.-K-*ϳR03r,J,K-BV+$xRKRSt*3R|RxJ3sJ⹉E]lz\\ PK
-     [6               com/PK
-     [6               com/thoughtworks/PK
-     [6               com/thoughtworks/qdox/PK
-     [6               com/thoughtworks/qdox/ant/PK
-     [6            &   com/thoughtworks/qdox/directorywalker/PK
-     [6               com/thoughtworks/qdox/junit/PK
-     [6               com/thoughtworks/qdox/model/PK
-     [6            !   com/thoughtworks/qdox/model/util/PK
-     [6               com/thoughtworks/qdox/parser/PK
-     [6            "   com/thoughtworks/qdox/parser/impl/PK
-     [6            %   com/thoughtworks/qdox/parser/structs/PK
-     [6               com/thoughtworks/qdox/tools/PK
-    [6R-    0   com/thoughtworks/qdox/ant/AbstractQdoxTask.classW_}+,, 16dˀݦvBq@`Z2BWݺI$=3ݤEZǽcofWB>|}z܀o-q^؇
-G:eN-˃(׫x7Mތhx+&zohzI;4!<,|SK4Vx>=ދix?|P~HL|X>Zq^yOc8>!O{Yg9*P+E_Re2FtΉ'̘c]
-T1?`*ؔ3}HMqH[sv̤n6)3I0*;OƝ
-S
-=ָ?4fL{K3;.޽3H̚:SeOǭtc)6bIi|O=5fؔu,+뜅Y3fæ%Rcs"MoͮmpH&MuyʎI$KeHNF;!ٸ%t1v1
-*3TyQUsތ9Y1m;WbvB)ήfG+]Ɉ9:3gmI	1&̽5]M3=iz
-mAMrGy1mHEm1p* ,Š`5E(UcVB,y-sfi:ƼxQԀ9zHy)XΡ648&JrV$*wD tWU_u|O)hWo[*긆Eu`Iq13?;::MIvΎR,^%|O?#XOtϩx^sktø59a%[W0[{A9Aǟ:xQ?OqR) O,4Ns4RN4+=bR*(h(ޝh1Lu{~9J;_4eb0]nmE#ٖff3P4oTA3Z7&3IyaQлJYCU|+#'d,17n{.Vĕ%ʂ(5O͐L1sۊΑ;衈B)}픽de-Q"|]y"I=m5k
-X0,C~4\NqyTx˫wspEnWEٴ op/~u+GY]Ԡ9dp!)_URDY,3"A&Fl5-hJ"q䲛-R%/tj~ b=V]dσA]|o/"|_Cu]n9נ-w+"f[<@-ԡoqݎns܃>Q/p7W]E P$Ի;^	}4.CӨH(ilܝK-C*ۭB3--b;J[%}؀-#kqFǀ<}C|z=a-ѺpdK"*T6~_(=HH|;!&$0_ʲ0g!\$>	QZKhi[y\w54hP$[-^I>.F۩Pٍ!%ph"(38fu되%R;F.]9,ħ-)NcuDMNHMD]b1H7C`Gd7^1Tuc`L3{fK8m5pS 1hİ4(!TOC궗=΍Q'x{I@V:gLLU#ɚĔIO*/(@㧤ϡ W᫔$24DL'~Fbԑ,C:/4}4e4I|A2+^/mywIT-}t#oNˡN3<@]C~YY
-,nPK
-    [6=}  {  >   com/thoughtworks/qdox/directorywalker/DirectoryScanner$1.classR[o0=NJC۬*qg@ހ!^6!!"xT$Ĭ޲X8N~~ ?
--	Rz|?;|<@*pvXp3 S(>42bY-87adP5Y1<u*&H"Q*HG<;:B^̥y(Y#ʶJC+x]"X%<q-?V0/-vƋBP邜z慴'g,l`K5OgCUD;gKh q wB=Ģ|i؎FxfV<=
-4%5k甭wXXm]]mѷ&-ӿ5687+\B:EAw:١j>1.%;X".ˮ
-..FPK
-    [6&/  	  <   com/thoughtworks/qdox/directorywalker/DirectoryScanner.classU[WWN20a2@-m.Z
-P#V,(C2!:3ҾOǾZתeQ>Wߙ	`e\o9DCE	\UqMCW[>*khbBp"/1bJ_iqS8na:ZwT܍3qìͩG˖m
-VFr܏
-Ĥ7]Osl,S7W_8iPƜ9]]_2{ƒJa%P.z/;Օq׼%idDugO{t3ER1]Qj(%QTOm,ϧR]xF{	-0: Ei6gyE{#,[YĚkI<88$E7Jekl!ڇTZRi"$:t|H2PƗmƩEs"8%1(FB&-<c:>:@GC*H <)-3=bAG*xE~$t|G:	/ᬊaTP,+(&:Rc-'uXgޏ% kU*)y 7z{vwJo;e N؜T؝b,8Z`t6\rW^*%JɬlxSILw;&IfН N}O퓐q;XX=8ɱY><ΝM+D7}	%})	([9h/vB ]5c|> Xl#!sLj0Lv-д	-k跲[8_]4A#@HS5!|#E>hH#DKh}~NmSɽL6שOx.v<G	?qYVH6P^l[R;tH(q ;%YR}`d`jEAλQ~/{a9A_|pjp}	tL7j8[\;OC72,w2j4\F	is/ZPK
-    [6?      7   com/thoughtworks/qdox/directorywalker/FileVisitor.class;o>f]NvvvFβ̜TFA-ĲD|}f#Wp~iQr*D 
-i/)ed0L//M()/./LɯO,JM,ON-G4lKNb^RP##00b1I&6 PK
-    [6KED      2   com/thoughtworks/qdox/directorywalker/Filter.class;o>f]NvvvF̜"FA-ĲD|}̜Tk(FҢT-RA'9?W$#4=<(X0%B?%(5$<1';H-j ļt},6FF&`dab`Ll PK
-    [683[O    8   com/thoughtworks/qdox/directorywalker/SuffixFilter.classR]OA=+`ժiDc_,;0TҤ?xw"6i3{{;s}sy$PtRSx``sk6fNv[Wofz_<[7Z
-CjW|`X(=5a!EHierSkkj3{sK-E({B	$?jF>&KT0apjHidlxW6^s[͐A/d13f5_,r"h->Ikc>K
-N36iZ9yU;`$G13fہ,PN]4f"+O1'1ǘo,@bۘ5c[!_PK
-    [6N'    ,   com/thoughtworks/qdox/JavaDocBuilder$1.classTkOP~VA1Љc
-76P(=lgt-_g#	~GM:mi{a
-oT C7U0`RQ򜖢I=Pю
-fx1(ST<C+4Xe+
-PW-q50|dqw!qxE&Y/ڎ=gOf>3tl6w%i6-ז:3,2A[ufJFʉZČ|`WmoŖz]mKFqoW*²+-r6Gqua˝zkW0wM^]
-5<5
-&@d8xv7/KKwyk|>^jx%-d%e$kf^ߡ^RM[C%]nz3m-%pwn
-ʨ-)h%*-aY0=2Mn)TFJ;dGCOy0LWii[]C0D=QM5AJiI3(2G,=qCI /D ~YK:KM|A$йA
-I*nbroSS8EOȮ}3(SĤ+TNqk'ӮKI*FqFg;\t*̃| m:1J;d($=! dHPK
-    [6`"'  7  *   com/thoughtworks/qdox/JavaDocBuilder.classY	`T>$o%` I&!@4$l!y	83KŪUF[VZQ[S׶nfb[׮V[70P1w߽g?sx<T_hE&)xa2Ť|VmKMayenFrD^:d58fTg_qL=Y2i<_R{xl|4C&MK-̤s&_.+Wa4*> خ#evGed(4$7-2Ufe	}Rfo&߉>|O]m*GpT~nr9Y dvH}LZϡ~o4vʇ?*/	!d8dMP]ȇe&p=}盄/	_O)59./U2{Af/%^6k&˩oM̾mwL~ke=}_
-<*{_GIOf-"unKyy_tPLj$ÿ-ehoŤOt7M,e?L_>m4_|K`ǻ1&=H(L#w.	Uu%ÑP&K[bUɝ=DŭUV;RUgD+"pGe'85CdL=.YgG[bh;S!W5%Xw^oL@/4-'3yJ63ykGdڍ];Ў-c-P<,73fAZPWu#v/=9"3ZM a>i̜ETZuV{/DU8c6Z&NtEMvr)a_v	;ۇM/%߉qNFIj_c,)=JʆM7;L,Zv(ioD]Gt9O1-2OkaT5ĹNmUd%p\pE*nCߪpWEv-wd#%aN;)ܡ*ێHp
-mjEjcq왖'nEdU6nI67ؗ#mbmQ;2
-54^ĂF&lm?'!pRSgc˚2!ymq{NƲj}8xژN-q$1v+u3*4`qWX.BoSЄT&R7<)5N⓫c guÎ&4ecK2Xn7ax)96$t9#[m]R1yC)OvacUVDɐ0	iTZ+-}I\wVmAo;R-/
-NgdIΈCZ<~m8b޶# ;ibC,Q;YiC`t#i$@SiJetҲ_ifl}h:/ٕfiN1+_X0!d]t%9q5",qcܖ;t6KCPDN*"aSMIdZ0'Mz( #}06c_*QTD I4IP(=MgU#DHti%׀+u]ή$"u!۱Bs-әfdGX6mS61PE3Ph:)I:xK5B8M3*Į咷tΡS˩͛wb7Ui_4Nq7f0/ѓLBzʢg9^-١Nn2(ɽ	MCy,=Aek @YCʧ!1|K⊥LU`TFXje@~AZczf&cBXܭ'UX#zRjCj
-X\,5QMxJxx&[jjij:!]LXj@IXj*)jk*T̂o-KUJ [j<2_-0ԩK6BK,RZ
-v*K@ʣ<RMV'Hj:S(0TdVVP#\|
-bD>%WuFI֨ZAgS,VczUDB^æsmiִnӆ5I'N"ұF̬qH<6,z
-fb32ۊZ/V<TRBl-jR fR'Y5d"dlTgڎ|xŕ<WtK[[ֵ`x^֤spWI;k>DؿR̌ nՁSP-jx-iک(
-mϢҫe*23noe!RQTDCܛ= [*.ddǜ&G2eM<.ѸXW5:'9Mi2z̓2d3nP$iE뎨	!Jqb2蛜)g*l_"iw8xӎ'U-3Tcr[9bXR6DfݞEl$cRF(8YRc-EŻ.ȫ-l:y70wJ&X9ȅ4ҧl-xڅ9-v{8ռ2(|v4՝+D]-<HNF0-A)ĺҲ\ɂp"
-C&}22I3rY)tJuۤ%ew~6\\;ZҊHgPt`r7OnHO'>>
-EJu%ϧ҃d,-.;CX67ؚ걝b9+SX <Ⱥ6)$];.-Oe:`ѺM7c)v!i8N|uvरN3I Id;;\;>PR-SxNµvtƢy=\Z[c&B	:
-kN5۔27lK6m)rY01\pT0>}p^D.CR{D2%-Ejc}Ijlvmܹ?N*7s@,n.J{I9N%"CIJ3F5k])DFUxE#BJ/e:'/	ENwF5=pN%p9oGf(jM3 exl:?H!z}HGϣԧOP~~OTU~N%	/㭚<+'K^>w'V*frE{R`M>LTP^dn`7<F=T4w0nu4ΥD3<*i!]@KBM8K̄w*?>p~J6+z1$4&lѳ[|^*,.+^>ہFP+"RHk@mZAaMr ^)PAS &MJ}h2}t\6D/C}T-<@l#@j4R*N,1@s9 a`7T@ʃ4yx2pw9b0I	^l{>@RM4cf=cq5Pi
-qq?Mo߈^O3Y0S**{hvE_i72;(Gh6]Mt-Fצ|i~
-huQ9i>^/\ʡr*L5X+\΄zYzhnu>ƪ@^ѼnYd|X@~;B:*rz1[`Q01,#\NǆŽtFe ϑwuY+S0}*{iV<|=*,/z_~"fg:W0e3=RTmLGU?FA#?Ht '۠;;LTOA>0{aXA<=?@ߣŏ! ~}_#Ϸa(8"zK0A_RzOLz0_G_&7ӷxGe8-#%CLЯ G̿ƚs|"tg&MZ-xh6pPy6<Zw{ktx]&|y\AE&hu@L: 9oJLsJ~Z58>v*
-dcds Ǿ41k&j6Pbu$VAo:'sSֳB
-;gп@w.Y/DsvV#lx uݴxz=iF	1aH"+m._M\ӳ:`L!<ܧvB#~Z*mDtހP4XV^CiSyڌ-<#,mWz9mmyd{u39ڨ^p&VzCE&|'iӁwdǑW8: SVZj+Fix;"wf"s |}+-\(Np<Ff&X [ht@B~)~5q};+zK}G_b~>z>von"G9y7Pĭn%Q
-}k/PN)ւ5Z8؂ӻBK&;Q~p|)7ӃFmx/z$-|-Tf7$@\+t x !2,hc3s)ȅ-K0!xY|EH-y(O Ä?Mbx#?E<DfDK63exǃ.R7Eb=ԙ-٘/-(rYH<Ҟ~J4IDO^m9D#-| & xRy >?D\0D<FQ)n2rZJKu\E<g]j&7%$Qiv]ve6TնT}7Ml`39_h黅$	Хٲ^!kOSdR%`]6Ƨ:/hC&Wf:0e4g4ҩPBB_	9:Th(I耔(WG$g3*JR6uo3zMg
-r*&/IՂ\uQeV-F*DSa"t YDx|t͙.>:]<l/(לG~4wխfBeEڸtZ]~J(Gx+fm t;`>OXd&lfZw35ל,4:p	 VHԦcjMaS9kbG_5+:C\K\b;pN0hr}*>K7MxY*[z"GB(/3%]N72"#tP?w~:kxS>ɸ6\TۻCg݉#GRjUt]m?/2崔@{%Ң,%Y|dN}^LJ6Zպ>_k?|O{!Jdf^5φhӢP^{;D/*B;C3=K?3*pJȍi߂t+v3b^yԴkfv^Zysj<S'Z^_
--}U~_0s{@C|C4_.GScD_/~:/;4)A
-~MίOE0r;@ԝ`S4nQ}pݰ{{k?N .;\!ހ7ܽY-4~Q+)?-|ݦ3o9֤nʆuܰdCzFq3b:9ک!jepe3ݬPK
-    [6(Ģ  9  /   com/thoughtworks/qdox/junit/APITestCase$1.classRMo@}8qZR>bq"@
-RFoUąK8 (xU	.3o罙ٝ?~C;<Tqm%p\CLyP#bGBx?!dbq-x
-:f(304,lub5P僡9S](bvOd3dp)=$:#~ʣ?i"af$)R#GyV4h3ylސ+Ki^I;TkYLtݢ93_⑏h0R2,D-(M#1u]KthLߤ&za5%mBD -)ȋM@eg{@j|$WbgayJ֔]69ks8.JeoZgTVPX%^u es]7HG˞PK
-    [6讗 -    -   com/thoughtworks/qdox/junit/APITestCase.classX	xT/ɼL^ $$8Y@M -!hlĵC#83`m*VhBmK]kҪZ[RVۯmf2C3|rgΣ{Ш8|~ݏo`7e[|ۏpM~܌[J8Տ6-][zҰϏ	pܯYHKi~Ãc&|1-ktwI'8O	5<Ys-inA-/ht-7~+i?h'--/IW|xՏ5-&.p#K9>Kû~t=i8Up~߇Ʒuvwm:u-Z֬S8'|^84DCp"'Fbr
-x0#3:6(gptC8=Im$j;}mй=9djYe$SƅI#j鏴;r5l1#:e]GsHҌ~;e(^(6D=FBa!9;WƻWXt;>>>5GP~{uܤ6m"Xҧ`V	*5*pvD)JXfI,ɣin]LL[ -=iUĈ8PD&YdIdҋd2c[BSHlˊ^o2vt}ɚuVY{c1#i.Mtf.Lٓ-wv<FKS2l'XmWvםiwܱ}xO7b$\jrPviٜL%\0o"M/-KnsG{;IHH""ЪHhcڑk~ۼzL)ؖ]mF,rVv< #:
-
-Ɍ
-Վp5}0|Jj*"?ѕWʧ4](TN2q\8ӧ*&(L.`7mt0Iq=F򩉺P>5IWUZW
-):ǠԵm`,ܗ{Uj*hn9fΡŕVi:R8t观v'P3uKHEن١qy0'M
-31zMA]RP/i13)#ޟU+Թty%hAS!Gr'.k0M:.tը({V;7}dD{BB{J#N#u{!tZ2g rr>J-M<2]gp?~ggGźZ"43,yX0db>'3kf9:FWǪ&zdȧ}j)&yEtu:^W-L+p/:'ˀ3OBUW+U%YXwwbk7Pzi:׸%]2WV&e\ٽ&ym+x\&:\oÒp[vYɼ9wǡJ<XրԞ^9QZg+,O;MK"ޞBRJcj|6|3EϞd<A65#dʦt`.?NNSn5Y0W±jfyW[ɝԊE\17%+3BlGpZ><k5cŋiu5yTCJx((M)XƩ7OwL|}',jyCt]!HreBaĜ[o@XNmu>7"{Q7b*k-K6im͛eKx7fӿ[LJ^fgsO;>Ka3tȵ旒gQ.xAʯp@ft᷄%}/) lڇ-T7>ќꝹ!-씏ga3Zi]
--1Q-쵢-+MY'cf/2mEχ{I!U?I3)s0-wlcag5k؏rFŞ
-53*<01<՛CN"$LXS3h9GͅCI
-NpTT0@ޓyQ9>zlX:zԩrUuèL;sNySOe`)iOQ}FS1Mx)MPH뽐HLV!ʾʽ'E\:|ĠҒo75Mfok*,)0kfn܍-fcC[:>77Ȇ].#ռaFw	F,	ٴuc<@3]Ms_Y"Yvz|}Lu"TBS+Ol%.&^0wf	QS4ZF{	Nm[Nx+tw/fGr=p}fn!$P۱iɐ'n=}&L˩{]kFP/#*DF-}F@K$%#A<Cxa8!-F|Ǩ	$A| >M!AA<s^</uA,.;z	0~g#7-AlBH^r/3'l*fuTo	oyxƻT=%vt2H>mB7ځrlvS|! < [
-PiT	)?&RLSeUc@1ǫ8AFMĀ¥KM4] w ~ ^I <c b+k}ky(sBO+--=i+m-8mbj}##U*_U|4Xb)gZ&P8aqYC0{[x)ao$W0!_͞X_ʺjwZ.j'=At<ґ@}z}zZJq >ՊZ*oךPk)G~
-EꡢLKy}f#NBGVCX3pR,T{FdsI="е>&p>lX]|*o1x]eE4c&EuT1CuQ:-vEf=n	& fiܢ~	Pz MwLpVircx	 _c._ PK
-    [6R͂  
-  ?   com/thoughtworks/qdox/model/AbstractInheritableJavaEntity.classMO@ߵJEQo/z4f@?-"ҔƲ^~?8[PBafv3o}xACk&t,T/X1+	_]-1AaHT:VyݣNܫP˦h3vвd3Mym[-by^-CnB*)G[dHrw[-b2+zmyw3
--gN8l/bM#J7!.;WK3#ӧ^_fw4;:<:͍*A	#@^:Ca@__Fz40偢A'2<{{bcQ@b&&)@|9sk/{絭GeRV OUHF3Ҙ,6hB
-st6M]xPK
-    [6_ݶw
-  r  4   com/thoughtworks/qdox/model/AbstractJavaEntity.classWTUΝ,&0;"B (+;;{qYJ4Jd2-ϲ~Usgv={|:gw#V3E>PXG]oDMi%qcw"IFIoߋ-2NqxqkM<n9tحvGqgwIzA<a~rO:~g:񠎟_8~:~!7g5$:֙Ͷk[|B-m-c	kl#ټC9js}ΦB\mCOasy
-\2:ntBs0ĜF9ӶW	|sp}wA[AEVrk%pjL2sm
-3,Z~Xx͌#bN;3D}YB
-WG;]W4&U08ae4bZK~.5Al\V'}0.6(9ZP)hu(͢{ xF0<a%]Uy|08
-F
-EBrd~5{dplqDw]g$:N<$(fvSr+
-=CTowʨ\߰G"ze8uTەQmz\*	R^vU DUı0,nMX-ZM1F\'q=BI^npp(/y2-wW\kM!GTt1뎋2N βKF\E@Eizk8uUg!4ڶmX*m0
-NAR127Ve-y]0XdݺuP7W
-=+ċQf΁ӦZ'@ΜB^G/ggȉ`+e{/-!	[KLÌC*DNfZPXS-%^AڱXc9<oA@/^`FR6_JPSICMSg?	~^rpHP9+"rl6}4.RVF9YgYaƨSE}cuy?uB^ǟ#7po<rX4~{"yYY^Bry<ݍQoadMlnQb-2z`D-űbn4s~Be&dz3gg7E̹lekܠܪrc҂יJozwLKnLΝfuK~nf,0RUt쵖l'6
-AFx:/c,FaS-IIe޻-3mtnf;T>;aH톖5gFh©^B]S5ҜF\4`"pVq^kc+jS!zs@V6Vk0+Q>\	^-ߦ{װ4𯚳sJyRИjJAgT?*z5U	=olq^액SEۑvÓhav-yM`֐v[ƫ7eG26cc.XL<4c>byT0AfUbI|3E#\E|m0W?M)s;[+׶ZCOkeGP`"řH	4.4ﳸK8xq!bfjd@\/NqK%5vcg}Tkb;tjW`UI
-['^--XjyުZ_uD'FʮMExg:1appk1Ø-Ӊ#7PBpoC Ӊ̲ٗfO'73U:čKmƑҐeo:1/n3X4&0'223w2{0-0N{V=gd[莋i+he;Mu3cpo
-	Ls|G0Jayх ;9Gf%D3hz8(W-61z7VEE:?r2ssǅhyYEq&_PA=pXDnܮG'Kw!V捹[{Qg]YD 6\K}h*};fĨ;.E	mVKSu9}f?}iC8:皔J*O2:btѕW,1)Xb> K|Wի^EWGu>qMTbn$k+y$[Tf|~
-R+P
--J'U&%|
-ުߢ_VoU/Va%S*|~
-~~~
->WP_S>ĠN24;>]&l	]*zWg|f6OJ5\yƒmt&3ע!*G{nόG1!ǹ'yx*Sy5sA]I`g(YJ|(w @%Ė'%P|Yw+z^({kTzxjz%PXIW}W}CyW"x-oV0Qz0^W~
-ZտL)q\!%Zr]j˰PK
-    [6Ȋ/  >	  ,   com/thoughtworks/qdox/model/Annotation.classV[WU	"^*T֪̍HPAɐLf`rĵ|?З>Zv-_]˟E$rԗ}g_79_~S!\LFqŬC0^}a2}˰X	cxX|ȷ x:--k_VLL-dѭ-AM;F6!rJiĲcCãE^4k#UZ1I˹4g*KHKV9pr,9#`F÷A]S;de4+]3lD2nΰ-sCE~69q!-nL:~9{jK&uRYYNa:vJ`kIrUa-p#.Eci!^;v1S)1bOPu8&RXtu
-2413<\	h|e{dP֭x9sY-
-{:.%aJ?ɳdT;|U\2^/H:aKG7ab[GE-juXejHx=qC1J`}1T$ַuRәQ!%MX-u%V3hsr\:DJn&Ϡu[p*/dUUFdAӑ^5uT-+ "Z[4ʫ[;ji%oG3VN6,
-EÛ"һ!0FoEJ\V7M2yA'OoC~R&I!@r\dxRG)ts1@P;ңvΧvOq$R}ogLP	D4P;!kN&@H#u&042_ś]ü0|kqy34rs=EBl-7PU\1~b}?(p!1D^58#ağESI	&Yb0O<HSbbVܦj>Q{T8w喊|PK
-    [6ZK  )  .   com/thoughtworks/qdox/model/BeanProperty.classn@&8?!--C U^ 5ʽ.[BҮw=g曳럿@G84aVl-z#Pi]x=w}\AP|'I3-?b!&^E=>t_XxB4quIjC*Yaѡd/)al<u
-=aǋN751ga%ŕsqܨڍ,?jՓ)'\2	O]w#r2+m.}bӤLf8I ]]ut*(Y&,,k=ڵٯy>T,Ao9Y@V:SU5iuB9Mg[q~PF%MI4 ԛĝ4@ܧi:]mVUkav*>Nt	1ig@)ړ^H~d'd3ڼx/S Y]h]HSyh^&Ha)̃+9PPK
-    [6d  E-  .   com/thoughtworks/qdox/model/ClassLibrary.classViWW~&**jHXVDQAAC2ѐDvw/~9#ϝl,;y_;؁؂a`aDƅ X.x>2Ge4(bAh e t\q%&Hˤ)t p]T U^ˋ+2^񚌛фJZJBEeI[z"үY{%TgN=NQ@1mLM',[PcŴiX͓KX~DkZzDĊu0"WcTdi1fSt
-mVOO~	yq_'o/zRMOj:ǈANÏdqGM՜q^5FkC	59L=9neC+(H(לxvCZۄ%mҨT=Z2f4C,9QOgnܐPYN"^2ᩨ6iFMyJN54L
-IŨJuK3UˠRM^uRITBӫ&<N#Тmeg>2"}鈌7$.F/WBGԝL[N0=)a#- g<i3uh+U(؉Sy9`j{]Vl+8ln!lWF3A4iѻ
-ZCA+"2P4nxS^S@wmb&]xO
->
->Ǭ̢U	:|X+UOI
-¯|2(*NWN)8)"Zi39Lk2)8U-gTg}yv*A4W jp︀Zz_8%J^_U-JjW6>Ԅ%Lc%)b
---K')}	3`P*6;3 ꗪeU^ň`¢iԒV\+G*4g!۲CMY"lgpJOv>|n|Q'vqmE~x)+<;~nK y.幌9(?و6B>~T`-a-6-ks8$읰1<{\KQGh)k^*r,n؜d<v#E|EQ!bY*ˁ`A<'vkpͫ6y~ 7nqq`r4-Yn42i*=U'Z2KYpzw,FRhҚvmzz1TA??If߅JG+j7jh6ƌ3# 4-ӏ>/Fax+>RJjdع>̝jﺸkc5QP#8fGo,17R8Dp߃njEI>n[8:.&c"d7>e*OX.,?-ZXz[px-ht>6Σ=c9:gg-ΰghu=n?W&S~҈ylk<>*@ދXmdnr6e}m=g?hǖvn$%PK
-    [6C8e>    2   com/thoughtworks/qdox/model/DefaultDocletTag.classURP]QQ@"\30ODAgoQ{C9g/k?F?Vp	e<Oq1i/&dLʘ1-cFB$w]얶:fvkLB@t̬0	u`$4	1
-[5-mI'9cg]Е04wommg7۴={Ӱw3Yt\̚ɳ,0ZL5g^M߰Dn=c6΁CMoNptnU[,jJ^MEjXd*P&#$@^g\%	H>0qDCS'QKu-Vc8\NƘ5Yf8UP㚂&4u-h\)6XP*cQ%\&2jbX12ԆPf@[E$P5g\3]k]1%6	曓b3NՁ*4X }Ԣ=Zd;II{p$%7GioW!Bj_a) Y`oEG?F	om褛"ew'L'-$NEX8ψȦf.1ށjJuKb`1/nx|U DZ%P):xE 8w{s"o$T&d$dzL-HWжhʴ,~Zhv(6>vP5PBZ#YR A@=DiF[7Gx<<$PK
-    [620{  H  9   com/thoughtworks/qdox/model/DefaultDocletTagFactory.classS[OANwۥk+P@EQp).	TbB@'2]vaS./&|D ?pfė9g93?~yLቃ1<u3; 䖃(ЯL`]I|ie%![JU勰&SA꫖h#Okq[{5RoƺO*RhNPxަQ&z[^G:'	gJ64J1MX_E]m<n؛+6nr=0_':3Y@?s>Z0_#0|t$sgV2g.1:(Y,(M,7d#9+EIn`Zh(!26gx;{
-Ɨ+Uh)a4||	PK
-    [6U>%    +   com/thoughtworks/qdox/model/DocletTag.class}PN1oY+'OA4x]Jy|(Ǌxxh7_??P!<z=XH$tzc,iΪ42Hp/tN=o%6chUyp!f8+KkDr4'ӧRϓp6t.Ğɩc8&[dF&GǌOf3"rW}:^)>0ҴtDZ;33	26~A)*՛20x
- =
-\G-l@-I_Dw	;PK
-    [6R     2   com/thoughtworks/qdox/model/DocletTagFactory.classMJA_o4twPP bp1^SL:vS]x0C q#2+WMܠ8A7	E}qǩ]ZlYL/dft"b+/s:ɘӇ*5(&7qF
-u3YDCpq7;3ẖ'C8O)|omC 4ih-T8PK
-    [6:+  B  .   com/thoughtworks/qdox/model/IndentBuffer.classNQNO
-v8)M4/0rځ2ө x	DWԵ6f}ֿ~ e<*#r
-i,rX),
-n	:{{+0YZKڶZvcY	<ZIפ^l{"-wc(L^kxթݵx,J^jպsyMhzǎ{{X-m6Lۻ(ص<J}q͗me_[[>] is"l<ԛf`+[7ZXo+P0@~
-`D(2
-n#>px`
-n@M\\o֩~tdچ ߆|\9L
-@/(M
-)hN
-9B9T
-,Oq1TBpq\bSQIaA	3$^]DKSOwG0C<ΐ7Cܱ>Fh^2US.Ts3as!q`jZ=ALz󏕲_L:03gbU[zxz@OEҧ>b>^Q&|Rl!>şǴqz(H>I.Z bXtזPK
-    [6&ToG  8  +   com/thoughtworks/qdox/model/JavaClass.classZ	|TչB $!aa&hĨlH 	H"p$C2ę	H[.-Zh"]*A]mkk7Ūw;7@&}?=o/C~Kp@/iȣR99W:i>_z /䋼̕y/^y."4ȾŲ(%:/Xs{+<ܒV=|xMsY>=N>u pJYJ>W51(;tp㐌7rw>}{/yzidWz}+"uPz1OpкEm6Jv/p@Nݠ]{s|'XnBy|2EV? V&nއһS>w|oyYWz),4>/x)ĻeGz{1}\ =(>!e?,GtWO)+}2~T)/<iFΟ {Kۙ5wFj=сĖhxu]ѭ}ѮPom<&Z-ڛV2}!3iH{kbC,4{Yu Gá^ov,UÃX&A-!0^0 `xD(3AT842xC$MhI@@L|?Sg1BLώҒMIԍ ΎP[d6?	'2T^9	ub^6G;kIW'ge-*SHwm["tSh#>UPbEU#R0MJ/AQjFumϨǆC3\ձ)ԙ\;8`qvf0oR<Yp 8`P|m.nt⁍C1%MI6X019B5M#yRJe
-\WzaOǬңst^+I?kH3:-rف(#r;*WA(4`SUr v:@LͽuYVvjPx;-vePfسlwۥ0RAW.H+n\)(e쑐m21-Djca-ЅI ~u,1R
-M
-dg׶WfGwGm!ULbѾ6{!2$5UAJOY)<Y1\`d4fj-mr8YG7[BPPEokK_q5$C~8S8z9֔xS$߭/8o3z^Hu%L޸v<.	BAtXi-ѷ׋NO ĚqCfXrPȞj#BF"f8EωNJkxi
-:`	)qiS)ı55oEAi~kZ+XX5B4#tƴpĆ Iitb7=m[Xn,K
-
-p5΁Xd;\kp{t5S^:74*BJ1vwwtRٵGyM77YK@<׺zBqYX.m)>A!:Y\RA;[>᲏A{c:Q>NBF1d65z̠ҭ}3~|A2Gz>~h꤬L'i(lB`Tȋ@ sVN΃ӧD(0)z~TV-~AK:380~6U 2ns0+Udw'4-eMކXPtkgSE*Πܹ,F+PªI: G>'-}_dQsMϠWe/u}zM~ WG~an'[cK]ğA.{Pg";i_:ܠ<I?0-@GAj=tZ``{-.1:t~#;~
-Gv@*p~MX{]d[^08u!_-~cp	/u'q06i#'[OiW}Jj"h_kR7yn[.:x"D}'AL}i$V5K6-ª3+!;t.3kTdFizjĵ.h\q[a, `!+ `#-BuX4Jtٙߎ
-OĞ`aD U3E!BIF|`:'
-zP%?yqI~
-6&_f~Jy~һ6ID5+9:35f 4b͗Y	z"|xGtaf8ըb6U5S%ǝQCsg4#+}o	&GٯMoY KKGQyHߦk'!7|y̸n>CI1{cS [3yjrEJ&$҄je	`~&ξ~xmTJhy#B{ޮZMjNբQEjwYclբtTVZTEQtaz)=abQCJusS]/E|'YT@eO4TEĊaBO>Q=oD}AKL:TGՊEPg-bVc*_i4:m4H&\C|"z@ת1'-έ&9kǤ^0n-Y|]8A;_&q*<(24P!?q,Ţi^F
-	| i+!V.hȇ sQZ4Z)'(_A*9)4/ZBq7fWL͕eٖ ǏQiKPau:]]ݰv]-bas.Mc~aO5<BOhpXx|&MMy
-'rQ'/Ƀ4EvV"TkhT99+9&Gb҃/aL3 g UYX=BUL-Gh62t|LϒU6/u3l,M"c̎A^?E!~4Ni3n,v+-t6D7NqVh6ۡ;9|Eo"ܾ]o!/qM=aDO}< sk.<PUB<:J_]{sπarw`#hSeW,^h7Ut8<mG.J(뫙aI:xX[Nd5.`=`:I/XZJpsG\.!K.T~B=|ځQB_ǋuGƛn8(pa:IEi"q zƁ``ʂ0tTS _ϟA {U a}Lu>] ' $3DSp|^p45 ]?I:G8BJJ7d.w{
-er=| M/9B?/nY|`/o[hiQ:ԗP'Phg^'U<Gz~dKxdj)r1Uƃ*˼!h %CnV&OzN7:U-X9H?QɢmśRMqp絹{Ֆy%)7B΅2pmpٕ*k$KNƎN`>\~.:OϨ ^nr3_c4g%\Q CtVˠdz?_ 4فv¶*,'sJH(mmUЪ@ ^|V 4M!^*b&h:غ7ހMhruVPOTSB`k@7WQܲ4,7rAjΩ׋27LxRX;=;=35(sKͥ4'riO @ȘIV)?k@9ne]\Q<	5$FȨ|Y!9bMQ1Kr]Ů 8(v	σt*s2"0㨚{:;]H5Zt_\sGF8\|F-x"ŵX%6Kl(^;T2 QOa_=HPI"na)P/u-KW(z(KlVeVe]FvNw	mAZ?UB%-se-^Eyƍs6RcQzb9@ +{k{ii\IݖX}fծAb^2]Y׭*{=e:$=L/YLyG2y2ėu47P	_U\M3T˝tw2Kk9BARc8fުDJK
-
-T/!d*=h)Wqp(Wk{-콶aEge,&dV͵xGS/CYm}ZPY^ۛ2ۿYo%J(dL:fiL4o	|MFHvbeSi&nۿ?TUiw!lC|
-'_ji^id[b)*䶔T
-Be(KJWP#P'G3)iJj>!>%=%vk	ș9}N
-w$4V(ǯJyA&Uv!$
-~y&n?>*-M-,-WAפm݆-PwPѧ	ˀ>`:8d-"<boa;'SE]b#QBd7j>~-5밆S MtqS9^P5(iyK-7qzP!6SڮM܇OD&:HZFȸ7ګ@(-D6Jw`ES=eğ3:+u)@Ja!8XU^#88:{ÞLYXv[mAA}J"".4|~(1.JNRQ
->LV5:C;.ܮ(_sSS桩Z~f*z.*-.!"7YVl+ ZZG7	Orpl@Q9U'YI3maJJA[wS!:Kj		?ڪ$/E41lm:yTUmMfS0^Rh)gabC+Ug;N;Aur!vZ(CczO3)Sꂣɯ#KGNqM17;{]iE]Ӎ+sWQXti%dU1"=s^O%:4摮-4N[De-xm]KfjG~ ;Y_eY|skKғ#GDy
-W}MA,{IЍrIW~ڠvO^lYz\F!LǍͅ33msq
-p3)RT,J>	@gT/-iW:<XU<\?^-UfJ,?L7=AU_7No"?PK
-    [6$'   "  0   com/thoughtworks/qdox/model/JavaClassCache.class;o>f]nvNv.FbF--h\b
-}ĲDjkF>NJTFk-,~Nb^~pIQf^&q%e 8'&g:(:nOJM.acd`d`b &F`(00 iV6#;H PK
-    [6a     1   com/thoughtworks/qdox/model/JavaClassParent.classQN0~NCPA3SK.̢$Vǰ[+C.cNM?^P%N<<	]-
-%~$C?\5g	({E%\K^a:\o	~F*cfV¼(XXmXb!o582噘hn߰	"7Sґy#ƚT\+o8vQn1GЩƩ]I8ˮ?/EdZB-i6LDˡtvqh#;k8PK
-    [6vL  	  +   com/thoughtworks/qdox/model/JavaField.classT]SU~R(lK>X[
-R>RDz$Kغf#o:tz?9m1M3;s9?Ø1\c^˒\c܏!FyVbXzxSx(?	cKޕ0Nt魊}Gvv7u۪T=i(0aXkhu	hiY5uuF=,01T`-wSL]:C~ȨM!Yecξ .]S1\}ծ>dUu]m,Ė6LW ?SJ e8QZh^:^qs%a'ֿĎ<+xB5j6]B=ȩmU*$RL},;Mk-RTm0
- QP0K
->L)
-v.
-qY.=|IYg2
-X`Y
-3]9Vq%.E7a[̎7IO+APM*v!YRצn#_@i-5]4zp	SC $Bo&w=gw  2»p S> _hbe?d0@(F<񖵏$(/+xܧϞN\N2Pϴqv0C|k~]y{u?uo	Dp!i""i5q'$)Eh(9+.ϞّgIި\{_d9YG7Eo"Wv6/@7k+
--9cM^"έ/]-w v22VBr9Rg:uo+/:claԫJnP&{ti,tHCm'F?e4nѶ[,[wzć=IrjOy:Tul	>|PK
-    [6a  &   ,   com/thoughtworks/qdox/model/JavaMethod.classX|Syq%Lmpveㄬ$5b%4keYJdɑK[,]5)&+Ytڤ$('[K֮m>tkwvi߹W׊f{|ϽYУtq<F;-1]IIG0rBG|!B/FЊ?0Ϟ-K'<CS!3s!_iY(RhWk"ZoO</07|Ao
-FЍ׿E, ?FOv	B=Y^/_:P-<_Bښ.
-;S^k"?=>an+>w2?=<ޤJi+] Geّ|[rW\xwSV&/\QW"UNY:@!t!$B[7̍
-8y3կۧI#ӓhV3Sd!#ΡߚкNE5B
-\\gu񴵻uWyvy">buծxIbUl{c!2
-+5?vX~ʍsix7XHB-Eab䴺Ckb8?9SYR.Vux#tx.ɜaԚ4Z G%@d6!]J)zc/.+$mY7:મ'uԂۧbEy8zk:emGo@G&Bh򰶐jDP~k(}8Ri][c>wK(+4,N؈aʹ&X s5&;FW|X;ebZCl&EJ@*.%DKs(bXh%-B{2mҶ|*^_~^z	N!-,^]8c>`9BqSNz,;[{Zr{Yi+ݙ)J2,qܛ@-0TvOkG3ei]/M	L;M;-`İ,?.7b?&5*w㨉7bې75GL#)[WTTA03ڬBP`*q|obo3UXE@sn5Um7qV&SթzwCZj[duj42\E-d2zGx?&l1PͦjQZV+,KB!yXrĽP1QkdYcX&:TCg
-(;쒐N=ge,N0
-w6ɢ;m2{~YkAcw-R76eF3YUH>Wt+_дEL@A(}XKr\f-`ĢGc=G" S^`d'S1^*{,Dt#(;[k0΍A05AY⾡u4f3,:8-A4F\`bũ=cTrYILSm
-"1J1`lߜP+A6W3r~~aJfd%Ǥ_3+ڮTQ<F'[~'~/Y\o^`eP]|| GӚ6Q~QЀ<5m)8-ov4F^PCWМrmP\j9dHeWGHsEi^C˟y/D{-վV]-;;z];*
-8TaT2UeNaa~|vvvޏݭJ|9uԧw՜tk)uO.J5Њ4jOtt`ZJ
-'1Q2FeW*uU0o0utqN6"k<v$r#8"-iJ$ e3X`DC[	`~ͷ1!e@v3N"h2$bl!]1#_/)|=` I4!{gOuuQ![ʲxC<yD&QVB˜d|-tJ?tQ>1K3C1lRt;XwtG(RO>$s%<Ew/3~fFiRDɒ<uΎrN[wE|zgq)ga'wҔ U}ǪƶsY\hLx8
-]QR]Q+ O95:*7]3Typp>[UZzlawp;ؕ xV̻w{L	@T;Y}[ZLņDGkx?6s'6;o-{V6j5w׫]]sW)~|u>LY7:=B⼅ĳJ<av5tɚ/k%~L'K!%tjF1lϬ1GAO0p@1aAVg-@7f|:>'j>I?y+pZʭ_7[N{xVC[zbD4HI-;pYD|g5ou@V?5gF7oy΄N&O3a;{%aQfY-pؽҰ eG :槜Zc[ntgPlwY>j7~'ydGu͑,oeGi()]	 _ @3_S=%Tf<3_@6>u6ǖ֟`,+gʉ[aڗ=pM3F9W͔3}[0_=v^~! -jդ#-:
-RUyvo^~k\>0t}^A6`~eٖ_2rM;,8ťoF'Ⓜ9m5?2s5]53n:dQf'834 <axPbZN"bLJF jѣL\A-decQ-S!w8NIqDoc0	|4AqȞAK=b[,irK_	s6mEC y-}X}hm,/HvC3b9Ь:{7o-q=S<<o;PUQ,SMXVMJЯqjnՊjj5-Eu9ީ^VeMA g&Iv	ǳZRm$LKrfA?B+ޠ9B. 𰋅ȴ>J̬%ߧ4/H`l(k4S>vg*ZEA:<K
-P]/uYtQ4ਮsyEs8kk/ {yNPK
-    [6_j  )  /   com/thoughtworks/qdox/model/JavaParameter.classT]OA=m۲"Qma?@A&@Bl˦]loA@be3]--9sϝ0aȸ!:Me/xØc<-"3ٵ镕CB.nѮ{yWշ7z0Kc,Q6]әfWгIzɨXs?nȩYV2.`)ᤝB33Vrg&OeON9B0t-XsVΙNȕDv(ſ-ZT;OMu.X0%y4h:d8]3JC_ܦwd6G][JѨI+r,7S;CI@s?PȪ}$Pf%YP ]sKKi:K˄nDTWE?.2$=g#ĜQP">bnu*BgLzb%SΚ!Ypqb'bb6h~5?'-hFخ)VaWqLxExK=§!i}}jn4He'EzI%zQ?$ȋzev
-h_!}nEpPPuG$[M{Bs"ɟSw eJ=fjd7qT&N1n*NohE`@!0T­ݥv7q/y\n}')`诣-:N
-	v1FB^rLPL:У|ֻPK
-    [6To    ,   com/thoughtworks/qdox/model/JavaSource.classW	t\Unf2eڤi'%V3Y@ՒHҔ̼$C'3KXٴ(ȢU(B
-mj	-в	(&*&"fIx''_<Ac!6k%\,7hsEď~f-?㧸ŏQUC[q`*c4 -?}w`P԰Kc6[{dWt/!+A<$r@N1<xRïhO,ͯ)?3=+gY[EA{IuA+~4?:^uM񖎷5Y_4U;
-[ËK柵x<i9'&gM5K2D$n.jT(TP3Bjsz+r&"Iu+Z&;mMWeVRzR13t2Y5,eK#I2O\ҎITb[lD͡^hӗN(vΓtڢqx2n}%
-fJxl0Ӌ#	wh$$˷{赺4nfQSeLtPMD˽:\O'Eh2jR|R5L{i篋V<$oaP
-yfoڌF,3FI]YI95
-0y|LN(qY$E3l.5dv#w]"M(ӜM(3Rʊ,e.!+24!bn113X#}	kN̤u|_g*neIa)L)ʢA!M6fesuN7aF:톕LXx"f%t8tD2<aPuH_6;뜈8\2:gGn;NuT	b(lUfLZ8
-#t;8$@HXz}ļÉI[,;֋bbKY?ӰD{-,r_q5oGÇ>"/
-(%Gxty>&JaUb(L5F\(^cJ-JS+uC)v,T[-5ZUR1e|ESU$k-5V3T@U2^1h_~(ɡF#C-|:`XX9iJG*ŤXoHvG/GLig"{d.Tuin58KbryHPtcFl2+MD\gF\mZ){n_ܝNuxI/m53{s<A;M-GYSL\Ӟi>4V/rи/vdt$jV"ﲌAGp8v/.]qkO-ie71ԇtb5AM%H<9Ť.ɦ)V>[}
-Xj5WEd"f2&p$#7uteƭOx=,O/:<5wFH6e>	=#,PWܗ0]Y9Xa5&-pN"VoV{gwW{_~;s;')\;uP`JpTp%v<XJGP}ͧk\Gs
-jZC8΁t'WRpCQOC(E͡r9$zIW--e9V>pZ"9ER%h{M04  ʷu`Tܵ&QN&j2f8l@D$23i[5">Kq0uUzbĆف+ee_c83ņbQ;<*-iHrZ]^c7㘢A<Ѷ҉wcrs.ked؋ɲ{wZaS|N B	iu<0L)S/ҖTLm(-vxΤ5g!@=U,m_E,u-*u-:RSr(JbȤE]E-CH4<GV͑b9rIrD:8j.@ji &"ICU0)$_WdA83~L߽U
-RiCp7zԖ'Q:h.amހ{N>e$:<4,][-&ЀCX63C#-/3av#γeyމKKY1/di3.ቇ-`nr]OԨܦnh.t{Qt$+Uv܍[
-~'B,\KoaāULq$GEE@'3Y<_?Y-TA4*-Ax#G7\89z 
->LcT	c3ݦu	y<i48(-MP%e}ס.	0PtC?B4Q=[jTXu5.]m5|5zFflqLf,f8|f{c.omN+٘*0G/Gy1S4⪲H>3",|-fN	pN$܊N0oewƚκ`:Ū2o=><*#Ux@}jU1-OxRSjVWu=Us^Pz/GzzofI9޶a	ng|z(t(=,4;32Xzr;ʤxF)\.ķmXK;.W̖6XG+f"^ܹ3hH'n9}LɹIq-s׻c$8|ƼW@Yksޡ2 ̼QQ5'N<xR)y%6j/Z6Iq?2qy6jL瀝˷^_sK);=8T߳-PK
-    [6      (   com/thoughtworks/qdox/model/Member.classmϱ0࿈8hܝp>IVJSBc-9 >Aoww@sDBv-bBI!kf#a-مQjIkZ.	nbŔ.6r&ډ*f:)ndnt&Hws<G|.z.!7PK
-    [67/  %  .   com/thoughtworks/qdox/model/ModelBuilder.classX|ULk>R;md@mI@SZmxM2_itfҧ"jEP/BD\lBXuUuwQub?2d/s=֛<j~-G3p?(^+cڼn!3ޯ~Dw7:_VmB~w!*{57up6ҋDЦTK \BRmj uzTX2\TmJ]ko2C,Y2[I#$V]=?(sBX"`.QʰgrY uBKBب nEe!DZhojw*bKaβhoiMrR_˴\{ӵYT:KVccJwNf/W++-YmUr
-N'חa/XRBJͲW6UђrdjmљM4!$ZKXՒvkG,ٔhI҇Ml{={0ޗOLŝuy+TwT؁X	鴓ni+s9%_ͬs$od2ýr;ݔ(rgץ:;lS\X)N$HRm&Tk-lJ\<D+D
-j	)D⤷Z:&K'tMXfkvmw#y`b)bXXū:B%*r)6:IU--]4-%L]P^jC:H0ap'.IX:k3twk6SKbݜ^5V%-)`C>p$@7Iy	Aק7dtptr5jm48JI8ij0
-M8d܃&ԚvbYG,/-5xjf$/݁״P:zzI}2ȺY>=f]^`qBs뼍Glj.Oiq۠%r2*I|{jEI~eACNWօ8HƝC#c5B~ /R!F+"9p9x<ƾ7㘋!);ݻL4^cnbj<8%HNw4/\XGAXzԻ_!t&u2/A5ƺ*Ck[:Ycn&,ݖ,yY <m^zC~8!Wo+ksM(R5:C@!!7yjFEm|@wF=˚[q6x;n>_8%lٲMx'ūd$ka͍6ރmفlܯ{qGWrwITҝr`AQ/:1Kvٲ[--7͖bKw҂hDmOBKz[a;N[ڴZG.{l{m'tj/lEߏï5_m»aXNmI-A9da9b1nGmyq<exʒ[mywʻw1lyxxwXBH~@ws-wm|Ж	)T?P}X^/v!>ƕm6S r\:\|2,m	|ҖO1d4<d˧qs`Lleڙl?~FN	\vGZ|Nz|xGU.vބXkc2$^ԟ5MLAjǤ>Eyd02u*pZe|xA%rnKEnKڟ5n;,fsa 1gvtD&5n{0FG\IȸX,X>0<}uF^\I1pRiʹl6U?i>5ZTR\8XM*P)2|A?t_ԞQ"E9o-KT=CՌ8t*rq{2dRqP8,E#s9o: fZVΝҍZZub.y>1BN	i'۝Gn`PʲPkXIfZ?Y숥ט"ù4U}4dSp+u-a/ǭ\uu@t+Y&&	3uѱ3&{nMj2=vvUC˼F7dgW'IoNAF^+e'`礬P^q
-:x8fXykB61E_0hc(̗e^1;1+$~+ȇr~iӐ]҇ꃿ'ͮن{=*{=~w?HJ#է`E$2r-By$ʫ{aGs
-4KNbTO1"*\j#0O)8bzn	}pk8VE<&p159e(dnRpvS[BvKG`x]#uQ
-T2TArqE9֓,2?{{ڔtzu?RÅ]rh8>i8~
-KPR~'A9ç0B/fi$f<^)s8s{1όxan|{Qu'XԃdAxOT(`8jKb_j{m9F!%E~\,5%u~߲@e a,R찿2ǴX@zX̖y<7a%bz>\}#ce	)3abIb+i4FzDQOSm&\p-f<&6x;S}ć7,"jtRd5d#l1>i'(ϋ<<J'|N؃
-&9u˰8>o\orD#h-W+\'}3G= 3M0E%;wh_]=J:q*Xİ0XsK8a<aK{O-x;_)b8NOVkk4V%:u8ZG=ZWWg'^jmgcC nNuM/R`?Ȥ_?e¯f[712Ө^PeNگ4K8I}fjKk-zy}8ۇ?,Zy
-]54F]^b^0Ȱe{m/i4m-cbT<tVh/Ѵ+.= O>j9R &恠7Xc?eɝvW-r@LoAӺBո7GQ75o2i1x!1`<362n$	݌{IyO}{m_}?3:ŏJ&uc.zCe?iJd>Jk:
-ך<<kVO>@YڧVEF􁠄j%|͋WO4b;b{k^:>k{meo(@#fWz3emcfT"Amўvjj[7L3ﯸ )NE?څ6_'}WCuk3.=O]z?^N&'5湟1:/_b57TF+(*8A	!Sw-!6΢s}&G%UTn'2VKjl>-U|cԕK7t^^Nu[āF׏>f9lTǱZWA!q{xsgFbWM4"am0o+	ƩjG\ưZ?3T^g&ncֿ_hb^K) A<SK7]LArIv䕠rjD1:bzz	<P'd*~?fH
-{{N&s{'c}U25-.3{s #W{ePK
-    [6P  t  &   com/thoughtworks/qdox/model/Type.classVWT.sa$# fU(T($%6pK<#ymԦMm5Jb?Ohs8*Y=眽9G7	!dɐs(Pa>2/bDb_JxE*drH{5Uo&)ҷDzK[XlˢH?-gA<5>584:~q-Da)N;sBbΙ҉ŬuP>v:IY"d"L'F
-9;3ͽ`{:Aվt2JLT1>,'9+L^֯؅NwΕr5ƐaÀN&hr"tRX2goQ/DW̃ndE6+lzC*g%L;ykRd=L[2E-{V4͌%E2D
-U~pή5#KN3&f`h'bU\rQC}+.Qp\ߴa3ũ)-w@底r_L3\1qYZQc&q,%RCz)-	0So%s0zOS}%gi-@b4l%=M[$p	V=ʳkXw(\kr]zޭ;?LѓJ{d#N1Cn7q i2|M|{eGd`~&/M|ǃlZ&t3/x61&LYgdx
-O-[{&>$&L2qMN_ǟY)ł=d4g\A(%ꩴtE5O
-M$ħwGyזTwl;w_ھ.ՙZU~҅Vrːf$.~o`}oi²\Y-}.X6uнo7l^k]7"y>xj5i+3]63i-wwc?O7NԠM̂\%ͪfyٿIrΉ\1
--h&GnB7Q}]3l"xcZk&T8DϚSE@IOWhxhNӂ9iݫYsV@ruBrQ$qP.z.NPOX`vѡ<lv߃y'yZX`FGfe=-zfC1drn~иmkb[	H˹HMS/ yKzve:>-PMOS>)7FW^B60(7+1zQ%.pn)* UZ-+W}*]uwxF%2Wߌ-!N++9ldV+qRqʏfGLoץH	:&
-˕ULͰ\e6C!EXWxPl]FC,ҰT]c+ײע:8ne|	Lnhƈ\{=DOt5y=lYlB?(%D(5q靻dz,<ZƻVQ?#QԲx?ӺۣUQrfJ5|fo~ˀ]}5՟kuM, J5ahY5Qa5oI(?y9	_/z`	k[B.5q0~I^^Y2Z<ԡ]ҙ#6t,o4!̱kb+ɱOX`)/>.6.`vֆTN'bgxPXRu3gn^~f^zYu K7-.ְsV+5eFVW
-;"¦vWh<
-fdGL^yEԓ*~ѼΤYrɲ{V=oH[啶\Riaϖȷka*	)WnKH*7r5	gpeNPK
-    [6Jy!    7   com/thoughtworks/qdox/model/util/OrderedMap$Entry.classS[OQNeXnU[A%K[[xA/'qv)(9sfo期>^LЌ~sqYDN\aWv;\q/\y0.n%6sy]}^SYSyveMMC-E+9&COQKdp4EsyAicE5)+3)E[TF\yӠj|^54XT<07d32YnʹBޠ\2s<kUCM(n,b
-ռ-H=:_,z5Top]K1nuhTv['LVՅ{J1[nLL#V_RoA/)u"Ǜ?lFЊ;N  -uRK81	w1.<1f-	#*#\G/CG\&8]?dRj؝H$xJC5d f͇ZU${+Hn<Z}hlh|{29A2@ ,9zфy$KS8cq|u &nig8Uݖ(l@oH`6xn\m!Fu"*fRdN붙]Be'c|GߠghE6NMS!M]^2U$+$cDÈX+k@gQ؆{,wj:^PlIK-iĕ=4ΧPe:gI-3脇0N7PK
-    [6l    <   com/thoughtworks/qdox/model/util/OrderedMap$OrderedSet.classRn@=8q&6iU*E҇"xA{lذ  *H| XM(}gfΜ9@PE,TP)\us,ㆋ[.kHtWfx02PZԫFsYK#PD<zB=罘nx+is}1x*JD[z$j-Y&(@N_O^#%y4&"iN&?
-+PZ(SPo4'8y17Fј';foWzfB$+P<fX4ܤqɞ}><LhGYq\$q/ӊ3:?t"-I !ts*-wu LXU:ͮ!j4,/Ysݥy/pqad#+w2C1G'29:eӆ}a떨>JΉ".Y.ۚ+8chq(PK
-    [6w91    1   com/thoughtworks/qdox/model/util/OrderedMap.classT]W[Eݓ{nJi,*h[hBB[kZm "-	{+|p-k|c-Dss%P|9s9{93#	`Bd8#7UCeni(6(oJOn2tPÌY݆l
-ӍtJW 1T#e	ğJS3ϬuzIMa{@dYjݐʒt[KuFf>o9WI4W
-^Zy5na(&Z;Ng$W[ȴu\[z&+Hx R%]-*O-rpWOahUG͖;FM-K-^q.K_kړ5CrM.o+sbU*u"#a.^lx5.)7[NE޳՝:lӣ9&ryP0g3<29XE<1
-o|G0	%s_4;[ժVۭKxK:)hLV݃Z;h+P;
-h5--,(/'1(sre]/w K]6}6-[(8/^EDb,iOqXAΌv-	
-U.jH*_ŠF.b>Ι;^B_̍"Db;H~t@2."a2m9d}km]y߻D/k2C*,!)0;S/0H'%5~xh~{럿QyJ(HqR\e/$ sOp!!D?A !is>t3?u+ݮ!+>N=ED3զqmq-GO-sLCPK
-    [6ė  	  0   com/thoughtworks/qdox/model/util/TagParser.classVVW&&@Bm?P"CrLFLL|7ZmeZ}>@M_L(۲V>g|? bXp*. H1)U)&u74cB1ܔ[aD;n㎊i-ݘƔ]-0"}-ݘW *MX%˽ W2egUjqU8is@KwΘyӱ7y`4q7oWsywv*Y{#^dBZx͚NE8
-:Hkd=X$|bf)s,[Yl3>䚹yPP }_%YYbrC6'-ǣ2m\
-b8"1s}##ʮe$̲LJoY75ġf'.7buI6rN:)͒t
-z&쪓7,FgƤ*8h=a{
-GF-K0sL*WdDsHfYVH":aDE^GdԤ/{Kc-E%:x@+WUW-VQW8CD7.*0,*(`OG"#lx{"Wڳ;"ܹ͒kn-ʛrv[#?ڮF^҈gZ[͌-a9+WZJ%/$6\{!'fWwaʨS2]w1T/=͌+rzAd-tfߨ3M{*3؝sZGɗY@umD"M26a-P-<]Znن-laxCr?i-P "l5-jLK5Q4zq1#ccƘjE0jGfh0:֠Ei
-rz8B(,0m,y vxC{Tt0j;6~!`}qzr9:Gk4^|[ߡ+.=C}A=	_Iɸ`ZRi2T|`d:0	A`p1u+أu}%6{Wh9"	j;1Y|'$&wM=lsgNGWR~k#?侫})v.v_Xp$5JхX7^fCIb'l-"I|6S'qӴ_YVn:||ﷶQX Bw~
-&GkPK
-    [6E-%  ^  *   com/thoughtworks/qdox/parser/Builder.classN1OA񂾀qt-F2b>2v ;3]Ks4*Np@q)A7L;	\i(POEg T3j*CiJ߸sSijtpO:?Q,o%.44E, \4.+5c_re?˵0+Ip^RwVL'v3,NЧ~YzMx5;. ˍ-4=h9帍v`PK
-    [6ԟ8,  )X  2   com/thoughtworks/qdox/parser/impl/JFlexLexer.class{|T̝{w޽[fHRB-$ !	!(-PT ((bZ1{v}gYsf->?sf̙3gνL^|Φqf pAENuaM7-'w#=("!Ax5$xIɂqp`
-Bx;GHG`:c*nN:c#=z^87B&A? ,AqGCc(6p@H]<r\|u\lC0\|O9] ,S]ŋ|Ow9JJrq8󌩮ZR[ZU;riD@XR2;gڸqSf
-FdQ^1'Cqf/hPRPPX]WX g0[$	re VO_b1?L=+{jnAN~I(qpBec&dOv"S867:@91{z1T8Sǚa3\ΔY+.H9gfVV,?c-)c`+fT/>5UK`;дIgΝ:p%?@eSAc&XΚV4!'{̤ra3h%jL]~Ιf/66RZ֤̩$).x@/T+#+J+E8yyp	E5ӳa^%I ]&RUKm\SkYT[-geEUrr*ˤڜ|ؙM
-`7ꨞ7eK,] UEԂz*W-clA[j(a'蔱eedTr1,).TmsMxUUչGj1Uea8jŢK+RtUM(]jD	-YP|Lڥ5&y`I6Nf>p'K͍έ`\WN/-TkTQ/^Y_P%W/\\Z$RYhqeqG6Z
-	|^Yg;Gj-/PcTdŜqlkqb
-JMSwaU#-c'(HۦKkH"cҪ&jFw}94Aެ<ܼVVG-iL2B(E֘mVvǼáb]y%:+ǾN+AB*^ZMu4fjs#GpuY:\y1jWFӕ#JrkjAE˳kjJWUG.-(_tn'Z\Yt~DcZs(-Wo	ً#&Hꪢ}x({.,>?Uу24L6>h
-kDs 
-̦Mw4_be?Z*iA!oSQF-+]2'evEKk"*.nho<ɶ->gMl-lvam¿C&n3y	{ fpcɮel+߁
-nF؉p-[YR+ɺ8/K+< '6-OJt-;̻5=8ޠ7}qz>`P&ȳԁ|P@>֨^>4ˇ.G𑀣|49p\1cu	0/냡<$?!M.,1Bʋx2zS47֦j3x	<gs<>^i+.ub5( 'Vj!h<5wk+|é,tva,NUzsLvbD@(v N'tz _/kq.OHraJ @S[/Cg&C JU feJe~-ʥYUT9_;*WbWQ_5(up6J!!P^@Uae==V6y-ӍtbBh
-4qv)~Sf] lNAorB$yػDö&ٷjC;FŞ7qX(կE"^h. -G^cGfm-M/	-dw-玟YwQhߥk.J~1.oZ)3@WRc?LfߊUt)VAwV9>/=Xx-a
-2	]((zSԢg8(QsT!uv}L[kј-a<-=d]%@ɦGeR<c^;e?zڜzEx`x>&< ZfeiXǏ-kq
-XJ6pOֵ9 [owܵmhu|+pY){+-7W&6w4MfCh b90؜SxÍ<&_[69l`s|h9lMh}y/.5l7j#~f;OՊ[ZK ٭--{Z|s{ ޖ-l C_}Ζ	ARǛfLv*xj?~wͽ;/?{Zby>oӣE|sxZq@uGq4<ϙN!se;U="Qv촱=A4}L	;v3qrM|2?yy;ɵs:Whӧt4&@z9yMuqmn8;N^r:	ƄKtzWnp7q7)>7;
-%V'mSZI'oOhZ
-d'&	,n7'?O|&%!lDl&g76-?'n^f+ؕepkJr_&lo Vw7
-#\Ů6+U]hqL NǶq-e`#g)aL݊#="8dwZ#NQY=Lp漍~tC\
-U-[CP@mࣸr;y_>@	 \WI8U-;w;Oq
-J]雊.D,8CC!&sՄw6@{N3pobpF&lmDѺ BO*_U50Vqb?n -!A pŪr)hzP	%^t=,Tf$*Tr.^>hdOlճ,?DhhW-tYH%ֺlOw%BED\֥H#iSb@=KM؞i+ӣgBh+gjthfs]tm~٦U緝;q*֔h)Vz.ܨBuGMnܶqF4э&
-NS,v|>7z-;֞I{OvMNόe,EpY3 Z`k1nQ7*5WMZem6}PEG9hQ(sf@!IK-um`?xA 4"$x3Ei55o?`g7M	E/KLzX=-3ۅVR
-d,DktPLX	Ps@0`y}3.tM?:-fNOoT=}њ+=vllLb<VV2H?ڝ`?`ńƃv0SGMؗQg9-4;{2$ᅡ5xz0nqlmp0^˧WX#'V|_6?wo+v^3,X7QFvhO4y]ϴ'E8ضt7IMUVQmgb-Oqx>&t^7'8KVu~HMUieҪHMz--CӗV__Rs-q0^U]lAW'עt1}Yͯ^'.:Ϩ0U[mrh%с?5f6s]63R˪,˨e˰VDXc&1kLۨ%߁[yR2gkO7u`tlKb3X	g߬Y,>ϋiφv)ƴˠ]ӎ@{^L{>Ĵ+0}>+cڋ]ӮЮi/vmL{)>-@=-g+h_loKlMfcڗA{M1І?>>oZGZmlM6oy[6lnfwڼ[h
-~"mvv{wؼ:$Nx7F\
-fDK{𯪬Q^vuP|"cl]fLaQUoHi-pvQ-'-&ɇO@f#Ʋ/Q!sZ*9F3jVkoe`:S2LwK1Lua*azLS,䨗
-~"kpt|&,һz:@EZѡ[1m#̝~%29̌77Yq1Dň18]W?++eް8\a93_X=(go3q6ŔS~YTf];l%S=>qѹ T(K<ڴo:31*=QP/])o
-QK?fLmS&`Ytg%~JϨ~lIJ.
-w#STHYZZHKrDkεS=CZkB];rHm0gJSALS32Ie(KQ.p`Cl2
-˧v0 {jN4=af5y	PS-`0<$zL#T6UhWjikS!uש֝z-&2y̩Lb̒Y)d e
-mk$,!:C?^{[2<&7><WثVc^mii@>"v(Ǜm5C#nc耍v#ԄC}kW 9*q-˷a췟,H.&!2|6+Kǆ*xe+V*XEjV,fe)۩,g6b_YE>MTAF^7g'܀)@o2t;Cb900|֥&))W)_<5-AɈq	Zmг2uMXK[ՎP:XM-JL@Te̫d	.z*an6ZTI%ToF^MPxܴxt)ww^ZyQ,5Y#,$&=ʺx9P1.)j[h;qRhgc3]ۼ~`5c1ZhN7P&?z<z=FSp=E⧐׿co ̀	u>",}}5cxacqeRzHtS7xOF7>_8>޸$8}>P/) V>o|K,dwfx>	u`}~CP 0VeatDn$=Hr-v o8IXb|jg}+Z\(ng:wl_J-;5/i!mM3--^Dt&IF-!vxK!#NIˎ@/eiZ`֫c¶-6PgwjMmԝت*#4(%#~,:a6r-u^ut\
-074|hL|Z6>2hB4QiycP$Wʀ9Hrco,ȯ]AOh񫗨Yy3zn8"-KK.;5²1'C;4:#
-⨴U!&cE7_ac	KX-c:j3d8!x~<a.Mٶ\?r({P΂2/a̓{1lhwުSF(coZ'l[llT(MA/><SA߭u
-[/;CVvcA-s8F?j-MƽS$
-0p^s)vou7YP}CMktvcB{oi\o~͖i?S$}z}:_8Cc9_3ނu-wPh`<|r@nq@APFBɅw1JP.r5PvC7G=glu;;CrP6C<M(C7P~'	tB
-Ė(xaO.ؓu:د3M/
-z( '@y
-SeCɂ2
-+"(S%ķg sṉ`q902<{̳!!faCͣlhɃ$@Kt5{.<V "Uy -4Cr7@%o4F6@%-ė $&9z[ )dXCihuگQڗXAG< z@rt!0qv+55G:
-[LfˠuZ'Kv!(yG̊4dlOoB9_~>.b҇Iߘ8AnC@%ot	@%Z%y;3P2R;NFȳuyUlNMB$솏d9yCR'~z[OV=G>Fϫi>׉5n~Eդggvc
-:1]D@øؾޒgnqK4toNE$9!c;,5N=a̓z,fm@lxMCD)&-tB0'RL\D"GNcIO1m8ĳZb\#iEɓ7b67;g;~{G$RrNjn@%%
-P]|z̺<'Vf;TP+HI[;Xg+N4{s6ŀl-V_Վ[.nr<LFذ `NŬh˝s784^gw3Q6YtYO>>2HO,Qt`)#KXz'[+DI`[@]bN1-{pvP`QAfO!r?Ec|\-p)6bQLl>D	b";E#^1-/뢒%DTTo"(XbbJXt(jeXW)yjX\szeبDqLlV.[5brئ\'nR6vCYܬ"nQ=QqrBܮ<)P^7DKNܭ$+{C/tqHaGDxx8Mw%ӹx\D'uS<SzxZO9=M] w/%xEzxC"o[X>^O}P&>K'93}\/_k}F_-׊z~Y)~o鷋}O.~
-oZ*׏B^UTSu#?UMKգ_T0j^jGM6Qjv4R;EjcXv7֪a*qأ5}@:xXb<5POkjouk3~Q'y)u[nZ6BGTwP-vUSԳ,wwo<w?u{Zu|5.T
-ubuRb:u{z{z{z{ֽWzzUuFV6MSn.ӧ3;D2۫G̎CfWz>ff'IjY>iP2U6Ϛ*EK:sI}ܥܭeU1ԏ̻Տ{i+9[{egu_o'__(hjtҜ3Az&k>Mz-9_K\ђ<[dv-s_K<u:y׺x^ֺz^Ӻ{/o^ޞ_>ߵ^M-h o6I-FzGi9ZHNzkޅo]M^x
-hSbVmw6ݻW;{6V=}\+>yʽk<WZ[ȧiU>]y_>%i_R}]o|o}C|}ck?&j|y?}U)_C-u+o]0|[|,mc>ֺDke/Cϖz̧Lqse,w@S^`P{d7(c}}[to~}ӳ}G?e1%s1/۷@9|7WDӷ.bN&}Wb5,ŷ
-52|%Tx?Ow.go龫[|;Q"Da
-ESKZaQXw8.`MhCc%ao &nalxe
-d}ᅪ0ȿ,($`"]WeߍIZ'.hT梁R-[hIhHb)ŋhT=hT'R
-MF&ZF'J%Im$P.Jڃ@R(M:jұ(uE],jQ72sV+lQzZˢ(S:ˀX¾ҹt-_X}l,4h%jY4ܢFYe[cZk8[4A^<O(&Y}Rh*T(Q@gIb)VTi<T$?4oEgKbVĢͲε<h՚#_ ZT&rrKy|h -@ҳht*7h^T%OUK b-tH@? h_ tLZn
-)3VJHۀ.\e%VR
-VSS(T$[#ȗSHVR+W|ؼ2ydd2|L|LX|Lx
-yț$"[m=l2x	|fyݿK""C5ȷ}Ȼe?{dbwd<e{e{w6idu6;eW&JdeeۧI2)>t)22W29m!LL
-L	#?(S#?$S"?l{2ddȏve,dM'dkȏ˴ rL+DniOʴgOvcV#?-=l dZe. E~Kt%{YmC{ds_#!;O1_7eǳ-;^,۲i,eNǑߗ~G@v#y)ǲOdo?]z"&T .CBvK{dtײȮ;]@^v"Wv-Qv'9m/2ÅmCf")3 %3C>%3 Lv̭\/DAdUvY^^ǻdYᏐ-٣7m!{e}/{Y	g9({NEDs#rt=GN쬃QQ"SJԢ-PTTda|pF1hPPP\PcOM@p#U~J BB!D݉mP!	!!!!-B{tҁ#a'΄]v#Iݩ&AؓaoЇ} p 	b5aAP#N8p$vhl1c	s	'S&"L"a>V'S g!L!T!#L#t³Q0%3	gCx.y8p6U`sZPNV!c_
-#T",BBFXpB-Z",CXJW`m%E~*^B6\*˺^.תWPJ fYn ]G6^O7PFMI[i,ɢԵfV.jBx+n=N}uw.»	Cx/}d Z"aQ	"|5>Jx16$|I§&|Y';?_ |%	_!|5	 '$7[oC.{~@!G~B)g~A%"o	#?HτJI)D9B(UBA$t$z	}~BI L 	%~-WbUl#z___#OPK
-    [6      0   com/thoughtworks/qdox/parser/impl/Parser$1.classK
-0jc\AgW
-=Aۦ& J?ޏ'<,10ĪՉ${B\ͤ0OTm4WOƛn)o>]@u-HCuwB&01?aPK
-    [6n    4   com/thoughtworks/qdox/parser/impl/Parser$Value.classRMo@}|o:MJ܊BRHqdc?ā @ȱؙ<O_zQF
-(zcCX98'2e2	_UdwUZi}
-ǋ-lQ:4'S!5QzΥɔ	3kf5勺VSz66<KTY3h\)N1w#yu29X9i$4?nPH9$Qf7Y_m&@pcz}g6
-ԇin"B;+
--3p&|9k^8Z~J'S
-*>s5uo"KX%th9M>%ٔ_)O(}kN;:3
-濁̲ȗ\w=7Ol>-#OpPK
-    [6>h
-H  7  .   com/thoughtworks/qdox/parser/impl/Parser.classͼg`6,z0ƀ`-8PIH!^^)!{=ɽ7w|6&!xIͬViOy}B~dyskss{Ĺv;`G!bv""ٹ[;O;#`CyX;@(DiDDv)Ӏg C/Dz9"w^AՈٹ;ݝFD2̛a筈c;0"ba;DP|1hg)/I`-2|}!,?9ϸKo?T)ί!_8-ߑ)VB+*Dj$@
-P Rp#U*4@VV1k%nҪ56`jN;hViUgp] ]VA{ zjKHf"Gl 50QqPp2?"NR#(Fk5FZ kHS9ZM"ϣ)Zj5UiZi5R堖d>*_bV@2%ӸA~j>︷@BjD@b-oE{${@-Eo eQX*;U	B堀U0\VbrhUauVUZ>3Z>Z+ZZ;ZZ~'Z~Z~7Z~ZZ[_kvvIҎND;QiN\;-J;mN;I;额n顝^N_@PѪVuZjV:DC:Lõ:B#:J:FcڤqZ	ZmDNdNjVjuVkuVgjuVgkuVjuVkuV[PXKT˴\+RZkZznFnfnVnvjV۵ڡNjVwiuVhuViuVhViVhViVOhVOiVhViV/hV/iVhViVohVoiVhViVhViVhViV_hV_iVhViV?hV?i/~Uj?h`Zn
-J:UunvMnD)ڍj7UiM׮ݘvB-*mn[)܊Ҫj)BE嵥R7n,)]^R
-9TEe7&mXJ9s]#EjveEuMQE-$)Y-(_[k6$_SFxAEU0bhvuER+\3fUeU5+VW8rÀEUեU֬-0X\p9?D:-ZzəNMsV)?IEI?Ο>=fF:D̚E$Iɚ1#ٹ3&C&@=TМ9S$SA31=waRfRdMJr̟ͺ7sބlpissL -ȚzkrǨI3ġ5+)YhGI3Q7pF3hp]rz|Ɯܜ\Dkz ?
-Bn\n-ssfO93MG=-?Q\p>?ߑZ`nΌv"cUrS,Ɲ73-A'Lʚǚu'PKsg̀=΂9\[W̡ӍƸ$2uI0>Oz,=y9s̝9zQ)gP̮Rsf%3IYrfCS-KFU51?#eB+1HkPs&gO``	 o".wRbfPiCǘg0)'dXK4k8ћsfSGOϚ }sfφv嫪u85,.()ɪJ$777k	-\?]S8UK܁NZ-gSQitK7kn)ڲ<`#	+V6{(cP>U\NVTTP2t[SossK)K}:=UQQiѝ5餲r[aʒeq5e
-䜻qm>+̦hK*,]C.q5mj)_+V*VUC2rԡ\Fs-G ae=WR'$fԮY^Z5x^eqQyAQUx+tkVQ׫ktmm5-W.WTRQޤ4R5E455hUUU1.&ńڊ-ŴN(@ۖ'ۺ*Rz&j/bQqEMBBXTՔ2R*j&\
--{RJj׬MBŤ $AKg-!:(^(=Wa-LB!^VZڵ%s+]͋=M&bw&-[͹rSk>ơҪKk&bЛsBZ/s- @Qr@n~pTyy[YPuӉ0+K6R@ZAcmW.OFfmުͤ5kuIeQ1TrkȜڪbR7X?T;䶰.w;ݎQ:*;yuE܌sscF9w;9v,Oou;] \r32֍'HsU|dΟǑN6?礨#*D$glԙ̉=Cn/w͌}ܾ_u8=QL:sy18OaYz0,tIkASWQ::i7NSuJ33әumQ:а;0fCCQwKեh Mshg*+iI)Elh`|C}	w:䎰;"Q7u8KX3p -<JPu	VKW޸fy%6<i<FfThπ(A4cr;N(u
--\uZ!w(4P6%32̎zTԹ9XF-W;D,zիV@JSssbԙzKjD7Vm`u.u((tఖA3g-Ba:G8GJѵy[\jc3J4OIYuqQ>K9Y!誓SN|
-ܣZ[d5UK9&\	373oLwΩiQ7Ɲ90aV	^ÝNƈusݩ3uRڠua,ѨsR]^^VLz)-ڪu6*<E˩Hrt.\йū*+h9U_%-2e.+ŢEse5+F.6!ᓢn>,2ɝIx]BĶOQw;T`uaw~]F݅"焨{ [ZQ&.v`I"u:22[Y-%:R]J*,usAY+<3 03bEU;6AQ'Cg<^/O5ZKZ5}4iԯrElnEI2 	$fy[Amog@O4yVRbYeӌШڎHO%Uw[	Ke%4x{du5S62\MsGgouM*).*c^/)ZYB.M؄=ЈG'd64~'E ۠ڷmnN>EԠTmF|F5yF-@Y3pI70u@>D01nz-)za鸗ɍ![Hh-2h*1V&EĠM&͐Fb~y3.id#QRxٸWMl)'HܐOQl> `-ȂJpK4=NFs6y)yףam5+E~MLl5Y'ېi5,og'-K-̟{78^{A[RbA^nF~-9tiy9n|y<Ov	w-b5hFx;6)/%wUc9/fUcf{/Ŕ:fKQ#7ǨfZ8h#6afStlKA}QVSVTN+f2Eeg3~cȘ}ɶ]}-'Wv\[kxc퀆2@JJ˫זge4\mvC%M-l'Ml-H8(/i~[GѰY9s9levH2OvMoW.)ھ(mtX-6(Ύf5*nҵ}^bm-|wO}5v{tމ"4^wfPY9#کҺL[:3MOƚRBR)l[gU=p;0Ycjo5ʇ5fwl*j=~FdZuΆ_i岯YeT-كÁUV%^d4t-J5m(gTC3gh)FhDkչVbf` t洠i|'șQ5n'/Ԛ2Zd4ȍ+2`M{\߽p	YqǤDeJzBĿT%k%=vsFseBl^-]^^:3	y7#V-|B2(
-.@&FiRlÛn䑟>, 7FFOB&HȘtbs|i`ƻ=3R"s{r-ri\OJkRMESFBf&YF|s>-(Jʴ
-%.#:!TdL_M4P:Us%!5D:#qLtlZ컇lMo[Z429qsMhxk_lJ:A sR2	V>gNMUiњс_bFEM9Y!_\v#i<bیN2͝cQ8׻U}f'P]hdr>T^Z'_V9]o]V.kxU_UVSZTq{eJ{"{W%v-ʔʺ!}>)#n5QQUt'MɔʶZ7[Ce8TSߢ'(ٷ3Y%%YM^#SFy)36qn5HpKm_{ d> I*C#_oɵT{"յ]e0`f,یKCs}=¿sSbeխN>DU49cV?pnGDI>
-GZk
-Ag?VλEk1+=5l4(3f-|܈fZ>"Q&WjQVYӅKqZ*teY0Jsf}X*pКnwl"Ѻ5Ұa%6erYu'wRсE>X":˛BBrӝɴETʻ(ȻI~go>(b|飖>&gk+O%}g?' "/%JkuoVwĿ' !$Jgs_Uo' #?sk/{?n-C>WĻ>D|R|2 B|4Ӊ|xo[*&MoK| ߞ#~gw	]#$WM|fC| ߏ~  !-È'~DI ?Z-waz-ͲtٖNlN8Gi{|J\6ң-ΚqLXc:әt3\gg>N!Ӆ":.q2]~q,]~8LN}1]i*K؏Aj!r	"=sC۸5iaя
-ZGJg-
-T4i@$B"mum.Um_'Mw߸Uݖ=QRmC"63n҅h!ZSF"p$DwmxIdb-01Q9d{=Itj ruqj)R:
-!*훔h$g#P۾є:XIq[BctIa*W5mقITG-֏DOIhn5;98MdfJ&J:GҎv<sЅ;v
-3LP$E&TtMQ25W [$x!Ri&N£.Rc;BdQ7yC-עyv#v?L[5xT^D% BT~Q1ajg$S:Q!`T`GAFݢua)lmL;-8Au"U']6ƀ2dse;&cc&a̩1Z$fҽ5OR'6AvO;GD814Ioq4َ90z%RW;2y*=Sb*MNss0NvNif*FTJ|kQ{rSiKS)S)T:3NuNkf*ڗY9=`>]/$*/VPz~AațQPHAzI^01qxH$&'UFcC"1q4aЋļ>q/i!l_i/iic*liiob"7p8HFL\Cכ77[LIן+{yGVf}b"}cb'~,%M'8ȫ$lEgܟqHQ0ex x,	ٌE91
-I1(SVTo%4nT^L<IdzL<EdQ1Ujgs¹|wq>KĳD
-YY#<Eh	?E˼EFL,+㈔zWxkW}DVEDVĽDʹ5kfbfae\ǸqFCpWLx1q;#1 b(o#! x@EKbb8L8p4hFLHrГ`89%&-għbO7襘8g٦s9א9ߐjȅ\dņ\bȥ\f\aȕ1qUFuzI יG7-rWrw!xAnEOm^>ael0<;-+&>+Hփr_LzQӛ|FGRG!O!O=M>isR1z0/-^1Zjx{ݐ7y3&>}˘mӨww5=S>@>2~LfS#p_.p_}핁|c!`L-Ɍ^+_La5?ѠF%F?LL(:28(C\CB$6DlHĐCrew H:ELz"!qnY)
-H)ƔږcLRWxʎ&W'28~Fa ]Mn=iH/CziHCϐ0d!lC2̶c[:ґtc,k8Kt<,K'XmDKs,ddKXkTKyC@ M#f"&&t7dV19ې9\CR`7d!	\E<VK x"r[Rb5/Ţ*&W;̫и	b]cr-E
-A62ڐs֐u)7,6 xmAe'-H%:u9r^1^gc.  y@7`*l*:TtdS)-SMEN7azL
-]gQ=9@ϥz)p^@t+ZcBҠQ;%@/%z[cr2 J=Ы^M.ӣuu
-XFcUn6VXVcیUn7VXevc;4ew(vMxbI-)ނ><ht}2G>gL>J1
-S}6OҒ)Z>-yc4aT>Gq'ٰySEҤ6[ԏ햆Mha;qg4/4y$`7:v3Pv->&(gdGg( aCcf/Ԃ|[Қ5oikkJig`@-׉|24p	lB 4ͮ	jLY=̽F^FېL
-+foslƔٟ%v7C1:@~|!CyaGlqaGR|&#v9͡}Glt(<bC[Ppfb#v;1ˡd;x_RdĎǐ<[=<0Vj c9KPT݃Wh/4d!R`%FԺ̐"SrCK)5]\[ed!W]]c
-cJcWW3_o!f4;(QHZ,G* hZ÷ik}Gc͑@#o3w6H:.+?;Hp!"ϊSYƖ:.IܱOޠB#[Jl.+h%[B&یl4Z'huv0φu[7&Ӟ^W[w'szZǁ`p#rQV~-|M}kmn;|'OzڿX$lL\[A;a#G9Q㭞[OY;<m?˳恵V/qw/[^zjzuk7xF[eorߡ軴7 }?cێOOmy/-m7oY{`h'Zg/V~k@-CO|')|OR$]3d'd$O2$S|Q3dL3f<IƼ܉˸['mLV6f<vƾآ}>GA|lb*Y}=dOk^~2Xgo@kA~X-fn;;;;;;;{w-7˖;m˝hͱNNNrrY;~n7oƱi2Xζ9f˹fyf+oЖEv<h]l[Rۯl"rVbRێܕUV^f=>>Wn;(sk[T8Z+_gmm!vmaHoG~;1vk&;x[	Ͷm'zObb={t[}gey9<|Gig컕W|Yz/^fVN;U&<w:?/nv&knv6kۭvfiퟝ]V^X}zKQtv	m}؛->j8Y->ɿn[yYyu,6q|6nOOH>(kfD%;RsKvvSdly;DH!D\ "V޹Ptq.}K0OE99umsDp7XV	Fo蒇!i1v)UwB
-K<|[7чd(|O'(qh^Ow]d/J.2)ه}~O@Jb%Rrv2l"fbD&=5p¹Ex'~)bEd;iS+*Ds9+S8P/N1-g-~M~hun!疀&9ml/kTӲn.JX؟AC*npUήOɩ8qU%4TFcWm|ѭRl(=1vq@Q4oYO0mfc
-o#ݠ2Q$&ZMG~DOAyH,uEcbx"b>-Kּ^\¥$tib~6[1O$&KSL	X}yUTYvGnSm(9ds|Ho3|هeŬ~}X>-9tod]b#CL7v-z;λ"yOLr3XLLBYR,.jU"W;fb1Mp
-qH0xFER|ތ9/~l(ϥ,D?tqa}/lh/Hw&h|+:8߉%f!UgPRZj~жz$4TŁ8dץ;2w9/"3oqK1⭪?,3R^
-^Rhg!D\ND9鬥TFTqNw dB^(6ANJqa{Xmר_=goP^hXqX|	Ra1,VcؚJNk䨄+9(vQVg+w(@ :+wIm½Hd<l2
-oU-ОjSЦ^yXdb(&nl2>v#L]-SߒZӒb|vcdZ)-M'-6-ä4!Y<xښL?oU$(I=(3J3C><0 ;I˄ŊH'|cr><	]W9{ȡ	.G{?	dhՠ:ѕC|*TO]_o!\ۥn;z5qtMtU4K9tѵ.*^G ҕK<"H)tB׽t=۸]I)tJ"躃
-Qt
-J	ZMzItnе.J56}߾[t}K9'k$]zW+?![G>ݳDoR64wlfb]_3]%rDhȞmFe;1ı˄{@bS;vuzKzǳw
-3C*x%Nq.E۶TZ鉐ؙ[,E?SM޲4yN*o-bK]d`wr]QVt2:n,~*u5O>[8}Y.ٜ^s8=r:qz$4VfCۿK\@붺p'5$=$/ň[tC\Wx1Nqs.N_ٜӓ8}9Gq
-NȻPzxPr~]R:YB6uuxhoa9ꘓat.t=nlkwCt{vMe.q$qd](j9/.4
-F{cF%_a&l=E&FٹnΣŽqOGs-ڣV@zoA:s=	T1xCճ7߲]jA]6G^ԩ{P{I:RtW;U_qNrzǚz7^Fe/wkY`;a^A;lf͉V9WdZKn.ׇ-;ŝuUMZg`+rf6.Xp׻VKa61=K=TN*CYw0z'Zs7/!n4X
-HKf6dw|LECK<5y)B?XGJDwlyl*"cax<aðt<t+/Oyϸv{Ng6CG*|54 oH- ^ -`te")[RSn6ggÖ&a;&}\۸#!DD"]DD*"1Pl.S8V7ZܩڈU[ ^WV2]u#UW骻zȅ,Rj[Qr'SMjK-!	5T>Fȗ(-?RcW  &USMvRgd<`59\pS59MrTTKwPcj:yV-v^RKWU*qSΧjZ*S 5Q\J-PkՁ`TUժFRN='R%ժÓ6NTG'6%]KLmNMMmIzP:+uNꂤwՅIKU&PW[k=u<uSx5Q>LmoU;Wתûԃ{#Gգ'ՓW3wճ/Ջo+_ԫ_Z7ѩ]t[>էBR_=V}ǫl~%RשwYOvJ}ܐ~Ѝi#7q}"Y69KNw;&q;%w;'ws$t't{$q{'q3p%Oq'Os'/r&/qG$W#pG'K>= 4wBEnv)Sv'H~ם?wvH-H/wqd$2]Eƻ%4R變Te*<r&r6r{p|6]y=<{T-Ȼd9{bJ')Y)y)%)Glq^r{Q%)W^r{mu)קސ{c4ٽ9uotoqG;;]~]сb2hXtdtTtsܗ׹Dot߈}7^ioO߻_Fu~SSfvu_ԅ冀?Srw^7ԛCIBԗC:PrEC)iBѴ>Դ!?mbEڒP˴PMigڤ]jvicڶPiτ=agڿBcA>cB-L>544}vhXЈBׇH?24>}s(+ЄBׇrw&`hJBuhFB3dh*ƅxC"Ё١EޥewEzԧ"EsS>pWFC;7y9sBL\NAp30I˲4$FxFOqR]eLi81p&֋38-`lӱ^+ZZ@[>v%o:0vN ΀.n^SoL>e؟q @A==8qpG07qzqXlw x'x8#^2NP2N$sz=px뉳ӽ(NN&$4g&Ĥ8J9qkW8'2.KGyE=|-f,px[_d\S^A=,g\^c%Zƃ=>Ho$C22ylo=md<	C$*;|Ps!6'cȱl28C7C6r$CN&MSqr0QiY{G!nq!	|C.l5Bo*E\K<>u!y|rCŕDy$jF|KMD0R QT@n%Rsvw;G2 ] ] = =PJo@&Y_@?@ ?OG  Ph<C #_` $&#v*nLC*L<;y 5B@]R!Ur*AV@U(O+]-k @w\Dk u(f=2n YPpȎH>:zϛ11&g<9f<$sؘĎNe4fi3ݘ;99\.<.|_,"_^w/eeKWhvbvQ7dg<vHB\0I#l5Q&țSDO$*1?IQ5ǘ6{riǱ=ǘ]:r1f?"]:](pѝ#F=!-~p@ .xA0C x;O%&/
- ryEŋ	qq">srs;ɩjB^:u17Q;
-  B8-Fr	`)i"r H=ј|VY  __2{#Y\ѷV%f)` (ćq=TU&Pr;F8Ai3)%lef21ȵ<_GZ3V1aC;q2v>OXe<gU&:r;_,Dơ&23q8D!kBU\m5cٵ[똹w71sLܭ#w36fìvÝXE.,pb.xY:̽1 As3>(cFoE,|+y?gO{ xsy7E LbaRw_g|M[3?6߱{Yx̧gCsQ|ҏgƟ0)g4d@?g/Mm_ٯ6\o.˽^҅0-<
-_/4gQ8l>q/,?q36{{m~Ia-7֒]W+^8fgֆm1sfϝʞ{#scݓ=w!{]f<Kw?z^^o&/{d8q|-b79& ;4v#ؑO#%x'|83Gɡc{&=,eb=:qo"d7x@i*\(ɞn~FcU}~O{#ur_ud@*ӳgcFzoq#qވFPm-c~E5--} 2 ] ]9uC;-#}o/olwoD0"900ct(Rw<tYsg]l/:X6+ax@` 70dS ;SL6@200+&7i"1xI>e+W,ỼEˈbh	Z2&%R
-Jfq8PXcg@eO|67yP5VCP0t1灿 J濚r~,>u5G_fv:&33oڦGDǳ7[gw"Ob<gv'Cb1M*u:g9`fΊtq6svl*98(cg{w;aq1]:3ڥ3ݼ(3s-cV/e:/^Ma73s\V	͐۹(
-smF`x'.ƻ_si-ϐ<`,|Ϻ1 QC,3>at~f|Yy_!%7^f+2P/n2M[w{3[?`CƏlQ32ZE>cF}K~57\AM]rUI?Uz`wh9U3N`6Cݽ`^H5f?4	M(+h%UFf'=)cKq-M}C]삱ؙo8nSv`vC	Ávk7|_a,?*ဍnY˔=\&.Tfbfޣ~Yh7@8Wz^F%?j
-]{+݃n7{i26afu.W3{\q#zb{V탻U{zݭ=}/Vgkc7;=9jUӪ=)Ye7h79Ynv7ꡠzDֻ{s1?"&0/ cf<nL5SӍvcs37&2J_Yp19%И<*c߻^G}tI;$Uğ!S<{'yxP_S9!
-ӥx<f@
- 
-H |@@K@+@k@@[@;@{@@G@'~@g@@W@7@w@@O@/@o@&/?` ` ``0``(``8`H(hX8,@6`" 0	00
-L fff 
-  EK K Eb@	
-P8PX TT5Z:zF!C8ь0˸8O`x"I'3¸TOg<LƳf<\gq+ㅌ1^x	㥌1^x㕌W1^x-c㵌1^x㍌71x㭌1x6;w2ɸ.ƻa>`|!Ƈa|1`|)Ƨa|9_`|%Ɨ_a|5`|-Ʒa|=?`#Ə?a3`+Ưa;`'1+0ɸ(_QA+  I@At- [ )Aw@RI? ??2)Hg 㟃6%HW _t1-Hw ſɈ 9#HO ]{WWd'H 	2 d/ _aK:ԗ.0_@2	t_AGRϹCddPte
-G_F)B2b/%}8Kҗ1J_-}#^"/["f/[#n-"/"v/#~"/;"/Ce"/;#/""/#/{""/{#2՗}_}֗c}Q֗g}9֗k}9֗Co}9חs}9Qח#r"/G"r/G#r"/"r/@xDb_f!r/}9ٗ9ɾɈ˾\f_NEt4g_!Br:b/g J2qڗ3}9ڗix˹ؾDm_GDn_"vr!/!~@Dp_.FDq_.E2Dr_!r9/}YRt_@TJu_Bdeb/Btjw_#r-b/+}Y8˵<ޗUFe-"/k}Qߗ}ߗ}y/EaXp|yV< _/Z`5c&|y<_u/7?AIdc}y
-&_n=Η@O頛}y艾<$_z/=ŗn幠<|y>龼 _n=ӗˋ@Šs}y)y|_^z/ +A/UjЋ}y-%ԗׂ^@/W+}y##҅ϫ/GI2=ٶJ9rzea폕tD/f>|9p-&JiZ$oPK
-    [6b,     (   com/thoughtworks/qdox/parser/Lexer.classEON@iR8Rib[ll`5| FCbppIKB
->xcVaJH<O/]:o*4=AU30TG[w0l!׶s?ZliƁ]\E)^կ-fǅ%crvL k3HEp"D1Is&}#PK
-    [6c[    1   com/thoughtworks/qdox/parser/ParseException.classSnQ=B+|XZa֏6cS45Mc..AI&>e{AZ?3sΜ9g_~ e$.ᆌ ֹ)EQ^EF榄[6B=2X!Ҵ{þŠc;O-;tl?ZO:ھV>?0-{Ȑ)c}A-B?	@ti2uMh}Nh;\}>ݣ1L"RMcx-!&X*wCiԭͰCS3E2̖\*A>16xefH>ۆ<GQe)VQ$R%P0dO--쟽5>V귓s	oR+qIWkK \|^MUo'`w^ X#ɏIJx`aA-|iBB_&ߢ)NfrąR6FWc,|dJ@+)4efe9ۼyOlNW:L+*EeP5=霩ҫX!'#KPK
-    [6H    2   com/thoughtworks/qdox/parser/structs/AnnoDef.classTmsU~nf͖B!(ͮ+PE,o$d7l*OpƆ8~8%48:r=9y6˯HU4M1ƻ#H=3&,71L\d3ydbl\
-|U,e>fޕ4Vy6-|*te[	䖷wnIaiq~+0!GZvgu=׶uM۵ԽvG]]5ݵ9ڤ9DN^]1ՠ]U-Ymy5Z2URw٢DaOת[g(Wl*v
-2*hn3Z-/]Hx#!:|Wݠ&=ln*1׼E{bN8xA`U*X"^p
-*rk
-(aڦ\ϰfn▅/𥁯,|oܶ ՉYP	"OlchnDtK_GMpW}/T(\[STSEt5<I;=:%\⪺{A[9Ho/RnC7IkuRZ-4?åi$Xp%њɕtF#Rnhc$o>R%'r9zdG`28}C ;2AoHT~6&蔢SsFP&!c,8!xWB@
--ўv&<-XO{˧"2%J-{(GylϜ?`1vqX`#8[sń@Gs(C=O{8AY!
-9+>Ghq'hyb$j4iNx#~[>[ԝaw PK
-    [6g    3   com/thoughtworks/qdox/parser/structs/ClassDef.classoSUƟKBv-" `񿂵i
-MCK }c,&F·3:>wwtF'===$<{ǟŪO8>5Ǫ7RTM%eoiX3lee5|n`jBGE::6{G]RX	+7fk{ZފXɱ=ߴHdZ_Z/tl	תx!/VbYsufO=sZVےǸ0B|i0^+{)w}>Xl˿..4[rZRbٲ:JnvwfafXY4^8~Gz-x;h^5=l)!.Uesw_6qvO,:Л=t;	_.U+AA-]5g6庥q{Iŧł Rxs' 
-E\JZpU__p/H]'0s6s
-R@dÁȄ=2q=ذ:VPemMuizҍ
-{>jr*<j1o,$^gR!}!ufHc^^-8\sT}pDv	D.=rX);O0zĉz.<k7u		<1qMlPdR)b_8w{w&!RJeP?bnncqJ5MS?!̠0J&E	E$[&eý݈n+@6:hh(BʞM]zsck<K;Yɇ713N-Xi=Їxc%8:`S1ˉ4dY$|H"#7{z&$oQ[ޕPK
-    [6~c{  <  3   com/thoughtworks/qdox/parser/structs/FieldDef.classT]se~6]4VZ54۲7-XP
-/fI&[lݨ?7-7\茄a?AxPZ-^9yyϿ{ -3~̚ +1o*pRp
-a-*YjG7d!Y%)M,+&.*|zkK綼N]CӘ]|sw2Snɪmىkq~tO-?gjP)=wVFBP*ߑxV$y-F3\nfM~7F2t8]e~F]Vz->)mRu])ӂ&zmơfʘYivk=QtwmM+A7E_9o5qLx_"'+x!u;cӘQĤ6ࠍxS`tw6VpEJp/ۨZqh-9'jб'-3S:ؐn|vKϹ?g[ӈ䗷@B͇P#JNN$9d_PrSd)_'?{B.Dwa$zeP߂ʬÀ9rLAmK-e8INxwbL_&Dz=D{nHՠj`o@4D4t~vg&\BP$2EA[:7Oj'e7wUXMshf!2>MMm٪OGzyyq_8b*NtO?!FỌmn4{xG-)8=2;.ɥs-ƒI2a$ F}TGe.c1oUcPK
-    [6   b  5   com/thoughtworks/qdox/parser/structs/LocatedDef.classON0פ	BK-b"@4.iG!^B՝|wwB#L3>)&)v	Ym}.tMHLc9!?[j8_eQ3ͭL:xIRʶ*Zsiēt^;kUk;:L?:^9B YKtӢ\01+D IoFGl1Ʒ/PK
-    [6Z(    4   com/thoughtworks/qdox/parser/structs/MethodDef.classTkSe~.--*
-`kI뭭Bm-B/^$YLt|?ؙBggy]nJL9{Ξ9_ghx_Yp40e\13W&Ŵ>-%ܐ'3J8k`B/&TϤļ2pҥU[Xw+0+FjUosGvՋnȸ5'ptJ^K,w⮅/$+TaЮ~  ]nu)-5𒀖-tʯjζe7늷_qNIacӥ(5R7^$ۖ#"ːwYVo;u>۟א[	sՃ݊G;̚ӪEY 2C?j@_6wXծl//l*UOVڽK~L>`# lǰ1,г7ild0"лΆ7pIx_-ܶqc-dm|]ܓ)Hܣ03a-26rs8/PO<2n4<pMwfU`|
-٩HO9%rnҜ'c(+S:-n (/\?ȧ[Д/q9:`4ivm;M-Oh(0_
-IrNtcrU("%i<az̌>#ѽ[D:5"M',
-DIBǉl"4S4S`菡k?Ҷ]LD#(wIvyui&#=͞`z)v@'cބǨSeװ݆qz9R!lb!ʢvqH^=R<.!۾0MRlEir
-_Uވy2^S'q0p&Åʍpq&l$=,k̂|gødmnPK
-    [60    1   com/thoughtworks/qdox/parser/structs/TagDef.classT]OQ=meCdjE	Olۥ-.lʟ/>h"%2νh0Mggs̶?~~	XBf2B%F77Ø"7w`Z=f&YaX¶4fbNQ;wBF͝gHOV2TlmPkXO[;EY3udxnd(íڭJ}m;/^7vMi9FuZ%i;
-r~!ke	xɳUrg2/$,%պ R5UoP)!|ŵ=d:s!j$`RkkrXv)Yj\oIs*S"F ʅ1b0p:XCPRq5~:3aVYGj'IswjFuʝWz ʒǸGⒽ@Q2dz&`Y l Rv 'Q?Hv 2#<z!:z <Ǆ£Ϝ#_SĻf\#!@мAP|u)y;BOri"~""ID	dw!KN0裩;ou8z|"=`CT69HH$- +fo(CDz|-knsXn#Mf(XI4Ms44M1$6.@}B
-(#CPK
-    [6UoI    2   com/thoughtworks/qdox/parser/structs/TypeDef.classN@[AT<-PhLƄBevqX2Vg2ϯdp9Eݘ6bȆ<?rwCZ1=#u2p}}2Od(Szo9 ҕJ}>ǧD&^$XTcI}gwu$:ą3T=q)-Yf#Qp"g]'2 t@eN~mROLvXTTZo`9WJY0_c-QSUa**3HoPK
-    [6w      $   com/thoughtworks/qdox/Searcher.class;o>f]NvvvFԲF--\b
-}ĲDbk(FҢT̜TFĢ","F9T12$'e&120201 ##y, +db` PK
-    [6D  A  .   com/thoughtworks/qdox/tools/QDoxTester$1.classR]o0=-͚(( Lm0HC	m+JSxbpܭE<OCB\
-Z}}rϹqwTp3:nh㖏ۄIe~HuTMRs>42JeEN&F&,si6-ަ	B/sfr0z7f4*A=@Ϛ$nЛY\5k,y)N?>#"8Ox/bF{G[EvD'h_6/"!Pq'*Sm8ߋ"1#Gq6Y+PPؖWK%HƯUA
-?ϳa=%\-t/(%^-XGМ)2gz_QK_BLn3'bry\pFj6KSeg
-kXĭPK
-    [6¼`    <   com/thoughtworks/qdox/tools/QDoxTester$ConsoleReporter.classVkse~6IM\hMJB,%"bAP
-@BC mmݍO^fQˌVgͨx-&%cfzss{_'F)a/yANI&83L
-r6ᤌ8	r^hd(2.ʘ.q3˸"cVU/ɘq-+Vŕ9fu+;m;ښZ:&!T
-q$H9JKnTlMBfۖ-!hU[w]ugJ7m={B®tӸ""MۄǅJiAĔUPYօ\F\e:]ʖjLS'q4*X[*EwͲWkͬkYtں:5bVC5А(@mӱNKڎ6٣&sI"߸eTJ&ɱdr/֚h%n6XTJ%~CB|ƪmR>moS)WAAX
-T,((EIjy$F]ÒeG-KK5N49(V␂>JNHSX댿)A=T>=_(	GHh}qaE+1e2V=\gM[YHܓt-G˒Qq\\LnP5vφ ##ݎ{ҹ'lWy[-z?X=-H/8zg+q4Mi!=H-~lHw{d(uq"+YAL~*pd~aE"6i(d">REk=c e[؍XDZ4(32$ȄI$2w,	V|\AH/$SAX@6!x
-eUbVMoVўxL`d#uc$)lS<>|;#?/#l&F3AoR#tboX ) v6"HƷpp8xmT{M0>FDɦn_T;+}f=dB&`B,~G'Ϝ/[vg=(>g=z}^zW[cPK
-    [6G1     5   com/thoughtworks/qdox/tools/QDoxTester$Reporter.classMN0!вQ$X*EBB{7C{6B8لEߓg{?!ViJ
-\\?mԗZ\:.~*o[BWL$FlXঃwZSEKSqJBiG_uw5b* S!]n,w;V~th+[rA[Z'eI=mPkPG V!FC|qsF8fNp PK
-    [6-94B
-  +  ,   com/thoughtworks/qdox/tools/QDoxTester.classW	|UOٝLvKKQ4-fۦ@HIZ6I)-)PNiwwl (P?EZ`mQTo/7fn5߼yJDvPqw&5l-aŻT[Cj܎bx
-T_C-nЎ;0_ܭQ4|RqEUhpPQQ-1{5,LаO-qP2/T(hh&A>!TG4bt<gQnCxT#T<&=-_T`/nW7Bfov;bsv<QwrӞ1\tUPAhj3+Rv6-!ovW푤g7yQ=tY?y<[σzy~ꠂy]=F2c yCgϷrצ`u	ӸMANA3{~jgHt)#p, !UphԐڽl42wʲ ]e-y>ݼge&wLPZ{cYb:
-H55ӵ(P)ͷcULTetu|tϲs֍a 8~DE1S-<L[L$7e@)8g9ݦqJH%iBpXTk(c`+a.[h,mG5ÆE4rR9-؅ uJ,(J5,\pٱ;⯓|3/6{mA$ʒ`Y4)ۊ
-Θc{|.=-#+;)v]	!@ŏu7(<XzlaLc;*SL<%u\sA":v*~_7LK[nr$FLGgn??3V+-wvX#LfJW_,q"y_u-g(m<-xm2XL_lrLa{B?O¿u<4@BaO]P*U%+UJŴzC_DTu^r&PPUWB&Y5V	樎'JmO2xQI^Ʊ
-XuE"Pp:#5$69f6~3*S/xvH/BCxDSvc!4xpƜ@su%hbZT+AL}oCeW)te(BR+\.#tG!Hv콹|F'^ͤEpg
-%=^'X]{Iм2qVbEĊ5IZ*TΝ] yI$
-o.k3Zcdi:{6hzݦ+आr9ae&,(A;vu3+em&gxęM<$f5rR)J6s|_Uڢ)!>4FU2Ka#l+g&Z˫˒f"sZ$f(͟
-ײc9f1#+vFxHOL	Y&G\%(xw	sngY:ް2yeYUxڐJjwVRNM{%L!k~2]#hdiA/&-=w!nYʔEu,gkyT "4
- TP9^zU5=<{~k~q&vr+J)M:{Bs<GixZOaT+:	Ø
-ios
-W@$2:Uaa]U'TPGG_ u#F/oqf)+Un!*)%=lC|m\yk`b Uib>Gv#Cϳp/ǟ]I4ͥX$bR)}SpZs)xIѩDx8je[iV41*朂+tnшxNH\2%3c"q7.cgQ0בB&-]-H6qw#hVWyK-)Fkey;'yaޖq,%{Ǳohch(q{M({䪹8%#YŝډXYH$g;{#~rNN^ҷۉfv35}݃1FGT*JW715Or}%`~\z-U泀8NDd-+ ~sܾq(**<BJF^:x.Z+N׎/vz:Z]VQySx$u(6NRcX²iJ(aYE+TF_&.GzSJ몊QC|R60=6v>9FtufV፬;Y
-!#g,^]hy\MבO2ŵ"{Jב]]ڐOU	|EbTPuT^db·,v {&IЋt"Ƿ`V{kR\0Q(PK
-     [6               META-INF/maven/PK
-     [6            %   META-INF/maven/com.thoughtworks.qdox/PK
-     [6            *   META-INF/maven/com.thoughtworks.qdox/qdox/PK
-    Z6@o	  6+  1   META-INF/maven/com.thoughtworks.qdox/qdox/pom.xml]o6}*1nC&9lm}
-hKJRv"ۉ^s8E-iCd0S88# ь\$5~y Y\.;wtpp,UKQ0` |`acF#C`0~>CljX"xY\ģg2%skjZؔD
-v0>|7og`N'{"x5ԓHGNZM7)wƊ+#1ddAi-IS4\
-DH*  }PmQ)1SPQ=F1-$
-!KQ4e)fSPSREђ$r#"х ,iGJ	'H＠HSA_1ʌʘĸ%97ao4Z"K*UVˌƨИOՒ,:VTYY|,MO,vgL*&GЂ>r=v끴1)KzMrP/B>JE=dM[=0,<|))+#Ý-4TFň9. "?H77жa=﾿[Q$c)/8ݛv&^@Vϩl^1G㦹]r>4ePєyLOQk)%qÎ*pn-'dJ#Ma)lrB}Vmlݐ2EI\u*`ofY2Orq7$]K`I=s-cKm-LϞqI@ $w&r	?uH|g2?hnx6TLt&ԚK;3?}\Glgda{#G}Ew\8fk 혔,ut9N-jw5SdDxIm^ZVx	tE;IuثT PEFjEk1Kn3&  q8	t',E!=BKjyF>DKHKȡW~تb("Q-ߔ% q$e"҇ Lh邨`7tӔ>65n@pDM-HZ  	᛿\NKJOO%4)HlM$˞|ó hhlRp1Z SLI݇YSR99zHrNn[%N~Ӑ'oh5>Z
-G&	`Pq]hn<om"RP=BpwpFm\-\LTѬ_ 	-G*$~谊_7qNRٱ-C`ZYc-Ű\t]6P%Tڰ}Ṭq'JCw6g{ST3)x] ,u#Ia$&ӭ
-m=Z?0bZPqmTS$swL̵utFk~,2!^T~.>H(E{e2(%4D7æ;v8'Aj6q[F8wЊf}wßN{FO=vGlFO=矣)ؔA1_J7ڜWn#r-N`5pMH勱r]-B=!/j|-%nkpjOuױs-T_-#eºKG=lZmהIp=bMҁi׶w:߅--7qp_l3cEMpب󎹑o̪w"Y\_{V'7vS<5-ARt[yɢ~M#]mm{6_CBWp6c~=ύ7>׭rCaHˇIxOIѕ]Fk'|nHᢿ[GUNc5VЧS"U-24jjHrM/%cZ>W˿f iO%%Qa.g.;X>eAnN,Ҙ6K:G~PulnF8$H~Kٌk(T6li64᱂y}-	/[RwrՁm,\Q'#k_^Ba[*e9=-)tTV㪩>\U !sPla i.E.` |Ⓛi05[k
-=V%䝧3'T<^P-y_BgWoۋyܦWvH9PK
-    [6k   n   8   META-INF/maven/com.thoughtworks.qdox/qdox/pom.propertiesSvOK-J,IMQHTM,KRv+T*S04U042224Rp
-Q0200*K-*ϳ533J//-LM+/M()/.+LɯJ,*LKL.* PK
-     [6            	          A    META-INF/PK
-    [6.tf   |              '   META-INF/MANIFEST.MFPK
-     [6                      A   com/PK
-     [6                      A   com/thoughtworks/PK
-     [6                      A  com/thoughtworks/qdox/PK
-     [6                      AD  com/thoughtworks/qdox/ant/PK
-     [6            &          A|  com/thoughtworks/qdox/directorywalker/PK
-     [6                      A  com/thoughtworks/qdox/junit/PK
-     [6                      A  com/thoughtworks/qdox/model/PK
-     [6            !          A4  com/thoughtworks/qdox/model/util/PK
-     [6                      As  com/thoughtworks/qdox/parser/PK
-     [6            "          A  com/thoughtworks/qdox/parser/impl/PK
-     [6            %          A  com/thoughtworks/qdox/parser/structs/PK
-     [6                      A1  com/thoughtworks/qdox/tools/PK
-    [6R-    0           k  com/thoughtworks/qdox/ant/AbstractQdoxTask.classPK
-    [6=}  {  >             com/thoughtworks/qdox/directorywalker/DirectoryScanner$1.classPK
-    [6&/  	  <             com/thoughtworks/qdox/directorywalker/DirectoryScanner.classPK
-    [6?      7             com/thoughtworks/qdox/directorywalker/FileVisitor.classPK
-    [6KED      2           ~  com/thoughtworks/qdox/directorywalker/Filter.classPK
-    [683[O    8           a  com/thoughtworks/qdox/directorywalker/SuffixFilter.classPK
-    [6N'    ,           ]  com/thoughtworks/qdox/JavaDocBuilder$1.classPK
-    [6`"'  7  *           x  com/thoughtworks/qdox/JavaDocBuilder.classPK
-    [6(Ģ  9  /           s2  com/thoughtworks/qdox/junit/APITestCase$1.classPK
-    [6讗 -    -           4  com/thoughtworks/qdox/junit/APITestCase.classPK
-    [6R͂  
-  ?            B  com/thoughtworks/qdox/model/AbstractInheritableJavaEntity.classPK
-    [6_ݶw
-  r  4           C  com/thoughtworks/qdox/model/AbstractJavaEntity.classPK
-    [6Ȋ/  >	  ,           N  com/thoughtworks/qdox/model/Annotation.classPK
-    [6ZK  )  .           !S  com/thoughtworks/qdox/model/BeanProperty.classPK
-    [6d  E-  .           U  com/thoughtworks/qdox/model/ClassLibrary.classPK
-    [6C8e>    2           [  com/thoughtworks/qdox/model/DefaultDocletTag.classPK
-    [620{  H  9           x_  com/thoughtworks/qdox/model/DefaultDocletTagFactory.classPK
-    [6U>%    +           a  com/thoughtworks/qdox/model/DocletTag.classPK
-    [6R     2           c  com/thoughtworks/qdox/model/DocletTagFactory.classPK
-    [6:+  B  .           +d  com/thoughtworks/qdox/model/IndentBuffer.classPK
-    [6&ToG  8  +           g  com/thoughtworks/qdox/model/JavaClass.classPK
-    [6$'   "  0           ~  com/thoughtworks/qdox/model/JavaClassCache.classPK
-    [6a     1             com/thoughtworks/qdox/model/JavaClassParent.classPK
-    [6vL  	  +           ܀  com/thoughtworks/qdox/model/JavaField.classPK
-    [6a  &   ,           (  com/thoughtworks/qdox/model/JavaMethod.classPK
-    [6_j  )  /             com/thoughtworks/qdox/model/JavaParameter.classPK
-    [6To    ,           ߖ  com/thoughtworks/qdox/model/JavaSource.classPK
-    [6      (           ΢  com/thoughtworks/qdox/model/Member.classPK
-    [67/  %  .           ģ  com/thoughtworks/qdox/model/ModelBuilder.classPK
-    [6P  t  &             com/thoughtworks/qdox/model/Type.classPK
-    [6Jy!    7             com/thoughtworks/qdox/model/util/OrderedMap$Entry.classPK
-    [6l    <           |  com/thoughtworks/qdox/model/util/OrderedMap$OrderedSet.classPK
-    [6w91    1             com/thoughtworks/qdox/model/util/OrderedMap.classPK
-    [6ė  	  0             com/thoughtworks/qdox/model/util/TagParser.classPK
-    [6E-%  ^  *             com/thoughtworks/qdox/parser/Builder.classPK
-    [6ԟ8,  )X  2             com/thoughtworks/qdox/parser/impl/JFlexLexer.classPK
-    [6      0             com/thoughtworks/qdox/parser/impl/Parser$1.classPK
-    [6n    4             com/thoughtworks/qdox/parser/impl/Parser$Value.classPK
-    [6>h
-H  7  .             com/thoughtworks/qdox/parser/impl/Parser.classPK
-    [6b,     (           D com/thoughtworks/qdox/parser/Lexer.classPK
-    [6c[    1           F com/thoughtworks/qdox/parser/ParseException.classPK
-    [6H    2           H com/thoughtworks/qdox/parser/structs/AnnoDef.classPK
-    [6g    3           L com/thoughtworks/qdox/parser/structs/ClassDef.classPK
-    [6~c{  <  3           P com/thoughtworks/qdox/parser/structs/FieldDef.classPK
-    [6   b  5           _T com/thoughtworks/qdox/parser/structs/LocatedDef.classPK
-    [6Z(    4           U com/thoughtworks/qdox/parser/structs/MethodDef.classPK
-    [60    1           Y com/thoughtworks/qdox/parser/structs/TagDef.classPK
-    [6UoI    2           ] com/thoughtworks/qdox/parser/structs/TypeDef.classPK
-    [6w      $           ^ com/thoughtworks/qdox/Searcher.classPK
-    [6D  A  .           p_ com/thoughtworks/qdox/tools/QDoxTester$1.classPK
-    [6¼`    <           a com/thoughtworks/qdox/tools/QDoxTester$ConsoleReporter.classPK
-    [6G1     5           Ef com/thoughtworks/qdox/tools/QDoxTester$Reporter.classPK
-    [6-94B
-  +  ,           g com/thoughtworks/qdox/tools/QDoxTester.classPK
-     [6                      Ar META-INF/maven/PK
-     [6            %          A@r META-INF/maven/com.thoughtworks.qdox/PK
-     [6            *          Ar META-INF/maven/com.thoughtworks.qdox/qdox/PK
-    Z6@o	  6+  1           r META-INF/maven/com.thoughtworks.qdox/qdox/pom.xmlPK
-    [6k   n   8           | META-INF/maven/com.thoughtworks.qdox/qdox/pom.propertiesPK    H H .  J}   
\ No newline at end of file
Index: src/java/org/apache/fop/render/pdf/pdfbox/AbstractPDFBoxHandler.java
===================================================================
--- src/java/org/apache/fop/render/pdf/pdfbox/AbstractPDFBoxHandler.java	(revision 1575872)
+++ src/java/org/apache/fop/render/pdf/pdfbox/AbstractPDFBoxHandler.java	(working copy)
@@ -33,6 +33,7 @@
 
 import org.apache.fop.apps.FOUserAgent;
 import org.apache.fop.events.EventBroadcaster;
+import org.apache.fop.fonts.FontInfo;
 import org.apache.fop.pdf.PDFDocument;
 import org.apache.fop.pdf.PDFFormXObject;
 import org.apache.fop.pdf.PDFPage;
@@ -64,7 +65,7 @@
             = Collections.synchronizedMap(new WeakHashMap<Object, Cache<String, Map<Object, Object>>>());
 
     protected PDFFormXObject createFormForPDF(ImagePDF image,
-            PDFPage targetPage, FOUserAgent userAgent, AffineTransform at) throws IOException {
+            PDFPage targetPage, FOUserAgent userAgent, AffineTransform at, FontInfo fontinfo) throws IOException {
 
         EventBroadcaster eventBroadcaster = userAgent.getEventBroadcaster();
         String originalImageUri = image.getInfo().getOriginalURI();
@@ -105,7 +106,7 @@
 
         PDFBoxAdapter adapter = new PDFBoxAdapter(targetPage, objectCache);
         PDFFormXObject form = adapter.createFormFromPDFBoxPage(pddoc, page, originalImageUri,
-                eventBroadcaster, at);
+                eventBroadcaster, at, fontinfo);
         return form;
     }
 
Index: src/java/org/apache/fop/render/pdf/pdfbox/ImageConverterPDF2G2D.java
===================================================================
--- src/java/org/apache/fop/render/pdf/pdfbox/ImageConverterPDF2G2D.java	(revision 1575872)
+++ src/java/org/apache/fop/render/pdf/pdfbox/ImageConverterPDF2G2D.java	(working copy)
@@ -26,11 +26,12 @@
 import java.io.IOException;
 import java.util.Map;
 
-import org.apache.pdfbox.pdfviewer.PageDrawer;
+
 import org.apache.pdfbox.pdmodel.PDDocument;
 import org.apache.pdfbox.pdmodel.PDPage;
 import org.apache.pdfbox.pdmodel.common.PDRectangle;
 
+import org.apache.pdfbox.rendering.PageDrawer;
 import org.apache.xmlgraphics.image.loader.Image;
 import org.apache.xmlgraphics.image.loader.ImageException;
 import org.apache.xmlgraphics.image.loader.ImageFlavor;
@@ -129,8 +130,8 @@
                         area.getHeight() / pageDimension.height);
                 g2d.transform(at);
 
-                PageDrawer drawer = new PageDrawer();
-                drawer.drawPage(g2d, page, pageDimension);
+                PageDrawer drawer = new PageDrawer(null);
+                drawer.drawPage(g2d, page, mediaBox);
             } catch (IOException ioe) {
                 //TODO Better exception handling
                 throw new RuntimeException("I/O error while painting PDF page", ioe);
Index: src/java/org/apache/fop/render/pdf/pdfbox/MergeCFFFonts.java
===================================================================
--- src/java/org/apache/fop/render/pdf/pdfbox/MergeCFFFonts.java	(revision 0)
+++ src/java/org/apache/fop/render/pdf/pdfbox/MergeCFFFonts.java	(working copy)
@@ -0,0 +1,422 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.fop.render.pdf.pdfbox;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.fontbox.cff.CFFFont;
+import org.apache.fontbox.cff.CFFParser;
+import org.apache.fontbox.cff.charset.CFFCharset;
+import org.apache.fontbox.cff.charset.CFFISOAdobeCharset;
+import org.apache.fontbox.cff.encoding.CFFEncoding;
+import org.apache.fontbox.cff.encoding.CFFStandardEncoding;
+
+import org.apache.fop.fonts.cff.CFFDataReader;
+import org.apache.fop.fonts.truetype.FontFileReader;
+import org.apache.fop.fonts.truetype.OTFSubSetFile;
+
+public class MergeCFFFonts extends OTFSubSetFile {
+
+    protected List<CFFDataReader> cffReaderList = new ArrayList<CFFDataReader>();
+    protected List<LinkedHashMap<Integer, Integer>> subsetGlyphsList = new ArrayList<LinkedHashMap<Integer, Integer>>();
+    private boolean fallbackIndex;
+    private int charsetOffset;
+
+    static class FontContainer {
+        final CFFFont font;
+        final FontFileReader fontFile;
+        FontContainer(CFFFont f, FontFileReader r) {
+            font = f;
+            fontFile = r;
+        }
+    }
+
+    public MergeCFFFonts() throws IOException {
+    }
+
+    public void readType1CFont(List<InputStream> streams, String embeddedName) throws IOException {
+        this.embeddedName = embeddedName;
+        int fontFileSize = 0;
+        Map<Set, FontContainer> fontMap = new HashMap<Set, FontContainer>();
+        for (InputStream is : streams) {
+            fontFile = new FontFileReader(is);
+            CFFParser p = new CFFParser();
+            CFFFont ff = p.parse(fontFile.getAllBytes()).get(0);
+            fontFileSize += fontFile.getFileSize();
+            FontContainer fc = new FontContainer(ff, fontFile);
+            fontMap.put(ff.getCharStringsDict().keySet(), fc);
+        }
+        Set<String> used = new HashSet<String>();
+        for (Map.Entry<Set, FontContainer> ff : fontMap.entrySet()) {
+            if (used.containsAll(ff.getKey())) {
+                continue;
+            }
+            used.addAll(ff.getKey());
+            fileFonts.add(ff.getValue().font);
+            LinkedHashMap<Integer, Integer> sg = new LinkedHashMap<Integer, Integer>();
+            for (int i = 0; i < ff.getValue().font.getCharset().getEntries().size() + 1; i++) {
+                sg.put(i, i);
+            }
+            subsetGlyphsList.add(sg);
+            cffReaderList.add(new CFFDataReader(ff.getValue().fontFile));
+        }
+        output = new byte[fontFileSize];
+        if (fileFonts.size() == 1) {
+            writeBytes(fontFile.getAllBytes());
+            return;
+        }
+        cffReader = cffReaderList.get(0);
+        subsetGlyphs = subsetGlyphsList.get(0);
+        createCFF();
+    }
+
+    @Override
+    protected void createCFF() throws IOException {
+        //Header
+        writeBytes(cffReader.getHeader());
+
+        //Name Index
+        writeIndex(Arrays.asList(fileFonts.get(0).getName().getBytes("UTF-8")));
+
+        //Keep offset of the topDICT so it can be updated once all data has been written
+        int topDictOffset = currentPos;
+        //Top DICT Index and Data
+        byte[] topDictIndex = cffReader.getTopDictIndex().getByteData();
+        int offSize = topDictIndex[2];
+        writeBytes(topDictIndex, 0, 3 + (offSize * 2));
+        writeTopDICT();
+        createCharStringData();
+
+        //String index
+        writeStringIndex();
+
+        Map<String, CFFDataReader.DICTEntry> topDICT = cffReader.getTopDictEntries();
+        final CFFDataReader.DICTEntry charString = topDICT.get("CharStrings");
+        final CFFDataReader.DICTEntry encodingEntry = topDICT.get("Encoding");
+
+        int encodingOffset;
+        if (encodingEntry != null && charString.getOffset() > encodingEntry.getOffset()) {
+            charsetOffset = currentPos;
+            if (!fallbackIndex) {
+                charsetOffset += 2;
+            }
+            writeCharsetTable(cffReader.getFDSelect() != null, !fallbackIndex);
+            encodingOffset = currentPos;
+            writeEncoding();
+        } else {
+            writeCard16(0);
+            encodingOffset = currentPos;
+            writeEncoding();
+            charsetOffset = currentPos;
+            writeCharsetTable(cffReader.getFDSelect() != null, false);
+        }
+
+        //Char Strings Index
+        int charStringOffset = currentPos;
+        writeIndex(subsetCharStringsIndex);
+
+        //Keep offset to modify later with the local subroutine index offset
+        int privateDictOffset = currentPos;
+        writePrivateDict();
+
+        //Local subroutine index
+        int localIndexOffset = currentPos;
+        if (!subsetLocalIndexSubr.isEmpty()) {
+            writeIndex(subsetLocalIndexSubr);
+        }
+
+        //Update the offsets
+        updateOffsets(topDictOffset, charsetOffset, charStringOffset, privateDictOffset, localIndexOffset, encodingOffset);
+    }
+
+    protected void writeEncoding() throws IOException {
+        List<Integer> chars = new ArrayList<Integer>();
+        for (CFFFont ff : fileFonts) {
+            CFFEncoding encoding = ff.getEncoding();
+            if (encoding instanceof CFFStandardEncoding) {
+                LinkedHashMap<String, CFFDataReader.DICTEntry> topDICT = cffReader.getTopDictEntries();
+                final CFFDataReader.DICTEntry encodingEntry = topDICT.get("Encoding");
+                if (encodingEntry != null && encodingEntry.getOperands().get(0).intValue() != 0
+                        && encodingEntry.getOperands().get(0).intValue() != 1) {
+                    int len = encoding.getEntries().size();
+                    if (len != gidToSID.size() - 1) {
+                        return;
+                    }
+                    writeByte(0);
+                    writeByte(len);
+                    for (Map.Entry<Integer, Integer> gid : gidToSID.entrySet()) {
+                        if (gid.getKey() == 0) {
+                            continue;
+                        }
+                        int code = encoding.getCode(gid.getValue());
+                        writeByte(code);
+                    }
+                }
+            } else {
+                for (CFFEncoding.Entry e : encoding.getEntries()) {
+                    int c = e.getCode();
+                    if (!chars.contains(c)) {
+                        chars.add(c);
+                    }
+                }
+            }
+        }
+        if (!chars.isEmpty()) {
+            writeCard16(chars.size());
+            for (int i : chars) {
+                writeByte(i);
+            }
+        }
+    }
+
+    protected void writeStringIndex() throws IOException {
+        gidToSID = new LinkedHashMap<Integer, Integer>();
+        List<String> strings = new ArrayList<String>();
+        int listIndex = 0;
+        for (LinkedHashMap<Integer, Integer> subsetglyph : subsetGlyphsList) {
+            CFFFont cffFont = fileFonts.get(listIndex);
+            cffReader = cffReaderList.get(listIndex);
+            int subsetGlyphIndex = 0;
+            for (CFFCharset.Entry e : cffFont.getCharset().getEntries()) {
+                int sid = e.getSID();
+                int gid = subsetglyph.get(subsetGlyphIndex);
+
+                //Check whether the SID falls into the standard string set
+                if (sid < NUM_STANDARD_STRINGS) {
+                    gidToSID.put(subsetglyph.get(gid), sid);
+                } else {
+                    int index = sid - NUM_STANDARD_STRINGS;
+                    if (index <= cffReader.getStringIndex().getNumObjects()) {
+                        gidToSID.put(subsetglyph.get(gid), stringIndexData.size() + NUM_STANDARD_STRINGS - 1);
+                        String data = new String(cffReader.getStringIndex().getValue(index), "US-ASCII");
+                        if (!strings.contains(data)) {
+                            strings.add(data);
+                        }
+                    } else {
+                        gidToSID.put(subsetglyph.get(gid), index);
+                    }
+                }
+                subsetGlyphIndex++;
+            }
+            listIndex++;
+        }
+
+        for (String s : strings) {
+            stringIndexData.add(s.getBytes("US-ASCII"));
+        }
+
+        //Write the String Index
+        if (!stringIndexData.isEmpty()) {
+            if (!strings.isEmpty() && !new String(stringIndexData.get(0), "UTF-8").equals(strings.get(0))) {
+                //Move copyright string to end
+                stringIndexData.add(stringIndexData.remove(0));
+            } else {
+                CFFFont f = fileFonts.get(0);
+                String notice = (String)f.getProperty("Notice");
+                if (notice != null) {
+                    stringIndexData.add(notice.getBytes("ISO-8859-1"));
+                }
+            }
+            stringIndexData.add(embeddedName.getBytes("UTF-8"));
+            writeIndex(stringIndexData);
+        } else {
+            CFFFont f = fileFonts.get(0);
+            String notice = (String)f.getProperty("Notice");
+            if (notice != null) {
+                writeIndex(Arrays.<byte[]>asList(notice.getBytes("ISO-8859-1"), embeddedName.getBytes("UTF-8")));
+            } else {
+                List<byte[]> sindex = new ArrayList<byte[]>();
+                sindex.add(cffReader.getStringIndex().getData());
+                if (sindex.size() > 1) {
+                    fallbackIndex = true;
+                    writeIndex(sindex);
+                } else if (sindex.size() == 1) {
+                    writeIndex(Arrays.asList(embeddedName.getBytes("UTF-8")));
+                } else {
+                    writeCard16(0);
+                }
+            }
+        }
+        cffReader = cffReaderList.get(0);
+    }
+
+    protected void createCharStringData() throws IOException {
+        //Create the new char string index
+        List<String> added = new ArrayList<String>();
+        subsetCharStringsIndex = new ArrayList<byte[]>();
+        for (int i = 0; i < subsetGlyphsList.size(); i++) {
+            cffReader = cffReaderList.get(i);
+            Map<String, CFFDataReader.DICTEntry> topDICT = cffReader.getTopDictEntries();
+            final CFFDataReader.DICTEntry privateEntry = topDICT.get("Private");
+            if (privateEntry != null) {
+                int privateOffset = privateEntry.getOperands().get(1).intValue();
+                Map<String, CFFDataReader.DICTEntry> privateDICT = cffReader.getPrivateDict(privateEntry);
+
+                if (privateDICT.containsKey("Subrs")) {
+                    int localSubrOffset = privateOffset + privateDICT.get("Subrs").getOperands().get(0).intValue();
+                    localIndexSubr = cffReader.readIndex(localSubrOffset);
+                }
+            }
+
+            globalIndexSubr = cffReader.getGlobalIndexSubr();
+
+            for (Map.Entry<String, byte[]> s : fileFonts.get(i).getCharStringsDict().entrySet()) {
+                if (!added.contains(s.getKey())) {
+                    subsetCharStringsIndex.add(s.getValue());
+                    added.add(s.getKey());
+                }
+            }
+        }
+        //Create the two lists which are to store the local and global subroutines
+        subsetLocalIndexSubr = new ArrayList<byte[]>();
+        subsetGlobalIndexSubr = new ArrayList<byte[]>();
+
+        localUniques = new ArrayList<Integer>();
+        globalUniques = new ArrayList<Integer>();
+
+        //Store the size of each subset index and clear the unique arrays
+        subsetLocalSubrCount = localUniques.size();
+        subsetGlobalSubrCount = globalUniques.size();
+        localUniques.clear();
+        globalUniques.clear();
+
+        cffReader = cffReaderList.get(0);
+    }
+
+    protected void writeCharsetTable(boolean cidFont, boolean afterstringindex) throws IOException {
+        Map<Integer, Integer> range = new LinkedHashMap<Integer, Integer>();
+        Set<String> strings = new HashSet<String>();
+        for (CFFFont ff : fileFonts) {
+            CFFCharset cSet = ff.getCharset();
+            String cClass = cSet.getClass().getName();
+            if (cClass.equals("org.apache.fontbox.cff.CFFParser$Format1Charset")
+                    || cClass.equals("org.apache.fontbox.cff.CFFParser$Format0Charset")) {
+                for (CFFCharset.Entry m : cSet.getEntries()) {
+                    if (!strings.contains(m.getName())) {
+                        range.put(m.getSID(), 0);
+                        strings.add(m.getName());
+                    }
+                }
+            } else {
+                writeByte(0);
+                for (Map.Entry<Integer, Integer> gid : gidToSID.entrySet()) {
+                    if (cidFont && gid.getKey() == 0) {
+                        continue;
+                    }
+                    writeCard16((cidFont) ? gid.getKey() : gid.getValue());
+                }
+                break;
+            }
+        }
+        if (!range.isEmpty()) {
+            writeFormat1CS(range, afterstringindex);
+        }
+    }
+
+    private void writeFormat1CS(Map<Integer, Integer> range, boolean afterstringindex) {
+        if (!afterstringindex) {
+            charsetOffset += 2;
+        }
+        writeByte(0);
+        writeCard16(1);
+        updateStandardRange(range);
+        for (Map.Entry<Integer, Integer> i : range.entrySet()) {
+            writeCard16(i.getKey());
+            writeByte(i.getValue());
+        }
+        writeByte(1);
+    }
+
+    private void updateStandardRange(Map<Integer, Integer> range) {
+        if (range.containsKey(NUM_STANDARD_STRINGS) && range.containsKey(NUM_STANDARD_STRINGS + 1)) {
+            boolean mixedCS = false;
+            for (int i : range.keySet()) {
+                if (i < NUM_STANDARD_STRINGS && i > 1) {
+                    mixedCS = true;
+                    break;
+                }
+            }
+            if (!mixedCS) {
+                if (range.containsKey(1)) {
+                    range.clear();
+                    range.put(1, 0);
+                }
+                int last = -1;
+                boolean simpleRange = false;
+                for (int i : range.keySet()) {
+                    simpleRange = (last + 1 == i);
+                    last = i;
+                }
+                if (simpleRange) {
+                    for (int i = NUM_STANDARD_STRINGS; i < NUM_STANDARD_STRINGS + subsetCharStringsIndex.size(); i++) {
+                        range.put(i, 0);
+                    }
+                } else {
+                    range.put(NUM_STANDARD_STRINGS, subsetCharStringsIndex.size());
+                }
+            }
+        }
+    }
+
+    @Override
+    protected void updateFixedOffsets(Map<String, CFFDataReader.DICTEntry> topDICT, int dataTopDictOffset,
+                                      int charsetOffset, int charStringOffset, int encodingOffset) {
+        //Charset offset in the top dict
+        final CFFDataReader.DICTEntry charset = topDICT.get("charset");
+        if (charset != null) {
+            int oldCharsetOffset = dataTopDictOffset + charset.getOffset();
+            int oldCharset = Integer.parseInt(String.format("%02x", output[oldCharsetOffset] & 0xff), 16);
+            if (oldCharset >= 32 && oldCharset <= 246) {
+                charsetOffset += 139;
+            }
+            output = updateOffset(output, oldCharsetOffset, charset.getOperandLength(), charsetOffset);
+        }
+
+        //Char string index offset in the private dict
+        final CFFDataReader.DICTEntry charString = topDICT.get("CharStrings");
+        int oldCharStringOffset = dataTopDictOffset + charString.getOffset();
+        int oldString = Integer.parseInt(String.format("%02x", output[oldCharStringOffset] & 0xff), 16);
+        if (oldString >= 32 && oldString <= 246) {
+            charStringOffset += 139;
+        }
+        if (!(fileFonts.get(0).getCharset() instanceof CFFISOAdobeCharset)) {
+            output = updateOffset(output, oldCharStringOffset, charString.getOperandLength(), charStringOffset);
+        }
+
+        final CFFDataReader.DICTEntry encodingEntry = topDICT.get("Encoding");
+        if (encodingEntry != null && encodingEntry.getOperands().get(0).intValue() != 0
+                && encodingEntry.getOperands().get(0).intValue() != 1) {
+            int oldEncodingOffset = dataTopDictOffset + encodingEntry.getOffset();
+            int oldEnc = Integer.parseInt(String.format("%02x", output[oldEncodingOffset] & 0xff), 16);
+            if (oldEnc >= 32 && oldEnc <= 246) {
+                encodingOffset += 139;
+            } else {
+                encodingOffset--;
+            }
+            output = updateOffset(output, oldEncodingOffset, encodingEntry.getOperandLength(), encodingOffset);
+        }
+    }
+}

Property changes on: src/java/org/apache/fop/render/pdf/pdfbox/MergeCFFFonts.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: src/java/org/apache/fop/render/pdf/pdfbox/MergeTTFonts.java
===================================================================
--- src/java/org/apache/fop/render/pdf/pdfbox/MergeTTFonts.java	(revision 0)
+++ src/java/org/apache/fop/render/pdf/pdfbox/MergeTTFonts.java	(working copy)
@@ -0,0 +1,376 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.fop.render.pdf.pdfbox;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.TreeMap;
+
+import org.apache.fontbox.ttf.MaximumProfileTable;
+
+import org.apache.fop.fonts.truetype.FontFileReader;
+import org.apache.fop.fonts.truetype.OFDirTabEntry;
+import org.apache.fop.fonts.truetype.OFMtxEntry;
+import org.apache.fop.fonts.truetype.OFTableName;
+import org.apache.fop.fonts.truetype.TTFSubSetFile;
+
+public class MergeTTFonts extends TTFSubSetFile {
+    private Map<Integer, Glyph> added = new TreeMap<Integer, Glyph>();
+    private int origIndexesLen = 0;
+    private byte[] lastbytes = null;
+    private int size = 0;
+    protected MaximumProfileTable maxp = new MaximumProfileTable();
+
+    static class Glyph {
+        final byte[] data;
+        final OFMtxEntry mtx;
+        Glyph(byte[] d, OFMtxEntry m) {
+            data = d;
+            mtx = m;
+        }
+    }
+
+    /**
+     * Create the glyf table and fill in loca table
+     */
+    private void readGlyf(Map<Integer, Integer> glyphs, FontFileReader in) throws IOException {
+        OFDirTabEntry entry = dirTabs.get(OFTableName.GLYF);
+        if (entry != null) {
+            int[] origIndexes = buildSubsetIndexToOrigIndexMap(glyphs);
+            for (int i = 0; i < origIndexes.length; i++) {
+                int nextOffset = 0;
+                int origGlyphIndex = origIndexes[i];
+                if (origGlyphIndex >= (mtxTab.length - 1)) {
+                    nextOffset = (int)lastLoca;
+                } else {
+                    nextOffset = (int)mtxTab[origGlyphIndex + 1].getOffset();
+                }
+                int glyphOffset = (int)mtxTab[origGlyphIndex].getOffset();
+                int glyphLength = nextOffset - glyphOffset;
+                if (glyphLength < 0) {
+                    continue;
+                }
+                byte[] glyphData = in.getBytes(
+                        (int)entry.getOffset() + glyphOffset,
+                        glyphLength);
+
+                Glyph g = new Glyph(glyphData, mtxTab[origGlyphIndex]);
+                if (!cid && (origIndexesLen == 0 || (glyphLength > 0 && i > 0))) {
+                    added.put(i, g);
+                } else if (cid) {
+                    added.put(i + origIndexesLen, g);
+                }
+            }
+            if (!cid) {
+                origIndexesLen = origIndexes.length;
+            } else {
+                origIndexesLen += origIndexes.length;
+            }
+        } else {
+            throw new IOException("Can't find glyf table");
+        }
+    }
+
+    private void createGlyf() throws IOException {
+        OFDirTabEntry entry = dirTabs.get(OFTableName.GLYF);
+        int size = 0;
+        int startPos = 0;
+        int endOffset = 0;    // Store this as the last loca
+
+        if (entry != null) {
+            pad4();
+            startPos = currentPos;
+            /* Loca table must be in order by glyph index, so build
+             * an array first and then write the glyph info and
+             * location offset.
+             */
+            glyphOffsets = new int[origIndexesLen];
+            for (Map.Entry<Integer, Glyph> gly : added.entrySet()) {
+                byte[] glyphData = gly.getValue().data;
+                int glyphLength = glyphData.length;
+                int i = gly.getKey();
+                int endOffset1 = endOffset;
+                // Copy glyph
+                writeBytes(glyphData);
+                // Update loca table
+                if (cid) {
+                    writeULong(locaOffset + i * 4, currentPos - startPos);
+                }
+                if ((currentPos - startPos + glyphLength) > endOffset1) {
+                    endOffset1 = (currentPos - startPos + glyphLength);
+                }
+
+                // Store the glyph boundary positions relative to the start of the font
+                glyphOffsets[i] = currentPos;
+                currentPos += glyphLength;
+                realSize += glyphLength;
+
+                endOffset = endOffset1;
+            }
+
+            size = currentPos - startPos;
+
+            currentPos += 12;
+            realSize += 12;
+            updateCheckSum(startPos, size + 12, OFTableName.GLYF);
+
+            // Update loca checksum and last loca index
+            writeULong(locaOffset + added.size() * 4, endOffset);
+            int locaSize = added.size() * 4 + 4;
+            int checksum = getCheckSum(output, locaOffset, locaSize);
+            writeULong(offsets.get(OFTableName.LOCA), checksum);
+            int padSize = (locaOffset + locaSize) % 4;
+            newDirTabs.put(OFTableName.LOCA,
+                    new OFDirTabEntry(locaOffset, locaSize + padSize));
+
+            if (!cid) {
+                int i = 0;
+                int offset = 0;
+                for (Glyph e : added.values()) {
+                    writeUShort(locaOffset + i * 2, offset / 2);
+                    offset += e.data.length;
+                    i++;
+                }
+                writeUShort(locaOffset + i * 2, offset / 2);
+            }
+        } else {
+            throw new IOException("Can't find glyf table");
+        }
+    }
+
+    /**
+     * Create the hmtx table by copying metrics from original
+     * font to subset font. The glyphs Map contains an
+     * Integer key and Integer value that maps the original
+     * metric (key) to the subset metric (value)
+     */
+    protected void createHmtx() throws IOException {
+        OFTableName hmtx = OFTableName.HMTX;
+        OFDirTabEntry entry = dirTabs.get(hmtx);
+        if (entry != null) {
+            pad4();
+            // int offset = (int)entry.offset;
+
+            int longHorMetricSize = added.size() * 4;
+            int leftSideBearingSize = added.size() * 4;
+            int hmtxSize = longHorMetricSize + leftSideBearingSize;
+
+            for (Map.Entry<Integer, Glyph> e : added.entrySet()) {
+                Integer subsetIndex = e.getKey();
+                OFMtxEntry mtx = e.getValue().mtx;
+                writeUShort(currentPos + subsetIndex * 4,
+                        mtx.getWx());
+                writeUShort(currentPos + subsetIndex * 4 + 2,
+                        mtx.getLsb());
+            }
+
+            updateCheckSum(currentPos, hmtxSize, hmtx);
+            currentPos += hmtxSize;
+            realSize += hmtxSize;
+        } else {
+            throw new IOException("Can't find hmtx table");
+        }
+    }
+
+    /**
+     * Returns a subset of the original font.
+     *
+     *
+     * @param subsetGlyphs Map of glyphs (glyphs has old index as (Integer) key and
+     * new index as (Integer) value)
+     * @throws IOException in case of an I/O problem
+     */
+    public void readFont(FontFileReader fontFile, Map<Integer, Integer> subsetGlyphs, boolean cid) throws IOException {
+        this.cid = cid;
+        if (subsetGlyphs.isEmpty()) {
+            return;
+        }
+        this.fontFile = fontFile;
+        lastbytes = fontFile.getAllBytes();
+        size += lastbytes.length;
+
+        readDirTabs();
+        readFontHeader();
+        getNumGlyphs();
+        readHorizontalHeader();
+        readHorizontalMetrics();
+        readIndexToLocation();
+        if (!cid && subsetGlyphs.size() <= 1) {
+            for (int i = 0; i < mtxTab.length; i++) {
+                subsetGlyphs.put(i, i);
+            }
+        }
+        scanGlyphs(fontFile, subsetGlyphs);
+        readGlyf(subsetGlyphs, fontFile);
+    }
+
+    public void writeFont(PDFBoxAdapter.Cmap cmap) throws IOException {
+        output = new byte[size * 2];
+        createDirectory();     // Create the TrueType header and directory
+        int sgsize = added.size();
+        if (!cid) {
+            writeCMAP(cmap);
+//            copyTable(fontFile, OFTableName.CMAP);
+        }
+        createHmtx();           // Create hmtx table
+        if (cid) {
+            createLoca(sgsize);    // create empty loca table
+        } else {
+            createLoca(numberOfGlyphs / 2);    // create empty loca table
+        }
+        createHead(fontFile);
+        createOS2(fontFile);                          // copy the OS/2 table
+        if (!cid) {
+            createHhea(fontFile, sgsize - 2);    // Create the hhea table
+        } else {
+            createHhea(fontFile, sgsize);    // Create the hhea table
+        }
+        if (maxp.getVersion() == 0) {
+            createMaxp(fontFile, sgsize);    // copy the maxp table
+        } else {
+            writeMaxp();
+        }
+        boolean optionalTableFound;
+        optionalTableFound = createCvt(fontFile);    // copy the cvt table
+        if (!optionalTableFound) {
+            // cvt is optional (used in TrueType fonts only)
+            log.debug("TrueType: ctv table not present. Skipped.");
+        }
+        optionalTableFound = createFpgm(fontFile);    // copy fpgm table
+        if (!optionalTableFound) {
+            // fpgm is optional (used in TrueType fonts only)
+            log.debug("TrueType: fpgm table not present. Skipped.");
+        }
+        createPost(fontFile);                         // copy the post table
+        optionalTableFound = createPrep(fontFile);    // copy prep table
+        if (!optionalTableFound) {
+            // prep is optional (used in TrueType fonts only)
+            log.debug("TrueType: prep table not present. Skipped.");
+        }
+        createName(fontFile);                         // copy the name table
+        createGlyf(); //create glyf table and update loca table
+        pad4();
+        createCheckSumAdjustment();
+    }
+
+    private void writeMaxp() {
+        int checksum = currentPos;
+        pad4();
+        int startPos = currentPos;
+        writeUShort((int) maxp.getVersion()); //version
+        writeUShort(0);
+        writeUShort(maxp.getNumGlyphs()); //numGlyphs
+        writeUShort(maxp.getMaxPoints()); //maxPoints
+        writeUShort(maxp.getMaxContours()); //maxContours
+        writeUShort(maxp.getMaxCompositePoints()); //maxCompositePoints
+        writeUShort(maxp.getMaxCompositeContours()); //maxCompositeContours
+        writeUShort(maxp.getMaxZones()); //maxZones
+        writeUShort(maxp.getMaxTwilightPoints()); //maxTwilightPoints
+        writeUShort(maxp.getMaxStorage()); //maxStorage
+        writeUShort(maxp.getMaxFunctionDefs()); //maxFunctionDefs
+        writeUShort(maxp.getMaxInstructionDefs()); //maxInstructionDefs
+        writeUShort(maxp.getMaxStackElements()); //maxStackElements
+        writeUShort(maxp.getMaxSizeOfInstructions()); //maxSizeOfInstructions
+        writeUShort(maxp.getMaxComponentElements()); //maxComponentElements
+        writeUShort(maxp.getMaxComponentDepth()); //maxComponentDepth
+        updateCheckSum(checksum, currentPos - startPos, OFTableName.MAXP);
+        realSize += currentPos - startPos;
+    }
+
+    private void writeCMAP(PDFBoxAdapter.Cmap cmap) {
+        int checksum = currentPos;
+        pad4();
+        int cmapPos = currentPos;
+        writeUShort(0); //version
+        writeUShort(1); //number of tables
+
+        Map<Integer, Integer> glyphIdToCharacterCode = cmap.glyphIdToCharacterCode;
+        writeUShort(cmap.platformId); //platformid
+        writeUShort(cmap.platformEncodingId); //platformEncodingId
+        writeULong(currentPos, currentPos - cmapPos + 12); //subTableOffset
+        currentPos += 12;
+
+        writeUShort(12); //subtableFormat
+        writeUShort(0);
+        writeULong(currentPos, (glyphIdToCharacterCode.size() * 12) + 16);
+        currentPos += 4;
+        writeULong(currentPos, 0);
+        currentPos += 4;
+        writeULong(currentPos, glyphIdToCharacterCode.size());
+        currentPos += 4;
+
+        for (Map.Entry<Integer, Integer> g : glyphIdToCharacterCode.entrySet()) {
+            writeULong(currentPos, g.getKey());
+            currentPos += 4;
+            writeULong(currentPos, g.getKey());
+            currentPos += 4;
+            writeULong(currentPos, g.getValue());
+            currentPos += 4;
+        }
+
+//            writeUShort(6); //subtableFormat
+//            int firstCode = -1;
+//            int lastCode = -1;
+//            List<Integer> codes = new ArrayList<Integer>();
+//            for (Map.Entry<Integer, Integer> g : glyphIdToCharacterCode.entrySet()) {
+//                if (firstCode < 0) {
+//                    firstCode = g.getKey();
+//                }
+//                while (lastCode > 0 && lastCode + 1 < g.getKey()) {
+//                    codes.add(0);
+//                    lastCode++;
+//                }
+//                codes.add(g.getValue());
+//
+//                lastCode = g.getKey();
+//            }
+//
+//            writeUShort((codes.size() * 2) + 6); //length
+//            writeUShort(0); //version
+//
+//            writeUShort(firstCode); //firstCode
+//            writeUShort(codes.size()); //entryCount
+//
+//            for (int i : codes) {
+//                writeUShort(i);
+//            }
+
+        updateCheckSum(checksum, currentPos - cmapPos, OFTableName.CMAP);
+        realSize += currentPos - cmapPos;
+    }
+
+    /**
+     * Get index from starting at lowest glyph position
+     * @param glyphs map
+     * @return index map
+     */
+    protected int[] buildSubsetIndexToOrigIndexMap(Map<Integer, Integer> glyphs) {
+        int[] origIndexes = new int[glyphs.size()];
+        int minIndex = Integer.MAX_VALUE;
+        for (int glyph : glyphs.values()) {
+            if (minIndex > glyph) {
+                minIndex = glyph;
+            }
+        }
+        for (Map.Entry<Integer, Integer> glyph : glyphs.entrySet()) {
+            int origIndex = glyph.getKey();
+            int subsetIndex = glyph.getValue() - minIndex;
+            origIndexes[subsetIndex] = origIndex;
+        }
+        return origIndexes;
+    }
+}

Property changes on: src/java/org/apache/fop/render/pdf/pdfbox/MergeTTFonts.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: src/java/org/apache/fop/render/pdf/pdfbox/PDFBoxAdapter.java
===================================================================
--- src/java/org/apache/fop/render/pdf/pdfbox/PDFBoxAdapter.java	(revision 1575872)
+++ src/java/org/apache/fop/render/pdf/pdfbox/PDFBoxAdapter.java	(working copy)
@@ -21,22 +21,42 @@
 
 import java.awt.geom.AffineTransform;
 import java.awt.geom.Rectangle2D;
+import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.io.Serializable;
+import java.text.DecimalFormat;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
+import java.util.LinkedHashMap;
 import java.util.List;
+import java.util.Locale;
 import java.util.Map;
 import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
+import java.util.regex.Pattern;
 
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+import org.apache.fontbox.cff.CFFFont;
+import org.apache.fontbox.cff.CFFParser;
+import org.apache.fontbox.cff.charset.CFFCharset;
+import org.apache.fontbox.cff.encoding.CFFEncoding;
+import org.apache.fontbox.cmap.CMap;
+
+import org.apache.fontbox.ttf.CMAPEncodingEntry;
+import org.apache.fontbox.ttf.GlyphData;
+import org.apache.fontbox.ttf.MaximumProfileTable;
+import org.apache.fontbox.ttf.TrueTypeFont;
 import org.apache.pdfbox.cos.COSArray;
 import org.apache.pdfbox.cos.COSBase;
 import org.apache.pdfbox.cos.COSBoolean;
@@ -45,9 +65,14 @@
 import org.apache.pdfbox.cos.COSInteger;
 import org.apache.pdfbox.cos.COSName;
 import org.apache.pdfbox.cos.COSNull;
+import org.apache.pdfbox.cos.COSNumber;
 import org.apache.pdfbox.cos.COSObject;
 import org.apache.pdfbox.cos.COSStream;
 import org.apache.pdfbox.cos.COSString;
+import org.apache.pdfbox.encoding.DictionaryEncoding;
+import org.apache.pdfbox.encoding.Encoding;
+import org.apache.pdfbox.encoding.EncodingManager;
+import org.apache.pdfbox.pdfparser.PDFStreamParser;
 import org.apache.pdfbox.pdmodel.PDDocument;
 import org.apache.pdfbox.pdmodel.PDDocumentCatalog;
 import org.apache.pdfbox.pdmodel.PDPage;
@@ -57,10 +82,31 @@
 import org.apache.pdfbox.pdmodel.common.COSStreamArray;
 import org.apache.pdfbox.pdmodel.common.PDRectangle;
 import org.apache.pdfbox.pdmodel.common.PDStream;
+import org.apache.pdfbox.pdmodel.font.PDCIDFont;
+import org.apache.pdfbox.pdmodel.font.PDCIDFontType2Font;
+import org.apache.pdfbox.pdmodel.font.PDFont;
+import org.apache.pdfbox.pdmodel.font.PDFontDescriptorDictionary;
+import org.apache.pdfbox.pdmodel.font.PDFontFactory;
+import org.apache.pdfbox.pdmodel.font.PDSimpleFont;
+import org.apache.pdfbox.pdmodel.font.PDTrueTypeFont;
+import org.apache.pdfbox.pdmodel.font.PDType0Font;
+import org.apache.pdfbox.pdmodel.font.PDType1Font;
+
 import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotation;
 import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm;
 
+
 import org.apache.fop.events.EventBroadcaster;
+import org.apache.fop.fonts.CustomFont;
+import org.apache.fop.fonts.EmbeddingMode;
+import org.apache.fop.fonts.FontInfo;
+import org.apache.fop.fonts.FontType;
+import org.apache.fop.fonts.MultiByteFont;
+import org.apache.fop.fonts.SingleByteEncoding;
+import org.apache.fop.fonts.SingleByteFont;
+import org.apache.fop.fonts.Typeface;
+import org.apache.fop.fonts.truetype.FontFileReader;
+import org.apache.fop.fonts.truetype.OTFSubSetFile;
 import org.apache.fop.pdf.PDFArray;
 import org.apache.fop.pdf.PDFDictionary;
 import org.apache.fop.pdf.PDFDocument;
@@ -71,13 +117,16 @@
 import org.apache.fop.pdf.PDFPage;
 import org.apache.fop.pdf.PDFRoot;
 import org.apache.fop.pdf.PDFStream;
+import org.apache.fop.pdf.RefPDFFont;
+import org.apache.fop.util.CharUtilities;
+import org.apache.pdfbox.util.operator.PDFOperator;
 
 /**
  * This class provides an adapter for transferring content from a PDFBox PDDocument to
  * FOP's PDFDocument. It is used to parse PDF using PDFBox and write content using
  * FOP's PDF library.
  */
-class PDFBoxAdapter {
+public class PDFBoxAdapter {
 
     /** logging instance */
     protected static Log log = LogFactory.getLog(PDFBoxAdapter.class);
@@ -86,12 +135,15 @@
             Arrays.asList(new String[] {"Filter", "DecodeParms"}));
     private static final Set page2form = new java.util.HashSet(
             Arrays.asList(new String[] {"Group", "LastModified", "Metadata"}));
+    private static final Pattern SUBSET_PATTERN = Pattern.compile("[A-Z][A-Z][A-Z][A-Z][A-Z][A-Z]\\+.+");
 
     private final PDFPage targetPage;
     private final PDFDocument pdfDoc;
 
     private final Map clonedVersion;
 
+    private final Map<COSDictionary, PDSimpleFont> fontMap = new HashMap<COSDictionary, PDSimpleFont>();
+
     /**
      * Creates a new PDFBoxAdapter.
      * @param targetPage The target FOP PDF page object
@@ -294,6 +346,976 @@
         }
     }
 
+    private String getUniqueFontName(COSDictionary fontData) throws IOException {
+        PDSimpleFont font = getFont(fontData);
+        String extra = "";
+        if (font instanceof PDType0Font
+                && font.getToUnicode() != null
+                && ((PDType0Font) font).getDescendantFont() instanceof PDCIDFontType2Font) {
+            if (!isSubsetFont(font.getBaseFont())) {
+                extra = "f3";
+            }
+            try {
+                ((PDCIDFontType2Font) ((PDType0Font) font).getDescendantFont()).getTTFFont();
+            } catch (IOException e) {
+                log.error(e);
+                return null;
+            }
+            return getName(font.getBaseFont()) + "_" + ((COSName)fontData.getItem(COSName.SUBTYPE)).getName() + extra;
+        }
+        if (font instanceof PDTrueTypeFont && isSubsetFont(font.getBaseFont())) {
+            TrueTypeFont tt = ((PDTrueTypeFont) font).getTTFFont();
+            for (CMAPEncodingEntry c : tt.getCMAP().getCmaps()) {
+                if (c.getGlyphId(1) > 0) {
+                    extra = "cid";
+                }
+            }
+            return getName(font.getBaseFont()) + "_" + ((COSName)fontData.getItem(COSName.SUBTYPE)).getName() + extra;
+        }
+//        if (!isSubsetFont(font.getBaseFont())) {
+//            return font.getBaseFont() + "_" + ((COSName)fontData.getItem(COSName.SUBTYPE)).getName();
+//        }
+        if (font instanceof PDType1Font) {
+            if (((PDType1Font) font).getType1CFont() == null
+                    || ((PDType1Font) font).getType1CFont().getCFFFont() == null) {
+                return null;
+            }
+            CFFEncoding encoding = ((PDType1Font)font).getType1CFont().getCFFFont().getEncoding();
+            String eClass = encoding.getClass().getName();
+            if (eClass.equals("org.apache.fontbox.cff.CFFParser$Format1Encoding")) {
+                extra = "f1enc";
+            } else if (eClass.equals("org.apache.fontbox.cff.CFFParser$Format0Encoding")) {
+                extra = "f0enc";
+            }
+            CFFCharset cs = ((PDType1Font)font).getType1CFont().getCFFFont().getCharset();
+            for (CFFCharset.Entry e : cs.getEntries()) {
+                if (e.getSID() < OTFSubSetFile.NUM_STANDARD_STRINGS) {
+                    extra += "stdcs";
+                }
+                break;
+            }
+            if (cs.getClass().getName().equals("org.apache.fontbox.cff.CFFParser$Format1Charset")) {
+                extra += "f1cs";
+            }
+            return getName(font.getBaseFont()) + "_" + ((COSName)fontData.getItem(COSName.SUBTYPE)).getName() + extra;
+        }
+        return null;
+    }
+
+    private static boolean isSubsetFont(String s) {
+        return SUBSET_PATTERN.matcher(s).matches();
+    }
+
+    private static String getName(String name) {
+        if (isSubsetFont(name)) {
+            return name.split("\\+")[1].replace(" ", "");
+        }
+        return name;
+    }
+
+    interface FOPPDFFont extends RefPDFFont {
+        String getFontName();
+        void setRef(PDFDictionary d);
+        String addFont(COSDictionary fontdata) throws IOException;
+        int size();
+    }
+
+    public class FOPPDFMultiByteFont extends MultiByteFont implements FOPPDFFont {
+        protected PDFDictionary ref;
+        private Map<Integer, Integer> newWidth = new TreeMap<Integer, Integer>();
+        private Map<String, Integer> charMapGlobal = new LinkedHashMap<String, Integer>();
+        private MergeTTFonts mergeFonts = new MergeTTFonts();
+        private Map<String, GlyphData> glyphs = new HashMap<String, GlyphData>();
+
+        public FOPPDFMultiByteFont(COSDictionary fontData, String name) {
+            super(null, EmbeddingMode.SUBSET);
+            //this stops fop modifying font later on
+            setEmbeddingMode(EmbeddingMode.FULL);
+            try {
+                readFontBBox(fontData);
+                setFontName(name);
+                addFont(fontData);
+            } catch (IOException e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+        public String addFont(COSDictionary fontData) throws IOException {
+            PDSimpleFont font = getFont(fontData);
+            setProperties(this, font);
+            PDSimpleFont mainFont = font;
+            TrueTypeFont ttf;
+            if (font instanceof PDType0Font) {
+                PDCIDFont cidFont = (PDCIDFont) ((PDType0Font) font).getDescendantFont();
+                setDefaultWidth((int) cidFont.getDefaultWidth());
+                mainFont = cidFont;
+                ttf = ((PDCIDFontType2Font) cidFont).getTTFFont();
+            } else {
+                ttf = ((PDTrueTypeFont) font).getTTFFont();
+                setDefaultWidth(1000);
+            }
+            GlyphData[] glyphData = ttf.getGlyph().getGlyphs();
+            Map<Integer, Integer> oldToNewGIMap = new HashMap<Integer, Integer>();
+            if (charMapGlobal.isEmpty()) {
+                oldToNewGIMap.put(0, 0); // .notdef glyph
+            }
+            CMap c = font.getToUnicodeCMap();
+            Map<Integer, String> mapping = getMapping(mainFont, c, glyphData.length);
+//            if (differentGlyphData(glyphData, mapping)) {
+//                return null;
+//            }
+            Map<Integer, String> gidToGlyph = new TreeMap<Integer, String>(mapping);
+            if (mainFont instanceof PDTrueTypeFont) {
+                CMAPEncodingEntry cmap = ttf.getCMAP().getCmaps()[0];
+                gidToGlyph.clear();
+                int[] gidToCode = cmap.getGlyphIdToCharacterCode();
+                for (int i = 1; i < glyphData.length; i++) {
+                    String mappedChar = mapping.get(gidToCode[i]);
+                    gidToGlyph.put(i, mappedChar);
+                }
+            }
+            int widthPos = font.getFirstChar() + 1;
+            for (Map.Entry<Integer, String> i : gidToGlyph.entrySet()) {
+                String mappedChar = i.getValue();
+                int key = i.getKey();
+                boolean skipWidth = mappedChar == null;
+                if (skipWidth) {
+                    mappedChar = (char)charMapGlobal.size() + "tmp";
+                } else if (mappedChar.length() > 1) {
+                    mappedChar = "" + (char)mappedChar.hashCode();
+                }
+                if (!charMapGlobal.containsKey(mappedChar)) {
+                    if (glyphData[key] == null
+                            && !CharUtilities.isAdjustableSpace(mappedChar.charAt(0))) {
+                        continue;
+                    }
+                    boolean addToEnd = charMapGlobal.containsValue(key);
+                    if (addToEnd) {
+                        addPrivateUseMapping(mappedChar.charAt(0), charMapGlobal.size() + 1);
+                        charMapGlobal.put(mappedChar, charMapGlobal.size() + 1);
+                    } else {
+                        addPrivateUseMapping(mappedChar.charAt(0), key);
+                        charMapGlobal.put(mappedChar, key);
+                    }
+                    int glyph = (int) mapChar(mappedChar.charAt(0));
+                    oldToNewGIMap.put(key, glyph);
+                    if (!skipWidth) {
+                        if (!(mainFont instanceof PDTrueTypeFont)) {
+                            widthPos = key;
+                        }
+                        float w = font.getFontWidth(widthPos);
+                        if (w >= 0) {
+                            newWidth.put(glyph, (int)w);
+                        }
+                    }
+                }
+                if (!skipWidth) {
+                    widthPos++;
+                }
+            }
+            FontFileReader ffr = readFontFile(mainFont);
+            mergeMaxp(ttf);
+            mergeFonts.readFont(ffr, oldToNewGIMap, true);
+            return getFontName();
+        }
+
+        private Map<Integer, String> getMapping(PDSimpleFont font, CMap c, int len) {
+            Map<Integer, String> mapping = new HashMap<Integer, String>();
+            int last = font.getLastChar();
+            if (last == -1) {
+                last = len;
+            }
+            int size = 1;
+            if (c.hasTwoByteMappings()) {
+                size = 2;
+            }
+            for (int i = font.getFirstChar(); i <= last; i++) {
+                String l = c.lookup(i, size);
+                if (l != null) {
+                    mapping.put(i, l);
+                }
+            }
+            return mapping;
+        }
+
+        private void mergeMaxp(TrueTypeFont ttf) {
+            MaximumProfileTable mp = ttf.getMaximumProfile();
+            MaximumProfileTable outMaxp = mergeFonts.maxp;
+            outMaxp.setVersion(mp.getVersion());
+            outMaxp.setNumGlyphs(outMaxp.getNumGlyphs() + mp.getNumGlyphs());
+            outMaxp.setMaxPoints(outMaxp.getMaxPoints() + mp.getMaxPoints());
+            outMaxp.setMaxContours(outMaxp.getMaxContours() + mp.getMaxContours());
+            outMaxp.setMaxCompositePoints(outMaxp.getMaxCompositePoints() + mp.getMaxCompositePoints());
+            outMaxp.setMaxCompositeContours(outMaxp.getMaxCompositeContours() + mp.getMaxCompositeContours());
+            outMaxp.setMaxZones(outMaxp.getMaxZones() + mp.getMaxZones());
+            outMaxp.setMaxTwilightPoints(outMaxp.getMaxTwilightPoints() + mp.getMaxTwilightPoints());
+            outMaxp.setMaxStorage(outMaxp.getMaxStorage() + mp.getMaxStorage());
+            outMaxp.setMaxFunctionDefs(outMaxp.getMaxFunctionDefs() + mp.getMaxFunctionDefs());
+            outMaxp.setMaxInstructionDefs(outMaxp.getMaxInstructionDefs() + mp.getMaxInstructionDefs());
+            outMaxp.setMaxStackElements(outMaxp.getMaxStackElements() + mp.getMaxStackElements());
+            outMaxp.setMaxSizeOfInstructions(outMaxp.getMaxSizeOfInstructions() + mp.getMaxSizeOfInstructions());
+            outMaxp.setMaxComponentElements(outMaxp.getMaxComponentElements() + mp.getMaxComponentElements());
+            outMaxp.setMaxComponentDepth(outMaxp.getMaxComponentDepth() + mp.getMaxComponentDepth());
+        }
+
+        private boolean differentGlyphData(GlyphData[] data, Map<Integer, String> mapping) throws IOException {
+            Map<String, Integer> tmpMap = new HashMap<String, Integer>();
+            for (Map.Entry<Integer, String> entry : mapping.entrySet()) {
+                if (!tmpMap.containsKey(entry.getValue())) {
+                    tmpMap.put(entry.getValue(), entry.getKey());
+                }
+            }
+            mapping.clear();
+            for (Map.Entry<String, Integer> entry : tmpMap.entrySet()) {
+                mapping.put(entry.getValue(), entry.getKey());
+            }
+
+            for (Map.Entry<Integer, String> n : mapping.entrySet()) {
+                if (data[n.getKey()] != null) {
+                    if (glyphs.containsKey(n.getValue()) && !glyphs.get(n.getValue()).equals(data[n.getKey()])) {
+                        return true;
+                    }
+                    glyphs.put(n.getValue(), data[n.getKey()]);
+                }
+            }
+            return false;
+        }
+
+        private FontFileReader readFontFile(PDFont font) throws IOException {
+            InputStream is = ((PDFontDescriptorDictionary)font.getFontDescriptor()).getFontFile2().createInputStream();
+            return new FontFileReader(new ByteArrayInputStream(IOUtils.toByteArray(is)));
+        }
+
+        public Map<Integer, Integer> getWidthsMap() {
+            return newWidth;
+        }
+
+        public PDFDictionary getRef() {
+            return ref;
+        }
+
+        public void setRef(PDFDictionary d) {
+            ref = d;
+        }
+
+        public int size() {
+            return 0;
+        }
+
+        private void readFontBBox(COSBase b) throws IOException {
+            if (b instanceof COSDictionary) {
+                COSDictionary dict = (COSDictionary)b;
+                for (Map.Entry<COSName, COSBase> n : dict.entrySet()) {
+                    readFontBBox(n.getValue());
+                    if (n.getKey() == COSName.FONT_BBOX) {
+                        COSArray w = (COSArray)n.getValue();
+                        float[] bboxf = w.toFloatArray();
+                        int[] bbox = new int[bboxf.length];
+                        for (int i = 0; i < bbox.length; i++) {
+                            bbox[i] = (int)bboxf[i];
+                        }
+                        setFontBBox(bbox);
+                    }
+                }
+            } else if (b instanceof COSObject) {
+                COSObject o = (COSObject)b;
+                readFontBBox(o.getObject());
+            } else if (b instanceof COSArray) {
+                COSArray o = (COSArray)b;
+                for (int i = 0; i < o.size(); i++) {
+                    readFontBBox(o.get(i));
+                }
+            }
+        }
+
+        public boolean isEmbeddable() {
+            return true;
+        }
+
+        public InputStream getInputStream() throws IOException {
+            mergeFonts.writeFont(null);
+            return new ByteArrayInputStream(mergeFonts.getFontSubset());
+        }
+    }
+
+    public static class Cmap {
+        int platformId;
+        int platformEncodingId;
+        Map<Integer, Integer> glyphIdToCharacterCode = new TreeMap<Integer, Integer>();
+    }
+
+    public class FOPPDFSingleByteFont extends SingleByteFont implements FOPPDFFont {
+        private Map<String, InputStream> fontFiles = new TreeMap<String, InputStream>();
+        private List<PDSimpleFont> fonts = new ArrayList<PDSimpleFont>();
+        protected PDFDictionary ref;
+        private Map<String, Integer> charMapGlobal = new LinkedHashMap<String, Integer>();
+        private Map<Integer, Integer> newWidth = new HashMap<Integer, Integer>();
+        private Map<String, byte[]> charStringsDict;
+        private Cmap newCmap = new Cmap();
+        private byte[] fontCache;
+
+        public FOPPDFSingleByteFont(COSDictionary fontData, String name) {
+            super(null);
+            if (fontData.getItem(COSName.SUBTYPE) == COSName.TRUE_TYPE) {
+                setFontType(FontType.TRUETYPE);
+            }
+            width = new int[0];
+            try {
+                PDSimpleFont font = getFont(fontData);
+                if (font instanceof PDType1Font) {
+                    fontCache = ((PDFontDescriptorDictionary)font.getFontDescriptor()).getFontFile3().getByteArray();
+                }
+                fonts.add(font);
+                setFirstChar(font.getFirstChar());
+                setLastChar(font.getLastChar());
+                readFontFile(font);
+                float[] bBoxF = font.getFontBoundingBox().getCOSArray().toFloatArray();
+                int[] bBox = new int[bBoxF.length];
+                for (int i = 0; i < bBox.length; i++) {
+                    bBox[i] = (int)bBoxF[i];
+                }
+                setFontBBox(bBox);
+
+                setFontName(name);
+                Object cmap = getCmap(font);
+                for (int i = font.getFirstChar(); i <= font.getLastChar(); i++) {
+                    String mappedChar = getChar(cmap, i);
+                    if (mappedChar != null && (!mappedChar.equals(" ") || i == 32)) {
+                        charMapGlobal.put(mappedChar, i);
+                    }
+                }
+                //mark font as used
+                notifyMapOperation();
+                setProperties(this, font);
+                if (font.getWidths() != null) {
+                    //if width contains 0 we cant rely on codeToNameMap
+                    boolean usesZero = font.getWidths().contains(0f);
+                    Set<Integer> codeToName = getCodeToName(font).keySet();
+                    for (int i = getFirstChar(); i <= Math.min(getLastChar(), getFirstChar() + font.getWidths().size()); i++) {
+                        if (usesZero || codeToName.contains(i)) {
+                            int w = font.getWidths().get(i - getFirstChar()).intValue();
+                            newWidth.put(i, w);
+                        } else {
+                            newWidth.put(i, 0);
+                        }
+                    }
+                }
+                mapping = new FOPPDFEncoding();
+            } catch (IOException e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+        private Map<Integer, String> getCodeToName(PDFont font) {
+            Map<Integer, String> codeToName = new HashMap<Integer, String>();
+            if (font.getFontEncoding() != null) {
+                COSBase cos = font.getFontEncoding().getCOSObject();
+                if (cos instanceof COSDictionary) {
+                    COSDictionary enc = (COSDictionary) cos;
+                    COSName baseEncodingName = (COSName) enc.getDictionaryObject(COSName.BASE_ENCODING);
+                    if (baseEncodingName != null) {
+                        try {
+                            Encoding baseEncoding = EncodingManager.INSTANCE.getEncoding(baseEncodingName);
+                            codeToName.putAll(baseEncoding.getCodeToNameMap());
+                        } catch (IOException e) {
+                            throw new RuntimeException(e);
+                        }
+                    }
+                    COSArray differences = (COSArray)enc.getDictionaryObject(COSName.DIFFERENCES);
+                    int currentIndex = -1;
+                    for (int i = 0; differences != null &&  i < differences.size(); i++) {
+                        COSBase next = differences.getObject(i);
+                        if (next instanceof COSNumber) {
+                            currentIndex = ((COSNumber)next).intValue();
+                        } else if (next instanceof COSName) {
+                            COSName name = (COSName)next;
+                            codeToName.put(currentIndex++, name.getName());
+                        }
+                    }
+                } else {
+                    return font.getFontEncoding().getCodeToNameMap();
+                }
+            }
+            return codeToName;
+        }
+
+        private Object getCmap(PDSimpleFont font) throws IOException {
+            COSStream stream = (COSStream)font.getToUnicode();
+            if (stream == null) {
+                return font.getFontEncoding();
+            }
+            return font.getToUnicodeCMap();
+        }
+
+        private void readFontFile(PDSimpleFont font) throws IOException {
+            PDFontDescriptorDictionary fd = (PDFontDescriptorDictionary) font.getFontDescriptor();
+            setFlags(fd.getFlags());
+            PDStream ff = fd.getFontFile3();
+            if (ff == null) {
+                ff = fd.getFontFile2();
+                if (ff == null) {
+                    ff = fd.getFontFile();
+                }
+            } else {
+                setFontType(FontType.TYPE1C);
+            }
+            fontFiles.put(getFirstChar() + "_" + fontFiles.size(), new ByteArrayInputStream(IOUtils.toByteArray(ff.createInputStream())));
+            if (font instanceof PDTrueTypeFont) {
+                TrueTypeFont ttfont = ((PDTrueTypeFont) font).getTTFFont();
+                CMAPEncodingEntry[] cmapList = ttfont.getCMAP().getCmaps();
+                CMAPEncodingEntry c = cmapList[0];
+                if (cmapList.length > 1) {
+                    c = cmapList[1];
+                }
+                newCmap.platformId = c.getPlatformId();
+                newCmap.platformEncodingId = c.getPlatformEncodingId();
+                for (int i = 0; i < 256 * 256; i++) {
+                    if (c.getGlyphId(i) != 0) {
+                        newCmap.glyphIdToCharacterCode.put(i, c.getGlyphId(i));
+                    }
+                }
+            }
+        }
+
+        @Override
+        public boolean hasChar(char c) {
+            return charMapGlobal.containsKey(String.valueOf(c));
+        }
+
+        @Override
+        public char mapChar(char c) {
+            return mapping.mapChar(c);
+        }
+
+        public String getEmbedFontName() {
+            return getName(fonts.get(0).getBaseFont());
+        }
+
+        public int[] getWidths() {
+            width = new int[getLastChar() - getFirstChar() + 1];
+            for (int i = getFirstChar(); i <= getLastChar(); i++) {
+                if (newWidth.containsKey(i)) {
+                    width[i - getFirstChar()] = newWidth.get(i);
+                } else {
+                    width[i - getFirstChar()] = 0;
+                }
+            }
+            return width.clone();
+        }
+
+        public String addFont(COSDictionary fontData) throws IOException {
+            PDSimpleFont font = getFont(fontData);
+            if (font instanceof PDType1Font && differentGlyphData(font)) {
+                return null;
+            }
+            fonts.add(font);
+            mergeWidths(font);
+            if (font.getFirstChar() < getFirstChar()) {
+                setFirstChar(font.getFirstChar());
+            }
+            for (int w : newWidth.keySet()) {
+                if (w > getLastChar()) {
+                    setLastChar(w);
+                }
+            }
+            readFontFile(font);
+            return getFontName();
+        }
+
+        public int size() {
+            return fontFiles.size();
+        }
+
+        private Map<String, byte[]> getCharStringsDict(PDSimpleFont font, boolean cache) throws IOException {
+            if (font.getFontDescriptor() instanceof PDFontDescriptorDictionary) {
+                PDStream ff3Stream = ((PDFontDescriptorDictionary)font.getFontDescriptor()).getFontFile3();
+                if (ff3Stream != null) {
+                    byte[] data = fontCache;
+                    if (!cache) {
+                        data = ff3Stream.getByteArray();
+                    }
+                    CFFFont ff = new CFFParser().parse(data).get(0);
+                    return ff.getCharStringsDict();
+                }
+            }
+            return new HashMap<String, byte[]>();
+        }
+
+        private boolean differentGlyphData(PDSimpleFont font) throws IOException {
+            if (charStringsDict == null && fonts.get(0) instanceof PDType1Font) {
+                charStringsDict = getCharStringsDict(fonts.get(0), true);
+            }
+            for (Map.Entry<String, byte[]> s : getCharStringsDict(font, false).entrySet()) {
+                if (charStringsDict.containsKey(s.getKey())) {
+                    int numberDiff = 0;
+                    byte[] b1 = charStringsDict.get(s.getKey());
+                    byte[] b2 = s.getValue();
+                    int b1Index = b1.length - 1;
+                    int b2Index = b2.length - 1;
+                    while (b1Index >= 0 && b2Index >= 0) {
+                        if (b1[b1Index] != b2[b2Index]) {
+                            numberDiff++;
+                            if (numberDiff > 2) {
+                                break;
+                            }
+                        }
+                        b1Index--;
+                        b2Index--;
+                    }
+                    if (numberDiff > 2) {
+//                        log.info(getFontName() + " " + s.getKey() + " not equal " + numberdiff);
+                        return true;
+                    }
+                }
+            }
+            return false;
+        }
+
+        private void mergeWidths(PDSimpleFont font) throws IOException {
+            int w = 0;
+            int skipGlyphIndex = getLastChar() + 1;
+            Object cmap = getCmap(font);
+            for (int i = font.getFirstChar(); i <= font.getLastChar(); i++) {
+                boolean addedWidth = false;
+                int glyphIndexPos = skipGlyphIndex;
+                if (font instanceof PDTrueTypeFont) {
+                    glyphIndexPos = i;
+                }
+                int neww = 0;
+                if (font.getWidths() != null) {
+                    neww = font.getWidths().get(i - font.getFirstChar()).intValue();
+                    if (!newWidth.containsKey(i) || newWidth.get(i) == 0) {
+                        if (font instanceof PDTrueTypeFont || (font.getFontEncoding() != null && getCodeToName(font).keySet().contains(i))) {
+                            newWidth.put(i, neww);
+                            glyphIndexPos = i;
+                        } else {
+                            newWidth.put(i, 0);
+                        }
+                        addedWidth = true;
+                    }
+                }
+                String mappedChar = getChar(cmap, i);
+                if (mappedChar != null && !charMapGlobal.containsKey(mappedChar)) {
+                    charMapGlobal.put(mappedChar, glyphIndexPos);
+                    if (!addedWidth && w < font.getWidths().size()) {
+                        newWidth.put(newWidth.size() + getFirstChar(), neww);
+                    }
+                    skipGlyphIndex++;
+                }
+                w++;
+            }
+        }
+
+        private String getChar(Object cmap, int i) throws IOException {
+            if (cmap instanceof CMap) {
+                CMap c = (CMap)cmap;
+                int size = 1;
+                if (c.hasTwoByteMappings()) {
+                    size = 2;
+                }
+                return c.lookup(i, size);
+            }
+            Encoding enc = (Encoding)cmap;
+            if (enc instanceof DictionaryEncoding) {
+                return enc.getName(i);
+            }
+            return enc.getCharacter(i);
+        }
+
+        public String getEncodingName() {
+            if (fonts.get(0).getFontEncoding() != null) {
+                COSBase cosObject = fonts.get(0).getFontEncoding().getCOSObject();
+                if (cosObject != null) {
+                    if (cosObject instanceof COSDictionary) {
+                        COSBase item = ((COSDictionary) cosObject).getItem(COSName.BASE_ENCODING);
+                        if (item != null) {
+                            return ((COSName)item).getName();
+                        }
+                    } else if (cosObject instanceof COSName) {
+                        return ((COSName) cosObject).getName();
+                    } else {
+                        throw new RuntimeException(cosObject.toString() + " not supported");
+                    }
+                }
+            }
+            return null;
+        }
+
+        class FOPPDFEncoding implements SingleByteEncoding {
+            private boolean cmap = false;
+
+            public String getName() {
+                return "FOPPDFEncoding";
+            }
+
+            public char mapChar(char c) {
+                if (charMapGlobal.containsKey(String.valueOf(c))) {
+                    return (char)charMapGlobal.get(String.valueOf(c)).intValue();
+                }
+                return 0;
+            }
+
+            private Map<Integer, String> getEncodingMap() {
+                Map<Integer, String> v = new TreeMap<Integer, String>();
+                List<String> added = new ArrayList<String>();
+                int skip = fonts.get(0).getLastChar() + 1;
+                for (PDFont font : fonts) {
+                    if (font.getFontEncoding() == null) {
+                        continue;
+                    }
+                    Map<Integer, String> codeToName = getCodeToName(font);
+                    for (int i = font.getFirstChar(); i <= font.getLastChar(); i++) {
+                        if (codeToName.keySet().contains(i)) {
+                            String s = codeToName.get(i);
+                            if (!added.contains(s)) {
+                                if (!v.containsKey(i)) {
+                                    v.put(i, s);
+                                } else {
+                                    v.put(skip, s);
+                                    skip++;
+                                }
+                            }
+                        }
+                    }
+                    added.addAll(v.values());
+                }
+                return v;
+            }
+
+            public String[] getCharNameMap() {
+                Collection<String> v = getEncodingMap().values();
+                return v.toArray(new String[v.size()]);
+            }
+
+            public char[] getUnicodeCharMap() {
+                if (cmap) {
+                    if (fonts.get(0).getToUnicode() == null) {
+                        return new char[0];
+                    }
+                    List<String> cmapStrings = new ArrayList<String>();
+                    Map<Integer, String> cm = new HashMap<Integer, String>();
+                    for (Map.Entry<String, Integer> o : charMapGlobal.entrySet()) {
+                        cm.put(o.getValue(), o.getKey());
+                    }
+                    for (int i = 0; i < getLastChar() + 1; i++) {
+                        if (cm.containsKey(i)) {
+                            cmapStrings.add(cm.get(i));
+                        } else {
+                            cmapStrings.add(" ");
+                        }
+                    }
+                    return fromStringToCharArray(cmapStrings);
+                }
+                cmap = true;
+                return toCharArray(getEncodingMap().keySet());
+            }
+
+            private char[] fromStringToCharArray(Collection<String> list) {
+                char[] ret = new char[list.size()];
+                int i = 0;
+                for (String e : list) {
+                    ret[i++] = e.charAt(0);
+                }
+                return ret;
+            }
+
+            private char[] toCharArray(Collection<Integer> list) {
+                char[] ret = new char[list.size()];
+                int i = 0;
+                for (int e : list) {
+                    ret[i++] = (char)e;
+                }
+                return ret;
+            }
+        }
+
+        public PDFDictionary getRef() {
+            return ref;
+        }
+
+        public void setRef(PDFDictionary d) {
+            ref = d;
+        }
+
+        public boolean isEmbeddable() {
+            return true;
+        }
+
+        public boolean isSymbolicFont() {
+            return false;
+        }
+
+        public InputStream getInputStream() throws IOException {
+            if (fontFiles.size() > 1 && getFontType() == FontType.TYPE1C) {
+                MergeCFFFonts s = new MergeCFFFonts();
+                s.readType1CFont(new ArrayList<InputStream>(fontFiles.values()), getEmbedFontName());
+                return new ByteArrayInputStream(s.getFontSubset());
+            }
+            if (fontFiles.size() > 1 && getFontType() == FontType.TRUETYPE) {
+                MergeTTFonts mergeFonts = new MergeTTFonts();
+                Map<Integer, Integer> chars = new HashMap<Integer, Integer>();
+                chars.put(0, 0);
+                for (InputStream ff : fontFiles.values()) {
+                    mergeFonts.readFont(new FontFileReader(ff), chars, false);
+                }
+                mergeFonts.writeFont(newCmap);
+                return new ByteArrayInputStream(mergeFonts.getFontSubset());
+            }
+            if (fontFiles.isEmpty()) {
+                return null;
+            }
+            return fontFiles.values().iterator().next();
+        }
+    }
+
+    private void setProperties(CustomFont cFont, PDSimpleFont font) {
+        if (font.getFontDescriptor() != null) {
+            cFont.setCapHeight((int) font.getFontDescriptor().getCapHeight());
+            cFont.setAscender((int)font.getFontDescriptor().getAscent());
+            cFont.setDescender((int)font.getFontDescriptor().getDescent());
+            cFont.setXHeight((int)font.getFontDescriptor().getXHeight());
+            cFont.setStemV((int)font.getFontDescriptor().getStemV());
+        }
+    }
+
+    public class PDFWriter {
+        protected StringBuilder s = new StringBuilder();
+        private String key;
+        private List<COSName> resourceNames;
+
+        public PDFWriter(String key, List<COSName> resourceNames) {
+            this.key = key;
+            this.resourceNames = resourceNames;
+        }
+
+        public String writeText(PDStream pdStream) throws IOException {
+            Iterator<Object> it = new PDFStreamParser(pdStream).getTokenIterator();
+            List<COSBase> arguments = new ArrayList<COSBase>();
+            while (it.hasNext()) {
+                Object o = it.next();
+                if (o instanceof PDFOperator) {
+                    PDFOperator op = (PDFOperator)o;
+                    readPDFArguments(op, arguments);
+                    s.append(op.getOperation() + "\n");
+                    arguments.clear();
+                    if (op.getImageParameters() != null) {
+                        for (Map.Entry<COSName, COSBase> cn : op.getImageParameters().entrySet()) {
+                            arguments.add(cn.getKey());
+                            arguments.add(cn.getValue());
+                        }
+                        readPDFArguments(op, arguments);
+                        s.append("ID " + new String(op.getImageData(), "ISO-8859-1"));
+                        arguments.clear();
+                    }
+                } else {
+                    arguments.add((COSBase)o);
+                }
+            }
+            return s.toString();
+        }
+
+        protected void readPDFArguments(PDFOperator op, Collection<COSBase> arguments) throws IOException {
+            for (COSBase c : arguments) {
+                processArg(op, c);
+            }
+        }
+
+        protected void processArg(PDFOperator op, COSBase c) throws IOException {
+            if (c instanceof COSInteger) {
+                s.append(((COSInteger) c).intValue());
+                s.append(" ");
+            } else if (c instanceof COSFloat) {
+                float f = ((COSFloat) c).floatValue();
+                s.append(new DecimalFormat("#.####").format(f));
+                s.append(" ");
+            } else if (c instanceof COSName) {
+                COSName cn = (COSName)c;
+                s.append("/" + cn.getName());
+                addKey(cn);
+                s.append(" ");
+            } else if (c instanceof COSString) {
+                s.append("<" + ((COSString) c).getHexString() + ">");
+            } else if (c instanceof COSArray) {
+                s.append("[");
+                readPDFArguments(op, (Collection<COSBase>) ((COSArray) c).toList());
+                s.append("] ");
+            } else if (c instanceof COSDictionary) {
+                Collection<COSBase> dictArgs = new ArrayList<COSBase>();
+                for (Map.Entry<COSName, COSBase> cn : ((COSDictionary)c).entrySet()) {
+                    dictArgs.add(cn.getKey());
+                    dictArgs.add(cn.getValue());
+                }
+                s.append("<<");
+                readPDFArguments(op, dictArgs);
+                s.append(">>");
+            } else {
+                throw new IOException(c + " not supported");
+            }
+        }
+
+        protected void addKey(COSName cn) {
+            if (resourceNames.contains(cn)) {
+                s.append(key);
+            }
+        }
+    }
+
+    public class MergeFontsPDFWriter extends PDFWriter {
+        private COSDictionary fonts;
+        private FontInfo fontInfo;
+        private Typeface font;
+        private PDSimpleFont oldFont = null;
+        private Map<COSName, String> fontsToRemove = new HashMap<COSName, String>();
+
+        public MergeFontsPDFWriter(COSDictionary fonts, FontInfo fontInfo, String key, List<COSName> resourceNames) {
+            super(key, resourceNames);
+            this.fonts = fonts;
+            this.fontInfo = fontInfo;
+        }
+
+        public String writeText(PDStream pdStream) throws IOException {
+            String txt = super.writeText(pdStream);
+            if (fontsToRemove.isEmpty()) {
+                return null;
+            }
+            for (COSName cn : fontsToRemove.keySet()) {
+                fonts.removeItem(cn);
+            }
+            return txt;
+        }
+
+        protected void readPDFArguments(PDFOperator op, Collection<COSBase> arguments) throws IOException {
+            for (COSBase c : arguments) {
+                if (c instanceof COSName) {
+                    COSName cn = (COSName)c;
+                    COSDictionary fontData = (COSDictionary)fonts.getDictionaryObject(cn.getName());
+                    String internalName = fontsToRemove.get(cn);
+                    if (internalName == null && fontData != null) {
+                        internalName = getNewFont(fontData, fontInfo);
+                    }
+                    if (fontData == null || internalName == null) {
+                        s.append("/" + cn.getName());
+                        addKey(cn);
+                        if (op.getOperation().equals("Tf")) {
+                            font = null;
+                            oldFont = null;
+                        }
+                    } else {
+                        s.append("/" + internalName);
+                        fontsToRemove.put(cn, internalName);
+                        font = fontInfo.getUsedFonts().get(internalName);
+                        oldFont = getFont(fontData);
+                    }
+                    s.append(" ");
+                } else if (c instanceof COSString && font != null && ((FOPPDFFont)font).size() != 1) {
+                    List<String> word = readCOSString((COSString)c, oldFont);
+//                    String str = ((COSString) c).getString();
+//                    if (font instanceof SingleByteFont && str.charAt(0) > 31) {
+//                        s.append("<" + ((COSString) c).getHexString() + ">");
+//                    } else
+                    if (word == null) {
+                        s.append("(" + ((COSString) c).getString() + ")");
+                    } else {
+                        String x = getMappedWord(word, font);
+                        if (x == null) {
+                            s.append("(" + ((COSString) c).getString() + ")");
+                        } else {
+                            s.append(x);
+                        }
+                    }
+                } else {
+                    processArg(op, c);
+                }
+            }
+        }
+
+        private String getMappedWord(List<String> word, Typeface font) throws IOException {
+            StringBuilder newOct = new StringBuilder();
+            StringBuilder newHex = new StringBuilder();
+            for (String str : word) {
+                char c = str.charAt(0);
+                if (str.length() > 1) {
+                    c = (char) str.hashCode();
+                }
+                if (font.hasChar(c)) {
+                    char mapped = font.mapChar(c);
+                    newHex.append(String.format("%1$04x", (mapped & 0xFFFF)).toUpperCase(Locale.getDefault()));
+                    switch(mapped) {
+                        case '(':
+                            newOct.append("\\(");
+                            break;
+                        case ')':
+                            newOct.append("\\)");
+                            break;
+                        case '\n':
+                            newOct.append("\\n");
+                            break;
+                        case '\r':
+                            newOct.append("\\r");
+                            break;
+                        case '\t':
+                            newOct.append("\\t");
+                            break;
+                        default:
+                            if (mapped > 31) {
+                                newOct.append(mapped);
+                            } else {
+                                newOct.append(String.format("\\%03o", (int)mapped));
+                            }
+                    }
+                } else {
+                    String s = null;
+                    if (oldFont.getFontEncoding() != null) {
+                        s = oldFont.getFontEncoding().getName(c);
+                    }
+                    if (s != null && font instanceof FOPPDFSingleByteFont && ((FOPPDFSingleByteFont)font).charMapGlobal.containsKey(s)) {
+                        int mapped = ((FOPPDFSingleByteFont)font).charMapGlobal.get(s);
+                        newOct.append(String.format("\\%03o", mapped));
+                    } else {
+                        return null;
+                    }
+                }
+            }
+            if (font instanceof SingleByteFont) {
+                return "(" + newOct.toString() + ")";
+            }
+            return "<" + newHex.toString() + ">";
+        }
+
+        private List<String> readCOSString(COSString s, PDSimpleFont oldFont) throws IOException {
+            List<String> word = new ArrayList<String>();
+            byte[] string = s.getBytes();
+            int codeLength;
+//            String t1Str = new String(string, "UTF-8");
+            for (int i = 0; i < string.length; i += codeLength) {
+                codeLength = 1;
+                String c = oldFont.encode(string, i, codeLength);
+//                if (oldFont instanceof PDType1Font && i < t1Str.length()) {
+//                    c = ((PDType1Font)oldFont).encodetype1(string, i, codeLength);
+//                }
+                if (c == null && i + 1 < string.length) {
+                    codeLength++;
+                    c = oldFont.encode(string, i, codeLength);
+                }
+                if (c == null) {
+                    return null;
+                }
+                word.add(c);
+            }
+            return word;
+        }
+    }
+
+    private PDSimpleFont getFont(COSDictionary fontData) throws IOException {
+        if (!fontMap.containsKey(fontData)) {
+            if (fontMap.size() > 10) {
+                fontMap.clear();
+            }
+            fontMap.put(fontData, (PDSimpleFont)PDFontFactory.createFont(fontData));
+        }
+        return fontMap.get(fontData);
+    }
+
     /**
      * Creates a PDFFormXObject (from FOP's PDF library) from a PDF page parsed with PDFBox.
      * @param sourceDoc the source PDF the given page to be copied belongs to
@@ -304,19 +1326,51 @@
      * @throws IOException if an I/O error occurs
      */
     public PDFFormXObject createFormFromPDFBoxPage(PDDocument sourceDoc, PDPage page, String key,
-            EventBroadcaster eventBroadcaster, AffineTransform atdoc) throws IOException {
+            EventBroadcaster eventBroadcaster, AffineTransform atdoc, FontInfo fontinfo) throws IOException {
         handleAcroForm(sourceDoc, page, eventBroadcaster, atdoc);
 
         PDResources sourcePageResources = page.findResources();
         PDFDictionary pageResources = null;
-        if (sourcePageResources != null) {
-            pageResources = (PDFDictionary)cloneForNewDocument(
-                    sourcePageResources.getCOSDictionary());
-            pdfDoc.registerObject(pageResources);
+        PDStream pdStream = page.getContents();
+        COSDictionary fonts = (COSDictionary)sourcePageResources.getCOSDictionary().getDictionaryObject(COSName.FONT);
+        COSDictionary fontsBackup = null;
+        if (fonts != null && pdfDoc.isMergeFontsEnabled()) {
+            fontsBackup = new COSDictionary(fonts);
+            String newStream = new MergeFontsPDFWriter(fonts, fontinfo, "", new ArrayList<COSName>()).writeText(pdStream);
+            if (newStream != null) {
+//                for (Object f : fonts.keySet().toArray()) {
+//                    COSDictionary fontdata = (COSDictionary)fonts.getDictionaryObject((COSName)f);
+//                    if (getUniqueFontName(fontdata) != null) {
+//                        fonts.removeItem((COSName)f);
+//                    }
+//                }
+                pdStream = new PDStream(sourceDoc, new ByteArrayInputStream(newStream.getBytes("ISO-8859-1")));
+                pdStream.addCompression();
+            }
         }
+        pageResources = (PDFDictionary)cloneForNewDocument(
+                sourcePageResources.getCOSDictionary());
+        pdfDoc.registerObject(pageResources);
 
+        PDFDictionary fontDict = (PDFDictionary)pageResources.get("Font");
+        if (fontDict != null && pdfDoc.isMergeFontsEnabled()) {
+            for (Map.Entry<String, Typeface> fontEntry : fontinfo.getUsedFonts().entrySet()) {
+                Typeface font = fontEntry.getValue();
+                if (font instanceof FOPPDFFont) {
+                    FOPPDFFont pdfFont = (FOPPDFFont)font;
+                    if (pdfFont.getRef() == null) {
+                        pdfFont.setRef(new PDFDictionary());
+                        pdfDoc.assignObjectNumber(pdfFont.getRef());
+                    }
+                    fontDict.put(fontEntry.getKey(), pdfFont.getRef());
+                }
+            }
+        }
+        if (fontsBackup != null) {
+            sourcePageResources.getCOSDictionary().setItem(COSName.FONT, fontsBackup);
+        }
+
         COSStream originalPageContents = null;
-        PDStream pdStream = page.getContents();
         if (pdStream != null) {
             originalPageContents = (COSStream)pdStream.getCOSObject();
         }
@@ -385,6 +1439,25 @@
         return form;
     }
 
+    private String getNewFont(COSDictionary fontData, FontInfo fontinfo) throws IOException {
+        String base = getUniqueFontName(fontData);
+        if (base == null) {
+            return null;
+        }
+        for (Typeface t : fontinfo.getUsedFonts().values()) {
+            if (t instanceof FOPPDFFont && base.equals(t.getFontName())) {
+                return ((FOPPDFFont)t).addFont(fontData);
+            }
+        }
+        if (base.endsWith("cid") || fontData.getItem(COSName.SUBTYPE) != COSName.TYPE1 && fontData.getItem(COSName.SUBTYPE) != COSName.TRUE_TYPE) {
+            fontinfo.addMetrics(base, new FOPPDFMultiByteFont(fontData, base));
+        } else {
+            fontinfo.addMetrics(base, new FOPPDFSingleByteFont(fontData, base));
+        }
+        fontinfo.useFont(base);
+        return base;
+    }
+
     private List getWidgets(PDPage page) throws IOException {
         List annots = page.getAnnotations();
         List widgets = new java.util.ArrayList();
Index: src/java/org/apache/fop/render/pdf/pdfbox/PDFBoxImageHandler.java
===================================================================
--- src/java/org/apache/fop/render/pdf/pdfbox/PDFBoxImageHandler.java	(revision 1575872)
+++ src/java/org/apache/fop/render/pdf/pdfbox/PDFBoxImageHandler.java	(working copy)
@@ -26,6 +26,7 @@
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
+import org.apache.fop.fonts.FontInfo;
 import org.apache.xmlgraphics.image.loader.Image;
 import org.apache.xmlgraphics.image.loader.ImageFlavor;
 
@@ -67,9 +68,9 @@
                 (float) at.getTranslateX(),
                 (float) (generator.getState().getTransform().getTranslateY() - h - y));
         }
-
+        FontInfo fontinfo = (FontInfo)context.getHint("fontinfo");
         PDFFormXObject form = createFormForPDF(pdfImage, pdfContext.getPage(),
-                pdfContext.getUserAgent(), formadjust);
+                pdfContext.getUserAgent(), formadjust, fontinfo);
         if (form == null) {
             return;
         }
Index: test/java/org/apache/fop/render/pdf/PDFBoxAdapterTestCase.java
===================================================================
--- test/java/org/apache/fop/render/pdf/PDFBoxAdapterTestCase.java	(revision 0)
+++ test/java/org/apache/fop/render/pdf/PDFBoxAdapterTestCase.java	(working copy)
@@ -0,0 +1,186 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.fop.render.pdf;
+
+import junit.framework.Assert;
+import org.apache.commons.io.IOUtils;
+import org.apache.fontbox.cff.CFFFont;
+import org.apache.fontbox.cff.CFFParser;
+import org.apache.fop.fonts.FontInfo;
+import org.apache.fop.pdf.PDFDocument;
+import org.apache.fop.pdf.PDFPage;
+import org.apache.fop.pdf.PDFResources;
+import org.apache.fop.render.pdf.pdfbox.PDFBoxAdapter;
+import org.apache.pdfbox.cos.COSDictionary;
+import org.apache.pdfbox.cos.COSName;
+import org.apache.pdfbox.pdmodel.PDDocument;
+import org.apache.pdfbox.pdmodel.PDPage;
+import org.apache.pdfbox.pdmodel.PDResources;
+import org.junit.Test;
+
+import java.awt.Rectangle;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Rectangle2D;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+
+public class PDFBoxAdapterTestCase {
+    private Rectangle2D r = new Rectangle2D.Double();
+    private PDFPage pdfpage = new PDFPage(new PDFResources(0), 0, r, r, r, r);
+    private PDFBoxAdapter adapter = new PDFBoxAdapter(pdfpage, null);
+    private static final String CFF1 = "test/resources/2fonts.pdf";
+    private static final String CFF2 = "test/resources/2fonts2.pdf";
+    private static final String CFF3 = "test/resources/simpleh.pdf";
+    private static final String CFF4 = "test/resources/simpleh2.pdf";
+    private static final String TTCID1 = "test/resources/ttcid1.pdf";
+    private static final String TTCID2 = "test/resources/ttcid2.pdf";
+    private static final String TTSubset1 = "test/resources/ttsubset.pdf";
+    private static final String TTSubset2 = "test/resources/ttsubset2.pdf";
+    private static final String ROTATE = "test/resources/rotate.pdf";
+    @Test
+    public void testPDFWriter() throws Exception {
+        FontInfo fi = new FontInfo();
+        PDDocument doc = PDDocument.load(CFF3);
+        PDPage page = (PDPage) doc.getDocumentCatalog().getAllPages().get(0);
+        PDResources sourcePageResources = page.findResources();
+        COSDictionary fonts = (COSDictionary)sourcePageResources.getCOSDictionary().getDictionaryObject(COSName.FONT);
+        PDFBoxAdapter.PDFWriter w = adapter. new MergeFontsPDFWriter(fonts, fi, "", new ArrayList<COSName>());
+        String msg = w.writeText(page.getContents());
+        Assert.assertTrue(msg, msg.contains("/Myriad_Pro"));
+
+        Assert.assertEquals(fi.getUsedFonts().size(), 1);
+
+        PDDocument doc2 = PDDocument.load(CFF4);
+        page = (PDPage) doc2.getDocumentCatalog().getAllPages().get(0);
+        sourcePageResources = page.findResources();
+        fonts = (COSDictionary)sourcePageResources.getCOSDictionary().getDictionaryObject(COSName.FONT);
+        w = adapter. new MergeFontsPDFWriter(fonts, fi, "", new ArrayList<COSName>());
+        msg = w.writeText(page.getContents());
+        Assert.assertTrue(msg, msg.contains("(\\t\\003\\n\\n\\003\\013\\013\\003\\003)Tj"));
+        doc2.close();
+        doc.close();
+    }
+
+    private COSDictionary getFont(PDDocument doc, String internalname) throws IOException {
+        PDPage page = (PDPage) doc.getDocumentCatalog().getAllPages().get(0);
+        PDResources sourcePageResources = page.findResources();
+        COSDictionary fonts = (COSDictionary)sourcePageResources.getCOSDictionary().getDictionaryObject(COSName.FONT);
+        return (COSDictionary) fonts.getDictionaryObject(internalname);
+    }
+
+    @Test
+    public void testCFF() throws Exception {
+        PDDocument doc = PDDocument.load(CFF1);
+        PDFBoxAdapter.FOPPDFSingleByteFont sbfont = adapter.new FOPPDFSingleByteFont(getFont(doc, "R11"), "MyriadPro-Regular_Type1f0encstdcs");
+
+        Assert.assertTrue(Arrays.asList(sbfont.getEncoding().getCharNameMap()).contains("bracketright"));
+        Assert.assertTrue(!Arrays.asList(sbfont.getEncoding().getCharNameMap()).contains("A"));
+        Assert.assertTrue(!Arrays.toString(sbfont.getEncoding().getUnicodeCharMap()).contains("A"));
+        Assert.assertEquals(sbfont.mapChar('A'), 0);
+        Assert.assertEquals(sbfont.getWidths().length, 28);
+        Assert.assertEquals(sbfont.getFirstChar(), 87);
+        Assert.assertEquals(sbfont.getLastChar(), 114);
+
+        PDDocument doc2 = PDDocument.load(CFF2);
+        String name = sbfont.addFont(getFont(doc2, "R11"));
+        Assert.assertTrue(name.contains("MyriadPro"));
+
+        Assert.assertEquals(sbfont.getFontName(), "MyriadPro-Regular_Type1f0encstdcs");
+        Assert.assertEquals(sbfont.getEncodingName(), "WinAnsiEncoding");
+        Assert.assertEquals(sbfont.mapChar('W'), 'W');
+        String x = IOUtils.toString(sbfont.getInputStream());
+        Assert.assertTrue(x, x.contains("Adobe Systems"));
+        Assert.assertEquals(sbfont.getEncoding().getName(), "FOPPDFEncoding");
+        Assert.assertTrue(Arrays.asList(sbfont.getEncoding().getCharNameMap()).contains("A"));
+        Assert.assertEquals(sbfont.getWidths().length, 65);
+        Assert.assertEquals(sbfont.getFirstChar(), 50);
+        Assert.assertEquals(sbfont.getLastChar(), 114);
+
+        Assert.assertEquals(sbfont.addFont(getFont(doc2, "R13")), null);
+
+        doc.close();
+        doc2.close();
+    }
+
+    @Test
+    public void testCFF2() throws Exception {
+        PDDocument doc = PDDocument.load(CFF3);
+        PDFBoxAdapter.FOPPDFSingleByteFont sbfont = adapter.new FOPPDFSingleByteFont(getFont(doc, "T1_0"), "Myriad_Pro_Type1f0encf1cs");
+        Assert.assertTrue(Arrays.asList(sbfont.getEncoding().getCharNameMap()).contains("uni004E"));
+        Assert.assertEquals(sbfont.mapChar('N'), 2);
+
+        PDDocument doc2 = PDDocument.load(CFF4);
+        String name = sbfont.addFont(getFont(doc2, "T1_1"));
+        Assert.assertTrue(name.contains("Myriad_Pro"));
+        Assert.assertEquals(sbfont.getFontName(), "Myriad_Pro_Type1f0encf1cs");
+        Assert.assertEquals(sbfont.getEncodingName(), null);
+        Assert.assertEquals(sbfont.mapChar('s'), 11);
+        byte[] is = IOUtils.toByteArray(sbfont.getInputStream());
+
+        CFFParser p = new CFFParser();
+        CFFFont ff = p.parse(is).get(0);
+        Assert.assertEquals(ff.getName(), "MLJOGA+Myriad_Pro");
+        Assert.assertEquals(ff.getCharset().getEntries().get(0).getSID(), 391);
+        Assert.assertEquals(ff.getCharset().getEntries().size(), 10);
+        Assert.assertTrue(ff.getCharStringsDict().keySet().contains("uni0073"));
+
+        Assert.assertEquals(sbfont.getEncoding().getCharNameMap().length, 10);
+        Assert.assertEquals(sbfont.getEncoding().getUnicodeCharMap().length, 10);
+        Assert.assertEquals(sbfont.getEncoding().getUnicodeCharMap()[11], 's');
+
+        doc.close();
+        doc2.close();
+    }
+
+    @Test
+    public void testTTCID() throws Exception {
+        PDDocument doc = PDDocument.load(TTCID1);
+        PDFBoxAdapter.FOPPDFMultiByteFont mbfont = adapter.new FOPPDFMultiByteFont(getFont(doc, "C2_0"), "ArialMT_Type0");
+        mbfont.addFont(getFont(doc, "C2_0"));
+//        Assert.assertEquals(mbfont.mapChar('t'), 62);
+
+        PDDocument doc2 = PDDocument.load(TTCID2);
+        String name = mbfont.addFont(getFont(doc2, "C2_0"));
+        Assert.assertEquals(name, "ArialMT_Type0");
+        Assert.assertEquals(mbfont.getFontName(), "ArialMT_Type0");
+        byte[] is = IOUtils.toByteArray(mbfont.getInputStream());
+        Assert.assertEquals(is.length, 38940);
+        doc.close();
+        doc2.close();
+    }
+
+    @Test
+    public void testTTSubset() throws Exception {
+        PDDocument doc = PDDocument.load(TTSubset1);
+        PDFBoxAdapter.FOPPDFSingleByteFont mbfont = adapter.new FOPPDFSingleByteFont(getFont(doc, "R9"), "TimesNewRomanPSMT_TrueType");
+        mbfont.addFont(getFont(doc, "R9"));
+        Assert.assertEquals(mbfont.mapChar('t'), 116);
+
+        PDDocument doc2 = PDDocument.load(TTSubset2);
+        String name = mbfont.addFont(getFont(doc2, "R9"));
+        Assert.assertEquals(name, "TimesNewRomanPSMT_TrueType");
+        Assert.assertEquals(mbfont.getFontName(), "TimesNewRomanPSMT_TrueType");
+        byte[] is = IOUtils.toByteArray(mbfont.getInputStream());
+        Assert.assertEquals(is.length, 47888);
+        doc.close();
+        doc2.close();
+    }
+
+}

Property changes on: test/java/org/apache/fop/render/pdf/PDFBoxAdapterTestCase.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: test/java/org/apache/fop/render/pdf/PDFRotateTestCase.java
===================================================================
--- test/java/org/apache/fop/render/pdf/PDFRotateTestCase.java	(revision 1575872)
+++ test/java/org/apache/fop/render/pdf/PDFRotateTestCase.java	(working copy)
@@ -52,6 +52,6 @@
         GraphicContext gc = new GraphicContext();
         g2d.setGraphicContext(gc);
         ig.getGraphics2DImagePainter().paint(g2d, rect);
-        Assert.assertTrue(g2d.getTransform().getShearX() == -0.12626262626262627);
+        Assert.assertEquals(g2d.getTransform().getShearX(), 0.12626262626262627);
     }
 }
