DIRECTORY BufferedRefresh, BufferedRefreshTypes, BufferedRefreshPort, CodeTimer, Imager, ImagerBackdoor, ImagerBitmapContext, ImagerDitherContext, ImagerPixel, ImagerSample, ImagerTransformation, Basics, Real; BufferedRefreshImpl: CEDAR PROGRAM IMPORTS BufferedRefreshPort, CodeTimer, Imager, ImagerBackdoor, ImagerBitmapContext, ImagerDitherContext, ImagerPixel, ImagerSample, ImagerTransformation, Basics, Real EXPORTS BufferedRefresh = BEGIN OPEN BufferedRefresh, BufferedRefreshTypes; CreateSandwich: PUBLIC PROC [layers: LIST OF Layer] RETURNS [Sandwich] = { sandwich: Sandwich ~ NEW[SandwichObj]; tail: LIST OF LayerData ¬ NIL; FOR list: LIST OF Layer ¬ layers, list.rest UNTIL list = NIL DO layerData: LayerData ~ NEW[LayerDataObj ¬ [name: list.first.name, refreshProc: list.first.refreshProc, wantsMap: list.first.backingMap, hasMap: FALSE, drawBkgnd: list.first.drawBkgnd]]; prev: LIST OF LayerData ~ tail; tail ¬ CONS[layerData, NIL]; IF prev=NIL THEN sandwich.layers ¬ tail ELSE prev.rest ¬ tail; ENDLOOP; RETURN[sandwich]; }; FitSandwichToScreen: PUBLIC PROC [sandwich: Sandwich, cw, ch: INTEGER, screen: Imager.Context, cx, cy: INTEGER ¬ 0] = { class: ATOM ~ Imager.GetClass[screen]; IF sandwich.class=class AND sandwich.cw=cw AND sandwich.ch=ch THEN RETURN; sandwich.cw ¬ cw; sandwich.ch ¬ ch; sandwich.cx ¬ cx; sandwich.cy ¬ cy; sandwich.class ¬ class; sandwich.viewerToClient ¬ ImagerTransformation.Scale[1.0]; sandwich.clientToViewer ¬ ImagerTransformation.Scale[1.0]; FOR list: LIST OF LayerData ¬ sandwich.layers, list.rest UNTIL list = NIL DO layer: LayerData ~ list.first; bottomLayer: BOOL ~ (list=sandwich.layers); IF layer.hasMap THEN { layer.backingMap ¬ NIL; layer.backingContext ¬ NIL; layer.hasMap ¬ FALSE; }; IF layer.wantsMap THEN { box: ImagerSample.Box ~ [min: [0, 0], max: [ch, cw]]; type: {none, bitmap, dither, cg6} ¬ none; IF bottomLayer THEN SELECT TRUE FROM class=$Bitmap => type ¬ bitmap; Basics.IsBound[LOOPHOLE[ImagerDitherContext.Create]] AND class=ImagerDitherContext.classCode => type ¬ dither; class=$CG6 => type ¬ cg6; -- instead of class=ImagerCG6Context.classCode so we can still source-share ENDCASE => type ¬ none ELSE type ¬ bitmap; -- all layers but the bottom are 1-bit masks SELECT type FROM bitmap => { layer.backingMap ¬ ImagerSample.NewSampleMap[box]; layer.backingContext ¬ ImagerBitmapContext.Create[ deviceSpaceSize: box.max, scanMode: [down, right], surfaceUnitsPerInch: [72.0, 72.0], pixelUnits: TRUE, fontCacheName: ImagerBitmapContext.classCode]; ImagerBitmapContext.SetBitmap[layer.backingContext, layer.backingMap]; }; dither => { screenMap: SampleMap ~ ImagerDitherContext.GetSampleMap[screen]; bps: ImagerSample.BitsPerSample ~ ImagerSample.GetBitsPerSample[screenMap]; layer.backingMap ¬ ImagerSample.NewSampleMap[box, bps]; layer.backingContext ¬ ImagerDitherContext.Create[box.max, [down, right], [72.0, 72.0], TRUE, ImagerDitherContext.classCode]; BufferedRefreshPort.SetDitherMapFromScreen[layer.backingContext, screen]; ImagerDitherContext.SetSampleMap[layer.backingContext, layer.backingMap]; }; cg6 => { bps: ImagerSample.BitsPerSample ~ 8; layer.backingMap ¬ ImagerSample.NewSampleMap[box, bps]; layer.backingContext ¬ BufferedRefreshPort.CreateCG6Context[box.max, TRUE, $CG6]; BufferedRefreshPort.SetCG6DitherMapFromScreen[layer.backingContext, screen]; BufferedRefreshPort.SetCG6SampleMap[layer.backingContext, layer.backingMap]; }; ENDCASE; layer.hasMap ¬ (type#none); layer.mapOK ¬ FALSE; }; ENDLOOP; }; bigRect: Imager.Rectangle ~ [-Real.LargestNumber, -Real.LargestNumber, Real.LargestNumber, Real.LargestNumber]; BigButNotTooBig: REAL = 1.0e+18; bigButNotTooBigRect: Imager.Rectangle = [-BigButNotTooBig, -BigButNotTooBig, 2*BigButNotTooBig, 2*BigButNotTooBig]; DrawSandwichInBoxes: PUBLIC PROC [sandwich: Sandwich, screen: Imager.Context, clientToViewer, viewerToClient: Imager.Transformation, clientData: REF, bkgndColor: Imager.Color, ignoreBackingMap: BOOL ¬ FALSE, noBuffer: BOOL ¬ FALSE, changeRects: LIST OF Imager.Rectangle] = { drawLayers: PROC ~ { FOR list: LIST OF LayerData ¬ sandwich.layers, list.rest UNTIL list = NIL DO layer: LayerData ~ list.first; bottomLayer: BOOL ~ (list=sandwich.layers); IF ignoreBackingMap THEN { IF screen#NIL THEN { CodeTimer.StartInt[$DrawIgnoreMap2, $Gargoyle]; [] ¬ DrawLayer[sandwich, screen, layer.refreshProc, layer.drawBkgnd, FALSE, bkgndColor, clientData, bottomLayer, rect]; CodeTimer.StopInt[$DrawIgnoreMap2, $Gargoyle]; }; } ELSE IF NOT layer.hasMap THEN { IF screen#NIL THEN { CodeTimer.StartInt[$DrawNoMap2, $Gargoyle]; [] ¬ DrawLayer[sandwich, screen, layer.refreshProc, layer.drawBkgnd, FALSE, bkgndColor, clientData, bottomLayer, rect]; CodeTimer.StopInt[$DrawNoMap2, $Gargoyle]; }; } ELSE { -- use backing map IF NOT layer.mapOK THEN { UpdateMap2: PROC = { CodeTimer.StartInt[$DrawBackingMap2, $Gargoyle]; Imager.TranslateT[layer.backingContext, [-sandwich.cx, -sandwich.cy]]; layer.drawnOn ¬ DrawLayer[sandwich, layer.backingContext, layer.refreshProc, layer.drawBkgnd, TRUE, bkgndColor, clientData, TRUE, bigRect]; -- use bigRect (so the whole layer is recomputed), because if a layer is not OK, it may have been marked that way long ago before the current rect was computed. To be safe, we will have to transfer the full screen in DoWithBuffer below as well. CodeTimer.StopInt[$DrawBackingMap2, $Gargoyle]; layer.mapOK ¬ TRUE; }; Imager.DoSave[layer.backingContext, UpdateMap2]; }; IF screen#NIL THEN IF bottomLayer THEN { CodeTimer.StartInt[$TransferLayer2, $Gargoyle]; Imager.DrawPixels[ context: screen, pixelMap: ImagerPixel.MakePixelMap[layer.backingMap], colorOperator: ImagerBackdoor.GetBufferColorOperator[screen], position: [0, sandwich.ch] ]; CodeTimer.StopInt[$TransferLayer2, $Gargoyle]; } ELSE { MaskLayer: PROC = { Imager.SetColor[screen, Imager.black]; Imager.MaskBitmap[screen, layer.backingMap, [sandwich.ch, 0]]; }; CodeTimer.StartInt[$MaskLayer2, $Gargoyle]; IF layer.drawnOn THEN Imager.DoSave[screen, MaskLayer]; CodeTimer.StopInt[$MaskLayer2, $Gargoyle]; }; }; ENDLOOP; }; x, y, w, h: INTEGER; rect: Imager.Rectangle; FOR list: LIST OF Imager.Rectangle ¬ changeRects, list.rest UNTIL list = NIL DO rect ¬ list.first; IF rect.x = -Real.LargestNumber THEN { x ¬ sandwich.cx; y ¬ sandwich.cy; w ¬ sandwich.cw; h ¬ sandwich.ch; } ELSE { thisRect: Imager.Rectangle ¬ ImagerTransformation.TransformRectangle[clientToViewer, rect]; x ¬ Real.Floor[thisRect.x]; y ¬ Real.Floor[thisRect.y]; w ¬ Real.Ceiling[thisRect.x + thisRect.w]-x; h ¬ Real.Ceiling[thisRect.y + thisRect.h]-y; }; sandwich.clientToViewer ¬ clientToViewer; sandwich.viewerToClient ¬ viewerToClient; IF screen=NIL THEN { CodeTimer.StartInt[$NILScreen2, $Gargoyle]; drawLayers[]; -- just update backing contexts CodeTimer.StopInt[$NILScreen2, $Gargoyle]; } ELSE { IF noBuffer THEN Imager.ConcatT[screen, viewerToClient] ELSE ImagerBackdoor.SetT[screen, idX ! Imager.Error => { -- get rid of Biscrollers transformation Imager.ConcatT[screen, viewerToClient]; -- old way if SetT not implemented CONTINUE; };]; IF noBuffer THEN { CodeTimer.StartInt[$NoBuffer2, $Gargoyle]; Imager.DoSaveAll[context: screen, action: drawLayers]; CodeTimer.StopInt[$NoBuffer2, $Gargoyle]; } ELSE { CodeTimer.StartInt[$DoWithBuffer2, $Gargoyle]; Imager.DoWithBuffer[context: screen, action: drawLayers, x: x, y: y, w: w, h: h, backgroundColor: bkgndColor]; CodeTimer.StopInt[$DoWithBuffer2, $Gargoyle]; }; }; ENDLOOP; }; DrawSandwich: PUBLIC PROC [sandwich: Sandwich, screen: Imager.Context, clientToViewer, viewerToClient: Imager.Transformation, clientData: REF, bkgndColor: Imager.Color, ignoreBackingMap: BOOL ¬ FALSE, noBuffer: BOOL ¬ FALSE, changeRect: Imager.Rectangle ¬ [-Real.LargestNumber, -Real.LargestNumber, Real.LargestNumber, Real.LargestNumber]] = { drawLayers: PROC ~ { FOR list: LIST OF LayerData ¬ sandwich.layers, list.rest UNTIL list = NIL DO layer: LayerData ~ list.first; bottomLayer: BOOL ~ (list=sandwich.layers); IF ignoreBackingMap THEN { IF screen#NIL THEN { CodeTimer.StartInt[$DrawIgnoreMap, $Gargoyle]; [] ¬ DrawLayer[sandwich, screen, layer.refreshProc, layer.drawBkgnd, FALSE, bkgndColor, clientData, bottomLayer, changeRect]; CodeTimer.StopInt[$DrawIgnoreMap, $Gargoyle]; }; } ELSE IF NOT layer.hasMap THEN { IF screen#NIL THEN { CodeTimer.StartInt[$DrawNoMap, $Gargoyle]; [] ¬ DrawLayer[sandwich, screen, layer.refreshProc, layer.drawBkgnd, FALSE, bkgndColor, clientData, bottomLayer, changeRect]; CodeTimer.StopInt[$DrawNoMap, $Gargoyle]; }; } ELSE { -- use backing map IF NOT layer.mapOK THEN { UpdateMap: PROC = { CodeTimer.StartInt[$DrawBackingMap, $Gargoyle]; Imager.TranslateT[layer.backingContext, [-sandwich.cx, -sandwich.cy]]; layer.drawnOn ¬ DrawLayer[sandwich, layer.backingContext, layer.refreshProc, layer.drawBkgnd, TRUE, bkgndColor, clientData, TRUE, bigRect]; -- use bigRect (so the whole layer is recomputed), because if a layer is not OK, it may have been marked that way long ago before the current changeRect was computed. To be safe, we will have to transfer the full screen in DoWithBuffer below as well. CodeTimer.StopInt[$DrawBackingMap, $Gargoyle]; layer.mapOK ¬ TRUE; }; Imager.DoSave[layer.backingContext, UpdateMap]; }; IF screen#NIL THEN IF bottomLayer THEN { CodeTimer.StartInt[$TransferLayer2, $Gargoyle]; Imager.DrawPixels[ context: screen, pixelMap: ImagerPixel.MakePixelMap[layer.backingMap], colorOperator: ImagerBackdoor.GetBufferColorOperator[screen], position: [sandwich.cx, sandwich.ch+sandwich.cy] ]; CodeTimer.StopInt[$TransferLayer2, $Gargoyle]; } ELSE { MaskLayer: PROC = { Imager.SetColor[screen, Imager.black]; Imager.MaskBitmap[screen, layer.backingMap, [sandwich.ch, 0]]; }; CodeTimer.StartInt[$MaskLayer, $Gargoyle]; IF layer.drawnOn THEN Imager.DoSave[screen, MaskLayer]; CodeTimer.StopInt[$MaskLayer, $Gargoyle]; }; }; ENDLOOP; }; x, y, w, h: INTEGER; IF changeRect.x = -Real.LargestNumber THEN { x ¬ sandwich.cx; y ¬ sandwich.cy; w ¬ sandwich.cw; h ¬ sandwich.ch; } ELSE { thisRect: Imager.Rectangle ¬ ImagerTransformation.TransformRectangle[clientToViewer, changeRect]; x ¬ Real.Floor[thisRect.x]; y ¬ Real.Floor[thisRect.y]; w ¬ Real.Ceiling[thisRect.x + thisRect.w]-x; h ¬ Real.Ceiling[thisRect.y + thisRect.h]-y; }; sandwich.clientToViewer ¬ clientToViewer; sandwich.viewerToClient ¬ viewerToClient; IF screen=NIL THEN { CodeTimer.StartInt[$NILScreen, $Gargoyle]; drawLayers[]; -- just update backing contexts CodeTimer.StopInt[$NILScreen, $Gargoyle]; } ELSE { IF noBuffer THEN Imager.ConcatT[screen, viewerToClient] ELSE ImagerBackdoor.SetT[screen, idX ! Imager.Error => { -- get rid of Biscrollers transformation Imager.ConcatT[screen, viewerToClient]; -- old way if SetT not implemented CONTINUE; };]; IF noBuffer THEN { CodeTimer.StartInt[$NoBuffer, $Gargoyle]; Imager.DoSaveAll[context: screen, action: drawLayers]; CodeTimer.StopInt[$NoBuffer, $Gargoyle]; } ELSE { CodeTimer.StartInt[$DoWithBuffer, $Gargoyle]; Imager.DoWithBuffer[context: screen, action: drawLayers, x: x, y: y, w: w, h: h, backgroundColor: bkgndColor]; CodeTimer.StopInt[$DoWithBuffer, $Gargoyle]; } }; }; idX: ImagerTransformation.Transformation = ImagerTransformation.Scale[1.0]; debug: BOOL ¬ FALSE; SetDebug: PROC [t: INT] = {debug ¬ t=1;}; pageBox: Imager.Rectangle ~ [ 0, 0, 8.5*72.0, 11.0*72.0]; DrawLayer: PROC [sandwich: Sandwich, context: Imager.Context, proc: RefreshProc, drawBkgnd: BOOL, mapUpdate: BOOL, bkgndColor: Imager.Color, clientData: REF ANY ¬ NIL, clear: BOOL ¬ FALSE, changeRect: Imager.Rectangle ¬ [-Real.LargestNumber, -Real.LargestNumber, Real.LargestNumber, Real.LargestNumber]] RETURNS [drewSomething: BOOL ¬ TRUE] = { inner: PROC ~ { bounds: Imager.Rectangle ¬ [0.0, 0.0, 0.0, 0.0]; Imager.ConcatT[context, sandwich.clientToViewer]; bounds ¬ ImagerBackdoor.GetBounds[context ! Imager.Error => CONTINUE]; IF bounds.w=0.0 OR bounds.h=0.0 THEN { -- unknown bounds. Unlikely case. IF drawBkgnd THEN { IF mapUpdate OR bkgndColor#NIL THEN { IF bkgndColor=NIL THEN Imager.SetColor[context, Imager.white] ELSE Imager.SetColor[context, bkgndColor]; Imager.MaskRectangle[context, IF changeRect.w # Real.LargestNumber THEN changeRect ELSE pageBox]; }; } ELSE IF clear THEN { Imager.SetColor[context, Imager.white]; Imager.MaskRectangle[context, IF changeRect.w # Real.LargestNumber THEN changeRect ELSE pageBox]; }; Imager.SetColor[context, Imager.black]; -- in case the client forgets drewSomething ¬ proc[context, IF changeRect.w # Real.LargestNumber THEN changeRect ELSE bigButNotTooBigRect, clientData]; } ELSE { -- known reasonable bounds. Likely case. IF drawBkgnd THEN { CodeTimer.StartInt[$LayerBkgnd, $Gargoyle]; IF mapUpdate OR bkgndColor#NIL THEN { IF bkgndColor=NIL THEN Imager.SetColor[context, Imager.white] ELSE Imager.SetColor[context, bkgndColor]; Imager.MaskRectangle[context, IF changeRect.w # Real.LargestNumber THEN changeRect ELSE bounds]; }; CodeTimer.StopInt[$LayerBkgnd, $Gargoyle]; } ELSE IF clear THEN { CodeTimer.StartInt[$LayerBkgnd, $Gargoyle]; Imager.SetColor[context, Imager.white]; Imager.MaskRectangle[context, IF changeRect.w # Real.LargestNumber THEN changeRect ELSE bounds]; CodeTimer.StopInt[$LayerBkgnd, $Gargoyle]; }; Imager.SetColor[context, Imager.black]; -- in case the client forgets drewSomething ¬ proc[context, IF changeRect.w # Real.LargestNumber THEN changeRect ELSE bounds, clientData]; }; }; Imager.DoSaveAll[context, inner]; }; FindLayer: PROC [sandwich: Sandwich, layerName: ATOM] RETURNS [layer: LayerData] = { FOR list: LIST OF LayerData ¬ sandwich.layers, list.rest UNTIL list = NIL DO IF list.first.name = layerName THEN RETURN[list.first]; ENDLOOP; ERROR; }; SetLayerOK: PUBLIC PROC [sandwich: Sandwich, layerName: ATOM, ok: BOOL] = { layer: LayerData ~ FindLayer[sandwich, layerName]; layer.mapOK ¬ ok; }; GetLayerOK: PUBLIC PROC [sandwich: Sandwich, layerName: ATOM] RETURNS [ok: BOOL] = { layer: LayerData ~ FindLayer[sandwich, layerName]; ok ¬ layer.mapOK; }; RepairLayer: PUBLIC PROC [sandwich: Sandwich, layerName: ATOM, proc: RefreshProc, bkgndColor: Imager.Color, clientData: REF ANY ¬ NIL, clear: BOOL ¬ FALSE] = { layer: LayerData ~ FindLayer[sandwich, layerName]; IF layer.hasMap AND (clear OR layer.mapOK) THEN { DoRepairLayer: PROC = { Imager.TranslateT[layer.backingContext, [-sandwich.cx, -sandwich.cy]]; layer.drawnOn ¬ DrawLayer[sandwich, layer.backingContext, proc, FALSE, TRUE, bkgndColor, clientData, clear]; layer.mapOK ¬ TRUE; }; Imager.DoSave[layer.backingContext, DoRepairLayer]; }; }; SameSizeMaps: PROC [a, b: SampleMap] RETURNS [BOOL] = { RETURN[ImagerSample.GetBox[a]=ImagerSample.GetBox[b]]; }; SaveLayer: PUBLIC PROC [sandwich: Sandwich, layerName: ATOM] = { layer: LayerData ~ FindLayer[sandwich, layerName]; IF NOT layer.hasMap THEN RETURN; IF layer.savedMap#NIL AND SameSizeMaps[layer.savedMap, layer.backingMap] THEN { ImagerSample.Transfer[dst: layer.savedMap, src: layer.backingMap]; } ELSE { layer.savedMap ¬ ImagerSample.Copy[layer.backingMap]; }; }; RestoreLayer: PUBLIC PROC [sandwich: Sandwich, layerName: ATOM] = { layer: LayerData ~ FindLayer[sandwich, layerName]; IF NOT layer.hasMap THEN RETURN; IF layer.savedMap#NIL AND SameSizeMaps[layer.savedMap, layer.backingMap] THEN { IF Imager.GetClass[layer.backingContext]=ImagerBitmapContext.classCode THEN { temp: Imager.SampleMap ~ layer.backingMap; layer.backingMap ¬ layer.savedMap; layer.savedMap ¬ temp; ImagerBitmapContext.SetBitmap[layer.backingContext, layer.backingMap]; } ELSE ImagerSample.Transfer[dst: layer.backingMap, src: layer.savedMap]; }; }; END. fBufferedRefreshImpl.mesa Copyright Ó 1986, 1987, 1988, 1989, 1990, 1992 by Xerox Corporation. All rights reserved. Contents: Builds up an abstraction of transparent layers onto which shapes can be drawn. Each layer may have a backing pixel map, in which case it need not be redrawn when other layers change. This scheme is used by Gargoyle and Solidviews. Pier, June 25, 1993 11:37 am PDT Bier, July 13, 1993 4:35 pm PDT Doug Wyatt, September 15, 1989 3:49:32 pm PDT Michael Plass, March 25, 1992 11:51 am PST [Artwork node; type 'ArtworkInterpress on' to command tool] Layers should be specified in back to front order. Tells the sandwich how big its buffers need to be. cx and cy specify the position of the lower left hand corner of the buffers. Construct the layer backing maps. keyword syntax is used here for compatibility with the Cedar7.0 version of ImagerBitmapContext.Create The color map is synchronized in case we are running on X or some other platform that can change the color map. Draw each of the layers following DrawPixels call courtesy MP. June 25, 1993. Compute x, y, w, h, and rect, which are free variables in drawLayers. IF ignoreBackingMap AND noBuffer THEN Imager.ConcatT[screen, viewerToClient] So MMM nested editors will work. For these cases, viewerToClient means editorToClient Including a backgroundColor argument speeds up the call by nearly a factor of 2 since the command doesn't need to read the existing pixels. Draw each of the layers following DrawPixels call courtesy MP. June 25, 1993. IF ignoreBackingMap AND noBuffer THEN Imager.ConcatT[screen, viewerToClient] So MMM nested editors will work. For these cases, viewerToClient means editorToClient Including a backgroundColor argument speeds up the call by nearly a factor of 2 since the command doesn't need to read the existing pixels. can raise Imager.Error or return 0 bounds, meaning bounds are unknown if bounds are unknown, use changeRect to draw. If this is a background layer: If we're updating a map here than clear to the background color (or white if none). Otherwise, clear only if the background color is non-NIL. For other layers: clear to white if asked. Imager.ClipRectangle[context, bounds]; -- UNNECESSARY and BUGGY Below, drawBkgnd is FALSE to avoid unintentional clearing of the full background layer If the named layer is backed with a bitmap, that bitmap will be copied for later use (see RestoreLayer). If the named layer is backed with a bitmap, then that bitmap will be replaced by the bitmap that most recently was saved (see SaveLayer). This will only happen if the saved bitmap and the current bitmap are of the same size. Ê¢•NewlineDelimiter –(cedarcode) style˜code™Kšœ ÏeœO™ZK™óK™ K™K™-K™*K™—šÏk ˜ Idefault˜Ç—K˜šÏnœžœž˜"Lšžœ ˜§Kšžœ˜—Kšžœžœ'˜1I artworkFigure• InterpressInterpress/Xerox/3.0  f j k j¡¥“ļ= ¤ ¨  ‡Ä8¿:¡£ r jnÄâ­+ ¢ ¨¡¡¨ˆˆˆ£¡ˆ¡¡ÅXeroxÅResearchÅ RGBLinear£¡¡¦ ç • ” ç¡•¡”­“Ä!ÁÄÿ+™Äe2ŽÄq5Äí:ï—ÄŽ'\ŽÄ!ÁÄÿ+—¡¡¡¡™¢¯“¡¡¨¢·“¢°“Ä!ÁÄÿ+™Äe2ŽÄq5Äí:ï—ÄŽ'\ŽÄ!ÁÄÿ+—¡¸ˆˆˆ£¡ ” ç¢•¢”­“Ä!ÁÄW+™Äe2ŽÄq5Äô²ï—ÄŽ'\ŽÄ!ÁÄW+—¡¡¡¡™¢¯“¡¡¨¢·“¢°“Ä!ÁÄW+™Äe2ŽÄq5Äô²ï—ÄŽ'\ŽÄ!ÁÄW+—¡¸ˆˆˆ£¡ ” ç£•£”­“Ä!ÁÄ ¯+™Äe2ŽÄq5Äü*ï—ÄŽ'\ŽÄ!ÁÄ ¯+—¡¡¡¡™¢¯“¡¡¨¢·“¢°“Ä!ÁÄ ¯+™Äe2ŽÄq5Äü*ï—ÄŽ'\ŽÄ!ÁÄ ¯+—¡¸ˆˆˆ£¡ ” ç¤•¤”­“Ä È×Ä"+™Äe2ŽÄq5Ä¢ï—ÄŽ'\ŽÄ È×Ä"+—¡¡¡¡™¢¯“¡¡¨¢·“¢°“Ä È×Ä"+™Äe2ŽÄq5Ä¢ï—ÄŽ'\ŽÄ È×Ä"+—¡¸¢¯“¡¡¨¢·“¢°“Ä!_ÄDk™Ä@…:Ä—¢¥¢¡ Ÿ¡º¢¯“¡¡¨¢·“¢°“ÄViaÄ~ºm™Ä!_ÄDk—˜”””£¡ ” ç¥•¥”­“ÄViaÄRu@™ÄLnGÄ_ÐA—ÄQ=ŽÄSdIÄRu@—ÄViaŽ¡¡¡¡™¢¯“¡¡¨¢·“¢°“ÄViaÄRu@™ÄLnGÄ_ÐA—ÄQ=ŽÄSdIÄRu@—ÄViaŽ¡¸ˆˆˆ£¡ ” ç¦•¦”­“ÄViaÄRu@™Ä¬ÌÄSdIŽÄRu@ÄViaŽ¡¡¡¡™¢¯“¡¡¨¢·“¢°“ÄViaÄRu@™Ä¬ÌÄSdIŽÄRu@ÄViaŽ¡¸ˆˆˆ£¡ ” ç§•§”­“ÄViaĬ̙Ä~ºmÄSdIŽÄ¬ÌÄViaŽ¡¡¡¡™¢¯“¡¡¨¢·“¢°“ÄViaĬ̙Ä~ºmÄSdIŽÄ¬ÌÄViaŽ¡¸ˆˆˆ£¡ ” ç¨•¨”­“ÄA¡7ă³—™Än§kŽÄ@…:Ä—Ä'dŽÄA¡7ă³——¡¡¡¡™¢¯“¡¡¨¢·“¢°“ÄA¡7ă³—™Än§kŽÄ@…:Ä—Ä'dŽÄA¡7ă³——¡¸¢¯“¡¡¨¢·“¢°“ÄViaÄ~ºm™Än§kă³——˜¢¯“¡¡¨¢·“¢°“ÄQ=ÄDk™Ä'dÄ—˜¢¯“¡¡¨¢·“¢°“ÄSdIÄ~ºm™ÄA¡7ă³——˜¢¯“¡¡¨¢·“¢°“Ä6õ/ÄK1™Ä6õ/ÄiC@ÄU*CÄz¿õÄO¡:Ä¿R¡’˜¢¯“¡¡¨¢·“¢°“Ä6õ/ÄK1™Ä—Õ„ÄS³6—Ä6õ/ÄK1—Ä& ÄS³6—˜ r j® ¤Äe§HÄÕ׋ ¢ ¥ ¨ÅxeroxÅ tiogafontsÅ Helvetica14£¡ “Ä ¤ ”©•© —¡¡¨  Š¡²“ÁScreen– k é r j® ¤Ä?÷eÄms† ¢ ¥ ¨ÅxeroxÅ tiogafontsÅ Helvetica14£¡ “Ä ¤ ”©•© —¡¡¨  Š¡²“ÁClient Coordinates– k é¢¯“¡¡¨¢·“¢°“Äʬ©Ä 4#™Äʬ©ÄEECÄ^úIġĭĺ&Äntu¡’˜¢¯“¡¡¨¢·“¢°“Äʬ©Ä 4#™Ä7x/ÄØ—Äʬ©Ä 4#—ÄTEÄØ—˜ r j® ¤Äb·Bħµ ¢ ¥ ¨ÅxeroxÅ tiogafontsÅ Helvetica14£¡ “Ä ¤ ”©•© —¡¡¨  Š¡²“ÁViewport– k é¢¯“¡¡¨¢·“¢°“þò™ÄÂ#5ı-’ÄO9Ägf¡“˜¢¯“¡¡¨¢·“¢°“Ä<¤EÄ«ª·™Ä:{TÄ*=Äaá}Ä.™$¡“˜¢¯“¡¡¨¢·“¢°“ÄO9Ägf™ÄıÄÏ/È—ÄO9Ägf—Ä{WÄÝ Ý—˜¢¯“¡¡¨¢·“¢°“Äaá}Ä.™$™ÄœÔÉÄ…?Ç—Äaá}Ä.™$—ÄP)jÄUB—˜¢¯“¡¡¨¢·“¢°“ÄViaÄ`ÉM™ÄSdIŽ˜¢¯“¡¡¨¢·“¢°“ÄViaÄE™ÄSdIŽ˜¢¯“¡¡¨¢·“¢°“ÄQ=ÄÒÇ™Ä_ÐAÄSdIÄRu@—Ĭ̘¢¯“¡¡¨¢·“¢°“ÄViaÄE™ÄSdIŽ˜¢¯“¡¡¨¢·“¢°“ÄSdIĬ̙Ä~ºmÄQ=ÄDk—Ä7 '˜ r j® ¤%Ä_ ¢ ¥ ¨ÅxeroxÅ tiogafontsÅ Helvetica14£¡ “Ä ¤ ”©•© —¡¡¨  Š¡²“ÁviewerToClient– k é r j® ¤Ö¾ ¢ ¥ ¨ÅxeroxÅ tiogafontsÅ Helvetica14£¡ “Ä ¤ ”©•© —¡¡¨  Š¡²“ÁclientToViewer– k é¢¯“¡¡¨¢·“¢°“e™-Ž˜¢¯“¡¡¨¢·“¢°“e™Ä\’ïÄÆ™ú—e—Ä\’ïĺ+ú—˜ r j® ¤5a ¢ ¥ ¨ÅxeroxÅ tiogafontsÅ Helvetica14£¡ “Ä ¤ ”©•© —¡¡¨  Š¡²“ÁClient Sandwich– k é¢¯“¡¡¨¢·“¢°“ÄMãïÄMãï™Äiå¢¯“¡¡¨¢·“¢°“ÄMãïÄMãï™  —ÄMãïÄMãï— Äºˆ—˜ r j® ¤)Ľ ¢ ¥ ¨ÅxeroxÅ tiogafontsÅ Helvetica14£¡ “Ä ¤ ”©•© —¡¡¨  Š¡²“ÁSandwich Bitmaps– k é¢¯“¡¡¨¢·“¢°“ÄSdIÄ`ÉM™ÄQ=ÄU;—˜¢¯“¡¡¨¢·“¢°“ÄSdIĬ̙ÄQ=ÄÒÇ—˜¢¯“¡¡¨¢·“¢°“ÄSdIÄE™ÄQ=ÄI 5—˜ k é k g•Artwork Interpress•Bounds90.0 mm xmin 0.0 mm ymin 171.8028 mm xmax 88.3587 mm ymax –G91.18092 mm topLeading 91.18092 mm topIndent 1.411111 mm bottomLeading šŸ=™=unitš Ÿœžœžœ žœžœžœ˜JK™2Kšœžœ˜&Kšœžœžœ žœ˜š žœžœžœžœžœž˜?Kšœžœvžœ$˜¹Kšœžœžœ˜Kšœžœ žœ˜Kšžœžœžœžœ˜>Kšžœ˜—Kšžœ ˜K˜K˜—š Ÿœžœžœžœ"žœ ˜wL™€Kšœžœ˜&Kš žœžœžœžœžœ˜JK˜K˜K˜K˜K˜NšÏb!™!K˜:K˜:š žœžœžœ(žœžœž˜LK˜Kšœ žœ˜+šžœžœ˜Kšœžœ˜Kšœžœ˜Kšœžœ˜K˜—šžœžœ˜K• CharPropsjPostfix0.83333 1 0.7 textColorPostfix0.83333 1 0.7 textColorPostfix0.83333 1 0.7 textColor˜5K˜)š žœ žœžœžœž˜$K˜Kšœžœžœ6˜nKšœÏcK˜eKšžœ˜—Kšžœ¡,˜@šžœž˜˜ K˜2˜2K˜K˜K˜"Kšœ žœ˜K˜.K™e—K˜FK˜—˜ K™oK˜@K˜KK˜7KšœYžœ!˜~Kšœ œ˜IK˜IK˜—˜K˜$K˜7KšœEžœ˜QKšœŸœ˜LK˜LK˜—Kšžœ˜—K˜Kšœžœ˜K˜—Kšžœ˜—K˜K˜—K˜oKšœžœ ˜ K˜sšŸœž œqžœ.žœžœ žœžœžœžœ˜’šœ žœ˜Kš ™š žœžœžœ(žœžœž˜LK˜Kšœ žœ˜+šžœžœ˜šžœžœžœ˜K˜/Kšœ4 Ðbkœ  œ˜wK˜.K˜—K˜—šžœžœžœžœ˜šžœžœžœ˜K˜+Kšœ4 ¢œ  œ˜wK˜*K˜—K˜—šžœ¡˜šžœžœ žœ˜šŸ œžœ˜K˜0K–J*Postfix0.83333 1 0.7 textColorPostfix0.83333 1 0.7 textColor˜FKšœM ¢œ¢œ ¡õ˜K˜/Kšœžœ˜K˜—K˜0K˜—šžœžœž˜šžœ žœ˜K˜/K™5šœ  œ˜K˜K˜5K˜=K˜K˜—K˜.K˜—šžœ˜šŸ œžœ˜K•StartOfExpansion;[context: Imager.Context, color: ImagerColorDefs.Color]˜&K˜>K˜—K˜+Kšžœžœ"˜7K˜*K˜——K˜—Kšžœ˜—K˜—Kšœ žœ˜K˜š žœžœžœ+žœžœž˜OK™EK˜šžœžœ˜&K˜CK˜—šžœ˜K˜[K˜K˜K˜,K˜,K˜—K˜)K˜)šžœžœžœ˜K˜+Kšœ¡˜-K˜*K˜—šžœ˜Kšžœžœ žœ'™Lšžœ žœ'˜7K™V—šžœ5¡(˜aKšœ(¡"˜JKšžœ˜ K˜—šžœ ˜ šžœ˜K˜*K˜6K˜)K˜—šžœ˜K˜.K˜oK™‹K˜-K˜——K˜—Kšžœ˜—L˜N˜—šŸ œžœžœqžœ.žœžœ žœžœx˜×šœ žœ˜Kš ™š žœžœžœ(žœžœž˜LK˜Kšœ žœ˜+šžœžœ˜šžœžœžœ˜K˜.Kšœ4 œ!  œ˜}K˜-K˜—K˜—šžœžœžœžœ˜šžœžœžœ˜K˜*Kšœ4 œ!  œ˜}K˜)K˜—K˜—šžœ¡˜šžœžœ žœ˜šŸ œžœ˜K˜/K–J*Postfix0.83333 1 0.7 textColorPostfix0.83333 1 0.7 textColor˜FKšœM œ¢œ¢œ ¡û˜‡K˜.Kšœžœ˜K˜—K˜/K˜—šžœžœž˜šžœ žœ˜K˜/K™5šœ  œ˜K˜K˜5K˜=K–ŽPostfix0.83333 1 0.7 textColor Postfix0.83333 1 0.7 textColorPostfix0.83333 1 0.7 textColorPostfix0.83333 1 0.7 textColor˜0K˜—K˜.K˜—šžœ˜šŸ œžœ˜K–;[context: Imager.Context, color: ImagerColorDefs.Color]˜&K˜>K˜—K˜*Kšžœžœ"˜7K˜)K˜——K˜—Kšžœ˜—K˜—Kšœ žœ˜šžœ$žœ˜,K˜CK˜—šžœ˜K˜aK˜K˜K˜,K˜,K˜—K˜)K˜)šžœžœžœ˜K˜*Kšœ¡˜-K˜)K˜—šžœ˜Kšžœžœ žœ'™Lšžœ žœ'˜7K™V—šžœ5¡(˜aKšœ(¡"˜JKšžœ˜ K˜—šžœ ˜ šžœ˜K˜)K˜6K˜(K˜—šžœ˜K˜-K˜nK™‹K˜,K˜——K˜—K˜K˜—K˜KKšœžœžœ˜KšŸœžœžœ˜)K˜K˜9šŸ œžœMžœ žœ(žœžœžœ žœžœužœžœžœ˜Øšœžœ˜K˜0K˜1K˜šœ<žœ˜FK™E—šžœžœžœ¡"˜Išžœ žœ˜šžœ žœ žœžœ˜%šžœ žœžœ'˜=Kšžœ&˜*—Kšœžœ#žœ žœ ˜aK˜—K˜—šžœžœ˜K˜'Kšœžœ#žœ žœ ˜aK˜—Kš¡/™/Kšœ(¡˜EKšœžœ#žœ žœ"˜yK˜—šžœ¡)˜0K™­K™*šžœ žœ˜K˜+šžœ žœ žœžœ˜%šžœ žœžœ'˜=Kšžœ&˜*—Kšœžœ#žœ žœ ˜`K˜—K˜*K˜—šžœžœžœ˜K˜+K˜'Kšœžœ#žœ žœ ˜`K˜*K˜—Kšœ'¡™?Kšœ(¡˜EKšœžœ#žœ žœ˜lK˜—K˜—K˜!K˜K˜—šŸ œžœ!žœžœ˜Tš žœžœžœ(žœžœž˜LKšžœžœžœ ˜7Kšžœ˜—Kšžœ˜K˜K˜—š Ÿ œžœžœ!žœžœ˜KK˜2K˜K˜K˜—š Ÿ œžœžœ!žœžœžœ˜TK˜2Kšœ žœ˜K˜K˜—šŸ œžœžœ!žœ<žœžœžœ žœžœ˜ K˜2šžœžœžœžœ˜1šŸ œžœ˜K™VK–J*Postfix0.83333 1 0.7 textColorPostfix0.83333 1 0.7 textColor˜FKšœ@¢œžœ!˜lKšœžœ˜K˜—K˜3K˜—K˜K˜—šŸ œžœžœžœ˜7Kšžœ0˜6K˜K˜—šŸ œžœžœ!žœ˜@K™hK˜2Kšžœžœžœžœ˜ šžœžœžœ0žœ˜OK˜BK˜—šžœ˜K˜5K˜—K˜K˜—šŸ œžœžœ!žœ˜CK™áK˜2Kšžœžœžœžœ˜ šžœžœžœ0žœ˜OšžœEžœ˜MK˜*K˜"K˜K˜FK˜—KšžœC˜GK˜—K˜—K˜Kšžœ˜K˜K˜—…—<¤e¬