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], 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; 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 ]; 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]}; 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]}; 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, oddWrap: BOOL] ~ { ctxData: CtxData ~ NARROW[context.data]; class: Class ~ ctxData.rasterContext.class; class.MaskFill[ctxData.rasterContext, path, oddWrap]; }; 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]) 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]) THEN SIGNAL Cant[$UninitializedState]; class.MaskVector[ctxData.rasterContext, p1, p2]; }; MyMaskDashedStroke: PROC[context: Context, path: PathProc, patternLen: NAT, pattern: PROC [NAT] RETURNS [REAL], offset, length: REAL] ~ { 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]) THEN SIGNAL Cant[$UninitializedState]; class.MaskDashedStroke[ctxData.rasterContext, path, patternLen, pattern, offset, length]; }; 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, oddWrap: BOOL, exclude: BOOL] ~ { ctxData: CtxData ~ NARROW[context.data]; class: Class ~ ctxData.rasterContext.class; class.Clip[ctxData.rasterContext, path, oddWrap, 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, GetInt: MyGetInt, GetReal: MyGetReal, GetT: MyGetT, GetFont: MyGetFont, GetColor: MyGetColor, GetClipper: MyGetClipper, 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, MaskVector: MyMaskVector, MaskDashedStroke: MyMaskDashedStroke, MaskRectangle: MyMaskRectangle, MaskRectangleI: MyMaskRectangleI, MaskPixel: MyMaskPixel, MaskBits: MyMaskBits, Clip: MyClip, ClipRectangle: MyClipRectangle, ClipRectangleI: MyClipRectangleI, GetCP: MyGetCP, GetBoundingRectangle: MyGetBoundingRectangle, propList: NIL ]]; END. vImagerMaskCaptureImpl.mesa Copyright c 1985, 1986 by Xerox Corporation. All rights reserved. Michael Plass, March 6, 1986 1:41:58 pm PST Doug Wyatt, May 7, 1986 5:52:08 pm PDT All bitmaps will be at least this big, in an attempt to improve locality. Bitmaps smaller than this will be allocated from the permanent zone. The surface origin away from the origin of device coords, since DeviceBox uses cardinals. Smaller than 16K to hit integerTrans often. This version includes zero-length runs needed to get the PD run representation to work. Assume the operator is a good guy and will use this to amplify the width vector. Κ‡˜codešœ™Kšœ Οmœ7™BK™+K™&—K˜šΟk ˜ Jšœžœ˜%Jšœžœ„˜Jšœžœ#˜7Jšœ žœs˜…Jšœ žœ,˜Kšœžœ˜(Kšœ+˜+Kšœžœ˜KšœB˜BKšœ˜—Kš‘œžœ)žœ˜Iš‘ œžœ"˜1Kšœžœ˜(Kšœ+˜+Kšœžœ˜Kšœ+˜+Kšœ˜—Kš‘ œžœ$žœ˜LKš‘ œžœ(žœ˜Tš‘œžœ žœžœ˜>Kšœžœ˜(Kšœ+˜+Kšžœžœžœžœ˜AKšžœ,˜2Kšœ˜—š‘ œžœ!žœžœ˜AKšœžœ˜(Kšœ+˜+šžœžœžœžœ˜7šœžœ˜J™P—Jšžœ˜ Jšœ˜—Kšžœžœžœžœ˜BKšžœ-˜3Kšœ˜—š‘œžœžœ˜:Kšœžœ˜(Kšœ+˜+Kšžœ%˜+Kšœ˜—š‘ œžœžœ ˜3Kšœžœ˜(Kšœ+˜+Kšžœžœžœžœ˜=Kšžœ(˜.Kšœ˜—Kš‘ œžœžœ žœ˜LKš‘ œžœžœ žœ˜Rš‘ œžœ)˜8Kšœžœ˜(Kšœ+˜+Kšœ(˜(Kšœ˜—š‘ œžœžœ˜-Kšœžœ˜(Kšœ+˜+Kšœ(˜(Kšœ˜—š‘ œžœžœ˜.Kšœžœ˜(Kšœ+˜+Kšœ(˜(Kšœ˜—š‘ œžœžœ˜0Kšœžœ˜(Kšœ+˜+Kšœ+˜+Kšœ˜—š‘œžœžœ˜1Kšœžœ˜(Kšœ+˜+Kšœ+˜+Kšœ˜—š‘œžœžœ˜+Kšœžœ˜(Kšœ+˜+Kšœ&˜&Kšœ˜—š‘ œžœžœ˜.Kšœžœ˜(Kšœ+˜+Kšœ)˜)Kšœ˜—š‘œžœ9žœ˜NKšœžœ˜(Kšœ+˜+Kšœ0˜0Kšœ˜—š‘ œžœžœžœžœžœžœ˜ZKšœžœ˜(Kšœ+˜+Kšœ>˜>Kšœ˜—š ‘œžœžœžœžœ˜?Kšœžœ˜(Kšœ+˜+Kšžœ/˜5Kšœ˜—Kš‘œžœžœžœ˜iš‘œžœ˜,Kšœžœ˜(Kšœ"žœ˜'Kšœ-˜-Kšœ˜—š‘œžœžœ˜8Kšœžœ˜(Kšœ+˜+Kšžœžœ!žœžœ˜MKšœ3˜3Kšœ˜—š‘ œžœ˜)Kšœžœ˜(Kšžœžœžœ˜:Kšœ˜Kšœ˜—š‘œžœžœ˜2Kšœžœ˜(Kšœ+˜+Kšžœžœžœ˜;Kšœ˜Kšœ-˜-Kšœ˜—š‘œžœžœ˜,Kšœžœ˜(Kšœ+˜+Kšžœžœžœ˜;Kšœ˜Kšœ&˜&Kšœ˜—Kš‘œžœžœ˜9Kš‘œžœžœ˜;Kš ‘ œžœžœžœ+žœ˜kKš ‘ œžœžœ žœžœ4˜Kš‘ œžœžœžœ˜FKš‘œžœXžœ˜‡Kš‘œžœ>žœžœ˜vš‘ œžœ,žœ˜EKšœžœ˜(Kšœ+˜+Kšœ5˜5Kšœ˜—š‘œžœ$˜9Kšœžœ˜(Kšœ+˜+Kšœ.˜.Kšœ˜—š‘œžœžœ˜AKšœžœ˜(Kšœ+˜+Kšœ8˜8Kšœ˜—š‘ œžœ+žœ˜FKšœžœ˜(Kšœ+˜+Kš žœžœžœžœžœžœ˜ŠKšœ6˜6Kšœ˜—š‘ œžœžœ˜5Kšœžœ˜(Kšœ+˜+Kš žœžœžœžœžœ˜jKšœ0˜0Kšœ˜—š‘œžœ0žœ žœžœžœžœžœ˜ŠKšœžœ˜(Kšœ+˜+Kš žœžœžœžœžœžœ˜ŠKšœY˜YKšœ˜—š‘ œžœ&˜7Kšœžœ˜(Kšœ+˜+Kšœ+˜+Kšœ˜—š‘ œžœžœžœžœžœ žœ˜~Kšœžœ˜(Kšœ+˜+Kšœ\˜\Kšœ˜—š‘œžœ,žœ žœ˜PKšœžœ˜(Kšœ+˜+Kšœ:˜:Kšœ˜—š‘œžœ*žœ˜HKšœžœ˜(Kšœ+˜+Kšœ7˜7Kšœ˜—š‘œžœžœ žœ˜PKšœžœ˜(Kšœ+˜+KšœA˜AKšœ˜K˜—šœžœ ˜&Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ ˜ Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ ˜ Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ ˜ Kšœ˜Kšœ˜Kšœ ˜ Kšœ˜Kšœ!˜!Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ'˜'Kšœ+˜+Kšœ˜Kšœ˜Kšœ˜Kšœ#˜#Kšœ#˜#Kšœ˜Kšœ˜Kšœ˜Kšœ%˜%Kšœ˜Kšœ!˜!Kšœ˜Kšœ˜Kšœ ˜ Kšœ˜Kšœ!˜!Kšœ˜Kšœ-˜-Kšœ ž˜ Jšœ˜J˜——Jšžœ˜J˜—…—To