DIRECTORY ScreenDefs: FROM "ScreenDefs", Graphics USING[Context, PaintMode, Color, SetPaintMode, SetCP, white, black, Box, FontRef, MakeFont, FontBox, Translate, ClipBox, DrawRope, Save, Restore, RopeBox], Rope USING [ROPE], ScreenDefsExtras, GraphicsBasic USING [Vec], CGArea USING [InsertBox, New,Ref], CGSource USING [Ref, Rep], CGDevice USING [Ref], CGContext USING [Ref], CGMatrix USING [Ref,Map], GraphicsOps USING [MoveDeviceRectangle], PointDefs: FROM "PointDefs" USING [ IntegerSequence,IntegerSequenceRec,ScrPt,X,Y], Font USING [FontRec, FontGraphicsClassRec, FONT], ImagerTransform USING [Transformation, Create, Concat], GriffinMemoryDefs USING [CZone], Real USING [RoundI], GriffinDefs: FROM "GriffinDefs", GriffinViewer USING[GetViewer, PaintProc, DoPaint], ViewerOps USING [Top2Bottom], ViewerClasses USING[Viewer]; ScreenFns: PROGRAM IMPORTS GraphicsOps, GriffinDefs, Graphics, GriffinMemoryDefs, CGArea, CGMatrix, Real, GriffinViewer, ViewerOps, ImagerTransform EXPORTS ScreenDefs, ScreenDefsExtras = BEGIN OPEN ScreenDefs,PointDefs,GriffinMemoryDefs; TY,BY,LX,RX: INTEGER; initTY,initBY,initLX,initRX: INTEGER; CLIP: BOOLEAN _ TRUE; CULL: BOOLEAN _ FALSE; FNC: Graphics.PaintMode; white: Graphics.Color=Graphics.white; black: Graphics.Color=Graphics.black; opaque: Graphics.PaintMode = opaque; transparent: Graphics.PaintMode = transparent; ClearScreen: PUBLIC PROCEDURE [dc: Context] = BEGIN tl: ScrPt _ [LX,TY]; br: ScrPt _ [RX,BY]; EraseBox[tl,br, dc]; END; SetViewport: PUBLIC PROCEDURE [width,height: INTEGER] = BEGIN LX _ initLX _ 0; RX _ initRX _ width; TY _ initTY _ 0; BY _ initBY _ height; END; SetClipEdges: PUBLIC PROCEDURE [tl,br: PointDefs.ScrPt] = { [tl,br] _ ClipToScreen[tl,br]; IF br[X]RX OR br[X]BY OR br[Y]initRX THEN br[X] _ initRX; IF tl[Y] < initTY THEN tl[Y] _ initTY; IF br[Y] >initBY THEN br[Y] _ initBY; RETURN[tl,br]; END; ClipPointToScreen: PUBLIC PROC [pt: ScrPt] RETURNS [ScrPt] = BEGIN IF pt[X] < initLX THEN pt[X] _ initLX; IF pt[X] >initRX THEN pt[X] _ initRX; IF pt[Y] < initTY THEN pt[Y] _ initTY; IF pt[Y] >initBY THEN pt[Y] _ initBY; RETURN[pt]; END; ResetClipEdges: PUBLIC PROCEDURE = BEGIN OPEN PointDefs; tl: PointDefs.ScrPt _ [initLX,initTY]; br: PointDefs.ScrPt _ [initRX,initBY]; SetClipEdges[tl,br]; END; ClipOn: PUBLIC PROCEDURE = BEGIN CLIP _ TRUE; END; PrimeClipper: PUBLIC PROC [tl,br: PointDefs.ScrPt] RETURNS [ClipperState] = BEGIN IF tl[X] > RX OR tl[Y] > BY OR br[X] < LX OR br[Y] < TY THEN RETURN[cull]; IF tl[X] IN [LX..RX] AND tl[Y] IN [TY..BY] AND br[X] IN [LX..RX] AND br[Y] IN [TY..BY] THEN {CLIP _ FALSE; RETURN[inside]}; CLIP _ TRUE; RETURN[clip]; END; SetFunction: PUBLIC PROCEDURE [fnc: Graphics.PaintMode] = BEGIN FNC _ fnc; END; Width: INTEGER; Grey: GreyType; SetLineParms: PUBLIC PROCEDURE [ width: INTEGER, grey: GreyType]= BEGIN Width _ width; CurrentBrush _ CodedBrushes[Width]; Grey _ grey; END; left: INTEGER = 0; right: INTEGER = 1; CodedBrush: TYPE = ARRAY [left..right] OF BrushSide; BrushSide: TYPE = PointDefs.IntegerSequence; CodedBrushes: ARRAY [1..8] OF CodedBrush; CurrentBrush: CodedBrush; xleft, xright: ARRAY [0..7] OF INTEGER; leftBrush: BrushSide; rightBrush: BrushSide; brushSize: INTEGER; topIndex: INTEGER; topY: INTEGER; -- top of brush centerX: INTEGER; StartChain: PUBLIC PROCEDURE[pt: ScrPt, dc: Context] = { ref: CGContext.Ref _ NARROW[dc.data]; newPt: GraphicsBasic.Vec _ CGMatrix.Map[ref.matrix,[pt[X],YFlip[pt[Y]]]]; brushIndex: INTEGER; cgSource.color _ Grey; cgSource.mode _ FNC; cgDevice _ ref.device; DeviceClipper[ref.matrix]; leftBrush _ CurrentBrush[left]; rightBrush _ CurrentBrush[right]; brushSize _ leftBrush.length; topIndex _ 0; topY _ Real.RoundI[newPt.y] - brushSize/2; -- top of brush centerX _ Real.RoundI[newPt.x]; FOR brushIndex IN [0..brushSize) DO xleft[brushIndex] _ centerX + leftBrush[brushIndex]; xright[brushIndex] _ centerX + rightBrush[brushIndex]; ENDLOOP; }; NextChainPoint: PUBLIC PROCEDURE[dx,dy: INTEGER, dc: Context]= BEGIN OPEN PointDefs; brushIndex, rangeIndex, temp: INTEGER; centerX _ centerX + dx; SELECT dy FROM -1 => BEGIN -- move brush up IF (topIndex _ topIndex -1) < 0 THEN topIndex _ topIndex + brushSize; NextScanLine[(topY + brushSize -1), xleft[topIndex], xright[topIndex], dc]; xleft[topIndex] _ 606; xright[topIndex] _ 0; topY _ topY - 1; END; 1 => BEGIN -- move brush down NextScanLine[topY, xleft[topIndex], xright[topIndex], dc]; xleft[topIndex] _ 606; xright[topIndex] _ 0; IF (topIndex _ topIndex +1) >= brushSize THEN topIndex _ 0; topY _ topY + 1; END; 0 => NULL; ENDCASE => BEGIN RETURN; END; rangeIndex _ topIndex; FOR brushIndex IN [0..brushSize) DO IF xleft[rangeIndex] > (temp _ centerX + leftBrush[brushIndex]) THEN xleft[rangeIndex] _ temp; IF xright[rangeIndex] < (temp _ centerX + rightBrush[brushIndex]) THEN xright[rangeIndex] _ temp; IF (rangeIndex _ rangeIndex + 1) >= brushSize THEN rangeIndex _ 0; ENDLOOP; END; EndChain: PUBLIC PROCEDURE [dc: Context] = BEGIN brushIndex: INTEGER; FOR brushIndex IN [0..brushSize) DO NextScanLine[topY, xleft[topIndex], xright[topIndex], dc]; topY _ topY + 1; IF (topIndex _ topIndex +1) >= brushSize THEN topIndex _ 0; ENDLOOP; END; SetFillParms: PUBLIC PROCEDURE [grey: GreyType] = {fillGrey _ grey}; fillGrey: GreyType _ black; StartArea: PUBLIC PROCEDURE[y: INTEGER, dc: Context] RETURNS[yScan,xOffset: INTEGER]= { ref: CGContext.Ref _ NARROW[dc.data]; newPt: GraphicsBasic.Vec _ CGMatrix.Map[ref.matrix,[0,YFlip[y]]]; yScan _ Real.RoundI[newPt.y]; xOffset _ Real.RoundI[newPt.x]; cgSource.color _ fillGrey; cgSource.mode _ FNC; cgDevice _ ref.device; DeviceClipper[ref.matrix]; RETURN[yScan,xOffset]; }; cgDevice: CGDevice.Ref _ NIL; cgBox: Graphics.Box; dLX,dRX,dTY,dBY: INTEGER; DeviceClipper: PROC [cgMatrix: CGMatrix.Ref] = { newPt: GraphicsBasic.Vec _ CGMatrix.Map[cgMatrix,[LX,YFlip[TY]]]; dLX _ Real.RoundI[newPt.x]; dTY _ Real.RoundI[newPt.y]; newPt _ CGMatrix.Map[cgMatrix,[RX,YFlip[BY]]]; dRX _ Real.RoundI[newPt.x]; dBY _ Real.RoundI[newPt.y]; }; NextScanLine: PUBLIC PROCEDURE[y,lx,rx: INTEGER, dc: Context] = { IF CLIP THEN BEGIN IF CULL THEN RETURN; IF lx>dRX OR rxdBY OR ydRX THEN rx _ dRX; END; cgBox _ [xmin: lx, ymin: y, xmax: rx, ymax: y]; CGArea.InsertBox[cgArea,cgBox]; cgDevice.Show[cgDevice,cgArea,cgSource,NIL]; }; HLine: PROCEDURE[y,lx,rx: INTEGER, grey: GreyType, dc: Context] = BEGIN IF CLIP THEN BEGIN IF CULL THEN RETURN; IF lx>RX OR rxBY OR yRX THEN rx _ RX; END; cgSource.color _ grey; cgSource.mode _ FNC; DrawBox[xmin: lx, ymin: y, xmax: rx, ymax: y, dc: dc]; END; InvertBox: PUBLIC PROCEDURE[tl,br: PointDefs.ScrPt, dc: Context] = BEGIN OPEN PointDefs; lx: INTEGER _ tl[X]; ty: INTEGER _ tl[Y]; --simpler this way on a number of counts rx: INTEGER _ br[X]; by: INTEGER _ br[Y]; IF CLIP THEN BEGIN IF CULL THEN RETURN; IF lx>RX OR rxBY OR byRX THEN rx _ RX; IF ty < TY THEN ty _ TY; IF by >BY THEN by _ BY; END; cgSource.mode _ invert; cgSource.color _ black; DrawBox[xmin: lx,ymin: ty,xmax: rx,ymax: by, dc: dc]; END; EraseBox: PUBLIC PROCEDURE[tl,br: PointDefs.ScrPt, dc: Context] = BEGIN OPEN PointDefs; lx: INTEGER _ tl[X]; ty: INTEGER _ tl[Y]; --simpler this way on a number of counts rx: INTEGER _ br[X]; by: INTEGER _ br[Y]; IF CLIP THEN BEGIN IF CULL THEN RETURN; IF lx>RX OR rxBY OR byRX THEN rx _ RX; IF ty < TY THEN ty _ TY; IF by >BY THEN by _ BY; END; cgSource.mode _ opaque; cgSource.color _ white; DrawBox[xmin: lx,ymin: ty,xmax: rx,ymax: by, dc: dc]; END; BoxFill: PUBLIC PROCEDURE[tl,br: PointDefs.ScrPt, dc: Context] = BEGIN OPEN PointDefs; lx: INTEGER _ tl[X]; ty: INTEGER _ tl[Y]; --simpler this way on a number of counts rx: INTEGER _ br[X]; by: INTEGER _ br[Y]; IF CLIP THEN BEGIN IF CULL THEN RETURN; IF lx>RX OR rxBY OR byRX THEN rx _ RX; IF ty < TY THEN ty _ TY; IF by >BY THEN by _ BY; END; cgSource.color _ fillGrey; cgSource.mode _ FNC; DrawBox[xmin: lx,ymin: ty,xmax: rx,ymax: by, dc: dc]; END; ngridpieces: INTEGER _ 0; gridT: INTEGER _ 3; GetGridParameters: PUBLIC PROCEDURE RETURNS[center: PointDefs.ScrPt,hgridlx,hgridrx,vgridty,vgridby,gridt: INTEGER]= BEGIN pt: PointDefs.ScrPt; ngridpieces _ 1+(initBY-initTY)/8; pt _ [(initRX-initLX)/2, (initBY-initTY)/2]; pt _ GriffinDefs.Grid[pt]; RETURN[pt,initLX,initRX,initTY,initBY,gridT]; END; BltVGrid: PUBLIC PROCEDURE[lx: INTEGER, dc: Context]= BEGIN ty: INTEGER _ GriffinDefs.Grid[[0,initTY]][Y]; THROUGH [0..ngridpieces] DO BLTBlockInScreen[vgridBlock,[lx,ty],transparent,dc]; ty _ ty+8; ENDLOOP; END; BltHGrid: PUBLIC PROCEDURE[ty: INTEGER, dc: Context]= BEGIN lx: INTEGER _ GriffinDefs.Grid[[0,initLX]][X]; THROUGH [0..ngridpieces] DO BLTBlockInScreen[hgridBlock,[lx,ty],transparent, dc]; lx _ lx+8; ENDLOOP; END; cgSource: CGSource.Ref _ CZone.NEW[CGSource.Rep _ [type: const, mode: opaque, fat: TRUE, color: black, bps: 0, xbase: NIL, xrast: 0]]; cgArea: CGArea.Ref _ CGArea.New[]; viewer: ViewerClasses.Viewer _ GriffinViewer.GetViewer[]; YFlip: PROC [y: INTEGER] RETURNS [INTEGER] = INLINE { RETURN[ViewerOps.Top2Bottom[viewer,y]]; }; menuFont: Graphics.FontRef _ Graphics.MakeFont["Cream10"]; ShowMenuString: PUBLIC PROCEDURE [origin: PointDefs.ScrPt, rope: Rope.ROPE, dc: Context] = { width,ascent: REAL; paintProc: GriffinViewer.PaintProc = { Graphics.ClipBox[self: dc, box: [xmin: LX, xmax: RX+1,ymin: YFlip[BY] , ymax: YFlip[TY]+1] ]; Graphics.Translate[dc,origin[X],YFlip[origin[Y]]]; Graphics.SetCP[dc,0,0]; [] _ Graphics.SetPaintMode[dc,opaque]; Graphics.DrawRope[self: dc,rope: rope,font: menuFont]; }; [,,,ascent] _ Graphics.FontBox[menuFont]; [,,width,] _ Graphics.RopeBox[font: menuFont, rope: rope]; origin[X] _ origin[X]-Real.RoundI[width/2]; origin[Y] _ origin[Y]+Real.RoundI[ascent]; IF dc=NIL THEN GriffinViewer.DoPaint[paintProc] ELSE {[] _ Graphics.Save[dc]; paintProc[dc]; Graphics.Restore[dc]}; }; flip: ImagerTransform.Transformation _ ImagerTransform.Create[0,-1,0,1,0,0]; DrawChar: PUBLIC PROCEDURE [font: Font.FONT, origin: PointDefs.ScrPt, char: CHAR, dc: Context] = { transformation: ImagerTransform.Transformation _ ImagerTransform.Concat[pre: font.actualTransformation, post: flip]; paintProc: GriffinViewer.PaintProc = { ref: CGContext.Ref _ NARROW[dc.data]; dorg: GraphicsBasic.Vec _ CGMatrix.Map[ref.matrix,[origin[X],YFlip[origin[Y]]]]; orgX: INTEGER _ Real.RoundI[dorg.x]; --origin in device coordinates orgY: INTEGER _ Real.RoundI[dorg.y]; lx,rx,y: INTEGER; fontProc: SAFE PROC [sMin, fMin: INTEGER, fSize: NAT] = TRUSTED { lx _ fMin+orgX; rx _ lx+fSize; y _ sMin+orgY; IF CLIP THEN BEGIN IF CULL THEN RETURN; IF lx>dRX OR rxdBY OR ydRX THEN rx _ dRX; END; cgBox _ [xmin: lx, ymin: y, xmax: rx, ymax: y]; CGArea.InsertBox[cgArea,cgBox]; }; DeviceClipper[ref.matrix]; --set up dRX, etc. cgSource.color _ black; cgSource.mode _ opaque; font.fontGraphicsClass.maskProc[font,transformation,char,fontProc]; ref.device.Show[ref.device,cgArea,cgSource,NIL]; }; IF dc=NIL THEN GriffinViewer.DoPaint[paintProc] ELSE paintProc[dc]; }; BLTBlockInScreen: PUBLIC PROCEDURE[src: BlockPtr, tl: PointDefs.ScrPt, fnc: Graphics.PaintMode, dc: Context]= BEGIN OPEN PointDefs; paintProc: GriffinViewer.PaintProc = { [] _ Graphics.SetPaintMode[dc,fnc]; Graphics.SetCP[dc, dlx,YFlip[dty]]; --flip y dc.procs.DrawBits[self: dc, base: src.base, raster: src.raster, bitsPerPixel: 0, w: drx-dlx+1, h: dby - dty +1, x: x, y: y, xorigin: x, yorigin: y]; }; dlx,dty,drx,dby,x,y: INTEGER; dlx _ tl[X]; dty _ tl[Y]; drx _ dlx + src.w -1; dby _ dty + src.h -1; IF CLIP THEN BEGIN IF CULL THEN RETURN; IF dlx>RX OR drxBY OR dbyRX THEN drx _ RX; IF dty < TY THEN dty _ TY; IF dby >BY THEN dby _ BY; END; x _ src.lx+(dlx-tl[X]); y _ src.ty+(dty-tl[Y]); IF dc=NIL THEN GriffinViewer.DoPaint[paintProc] ELSE paintProc[dc]; END; DrawBox: PROC[xmin,ymin,xmax,ymax: INTEGER, dc: Context] = { paintProc: PROC[dc: Graphics.Context] = { ref: CGContext.Ref _ NARROW[dc.data]; newMin: GraphicsBasic.Vec _ CGMatrix.Map[ref.matrix,[xmin,YFlip[ymin]]]; newMax: GraphicsBasic.Vec _ CGMatrix.Map[ref.matrix,[xmax,YFlip[ymax]]]; cgBox: Graphics.Box _ [xmin: newMin.x, ymin: newMin.y, xmax: newMax.x, ymax: newMax.y]; CGArea.InsertBox[cgArea,cgBox]; ref.device.Show[ref.device,cgArea,cgSource,NIL]; }; IF dc=NIL THEN GriffinViewer.DoPaint[paintProc] ELSE paintProc[dc]; }; MoveScreenBox: PUBLIC PROCEDURE[tl,br: PointDefs.ScrPt,dx,dy: INTEGER] = BEGIN paintProc: PROC[dc: Graphics.Context] = { ref: CGContext.Ref _ NARROW[dc.data]; from: GraphicsBasic.Vec _ CGMatrix.Map[ref.matrix,[tl[X],YFlip[tl[Y]]]]; to: GraphicsBasic.Vec _ CGMatrix.Map[ref.matrix,[tl[X]+dx,YFlip[tl[Y]+dy]]]; xbr: GraphicsBasic.Vec _ CGMatrix.Map[ref.matrix,[br[X],YFlip[br[Y]]]]; lx: INTEGER _ Real.RoundI[to.x]; ty: INTEGER _ Real.RoundI[to.y]; rx: INTEGER _ Real.RoundI[lx+xbr.x-from.x]; by: INTEGER _ Real.RoundI[ty+xbr.y-from.y]; IF lx>RX OR rxBY OR byRX THEN rx _ RX; IF ty < TY THEN ty _ TY; IF by >BY THEN by _ BY; GraphicsOps.MoveDeviceRectangle[self: dc, width: rx-lx+1, height: by-ty+1, --trust we're not scaled fromX: MAX[LX,Real.RoundI[from.x]], fromY: MAX[TY,Real.RoundI[from.y]], toX: lx, toY: ty]; }; GriffinViewer.DoPaint[paintProc]; END; vgridBlock,hgridBlock: ScreenDefs.BlockPtr; vgridbits: PACKED ARRAY [0..8) OF CARDINAL _ ALL[040000B]; hgridbits: PACKED ARRAY [0..4) OF CARDINAL _ ALL[100200B]; vgridBlock _ NEW[Block _ [@vgridbits,1,0,0,3,8]]; hgridBlock _ NEW[Block _ [@hgridbits,1,0,0,8,3]]; vgridbits[0] _ 120000B; --rest are "040000B" hgridbits[1] _ 77577B; --rest are "100200B" CodedBrushes[1] _[NEW[IntegerSequenceRec[1]],NEW[IntegerSequenceRec[1]]]; CodedBrushes[1][left][0]_ 0; CodedBrushes[1][right][0]_ 0; CodedBrushes[2] _[NEW[IntegerSequenceRec[2]],NEW[IntegerSequenceRec[2]]]; CodedBrushes[2][left][0]_ -1; CodedBrushes[2][left][1]_ -1; CodedBrushes[2][right][0]_ 0; CodedBrushes[2][right][1]_ 0; CodedBrushes[3] _[NEW[IntegerSequenceRec[3]],NEW[IntegerSequenceRec[3]]]; CodedBrushes[3][left][0]_ 0; CodedBrushes[3][left][1]_ -1; CodedBrushes[3][left][2]_ 0; CodedBrushes[3][right][0]_ 0; CodedBrushes[3][right][1]_ 1; CodedBrushes[3][right][2]_ 0; CodedBrushes[4] _[NEW[IntegerSequenceRec[4]],NEW[IntegerSequenceRec[4]]]; CodedBrushes[4][left][0]_ -1; CodedBrushes[4][left][1]_ -2; CodedBrushes[4][left][2]_ -2; CodedBrushes[4][left][3]_ -1; CodedBrushes[4][right][0]_ 0; CodedBrushes[4][right][1]_ 1; CodedBrushes[4][right][2]_ 1; CodedBrushes[4][right][3]_ 0; END. œmstone January 26, 1983 6:23 pm Low level screen functions Last Edited by: Stone, February 15, 1984 11:43:26 am PST Last Edited by: Pier, February 14, 1984 6:50:55 pm PST clears the current screen defines the current screen changes clipping edges of current screen. Must stay inside initial clip window clip clipping window This routine "scan converts" a chain encoding and draws main loop for processing a point topIndex now points to bottom of xRanges now write out lowest scan line. and reset for new entries first write out top scan line and reset for new entries EndChain[dc]; blt whole brush for strictly horizontal movements DrawNextDot[0,0,dc]; cleanup remaining brush lines when finished These parameters are in DEVICE coordinates actual calls to the GraphicsPackage we've got to change y for a bottomUp coordinate system y,xmin,xsize relative to the character origin I want edges Initialize coded brushes Ê˘J˜Jšœ™Jšœ™Jšœ8™8Jšœ6™6J˜šÏk ˜ Jšœ œ˜Jšœ œ–˜¤Jšœœœ˜Jšœ˜Jšœœ˜Jšœœ˜"Jšœ œ ˜Jšœ œ˜Jšœ œ˜Jšœ œ ˜Jšœ œ˜(Jš œ œ œ,œœ˜RJšœœ!œ˜1J˜7Jšœœ ˜ Jšœœ ˜Jšœ œ˜ Jšœœ ˜3Jšœ œ˜Jšœœ ˜J˜—Jšœ ˜Jšœy˜€Jšœ˜&Jšœœ(˜2J˜J˜Jš œœœœœ˜Jšœœ˜%Jšœœœ˜Jšœœœ˜Jšœ˜J˜J˜%J˜%J˜$J˜.J˜J˜Jšœ™JšÏn œœ œ˜.Jš˜Jšœ œœ˜Jšœ œœ˜J˜Jšœ˜J˜Jšœ™Jšž œœ œœ˜8Jš˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜J˜J˜JšœO™OJšž œœ œ˜;šœ™J˜Jšœœœœœœœœ˜.šœœœ˜Jšœœ˜ Jšœœ˜ Jšœœ˜ Jšœœ˜ J˜—J˜J˜—Jšž œœœœ˜AJš˜šœœœœœœœœœœœ˜/Jšœœ˜—Jšœœ œœ ˜'Jšœœ œœ ˜%Jšœœ œœ ˜'Jšœœ œœ ˜%Jšœ˜Jšœ˜J˜Jšžœœœ œ ˜Jšœœ ˜Jšœœ˜&J˜Jšœ ™ J˜J˜šœ˜šœœŸ˜šœ˜Jšœ!˜%Jšœ(™(—Jšœ™J˜KJšœ™J˜J˜J˜Jšœ˜J˜—šœœŸ˜Jšœ™J˜:Jšœ™J˜J˜Jšœ'œ˜;J˜Jšœ˜—Jšœœ˜ Jšœ˜—Jšœ?™?šœ™Jšœ˜Jšœ˜—J˜šœ œ˜$šœ=˜?Jšœ˜—šœ?˜AJšœ˜—šœ+˜-Jšœ˜—Jšœ˜—Jšœ˜J˜Jšžœœ œ˜*Jš˜Jšœ+™+Jšœ œ˜šœ œ˜ Jš˜J˜:J˜šœ&˜(Jšœ˜—Jšœ˜—Jšœ˜J˜J˜Jšž œœ œ&˜DJ˜J˜š ž œœ œœœœ˜WJšœœ ˜%J˜AJ˜J˜J˜Jšœœ˜J˜J˜Jšœ˜J˜J˜—Jšœœ˜J˜Jšœœ˜J˜šž œœ˜0Jšœ2œœ˜AJ˜J˜Jšœœœ˜.J˜J˜J˜J˜—Jšœ*™*šž œœ œ œ˜Ašœœœ˜Jšœœœœ˜Jš œœœœœœŸ˜9Jšœ œ ˜Jšœ œ ˜Jšœ˜—J˜/J˜Jšœ'œ˜,J˜J˜—Jšžœ œ œ ˜AJš˜šœœœ˜Jšœœœœ˜JšœœœœœœœœœœŸ˜5Jšœœœœ˜Jšœœœœ˜Jšœ˜—J˜Jšœœ˜J˜6Jšœ˜J˜Jšž œœ œ'˜BJšœœ ˜Jš œœœœœŸ(˜RJš œœœœœ˜)šœœœ˜Jšœœœœ˜JšœœœœœœœœœœŸ˜7Jšœœœœ˜Jšœœœœ˜Jšœœœœ˜Jšœœœœ˜Jšœ˜—J˜J˜J˜5Jšœ˜J˜Jšžœœ œ'˜AJšœœ ˜Jš œœœœœŸ(˜RJš œœœœœ˜)šœœœ˜Jšœœœœ˜JšœœœœœœœœœœŸ˜7Jšœœœœ˜Jšœœœœ˜Jšœœœœ˜Jšœœœœ˜Jšœ˜—J˜J˜J˜5Jšœ˜J˜Jšžœœ œ'˜@Jšœœ ˜Jš œœœœœŸ(˜RJš œœœœœ˜)šœœœ˜Jšœœœœ˜JšœœœœœœœœœœŸ˜7Jšœœœœ˜Jšœœœœ˜Jšœœœœ˜Jšœœœœ˜Jšœ˜—J˜Jšœœ˜J˜5Jšœ˜J˜Jšœ œ˜Jšœœ˜šžœœ ˜#Jšœ@œ˜P—Jš˜J˜J˜"J˜,J˜Jšœ'˜-Jšœ˜J˜Jšžœœ œœ˜5Jš˜Jšœœ œ˜.šœ˜J˜4J˜ Jšœ˜—Jšœ˜J˜Jšžœœ œœ˜5Jš˜Jšœœ œ˜.šœ˜J˜5J˜ Jšœ˜—Jšœ˜J˜Jšœ#™#Jšœœ1œœ ˜†J˜"J˜9J˜š žœœœœœœ˜5Jšœ!˜'J˜J˜—J˜:šžœœ œ&œ˜\Jšœœ˜Jšœ&˜&šœ6™6˜Jš œ œœœœ˜B—Jšœœœ˜2J˜J˜&Jšœ6˜6J˜—Jšœ)˜)Jšœ:˜:Jšœœ œ˜+Jšœœ œ˜*Jšœœœ!˜/Jšœ?˜CJ˜J˜J˜—J˜Lš žœœ œ œ!œ˜b˜0J˜C—šÏb œ˜&Jšœœ ˜%Jšœ:œœ˜PJšœœŸ˜CJšœœ˜$Jšœ œ˜Jš  œœœœ œœ˜Bšœ-™-J˜J˜J˜šœœœ˜Jšœœœœ˜Jš œœœœœœŸ˜9Jšœ œ ˜Jšœ œ ˜Jšœ˜—J˜/J˜J˜—JšœŸ˜-J˜Jšœ˜JšœC˜CJšœ+œ˜0J˜—Jšœœœ!œ˜CJ˜J˜J˜—Jšžœœ œK˜mJšœœ ˜˜&J˜#Jšœ$Ÿ˜,˜J˜4J˜C—J˜J˜—Jšœœ˜šœ ™ Jšœ œ œ˜J˜J˜—šœœœ˜Jšœœœœ˜JšœœœœœœœœœœŸ˜;Jšœœœœ˜Jšœœœœ˜Jšœœœœ˜Jšœœœœ˜Jšœ˜—Jšœœœ˜/Jšœœœ"œ˜CJšœ˜J˜šžœœœ˜<šœ œ˜)Jšœœ ˜%J˜HJ˜H˜6J˜ —J˜Jšœ+œ˜0J˜—Jšœœœ"œ˜CJ˜J˜—Jšž œœ œœ˜Hš˜šœ œ˜)Jšœœ ˜%Jšœ6œ œ˜HJšœ4œœ˜Lšœ5œ œ˜GJšœœœ˜AJšœœ%œ ˜W—JšœœœœœœœœœœŸ˜7Jšœœœœ˜Jšœœœœ˜Jšœœœœ˜Jšœœœœ˜˜)Jšœ!Ÿ˜9Jš œœœœœ˜GJ˜J˜——J˜!—Jšœ˜J˜J˜J˜+Jš œ œœœœœ ˜:Jš œ œœœœœ ˜:J˜Jšœ œ!˜1Jšœ œ!˜1J˜JšœŸ˜,JšœŸ˜+J˜šœ™Jšœœœ˜IJ˜J˜Jšœœœ˜IJ˜J˜J˜J˜Jšœœœ˜IJ˜J˜J˜J˜J˜J˜Jšœœœ˜IJ˜J˜J˜J˜J˜J˜J˜J˜J˜Jšœ˜J˜J˜J˜——…—;xTß