ImagerColor24DeviceImpl.mesa
Copyright © 1984, 1985 by Xerox Corporation. All rights reserved.
Michael Plass, August 13, 1985 10:50:50 am PDT
Doug Wyatt, May 30, 1985 11:25:23 pm PDT
DIRECTORY
Basics USING [bitsPerWord, BYTE, LongMult],
FunctionCache USING [Cache, GlobalCache, CompareProc, Insert, Lookup],
ImagerColorDefs USING [Color, ColorOperator, ConstantColor, ConstantColorImplRep, SampledColor],
ImagerColorOperator USING [GetColorOperatorClass, Mapper, MapPixels, NewMapper],
ImagerColorPrivate USING [ConstantColorClass, ConstantColorClassRep, ConstantColorImpl, ConstantColorImplRep],
ImagerColor24DevicePrivate USING [Case, StippleArray, Channel, bitsPerPixelA, bitsPerPixelB, Data, DataRep, SampledColorData, SampledColorDataRep],
ImagerDevice USING [BoxProc, Class, ClassRep, Device, DeviceBox, DeviceRep, HalftoneParameters, RunProc],
ImagerPixelArray USING [GetPixels, MaxSampleValue],
ImagerPixelArrayDefs USING [PixelArray],
ImagerPixelMap USING [Create, PixelMap],
ImagerRaster USING [],
ImagerSample USING [GetPointer, GetPointSamples, NewBuffer, Sample, SampleBuffer, Sampler, SamplerRep, SetSamplerIncrements, SetSamplerPosition, UnsafePutF, UnsafePutS, UnsafeSamples],
ImagerTransformation USING [ApplyPreRotate, Cat, Transformation, Translate],
PrincOps USING [BBTableSpace, BitBltFlags, BitBltTable, BitBltTablePtr, DstFunc, op, zBNDCK, zINC],
PrincOpsUtils USING [AlignedBBTable, BITBLT, ByteBlt, LongCopy],
Real USING [RoundC],
Terminal USING [FrameBuffer, GetColorFrameBufferA, GetColorFrameBufferB, ModifyColorFrame, Virtual],
Vector2 USING [VEC];
ImagerColor24DeviceImpl: CEDAR PROGRAM
IMPORTS Basics, FunctionCache, ImagerColorOperator, ImagerPixelArray, ImagerPixelMap, ImagerSample, ImagerTransformation, PrincOpsUtils, Real, Terminal
EXPORTS ImagerColorDefs, ImagerRaster
~ BEGIN OPEN ImagerDevice, ImagerColor24DevicePrivate;
BYTE: TYPE ~ Basics.BYTE;
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;
Sample: TYPE ~ ImagerSample.Sample;
SampleBuffer: TYPE ~ ImagerSample.SampleBuffer;
UnsafeSamples: TYPE ~ ImagerSample.UnsafeSamples;
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: $FullColorDisplay,
SetColor: Color24SetColor,
SetPriority: Color24SetPriority,
SetHalftone: Color24SetHalftone,
MaskRuns: Color24MaskRuns,
MaskBoxes: Color24MaskBoxes,
MaskBits: Color24MaskBits,
MoveBoxes: Color24MoveBoxes
]];
NewColor24Device: PUBLIC PROC [terminal: Terminal.Virtual] RETURNS[Device] ~ {
frameA: Terminal.FrameBuffer ~ Terminal.GetColorFrameBufferA[terminal];
frameB: Terminal.FrameBuffer ~ Terminal.GetColorFrameBufferB[terminal];
IF frameA=NIL OR frameA.bitsPerPixel#bitsPerPixelA
OR
frameB=NIL OR frameB.bitsPerPixel#bitsPerPixelB THEN RETURN[NIL]
ELSE {
data: Data ~ NEW[DataRep ← [terminal: terminal, frame: [A: frameA, B: frameB]]];
pixelsPerInch: REAL ~ terminal.colorPixelsPerInch;
surfaceToDevice: Transformation ~ ImagerTransformation.Translate[[frameA.height, 0]];
surfaceToDevice.ApplyPreRotate[90];
RETURN[NEW[ImagerDevice.DeviceRep ← [class: class,
box: [smin: 0, fmin: 0, smax: frameA.height, fmax: frameA.width],
surfaceToDevice: surfaceToDevice,
surfaceUnitsPerInch: [pixelsPerInch, pixelsPerInch],
surfaceUnitsPerPixel: 1,
data: data]]];
};
};
nullBitBltTable: PrincOps.BitBltTable ~ [
dst: [word: NIL, bit: 0], dstBpl: 0,
src: [word: NIL, bit: 0], srcDesc: [srcBpl[0]],
width: 0, height: 0, flags: []
];
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;
};
PixelFromIntensity: PROC[i: REAL] RETURNS[BYTE] ~ {
IF i<=0 THEN RETURN[0];
IF i>=1 THEN RETURN[BYTE.LAST];
RETURN[Real.RoundC[i*BYTE.LAST]];
};
Color24SetColor: PROC [device: Device, color: Color, viewToDevice: Transformation] ~ {
data: Data ~ NARROW[device.data];
WITH color SELECT FROM
color: ConstantColor => {
impl: ConstantColorImpl ~ color.impl;
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.grayWordA ← data.grayWordB ← word
ELSE { data.stipple ← StippleArrayFromWord[word]; data.case ← stipple };
};
rgb => {
pixelR: BYTE ~ PixelFromIntensity[impl.val.R];
pixelG: BYTE ~ PixelFromIntensity[impl.val.G];
pixelB: BYTE ~ PixelFromIntensity[impl.val.B];
data.grayWordA ← pixelR*400B+pixelG;
data.grayWordB ← pixelB*400B+pixelB;
};
ENDCASE => {
pixel: BYTE ~ PixelFromIntensity[impl.Y];
data.grayWordA ← data.grayWordB ← pixel*400B+pixel;
};
};
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.paToDevice ← ImagerTransformation.Cat[pa.m, color.um, viewToDevice];
IF data.buffer=NIL THEN data.buffer ← ImagerSample.NewBuffer[1, data.frame[A].width];
};
ENDCASE => ERROR; -- unknown color variant
};
Color24SetPriority: PROC[device: Device, priorityImportant: BOOL] ~ {
};
Color24SetHalftone: PROC[device: Device, halftone: HalftoneParameters] ~ {
data: Data ~ NARROW[device.data];
data.halftone ← halftone;
};
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
--ImagerMask.--RunsFromBox: PROC[box: DeviceBox, run: RunProc] ~ {
fMin: INTEGER ~ box.fmin;
fSize: NAT ~ box.fmax-box.fmin;
FOR s: CARDINAL IN[box.smin..box.smax) DO
run[sMin: s, fMin: fMin, fSize: fSize];
ENDLOOP;
};
--ImagerMask.--RunsFromBits: PROC[base: LONG POINTER, wordsPerLine: NAT,
sBits, fBits, sRuns, fRuns, sSize, fSize: NAT, run: RunProc] ~ TRUSTED {
FOR s: NAT IN[0..sSize) DO
Bit: TYPE ~ [0..1];
BitSequence: TYPE ~ RECORD[PACKED SEQUENCE COMPUTED CARDINAL OF Bit];
bits: LONG POINTER TO BitSequence ~ base+Basics.LongMult[sBits+s, wordsPerLine];
state: {off, on} ← off;
f0: NAT ← 0;
FOR f: NAT IN[0..fSize) DO
bit: Bit ~ bits[fBits+f];
SELECT state FROM
off => IF bit=1 THEN { f0 ← f; state ← on };
on => IF bit=0 THEN { run[sMin: sRuns+s, fMin: fRuns+f0, fSize: f-f0]; state ← off };
ENDCASE => ERROR;
ENDLOOP;
IF state=on THEN run[sMin: sRuns+s, fMin: fRuns+f0, fSize: fSize-f0];
ENDLOOP;
};
Color24MaskRunsInternal: PROC[data: Data, bounds: DeviceBox, runs: PROC[RunProc]] ~ {
frameA: Terminal.FrameBuffer ~ data.frame[A];
baseA: LONG POINTER ~ frameA.base;
wordsPerLineA: NAT ~ frameA.wordsPerLine;
frameB: Terminal.FrameBuffer ~ data.frame[B];
baseB: LONG POINTER ~ frameB.base;
wordsPerLineB: NAT ~ frameB.wordsPerLine;
SELECT data.case FROM
nil => ERROR; -- color not initialized
constant => TRUSTED {
bbspace: PrincOps.BBTableSpace;
bb: PrincOps.BitBltTablePtr ~ PrincOpsUtils.AlignedBBTable[@bbspace];
color24ConstantRun: PROC[sMin, fMin: INTEGER, fSize: NAT] ~ TRUSTED {
fmin: NAT ~ Check[fMin, frameA.width];
fmax: NAT ~ Check[fmin+fSize, frameA.width];
smin: NAT ~ Check[sMin, frameA.height];
smax: NAT ~ Check[smin+1, frameA.height];
bb.dst.word ← baseA+Basics.LongMult[smin, wordsPerLineA]+fmin;
bb.dst.bit ← 0;
bb.dstBpl ← wordsPerLineA*bitsPerWord;
bb.src.word ← LOOPHOLE[@data.grayWordA];
bb.width ← (fmax-fmin)*16;
PrincOpsUtils.BITBLT[bb];
bb.dst.word ← baseB+Basics.LongMult[smin, wordsPerLineB]+fmin/2;
bb.dst.bit ← (fmin MOD 2)*8;
bb.dstBpl ← wordsPerLineB*bitsPerWord;
bb.src.word ← LOOPHOLE[@data.grayWordB];
bb.width ← (fmax-fmin)*8;
PrincOpsUtils.BITBLT[bb];
};
bb^ ← nullBitBltTable;
bb.srcDesc.gray ← [yOffset: 0, widthMinusOne: 0, heightMinusOne: 0];
bb.height ← 1;
bb.flags ← data.flags;
runs[color24ConstantRun];
};
stipple => TRUSTED {
bbspace: PrincOps.BBTableSpace;
bb: PrincOps.BitBltTablePtr ~ PrincOpsUtils.AlignedBBTable[@bbspace];
srcBase: LONG POINTER ~ @data.stipple;
color24StippleRun: PROC[sMin, fMin: INTEGER, fSize: NAT] ~ TRUSTED {
fmin: NAT ~ Check[fMin, frameA.width];
fmax: NAT ~ Check[fmin+fSize, frameA.width];
smin: NAT ~ Check[sMin, frameA.height];
smax: NAT ~ Check[smin+1, frameA.height];
dstLineA: LONG POINTER ~ baseA+Basics.LongMult[smin, wordsPerLineA];
dstLineB: LONG POINTER ~ baseB+Basics.LongMult[smin, wordsPerLineB];
srcLine: LONG POINTER ~ srcBase+(smin MOD 4)*4;
FOR f: NAT IN [fmin..MIN[fmin+4, fmax]) DO
bb.src.word ← srcLine+(f MOD 4);
bb.height ← (fmax-f+3)/4;
bb.dst.word ← dstLineA+f;
bb.dst.bit ← 0;
bb.dstBpl ← 4*16;
bb.width ← 16;
PrincOpsUtils.BITBLT[bb];
bb.dst.word ← dstLineB+f/2;
bb.dst.bit ← (f MOD 2)*8;
bb.dstBpl ← 4*8;
bb.width ← 8;
PrincOpsUtils.BITBLT[bb];
ENDLOOP;
};
bb^ ← nullBitBltTable;
bb.srcDesc.gray ← [yOffset: 0, widthMinusOne: 0, heightMinusOne: 0];
bb.flags ← data.flags;
runs[color24StippleRun];
};
sampled => {
scd: SampledColorData ~ GetSampledColorData[data];
dstFunc: PrincOps.DstFunc ~ IF data.zerosAreClear THEN and ELSE null;
heightLimit: NATNAT.LAST;
widthLimit: NATNAT.LAST;
base: ARRAY Channel OF LONG POINTERALL[NIL];
wordsPerLine: ARRAY Channel OF NAT;
FOR c: Channel IN Channel DO
heightLimit ← MIN[heightLimit, data.frame[c].height];
widthLimit ← MIN[widthLimit, data.frame[c].width];
base[c] ← data.frame[c].base;
wordsPerLine[c] ← data.frame[c].wordsPerLine;
ENDLOOP;
IF dstFunc=null AND data.paToDevice.form = 3 AND data.paToDevice.integerTrans THEN {
sSizeSource: NAT ~ scd.source[A].sSize;
fSizeSource: NAT ~ scd.source[A].fSize;
color24FastSampledRun: PROC[sMin, fMin: INTEGER, fSize: NAT] ~ TRUSTED {
smin: NAT ~ Check[sMin, heightLimit];
fmin: NAT ← Check[fMin, widthLimit];
count: NAT ← Check[fSize, widthLimit-fmin];
sMinSource: INTEGERINT[smin]-data.paToDevice.tx;
fMinSource: INTEGERINT[fmin]-data.paToDevice.ty;
dstLine: ARRAY Channel OF LONG POINTER;
srcLine: ARRAY Channel OF LONG POINTER;
WHILE sMinSource < 0 DO sMinSource ← sMinSource + (NAT.LAST/sSizeSource)*sSizeSource ENDLOOP;
sMinSource ← NAT[sMinSource] MOD sSizeSource;
WHILE fMinSource < 0 DO fMinSource ← fMinSource + (NAT.LAST/fSizeSource)*fSizeSource ENDLOOP;
fMinSource ← NAT[fMinSource] MOD fSizeSource;
FOR c: Channel IN Channel DO
source: ImagerPixelMap.PixelMap ~ scd.source[c];
dstLine[c] ← base[c]+Basics.LongMult[smin, wordsPerLine[c]];
srcLine[c] ← source.refRep.pointer+Basics.LongMult[NAT[sMinSource], source.refRep.rast];
ENDLOOP;
UNTIL count = 0 DO
delta: NAT ~ MIN[count, fSizeSource-fMinSource];
PrincOpsUtils.LongCopy[from: srcLine[A]+fMinSource, nwords: delta, to: dstLine[A]+fmin];
[] ← PrincOpsUtils.ByteBlt[from: [srcLine[B], fMinSource, fMinSource+delta], to: [dstLine[B], fmin, widthLimit]];
fMinSource ← fMinSource + delta;
IF fMinSource >= fSizeSource THEN fMinSource ← fMinSource-fSizeSource;
fmin ← fmin + delta;
count ← count - delta;
ENDLOOP;
};
runs[color24FastSampledRun];
}
ELSE {
buffer: SampleBuffer ~ data.buffer;
color24SampledRun: PROC[sMin, fMin: INTEGER, fSize: NAT] ~ CHECKED {
s: NAT ~ Check[sMin, heightLimit];
f: NAT ~ Check[fMin, widthLimit];
count: NAT ~ Check[fSize, widthLimit-f];
FOR c: Channel IN Channel DO
sampler: ImagerSample.Sampler ~ data.sampler[c];
bufferPointer: 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: bufferPointer, count: count,
base: base[c], wordsPerLine: wordsPerLine[c], bitsPerSample: sampler.bitsPerSample, s: s, f: f, dstFunc: dstFunc]};
ENDLOOP;
};
FOR c: Channel IN Channel DO
t: ImagerPixelMap.PixelMap ~ scd.source[c];
sampler: ImagerSample.Sampler ~ IF data.sampler[c] = NIL THEN (data.sampler[c] ← NEW[ImagerSample.SamplerRep ← []]) ELSE data.sampler[c];
sampler.base ← t.refRep.pointer;
sampler.wordsPerLine ← t.refRep.rast;
sampler.bitsPerSample ← data.frame[c].bitsPerPixel;
sampler.sMin ← t.sMin;
sampler.fMin ← t.fMin;
sampler.sSize ← t.sSize;
sampler.fSize ← t.fSize;
ImagerSample.SetSamplerIncrements[sampler, data.paToDevice];
ImagerSample.SetSamplerPosition[sampler: data.sampler[c],
m: data.paToDevice, s: bounds.smin, f: bounds.fmin];
ENDLOOP;
runs[color24SampledRun];
};
};
ENDCASE => ERROR; -- illegal case
};
me: REF TEXT ~ "color24"; -- a globally unique REF for use a key in the global cache.
GetSampledColorData: PROC [data: Data] RETURNS [scd: SampledColorData] ~ {
cache: FunctionCache.Cache ← FunctionCache.GlobalCache[];
compare: FunctionCache.CompareProc ~ {RETURN [argument=data.sampledColor.pa]};
scd ← NARROW[FunctionCache.Lookup[cache, compare, me].value];
IF scd = NIL THEN {
color: SampledColor ~ data.sampledColor;
pa: PixelArray ~ color.pa;
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];
mapperR: ImagerColorOperator.Mapper ~ ImagerColorOperator.NewMapper[
op: colorOperator, component: $Red, maxIn: maxIn, maxOut: 255];
mapperG: ImagerColorOperator.Mapper ~ ImagerColorOperator.NewMapper[
op: colorOperator, component: $Green, maxIn: maxIn, maxOut: 255];
mapperB: ImagerColorOperator.Mapper ~ ImagerColorOperator.NewMapper[
op: colorOperator, component: $Blue, maxIn: maxIn, maxOut: 255];
base: ARRAY Channel OF LONG POINTERALL[NIL];
lineA: LONG POINTERNIL;
rast: ARRAY Channel OF NATALL[0];
sampledColorDataSize: INT ← 0;
scd ← NEW[SampledColorDataRep];
FOR c: Channel IN Channel DO
bpp: CARDINAL ~ data.frame[c].bitsPerPixel;
lgbpp: CARDINAL ~ SELECT bpp FROM 8 => 3, 16 => 4, ENDCASE => ERROR;
t: ImagerPixelMap.PixelMap ~ ImagerPixelMap.Create[lgbpp, [0, 0, sSize, fSize]];
sampledColorDataSize ← sampledColorDataSize + t.refRep.words;
base[c] ← t.refRep.pointer;
rast[c] ← t.refRep.rast;
scd.source[c] ← t;
ENDLOOP;
lineA ← base[A];
FOR s: NAT IN[0..sSize) DO
ImagerPixelArray.GetPixels[pa: pa, s: s, f: 0, buffer: pixels, count: fSize];
ImagerColorOperator.MapPixels[mapper: mapperG, pixels: pixels,
buffer: buffer, count: fSize];
TRUSTED { ImagerSample.UnsafePutF[samples: bufferPointer, count: fSize,
base: base[A], wordsPerLine: rast[A],
bitsPerSample: 16, s: s, f: 0] };
ImagerColorOperator.MapPixels[mapper: mapperR, pixels: pixels,
buffer: buffer, count: fSize];
TRUSTED {
ImagerSample.UnsafePutS[samples: bufferPointer, count: fSize,
base: lineA, wordsPerLine: 1,
bitsPerSample: 8, s: 0, f: 0];
lineA ← lineA + rast[A];
};
ImagerColorOperator.MapPixels[mapper: mapperB, pixels: pixels,
buffer: buffer, count: fSize];
TRUSTED { ImagerSample.UnsafePutF[samples: bufferPointer, count: fSize,
base: base[B], wordsPerLine: rast[B],
bitsPerSample: 8, s: s, f: 0] };
ENDLOOP;
FunctionCache.Insert[cache, data.sampledColor.pa, scd, sampledColorDataSize, me];
};
};
Color24MaskBoxesInternal: PROC[data: Data, bounds: DeviceBox, boxes: PROC[BoxProc]] ~ {
IF data.case=constant THEN TRUSTED {
frameA: Terminal.FrameBuffer ~ data.frame[A];
baseA: LONG POINTER ~ frameA.base;
wordsPerLineA: NAT ~ frameA.wordsPerLine;
frameB: Terminal.FrameBuffer ~ data.frame[B];
baseB: LONG POINTER ~ frameB.base;
wordsPerLineB: NAT ~ frameB.wordsPerLine;
bbspace: PrincOps.BBTableSpace;
bb: PrincOps.BitBltTablePtr ~ PrincOpsUtils.AlignedBBTable[@bbspace];
color24ConstantBox: PROC[box: DeviceBox] ~ TRUSTED {
fmin: NAT ~ Check[box.fmin, frameA.width];
fmax: NAT ~ Check[box.fmax, frameA.width];
smin: NAT ~ Check[box.smin, frameA.height];
smax: NAT ~ Check[box.smax, frameA.height];
bb.height ← smax-smin;
bb.dst.word ← baseA+Basics.LongMult[smin, wordsPerLineA]+fmin;
bb.dst.bit ← 0;
bb.dstBpl ← wordsPerLineA*bitsPerWord;
bb.src.word ← LOOPHOLE[@data.grayWordA];
bb.width ← (fmax-fmin)*16;
PrincOpsUtils.BITBLT[bb];
bb.dst.word ← baseB+Basics.LongMult[smin, wordsPerLineB]+fmin/2;
bb.dst.bit ← (fmin MOD 2)*8;
bb.dstBpl ← wordsPerLineB*bitsPerWord;
bb.src.word ← LOOPHOLE[@data.grayWordB];
bb.width ← (fmax-fmin)*8;
PrincOpsUtils.BITBLT[bb];
};
bb^ ← nullBitBltTable;
bb.srcDesc.gray ← [yOffset: 0, widthMinusOne: 0, heightMinusOne: 0];
bb.flags ← data.flags;
boxes[color24ConstantBox];
}
ELSE {
color24NonConstantBox: PROC[box: DeviceBox] ~ {
runs: PROC[run: RunProc] ~ { --ImagerMask.--RunsFromBox[box: box, run: run] };
Color24MaskRunsInternal[data: data, bounds: box, runs: runs];
};
boxes[color24NonConstantBox];
};
};
ModifyColorFrame: PROC [vt: Terminal.Virtual, action: PROC, xmin: NAT, ymin: NAT, xmax: NAT, ymax: NAT] ~ INLINE {
IF vt = NIL THEN action[]
ELSE Terminal.ModifyColorFrame[vt: vt, action: action, xmin: xmin, ymin: ymin, xmax: xmax, ymax: ymax];
};
Color24MaskRuns: PROC[device: Device, bounds: DeviceBox, runs: PROC[RunProc]] ~ {
data: Data ~ NARROW[device.data];
color24MaskRunsAction: PROC ~ { Color24MaskRunsInternal[data, bounds, runs] };
ModifyColorFrame[vt: data.terminal, action: color24MaskRunsAction,
xmin: bounds.fmin, ymin: bounds.smin, xmax: bounds.fmax, ymax: bounds.smax];
};
Color24MaskBoxes: PROC[device: Device, bounds: DeviceBox, boxes: PROC[BoxProc]] ~ {
data: Data ~ NARROW[device.data];
color24MaskBoxesAction: PROC ~ { Color24MaskBoxesInternal[data, bounds, boxes] };
ModifyColorFrame[vt: data.terminal, action: color24MaskBoxesAction,
xmin: bounds.fmin, ymin: bounds.smin, xmax: bounds.fmax, ymax: bounds.smax];
};
Color24MaskBits: PROC[device: Device, srcBase: LONG POINTER, srcWordsPerLine: NAT,
ts, tf: INTEGER, boxes: PROC[BoxProc]] ~ {
data: Data ~ NARROW[device.data];
color24MaskBitsBox: PROC[box: DeviceBox] ~ {
color24MaskBitsBoxAction: PROC ~ {
runs: PROC[run: RunProc] ~ { --ImagerMask.--RunsFromBits[
base: srcBase, wordsPerLine: srcWordsPerLine,
sBits: box.smin-ts, fBits: box.fmin-tf, sRuns: box.smin, fRuns: box.fmin,
sSize: box.smax-box.smin, fSize: box.fmax-box.fmin, run: run];
};
Color24MaskRunsInternal[data: data, bounds: box, runs: runs];
};
ModifyColorFrame[vt: data.terminal, action: color24MaskBitsBoxAction,
xmin: box.fmin, ymin: box.smin, xmax: box.fmax, ymax: box.smax];
};
boxes[color24MaskBitsBox];
};
Color24MoveBoxes: PROC [device: Device, ts, tf: INTEGER, boxes: PROC[BoxProc]] ~ TRUSTED {
data: Data ~ NARROW[device.data];
frameA: Terminal.FrameBuffer ~ data.frame[A];
baseA: LONG POINTER ~ frameA.base;
wordsPerLineA: NAT ~ frameA.wordsPerLine;
frameB: Terminal.FrameBuffer ~ data.frame[B];
baseB: LONG POINTER ~ frameB.base;
wordsPerLineB: NAT ~ frameB.wordsPerLine;
bbspace: PrincOps.BBTableSpace;
bb: PrincOps.BitBltTablePtr ~ PrincOpsUtils.AlignedBBTable[@bbspace];
moveBox: PROC[box: DeviceBox] ~ TRUSTED {
dfmin: NAT ~ Check[box.fmin, frameA.width];
dsmin: NAT ~ Check[box.smin, frameA.height];
dfmax: NAT ~ Check[box.fmax, frameA.width];
dsmax: NAT ~ Check[box.smax, frameA.height];
sfmin: NAT ~ dfmin-tf;
ssmin: NAT ~ dsmin-ts;
sfmax: NAT ~ dfmax-tf;
ssmax: NAT ~ dsmax-ts;
bplA: INTEGER ← wordsPerLineA*bitsPerWord;
bplB: INTEGER ← wordsPerLineB*bitsPerWord;
ss: NAT ← ssmin;
ds: NAT ← dsmin;
action: SAFE PROC ~ TRUSTED {
bb.dst.word ← baseA+Basics.LongMult[ds, wordsPerLineA]+dfmin;
bb.dst.bit ← 0;
bb.dstBpl ← bplA;
bb.src.word ← baseA+Basics.LongMult[ss, wordsPerLineA]+sfmin;
bb.src.bit ← 0;
bb.srcDesc.srcBpl ← bplA;
bb.width ← (dfmax-dfmin)*16;
PrincOpsUtils.BITBLT[bb];
bb.dst.word ← baseB+Basics.LongMult[ds, wordsPerLineB]+dfmin/2;
bb.dst.bit ← (dfmin MOD 2)*8;
bb.dstBpl ← bplB;
bb.src.word ← baseB+Basics.LongMult[ss, wordsPerLineB]+sfmin/2;
bb.src.bit ← (sfmin MOD 2)*8;
bb.srcDesc.srcBpl ← bplB;
bb.width ← (dfmax-dfmin)*8;
PrincOpsUtils.BITBLT[bb];
};
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;
ss ← ssmax-1; ds ← dsmax-1;
bplA ← -bplA; bplB ← -bplB;
};
};
bb.height ← dsmax-dsmin;
ModifyColorFrame[vt: data.terminal, action: action,
xmin: MIN[dfmin, sfmin], ymin: MIN[dsmin, ssmin],
xmax: MAX[dfmax, sfmax], ymax: MAX[dsmax, ssmax]];
};
bb^ ← nullBitBltTable;
boxes[moveBox];
};
END.