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], Scaled USING [FromReal], Vector2 USING [VEC]; ImagerMaskCaptureImpl: CEDAR MONITOR IMPORTS Basics, Imager, ImagerRaster, ImagerMask, ImagerManhattan, ImagerTransformation, ImagerPixelMap, ImagerBackdoor, Scaled EXPORTS ImagerMaskCapture, Imager ~ BEGIN smallestBitmap: NAT _ 10; 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; 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 { escapement: VEC _ ImagerBackdoor.GetCP[ctxData.rasterContext]; p: Manhattan ~ GetRectangles[context]; IF ABS[escapement.x] <= 16383.0 AND ABS[escapement.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.sEscapement _ Scaled.FromReal[escapement.x]; charMask.fEscapement _ Scaled.FromReal[escapement.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, MaskRectangle: MyMaskRectangle, MaskRectangleI: MyMaskRectangleI, MaskStroke: MyMaskStroke, MaskVector: MyMaskVector, MaskDashedStroke: MyMaskDashedStroke, MaskPixel: MyMaskPixel, MaskBits: MyMaskBits, Clip: MyClip, ClipRectangle: MyClipRectangle, ClipRectangleI: MyClipRectangleI, GetCP: MyGetCP, GetBoundingRectangle: MyGetBoundingRectangle, propList: NIL ]]; END. 6ImagerMaskCaptureImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Michael Plass, July 19, 1985 4:41:11 pm PDT Doug Wyatt, November 27, 1985 6:48:04 pm PST All bitmaps will be at least this big, in an attempt to improve locality. 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 escapement vector. ΚI˜codešœ™Kšœ Οmœ1™Kšœ&˜&š žœžœžœžœžœ˜GKšœ5˜5Kšœ žœžœ žœ˜:Kšœžœ˜šœ ˜ Kšžœžœ#˜CKšžœ*˜.—šžœ žœžœ˜Kšœ'˜'Kšœ)˜)Kšœžœ˜Kšœ5˜5Kšœ5˜5Kšœ˜—Kšœ˜—Kšœ˜Kšœ˜—Kšœ˜Kšœ˜K˜—š ‘ œžœžœ žœžœ˜_šœ7˜7šžœž˜Kšœ8žœ˜?Kšžœžœ˜—Kšœ˜—Kšœ4˜4Kšœ˜Kšžœ1˜7Kšœ˜K˜—š ‘œžœžœ žœžœžœ˜kKšœ ˜ Kšœžœ˜(Kšœ žœžœ˜šœžœ˜Kšœ˜Kšœ˜Kšœ˜—Kšœ˜Kšœ˜Kšœ˜Kšœ9˜9Kšœ˜Kšœ˜K˜—š‘ œžœžœ žœ/˜WKšœ-˜-Kšœ ˜ Kšœ˜Kšœ˜K˜—š ‘ œžœžœ žœžœ˜hKšœ-˜-Kšœ3˜3Kšœ˜šžœžœžœž˜-Kšœ˜Kšžœ˜—Kšœ˜Kšœ˜K˜—šžœžœžœ˜Kš œžœžœžœžœžœžœ˜.Kš œžœžœ žœžœžœžœ˜0Kšœžœž˜Kšœ˜K˜—Kšœ žœžœ ˜šœ žœžœ˜K˜K˜Kšœžœ˜Kšœ žœžœ˜Kšœ"˜"Kšœžœ˜Kšœ žœ˜K˜Kšœž˜Kšœ˜K˜—Kš œžœžœžœžœ˜'š‘œžœžœžœ˜=Kšœžœ˜(Kšœ+˜+Kšœžœ˜Kšœ2žœ˜OKšœ˜Kšœ˜—š‘œžœ%žœ˜;Kšœžœ˜(Kšœ+˜+Kšœžœ˜KšœA˜AKšœ˜—š‘ œžœ&žœ˜>Kšœžœ˜(Kšœ+˜+Kšœžœ˜KšœB˜BKšœ˜—Kš‘œžœ)žœ˜Iš‘ œžœ"˜1Kšœžœ˜(Kšœ+˜+Kšœžœ˜Kšœ+˜+Kšœ˜—Kš‘ œžœ$žœ˜LKš‘ œžœ(žœ˜Tš‘œžœ žœžœ˜>Kšœžœ˜(Kšœ+˜+Kšžœžœžœžœ˜AKšžœ,˜2Kšœ˜—š‘ œžœ!žœžœ˜AKšœžœ˜(Kšœ+˜+šžœžœžœžœ˜7šœžœ˜K™U—Kšžœ˜ Kšœ˜—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šœ ž˜ Kšœ˜K˜—Kšžœ˜—…—Sdmγ