CStitching.mesa
Copyright © 1983, 1987 by Xerox Corporation. All rights reserved.
Written by Mark Shand, September 12, 1983 11:40 pm
Last Edited by: McCreight, November 28, 1983 5:53 pm
Last Edited by: Christian Jacobi, February 24, 1984 12:14 pm
Last Edited by: Mark Shand, June 1, 1984 2:20:32 pm PDT
Re written by: Christian Jacobi, January 18, 1986 11:33:07 am PST
Last edited by: Christian Jacobi, March 20, 1987 4:48:36 pm PST
DIRECTORY
D2Basic USING [Number, Vector, Rect];
CStitching: CEDAR DEFINITIONS =
-- Types.
Number: TYPE = D2Basic.Number;
Pos: TYPE = D2Basic.Vector;
Rect:
TYPE = D2Basic.Rect;
-- WARNING: Conventions are different from ChipNDale:
-- In CornerStitching, lower left border is inclusive; upper right border is exclusive.
all: Rect = [Number.
FIRST, Number.
FIRST, Number.
LAST, Number.
LAST];
Tile: TYPE = REF --READONLY-- TileRec;
TileRec:
TYPE =
RECORD [
--all fields readonly
eN, sW: Tile ← NIL,
nE, wS: LONG POINTER TO TileRec ← NIL,
pos: Pos,
value: REF ← NIL -- NIL for space tiles
];
-- Tiles are recollected whenever they are not part of a tesselation! dont keep on to tiles.
-- Corner stitching with ref's is too circular for the current Cedar safestorage,
-- therefore two stitches are made pointers (idea of Mark Brown).
-- eN... eastern-most neighbour to the North; capitalization enlightens asymetry)
-- pos: lower left corner
Tesselation: TYPE = REF TesselationRec;
TesselationRec:
TYPE =
RECORD [
--do never use NEW
state: State,--readonly, not all implementations use this field
immute: PRIVATE BOOL ← FALSE,
current, southEast: PRIVATE Tile ←, --readonly
tileCount: PRIVATE INT ← 1, --readonly
stopFlag: REF BOOL,
data: REF
];
-- Use only NewTesselation to create Tesselations (Finalization!)
-- data: reserved for clients
-- stopFlag: reserved for clients
State:
TYPE =
RECORD [
--readonly
r: Rect𡤊ll,
yf: Number←LAST[Number], --fathers limitting y
ys: Number←LAST[Number] --lowest sons lowest y
];
-- All procedures sharing a Tesselation must be synchrounized by caller;
-- CStitching itself does not monitor clients (even if using the same Tesselation).
-- Synchrounization errors can propagate to unrelated Tesselation!
-- Worlds.
NewTesselation:
PROC [data:
REF ←
NIL, stopFlag:
REF
BOOL ←
NIL]
RETURNS [Tesselation];
-- Creates a new Tesselation
ResetTesselation:
PROC [plane: Tesselation, stopFlag:
REF
BOOL ←
NIL];
-- Returns the tile memory; Tesselation is ready for fresh usage
TrustedDisposeTesselation:
PROC [plane: Tesselation];
-- Returns the tile memory and the Tesselation
-- Caller absolutely guarantees there exists no pointer to plane anymore.
DumpCache:
PROC;
-- Returns cached memory used globaly for Tiles of all Tesselations
-- Modifying.
ChangeRect:
PROC [plane: Tesselation, rect: Rect, new:
REF ←
NIL];
-- Change the rect having new as tile value
-- Beware: rect must lie completely in the changeable area (even for identity changes)
ChangeTile:
PROC [plane: Tesselation, tile: Tile, new:
REF ←
NIL];
-- Change a tile
-- Beware: tile must lie completely in the changeable area (even for identity changes)
RectProc: TYPE = PROC [plane: Tesselation, rect: Rect, oldValue: REF, data: REF];
ChangeEnumerateArea:
PROC [plane: Tesselation, rect: Rect, eachRect: RectProc, data:
REF ←
NIL, skip:
REF ←];
-- For each rectangle in rect (with value # skip) call "eachRect"; (rect must be changeable)
-- eachRect is must not change any point outside its rect area.
-- Outside eachRect's rect the maximal size properties dont hold while the enumeration.
-- Enumerations.
FindTile:
PROC [plane: Tesselation, pos: Pos]
RETURNS [Tile];
-- Finds the tile which contains the point at pos
TileProc: TYPE = PROC [tile: Tile, data: REF];
EnumerateArea:
PROC [plane: Tesselation, rect: Rect, eachTile: TileProc, data:
REF ←
NIL, skip:
REF ←
NIL];
-- Enumerates all the tiles covering points of rect in plane.
-- While the enumeration the plane must not be changed
-- data: passed through to the eachTile procedure.
-- skip: tiles with value skip will be ignored and not enumerated.
-- To get every tile, set skip to some value not existing value (e.g. NEW[INT]).
-- rect must must be changeable or the maximal size properties dont hold
-- In EnumerateArea the order of enumeration is well defined. A tile appears in the enumeration immediately after the last of its children. Where tileA is defined to be a child of tileB iff its sW stitch points to tileB. Children are ordered such that the southernmost is the last. For tiles touching the western and southern borders these rules do not apply, these tiles are parent-less. Such tiles appear at some point after all the parent-less tiles touching touching a given parent-less tile's northern and western borders have been enumerated.
Region: TYPE = RECORD [rect: Rect, value: REF]; -- value NIL for space tiles
ListArea:
PROC [plane: Tesselation, rect: Rect, skip:
REF ←
NIL]
RETURNS [
LIST
OF
REF Region];
-- Returns a list of regions describing the area rect in the tesselation plane.
-- Regions with tile value skip are not returned.
-- rect must must be changeable or the maximal size properties dont hold
EnumerateNeighborhood:
PROC [plane: Tesselation, tile: Tile, eachTile: TileProc, data:
REF ←
NIL, skip:
REF ←
NIL];
-- Enumerates all tiles touching the given tile.
-- [The current implementation starts the enumeration in the SW corner and
-- continues clockwise]
-- The plane may not be modified during the enumeration.
-- The data variable is passed through to eachTile.
-- Tiles with value skip are skipped.
-- Stepping from Tile to Tile.
-- Coordinates increase from south to north, and west to east. All tile worlds are
-- bordered by tiles at infinity so bounded searches wil never find NIL tiles.
-- never need worry about tile = NIL.
-- The tiles at infinity are not stitched to tiles in the Tesselation, rather they are
-- stitched to each other in the manner of the bevelled edges of a picture frame.
-- The meanings of the stepping routines are as follows ...
-- EN — eastern most tile to the north
-- NE — northern most tile to the east
-- WS — western most tile to the south
-- SW — southern most tile to the west
EN:
PROC [tile: Tile]
RETURNS [Tile] =
INLINE {
RETURN [tile.eN]
};
NE:
PROC [tile: Tile]
RETURNS [Tile] =
INLINE {
TRUSTED { RETURN [LOOPHOLE[tile.nE]] }
};
WS:
PROC [tile: Tile]
RETURNS [Tile] =
INLINE {
TRUSTED { RETURN [LOOPHOLE[tile.wS]] }
};
SW:
PROC [tile: Tile]
RETURNS [Tile] =
INLINE {
RETURN [tile.sW]
};
-- Enquiries
Area:
PROC [t: Tile]
RETURNS [Rect] =
TRUSTED
INLINE {
--rect of tile; (upper and right border exclusive)
RETURN [[x1: t.pos.x, y1: t.pos.y, x2: t.nE.pos.x, y2: t.eN.pos.y]]
};
NEdge: PROC [t: Tile] RETURNS [Number] = INLINE {RETURN [t.eN.pos.y]};
EEdge: PROC [t: Tile] RETURNS [Number] = TRUSTED INLINE {RETURN [t.nE.pos.x]};
SEdge: PROC [t: Tile] RETURNS [Number] = INLINE {RETURN [t.pos.y]};
WEdge: PROC [t: Tile] RETURNS [Number] = INLINE {RETURN [t.pos.x]};
IsEmpty:
PROC [plane: Tesselation, rect: Rect ← all, skip:
REF ←
NIL]
RETURNS [
BOOL];
-- Returns whether rect in plane has only tiles with value skip.
-- rect must must be changeable
BBox:
PROC [plane: Tesselation, rect: Rect ← all, skip:
REF ←
NIL]
RETURNS [bBox: Rect];
-- Returns a minimal bounding box for non-skip tiles in rect
-- rect must must be changeable.
END.