ImagerFourColorContextImpl.mesa
Copyright Ó 1989, 1990, 1991, 1992, 1993 by Xerox Corporation. All rights reserved.
Tim Diebert: January 6, 1993 12:04 pm PST
Doug Wyatt, September 14, 1989 2:34:44 pm PDT
Dave Rumph, May 25, 1990 12:43:50 pm PDT
Michael Plass, March 27, 1992 11:58 pm PST
DIRECTORY
ImagerFourColorContext USING [Toner],
Imager USING [Context],
ImagerBrick USING [HalftoneProperties],
ImagerColor USING [Color],
ImagerDevice USING [AllowedMasks, Device, DeviceClass, DeviceClassRep, DeviceParm, MakeDeviceParm],
ImagerMaskCache USING [GetNamedCache, SetNamedCacheParameters],
ImagerPrintColor USING [DeviceColorData, MaskBoxes, NewDeviceColorData, SetDeviceColorData, SetSeparation],
ImagerPrivate USING [Class],
ImagerRaster USING [Create, CreateClass, GetDevice, SetDeviceClipBox],
ImagerSample USING [BasicTransfer, Box, Function, GetBox, RasterSampleMap, RawDescriptor, RawListTransfer, SampleMap],
ImagerTransformation USING [Transformation, ScanMode],
PrintColor USING [ColorCorrection, HalftoneProperties, LogicalDevice, Toner],
SF USING [Box, BoxAction, BoxGenerator, Vec],
SFInline USING [Size, Sub],
Vector2 USING [VEC];
ImagerFourColorContextImpl: CEDAR PROGRAM
IMPORTS ImagerDevice, ImagerMaskCache, ImagerPrintColor, ImagerRaster, ImagerSample, SFInline
EXPORTS ImagerFourColorContext
~ BEGIN
Copied types
Color: TYPE ~ ImagerColor.Color;
Context: TYPE ~ Imager.Context;
Transformation: TYPE ~ ImagerTransformation.Transformation;
Local types
Toner: TYPE ~ ImagerFourColorContext.Toner; -- {black, cyan, magenta, yellow};
toners: ARRAY Toner OF PrintColor.Toner ~ [black, cyan, magenta, yellow];
Data: TYPE ~ REF DataRep;
DataRep: TYPE ~ RECORD [
bitmaps: ARRAY Toner OF ImagerSample.SampleMap ¬ ALL[NIL],
deviceColorData: ARRAY Toner OF ImagerPrintColor.DeviceColorData ¬ ALL[NIL]
];
Local variables
fontCacheName: ATOM ~ $FourColorPrint;
fontCacheMaxSize: INT ¬ 8000;
Exported procedures
Create: PUBLIC PROC [deviceSpaceSize: SF.Vec, scanMode: ImagerTransformation.ScanMode, surfaceUnitsPerInch: Vector2.VEC, logicalDevice: PrintColor.LogicalDevice, halftoneProperties: PrintColor.HalftoneProperties, correction: PrintColor.ColorCorrection, interpolate: BOOL, bitmaps: ARRAY Toner OF ImagerSample.SampleMap]
RETURNS [Imager.Context] ~ {
box: ImagerSample.Box ~ ImagerSample.GetBox[map: bitmaps[black]];
data: Data ~ NEW[DataRep ¬ [
bitmaps: bitmaps,
deviceColorData: ALL[NIL]
]];
deviceParm: ImagerDevice.DeviceParm ~ ImagerDevice.MakeDeviceParm[
class: deviceClass,
sSize: deviceSpaceSize.s,
fSize: deviceSpaceSize.f,
scanMode: scanMode,
surfaceUnitsPerInch: surfaceUnitsPerInch,
surfaceUnitsPerPixel: 1,
fontCache: ImagerMaskCache.GetNamedCache[fontCacheName]
];
context: Imager.Context ~ ImagerRaster.Create[class: contextClass, deviceClass: deviceClass, deviceParm: deviceParm, data: data, pixelUnits: FALSE];
ImagerRaster.SetDeviceClipBox[context: context, clipBox: box];
FOR t: Toner IN Toner DO
data.deviceColorData[t] ¬ ImagerPrintColor.NewDeviceColorData[logicalDevice: logicalDevice, halftoneProperties: halftoneProperties, correction: correction, interpolate: interpolate];
ImagerPrintColor.SetSeparation[data.deviceColorData[t], toners[t]];
ENDLOOP;
RETURN [context]
};
SetBitmaps: PUBLIC PROC [context: Imager.Context,
bitmaps: ARRAY Toner OF ImagerSample.SampleMap] ~ {
device: ImagerDevice.Device = ImagerRaster.GetDevice[context];
data: Data ~ NARROW[device.data];
box: ImagerSample.Box ~ ImagerSample.GetBox[map: bitmaps[black]];
ImagerRaster.SetDeviceClipBox[context: context, clipBox: box];
FOR t: Toner IN Toner DO
data.bitmaps[t] ¬ bitmaps[t];
ENDLOOP;
};
Imager procedures
MySetColor: PROC [device: ImagerDevice.Device, color: Color, viewToDevice: Transformation] ~ {
data: Data ~ NARROW[device.data];
constant: BOOL ¬ TRUE;
allowFunnyBoxes: BOOL ¬ TRUE;
allRasterSampleMaps: BOOL ¬ TRUE;
FOR t: Toner IN Toner DO
deviceColorData: ImagerPrintColor.DeviceColorData ~ data.deviceColorData[t];
ImagerPrintColor.SetDeviceColorData[deviceColorData, color, viewToDevice];
IF deviceColorData.case # constant THEN constant ¬ FALSE;
IF deviceColorData.case >= sampledColor THEN allowFunnyBoxes ¬ FALSE;
IF NOT ISTYPE[data.bitmaps[t], ImagerSample.RasterSampleMap]
THEN allRasterSampleMaps ¬ FALSE
ENDLOOP;
device.state.allow ¬ [
unorderedBoxes: allowFunnyBoxes,
multipleCoverage: allowFunnyBoxes,
bitmap: constant,
rawBitmaps: (constant AND allRasterSampleMaps)
];
};
The following is nifty, but unfortunately, it doesn't work for transparent sampled blacks, in which the non-black toners' action is a nop, breaking the recursion. -- Dave Rumph, May 25, 1990 12:40:46 pm PDT
MyMaskBoxes: PROC [device: ImagerDevice.Device, bounds: SF.Box, boxes: SF.BoxGenerator] ~ {
data: Data ~ NARROW[device.data];
Here's a good one for you...
Inner: PROC [which: Toner, prevBoxAction: SF.BoxAction ← NIL] ~ {
NextGen: SF.BoxGenerator = {
[boxAction: SF.BoxAction]
ThisAction: SF.BoxAction = { prevBoxAction[box]; boxAction[box] };
IF which = Toner.LAST
THEN boxes[ThisAction]
ELSE Inner[which.SUCC, IF prevBoxAction = NIL THEN boxAction ELSE ThisAction];
};
ImagerPrintColor.MaskBoxes[data.bitmaps[which], data.deviceColorData[which], bounds, NextGen];
};
Inner[Toner.FIRST];
};
TranslateHalftoneProperties: PROC [h: ImagerBrick.HalftoneProperties] RETURNS [PrintColor.HalftoneProperties] ~ {
Eliminate this when PrintColor.HalftoneProperties becomes the same as ImagerBrick.HalftoneProperties
RETURN[
IF h = NIL
THEN NIL
ELSE CONS[
[type: h.first.type, toner: LOOPHOLE[h.first.toner], brick: h.first.brick],
TranslateHalftoneProperties[h.rest]]]
};
MySetHalftoneProperties: PROC [device: ImagerDevice.Device, halftoneProperties: ImagerBrick.HalftoneProperties] ~ {
data: Data ~ NARROW[device.data];
h: PrintColor.HalftoneProperties ~ TranslateHalftoneProperties[halftoneProperties];
FOR which: Toner IN Toner DO
data.deviceColorData[which].halftoneProperties ¬ h;
ENDLOOP;
Note that a SetColor should be done before further masking.
};
MyMaskBoxes: PROC [device: ImagerDevice.Device, bounds: SF.Box, boxes: SF.BoxGenerator] ~ {
data: Data ~ NARROW[device.data];
FOR which: Toner IN Toner DO
ImagerPrintColor.MaskBoxes[data.bitmaps[which], data.deviceColorData[which], bounds, boxes];
ENDLOOP;
};
MyMaskBitmap: PROC [device: ImagerDevice.Device, bitmap: ImagerSample.SampleMap, delta: SF.Vec, bounds: SF.Box, boxes: SF.BoxGenerator] ~ {
data: Data ~ NARROW[device.data];
function: ARRAY Toner OF ImagerSample.Function ¬ ALL[[null, null]];
Box: SF.BoxAction = {
[box: SF.Box]
FOR t: Toner IN Toner DO
ImagerSample.BasicTransfer[dst: data.bitmaps[t], src: bitmap, dstMin: box.min,
srcMin: SFInline.Sub[box.min, delta], size: SFInline.Size[box], function: function[t]];
ENDLOOP;
};
FOR t: Toner IN Toner DO
IF data.deviceColorData[t].case # constant THEN ERROR;
SELECT data.deviceColorData[t].ink FROM
nop => NULL;
set => function[t] ¬ [or, null];
remove => function[t] ¬ [and, complement];
ENDCASE => ERROR;
ENDLOOP;
boxes[Box];
};
MyMaskRawBitmaps: PROC [device: ImagerDevice.Device, list: LIST OF ImagerSample.RawDescriptor] = {
data: Data = NARROW[device.data];
function: ImagerSample.Function ¬ [null, null];
FOR t: Toner IN Toner DO
local: ImagerSample.RasterSampleMap ~ NARROW [data.bitmaps[t]];
IF data.deviceColorData[t].case # constant THEN ERROR;
SELECT data.deviceColorData[t].ink FROM
nop => NULL;
set => function ¬ [or, null];
remove => function ¬ [and, complement];
ENDCASE => ERROR;
ImagerSample.RawListTransfer[dst: local, src: list, function: function];
ENDLOOP;
};
Start trap
deviceClass: ImagerDevice.DeviceClass ~ NEW[ImagerDevice.DeviceClassRep ¬ [
SetColor: MySetColor,
SetHalftoneProperties: MySetHalftoneProperties,
MaskBoxes: MyMaskBoxes,
MaskBitmap: MyMaskBitmap,
MaskRawBitmaps: MyMaskRawBitmaps
]];
contextClass: ImagerPrivate.Class ~ ImagerRaster.CreateClass[type: $FourColor];
ImagerMaskCache.SetNamedCacheParameters[fontCacheName,
[sizeLimit: fontCacheMaxSize, runsCost: [slope: 2, offset: 3]]];
END.