XlBitmapImagerImpl.mesa
Copyright Ó 1990, 1991, 1992 by Xerox Corporation. All rights reserved.
Created by Christian Jacobi, October 30, 1990 2:20:01 pm PST
Christian Jacobi, August 19, 1993 12:21 pm PDT
Willie-s, October 17, 1991 1:55 pm PDT
Michael Plass, January 20, 1992 1:05 pm PST
That particular part of XlBitmapImpl which uses imager device features.
These functions are separated out to allow Imager-less XlBitmap implementation for you know who.
DIRECTORY
Imager,
ImagerBitmapContext,
ImagerBrick,
ImagerColor,
ImagerDevice,
ImagerDeviceInterchange,
ImagerDither,
ImagerDitherContext,
ImagerMaskCache,
ImagerRaster,
ImagerSample,
SF,
SFInline,
XlBitmap,
XlBitmapPrivate,
XlBitmapFriends;
XlBitmapImagerImpl: CEDAR MONITOR
IMPORTS ImagerBitmapContext, ImagerDevice, ImagerDitherContext, ImagerRaster, ImagerSample, SFInline
EXPORTS XlBitmap, XlBitmapFriends =
BEGIN OPEN XlBitmap, XlBitmapPrivate;
BitmapRep: PUBLIC TYPE = XlBitmapPrivate.BitmapRepDef;
ContextCreator: TYPE = XlBitmapFriends.ContextCreator;
CharMask: TYPE ~ ImagerMaskCache.CharMask;
Color: TYPE ~ Imager.Color;
Device: TYPE ~ ImagerDevice.Device;
DeviceClass: TYPE ~ ImagerDevice.DeviceClass;
PixelMap: TYPE ~ Imager.PixelMap;
SampleMap: TYPE ~ Imager.SampleMap;
Transformation: TYPE ~ Imager.Transformation;
CreatorRegistration: TYPE = RECORD [bpp: INT, creator: ContextCreator];
creators: LIST OF CreatorRegistration ¬ NIL;
RegisterContextCreator: PUBLIC ENTRY PROC [bpp: INT, creator: ContextCreator] = {
IF creator#NIL THEN creators ¬ CONS[[bpp, creator], creators];
};
InternalCreateContext: PROC [sm: ImagerSample.RasterSampleMap, surfaceUnitsPerPixel: NAT ¬ 1, extras: REF ANY] RETURNS [Imager.Context] = {
bpp: ImagerSample.BitsPerSample ~ ImagerSample.GetBitsPerSample[sm];
FOR l: LIST OF CreatorRegistration ¬ creators, l.rest WHILE l#NIL DO
IF l.first.bpp=bpp THEN RETURN [l.first.creator[sm, surfaceUnitsPerPixel, extras]]
ENDLOOP;
ERROR;
};
hasSwitchBuffer: BOOL ¬ TRUE;
DebugSwitchBufferTRUE: PROC [] = {hasSwitchBuffer ¬ TRUE};
DebugSwitchBufferFALSE: PROC [] = {hasSwitchBuffer ¬ FALSE};
AssertDevice: PROC [b: Bitmap, context: Imager.Context] RETURNS [Imager.Context] = {
iState: ImagerDeviceInterchange.InterchangeState ¬ ImagerRaster.GetInterchangeState[context];
iData: InterceptData ¬ NEW[InterceptDataRep ¬ [
device: iState.device,
buffered: FALSE,
b: b
]];
worksState: ImagerDevice.WorksState ~ iState.device.worksState;
iState.device ¬ ImagerDevice.MakeDevice[
class: IF hasSwitchBuffer THEN modifiedDeviceClass1 ELSE modifiedDeviceClass2,
parm: iState.device.parm,
state: iState.device.state,
data: iData
];
iState.device.worksState ¬ worksState;
RETURN [ ImagerRaster.ContextFromInterchangeState[iState, context] ];
};
CreateContext: PUBLIC PROC [bitmap: Bitmap, surfaceUnitsPerPixel: NAT ¬ 1] RETURNS [context: Imager.Context] = {
bpp: ImagerSample.BitsPerSample = ImagerSample.GetBitsPerSample[bitmap.sm];
IF bpp = 1
THEN {
context ¬ ImagerBitmapContext.Create[deviceSpaceSize: bitmap.sz, scanMode: [slow: down, fast: right], surfaceUnitsPerInch: [72, 72], surfaceUnitsPerPixel: surfaceUnitsPerPixel, pixelUnits: TRUE, fontCacheName: $Bitmap];
ImagerBitmapContext.SetBitmap[context: context, bitmap: bitmap.sm];
}
ELSE {
context ¬ InternalCreateContext[bitmap.sm, surfaceUnitsPerPixel, bitmap.colormapEntries];
};
context ¬ AssertDevice[bitmap, context];
};
PostIntercept: PROC [b: Bitmap, box: SF.Box] = INLINE {
IF ~SFInline.Inside[inner: box, outer: b.delayBox] THEN
FOR postList: ICClosures ¬ b.postList, postList.rest WHILE postList#NIL DO
postList.first.proc[box, postList.first.data, FALSE];
ENDLOOP;
};
IPostIntercept: PROC [iData: InterceptData, box: SF.Box] = {
IF ~iData.buffered THEN PostIntercept[iData.b, box];
};
IPreIntercept: PROC [iData: InterceptData, box: SF.Box] = {
IF ~iData.buffered THEN
FOR preList: ICClosures ¬ iData.b.preList, preList.rest WHILE preList#NIL DO
preList.first.proc[box, preList.first.data, TRUE];
ENDLOOP;
};
InterceptData: TYPE ~ REF InterceptDataRep;
InterceptDataRep: TYPE ~ RECORD [
device: Device,
buffered: BOOL,
b: Bitmap
];
ModifySetColor: PROC [device: Device, color: Color, viewToDevice: Transformation] ~ {
iData: InterceptData ~ NARROW[device.data];
iData.device.class.SetColor[iData.device, color, viewToDevice];
};
ModifySetPriority: PROC [device: Device, priorityImportant: BOOL] ~ {
iData: InterceptData ~ NARROW[device.data];
iData.device.class.SetPriority[iData.device, priorityImportant];
};
ModifySetHalftoneProperties: PROC [device: Device, halftoneProperties: ImagerBrick.HalftoneProperties] ~ {
iData: InterceptData ~ NARROW[device.data];
IF iData.device.class.SetHalftoneProperties = NIL THEN RETURN;
iData.device.class.SetHalftoneProperties[iData.device, halftoneProperties];
};
ModifyMaskBoxes: PROC [device: Device, bounds: SF.Box, boxes: SF.BoxGenerator] ~ {
iData: InterceptData ~ NARROW[device.data];
iData.device.class.MaskBoxes[iData.device, bounds, boxes];
IPostIntercept[iData, bounds];
};
ModifyMaskRegion: PROC [device: Device, bounds: SF.Box, edgeGenerator: PROC [ImagerSample.EdgeAction]] ~ {
iData: InterceptData ~ NARROW[device.data];
iData.device.class.MaskRegion[iData.device, bounds, edgeGenerator];
IPostIntercept[iData, bounds];
};
ModifyMaskBitmap: PROC [device: Device, bitmap: SampleMap, delta: SF.Vec, bounds: SF.Box, boxes: SF.BoxGenerator] ~ {
iData: InterceptData ~ NARROW[device.data];
iData.device.class.MaskBitmap[iData.device, bitmap, delta, bounds, boxes];
IPostIntercept[iData, bounds];
};
ModifyMaskRawBitmaps: PROC [device: Device, list: LIST OF ImagerSample.RawDescriptor] ~ {
--I believe this is a very frequent case worth optimizing
iData: InterceptData ~ NARROW[device.data];
iData.device.class.MaskRawBitmaps[iData.device, list];
IF ~iData.buffered AND list#NIL THEN {
bounds: SF.Box ¬ list.first.box; list ¬ list.rest;
WHILE list#NIL DO
bounds.min ¬ SFInline.Min[bounds.min, list.first.box.min];
bounds.max ¬ SFInline.Max[bounds.max, list.first.box.max];
list ¬ list.rest;
ENDLOOP;
PostIntercept[iData.b, bounds];
};
};
ModifyDrawBitmap: PROC [device: Device, bitmap: SampleMap, delta: SF.Vec, bounds: SF.Box, boxes: SF.BoxGenerator] ~ {
iData: InterceptData ~ NARROW[device.data];
iData.device.class.DrawBitmap[iData.device, bitmap, delta, bounds, boxes];
IPostIntercept[iData, bounds];
};
ModifyMaskChar: PROC [device: Device, delta: SF.Vec, mask: CharMask] ~ {
iData: InterceptData ~ NARROW[device.data];
iData.device.class.MaskChar[iData.device, delta, mask];
IPostIntercept[iData, SFInline.Displace[mask.box, delta]];
};
ModifyMaskThinVector: PROC [device: Device, p0, p1: SF.Vec] ~ {
iData: InterceptData ~ NARROW[device.data];
sMin: INTEGER ~ MIN[p0.s, p1.s];
sMax: INTEGER ~ p0.s+p1.s-sMin;
fMin: INTEGER ~ MIN[p0.f, p1.f];
fMax: INTEGER ~ p0.f+p1.f-fMin;
iData.device.class.MaskThinVector[iData.device, p0, p1];
IPostIntercept[iData, [min: [sMin, fMin], max: [sMax, fMax]]];
};
ModifyMoveBox: PROC [device: Device, dstMin, srcMin, size: SF.Vec] ~ {
iData: InterceptData ~ NARROW[device.data];
iData.device.class.MoveBox[iData.device, dstMin, srcMin, size];
IPostIntercept[iData, [min: dstMin, max: SFInline.Add[dstMin, size]]];
};
ModifySwitchBuffer1: PROC [device: Device, bounds: SF.Box, copy: BOOL, alt: BOOL] ~ {
iData: InterceptData ~ NARROW[device.data];
iData.device.class.SwitchBuffer[iData.device, bounds, copy, alt];
iData.buffered ¬ alt;
IF ~alt AND copy THEN IPostIntercept[iData, bounds];
};
ModifySwitchBuffer2: PROC [device: Device, bounds: SF.Box, copy: BOOL, alt: BOOL] ~ {
iData: InterceptData ~ NARROW[device.data];
<<don't; its faster not to iData.device.class.SwitchBuffer[iData.device, bounds, copy, alt];>>
iData.buffered ¬ alt;
IF ~alt AND copy THEN IPostIntercept[iData, bounds];
};
ModifyGetBufferColorOperator: PROC [device: Device] RETURNS [ImagerColor.ColorOperator] ~ {
iData: InterceptData ~ NARROW[device.data];
IF iData.device.class.GetBufferColorOperator = NIL THEN RETURN [NIL];
RETURN [iData.device.class.GetBufferColorOperator[device]]
};
ModifyAccessBuffer: PROC [device: Device, box: SF.Box, action: PROC [pixelMap: PixelMap]] ~ {
iData: InterceptData ~ NARROW[device.data];
IPreIntercept[iData, box];
iData.device.class.AccessBuffer[iData.device, box, action];
IPostIntercept[iData, box];
};
modifiedDeviceClass1: DeviceClass ~ NEW [ImagerDevice.DeviceClassRep ¬ [
SetColor: ModifySetColor,
SetPriority: ModifySetPriority,
SetHalftoneProperties: ModifySetHalftoneProperties,
MaskBoxes: ModifyMaskBoxes,
MaskRegion: ModifyMaskRegion,
MaskBitmap: ModifyMaskBitmap,
MaskRawBitmaps: ModifyMaskRawBitmaps,
DrawBitmap: ModifyDrawBitmap,
MaskChar: ModifyMaskChar,
MaskThinVector: ModifyMaskThinVector,
MoveBox: ModifyMoveBox,
SwitchBuffer: ModifySwitchBuffer1,
GetBufferColorOperator: ModifyGetBufferColorOperator,
AccessBuffer: ModifyAccessBuffer
]];
modifiedDeviceClass2: DeviceClass ~ NEW [ImagerDevice.DeviceClassRep ¬ [
SetColor: ModifySetColor,
SetPriority: ModifySetPriority,
SetHalftoneProperties: ModifySetHalftoneProperties,
MaskBoxes: ModifyMaskBoxes,
MaskRegion: ModifyMaskRegion,
MaskBitmap: ModifyMaskBitmap,
MaskRawBitmaps: ModifyMaskRawBitmaps,
DrawBitmap: ModifyDrawBitmap,
MaskChar: ModifyMaskChar,
MaskThinVector: ModifyMaskThinVector,
MoveBox: ModifyMoveBox,
SwitchBuffer: ModifySwitchBuffer2,
GetBufferColorOperator: ModifyGetBufferColorOperator,
AccessBuffer: ModifyAccessBuffer
]];
DitherContextCreator: ContextCreator = {
context ¬ ImagerDitherContext.Create[deviceSpaceSize: ImagerSample.GetSize[sm], scanMode: [slow: down, fast: right], surfaceUnitsPerInch: [72, 72], pixelUnits: TRUE, fontCacheName: $Bitmap];
WITH extras SELECT FROM
entries: ImagerDither.MapEntries =>
ImagerDitherContext.SetDitherMap[context, entries];
ENDCASE => {};
ImagerDitherContext.SetSampleMap[context: context, sampleMap: sm];
};
RegisterContextCreator[8, DitherContextCreator];
RegisterContextCreator[4, DitherContextCreator];
RegisterContextCreator[2, DitherContextCreator];
END.