DIRECTORY Draw2d, GGBasicTypes, GGCaret, GGCoreTypes, GGModelTypes, GGSegmentTypes, GGShapes, GGStoragePools, Imager, ImagerTransformation, Lines2d, Real, SF, Vectors2d; GGShapesImpl: CEDAR PROGRAM IMPORTS Draw2d, GGStoragePools, Lines2d, Vectors2d, Imager, Real EXPORTS GGShapes = BEGIN BoundBox: TYPE = GGCoreTypes.BoundBox; Circle: TYPE = GGBasicTypes.Circle; Line: TYPE = GGCoreTypes.Line; Point: TYPE = GGBasicTypes.Point; Ray: TYPE = GGBasicTypes.Ray; Vector: TYPE = GGBasicTypes.Vector; SelectionClass: TYPE = GGSegmentTypes.SelectionClass; jointSize: INTEGER = Real.Round[GGModelTypes.jointSize]; halfJointSize: REAL = GGModelTypes.halfJointSize; hotJointSize: INTEGER = Real.Round[GGModelTypes.hotJointSize]; halfHotJointSize: REAL = GGModelTypes.halfHotJointSize; DrawWhiteRectangle: PUBLIC PROC [dc: Imager.Context, loX, loY, hiX, hiY: REAL, strokeWidth: REAL _ 1.0] = { DoDrawRect: PROC = { strokeWidth2: REAL _ strokeWidth+strokeWidth; width: REAL _ hiX-loX; height: REAL _ hiY-loY; Imager.SetColor[dc, Imager.black]; Imager.MaskRectangle[dc, [loX-strokeWidth, loY-strokeWidth, width+strokeWidth2, height+strokeWidth2]]; Imager.SetColor[dc, Imager.white]; Imager.MaskRectangle[dc, [loX, loY, width, height]]; }; Imager.DoSave[dc, DoDrawRect]; }; DrawRectangle: PUBLIC PROC [dc: Imager.Context, loX, loY, hiX, hiY: REAL, strokeWidth: REAL _ 1.0] = { DoDrawRect: PROC = { RectanglePath: Imager.PathProc = { moveTo[[loX, loY]]; lineTo[[loX, hiY]]; lineTo[[ hiX, hiY]]; lineTo[[ hiX, loY]]; lineTo[[loX, loY]]; }; Imager.SetStrokeWidth[dc, strokeWidth]; Imager.SetStrokeEnd[dc, square]; Imager.SetStrokeJoint[dc, round]; Imager.MaskStroke[dc, RectanglePath, TRUE]; }; Imager.DoSave[dc, DoDrawRect]; }; DrawFilledRectangle: PUBLIC PROC [dc: Imager.Context, loX, loY, hiX, hiY: REAL] = { DoDrawFilledRectangle: PROC = { Imager.SetXY[dc, [loX, loY]]; -- set the current position Imager.Move[dc]; -- move the origin to the current position Imager.SetColor[dc, Imager.black]; Imager.MaskRectangle[dc, [0, 0, hiX-loX, hiY-loY]]; }; Imager.DoSave[dc, DoDrawFilledRectangle]; }; DrawSquare: PUBLIC PROC [dc: Imager.Context, center: Point, side: REAL, strokeWidth: REAL _ 1.0] = { halfSide: REAL _ side/2.0; DoDrawSquare: PROC = { SquarePath: Imager.PathProc = { moveTo[[- halfSide, - halfSide]]; lineTo[[- halfSide, halfSide]]; lineTo[[ halfSide, halfSide]]; lineTo[[ halfSide, - halfSide]]; lineTo[[- halfSide, - halfSide]]; }; Imager.SetXY[dc, [center.x, center.y]]; Imager.Move[dc]; Imager.SetStrokeWidth[dc, strokeWidth]; Imager.SetStrokeEnd[dc, square]; Imager.SetStrokeJoint[dc, round]; Imager.MaskStroke[dc, SquarePath, TRUE]; }; Imager.DoSave[dc, DoDrawSquare]; }; DrawPlus: PUBLIC PROC [dc: Imager.Context, center: Point] = { halfSide: REAL = 5.0; DoDrawPlus: PROC = { Horiz: Imager.PathProc = { moveTo[[-halfSide, 0.0]]; lineTo[[halfSide, 0.0]]; }; Vert: Imager.PathProc = { moveTo[[0.0, -halfSide]]; lineTo[[0.0, halfSide]]; }; Imager.SetXY[dc, [center.x, center.y]]; Imager.Move[dc]; Imager.SetStrokeWidth[dc, 2.0]; Imager.SetStrokeEnd[dc, square]; Imager.MaskStroke[dc, Horiz, FALSE]; Imager.MaskStroke[dc, Vert, FALSE]; }; Imager.DoSave[dc, DoDrawPlus]; }; DrawBoundBox: PUBLIC PROC [dc: Imager.Context, bBox: BoundBox, strokeWidth: REAL _ 1.0] = { DrawRectangle[dc, bBox.loX, bBox.loY, bBox.hiX, bBox.hiY, strokeWidth]; }; DrawFilledSquare: PUBLIC PROC [dc: Imager.Context, center: Point, side: REAL] = { halfSide: REAL _ side/2.0; DoDrawFilledSquare: PROC = { Imager.SetXY[dc, [center.x, center.y]]; -- set the current position Imager.Move[dc]; -- move the origin to the current position Imager.SetColor[dc, Imager.black]; Imager.MaskRectangle[dc, [- halfSide, - halfSide, side, side]]; }; Imager.DoSave[dc, DoDrawFilledSquare]; }; DrawEmptySquare: PROC [dc: Imager.Context, center: Point, side: REAL, strokeWidth: REAL] = { DoDrawEmptySquare: PROC = { Imager.SetXY[dc, [center.x, center.y]]; Imager.Move[dc]; -- move the origin to the current position Imager.SetColor[dc, Imager.black]; Imager.MaskRectangle[dc, [-halfSide, -halfSide, side, side]]; Imager.SetColor[dc, Imager.white]; Imager.MaskRectangle[dc, [-halfSide+strokeWidth, -halfSide+strokeWidth, side-width2, side-width2]]; }; halfSide, width2: REAL; side _ side; halfSide _ side/2.0; width2 _ 2.0*strokeWidth; Imager.DoSave[dc, DoDrawEmptySquare]; }; DrawSpot: PUBLIC PROC [dc: Imager.Context, point: Point] = { DoDrawSpot: PROC = { Imager.SetXY[dc, [point.x, point.y]]; Imager.Move[dc]; Imager.MaskRectangle[dc, [0.0, 0.0, 1.0, 1.0]]; }; Imager.DoSave[dc, DoDrawSpot]; }; DrawLine: PUBLIC PROC [dc: Imager.Context, line: Line, clippedBy: Imager.Rectangle, strokeWidth: REAL _ 1.0, zip: Draw2d.Zip _ NIL] = { count: NAT; ray: Ray; params: ARRAY[1..2] OF REAL; p1, p2, basePoint: Point; direction: Vector; p1 _ [clippedBy.x, clippedBy.y]; p2 _ [clippedBy.x + clippedBy.w, clippedBy.y + clippedBy.h]; basePoint _ Lines2d.PointOnLine[line]; direction _ Lines2d.DirectionOfLine[line]; ray _ AllocateRay[basePoint, direction]; [count, params] _ Lines2d.LineRayMeetsBox[ray, p1.x, p1.y, p2.x, p2.y]; IF count = 2 THEN { p1 _ Lines2d.EvalRay[ray, params[1]]; p2 _ Lines2d.EvalRay[ray, params[2]]; Imager.SetStrokeWidth[dc, strokeWidth]; Draw2d.Line[dc, p1, p2, solid, zip]; }; DoFreeRay[rayPool, ray]; }; DrawLittleLine: PUBLIC PROC [dc: Imager.Context, line: Line, point: Point] = { }; DrawFilledLoLeftSquare: PUBLIC PROC [dc: Imager.Context, loLeft: Point, side: REAL] = { DoDrawRect: PROC = { Imager.SetXY[dc, [loLeft.x, loLeft.y]]; Imager.Move[dc]; Imager.MaskRectangle[dc, [0.0, 0.0, side, side]]; }; Imager.DoSave[dc, DoDrawRect]; }; DrawCircle: PUBLIC PROC [dc: Imager.Context, circle: Circle] = { leftSide, rightSide: Point; DoDrawCircle: PROC = { CirclePath: Imager.PathProc = { moveTo[[leftSide.x, leftSide.y]]; arcTo[[rightSide.x, rightSide.y], [ leftSide.x, leftSide.y]]; }; Imager.SetStrokeWidth[dc, 1.0]; Imager.SetStrokeEnd[dc, round]; Imager.MaskStroke[dc, CirclePath, TRUE]; }; leftSide _ [circle.origin.x - circle.radius, circle.origin.y]; rightSide _ [circle.origin.x + circle.radius, circle.origin.y]; Imager.DoSave[dc, DoDrawCircle]; }; starBurstsOn: BOOL _ TRUE; starBurstWidth: REAL _ 0.0; tryDraw2d: BOOL _ TRUE; R: REAL _ 7.0; cos30: REAL = 0.8660254; sin30: REAL = 0.5; yR: REAL _ cos30*R; xR: REAL _ sin30*R; DrawStarburst: PUBLIC PROC [dc: Imager.Context, point: Point, scale: REAL _ 1.0, zip: Draw2d.Zip _ NIL] = { DoDrawGlow: PROC = { leftX, loX, hiX, rightX, loY, hiY: REAL; scaledR, scaledXR, scaledYR: REAL; Imager.SetColor[dc, Imager.black]; Imager.SetStrokeWidth[dc, starBurstWidth]; scaledR _ R*scale; scaledXR _ xR*scale; scaledYR _ yR*scale; leftX _ point.x-scaledR; loX _ point.x-scaledXR; hiX _ point.x+scaledXR; rightX _ point.x+scaledR; loY _ point.y-scaledYR; hiY _ point.y+scaledYR; IF tryDraw2d THEN { Draw2d.Line[dc, [leftX, point.y], [rightX, point.y], solid, zip]; Draw2d.Line[dc, [loX, loY], [hiX, hiY], solid, zip]; Draw2d.Line[dc, [hiX, loY], [loX, hiY], solid, zip]; } ELSE { Imager.MaskVector[dc, [leftX, point.y], [rightX, point.y]]; Imager.MaskVector[dc, [loX, loY], [hiX, hiY]]; Imager.MaskVector[dc, [hiX, loY], [loX, hiY]]; }; }; IF starBurstsOn THEN Imager.DoSave[dc, DoDrawGlow]; }; DrawArrow: PUBLIC PROC [dc: Imager.Context, tip: Point, base: Point, strokeWidth: REAL] = { OPEN Vectors2d; DrawArrowAux: Imager.PathProc = { moveTo[tip]; lineTo[Sub[tip, Add[Scale[axis, height], Scale[perp, halfWidth]]]]; lineTo[Sub[tip, Add[Scale[axis, height], Scale[perp, -halfWidth]]]]; lineTo[tip]; }; axis: Vector; perp: Vector; height: REAL _ strokeWidth+5.0; halfWidth: REAL _ strokeWidth+3.0; IF tip = base THEN RETURN; axis _ Normalize[Vectors2d.Sub[tip, base]]; perp _ [axis.y, -axis.x]; Imager.MaskFill[context: dc, path: DrawArrowAux, oddWrap: FALSE] }; ArrowSize: PUBLIC PROC [strokeWidth: REAL] RETURNS [height, halfWidth: REAL] = { height _ strokeWidth+5.0; halfWidth _ strokeWidth+3.0; }; DrawCaret: PUBLIC PROC [dc: Imager.Context, point: Point, normal: Vector, scale: REAL _ 1.0] = { halfWidth: REAL = GGCaret.caretWidth/2.0; fullHeight: REAL = GGCaret.caretHeight; caretDirection: Vector; point1, point2, midPoint: Point; DoDrawCaret: PROC = { CaretPath: Imager.PathProc = { moveTo[point1]; lineTo[point]; lineTo[point2]; }; Imager.SetStrokeWidth[dc, 0.0]; Imager.MaskStroke[dc, CaretPath, FALSE]; }; caretDirection _ Vectors2d.Normalize[normal]; midPoint _ Vectors2d.Add[point, Vectors2d.Scale[caretDirection, fullHeight*scale]]; caretDirection _ Vectors2d.Scale[caretDirection, halfWidth*scale]; point1.x _ midPoint.x + caretDirection.y; point1.y _ midPoint.y - caretDirection.x; point2.x _ midPoint.x - caretDirection.y; point2.y _ midPoint.y + caretDirection.x; Imager.DoSave[dc, DoDrawCaret]; }; DrawAnchor: PUBLIC PROC [dc: Imager.Context, point: Point, normal: Vector, scale: REAL _ 1.0] = { DoDrawAnchor: PROC = { ArmPath: Imager.PathProc = { moveTo[[nearX, stroke]]; lineTo[[farX, stroke]]; lineTo[[midX, bottom]]; lineTo[[midX, -stroke]]; lineTo[[nearX, -stroke]]; }; side: REAL _ 3.5*scale; insideWing: REAL _ 7.0*scale; width: REAL _ 6.0*scale; height: REAL _ 8.0*scale; bottom: REAL _ -8.5*scale; stroke: REAL _ 0.5*scale; nearX, midX, farX: REAL; degrees: REAL; epsilon: REAL = 0.1; Imager.SetXY[dc, [point.x, point.y]]; -- set the current position degrees _ Vectors2d.AngleFromVector[normal] + 90.0; Imager.Move[dc]; IF ABS[degrees] > epsilon THEN Imager.RotateT[dc, degrees]; Imager.SetColor[dc, Imager.black]; Imager.SetStrokeEnd[dc, square]; Imager.SetStrokeWidth[dc, scale]; Imager.MaskVector[dc, [-side, -side], [-side, side]]; Imager.MaskVector[dc, [-side, side], [side, side]]; Imager.MaskVector[dc, [side, side], [side, -side]]; Imager.MaskVector[dc, [side, -side], [-side, -side]]; nearX _ side; midX _ insideWing; farX _ insideWing+width; Imager.MaskFill[dc, ArmPath]; nearX _ -side; midX _ -insideWing; farX _ -insideWing-width; Imager.MaskFill[dc, ArmPath]; }; Imager.DoSave[dc, DoDrawAnchor]; }; DrawCP: PUBLIC PROC [dc: Imager.Context, point: Point, scale: REAL _ 1.0] = { <> DrawEmptySquare[dc, point, jointSize*scale, scale]; }; DrawJoint: PUBLIC PROC [dc: Imager.Context, point: Point, scale: REAL _ 1.0] = { <> { DrawEmptySquare[dc, point, jointSize*scale, scale]; DrawFilledSquare[dc, point, 2.0*scale]; }; }; DrawSelectedJoint: PUBLIC PROC [dc: Imager.Context, point: Point, selectClass: SelectionClass, scale: REAL _ 1.0] = { <> IF selectClass=hot THEN DrawEmptySquare[dc, point, hotJointSize*scale, scale] ELSE IF selectClass=normal THEN DrawFilledSquare[dc, point, jointSize*scale] ELSE ERROR; }; DrawQuickSelectedJoint: PUBLIC PROC [dc: Imager.Context, point: Point, selectClass: SelectionClass, scale: REAL] = { IF selectClass=normal THEN { scaleJOver2: REAL _ scale*halfJointSize; DrawFilledRectangle[dc, point.x-3.0*scaleJOver2, point.y-scaleJOver2, point.x+scaleJOver2, point.y+scaleJOver2]; } ELSE IF selectClass=hot THEN { scaleHJOver2: REAL _ scale*halfHotJointSize; Imager.SetColor[dc, Imager.black]; DrawWhiteRectangle[dc, point.x-scale*(halfHotJointSize+jointSize), point.y-scaleHJOver2, point.x+scaleHJOver2, point.y+scaleHJOver2, scale]; } ELSE ERROR; }; rayPool: GGStoragePools.StoragePool; rayPoolClass: GGStoragePools.StoragePoolClass; RayPool: TYPE = REF RayPoolObj; RayPoolObj: TYPE = RECORD [ index: NAT _ 0, rays: SEQUENCE len: NAT OF Ray ]; maxRays: NAT = 6; AllocateRay: PROC [base: Point, direction: Vector] RETURNS [ray: Ray] = { ray _ NARROW[DoAllocateRay[rayPool]]; ray.p _ base; ray.d _ direction; }; MakeRayStorage: PROC [pool: GGStoragePools.StoragePool] = { realPool: RayPool _ NEW[RayPoolObj[maxRays]]; FOR i: NAT IN [0..5] DO realPool[i] _ Lines2d.CreateRay[[0,0], [0,0]]; ENDLOOP; realPool.index _ maxRays; pool.data _ realPool; }; DoAllocateRay: PROC [pool: GGStoragePools.StoragePool] RETURNS [item: REF ANY] = { realPool: RayPool _ NARROW[pool.data]; IF realPool.index = 0 THEN item _ Lines2d.CreateRay[[0,0], [0,0]] -- pool is empty, allocate one ELSE { realPool.index _ realPool.index - 1; item _ realPool[realPool.index]; }; }; DoFreeRay: PROC [pool: GGStoragePools.StoragePool, item: REF ANY] = { realPool: RayPool _ NARROW[pool.data]; realItem: Ray _ NARROW[item]; IF realPool.index = maxRays THEN RETURN; -- pool is full. Toss ray on the floor. realPool[realPool.index] _ realItem; realPool.index _ realPool.index + 1; }; Init: PROC = { rayPoolClass _ GGStoragePools.CreateClass[$RayPool, DoAllocateRay, DoFreeRay]; rayPool _ GGStoragePools.CreatePool[rayPoolClass, MakeRayStorage]; }; Init[]; END. ÒGGShapesImpl.mesa Contents: Predefined shapes for use in Gargoyle (e.g. squares for control points). Copyright Ó 1988 by Xerox Corporation. All rights reserved. Pier, January 18, 1988 3:48:16 pm PST Eisenman, July 24, 1987 5:21:27 pm PDT Bier, October 24, 1988 3:46:50 pm PDT Generic Draws the indicated rectangle (not filled). Draws the indicated rectangle (not filled). Imager.Trans[dc]; Imager.Trans[dc]; Draws an outer black square of length "side", and an inner white square of length "side-2*strokeWidth" Draw a short line (1 inch) centered on point, parallel to line. Draw a six pointed starburst of outer radius R and inner radius r. r: REAL _ 3.0; xr: REAL _ cos30*r; yr: REAL _ sin30*r; Draw2d.Line[dc, [0.0, r], [0.0, R], solid, zip]; Draw2d.Line[dc, [0.0, -r], [0.0, -R], solid, zip]; Draw2d.Line[dc, [xr, yr], [xR, yR], solid, zip]; Draw2d.Line[dc, [-xr, -yr], [-xR, -yR], solid, zip]; Draw2d.Line[dc, [-xr, yr], [-xR, yR], solid, zip]; Draw2d.Line[dc, [xr, -yr], [xR, -yR], solid, zip]; Imager.MaskVector[dc, [0.0, r], [0.0, R]]; Imager.MaskVector[dc, [0.0, -r], [0.0, -R]]; Imager.MaskVector[dc, [xr, yr], [xR, yR]]; Imager.MaskVector[dc, [-xr, -yr], [-xR, -yR]]; Imager.MaskVector[dc, [-xr, yr], [-xR, yR]]; Imager.MaskVector[dc, [xr, -yr], [xR, -yR]]; The arrowhead will fit in a box of size height by (halfWidth*2). Gargoyle-specified Scale the caret by "scale" about "point" before drawing it. Draw the square in the middle. Draw the two wings. The Pool of Rays Ê"˜Icodešœ™šÏnœJ™RK™Kšœžœ!˜7K˜K™š œžœžœ*žœžœ ˜kKšœ+™+š œžœ˜Kšœžœ˜-Kšœžœ ˜Kšœžœ ˜Kšœ"˜"šœ˜KšœM˜M—Kšœ"˜"Kšœ4˜4Kšœ˜—Kšœ˜Kšœ˜K˜—š œžœžœ*žœžœ ˜fKšœ+™+š œžœ˜š œ˜"Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜—Kšœ'˜'Kšœ ˜ Kšœ!˜!Kšœ%žœ˜+Kšœ˜—Kšœ˜Kšœ˜K˜—šœž œ*žœ˜Sšœžœ˜Kšœ Ïc˜;KšœŸ*˜=Kšœ"˜"Kšœ3˜3Kšœ˜—Kšœ)˜)Kšœ˜K˜—š œžœžœ+žœžœ ˜dKšœ žœ ˜š œžœ˜š œ˜Kšœ!˜!Kšœ ˜ Kšœ˜Kšœ!˜!Kšœ"˜"K˜—Kšœ'˜'Kšœ™Kšœ˜Kšœ'˜'Kšœ ˜ Kšœ!˜!Kšœ"žœ˜(K˜—Kšœ ˜ K˜K˜—šœžœžœ(˜=Kšœ žœ˜š œžœ˜šœ˜K˜Kšœ˜K˜—šœ˜K˜Kšœ˜K˜—Kšœ'˜'Kšœ™Kšœ˜Kšœ˜Kšœ ˜ Kšœžœ˜$Kšœžœ˜#K˜—Kšœ˜K˜K˜—š œžœžœ3žœ ˜[KšœG˜GK˜K˜—K˜šœž œ+žœ˜QKšœ žœ ˜šœžœ˜Kšœ*Ÿ˜EKšœŸ*˜=Kšœ"˜"Kšœ?˜?K˜—Kšœ&˜&K˜K˜—šœžœ+žœžœ˜\Kšœ-™-Kšœ8™8šœžœ˜Kšœ'˜'KšœŸ*˜=Kšœ"˜"Kšœ=˜=K˜"Kšœc˜cK˜—Kšœž˜Kšœ ˜ Kšœ˜Kšœ˜Kšœ%˜%K˜K˜—šœžœžœ'˜<š œžœ˜Kšœ%˜%Kšœ˜Kšœ/˜/K˜—Kšœ˜K˜K˜—š œžœžœLžœžœ˜‡Kšœžœ˜ K˜ Kšœžœžœžœ˜Kšœ˜K˜Kšœ ˜ Kšœ<˜˜>K˜—Kšœ˜Kšœ˜Kšœ"žœ˜(K˜—Kšœ>˜>Kšœ?˜?Kšœ ˜ K˜K˜—Iprocšœžœžœ˜Lšœžœ˜Lšœ žœžœ˜Lšœžœ˜Lšœžœ ˜Lšœžœ˜Lšœžœ ˜Lšœžœ ˜L˜L˜š œžœžœ+žœžœ˜kL™Bš œžœ˜Lšœžœ™Lšœžœ ™Lšœžœ ™Lšœ#žœ˜(Lšœžœ˜"Lšœ"˜"Lšœ*˜*Lšœ˜Lšœ˜Lšœ˜Lšœ˜Lšœ˜Lšœ˜Lšœ˜Lšœ˜Lšœ˜šžœ žœ˜LšœA˜ALšœ4˜4Lšœ4˜4Lšœ0™0Lšœ2™2Lšœ0™0Lšœ4™4Lšœ2™2Lšœ2™2L˜—šžœ˜Lšœ;˜;Lšœ.˜.Lšœ.˜.Lšœ*™*Lšœ,™,Lšœ*™*Lšœ.™.Lšœ,™,Lšœ,™,L˜—L˜—Lšžœžœ˜3L˜L˜—š œžœžœ<žœ˜[Kšžœ ˜š œ˜!Kšœ ˜ KšœC˜CKšœD˜DKšœ ˜ K˜—Kšœ ˜ Kšœ ˜ Kšœžœ˜Kšœ žœ˜"Kšžœ žœžœ˜Kšœ+˜+Kšœ˜K•StartOfExpansionP[context: Imager.Context, path: ImagerPath.PathProc, parity: BOOL _ FALSE]šœ:žœ˜@K˜K˜—š œžœžœžœžœžœ˜PKšœ@™@Kšœ˜Kšœ˜K˜—K™K™š œžœžœ;žœ ˜`Kšœ;™;Kšœ žœ˜)Kšœ žœ˜'Kšœ˜Kšœ ˜ š œžœ˜š œ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜—Kšœ˜Kšœ!žœ˜(Kšœ˜—K˜Kšœ-˜-KšœS˜SKšœB˜BKšœ)˜)Kšœ)˜)Kšœ)˜)Kšœ)˜)Kšœ˜Kšœ˜—š œžœžœ;žœ ˜aš œžœ˜šœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜K˜—Kšœžœ ˜Kšœ žœ ˜Kšœžœ ˜Kšœžœ ˜Kšœžœ˜Kšœžœ ˜Kšœžœ˜Kšœ žœ˜Kšœ žœ˜Kšœ(Ÿ˜CKšœ3˜3Kšœ˜Kšžœžœžœ˜;Kšœ"˜"Kšœ ˜ Kšœ!˜!KšÏb™Kšœ5˜5Kšœ3˜3Kšœ3˜3Kšœ5˜5Kš ™šœ9˜9Kšœ˜—šœ<˜