DIRECTORY Basics USING [LongDiv, LongDivMod, LongMult], ImagerColor USING [Color, ConstantColor, SampledColor], ImagerDevice USING [Class, ClassRep, Device, DeviceRep, HalftoneParameters, RunProc], ImagerPixelMap USING [DeviceRectangle, Fill, Get8Bits, PixelMap], ImagerTransformation USING [PreRotate, Transformation, Translate], PrincOps USING [zBNDCK, zINC], Real USING [RoundC]; ImagerSmoothGrayDeviceImpl: CEDAR PROGRAM IMPORTS Basics, ImagerPixelMap, ImagerTransformation, Real ~ BEGIN Device: TYPE ~ ImagerDevice.Device; RunProc: TYPE ~ ImagerDevice.RunProc; HalftoneParameters: TYPE ~ ImagerDevice.HalftoneParameters; DeviceRectangle: TYPE ~ ImagerPixelMap.DeviceRectangle; Transformation: TYPE ~ ImagerTransformation.Transformation; Color: TYPE ~ ImagerColor.Color; ConstantColor: TYPE ~ ImagerColor.ConstantColor; SampledColor: TYPE ~ ImagerColor.SampledColor; Case: TYPE ~ {nil, constant, gray, sampled}; Data: TYPE ~ REF DataRep; DataRep: TYPE ~ RECORD[ frame: ImagerPixelMap.PixelMap, -- the frame buffer case: Case _ nil, -- what type of color pixelValue: [0..255] _ 0 -- for ConstantColor ]; defaultPixelsPerInch: REAL ~ 42; defaultSurfaceUnitsPerPixel: NAT ~ 5; class: ImagerDevice.Class ~ NEW[ImagerDevice.ClassRep _ [ type: $SmoothGrayDisplay, SetColor: SetColor, SetPriority: SetPriority, SetHalftone: SetHalftone, MaskRuns: MaskRuns ]]; Create: PROC[frame: ImagerPixelMap.PixelMap, pixelsPerInch: REAL _ defaultPixelsPerInch, surfaceUnitsPerPixel: NAT _ defaultSurfaceUnitsPerPixel] RETURNS[Device] ~ { data: Data ~ NEW[DataRep _ [frame: frame]]; unitsPerInch: REAL ~ pixelsPerInch*surfaceUnitsPerPixel; sSize: NAT ~ frame.sSize*surfaceUnitsPerPixel; fSize: NAT ~ frame.fSize*surfaceUnitsPerPixel; surfaceToDevice: Transformation ~ ImagerTransformation.Translate[[sSize, 0]]; surfaceToDevice.PreRotate[90]; RETURN[NEW[ImagerDevice.DeviceRep _ [class: class, clipBox: [sMin: 0, fMin: 0, sSize: sSize, fSize: fSize], surfaceToDevice: surfaceToDevice, surfaceUnitsPerInch: [unitsPerInch, unitsPerInch], surfaceUnitsPerPixel: surfaceUnitsPerPixel, data: data]]]; }; SetColor: PROC[device: Device, color: Color, viewToDevice: Transformation] ~ { data: Data ~ NARROW[device.data]; WITH color SELECT FROM color: ConstantColor => { data.pixelValue _ Real.RoundC[MIN[MAX[color.cie.Y, 0], 1]*255]; data.case _ constant; }; ENDCASE => ERROR; -- not implemented }; SetPriority: PROC[device: Device, priorityImportant: BOOL] ~ { }; SetHalftone: PROC[device: Device, halftone: HalftoneParameters] ~ { }; Check: PROC[x: INTEGER, max: NAT] RETURNS[NAT] ~ TRUSTED MACHINE CODE { PrincOps.zINC; PrincOps.zBNDCK }; MaskRuns: PROC[device: Device, runs: PROC[RunProc]] ~ { data: Data ~ NARROW[device.data]; pixelValue: [0..255] ~ data.pixelValue; lineBuff: ARRAY [0..2050] OF INTEGER _ ALL[0]; minPixel: NAT _ data.frame.fSize; maxPixel: NAT _ 0; vupp: NAT _ device.surfaceUnitsPerPixel; squpp: NAT _ vupp*vupp; line: NAT _ 0; s: NAT _ line*vupp; sModVupp: NAT _ 0; fImageLimit: NAT _ data.frame.fOrigin+data.frame.fMin+data.frame.fSize; fSizeSpatial: NAT ~ data.frame.fSize*vupp; 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 { data.frame.Fill[[line, bltStart, 1, pixel-bltStart], pixelValue]; }; IF pixel <= maxPixel AND pixel < fImageLimit THEN { oldValue: CARDINAL _ data.frame.Get8Bits[line, pixel]; mix: CARDINAL _ lineBuff[pixel]; mixedValue: CARDINAL _ Basics.LongDiv[ Basics.LongMult[oldValue, squpp-mix]+Basics.LongMult[pixelValue, mix], squpp ]; data.frame.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 _ data.frame.fSize; maxPixel _ 0; }; run: PROC [sMin, fMin: INTEGER, fSize: NAT] ~ { q0, r0, q1, r1: CARDINAL; f0: CARDINAL _ Check[fMin, fSizeSpatial]; f1: CARDINAL _ Check[fMin+fSize, fSizeSpatial]; 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; }; }; runs[run]; run[s+vupp+1, 0, 0]; }; END. pImagerSmoothGrayDeviceImpl.mesa Copyright c 1984 Xerox Corporation. All rights reserved. Michael Plass, July 19, 1984 12:57:21 pm PDT Doug Wyatt, November 3, 1984 12:01:16 pm PST This is an example implementation of an Imager display device. It implements an 8-bit-per-pixel gray-level display with antialiasing. DoUnderLock: PROC [data: Data, action: PROC, rectangle: DeviceRectangle] ~ { vt: Terminal.Virtual _ Terminal.Current[]; vupp: NAT _ data.class.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]; }; IF x IN[0..max] THEN RETURN[x] ELSE ERROR RuntimeError.BoundsFault Ê¢˜™Jšœ Ïmœ.™9J™,J™,J™—šÏk ˜ Jšœžœ!˜-Jšœ žœ&˜7Jšœ žœC˜UJšœžœ-˜AJšœžœ(˜BJšœ žœ˜Jšœžœ ˜J˜—Jšœž ˜)Jšžœ3˜:Jšœž˜J™™†J˜—Jšœžœ˜#Jšœ žœ˜%Jšœžœ#˜;Jšœžœ"˜7J˜Jšœžœ'˜;Jšœžœ˜ Jšœžœ˜0Jšœžœ˜.J˜Jšœžœ"˜,J˜Jšœžœžœ ˜šœ žœžœ˜Jšœ Ïc˜3JšœŸ˜'JšœŸ˜-J˜J˜—Jšœžœ˜ Jšœžœ˜%J˜šœžœ˜9Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜J˜—šÏnœžœ ˜,Jšœžœ˜+Jšœžœ žœ ˜LJšœ žœ˜+Jšœžœ&˜8Jšœžœ$˜.Jšœžœ$˜.JšœM˜MJšœ˜šžœžœ(˜2Jšœ8˜8Jšœ!˜!Jšœ2˜2Jšœ+˜+Jšœ˜—J˜J˜—š  œžœžœ!™LJšœ*™*Jšœžœ ™)šœ™Jšœ™Jšœžœ™"Jšœžœ™"Jšœžœ0™9Jšœžœ/™8Jšœ™—Jšœ žœ+™:Jšœ$™$Jšœ™J™—š œžœ@˜NJšœ žœ˜!šžœžœž˜˜Jšœžœžœ žœ˜?J˜J˜—JšžœžœŸ˜$—Jšœ˜J˜—š  œžœ$žœ˜>Jšœ˜J˜—š  œžœ2˜CJ˜J˜—š  œžœžœžœžœžœ˜0Jšžœžœžœ$˜8Jš žœžœ žœžœžœžœ™BJ˜—š œžœžœ˜7Jšœ žœ˜!Jšœ'˜'Jš œ žœ žœžœžœ˜.Jšœ žœ˜!Jšœ žœ˜Jšœžœ˜(Jšœžœ ˜Jšœžœ˜Jšœžœ ˜Jšœ žœ˜Jšœ žœ7˜GJšœžœ˜*š œžœ˜Jšœžœ˜ Jšœžœ ˜šžœžœžœž˜%Jšœ&˜&Jšžœ˜—Jšœžœžœ˜!šžœž˜Jšœ žœ˜Jšžœžœž ˜7Jšœ˜Jšžœžœž ˜;šžœžœ˜JšœA˜AJšœ˜—šžœžœžœ˜3Jšœ žœ$˜6Jšœžœ˜ šœ žœ˜&JšœF˜FJšœ˜J˜—Jšœ1˜1Jšœ˜—šžœžœ˜Jšœ˜Jšœ˜—Jšž˜—Jšœ˜šžœžœžœž˜%Jšœ˜Jšžœ˜—Jšœ˜Jšœ ˜ Jšœ˜—šœžœžœ žœ˜/Jšœžœ˜Jšœžœ˜)Jšœžœ#˜/šžœ ž˜J˜ Jšœ˜šžœžœ˜J˜ Jšœ ˜ Jšœ˜Jšœ˜—Jšž˜—šžœ žœ˜Jšœ'˜'Jšœ'˜'Jšžœžœ˜$Jšžœžœ˜$Jšœ(˜(Jšœ%˜%Jšœ(˜(Jšœ%˜%Jšœ˜—Jšœ˜—J˜ Jšœ˜Jšœ˜J˜—Jšžœ˜—…—t†