DIRECTORY Draw2d, Imager, ImagerBackdoor, ImagerDevice, ImagerFont, ImagerOps, ImagerRasterPrivate, ImagerState, ImagerTransformation, IO, Real, Rope, Vector2; Draw2dImpl: CEDAR PROGRAM IMPORTS Imager, ImagerFont, ImagerOps, ImagerRasterPrivate, ImagerTransformation, Real, Vector2 EXPORTS Draw2d, Imager ~ BEGIN Context: TYPE ~ Imager.Context; VEC: TYPE ~ Imager.VEC; -- RECORD [x, y: REAL] DrawType: TYPE ~ Draw2d.DrawType; MarkType: TYPE ~ Draw2d.MarkType; PixelProc: TYPE ~ Draw2d.PixelProc; Clear: PUBLIC PROC [context: Context, width, height: INTEGER] ~ { Imager.SetColor[context, Imager.white]; Imager.MaskRectangleI[context, 0, 0, width, height]; Imager.SetColor[context, Imager.black]; }; InitFont: PUBLIC PROC [context: Context] ~ { Imager.SetFont[context, ImagerFont.Find["xerox/tiogafonts/helvetica10"]]; }; Label: PUBLIC PROC [context: Context, vec: VEC, rope: Rope.ROPE] ~ { Imager.SetXY[context, vec]; Imager.ShowRope[context, rope]; }; DoWithBuffer: PUBLIC PROC [context: Context, width, height: INTEGER, action: PROC] ~ { InitFont[context]; Imager.SetStrokeWidth[context, 0.0]; ImagerOps.DoWithBuffer[context, action, 0, 0, width, height]; }; Line: PUBLIC PROC [context: Context, vec0, vec1: VEC, drawType: DrawType _ solid] ~ { SELECT drawType FROM solid => Solid[context, vec0, vec1]; dot => Dot[context, vec0, vec1]; dash => Dash[context, vec0, vec1]; ENDCASE => NULL; }; DoWithLine: PUBLIC PROC [vec0, vec1: VEC, pixelProc: PixelProc] ~ { x0: INTEGER _ Real.RoundI[vec0.x]; y0: INTEGER _ Real.RoundI[vec0.y]; x1: INTEGER _ Real.RoundI[vec1.x]; y1: INTEGER _ Real.RoundI[vec1.y]; dyPos: BOOL ~ y1 > y0; dxPos: BOOL ~ x1 > x0; dy: INTEGER _ IF dyPos THEN y1-y0 ELSE y0-y1; dx: INTEGER _ IF dxPos THEN x1-x0 ELSE x0-x1; eincy: INTEGER ~ dy+dy; eincx: INTEGER ~ dx+dx; x, y, incx, incy: INTEGER; SELECT TRUE FROM dy = 0 => { IF NOT dxPos THEN {t: INTEGER _ x0; x0 _ x1; x1 _ t}; FOR x: INTEGER IN [x0..x1] DO pixelProc[x, y0]; ENDLOOP; }; dx = 0 => { IF NOT dyPos THEN {t: INTEGER _ y0; y0 _ y1; y1 _ t}; FOR y: INTEGER IN [y0..y1] DO pixelProc[x0, y]; ENDLOOP; }; dy > dx => { e: INTEGER _ eincx-dy; IF dyPos THEN {y _ y0; x _ x0; incx _ IF dxPos THEN 1 ELSE -1} ELSE {y _ y1; x _ x1; incx _ IF dxPos THEN -1 ELSE 1}; WHILE dy >= 0 DO pixelProc[x, y]; IF e > 0 THEN {x _ x+incx; e _ e-eincy}; e _ e+eincx; y _ y+1; dy _ dy-1; ENDLOOP; }; ENDCASE => { e: INTEGER _ eincy-dx; IF dxPos THEN {x _ x0; y _ y0; incy _ IF dyPos THEN 1 ELSE -1} ELSE {x _ x1; y _ y1; incy _ IF dyPos THEN -1 ELSE 1}; WHILE dx >= 0 DO pixelProc[x, y]; IF e > 0 THEN {y _ y+incy; e _ e-eincx}; e _ e+eincy; x _ x+1; dx _ dx-1; ENDLOOP; }; }; Dot: PROC [context: Context, vec0, vec1: VEC] ~ { stepInc: VEC; delta: VEC _ [vec1.x-vec0.x, vec1.y-vec0.y]; nSteps: INTEGER _ Real.RoundI[0.2*Real.SqRt[delta.x*delta.x+delta.y*delta.y]]; IF nSteps < 1 THEN RETURN; stepInc _ [delta.x/nSteps, delta.y/nSteps]; FOR n: NAT IN [0..nSteps) DO Imager.MaskRectangle[context, [vec0.x, vec0.y, 1, 1]]; vec0 _ [vec0.x+stepInc.x, vec0.y+stepInc.y]; ENDLOOP; }; Dash: PROC [context: Context, vec0, vec1: VEC] ~ { delta: VEC _ [vec1.x-vec0.x, vec1.y-vec0.y]; nSteps: INTEGER _ Real.RoundI[0.10*Real.SqRt[delta.x*delta.x+delta.y*delta.y]]; IF nSteps > 0 THEN { stepInc: VEC _ [delta.x/nSteps, delta.y/nSteps]; drawInc: VEC _ [0.5*stepInc.x, 0.5*stepInc.y]; FOR n: NAT IN[0..nSteps) DO Solid[context, vec0, [vec0.x+drawInc.x, vec0.y+drawInc.y]]; vec0 _ [vec0.x+stepInc.x, vec0.y+stepInc.y]; ENDLOOP; }; }; Data: TYPE ~ ImagerRasterPrivate.Data; State: TYPE ~ ImagerState.State; StateRep: PUBLIC TYPE ~ ImagerState.StateRep; -- export to Imager.StateRep Solid: PROC [context: Context, vec0, vec1: VEC] ~ { -- Bresenham's method state: State ~ context.state; needs: ImagerRasterPrivate.Flags ~ [clientToDevice: TRUE, clientClipper: TRUE, deviceColor: TRUE, devicePriority: TRUE]; WITH context.data SELECT FROM data: Data => { device: ImagerDevice.Device ~ data.device; bounds: ImagerDevice.DeviceBox _ data.clientClipBox; IF bounds.smin = bounds.smax OR bounds.fmin = bounds.fmax THEN RETURN; bounds.smin _ bounds.smin+1; -- simplify clipping bounds.fmin _ bounds.fmin+1; bounds.smax _ bounds.smax-1; -- simplify clipping bounds.fmax _ bounds.fmax-1; IF state.changed # ImagerState.notChanged THEN ImagerRasterPrivate.NoteStateChanges[data, state]; IF ImagerRasterPrivate.AndFlags[data.valid, needs] # needs THEN ImagerRasterPrivate.ValidateIfNeeded[data, state, needs]; IF state.np.strokeWidth = 0 AND data.clientClipBoxOnly AND device.class.MaskBoxes#NIL THEN { d0: VEC _ ImagerTransformation.Transform[data.clientToDevice, vec0]; d1: VEC _ ImagerTransformation.Transform[data.clientToDevice, vec1]; Boxes: PROC [box: ImagerDevice.BoxProc] ~ { DoSolid[d0, d1, data.clientClipBox, box]; }; IF d0.x < bounds.smin THEN { IF d1.x < bounds.smin THEN RETURN; d0.y _ d0.y+(bounds.smin-d0.x)*(d1.y-d0.y)/(d1.x-d0.x); d0.x _ bounds.smin; } ELSE IF d0.x > bounds.smax THEN { IF d1.x > bounds.smax THEN RETURN; d0.y _ d0.y+(bounds.smax-d0.x)*(d1.y-d0.y)/(d1.x-d0.x); d0.x _ bounds.smax; }; IF d1.x < bounds.smin THEN { IF d0.x < bounds.smin THEN RETURN; d1.y _ d1.y+(bounds.smin-d1.x)*(d0.y-d1.y)/(d0.x-d1.x); d1.x _ bounds.smin; } ELSE IF d1.x > bounds.smax THEN { IF d0.x > bounds.smax THEN RETURN; d1.y _ d1.y+(bounds.smax-d1.x)*(d0.y-d1.y)/(d0.x-d1.x); d1.x _ bounds.smax; }; IF d0.y < bounds.fmin THEN { IF d1.y < bounds.fmin THEN RETURN; d0.x _ d0.x+(bounds.fmin-d0.y)*(d1.x-d0.x)/(d1.y-d0.y); d0.y _ bounds.fmin; } ELSE IF d0.y > bounds.fmax THEN { IF d1.y > bounds.fmax THEN RETURN; d0.x _ d0.x+(bounds.fmax-d0.y)*(d1.x-d0.x)/(d1.y-d0.y); d0.y _ bounds.fmax; }; IF d1.y < bounds.fmin THEN { IF d0.y < bounds.fmin THEN RETURN; d1.x _ d1.x+(bounds.fmin-d1.y)*(d0.x-d1.x)/(d0.y-d1.y); d1.y _ bounds.fmin; } ELSE IF d1.y > bounds.fmax THEN { IF d0.y > bounds.fmax THEN RETURN; d1.x _ d1.x+(bounds.fmax-d1.y)*(d0.x-d1.x)/(d0.y-d1.y); d1.y _ bounds.fmax; }; device.class.MaskBoxes[device: device, bounds: bounds, boxes: Boxes]; RETURN; }; }; ENDCASE => NULL; Imager.MaskVector[context, vec0, vec1]; }; DoSolid: PROC [d0, d1: VEC, clip: ImagerDevice.DeviceBox, box: ImagerDevice.BoxProc] ~ { s0: INTEGER _ Real.RoundI[d0.x]; f0: INTEGER _ Real.RoundI[d0.y]; s1: INTEGER ~ Real.RoundI[d1.x]; f1: INTEGER ~ Real.RoundI[d1.y]; dsPos: BOOL ~ s1 > s0; dfPos: BOOL ~ f1 > f0; ds: INTEGER _ IF dsPos THEN s1-s0 ELSE s0-s1; df: INTEGER _ IF dfPos THEN f1-f0 ELSE f0-f1; eincs: INTEGER ~ ds+ds; eincf: INTEGER ~ df+df; len: INTEGER _ 0; s, f, incf, incs: INTEGER; SELECT TRUE FROM ds = 0 => { f _ IF dfPos THEN f0 ELSE f1; box[[smin: s0, fmin: f, smax: s0+1, fmax: f+df]]; }; df = 0 => { s _ IF dsPos THEN s0 ELSE s1; box[[smin: s, fmin: f0, smax: s+ds, fmax: f0+1]]; }; ds > df => { e: INTEGER _ eincf-ds; IF dsPos THEN {s _ s0; f _ f0; incf _ IF dfPos THEN 1 ELSE -1} ELSE {s _ s1; f _ f1; incf _ IF dfPos THEN -1 ELSE 1}; WHILE ds >= 0 DO len _ len+1; IF e > 0 THEN { box[[smin: s, fmin: f, smax: s+len, fmax: f+1]]; f _ f+incf; e _ e-eincs; s _ s+len; len _ 0; }; e _ e+eincf; ds _ ds-1; ENDLOOP; IF len > 0 THEN box[[smin: s, fmin: f, smax: s+len, fmax: f+1]]; }; ENDCASE => { e: INTEGER _ eincs-df; IF dfPos THEN {f _ f0; s _ s0; incs _ IF dsPos THEN 1 ELSE -1} ELSE {f _ f1; s _ s1; incs _ IF dsPos THEN -1 ELSE 1}; WHILE df >= 0 DO len _ len+1; IF e > 0 THEN { box[[smin: s, fmin: f, smax: s+1, fmax: f+len]]; s _ s+incs; e _ e-eincf; f _ f+len; len _ 0; }; e _ e+eincs; df _ df-1; ENDLOOP; IF len > 0 THEN box[[smin: s, fmin: f, smax: s+1, fmax: f+len]]; }; }; Mark: PUBLIC PROC [context: Context, vec: VEC, markType: MarkType _ cross] ~ { Action: PROC ~ { Dot: PROC ~ {Imager.MaskRectangle[context, [vec.x-1, vec.y-1, 3, 3]]}; X: PROC ~ { Solid[context, [vec.x-4.0, vec.y-4.0], [vec.x+4.0, vec.y+4.0]]; Solid[context, [vec.x+4.0, vec.y-4.0], [vec.x-4.0, vec.y+4.0]]; }; Cross: PROC ~ { Solid[context, [vec.x-5.0, vec.y], [vec.x+5.0, vec.y]]; Solid[context, [vec.x, vec.y-5.0], [vec.x, vec.y+5.0]]; }; SELECT markType FROM dot => Dot[]; x => X[]; cross => Cross[]; asterisk => {Cross[]; X[];}; ENDCASE => NULL; }; Imager.DoSave[context, Action]; }; Square: PUBLIC PROC [context: Context, vec: VEC, size: REAL] ~ { size2: REAL _ size+size; Imager.MaskRectangle[context, [vec.x-size-1, vec.y-size, size2, size2]]; }; Arrow: PUBLIC PROC [context: Context, tail, head: VEC, vary: BOOL _ TRUE] ~ { v: VEC _ Vector2.Sub[head, tail]; mul: REAL _ IF v.x*v.x+v.y*v.y > 75.0*75.0 THEN -0.175*75.0/Vector2.Length[v] ELSE -0.175; vv: VEC _ Vector2.Mul[v, mul]; p0: VEC _ Vector2.Add[Vector2.Add[head, vv], [0.5*vv.y, -0.5*vv.x]]; p1: VEC _ Vector2.Add[p0, [-vv.y, vv.x]]; Solid[context, head, tail]; Solid[context, head, p0]; Solid[context, head, p1]; }; END. άDraw2dImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Bloomenthal, September 16, 1986 12:36:26 pm PDT Type Declarations General Procedures Line Drawing Procedures Miscellaneous Procedures Κ Š˜šœ™Jšœ Οmœ1™˜XJšœžœ˜ Jšœžœ˜ Jšœžœ˜ Jšœžœ˜ Jšœžœ ˜Jšœžœ ˜Jš œžœžœžœžœ˜-Jš œžœžœžœžœ˜-Jšœžœ ˜Jšœžœ ˜Jšœžœ˜Jšœžœ˜J˜šžœžœž˜šœ ˜ Jšœžœžœžœ˜Jšœ1˜1Jšœ˜—šœ ˜ Jšœžœžœžœ˜Jšœ1˜1Jšœ˜—šœ ˜ Jšœžœ ˜šžœ˜Jšžœžœžœžœ˜5Jšžœžœžœžœ˜7—šžœ ž˜J˜ šžœžœ˜Jšœ0˜0Jšœ ˜ Jšœ ˜ Jšœ ˜ J˜Jšœ˜—Jšœ ˜ J˜ Jšžœ˜—Jšžœ žœ1˜@J˜—šžœ˜ Jšœžœ ˜šžœ˜Jšžœžœžœžœ˜5Jšžœžœžœžœ˜7—šžœ ž˜J˜ šžœžœ˜Jšœ0˜0Jšœ ˜ Jšœ ˜ Jšœ ˜ Jšœ˜Jšœ˜—Jšœ ˜ J˜ Jšžœ˜—Jšžœ žœ1˜@J˜——Jšœ˜——š ™š£œžœžœžœ!˜Nš£œžœ˜Jš£œžœ=˜Fš£œžœ˜ Jšœ?˜?Jšœ?˜?J˜—š£œžœ˜Jšœ7˜7Jšœ7˜7J˜—šžœ ž˜J˜ J˜ J˜J˜Jšžœžœ˜—J˜—J˜J˜J˜—š £œžœžœžœžœ˜@Jšœžœ ˜JšœH˜HJ˜J˜—š £œžœžœ žœžœžœ˜MJšœžœ˜!Jš œžœžœžœžœ˜ZJšœžœ˜Jšœžœ=˜DJšœžœ"˜)Jšœ˜Jšœ˜Jšœ˜J˜—J˜—šžœ˜J™——…—"8.ž