DIRECTORY AIS, AtomButtonsTypes, Feedback, FS, Imager, ImagerColor, ImagerColorPrivate, ImagerPixelArray, ImagerTransformation, Real, Rope, SVShading, SV2d, SVBasicTypes, SVFiles, SVImage, SVModelTypes, SVVector2d, ViewerClasses; SVImageImpl: CEDAR PROGRAM IMPORTS AIS, Feedback, FS, Imager, ImagerColor, ImagerColorPrivate, ImagerPixelArray, ImagerTransformation, Real, Rope, SVShading, SVFiles, SVVector2d EXPORTS SVImage = BEGIN BoundBox: TYPE = REF BoundBoxObj; BoundBoxObj: TYPE = SVBasicTypes.BoundBoxObj; Color: TYPE = Imager.Color; FeedbackData: TYPE = AtomButtonsTypes.FeedbackData; FRef: TYPE = AIS.FRef; Image: TYPE = REF ImageObj; ImageObj: TYPE = SVImage.ImageObj; Point2d: TYPE = SV2d.Point2d; Viewer: TYPE = ViewerClasses.Viewer; WRef: TYPE = AIS.WRef; IsEven: PRIVATE PROC [n: NAT] RETURNS [BOOL] = { RETURN [(n/2)*2 = n]; }; RoundDown: PRIVATE PROC [r: REAL] RETURNS [rDown: INTEGER] = { IF r = 0 THEN RETURN[0]; IF r > 0 THEN { rDown _ Real.Fix[r]; RETURN} ELSE { r _ -r;-- make it positive rDown _ Real.Fix[r]; rDown _ rDown + 1; rDown _ - rDown; }; }; RoundUp: PRIVATE PROC [r: REAL] RETURNS [rUp: INTEGER] = { IF r = 0 THEN RETURN[0]; IF r > 0 THEN { rUp _ Real.Fix[r]; rUp _ rUp + 1; RETURN} ELSE { r _ -r;-- make it positive rUp _ Real.Fix[r]; rUp _ - rUp; }; }; CountSamples: PUBLIC PROC [realMinX, realMinY, realMaxX, realMaxY, resolution: REAL] RETURNS [numberOfSamplesX, numberOfSamplesY: NAT] = { xExtent, yExtent, realSamplesX, realSamplesY: REAL; xExtent _ realMaxX - realMinX; -- x extent in screen dots yExtent _ realMaxY - realMinY; -- y extent in screen dots realSamplesX _ (xExtent*resolution)/72.0; realSamplesY _ (yExtent*resolution)/72.0; numberOfSamplesX _ Real.Fix[realSamplesX] + 2; numberOfSamplesY _ Real.Fix[realSamplesY] + 2; IF NOT IsEven[numberOfSamplesX] THEN numberOfSamplesX _ numberOfSamplesX + 1; IF NOT IsEven[numberOfSamplesY] THEN numberOfSamplesY _ numberOfSamplesY + 1; }; -- end of CountSamples OpenImage: PUBLIC PROC [aisRope: Rope.ROPE, bAndWOnly: BOOL, realMinX, realMinY, realMaxX, realMaxY, resolution: REAL, feedback: FeedbackData] RETURNS [I: Image, numberOfSamplesX, numberOfSamplesY: NAT] = { f: AIS.FRef; raster: AIS.Raster; I _ NEW[ImageObj]; [numberOfSamplesX, numberOfSamplesY] _ CountSamples[realMinX, realMinY, realMaxX, realMaxY, resolution]; raster _ NEW[AIS.RasterPart _ [numberOfSamplesY, numberOfSamplesX, rd, 8, -1, 65535]]; IF bAndWOnly THEN { I.bAndWOnly _ TRUE; f _ AIS.CreateFile[aisRope, raster]; I.bwWindow _ AIS.OpenWindow[f]; Feedback.PutF[feedback, oneLiner, " New %g created.", [rope[aisRope]]]; } ELSE { redRope: Rope.ROPE _ Rope.Concat[SVFiles.FilenameMinusExtension[aisRope], "-red.ais"]; greenRope: Rope.ROPE _ Rope.Concat[SVFiles.FilenameMinusExtension[aisRope], "-grn.ais"]; blueRope: Rope.ROPE _ Rope.Concat[SVFiles.FilenameMinusExtension[aisRope], "-blu.ais"]; bwRope: Rope.ROPE _ aisRope; I.bAndWOnly _ FALSE; f _ AIS.CreateFile[redRope, raster]; I.redWindow _ AIS.OpenWindow[f]; f _ AIS.CreateFile[greenRope, raster]; I.greenWindow _ AIS.OpenWindow[f]; f _ AIS.CreateFile[blueRope, raster]; I.blueWindow _ AIS.OpenWindow[f]; f _ AIS.CreateFile[bwRope, raster]; I.bwWindow _ AIS.OpenWindow[f]; Feedback.PutF[feedback, end, " New color %g's created.", [rope[aisRope]]]; }; }; -- end of OpenImage Truncate: PROC [value: REAL] RETURNS [m: CARDINAL] = { SELECT value FROM <0 => ERROR; >255.0 => m _ 255; ENDCASE => m _ Real.Fix[value]; }; PutImage2: PROC [I: Image, i, j: INTEGER, color: Color, minX, maxX, minY, maxY: INTEGER] = { intRed, intGreen, intBlue, intIntensity: CARDINAL; red, green, blue, intensity: REAL; [red, green, blue] _ SVShading.ExtractRGB[color]; intensity _ ImagerColorPrivate.IntensityFromColor[NARROW[color]]; intRed _ Truncate[red*255.0]; intGreen _ Truncate[green*255.0]; intBlue _ Truncate[blue*255.0]; intIntensity _ Truncate[intensity*255.0]; AIS.WriteSample[I.redWindow, intRed, maxY - i, j - minX]; AIS.WriteSample[I.greenWindow, intGreen, maxY - i, j - minX]; AIS.WriteSample[I.blueWindow, intBlue, maxY - i, j - minX]; AIS.WriteSample[I.bwWindow, intIntensity, maxY - i, j - minX]; }; RGBTo8Bits: PUBLIC PROC [r,g,b: REAL] RETURNS [red, green, blue, black: NAT] = { k: REAL; red _ Real.Fix[r*255.0]; green _ Real.Fix[g*255.0]; blue _ Real.Fix[b*255.0]; k _ IntensityFromRGB[r,g,b]; black _ Real.Fix[k*255.0]; }; IntensityFromRGB: PROC [r,g,b: REAL] RETURNS [REAL] ~ { Y: REAL ~ 0.30*r+0.59*g+0.11*b; IF Y<=0 THEN RETURN[0]; RETURN[Y]; }; PutImage: PUBLIC PROC [I: Image, i, j: INTEGER, color: Color, xSamples, ySamples: NAT] = { IF I.bAndWOnly THEN { intIntensity: CARDINAL; intensity: REAL; intensity _ ImagerColorPrivate.IntensityFromColor[NARROW[color]]; intIntensity _ Truncate[intensity*255.0]; AIS.WriteSample[I.bwWindow, intIntensity, ySamples-i, j]; } ELSE { intRed, intGreen, intBlue, intIntensity: CARDINAL; red, green, blue, intensity: REAL; [red, green, blue] _ SVShading.ExtractRGB[color]; intensity _ ImagerColorPrivate.IntensityFromColor[NARROW[color]]; intRed _ Truncate[red*255.0]; intGreen _ Truncate[green*255.0]; intBlue _ Truncate[blue*255.0]; intIntensity _ Truncate[intensity*255.0]; AIS.WriteSample[I.redWindow, intRed, ySamples-i, j]; AIS.WriteSample[I.greenWindow, intGreen, ySamples-i, j]; AIS.WriteSample[I.blueWindow, intBlue, ySamples-i, j]; AIS.WriteSample[I.bwWindow, intIntensity, ySamples-i, j]; }; }; CloseImage: PUBLIC PROC [I: Image, aisRope: Rope.ROPE, comment: Rope.ROPE, feedback: FeedbackData] = { f: AIS.FRef; IF I.bAndWOnly THEN { f _ I.bwWindow.fref; AIS.CloseWindow[I.bwWindow]; AIS.WriteComment[f, comment]; AIS.CloseFile[f]; Feedback.PutF[feedback, end, "%g now closed", [rope[aisRope]]]; Feedback.Blink[feedback]; } ELSE { f _ I.blueWindow.fref; AIS.CloseWindow[I.blueWindow]; AIS.WriteComment[f, comment]; AIS.CloseFile[f]; f _ I.bwWindow.fref; AIS.CloseWindow[I.bwWindow]; AIS.WriteComment[f, comment]; AIS.CloseFile[f]; f _ I.redWindow.fref; AIS.CloseWindow[I.redWindow]; AIS.WriteComment[f, comment]; AIS.CloseFile[f]; f _ I.greenWindow.fref; AIS.CloseWindow[I.greenWindow]; AIS.WriteComment[f, comment]; AIS.CloseFile[f]; Feedback.PutF[feedback, end, " (red grn blu BandW) %g now closed.", [rope[aisRope]]]; Feedback.Blink[feedback]; }; }; -- end of CloseImage BoundBoxOfImage: PRIVATE PROC [image: ImagerPixelArray.PixelArray, resolution: REAL _ 72.0] RETURNS [boundBox: BoundBox] = { xExtent, yExtent: REAL; xExtent _ (image.fSize/resolution)*72.0; yExtent _ (image.sSize/resolution)*72.0; boundBox _ NEW[BoundBoxObj]; boundBox.loX _ boundBox.loY _ 0; boundBox.hiX _ xExtent; boundBox.hiY _ yExtent; }; NewBlackAndWhiteImage: PROC [imageName: Rope.ROPE, feedback: FeedbackData] RETURNS [image: ImagerPixelArray.PixelArray, success: BOOL] = { bwName: Rope.ROPE _ Rope.Concat[SVFiles.FilenameMinusExtension[imageName],".ais"]; success _ TRUE; image _ ImagerPixelArray.FromAIS[imageName !FS.Error => {success _ FALSE; CONTINUE}]; IF NOT success THEN { Feedback.Append[feedback, "Open AIS file failed", oneLiner]; Feedback.Blink[feedback]; RETURN}; }; NewColorImage: PUBLIC PROC [imageName: Rope.ROPE, feedback: FeedbackData] RETURNS [image: ImagerPixelArray.PixelArray, success: BOOL] = { redName: Rope.ROPE _ Rope.Concat[SVFiles.FilenameMinusExtension[imageName],"-red.ais"]; greenName: Rope.ROPE _ Rope.Concat[SVFiles.FilenameMinusExtension[imageName],"-grn.ais"]; blueName: Rope.ROPE _ Rope.Concat[SVFiles.FilenameMinusExtension[imageName],"-blu.ais"]; success _ TRUE; image _ ImagerPixelArray.Join3AIS[redName, greenName, blueName !FS.Error => {success _ FALSE; CONTINUE}]; IF NOT success THEN { Feedback.Append[feedback, "Open AIS file failed", oneLiner]; Feedback.Blink[feedback]; RETURN}; }; DrawAlignedBlackAndWhiteImage: PUBLIC PROC [dc: Imager.Context, imageName: Rope.ROPE, resolution: REAL, screenWRTCamera: Point2d, boundBox: BoundBox, feedback: FeedbackData] = { stepSize, xStart, yStart: REAL; samplesX, samplesY: NAT; aisFile: AIS.FRef; raster: AIS.Raster; originScreen, screenExtent: Point2d; originCameraX, originCameraY: REAL; DrawAlignedBlackAndWhiteImageAux: SAFE PROC = { Imager.TranslateT[dc, [xStart, yStart]]; DrawBlackAndWhiteImage[dc, imageName, screenExtent, resolution, feedback]; }; aisFile _ AIS.OpenFile[imageName, FALSE]; raster _ AIS.ReadRaster[aisFile]; AIS.CloseFile[aisFile]; samplesX _ raster.scanLength; samplesY _ raster.scanCount; stepSize _ 72.0/resolution; -- in screen dots per sample IF boundBox = NIL THEN { originCameraX _ 0.0; originCameraY _ 0.0; } ELSE { originCameraX _ (boundBox.hiX + boundBox.loX)/2.0; originCameraY _ (boundBox.hiY + boundBox.loY)/2.0; }; originScreen _ SVVector2d.Sub[[originCameraX, originCameraY], screenWRTCamera]; screenExtent[1] _ Real.Float[samplesX-1]*stepSize; -- screen dots screenExtent[2] _ Real.Float[samplesY-1]*stepSize; -- screen dots xStart _ originScreen[1] - screenExtent[1]/2.0; yStart _ originScreen[2] - screenExtent[2]/2.0; Imager.DoSaveAll[dc, DrawAlignedBlackAndWhiteImageAux]; }; DrawAlignedColorImage: PUBLIC PROC [dc: Imager.Context, imageName: Rope.ROPE, resolution: REAL, screenWRTCamera: Point2d, boundBox: BoundBox, feedback: FeedbackData] = { stepSize, xStart, yStart: REAL; samplesX, samplesY: NAT; aisFile: AIS.FRef; raster: AIS.Raster; originScreen, screenExtent: Point2d; originCameraX, originCameraY: REAL; redName: Rope.ROPE _ Rope.Concat[SVFiles.FilenameMinusExtension[imageName],"-red.ais"]; DrawAlignedColorImageAux: SAFE PROC = { Imager.TranslateT[dc, [xStart, yStart]]; DrawColorImage[dc, imageName, screenExtent, resolution, feedback]; }; aisFile _ AIS.OpenFile[redName, FALSE]; raster _ AIS.ReadRaster[aisFile]; AIS.CloseFile[aisFile]; samplesX _ raster.scanLength; samplesY _ raster.scanCount; stepSize _ 72.0/resolution; -- in screen dots per sample IF boundBox = NIL THEN { originCameraX _ 0.0; originCameraY _ 0.0; } ELSE { originCameraX _ (boundBox.hiX + boundBox.loX)/2.0; originCameraY _ (boundBox.hiY + boundBox.loY)/2.0; }; originScreen _ SVVector2d.Sub[[originCameraX, originCameraY], screenWRTCamera]; screenExtent[1] _ Real.Float[samplesX-1]*stepSize; -- screen dots screenExtent[2] _ Real.Float[samplesY-1]*stepSize; -- screen dots xStart _ originScreen[1] - screenExtent[1]/2.0; yStart _ originScreen[2] - screenExtent[2]/2.0; Imager.DoSaveAll[dc, DrawAlignedColorImageAux]; }; DrawBlackAndWhiteAtOrigin: PUBLIC PROC [dc: Imager.Context, imageName: Rope.ROPE, resolution: REAL _ 72.0, feedback: FeedbackData] = { stepSize: REAL; samplesX, samplesY: NAT; aisFile: AIS.FRef; raster: AIS.Raster; screenExtent: Point2d; aisFile _ AIS.OpenFile[imageName, FALSE]; raster _ AIS.ReadRaster[aisFile]; AIS.CloseFile[aisFile]; samplesX _ raster.scanLength; samplesY _ raster.scanCount; stepSize _ 72.0/resolution; -- in screen dots per sample screenExtent[1] _ Real.Float[samplesX-1]*stepSize; -- screen dots screenExtent[2] _ Real.Float[samplesY-1]*stepSize; -- screen dots DrawBlackAndWhiteImage[dc, imageName, screenExtent, resolution, feedback]; }; DrawColorImageAtOrigin: PUBLIC PROC [dc: Imager.Context, imageName: Rope.ROPE, resolution: REAL _ 72.0, feedback: FeedbackData] = { stepSize: REAL; samplesX, samplesY: NAT; aisFile: AIS.FRef; redName: Rope.ROPE _ Rope.Concat[SVFiles.FilenameMinusExtension[imageName],"-red.ais"]; raster: AIS.Raster; screenExtent: Point2d; aisFile _ AIS.OpenFile[redName, FALSE]; raster _ AIS.ReadRaster[aisFile]; AIS.CloseFile[aisFile]; samplesX _ raster.scanLength; samplesY _ raster.scanCount; stepSize _ 72.0/resolution; -- in screen dots per sample screenExtent[1] _ Real.Float[samplesX-1]*stepSize; -- screen dots screenExtent[2] _ Real.Float[samplesY-1]*stepSize; -- screen dots DrawColorImage[dc, imageName, screenExtent, resolution, feedback]; }; DrawBlackAndWhiteImage: PROC [dc: Imager.Context, imageName: Rope.ROPE, screenExtent: Point2d, resolution: REAL _ 72.0, feedback: FeedbackData] = { minX, maxX, minY, maxY: REAL; image: ImagerPixelArray.PixelArray; success: BOOL; scale: REAL; colors: Imager.ColorOperator _ ImagerColor.NewColorOperatorGrayLinear[255, 0]; DrawBlackAndWhiteImageAux: SAFE PROC = { Imager.SetSampledColor[dc, image, ImagerTransformation.Scale[scale], colors]; Imager.MaskBox[dc, [minX, minY, maxX, maxY]]; }; [image, success] _ NewBlackAndWhiteImage[imageName, feedback]; IF NOT success THEN RETURN; scale _ 72.0/resolution; minX _ 0.0; minY _ 0.0; maxX _ screenExtent[1]; maxY _ screenExtent[2]; Imager.DoSaveAll[dc, DrawBlackAndWhiteImageAux]; }; DrawColorImage: PROC [dc: Imager.Context, imageName: Rope.ROPE, screenExtent: Point2d, resolution: REAL _ 72.0, feedback: FeedbackData] = { minX, maxX, minY, maxY: REAL; image: ImagerPixelArray.PixelArray; success: BOOL; scale: REAL; colors: Imager.ColorOperator _ ImagerColor.NewColorOperatorRGB[255]; DrawColorImageAux: SAFE PROC = { Imager.SetSampledColor[dc, image, ImagerTransformation.Scale[scale], colors]; Imager.MaskBox[dc, [minX, minY, maxX, maxY]]; }; [image, success] _ NewColorImage[imageName, feedback]; IF NOT success THEN RETURN; scale _ 72.0/resolution; minX _ 0.0; minY _ 0.0; maxX _ screenExtent[1]; maxY _ screenExtent[2]; Imager.DoSaveAll[dc, DrawColorImageAux]; }; END. ΆFile: SVImageImpl.mesa Last edited by Bier on August 7, 1987 3:24:08 pm PDT Copyright c 1984 by Xerox Corporation. All rights reserved. Contents: Routines for manipulating 24 bit per pixel color images find the largest integer less than r (or equal to if r is positive). find the smallest integer greater than r (or equal to if r is negative). We are given a minimum bounding box to be filled. Calculate the number of samples in the x direction as follows: Find the number of samples which will just fit in the alloted x extent. Now add one (Since + 1 = number of samples, we actually add two). If the resulting number is odd, add 1 again. Do the same for the y direction. (Because of unimplemented features in some of the printing software, it is useful to round all ais file sizes to even numbers of pixels.) xExtent/72 = x extent in inches. (xExtent/72)*resolution = samples which will fit. Round this down to the nearest integer. Bound box is in camera coordinates DeleteFile: PROC [name: Rope.ROPE, feedback: FeedbackData] = { AIS.DeleteFile[name]; Feedback.PutF[feedback, begin, "%g... ", [rope[name]]]; }; -- end of DeleteFile Truncate the REAL value to 0-255 i is row. j is column. i = maxY maps to 0. i = minY maps to maxY-minY. j = maxX maps to maxX-minX. j = minX maps to 0. Stolen from ImagerColorImpl.mesa by Bier on March 26, 1986. IF Y>=1 THEN RETURN[1]; i is row. j is column. i = ySamples maps to 0. i = 1 maps to ySamples-1. j = xSamples-1 maps to xSamples-1. j = 0 maps to 0. xExtent, yExtent are now in units of samples. Resolution is in samples per inch. There are 72 screen dots per inch. We wish to normalize as if xmin = ymin = 0; Count how many samples there are in the x and y directions of the image. Look at the resolution (samples per inch. default is 72.0). This gives the actual size of the image, in inches. Frame it evenly around the clipBox. The clipBox is in Camera coordinates. Strategy: Find the center of the clipBox in camera coordinates. Convert to screen coordinates. Find the width of the ais image (in screen coordinates -- just use 72.0 as a magic number). Find the origin (xStart, yStart) in screen coordinates. resolution _ ReadAIS.ResolutionFromInfo[info]; -- for now, receive as argument Compute xStart and yStart. xStart _ xStart - stepSize/2.0; yStart _ yStart - stepSize/2.0; Count how many samples there are in the x and y directions of the image. Look at the resolution (default is 72.0). This gives the actual size of the image. Frame it evenly around the clipBox. resolution _ ReadAIS.ResolutionFromInfo[info]; Compute xStart and yStart. clipBox in units of screen dots, in coordinates whose origin is the lower left hand corner of the ais image. resolution is in dots per inch (72 is screen resolution). Draws the ais file of given resolution such that its lower left hand corner is at the current origin of dc. This involves several steps. 1) Find the total size of the clipBox. If no clipBox is given, use the whole image size. 2) Find the scaling factors needed to interpret the image as having the stated resolution 3) Translate appropriately 4) Draw. OPEN THE IMAGE Now find the scaling factors for the given resolution. box bounds in screen coordinates See comment for DrawBlackAndWhiteImage colors: Imager.ColorOperator _ ImagerColor.RGBLinearColorModel[255]; OPEN THE IMAGE Now find the scaling factors for the given resolution. box bounds in screen coordinates Κΐ– "cedar" style˜Iheadšœ™Iprocšœ4™4Jšœ Οmœ1™šœD™DLšžœžœžœ˜šžœžœ˜Lšœ˜Lšžœ˜—šžœ˜Lšœ˜Lšœ˜Lšœ˜Lšœ˜Lšœ˜—Lšœ˜—L˜Lš Ÿœžœžœžœžœžœ˜:šœH™HLšžœžœžœ˜šžœžœ˜Lšœ˜Lšœ˜Lšžœ˜—šžœ˜Lšœ˜Lšœ˜Lšœ ˜ Lšœ˜—Lšœ˜—L˜š œŸ œžœžœ6žœžœ&žŸ˜‹LšŸœϋ™όLšœ.žœ˜4Lšœ9˜9Lšœ9˜9Lšœ)˜)Lšœ)˜)Lšœ.˜.Lšœ.˜.Lšžœžœžœ)˜MLšžœžœžœ)˜MLšœ˜—L˜Lšœ˜šŸ œžœžœžœ žœ6žœžœŸœ-žœ˜ΞLšœ#™#L™Lšœžœ˜ Lšœžœ˜L˜Lšœžœ ˜L˜Lšœh˜hL˜Lšœ žœžœF˜VL˜šžœ žœ˜Lšœžœ˜Lšœ$˜$Lšœ žœ˜LšœG˜GLšœ˜—šžœ˜LšœžœD˜VLšœžœD˜XLšœžœD˜WLšœ žœ ˜L˜Lšœžœ˜Lšœ˜Lšœ$˜$Lšœžœ˜ Lšœ&˜&Lšœžœ˜"Lšœ%˜%Lšœžœ˜!Lšœ#˜#Lšœ žœ˜LšœJ˜JLšœ˜—LšœΟc˜L˜—šŸ œžœ žœ™>Lšžœ™Lšœ7™7Lšœ™—L˜š Ÿœžœ žœžœžœ˜6Lšœ ™ šžœž˜Lšœžœ˜ Lšœ˜Lšžœ˜—Lšœ˜—L˜šŸ œžœžœ(žœ˜\LšœH™HLšœ0™0Lšœ)žœ˜2Lšœžœ˜"Lšœ1˜1Lšœ2žœ ˜ALšœ˜Lšœ!˜!Lšœ˜Lšœ)˜)Lšžœ6˜9Lšžœ:˜=Lšžœ8˜;Lšžœ;˜>Lšœ˜—L˜š Ÿ œžœžœ žœžœžœ˜PLšœžœ˜Lšœ˜Lšœ˜Lšœ˜Lšœ˜Lšœ˜L˜L˜—codeš Ÿœžœ žœžœžœ˜7M™;Mšœžœ˜Mšžœžœžœ˜Mšžœžœžœ™Mšžœ˜ M˜M˜—š Ÿœžœžœžœžœ$žœ˜ZLšœJ™JLšœ4™4šžœ žœ˜Lšœžœ˜Lšœ žœ˜Lšœ2žœ ˜ALšœ)˜)Lšžœ žœ(˜9L˜—šžœ˜Lšœ)žœ˜2Lšœžœ˜"Lšœ1˜1Lšœ2žœ ˜ALšœ˜Lšœ!˜!Lšœ˜Lšœ)˜)Lšžœ žœ#˜4Lšžœ žœ'˜8Lšžœ žœ%˜6Lšžœ žœ(˜9L˜—Lšœ˜—L˜š Ÿ œžœžœŸœžœžœ˜fLšœžœ˜ šžœ žœ˜Lšœ˜Lšžœ˜Jšžœ˜Jšžœ˜Lšœ?˜?Lšœ˜L˜—šžœ˜Lšœ˜Lšžœ˜Jšžœ˜Jšžœ˜Lšœ˜Lšžœ˜Jšžœ˜Jšžœ˜Lšœ˜Lšžœ˜Jšžœ˜Jšžœ˜Lšœ˜Lšžœ˜Jšžœ˜Jšžœ˜LšœU˜ULšœ˜L˜—Lšœ ˜—L˜š Ÿœžœžœ2žœ žœ˜|Lšœžœ˜LšœQ™QLšœO™OLšœ(˜(Lšœ(˜(Lšœ žœ˜Lšœ ˜ Lšœ/˜/Lšœ˜—L˜š Ÿœžœžœžœ/žœ˜ŠLšœ žœA˜RLšœ žœ˜šœ*˜*Lšœžœžœžœ˜*—šžœžœ žœ˜Lšœ<˜˜>Lšœžœžœžœ˜*—šžœžœ žœ˜Lšœ<˜˜>šžœžœ žœžœ˜Lšœ6™6—šœ˜Lšœ ™ —Lšœ ˜ Lšœ ˜ Lšœ˜Lšœ˜Lšœ0˜0Lšœ˜L˜—L˜L˜šŸœžœ&žœ%žœ$˜‹Lšœ&™&Lšœžœ˜Lšœ#˜#Lšœ žœ˜Lšœžœ˜ LšœD™DLšœD˜DšŸœž œ˜ LšœM˜MLšœ-˜-L˜Lšžœžœž™—Lšœ6˜6šžœžœ žœžœ˜Lšœ6™6—šœ˜Lšœ ™ —Lšœ ˜ Lšœ ˜ Lšœ˜Lšœ˜Lšœ(˜(Lšœ˜—L˜L˜Lšžœ˜—…—3tPκ