<> <> <> <> DIRECTORY Basics USING [bitsPerWord, LongMult], ImagerColor, ImagerDevice USING [Class, ClassRep, Device, DeviceRep, HalftoneParameters, RunProc], ImagerPixelArray, ImagerPixelArrayPrivate, ImagerPixelMap USING [DeviceRectangle, Function, PixelMap], ImagerTransformation, PrincOps USING [BBTableSpace, BitBltTable, BitBltTablePtr, zBNDCK, zINC], PrincOpsUtils USING [AlignedBBTable, BITBLT], Vector2 USING [VEC]; ImagerLFDeviceImpl: CEDAR PROGRAM IMPORTS Basics, ImagerColor, ImagerTransformation, PrincOpsUtils ~ BEGIN Device: TYPE ~ ImagerDevice.Device; RunProc: TYPE ~ ImagerDevice.RunProc; HalftoneParameters: TYPE ~ ImagerDevice.HalftoneParameters; DeviceRectangle: TYPE ~ ImagerPixelMap.DeviceRectangle; VEC: TYPE ~ Vector2.VEC; Transformation: TYPE ~ ImagerTransformation.Transformation; Color: TYPE ~ ImagerColor.Color; ConstantColor: TYPE ~ ImagerColor.ConstantColor; SampledColor: TYPE ~ ImagerColor.SampledColor; ColorOperator: TYPE ~ ImagerColor.ColorOperator; GrayArray: TYPE ~ ARRAY [0..16) OF CARDINAL; grayHeight: NAT ~ 16; -- must not exceed 16, should be a power of 2 checkeredGray: GrayArray ~ [ 05555H, -- . @ . @ . @ . @ . @ . @ . @ . @ 0AAAAH, -- @ . @ . @ . @ . @ . @ . @ . @ . 05555H, -- . @ . @ . @ . @ . @ . @ . @ . @ 0AAAAH, -- @ . @ . @ . @ . @ . @ . @ . @ . 05555H, -- . @ . @ . @ . @ . @ . @ . @ . @ 0AAAAH, -- @ . @ . @ . @ . @ . @ . @ . @ . 05555H, -- . @ . @ . @ . @ . @ . @ . @ . @ 0AAAAH, -- @ . @ . @ . @ . @ . @ . @ . @ . 05555H, -- . @ . @ . @ . @ . @ . @ . @ . @ 0AAAAH, -- @ . @ . @ . @ . @ . @ . @ . @ . 05555H, -- . @ . @ . @ . @ . @ . @ . @ . @ 0AAAAH, -- @ . @ . @ . @ . @ . @ . @ . @ . 05555H, -- . @ . @ . @ . @ . @ . @ . @ . @ 0AAAAH, -- @ . @ . @ . @ . @ . @ . @ . @ . 05555H, -- . @ . @ . @ . @ . @ . @ . @ . @ 0AAAAH -- @ . @ . @ . @ . @ . @ . @ . @ . ]; desktopGray: GrayArray ~ [ 01111H, -- . . . @ . . . @ . . . @ . . . @ 01111H, -- . . . @ . . . @ . . . @ . . . @ 04444H, -- . @ . . . @ . . . @ . . . @ . . 04444H, -- . @ . . . @ . . . @ . . . @ . . 01111H, -- . . . @ . . . @ . . . @ . . . @ 01111H, -- . . . @ . . . @ . . . @ . . . @ 04444H, -- . @ . . . @ . . . @ . . . @ . . 04444H, -- . @ . . . @ . . . @ . . . @ . . 01111H, -- . . . @ . . . @ . . . @ . . . @ 01111H, -- . . . @ . . . @ . . . @ . . . @ 04444H, -- . @ . . . @ . . . @ . . . @ . . 04444H, -- . @ . . . @ . . . @ . . . @ . . 01111H, -- . . . @ . . . @ . . . @ . . . @ 01111H, -- . . . @ . . . @ . . . @ . . . @ 04444H, -- . @ . . . @ . . . @ . . . @ . . 04444H -- . @ . . . @ . . . @ . . . @ . . ]; Case: TYPE ~ {nil, constant, gray, sampled}; defaultHalftone: HalftoneParameters _ [dotsPerInch: 18, angle: 30, shape: 0.5]; Data: TYPE ~ REF DataRep; DataRep: TYPE ~ RECORD[ frame: ImagerPixelMap.PixelMap, -- the bitmap pixelsPerInch: REAL, -- declared resolution <> case: Case _ nil, -- what type of color function: ImagerPixelMap.Function _ [null, null], -- bitblt function gray: GrayArray _ ALL[0] -- bitblt gray block <> <> <> <> <> <> <> <> <> <> <> ]; class: ImagerDevice.Class ~ NEW[ImagerDevice.ClassRep _ [ type: $LFDisplay, SetColor: SetColor, SetPriority: SetPriority, SetHalftone: SetHalftone, MaskRuns: MaskRuns ]]; <> <> <<>> defaultPixelsPerInch: REAL ~ 72; Create: PUBLIC PROC[frame: ImagerPixelMap.PixelMap, pixelsPerInch: REAL _ defaultPixelsPerInch] RETURNS[Device] ~ { data: Data ~ NEW[DataRep _ [frame: frame, pixelsPerInch: pixelsPerInch]]; surfaceToDevice: Transformation ~ ImagerTransformation.Translate[[frame.sSize, 0]]; surfaceToDevice.ApplyPreRotate[90]; <> <> RETURN[NEW[ImagerDevice.DeviceRep _ [class: class, clipBox: [sMin: 0, fMin: 0, sSize: frame.sSize, fSize: frame.fSize], surfaceToDevice: surfaceToDevice, surfaceUnitsPerInch: [pixelsPerInch, pixelsPerInch], surfaceUnitsPerPixel: 1, data: data]]]; }; <> <> <> <<>> <> <> <> <> <> <> <> <> <> <<};>> <<>> SetColor: PROC[device: Device, color: Color, viewToDevice: Transformation] ~ { data: Data ~ NARROW[device.data]; WITH color SELECT FROM color: ConstantColor => { data.function _ [null, null]; SELECT color FROM ImagerColor.black => { data.gray _ ALL[177777B]; data.case _ constant }; ImagerColor.white => { data.gray _ ALL[0]; data.case _ constant }; ENDCASE => { data.gray _ checkeredGray; data.case _ gray }; <> }; < {>> <> <> <> <> <> <> <> <> <> <> <> <> < {>> <> <<};>> < {>> <> <> <> <> <> <> <> <> <> <<};>> < {>> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <<};>> < ERROR; -- unknown ColorOperator>> <> <> <> <> <> <<};>> ENDCASE => ERROR; -- unknown color variant }; SetPriority: PROC[device: Device, priorityImportant: BOOL] ~ { }; SetHalftone: PROC[device: Device, halftone: HalftoneParameters] ~ { data: Data ~ NARROW[device.data]; <> }; nullBitBltTable: PrincOps.BitBltTable ~ [ dst: [word: NIL, bit: 0], dstBpl: 0, src: [word: NIL, bit: 0], srcDesc: [srcBpl[0]], width: 0, height: 0, flags: []]; 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]; frame: ImagerPixelMap.PixelMap ~ data.frame; SELECT data.case FROM nil => ERROR; -- color not initialized constant, gray => TRUSTED { bbspace: PrincOps.BBTableSpace; bb: PrincOps.BitBltTablePtr ~ PrincOpsUtils.AlignedBBTable[@bbspace]; gray: LONG POINTER ~ LOOPHOLE[@data.gray]; base: LONG POINTER ~ frame.refRep.pointer; rast: CARDINAL ~ frame.refRep.rast; runConstant: PROC[sMin, fMin: INTEGER, fSize: NAT] ~ TRUSTED { f: NAT ~ Check[fMin, frame.fSize]; s: NAT ~ Check[sMin, frame.sSize]; bb.dst.word _ base+Basics.LongMult[s, rast]+f/Basics.bitsPerWord; bb.dst.bit _ f MOD Basics.bitsPerWord; bb.width _ Check[fSize, frame.fSize-f]; bb.height _ Check[1, frame.sSize-s]; PrincOpsUtils.BITBLT[bb]; }; runGray: PROC[sMin, fMin: INTEGER, fSize: NAT] ~ TRUSTED { f: NAT ~ Check[fMin, frame.fSize]; s: NAT ~ Check[sMin, frame.sSize]; bb.dst.word _ base+Basics.LongMult[s, rast]+f/Basics.bitsPerWord; bb.dst.bit _ bb.src.bit _ f MOD Basics.bitsPerWord; bb.src.word _ gray+(bb.srcDesc.gray.yOffset _ s MOD grayHeight); bb.width _ Check[fSize, frame.fSize-f]; bb.height _ Check[1, frame.sSize-s]; PrincOpsUtils.BITBLT[bb]; }; bb^ _ nullBitBltTable; bb.dstBpl _ rast*Basics.bitsPerWord; bb.src.word _ gray; bb.src.bit _ 0; bb.srcDesc.gray _ [yOffset: 0, widthMinusOne: 0, heightMinusOne: grayHeight-1]; bb.flags _ [direction: forward, disjoint: TRUE, gray: TRUE, srcFunc: data.function.srcFunc, dstFunc: data.function.dstFunc]; runs[IF data.case=constant THEN runConstant ELSE runGray]; }; < {>> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <<};>> <> <<};>> ENDCASE => ERROR; -- illegal case }; <<>> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <<};>> <> <> <> <> <> <> <<};>> <<>> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <<};>> <> <> <> <> <> <> <> <> <<};>> <<>> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <<};>> <> <> <> <> <> <> <<};>> <<>> END.