~
BEGIN
ROPE: TYPE ~ Rope.ROPE;
Context: TYPE ~ Imager.Context;
CharMask: TYPE ~ ImagerDevice.CharMask;
Toners: TYPE ~ LIST OF ImagerPD.Toner;
PrinterType: TYPE ~ ImagerPD.PrinterType;
ColorSeparationProc: TYPE ~ ImagerPD.ColorSeparationProc;
SpecialSeparationProc: TYPE ~ ImagerPD.SpecialSeparationProc;
Color: TYPE ~ ImagerColorDefs.Color;
ConstantColor: TYPE ~ ImagerColorDefs.ConstantColor;
SampledColor: TYPE ~ ImagerColorDefs.SampledColor;
ColorOperator: TYPE ~ ImagerColorDefs.ColorOperator;
Device: TYPE ~ ImagerDevice.Device;
PixelMap: TYPE ~ ImagerPixelMap.PixelMap;
PixelArray: TYPE ~ ImagerPixelArrayDefs.PixelArray;
Tile: TYPE ~ ImagerPixelMap.Tile;
Transformation: TYPE ~ ImagerTransformation.Transformation;
DeviceCode: TYPE ~ PDFileFormat.DeviceCode;
Sample: TYPE ~ ImagerSample.Sample;
SampleBuffer: TYPE ~ ImagerSample.SampleBuffer;
UnsafeSamples: TYPE ~ ImagerSample.UnsafeSamples;
ConstantColorImpl: TYPE ~ REF ConstantColorImplRep;
ConstantColorImplRep:
PUBLIC
TYPE ~ ImagerColorPrivate.ConstantColorImplRep;
export to ImagerColorDefs.ConstantColorImplRep
PD: TYPE ~ REF PDRep;
PDRep:
PUBLIC
TYPE ~ ImagerPDPrivate.PDRep;
ColorKind:
TYPE ~ ImagerPDPrivate.ColorKind;
DeviceData: TYPE ~ ImagerPDPrivate.DeviceData;
DeviceDataRep: TYPE ~ ImagerPDPrivate.DeviceDataRep;
TileEntry:
TYPE ~ ImagerPDPrivate.TileEntry;
CreateTile:
PUBLIC
PROC [pixelMap: PixelMap, phase:
INTEGER ← 0, copy:
BOOL ←
TRUE]
RETURNS [tile: Tile] ~ {
IF copy OR pixelMap.sMin#0 OR pixelMap.fMin#0 THEN pixelMap ← ImagerPixelMap.Copy[pixelMap];
tile ← [sOrigin: pixelMap.sOrigin, fOrigin: pixelMap.fOrigin, sSize: pixelMap.sSize, fSize: pixelMap.fSize, phase: Mod[phase, pixelMap.fSize], refRep: pixelMap.refRep];
WHILE tile.sOrigin < 0
DO
tile.sOrigin ← tile.sOrigin + tile.sSize;
tile.fOrigin ← tile.fOrigin + tile.phase;
ENDLOOP;
WHILE tile.fOrigin < 0
DO
tile.fOrigin ← tile.fOrigin + tile.fSize;
ENDLOOP;
};
CopyTile:
PROC [tile: Tile]
RETURNS [Tile] ~ {
RETURN [CreateTile[[tile.sOrigin, tile.fOrigin, 0, 0, tile.sSize, tile.fSize, tile.refRep], tile.phase, TRUE]];
};
CreateFromPrinterType:
PUBLIC
PROC [name:
ROPE, printerType: PrinterType, toners: Toners ←
NIL, tonerUniverse: Toners ←
NIL, pixelsPerHalftoneDot:
REAL]
RETURNS [
PD] ~ {
SELECT printerType
FROM
raven300 =>
RETURN[CreateFromParameters[name: name,
deviceCode: DeviceCode[raven].ORD,
sResolution: 300, fResolution: 300,
imageSSize: 300*8+300/2, imageFSize: 300*11, -- 8.5 by 11 inches
toners: IF toners # NIL THEN toners ELSE LIST[black], leftovers: TRUE, bandSSize: 16, maxLoadWords: 60000, fontTuning: NIL, tonerUniverse: tonerUniverse, pixelsPerHalftoneDot: pixelsPerHalftoneDot]];
raven384 =>
RETURN[CreateFromParameters[name: name,
deviceCode: DeviceCode[hornet].ORD,
sResolution: 384, fResolution: 384,
imageSSize: 384*8+384/2, imageFSize: 384*11, -- 8.5 by 11 inches
toners: IF toners # NIL THEN toners ELSE LIST[black], leftovers: TRUE, bandSSize: 16, maxLoadWords: 60000, fontTuning: NIL, tonerUniverse: tonerUniverse, pixelsPerHalftoneDot: pixelsPerHalftoneDot]];
plateMaker =>
RETURN[CreateFromParameters[name: name,
deviceCode: DeviceCode[mig].ORD,
sResolution: 1200, fResolution: 1200,
imageSSize: 13800, imageFSize: 11400, -- 11.5 by 9.5 inches
toners: IF toners # NIL THEN toners ELSE LIST[black], leftovers: TRUE, bandSSize: 16, maxLoadWords: 60000, fontTuning: NIL, tonerUniverse: tonerUniverse, pixelsPerHalftoneDot: pixelsPerHalftoneDot]];
c150 =>
RETURN[CreateFromParameters[name: name,
deviceCode: PrinterType[c150].ORD,
sResolution: 120, fResolution: 120,
imageSSize: 1320, imageFSize: 1020,
toners: LIST[black, cyan, magenta, yellow], leftovers: FALSE, bandSSize: 48, maxLoadWords: 60000, fontTuning: NIL, pixelsPerHalftoneDot: pixelsPerHalftoneDot]];
color400 =>
RETURN[CreateFromParameters[name: name,
deviceCode: PrinterType[color400].ORD,
sResolution: 400, fResolution: 400,
imageSSize: 5500, imageFSize: 4096,
toners: LIST[yellow, magenta, cyan, black], leftovers: FALSE, bandSSize: 50, maxLoadWords: 100000, fontTuning: NIL, pixelsPerHalftoneDot: pixelsPerHalftoneDot]];
puffin =>
RETURN[CreateFromParameters[name: name,
deviceCode: DeviceCode[puffin].ORD,
sResolution: 384, fResolution: 384,
imageSSize: 384*11, imageFSize: 384*8+384/2, -- 11 by 8.5 inches
toners: IF toners # NIL THEN toners ELSE LIST[cyan, magenta, yellow], leftovers: TRUE, bandSSize: 16, maxLoadWords: 60000, fontTuning: NIL, tonerUniverse: tonerUniverse, pixelsPerHalftoneDot: pixelsPerHalftoneDot]];
versatec =>
RETURN[CreateFromParameters[name: name,
deviceCode: DeviceCode[colorVersatec].ORD,
sResolution: 200, fResolution: 200,
imageSSize: 200*163, imageFSize: 200*40, -- 163 by 40 inches
toners: IF toners # NIL THEN toners ELSE LIST[black], leftovers: FALSE, bandSSize: 64, maxLoadWords: 100000, fontTuning: NIL, tonerUniverse: tonerUniverse, pixelsPerHalftoneDot: pixelsPerHalftoneDot]];
colorVersatec =>
RETURN[CreateFromParameters[name: name,
deviceCode: DeviceCode[colorVersatec].ORD,
sResolution: 200, fResolution: 200,
imageSSize: 200*163, imageFSize: 200*40, -- 163 by 40 inches
toners: LIST[black, cyan, magenta, yellow], leftovers: FALSE, bandSSize: 64, maxLoadWords: 100000, fontTuning: NIL, pixelsPerHalftoneDot: pixelsPerHalftoneDot]];
ENDCASE => ERROR Imager.Error[[$unimplemented, "Unknown printer type."]];
CreateDevice:
PROC [deviceData: DeviceData, sSize, fSize, sPixelsPerInch, fPixelsPerInch:
CARDINAL]
RETURNS [Device] ~ {
sInches: REAL ~ REAL[sSize]/REAL[sPixelsPerInch];
fInches: REAL ~ REAL[fSize]/REAL[fPixelsPerInch];
surfaceToDevice: Transformation ~ ImagerTransformation.Scale[1];
xPixelsPerInch: CARDINAL ← sPixelsPerInch;
yPixelsPerInch: CARDINAL ← fPixelsPerInch;
Call the larger dimension y; see the Interpress standard, section 4.3.1.
IF sInches>fInches
THEN {
-- s (y) is top-to-bottom, f (x) is left-to-right
surfaceToDevice.ApplyPreTranslate[[sSize, 0]];
surfaceToDevice.ApplyPreRotate[90];
xPixelsPerInch ← fPixelsPerInch; yPixelsPerInch ← sPixelsPerInch;
}
ELSE NULL; -- s (x) is left-to-right, f (y) is bottom-to-top
RETURN[
NEW[ImagerDevice.DeviceRep ← [
class: deviceClass,
box: [smin: 0, fmin: 0, smax: sSize, fmax: fSize],
surfaceToDevice: surfaceToDevice,
surfaceUnitsPerInch: [xPixelsPerInch, yPixelsPerInch],
surfaceUnitsPerPixel: 1,
data: deviceData
]]];
};
deviceClass: ImagerDevice.Class ~
NEW[ImagerDevice.ClassRep ← [
type: $PD,
SetColor: SetColor,
SetPriority: SetPriority,
SetHalftone: SetHalftone,
MaskRuns: MaskRuns,
MaskBoxes: MaskBoxes,
MaskBits: MaskBits,
MaskChar: MaskChar
]];
TonerSetFromToners:
PROC [toners: Toners]
RETURNS [tonerSet:
PACKED
ARRAY PDFileWriter.Toner
OF
BOOL] ~ {
tonerSet ← ALL[FALSE];
FOR t: Toners ← toners, t.rest
UNTIL t=
NIL
DO
pdt: PDFileWriter.Toner ~ VAL[ORD[t.first]];
IF tonerSet[pdt] THEN Imager.Error[[$specification, "Multiple use of same toner in PD Create"]];
tonerSet[pdt] ← TRUE;
ENDLOOP;
};
rastWeight: REAL ← 1.7;
fontCacheSize:
NAT ← 8000;
nilTile: Tile ~ [0,0,0,0,0,NIL];
nilPixelMap: PixelMap ~ [0,0,0,0,0,0,
NIL];
TileFromBrick:
PROC [brick: ImagerBrick.Brick]
RETURNS [tile: Tile] ~ {
pm: PixelMap ← ImagerPixelMap.Create[4, [0, 0, brick.sSize, brick.fSize]];
max: CARDINAL ~ Basics.BITSHIFT[1, Basics.BITSHIFT[1, pmLgBitsPerSample]] - 1;
FOR s:
NAT
IN[0..brick.sSize)
DO
FOR f:
NAT
IN[0..brick.fSize)
DO
r: REAL ~ ImagerBrick.GetElement[brick, s, f];
sample: Sample ~ Real.Round[r*max];
pm.PutPixel[s, f, sample];
ENDLOOP;
ENDLOOP;
tile ← CreateTile[pm, brick.phase, FALSE];
};
defaultScreenAngle:
ARRAY PDFileWriter.Toner[black..yellow]
OF
REAL ← [
black: 45,
cyan: 75,
magenta: 105,
yellow: 90
];
GetDefaultBricks:
PROC [deviceData: DeviceData, pixelsPerHalftoneDot:
REAL] ~ {
FOR t: PDFileWriter.Toner
IN PDFileWriter.Toner
DO
IF deviceData.tonerSet[t]
THEN {
angle: REAL ~ IF t IN[black..yellow] THEN defaultScreenAngle[t] ELSE 0;
brick: ImagerBrick.Brick ~ ImagerBrick.NewBrick[freq: pixelsPerHalftoneDot, angle: angle, filter: ImagerBrick.DotScreen];
deviceData.halftoneBrick[t] ← NEW[Tile ← TileFromBrick[brick]];
};
ENDLOOP;
};
CreateFromParameters:
PUBLIC
PROC [name:
ROPE, deviceCode:
CARDINAL,
sResolution, fResolution:
CARDINAL,
-- pixels per inch
imageSSize, imageFSize:
CARDINAL,
-- pixels
toners: Toners, leftovers:
BOOL, bandSSize:
NAT, maxLoadWords:
INT, fontTuning:
ROPE, tonerUniverse: Toners ←
NIL, pixelsPerHalftoneDot:
REAL]
RETURNS [
PD] ~ {
writer: PDFileWriter.PDState ~ PDFileWriter.Create[
fileName: name,
deviceCode: VAL[deviceCode],
sResolution: sResolution,
fResolution: fResolution,
imageSSize: imageSSize,
imageFSize: imageFSize,
bandSSize: bandSSize,
leftOverMode: leftovers,
maxLoadWords: maxLoadWords
];
deviceData: DeviceData ~
NEW [DeviceDataRep ← [
writer: writer,
sSize: imageSSize,
fSize: imageFSize,
feed: FALSE,
strip: FALSE,
imageStarted: FALSE,
tonerSet: TonerSetFromToners[toners],
tonerUniverseSet: TonerSetFromToners[IF tonerUniverse # NIL THEN tonerUniverse ELSE toners],
toner: black,
maskTab: RefTab.Create[997],
colorKind: nil,
tileTable: NEW[ImagerPDPrivate.TileTableRep[17]],
colorTile: nilTile,
colorClear: FALSE,
sampledSource: nilPixelMap,
paToDevice: ImagerTransformation.Scale[0],
scratchPM: NIL,
sampler: NEW[ImagerSample.SamplerRep ← []],
bitBuffer: ImagerSample.NewBuffer[1, (imageFSize+bitsPerWord-1)/bitsPerWord + 1],
sampleBuffer: ImagerSample.NewBuffer[1, imageFSize],
brickBuffer: ImagerSample.NewBuffer[1, MAX[imageFSize, 100]],
halftoneBrick: ALL[NIL]
]];
device: Device ~ CreateDevice[deviceData: deviceData, sSize: imageSSize, fSize: imageFSize, sPixelsPerInch: sResolution, fPixelsPerInch: fResolution];
fontCacheID: ATOM ~ IF Rope.Size[fontTuning] = 0 THEN $PD ELSE Atom.MakeAtom[fontTuning];
context: Context ~ ImagerRaster.Create[device: device, pixelUnits: FALSE, fontCache: ImagerCache.GetNamedCache[fontCacheID, fontCacheSize], rastWeight: rastWeight];
pd:
PD ~
NEW [PDRep ← [
context: context,
toners: toners,
deviceData: deviceData
]];
GetDefaultBricks[deviceData, pixelsPerHalftoneDot];
RETURN[pd];
};
Close:
PUBLIC
PROC [pd:
PD] ~ {
PDFileWriter.Close[pd.deviceData.writer];
};
StartImage:
PROC [deviceData: DeviceData] ~ {
tonerSet: PACKED ARRAY PDFileFormat.Toner OF BOOL ← ALL[FALSE];
tonerSet[deviceData.toner] ← TRUE;
PDFileWriter.StartImage[pdState: deviceData.writer, toners: tonerSet, feed: deviceData.feed, strip: deviceData.strip];
deviceData.imageStarted ← TRUE;
};
identity: Transformation ~ ImagerTransformation.Scale[1];
DoPage:
PUBLIC
PROC [pd:
PD, action:
PROC [context: Context], pixelUnits:
BOOL ←
FALSE] ~ {
proc: PROC ~ {action[pd.context]};
littleRectangle:
PROC ~ {
PD files don't work very well with empty separations.
Imager.SetGray[pd.context, 0];
ImagerBackdoor.SetT[pd.context, identity];
Imager.MaskRectangleI[pd.context, 0, 0, 1, 1];
};
pd.deviceData.feed ← TRUE;
FOR t: Toners ← pd.toners, t.rest
UNTIL t=
NIL
DO
tonerCard: CARDINAL ~ ORD[t.first];
toner: PDFileFormat.Toner ~ VAL[tonerCard];
pd.deviceData.toner ← toner;
pd.deviceData.imageStarted ← FALSE;
pd.deviceData.strip ← t.rest=NIL;
StartImage[pd.deviceData];
Imager.SetGray[pd.context, 1];
Imager.DoSaveAll[pd.context, littleRectangle];
Imager.DoSaveAll[pd.context, proc];
IF pd.deviceData.strip
AND NOT pd.deviceData.imageStarted
THEN {
Were we more clever, we would not generate StartImage for empty separations.
};
IF pd.deviceData.imageStarted
THEN {
PDFileWriter.EndPage[pd.deviceData.writer];
pd.deviceData.feed ← FALSE;
};
ENDLOOP;
};
SetPriority:
PROC [device: Device, priorityImportant:
BOOL] ~ {
deviceData: DeviceData ~ NARROW[device.data];
[] ← PDFileWriter.SetPriorityImportant[deviceData.writer, priorityImportant];
};
SetHalftone:
PROC[device: Device, halftone: ImagerDevice.HalftoneParameters] ~ {
deviceData: DeviceData ~ NARROW[device.data];
};
Check:
PROC [x:
INTEGER, max:
NAT]
RETURNS[
NAT] ~
TRUSTED MACHINE CODE { PrincOps.zINC; PrincOps.zBNDCK };
IF x IN[0..max] THEN RETURN[x] ELSE ERROR RuntimeError.BoundsFault
TileHash:
PROC [tile: Tile]
RETURNS [hash:
CARDINAL] ~
TRUSTED {
p: LONG POINTER ← tile.refRep.pointer;
count: LONG CARDINAL ← Basics.LongMult[tile.refRep.rast, tile.sSize];
IF tile.refRep.lgBitsPerPixel # 0 OR tile.refRep.rast # NAT[tile.fSize+bitsPerWord-1]/bitsPerWord THEN ERROR;
hash ← 0;
UNTIL count = 0
DO
nWords: CARDINAL ~ MIN[count, NAT.LAST];
hash ← Checksum.ComputeChecksum[cs: hash, nWords: nWords, p: p];
p ← p + nWords;
count ← count - nWords;
ENDLOOP;
};
TileEqual:
PROC [a, b: Tile]
RETURNS [
BOOL] ~ {
IF a.sOrigin = b.sOrigin
AND a.fOrigin = b.fOrigin
AND a.sSize = b.sSize
AND a.fSize = b.fSize
AND a.phase = b.phase
AND a.refRep.lgBitsPerPixel = b.refRep.lgBitsPerPixel
AND a.refRep.rast = b.refRep.rast
THEN
TRUSTED {
ap: LONG POINTER TO WORD ← a.refRep.pointer;
bp: LONG POINTER TO WORD ← b.refRep.pointer;
FOR i:
LONG
CARDINAL
IN [0..Basics.LongMult[a.refRep.rast, a.refRep.lines])
DO
IF (ap+i)^ # (bp+i)^ THEN RETURN [FALSE];
ENDLOOP;
RETURN [TRUE];
}
ELSE RETURN [FALSE];
};
bitsPerWord: NAT ~ Basics.bitsPerWord;
PutTileIntoLoad:
PROC [writer: PDFileWriter.PDState, tile: Tile]
RETURNS [
LONG
CARDINAL] ~
TRUSTED {
IF tile.refRep.lgBitsPerPixel # 0 OR NAT[tile.refRep.rast] # (tile.fSize+bitsPerWord-1)/bitsPerWord THEN ERROR;
RETURN [PDFileWriter.LoadContiguousColorTile[pdState: writer, phase: tile.phase, sMin: tile.sOrigin, fMin: tile.fOrigin, sSize: tile.sSize, fSize: tile.fSize, bitsPtr: tile.refRep.pointer]];
};
TileLoadWords:
PROC [tile: Tile]
RETURNS [
INT] ~ {
RETURN [SIZE[PDFileFormat.Tile] + Basics.LongMult[tile.refRep.rast, tile.sSize]];
};
SetColorFromTile:
PROC [deviceData: DeviceData, tile: Tile, clear:
BOOL, copy:
BOOL] ~ {
hash: CARDINAL ~ TileHash[tile];
bucket: NAT ~ hash MOD deviceData.tileTable.mod;
loadIndex: LONG CARDINAL ← 0;
found: BOOL ← FALSE;
FOR t:
LIST
OF TileEntry ← deviceData.tileTable[bucket], t.rest
UNTIL (found
OR t =
NIL)
DO
IF t.first.hash = hash
AND TileEqual[tile, t.first.tile]
THEN {
found ← TRUE;
loadIndex ← t.first.loadIndex;
};
ENDLOOP;
IF
NOT found
AND TileLoadWords[tile] <= PDFileWriter.RemainingLoadSize[deviceData.writer]
THEN {
loadIndex ← PutTileIntoLoad[deviceData.writer, tile];
deviceData.tileTable[bucket] ← CONS[[loadIndex, hash, IF copy THEN CopyTile[tile] ELSE tile], deviceData.tileTable[bucket]];
found ← TRUE;
};
IF found
THEN {
PDFileWriter.SetColorTile[pdState: deviceData.writer, toner: deviceData.toner, tileRef: loadIndex, tFlag: (IF clear THEN transparent ELSE opaque)];
deviceData.colorKind ← constant;
deviceData.colorTile.refRep ← NIL;
}
ELSE {
deviceData.colorTile ← (IF copy THEN CopyTile[tile] ELSE tile);
deviceData.colorClear ← clear;
deviceData.colorKind ← tile;
IF clear THEN PDFileWriter.SetColorInk[deviceData.writer, deviceData.toner]
ELSE PDFileWriter.NewPriorityLevel[pdState: deviceData.writer, toner: deviceData.toner];
};
};
UniformColor: TYPE ~ {ink, noInk, off};
SetColorUniform:
PROC [deviceData: DeviceData, u: UniformColor] ~ {
SELECT u
FROM
ink => PDFileWriter.SetColorInk[deviceData.writer, deviceData.toner];
noInk => PDFileWriter.SetColorClear[deviceData.writer, deviceData.toner];
off => PDFileWriter.SetColorOff[deviceData.writer, deviceData.toner];
ENDCASE => NULL;
deviceData.colorKind ← constant;
};
SetColorFromFraction:
PROC [deviceData: DeviceData, f:
REAL] ~ {
SELECT f
FROM
>= 0.9999 => {
-- all toner
SetColorUniform[deviceData, ink]
};
<= 0.0001 => {
-- no toner
SetColorUniform[deviceData, noInk]
};
ENDCASE => {
tile: REF Tile ~ deviceData.halftoneBrick[deviceData.toner];
pm: PixelMap ← deviceData.scratchPM.Reshape[0, [tile.sOrigin, tile.fOrigin, tile.sSize, tile.fSize]];
brickBuffer: SampleBuffer ~ deviceData.brickBuffer;
max: CARDINAL ~ Basics.BITSHIFT[1, Basics.BITSHIFT[1, pmLgBitsPerSample]] - 1;
samp: CARDINAL ← Real.Round[(1.0-f)*max];
ImagerPixelMap.Clear[pm];
FOR s:
NAT
IN [0..tile.sSize)
DO
GetBrickSamples[tile: tile, s: s+tile.sOrigin, f: tile.fOrigin, buffer: brickBuffer, bi: 0, bj: 0, count: tile.fSize];
FOR j:
NAT
IN [0..tile.fSize)
DO
brickBuffer[j] ← samp-brickBuffer[j];
ENDLOOP;
TRUSTED {
samples: UnsafeSamples ~ brickBuffer.GetPointer[0, 0, pm.fSize];
ImagerSample.UnsafePutFSign[samples: samples, count: pm.fSize, s: s, f: 0, base: pm.refRep.pointer, wordsPerLine: pm.refRep.rast];
};
ENDLOOP;
SetColorFromTile[deviceData: deviceData, tile: CreateTile[pixelMap: pm, phase: tile.phase, copy: FALSE], clear: FALSE, copy: TRUE];
deviceData.scratchPM ← pm.refRep;
};
};
UCR:
TYPE ~
RECORD [
blackGamma: REAL,
blackThreshold: REAL,
removedFraction: REAL
];
ucr:
UCR ← [
blackGamma: 0.7,
blackThreshold: 0.1,
removedFraction: 0.0
];
SetColorFromRGB:
PROC [deviceData: DeviceData, rgb: ImagerColor.
RGB, Y:
REAL] ~ {
IF deviceData.tonerUniverseSet[cyan]
AND deviceData.tonerUniverseSet[magenta]
AND deviceData.tonerUniverseSet[yellow]
THEN {
minCMY: REAL ← 1.0 - MAX[MAX[rgb.R, rgb.G], rgb.B];
IF deviceData.tonerUniverseSet[black]
AND minCMY >= ucr.blackThreshold
THEN {
Do Undercolor removal (UCR)
SELECT deviceData.toner
FROM
cyan => SetColorFromFraction[deviceData, (1.0 - rgb.R) - ((minCMY - ucr.blackThreshold) * ucr.removedFraction)];
magenta => SetColorFromFraction[deviceData, (1.0 - rgb.G) - ((minCMY - ucr.blackThreshold) * ucr.removedFraction)];
yellow => SetColorFromFraction[deviceData, (1.0 - rgb.B) - ((minCMY - ucr.blackThreshold) * ucr.removedFraction)];
black => SetColorFromFraction[deviceData, (minCMY - ucr.blackThreshold) * ucr.blackGamma];
ENDCASE => SetColorUniform[deviceData, noInk];
}
ELSE
SELECT deviceData.toner
FROM
cyan => SetColorFromFraction[deviceData, 1.0 - rgb.R];
magenta => SetColorFromFraction[deviceData, 1.0 - rgb.G];
yellow => SetColorFromFraction[deviceData, 1.0 - rgb.B];
ENDCASE => SetColorUniform[deviceData, noInk];
}
ELSE
IF deviceData.tonerUniverseSet[black]
THEN {
SetColorFromFraction[deviceData, 1.0 - Y];
}
ELSE ERROR;
};
UnimplementedColor:
PUBLIC
SIGNAL [color: Color] ~
CODE;
FloorMod4:
PROC [r:
REAL]
RETURNS [
NAT] ~ {
WHILE r<0 DO r ← r + 4.0 ENDLOOP;
WHILE r>=1024.0 DO r ← r - 1024.0 ENDLOOP;
RETURN [Real.Fix[r] MOD 4];
};
SetColor:
PROC [device: Device, color: Color, viewToDevice: Transformation] ~ {
deviceData: DeviceData ~ NARROW[device.data];
writer: PDFileWriter.PDState ~ deviceData.writer;
deviceData.colorKind ← nil;
WITH color
SELECT
FROM
color: ConstantColor => {
impl: ConstantColorImpl ~ color.impl;
WITH impl: impl
SELECT
FROM
stipple => {
word: CARDINAL ~ impl.word;
clear: BOOL ~ impl.function = paint;
pm: PixelMap ← deviceData.scratchPM.Reshape[0, [0, 0, 4, 4]];
w: CARDINAL ← word;
SELECT impl.function
FROM
replace, paint => NULL;
ENDCASE => SIGNAL UnimplementedColor[color];
FOR y:
NAT
DECREASING IN [0..4)
DO
FOR x: NAT IN [0..4) DO
bit: [0..1] ← w/(
CARDINAL[256]*128);
sf: VEC ~ ImagerTransformation.Transform[viewToDevice, [x+0.5, y+0.5]];
s: NAT ~ FloorMod4[sf.x];
f: NAT ~ FloorMod4[sf.y];
pm.PutPixel[s, f, w/(CARDINAL[256]*128)];
w ← (w - bit*(CARDINAL[256]*128))*2;
ENDLOOP;
ENDLOOP;
SetColorFromTile[deviceData, ImagerPixelMap.CreateTile[pm, 0], clear, FALSE];
deviceData.scratchPM ← pm.refRep;
};
gray => {
IF deviceData.tonerSet[black]
THEN {
SetColorFromFraction[deviceData, IF deviceData.toner = black THEN impl.f ELSE 0.0];
}
ELSE SetColorFromRGB[deviceData, [impl.Y, impl.Y, impl.Y], impl.Y];
};
rgb => {
SetColorFromRGB[deviceData, impl.val, impl.Y];
};
cie => {
SetColorFromRGB[deviceData, ImagerColor.RGBFromCIE[impl.val], impl.Y];
};
ENDCASE => ERROR;
};
color: SampledColor => {
pa: PixelArray ~ color.pa;
um: Transformation ~ color.um;
colorOperator: ColorOperator ~ color.colorOperator;
fullColor: BOOL ~ deviceData.tonerUniverseSet[cyan] AND deviceData.tonerUniverseSet[magenta] AND deviceData.tonerUniverseSet[yellow];
ImagerTransformation.ApplyCat[deviceData.paToDevice, pa.m, color.um, viewToDevice];
SELECT ImagerColorOperator.GetColorOperatorClass[colorOperator]
FROM
$SampledBlack => SetColorFromSampledBlack[device, pa, FALSE];
$SampledBlackClear => SetColorFromSampledBlack[device, pa, TRUE];
$GrayLinear, $GrayDensity, $GrayVisual => {
IF deviceData.tonerUniverseSet[black]
AND deviceData.toner # black
THEN {
SetColorUniform[deviceData, noInk];
}
ELSE SetColorFromPixelArray[device, pa, colorOperator, $Intensity];
};
ENDCASE => {
IF fullColor
THEN {
component:
ATOM ~
SELECT deviceData.toner
FROM
cyan => $Red,
magenta => $Green,
yellow => $Blue,
ENDCASE => NIL;
IF component=
NIL
THEN {
SetColorUniform[deviceData, noInk];
}
ELSE SetColorFromPixelArray[device, pa, colorOperator, component];
}
ELSE {
SetColorFromPixelArray[device, pa, colorOperator, $Intensity];
};
};
};
ENDCASE => ERROR;
};
me:
REF
TEXT ~ "PD";
-- a globally unique REF for use as a clientID in the global cache.
SetColorFromSampledBlack:
PROC [device: Device, pa: PixelArray, clear:
BOOL] ~ {
deviceData: DeviceData ~ NARROW[device.data];
IF deviceData.tonerUniverseSet[black]
AND deviceData.toner # black
THEN {
SetColorUniform[deviceData, IF clear THEN off ELSE noInk];
}
ELSE {
cache: FunctionCache.Cache ~ FunctionCache.GlobalCache[];
compare: FunctionCache.CompareProc ~ {RETURN [argument=pa]};
scd: REF PixelMap ← NARROW[FunctionCache.Lookup[cache, compare, me].value];
IF scd =
NIL
THEN
TRUSTED {
source: ImagerPixelMap.PixelMap ~ ImagerPixelMap.Create[
lgBitsPerPixel: 0, bounds: [sMin: 0, fMin: 0, sSize: pa.sSize, fSize: pa.fSize]];
ImagerPixelMap.Clear[source];
ImagerPixelArray.UnsafeGetBits[pa: pa, i: 0, s: 0, f: 0, dst: [word: source.refRep.pointer, bit: 0], dstBpl: source.refRep.rast*bitsPerWord, width: source.fSize, height: source.sSize];
scd ← NEW[PixelMap ← source];
FunctionCache.Insert[cache, pa, scd, source.refRep.words, me];
};
deviceData.sampledSource ← scd^;
IF deviceData.paToDevice.form = 3
AND deviceData.paToDevice.integerTrans
THEN {
SetColorFromTile[deviceData, CreateTile[scd^.ShiftMap[deviceData.paToDevice.tx, deviceData.paToDevice.ty], 0], clear, FALSE];
}
ELSE {
deviceData.colorKind ← sampledBlack;
deviceData.colorClear ← clear;
PDFileWriter.SetColorInk[deviceData.writer, deviceData.toner];
};
};
};
pmLgBitsPerSample:
NAT ~ 3;
-- for sampled color source
SetColorFromPixelArray:
PROC [device: Device, pa: PixelArray, colorOperator: ColorOperator, component:
ATOM] ~ {
deviceData: DeviceData ~ NARROW[device.data];
cache: FunctionCache.Cache ~ FunctionCache.GlobalCache[];
compare: FunctionCache.CompareProc ~ {
WITH argument
SELECT
FROM
a: REF ARRAY [0..1] OF REF => RETURN [a[0]=pa AND a[1]=component];
ENDCASE => RETURN [FALSE];
};
scd: REF PixelMap ← NARROW[FunctionCache.Lookup[cache, compare, me].value];
IF scd =
NIL
THEN
TRUSTED {
bitsPerSample: NAT ~ Basics.BITSHIFT[1, pmLgBitsPerSample];
maxSample: Sample ~ Basics.BITSHIFT[1, bitsPerSample]-1;
sSize: NAT ~ pa.sSize;
fSize: NAT ~ pa.fSize;
maxIn: Sample ~ ImagerPixelArray.MaxSampleValue[pa, 0];
pm: ImagerPixelMap.PixelMap ~ ImagerPixelMap.Create[
lgBitsPerPixel: pmLgBitsPerSample,
bounds: [sMin: 0, fMin: 0, sSize: sSize, fSize: fSize]];
pixels: SampleBuffer ~ ImagerSample.NewBuffer[pa.samplesPerPixel, fSize];
buffer: SampleBuffer ~ ImagerSample.NewBuffer[1, fSize];
mapper: ImagerColorOperator.Mapper ~ ImagerColorOperator.NewMapper[
op: colorOperator, component: component, maxIn: maxIn, maxOut: maxSample];
samples: UnsafeSamples ~ buffer.GetPointer[0, 0, fSize];
pmBase: LONG POINTER ~ pm.refRep.pointer;
pmWordsPerLine: NAT ~ pm.refRep.rast;
a: REF ARRAY [0..1] OF REF ← NEW[ARRAY [0..1] OF REF ← [pa, component]];
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, count: fSize];
TRUSTED { ImagerSample.UnsafePutF[samples: samples, count: fSize,
base: pmBase, wordsPerLine: pmWordsPerLine,
bitsPerSample: bitsPerSample, s: s, f: 0] };
ENDLOOP;
scd ← NEW[ImagerPixelMap.PixelMap ← pm];
FunctionCache.Insert[cache, pa, scd, pm.refRep.words, me];
};
deviceData.sampledSource ← scd^;
deviceData.colorKind ← sampled;
PDFileWriter.NewPriorityLevel[pdState: deviceData.writer, toner: deviceData.toner];
};
DeviceBox:
TYPE ~ ImagerDevice.DeviceBox;
DivMod:
PROC [n:
INTEGER, d:
NAT]
RETURNS [quotient:
INTEGER, remainder:
NAT] ~ {
Number-theoretic: 0 <= remainder < d, n = quotient*d + remainder
IF d#1
THEN {
nn: Basics.LongNumber ← [li[n]];
qq: Basics.LongNumber ← [lc[0]];
IF nn.li < 0 THEN {nn.highbits ← nn.highbits + d; -- qq.highbits ← CARDINAL.LAST --};
[quotient: qq.lowbits, remainder: remainder] ← Basics.LongDivMod[nn.lc, d];
quotient ← qq.li;
quotient ← LOOPHOLE[qq.lowbits];
}
ELSE RETURN [quotient: n, remainder: 0];
};
Mod:
PROC [n:
INT, d:
NAT]
RETURNS [remainder:
NAT] ~ {
Number-theoretic: 0 <= remainder < d
IF d#1
THEN {
nn: Basics.LongNumber ← [li[n]];
WHILE nn.li < 0 DO nn.highbits ← nn.highbits + d ENDLOOP;
WHILE nn.highbits >= d DO nn.highbits ← nn.highbits - d ENDLOOP;
RETURN [Basics.LongDivMod[nn.lc, d].remainder];
}
ELSE RETURN [remainder: 0];
};
Mul:
PROC [a:
INTEGER, b:
NAT]
RETURNS [
INT] ~ {
IF a >= 0 THEN RETURN [Basics.LongMult[a, b]]
ELSE RETURN [-INT[Basics.LongMult[-a, b]]];
};
cd: REF PixelMap ← NIL;
GetBrickSamples:
PROC [tile:
REF Tile, s, f:
INTEGER, buffer: SampleBuffer, bi, bj, count:
NAT] ~
TRUSTED {
samples: UnsafeSamples ~ buffer.GetPointer[bi, bj, count];
refRep: REF ImagerPixelMap.PixelMapRep ~ tile.refRep;
base: LONG POINTER ~ refRep.pointer;
wordsPerLine: NAT ~ refRep.rast;
bitsPerSample: ImagerSample.BitsPerSample ~ Basics.BITSHIFT[1, refRep.lgBitsPerPixel];
fSizeTile: NAT ~ tile.fSize;
initCount: NAT ~ MIN[fSizeTile, count];
b: INTEGER;
s0, f0, c0: NAT;
[quotient: b, remainder: s0] ← DivMod[s-tile.sOrigin, tile.sSize];
f0 ← Mod[f-tile.fOrigin-Mul[b, tile.phase], tile.fSize];
c0 ← MIN[initCount, tile.fSize-f0];
ImagerSample.UnsafeGetF[samples: samples, count: c0, s: s0, f: f0, base: base, wordsPerLine: wordsPerLine, bitsPerSample: bitsPerSample];
IF c0 < initCount
THEN {
ImagerSample.UnsafeGetF[samples: samples+c0, count: initCount-c0, s: s0, f: 0, base: base, wordsPerLine: wordsPerLine, bitsPerSample: bitsPerSample];
};
IF count > fSizeTile
THEN {
PrincOpsUtils.LongCopy[from: samples, nwords: count-fSizeTile, to: samples+fSizeTile];
};
IF cd #
NIL
THEN {
ImagerSample.UnsafePutF[samples: ImagerSample.GetPointer[buffer, 0, 0, cd.fSize], count: cd.fSize, s: Mod[s-cd.sOrigin, cd.sSize], f: 0, base: cd.refRep.pointer, wordsPerLine: cd.refRep.rast, bitsPerSample: Basics.BITSHIFT[1, cd.refRep.lgBitsPerPixel]];
};
};
MaskRuns:
PROC[device: Device, bounds: DeviceBox, runs:
PROC[ImagerDevice.RunProc]] ~ {
deviceData: DeviceData ~ NARROW[device.data];
SELECT deviceData.colorKind
FROM
nil => ERROR; -- color not initialized
constant => {
PDFileWriter.MaskRunGroup[deviceData.writer, runs];
};
sampled, sampledBlack =>
TRUSTED {
binary: BOOL ~ deviceData.colorKind=sampledBlack;
tFlag: PDFileWriter.TFlag ~ IF binary AND deviceData.colorClear THEN transparent ELSE opaque;
sampler: ImagerSample.Sampler ~ deviceData.sampler;
sampleBuffer: SampleBuffer ~ deviceData.sampleBuffer;
brickBuffer: SampleBuffer ~ deviceData.brickBuffer;
bitBuffer: SampleBuffer ~ deviceData.bitBuffer;
bitBufferSize: NAT ~ bounds.fmax-bounds.fmin;
bitBufferPointer: LONG POINTER ~ bitBuffer.GetPointer[0, 0, (bitBufferSize+bitsPerWord-1)/bitsPerWord];
deliverLine: PROC[p: PROC [LONG POINTER]] ~ TRUSTED {p[bitBufferPointer]};
tile: REF Tile ~ deviceData.halftoneBrick[deviceData.toner];
pdSampledRun:
PROC [sMin, fMin:
INTEGER, fSize:
NAT] ~
TRUSTED {
ImagerSample.GetPointSamples[sampler: sampler, s: sMin, f: fMin,
buffer: sampleBuffer, bi: 0, bj: 0, count: fSize];
GetBrickSamples[tile: tile, s: sMin, f: fMin, buffer: brickBuffer, bi: 0, bj: 0, count: fSize];
ImagerSample.SubSamples[samples: brickBuffer, si: 0, sj: 0,
buffer: sampleBuffer, bi: 0, bj: 0, count: fSize];
TRUSTED {
samples: UnsafeSamples ~ sampleBuffer.GetPointer[0, 0, fSize];
bitBuffer[fSize/bitsPerWord] ← 0;
ImagerSample.UnsafePutFSign[samples: samples, count: Check[fSize, bitBufferSize],
s: 0, f: 0, base: bitBufferPointer, wordsPerLine: 0];
PDFileWriter.ColorSamples[pdState: deviceData.writer, toner: deviceData.toner,
sMin: sMin, fMin: fMin, sSize: 1, fSize: fSize, deliverProc: deliverLine,
tFlag: tFlag];
};
};
pdSampledBlackRun:
PROC [sMin, fMin:
INTEGER, fSize:
NAT] ~
TRUSTED {
ImagerSample.GetPointSamples[sampler: sampler, s: sMin, f: fMin,
buffer: sampleBuffer, bi: 0, bj: 0, count: fSize];
TRUSTED {
samples: UnsafeSamples ~ sampleBuffer.GetPointer[0, 0, fSize];
bitBuffer[fSize/bitsPerWord] ← 0;
ImagerSample.UnsafePutF[samples: samples, count: Check[fSize, bitBufferSize],
s: 0, f: 0, base: bitBufferPointer, wordsPerLine: 0, bitsPerSample: 1];
PDFileWriter.ColorSamples[pdState: deviceData.writer, toner: deviceData.toner,
sMin: sMin, fMin: fMin, sSize: 1, fSize: fSize, deliverProc: deliverLine,
tFlag: tFlag];
};
};
t: ImagerPixelMap.PixelMap ~ deviceData.sampledSource;
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, deviceData.paToDevice];
ImagerSample.SetSamplerPosition[sampler: sampler, m: deviceData.paToDevice, s: bounds.smin, f: bounds.fmin];
IF binary THEN runs[pdSampledBlackRun] ELSE runs[pdSampledRun];
};
tile => {
tFlag: PDFileWriter.TFlag ~ IF deviceData.colorClear THEN transparent ELSE opaque;
scratch: REF ImagerPixelMap.PixelMapRep ← deviceData.scratchPM;
pdTileRun:
PROC [sMin, fMin:
INTEGER, fSize:
NAT] ~ {
pm: PixelMap ~ ImagerPixelMap.Reshape[scratch, 0, [sMin, fMin, 1, fSize]];
deliverLine: PROC[p: PROC [LONG POINTER]] ~ TRUSTED {p[pm.refRep.pointer]};
ImagerPixelMap.TransferTile[pm, deviceData.colorTile];
PDFileWriter.ColorSamples[pdState: deviceData.writer, toner: deviceData.toner,
sMin: sMin, fMin: fMin, sSize: 1, fSize: fSize, deliverProc: deliverLine,
tFlag: tFlag];
scratch ← pm.refRep;
};
runs[pdTileRun];
deviceData.scratchPM ← scratch;
};
ENDCASE => ERROR; -- illegal case
};
GetLoadEntry:
PROC [deviceData: DeviceData, mask: CharMask]
RETURNS [
REF
INT] ~ {
refInt: REF INT ← NARROW[RefTab.Fetch[deviceData.maskTab, mask].val];
load: INT ← 0;
IF refInt#NIL THEN RETURN [refInt];
WITH mask
SELECT
FROM
raster:
REF ImagerDevice.CharMaskRep.raster => {
loadWords: INT ~ SIZE[PDFileFormat.SampleArray] + Basics.LongMult[raster.sSizeBB, (raster.fSizeBB+bitsPerWord-1)/bitsPerWord];
IF loadWords > PDFileWriter.RemainingLoadSize[deviceData.writer] THEN RETURN[NIL];
TRUSTED {load ← PDFileWriter.LoadContiguousSampleArray[pdState: deviceData.writer, sSize: raster.sSizeBB, fSize: raster.fSizeBB, bitsPtr: @(raster[0])]};
};
runs:
REF ImagerDevice.CharMaskRep.runs => {
Runs:
PROC [run:
PROC [sMin, fMin:
INTEGER, fSize:
NAT]] ~ {
s: INTEGER ← 0;
sMax: INTEGER ~ runs.sSizeBB;
FOR i:
NAT
IN [0..runs.nRuns)
WHILE s < sMax
DO
r: ImagerDevice.Run ~ runs[i];
IF r.fSize # 0 THEN run[s, r.fMin, r.fSize];
IF r.lastRun THEN s ← s + 1;
ENDLOOP;
};
loadWords: INT ~ SIZE[PDFileFormat.RunGroup] + runs.nRuns*SIZE[PDFileFormat.Run];
IF loadWords > PDFileWriter.RemainingLoadSize[deviceData.writer] THEN RETURN[NIL];
load ← PDFileWriter.LoadRunGroup[deviceData.writer, Runs];
};
ENDCASE => ERROR;
refInt ← NEW[INT ← load];
[] ← RefTab.Store[deviceData.maskTab, mask, refInt];
RETURN [refInt];
};
MaskChar:
PROC [device: Device, s, f:
INTEGER, mask: CharMask] ~ {
deviceData: DeviceData ~ NARROW[device.data];
loadEntry: REF INT ← GetLoadEntry[deviceData, mask];
sMin: NAT ~ s+mask.sMinBB;
fMin: NAT ~ f+mask.fMinBB;
IF deviceData.colorKind=constant
AND loadEntry#
NIL
THEN {
load: LONG CARDINAL ~ loadEntry^;
SELECT mask.rep
FROM
raster => PDFileWriter.MaskSamplesRef[deviceData.writer, load, sMin, fMin];
runs => PDFileWriter.MaskRunGroupRef[deviceData.writer, load, sMin, fMin];
ENDCASE => ERROR;
}
ELSE
WITH mask
SELECT
FROM
raster:
REF ImagerDevice.CharMaskRep.raster => {
boxes: PROC[action: PROC[DeviceBox]] ~ {action[[smin: sMin, fmin: fMin, smax: sMin+mask.sSizeBB, fmax: fMin+mask.fSizeBB]]};
TRUSTED {MaskBits[device: device,
srcBase: @raster[0],
srcWordsPerLine: (raster.fSizeBB+(bitsPerWord-1))/bitsPerWord,
ts: sMin,
tf: fMin,
boxes: boxes
]};
};
runs:
REF ImagerDevice.CharMaskRep.runs => {
Runs:
PROC [run: ImagerDevice.RunProc] ~ {
s: INTEGER ← sMin;
sMax: INTEGER ~ sMin+runs.sSizeBB;
FOR i:
NAT
IN [0..runs.nRuns)
WHILE s < sMax
DO
r: ImagerDevice.Run ~ runs[i];
IF r.fSize # 0 THEN run[s, r.fMin+fMin, r.fSize];
IF r.lastRun THEN s ← s + 1;
ENDLOOP;
};
MaskRuns[device: device, bounds: [smin: sMin, fmin: fMin, smax: sMin+mask.sSizeBB, fmax: fMin+mask.fSizeBB], runs: Runs];
};
ENDCASE => ERROR;
};
MaskBoxes:
PROC[device: Device, bounds: DeviceBox, boxes:
PROC[ImagerDevice.BoxProc]] ~ {
deviceData: DeviceData ~ NARROW[device.data];
SELECT deviceData.colorKind
FROM
nil => ERROR; -- color not initialized
constant => {
constantBox:
PROC[box: DeviceBox] ~ {
PDFileWriter.MaskRectangle[deviceData.writer, box.smin, box.fmin, box.smax-box.smin, box.fmax-box.fmin];
};
boxes[constantBox];
};
ENDCASE => {
hardBox:
PROC[box: DeviceBox] ~ {
runs: PROC[run: ImagerDevice.RunProc] ~ { ImagerMask.RunsFromBox[box: box, run: run] };
MaskRuns[device: device, bounds: box, runs: runs];
};
boxes[hardBox];
};
};
MaskBits:
PROC[device: Device, srcBase:
LONG
POINTER, srcWordsPerLine:
NAT,
ts, tf:
INTEGER, boxes:
PROC[ImagerDevice.BoxProc]] ~ {
deviceData: DeviceData ~ NARROW[device.data];
hardMaskBitsBox:
PROC[box: DeviceBox] ~ {
hardMaskBitsBoxAction:
PROC ~ {
runs:
PROC[run: ImagerDevice.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];
};
MaskRuns[device: device, bounds: box, runs: runs];
};
};
SELECT deviceData.colorKind
FROM
nil => ERROR; -- color not initialized
constant => {
boxAction:
PROC[box: DeviceBox] ~ {
Line:
PROC[p:
PROC [
LONG
POINTER]] ~
TRUSTED {
a: LONG POINTER ← srcBase;
FOR c:
CARDINAL
IN [box.smin..box.smax)
DO
p[a];
a ← a + srcWordsPerLine;
ENDLOOP;
};
IF INTEGER[box.smin]#ts OR INTEGER[box.fmin]#tf THEN hardMaskBitsBox[box]
ELSE PDFileWriter.MaskSamples[
pdState: deviceData.writer,
sMin: ts,
fMin: tf,
sSize: box.smax-box.smin,
fSize: box.fmax-box.fmin,
deliverProc: Line
];
};
boxes[boxAction];
};
ENDCASE => boxes[hardMaskBitsBox];
};