-- PressFontReaderImpl.mesa DIRECTORY Ascii, CIFS, Environment, File, Graphics, CGPrivate, PressFontReader, PressFontFormat, RealConvert, Rope, Space; PressFontReaderImpl: PROGRAM IMPORTS CIFS, File, Graphics, CGPrivate, PressFontFormat, Rope, RealConvert, Space EXPORTS PressFontReader = BEGIN OPEN PressFontReader, F: PressFontFormat; Handle: PUBLIC TYPE = REF PressFontFileRec; PressFontFileRec: PUBLIC TYPE = RECORD [ openFile: CIFS.OpenFile, space: Space.Handle, base: LONG POINTER, length: INT, names: LIST OF CodeNamePair ]; CodeNamePair: TYPE = RECORD [ code: [0..256), name: ROPE ]; Error: PUBLIC SIGNAL[errorCode: ErrorCode, fontFileWordOffset: INT] = CODE; NameFromCode: PROCEDURE [handle: Handle, code: [0..256)] RETURNS [ROPE] = { FOR n: LIST OF CodeNamePair _ handle.names, n.rest UNTIL n=NIL DO IF n.first.code = code THEN RETURN [n.first.name]; ENDLOOP; RETURN [NIL] }; FromFile: PUBLIC PROCEDURE [fileName: ROPE] RETURNS [handle: Handle] = { fileC: File.Capability; handle _ NEW[PressFontFileRec]; handle.openFile _ CIFS.Open[fileName, CIFS.read+CIFS.dontCheck]; fileC _ CIFS.GetFC[handle.openFile]; handle.space _ Space.Create[size: File.GetSize[fileC], parent: Space.virtualMemory]; Space.Map[space: handle.space, window: [file: fileC, base: 1]]; handle.base _ Space.LongPointer[handle.space]; handle.length _ File.GetSize[fileC]; handle.length _ handle.length * Environment.wordsPerPage; EnumerateIndex[handle, TabulateNames]; }; ExtractName: PROCEDURE [p: LONG POINTER TO name F.RawIndex] RETURNS [rope: ROPE] = { i: NAT _ 1; len: [0..20) _ p.fontname[0]-Ascii.NUL; charProc: SAFE PROC RETURNS [char: CHAR] = TRUSTED { char _ p.fontname[i]; i _ i + 1; }; rope _ Rope.FromProc[len, charProc]; }; TabulateNames: VisitProc = { IF p.hdr.type = name THEN { pp: LONG POINTER _ p; nameIndex: LONG POINTER TO name F.RawIndex _ pp; handle.names _ CONS[[nameIndex.code, ExtractName[nameIndex]], handle.names] } }; VisitProc: TYPE = PROCEDURE [handle: Handle, p: LONG POINTER TO F.RawIndex] RETURNS [quit: BOOLEAN _ FALSE]; EnumerateIndex: PROCEDURE [handle: Handle, visitProc: VisitProc] = { p: LONG POINTER TO F.RawIndex _ handle.base; offset: INT _ 0; DO p: LONG POINTER TO F.RawIndex _ handle.base + offset; newOffset: INT _ offset + p.hdr.length; IF newOffset > handle.length THEN ERROR Error[fontIndexTooLong, offset]; IF visitProc[handle, p] THEN EXIT; IF p.hdr.type = end THEN EXIT; offset _ newOffset; ENDLOOP }; Close: PUBLIC PROCEDURE [handle: Handle] = { Space.Delete[handle.space]; CIFS.Close[handle.openFile]; handle.openFile _ NIL; handle.space _ Space.nullHandle; handle.base _ NIL; handle.length _ 0; handle.names _ NIL; }; FirstFont: PUBLIC PROCEDURE [handle: Handle] RETURNS [font: Font] = { visitFontProc: VisitFontProc = {quit _ TRUE}; font _ EnumerateDirectory[handle, visitFontProc]; }; ListFonts: PUBLIC PROCEDURE [handle: Handle] RETURNS [fonts: LIST OF Font] = { visitProc: VisitProc = { SELECT p.hdr.type FROM splines, chars, widths => { fontInfoRec: FontInfoRec; GetFontInfo[handle, p, @fontInfoRec]; fonts _ CONS[MakeFont[handle, fontInfoRec, p], fonts]; }; ENDCASE; }; fonts _ NIL; EnumerateIndex[handle, visitProc]; }; EnumerateDirectory: PUBLIC PROCEDURE [handle: Handle, visitFontProc: VisitFontProc] RETURNS [font: Font] = { visitProc: VisitProc = { SELECT p.hdr.type FROM splines, chars, widths => { fontInfoRec: FontInfoRec; GetFontInfo[handle, p, @fontInfoRec]; quit _ visitFontProc[fontInfoRec]; IF quit THEN font _ MakeFont[handle, fontInfoRec, p]; }; ENDCASE; }; EnumerateIndex[handle, visitProc]; }; GetFontInfo: PROCEDURE [handle: Handle, raw: LONG POINTER, fontInfoRec: LONG POINTER TO FontInfoRec] = { p: LONG POINTER TO chars F.RawIndex _ raw; fontInfoRec.family _ NameFromCode[handle, p.family]; fontInfoRec.face _ p.face; fontInfoRec.bc _ p.bc; fontInfoRec.ec _ p.ec; fontInfoRec.size _ p.size/100000.0; fontInfoRec.rotation _ p.rotation/60.0; fontInfoRec.representation _ SELECT p.hdr.type FROM splines => outline, chars => raster, widths => widthsOnly, ENDCASE => ERROR; IF p.hdr.type # chars THEN {fontInfoRec.xRes _ fontInfoRec.yRes _ 0} ELSE { fontInfoRec.xRes _ p.resolutionx/10.0; fontInfoRec.yRes _ p.resolutiony/10.0; } }; MakeFont: PROCEDURE [handle: Handle, info: FontInfoRec, raw: LONG POINTER] RETURNS [font: REF FontRec] = { font _ NEW[FontRec]; font.info _ info; font.pressFontFile _ handle; SELECT info.representation FROM raster => {p: REF raster FontPrivateRec _ NEW[raster FontPrivateRec]; r: LONG POINTER TO chars F.RawIndex _ raw; nChars: NAT _ info.ec - info.bc + 1; dataOffset, dirOffset, rasterOffset: LONG CARDINAL; IF r.hdr.type # chars THEN ERROR Error[cantHappen, raw-handle.base]; p.indexEntry _ r; p.base _ handle.base; dataOffset _ F.LongCardinalFromBcplLongPointer[r.startaddress]; dirOffset _ dataOffset + nChars*SIZE[F.BoundingBox]; rasterOffset _ dirOffset + nChars*SIZE[F.bcplLONGPOINTER]; IF rasterOffset - dataOffset > F.BcplToMesaLongCardinal[r.length] THEN ERROR Error[dataSegmentTooLong, dataOffset]; p.rasterStart _ rasterOffset; p.rasterEnd _ dataOffset + F.BcplToMesaLongCardinal[r.length]; p.dataDesc _ DESCRIPTOR[p.base+dataOffset, nChars]; p.dirDesc _ DESCRIPTOR[p.base+dirOffset, nChars]; font.private _ p}; outline => {p: REF outline FontPrivateRec _ NEW[outline FontPrivateRec]; r: LONG POINTER TO splines F.RawIndex _ raw; nChars: NAT _ info.ec - info.bc + 1; dataOffset, dirOffset, commandOffset: LONG CARDINAL; IF r.hdr.type # splines THEN ERROR Error[cantHappen, raw-handle.base]; p.indexEntry _ r; p.base _ handle.base; dataOffset _ F.LongCardinalFromBcplLongPointer[r.startaddress]; dirOffset _ dataOffset + nChars*SIZE[F.BcplSplineData]; commandOffset _ dirOffset + nChars*SIZE[F.bcplLONGPOINTER]; IF commandOffset - dataOffset > F.BcplToMesaLongCardinal[r.length] THEN ERROR Error[dataSegmentTooLong, dataOffset]; p.commandStart _ commandOffset; p.commandEnd _ dataOffset + F.BcplToMesaLongCardinal[r.length]; p.dataDesc _ DESCRIPTOR[p.base+dataOffset, nChars]; p.dirDesc _ DESCRIPTOR[p.base+dirOffset, nChars]; font.private _ p}; widthsOnly => {p: REF widthsOnly FontPrivateRec _ NEW[widthsOnly FontPrivateRec]; r: LONG POINTER TO widths F.RawIndex _ raw; nChars: NAT _ info.ec - info.bc + 1; segOffset, xWidthOffset, yWidthOffset: LONG CARDINAL; nx, ny: NAT; IF r.hdr.type # widths THEN ERROR Error[cantHappen, raw-handle.base]; p.indexEntry _ r; p.base _ handle.base; segOffset _ F.LongCardinalFromBcplLongPointer[r.startaddress]; p.widthSeg _ p.base + segOffset; nx _ IF p.widthSeg.XWidthFixed THEN 1 ELSE nChars; ny _ IF p.widthSeg.YWidthFixed THEN 1 ELSE nChars; xWidthOffset _ segOffset + SIZE[F.BcplWidthSegment]; p.xWidthDesc _ DESCRIPTOR[p.base+xWidthOffset, nx]; yWidthOffset _ xWidthOffset + nx; p.yWidthDesc _ DESCRIPTOR[p.base+yWidthOffset, ny]; IF yWidthOffset + ny - segOffset # F.BcplToMesaLongCardinal[r.length] THEN ERROR Error [consistencyCheck, raw-handle.base]; font.private _ p}; ENDCASE => ERROR; }; GetCharInfo: PUBLIC PROCEDURE [font: Font, char: CHAR] RETURNS [info: CharInfo] = { private: REF FontPrivateRec _ font.private; handle: Handle _ font.pressFontFile; IF private.base # handle.base THEN ERROR Error[fileHasBeenClosed, 0]; WITH priv: private SELECT FROM raster => { IF priv.indexEntry.hdr.type # chars THEN ERROR Error[cantHappen, 0]; IF (NOT char IN [font.info.bc..font.info.ec]) THEN RETURN[[0,0,0,0,0,0]] ELSE { data: F.BoundingBox _ priv.dataDesc[char-font.info.bc]; xscale: REAL _ 0.0254/(font.info.xRes*font.info.size); yscale: REAL _ 0.0254/(font.info.yRes*font.info.size); IF data.BBdy = LAST[CARDINAL] THEN RETURN[[0,0,0,0,0,0]]; info.widthX _ BcplFractionToMesaReal[data.xwidth]*xscale; info.widthY _ BcplFractionToMesaReal[data.ywidth]*yscale; info.minX _ data.BBox*xscale; info.minY _ data.BBoy*yscale; info.maxX _ data.BBdx*xscale + info.minX; info.maxY _ data.BBdy*yscale + info.minY; }; }; outline => { IF priv.indexEntry.hdr.type # splines THEN ERROR Error[cantHappen, 0]; IF (NOT char IN [font.info.bc..font.info.ec]) OR priv.dataDesc[char-font.info.bc].xwidth = F.missingCharValue THEN RETURN[[0,0,0,0,0,0]] ELSE { data: F.BcplSplineData _ priv.dataDesc[char-font.info.bc]; info.widthX _ BcplToMesaReal[data.xwidth]; info.widthY _ BcplToMesaReal[data.ywidth]; info.minX _ BcplToMesaReal[data.bbox]; info.minY _ BcplToMesaReal[data.bboy]; info.maxX _ BcplToMesaReal[data.rightx]; info.maxY _ BcplToMesaReal[data.topy]; }; }; widthsOnly => { IF priv.indexEntry.hdr.type # widths THEN ERROR Error[cantHappen, 0]; IF (NOT char IN [font.info.bc..font.info.ec]) THEN RETURN[[0,0,0,0,0,0]] ELSE { data: F.BcplWidthSegment _ priv.widthSeg^; scale: REAL _ IF font.info.size = 0.0 THEN 0.001 ELSE 100000.0/font.info.size; wx: INTEGER _ priv.xWidthDesc[IF data.XWidthFixed THEN 0 ELSE char-font.info.bc]; wy: INTEGER _ priv.yWidthDesc[IF data.YWidthFixed THEN 0 ELSE char-font.info.bc]; IF wx = FIRST[INTEGER] OR wy = FIRST[INTEGER] THEN RETURN[[0,0,0,0,0,0]]; info.widthX _ wx*scale; info.widthY _ wy*scale; info.minX _ data.FBBox*scale; info.minY _ data.FBBoy*scale; info.maxX _ data.FBBdx*scale + info.minX; info.maxY _ data.FBBdy*scale + info.minY; }; }; ENDCASE => ERROR; }; DrawChar: PUBLIC PROCEDURE [context: Graphics.Context, font: Font, char: CHAR] = { mark: Graphics.Mark _ Graphics.Save[context]; scalex: REAL _ IF font.info.size = 0.0 THEN 1.0 ELSE 0.0254/(font.info.size*font.info.xRes); scaley: REAL _ IF font.info.size = 0.0 THEN 1.0 ELSE 0.0254/(font.info.size*font.info.yRes); xRef, yRef: REAL; charInfo: CharInfo _ GetCharInfo[font, char]; [xRef, yRef] _ Graphics.GetCP[context]; Graphics.Scale[context, scalex, scaley]; SELECT font.info.representation FROM raster => { DrawCharRaster[context, font, char]; }; outline => { Graphics.Translate[context, xRef, yRef]; Graphics.DrawArea[self: context, path: GetCharPath[font, char], parityFill: TRUE]; }; ENDCASE; Graphics.Restore[context, mark]; Graphics.SetCP[context, xRef+charInfo.widthX, yRef+charInfo.widthY]; }; DrawCharRaster: PUBLIC PROCEDURE [context: Graphics.Context, font: Font, char: CHAR] = { handle: Handle _ font.pressFontFile; private: REF FontPrivateRec _ font.private; WITH priv: private SELECT FROM raster => BEGIN IF priv.base # handle.base THEN ERROR Error[fileHasBeenClosed, 0]; IF priv.indexEntry.hdr.type # chars THEN ERROR Error[cantHappen, 0]; IF (NOT char IN [font.info.bc..font.info.ec]) THEN RETURN ELSE { mark: Graphics.Mark; data: F.BoundingBox _ priv.dataDesc[char-font.info.bc]; offset: LONG CARDINAL _ F.LongCardinalFromBcplLongPointer[priv.dirDesc[char-font.info.bc]]; rawRasterPointer: LONG POINTER _ BASE[priv.dirDesc] + offset; r: F.RasterPointer _ rawRasterPointer; rawRasterPointer _ rawRasterPointer + SIZE[F.RasterDimension]; IF data.BBdy = LAST[CARDINAL] THEN RETURN; IF offset = LAST[LONG CARDINAL] THEN RETURN; IF (rawRasterPointer-priv.base) < priv.rasterStart OR (rawRasterPointer-priv.base) >= priv.rasterEnd THEN ERROR Error[invalidPointerInFile, @(priv.dirDesc[char-font.info.bc]) - priv.base]; Graphics.SetCP[self: context, x: data.BBox, y: data.BBoy, rel: TRUE]; mark _ Graphics.Save[context]; Graphics.Rotate[context, 90]; CGPrivate.DrawBits[ self: context, base: rawRasterPointer, raster: r.height, bitsPerPixel: 0, x: 0, y: 0, w: data.BBdy, h: data.BBdx, xorigin:0, yorigin: 0 ]; Graphics.Restore[context, mark]; Graphics.SetCP[self: context, x: BcplFractionToMesaReal[data.xwidth] - data.BBox, y: BcplFractionToMesaReal[data.ywidth] - data.BBoy, rel: TRUE]; }; END; ENDCASE => ERROR Error[wrongFontFormatForThisOperation, 0] }; BcplToMesaReal: PROCEDURE [b: F.BcplREAL] RETURNS [r: REAL] = { r _ RealConvert.BcplToIeee[LOOPHOLE[b]] }; BcplFractionToMesaReal: PROCEDURE [f: F.bcplFraction] RETURNS [r: REAL] = { r _ F.BcplToMesaFraction[f]/(LAST[CARDINAL]+1.0); }; GetCharOutline: PUBLIC PROCEDURE [ font: Font, char: CHAR, moveToProc: MoveToProc, lineToProc: LineToProc, curveToProc: CurveToProc, drawAreaProc: DrawAreaProc ] = { p: LONG POINTER; handle: Handle _ font.pressFontFile; curX, curY: REAL _ 0.0; private: REF FontPrivateRec _ font.private; WITH spline: private SELECT FROM outline => BEGIN IF spline.base # handle.base THEN ERROR Error[fileHasBeenClosed, 0]; IF spline.indexEntry.hdr.type # splines THEN ERROR Error[cantHappen, 0]; IF NOT char IN [font.info.bc..font.info.ec] THEN RETURN; IF spline.dataDesc[char-font.info.bc].xwidth = F.missingCharValue THEN RETURN; p _ BASE[spline.dirDesc] + F.LongCardinalFromBcplLongPointer[spline.dirDesc[char-font.info.bc]]; DO splineCommand: LONG POINTER TO F.BcplSplineCommand _ p; IF (p-spline.base) < spline.commandStart OR (p-spline.base) >= spline.commandEnd THEN ERROR Error[invalidPointerInFile, @(spline.dirDesc[char-font.info.bc])-spline.base]; SELECT splineCommand.type FROM F.moveToCode => {cmd: LONG POINTER TO MoveTo F.BcplSplineCommand _ p; moveToProc[curX _ BcplToMesaReal[cmd.x], curY _ BcplToMesaReal[cmd.y]]; p _ p + SIZE[MoveTo F.BcplSplineCommand]; }; F.drawToCode => {cmd: LONG POINTER TO DrawTo F.BcplSplineCommand _ p; lineToProc[curX _ BcplToMesaReal[cmd.x], curY _ BcplToMesaReal[cmd.y]]; p _ p + SIZE[DrawTo F.BcplSplineCommand]; }; F.drawCurveCode => {cmd: LONG POINTER TO DrawCurve F.BcplSplineCommand _ p; b: Bezier _ CoeffsToBezier[[ [curX, curY], [BcplToMesaReal[cmd.x0], BcplToMesaReal[cmd.y0]], [BcplToMesaReal[cmd.x1], BcplToMesaReal[cmd.y1]], [BcplToMesaReal[cmd.x2], BcplToMesaReal[cmd.y2]] ]]; [curX, curY] _ b.b3; curveToProc[b.b1.x, b.b1.y, b.b2.x, b.b2.y, b.b3.x, b.b3.y]; p _ p + SIZE[DrawCurve F.BcplSplineCommand]; }; F.newObjectCode => { drawAreaProc[]; p _ p + SIZE[NewObject F.BcplSplineCommand]; }; F.endSplineCode => { drawAreaProc[]; EXIT }; ENDCASE => ERROR Error[invalidCodeInFile, p-spline.base]; ENDLOOP END; ENDCASE => ERROR Error[wrongFontFormatForThisOperation, 0] }; GetCharPath: PUBLIC PROCEDURE [font: Font, char: CHAR] RETURNS [path: Graphics.Path] = { moveToProc: PressFontReader.MoveToProc = {Graphics.MoveTo[path, x, y, FALSE]}; lineToProc: PressFontReader.LineToProc = {Graphics.LineTo[path, x, y]}; curveToProc: PressFontReader.CurveToProc = {Graphics.CurveTo[path, x1, y1, x2, y2, x3, y3]}; drawAreaProc: PressFontReader.DrawAreaProc = {}; path _ Graphics.NewPath[]; GetCharOutline[font, char, moveToProc, lineToProc, curveToProc, drawAreaProc]; }; Vec: TYPE = RECORD [x,y: REAL]; VecAdd: PROCEDURE [a: Vec, b: Vec] RETURNS [Vec] = INLINE {RETURN[[a.x+b.x,a.y+b.y]]}; VecSub: PROCEDURE [a: Vec, b: Vec] RETURNS [Vec] = INLINE {RETURN[[a.x-b.x,a.y-b.y]]}; VecDiv: PROCEDURE [a: Vec, s: REAL] RETURNS [Vec] = INLINE {RETURN[[a.x/s,a.y/s]]}; Coeffs: TYPE = RECORD[c0,c1,c2,c3: Vec]; Bezier: TYPE = RECORD[b0,b1,b2,b3: Vec]; CoeffsToBezier: PROCEDURE [c: Coeffs] RETURNS [b: Bezier] = { OPEN b,c; b0_c0; b1_VecAdd[c0,VecDiv[c1,3]]; b2_VecAdd[b1,VecDiv[VecAdd[c1,c2],3]]; b3_VecAdd[VecAdd[VecAdd[c0,c1],c2],c3]; }; SplineBase: PROCEDURE [d: LONG DESCRIPTOR FOR ARRAY OF F.BcplSplineData] RETURNS [p: LONG POINTER] = { p _ BASE[d]; }; DirBase: PROCEDURE [d: LONG DESCRIPTOR FOR ARRAY OF F.bcplLONGPOINTER] RETURNS [p: LONG POINTER] = { p _ BASE[d]; }; splineDataPointer: LONG POINTER TO F.BcplSplineData; bcplPtrPointer: LONG POINTER TO F.bcplLONGPOINTER; moveToPointer: LONG POINTER TO MoveTo F.BcplSplineCommand; drawCurvePointer: LONG POINTER TO DrawCurve F.BcplSplineCommand; splineDataPointer _ NIL; bcplPtrPointer _ NIL; moveToPointer _ NIL; drawCurvePointer _ NIL; END. -- Written by Michael Plass on August 5, 1982 11:01 am -- Last edit by Michael Plass on August 11, 1982 11:43 am -- The call by reference is to avoid a long REF-containing return record. -- Routines for converting to bezier points. -- Stuff to help in debugging; ΚK– "Mesa" style˜J˜JšΟcœ˜Jšœ6™6Jšœ9™9šΟk ˜ Jšœ˜Jšžœ˜Jšœ ˜ Jšœ˜Jšœ ˜ J˜ Jšœ˜Jšœ˜J˜ Jšœ˜Jšœ˜—procšœž˜Jšžœžœ@žœ˜RJšžœ˜Jšœž˜Jšžœ%˜)Jšœžœžœžœ˜+šœžœžœžœ˜(Jšœ žœ ˜J˜Jšœžœžœ˜Jšœžœ˜ Jšœžœžœ˜Jšœ˜—šœžœžœ˜J˜Jšœž˜ J˜—Kš Οnœžœžœ+žœžœ˜KšŸ œž œ"žœžœ˜Kš žœžœžœ%žœžœž˜AJšžœžœžœ˜2Jšžœ˜—Jšžœžœ˜ J˜—š Ÿœžœž œ žœžœ˜HJšœ˜Jšœ žœ˜Jšœžœžœžœ ˜@Jšœžœ˜$JšœT˜TJšœ?˜?Jšœ.˜.Jšœ$˜$Jšœ9˜9Jšœ'˜'J˜—š Ÿ œž œžœžœžœ˜;Jšžœžœ˜Jšœžœ˜ Jšœ#žœ˜'š œ žœžœžœžœžœ˜4Jšœ#˜#—Jšœ$˜$J˜—šŸ œ˜šžœžœ˜Jšœžœžœ˜Jšœ žœžœžœ˜0Jšœžœ8˜KJ˜—J˜—š Ÿ œžœž œžœžœžœ ˜KJšžœžœžœ˜ —šŸœž œ+˜DJšœžœžœžœ˜,Jšœ˜šž˜Jšœžœžœžœ#˜5Jšœ'˜'Jšœžœžœ!˜HJšžœžœžœ˜"Jšžœžœžœ˜Jšœ˜Jšž˜—J˜—šŸœžœž œ˜,Jšœ˜Jšžœ˜Jšœžœ˜Jšœ ˜ Jšœžœ˜Jšœ˜Jšœžœ˜Jšœ˜—šŸ œžœžœ˜EJšŸ œžœ˜-Jšœ1˜1J˜—š Ÿ œžœžœ žœžœ ˜NšŸ œ˜šžœ ž˜˜J˜Jšœ%˜%Jšœžœ*˜6J˜—Jšžœ˜—J˜—Jšœ ˜ Jšœ"˜"J˜—šŸœžœž œ0žœ˜lšŸ œ˜šžœ ž˜˜J˜Jšœ%˜%Jšœ"˜"Jšžœžœ)˜5J˜—Jšžœ˜—J˜—Jšœ"˜"J˜—šŸ œž œžœžœžœžœžœ˜hJšI™IJš œžœžœžœžœ˜*Jšœ4˜4Jšœ˜Jšœ˜Jšœ˜Jšœ#˜#Jšœ'˜'šœžœ ž˜3J˜J˜J˜Jšžœžœ˜—Jšžœžœ*˜Dšžœ˜Jšœ&˜&Jšœ&˜&J˜—J˜—š Ÿœž œ*žœžœžœžœ ˜jJšœžœ ˜Jšœ˜Jšœ˜šžœž˜šœžœžœ˜EJšœžœžœžœ˜*Jšœžœ˜$Jšœ%žœžœ˜3Jšžœžœžœ$˜DJ˜Jšœ˜Jšœ?˜?Jšœ žœ˜4Jšœ"žœ˜:šžœ@ž˜FJšžœ&˜,—Jšœ˜Jšœ>˜>Jšœ ž œ˜3Jšœ ž œ˜1Jšœ˜—šœžœžœ˜HJšœžœžœžœ˜,Jšœžœ˜$Jšœ&žœžœ˜4Jšžœžœžœ#˜FJ˜Jšœ˜Jšœ?˜?Jšœ žœ˜7Jšœ#žœ˜;šžœAž˜GJšžœ&˜,—Jšœ˜Jšœ?˜?Jšœ ž œ˜3Jšœ ž œ˜1Jšœ˜—šœžœžœ˜QJšœžœžœžœ˜+Jšœžœ˜$Jšœ'žœžœ˜5Jšœžœ˜ Jšžœžœžœ#˜EJ˜Jšœ˜Jšœ>˜>Jšœ ˜ Jšœžœžœžœ˜2Jšœžœžœžœ˜2Jšœžœ˜4Jšœž œ˜3Jšœ!˜!Jšœž œ˜3šžœDž˜JJšžœ+˜0—Jšœ˜—Jšžœžœ˜—J˜—š Ÿ œžœž œžœžœ˜SJšœ žœ˜+Jšœ$˜$Jšžœžœžœ˜Ešžœžœž˜šœ ˜ Jšžœ"žœžœ˜DJš žœžœžœžœžœ˜Hšžœ˜Jšœžœ0˜7Jšœžœ*˜6Jšœžœ*˜6Jš žœ žœžœžœžœ˜9Jšœ9˜9Jšœ9˜9Jšœ˜Jšœ˜Jšœ)˜)Jšœ)˜)J˜—Jšœ˜—šœ ˜ Jšžœ$žœžœ˜FJšžœžœžœžœ+žœžœžœ˜ˆšžœ˜Jšœžœ3˜:Jšœ*˜*Jšœ*˜*Jšœ&˜&Jšœ&˜&Jšœ(˜(Jšœ&˜&J˜—J˜—šœ˜Jšžœ#žœžœ˜EJš žœžœžœžœžœ˜Hšžœ˜Jšœžœ#˜*J˜NJš œžœžœžœžœ˜QJš œžœžœžœžœ˜QJšžœžœžœžœžœžœžœžœ˜JJšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ)˜)Jšœ)˜)J˜—Jšœ˜—Jšžœžœ˜—J˜—šŸœžœž œ/žœ˜RJšœ-˜-Jš œžœžœžœžœ(˜\Jš œžœžœžœžœ(˜\Jšœ žœ˜Jšœ-˜-Jšœ'˜'Jšœ(˜(šžœž˜$šœ ˜ Jšœ$˜$Jšœ˜—šœ ˜ Jšœ(˜(JšœLžœ˜RJšœ˜—Jšžœ˜—Jšœ ˜ JšœD˜DJ˜—šŸœžœž œ/žœ˜XJšœ$˜$Jšœ žœ˜+šžœžœž˜šœ ž˜Jšžœžœžœ˜BJšžœ"žœžœ˜DJš žœžœžœžœž˜9šžœ˜J˜Jšœžœ0˜7JšœžœžœžœB˜[Jšœžœžœžœ˜=Jšœžœ"˜&Jšœ+žœ˜>Jš žœ žœžœžœžœ˜*Jš žœ žœžœžœžœžœ˜,Jšžœ1žœ0žœžœL˜ΌJšœE˜EJšœ˜Jšœ˜Jšœž˜žJšœ ˜ Jšœ‘˜‘J˜—Jšžœ˜—Jšžœžœ)˜:—J˜—š Ÿœž œžœ žœžœ˜?Jšœžœ˜'J˜—š Ÿœž œžœžœžœ˜KJšœžœžœžœ˜1J˜—šŸœžœž œ˜"Jšœ ˜ Jšœžœ˜#Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœžœžœ˜Jšœ$˜$Jšœ žœ˜Jšœ žœ˜+šžœžœž˜ šœ ž˜Jšžœžœžœ˜DJšžœ&žœžœ˜HJš žœžœžœžœžœ˜8Jšžœ-žœžœžœ˜NJšœžœD˜`š žœžœžœžœžœ˜:Jšžœ&žœ%žœžœN˜ͺšžœž˜š œžœžœžœžœ˜EJšœG˜GJšœžœžœ˜)Jšœ˜—š œžœžœžœžœ˜EJšœG˜GJšœžœžœ˜)Jšœ˜—š œžœžœžœ žœ˜Kšœ˜Jšœ ˜ Jšœ1˜1Jšœ1˜1Jšœ0˜0J˜—Jšœ˜Jšœ=˜=Jšœžœ žœ˜,Jšœ˜—šœ˜Jšœ˜Jšœžœ žœ˜,Jšœ˜—šœ˜Jšœ˜Jšž˜Jšœ˜—Jšžœžœ)˜9—Jšž˜—Jšžœ˜—Jšžœžœ)˜:—J˜—šŸ œžœžœžœ˜XJšœFžœ˜NJšœG˜GJšœ\˜\Jšœ0˜0Jšœ˜JšœN˜NJšœ˜—Kš,™,Kšœžœžœžœ˜Kš Ÿœž œžœ žœžœ˜VKš Ÿœž œžœ žœžœ˜VKš Ÿœž œ žœžœ žœžœ˜SKšœžœžœ˜(Kšœžœžœ˜(šŸœž œ žœ˜=Jšžœ˜ J˜J˜J˜&J˜'J˜—Kš™šŸ œž œžœž œžœžœžœžœžœžœžœ˜fJšœžœ˜ J˜—šŸœž œžœž œžœžœžœžœžœžœžœ˜dJšœžœ˜ J˜—Kšœ4˜4Kšœ2˜2Kšœ:˜:Kšœ@˜@Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšžœ˜——…—<Nk