-- CGPoolImpl.mesa
-- Last changed by Doug Wyatt, September 20, 1982 4:06 pm

DIRECTORY
CGClipper USING [Assign, Copy],
CGContext USING [Level, PoolData, PoolDataRep, PoolNode, PoolNodeRep, Ref],
CGMatrix USING [Assign, Copy],
CGPrivate USING [Context],
CGStorage USING [pZone, qZone],
GraphicsBasic USING [black, Mark, nullMark];

CGPoolImpl: CEDAR PROGRAM
IMPORTS CGClipper, CGMatrix, CGStorage
EXPORTS CGContext, CGPrivate = { OPEN CGContext;

Mark: TYPE = GraphicsBasic.Mark;
nullMark: Mark = GraphicsBasic.nullMark;

Context: TYPE = CGPrivate.Context;

dataZone: ZONE = CGStorage.pZone;
nodeZone: ZONE = CGStorage.qZone;

nil: Level = LAST[Level];

nullNode: PoolNodeRep = [matrixLevel: nil, clipperLevel: nil, fillLevel: nil, cpLevel: nil,
yUp: FALSE, fill: [mode: opaque, fat: FALSE, color: GraphicsBasic.black],
matrix: NIL, clipper: NIL, cp: [0,0]];

Save: PUBLIC PROC[self: Context] RETURNS[Mark] = {
ctx: Ref ← NARROW[self.data];
oldlev: Level ← ctx.level; -- current level
newlev: Level ← oldlev + 1;
data: PoolData ← ctx.pooldata;
space: NATIF data=NIL THEN 0 ELSE data.space;
node: PoolNode ← NIL;
IF newlev=nil THEN ERROR;
IF space<newlev THEN {
old: PoolData ← data;
size: NATIF space=0 THEN 2 ELSE 2*space;
ctx.pooldata ← data ← dataZone.NEW[PoolDataRep[size]];
FOR i: NAT IN[0..space) DO data[i] ← old[i] ENDLOOP;
};
node ← data[oldlev];
IF node=NIL THEN data[oldlev] ← node ← nodeZone.NEW[PoolNodeRep ← nullNode];
ctx.poolnode ← node;
ctx.level ← newlev;
RETURN[[oldlev]];
};

Restore: PUBLIC PROC[self: Context, mark: Mark] = {
ctx: Ref ← NARROW[self.data];
lev: Level ← ctx.level;
oldlev: Level ← 0;
data: PoolData ← ctx.pooldata;
IF mark=nullMark THEN { IF lev>0 THEN oldlev ← lev - 1 ELSE RETURN }
ELSE { [oldlev] ← mark; IF oldlev>=lev THEN RETURN };
WHILE lev>oldlev DO
node: PoolNode ← data[lev ← lev - 1];
IF node.matrixLevel#nil THEN {
IF node.matrixLevel<=lev THEN {
CGMatrix.Assign[ctx.matrix, node.matrix];
ctx.yUp ← node.yUp;
ctx.matrixLevel ← node.matrixLevel;
};
node.matrixLevel ← nil;
};
IF node.clipperLevel#nil THEN {
IF node.clipperLevel<=lev THEN {
CGClipper.Assign[ctx.clipper, node.clipper];
ctx.clipperLevel ← node.clipperLevel;
};
node.clipperLevel ← nil;
};
IF node.fillLevel#nil THEN {
IF node.fillLevel<=lev THEN {
ctx.fill ← node.fill;
ctx.fillLevel ← node.fillLevel;
};
node.fillLevel ← nil;
};
ENDLOOP;
ctx.poolnode ← IF lev>0 THEN data[lev-1] ELSE NIL;
ctx.level ← lev;
};

SaveClipper: PUBLIC PROC[self: Ref] = {
node: PoolNode ← self.poolnode;
IF node.clipper=NIL THEN node.clipper ← CGClipper.Copy[self.clipper]
ELSE CGClipper.Assign[node.clipper,self.clipper];
node.clipperLevel ← self.clipperLevel;
self.clipperLevel ← self.level;
};

SaveMatrix: PUBLIC PROC[self: Ref] = {
node: PoolNode ← self.poolnode;
IF node.matrix=NIL THEN node.matrix ← CGMatrix.Copy[self.matrix]
ELSE CGMatrix.Assign[node.matrix,self.matrix];
node.yUp ← self.yUp;
node.yUp ← self.yUp;
node.matrixLevel ← self.matrixLevel;
self.matrixLevel ← self.level;
};

SaveFill: PUBLIC PROC[self: Ref] = {
node: PoolNode ← self.poolnode;
node.fill ← self.fill;
node.fillLevel ← self.fillLevel;
self.fillLevel ← self.level;
};

SaveCP: PUBLIC PROC[self: Ref] = {
node: PoolNode ← self.poolnode;
node.cp ← self.cp;
node.cpLevel ← self.cpLevel;
self.cpLevel ← self.level;
};

ResetPool: PUBLIC PROC[self: Ref] = {
self.matrixLevel ← 0;
self.clipperLevel ← 0;
self.fillLevel ← 0;
self.cpLevel ← 0;
self.poolnode ← NIL;
self.level ← 0;
};

}.