ImagerGrayImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Last edited by: Mik Lamming - September 30, 1986 9:06:04 am PDT
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;
Must use a version of ImagerRasterImpl that allows MaskBoxes and MaskBits to be NIL.
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: BOOLFALSE, -- special case for sampled black clear.
flags: PrincOps.BitBltFlags ← [], -- bitblt flags
grayWord: WORD ← 0, -- bitblt gray word
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: BOOLTRUE, blackBackground: BOOLFALSE] 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: REFNIL, cacheFonts: BOOLTRUE] 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 };
IF x IN[0..max] THEN RETURN[x] ELSE ERROR RuntimeError.BoundsFault
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]~ {
bounds are in device coordinates.
rect is in pixel coordinates.
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 dsmin<ssmax AND dsmax>ssmin THEN {
bb.flags.disjoint ← FALSE;
IF dsmin=ssmin AND dfmin<sfmax AND dfmax>sfmin 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.