<> <> <> <> 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; <> permanentThreshold: NAT _ 0; <> <<>> 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; <> <> 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] ~ { <> s: INTEGER _ IF 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: BOOL _ TRUE; 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: BOOL _ TRUE; 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 BOOL _ ALL[FALSE], real: PACKED ARRAY RealKey OF BOOL _ ALL[FALSE], font: BOOL _ FALSE, strokeDashes: BOOL _ FALSE ]; CtxData: TYPE ~ REF CtxDataRep; CtxDataRep: TYPE ~ RECORD [ rasterContext: Context, deviceData: DeviceData, ok: OK, amplified: BOOLEAN _ FALSE, 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; <> 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.