DIRECTORY BufferedRefresh, BufferedRefreshExtras, BufferedRefreshPort, CodeTimer, Imager, ImagerBackdoor, ImagerBitmapContext, ImagerBox, ImagerColor, ImagerDitherContext, ImagerPixel, ImagerSample, ImagerTransformation, PBasics, Real, SF; BufferedRefreshImpl: CEDAR PROGRAM IMPORTS BufferedRefreshPort, CodeTimer, Imager, ImagerBackdoor, ImagerBitmapContext, <> ImagerColor, ImagerDitherContext, ImagerSample, ImagerTransformation, PBasics, Real, SF EXPORTS BufferedRefresh, BufferedRefreshExtras = BEGIN OPEN BufferedRefresh; 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]]; 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] = { 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.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; PBasics.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 ANY, 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, 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, clientData, bottomLayer, rect]; CodeTimer.StopInt[$DrawNoMap2, $Gargoyle]; }; } ELSE { -- use backing map IF NOT layer.mapOK THEN { CodeTimer.StartInt[$DrawBackingMap2, $Gargoyle]; layer.drawnOn _ DrawLayer[sandwich, layer.backingContext, layer.refreshProc, 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; }; IF screen#NIL THEN IF bottomLayer THEN { TransferLayer: PROC [pixelMap: ImagerPixel.PixelMap] ~ { IF pixelMap.samplesPerPixel=1 THEN { dst: SampleMap ~ pixelMap[0]; src: SampleMap ~ layer.backingMap; dstBox: SF.Box ~ ImagerSample.GetBox[dst]; srcBox: SF.Box _ ImagerSample.GetBox[src]; delta: SF.Vec; size: SF.Vec _ SF.Size[srcBox]; srcBox _ SF.Intersect[srcBox, [[size.s-(y+h), x],[size.s-y, x+w]]]; delta _ SF.Sub[dstBox.min, srcBox.min]; ImagerSample.Transfer[dst: dst, src: src, delta: delta]; }; }; thisRect: Imager.Rectangle; CodeTimer.StartInt[$TransferLayer2, $Gargoyle]; thisRect _ [0,0,sandwich.cw,sandwich.ch]; ImagerBackdoor.AccessBufferRectangle[screen, TransferLayer, thisRect]; 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 _ 0; y _ 0; 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 ignoreBackingMap AND 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: bufferBkgnd]; CodeTimer.StopInt[$DoWithBuffer2, $Gargoyle]; }; }; ENDLOOP; }; DrawSandwich: PUBLIC PROC [sandwich: Sandwich, screen: Imager.Context, clientToViewer, viewerToClient: Imager.Transformation, clientData: REF ANY, 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, 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, clientData, bottomLayer, changeRect]; CodeTimer.StopInt[$DrawNoMap, $Gargoyle]; }; } ELSE { -- use backing map IF NOT layer.mapOK THEN { CodeTimer.StartInt[$DrawBackingMap, $Gargoyle]; layer.drawnOn _ DrawLayer[sandwich, layer.backingContext, layer.refreshProc, 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; }; IF screen#NIL THEN IF bottomLayer THEN { TransferLayer: PROC [pixelMap: ImagerPixel.PixelMap] ~ { IF pixelMap.samplesPerPixel=1 THEN { dst: SampleMap ~ pixelMap[0]; src: SampleMap ~ layer.backingMap; dstBox: SF.Box ~ ImagerSample.GetBox[dst]; srcBox: SF.Box _ ImagerSample.GetBox[src]; delta: SF.Vec; size: SF.Vec _ SF.Size[srcBox]; srcBox _ SF.Intersect[srcBox, [[size.s-(y+h), x],[size.s-y, x+w]]]; delta _ SF.Sub[dstBox.min, srcBox.min]; ImagerSample.Transfer[dst: dst, src: src, delta: delta]; }; }; thisRect: Imager.Rectangle; CodeTimer.StartInt[$TransferLayer, $Gargoyle]; thisRect _ [0,0,sandwich.cw,sandwich.ch]; ImagerBackdoor.AccessBufferRectangle[screen, TransferLayer, thisRect]; CodeTimer.StopInt[$TransferLayer, $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 _ 0; y _ 0; 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 ignoreBackingMap AND 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: bufferBkgnd]; CodeTimer.StopInt[$DoWithBuffer, $Gargoyle]; } }; }; idX: ImagerTransformation.Transformation = ImagerTransformation.Scale[1.0]; debug: BOOL _ FALSE; SetDebug: PROC [t: INT] = {debug _ t=1;}; DrawLayer: PROC [sandwich: Sandwich, context: Imager.Context, proc: RefreshProc, 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. 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 clear THEN { CodeTimer.StartInt[$LayerWhite, $Gargoyle]; Imager.SetColor[context, Imager.white]; Imager.MaskRectangle[context, IF changeRect.w # Real.LargestNumber THEN changeRect ELSE bounds]; CodeTimer.StopInt[$LayerWhite, $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, clientData: REF ANY _ NIL, clear: BOOL _ FALSE] = { layer: LayerData ~ FindLayer[sandwich, layerName]; IF layer.hasMap AND (clear OR layer.mapOK) THEN { layer.drawnOn _ DrawLayer[sandwich, layer.backingContext, proc, clientData, clear]; layer.mapOK _ TRUE; }; }; 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]; }; }; bufferBkgnd: Imager.Color _ Imager.white; SetBkgndRed: PROC = { bufferBkgnd _ ImagerColor.ColorFromRGB[[1.0, 0.0, 0.0]]; }; SetBkgndWhite: PROC = { bufferBkgnd _ ImagerColor.ColorFromRGB[[1.0, 1.0, 1.0]]; }; END. ìBufferedRefreshImpl.mesa Copyright Ó 1986, 1987, 1988, 1989, 1990 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, August 28, 1991 6:42 pm PDT Bier, September 20, 1991 11:43 am PDT Doug Wyatt, September 15, 1989 3:49:32 pm PDT [Artwork node; type 'ArtworkInterpress on' to command tool] Layers should be specified in back to front order. 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 ImagerSample.BasicTransfer[dst: dst, src: src, dstMin: dstBox.min, srcMin: box.min, size: SF.Size[box]]; Compute x, y, w, h, and rect, which are free variables in drawLayers. 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 ImagerSample.BasicTransfer[dst: dst, src: src, dstMin: dstBox.min, srcMin: box.min, size: SF.Size[box]]; IF changeRect.x = -Real.LargestNumber THEN thisRect _ [0,0,sandwich.cw,sandwich.ch] ELSE thisRect _ changeRect; 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 Don't clear, intersect or clip if bounds are unknown. Just use changeRect to draw. Imager.ClipRectangle[context, bounds]; -- UNNECESSARY and BUGGY 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. ÊB– "cedar" style•NewlineDelimiter ˜codešœ™KšœT™TKšœó™óK™!K™%K™-—K™šÏk ˜ Idefaultšœâœ˜å—K˜šÏnœœ˜"Lšœ´˜»Kšœ)˜0—Kšœœ˜I 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˜—šžœœœœ˜bKšœœ˜&Kš œœœœœ˜JKšœ˜Kšœ˜Kšœ˜NšÏb!™!Kšœ:˜:Kšœ:˜:š œœœ(œœ˜LKšœ˜Kšœ œ˜+šœœ˜Kšœœ˜Kšœœ˜Kšœœ˜K˜—šœœ˜Kšœ5˜5K˜)š œ œœœ˜$Kšœ˜Kšœœœ6˜oKšœÏcK˜eKšœ˜—Kšœ ,˜@šœ˜šœ ˜ Kšœ2˜2šœ2˜2Kšœ˜Kšœ˜Kšœ"˜"Kšœ œ˜Kšœ.˜.Kšœe™e—KšœF˜FK˜—šœ ˜ K™oKšœ@˜@KšœK˜KKšœ7˜7KšœYœ!˜~KšœŸœ˜IKšœI˜IK˜—šœ˜Kšœ$˜$Kšœ7˜7KšœEœ˜QKšœžœ˜LKšœL˜LK˜—Kšœ˜—Kšœ˜Kšœœ˜K˜—Kšœ˜—K˜K˜—Kšœo˜oKšœœ ˜ Kšœs˜sšžœ œqœœœœ œœœœ˜üšœ œ˜KšŸ™š œœœ(œœ˜LKšœ˜Kšœ œ˜+šœœ˜šœœœ˜Kšœ/˜/Kšœ!Ÿœ!˜SKšœ.˜.K˜—K˜—šœœœœ˜šœœœ˜Kšœ+˜+Kšœ!Ÿœ!˜SKšœ*˜*K˜—K˜—šœ ˜šœœ œ˜Kšœ0˜0Kšœ:ŸœœŸœ õ˜ÞKšœ/˜/Kšœœ˜K˜—šœœ˜šœ œ˜šž œœ%˜8šœœ˜$Kšœ˜Kšœ"˜"Kšœœ ˜*Kšœœ ˜*Kšœœ˜Kšœœœ˜Kšœ œ8˜CKšœœ˜'Kšœ8˜8KšœZœ ™hK˜—Kšœ˜—K˜Kšœ/˜/Kšœ)˜)KšœF˜FKšœ.˜.K˜—šœ˜šž œœ˜K•StartOfExpansion;[context: Imager.Context, color: ImagerColorDefs.Color]šœ&˜&Kšœ>˜>K˜—Kšœ+˜+Kšœœ"˜7Kšœ*˜*K˜——K˜—Kšœ˜—K˜—Kšœ œ˜Kšœ˜š œœœ+œœ˜OK™EK˜šœœ˜&Kšœ/˜/K˜—šœ˜Kšœ[˜[Kšœ7˜7Kšœ,˜,Kšœ,˜,K˜—Kšœ)˜)Kšœ)˜)šœœœ˜Kšœ+˜+Kšœ ˜-Kšœ*˜*K˜—šœ˜šœœ œ'˜LK™V—šœ5 (˜aKšœ( "˜JKšœ˜ Kšœ˜—šœ ˜ šœ˜Kšœ*˜*Kšœ6˜6Kšœ)˜)K˜—šœ˜Kšœ.˜.Kšœp˜pKšœ‹™‹Kšœ-˜-K˜——K˜—Jšœ˜—L˜N˜—šž œœœqœœœœ œœx˜Ášœ œ˜KšŸ™š œœœ(œœ˜LKšœ˜Kšœ œ˜+šœœ˜šœœœ˜Kšœ.˜.Kšœ!Ÿœ'˜YKšœ-˜-K˜—K˜—šœœœœ˜šœœœ˜Kšœ*˜*Kšœ!Ÿœ'˜YKšœ)˜)K˜—K˜—šœ ˜šœœ œ˜Kšœ/˜/Kšœ:ŸœœŸœ û˜äKšœ.˜.Kšœœ˜K˜—šœœ˜šœ œ˜šž œœ%˜8šœœ˜$Kšœ˜Kšœ"˜"Kšœœ ˜*Kšœœ ˜*Kšœœ˜Kšœœœ˜Kšœ œ8˜CKšœœ˜'Kšœ8˜8KšœZœ ™hK˜—Kšœ˜—K˜Kšœ.˜.šœ$œ)™SKšœ™—Kšœ)˜)KšœF˜FKšœ-˜-K˜—šœ˜šž œœ˜K–;[context: Imager.Context, color: ImagerColorDefs.Color]šœ&˜&Kšœ>˜>K˜—Kšœ*˜*Kšœœ"˜7Kšœ)˜)K˜——K˜—Kšœ˜—K˜—Kšœ œ˜šœ$œ˜,Kšœ/˜/K˜—šœ˜Kšœa˜aKšœ7˜7Kšœ,˜,Kšœ,˜,K˜—Kšœ)˜)Kšœ)˜)šœœœ˜Kšœ*˜*Kšœ ˜-Kšœ)˜)K˜—šœ˜šœœ œ'˜LK™V—šœ5 (˜aKšœ( "˜JKšœ˜ Kšœ˜—šœ ˜ šœ˜Kšœ)˜)Kšœ6˜6Kšœ(˜(K˜—šœ˜Kšœ-˜-Kšœo˜oKšœ‹™‹Kšœ,˜,K˜——K˜—K˜K˜—K˜KKšœœœ˜Kšžœœœ˜)K˜šž œœNœœœ œœuœœœ˜œšœœ˜Kšœ0˜0Kšœ1˜1šœ<œ˜FKšœE™E—šœœœ "˜IKš S™SKšœ( ˜EKšœœ#œ œ"˜yK˜—šœ )˜0šœœ˜Kšœ+˜+Kšœ'˜'Kšœœ#œ œ ˜`Kšœ*˜*K˜—Kšœ' ™?Kšœ( ˜EKšœœ#œ œ˜lKšœ˜—Kšœ˜—Kšœ!˜!K˜K˜—šž œœ!œœ˜Tš œœœ(œœ˜LKšœœœ ˜7Kšœ˜—Kšœ˜K˜K˜—š ž œœœ!œœ˜KKšœ2˜2Kšœ˜K˜K˜—š ž œœœ!œœœ˜TKšœ2˜2Kšœ œ˜K˜K˜—šž œœœ!œ"œœœ œœ˜†Kšœ2˜2šœœœœ˜1KšœS˜SKšœœ˜K˜—K˜K˜—šž œœœœ˜7Kšœ0˜6K˜K˜—šž œœœ!œ˜@K™hKšœ2˜2Kšœœœœ˜ šœœœ0œ˜OKšœB˜BK˜—šœ˜Kšœ5˜5K˜—K˜K˜—šž œœœ!œ˜CKšœá™áKšœ2˜2Kšœœœœ˜ šœœœ0œ˜OšœEœ˜MKšœ*˜*Kšœ"˜"Kšœ˜KšœF˜FK˜—KšœC˜GK˜—K˜K˜—K˜)K˜šž œœ˜K˜8K˜—šž œœ˜K˜8K˜—K˜Kšœ˜J˜J˜—…—:aH