ImagerDeviceBitmapImpl.mesa
Copyright © 1984, 1985, 1986 by Xerox Corporation. All rights reserved.
Michael Plass, September 16, 1985 3:37:29 pm PDT
Doug Wyatt, March 20, 1986 2:50:24 pm PST
DIRECTORY
FunctionCache USING [Cache, CompareProc, GlobalCache, Insert, Lookup],
ImagerBrick USING [Brick, BrickRep, ThresholdsFromBrick],
ImagerColor,
ImagerDevice,
ImagerDeviceBitmapPrivate USING [Case, Data, DataRep],
ImagerMask USING [RunsFromBits, RunsFromBox],
ImagerPixelArray,
ImagerRaster USING [],
ImagerSample,
ImagerTransformation,
PrincOps,
PrincOpsUtils,
Real USING [RoundC],
Vector2 USING [VEC];
ImagerDeviceBitmapImpl: CEDAR PROGRAM
IMPORTS FunctionCache, ImagerBrick, ImagerColor, ImagerDevice, ImagerMask, ImagerPixelArray, ImagerSample, ImagerTransformation, Real
EXPORTS ImagerRaster
~ BEGIN OPEN ImagerDevice, ImagerDeviceBitmapPrivate;
VEC: TYPE ~ Vector2.VEC;
Transformation: TYPE ~ ImagerTransformation.Transformation;
Color: TYPE ~ ImagerColor.Color;
ConstantColor: TYPE ~ ImagerColor.ConstantColor;
SampledColor: TYPE ~ ImagerColor.SampledColor;
ColorOperator: TYPE ~ ImagerColor.ColorOperator;
PixelArray: TYPE ~ ImagerPixelArray.PixelArray;
Sample: TYPE ~ ImagerSample.Sample;
SampleBuffer: TYPE ~ ImagerSample.SampleBuffer;
SampleMap: TYPE ~ ImagerSample.SampleMap;
me: REF TEXT ~ "BitDev"; -- a globally unique REF for use as a clientID in the global cache.
classBitmap: ImagerDevice.DeviceClass ~ ImagerDevice.NewClass[
type: $Bitmap,
SetColor: SetColorBitmap,
SetPriority: SetPriorityBitmap,
SetHalftone: SetHalftoneBitmap,
MaskBoxes: MaskBoxesBitmap,
MaskBits: MaskBitsBitmap,
DrawBits: DrawBitsBitmap,
MoveBoxes: MoveBoxesBitmap
];
NewBitmapDevice: PUBLIC PROC [frame: SampleMap, pixelsPerInch: REAL]
RETURNS [Device] ~ {
data: Data ~ NEW[DataRep ← [frame: frame, paToDevice: ImagerTransformation.Scale[0]]];
surfaceToDevice: Transformation ~ ImagerTransformation.XYToSF[
scanMode: [slow: down, fast: right], sSize: frame.size.s, fSize: frame.size.f];
RETURN[NEW[ImagerDevice.DeviceRep ← [class: classBitmap, data: data,
box: [min: [0, 0], max: frame.size],
surfaceToDevice: surfaceToDevice,
surfaceUnitsPerInch: [pixelsPerInch, pixelsPerInch],
surfaceUnitsPerPixel: 1
]]];
};
defaultBrick: ImagerBrick.Brick ← InitDefaultBrick[];
InitDefaultBrick: PROC RETURNS [ImagerBrick.Brick] ~ {
brick: ImagerBrick.Brick ~ NEW[ImagerBrick.BrickRep[16] ← [
sSize: 4, fSize: 4, phase: 0, u: 1, v: 1, samples: ]];
Val: PROC[n: [1..16]] RETURNS [REAL] ~ { RETURN[(n-0.5)/16.0] };
brick[00] ← Val[01]; brick[01] ← Val[09]; brick[02] ← Val[03]; brick[03] ← Val[11];
brick[04] ← Val[15]; brick[05] ← Val[05]; brick[06] ← Val[13]; brick[07] ← Val[07];
brick[08] ← Val[04]; brick[09] ← Val[12]; brick[10] ← Val[02]; brick[11] ← Val[10];
brick[12] ← Val[14]; brick[13] ← Val[08]; brick[14] ← Val[16]; brick[15] ← Val[06];
RETURN[brick];
};
stippleTableMax: NAT ~ 16;
stippleTable: ARRAY [0..stippleTableMax] OF WORD ← [
0FFFFH, 07FFFH, 07FDFH, 05FDFH, 05F5FH, 05B5FH, 05B5EH, 05A5EH,
05A5AH, 01A5AH, 01A4AH, 00A4AH, 00A0AH, 0080AH, 00802H, 00002H, 00000H
];
StippleFromIntensity: PROC [Y: REAL] RETURNS [WORD] ~ {
IF Y<=0 THEN RETURN[WORD.LAST]; -- black
IF Y>=1 THEN RETURN[0]; -- white
RETURN[stippleTable[Real.RoundC[Y*stippleTableMax]]];
};
maxSourceSample: Sample ~ 255;
SetColorBitmap: PROC[self: Device, color: Color, viewToDevice: Transformation] ~ {
data: Data ~ NARROW[self.data];
WITH color SELECT FROM
color: ImagerColor.ConstantColor => {
Y: REAL ~ ImagerColor.SignalFromColor[color];
stipple: WORD ~ StippleFromIntensity[Y];
IF stipple=WORD.LAST OR stipple=0 THEN {
data.value ← IF stipple=0 THEN 0 ELSE 1;
data.case ← fill;
}
ELSE {
data.tile ← ImagerSample.TileFromStipple[stipple];
data.s0 ← data.f0 ← 0; data.phase ← 0;
data.case ← tile;
};
data.function ← [null, null];
data.src ← NIL;
};
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 => {
maxOut: PixelProc ~ { check: [0..1) ~ i; RETURN[maxSourceSample] };
data.pixelMap ← ImagerColor.Translate[self: color.colorOperator,
output: outputIntensity, pa: color.pa, maxOut: maxOut];
data.paToDevice.ApplyCat[color.pa.m, color.um, viewToDevice];
data.case ← sampledColor;
};
color: ImagerColor.SpecialColor => SELECT color.type FROM
$Invert => {
data.value ← 1;
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 => SetColorBitmap[self, color.substitute, viewToDevice];
ENDCASE => ERROR; -- unknown color variant
};
SetPriorityBitmap: PROC[self: Device, priorityImportant: BOOL] ~ {
};
SetHalftoneBitmap: PROC[self: Device, halftone: HalftoneParameters] ~ {
data: Data ~ NARROW[self.data];
data.halftone ← halftone;
};
MaskBoxesBitmap: PROC [data: Data, bounds: Box, boxes: BoxGenerator] ~ {
SELECT data.case FROM
nil => ERROR; -- color not initialized
fill => {
ImagerSample.FillBoxes[self: data.frame, boxes: boxes,
value: data.value, function: data.function];
};
tile => {
ImagerSample.TileBoxes[self: data.frame, boxes: boxes,
tile: data.src, 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 [samples: SampleBuffer, min: Vec] ~ {
ImagerSample.PutSamples[self: data.frame, min: min,
samples: samples, function: data.function];
};
ImagerSample.Resample[self: data.src, m: data.srcToDevice,
boxes: boxes, bounds: bounds, action: sampledColorAction];
};
ENDCASE => ERROR; -- bogus case
};
MaskBitsOp: TYPE ~ {null, set1, set0, neg};
mop1: ARRAY PrincOps.DstFunc OF MaskBitsOp ← [null: set1, and: null, or: set1, xor: neg];
mop0: ARRAY PrincOps.DstFunc OF MaskBitsOp ← [null: set0, and: set0, or: null, xor: null];
MaskBitsBitmap: PROC [self: Device, bounds: Box, boxes: BoxGenerator,
mask: SampleMap, offset: Vec] ~ {
data: Data ~ NARROW[self.data];
IF data.case=fill THEN {
value1: BOOL ~ (data.value MOD 2=0)#(data.function.srcFunc=null);
op: MaskBitsOp ~ (IF value1 THEN mop1 ELSE mop0)[data.function.dstFunc];
function: Function ← nullFunction;
SELECT op FROM
null => NULL;
set1 => function ← [dstFunc: or, srcFunc: null];
set0 => function ← [dstFunc: and, srcFunc: complement];
neg => function ← [dstFunc: xor, srcFunc: null];
ENDCASE => ERROR;
IF op#null THEN ImagerSample.TransferBoxes[dst: data.frame, src: mask,
boxes: boxes, srcOffset: offset, function: function];
}
ELSE {
bitsToBoxes: BoxGenerator ~ { ImagerMask.BitsToBoxes[mask, offset, boxes] };
MaskBoxesBitmap[self, bitsToBoxes, bounds];
}
};
MoveBoxesBitmap: PROC [self: Device, boxes: BoxGenerator, offset: Vec] ~ {
data: Data ~ NARROW[self.data];
ImagerSample.MoveBoxes[self: data.frame, boxes: boxes, srcOffset: offset];
};
END.