<> <> <> <> <> <<>> DIRECTORY FS, Imager, ImagerBackdoor, ImagerColor, ImagerColorDefs, ImagerColorPrivate, ImagerFont, ImagerFontPrivate, ImagerPath, ImagerPixelArray, ImagerPress, ImagerPressFontSubst, ImagerPrivate, ImagerState, ImagerTransformation, IO, Real, RealFns, RefTab, Rope, SirPress, Vector2; ImagerPressImpl: CEDAR PROGRAM IMPORTS FS, Imager, ImagerBackdoor, ImagerColor, ImagerFont, ImagerFontPrivate, ImagerPath, ImagerPressFontSubst, ImagerState, ImagerTransformation, Real, RealFns, RefTab, SirPress, Vector2 EXPORTS Imager, ImagerColorDefs, ImagerFont, ImagerPress ~ BEGIN ROPE: TYPE ~ Rope.ROPE; Rectangle: TYPE ~ ImagerTransformation.Rectangle; PixelArray: TYPE ~ ImagerPixelArray.PixelArray; RealKey: TYPE ~ ImagerBackdoor.RealKey; IntKey: TYPE ~ ImagerBackdoor.IntKey; Transformation: TYPE ~ ImagerTransformation.Transformation; Font: TYPE ~ ImagerFont.Font; Color: TYPE ~ ImagerColorDefs.Color; VEC: TYPE ~ Vector2.VEC; PathProc: TYPE ~ ImagerPath.PathProc; ColorOperator: TYPE ~ ImagerColorDefs.ColorOperator; Context: TYPE ~ Imager.Context; PrinterType: TYPE ~ ImagerPress.PrinterType; Class: TYPE ~ ImagerPrivate.Class; ClassRep: PUBLIC TYPE ~ ImagerPrivate.ClassRep; -- export to Imager.ClassRep State: TYPE ~ ImagerState.State; StateRep: PUBLIC TYPE ~ ImagerState.StateRep; -- export to Imager.StateRep FontImpl: TYPE ~ REF FontImplRep; FontImplRep: PUBLIC TYPE ~ ImagerFontPrivate.FontImplRep; -- export to ImagerFont.FontImplRep ConstantColorImpl: TYPE ~ ImagerColorPrivate.ConstantColorImpl; ConstantColorImplRep: PUBLIC TYPE ~ ImagerColorPrivate.ConstantColorImplRep; -- export to ImagerColorDefs.ConstantColorImplRep Data: TYPE ~ REF DataRep; DataRep: TYPE ~ RECORD [ sirpress: SirPress.PressHandle, printerType: PrinterType, wantWarnings: INT _ 0, pageWidth: NAT, pageHeight: NAT, page: INT _ 1, cpValid: BOOL _ FALSE, hue, sat, val: [0..255] _ 0, fontTable: RefTab.Ref, scratchT: Transformation, scratchText: REF TEXT, lastPFD: REF _ NIL ]; Create: PUBLIC PROC [outputStream: IO.STREAM, fileNameForHeaderPage: ROPE, creatorName: ROPE, printerType: PrinterType, printingMode: ImagerPress.PrintingMode, pageWidthMicas: INT, pageHeightMicas: INT] RETURNS [context: Context] ~ { data: Data ~ NEW[DataRep _ [ sirpress: SirPress.Create[outputStream, fileNameForHeaderPage, creatorName, (SELECT printingMode FROM normal => normal, reverse => reverse, solid => solid, transparent => transparent, ENDCASE => ERROR)], printerType: printerType, pageWidth: MAX[MIN[pageWidthMicas, NAT.LAST], 0], pageHeight: MAX[MIN[pageHeightMicas, NAT.LAST], 0], fontTable: RefTab.Create[], scratchT: ImagerTransformation.Scale[0], scratchText: NEW[TEXT[80]] ]]; state: State ~ NEW[StateRep _ []]; state.T _ ImagerTransformation.Scale[100000]; state.color _ Imager.MakeGray[1]; context _ NEW[Imager.ContextRep _ [class: class, state: state, data: data, propList: NIL]]; }; SimpleCreate: PUBLIC PROC [fileName: ROPE, printerType: PrinterType _ press] RETURNS [context: Context] ~ { outputStream: IO.STREAM ~ FS.StreamOpen[fileName, $create]; context _ Create[outputStream, fileName, NIL, printerType, normal, 21590, 27940]; }; DoWithWarnings: PUBLIC PROC [context: Context, action: PROC] ~ { data: Data ~ NARROW[context.data]; data.wantWarnings _ data.wantWarnings + 1; action[! UNWIND => data.wantWarnings _ data.wantWarnings - 1]; data.wantWarnings _ data.wantWarnings - 1; }; Warning: PUBLIC SIGNAL [code: ATOM, explanation: ROPE, page, micaX, micaY: INT] ~ CODE; nullVec: VEC ~ [Real.LargestNumber, Real.LargestNumber]; Warn: PROC [context: Context, code: ATOM, explanation: ROPE, position: VEC _ nullVec] ~ { data: Data ~ NARROW[context.data]; state: State ~ context.state; IF data.wantWarnings > 0 THEN { IF position = nullVec THEN position _ ImagerBackdoor.GetCP[context]; position _ ImagerTransformation.Transform[state.T, position]; SIGNAL Warning[code, explanation, data.page, CRound[position.x, data.pageWidth], CRound[position.y, data.pageHeight]]; }; }; NewPage: PUBLIC PROC [context: Context] ~ { data: Data ~ NARROW[context.data]; state: State ~ context.state; SirPress.WritePage[data.sirpress]; state^ _ []; state.T _ ImagerTransformation.Scale[100000]; state.color _ Imager.MakeGray[1]; data.page _ data.page + 1; data.cpValid _ FALSE; data.hue _ data.sat _ data.val _ 0; data.lastPFD _ NIL; }; ValidateConstantColor: PUBLIC PROC [context: Context, pos: VEC _ nullVec] ~ { data: Data ~ NARROW[context.data]; state: State ~ context.state; sirpress: SirPress.PressHandle ~ data.sirpress; WITH state.color SELECT FROM c: ImagerColorDefs.ConstantColor => { impl: ConstantColorImpl ~ c.impl; hsv: ImagerColor.HSV _ [H: 0, S: 0, V: impl.Y]; h, s, v: [0..255] _ 0; WITH impl: impl SELECT FROM stipple => Warn[context, $SpecialColorNotAllowed, "Special color replaced by gray", pos]; gray => NULL; rgb => hsv _ ImagerColor.HSVFromRGB[impl.val]; cie => hsv _ ImagerColor.HSVFromRGB[ImagerColor.RGBFromCIE[impl.val]]; ENDCASE => Warn[context, $UnknownConstantColor, "Unknown constant color replaced by gray", pos]; h _ CRound[hsv.H*240, 240]; s _ CRound[hsv.S*255, 255]; v _ CRound[hsv.V*255, 255]; IF h#data.hue THEN { SirPress.SetHue[sirpress, data.hue _ h]; }; IF s#data.sat THEN { SirPress.SetSaturation[sirpress, data.sat _ s]; }; IF v#data.val THEN { SirPress.SetBrightness[sirpress, data.val _ v]; }; }; ENDCASE => { Warn[context, $SampledColorNotAllowed, "Sampled color not allowed for this mask", pos]; data.hue _ data.sat _ data.val _ 0; SirPress.SetColor[sirpress, 0, 0, 0]; }; }; SetSamplingProperties: PUBLIC PROC [context: Context, screenAngle: INT, screenAmplitude: INT, screenFrequency: INT, minIntensity: INT, maxIntensity: INT] ~ { refSamplingProperties: REF SirPress.SamplingProperties _ NEW[SirPress.SamplingProperties _ [omitted: FALSE, screenAngle: screenAngle, screenAmplitude: screenAmplitude, screenFrequency: screenAmplitude, minIntensity: minIntensity, maxIntensity: maxIntensity]]; Imager.PutProp[context, $PressSamplingProperties, refSamplingProperties]; }; Close: PUBLIC PROC [context: Context] ~ { WITH context.data SELECT FROM data: Data => { SirPress.ClosePress[data.sirpress]; }; ENDCASE => NULL; }; MyShow: PROC [context: Context, string: ImagerFont.XStringProc, xrel: BOOL] ~ { data: Data ~ NARROW[context.data]; xmax: REAL ~ data.pageWidth; ymax: REAL ~ data.pageHeight; sirpress: SirPress.PressHandle ~ data.sirpress; state: State ~ context.state; font: Font ~ state.font; fontImpl: FontImpl ~ font.impl; fontName: ROPE ~ fontImpl.typeface.name; offset: VEC _ [0,0]; composite: Transformation ~ CompositeT[]; CompositeT: PROC RETURNS [Transformation] ~ INLINE { t: Transformation ~ data.scratchT; t^ _ state.T^; t.c _ t.f _ 0; ImagerTransformation.ApplyPreConcat[t, font.charToClient]; offset _ [t.c, t.f]; t.c _ t.f _ 0; RETURN [t]; }; pfd: ImagerPressFontSubst.PressFontDescription ~ ImagerPressFontSubst.FindSubstitute[fontName, composite, data.printerType]; amplifySpace: REAL ~ state.np.amplifySpace; testAmplified: BOOL ~ amplifySpace#1; testCorrection: BOOL ~ state.np.correctPass#0; odd: BOOL _ FALSE; startCP: VEC _ nullVec; text: REF TEXT ~ data.scratchText; pressCP: VEC _ nullVec; pressSpace: VEC _ nullVec; Flush: PROC ~ { IF text.length > 0 THEN { IF startCP#nullVec THEN TRUSTED { SirPress.PutText[sirpress, LOOPHOLE[text], Real.Round[startCP.x], Real.Round[startCP.y]]; } ELSE TRUSTED { SirPress.PutTextHere[sirpress, LOOPHOLE[text]]; }; text.length _ 0; }; startCP _ nullVec; }; charAction: PROC [char: ImagerFont.XChar] ~ { IF odd THEN {Imager.SetXRel[context, CARDINAL[char.code]+256*CARDINAL[char.set]]} ELSE { width: VEC _ font.Width[char]; didPutChar: BOOL _ FALSE; IF testAmplified AND font.Amplified[char] THEN width _ width.Mul[amplifySpace]; Imager.Trans[context]; IF state.np.noImage=0 THEN { IF char.set = 0 AND pfd#NIL THEN { IF pressCP # state.p.cp THEN { Flush[]; pressCP _ state.p.cp; startCP _ Vector2.Add[pressCP, offset]; }; IF pressCP.x IN [0.0..xmax) AND pressCP.y IN [0.0..ymax) THEN { i: NAT ~ text.length; IF text.length = text.maxLength THEN Flush[]; text[text.length] _ VAL[char.code]; text.length _ text.length + 1; didPutChar _ TRUE; }; } ELSE { Flush[]; ImagerFontPrivate.MaskChar[font, char, context]; }; }; Imager.SetXYRel[context, width]; pressCP _ IF didPutChar AND pfd.veryClose THEN state.p.cp ELSE nullVec; IF testCorrection THEN SELECT ImagerFont.Correction[font, char] FROM none => NULL; space => Imager.CorrectSpace[context, width]; mask => Imager.CorrectMask[context]; ENDCASE => ERROR; }; odd _ xrel AND NOT odd; }; saveAction: PROC ~ { text.length _ 0; ValidateConstantColor[context]; string[charAction]; Flush[]; }; IF pfd # NIL AND pfd # data.lastPFD THEN { refCode: REF NAT _ NARROW[RefTab.Fetch[data.fontTable, pfd].val]; IF refCode = NIL THEN { refCode _ NEW[NAT _ SirPress.GetFontCode[sirpress, pfd.family, pfd.size, pfd.face, pfd.rotation, SirPress.mica]]; [] _ RefTab.Store[data.fontTable, pfd, refCode]; }; SirPress.SetFontFromCode[sirpress, refCode^]; data.lastPFD _ pfd; }; IF testAmplified THEN { w: VEC _ state.T.TransformVec[font.Width[[0, 40B]].Mul[amplifySpace]]; SirPress.SetSpace[sirpress, Real.Round[w.x], Real.Round[w.y]]; } ELSE SirPress.ResetSpace[sirpress]; Imager.DoSave[context, saveAction]; }; MyShowText: PROC [context: Context, text: REF READONLY TEXT, start, len: NAT, xrel: BOOL] ~ { string: ImagerFont.XStringProc ~ { ImagerFont.MapText[text, start, len, charAction] }; MyShow[context, string, xrel]; }; BezierToCoeffs: PROC [b0, b1, b2, b3: Vector2.VEC] RETURNS [c0, c1, c2, c3: Vector2.VEC] = { t: Vector2.VEC _ b2.Sub[b1].Mul[3]; c0 _ b0; c1 _ b1.Sub[b0].Mul[3]; c2 _ t.Sub[c1]; c3 _ b3.Sub[b0.Add[t]]; }; Bezier: TYPE ~ RECORD [b0, b1, b2, b3: VEC]; Add: PROC[a: VEC, b: VEC] RETURNS[VEC] = INLINE { RETURN[[a.x+b.x,a.y+b.y]] }; Sub: PROC[a: VEC, b: VEC] RETURNS[VEC] = INLINE { RETURN[[a.x-b.x,a.y-b.y]] }; In: PROC[a: VEC, b: VEC, c: VEC] RETURNS[BOOLEAN] = INLINE { RETURN[a.x IN[b.x..c.x] AND a.y IN[b.y..c.y]] }; Min: PROC[a: VEC, b: VEC] RETURNS[VEC] = INLINE { RETURN[[MIN[a.x,b.x],MIN[a.y,b.y]]] }; Max: PROC[a: VEC, b: VEC] RETURNS[VEC] = INLINE { RETURN[[MAX[a.x,b.x],MAX[a.y,b.y]]] }; FlatBezier: PROC[bezier: Bezier, epsilon: REAL] RETURNS[BOOLEAN] ~ { dx,dy: REAL; d1,d2,d,bl,bh: VEC; oh: VEC=[0.5,0.5]; bh _ Add[Max[bezier.b0,bezier.b3],oh]; bl _ Sub[Min[bezier.b0,bezier.b3],oh]; IF NOT In[bezier.b1,bl,bh] OR NOT In[bezier.b2,bl,bh] THEN RETURN[FALSE]; d1 _ Sub[bezier.b1,bezier.b0]; d2 _ Sub[bezier.b2,bezier.b0]; d _ Sub[bezier.b3,bezier.b0]; dx _ ABS[d.x]; dy _ ABS[d.y]; IF dx+dy < 1 THEN RETURN[TRUE]; IF dy < dx THEN { dydx: REAL _ d.y/d.x; RETURN[ABS[d2.y-d2.x*dydx]> delta: VEC ~ Vector2.Sub[p1, p0]; denom: REAL ~ Vector2.Dot[[a,b], delta]; num: REAL ~ c-Vector2.Dot[[a,b], p0]; t: REAL ~ num/denom; RETURN [Vector2.Add[p0, Vector2.Mul[delta, t]]]; }; PressPath: PROC [context: Context, path: PathProc] RETURNS [VEC] ~ { data: Data ~ NARROW[context.data]; sirpress: SirPress.PressHandle ~ data.sirpress; state: State ~ context.state; t: Transformation ~ state.T; lp: VEC _ [0.0, 0.0]; xmax: REAL ~ data.pageWidth; ymax: REAL ~ data.pageHeight; moveTo: ImagerPath.MoveToProc ~ { SirPress.PutMoveTo[sirpress, CRound[p.x, data.pageWidth], CRound[p.y, data.pageHeight]]; lp _ p; }; curse: NAT _ 4; lineTo: ImagerPath.LineToProc ~ { cross: VEC; SELECT TRUE FROM lp.x < 0.0 AND p1.x > 0.0, lp.x > 0.0 AND p1.x < 0.0 => cross _ Intersection[lp, p1, 1, 0, 0]; lp.y < 0.0 AND p1.y > 0.0, lp.y > 0.0 AND p1.y < 0.0 => cross _ Intersection[lp, p1, 0, 1, 0]; lp.x < xmax AND p1.x > xmax, lp.x > xmax AND p1.x < xmax => cross _ Intersection[lp, p1, 1, 0, xmax]; lp.y < ymax AND p1.y > ymax, lp.y > ymax AND p1.y < ymax => cross _ Intersection[lp, p1, 0, 1, ymax]; ENDCASE => { SirPress.PutDrawTo[sirpress, CRound[p1.x, data.pageWidth], CRound[p1.y, data.pageHeight]]; lp _ p1; RETURN; }; curse _ curse-1; lineTo[cross]; lineTo[p1]; curse _ curse+1; }; curveTo: ImagerPath.CurveToProc ~ { IF MIN[lp.x, lp.y, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y] < 0.0 OR MAX[lp.x, p1.x, p2.x, p3.x] > xmax OR MAX[lp.y, p1.y, p2.y, p3.y] > ymax THEN { IF FlatBezier[[lp, p1, p2, p3], 1] OR MIN[lp.x, p1.x, p2.x, p3.x] > xmax OR MAX[lp.x, lp.y, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y] < 0.0 OR MIN[lp.y, p1.y, p2.y, p3.y] > ymax THEN { SirPress.PutDrawTo[sirpress, CRound[p3.x, data.pageWidth], CRound[p3.y, data.pageHeight]]; lp _ p3; } ELSE { a, b: Bezier; [a, b] _ Split[[lp, p1, p2, p3]]; curveTo[a.b1, a.b2, a.b3]; curveTo[b.b1, b.b2, b.b3]; }; } ELSE { c0, c1, c2, c3: Vector2.VEC; [c0, c1, c2, c3] _ BezierToCoeffs[lp, p1, p2, p3]; SirPress.PutCubic[sirpress, c1.x, c1.y, c2.x, c2.y, c3.x, c3.y]; lp _ p3; }; }; ImagerPath.Transform[path, t, moveTo, lineTo, curveTo]; RETURN [lp]; }; MyMaskFill: PROC [context: Context, path: PathProc, oddWrap: BOOL] ~ { data: Data ~ NARROW[context.data]; lp: VEC; ValidateConstantColor[context]; SirPress.StartOutline[data.sirpress]; lp _ PressPath[context, path]; SirPress.EndOutline[data.sirpress]; IF data.printerType = spruce THEN Warn[context, $MaskFillNotImplemented, "Spruce will not like MaskFill", lp]; IF oddWrap THEN Warn[context, $WrapFillNotImplemented, "Press will use parity fill", lp]; }; CRound: PROC [real: REAL, bound: NAT] RETURNS [NAT] ~ { IF real <= 0 THEN RETURN [0] ELSE IF real >= bound THEN RETURN [bound] ELSE RETURN [Real.RoundC[real]] }; MyMaskRectangle: PROC [context: Context, r: Rectangle] ~ { data: Data ~ NARROW[context.data]; sirpress: SirPress.PressHandle ~ data.sirpress; state: State ~ context.state; t: Transformation ~ state.T; p0: VEC ~ ImagerTransformation.Transform[t, [r.x, r.y]]; v1: VEC ~ ImagerTransformation.TransformVec[t, [r.w, 0]]; v2: VEC ~ ImagerTransformation.TransformVec[t, [0.0, r.h]]; IF (v1.x = 0.0 AND v2.y = 0.0) OR (v1.y = 0.0 AND v2.x = 0.0) THEN { x0: REAL _ p0.x; y0: REAL _ p0.y; x1: REAL _ p0.x + v1.x + v2.x; y1: REAL _ p0.y + v1.y + v2.y; ox, oy, ow, oh: NAT; IF x0 > x1 THEN {t: REAL _ x0; x0 _ x1; x1 _ t}; IF y0 > y1 THEN {t: REAL _ y0; y0 _ y1; y1 _ t}; ox _ CRound[x0, data.pageWidth]; oy _ CRound[y0, data.pageHeight]; ow _ CRound[x1, data.pageWidth]-ox; oh _ CRound[y1, data.pageHeight]-oy; WITH state.color SELECT FROM c: ImagerColorDefs.ConstantColor => { ValidateConstantColor[context, [r.x, r.y]]; SirPress.PutRectangle[sirpress, ox, oy, ow, oh]; data.cpValid _ FALSE; }; c: ImagerColorDefs.SampledColor => { ValidateConstantColor[context, [r.x, r.y]]; -- will want to do scanned rectangle instead someday SirPress.PutRectangle[sirpress, ox, oy, ow, oh]; data.cpValid _ FALSE; }; ENDCASE => ERROR; } ELSE { pathProc: PathProc ~ { moveTo[[r.x, r.y]]; lineTo[[r.x+r.w, r.y]]; lineTo[[r.x+r.w, r.y+r.h]]; lineTo[[r.x, r.y+r.h]]; }; IF data.printerType=spruce THEN { Warn[context, $HardTransformation, "Unaligned rectangle", p0]; }; Imager.MaskFill[context: context, path: pathProc, parity: TRUE]; }; }; MyMaskRectangleI: PROC [context: Context, x, y, w, h: INTEGER] ~ { MyMaskRectangle[context, [x, y, w, h]]; }; MyMaskStroke: PROC [context: Context, path: PathProc, closed: BOOL] ~ { data: Data ~ NARROW[context.data]; Warn[context, $Unimplemented, "MaskStroke not implemented"]; }; MyMaskDashedStroke: PROC [context: Context, path: PathProc, patternLen: NAT, pattern: PROC [NAT] RETURNS [REAL], offset, length: REAL] ~ { data: Data ~ NARROW[context.data]; Warn[context, $Unimplemented, "MaskDashedStroke not implemented"]; }; MyMaskVector: PROC [context: Context, p1, p2: VEC] ~ { data: Data ~ NARROW[context.data]; state: State ~ context.state; strokeWidth: REAL ~ state.np.strokeWidth; strokeEnd: Imager.StrokeEnd ~ VAL[NAT[state.np.strokeEnd]]; r: REAL ~ strokeWidth*0.5; proc: PROC ~ { pathProc: PathProc ~ { moveTo[[s, -r]]; arcTo[[s+r, 0], [s, r]]; lineTo[[0, r]]; arcTo[[-r, 0], [0, -r]]; }; v: VEC ~ Vector2.Sub[p2, p1]; s: REAL ~ RealFns.SqRt[v.x*v.x+v.y*v.y]; sin: REAL ~ IF s=0 THEN 0.0 ELSE v.y/s; cos: REAL ~ IF s=0 THEN 1.0 ELSE v.x/s; m: Transformation ~ data.scratchT; m.a _ m.e _ cos; m.b _ -sin; m.d _ sin; m.c _ m.f _ 0; m.form _ 0; m.integerTrans _ FALSE; Imager.TranslateT[context, p1]; Imager.ConcatT[context, m]; SELECT strokeEnd FROM square => {MyMaskRectangle[context, [-r, -r, s+2*r, strokeWidth]]}; butt => {MyMaskRectangle[context, [0, -r, s, strokeWidth]]}; round => {MyMaskFill[context, pathProc, TRUE]}; ENDCASE => ERROR; }; IF strokeWidth >= 0 THEN Imager.DoSaveAll[context, proc]; }; MyMaskPixel: PROC [context: Context, pa: PixelArray] ~ { data: Data ~ NARROW[context.data]; Warn[context, $Unimplemented, "MaskPixel not implemented"]; }; MyMaskBits: PROC [context: Context, base: LONG POINTER, wordsPerLine: NAT, sMin, fMin, sSize, fSize: NAT, tx, ty: INTEGER] ~ { data: Data ~ NARROW[context.data]; Warn[context, $Unimplemented, "MaskBits not implemented"]; }; MyGetBoundingRectangle: PROC [context: Context] RETURNS [Rectangle] ~ { state: State ~ context.state; data: Data ~ NARROW[context.data]; RETURN[state.T.InverseTransformRectangle[[x: 0, y: 0, w: data.pageWidth, h: data.pageHeight]]]; }; class: Class ~ NEW [ClassRep _ [ type: $Press, DoSave: ImagerState.StateDoSave, SetInt: ImagerState.StateSetInt, SetReal: ImagerState.StateSetReal, SetT: ImagerState.StateSetT, SetFont: ImagerState.StateSetFont, SetColor: ImagerState.StateSetColor, SetClipper: ImagerState.StateSetClipper, GetInt: ImagerState.StateGetInt, GetReal: ImagerState.StateGetReal, GetT: ImagerState.StateGetT, GetFont: ImagerState.StateGetFont, GetColor: ImagerState.StateGetColor, GetClipper: ImagerState.StateGetClipper, ConcatT: ImagerState.StateConcatT, Scale2T: ImagerState.StateScale2T, RotateT: ImagerState.StateRotateT, TranslateT: ImagerState.StateTranslateT, Move: ImagerState.StateMove, SetXY: ImagerState.StateSetXY, SetXYRel: ImagerState.StateSetXYRel, Show: MyShow, ShowText: MyShowText, StartUnderline: ImagerState.StateStartUnderline, MaskUnderline: ImagerState.StateMaskUnderline, CorrectMask: ImagerState.StateCorrectMask, CorrectSpace: ImagerState.StateCorrectSpace, Space: ImagerState.StateSpace, SetCorrectMeasure: ImagerState.StateSetCorrectMeasure, SetCorrectTolerance: ImagerState.StateSetCorrectTolerance, Correct: ImagerState.StateCorrect, DontCorrect: ImagerState.StateDontCorrect, SetGray: ImagerState.StateSetGray, SetSampledColor: ImagerState.StateSetSampledColor, SetSampledBlack: ImagerState.StateSetSampledBlack, MaskFill: MyMaskFill, MaskStroke: MyMaskStroke, MaskRectangle: MyMaskRectangle, MaskRectangleI: MyMaskRectangleI, MaskVector: MyMaskVector, MaskDashedStroke: MyMaskDashedStroke, MaskPixel: MyMaskPixel, MaskBits: MyMaskBits, Clip: ImagerState.StateClip, ClipRectangle: ImagerState.StateClipRectangle, ClipRectangleI: ImagerState.StateClipRectangleI, GetCP: ImagerState.StateGetCP, GetBoundingRectangle: MyGetBoundingRectangle, propList: NIL ]]; END.