DIRECTORY Basics USING [BITSHIFT, bitsPerWord, CARD, LongDivMod, LongMult, LongNumber, RawWords], FunctionCache USING [Cache, CompareProc, GlobalCache, Insert, Lookup], Imager USING [ClassRep, Context, DoSaveAll, Error, ScaleT], ImagerCache USING [GetNamedCache, Ref], ImagerColorDefs USING [Color, ColorOperator, ConstantColor, ConstantColorImplRep, SampledColor], ImagerColorOperator USING [GetColorOperatorClass, Mapper, MapPixels, NewMapper], ImagerColorPrivate USING [ConstantColorClass, ConstantColorClassRep, ConstantColorImpl, ConstantColorImplRep], ImagerDevice USING [BoxProc, Class, ClassRep, Device, DeviceBox, DeviceRep, HalftoneParameters, RunProc], ImagerGray USING [], ImagerOps USING [PixelArrayFromPixelMaps], ImagerPixelArray USING [GetPixels, MaxSampleValue], ImagerPixelArrayDefs USING [PixelArray], ImagerPixelMap USING [BoundedWindow, Clear, Clip, Copy, Create, DeviceRectangle, Fill, PixelMap, PixelMapRep, ShiftMap], ImagerRaster USING [Create], ImagerRasterPrivate USING [Data, DeviceRectangle], ImagerSample USING [GetPointer, GetPointSamples, NewBuffer, Sample, SampleBuffer, Sampler, SamplerRep, SetSamplerIncrements, SetSamplerPosition, UnsafePutF, UnsafeSamples], ImagerTransformation USING [ApplyPreRotate, Cat, Concat, Invert, Rectangle, Transformation, TransformRectangle, Translate], PixelMapOps USING [], PrincOps USING [BBTableSpace, BitBltFlags, BitBltTable, BitBltTablePtr, op, zBNDCK, zINC], PrincOpsUtils USING [AlignedBBTable, BITBLT, LongZero], Real USING [RoundC], Vector2 USING [VEC]; ImagerGrayImpl: CEDAR PROGRAM IMPORTS Basics, FunctionCache, Imager, ImagerCache, ImagerColorOperator, ImagerPixelArray, ImagerPixelMap, ImagerRaster, ImagerSample, ImagerTransformation, PrincOpsUtils, Real, ImagerOps EXPORTS ImagerGray, ImagerColorDefs ~ BEGIN VEC: TYPE ~ Vector2.VEC; Transformation: TYPE ~ ImagerTransformation.Transformation; Color: TYPE ~ ImagerColorDefs.Color; ConstantColor: TYPE ~ ImagerColorDefs.ConstantColor; SampledColor: TYPE ~ ImagerColorDefs.SampledColor; ColorOperator: TYPE ~ ImagerColorDefs.ColorOperator; PixelArray: TYPE ~ ImagerPixelArrayDefs.PixelArray; PixelMap: TYPE ~ ImagerPixelMap.PixelMap; DeviceRectangle: TYPE ~ ImagerPixelMap.DeviceRectangle; Sample: TYPE ~ ImagerSample.Sample; Sampler: TYPE ~ ImagerSample.Sampler; SampleBuffer: TYPE ~ ImagerSample.SampleBuffer; UnsafeSamples: TYPE ~ ImagerSample.UnsafeSamples; DeviceBox: TYPE ~ ImagerDevice.DeviceBox; Rectangle: TYPE ~ ImagerTransformation.Rectangle; Context: TYPE ~ Imager.Context; Device: TYPE ~ ImagerDevice.Device; RunProc: TYPE ~ ImagerDevice.RunProc; BoxProc: TYPE ~ ImagerDevice.BoxProc; ConstantColorImpl: TYPE ~ ImagerColorPrivate.ConstantColorImpl; ConstantColorImplRep: PUBLIC TYPE ~ ImagerColorPrivate.ConstantColorImplRep; ConstantColorClass: TYPE ~ ImagerColorPrivate.ConstantColorClass; ConstantColorClassRep: PUBLIC TYPE ~ ImagerColorPrivate.ConstantColorClassRep; bitsPerWord: NAT ~ Basics.bitsPerWord; class: ImagerDevice.Class ~ NEW[ImagerDevice.ClassRep _ [ type: $Gray, SetColor: GraySetColor, SetPriority: GraySetPriority, SetHalftone: GraySetHalftone, MaskRuns: GrayMaskRuns, MaskBoxes: NIL, MaskBits: NIL, MoveBoxes: GrayMoveBoxes ]]; Lg: PROC [n: NAT] RETURNS [NAT] ~ { RETURN[SELECT n FROM 1 => 0, 2 => 1, 4 => 2, 8 => 3, 16 => 4, ENDCASE => ERROR] }; fontCacheID: ATOM ~ $Gray; fontCacheSize: NAT _ 4000; fontRastWeight: REAL _ 0.0; Case: TYPE ~ {nil, constant, stipple, sampled}; StippleArray: TYPE ~ PACKED ARRAY [0..16) OF WORD; Data: TYPE ~ REF DataRep; DataRep: TYPE ~ RECORD[ component: ATOM, pixelMap: ImagerPixelMap.PixelMap, maxValue: Sample, sOrigin, fOrigin: INTEGER, -- used for providing d to change proc. deviceToPixel: Transformation, change: PROC[changeData: REF, d: DeviceRectangle, action: PROC], changeData: REF, case: Case _ nil, -- what type of color zerosAreClear: BOOL _ FALSE, -- special case for sampled black clear. flags: PrincOps.BitBltFlags _ [], -- bitblt flags constant: Sample _ 0, -- for case = constant stipple: StippleArray _ ALL[0], -- stipple pattern fTileOrg: NAT _ 0, sTileOrg: NAT _ 0, sampledColor: ImagerColorDefs.SampledColor _ NIL, -- sampled color sampledColorData: SampledColorData _ NIL, -- cached data associated with sampledColor paToPixel: Transformation _ NIL, -- transformation from pa coords to pixelMap coords sampBuffer: ImagerSample.SampleBuffer _, -- scan line buffer for samples from sampledColor lineBuffer: ImagerSample.SampleBuffer _, -- for ops that cannot go directly to frame sampler: ImagerSample.Sampler _ -- sampler information ]; SampledColorData: TYPE ~ REF SampledColorDataRep; SampledColorDataRep: TYPE ~ RECORD [ source: ImagerPixelMap.PixelMap, key: SampledColorKey ]; MakePixelArray: PUBLIC PROC [action: PROC [Context], sSize, fSize: NAT, components: LIST OF ATOM, viewToPixel: Transformation _ NIL, initialScale: REAL _ 1.0, lgBitsPerSample: NAT _ 3, cacheFonts: BOOL _ TRUE, blackBackground: BOOL _ FALSE] RETURNS [PixelArray] ~ { pixelMap: PixelMap ~ ImagerPixelMap.Create[lgBitsPerSample, [0, 0, sSize, fSize]]; c: Context ~ Create[pixelMap: pixelMap, component: $Intensity, viewToPixel: viewToPixel, initialScale: initialScale, change: NIL, changeData: NIL, cacheFonts: cacheFonts]; proc: PROC ~ {action[c]}; list: LIST OF PixelMap _ NIL; last: LIST OF PixelMap _ NIL; FOR a: LIST OF ATOM _ components, a.rest UNTIL a=NIL DO pm: PixelMap; IF blackBackground THEN ImagerPixelMap.Clear[pixelMap] ELSE ImagerPixelMap.Fill[pixelMap, [0, 0, sSize, fSize], CARDINAL.LAST]; SetComponent[c, a.first]; Imager.DoSaveAll[c, proc]; IF a.rest = NIL THEN pm _ pixelMap ELSE pm _ ImagerPixelMap.Copy[pixelMap]; IF last = NIL THEN {list _ last _ LIST[pm]} ELSE {last.rest _ LIST[pm]; last _ last.rest}; ENDLOOP; RETURN [ImagerOps.PixelArrayFromPixelMaps[list, ImagerTransformation.Invert[viewToPixel]]] }; SetComponent: PUBLIC PROC [context: Context, component: ATOM] ~ { WITH context.data SELECT FROM rasterData: ImagerRasterPrivate.Data => { WITH rasterData.device.data SELECT FROM data: Data => { data.component _ component; }; ENDCASE => NULL; }; ENDCASE => NULL; }; LikeScreen: PUBLIC PROC [sSize: NAT] RETURNS [Transformation] ~ { m: Transformation ~ ImagerTransformation.Translate[[sSize, 0]]; m.ApplyPreRotate[90]; RETURN [m]; }; Create: PUBLIC PROC [pixelMap: PixelMap, component: ATOM, viewToPixel: Transformation _ NIL, initialScale: REAL _ 1.0, change: PROC[changeData: REF, d: DeviceRectangle, action: PROC] _ NIL, changeData: REF _ NIL, cacheFonts: BOOL _ TRUE] RETURNS [context: Context] ~ { device: ImagerDevice.Device ~ DeviceFromPixelMap[pixelMap, component, viewToPixel, change, changeData]; fontCache: ImagerCache.Ref ~ IF cacheFonts THEN ImagerCache.GetNamedCache[atom: fontCacheID, createSize: fontCacheSize] ELSE NIL; context _ ImagerRaster.Create[device: device, pixelUnits: TRUE, fontCache: fontCache, rastWeight: fontRastWeight]; Imager.ScaleT[context, initialScale]; }; DeviceBoxFromRectangle: PROC [r: Rectangle] RETURNS [DeviceBox] ~ { smin: CARDINAL _ Real.RoundC[r.x]; fmin: CARDINAL _ Real.RoundC[r.y]; smax: CARDINAL _ Real.RoundC[r.x+r.w]; fmax: CARDINAL _ Real.RoundC[r.y+r.h]; IF smin > smax THEN {t: CARDINAL _ smin; smin _ smax; smax _ t}; IF fmin > fmax THEN {t: CARDINAL _ fmin; fmin _ fmax; fmax _ t}; RETURN [[smin: smin, fmin: fmin, smax: smax, fmax: fmax]] }; DBFromDR: PROC [r: DeviceRectangle] RETURNS [DeviceBox] ~ { RETURN [[smin: r.sMin, fmin: r.fMin, smax: r.sMin+r.sSize, fmax: r.fMin+r.fSize]] }; DeviceFromPixelMap: PROC [pixelMap: PixelMap, component: ATOM, viewToPixel: Transformation, change: PROC[changeData: REF, d: DeviceRectangle, action: PROC], changeData: REF] RETURNS [ImagerDevice.Device] ~ { w: ImagerPixelMap.DeviceRectangle ~ ImagerPixelMap.BoundedWindow[pixelMap]; pm: ImagerPixelMap.PixelMap ~ pixelMap.Clip[w].ShiftMap[-w.sMin, -w.fMin]; maxValue: CARDINAL ~ Basics.BITSHIFT[1, Basics.BITSHIFT[1, pm.refRep.lgBitsPerPixel]]-1; sampBuffer: SampleBuffer ~ ImagerSample.NewBuffer[1, pm.fSize]; lineBuffer: SampleBuffer ~ ImagerSample.NewBuffer[1, pm.fSize]; sampler: ImagerSample.Sampler ~ NEW[ImagerSample.SamplerRep _ []]; pixelToDevice: Transformation ~ ImagerTransformation.Translate[[w.sMin, w.fMin]]; surfaceToDevice: Transformation ~ viewToPixel.Concat[pixelToDevice]; surfaceRectangle: Rectangle ~ ImagerTransformation.TransformRectangle[pixelToDevice, [pm.sMin, pm.fMin, pm.sSize, pm.fSize]]; surface: DeviceBox ~ DeviceBoxFromRectangle[surfaceRectangle]; data: Data ~ NEW[DataRep _ [ component: component, pixelMap: pm, maxValue: maxValue, sOrigin: w.sMin, fOrigin: w.fMin, deviceToPixel: ImagerTransformation.Invert[pixelToDevice], change: change, changeData: changeData, sampBuffer: sampBuffer, lineBuffer: lineBuffer, sampler: sampler ]]; RETURN [NEW[ImagerDevice.DeviceRep _ [class: class, box: surface, surfaceToDevice: surfaceToDevice, surfaceUnitsPerInch: [72, 72], surfaceUnitsPerPixel: 1, data: data]]] }; GraySetPriority: PROC [device: Device, priorityImportant: BOOL] ~ { }; GraySetHalftone: PROC [device: Device, halftone: ImagerDevice.HalftoneParameters] ~ { }; PixelFromIntensity: PROC[i: REAL, maxValue: CARDINAL] RETURNS[CARDINAL] ~ { IF i<=0.0 THEN RETURN[0]; IF i>=1.0 THEN RETURN[maxValue]; RETURN[Real.RoundC[i*maxValue]]; }; GraySetColor: PROC [device: Device, color: Color, viewToDevice: Transformation] ~ { data: Data ~ NARROW[device.data]; data.case _ nil; data.sampledColor _ NIL; data.sampledColorData _ NIL; IF data.component = $Alpha THEN { data.case _ constant; data.constant _ data.maxValue; RETURN; }; WITH color SELECT FROM color: ConstantColor => { MakeSampleFromColor: PROC [c: REAL] RETURNS [Sample] ~ { RETURN [ SELECT data.maxValue FROM 1 => PixelFromIntensity[c, 1] * 0FFFFH, 3 => PixelFromIntensity[c, 3] * 05555H, 15 => PixelFromIntensity[c, 15] * 01111H, 255 => PixelFromIntensity[c, 255] * 0101H, ENDCASE => ERROR ]; }; impl: ConstantColorImpl ~ color.impl; c: REAL; data.case _ constant; data.flags _ [disjoint: TRUE, gray: TRUE, srcFunc: null, dstFunc: null]; WITH impl: impl SELECT FROM stipple => { word: WORD ~ impl.word; SELECT impl.function FROM replace => { data.flags.srcFunc _ complement }; paint => { data.flags.srcFunc _ complement; data.flags.dstFunc _ and }; invert => { data.flags.dstFunc _ xor }; erase => { data.flags.dstFunc _ or }; ENDCASE => ERROR; IF word=WORD.LAST THEN data.constant _ word ELSE { data.stipple _ StippleArrayFromWord[word]; data.case _ stipple }; }; rgb => { SELECT data.component FROM $Intensity => data.constant _ MakeSampleFromColor[impl.Y]; $Red => data.constant _ MakeSampleFromColor[impl.val.R]; $Green => data.constant _ MakeSampleFromColor[impl.val.G]; $Blue => data.constant _ MakeSampleFromColor[impl.val.B]; ENDCASE => ERROR Imager.Error[[$unimplemented, "Unknown component name"]]; }; gray => data.constant _ MakeSampleFromColor[impl.Y] ENDCASE => ERROR; }; color: SampledColor => { pa: PixelArray ~ color.pa; um: Transformation ~ color.um; colorOperator: ColorOperator ~ color.colorOperator; data.sampledColor _ color; data.case _ sampled; data.zerosAreClear _ ImagerColorOperator.GetColorOperatorClass[colorOperator] = $SampledBlackClear; data.paToPixel _ ImagerTransformation.Cat[pa.m, color.um, viewToDevice, data.deviceToPixel]; SetUpSampledColorData[data]; }; ENDCASE => ERROR; -- unknown color variant }; StippleArrayFromWord: PROC [t: WORD] RETURNS[array: StippleArray _ ALL[0]] ~ { bits: PACKED ARRAY [0..16) OF BOOL ~ LOOPHOLE[t]; FOR i: [0..16) IN [0..16) DO IF bits[i] THEN array[i] _ WORD.LAST ENDLOOP; }; me: REF TEXT ~ "Gray"; -- a globally unique REF for use as a clientID in the global cache. SampledColorKey: TYPE ~ RECORD [pa: PixelArray, component: ATOM]; SetUpSampledColorData: PROC [data: Data] ~ { cache: FunctionCache.Cache _ FunctionCache.GlobalCache[]; color: SampledColor ~ data.sampledColor; pa: PixelArray ~ color.pa; component: ATOM ~ data.component; key: SampledColorKey ~ [data.sampledColor.pa, data.component]; compare: FunctionCache.CompareProc ~ {RETURN [ WITH argument SELECT FROM p: REF SampledColorKey => (p^=key), ENDCASE => FALSE ]}; scd: SampledColorData _ NARROW[FunctionCache.Lookup[cache, compare, me].value]; IF color = NIL THEN ERROR; IF scd = NIL THEN TRUSTED { colorOperator: ColorOperator ~ color.colorOperator; samplesPerPixel: NAT ~ pa.samplesPerPixel; sSize: NAT ~ pa.sSize; fSize: NAT ~ pa.fSize; maxIn: Sample ~ ImagerPixelArray.MaxSampleValue[pa, 0]; pixels: SampleBuffer ~ ImagerSample.NewBuffer[samplesPerPixel, fSize]; buffer: SampleBuffer ~ ImagerSample.NewBuffer[1, fSize]; bufferPointer: UnsafeSamples ~ buffer.GetPointer[0, 0, fSize]; mapper: ImagerColorOperator.Mapper ~ ImagerColorOperator.NewMapper[op: colorOperator, component: data.component, maxIn: maxIn, maxOut: data.maxValue]; t: ImagerPixelMap.PixelMap ~ ImagerPixelMap.Create[data.pixelMap.refRep.lgBitsPerPixel, [0, 0, sSize, fSize]]; line: LONG POINTER TO Basics.RawWords _ t.refRep.pointer; rast: NAT ~ t.refRep.rast; bps: NAT ~ Basics.BITSHIFT[1, t.refRep.lgBitsPerPixel]; sampledColorDataSize: INT _ t.refRep.words+SIZE[ImagerPixelMap.PixelMap]+SIZE[ImagerPixelMap.PixelMapRep]; scd _ NEW[SampledColorDataRep _ [t, key]]; FOR s: NAT IN[0..sSize) DO ImagerPixelArray.GetPixels[pa: pa, s: s, f: 0, buffer: pixels, count: fSize]; ImagerColorOperator.MapPixels[mapper: mapper, pixels: pixels, buffer: buffer, bi: 0, count: fSize]; ImagerSample.UnsafePutF[samples: bufferPointer, count: fSize, s: s, f: 0, base: t.refRep.pointer, wordsPerLine: rast, bitsPerSample: bps]; ENDLOOP; FunctionCache.Insert[cache, NEW[SampledColorKey _ key], scd, sampledColorDataSize, me]; }; data.sampledColorData _ scd; }; Mod: PROC [n: INTEGER, d: NAT] RETURNS [NAT] ~ { nn: Basics.LongNumber _ [li[n]]; IF nn.li < 0 THEN nn.highbits _ nn.highbits + d; RETURN [Basics.LongDivMod[nn.lc, d].remainder]; }; ClearSampleBuffer: PROC[buffer: SampleBuffer, i, j: NAT _ 0, count: NAT] ~ TRUSTED { pointer: LONG POINTER ~ ImagerSample.GetPointer[buffer, i, j, count]; PrincOpsUtils.LongZero[where: pointer, nwords: count*SIZE[Sample]]; }; 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: CARDINAL, max: NAT] RETURNS[NAT] ~ TRUSTED MACHINE CODE { PrincOps.zINC; PrincOps.zBNDCK }; GrayMaskRunsInternal: PROC[data: Data, bounds: DeviceBox, runs: PROC[RunProc]] ~ { bitsPerWord: NAT ~ Basics.bitsPerWord; pixelMap: ImagerPixelMap.PixelMap ~ data.pixelMap; lgBitsPerPixel: NAT ~ pixelMap.refRep.lgBitsPerPixel; base: LONG POINTER ~ pixelMap.refRep.pointer; wordsPerLine: NAT ~ pixelMap.refRep.rast; bitsPerPixel: NAT ~ Basics.BITSHIFT[1, lgBitsPerPixel]; SELECT data.case FROM nil => ERROR; -- color not initialized constant => TRUSTED { bbspace: PrincOps.BBTableSpace; bb: PrincOps.BitBltTablePtr ~ PrincOpsUtils.AlignedBBTable[@bbspace]; grayConstantRun: PROC[sMin, fMin: INTEGER, fSize: NAT] ~ TRUSTED { f: NAT ~ Check[fMin, pixelMap.fSize]; s: NAT ~ Check[sMin, pixelMap.sSize]; line: LONG POINTER ~ base+Basics.LongMult[s, wordsPerLine]; bit: CARDINAL ~ f*bitsPerPixel; bb.dst.word _ line+bit/bitsPerWord; bb.dst.bit _ bit MOD bitsPerWord; bb.width _ Check[fSize, pixelMap.fSize-f]*bitsPerPixel; bb.height _ Check[1, pixelMap.sSize-s]; PrincOpsUtils.BITBLT[bb]; }; bb^ _ nullBitBltTable; bb.dstBpl _ wordsPerLine*bitsPerWord; bb.src.word _ LOOPHOLE[@data.constant]; bb.srcDesc.gray _ [yOffset: 0, widthMinusOne: 0, heightMinusOne: 0]; bb.flags _ data.flags; runs[grayConstantRun]; }; stipple => TRUSTED { bbspace: PrincOps.BBTableSpace; bb: PrincOps.BitBltTablePtr ~ PrincOpsUtils.AlignedBBTable[@bbspace]; srcBase: LONG POINTER ~ LOOPHOLE[@data.stipple]; srcWordsPerLine: NAT ~ (4*bitsPerPixel)/bitsPerWord; grayStippleRun: PROC[sMin, fMin: INTEGER, fSize: NAT] ~ TRUSTED { fmin: NAT ~ Check[fMin, pixelMap.fSize]; fmax: NAT ~ Check[fmin+fSize, pixelMap.fSize]; smin: NAT ~ Check[sMin, pixelMap.sSize]; smax: NAT ~ Check[smin+1, pixelMap.sSize]; dstLine: LONG POINTER ~ base+Basics.LongMult[smin, wordsPerLine]; srcLine: LONG POINTER ~ srcBase+(smin MOD 4)*srcWordsPerLine; FOR f: NAT IN [fmin..MIN[fmin+4, fmax]) DO dstBit: NAT ~ f*bitsPerPixel; srcBit: NAT ~ (f MOD 4)*bitsPerPixel; bb.dst.word _ dstLine+dstBit/bitsPerWord; bb.dst.bit _ dstBit MOD bitsPerWord; bb.src.word _ srcLine+srcBit/bitsPerWord; bb.src.bit _ srcBit MOD bitsPerWord; bb.height _ (fmax-f+3)/4; PrincOpsUtils.BITBLT[bb]; ENDLOOP; }; bb^ _ nullBitBltTable; bb.dstBpl _ 4*bitsPerPixel; bb.srcDesc.gray _ [yOffset: 0, widthMinusOne: 0, heightMinusOne: 0]; bb.width _ bitsPerPixel; bb.flags _ data.flags; runs[grayStippleRun]; }; sampled => { graySampledRun: PROC[sMin, fMin: INTEGER, fSize: NAT] ~ CHECKED { s: NAT ~ Check[sMin, pixelMap.sSize]; f: NAT ~ Check[fMin, pixelMap.fSize]; count: NAT ~ Check[fSize, pixelMap.fSize-f]; samples: ImagerSample.UnsafeSamples ~ buffer.GetPointer[0, f, count]; ImagerSample.GetPointSamples[sampler: sampler, s: s, f: f, buffer: buffer, bi: 0, bj: f, count: count]; TRUSTED { ImagerSample.UnsafePutF[samples: samples, count: count, base: base, wordsPerLine: wordsPerLine, bitsPerSample: 8, s: s, f: f, dstFunc: null]}; }; t: PixelMap _ data.sampledColorData.source; buffer: SampleBuffer ~ data.sampBuffer; sampler: ImagerSample.Sampler ~ data.sampler; sampler.base _ t.refRep.pointer; sampler.wordsPerLine _ t.refRep.rast; sampler.bitsPerSample _ Basics.BITSHIFT[1, t.refRep.lgBitsPerPixel]; sampler.sMin _ t.sMin; sampler.fMin _ t.fMin; sampler.sSize _ t.sSize; sampler.fSize _ t.fSize; ImagerSample.SetSamplerIncrements[sampler, data.paToPixel]; ImagerSample.SetSamplerPosition[sampler: sampler, m: data.paToPixel, s: bounds.smin, f: bounds.fmin]; runs[graySampledRun]; }; ENDCASE => ERROR; -- illegal case }; RectFromDeviceBox: PROC[data: Data, bounds: DeviceBox] RETURNS [rect: DeviceRectangle]~ { smin: CARDINAL ~ bounds.smin; smax: CARDINAL ~ bounds.smax; fmin: CARDINAL ~ bounds.fmin; fmax: CARDINAL ~ bounds.fmax; rect.sMin _ data.sOrigin + smin; rect.fMin _ data.fOrigin + fmin; rect.sSize _ smax - smin; rect.fSize _ fmax - fmin; }; GrayMaskRuns: PROC[device: Device, bounds: DeviceBox, runs: PROC[RunProc]] ~ { data: Data ~ NARROW[device.data]; smoothMaskRunsAction: PROC ~ { GrayMaskRunsInternal[data, bounds, runs] }; IF data.change = NIL THEN GrayMaskRunsInternal[data, bounds, runs] ELSE data.change[data.changeData, RectFromDeviceBox[data, bounds], smoothMaskRunsAction]; }; GrayMoveBoxes: PROC [device: Device, ts, tf: INTEGER, boxes: PROC[BoxProc]] ~ TRUSTED { data: Data ~ NARROW[device.data]; bitsPerWord: NAT ~ Basics.bitsPerWord; pixelMap: ImagerPixelMap.PixelMap ~ data.pixelMap; lgBitsPerPixel: NAT ~ pixelMap.refRep.lgBitsPerPixel; base: LONG POINTER ~ pixelMap.refRep.pointer; wordsPerLine: NAT ~ pixelMap.refRep.rast; bitsPerPixel: NAT ~ Basics.BITSHIFT[1, lgBitsPerPixel]; bbspace: PrincOps.BBTableSpace; bb: PrincOps.BitBltTablePtr ~ PrincOpsUtils.AlignedBBTable[@bbspace]; moveBox: PROC[box: DeviceBox] ~ TRUSTED { dfmin: NAT ~ Check[box.fmin, pixelMap.fSize]; dsmin: NAT ~ Check[box.smin, pixelMap.sSize]; dfmax: NAT ~ Check[box.fmax, pixelMap.fSize]; dsmax: NAT ~ Check[box.smax, pixelMap.sSize]; sfmin: NAT ~ dfmin-tf; ssmin: NAT ~ dsmin-ts; sfmax: NAT ~ dfmax-tf; ssmax: NAT ~ dsmax-ts; dstBit: CARDINAL ~ dfmin*bitsPerPixel; srcBit: CARDINAL ~ sfmin*bitsPerPixel; bpl: INTEGER _ wordsPerLine*bitsPerWord; ss: NAT _ ssmin; ds: NAT _ dsmin; bb.flags _ [disjoint: TRUE, disjointItems: TRUE, direction: forward, gray: FALSE]; IF dsminssmin THEN { bb.flags.disjoint _ FALSE; IF dsmin=ssmin AND dfminsfmin THEN bb.flags.disjointItems _ FALSE; IF dsmin>ssmin OR (dsmin=ssmin AND dfmin>sfmin) THEN { bb.flags.direction _ backward; bpl _ -bpl; ss _ ssmax-1; ds _ dsmax-1; }; }; bb.dst.word _ base+Basics.LongMult[ds, wordsPerLine]+dstBit/bitsPerWord; bb.dst.bit _ dstBit MOD bitsPerWord; bb.dstBpl _ bpl; bb.src.word _ base+Basics.LongMult[ss, wordsPerLine]+srcBit/bitsPerWord; bb.src.bit _ srcBit MOD bitsPerWord; bb.srcDesc.srcBpl _ bpl; bb.width _ (dfmax-dfmin)*bitsPerPixel; bb.height _ dsmax-dsmin; PrincOpsUtils.BITBLT[bb] }; bb^ _ nullBitBltTable; boxes[moveBox]; }; END. ˜ImagerGrayImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Last edited by: Mik Lamming - September 30, 1986 9:06:04 am PDT Must use a version of ImagerRasterImpl that allows MaskBoxes and MaskBits to be NIL. grayWord: WORD _ 0, -- bitblt gray word IF x IN[0..max] THEN RETURN[x] ELSE ERROR RuntimeError.BoundsFault bounds are in device coordinates. rect is in pixel coordinates. Κ‡˜code™Kšœ Οmœ1™˜>šœ žœ ˜Kšœ˜Kšœ ˜ K˜Kšœ˜Kšœ˜Kšœ:˜:Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜—šžœžœ(˜3Kšœ ˜ Kšœ!˜!Kšœ˜Kšœ˜Kšœ ˜ —Kšœ˜K˜—š‘œžœ%žœ˜CKšœ˜K˜—š‘œžœ@˜UK˜K˜—š ‘œžœžœ žœžœžœ˜KKšžœžœžœ˜Kšžœžœžœ ˜ Kšžœ˜ K˜K˜—š‘ œžœA˜SKšœ žœ˜!Kšœ˜Kšœžœ˜Kšœžœ˜šžœžœ˜!Kšœ˜Kšœ˜Kšžœ˜Kšœ˜—šžœžœž˜˜š‘œžœžœžœ ˜8šžœ˜šžœž˜Kšœ'˜'Kšœ'˜'Kšœ)˜)Kšœ*˜*Kšžœž˜—K˜—K˜—K˜%Kšœžœ˜Kšœ˜Kšœžœžœ ˜Hšžœ žœž˜šœ ˜ Kšœžœ ˜šžœž˜Kšœ/˜/KšœG˜GKšœ'˜'Kšœ%˜%Kšžœžœ˜—Kšžœžœžœžœ˜+KšžœD˜HKšœ˜—šœ˜šžœž˜Kšœ:˜:Kšœ8˜8Kšœ:˜:Kšœ9˜9Kšžœžœ:˜J—Kšœ˜—Kšœ3˜3Kšžœžœ˜—K˜—šœ˜Kšœ˜Kšœ˜Kšœ3˜3Kšœ˜K˜Kšœc˜cKšœ\˜\Kšœ˜K˜—Kšžœžœ’˜*—Kšœ˜K˜—š ‘œžœžœžœžœ˜NKš œžœžœ žœžœžœ˜1Kšžœ žœ žœžœ žœ žœžœžœ˜JK˜K˜—šœžœžœ ’C˜ZK˜—šœžœžœžœ˜AK˜—š‘œžœ˜,Kšœ9˜9Kšœ(˜(Kšœ˜Kšœ žœ˜!Kšœ>˜>š‘œžœ˜.šžœ žœž˜Kšœžœ˜#Kšžœž˜—Kšœ˜—Kšœžœ1˜OKšžœ žœžœžœ˜šžœžœžœžœ˜Kšœ3˜3Kšœžœ˜*Kšœžœ ˜Kšœžœ ˜Kšœ7˜7KšœF˜FKšœ8˜8K˜>Kšœ–˜–Kšœo˜oKšœžœžœžœ$˜9Kšœžœ˜Kšœžœ žœ˜7Kšœžœžœžœ˜jKšœžœ!˜*šžœžœžœ ž˜KšœM˜MKšœc˜cK•StartOfExpansionρ[samples: ImagerSample.UnsafeSamples, count: NAT, s: NAT _ 0, f: NAT _ 0, base: LONG POINTER, wordsPerLine: NAT, bitsPerSample: ImagerSample.BitsPerSample, srcFunc: PrincOps.SrcFunc _ null, dstFunc: PrincOps.DstFunc _ null]šœŠ˜ŠKšžœ˜—Kšœžœ8˜WKšœ˜—K˜Kšœ˜K˜—š ‘œžœžœžœžœžœ˜0Kšœ ˜ Kšžœ žœ˜0Kšžœ)˜/Kšœ˜K˜—š ‘œžœžœ žœžœ˜TKšœ žœžœ0˜EKšœ5žœ ˜CKšœ˜K˜—šœ)˜)Kšœ žœ˜$Kšœ žœ ˜/Kšœ˜Kšœ˜K˜—š ‘œžœžœžœžœžœ˜1Kšžœžœžœ$˜8Kš žœžœ žœžœžœžœ™BK˜—š‘œžœ&žœ˜RKšœ žœ˜&Kšœ2˜2Kšœžœ"˜5Kšœžœžœ˜-Kšœžœ˜)Kšœžœ žœ˜7šžœ ž˜Kšœžœ’˜&šœ žœ˜K˜KšœE˜Eš ‘œžœ žœ žœžœ˜BKšœžœ˜%Kšœžœ˜%Kšœžœžœ)˜;Kšœžœ˜Kšœ#˜#Kšœžœ ˜!Kšœ7˜7Kšœ'˜'Kšœžœ˜K˜—Kšœ˜Kšœ%˜%Kšœžœ˜'KšœD˜DKšœ˜Kšœ˜K˜—šœ žœ˜K˜KšœE˜EKšœ žœžœžœ˜0Kšœžœ ˜4š ‘œžœ žœ žœžœ˜AKšœžœ˜(Kšœžœ%˜.Kšœžœ˜(Kšœžœ!˜*Kšœ žœžœ,˜AKšœ žœžœžœ˜=š žœžœžœžœž˜*Kšœžœ˜Kšœžœžœ˜%Kšœ)˜)Kšœžœ ˜$Kšœ)˜)Kšœžœ ˜$Kšœ˜Kšœžœ˜Kšžœ˜—K˜—Kšœ˜Kšœ˜KšœD˜DKšœ˜Kšœ˜Kšœ˜K˜—˜ š ‘œžœ žœ žœžœ˜AKšœžœ˜%Kšœžœ˜%Kšœžœ"˜,KšœE˜EKšœh˜hKšžœ’˜™K˜—Kšœ+˜+Kšœ'˜'Kšœ-˜-Kšœ ˜ Kšœ%˜%Kšœžœ˜DKšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ;˜;Kšœf˜fKšœ˜K˜—Kšžœžœ’˜!—K˜K˜—š‘œžœ žœ˜YKšœ!™!Kšœ™Kšœžœ˜Kšœžœ˜Kšœžœ˜Kšœžœ˜Kšœ ˜ Kšœ ˜ Kšœ˜Kšœ˜Kšœ˜K˜—š‘ œžœ*žœ˜NKšœ žœ˜!Kšœžœ0˜JKšžœžœžœ)˜BKšžœU˜YK˜K˜—š ‘ œžœžœ žœ žœ˜WKšœ žœ˜!Kšœ žœ˜&Kšœ2˜2Kšœžœ"˜5Kšœžœžœ˜-Kšœžœ˜)Kšœžœ žœ˜7K˜KšœE˜Eš‘œžœžœ˜)Kšœžœ#˜-Kšœžœ#˜-Kšœžœ#˜-Kšœžœ#˜-Kšœžœ ˜Kšœžœ ˜Kšœžœ ˜Kšœžœ ˜Kšœžœ˜&Kšœžœ˜&Kšœžœ˜(Kšœžœ ˜Kšœžœ ˜Kšœžœžœžœ˜Ršžœ žœ žœ˜%Jšœžœ˜Kš žœ žœ žœ žœžœ˜Sšžœ žœžœžœ˜6JšœF˜FK˜—K˜—KšœH˜HKšœžœ ˜$Kšœ˜KšœH˜HKšœžœ ˜$Kšœ˜Kšœ&˜&Kšœ˜Kšœžœ˜K˜—Kšœ˜K˜K˜—K˜—K˜Kšžœ˜—…—Nςf