DIRECTORY Imager, ImagerBasic, ImagerDefault, ImagerOps USING [DRound], ImagerTransform, Real; ImagerDefaultImpl: CEDAR PROGRAM IMPORTS Imager, ImagerOps, ImagerTransform, Real EXPORTS ImagerDefault ~ BEGIN OPEN Imager; DoSave: PUBLIC PROC[context: Context, body: PROC] ~ { state: State ~ context.state; saved: StateRep ~ state^; Restore: PROC ~ { state.T _ saved.T; state.priorityImportant _ saved.priorityImportant; state.mediumXSize _ saved.mediumXSize; state.mediumYSize _ saved.mediumYSize; state.fieldXMin _ saved.fieldXMin; state.fieldYMin _ saved.fieldYMin; state.fieldXMax _ saved.fieldXMax; state.fieldYMax _ saved.fieldYMax; state.showVec _ saved.showVec; state.color _ saved.color; state.noImage _ saved.noImage; state.strokeWidth _ saved.strokeWidth; state.strokeEnd _ saved.strokeEnd; state.underlineStart _ saved.underlineStart; state.amplifySpace _ saved.amplifySpace; state.correctPass _ saved.correctPass; state.correctShrink _ saved.correctShrink; state.correctTX _ saved.correctTX; state.correctTY _ saved.correctTY; state.clipper _ saved.clipper; }; body[! UNWIND => Restore[]]; Restore[]; }; DoSaveAll: PUBLIC PROC[context: Context, body: PROC] ~ { state: State ~ context.state; saved: StateRep ~ state^; Restore: PROC ~ { state^ _ saved }; body[! UNWIND => Restore[]]; Restore[]; }; SetPriorityImportant: PUBLIC PROC[context: Context, priorityImportant: BOOL] ~ { context.state.priorityImportant _ IF priorityImportant THEN 1 ELSE 0; }; SetFont: PUBLIC PROC[context: Context, font: FONT] ~ { context.state.showVec _ font; }; SetColor: PUBLIC PROC[context: Context, color: Color] ~ { context.state.color _ color; }; SetNoImage: PUBLIC PROC[context: Context, noImage: BOOL] ~ { context.state.noImage _ IF noImage THEN 1 ELSE 0; }; SetStrokeWidth: PUBLIC PROC[context: Context, strokeWidth: REAL] ~ { context.state.strokeWidth _ strokeWidth; }; SetStrokeEnd: PUBLIC PROC[context: Context, strokeEnd: StrokeEnd] ~ { context.state.strokeEnd _ (SELECT strokeEnd FROM square => 0, butt => 1, round => 2, ENDCASE => ERROR); }; SetAmplifySpace: PUBLIC PROC[context: Context, amplifySpace: REAL] ~ { context.state.amplifySpace _ amplifySpace; }; SetCorrectShrink: PUBLIC PROC[context: Context, correctShrink: REAL] ~ { context.state.correctShrink _ correctShrink; }; SetSampledColor: PUBLIC PROC[context: Context, pa: PixelArray, pixelT: Transformation, colorOperator: ATOM] ~ { state: State ~ context.state; color: SampledColor ~ NEW[ColorRep.sampled _ [sampled[ transparent: FALSE, pa: pa, m: pixelT.Concat[state.T], colorOperator: colorOperator ]]]; state.color _ color; }; SetSampledBlack: PUBLIC PROC[context: Context, pa: PixelArray, pixelT: Transformation, transparent: BOOL] ~ { state: State ~ context.state; color: SampledColor ~ NEW[ColorRep.sampled _ [sampled[ transparent: transparent, pa: pa, m: pixelT.Concat[state.T], colorOperator: $SampledBlack ]]]; state.color _ color; }; ConcatT: PUBLIC PROC[context: Context, m: Transformation] ~ { state: State ~ context.state; state.T _ ImagerTransform.Concat[m, state.T]; }; ScaleT: PUBLIC PROC[context: Context, s: REAL] ~ { state: State ~ context.state; state.T _ ImagerTransform.PreScale[s, state.T]; }; Scale2T: PUBLIC PROC[context: Context, sx, sy: REAL] ~ { state: State ~ context.state; state.T _ ImagerTransform.PreScale2[sx, sy, state.T]; }; RotateT: PUBLIC PROC[context: Context, a: REAL] ~ { state: State ~ context.state; state.T _ ImagerTransform.PreRotate[a, state.T]; }; TranslateT: PUBLIC PROC[context: Context, x, y: REAL] ~ { state: State ~ context.state; state.T _ ImagerTransform.PreTranslate[x, y, state.T]; }; Move: PUBLIC PROC[context: Context] ~ { state: State ~ context.state; new: Pair ~ [state.cpx, state.cpy]; t: Transformation ~ state.T; state.T _ ImagerTransform.Create[t.a, t.b, new.x, t.d, t.e, new.y]; }; Trans: PUBLIC PROC[context: Context] ~ { state: State ~ context.state; new: Pair ~ ImagerOps.DRound[[state.cpx, state.cpy]]; t: Transformation ~ state.T; state.T _ ImagerTransform.Create[t.a, t.b, new.x, t.d, t.e, new.y]; }; SetXY: PUBLIC PROC[context: Context, x, y: REAL] ~ { state: State ~ context.state; [[state.cpx, state.cpy]] _ ImagerTransform.Transform[[x, y], state.T]; }; SetXYI: PUBLIC PROC[context: Context, x, y: INTEGER] ~ { context.SetXY[x, y]; }; SetXYRel: PUBLIC PROC[context: Context, x, y: REAL] ~ { state: State ~ context.state; delta: Pair ~ ImagerTransform.TransformVec[[x, y], state.T]; state.cpx _ state.cpx + delta.x; state.cpy _ state.cpy + delta.y; }; SetXYRelI: PUBLIC PROC[context: Context, x, y: INTEGER] ~ { context.SetXYRel[x, y]; }; MaskVector: PUBLIC PROC[context: Context, x1, y1, x2, y2: REAL] ~ { vector: PathProc ~ { move[[x1, y1]]; line[[x2, y2]] }; context.MaskStrokePath[vector]; }; MaskVectorI: PUBLIC PROC[context: Context, x1, y1, x2, y2: INTEGER] ~ { context.MaskVector[x1, y1, x2, y2]; }; StartUnderline: PUBLIC PROC[context: Context] ~ { state: State ~ context.state; cp: Pair ~ ImagerTransform.InverseTransform[[state.cpx, state.cpy], state.T]; state.underlineStart _ cp.x; }; MaskUnderline: PUBLIC PROC[context: Context, dy, h: REAL] ~ { body: PROC ~ { state: State ~ context.state; cp: Pair ~ ImagerTransform.InverseTransform[[state.cpx, state.cpy], state.T]; context.SetXY[state.underlineStart, cp.y-dy-h]; context.Trans[]; context.MaskRectangle[0, 0, cp.x-state.underlineStart, h]; }; context.DoSaveAll[body]; }; MaskUnderlineI: PUBLIC PROC[context: Context, dy, h: INTEGER] ~ { context.MaskUnderline[dy, h]; }; ClipRectangle: PUBLIC PROC[context: Context, x, y, w, h: REAL] ~ { state: State ~ context.state; rectangle: PathProc ~ { move[[x, y]]; line[[x+w, y]]; line[[x+w, y+h]]; line[[x, y+h]]; }; ClipOutlinePath[context, rectangle]; WITH state.clipper SELECT FROM clipper: ImagerBasic.ClientClipper => { t: Transformation ~ state.T; clipper.first.easyRectangle _ (t.a = 0 AND t.e = 0) OR (t.b = 0 AND t.d = 0); }; ENDCASE => ERROR Imager.Error[$Bug]; }; ClipRectangleI: PUBLIC PROC[context: Context, x, y, w, h: INTEGER] ~ { context.ClipRectangle[x, y, w, h]; }; ExcludeRectangle: PUBLIC PROC[context: Context, x, y, w, h: REAL] ~ { ClipRectangle[context, x, y, w, h]; WITH context.state.clipper SELECT FROM clipper: ImagerBasic.ClientClipper => clipper.first.exclude _ TRUE; ENDCASE => ERROR Imager.Error[$Bug]; }; ExcludeRectangleI: PUBLIC PROC[context: Context, x, y, w, h: INTEGER] ~ { context.ExcludeRectangle[x, y, w, h]; }; CorrectMask: PUBLIC PROC[context: Context] ~ { state: State ~ context.state; SELECT state.correctPass FROM 1 => state.correctMaskCount _ state.correctMaskCount + 1; 2 => IF state.correctMaskCount > 0 THEN { spx: REAL ~ state.correctMaskX/state.correctMaskCount; spy: REAL ~ state.correctMaskY/state.correctMaskCount; state.correctMaskX _ state.correctMaskX - spx; state.correctMaskY _ state.correctMaskY - spy; state.correctMaskCount _ state.correctMaskCount - 1; state.cpx _ state.cpx + spx; state.cpy _ state.cpy + spy; }; ENDCASE => NULL; }; CorrectSpace: PUBLIC PROC[context: Context, x, y: REAL] ~ { state: State ~ context.state; CorrectSpaceView[context, ImagerTransform.TransformVec[[x, y], state.T]]; }; CorrectSpaceView: PUBLIC PROC[context: Context, v: Pair] ~ { state: State ~ context.state; SELECT state.correctPass FROM 1 => { state.correctSumX _ state.correctSumX + v.x; state.correctSumY _ state.correctSumY + v.y; }; 2 => { Div: PROC [num, denom: REAL] RETURNS [REAL] ~ { IF denom = 0.0 THEN { IF num = 0.0 THEN RETURN [0.0] ELSE ERROR Imager.Error[$ZeroDivideInCorrectSpace] } ELSE RETURN [num/denom] }; spx: REAL ~ Div[v.x*state.correctSpaceX, state.correctSumX]; spy: REAL ~ Div[v.y*state.correctSpaceY, state.correctSumY]; state.correctSumX _ state.correctSumX - v.x; state.correctSumY _ state.correctSumY - v.y; state.correctSpaceX _ state.correctSpaceX - spx; state.correctSpaceY _ state.correctSpaceY - spy; state.cpx _ state.cpx + spx; state.cpy _ state.cpy + spy; }; ENDCASE => NULL; }; SetCorrectMeasure: PUBLIC PROC[context: Context, x, y: REAL] ~ { state: State ~ context.state; [[state.correctMX, state.correctMY]] _ ImagerTransform.TransformVec[[x, y], state.T]; }; SetCorrectTolerance: PUBLIC PROC[context: Context, x, y: REAL] ~ { state: State ~ context.state; [[state.correctTX, state.correctTY]] _ ImagerTransform.TransformVec[[x, y], state.T]; }; Space: PUBLIC PROC[context: Context, x: REAL] ~ { state: State ~ context.state; v: Pair ~ ImagerTransform.TransformVec[[x, 0], state.T]; state.cpx _ state.cpx + v.x; state.cpy _ state.cpy + v.y; SELECT state.correctPass FROM 1 => { state.correctSumX _ state.correctSumX + v.x; state.correctSumY _ state.correctSumY + v.y; }; 2 => IF state.correctMaskCount > 0 THEN { Div: PROC [num, denom: REAL] RETURNS [REAL] ~ { IF denom = 0.0 THEN { IF num = 0.0 THEN RETURN [0.0] ELSE ERROR Imager.Error[$ZeroDivideInCorrectSpace] } ELSE RETURN [num/denom] }; spx: REAL ~ Div[v.x*state.correctSpaceX, state.correctSumX]; spy: REAL ~ Div[v.y*state.correctSpaceY, state.correctSumY]; state.correctSumX _ state.correctSumX - v.x; state.correctSumY _ state.correctSumY - v.y; state.correctSpaceX _ state.correctSpaceX - spx; state.correctSpaceY _ state.correctSpaceY - spy; state.cpx _ state.cpx + spx; state.cpy _ state.cpy + spy; }; ENDCASE => NULL; }; SpaceI: PUBLIC PROC [context: Context, x: INTEGER] ~ { context.Space[x]; }; Correct: PUBLIC PROC[context: Context, body: PROC] ~ { state: State ~ context.state; Length: PROC [x, y: REAL] RETURNS [REAL] ~ { RETURN [Real.SqRt[x*x + y*y]]; }; state.correctcpx _ state.cpx; state.correctcpy _ state.cpy; state.noImage _ 1; state.correctMaskCount _ 0; state.correctSumX _ state.correctSpaceY _ 0; state.correctPass _ 1; Imager.DoSave[context, body]; state.correctTargetX _ state.correctcpx + state.correctMX; state.correctTargetY _ state.correctcpy + state.correctMY; state.correctMaskX _ state.correctMaskY _ 0; state.correctMaskCount _ state.correctMaskCount - 1; state.correctSpaceX _ state.correctTargetX - state.cpx; state.correctSpaceY _ state.correctTargetY - state.cpy; CHECKED { IF ( Length[state.correctSpaceX, state.correctSpaceY] > state.correctShrink*Length[state.correctSumX, state.correctSumY] AND Length[state.correctcpx - state.correctTargetX, state.correctcpy - state.correctTargetY] < Length[state.correctcpx - state.cpx, state.correctcpy - state.cpy] ) THEN { state.correctMaskX _ state.correctSpaceX + state.correctShrink*state.correctSumX; state.correctMaskY _ state.correctSpaceY + state.correctShrink*state.correctSumY; state.correctSpaceX _ state.correctSpaceX - state.correctMaskX; state.correctSpaceY _ state.correctSpaceY - state.correctMaskY; }; IF state.correctSumX = 0 AND state.correctSpaceX # 0 THEN { state.correctMaskX _ state.correctSpaceX; state.correctSpaceX _ 0; }; IF state.correctSumY = 0 AND state.correctSpaceY # 0 THEN { state.correctMaskY _ state.correctSpaceY; state.correctSpaceY _ 0; }; }; state.cpx _ state.correctcpx; state.cpy _ state.correctcpy; state.noImage _ 0; state.correctPass _ 2; Imager.DoSave[context, body]; state.correctPass _ 0; IF Length[state.correctTargetX - state.cpx, state.correctTargetY - state.cpy] > Length[state.correctTX, state.correctTY] THEN ERROR Imager.Error[$UnableToProperlyAdjustMaskPositions]; state.cpx _ state.correctTargetX; state.cpy _ state.correctTargetY; }; END. œImagerDefaultImpl.mesa Michael Plass, April 12, 1984 3:08:20 pm PST Doug Wyatt, July 23, 1984 12:39:51 pm PDT InitialStateRep: ImagerBasic.StateRep ~ [ cpx: 0.0, cpy: 0.0, correctMX: 0.0, correctMY: 0.0, correctMaskCount: 0, correctMaskX: 0.0, correctMaskY: 0.0, correctSumX: 0.0, correctSumY: 0.0, correctSpaceX: 0.0, correctSpaceY: 0.0, correctcpx: 0.0, correctcpy: 0.0, correctTargetX: 0.0, correctTargetY: 0.0, T: ImagerTransform.Create[1,0,0,0,1,0], priorityImportant: 0, mediumXSize: 0, mediumYSize: 0, fieldXMin: 0, fieldYMin: 0, fieldXMax: 0, fieldYMax: 0, showVec: NIL, color: NIL, noImage: 0, strokeWidth: 0.0, strokeEnd: 0, underlineStart: 0.0, amplifySpace: 1.0, correctPass: 0, correctShrink: 0.5, correctTX: 0.0, correctTY: 0.0, clipper: NIL, propertyList: NIL ]; InitState: PUBLIC PROC [context: Context] ~ { state: State _ NEW[ImagerBasic.StateRep _ InitialStateRep]; state.color _ Imager.black; context.state _ state; }; GetCP: PUBLIC PROC [context: Context] RETURNS [cp: Pair] ~ { WITH context.state SELECT FROM state: State => { cp _ ImagerTransform.InverseTransform[[state.cpx, state.cpy], state.T]; }; ENDCASE => ERROR Imager.Error[$Bug]; }; GetCPRounded: PUBLIC PROC [context: Context] RETURNS [cp: Pair] ~ { WITH context.state SELECT FROM state: State => { cp _ ImagerTransform.InverseTransform[[Real.RoundLI[state.cpx], Real.RoundLI[state.cpy]], state.T]; }; ENDCASE => ERROR Imager.Error[$Bug]; }; ClipOutline: PUBLIC PROC[context: Context, pathProc: PathProc, pathData: REF] ~ { WITH context.state SELECT FROM state: State => { trans: ImagerTransform.TransformationRec ~ state.T.Contents; XForm: PROC [p: Pair] RETURNS [Pair] ~ { RETURN [[trans.a*p.x+trans.b*p.y+trans.c, trans.d*p.x+trans.e*p.y+trans.f]] }; tList: LIST OF Trajectory _ NIL; Move: PROC [p: Pair] ~ {tList _ CONS[Imager.MoveTo[XForm[p]], tList]}; Line: PROC [p: Pair] ~ {tList.first _ tList.first.LineTo[XForm[p]]}; Curve: PROC [p1, p2, p3: Pair] ~ { tList.first _ tList.first.CurveTo[XForm[p1], XForm[p2], XForm[p3]] }; Conic: PROC [p1, p2: Pair, r: REAL] ~ { tList.first _ tList.first.ConicTo[XForm[p1], XForm[p2], r] }; pathMap[pathData, Move, Line, Curve, Conic]; state.clipper _ CONS[[exclude: FALSE, easyRectangle: FALSE, pathMap: MapTrajectoryList, pathData: tList], state.clipper]; }; ENDCASE => ERROR Imager.Error[$InvalidState]; }; MapTrajectory: PathMapType = { t: Trajectory = NARROW[data]; move[t.lp]; FOR x: Trajectory _ t, x.prev UNTIL x.prev=NIL DO p0: Pair = x.prev.lp; WITH x SELECT FROM x: REF TrajectoryRep[line] => line[p0]; x: REF TrajectoryRep[curve] => curve[x.p2, x.p1, p0]; x: REF TrajectoryRep[conic] => conic[x.p1, p0, x.r]; x: REF TrajectoryRep[move] => ERROR; ENDCASE => ERROR; ENDLOOP; }; MapTrajectoryList: PathMapType = { FOR x: LIST OF Trajectory _ NARROW[data], x.rest UNTIL x = NIL DO MapTrajectory[x.first, move, line, curve, conic] ENDLOOP; }; ExcludeOutline: PUBLIC PROC[context: Context, pathMap: PathMapType, pathData: REF] ~ { WITH context.state SELECT FROM state: State => { ClipOutline[context, pathMap, pathData]; state.clipper.first.exclude _ TRUE; }; ENDCASE => ERROR Imager.Error[$InvalidState]; }; Equivalent to {SetXYRel[context, [x, 0]]; CorrectSpace[context, [x, 0]]} The interpress document asks that this be the length in meters, but since it is only used for comparisons, view coordinates should work as well. If the view coordinates had non-uniform scaling, this would have to be accounted for here. Reset: PUBLIC PROC [context: Context] ~ { WITH context.state SELECT FROM state: State => { propertyList: REF _ state.propertyList; state^ _ InitialStateRep; state.color _ Imager.black; state.propertyList _ propertyList; }; ENDCASE => ERROR Imager.Error[$Bug]; }; DrawBitmap: PUBLIC PROC [context: Context, base: LONG POINTER, raster: CARDINAL, area: IntRectangle] ~ { ERROR Imager.Error[$NotYetImplemented]; }; MaskBits: PUBLIC PROC [context: Context, base: LONG POINTER, raster: CARDINAL, tile: IntRectangle, area: IntRectangle] ~ { ERROR Imager.Error[$NotYetImplemented]; }; GetSurfaceBounds: PUBLIC PROC [context: Context] RETURNS [IntRectangle] ~ { WITH context.state SELECT FROM state: State => { ERROR Imager.Error[$NotYetImplemented]; }; ENDCASE => ERROR Imager.Error[$Bug]; }; ʹ˜™J™,J™)—J˜šÏk ˜ Jšœ˜Jšœ ˜ Jšœ˜Jšœ œ ˜Jšœ˜Jšœ˜J˜—Jšœœ˜ Jšœ)˜0Jšœ˜Jšœœœ˜J˜šœ)™)Jšœ ™ Jšœ ™ Jšœ™Jšœ™Jšœ™Jšœ™Jšœ™Jšœ™Jšœ™Jšœ™Jšœ™Jšœ™Jšœ™Jšœ™Jšœ™Jšœ'™'Jšœ™Jšœ™Jšœ™Jšœ ™ Jšœ ™ Jšœ ™ Jšœ ™ Jšœ œ™ Jšœœ™ Jšœ ™ Jšœ™Jšœ ™ Jšœ™Jšœ™Jšœ™Jšœ™Jšœ™Jšœ™Jšœ œ™ Jšœ™Jšœ™J™—šÏn œ œ™-Jšœœ)™;Jšœ™Jšœ™Jšœ™J™—J˜šžœœœœ˜5Jšœ˜Jšœ˜šžœœ˜Jšœ˜Jšœ2˜2Jšœ&˜&Jšœ&˜&Jšœ"˜"Jšœ"˜"Jšœ"˜"Jšœ"˜"Jšœ˜Jšœ˜Jšœ˜Jšœ&˜&Jšœ"˜"Jšœ,˜,Jšœ(˜(Jšœ&˜&Jšœ*˜*Jšœ"˜"Jšœ"˜"Jšœ˜Jšœ˜—Jšœœ˜J˜ Jšœ˜J˜—šž œœœœ˜8Jšœ˜Jšœ˜Jšžœœ˜#Jšœœ˜J˜ Jšœ˜J˜—šžœœœ&œ˜PJšœ"œœœ˜EJ˜J˜—šžœœœœ˜6Jšœ˜J˜J˜—šžœœœ$˜9Jšœ˜J˜J˜—šž œœœœ˜J˜šœœ˜6Jšœ˜Jšœ˜Jšœ˜Jšœ˜J˜—Jšœ˜Jšœ˜J˜—šžœ œ)˜=J˜Jšœ-˜-Jšœ˜J˜—šžœ œœ˜2J˜Jšœ/˜/Jšœ˜J˜—šžœ œœ˜8J˜Jšœ5˜5Jšœ˜J˜—šžœ œœ˜3J˜Jšœ0˜0Jšœ˜J˜—šž œ œœ˜9J˜Jšœ6˜6Jšœ˜J˜—šžœ œ˜'J˜Jšœ#˜#Jšœ˜JšœC˜CJšœ˜J˜—šžœ œ˜(J˜Jšœ5˜5Jšœ˜JšœC˜CJšœ˜J˜—šžœœœœ˜4J˜JšœF˜FJšœ˜J˜—šžœœœœ˜8J˜Jšœ˜J˜—šžœ œœ˜7J˜Jšœ<˜œ˜CJšœœ˜$—Jšœ˜J˜—šžœ œœ˜IJšœ%˜%Jšœ˜J˜—šž œ œ˜.Jšœ˜šœ˜Jšœ9˜9šœœœ˜)Jšœœ-˜6Jšœœ-˜6Jšœ.˜.Jšœ.˜.Jšœ4˜4Jšœ˜Jšœ˜Jšœ˜—Jšœœ˜—Jšœ˜J˜—šž œœœœ˜;Jšœ˜JšœEœ˜IJšœ˜J˜—šžœ œ˜