<> <> <> <<>> DIRECTORY Atom, Basics, Imager, ImagerBasic, ImagerDisplay, ImagerFrameBuffer, ImagerManhattan, ImagerMasks, ImagerPixelMaps, ImagerPrivate, Terminal, TerminalExtras; ImagerSmoothGrayDisplayImpl: CEDAR PROGRAM IMPORTS Atom, Basics, Imager, ImagerDisplay, ImagerFrameBuffer, ImagerMasks, ImagerPixelMaps, ImagerPrivate, Terminal, TerminalExtras ~ 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; exampleDisplayClass: ImagerDisplay.DisplayClass ~ NEW[ImagerDisplay.DisplayClassRep _ [ displayType: $SmoothGray, viewUnitsPerPixel: 5, Create: Create, ApplyMask: ApplyMask, DoUnderLock: DoUnderLock ]]; Create: PROC [displayClass: DisplayClass, creationData: REF] RETURNS [displayData: DisplayData] ~ { <> ppi: REAL _ 42; frameBuffer: REF ImagerPixelMaps.PixelMap _ NIL; 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; }; buffer: REF ImagerPixelMaps.PixelMap => frameBuffer _ buffer; ENDCASE => NULL; displayData _ NEW[DisplayDataRep[1]]; displayData.displayClass _ displayClass; displayData.xRes _ ppi*exampleDisplayClass.viewUnitsPerPixel; displayData.yRes _ ppi*exampleDisplayClass.viewUnitsPerPixel; displayData.rotate _ TRUE; IF frameBuffer = NIL THEN TRUSTED {displayData[0] _ ImagerFrameBuffer.GrayScaleDisplay8[]} ELSE displayData[0] _ frameBuffer^; displayData.surfaceWidth _ displayData[0].fSize*exampleDisplayClass.viewUnitsPerPixel; displayData.surfaceHeight _ displayData[0].sSize*exampleDisplayClass.viewUnitsPerPixel; }; DoUnderLock: PROC [displayData: DisplayData, action: PROC, rectangle: DeviceRectangle] ~ { vt: Terminal.Virtual _ Terminal.Current[]; vupp: NAT _ displayData.displayClass.viewUnitsPerPixel; TerminalExtras.LockColorFrame[ vt: vt, xmin: MAX[rectangle.fMin, 0]/vupp, ymin: MAX[rectangle.sMin, 0]/vupp, xmax: MAX[rectangle.fMin+rectangle.fSize+vupp-1, 0]/vupp, ymax: MAX[rectangle.sMin+rectangle.sSize+vupp-1, 0]/vupp ]; action[! UNWIND => {TerminalExtras.UnlockColorFrame[vt]}]; TerminalExtras.UnlockColorFrame[vt]; }; ApplyMask: PROC [displayData: DisplayData, color: Color, mask: Mask, sTranslate, fTranslate: INTEGER] ~ { LockedApplyMask: PROC ~ { WITH color SELECT FROM constantColor: ConstantColor => { pixelValue: [0..255] _ constantColor.Y/256; lineBuff: ARRAY [0..2050] OF INTEGER _ ALL[0]; minPixel: NAT _ displayData[0].fSize; maxPixel: NAT _ 0; vupp: NAT _ displayData.displayClass.viewUnitsPerPixel; squpp: NAT _ vupp*vupp; line: NAT _ CARDINAL[MAX[bb.sMin, 0]]/vupp; s: NAT _ line*vupp; sModVupp: NAT _ 0; fImageLimit: NAT _ displayData[0].fOrigin+displayData[0].fMin+displayData[0].fSize; DoLine: PROC ~ { sum: NAT _ 0; pixel: NAT _ minPixel; FOR j: NAT IN [minPixel..maxPixel] DO lineBuff[j] _ sum _ sum + lineBuff[j]; ENDLOOP; lineBuff[maxPixel+1] _ LAST[NAT]; WHILE pixel <= maxPixel DO bltStart: NAT; WHILE lineBuff[pixel] = 0 DO pixel _ pixel + 1 ENDLOOP; bltStart _ pixel; WHILE lineBuff[pixel] = squpp DO pixel _ pixel + 1 ENDLOOP; IF pixel > bltStart THEN { displayData[0].Fill[[line, bltStart, 1, pixel-bltStart], pixelValue]; }; IF pixel <= maxPixel AND pixel < fImageLimit THEN { oldValue: CARDINAL _ displayData[0].Get8Bits[line, pixel]; mix: CARDINAL _ lineBuff[pixel]; mixedValue: CARDINAL _ Basics.LongDiv[ Basics.LongMult[oldValue, squpp-mix]+Basics.LongMult[pixelValue, mix], squpp ]; displayData[0].Fill[[line, pixel, 1, 1], mixedValue]; }; IF pixel <= maxPixel THEN { pixel _ pixel + 1; }; ENDLOOP; lineBuff[maxPixel+1] _ 0; FOR j: NAT IN [minPixel..maxPixel] DO lineBuff[j] _ 0; ENDLOOP; minPixel _ displayData[0].fSize; maxPixel _ 0; }; RunProc: PROC [sMin, fMin: INTEGER, fSize: NAT] ~ { q0, r0, q1, r1: CARDINAL; f0: CARDINAL _ MIN[MAX[fMin, 0], displayData.surfaceWidth]; f1: CARDINAL _ MIN[MAX[fMin+fSize, 0], displayData.surfaceWidth]; WHILE s < sMin DO s _ s + 1; sModVupp _ sModVupp + 1; IF sModVupp = vupp THEN { DoLine[]; sModVupp _ 0; line _ line + 1; }; ENDLOOP; IF fSize > 0 THEN { [q0, r0] _ Basics.LongDivMod[f0, vupp]; [q1, r1] _ Basics.LongDivMod[f1, vupp]; IF q0 < minPixel THEN minPixel _ q0; IF q1 > maxPixel THEN maxPixel _ q1; lineBuff[q0] _ lineBuff[q0] + vupp - r0; lineBuff[q0+1] _ lineBuff[q0+1] + r0; lineBuff[q1] _ lineBuff[q1] + r1 - vupp; lineBuff[q1+1] _ lineBuff[q1+1] - r1; }; }; ImagerMasks.GenerateRuns[ mask: mask, clipper: displayData.compositeClipper, runProc: RunProc, sTranslate: sTranslate, fTranslate: fTranslate ]; RunProc[s+vupp+1, 0, 0]; }; 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.