<> <> <> <> <> <> <<>> DIRECTORY BufferedRefresh, BufferedRefreshTypes, Imager, ImagerBackdoor, ImagerBitmapContext, ImagerSample, ImagerTransformation; BufferedRefreshImpl: CEDAR PROGRAM IMPORTS Imager, ImagerBackdoor, ImagerBitmapContext, ImagerSample, ImagerTransformation EXPORTS BufferedRefresh = BEGIN RefreshProc: TYPE = BufferedRefreshTypes.RefreshProc; Layer: TYPE = BufferedRefreshTypes.Layer; Sandwich: TYPE = REF SandwichObj; SandwichObj: TYPE = BufferedRefreshTypes.SandwichObj; LayerData: TYPE = REF LayerDataObj; LayerDataObj: TYPE = BufferedRefreshTypes.LayerDataObj; << [Artwork node; type 'ArtworkInterpress on' to command tool] >> StartLayerDataList: PUBLIC PROC [] RETURNS [entityList, ptr: LIST OF LayerData] = { ptr _ entityList _ NIL; }; AddLayerData: PUBLIC PROC [entity: LayerData, entityList, ptr: LIST OF LayerData] RETURNS [newList, newPtr: LIST OF LayerData] = { IF ptr = NIL THEN { IF NOT entityList = NIL THEN ERROR; newPtr _ newList _ CONS[entity, NIL]; RETURN; } ELSE { newList _ entityList; ptr.rest _ CONS[entity, NIL]; newPtr _ ptr.rest; }; }; <<>> CreateSandwich: PUBLIC PROC [layers: LIST OF Layer] RETURNS [sandwich: Sandwich] = { <> layerData: LayerData; ptr: LIST OF LayerData; sandwich _ NEW[SandwichObj]; [sandwich.layers, ptr] _ StartLayerDataList[]; FOR list: LIST OF Layer _ layers, list.rest UNTIL list = NIL DO layerData _ NEW[LayerDataObj _ [name: list.first.name, refreshProc: list.first.refreshProc, hasMap: list.first.backingMap]]; [sandwich.layers, ptr] _ AddLayerData[layerData, sandwich.layers, ptr]; ENDLOOP; }; FitSandwichToScreen: PUBLIC PROC [sandwich: Sandwich, cw, ch: INTEGER] = { IF sandwich.chunkingBitmap=NIL THEN DoFitSandwichToScreen[sandwich, cw, ch] ELSE { curSize: ImagerSample.Vec _ ImagerSample.GetSize[sandwich.chunkingBitmap]; IF curSize.s#ch OR curSize.f#cw THEN DoFitSandwichToScreen[sandwich, cw, ch]; }; }; DoFitSandwichToScreen: PROC [sandwich: Sandwich, cw, ch: INTEGER] = { layer: LayerData; rect: Imager.Rectangle; <> sandwich.chunkingBitmap _ ImagerSample.NewSampleMap[[max: [ch, cw]]]; sandwich.chunkingContext _ ImagerBitmapContext.Create[[ch, cw], [down, right], [72.0, 72.0], TRUE, $Bitmap]; ImagerBitmapContext.SetBitmap[sandwich.chunkingContext, sandwich.chunkingBitmap]; sandwich.ch _ ch; <> 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 _ list.first; IF layer.hasMap THEN { layer.backingMap _ ImagerSample.NewSampleMap[[max: [ch, cw]]]; layer.backingContext _ ImagerBitmapContext.Create[[ch, cw], [down, right], [72.0, 72.0], TRUE, $Bitmap]; ImagerBitmapContext.SetBitmap[layer.backingContext, layer.backingMap]; <> rect _ ImagerBackdoor.GetBounds[layer.backingContext]; Imager.SetColor[layer.backingContext, Imager.white]; Imager.MaskRectangle[layer.backingContext, rect]; layer.mapOK _ FALSE; } ELSE { layer.backingMap _ NIL; layer.backingContext _ NIL; }; ENDLOOP; }; DrawSandwich: PUBLIC PROC [sandwich: Sandwich, screen: Imager.Context, clientToViewer, viewerToClient: Imager.Transformation, clientData: REF ANY, ignoreBackingMap: BOOL _ FALSE] = { <> chunking: Imager.Context _ sandwich.chunkingContext; boundRect: Imager.Rectangle; rect: Imager.Rectangle; layer: LayerData; <> Imager.ConcatT[screen, viewerToClient]; -- get rid of the Biscrollers transformation FOR list: LIST OF LayerData _ sandwich.layers, list.rest UNTIL list = NIL DO layer _ list.first; IF layer.hasMap THEN { Imager.ConcatT[layer.backingContext, sandwich.viewerToClient]; -- undo the last Imager.ConcatT[layer.backingContext, clientToViewer]; -- do the new }; ENDLOOP; sandwich.viewerToClient _ viewerToClient; <> boundRect _ ImagerBackdoor.GetBounds[screen]; IF ignoreBackingMap THEN { Imager.SetColor[screen, Imager.white]; Imager.MaskRectangle[screen, boundRect]; } ELSE { Imager.SetColor[chunking, Imager.white]; Imager.MaskRectangle[chunking, boundRect]; }; FOR list: LIST OF LayerData _ sandwich.layers, list.rest UNTIL list = NIL DO layer _ list.first; IF ignoreBackingMap THEN { DirectToScreen: PROC = { Imager.ConcatT[screen, clientToViewer]; rect _ ImagerBackdoor.GetBounds[screen]; layer.refreshProc[screen, rect, clientData]; }; Imager.DoSaveAll[screen, DirectToScreen]; } ELSE { IF NOT layer.hasMap THEN { DirectToChunking: PROC = { Imager.ConcatT[chunking, clientToViewer]; rect _ ImagerBackdoor.GetBounds[chunking]; layer.refreshProc[chunking, rect, clientData]; }; Imager.DoSaveAll[chunking, DirectToChunking]; } ELSE { IF NOT layer.mapOK THEN { rect _ ImagerBackdoor.GetBounds[layer.backingContext]; Imager.SetColor[layer.backingContext, Imager.white]; Imager.MaskRectangle[layer.backingContext, rect]; layer.refreshProc[layer.backingContext, rect, clientData]; layer.mapOK _ TRUE; }; LayerToChunking[sandwich, layer, chunking]; }; }; ENDLOOP; IF NOT ignoreBackingMap THEN ChunkingToScreen[sandwich, screen]; }; ChunkingToScreen: PROC [sandwich: Sandwich, screen: Imager.Context] = { ChunkingToScreenAux: PROC = { Imager.DrawBitmap[screen, chunkingBitmap, [sandwich.ch, 0]]; }; chunkingBitmap: Imager.SampleMap _ sandwich.chunkingBitmap; Imager.DoSaveAll[screen, ChunkingToScreenAux]; }; LayerToChunking: PROC [sandwich: Sandwich, layer: LayerData, chunking: Imager.Context] = { UpdateBackingMap: PROC = { Imager.SetColor[chunking, Imager.black]; Imager.MaskBitmap[chunking, backingMap, [sandwich.ch, 0]]; }; backingMap: Imager.SampleMap _ layer.backingMap; Imager.DoSaveAll[chunking, UpdateBackingMap]; }; <<>> 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; }; GetLayerContext: PUBLIC PROC [sandwich: Sandwich, layerName: ATOM] RETURNS [backingContext: Imager.Context] = { layer: LayerData _ FindLayer[sandwich, layerName]; backingContext _ layer.backingContext; }; 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; }; END.