Enumeration
enumerateMethod:
PUBLIC Pipal.Method ← Pipal.RegisterMethod["RealEnumerate"];
HasEnumerate:
PUBLIC
PROC [object: Pipal.Object]
RETURNS [
BOOL] = {
RETURN [Pipal.ObjectMethod[object, enumerateMethod]#NIL OR Pipal.ObjectMethod[object, PipalInt.enumerateMethod]#NIL];
};
Enumerate:
PUBLIC EnumerateProc = {
data: REF ← Pipal.ObjectMethod[object, enumerateMethod];
quit ← (IF data=NIL THEN UseIntEnumerate ELSE NARROW [data, REF EnumerateProc]^)[object, each, transformation];
};
UseIntEnumerate: EnumerateProc = {
EachChild: PipalInt.EachChildProc = {
realTransformation: Transformation ← CopyTransformation[rt];
ApplyRealInt[realTransformation, transformation];
quit ← each[realTransformation, child];
DestroyTransformation[realTransformation];
};
rt: Transformation ← transformation; -- just renaming!
quit ← PipalInt.Enumerate[object, EachChild];
};
NthChild:
PUBLIC PROC [object: Pipal.Object, transformation: Transformation, rank:
NAT ← 0]
RETURNS [nthTrans: Transformation, nthChild: Pipal.Object ←
NIL] = {
EachChild: EachChildProc = {
IF rank=0
THEN {nthChild ← child; nthTrans ← CopyTransformation[transformation]; quit ← TRUE}
ELSE rank ← rank - 1;
};
[] ← Enumerate[object, EachChild, transformation];
};
CountChildren:
PUBLIC
PROC [object: Pipal.Object]
RETURNS [count:
NAT ← 0] = {
realTransformation: Transformation ← CreateTransformation[];
EachChild: EachChildProc = {count ← count + 1};
[] ← Enumerate[object, EachChild, realTransformation];
DestroyTransformation[realTransformation];
};
Size
It's kind of tricky: objects inherently have a size, but no bbox. However, within an overlay, objects have a bbox. The implementation reflects that situation, and the bbox and size methods play ping-pong.
sizeMethod: PUBLIC Pipal.Method ← Pipal.RegisterMethod["RealSize"];
bboxMethod:
PUBLIC Pipal.Method ← Pipal.RegisterMethod["RealBBox"];
ObjectSize:
PUBLIC SizeProc = {
ref: REF = Pipal.ObjectMethod[object, sizeMethod];
size ← (IF ref=NIL THEN SizeFromEnumerate ELSE NARROW [ref, REF SizeProc]^)[object];
};
BBox:
PUBLIC BBoxProc = {
ref: REF = Pipal.ObjectMethod[object, bboxMethod];
bbox ← (
SELECT
TRUE
FROM
ref#NIL => (NARROW [ref, REF BBoxProc]^),
HasEnumerate[object] => BBoxFromEnumerate,
ENDCASE => BBoxFromSize)[object, transformation];
};
UseIntSize:
PUBLIC SizeProc = {
size ← PipalRealInline.IntToRealVector[PipalInt.ObjectSize[object]];
};
SizeFromEnumerate: SizeProc = {
transformation: Transformation ← CreateTransformation[];
size ← BBoxFromEnumerate[object, transformation].size;
DestroyTransformation[transformation];
};
BBoxFromEnumerate: BBoxProc = {
ComputeBBoxRec: EachChildProc = {
bbox ← BoundingBox[bbox, BBox[child, transformation]];
};
bbox ← emptyRectangle;
[] ← Enumerate[object, ComputeBBoxRec, transformation];
};
BBoxFromSize: BBoxProc = {
bbox ← TransformRectangle[transformation, [zeroVector, ObjectSize[object]]];
};
cachedSizes: Pipal.ObjectCache ← Pipal.CreateObjectCache[];
CachedSizeFromEnumerate:
PUBLIC SizeProc = {
refSize: REF Size ← NARROW [RefTab.Fetch[cachedSizes, object].val];
IF refSize#NIL THEN RETURN [refSize^];
size ← SizeFromEnumerate[object];
refSize ← NEW [Size ← size];
[] ← RefTab.Store[cachedSizes, object, refSize];
};
cachedBBoxes: Pipal.ObjectCache ← Pipal.CreateObjectCache[];
CachedBBoxFromEnumerate:
PUBLIC BBoxProc = {
refBBox: REF Rectangle ← NARROW [RefTab.Fetch[cachedBBoxes, object].val];
IF refBBox#
NIL
THEN bbox ← refBBox^
ELSE {
transformation: Transformation ← CreateTransformation[];
bbox ← BBoxFromEnumerate[object, transformation];
DestroyTransformation[transformation];
refBBox ← NEW [Rectangle ← bbox];
[] ← RefTab.Store[cachedBBoxes, object, refBBox];
};
bbox ← TransformRectangle[transformation, bbox];
};