ImagerDeviceColor24Impl.mesa
Copyright © 1984, 1985, 1986 by Xerox Corporation. All rights reserved.
Michael Plass, August 13, 1985 10:50:50 am PDT
Doug Wyatt, March 6, 1986 9:29:27 pm PST
DIRECTORY
FunctionCache USING [Cache, GlobalCache, CompareProc, Insert, Lookup],
ImagerColor,
ImagerDeviceColor24Private,
ImagerDevice,
ImagerRaster USING [],
ImagerSample,
ImagerTransformation,
SF,
Terminal USING [FrameBuffer, GetColorFrameBufferA, GetColorFrameBufferB, ModifyColorFrame, Virtual],
Vector2 USING [VEC];
ImagerDeviceColor24Impl: CEDAR PROGRAM
IMPORTS FunctionCache, ImagerColor, ImagerDevice, ImagerSample, ImagerTransformation, SF, Terminal
EXPORTS ImagerRaster
~ BEGIN OPEN ImagerDevice, ImagerDeviceColor24Private;
Transformation: TYPE ~ ImagerTransformation.Transformation;
PixelProc: TYPE ~ ImagerSample.PixelProc;
PixelBuffer: TYPE ~ ImagerSample.PixelBuffer;
PixelMap: TYPE ~ ImagerSample.PixelMap;
outputRGB: ImagerColor.ColorOutput ← NIL;
classColor24: DeviceClass ~ NewClass[
type: $FullColorDisplay,
SetColor: SetColorColor24,
MaskBoxes: MaskBoxesColor24,
MoveBoxes: MoveBoxesColor24
];
NewColor24Device: PUBLIC PROC [terminal: Terminal.Virtual] RETURNS [Device] ~ {
frameBufferA: Terminal.FrameBuffer ~ Terminal.GetColorFrameBufferA[terminal];
frameBufferB: Terminal.FrameBuffer ~ Terminal.GetColorFrameBufferB[terminal];
IF frameBufferA=NIL OR frameBufferA.bitsPerPixel#bitsPerPixelA OR
frameBufferB=NIL OR frameBufferB.bitsPerPixel#bitsPerPixelB THEN RETURN[NIL]
ELSE {
frameA: SampleMap ~ ImagerSample.MapFromFrameBuffer[frameBufferA];
frameB: SampleMap ~ ImagerSample.MapFromFrameBuffer[frameBufferB];
data: Data ~ NEW[DataRep ← [terminal: terminal, frameA: frameA, frameB: frameB]];
pixelsPerInch: REAL ~ terminal.colorPixelsPerInch;
surfaceToDevice: Transformation ~ ImagerTransformation.XYToSF[
scanMode: [slow: down, fast: right], sSize: frameA.size.s, fSize: frameA.size.f];
TRUSTED { data.frameRG ← ImagerSample.UnsafeNewSampleMap[
size: [s: frameA.size.s, f: frameA.size.f*2], bitsPerSample: frameA.bitsPerSample/2,
bitsPerLine: frameA.bitsPerLine, base: frameA.base,
ref: frameBufferA.vm, words: frameBufferA.vm.words] };
RETURN[NEW[ImagerDevice.DeviceRep ← [class: classColor24,
box: [min: [s: 0, f: 0], max: frameA.size],
surfaceToDevice: surfaceToDevice,
surfaceUnitsPerInch: [pixelsPerInch, pixelsPerInch],
surfaceUnitsPerPixel: 1,
data: data]]];
};
};
me: REF TEXT ~ "DeviceColor24"; -- a globally unique REF for use a key in the global cache.
SetColorColor24: SetColorProc ~ {
data: Data ~ NARROW[self.data];
WITH color SELECT FROM
color: ImagerColor.ConstantColor => {
maxOut: PixelProc ~ { check: [0..3) ~ i; RETURN[255] };
pixelAction: PROC [pixelOut: PixelProc] ~ {
data.valueA ← pixelOut[0]*256+pixelOut[1];
data.valueB ← pixelOut[2];
};
color.PixelFromColor[output: outputRGB, maxOut: maxOut, pixelAction: pixelAction];
data.function ← [null, null];
data.case ← fill;
};
color: ImagerColor.SampledBlack => {
data.tile ← color.pa.MapFromLayer[0];
data.paToDevice.ApplyCat[color.pa.m, color.um, viewToDevice];
data.function ← IF color.clear THEN [or, null] ELSE [null, null];
IF data.srcToDevice.form=3 THEN {
data.s0 ← data.f0 ← 0;
data.phase ← 0;
data.case ← tile;
}
ELSE data.case ← sampledBlack;
};
color: ImagerColor.SampledColor => {
pm: ImagerSample.PixelMap ← NIL;
cache: FunctionCache.Cache ~ FunctionCache.GlobalCache[];
compare: FunctionCache.CompareProc ~ {
WITH argument SELECT FROM arg: ImagerColor.SampledColor =>
RETURN[arg.pa=color.pa AND arg.colorOperator=color.colorOperator];
ENDCASE => RETURN[FALSE];
};
WITH cache.Lookup[compare: compare, clientID: me].value SELECT FROM
value: ImagerSample.PixelMap => pm ← value;
ENDCASE => {
maxOut: PixelProc ~ { check: [0..3) ~ i; RETURN[255] };
pm ← ImagerColor.Translate[self: color.colorOperator,
output: outputRGB, pa: color.pa, maxOut: maxOut];
IF color.pa.immutable THEN cache.Insert[argument: color, value: pm,
size: 3*INT[pm.size.s]*INT[pm.size.f]/2, clientID: me];
};
data.pm ← pm;
data.pmToDevice.ApplyCat[color.pa.m, color.um, viewToDevice];
data.case ← sampledColor;
};
color: ImagerColor.SpecialColor => SELECT color.type FROM
$Invert => {
data.valueA ← 377B*400B+377B;
data.valueB ← 377B;
data.function ← [xor, null];
data.case ← fill;
};
$Stipple => {
stipple: StippleData ~ NARROW[color.data];
data.tile ← stipple.tile;
data.function ← stipple.function;
data.s0 ← data.f0 ← 0; data.phase ← 0;
data.case ← tile;
};
ENDCASE => SetColorColor24[self, color.substitute, viewToDevice];
ENDCASE => ERROR; -- unknown color variant
};
ModifyColorFrame: PROC [data: Data, action: PROC, bounds: Box] ~ INLINE {
IF data.terminal=NIL THEN action[]
ELSE Terminal.ModifyColorFrame[vt: data.terminal, action: action,
xmin: bounds.min.f, ymin: bounds.min.s, xmax: bounds.max.f, ymax: bounds.max.s];
};
interpolate: BOOLTRUE;
MaskBoxesColor24: MaskBoxesProc ~ {
data: Data ~ NARROW[self.data];
actionMaskBoxesColor24: PROC ~ {
SELECT data.case FROM
nil => ERROR; -- color not initialized
fill => {
data.frameA.FillBoxes[boxes: boxes,
value: data.valueA, function: data.function];
data.frameB.FillBoxes[boxes: boxes,
value: data.valueB, function: data.function];
};
tile => {
data.frameA.TileBoxes[boxes: boxes, tile: data.tileA,
s0: data.s0, f0: data.f0, phase: data.phase, function: data.function];
data.frameB.TileBoxes[boxes: boxes, tile: data.tileB,
s0: data.s0, f0: data.f0, phase: data.phase, function: data.function];
};
sampledBlack => {
sampledBlackAction: PROC [samples: SampleBuffer, min: Vec] ~ {
ImagerSample.PutSamples[self: data.frame, min: min,
samples: samples, function: data.function];
};
ImagerSample.Resample[self: data.tile, m: data.srcToDevice, interpolate: FALSE,
boxes: boxes, bounds: bounds, action: sampledBlackAction];
};
sampledColor => {
sampledColorAction: PROC [pixels: PixelBuffer, min: Vec] ~ {
s: NAT ~ min.s; f: NAT ~ min.f;
data.frameRG.PutSamples[min: [s: s, f: f*2], delta: [s: 0, f: 2],
samples: pixels[0], function: data.function];
data.frameRG.PutSamples[min: [s: s, f: f*2+1], delta: [s: 0, f: 2],
samples: pixels[1], function: data.function];
data.frameB.PutSamples[min: [s: s, f: f], delta: [s: 0, f: 1],
samples: pixels[2], function: data.function];
};
data.pm.Resample[m: data.pmToDevice, interpolate: interpolate,
boxes: boxes, bounds: bounds, action: sampledColorAction];
};
ENDCASE => ERROR; -- bogus case
};
ModifyColorFrame[data: data, action: actionMaskBoxesColor24, bounds: bounds];
};
MoveBoxesColor24: MoveBoxesProc ~ {
data: Data ~ NARROW[self.data];
actionMoveBoxesColor24: PROC ~ {
data.frameA.MoveBoxes[boxes: boxes, srcOffset: offset];
data.frameB.MoveBoxes[boxes: boxes, srcOffset: offset];
};
dmin: Vec ~ bounds.min;
dmax: Vec ~ bounds.max;
smin: Vec ~ dmin.Add[offset];
smax: Vec ~ dmax.Add[offset];
moveBounds: Box ~ [min: dmin.Min[smin], max: dmax.Max[smax]];
ModifyColorFrame[data: data, action: actionMoveBoxesColor24, bounds: moveBounds];
};
END.