ImagerMaskCaptureImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Michael Plass, March 6, 1986 1:41:58 pm PST
Doug Wyatt, May 19, 1985 5:21:35 pm PDT
DIRECTORY
Basics USING [bitsPerWord, LongMult],
Imager USING [ClassRep, Color, ColorOperator, ConcatT, Context, ContextRep, DoSave, MaskUnderline, PathProc, PixelArray, SetXY, StartUnderline],
ImagerBackdoor USING [Clipper, GetCP, IntKey, RealKey],
ImagerDevice USING [BoxProc, CharMask, CharMaskRep, Class, ClassRep, Device, DeviceBox, DeviceRep, HalftoneParameters, Run, RunProc],
ImagerFont USING [CorrectionType, Font, XChar, XStringProc],
ImagerManhattan USING [BoundingBox, CreateFromBox, CreateFromRuns, Destroy, MapRuns, Polygon, Shift, Union],
ImagerMask USING [RunsFromBits],
ImagerMaskCapture USING [],
ImagerPixelMap USING [Clear, Create, CreateFrameBuffer, DeviceRectangle, Fill, PixelMap, ShiftMap],
ImagerPrivate USING [ClassRep, StrokeDashes],
ImagerRaster USING [Create],
ImagerTransformation USING [Rectangle, Transformation, Translate],
Real USING [LargestNumber],
SafeStorage USING [GetPermanentZone, GetSystemZone],
Scaled USING [FromReal],
Vector2 USING [VEC];
ImagerMaskCaptureImpl: CEDAR MONITOR
IMPORTS Basics, Imager, ImagerRaster, ImagerMask, ImagerManhattan, ImagerTransformation, ImagerPixelMap, ImagerBackdoor, SafeStorage, Scaled
EXPORTS ImagerMaskCapture, Imager
~ BEGIN
smallestBitmap: NAT ← 10;
All bitmaps will be at least this big, in an attempt to improve locality.
permanentThreshold: NAT ← 0;
Bitmaps smaller than this will be allocated from the permanent zone.
PixelMap: TYPE ~ ImagerPixelMap.PixelMap;
Manhattan: TYPE ~ ImagerManhattan.Polygon;
DeviceBox: TYPE ~ ImagerDevice.DeviceBox;
DeviceRectangle: TYPE ~ ImagerPixelMap.DeviceRectangle;
Class: TYPE ~ REF ClassRep;
ClassRep: PUBLIC TYPE ~ ImagerPrivate.ClassRep; -- export to Imager.ClassRep
Context: TYPE ~ Imager.Context;
Color: TYPE ~ Imager.Color;
ColorOperator: TYPE ~ Imager.ColorOperator;
Device: TYPE ~ ImagerDevice.Device;
Font: TYPE ~ ImagerFont.Font;
PathProc: TYPE ~ Imager.PathProc;
PixelArray: TYPE ~ Imager.PixelArray;
Rectangle: TYPE ~ ImagerTransformation.Rectangle;
Transformation: TYPE ~ ImagerTransformation.Transformation;
VEC: TYPE ~ Vector2.VEC;
StrokeDashes: TYPE ~ ImagerPrivate.StrokeDashes;
Clipper: TYPE ~ ImagerBackdoor.Clipper;
IntKey: TYPE ~ ImagerBackdoor.IntKey;
RealKey: TYPE ~ ImagerBackdoor.RealKey;
XChar: TYPE ~ ImagerFont.XChar;
CorrectionType: TYPE ~ ImagerFont.CorrectionType;
CharMask: TYPE ~ ImagerDevice.CharMask;
RunProc: TYPE ~ ImagerDevice.RunProc;
BoxProc: TYPE ~ ImagerDevice.BoxProc;
surfaceOrigin: NAT ~ 10000;
The surface origin away from the origin of device coords, since DeviceBox uses cardinals.
Smaller than 16K to hit integerTrans often.
DeviceData: TYPE ~ REF DeviceDataRep;
DeviceDataRep: TYPE ~ RECORD [
rectangles: Manhattan
];
CreateDevice: PROC RETURNS [Device] ~ {
deviceData: DeviceData ~ NEW[DeviceDataRep ← [
rectangles: NIL
]];
device: Device ~ NEW[ImagerDevice.DeviceRep ← [
class: deviceClass,
data: deviceData,
box: [smin: 0, fmin: 0, smax: 2*surfaceOrigin-1, fmax: 2*surfaceOrigin-1],
surfaceToDevice: ImagerTransformation.Translate[[surfaceOrigin, surfaceOrigin]],
surfaceUnitsPerInch: [1,1], -- doesn't really matter
surfaceUnitsPerPixel: 1
]];
RETURN [device];
};
deviceClass: ImagerDevice.Class ~ NEW[ImagerDevice.ClassRep ← [
type: $RasterCapture,
SetColor: NullSetColor,
SetPriority: NullSetPriority,
SetHalftone: NullSetHalftone,
MaskRuns: MaskRuns,
MaskBoxes: MaskBoxes,
MaskBits: MaskBits
]];
NullSetColor: PROC[device: Device, color: Color, viewToDevice: Transformation] ~ {};
NullSetPriority: PROC[device: Device, priorityImportant: BOOL] ~ {};
NullSetHalftone: PROC[device: Device, halftone: ImagerDevice.HalftoneParameters] ~ {};
MaskManhattan: PROC[device: Device, addition: Manhattan] ~ {
deviceData: DeviceData ~ NARROW[device.data];
new: Manhattan ~ ImagerManhattan.Union[addition, deviceData.rectangles];
ImagerManhattan.Destroy[addition];
ImagerManhattan.Destroy[deviceData.rectangles];
deviceData.rectangles ← new;
};
MaskRuns: PROC[device: Device, bounds: DeviceBox, runs: PROC[RunProc]] ~ {
Runs: PROC[run: RunProc, repeat: PROC[NAT]] ~ {runs[run]};
MaskManhattan[device, ImagerManhattan.CreateFromRuns[Runs]];
};
MaskBoxes: PROC[device: Device, bounds: DeviceBox, boxes: PROC[BoxProc]] ~ {
Box: PROC[b: DeviceBox] ~ {
MaskManhattan[device, ImagerManhattan.CreateFromBox[[b.smin, b.fmin, b.smax-b.smin, b.fmax-b.fmin]]];
};
boxes[Box];
};
MaskBits: PROC[device: Device, srcBase: LONG POINTER, srcWordsPerLine: NAT,
ts, tf: INTEGER, boxes: PROC[BoxProc]] ~ {
Box: PROC[b: DeviceBox] ~ {
ManhattanRuns: PROC[run: RunProc, repeat: PROC[NAT]] ~ {
ImagerMask.RunsFromBits[
base: srcBase,
wordsPerLine: srcWordsPerLine,
sBits: b.smin-ts,
fBits: b.fmin-tf,
sSize: b.smax-b.smin,
fSize: b.fmax-b.fmin,
sRuns: b.smin,
fRuns: b.fmin,
run: run
];
};
MaskManhattan[device, ImagerManhattan.CreateFromRuns[ManhattanRuns]];
};
boxes[Box];
};
CreateContext: PROC RETURNS [Context] ~ {
ctxData: CtxData ~ NEW[CtxDataRep];
device: Device ~ CreateDevice[];
ctxData.rasterContext ← ImagerRaster.Create[device: device, pixelUnits: TRUE, fontCache: NIL];
ctxData.deviceData ← NARROW[device.data];
ctxData.smin ← ctxData.fmin ← Real.LargestNumber;
ctxData.smax ← ctxData.smax ← -Real.LargestNumber;
RETURN [NEW[Imager.ContextRep ← [class: captureClass, state: NIL, data: ctxData]]];
};
c1: Context ← NIL;
c2: Context ← NIL;
GetContext: ENTRY PROC RETURNS [context: Context] ~ {
IF c1#NIL THEN {context ← c1; c1 ← NIL}
ELSE IF c2#NIL THEN {context ← c2; c2 ← NIL}
ELSE context ← CreateContext[];
};
FreeContext: ENTRY PROC [context: Context] ~ {
ctxData: CtxData ~ NARROW[context.data];
rasterContext: Context ~ ctxData.rasterContext;
deviceData: DeviceData ~ ctxData.deviceData;
ctxData^ ← [rasterContext: rasterContext, deviceData: deviceData, firstFont: NIL, firstChar: [0,0], smin: Real.LargestNumber, fmin: Real.LargestNumber, smax: Real.LargestNumber, fmax: -Real.LargestNumber];
deviceData.rectangles ← NIL;
IF c1=NIL THEN {c1 ← context} ELSE c2 ← context;
};
GetRectangles: PROC [context: Context] RETURNS [p: Manhattan] ~ {
ctxData: CtxData ~ NARROW[context.data];
p ← ctxData.deviceData.rectangles;
ctxData.deviceData.rectangles ← NIL;
};
RasterCharMaskFromManhattan: PROC [p: Manhattan, bb: DeviceRectangle] RETURNS [mask: REF ImagerDevice.CharMaskRep.raster] ~ TRUSTED {
rast: NAT ~ (bb.fSize+(Basics.bitsPerWord-1))/Basics.bitsPerWord;
bitmapWords: LONG CARDINAL ~ Basics.LongMult[bb.sSize, rast];
pixelMap: PixelMap;
zone: ZONE ~ IF bitmapWords < permanentThreshold THEN SafeStorage.GetPermanentZone[] ELSE SafeStorage.GetSystemZone[];
IF bitmapWords > NAT.LAST THEN RETURN [NIL];
mask ← NEW[ImagerDevice.CharMaskRep.raster[MAX[NAT[bitmapWords], smallestBitmap]]];
mask.flag ← ALL[0];
IF bb.sSize = 0 OR bb.fSize = 0 THEN {
mask.sMinBB ← mask.fMinBB ← mask.sSizeBB ← mask.fSizeBB ← 0;
}
ELSE {
mask.sMinBB ← INTEGER[bb.sMin]-surfaceOrigin;
mask.fMinBB ← INTEGER[bb.fMin]-surfaceOrigin;
mask.sSizeBB ← bb.sSize;
mask.fSizeBB ← bb.fSize;
};
pixelMap ← ImagerPixelMap.CreateFrameBuffer[pointer: @mask[0], words: bitmapWords, lgBitsPerPixel: 0, rast: rast, lines: bb.sSize, ref: mask];
pixelMap ← pixelMap.ShiftMap[bb.sMin, bb.fMin];
pixelMap.Clear[];
WHILE p # NIL DO
pixelMap.Fill[p.first, 1];
p ← p.rest;
ENDLOOP;
};
RunsCharMaskFromManhattan: PROC [p: Manhattan, bb: DeviceRectangle, nRuns: INT] RETURNS [mask: REF ImagerDevice.CharMaskRep.runs] ~ {
i: NAT ← 0;
s: NAT ← 0;
sMinBB: INTEGER ~ INTEGER[bb.sMin]-surfaceOrigin;
fMinBB: INTEGER ~ INTEGER[bb.fMin]-surfaceOrigin;
Run: PROC [sMin, fMin: INTEGER, fSize: NAT] ~ {
smin: NAT ~ sMin-sMinBB-surfaceOrigin;
fmin: NAT ~ fMin-fMinBB-surfaceOrigin;
IF smin # s THEN {
mask[i-1].lastRun ← TRUE;
s ← s + 1;
WHILE smin > s DO
mask[i] ← [fMin: 0, lastRun: TRUE, fSize: 0];
i ← i + 1;
s ← s + 1;
ENDLOOP;
};
mask[i] ← [fMin: fmin, lastRun: FALSE, fSize: fSize];
i ← i + 1;
};
IF nRuns = 0 OR nRuns > NAT.LAST/2 THEN RETURN [NIL];
mask ← NEW[ImagerDevice.CharMaskRep.runs[nRuns]];
mask.flag ← ALL[0];
mask.sMinBB ← sMinBB;
mask.fMinBB ← fMinBB;
mask.sSizeBB ← bb.sSize;
mask.fSizeBB ← bb.fSize;
ImagerManhattan.MapRuns[p, Run];
IF i#nRuns THEN ERROR;
IF s+1 # bb.sSize THEN ERROR;
mask[i-1].lastRun ← TRUE;
};
CountRuns: PROC [p: Manhattan] RETURNS [runs: INT ← 0] ~ {
This version includes zero-length runs needed to get the PD run representation to work.
s: INTEGERIF p # NIL THEN p.first.sMin ELSE 0;
WHILE p # NIL DO
sMin: INTEGER ~ p.first.sMin;
sSize: INTEGER ~ p.first.sSize;
IF sMin > s THEN {runs ← runs + (sMin - s)};
s ← sMin+sSize;
runs ← runs + sSize;
p ← p.rest;
ENDLOOP;
};
Capture: PUBLIC PROC [operator: PROC[Context], m: Transformation, r: REAL] RETURNS [charMask: CharMask ← NIL] ~ {
context: Context ~ GetContext[];
ctxData: CtxData ~ NARROW[context.data];
complete: BOOLTRUE;
proc: PROC ~ {
Imager.ConcatT[context, m];
operator[context ! Cant => {complete ← FALSE; CONTINUE}];
};
Imager.SetXY[context, [0,0]];
Imager.DoSave[context, proc];
IF NOT complete THEN {
ImagerManhattan.Destroy[GetRectangles[context]];
}
ELSE {
width: VEC ← ImagerBackdoor.GetCP[ctxData.rasterContext];
p: Manhattan ~ GetRectangles[context];
IF ABS[width.x] <= 16383.0 AND ABS[width.y] <= 16383.0 THEN {
bb: DeviceRectangle ~ ImagerManhattan.BoundingBox[p];
bitmapWords: REAL ~ REAL[bb.sSize]*REAL[(bb.fSize+15)/16];
nRuns: INT ~ CountRuns[p];
charMask ← (
IF nRuns*2*r >= bitmapWords THEN RasterCharMaskFromManhattan[p, bb]
ELSE RunsCharMaskFromManhattan[p, bb, nRuns]);
IF charMask#NIL THEN {
charMask.amplified ← ctxData.amplified;
charMask.correction ← ctxData.correction;
charMask.metricsValid ← TRUE;
charMask.sWidth ← Scaled.FromReal[width.x];
charMask.fWidth ← Scaled.FromReal[width.y];
};
};
ImagerManhattan.Destroy[p];
};
FreeContext[context];
};
CaptureBounds: PUBLIC PROC [operator: PROC[Context], m: Transformation] RETURNS [Rectangle] ~ {
p: Manhattan ← CaptureManhattan[operator, m ! Cant => {
SELECT why FROM
$GetT, $GetColor, $GetClipper, $GetBoundingRectangle => REJECT;
ENDCASE => RESUME;
}];
d: DeviceRectangle ~ ImagerManhattan.BoundingBox[p];
ImagerManhattan.Destroy[p];
RETURN [[x: d.sMin, y: d.fMin, w: d.sSize, h: d.fSize]]
};
CaptureManhattan: PUBLIC PROC [operator: PROC[Context], m: Transformation] RETURNS [p: Manhattan ← NIL] ~ {
context: Context ~ GetContext[];
ctxData: CtxData ~ NARROW[context.data];
complete: BOOLTRUE;
proc: PROC ~ {
Imager.ConcatT[context, m];
operator[context];
};
Imager.SetXY[context, [0,0]];
Imager.DoSave[context, proc];
p ← GetRectangles[context];
ImagerManhattan.Shift[p, -surfaceOrigin, -surfaceOrigin];
FreeContext[context];
};
CaptureRuns: PUBLIC PROC [operator: PROC[Context], m: Transformation, run: RunProc] ~ {
p: Manhattan ← CaptureManhattan[operator, m];
ImagerManhattan.MapRuns[p, run];
ImagerManhattan.Destroy[p];
};
CaptureBitmap: PUBLIC PROC [operator: PROC[Context], m: Transformation] RETURNS [pixelMap: PixelMap] ~ {
p: Manhattan ← CaptureManhattan[operator, m];
pixelMap ← ImagerPixelMap.Create[0, p.BoundingBox];
pixelMap.Clear;
FOR t: Manhattan ← p, t.rest UNTIL t = NIL DO
pixelMap.Fill[t.first, 1];
ENDLOOP;
ImagerManhattan.Destroy[p];
};
OK: TYPE ~ RECORD [
int: PACKED ARRAY IntKey OF BOOLALL[FALSE],
real: PACKED ARRAY RealKey OF BOOLALL[FALSE],
font: BOOLFALSE,
strokeDashes: BOOLFALSE
];
CtxData: TYPE ~ REF CtxDataRep;
CtxDataRep: TYPE ~ RECORD [
rasterContext: Context,
deviceData: DeviceData,
ok: OK,
amplified: BOOLEANFALSE,
correction: CorrectionType ← none,
nChars: INT ← 0,
firstFont: REF,
firstChar: XChar,
smin, fmin, smax, fmax: REAL
];
Cant: PUBLIC SIGNAL [why: ATOM] ~ CODE;
MyDoSave: PROC[context: Context, action: PROC, all: BOOL] ~ {
ctxData: CtxData ~ NARROW[context.data];
class: Class ~ ctxData.rasterContext.class;
ok: OK ~ ctxData.ok;
class.DoSave[ctxData.rasterContext, action, all ! UNWIND => {ctxData.ok ← ok}];
ctxData.ok ← ok;
};
MySetInt: PROC[context: Context, key: IntKey, val: INT] ~ {
ctxData: CtxData ~ NARROW[context.data];
class: Class ~ ctxData.rasterContext.class;
ctxData.ok.int[key] ← TRUE;
class.SetInt[context: ctxData.rasterContext, key: key, val: val];
};
MySetReal: PROC[context: Context, key: RealKey, val: REAL] ~ {
ctxData: CtxData ~ NARROW[context.data];
class: Class ~ ctxData.rasterContext.class;
ctxData.ok.real[key] ← TRUE;
class.SetReal[context: ctxData.rasterContext, key: key, val: val];
};
MySetT: PROC[context: Context, m: Transformation] ~ {SIGNAL Cant[$SetT]};
MySetFont: PROC[context: Context, font: Font] ~ {
ctxData: CtxData ~ NARROW[context.data];
class: Class ~ ctxData.rasterContext.class;
ctxData.ok.font ← TRUE;
class.SetFont[ctxData.rasterContext, font];
};
MySetColor: PROC[context: Context, color: Color] ~ {SIGNAL Cant[$SetColor]};
MySetClipper: PROC[context: Context, clipper: Clipper] ~ {SIGNAL Cant[$SetClipper]};
MySetStrokeDashes: PROC[context: Context, strokeDashes: StrokeDashes] ~ {
ctxData: CtxData ~ NARROW[context.data];
class: Class ~ ctxData.rasterContext.class;
ctxData.ok.strokeDashes ← TRUE;
class.SetStrokeDashes[ctxData.rasterContext, strokeDashes];
};
MyGetInt: PROC[context: Context, key: IntKey] RETURNS[INT] ~ {
ctxData: CtxData ~ NARROW[context.data];
class: Class ~ ctxData.rasterContext.class;
IF NOT ctxData.ok.int[key] THEN SIGNAL Cant[$UninitializedState];
RETURN [class.GetInt[ctxData.rasterContext, key]];
};
MyGetReal: PROC[context: Context, key: RealKey] RETURNS[REAL] ~ {
ctxData: CtxData ~ NARROW[context.data];
class: Class ~ ctxData.rasterContext.class;
IF key=amplifySpace AND NOT ctxData.ok.real[key] THEN {
ctxData.amplified ← TRUE;
Assume the operator is a good guy and will use this to amplify the width vector.
RETURN [1.0];
};
IF NOT ctxData.ok.real[key] THEN SIGNAL Cant[$UninitializedState];
RETURN [class.GetReal[ctxData.rasterContext, key]];
};
MyGetT: PROC[context: Context] RETURNS[Transformation] ~ {
ctxData: CtxData ~ NARROW[context.data];
class: Class ~ ctxData.rasterContext.class;
RETURN [class.GetT[ctxData.rasterContext]];
};
MyGetFont: PROC[context: Context] RETURNS[Font] ~ {
ctxData: CtxData ~ NARROW[context.data];
class: Class ~ ctxData.rasterContext.class;
IF NOT ctxData.ok.font THEN SIGNAL Cant[$UninitializedState];
RETURN [class.GetFont[ctxData.rasterContext]];
};
MyGetColor: PROC[context: Context] RETURNS[Color] ~ {ERROR Cant[$GetColor]};
MyGetClipper: PROC[context: Context] RETURNS[Clipper] ~ {ERROR Cant[$GetClipper]};
MyGetStrokeDashes: PROC[context: Context] RETURNS[StrokeDashes] ~ {
ctxData: CtxData ~ NARROW[context.data];
class: Class ~ ctxData.rasterContext.class;
IF NOT ctxData.ok.strokeDashes THEN SIGNAL Cant[$GetStrokeDashes];
RETURN [class.GetStrokeDashes[ctxData.rasterContext]];
};
MyConcatT: PROC[context: Context, m: Transformation] ~ {
ctxData: CtxData ~ NARROW[context.data];
class: Class ~ ctxData.rasterContext.class;
class.ConcatT[ctxData.rasterContext, m];
};
MyScale2T: PROC[context: Context, s: VEC] ~ {
ctxData: CtxData ~ NARROW[context.data];
class: Class ~ ctxData.rasterContext.class;
class.Scale2T[ctxData.rasterContext, s];
};
MyRotateT: PROC[context: Context, a: REAL] ~ {
ctxData: CtxData ~ NARROW[context.data];
class: Class ~ ctxData.rasterContext.class;
class.RotateT[ctxData.rasterContext, a];
};
MyTranslateT: PROC[context: Context, t: VEC] ~ {
ctxData: CtxData ~ NARROW[context.data];
class: Class ~ ctxData.rasterContext.class;
class.TranslateT[ctxData.rasterContext, t];
};
MyMove: PROC[context: Context, rounded: BOOL] ~ {
ctxData: CtxData ~ NARROW[context.data];
class: Class ~ ctxData.rasterContext.class;
class.Move[ctxData.rasterContext, rounded];
};
MySetXY: PROC[context: Context, p: VEC] ~ {
ctxData: CtxData ~ NARROW[context.data];
class: Class ~ ctxData.rasterContext.class;
class.SetXY[ctxData.rasterContext, p];
};
MySetXYRel: PROC[context: Context, v: VEC] ~ {
ctxData: CtxData ~ NARROW[context.data];
class: Class ~ ctxData.rasterContext.class;
class.SetXYRel[ctxData.rasterContext, v];
};
MyShow: PROC[context: Context, string: ImagerFont.XStringProc, xrel: BOOL] ~ {
ctxData: CtxData ~ NARROW[context.data];
class: Class ~ ctxData.rasterContext.class;
class.Show[ctxData.rasterContext, string, xrel];
};
MyShowText: PROC[context: Context, text: REF READONLY TEXT, start, len: NAT, xrel: BOOL]~{
ctxData: CtxData ~ NARROW[context.data];
class: Class ~ ctxData.rasterContext.class;
class.ShowText[ctxData.rasterContext, text, start, len, xrel];
};
MyGetCP: PROC[context: Context, rounded: BOOL] RETURNS[VEC] ~ {
ctxData: CtxData ~ NARROW[context.data];
class: Class ~ ctxData.rasterContext.class;
RETURN [class.GetCP[ctxData.rasterContext, rounded]];
};
MyGetBoundingRectangle: PROC[context: Context] RETURNS [Rectangle] ~ {ERROR Cant[$GetBoundingRectangle]};
MyStartUnderline: PROC[context: Context] ~ {
ctxData: CtxData ~ NARROW[context.data];
ctxData.ok.real[underlineStart] ← TRUE;
Imager.StartUnderline[ctxData.rasterContext];
};
MyMaskUnderline: PROC[context: Context, dy, h: REAL] ~ {
ctxData: CtxData ~ NARROW[context.data];
class: Class ~ ctxData.rasterContext.class;
IF NOT ctxData.ok.real[underlineStart] THEN SIGNAL Cant[$UninitializedState];
Imager.MaskUnderline[ctxData.rasterContext, dy, h];
};
MyCorrectMask: PROC[context: Context] ~ {
ctxData: CtxData ~ NARROW[context.data];
IF ctxData.correction#none THEN SIGNAL Cant[$CorrectMask];
ctxData.correction ← mask;
};
MyCorrectSpace: PROC[context: Context, v: VEC] ~ {
ctxData: CtxData ~ NARROW[context.data];
class: Class ~ ctxData.rasterContext.class;
IF ctxData.correction#none THEN SIGNAL Cant[$CorrectSpace];
ctxData.correction ← space;
class.CorrectSpace[ctxData.rasterContext, v];
};
MySpace: PROC[context: Context, x: REAL] ~ {
ctxData: CtxData ~ NARROW[context.data];
class: Class ~ ctxData.rasterContext.class;
IF ctxData.correction#none THEN SIGNAL Cant[$CorrectSpace];
ctxData.correction ← space;
class.Space[ctxData.rasterContext, x];
};
MySetCorrectMeasure: PROC[context: Context, v: VEC] ~ {};
MySetCorrectTolerance: PROC[context: Context, v: VEC] ~ {};
MyCorrect: PROC[context: Context, action: PROC] ~ {SIGNAL Cant[$Correct]; MyDoSave[context, action, TRUE]};
MyDontCorrect: PROC[context: Context, action: PROC, saveCP: BOOL] ~ {SIGNAL Cant[$Correct]; MyDoSave[context, action, saveCP]};
MySetGray: PROC[context: Context, f: REAL] ~ {SIGNAL Cant[$SetColor]};
MySetSampledColor: PROC[context: Context, pa: PixelArray,
m: Transformation, colorOperator: ColorOperator] ~ {SIGNAL Cant[$SetColor]};
MySetSampledBlack: PROC[context: Context, pa: PixelArray,
m: Transformation, clear: BOOL] ~ {SIGNAL Cant[$SetColor]};
MyMaskFill: PROC[context: Context, path: PathProc, parity: BOOL] ~ {
ctxData: CtxData ~ NARROW[context.data];
class: Class ~ ctxData.rasterContext.class;
class.MaskFill[ctxData.rasterContext, path, parity];
};
MyMaskRectangle: PROC[context: Context, r: Rectangle] ~ {
ctxData: CtxData ~ NARROW[context.data];
class: Class ~ ctxData.rasterContext.class;
class.MaskRectangle[ctxData.rasterContext, r];
};
MyMaskRectangleI: PROC[context: Context, x, y, w, h: INTEGER] ~ {
ctxData: CtxData ~ NARROW[context.data];
class: Class ~ ctxData.rasterContext.class;
class.MaskRectangleI[ctxData.rasterContext, x, y, w, h];
};
MyMaskStroke: PROC[context: Context, path: PathProc, closed: BOOL] ~ {
ctxData: CtxData ~ NARROW[context.data];
class: Class ~ ctxData.rasterContext.class;
IF NOT (ctxData.ok.real[strokeWidth] AND ctxData.ok.int[strokeEnd] AND ctxData.ok.int[strokeJoint] AND ctxData.ok.strokeDashes) THEN SIGNAL Cant[$UninitializedState];
class.MaskStroke[ctxData.rasterContext, path, closed];
};
MyMaskVector: PROC[context: Context, p1, p2: VEC] ~ {
ctxData: CtxData ~ NARROW[context.data];
class: Class ~ ctxData.rasterContext.class;
IF NOT (ctxData.ok.real[strokeWidth] AND ctxData.ok.int[strokeEnd] AND ctxData.ok.strokeDashes) THEN SIGNAL Cant[$UninitializedState];
class.MaskVector[ctxData.rasterContext, p1, p2];
};
MyMaskPixel: PROC[context: Context, pa: PixelArray] ~ {
ctxData: CtxData ~ NARROW[context.data];
class: Class ~ ctxData.rasterContext.class;
class.MaskPixel[ctxData.rasterContext, pa];
};
MyMaskBits: PROC[context: Context, base: LONG POINTER, wordsPerLine: NAT,
sMin, fMin, sSize, fSize: NAT, tx, ty: INTEGER] ~ {
ctxData: CtxData ~ NARROW[context.data];
class: Class ~ ctxData.rasterContext.class;
class.MaskBits[ctxData.rasterContext, base, wordsPerLine, sMin, fMin, sSize, fSize, tx, ty];
};
MyClip: PROC[context: Context, path: PathProc, parity: BOOL, exclude: BOOL] ~ {
ctxData: CtxData ~ NARROW[context.data];
class: Class ~ ctxData.rasterContext.class;
class.Clip[ctxData.rasterContext, path, parity, exclude];
};
MyClipRectangle: PROC[context: Context, r: Rectangle, exclude: BOOL] ~ {
ctxData: CtxData ~ NARROW[context.data];
class: Class ~ ctxData.rasterContext.class;
class.ClipRectangle[ctxData.rasterContext, r, exclude];
};
MyClipRectangleI: PROC[context: Context, x, y, w, h: INTEGER, exclude: BOOL] ~ {
ctxData: CtxData ~ NARROW[context.data];
class: Class ~ ctxData.rasterContext.class;
class.ClipRectangleI[ctxData.rasterContext, x, y, w, h, exclude];
};
captureClass: Class ~ NEW[ClassRep ← [
type: $Capture,
DoSave: MyDoSave,
SetInt: MySetInt,
SetReal: MySetReal,
SetT: MySetT,
SetFont: MySetFont,
SetColor: MySetColor,
SetClipper: MySetClipper,
SetStrokeDashes: MySetStrokeDashes,
GetInt: MyGetInt,
GetReal: MyGetReal,
GetT: MyGetT,
GetFont: MyGetFont,
GetColor: MyGetColor,
GetClipper: MyGetClipper,
GetStrokeDashes: MyGetStrokeDashes,
ConcatT: MyConcatT,
Scale2T: MyScale2T,
RotateT: MyRotateT,
TranslateT: MyTranslateT,
Move: MyMove,
SetXY: MySetXY,
SetXYRel: MySetXYRel,
Show: MyShow,
ShowText: MyShowText,
StartUnderline: MyStartUnderline,
MaskUnderline: MyMaskUnderline,
CorrectMask: MyCorrectMask,
CorrectSpace: MyCorrectSpace,
Space: MySpace,
SetCorrectMeasure: MySetCorrectMeasure,
SetCorrectTolerance: MySetCorrectTolerance,
Correct: MyCorrect,
DontCorrect: MyDontCorrect,
SetGray: MySetGray,
SetSampledColor: MySetSampledColor,
SetSampledBlack: MySetSampledBlack,
MaskFill: MyMaskFill,
MaskStroke: MyMaskStroke,
MaskRectangle: MyMaskRectangle,
MaskRectangleI: MyMaskRectangleI,
MaskVector: MyMaskVector,
MaskPixel: MyMaskPixel,
MaskBits: MyMaskBits,
Clip: MyClip,
ClipRectangle: MyClipRectangle,
ClipRectangleI: MyClipRectangleI,
GetCP: MyGetCP,
GetBoundingRectangle: MyGetBoundingRectangle,
propList: NIL
]];
END.