CDCurvesImpl.mesa
Copyright © 1985, 1986 by Xerox Corporation. All rights reserved.
by Christian Jacobi, March 30, 1985 12:19:40 pm PST
Last Edited by: Jacobi June 19, 1986 12:52:31 pm PDT
DIRECTORY
CDInstances,
CDCurves,
CDTexts,
CD,
CDBasics,
CDLayers,
CDIO,
CDOps,
Imager,
ImagerPath,
Rope,
TokenIO,
Vector2;
CDCurvesImpl: CEDAR PROGRAM
IMPORTS CD, CDBasics, CDLayers, CDIO, CDOps, Imager, ImagerPath, Rope, TokenIO
EXPORTS CDCurves =
BEGIN
CurvePtr: TYPE = CDCurves.CurvePtr;
CurveRec: TYPE = CDCurves.CurveRec;
LoP: TYPE = LIST OF CD.Position;
splineClass: PUBLIC CD.ObjectClass ← CD.RegisterObjectClass[$Spline0, [
drawMe: DrawSpline,
quickDrawMe: DrawSpline,
hitInside: HitInsideCurve,
describe: Describe,
internalRead: ReadCurve,
internalWrite: WriteCurve,
description: "spline"
]];
lineClass: PUBLIC CD.ObjectClass ← CD.RegisterObjectClass[$Line0, [
drawMe: DrawSpline,
quickDrawMe: DrawSpline,
hitInside: HitInsideCurve,
describe: Describe,
internalRead: ReadCurve,
internalWrite: WriteCurve,
description: "line"
]];
polygonClass: PUBLIC CD.ObjectClass ← CD.RegisterObjectClass[$Polygon0, [
drawMe: DrawFilledCurve,
quickDrawMe: DrawFilledCurve,
hitInside: HitInsideCurve,
describe: Describe,
internalRead: ReadCurve,
internalWrite: WriteCurve,
description: "polygon"
]];
filledCurveClass: PUBLIC CD.ObjectClass ← CD.RegisterObjectClass[$FilledCurve0, [
drawMe: DrawFilledCurve,
quickDrawMe: DrawFilledCurve,
hitInside: HitInsideCurve,
describe: Describe,
internalRead: ReadCurve,
internalWrite: WriteCurve,
description: "filled curve"
]];
CopyList: PROC [points: LoP, w: CD.Number𡤀] RETURNS [copy: LoP←NIL, r: CD.Rect, leng: INT𡤀] =
BEGIN
min: CD.Position ← CDBasics.highposition;
max: CD.Position ← CDBasics.minposition;
FOR class: LoP ← points, class.rest WHILE class#NIL DO
leng ← leng+1;
min ← CDBasics.MinPoint[min, class.first];
max ← CDBasics.MaxPoint[max, class.first];
ENDLOOP;
min ← [min.x-w, min.y-w];
max ← [max.x+w, max.y+w];
FOR class: LoP ← points, class.rest WHILE class#NIL DO
copy ← CONS[CDBasics.SubPoints[class.first, min], copy];
ENDLOOP;
r ← CDBasics.ToRect[min, max];
IF (r.x2-r.x1)>LAST[NAT] OR (r.y2-r.y1)>LAST[NAT] THEN CD.Error[callingError, "size out of range"];
END;
CreatePolygon: PUBLIC PROC [points: LIST OF CD.Position, layer: CD.Layer] RETURNS [ob: CD.Object←NIL, offset: CD.Position←[0, 0]] =
BEGIN
r: CD.Rect; leng: INT;
cp: CurvePtr = NEW[CurveRec];
[cp.points, r, leng] ← CopyList[points, 0];
IF leng<3 THEN RETURN;
cp.path ← ImagerPath.MoveTo[[cp.points.first.x, cp.points.first.y]];
FOR class: LoP ← cp.points.rest, class.rest WHILE class#NIL DO
cp.path ← ImagerPath.LineTo[cp.path, [class.first.x, class.first.y]];
ENDLOOP;
ob ← NEW[CD.ObjectRep←[
size: CDBasics.MaxPoint[[1, 1], CDBasics.SizeOfRect[r]],
layer: CDLayers.AbstractToPaint[layer],
class: polygonClass,
specificRef: cp
]];
offset ← CDBasics.BaseOfRect[r];
END;
CreateFilledCurve: PUBLIC PROC [points: LIST OF CD.Position, layer: CD.Layer] RETURNS [ob: CD.Object←NIL, offset: CD.Position←[0, 0]] =
BEGIN
r: CD.Rect; leng: INT; pl: LoP;
cp: CurvePtr = NEW[CurveRec];
[cp.points, r, leng] ← CopyList[points, 0];
IF leng<4 THEN RETURN;
cp.path ← ImagerPath.MoveTo[[cp.points.first.x, cp.points.first.y]];
pl ← cp.points.rest;
WHILE pl # NIL DO
p1, p2, p3: Vector2.VEC;
p1 ← [pl.first.x, pl.first.y]; IF pl.rest#NIL THEN pl ← pl.rest;
p2 ← [pl.first.x, pl.first.y]; IF pl.rest#NIL THEN pl ← pl.rest;
p3 ← [pl.first.x, pl.first.y]; pl ← pl.rest;
cp.path ← ImagerPath.CurveTo[cp.path, p1, p2, p3];
ENDLOOP;
ob ← NEW[CD.ObjectRep←[
size: CDBasics.MaxPoint[[1, 1], CDBasics.SizeOfRect[r]],
layer: CDLayers.AbstractToPaint[layer],
class: filledCurveClass,
specificRef: cp
]];
offset ← CDBasics.BaseOfRect[r];
END;
CreateSpline: PUBLIC PROC [points: LIST OF CD.Position, w: CD.Number, layer: CD.Layer] RETURNS [ob: CD.Object←NIL, offset: CD.Position←[0, 0]] =
BEGIN
r: CD.Rect; leng: INT; pl: LoP;
cp: CurvePtr = NEW[CurveRec];
w2: INTMAX[1, (w+1)/2];
[cp.points, r, leng] ← CopyList[points, w2];
IF leng<1 THEN RETURN;
cp.w ← w2*2;
cp.path ← ImagerPath.MoveTo[[cp.points.first.x, cp.points.first.y]];
pl ← cp.points.rest;
WHILE pl # NIL DO
p1, p2, p3: Vector2.VEC;
p1 ← [pl.first.x, pl.first.y]; IF pl.rest#NIL THEN pl ← pl.rest;
p2 ← [pl.first.x, pl.first.y]; IF pl.rest#NIL THEN pl ← pl.rest;
p3 ← [pl.first.x, pl.first.y]; pl ← pl.rest;
cp.path ← ImagerPath.CurveTo[cp.path, p1, p2, p3];
ENDLOOP;
ob ← NEW[CD.ObjectRep←[
size: CDBasics.MaxPoint[[cp.w, cp.w], CDBasics.SizeOfRect[r]],
layer: CDLayers.AbstractToPaint[layer],
class: splineClass,
specificRef: cp
]];
offset ← CDBasics.BaseOfRect[r];
END;
CreateLine: PUBLIC PROC [points: LIST OF CD.Position, w: CD.Number, layer: CD.Layer] RETURNS [ob: CD.Object←NIL, offset: CD.Position←[0, 0]] =
BEGIN
r: CD.Rect; leng: INT; pl: LoP;
cp: CurvePtr = NEW[CurveRec];
w2: INTMAX[1, (w+1)/2];
[cp.points, r, leng] ← CopyList[points, w2];
IF leng<1 THEN RETURN;
cp.w ← w2*2;
cp.path ← ImagerPath.MoveTo[[cp.points.first.x, cp.points.first.y]];
pl ← cp.points.rest;
WHILE pl # NIL DO
p1: Vector2.VEC ← [pl.first.x, pl.first.y];
pl ← pl.rest;
cp.path ← ImagerPath.LineTo[cp.path, p1];
ENDLOOP;
ob ← NEW[CD.ObjectRep←[
size: CDBasics.MaxPoint[[cp.w, cp.w], CDBasics.SizeOfRect[r]],
layer: CDLayers.AbstractToPaint[layer],
class: lineClass,
specificRef: cp
]];
offset ← CDBasics.BaseOfRect[r];
END;
HitInsideCurve: PROC [ob: CD.Object, hitRect: CD.Rect] RETURNS [yes: BOOL] = {
RETURN [ CDBasics.Intersect[ob.class.interestRect[ob], hitRect] ];
};
DrawFilledCurve: PROC [inst: CD.Instance, pos: CD.Position, orient: CD.Orientation, pr: CD.DrawRef] =
BEGIN
FilledCurveInContext: PROC [context: Imager.Context, ob: CD.Object, layer: CD.Layer] = {
Imager.ClipRectangleI[context, 0, 0, ob.size.x, ob.size.y];
Imager.MaskFillTrajectory[context, NARROW[ob.specificRef, CurvePtr].path, TRUE];
};
pr.drawContext[pr, FilledCurveInContext, inst.ob, pos, orient, inst.ob.layer]
END;
DrawSpline: PROC [inst: CD.Instance, pos: CD.Position, orient: CD.Orientation, pr: CD.DrawRef] =
BEGIN
SplineInContext: PROC [context: Imager.Context, ob: CD.Object, layer: CD.Layer] = {
Imager.ClipRectangleI[context, 0, 0, ob.size.x, ob.size.y];
Imager.SetStrokeWidth[context: context, strokeWidth: NARROW[ob.specificRef, CurvePtr].w];
Imager.SetStrokeEnd[context: context, strokeEnd: square];
Imager.MaskStrokeTrajectory[context, NARROW[ob.specificRef, CurvePtr].path, FALSE];
};
pr.drawContext[pr, SplineInContext, inst.ob, pos, orient, inst.ob.layer]
END;
Describe: PROC[me: CD.Object] RETURNS [Rope.ROPE] = {
RETURN [Rope.Cat[me.class.description, " ", CDOps.LayerName[me.layer]]]
};
WriteCurve: CD.InternalWriteProc -- PROC [me: Object] -- =
BEGIN
Length: PROC [points: LIST OF CD.Position] RETURNS [n: NAT ← 0] = {
FOR l: LIST OF CD.Position ← points, l.rest WHILE l#NIL DO n ← n+1 ENDLOOP
};
cp: CurvePtr = NARROW[me.specificRef];
l: NAT ← Length[cp.points];
CDIO.WriteLayer[me.layer];
SELECT me.class FROM
lineClass => {TokenIO.WriteInt[0]; TokenIO.WriteInt[cp.w]};
polygonClass => TokenIO.WriteInt[1];
splineClass => {TokenIO.WriteInt[2]; TokenIO.WriteInt[cp.w]};
filledCurveClass => TokenIO.WriteInt[3];
ENDCASE => ERROR;
TokenIO.WriteInt[l];
FOR pl: LoP ← cp.points, pl.rest WHILE pl#NIL DO
CDIO.WritePos[pl.first];
ENDLOOP;
END;
ReadCurve: CD.InternalReadProc --PROC [] RETURNS [Object]-- =
BEGIN
ob: CD.Object ← NIL; kind, w, leng: INT; layer: CD.Layer;
points: LoP ← NIL;
layer ← CDIO.ReadLayer[];
SELECT kind TokenIO.ReadInt[] FROM
0, 2 => w ← TokenIO.ReadInt[];
ENDCASE => NULL;
leng ← TokenIO.ReadInt[];
FOR i: INT IN [1..leng] DO
points ← CONS[CDIO.ReadPos[], points];
ENDLOOP;
SELECT kind FROM
0 => ob ← CreateLine[points, w, layer].ob;
1 => ob ← CreatePolygon[points, layer].ob;
2 => ob ← CreateSpline[points, w, layer].ob;
3 => ob ← CreateFilledCurve[points, layer].ob;
ENDCASE;
RETURN [ob]
END;
END.