From a21030a5024640738b3ba1069110dc73a5d8858a Mon Sep 17 00:00:00 2001 From: Artur Adib Date: Thu, 8 Dec 2011 17:13:17 -0500 Subject: [PATCH 01/12] Throw error when pixels don't match --- src/image.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/image.js b/src/image.js index 217e081c2..57c6d415f 100644 --- a/src/image.js +++ b/src/image.js @@ -198,6 +198,10 @@ var PDFImage = (function pdfImage() { var opacityPos = 0; var length = width * height * 4; + // Is there a one-to-one correspondence between pixels in the loop below? + if (length !== 4*comps.length/3) + error('Number of image pixels mismatch'); + for (var i = 0; i < length; i += 4) { buffer[i] = comps[compsPos++]; buffer[i + 1] = comps[compsPos++]; From fcbe4f13d100faee0c7da461601a6ae4811c797a Mon Sep 17 00:00:00 2001 From: Artur Adib Date: Thu, 8 Dec 2011 18:19:36 -0500 Subject: [PATCH 02/12] More sanity checks --- src/image.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/image.js b/src/image.js index 57c6d415f..f24d28638 100644 --- a/src/image.js +++ b/src/image.js @@ -200,7 +200,7 @@ var PDFImage = (function pdfImage() { // Is there a one-to-one correspondence between pixels in the loop below? if (length !== 4*comps.length/3) - error('Number of image pixels mismatch'); + error('Number of image pixels mismatch (RGB)'); for (var i = 0; i < length; i += 4) { buffer[i] = comps[compsPos++]; @@ -226,6 +226,10 @@ var PDFImage = (function pdfImage() { var comps = this.getComponents(imgArray); var length = width * height; + // Is there a one-to-one correspondence between pixels in the loop below? + if (length !== comps.length) + error('Number of image pixels mismatch (Gray)'); + for (var i = 0; i < length; ++i) buffer[i] = comps[i]; } From de33e44b09504f38f36f72f62b448caddd8a8c7b Mon Sep 17 00:00:00 2001 From: Artur Adib Date: Fri, 9 Dec 2011 14:57:52 -0500 Subject: [PATCH 03/12] Lint --- src/image.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/image.js b/src/image.js index f24d28638..a691bcd8c 100644 --- a/src/image.js +++ b/src/image.js @@ -199,7 +199,7 @@ var PDFImage = (function pdfImage() { var length = width * height * 4; // Is there a one-to-one correspondence between pixels in the loop below? - if (length !== 4*comps.length/3) + if (length !== 4 * comps.length / 3) error('Number of image pixels mismatch (RGB)'); for (var i = 0; i < length; i += 4) { From 2113e0615e835862d800b88bacccbdbf21c72c01 Mon Sep 17 00:00:00 2001 From: Artur Adib Date: Mon, 12 Dec 2011 14:33:26 -0500 Subject: [PATCH 04/12] Reverting error(); warn() instead of TODO() --- src/image.js | 8 -------- src/parser.js | 2 +- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/src/image.js b/src/image.js index a691bcd8c..217e081c2 100644 --- a/src/image.js +++ b/src/image.js @@ -198,10 +198,6 @@ var PDFImage = (function pdfImage() { var opacityPos = 0; var length = width * height * 4; - // Is there a one-to-one correspondence between pixels in the loop below? - if (length !== 4 * comps.length / 3) - error('Number of image pixels mismatch (RGB)'); - for (var i = 0; i < length; i += 4) { buffer[i] = comps[compsPos++]; buffer[i + 1] = comps[compsPos++]; @@ -226,10 +222,6 @@ var PDFImage = (function pdfImage() { var comps = this.getComponents(imgArray); var length = width * height; - // Is there a one-to-one correspondence between pixels in the loop below? - if (length !== comps.length) - error('Number of image pixels mismatch (Gray)'); - for (var i = 0; i < length; ++i) buffer[i] = comps[i]; } diff --git a/src/parser.js b/src/parser.js index 036191677..c307c9276 100644 --- a/src/parser.js +++ b/src/parser.js @@ -249,7 +249,7 @@ var Parser = (function parserParser() { if (name == 'CCITTFaxDecode' || name == 'CCF') { return new CCITTFaxStream(stream, params); } - TODO('filter "' + name + '" not supported yet'); + warn('filter "' + name + '" not supported yet'); return stream; } }; From bed87284dbb076c52086a154a1922bc85014e7c5 Mon Sep 17 00:00:00 2001 From: notmasteryet Date: Mon, 12 Dec 2011 21:32:20 -0600 Subject: [PATCH 05/12] Fixing Type3 text layer creation and character spacing --- src/canvas.js | 53 ++++++++++++++++++++++++++------------------------- src/fonts.js | 31 ++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 26 deletions(-) diff --git a/src/canvas.js b/src/canvas.js index fdb537372..5005d6e23 100644 --- a/src/canvas.js +++ b/src/canvas.js @@ -638,17 +638,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() { geometry.hScale = tr[0] - bl[0]; geometry.vScale = tr[1] - bl[1]; } - var spaceGlyph = font.charsToGlyphs(' '); - - // Hack (sometimes space is not encoded) - if (spaceGlyph.length === 0 || spaceGlyph[0].width === 0) - spaceGlyph = font.charsToGlyphs('i'); - - // Fallback - if (spaceGlyph.length === 0 || spaceGlyph[0].width === 0) - spaceGlyph = [{width: 0}]; - - geometry.spaceWidth = spaceGlyph[0].width; + geometry.spaceWidth = font.spaceWidth; return geometry; }, @@ -687,13 +677,6 @@ var CanvasGraphics = (function CanvasGraphicsClosure() { var textSelection = textLayer && !skipTextSelection ? true : false; var textRenderingMode = current.textRenderingMode; - if (textSelection) { - ctx.save(); - this.applyTextTransforms(); - text.geom = this.getTextGeometry(); - ctx.restore(); - } - // Type3 fonts - each glyph is a "mini-PDF" if (font.coded) { ctx.save(); @@ -701,6 +684,14 @@ var CanvasGraphics = (function CanvasGraphicsClosure() { ctx.translate(current.x, current.y); ctx.scale(textHScale, 1); + + if (textSelection) { + this.save(); + ctx.scale(fontSize, fontSize); + ctx.transform.apply(ctx, fontMatrix); + text.geom = this.getTextGeometry(); + this.restore(); + } for (var i = 0; i < glyphsLength; ++i) { var glyph = glyphs[i]; @@ -720,7 +711,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() { var width = transformed[0] * fontSize + charSpacing; ctx.translate(width, 0); - current.x += width * textHScale2; + current.x += width * textHScale; text.str += glyph.unicode; text.length++; @@ -730,6 +721,8 @@ var CanvasGraphics = (function CanvasGraphicsClosure() { } else { ctx.save(); this.applyTextTransforms(); + if (textSelection) + text.geom = this.getTextGeometry(); var width = 0; for (var i = 0; i < glyphsLength; ++i) { @@ -780,18 +773,25 @@ var CanvasGraphics = (function CanvasGraphicsClosure() { showSpacedText: function canvasGraphicsShowSpacedText(arr) { var ctx = this.ctx; var current = this.current; + var font = current.font; var fontSize = current.fontSize; - var textHScale2 = current.textHScale * - (current.font.fontMatrix || IDENTITY_MATRIX)[0]; + var textHScale = current.textHScale; + if (!font.coded) + textHScale *= (font.fontMatrix || IDENTITY_MATRIX)[0]; var arrLength = arr.length; var textLayer = this.textLayer; - var font = current.font; var text = {str: '', length: 0, canvasWidth: 0, geom: {}}; var textSelection = textLayer ? true : false; if (textSelection) { ctx.save(); - this.applyTextTransforms(); + if (font.coded) { + ctx.transform.apply(ctx, current.textMatrix); + ctx.scale(1, -1); + ctx.translate(current.x, -1 * current.y); + ctx.scale(textHScale, 1); + } else + this.applyTextTransforms(); text.geom = this.getTextGeometry(); ctx.restore(); } @@ -799,7 +799,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() { for (var i = 0; i < arrLength; ++i) { var e = arr[i]; if (isNum(e)) { - var spacingLength = -e * 0.001 * fontSize * textHScale2; + var spacingLength = -e * 0.001 * fontSize * textHScale; current.x += spacingLength; if (textSelection) { @@ -807,9 +807,10 @@ var CanvasGraphics = (function CanvasGraphicsClosure() { text.canvasWidth += spacingLength; if (e < 0 && text.geom.spaceWidth > 0) { // avoid div by zero var numFakeSpaces = Math.round(-e / text.geom.spaceWidth); - for (var j = 0; j < numFakeSpaces; ++j) + if (numFakeSpaces > 0) { text.str += ' '; - text.length += numFakeSpaces > 0 ? 1 : 0; + text.length++; + } } } } else if (isString(e)) { diff --git a/src/fonts.js b/src/fonts.js index de8a76dcd..731363a67 100644 --- a/src/fonts.js +++ b/src/fonts.js @@ -2101,6 +2101,37 @@ var Font = (function FontClosure() { return rule; }, + get spaceWidth() { + // trying to estimate space character width + var possibleSpaceReplacements = ['space', 'minus', '1', 'i']; + var width; + for (var i = 0, ii = possibleSpaceReplacements.length; i < ii; i++) { + var glyphName = possibleSpaceReplacements[i]; + // if possible, getting width by glyph name + if (glyphName in this.widths) { + width = this.widths[glyphName]; + break; + } + var glyphUnicode = GlyphsUnicode[glyphName]; + // finding the charcode via unicodeToCID map + var charcode = 0; + if (this.composite) + charcode = this.unicodeToCID[glyphUnicode]; + // ... via toUnicode map + if (!charcode && 'toUnicode' in this) + charcode = this.toUnicode.indexOf(glyphUnicode); + // setting it to unicode if negative or undefined + if (!(charcode > 0)) + charcode = glyphUnicode; + // trying to get width via charcode + width = this.widths[charcode]; + if (width) + break; // the non-zero width found + } + width = (width || this.defaultWidth) * this.widthMultiplier; + return shadow(this, 'spaceWidth', width); + }, + charToGlyph: function fonts_charToGlyph(charcode) { var unicode, width, codeIRQueue; From fb3a9a9828e32b90f0ac76f0c3676100a068b18a Mon Sep 17 00:00:00 2001 From: notmasteryet Date: Mon, 12 Dec 2011 21:42:39 -0600 Subject: [PATCH 06/12] Add reftest for issue #918 --- test/pdfs/.gitignore | 1 + test/pdfs/issue918.pdf | Bin 0 -> 52483 bytes test/test_manifest.json | 6 ++++++ 3 files changed, 7 insertions(+) create mode 100644 test/pdfs/issue918.pdf diff --git a/test/pdfs/.gitignore b/test/pdfs/.gitignore index d3caa968a..23ba6340e 100644 --- a/test/pdfs/.gitignore +++ b/test/pdfs/.gitignore @@ -19,3 +19,4 @@ !issue840.pdf !scan-bad.pdf !freeculture.pdf +!issue918.pdf diff --git a/test/pdfs/issue918.pdf b/test/pdfs/issue918.pdf new file mode 100644 index 0000000000000000000000000000000000000000..ac1a9c37f5e832ed353f2f0f66d167af3713749c GIT binary patch literal 52483 zcmbST1z1&0yFGM=(tT)|L zAb#TI|9(vnV4v~3>LXe3;AwW_RZ! z5dcFWf206~Afr1Dg@K2E#t1!(@mF{lBNPUPLjTA*6nYr#uMlZnC=_W9C{ze|@sDgn zVTa$tpr*JNFXCD|S{+uH@SioOaP5Y>wJVrU;f95~wVX9jf!4TuYSxan?si}pR1o={ zo4c#Eg#)hFs6Yo)rCEwHbiyf#X_Z2Z0=vTxMO`K*IV2>&14EbF&YID{p7U`|+5J=+ zuY8eCT8mCj8Rz)uZrxg^K@&4mw+@~wdY>vxUhWz7W4-%Isrq#DM{Vt3W$t9$R{^q{ zP~HCJA79shMn^916Bz0(?G#UbPp+Y32E{T5tNSv3R@sbr%Qk@X#Cyh_UPNKZqIIKs z6SLYQ?n^q;PQYbK3;&5O980$5&0cJgDd=PJ=2-Q-xLB2!WpQShJa^7ltVT#;XJW*Z ziHK4$&1vZP(yLav558ytVZb#Ka??*l3QNv|T7`BuxG% zWp9xVFLP)7w`XFO7Fti0^Eu{Ba{2LU%p9>2TU=G3o$-QDd1HRo04K&G={@XZ4}P>l zR4=J_9#Lp~JKskJ*DilWf9xW+esk<6<#n+k=V9l8K6|?gL(M%={Kv$^s}6X=@Tx|k z=4=_l(+UqXy+6A4zcvsE<2$u z@3YEt&Z;Nqbp>9B&gl4g{?vrF*q4+iCD*l4-%%3L&BCJpgws$h6H1N6ztbXQ#BcUh z$ZWlI_VFJ1s+cR8`0#l|I@-Oi_Apv{NIPd`9cc#!j+pD-wM@YeT!HSo+Q;)W7Z(iU@Bm4!^6#P3YYtSozS+6 z^%)ONz>VUoR<80dzwQTfU+Ilt=CUgc+v33cPF;%j25$`VScf4{aY0t}I{dy>bb&!~ z3BT5RbDXT(s8T1?OHz~z*y;C`N16f?~1 zEpg?V>`1GPiSS4iTUcoSMqd@H!h^xetxR|0!9ZUWB9$A1r&IiEN( zF5>5OT0CTA3a)W4B4-e&L%riK$VoSkMR{Mb_f$*ppVbmDn83+i)C-I(fF;HyKTR}J zP2z=%@M&Fzu$+@Yv(KhN7xUmqAH5f1Knhc;9ltxHy~1qePP|;*VQyMC@n#M&(b^&0 z;nm0~DM#DumGa$I?hUEpc@3|WO+JP(em+j08R4AO%a*ur$()2<@!`&W#Zax87Fwv) zt+wi&M4eBlq2Bo+B}6GP+i6LuS0Zmvkueyl-ybeHsmz}qo4Pe#v8g`PH;FNdIwyuj zo-rb|_*%L&V9`OFHd@!io>>=bd2!S4j?jzk&+WcLB1>JL%+0Ec>t)^!(c~jGlFrSIKjMcW=pwJEgZasqFE*qxG0>RsU2C9wT3BiCEAz8#xL!Ax^|}M z+0;iCQ$~vA&SO1puTPK26@SlVqlXu!O|A0?BVxNmm~1-GvorZY*5z_aYgM#vivj{W z3M+P^(SZYH-%8O~cXl*~Yv4!K_;hcvK9u06gV&fNRIaD!$b1h zpWJz>-A{P7|2F-JoOF-i&xYVadJrv$A%tHS@=Ol`(^G;@UzmoW;!txW$*{z`Ri}wp zZ!`rAnC#Ny7MSd2)Zwzq=NFsoYM}JsN=Z|M*k#?j#H&dWvWt-PpO+-PGw!-MjXRAB zdZWzXeQH*P&e}v^5crAyq~22w%u2-m6I_HLvh#S@uh}8RBcsy9C4p4v>9oztbby;8 z^waK6;zb$7Fv~7^D9&`yE32JB=_|7=oHJrs?s8%1e8OE_+_$E~_Hpn+EM=SUTN-a@ z7qNbRy3HJEDUgre5><)QL03X0UF3n+LjjV*my3R3b9Jm!WQ`|X^NO>5?@RcqLpt5q zL->Y6TL0Knf^YlNtK|YOCt@;beJce8Yi)v3n#8Vf5fVMoZkcfDNO58_c*rI)l=Z`_ z4rLB^cn5{@r&ZdiW;wHm3l$MLVHS_xUuH=p3^Crt^ybUD<`C&|VF=fg*xi+w-Gj7b z-h`oBae>)=Nh_*D{v0#!m^0QxNha!65`0KQ1NId56m&&aIDpumGHbNo=4S9?P@Mv! zfA2d=uk!l0KfFO1JcX2~y)Gn{Wg$$8t>T=iPRYZZNgsVTqN1NTJ$Crn`pUt+_Je_f z4Od6lldDTNK4-3$?rmw-!SYuZ^Lrj9?itv6TB%CN{jY(+gcxfTQQp!>{)Hy#7D_kP!z^cK=L~aPX)e5S z9aTK}2ATGYMxs}koyH$<%Dhj09gTI9d_vJiaJ{^kys#w@)`=&|StOeKJuSm^-M%wE zmrDPZnnYcahr@u_1=R#Imrr?{0Sn92Lu_j{;M^aE&4vn=fF-ZKBmKB(XK25DKqFS>Cq zsj=3-Y8^GDd0HtlC}>cO9E z2$xoHR}^hre8|p89%WO*;a9gpZ~a-x`$>z;0A4Gr1MlX{k4@=;%`G)IWg+i`>z-WQ z3KJ+v=d>9Z8miFlj?iH~2pDB@*~C>ITUju_{U+$nO*lzI_&fZZQDD)>|?#T1Ps6{p2V(IeKTW313o8Ld-0~Jit0c5zf-X zRm=5*xs*JST=>ep+>cmwj$XbY?*ixM64z_1>*op|-p(lH(=4C7fJo+YjxOnol4j_A5FyM=}Sgz>0rxIoX7Kh zzsiF^5si4FcdEh9?#Bz9G`N1Bv$i9nnnJmdz;50&ZjY++50+cFJUf8$F@9 zg@#6zdEY)z4h+NCKYv+m`#FcVFtf}$oM*VF<+iD`97!|x*fk6~Vzl!DqYvziB0RB| z8C15zynch}y4BCbPlJk{?S4AAj5PCF8=NZbSlmOr`J|C3SxY+9((-J9>T9p>F)Nl2 zCuM)J)N>-a95as=FVTm=!c!*;iLqK$n`G!jWLNA&wmTH@KKwZFeokR_uPNS=VYM4n zW500E7X_8`y3DDDJhNL5gYuu4W%L1Own+*f)0~P3%V-5d<_UYzRO};N2>Jl}WOknh zolIfgRWK)y`*Viwm`TOedBz>@XK*FzjWt!f*xSA)ymlJNc*~sZ4+lA$xN5kkMcQ24 z#HR|HH-bz;7cNFYd9EzX{oKYI?EZ)svhaX#VwU7B4^{8GFXcDAS7R$G15nfwhDeAB zh=qtq;Ngw|mU+Bj8v_zQ;_U#utEiz13RxI~%G_x94;@$|3gR9MyvQ5yZ|1^O&Z}0o zROf@HXjlpivVVo@e_0PP9Dmw;a}VotfwTLm7CO7TF9_t`IQMK1?^;^2ox1WZbMSHzEmimBcc1&UEQfcaZK4SZ)kbxDsWN=a`uz7AZukgEOSD0TQ(^&Qu^lXc16KOf* z8KaB%lnFQo++)3@i`DTtsb5+9H44j@GZt%et0~0sE_l9X&~AQ2rA&(Bz#1Z^MuPfg z^`ay(rAVr1z1jOg`^PCS(js4^3$3Tc|Ila%L~PT&r<5pq^&Z`x;C`I6XQ(1hKy@d| z9Ou(DJj$o?VW*b+%q}?$auR#6?hzwwgy4hv^yp%1H?TKxlpbAx7+e7Nqu{V%Hls)3 zgOfhyZgNP-C}IwohiTG5S$Z{S#cW_bFtxtElsvlvFSQBO(Dh(lLPA>(l|EyB%#C;r z>4#jkrr+56TD(I!=S5a@)V8#Gw4)!tAet#-u+PuYnBnPnZ4TBWL11UdF?U4xWGbH^Qf<(XWT z_qjK3ueOfPNtSU~pz#SH+;mR0&Dqxg{3mUr-}7q%yyWH5%BDLOmPTZrYPmH!?G=Wf(fn7c4E;2*wB=pA^ZB5BqS>Jqtq=jNv+){=gQR2Y&NGSxg9?Jq z>!Eq+Okf;N(OrZ@{NbfLU8ItcSWV}!#AkimwHsZ!!eV(zF_r}BUu5n_3`A{&=K60m zW+>aL)|q}&99XdLWL%(fk|p#^?4~qBu>h+my{%fB+Yw{kqs|GtC-XAy5=ok|W+D;g zSG=Knw)(5a`PWI*@AE5=EBHq3k}kgUn(OSn?>`u@B%`;AZe;yY6<8@{u*J-ZfSDDY7%S*&t6{KI>p?+06JU7jAd zIaxox`1BBVd)%8RkwDHyB`a4cGgh%CnCbj^pWyRG`Tg$;C>!Q5`iCg8no>EZ{lA-U z`MKNZdD?X`HA(tN#SLp?8Kn=;7lj-26|GA_rl2G859p(NriQU9d93#(+=edOAK*YHPhoB?pLFGk;=2FrDmDwy7C0+HDm(!7Re+; zeOkRc1|!M4H#Sy-Q^}X_EwYYsW#l@PE^N*?#CW>7NfRzVSfSP59&yBx!T_yCbbQ5@ zhv9U#7iE#mXFy-8j7!T4W7ExJ2gOQK*?Z>WK}w?1 zqFH2&QOp)bHeo`$BF#JPs{HEX;znPy4NdBUpvs`n7ah4rf|dtfL}-+DJ-G?Nm*(yB zl-A%tfu&8ZIgbX?_9)l|;5%Q-t`3AqG0O3Yl$xU;>z@v@~MuA z$6};jo0bWO_eEWc+U$`+W}j>~n|KD&F4@AIc8`)swYgI0MG_y~gUSXLGv$Ws+?H&U zA+DL>Ywz4laHoi8S5d`wOiNC+(V6{p=wAyXhaL&SKq*r6aYj;>(h2NZy!r3C*aR$* z5u|KJmnpekRP@#youue6`*?n!HlfZFEU$;s#1b{F67P4c5?gTB@`fmkwKf}XotO=CB zUg-$((uoO-Y@~0V?ce3N6-)_1~@5}yng@vvzX zwjDlySCnnJ%x^B2{40Q7JVv4y;aHlDC}uwAl*78d4{EI3jw+0k4wzN`3OW$eSK}9cfcy+3I&+e#0Pp%2od*4I? z^IzLq91nTH2O-Eh>KC?i79make)Xh*28QA9((^-Hu?%Tb6yN6Fuw8gy96bM6+pVSW zhx&SY-7Qtl0>;hri!{`fyDH8x#S_qihO%m(73Z|vgRG&fjP)qdD}CD&ws*a2)3gG; zRlWvK63prb;)81{$D8jVh928{ppKmnxZY9k9Xm%oEl*YwpZ~oJ=h5RbZO%`o{q3k; z@hi>u_&VP`MzyBV*4lmb*bCI#pK(%evBN?XILGDtkDdoC&|qMl@&yN&D%h@SCE z#Hj{4v*QhepL7raCrcw30C~ngXvL~EF+=#W@aQROXO(*3agB0ZcvtfukW()!fy=W7 zg;p;^>cV5Bl%+2rK3|o+QD^BnJ0>Y6(gRbrVpc4+s(!3F!#HDWHbcqw>uM#QeKAc}?)2t+SKVw6wt&WR#`RU%2rzv?w|!Gj)DPylM~(+3bFL zlm3-&b=A57^_!oadqH#;_H}waI#`3YHBE;X&AM)T++Heq#IXExXFc0-zoJ~_^LsNc zuCaP)(SquCcx%d>qR^ktj&gjs2ZELLb{6GlEWu zLAPI(&DyEBQBT2t&X)4IYDGEma}=6Ygg}4Zvm#gKZ&Oj|bR*aEC>zenkr*&nVd4@r zhp!7Y6(LF=vPZ6b3vj;Bq`RJ9F5QDeI&Au+cNg#Ccx>{i20Xia4?Vf$Q}2-kx+cH^ zIVnL`Q%t1VU-@fTqT1(<*OYORS3DyICIYPrJQnjf4W}~O2%$B=K@GODRgg|)VED$s zx44}Xeuv&g$UMCf#R*MR%P#U_Sd*>o^TKOt_8k^-i;54GTi*DHX57pxSmz^D>h>Zl zdsE=mDup2>NX_>RbXBpfSt|mwaXhhzk%4+xC!E@hv4lOLYf?`ME|EML&E22UGK)5> zlO(o18Dd*~=@~VNY6h#48;c!lYmUdJ?Mp6k!-EBCI;!y9$h0PIKO}J12UQ4KLBwJa;iOg4GIQ?Hb*~%05J`++aEoEfC0J9 z(GNh%1jucEy(9<*L^r>#foP8t2NX=u--!b%oI{it851BZ0)8HSAS?ie9VZPakzmIu z14<>>abkdy33i+q6e0|U{mv2~B7z+!jg%O{j?+e}j$pqN2ZTt6Zt7t%0BsWdICUrl z3Wgsik5n+hkE0e52E&ij7Zd`+kMjixpy01V_;~>t8S)JQLEgiR2|{=UkeNFA zS`f+$D8~Tx7mQZ~S%km;`C+{L{9w2+FY={7e!v8f@gCkkx_fj3FbeWj7?k(0qWA@Q z0j=863r8W+YP?88!g)o2DiA{Em7kwi;3$tk5)fWE%oN#h52aT~3;!0)DL6U0t6R9c zUh@JQLx4zNK)oI2_n&K1Tt071OKW`T@Oq5Lj@mF#|ONi zX7MXYKtKlM0LZ6|j1!Pc9vGMhXzqYz1w??X9jX41k8$}7uUWaA4LcK=a9ctY$4$o`P&{-f|a)b}07d#Kz49v;5(Te1fQ29)1P|0C9e z0>jB4w~<*ws`a42K=IG*Qx$uM-Qu?m|BaG{K~7Errri>U_{8{SR7}i%!E`s2&ySy? za5XR-0zBA(Mz|M@UMW7S=sMJ+F@AMy78vnqNfoNCn{N-7S=2F(rHx(cHyfvV3t{1u zeE9jCBJ?|12lkJy=JqKOQ@)pI-}^1qP=5r!4{Ri8B^eOCDq6aD-T(F?8HlIlvAF|C z_-g@(Sopq25!js#0BUeIqEmYM8I>hDe3U3@L>JX;qxBfw6&nOUw;8w4tB>%!>jj|49HIE;#(0Uk707F)iR2BqSlEvQK4r zuf`^!gyY34^~|__pB^AGga}R!Y=a_Q7jExfNF=>q;JP4&AH}qK!$HwEpAFmNr_KM zNqG?hfuKU+#Bb5o5JdP0=^YW`=V(8g2-Xpx-E|__eFOqwk@WUm0#_^^sLS0<>eS+# z9QgiCa|$`>KfjKBjoYY&ukdCdJ2pS2uh##If#aiuK*@jB`$7%7Hb|X98(~Yzm%zyR z3juJJSRav^;g!&(=d%W39_`xAAN>jQ?mXpM6iDdK2!$52Ue6rT8_k=f%Dgv6S3Kd< zj8Y6OMco=EjiD+63F~8ey+oa#LQSNszc9{fKqyoW7cNd{?7=sYUSTV9)zqTIN1vgw zvc5(3=}q>h8-K4$>T9My5xdQtUkS(CYDMT7K7Oy7tyq5^7*+oPLzM6s9*` z4WdVlHLu|qKz>+TCmpnve(ZWY?dCYu9P;Si0 zHh#I8%NJGar_tez@wX0_A2~st%{T%l!Rh4HHVF81wDO#{NZ-gd9lQE|pt!mQezO8GElVeTD+gbSSm zw<9x!pPA5b&Va9sv&inNG2h+IxT$SRw6VXr9^n1mOOuv6vRE8^L)2r_P(8SRxSAq{cC|7$ru|S=Atp#CzrIR2a{+Pyxz?z)F`U#{E#TM zbZqwWu-D$(8{iu8zp!T{jowC0k?y~1EtF;T`8wxQH7RWgJS72Z)%ppXaD;;1i~Opp z4;NgFT^iFKji&{1{J4(y4d&D6XFAb6b!t;PcFzudhku(!paLhG8eE_s&TohuFfDau ze~*|Xe~*~Zx&J<59$4(P)vqFmej?DMbnfk=#a5W_HPjyz`mYh8t!HB4`%zLN=*@Sq zSZJiC5tyOg;0}Km|sP%L%bFyMGcv4>9;_5#*AF!|G+p zq>9iRhtRl5r%1Eypake6`{KKUW{F?kAQn^(}W!%*9&poX=0bl5> zW&8_$hQo&8Wm>=-q17i)0qE4UApBZKQZ;_`NNNts%QE@LVl^^+0$`5tpZr^`rj1mq z6(H4W7$Tv&p$Gy55oiL9_^}`OVLd2_h?3ABJcZJVIg4q7>4_8WKxE*j2MZ?M1EEbC)6jT4TEIks7vXDuyP*Ati6KeF<*3mZGv5L=bO- zY(Z5kb+E!J7jg1u=u*YI<)AhoN?-waLJsl+qUvBo5bZR@zSeiQby~4rry?eLR zjG}T%`0M8K)AJ*uyS5O>Qksx&XT}QUo2OVRdil*n9|(Hu_R<*m-4fN!7zb{t3~!(r zcVA*Z)rQEm&Dm`Dms0yl-!Dc`l6I+){}u{#9knLn;ay{@UxeVHzc`vAK6<_$p;m^m)u8+l*TPXBlXmVw#U-C z-@Y=kC%yP2R z65{R;&9^Tz=*SB~tZb&i@TS1wa(C1mRjh%qb%k1|*`Kw<&(%k4Zb&?LYDDE`A`g}C zVnQKwR_lrIHH-|kd!Ue#ukifBd;VcRe>ObED0oJNoFU~w>{}zp8LS>!Py18Nd1fc} zZ+YrWpF{}&D+8##5+IEOu&cCs^*u1IOg+&*#PpMn{wLN`&P=@1@Xxp*D}kA)p{SQs zg<=1FiFyBqY^|#?c76iT}bcMw@VonJ1E=leYhb* zKT62+?JWy^8?9{A&#>ND%{9sfjH;9{`w}xkTO~Jh<7sG_^&4F7D-+A!k|?UfZc+Z$ zRd*quWHYjt!oa~C)($st)~w`xUT7!oTNbNdaOkt!H&7MhIj3-qJ4(5jPXDR2!;Ol% z7asZVS6*lAWbY*~^b}71++TRRJxY6nS61UiYG(I4qbdon0*cX^*Q}d;U!U7v^Zxb; zA@z>vF0J4y2>)fN(5ZI%KX}F`S&8%*V9@{}4bfa6u2LPV|3cAMk>^RUgLbImmDW;} zmT!=T#5@3WyuzZ`o2?9==)Oy9v{#SusI^h{j5v$UF-_&X{hGFArGhhKRCmR|cu_yk z_J+y;bA+`0bMN`{AKt>@&wYb?>RJL=L{`E$eS1N zi^|BUv8WCB^VtpT)Lc(B%h`Qm=*i~e(F?V2LT*K}6~{hk5ei4(@jr{3f?~3Vcyr|G zh7n`4P~oX74PR0m)brg*p0m&cMUpthgZ>sRhItk zgv~aa2lJM`Dd$#1`N-_$-olum5$_j$CQCZQ)iyNO9z@RL`7fZwwi=EHYC2yb{;U1LQEdBO&04gIrBb4mG1=ip6czk7(HgHIl|iKn3deYJ!LND9UNtj zOP4=^+|+ic{Lm)rXudpXQ!tyR33_P&JJmX8_Hki4Co1+zeniT=Cet1I#03Z@TOyv6S?b#tsh?IG-l0nW#ylMEFJ+JKr- ze4y;cgl7@=aO~>&pHn3;mAb0eea9+d7))C6wh9|P)j((VjA4Hf3a@+1fzbz8QURln zP(5Cf7hhKXITj6;@CbZ1Q4vaZ5BI)#8}69a+*Rx-e1+P;(AIa&gk#RbTL*Z1+4%iU z=LlIa&$p3$QWXv;y-OeZt!D+>1=lj#7u!<9ns@<~Z|*CKTy0todfd1|&dU&fX$8e= zIlIP>;$DiyA58l0>5TxHNFH+wQFEd`4^A(P5^@@kyTmu2Oe?-N zyqomyM;ok|&H8O=8hS^;L}l-&qa96ZSP%F^x80sc`f8X(TT$5cJBV!DFUB~QLnSYq zGA&>2Gs!1-CxmL&`D@VBVK?$DSWfwS!?RfM7I#^_bA_=6t=l|a7yM#0k ziSsW46vswL@E^;`vCKqNX)F_8ne}g`BH`z!F_5vavye_^~?u%#qMaPkk>xg zo7qU7q9DiEt`xvxz%qH5^jb&Te5?Ic(tXX1^*f_iD}BEZZyS5RRep1|nsvOyg1cXi zu~eJIfwbhV8w;%eQmSJ-T3zwN8rr7rOG zkf-H)5N|09SHRlhWj~IS^{z4OXiefBpzh3usGVj^{u9PL#D@>T-y;$VfX0ux7+`@5 zAmv9q5&(|_konOy6kxUhCgbP_Kw%vsD902Q@Zzrrg5bjyGV%cs&EZP&@Ff6#2JrQx zmyozRaw&m)fW+O8lSabb0N{S~007kmj?)H^@yzIJ1MCsNZXLaQm~-TF zxDYbUqc;VBV-=8fh9ozDtAF?+_{qWgFTx1&2VwN<`Xph*|NkP44jCJuMt(6yP~krr zqr(OYJUlC91TaPb_X)6@Lck#er!hu{HGG0G5)3{)qZ)v?PiKFS zWY1xQ|Cgg001oS{OL_j2h~1O8azH+TA9`nzxI>km(HEr(U7(G!7`>S4LcUSwnz=^2aqT?I7to_~k!Vt$ ziOhzCQX~!OJB)Me60S2K{&8Ufc@s{;Wb9c**&f_jf>0S~r08A2$iefkEf@1eZ&Ddm zt0E#LC7&^oUwVH{qKhsadh^k1BAb98md=Zp)9CmmyG_?qtf!4rgQkj`$EZFuyZd^L zO)wvT$|@39Pa9JK3j2&kgu+g)BLJQV4n^`r7?xL=F=Wxuj=(@>c$Pm(5>dR$Z>k73 z1puEoZvRRZl?g#s5l-eiF`>x;NhqOT6`}9e5NP;O2nJBoE&|2sm=dZgjMzA}7-#lu zq5OYAntv2S7DH9{S1E{*j1crU&=;kK1p0FR0{TKtc6o98Lvb<7O)_|K@yYOk3{z4j zA>fcQgj0Q_v@2Ku{6Y_Fi2#33O6(xl!Uk;PKe5Yr55Zt=zJ~zKmm&z-kJ%w{ZKBf+78;wymn zxh^sC_o(T3P{`*$Ui z14H>2H2R-LZgtg)zy9*b(!=)#dC8^JMD=?`>&JJ`A8kJ; zTESDkGZ3DFBG{attL1O2xd3uRCBUnn{FD^``2#WgPp)Mm_lT=GF~JZxx}XOm?tFZ< z^Z<=|Gm}U^>(BN(xIRkHQ6vKLE{XITl`Ca=R%34yn)be)a(FH;p%$TSaA4cx!r7Zv z`c3CRPiSF8&UAdr@mU@XMcX>~YWS;w)_9)^^{ftd%a7ueJ*+z=8b%)37eS+*L*%Db zl@M~0Ivchqc+%NRk1Izioky84!#)pnDx3i z78|*1N$;cnatvGGM?1Z(x|v?K*kMi%X3tUg&cP&)WXM=Oev` zw(k`6p-LjDXqdYwM;Jw)!#r%H0&FAALx@6K9Os<&Gh=QvvwAd-NGsZYnQ8IdZHKfx z)FI^*|G1#38UL3%7?*YKQJ!kn6K>zXF*C5gj)<5!-ky6I$pRvG=cwu?fBfM%2^68fIH3I;zb>_jQ(JBqB!W_X?!&qhFQ1K^0dFwfB_^@7|%gOU; zR2a`x0@2v+RXMcDbDOqF=k#MHg*a}nUNPU>6=LUqRrChG0fX#DQ^>-kL#5ljP;wSJ%CC@~3KW5ra>SF(}{jL5b`Rlq!`R9VXn5rR6!LS;$a4i=>F&>lS2ta;vR`|5HA zPf;Fgy1@|t5chm}BgJDwTJGZFtFseS!#w0S^-9aCCL!d@z-De=af|Z0>MY#51P)vm zzLkF__OBcdb9U1bv8}C%iJ&X$7xPa_>XMnIh@`JCkEggPu0PV4G7XA#3-D3X;M}_F zD*m2fkxX#0&2Kp;oo2A5m6G5`S8`U`-mYWA(tfo(Ma!Di_^F#= zHLqtcZHC<%y&1ol#y(anXve?3CVUhnZ9`M2W9vPJyR()^1kbzwpY~&nj zkT)pW8id&?a~?hPp)5x@w+i~DA@nZM?|mcfg6>OYtmf~F!`>@YW*f?yzaI_qjDtQ> z9c@bizmG3tOr%*|Q%%})A34{$tUaPZL@cP-&$=xA1A9C6BGW2#1tKct<9`cl*t*t+ z(98E}wHLv5(H$)*ZC$DCPYbe~oEplCQBABZx1L%H-snvRI~cc6{mxA1%pM1ul`G`wYKt}vI%3hPB?BpdiHGpine&5 zj&)ZCF+sG!_QxNdl|L$z-y1t<2+yR<6j%?B=jZc?6gCB$?kbUAU$n6*SfWkNzSm*J z{N)=V7wof33{UdKUT$``&fO>o7BPyob~9=?Q{p%5y_sjIZJ#o~^sf;etic0&u_bdk zSPc?!(*in4^ke2j@cQBt961E(C&(Hu^AkDla`_C$ieDs~Z+~LP5NE>BhhHNf6vgI_ zWiR~XRD=%@ww=)|P?3}F6kK2c4n+=cI(-6q5U74x*)Licii%6kap{tb)o*W6EvgFe z78_6X7NvrI$%k+$rTi(sqg{+Y7i6Wt^dU~kmqmwOZ8WIE8}fre4i=<*fRL(RWeAdk zT7<_(VHK%8LztU8O0j>S0X$4d8QfpV*SvP`>Npw(G>Dd?isputG-4c!gSvjA`v3tF z#-ybDMUneTg^irrdC%y_PUPq*#(RJ?lh>v)BZEXAnz~6R#97c zx8&BME#-R3g4`P-B#eqEEbpezm#O#U?6;x*M7!mp^)r?>yEtLgo`m-6eQUF*Sb<9y zsGeV3y8QLt^V6yNc*7AOj5{f%?&9&)7cXE%~^`!;HXoNTLDgAJZpOs zJ~={u?v+G}yD(QvNx7}c9tHKK)enyvxL?@8S_02c1OEHHz{s9b#jo1l=xrLU+oIt? zUZAkO_J>m7Yi}OP(Yo4SpjrdZ%F0owSSHBQEL-~JxM+88p?;AK^*X)@e)>kxURLr%c1*RX4zcfMAtu-yo#o?V%;E?Mxo2W zn1`==4qv)+>7ZhVp~ZK)y{VFEQ|Q`*!AP?_Ik!{AhyZ%^hY^6aJ`^cHJ;KP4y6wY7 zC=%vE0tx_VcKig6)TAE&0FJ#x`qxLV0Z`R35{E=Mj*&P3-T;37dI^B*0O;e_4*-ff z91#yc2T+E?ap35O02qJ*k6#0@n4|Rnz}bY3mte*KvULc<9U)U^3k8LEk-0bo*MtEO zP=ps5-LJa<(Dh5!{m<3!4**p+fG7#Td4c>MT?6fX|>2TO#MVx@c zfP+l`Xj%UXhaEvnhev?|n-~7TzYbN!Kme%Nf5TqD<^ev7qX3C$0XqixEP%`b`vZQz z0>GNUJzxXDAFvnzNdotf0e}+%0RT7u5h(yBA0o;?fCRe$R1*l02?5YE5FkGTpkyFG zqGbTO3G=rez02&jWY@E8b?-vS*C z2$0_*#oiV`hXMj*YRD61kys%RAX7sgCj0vUS>Ou!1z>z&hsNn=#{v(K-yWYB3tS;n z`|F%opydMhM8G0{G{UL&&s{jEnwULSsoJVX|_Mi&2XFcNtOne3q&-2&K)fV@6zHc+6^0KnKk z8HFO%_7=zximbBVFzTT}pg;&k9-(`D8#u`icpDkQfQ>Bw+y*2C#Y06mQlO~ob_8*exc#*-OG*MTy8ohjJ_xEOvWj2xLkrp?3Pk{TmwEgI zQPN|S1VM8h%!ug*>F)u`g2Ejm{%SCD*5o)PPY5Rw69S>g&N!(h&|X6s0habxVVMG; zJ#$4mDb`;?MRkPN@M#_j(4PM2-T$_{fC`-iRN&8tkR=9Lz}+ye{wgs1@0Dm$@_$~5 z9?QIwBv<{+WBmY8X3#!E=q`iQZji)OkZ34^fv8&U%80v>qHW@GhI2qu_`1-%M8Gfdwy^ zd8T`#Tjpzwd>rEtozA^U&{xR{waw_7SP>TBW zP>PD#iiW?$K)K_W18}fotl8cmnz^07VOsYWoy{nR1O}_P^ znE?m}v~?m(UPH~NQoJBUq2Z}VV*rPNpS8wee}V5OTI#Ru82`VPN<+EB0BQG=l9oD` zCF~1q3ZIa~FZTnv6yF>1gX|&vK!LxOLmaa5=BL)vv6uJXfiHoRo;n;l2OSaQB)SnU{ZzD-9qg{-5$L`sOcUXbcl7+2k?KptOh9oZr* z5{y5>%{05F6U$95TbHfp-agqLnkyRU(@&?xglNPN>y3O!Ei#A0;ij|$4q7ixViKtqHgcfV?? zdAu6bS6pHdSBa!km%|d^JaZ7RKuNcHUD)y=0CYyKJLd5bjzz~ z7`m#zC?-5GL)V|1jxPV_@i^eZ)uTN}i%5D2;K~?$>cL|N{tX!jG+8=QM1XlKLl+jM z9|RH`2?*=a+NS3VN#VdWR0RCE_iL8TVKYWQwP0sQe1%W)sHQ!~2mFwmB+2lBg@J80 z&p1XY`>+o+<%bO-VZPrrk(P0W+>%xq*JYvs2H&F+n~z4_5}9_auk7_~|LNajCCj;c zLs8%MW}dQ)O}8Km{2?sas$ux;vXsrUG*>CM*=TeJ&Iqbel=SmeFJZmKCS+#WZoMyH zRXrrzrPxX>JK7OCYX{ozH4kcNsfIYagC+78^nE-67#w0l+K?B=*pL=TT30n(&6W3I0{cVXs=x@8hjmz5 zNvdOmhS_;V{P$JIIO{Jr#Hx$kCN>ZaJgc#fb-l zMz0gODoC_Tf0Kk9n2RGavqN7aB!l)O4-oiEQenqFh|?uI0vxKu) zBptUl=kCmYr6xbcWByLMV$_*V1?@$F&rUJ$PW$IznkUzsR0)f&!}jOFa!KR^g!Lf* zLMsKe);wrD#}ip$Gi?xNxPNd5ZL8dB^|y{PALk}$>&MrFya!B{JBV8Y{!yICwqI+m zR}H@z*O?-h)X$9fJ=Fkbcfv&e+C~X~4~GJi0?0xa@3+sb`@dY!l>gl6k6q9Mv<4JR zOyW&6nf{npUZl1m?N}nk(_1EFr61lC&%_WkyyO1|zW)&Mk9s=U=X! z1SIj)gZ@R%?ApNuPr5Qsj?W{NM8{XNFv6Rd#o&+lRAS7N#{T<^z5e%IsXG_yB5t9- z1Y7V`~I*|HtAt{>U z3x>3zd;`dodq*dbl%$3}N%@7&qQI_@){}lV$;9(8r`A{wUuFfhk#RrU_B{a!D+T6n z-l(2AY8YY;HfRr;*|;A%Tv9PE>mszk`NBMdb4RB}l+~KYlcvFwL>KGz{UHf`6w#H1 zv^ta&Yqtldwyra~hJSBwydQfgHw}$}#D1D&cGfhPcCdm=t64$%I~s(GbAuFYckRS+ zV*sstQOG0A^Aw{MSDr3^-ru+8kG3K0`@~%huFkt2PLzo9Vla5QW#*nsO% zy>w>TacGjQ1`@Q5H=+KIYh=3G7lj{rZgyNmNF%jgd!?MDHI|Uk@Ky6(AzoOd)@p0 z-uJ%l*=w)8*RzJb*0Y}VJii~c;@&P7sq}fF%D5?YkG;xSFE9{#ap&%FNQ;$t7AFZmnQ z->;W3KRqh^sdE3^naqe*e=QOdHLF(>OW1k%0j8Q77CnnF%Guoei;d_Gr^nVGxyq4R z$L7X_K8t!Pb90$JO}og>(sa_WN#g{$ubfE`J!i@p?C5UOlcfx#H7P7V^KCKj72eeh zk59%mQ>2J=wuvm;y#6Ix_0g)c@M>f0Hv4Hl;p)S6n>O3l)mS2fbMiV2<{j{jvZM}y zu#zP9=mw3XbsvP7#G@q&HYpi`WrqA;9>+v>cz=G)J}i3-JjwLtTT+bDx!|P9sVpb+tulOx18z1 z+s2EXCcQhq{8;d1xgJ<|*R}K@Ng+LgMEZlIkc6IoM&{`&!yl^VFW5idu6@LQ)@R;s zce3QOF`9;>ikpT3KrU@t)pCh2u?oA85LzE_R4#BDV*5-vRnXwVZ*ZF#PY-bOwFbF5 z#8N|tRCxWiL1Kj3wt|}LeVAXuo84(lZW=3#_Ur?G=}R3l3+;6FlE0e^?8J&@RWhsU z?nahaXpKJ}4bYca$m;ph14YW2*4FNx4X^znzuYcmamXhM)_y{a7doiq|CS-Df+6RHKG=mz#jZHhSx!J}-keUTW#mEezY!V>Ih z&7eK4+}fTN1L;bFmF9nRrSo`Qso>w~O6n)ipBs*Z(f6U-5X`WlTE-}c-=ujkdXu)0 zsO!AFS#GH@fkB(mR9f%Z>%--zlf$WG|tr&t>%U`v+kT_}ro737} z)&TyB@W*%)JYY*ljlMw>Pj=Sb zb6YCT{*|bs7MpBfUCHMpjpEiFMb~LiSHucB?Rn4nz9^|L7b&jKLjL-ZXlMWK=$QPg zQS;LGJqL|?m2ca|IFXaT=H%-T`nlwt!(4qPI>H18VcH758w1L335bwfRo)AnP7 z_G6~y&KLU0^Mu>a(aD9$Y0mKLU2%@je6)*7{Z-_4ra9H9KGMq_jhS;+X*Ni`#{Q=; zV+r2zz5BmrEpBfZ@v~0gka{=7@r(Yj!sacvW$hLvN4VoRN^R6{R%6xjfxy18kzI9s zT|&v~Cwerh9N0Au-eb1>(i2zGrPa82b1{oF60Rsn-kLAo_bhaFDlGVOr(e)Z!&@(H zm@e29dA%4rF1*)Np4H&6afC>4YK?dK-M-rN4>2{YljRSU>Q!{FA1Lw^ZqfGwPfs<3*T?*>m!O+-hClb5r4gd(+AhrAY64Tyh=TXgC&0xjiwF zZ7b0)BqthN(Z`aDUJM846}p>pbM?$saGSNfS362FQkN~UNJ))z{rBPIv=aN-E9)OoXgb<51A z!%|qTs%cu6O#AMuFC^OZOYD_!{2A8*7e6R9%0`fQ|JoO+t#V zY*4&wPK})kp1R%SL_kU{&q55T$io{f4{ho9s0cD^sl}GGZae9p%cwWc6hXNSwPQ)? zXuQFtkDhYyhfaImBH@(UE$1R=c1Au!{N_XO^Teohk{b2}Zzk|`9Qx=P&n&S3P*Cvx-l+q#;JB0TuWeqQfIhIeIQKH^CImM*@N zF84uzvJ*eG7u=G%LZ3gz!IX9f;6VVqCHHiyZ(`qe6lm%0&bLP@M*iS-c^+D1#_N0S z`H{BJ&LXbKc7W! zQY-c6p4z4pUB3IoTO^ph;L;MLA*=yxwerJRA&;`tpN*b*JDq+Y7JmGe|BIEA#aZycC!Z>R9y)gpE5Rgt`vQfR<|=D`H|@N^Ij7yp5|Go*sFWWU&Xu|r(%_` z>fXG$wyZcKv4m!f>`o9Gszy&WEkQx29w;T2D>{Ak_N~H06h08c%XyQX6snE;rd!DE zAGMCb$9|u#xWGG~Y}rp-rCH%zsV!btYe4t>jF)&#rDEjtLzh(Fz08y^DcZ zA6=0fEMY=scE_&lFEeA;cvSL%ERmM3zu}^1EbkZzACEdCFXiPCw`%0qC`ykQY2Rov z#kA=AjbuOA9InA^ifIlo!zfVG?oxydk!%3KQ=j z{y4ZKm|C4Bd+&heAQ9!3EVl8q7BYpaYeiQ^ZKGkn*$<{7z*J~^1rb?yf-FH`?~|n2 z*36GnZ8GKAc8obaMF~H@_s>ZD=R7volD_-u}8|9z44$3xQ{j4vs6 zI*GWF%f&=p=yuDT?@gIa|87kq7RvfT#?#G$la7w!H(zy&{WfYEXN~2Tl^jMYy4{v_on(yVYX}kRw9ET{v0d#m3HU067&wv2J$ZqIvJ~+eq zNoGkM4Y9TWtUPPOgn;GnYqRdntJS0m{+riI<_1AZ7UJC3q0=lKiScgEOC zaj4MTXppRqm!xGEJ{53+RCFZPn}zDRz>T(!8J_YyM|GQ?e5306HfvGK?+oTe&f%Lk z*p{_n6j9K6a;kC)pqh#k)h9h0!_yc*+UKXcM@I;_g2AQOC`!omX_*7XMm!W~b#(Qv z3)Jb+3VHOMQ4M|U^Eui1XXc)5`a;J={lxSn6C^Y*-jsO*OGV$7;G!SsOn1wd z8VRqR7)Xf}{m^ghIw|zlSB_2K8ob1qhCH}I%(TTQKsMzk)dEwtr%G20FJsVn*y7&o zmt9HWm3;knT9z6JQ|{7vb;qclO212oxkoCms!W@Y;yxTas#*VK@SfkHaG0UV5cjS< zS$Aglr6}grdS4i|erymyYJ9@t>*fu$b?q8}>k&8?BVVFrp)+hMCucN;nb{v3IuUZ$ zzcHe(+tWBXnE+}R45^4m?Sj$c9Ibf8<;;N->d9XKL8k$+rg1+kG~U#O5Tcvi>K=h; zg1wc7H<)Wh>hc?A3c5%a=Rd2BPu58Kn=HyH5$Fs(3s<;{|IQ|?+WS1xYFgfXy# zMPjP;%Hu1td_skKo{C9Usc+pPON0ckJC^H7PUP;nJ@WO_QK9rJZjyRsb=f?VVg_6h z4DfK^)TieWZD_I57i?iT!yw6HQSc7l8Fs@jT9sRuGe$)oLgS`N2P(So`#%U(%PR))p zD(5=o%}I~#^*R5lM)MSd{qvt}wXdaj9eNh4w3Ee4y!=?V34O_R&IHrkF=^xOz2UZn zk1zBdZhQOO#cbSAF1yop`}hI5Y-1O;{iKS^q#-ZGA8%gEEi1IdCg8QxP5h2z1NDF(Ky!`9<6)C^UD z-%mfljAa<1Q0;rR-^gt@7eQ^8$X5C!-cQLhL#6RX@aE?A`JZ*J!qn9%p}vgTkVOW* zo1^R5Rds=Qt-q{pF>zWcXG%w?c^jVzUGFju>Fsd;{QEptF7gzQ-}@8Z0=!%*9<^!G z7x-H%>?ZeSS($S8Ih)eSi@N57-+z}{meHFedoki70^CN6XHR zw?A6h?AF_#AJ}wxg&zHFZ%6+l9{)#z+iMa+ycR0QHENB8<&Okn&AjvuTep^-$;hmc z0AwMersKyt&ze70d^UW}`>`6M`LzBV?SdK~CmGGOM@ZvkuVb#sGOV1`l{9A$I{x@H zF#MZiP_dq4vX!J$-DOX^Orhf;iPxQ~p0~@h%rj$5&7KHch%09}PNH*JjcwDG0A6BS zT_wY1r~*;MJ*o1%L#v#~aB~3BGWxmuyW8uM@He=e-X8fm zZ!3$J4ZEjHLe!K+U4JY7W;lF8(M0*JTZgaT(^s>{;|>K&h#zPz?I~hbwBZ`b)DA_t zU!&k|u&ln^$McIu0?(b8@FTZHxmm#gM3~7=1bi zbpc)0?`787Z5?n9^(vb^m%X^GUP^bAhO(v(^~9Mw2Su^J|ICmo@3xy(Hg#ay%Cb`KOM@4$np9VN%k198YcCQ=6vZ9FD1O-`oU?TrGN*Qt&-_grd?726 z|((?YF#omUR~ZJx!pB9_~;CD-a$% zQ<^^d=6*Mz#wD}dL=M3W`8^;uAJ6k*R@C``E-Vbt*f(Ooma^o0;$AqlxP5TEg>_%f z>$4fTwZ~t3DhWJqYl;2o7S^!uq*qIrIXY#ZYryUz=`i!smR!swnkrc>?hX<1^Au6F zWXy6DY0M+b<#E-_!ZP+DKV?kRO%N#eh2M>c9=3`zp}rzhQ&(Ixg7bGLNg$>hBbPrM zuT(dGNE$k8^o~>RMTx98<&Pa_N~B>=WosHdPa1@il`WWW3Y>_T0N(CDIdo_VzuiE1tQTc>!nBxSsCH3vbGQKbhF!`>P$9 zmsBsbXcYQ5>S#PqSt2@ID$Hd3!3#3i*cbeg(Um83d`T!x+&vl@YqeeYOf)Scnaw9( zNM#+WAV04e&pquWMi*J-e%DPPjH#Z#X~(7CIZd|TQs3p^)JqH80!fD!pK5MCYPPIl zfs+J+QS&TC5vW+K6us_j?y$GPeCm^#A#o@4`Ngwno2GvVhQ#CbZ%Jt4Lya{P1mzF|DaT1Q$!pBPc53ordPA3N z{~>ORD{UtDcboj03{gK2&Dt_RE{P03!H@a6sQsT&) zZ~052uLE6t?%Jh4XgKQ~+?dp$6VY5z95D#z93$+A zVsWNY=7aQxbl=LAl!R?N(-V1jc}j=v+;>j&Kt%dvgh^>&ivCZMSte4CU2`mk{llv9 z!VW@TgMpKGE+L2`@z z#KfIykts$&hFh(M_C{Au=}J3Iu)i*S&|f5^C){6|AY|p64L|q=Sl;#1u2eh;s<2fV z(A)h&&muc$?**RbUD_TIl+*9|6-#G#JAdy;dy_VN`pUk(^q9FK9OW)u+$UeXuet|K z?^rho&gjoRxfr5ZG($*^e~{1?}GV0)0LCbSxHedOR zb<~c>RNg=w?y+&NRVW#zn&$POES?~JLzV!eU#arv`F#Stvct_vU|h!We$oWOCs^!Y zvPjg9`bt4n_3Yp!<=Zd|-hi+jkIY3YADe%4X-N8#^o6wdBT26-EIbtvF~UT8uWH0@ zh2*6B-c4bZzz%DxnkouO=m2QZ+31Cz@gW3#&#Sz&opfVIYHWa~1w{b!YcnP->PnqP z_6G@{yMF-GypZkm2{&r=#y=@8H!m+M5AM`16Du*s7TfLlmE6a_Qq1djsq)&O=dBjK zr0=Kas6Q11WX;6 zuW{%9xPUI;5G3lqaiGD0&nF)za09M}=`B)5z&)Rn2z*UzQ#ILEd2)sdhMsT3sYU6V zz6!U=>}WtNlG3+Q;c$Fv>*&zryE17vujZDOMHCT+qS5;KLF6tm^79~MQ7QWHVU{~F zeCvSp09#Uz?xB^uj(wv}Wq$FT;g_D+rSuaAr1$kt1@(`r9bxtF{}iMamWcT&+v{+v zJVN7LL1|Rob@O%uk#MB~xsmw`urpuMIC}1txwJhlvy8oTG#Y!#qQQuirGY{UscjZ$ zX8-JHNv3kkFSMC`593m)4dt=K#8*8Fd>6`p(K7Yce&ty@1OAihle`sutv>@7ZKv?z zKuTMX{J1X~>oeHLS{rV$Ll{%a*DPpUwt4exS#c!hnf>D@{{LeXL_(uL72dcI`vCZh z{wDnhd;}LMPg2p-|4`!vPQfr773U(AI%*{D2!cR1B!Ml#9^;m&I7hhqaqX%O)$T($SlO4M zmrU?^D&yl0K6nUq(z5*Myw@)ynHQq9yPHZ#OQ0BP90>(fch%y3Yfke+RK@>dMcK06 zha#e!cm|F{R)G(#+Zve-^99mE$$m=vA}_K#kzZpr%mxlcW)&tkJC!q1eSty(_z2pt z_m8N}QAnQjadRJtypZ{{J;~te%?h?xmdmEy61@S1PqB|%X3wxQ+>?D3;D6_s{?&UQ zf8I%DxYzPq)^g;`a9NIUg?X$ZrzOgFO%&DJMXy2Q7oMBE@{Cs^?E$$H& zE}^GnykvR$X}n~b zk9-Gw9n;>FoF{(sS!K)mDvHRH>~I%^*b89A-N}(k8g*{eBL|DKy>)w}8OnCO)GRJU zWoZ;oTIp&iz5$rMf#j)NNxh9uFCbb{d70F#(ziXf#$R?mm9l#(n0IX*&A8fQUCz5@xmSWQy1Fv`oITqU^hC{6 zc0RZ5i5*DO>=Cp($#X@F>-sJBCn}LM-n0kMRwNNNCYtJtsTcJ{HMDe9F;OcywR1tR z5AtCbrC?K08KU*3jC=jRkqSQzsog)Ace?q`J+_B8Ue>h`$HUSHyucX=%D{L zK8HBY?$*m2>jWMF%=*X?@evfoOrro?`;RN)MI;oqkwrMz3BxuTS5&E$)JhoXAm-$F#91 z@)r#8G@M*&)%-T^I#RbKaExgSn&R?#)cU5q zM?y>JL3a}6tr{b%g!;%6cJ13$98XF8dc2%&6ptHQQm%NldwY;Cck9hFWm301-yNT) z9@9yRSHF;G7Zy+v8r*kR;wMbG=%nE0jk$F-m*^}Sz(fK2JOJQ76BErnAqb$JJ;f~w zXd|L_k{9wk(u0VF(CpnE1D62~{9>yHa8(H4J1(u$?`D?yz7VBN^j z7UhQd_+*@RmVD&g7x=52^r(TMk1KUi1wI^=YSJ^s2&_iUo~ocvUGN|`NnOheF?4g~ z-pg)OTwh18h}9k|cb&h`7qPVb`CUb7|J;Rp_WRDN<;^_%Ixp8FVR%)pXvX!E_pHsm z$g{Z1`9~$K>U#~wBTXW{ai4mp^|IFWTHnQA#>yWu*zUnDlOLTX%~Q&6+PtNsh|5I2Z2-sF@RBN?hCVirEKd5- ztz6bM^KgnmRQ=|4-mrq`1$%cjG-$G6~)X7`CFjmF7FJ2xVu71wXHv{OV8U}fv3mg+F zpWyVrQy+0;$|EbS&ZS)U-0M6S|Hsew%G?ps8Ffz4HC_<^Fnu8BL_5ZLNh-^gRXc-47Phbq3M#zV2@>`z0cDEQOBF=ko5 zCMA*;GPhrQ55=MGgnzizC^2)!##>8s(50JtNAdMxgf_j#`HtBqZD5*S?Y^6()&|;c>%Yf$0ti}$1i!PB&Is# zn|S2Z=6EdvR-K1x^cqD6zF+*dZzz+qr?XiwQCBPH(bx@drd*e{93g=bv+Q(tG-OjB zX%9E#{hqa-_uionQ?DIduj~tG3wop*rLAZr-PsVHyM`E)&X-?25A%(^Epqaz`biSy zaj$}KXED~J>4*9ct~e<-bcwyJAO5wsvQh6OT{x+Bsp_WWbVxj?^w!#d$SLB_{&4lI zWgkM$a@E|5BnJpnoVIFzAxz<;y@?T~R`*Kh@O!1tOyC%Wb0yMYIaU8V9>RbmeWz~* zUo3fTGK_B!*uNVWhz)R-^o!NH|IoNDzGEqCe<<)nYzf=LcX^nonf1QA6q~0 zCW0kJ%k`jZpgF-Dij}MZG41ASG3_u=%iJC6|I{+6<6q-w{Xt#bMo-V#Pex-2ALavi z6lxvxk0#V4!KSV`Qq1kdlYOLo@Dp4sh!|g(CPM(&7o%aZ%8D=;PPN)?t&SW)x|>F4 zA@L~STkA;$LjQ2(RX;e&A->z-B;5zJob4*$i-l3+`n*l?}KhX)URzKmgLC zCvpy%0@zMroy63+#5)SRcV;)7;-k~~?uud6<0M@An};db2Rn*YcVv+)cx6jx-)t*8 zwf*o26Ej2Ap2HUG+Yjhhm$JL{896a=pGt2Yj(tCu;4_|fiMrO)LlYOJsZ+jbpZ^z} zT12Wk)aQ`*7Kx*?<{vx`!3~HMTX5d$=W9bRN18+q;hI~SR#cDR8gK=_VY6s>1l1#- zTs{QO(ZgY-u^}o()r8{)>=~dLgYm3Kxq1y~pV+)&TQ`6bo$8>GeK!!0TN()b1<@?P z$noc!g`!!U|B7Z=jr{$$(Jax?i&V{|0P-@4it|f9HxpvnQ7JrX5!U<>27nu$FiopE zAXFP7qZ(JDluWuwmnf+lBa6?G#x3ZeqTQlE2r!onlZe{>m`T^j1`{U#t|eHKD(CZ9 zo&hF*X_J)SRB0rhf~NtP2>=nmsm2VgshirhZkuaJc!2vYj((;E@{=g$nTMXtwXZ%WHyJ*>TrR4d{}OQY!4w8K%xM|KPGq_ezJco!iRP%3}JtjtZXXtk$!oQOycP zvV&qtT3LSG?+dPGahZlOI-4F!*UMv2oqA4p(fhuOk@#rr=OJAYcPt-?oh4a<8LX;c zUo3}brNPWCd_Y+H^3LowG za4?(qF&nPe-5k_<2Ag|8;u#LMHZm}TF&=-`I6PLyIyBG!gq5+NiU7bK1P~c`G@gF} zk%1t2FoVN2;&9w)dTTR(hWG&3^}OBexFTL$UsGer>HH9r%5Na?ZM%95%=nrJP*8#>r5S< z*1^7PD%lajUPXoFYchg+lRRfE+Cl1dq7p$-#V|PzbCLk0HGq1Wm`D_fC#Kk1cM=6c zL1c+H09himl*{dhR`Ye_1F{65vgG~4l^E^ypAU$W80cv_80eY$xj31o0ccknfVtE~ zR3ohr(@0LlG=de;h7cmrQd=N3nIkb_!^rMRkm< zO>K(qh@YF+c+38WC^X@b7vK(nh<;8!$L79m5}dPBBZch|-S+Y?mN7QoWSwCa9xmz- z%h#L*htEcg55E8L%bwM+i7S+~Cq$nmz}TJ7hm(?LPVD>rj`2jj#Hn*lB!jZ2x{c)L z?yAa+iM*khiO{1esuQd*Amh9Z*Su9;%=NO4Q9J~xEnLadu**fGpm~fTZ6-Z2?#d1WM&M9j zu}(uNLoN;BoVyh@7#a7eCgY<6+*e&^JPw&I9$-;7;A=GRyC|g99~Ar}(FnP`;O3C{ z&Eei1rHr_@!KJC?Dp|q8${Bsq94fz>Ct+1yrk19MOh=CxTzZ%WHby_o_UD^fXV^Ub zYRWEeey#kLnp^U%!^N`=(G{mAqw89plTah*hQeGPR^&1@*S*Q@RG!BiH0(t$GIMgV zv{gho_NY1CxykG8S*!NkJUZOr5oe~6p_kLPrwtEVFhz#*+?hCJ(<7JYK<#Y}1(rfr zbqe4+IfuoYrNdwK=Upc$>0? znc6vrMsrJ%G|dlU@4~6D9@-y6P91zgEk2Wv{G7cojJ?49FtoPcT%(AjOwy6T6V4}1IpA@&BnCRm@W#IZLzn4kOaTFdUCHMUW6vz(qRqZFlb zzWK6;we>fZ&y$9IN!yoU6>LrXn>OIqS*U=4lwbg&WnbQawjPvD+YSCPN0qV(U*0w`xyvG1tuwLf9j6&57mm7$VJp`1JWqHz(M>( zdu)i8GVQ)OuOA>%F!ThEvTo~S2d*p2^+#(>M@NL@H5rab6;I;XJ$ zt;vIm*SI^2KAxSWD$Lix%`g6by!dOpGpE33*hz%LtL(kkmc)TXXL2& zDq6WnYULN}v)jMx?=&e0nQ6+=%OUl-t3WmLuJ3@TMhl_E;E-!I;r%wbdJ{*?9 z!DJJ&H${v9Yw?!N;l%40vImWZAoGA8Z;H5Wj*wm3ddpEjn^K#0`IeG?1RqQv1?A*Sx#|=#3$ez<)jkK{U~) zz?t{2JrdUAX~3rtNpg}aD*pUK$1&$L%e3W|wLk^*(E~A?i@kM=B8qTljYb3O0Z=#~ zvh9E5HrwzCpWV_Y{2U+}s+uPPJWGJKL`eyET9(J|f;W^=UJFRyU2vx)kHVQ&Ku%GP=Bz2-xM@}(Mv`=*J?d^9- zhx@*gmAjmZe|U{f@1fauuHQQlXvg$CLvIZM>8Sc{e&n-XdqW+LG0+37e<0(y`I&_Ak_+6wNT=Ad-fY&C zSb~oi!lnh7vg>%y3J^=y`UMt_g<5?T30fYG2b^5Jkb?ts)%82Fa6B;K>KzPVF#B@{ zV9P=WXRCKmaDYF%et}1#UB5uU0SfKv1%S&1aI|Z`v2ca;@&TYO9ux_B6+qa?j0+@G=`U|2jj36u)}_^u*p;4dK3ET|3e7XYFdv0gY(&mr=ywL1{y)_U>y zw?VE6_-7!FuJ!7Jy*q@gy>#n+zLRYI; zz3VbSWv+U@;qO7nym+@k{BuAg^tu#~q)34Cy!w9Nn2N*`;okWY~Xk7>}j#tlcp=@A;Bi9+^AUtKjRJB$p_%x7z$PEDmGx86+A=IYG zzxWM-ba)#)^ggI3R;|&iSD=QVPgkn}_1~&}bM+nsSG?XKP_HBZ5FJ7T0{MsP5E?5W zmhaD7fGl`h0RAnYxIc7SHL2J@C2MjCVj;8auqVEEFYmshi_CF7q5?*}0BsI`Vzdq2L!)x22QRZ_^+tAASP zZ%Nncjc-u2oHUqgSDSV9HwwG~kVN7;VKsfNuB+*2s9vin_-;bFu00DgfRIPvPUf^BuRbMHvY=JcjU%oc< zHLd*w6YBcJqYWlde52vtCu8F8<80;{2)C6n*`p1YF?S6KB*1P*f)DQRqW(R2JK?4^ z$kHG)Uz_>ilBL*%V)4@?FtUtHvjhnc5%7nSa<;$E7WyE&Nma?jB- ze&2_^mL_wWzcHI0?!jC=E#S-_bRcKZEyu#o!b0FUgvT5(7 zeznZww?)g3T5#ob`B2eGIFF>%e=|HM_dxg{FB~aT@;)#+^=o~R>nuh=zMz8TvbfjS zeyq6H?{JoPqP0P14oXPgP-Q^P#_|N(l|LH{NgpU>D(ui0J@F;|3ipMhC-nwYPETb> zF1p)tO&lLgxYMI_HDEzLF34Ky%w3wMS=uW)T-FYD7A&~|h@VpA?9<)$u}o8n@o|^G zTuM<%^c}9fZpUSA$~7Re;MXR zb|EFc!QshSe==v`S3M(67e0+G{D_Br(CC6QcMljbNGU2-o9idfh*`&#|s>RQN47vlxNXz5$8P@f0EY9`FF=q9Q@C&*Qi&H&>Fgh9o67d@(-|1J8Pw3rdq(x{>0YRw!7ns zm|KPhin)}0{~~9+QyWTaj)r3&rEr*-%*8XlK}D`dWw^RSX|M9Ok9csuseNX zj?J}@D$S;zDw1R-$!DCkJ61$nyS~H~=J<+ybUI=;>~uEU?<^;^`}wX=+cK8#rzjm( z?&x|M9yo6+7VG7k!`hAxY2bTsAg_c5 zkd_tT(ctEF&>{J?H;%8+zKlbhV&;tAL;sz&XSIG>%2H>)zi0bppzt?mxS#~7_j`%b zo&uWU$znTJ8P=D#Vs`H6q}?WFWopp+JvgD=uUCJUZm4L2oA*JpobR!P=Unm!{P+z# zSSF4ixm%QFpvrP}sA9HGx1@ijBFndFvh(+w1Mb|~8HT4?zcv)=h~1T|K5aNyl}+JJ zc}w1((uTWP%#JNx4J%ji!r~ao7cDOeG~bCQU-e3@lvo}j$HmAU)6w=9sBqO%X}!V=6r~{?=Y5vTUln(EN~KtI`%~F|_dotMUyU@qxAfamHvRCgr`vC4 zN%%Xw$6EW{Xc$X7`tw1NqBU7oOTF{+d#2i_j1}x!i~8bK8+QymC{y2|=dN20tC3M^ zO4ELT(sS{owB27YSljp}EHy;;%FAT!cN$6O#vJeW&A+m?Q@+`nYTso2L&i~DorPj# zg!^*w&jY&2Y{#v?%rK08^|u|eo}#`Sx>JNnEs8ErH9Z`&D^@Agt#Q$uL3hE0CyR%v zX5h}#4`NxD=ylnS&+)eo(tir;+Ml6z@29-v#cC4c!n)i0w~>9*5^wari0bHn{K-O% zJ4B6+wL7M_>0)-dl99*lp$pWuR>Hx%kXo76<%X!&94N1@B!QS+{e^E?TAKEXvhTin zZ<%R?+LI(J%g^&w4gdI4o12zeV!J=I>GG9)8sc>okczGO^u+aQv7wHxro5hoQ}59G zC-M<0bm>tpDJKGtHQ!J*FJ&8iug&@>?z4~j>pKx8H;0)Wo%t^WXDIbWmN?mC>AB5v zg++!!=Ep9;#+eK+lG{w%uAoasg>M->m@M}z@#;s5H;>sw4eiVJz1^F8$gFA~{x?w6VpJRKZqRUldKC?YFQg`1~A5v+1ej;q( ze2Q`6g{9qcOUe<4GW%J7DL$1s7hKQ#?l+Zu0~dU=Z91g;|5-9k9Q|FvqPezv`-ebi zZJ%c3>f-5$U!5WCK@Mn=@(QRwi?fNNyDM1n!Kw@15dbvz)s5rdn)}~n8F;z`z-{qc z5AX_2pCG8+4(7aVWlr9J^niPW`nvl2 zySl-B9i0yW(LgqHe@9zyVzp z2JER&a_cfm0gWAgKnxPj(DSG(9ECtA$n0@-@^n0MU>E$5uVbJ`fU6_?=-TtL(m>6F z1ojN{2I7HVKn3#xN9Oq7_}YSE{)6oQ^h5|~23oL9lt<74Tj<(9U{fLsHqLJF)iewi z195vn|Gl6$sLRg$3Hw5u||&$Yw#9rhta_hJ5T#)t(+W`<_=Yy5DL{HD zVLmhpvL6to$wJl{qBQKrXE6Z7fjA#V7P1KtK8wLZIxt}xC}LxpEVOeb$|nyQ3kcKX z5RlqUl!o3YpPU?I@FB{l0L3v9rpZJ0E#kCI`a>QI?QjU6#o~<_L}?hv@QF4&Ql_*VN!#4vAZ4lxBVLr6%hH(HaXwY_>Fdvxc zi2E1V#x{IgzzPPeBt*~3A|Qh%;rnFKkkOSWO%}2b6QyAxt1n@i9C#s78VcB{Hk1K~ zTsG!IZ5S^gco15`2+NR{g)GuUX&dJQBo+Z#cnR}iF;GAjQ5qQd#Ayn63nF1Y1vC_C zLX;-Ip{<~WjJUoi@JSQPj6%pkc0PjlfmqTF;}iu%As#~*ITS?qNc8N+c?g36t0{3l zl-!1KfI?w6%vT_W53)NGmVpLQY8%pIAxc7`d|1dlPnd>5Y-}qGYQxw-VPqliVWMZ{ zA^Rp_nk<+kHl%GFyC_-NjqNOph3wpf?~}vZMu^fd8|HhIocxCM7bTC_*jDmrV2C3s z1B~4b{U$HJvF))4=%|NK7A$7NoC9^+hI%Lo=yMH_5kgjY1>kH>_o7pvn=~15BqI=1DNyL$)?T zSwJ@8wnC$T+DM!a6tdx2G-iW-fJVzh3Or#MXa(prf-nt(Kc68=!$1cgL}~IH%auiJ zSf{~Kv9axe*0|w)vRLRaim(hh#73Fr&>PlOpd~_QN`%h>@ivqp4|oVS2*bQ?c z27JK8{f0rKH|SCrpo$XDyBIWfqs$n@2K@?5?Hkr}3>a6$eT2cvZkXFa+TY(>pueN1 zx2r!b-d3%5#LWlnoq<@;A+V{B57-ss_rBoD%=4Hle&;2lw+C*kgvKhkxVXB=qn*)m z7_1Y*4I}HSfJMo>Iicm<0AsC+5>nPp!4=v(qTRsE;^^!mr=Z{hbO}dCq_Z=ay;Sf< Z?SMc>|3Lh{4g Date: Tue, 13 Dec 2011 12:58:27 -0500 Subject: [PATCH 07/12] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f3500ae4d..97db68d36 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # pdf.js - + ## Overview From 45ef8742ac4dc45e7fddd5f2eb3bed9608b7439c Mon Sep 17 00:00:00 2001 From: notmasteryet Date: Tue, 13 Dec 2011 18:28:02 -0600 Subject: [PATCH 08/12] type3 font.coded comment; proper geometery for showText; glyph name --- src/canvas.js | 4 ++-- src/fonts.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/canvas.js b/src/canvas.js index 5005d6e23..4aaf75508 100644 --- a/src/canvas.js +++ b/src/canvas.js @@ -687,8 +687,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() { if (textSelection) { this.save(); - ctx.scale(fontSize, fontSize); - ctx.transform.apply(ctx, fontMatrix); + ctx.scale(1, -1); text.geom = this.getTextGeometry(); this.restore(); } @@ -785,6 +784,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() { if (textSelection) { ctx.save(); + // Type3 fonts - each glyph is a "mini-PDF" (see also showText) if (font.coded) { ctx.transform.apply(ctx, current.textMatrix); ctx.scale(1, -1); diff --git a/src/fonts.js b/src/fonts.js index 731363a67..83ce4abaa 100644 --- a/src/fonts.js +++ b/src/fonts.js @@ -2103,7 +2103,7 @@ var Font = (function FontClosure() { get spaceWidth() { // trying to estimate space character width - var possibleSpaceReplacements = ['space', 'minus', '1', 'i']; + var possibleSpaceReplacements = ['space', 'minus', 'one', 'i']; var width; for (var i = 0, ii = possibleSpaceReplacements.length; i < ii; i++) { var glyphName = possibleSpaceReplacements[i]; From 02bf65fc0dd32d4577bfe8cbedacbf2ca5930fdf Mon Sep 17 00:00:00 2001 From: Brendan Dahl Date: Wed, 14 Dec 2011 12:30:20 -0800 Subject: [PATCH 09/12] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 97db68d36..7e5d2eeb3 100644 --- a/README.md +++ b/README.md @@ -205,3 +205,4 @@ a "PDF Reference" from Adobe: Recommended chapters to read: "2. Overview", "3.4 File Structure", "4.1 Graphics Objects" that lists the PDF commands. + From d1f4e7c7d53308c53695ba12c048a0f9649d3512 Mon Sep 17 00:00:00 2001 From: Brendan Dahl Date: Wed, 14 Dec 2011 14:02:00 -0800 Subject: [PATCH 10/12] Change to passing promises. --- src/core.js | 23 +++++++----------- src/worker.js | 65 ++++++++++++++------------------------------------- 2 files changed, 26 insertions(+), 62 deletions(-) diff --git a/src/core.js b/src/core.js index dc44edb76..a6effd2bd 100644 --- a/src/core.js +++ b/src/core.js @@ -515,8 +515,7 @@ var PDFDoc = (function PDFDocClosure() { // Tell the worker the file it was created from. messageHandler.send('workerSrc', workerSrc); - messageHandler.on('test', function pdfDocTest(message) { - var supportTypedArray = message.data; + messageHandler.on('test', function pdfDocTest(supportTypedArray) { if (supportTypedArray) { this.worker = worker; this.setupMessageHandler(messageHandler); @@ -554,8 +553,7 @@ var PDFDoc = (function PDFDocClosure() { setupMessageHandler: function(messageHandler) { this.messageHandler = messageHandler; - messageHandler.on('page', function pdfDocPage(message) { - var data = message.data; + messageHandler.on('page', function pdfDocPage(data) { var pageNum = data.pageNum; var page = this.pageCache[pageNum]; var depFonts = data.depFonts; @@ -563,8 +561,7 @@ var PDFDoc = (function PDFDocClosure() { page.startRenderingFromIRQueue(data.IRQueue, depFonts); }, this); - messageHandler.on('obj', function pdfDocObj(message) { - var data = message.data; + messageHandler.on('obj', function pdfDocObj(data) { var id = data[0]; var type = data[1]; @@ -601,8 +598,7 @@ var PDFDoc = (function PDFDocClosure() { } }, this); - messageHandler.on('font_ready', function pdfDocFontReady(message) { - var data = message.data; + messageHandler.on('font_ready', function pdfDocFontReady(data) { var id = data[0]; var font = new FontShape(data[1]); @@ -614,8 +610,7 @@ var PDFDoc = (function PDFDocClosure() { } }.bind(this)); - messageHandler.on('page_error', function pdfDocError(message) { - var data = message.data; + messageHandler.on('page_error', function pdfDocError(data) { var page = this.pageCache[data.pageNum]; if (page.callback) page.callback(data.error); @@ -623,9 +618,9 @@ var PDFDoc = (function PDFDocClosure() { throw data.error; }, this); - messageHandler.on('jpeg_decode', function(message) { - var imageData = message.data[0]; - var components = message.data[1]; + messageHandler.on('jpeg_decode', function(data, promise) { + var imageData = data[0]; + var components = data[1]; if (components != 3 && components != 1) error('Only 3 component or 1 component can be returned'); @@ -652,7 +647,7 @@ var PDFDoc = (function PDFDocClosure() { buf[j] = data[i]; } } - message.reply({ data: buf, width: width, height: height}); + promise.resolve({ data: buf, width: width, height: height}); }).bind(this); var src = 'data:image/jpeg;base64,' + window.btoa(imageData); img.src = src; diff --git a/src/worker.js b/src/worker.js index c0496015a..c18de65ad 100644 --- a/src/worker.js +++ b/src/worker.js @@ -3,41 +3,6 @@ 'use strict'; -/** - * A wrapper for data to facilitate adding functionality to messages. - */ -function Message(data) { - this.data = data; - this.allowsReply = false; - this.combObj; - this.id; -} -Message.prototype = { - /** - * Reply to the action handler that sent the message. - */ - reply: function messageReply(data) { - if (!this.allowsReply) - error('This message does not accept replies.'); - - this.combObj.postMessage({ - isReply: true, - callbackId: this.id, - data: data - }); - }, - /** - * Setup the message to allow a reply. - * @param {Object} combObj The handler that has a postMessage function. - * @param {String} id The id to identify this message. - */ - setupReply: function setupReply(combObj, id) { - this.allowsReply = true; - this.combObj = combObj; - this.id = id; - } -}; - function MessageHandler(name, comObj) { this.name = name; this.comObj = comObj; @@ -65,11 +30,19 @@ function MessageHandler(name, comObj) { } } else if (data.action in ah) { var action = ah[data.action]; - var message = new Message(data.data); - if (data.callbackId) - message.setupReply(comObj, data.callbackId); - - action[0].call(action[1], message); + if (data.callbackId) { + var promise = new Promise(); + promise.then(function(resolvedData) { + comObj.postMessage({ + isReply: true, + callbackId: data.callbackId, + data: resolvedData + }); + }); + action[0].call(action[1], data.data, promise); + } else { + action[0].call(action[1], data.data); + } } else { throw 'Unkown action from worker: ' + data.action; } @@ -108,8 +81,7 @@ var WorkerMessageHandler = { setup: function wphSetup(handler) { var pdfDoc = null; - handler.on('test', function wphSetupTest(message) { - var data = message.data; + handler.on('test', function wphSetupTest(data) { handler.send('test', data instanceof Uint8Array); }); @@ -120,15 +92,13 @@ var WorkerMessageHandler = { // undefined action `workerSrc`. }); - handler.on('doc', function wphSetupDoc(message) { - var data = message.data; + handler.on('doc', function wphSetupDoc(data) { // Create only the model of the PDFDoc, which is enough for // processing the content of the pdf. pdfDoc = new PDFDocModel(new Stream(data)); }); - handler.on('page_request', function wphSetupPageRequest(message) { - var pageNum = message.data; + handler.on('page_request', function wphSetupPageRequest(pageNum) { pageNum = parseInt(pageNum); @@ -177,8 +147,7 @@ var WorkerMessageHandler = { }); }, this); - handler.on('font', function wphSetupFont(message) { - var data = message.data; + handler.on('font', function wphSetupFont(data) { var objId = data[0]; var name = data[1]; var file = data[2]; From ddf9c43116c2d8c21b82c41a4b2da136c2d2b8a8 Mon Sep 17 00:00:00 2001 From: notmasteryet Date: Wed, 14 Dec 2011 18:44:35 -0600 Subject: [PATCH 11/12] Fixing setting of auto-zoom value in bookmarks (#938) --- web/viewer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/viewer.js b/web/viewer.js index bdcac09d5..daf0174ab 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -537,7 +537,7 @@ var PageView = function pageView(container, content, id, pageWidth, pageHeight, ]; if (scale && scale !== PDFView.currentScale) - PDFView.setScale(scale, true); + PDFView.parseScale(scale, true); setTimeout(function pageViewScrollIntoViewRelayout() { // letting page to re-layout before scrolling From 8096d747c0f0ff85f9a39b43e56d7c2153cc9913 Mon Sep 17 00:00:00 2001 From: Brendan Dahl Date: Thu, 15 Dec 2011 15:13:48 -0800 Subject: [PATCH 12/12] Fix nits. --- src/canvas.js | 4 ++-- src/image.js | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/canvas.js b/src/canvas.js index e056fe0f2..e42f53cf1 100644 --- a/src/canvas.js +++ b/src/canvas.js @@ -1106,9 +1106,9 @@ var CanvasGraphics = (function CanvasGraphicsClosure() { paintImageXObject: function canvasGraphicsPaintImageXObject(objId) { var imgData = this.objs.get(objId); - if (!imgData) { + if (!imgData) error('Dependent image isn\'t ready yet'); - } + this.save(); var ctx = this.ctx; var w = imgData.width; diff --git a/src/image.js b/src/image.js index 2f99dee54..22a9f9eb4 100644 --- a/src/image.js +++ b/src/image.js @@ -214,7 +214,6 @@ var PDFImage = (function PDFImageClosure() { bits = remainingBits; } } - if(decodeMap) console.timeEnd('getComps'); return output; }, getOpacity: function getOpacity() {