<> <> <> <<>> DIRECTORY Atom, Basics, Imager, ImagerBasic, ImagerDisplay, ImagerFrameBuffer, ImagerManhattan, ImagerMasks, ImagerPixelMaps, ImagerPrivate, Terminal, TerminalExtras, ImagerTransform, Scaled; ImagerExampleDisplayImpl: CEDAR PROGRAM IMPORTS Atom, Basics, Imager, ImagerDisplay, ImagerFrameBuffer, ImagerMasks, ImagerPrivate, Terminal, TerminalExtras, ImagerTransform, Scaled ~ BEGIN <> DisplayClass: TYPE ~ ImagerDisplay.DisplayClass; DisplayClassRep: TYPE ~ ImagerDisplay.DisplayClassRep; DisplayData: TYPE ~ ImagerDisplay.DisplayData; DisplayDataRep: TYPE ~ ImagerDisplay.DisplayDataRep; DeviceRectangle: TYPE ~ ImagerBasic.DeviceRectangle; Color: TYPE ~ ImagerBasic.Color; ColorRep: TYPE ~ ImagerBasic.ColorRep; SampledColor: TYPE = REF ColorRep.sampled; ConstantColor: TYPE = REF ColorRep.constant; SpecialColor: TYPE = REF ColorRep.special; Mask: TYPE ~ ImagerMasks.Mask; ManhattanPolygon: TYPE ~ ImagerManhattan.Polygon; Transformation: TYPE ~ ImagerTransform.Transformation; Pair: TYPE ~ ImagerBasic.Pair; PixelMap: TYPE ~ ImagerPixelMaps.PixelMap; exampleDisplayClass: ImagerDisplay.DisplayClass ~ NEW[ImagerDisplay.DisplayClassRep _ [ displayType: $Gray8bpp, viewUnitsPerPixel: 1, Create: Create, ApplyMask: ApplyMask, DoUnderLock: DoUnderLock ]]; Create: PROC [displayClass: DisplayClass, creationData: REF] RETURNS [displayData: DisplayData] ~ { <> ppi: REAL _ 42; WITH creationData SELECT FROM props: Atom.PropList => { ppiRef: REF _ Atom.GetPropFromList[props, $pixelsPerInch]; WITH ppiRef SELECT FROM r: REF REAL => ppi _ r^; i: REF INT => ppi _ i^; ENDCASE => NULL; }; ENDCASE => NULL; displayData _ NEW[DisplayDataRep[1]]; displayData.displayClass _ displayClass; displayData.xRes _ ppi; displayData.yRes _ ppi; displayData.rotate _ TRUE; TRUSTED {displayData[0] _ ImagerFrameBuffer.GrayScaleDisplay8[]}; displayData.surfaceWidth _ displayData[0].fSize; displayData.surfaceHeight _ displayData[0].sSize; }; DoUnderLock: PROC [displayData: DisplayData, action: PROC, rectangle: DeviceRectangle] ~ { vt: Terminal.Virtual _ Terminal.Current[]; TerminalExtras.LockColorFrame[ vt: vt, xmin: MAX[rectangle.fMin, 0], ymin: MAX[rectangle.sMin, 0], xmax: MAX[rectangle.fMin+rectangle.fSize, 0], ymax: MAX[rectangle.sMin+rectangle.sSize, 0] ]; action[! UNWIND => {TerminalExtras.UnlockColorFrame[vt]}]; TerminalExtras.UnlockColorFrame[vt]; }; SurfaceToDevice: PROC [displayData: DisplayData] RETURNS [Transformation] ~ { IF displayData.rotate THEN RETURN [ImagerTransform.FromRec[[ a: 0, b: -1, c: displayData.surfaceHeight, d: 1, e: 0, f: 0 ]]] ELSE RETURN [ImagerTransform.Scale[1]] }; ApplyMask: PROC [displayData: DisplayData, color: Color, mask: Mask, sTranslate, fTranslate: INTEGER] ~ { LockedApplyMask: PROC ~ { function: ImagerPixelMaps.Function _ [null, null]; IF color = Imager.XOR THEN { color _ Imager.white; function _ [xor, null]; }; WITH color SELECT FROM constantColor: ConstantColor => { pixelValue: [0..255] _ constantColor.Y/256; ImagerMasks.ApplyConstant[ mask: mask, clipper: displayData.compositeClipper, dest: displayData[0], value: pixelValue, function: function, sTranslate: sTranslate, fTranslate: fTranslate ]; }; sampledColor: SampledColor => { buffer: ImagerBasic.PixelBuffer _ NEW[ImagerBasic.PixelBufferRep[displayData[0].fSize]]; invertOutput: CARDINAL _ 0; transform: Transformation _ ImagerTransform.Concat[ImagerTransform.Concat[ImagerTransform.Concat[ sampledColor.pa.m, sampledColor.m], ImagerTransform.Translate[displayData.viewOrigin.x, displayData.viewOrigin.y]], SurfaceToDevice[displayData]]; delta: Pair _ ImagerTransform.InverseTransformVec[[0, 1], transform]; xDelta: Scaled.Value _ Scaled.FromReal[delta.x]; yDelta: Scaled.Value _ Scaled.FromReal[delta.y]; SampledColorRun: PROC [sMin, fMin: INTEGER, fSize: NAT] ~ TRUSTED { start: Pair _ ImagerTransform.InverseTransform[[sMin, fMin], transform]; WHILE start.x > NAT.LAST DO start.x _ start.x - sampledColor.pa.xPixels; ENDLOOP; WHILE start.x < 0 DO start.x _ start.x + sampledColor.pa.xPixels; ENDLOOP; WHILE start.y > NAT.LAST DO start.y _ start.y - sampledColor.pa.yPixels; ENDLOOP; WHILE start.y < 0 DO start.y _ start.y + sampledColor.pa.yPixels; ENDLOOP; sampledColor.pa.get[sampledColor.pa, buffer, fSize, 0, Scaled.FromReal[start.x], Scaled.FromReal[start.y], xDelta, yDelta]; TRUSTED { pm: PixelMap _ displayData[0]; lineBufferPtr: LONG POINTER _ pm.refRep.pointer + Basics.LongMult[(sMin - pm.sOrigin), pm.refRep.rast]; lineArray: LONG POINTER TO PACKED ARRAY [0..0) OF [0..256) _ lineBufferPtr; IF invertOutput = 0 AND sampledColor.pa.maxSampleValue = 255 THEN { FOR j: CARDINAL IN [0..fSize) DO lineArray[j+fMin] _ buffer[j]; ENDLOOP; } ELSE { multiplier: CARDINAL _ (255*256+127)/sampledColor.pa.maxSampleValue; FOR j: CARDINAL IN [0..fSize) DO lineArray[j+fMin] _ Basics.BITSHIFT[Basics.BITXOR[buffer[j]*multiplier, invertOutput], -8]; ENDLOOP; }; }; }; SELECT sampledColor.colorOperator FROM $SampledBlack => invertOutput _ CARDINAL.LAST; $Intensity => NULL; ENDCASE => Imager.Error[$UnknownColorModel]; ImagerMasks.GenerateRuns[mask, displayData.compositeClipper, SampledColorRun, sTranslate, fTranslate]; }; ENDCASE => Imager.Error[$UnsupportedColorType]; }; bb: DeviceRectangle _ ImagerMasks.BoundingBox[mask]; bb.sMin _ bb.sMin + sTranslate; bb.fMin _ bb.fMin + fTranslate; IF color # displayData.cachedColor THEN { displayData.cachedColorData _ NIL; <> displayData.cachedColor _ color; }; DoUnderLock[displayData, LockedApplyMask, bb]; }; exampleImagerClass: ImagerPrivate.Class ~ ImagerDisplay.CreateImagerClass[exampleDisplayClass]; ImagerPrivate.RegisterDevice[exampleImagerClass]; END.