-- DrawSplineImpl.mesa
-- Last changed by Doug Wyatt, September 9, 1980 2:46 PM

DIRECTORY
Graphics,
Cubic,
DrawSpline,
SplineDefs,
SystemDefs;

DrawSplineImpl: PROGRAM
IMPORTS Graphics,SplineDefs,SystemDefs
EXPORTS DrawSpline = {
OPEN Graphics,Cubic;

KnotHead: TYPE = POINTER TO Knot;
Knot: TYPE = RECORD[x,y: REAL,link: POINTER TO Knot];
KnotArray: TYPE = DESCRIPTOR FOR ARRAY OF SplineDefs.FPCoords;
knotchain: KnotHead←NIL;
knotcnt: INTEGER←0;
Alloc: PROCEDURE[CARDINAL] RETURNS[POINTER] ← SystemDefs.AllocateHeapNode;
Free: PROCEDURE[POINTER] ← SystemDefs.FreeHeapNode;

StartSpline: PUBLIC PROCEDURE = {
IF knotchain # NIL THEN { knotcnt←0; FreeChain[] };
};

EnterKnot: PUBLIC PROCEDURE[x,y: REAL] = {
k: POINTER TO Knot←Alloc[SIZE[Knot]];
k.link←knotchain;
k.x←x; k.y←y;
knotchain←k;
knotcnt←knotcnt+1;
};

DrawSpline: PUBLIC PROCEDURE[dc: DisplayContext] = {
i: INTEGER;
tknot: POINTER TO Knot;
knots: KnotArray;
i←knotcnt;
knots←DESCRIPTOR[Alloc[i*SIZE[SplineDefs.FPCoords]],i];
UNTIL i = 0 DO
i←i-1;
knots[i][2]←knotchain.y;
knots[i][1]←knotchain.x;
tknot←knotchain;
knotchain←knotchain.link;
Free[tknot];
ENDLOOP;
knotcnt←0;
DrawSpln[dc,knots,naturalAL];
Free[BASE[knots]];
};

DrawCyclicSpline: PUBLIC PROCEDURE[dc: DisplayContext] = {
i,j: INTEGER;
tknot: POINTER TO Knot;
knots: KnotArray;
i←knotcnt+1; -- get number of knots.
j←i-1; -- get last position.
knots←DESCRIPTOR[Alloc[i*SIZE[SplineDefs.FPCoords]],i];
UNTIL i = 1 DO
i←i-1;
knots[i][2]←knotchain.y;
knots[i][1]←knotchain.x;
tknot←knotchain;
knotchain←knotchain.link;
Free[tknot];
ENDLOOP;
knots[0]←knots[j]; -- close the curve
knotcnt←0;
DrawSpln[dc,knots,cyclicAL];
Free[BASE[knots]];
};

DrawBlob: PUBLIC PROCEDURE[dc: DisplayContext] = {
i,j: INTEGER;
tknot: POINTER TO Knot;
knots: KnotArray;
StartAreaPath[dc];
i←knotcnt+1; -- get number of knots.
j←i-1; -- get last position.
knots←DESCRIPTOR[Alloc[i*SIZE[SplineDefs.FPCoords]],i];
UNTIL i = 1 DO
i←i-1;
knots[i][2]←knotchain.y;
knots[i][1]←knotchain.x;
tknot←knotchain;
knotchain←knotchain.link;
Free[tknot];
ENDLOOP;
knots[0]←knots[j]; -- close the curve
knotcnt←0;
EnterSpline[dc,knots,cyclicAL];
Free[BASE[knots]];
DrawArea[dc];
};

FreeChain: PROCEDURE = {
UNTIL knotchain = NIL DO
tknot: POINTER TO Knot←knotchain;
knotchain←knotchain.link;
Free[tknot];
ENDLOOP;
};

DrawSpln: PROCEDURE[dc: DisplayContext,
knots: KnotArray, type: SplineDefs.SplineType] = {
DrawC: PROCEDURE[c: POINTER TO Coeffs] = { DrawCubic[dc,c] };
GenerateSpline[knots,type,DrawC];
};

EnterSpline: PROCEDURE[dc: DisplayContext,
knots: KnotArray, type: SplineDefs.SplineType] = {
EnterC: PROCEDURE[c: POINTER TO Coeffs] = { EnterCubic[dc,c] };
GenerateSpline[knots,type,EnterC];
};

GenerateSpline: PROCEDURE[knots: KnotArray, type: SplineDefs.SplineType,
Proc: PROCEDURE[POINTER TO Coeffs]] = {
allcoeffs: DESCRIPTOR FOR ARRAY OF SplineDefs.Coeffs;
cf: Coeffs;
i: CARDINAL;
allcoeffs ← SplineDefs.MakeSpline[knots,type];
FOR i IN[0..LENGTH[allcoeffs]) DO
OPEN SplineDefs;
cf←[[allcoeffs[i].t0[X],allcoeffs[i].t0[Y]],
[allcoeffs[i].t1[X],allcoeffs[i].t1[Y]],
[allcoeffs[i].t2[X],allcoeffs[i].t2[Y]],
[allcoeffs[i].t3[X],allcoeffs[i].t3[Y]]];
Proc[@cf];
ENDLOOP;
SplineDefs.FreeCoeffs[allcoeffs];
};

SplineDefs.InitSplines[alloc: Alloc, free: Free];

}.