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 VEC: TYPE ~ Vector2.VEC; MarkType: TYPE ~ Draw2d.MarkType; DrawType: TYPE ~ Draw2d.DrawType; InitFont: PUBLIC PROC [context: Imager.Context] ~ { font: ImagerFont.Font _ ImagerFont.Scale[ImagerFont.Find["xerox/pressfonts/helvetica-mrr"], 12.0]; Imager.SetFont[context, font]; }; Label: PUBLIC PROC [context: Imager.Context, p: VEC, rope: Rope.ROPE] ~ { Imager.SetXY[context, p]; Imager.ShowRope[context, rope]; }; DoWithBuffer: PUBLIC PROC [context: Imager.Context, action: PROC, w, h: INTEGER] ~ { InitFont[context]; Imager.SetStrokeWidth[context, 0.0]; ImagerOps.DoWithBuffer[context, action, 0, 0, w, h]; }; DoNoBuffer: PUBLIC PROC [context: Imager.Context, action: PROC, w, h: INTEGER] ~ { InitFont[context]; action[]; }; ShowList: PUBLIC PROC [list: LIST OF VEC, context: Imager.Context] ~ { p0: VEC; IF list # NIL THEN p0 _ list.first ELSE RETURN; FOR l: LIST OF VEC _ list.rest, l.rest WHILE l # NIL DO Solid[context, p0, l.first]; p0 _ l.first; ENDLOOP; }; ClearContext: PUBLIC PROC [context: Imager.Context, x, y, w, h: INTEGER] ~ { Imager.SetColor[context, Imager.white]; Imager.MaskRectangleI[context, 0, 0, w, h]; Imager.SetColor[context, Imager.black]; }; Mark: PUBLIC PROC [context: Imager.Context, p: VEC, type: MarkType _ cross] ~ { Action: PROC ~ { Dot: PROC ~ {Imager.MaskRectangle[context, [p.x-1, p.y-1, 3, 3]]}; X: PROC ~ { Solid[context, [p.x-4.0, p.y-4.0], [p.x+4.0, p.y+4.0]]; Solid[context, [p.x+4.0, p.y-4.0], [p.x-4.0, p.y+4.0]]; }; Cross: PROC ~ { Solid[context, [p.x-5.0, p.y], [p.x+5.0, p.y]]; Solid[context, [p.x, p.y-5.0], [p.x, p.y+5.0]]; }; SELECT type FROM dot => Dot[]; x => X[]; cross => Cross[]; asterisk => {Cross[]; X[];}; ENDCASE => NULL; }; Imager.DoSave[context, Action]; }; Draw: PUBLIC PROC [context: Imager.Context, p0, p1: VEC, type: DrawType _ solid] ~ { SELECT type FROM solid => Solid[context, p0, p1]; dot => Dot[context, p0, p1]; dash => Dash[context, p0, p1]; ENDCASE => NULL; }; Data: TYPE ~ ImagerRasterPrivate.Data; State: TYPE ~ ImagerState.State; StateRep: PUBLIC TYPE ~ ImagerState.StateRep; -- export to Imager.StateRep Solid: PUBLIC PROC [context: Imager.Context, p0, p1: 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.smax _ MAX[bounds.smin, bounds.smax-1]; -- simplify clipping bounds.fmax _ MAX[bounds.fmin, 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, p0]; d1: VEC _ ImagerTransformation.Transform[data.clientToDevice, p1]; 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, p0, p1]; }; 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; IF ds = 0 THEN { f _ IF dfPos THEN f0 ELSE f1; box[[smin: s0, fmin: f, smax: s0+1, fmax: f+df]]; RETURN; }; IF df = 0 THEN { s _ IF dsPos THEN s0 ELSE s1; box[[smin: s, fmin: f0, smax: s+ds, fmax: f0+1]]; RETURN; }; IF ds > df THEN { 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]]; } ELSE { 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]]; }; }; Dot: PUBLIC PROC [context: Imager.Context, p0, p1: VEC] ~ { stepInc: VEC; delta: VEC _ [p1.x-p0.x, p1.y-p0.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, [p0.x, p0.y, 1, 1]]; p0 _ [p0.x+stepInc.x, p0.y+stepInc.y]; ENDLOOP; }; Dash: PUBLIC PROC [context: Imager.Context, p0, p1: VEC] ~ { drawInc, stepInc: VEC; delta: VEC _ [p1.x-p0.x, p1.y-p0.y]; nSteps: INTEGER _ Real.RoundI[0.10*Real.SqRt[delta.x*delta.x+delta.y*delta.y]]; IF nSteps < 1 THEN RETURN; stepInc _ [delta.x/nSteps, delta.y/nSteps]; drawInc _ [0.5*stepInc.x, 0.5*stepInc.y]; FOR n: NAT IN[0..nSteps) DO Solid[context, p0, [p0.x+drawInc.x, p0.y+drawInc.y]]; p0 _ [p0.x+stepInc.x, p0.y+stepInc.y]; ENDLOOP; }; Arrow: PUBLIC PROC [context: Imager.Context, head, tail: VEC] ~ { v: VEC _ Vector2.Mul[Vector2.Sub[head, tail], -0.175]; p0: VEC _ Vector2.Add[Vector2.Add[head, v], [0.5*v.y, -0.5*v.x]]; p1: VEC _ Vector2.Add[p0, [-v.y, v.x]]; Solid[context, head, tail]; Solid[context, head, p0]; Solid[context, head, p1]; }; Square: PUBLIC PROC [context: Imager.Context, x, y, size: REAL] ~ { Imager.MaskRectangle[context, [x-size-1, y-size, 2*size, 2*size]]; }; debugStream: IO.STREAM _ NIL; Debug: PUBLIC PROC [s: IO.STREAM] ~ {debugStream _ s}; END. Draw2dImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Bloomenthal, June 9, 1986 5:23:16 pm PDT once: BOOL _ FALSE; pixelBuffer: Pixels.PixelBuffer; IF NOT once THEN { once _ TRUE; [pixelBuffer, ] _ Pixels.GetFromImagerContext[context, FALSE, FALSE]; Imager.PutProp[context, $PixelBuffer, NEW[Pixels.PixelBuffer _ pixelBuffer]]; }; IF invert THEN Imager.SetColor[context, ImagerBackdoor.invert]; Solid: PUBLIC PROC [context: Imager.Context, p0, p1: VEC] ~ { -- Crow's method pixelValue: Pixels.SampleSet _ Pixels.GetSampleSet[1]; -- pixelBuffer _ NARROW[Imager.GetProp[context, $PixelBuffer], REF Pixels.PixelBuffer]^; pixelValue[0] _ 255; ScanConvert.PutLine[pixelBuffer, [Real.FixC[p0.x], Real.FixC[p0.y]], [Real.FixC[p1.x], Real.FixC[p1.y]], pixelValue]; }; Ê R˜šœ™Jšœ Ïmœ1™˜XJšœžœ˜ Jšœžœ˜ Jšœžœ˜ Jšœžœ˜ Jšœžœ ˜Jšœžœ ˜Jš œžœžœžœžœ˜-Jš œžœžœžœžœ˜-Jšœžœ ˜Jšœžœ ˜Jšœžœ˜Jšœžœ˜J˜šžœžœ˜Jšœžœžœžœ˜Jšœ1˜1Jšž˜Jšœ˜J˜—šžœžœ˜Jšœžœžœžœ˜Jšœ1˜1Jšž˜Jšœ˜—J˜šžœ˜ šžœ˜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šœ˜J˜—š œžœžœ#žœ˜;Jšœ žœ˜ Jšœžœ˜$Jšœžœ?˜NJšžœ žœžœ˜J˜+šžœžœžœ ž˜J˜2J˜&Jšžœ˜—J˜J˜—š œžœžœ#žœ˜