PipalIntImpl.mesa
Copyright Ó 1985, 1987 by Xerox Corporation. All rights reserved.
Bertrand Serlet May 18, 1988 12:10:59 pm PDT
Louis Monier January 15, 1988 11:30:47 pm PST
DIRECTORY Basics, IO, Pipal, PipalInt, PipalIntInline, RefTab;
PipalIntImpl: CEDAR PROGRAM
IMPORTS Basics, IO, Pipal, PipalIntInline, RefTab
EXPORTS PipalInt, PipalIntInline =
BEGIN OPEN PipalInt;
Printing Utilities
VectorToRope: PUBLIC PROC [v: Vector] RETURNS [rope: Pipal.ROPE] = {
rope ← IO.PutFR["[%g, %g]", IO.int[v.x], IO.int[v.y]];
};
RectangleToRope: PUBLIC PROC [r: Rectangle] RETURNS [rope: Pipal.ROPE] = {
rope ← IO.PutFR["[base: %g, size: %g]", IO.rope[VectorToRope[r.base]], IO.rope[VectorToRope[r.size]]];
};
OrientationToRope: PUBLIC PROC [o: Orientation] RETURNS [rope: Pipal.ROPE] = {
rope ← SELECT o FROM
identity => "identity",
mirrorX => "mirrorX",
rotate90 => "rotate90",
rotate90X => "rotate90X",
rotate180 => "rotate180",
rotate180X => "rotate180X",
rotate270 => "rotate270",
rotate270X => "rotate270X",
ENDCASE => ERROR;
};
TransformationToRope: PUBLIC PROC [t: Transformation] RETURNS [rope: Pipal.ROPE] = {
rope ← IO.PutFR["[%g, %g]", IO.rope[VectorToRope[t.translation]], IO.rope[OrientationToRope[t.orientation]]];
};
Operations on Vectors
Add: PUBLIC PROC [v1, v2: Vector] RETURNS [Vector] = { RETURN [PipalIntInline.Add[v1, v2]] };
Sub: PUBLIC PROC [v1, v2: Vector] RETURNS [Vector] = { RETURN [PipalIntInline.Sub[v1, v2]] };
Min: PUBLIC PROC [v1, v2: Vector] RETURNS [Vector] = { RETURN [PipalIntInline.Min[v1, v2]] };
Max: PUBLIC PROC [v1, v2: Vector] RETURNS [Vector] = { RETURN [PipalIntInline.Max[v1, v2]] };
Neg: PUBLIC PROC [v: Vector] RETURNS [Vector] = { RETURN [PipalIntInline.Neg[v]] };
IsDegeneratedSize: PUBLIC PROC [s: Size] RETURNS [BOOL] = { RETURN [PipalIntInline.IsDegeneratedSize[s]] };
IsEmptySize: PUBLIC PROC [s: Size] RETURNS [BOOL] = { RETURN [PipalIntInline.IsEmptySize[s]] };
Operations on Intervals
IntersectionIntervals: PUBLIC PROC [i1, i2: Interval] RETURNS [Interval]
= {RETURN [PipalIntInline.IntersectionIntervals[i1, i2]] };
UnionIntervals: PUBLIC PROC [i1, i2: Interval] RETURNS [Interval]
= {RETURN [PipalIntInline.UnionIntervals[i1, i2]] };
DoIntervalsIntersect: PUBLIC PROC [i1, i2: Interval] RETURNS [BOOL]
= { RETURN [PipalIntInline.DoIntervalsIntersect[i1, i2]] };
IsInsideInterval: PUBLIC PROC [container, candidate: Interval] RETURNS [BOOL]
= { RETURN [PipalIntInline.IsInsideInterval[container, candidate]] };
IsInsideIntervalNumber: PUBLIC PROC [container: Interval, candidate: Number] RETURNS [BOOL] = { RETURN [PipalIntInline.IsInsideIntervalNumber[container, candidate]] };
Operations on Rectangles
Transformations
Translate: PUBLIC PROC [r: Rectangle, v: Vector] RETURNS [Rectangle]
= { RETURN [PipalIntInline.Translate[r, v]] };
Extend: PUBLIC PROC [r: Rectangle, n: Number] RETURNS [Rectangle]
= { RETURN [[[r.base.x-n, r.base.y-n], [r.size.x+n+n, r.size.y+n+n]]] };
IntersectBox: PUBLIC PROC [r1, r2: Rectangle] RETURNS [r: Rectangle] = {
Could be optimized
r.base ← PipalIntInline.Max[r1.base, r2.base];
r.size ← PipalIntInline.Sub[PipalIntInline.Min[PipalIntInline.Extremity[r1], PipalIntInline.Extremity[r2]], r.base];
};
BoundingBox: PUBLIC PROC [r1, r2: Rectangle] RETURNS [r: Rectangle] = {
Could be optimized
r.base ← PipalIntInline.Min[r1.base, r2.base];
r.size ← PipalIntInline.Sub[PipalIntInline.Max[PipalIntInline.Extremity[r1], PipalIntInline.Extremity[r2]], r.base];
};
BoundingRectangle: PUBLIC PROC [p1, p2: Position] RETURNS [r: Rectangle] = {
Could be inlined
r.base ← PipalIntInline.Min[p1, p2];
r.size ← PipalIntInline.Sub[PipalIntInline.Max[p1, p2], r.base];
};
Predicates
IsDegeneratedRectangle: PUBLIC PROC [r: Rectangle] RETURNS [BOOL]
= { RETURN [PipalIntInline.IsDegeneratedRectangle[r]] };
IsEmptyRectangle: PUBLIC PROC [r: Rectangle] RETURNS [BOOL]
= { RETURN [PipalIntInline.IsEmptyRectangle[r]] };
DoRectanglesIntersect: PUBLIC PROC [r1, r2: Rectangle] RETURNS [BOOL]
= { RETURN [PipalIntInline.DoRectanglesIntersect[r1, r2]] };
IsInsideRectangle: PUBLIC PROC [container, candidate: Rectangle] RETURNS [BOOL]
= { RETURN [PipalIntInline.IsInsideRectangle[container, candidate]] };
IsInsidePoint: PUBLIC PROC [container: Rectangle, candidate: Position] RETURNS [BOOL]
= { RETURN [PipalIntInline.IsInsidePoint[container, candidate]] };
Others
AlwaysQuit: PUBLIC RectangleProc = {quit ← TRUE};
Extremity: PUBLIC PROC [r: Rectangle] RETURNS [Position]
= { RETURN [PipalIntInline.Extremity[r]] };
DecomposeRect: PUBLIC PROC [r, clip: Rectangle, inside, outside: RectangleProc ← NIL] RETURNS [quit: BOOLFALSE] = {
clipext: Position = PipalIntInline.Extremity[clip];
rext: Position = PipalIntInline.Extremity[r];
delta: Vector = PipalIntInline.Sub[r.base, clip.base];
IF clip.base.x<r.base.x THEN {
IF outside#NIL THEN quit ← outside[[clip.base, [MIN[clip.size.x, delta.x], clip.size.y]]];
IF clipext.x<r.base.x OR quit THEN RETURN;
};
IF clip.base.y<r.base.y THEN {
IF outside#NIL THEN quit ← outside[[[MAX[r.base.x, clip.base.x], clip.base.y], [clip.size.x, MIN[clip.size.y, delta.y]]]];
IF clipext.y<r.base.y OR quit THEN RETURN;
};
IF rext.y<clipext.y THEN {
IF outside#NIL THEN quit ← outside[[[MAX[r.base.x, clip.base.x], MAX[rext.y, clip.base.y]], clip.size]];
IF rext.y<clip.base.y OR quit THEN RETURN;
};
IF rext.x<clipext.x THEN {
IF outside#NIL THEN quit ← outside[[[MAX[rext.x, clip.base.x], MAX[r.base.y, clip.base.y]], [clip.size.x, MIN[clip.size.y, delta.y]]]];
IF rext.x<clip.base.x OR quit THEN RETURN;
};
IF inside#NIL THEN quit ← inside[IntersectBox[r, clip]];
};
Center: PUBLIC PROC [r: Rectangle] RETURNS [Position]
= { RETURN [[r.base.x+r.size.x/2, r.base.y+r.size.y/2]] };
Operations on Transformations
OrientVector: PROC [orientation: Orientation, v: Vector] RETURNS [Vector] = {
Can be inlined!!!!
SELECT orientation FROM
identity => RETURN [[+v.x, +v.y]];
mirrorX => RETURN [[-v.x, +v.y]];
rotate90 => RETURN [[-v.y, +v.x]];
rotate90X => RETURN [[+v.y, +v.x]];
rotate180 => RETURN [[-v.x, -v.y]];
rotate180X => RETURN [[+v.x, -v.y]];
rotate270 => RETURN [[+v.y, -v.x]];
rotate270X => RETURN [[-v.y, -v.x]];
ENDCASE => ERROR;
};
TransformVector: PUBLIC PROC [t: Transformation, v: Vector] RETURNS [Vector] = {
Can be inlined!!!!
RETURN [PipalIntInline.Add[t.translation, OrientVector[t.orientation, v]]];
};
TransformBBox: PUBLIC PROC [t: Transformation, s: Size] RETURNS [Rectangle] = {
Can be inlined!!!!
RETURN [TransformRectangle[t, [zeroVector, s]]];
};
TransformRectangle: PUBLIC PROC [t: Transformation, r: Rectangle] RETURNS [Rectangle] = {
Can be inlined!!!!
RETURN [PipalIntInline.Translate[
[SELECT t.orientation FROM
identity =>  [+r.base.x, +r.base.y],
mirrorX =>  [-r.base.x-r.size.x, +r.base.y],
rotate90 =>  [-r.base.y-r.size.y, +r.base.x],
rotate90X =>  [+r.base.y, +r.base.x],
rotate180 =>  [-r.base.x-r.size.x, -r.base.y-r.size.y],
rotate180X => [+r.base.x, -r.base.y-r.size.y],
rotate270 =>  [+r.base.y, -r.base.x-r.size.x],
rotate270X => [-r.base.y-r.size.y, -r.base.x-r.size.x],
ENDCASE =>  ERROR,
PipalIntInline.OrientSize[t.orientation, r.size]],
t.translation
]];
};
Compose: PUBLIC PROC [t1, t2: Transformation] RETURNS [Transformation] = {
Can be inlined!!!!
RETURN [[TransformVector[t1, t2.translation], PipalIntInline.ComposeOrientation[t1.orientation, t2.orientation]]];
};
Enumeration Method
enumerateMethod: PUBLIC Pipal.Method ← Pipal.RegisterMethod["IntEnumerate"];
HasEnumerate: PUBLIC PROC [object: Pipal.Object] RETURNS [BOOL] = {
RETURN [Pipal.ObjectMethod[object, enumerateMethod]#NIL];
};
Enumerate: PUBLIC EnumerateProc = {
quit ← (NARROW [Pipal.ObjectMethod[object, enumerateMethod], REF EnumerateProc]^)[object, each, transformation];
};
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 ← transformation; quit ← TRUE}
ELSE rank ← rank - 1;
};
[] ← Enumerate[object, EachChild, transformation];
};
CountChildren: PUBLIC PROC [object: Pipal.Object] RETURNS [count: NAT ← 0] = {
EachChild: EachChildProc = {count ← count + 1};
[] ← Enumerate[object, EachChild];
};
Size Method
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["IntSize"];
bboxMethod: PUBLIC Pipal.Method ← Pipal.RegisterMethod["IntBBox"];
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];
};
SizeFromEnumerate: SizeProc = {
RETURN [BBoxFromEnumerate[object, []].size];
};
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 {
bbox ← BBoxFromEnumerate[object, []];
refBBox ← NEW [Rectangle ← bbox];
[] ← RefTab.Store[cachedBBoxes, object, refBBox];
};
bbox ← TransformRectangle[transformation, bbox];
};
AbutBox Method
abutBoxMethod: PUBLIC Pipal.Method ← Pipal.RegisterMethod["IntAbutBox"];
AbutBox: PUBLIC AbutBoxProc = {
ref: REF = Pipal.ObjectMethod[object, abutBoxMethod];
abutBox ← (IF ref=NIL THEN AbutBoxFromEnumerate ELSE NARROW [ref, REF AbutBoxProc]^)[object];
};
AbutBoxFromEnumerate: AbutBoxProc = {
ComputeBBox: EachChildProc = {
abutBox ← BoundingBox[abutBox, TransformRectangle[transformation, AbutBox[child]]];
};
abutBox ← emptyRectangle;
[] ← Enumerate[object, ComputeBBox];
};
AbutBoxFromSize: PUBLIC AbutBoxProc = {
abutBox ← [zeroVector, ObjectSize[object]];
};
cachedAbutBoxes: Pipal.ObjectCache ← Pipal.CreateObjectCache[];
CachedAbutBoxFromEnumerate: PUBLIC AbutBoxProc = {
refAbutBox: REF Rectangle ← NARROW [RefTab.Fetch[cachedAbutBoxes, object].val];
IF refAbutBox#NIL THEN RETURN [refAbutBox^];
abutBox ← AbutBoxFromEnumerate[object];
refAbutBox ← NEW [Rectangle ← abutBox];
[] ← RefTab.Store[cachedAbutBoxes, object, refAbutBox];
};
Geometrical Classes
General Transform
transformClass: PUBLIC Pipal.Class ← Pipal.RegisterClass["IntTransform", CODE [TransformRec]];
EnumerateTransform: EnumerateProc = {
transform: Transform ← NARROW [object];
quit ← each[Compose[transformation, transform.transformation], transform.child];
};
DescribeTransform: Pipal.DescribeProc = {
transform: Transform ← NARROW [object];
Pipal.PutIndent[out, indent, cr];
IO.PutF[out, "IntTransform %g of : ", IO.rope[TransformationToRope[transform.transformation]]];
Pipal.Describe[out, transform.child, indent+1, level-1, cr];
};
CreateTransform: PUBLIC PROC [transformation: Transformation, child: Pipal.Object] RETURNS [transform: Transform] = {
transform ← NEW [TransformRec ← [transformation, child]];
};
Translation
translationClass: PUBLIC Pipal.Class ← Pipal.RegisterClass["IntTranslation", CODE [TranslationRec]];
EnumerateTranslation: EnumerateProc = {
Could be optimized
translation: Translation ← NARROW [object];
quit ← each[Compose[transformation, [translation.vector]], translation.child];
};
DescribeTranslation: Pipal.DescribeProc = {
translation: Translation ← NARROW [object];
Pipal.PutIndent[out, indent, cr];
IO.PutF[out, "IntTranslation %g of : ", IO.rope[VectorToRope[translation.vector]]];
Pipal.Describe[out, translation.child, indent+1, level-1, cr];
};
CreateTranslation: PUBLIC PROC [vector: Vector, child: Pipal.Object] RETURNS [translation: Translation] = {
translation ← NEW [TranslationRec ← [vector, child]];
};
Orient
orientClass: PUBLIC Pipal.Class ← Pipal.RegisterClass["IntOrient", CODE [OrientRec]];
EnumerateOrient: EnumerateProc = {
Could be optimized
orient: Orient ← NARROW [object];
quit ← each[Compose[transformation, [zeroVector, orient.orientation]], orient.child];
};
DescribeOrient: Pipal.DescribeProc = {
orient: Orient ← NARROW [object];
Pipal.PutIndent[out, indent, cr];
IO.PutF[out, "IntOrient %g of : ", IO.rope[OrientationToRope[orient.orientation]]];
Pipal.Describe[out, orient.child, indent+1, level-1, cr];
};
CreateOrient: PUBLIC PROC [orientation: Orientation, child: Pipal.Object] RETURNS [orient: Orient] = {
orient ← NEW [OrientRec ← [orientation, child]];
};
Compacted creation of objects
TransformObject: PUBLIC PROC [transformation: Transformation, child: Pipal.Object] RETURNS [Pipal.Object] = {
RETURN [WITH child SELECT FROM
transform: Transform =>
TransformObject[Compose[transformation, transform.transformation], transform.child],
translation: Translation =>
TransformObject[Compose[transformation, [translation.vector]], translation.child],
orient: Orient =>
TransformObject[Compose[transformation, [orientation: orient.orientation]], orient.child],
ENDCASE  => SELECT TRUE FROM
transformation=[] => child,
transformation.orientation=identity => CreateTranslation[transformation.translation, child],
transformation.translation=zeroVector => CreateOrient[transformation.orientation, child],
ENDCASE => CreateTransform[transformation, child]
];
};
Abut-related Annotations and Classes
Abut Box Annotation
abutBoxProp: PUBLIC ATOM ← $AbutBoxAnnotation;
CreateAbutBoxAnnotation: PUBLIC PROC [child: Pipal.Object, rectangle: Rectangle] RETURNS [annotation: Pipal.Annotation] = {
annotation ← Pipal.CreateAnnotation[child, abutBoxProp, NEW [Rectangle ← rectangle]];
};
Abut
abutClass: PUBLIC Pipal.Class ← Pipal.RegisterClass["IntAbut", CODE [AbutRec]];
EnumerateAbut: EnumerateProc = {
abut: Abut ← NARROW [object];
pos: Position ← zeroVector;
FOR i: NAT IN [0 .. abut.size) DO
ab: Rectangle = AbutBox[abut[i]];
quit ← each[Compose[transformation, [Sub[pos, ab.base]]], abut[i]];
IF quit THEN RETURN;
IF abut.inX THEN pos.x ← pos.x + ab.size.x ELSE pos.y ← pos.y + ab.size.y;
ENDLOOP;
};
DescribeAbut: Pipal.DescribeProc = {
abut: Abut ← NARROW [object];
Pipal.PutIndent[out, indent, cr];
IO.PutF[out, "Abut in %g of: ", IO.rope[IF abut.inX THEN "X" ELSE "Y"]];
IF level=1 THEN {IO.PutRope[out, "..."]; RETURN};
FOR i: NAT IN [0 .. abut.size) DO
Pipal.Describe[out, abut[i], indent+1, level-1, cr];
ENDLOOP;
};
CreateAbut: PUBLIC PROC [inX: BOOL, children: Pipal.Objects] RETURNS [abut: Abut] = {
size: NAT ← Pipal.Length[children];
abut ← NEW [AbutRec[size]];
abut.inX ← inX;
FOR i: NAT IN [0 .. size) DO abut[i] ← children.first; children ← children.rest ENDLOOP;
IF size#0 THEN {
irs0: Size = AbutBox[abut[0]].size;
FOR i: NAT IN [1 .. size) DO
irs: Size = AbutBox[abut[i]].size;
IF (IF inX THEN irs0.y#irs.y ELSE irs0.x#irs.x) THEN ERROR; -- incompatible x dimension for an abutY or incompatible y dimension for an abutX
ENDLOOP;
};
};
Miscellaneous
HashByEnumeration: PUBLIC Pipal.HashProc = {
Each: EachChildProc = {
hash ← hash + transformation.translation.x + transformation.translation.y + ORD [transformation.orientation] + Pipal.Hash[child] + 1;
};
hash ← Pipal.HashObjectClass[object];
[] ← Enumerate[object, Each];
};
hashCache: Pipal.ObjectCache ← Pipal.CreateObjectCache[];
CachedHashByEnumeration: PUBLIC Pipal.HashProc = {
refHash: REF CARDNARROW [RefTab.Fetch[hashCache, object].val];
IF refHash#NIL THEN RETURN [refHash^];
hash ← HashByEnumeration[object];
[] ← RefTab.Store[hashCache, object, NEW [CARD ← hash]];
};
HashObjectSize: PUBLIC Pipal.HashProc = {
size: Size = ObjectSize[object];
hash ← size.x+size.y;
};
EqualByEnumeration: PUBLIC Pipal.EqualProc = {
size: NAT ← CountChildren[object1];
IF CountChildren[object2]#size THEN RETURN [FALSE];
FOR i: NAT IN [0 .. size) DO
nthTrans1: Transformation; nthChild1: Pipal.Object;
nthTrans2: Transformation; nthChild2: Pipal.Object;
[nthTrans1, nthChild1] ← NthChild[object1];
[nthTrans2, nthChild2] ← NthChild[object2];
IF nthTrans1#nthTrans2 OR NOT Pipal.Equal[nthChild1, nthChild2]
THEN RETURN [FALSE];
ENDLOOP;
RETURN [TRUE];
};
AtEdge: PUBLIC PROC [abutBox: Rectangle, trans: Transformation, object: Pipal.Object] RETURNS [BOOL] = {
RETURN [NOT IsInsideRectangle[Extend[abutBox, -1], BBox[object, trans]]];
};
Initialization
Rotation composition table
composeTable: PUBLIC ARRAY Orientation OF ARRAY Orientation OF Orientation;
ReallyComposeOrientation: PROC [o1, o2: Orientation] RETURNS [Orientation] = {
This procedure produces the composite orientation obtained by first doing o1 and then doing o2. It uses the observation that a reflection in x followed by a z-degree clockwise rotation is the same as a (360-z)-degree clockwise rotation followed by a reflection in x. Thus if o1 contains a final reflection, then o2's rotation operates in reverse.
refl1: [0..1] ~ Basics.BITAND[ORD[o1], 1];
rot2: [0..6] ← Basics.BITAND[ORD[o2], 6];
IF refl1#0 AND rot2#0 THEN rot2 ← 8-rot2;
RETURN [VAL[Basics.BITAND[
Basics.BITAND[ORD[o1], 6] + rot2 + Basics.BITXOR[refl1, Basics.BITAND[ORD[o2], 1]],
7]]];
};
Pipal Classes
EnumerateOverlay: EnumerateProc ~ {
overlay: Pipal.Overlay ← NARROW [object];
FOR i: NAT IN [0..overlay.size) DO
IF each[transformation, overlay[i]] THEN RETURN[TRUE];
ENDLOOP;
};
EnumerateIcon: EnumerateProc ~ {
icon: Pipal.Icon ← NARROW [object];
quit ← each[transformation, icon.reference];
};
EnumerateAnnotation: EnumerateProc ~ {
annotation: Pipal.Annotation ← NARROW [object];
quit ← each[transformation, annotation.child];
};
SizeAnnotation: SizeProc = {
size ← BBoxAnnotation[object, []].size;
};
BBoxAnnotation: BBoxProc = {
annotation: Pipal.Annotation ← NARROW [object];
bbox ← BBox[annotation.child, transformation];
IF annotation.key=abutBoxProp THEN bbox ← BoundingBox[
bbox,
TransformRectangle[transformation, (NARROW [annotation.value, REF Rectangle]^)]
];
};
AbutBoxAnnotation: AbutBoxProc = {
annotation: Pipal.Annotation ← NARROW [object];
abutBox ← IF annotation.key=abutBoxProp
THEN (NARROW [annotation.value, REF Rectangle]^)
ELSE AbutBox[annotation.child];
};
Rotation composition table
FOR o1: Orientation IN Orientation DO
FOR o2: Orientation IN Orientation DO
composeTable[o1][o2] ← ReallyComposeOrientation[o2, o1];
ENDLOOP;
ENDLOOP;
Pipal Classes
Pipal.PutClassMethod[Pipal.overlayClass, enumerateMethod, NEW [EnumerateProc ← EnumerateOverlay]];
Pipal.PutClassMethod[Pipal.overlayClass, sizeMethod, NEW [SizeProc ← CachedSizeFromEnumerate]];
Pipal.PutClassMethod[Pipal.overlayClass, bboxMethod, NEW [BBoxProc ← CachedBBoxFromEnumerate]];
Pipal.PutClassMethod[Pipal.overlayClass, abutBoxMethod, NEW [AbutBoxProc ← CachedAbutBoxFromEnumerate]];
Pipal.PutClassMethod[Pipal.overlayClass, Pipal.hashMethod, NEW [Pipal.HashProc ← CachedHashByEnumeration]];
Pipal.PutClassMethod[Pipal.overlayClass, Pipal.equalMethod, NEW [Pipal.EqualProc ← EqualByEnumeration]];
Pipal.PutClassMethod[Pipal.iconClass, enumerateMethod, NEW [EnumerateProc ← EnumerateIcon]];
Pipal.PutClassMethod[Pipal.iconClass, Pipal.hashMethod, NEW [Pipal.HashProc ← HashByEnumeration]];
Pipal.PutClassMethod[Pipal.iconClass, Pipal.equalMethod, NEW [Pipal.EqualProc ← EqualByEnumeration]];
Pipal.PutClassMethod[Pipal.annotationClass, enumerateMethod, NEW [EnumerateProc ← EnumerateAnnotation]];
Pipal.PutClassMethod[Pipal.annotationClass, sizeMethod, NEW [SizeProc ← SizeAnnotation]];
Pipal.PutClassMethod[Pipal.annotationClass, bboxMethod, NEW [BBoxProc ← BBoxAnnotation]];
Pipal.PutClassMethod[Pipal.annotationClass, abutBoxMethod, NEW [AbutBoxProc ← AbutBoxAnnotation]];
Classes defined in this interface
Pipal.PutClassMethod[transformClass, enumerateMethod, NEW [EnumerateProc ← EnumerateTransform]];
Pipal.PutClassMethod[transformClass, Pipal.describeMethod, NEW [Pipal.DescribeProc ← DescribeTransform]];
Pipal.PutClassMethod[transformClass, Pipal.hashMethod, NEW [Pipal.HashProc ← HashByEnumeration]];
Pipal.PutClassMethod[transformClass, Pipal.equalMethod, NEW [Pipal.EqualProc ← EqualByEnumeration]];
Pipal.PutClassMethod[translationClass, enumerateMethod, NEW [EnumerateProc ← EnumerateTranslation]];
Pipal.PutClassMethod[translationClass, Pipal.describeMethod, NEW [Pipal.DescribeProc ← DescribeTranslation]];
Pipal.PutClassMethod[translationClass, Pipal.hashMethod, NEW [Pipal.HashProc ← HashByEnumeration]];
Pipal.PutClassMethod[translationClass, Pipal.equalMethod, NEW [Pipal.EqualProc ← EqualByEnumeration]];
Pipal.PutClassMethod[orientClass, enumerateMethod, NEW [EnumerateProc ← EnumerateOrient]];
Pipal.PutClassMethod[orientClass, Pipal.describeMethod, NEW [Pipal.DescribeProc ← DescribeOrient]];
Pipal.PutClassMethod[orientClass, Pipal.hashMethod, NEW [Pipal.HashProc ← HashByEnumeration]];
Pipal.PutClassMethod[orientClass, Pipal.equalMethod, NEW [Pipal.EqualProc ← EqualByEnumeration]];
Pipal.PutClassMethod[abutClass, enumerateMethod, NEW [EnumerateProc ← EnumerateAbut]];
Pipal.PutClassMethod[abutClass, Pipal.describeMethod, NEW [Pipal.DescribeProc ← DescribeAbut]];
Pipal.PutClassMethod[abutClass, Pipal.hashMethod, NEW [Pipal.HashProc ← CachedHashByEnumeration]];
Pipal.PutClassMethod[abutClass, Pipal.equalMethod, NEW [Pipal.EqualProc ← EqualByEnumeration]];
Pipal.PutClassMethod[abutClass, sizeMethod, NEW [SizeProc ← CachedSizeFromEnumerate]];
Pipal.PutClassMethod[abutClass, bboxMethod, NEW [BBoxProc ← CachedBBoxFromEnumerate]];
Pipal.PutClassMethod[abutClass, abutBoxMethod, NEW [AbutBoxProc ← CachedAbutBoxFromEnumerate]];
END.