PipalInt.mesa 
Copyright Ó 1988 by Xerox Corporation. All rights reserved.
Louis Monier January 15, 1988 11:24:39 pm PST
Bertrand Serlet May 19, 1988 0:34:15 am PDT
Barth, January 26, 1988 11:30:32 am PST
DIRECTORY Pipal;
PipalInt: CEDAR DEFINITIONS = BEGIN
Theory
Type definitions and basic operations for Pipal integer data structures. Integers are used for layout and schematic capture.
Types
Number: TYPE = INT32;
infinity: Number = LAST [Number]/2;
Vector: TYPE = RECORD [
x: Number, -- horizontal dimension, going right
y: Number]; -- vertical dimension, going down
Position: TYPE = Vector; -- alias when a vector expresses a position
Size: TYPE = Vector; -- alias when a vector expresses a size
zeroVector: Vector = [0, 0];
emptySize: Size = [-infinity, -infinity];
Interval: TYPE = RECORD [
base: Number,
size: Number];
size<=0 <=> empty interval. All empty intervals are legal. Intervals are closed at the base and open at the extremity. If anyone can tell us why this should be so please do.
Rectangle: TYPE = RECORD [
base: Vector,
size: Size];
size.x<=0 or size.y<=0 <=> empty rectangle. All empty rectangles are legal
emptyRectangle: Rectangle = [[infinity/2, infinity/2], emptySize];
fullRectangle: Rectangle = [[-infinity/2, -infinity/2], [infinity, infinity]];
RectangleProc: TYPE = PROC [rect: Rectangle] RETURNS [quit: BOOLFALSE];
Standard types for enumerations of rectangles.
Orientation: TYPE = MACHINE DEPENDENT {identity(0), mirrorX(1), rotate90(2), rotate90X(3), rotate180(4), rotate180X(5), rotate270(6), rotate270X(7)};
An orientation represents an anticlockwise rotation maybe followed by a reflection in x.
[Reflection in x means: modify x coordinates, leave y coordinates]
Transformation: TYPE = RECORD [translation: Vector ← zeroVector, orientation: Orientation ← identity];
A transformation represents an orientation followed by a translation.
Printing Utilities
VectorToRope: PROC [v: Vector] RETURNS [Pipal.ROPE];
RectangleToRope: PROC [r: Rectangle] RETURNS [Pipal.ROPE];
OrientationToRope: PROC [o: Orientation] RETURNS [Pipal.ROPE];
TransformationToRope: PROC [t: Transformation] RETURNS [Pipal.ROPE];
Vector Operations
Transformations
Add: PROC [v1, v2: Vector] RETURNS [Vector];
Sum, v1+v2.
Sub: PROC [v1, v2: Vector] RETURNS [Vector];
Difference, v1-v2.
Min: PROC [v1, v2: Vector] RETURNS [Vector];
Max: PROC [v1, v2: Vector] RETURNS [Vector];
Neg: PROC [v: Vector] RETURNS [Vector];
Negative, -v.
Predicates
IsDegeneratedSize: PROC [s: Size] RETURNS [BOOL];
Returns TRUE iff s.x<0 OR s.y<0.
IsEmptySize: PROC [s: Size] RETURNS [BOOL];
Returns TRUE iff s.x<=0 OR s.y<=0.
Interval Operations
IntersectionIntervals: PROC [i1, i2: Interval] RETURNS [Interval];
UnionIntervals: PROC [i1, i2: Interval] RETURNS [Interval];
DoIntervalsIntersect: PROC [i1, i2: Interval] RETURNS [BOOL];
IsInsideInterval: PROC [container, candidate: Interval] RETURNS [BOOL];
Returns TRUE iff candidate is inside of container.
IsInsideIntervalNumber: PROC [container: Interval, candidate: Number] RETURNS [BOOL];
Returns TRUE iff candidate is inside of container.
Extremity is included.
Rectangle Operations
Transformations
Translate: PROC [r: Rectangle, v: Vector] RETURNS [Rectangle];
Extend: PROC [r: Rectangle, n: Number] RETURNS [Rectangle];
IntersectBox: PROC [r1, r2: Rectangle] RETURNS [Rectangle];
fullRectangle is a neutral element for this operation.
BoundingBox: PROC [r1, r2: Rectangle] RETURNS [Rectangle];
emptyRectangle is a neutral element for this operation.
BoundingRectangle: PROC [p1, p2: Position] RETURNS [Rectangle];
no neutral element for this operation.
Predicates
IsDegeneratedRectangle: PROC [r: Rectangle] RETURNS [BOOL];
IsEmptyRectangle: PROC [r: Rectangle] RETURNS [BOOL];
DoRectanglesIntersect: PROC [r1, r2: Rectangle] RETURNS [BOOL];
Returns TRUE iff r1 and r2 have some common points or border; TRUE if rects touch on a single point.
IsInsideRectangle: PROC [container, candidate: Rectangle] RETURNS [BOOL];
IsInsidePoint: PROC [container: Rectangle, candidate: Position] RETURNS [BOOL];
Others
AlwaysQuit: RectangleProc;
Extremity: PROC [r: Rectangle] RETURNS [Position];
DecomposeRect: PROC [r, clip: Rectangle, inside, outside: RectangleProc ← NIL] RETURNS [quit: BOOLFALSE];
Calls inside [part of r inside of clip] and outside [parts of r outside of clip].
Border points might be part of both calls.
NIL call backs means discard.
Center: PROC [r: Rectangle] RETURNS [Position];
Returns center of rect r
Transformation Operations
Application
TransformVector: PROC [t: Transformation, v: Vector] RETURNS [Vector];
TransformBBox: PROC [t: Transformation, s: Size] RETURNS [Rectangle];
Same as TransformRectangle[t, [zeroVector, s]];
TransformRectangle: PROC [t: Transformation, r: Rectangle] RETURNS [Rectangle];
Composition
Compose: PROC [t1, t2: Transformation] RETURNS [Transformation];
For each position p, the following equality holds:
TransformVector [Compose [t1, t2], p] = TransformVector [t1, TransformVector [t2, p]]
Enumeration Method
enumerateMethod: Pipal.Method;
EachChildProc: TYPE = PROC [transformation: Transformation, child: Pipal.Object] RETURNS [quit: BOOLFALSE];
EnumerateProc: TYPE = PROC [object: Pipal.Object, each: EachChildProc, transformation: Transformation ← []] RETURNS [quit: BOOL ← FALSE];
Enumerates all children of an object.
There is an implicit overlay to compose all children.
HasEnumerate: PROC [object: Pipal.Object] RETURNS [BOOL];
Enumerate: EnumerateProc;
Short cut for applying the enumerate method.
No enumerate method => crash and burn.
Successive invocations with the same object should apply each in the same order.
NthChild: PROC [object: Pipal.Object, transformation: Transformation ← [], rank: NAT ← 0] RETURNS [nthTrans: Transformation, nthChild: Pipal.Object ← NIL];
Returns the Nth child, 0 being of course the first child, NIL if no such child.
CountChildren: PROC [object: Pipal.Object] RETURNS [count: NAT];
Returns the number of children obtained by enumeration.
Size Method
sizeMethod: Pipal.Method;
bboxMethod: Pipal.Method;
SizeProc: TYPE = PROC [object: Pipal.Object] RETURNS [size: Size];
BBoxProc: TYPE = PROC [object: Pipal.Object, transformation: Transformation] RETURNS [bbox: Rectangle];
ObjectSize: SizeProc;
Short cut for applying the size method.
Default when no size method is found is:
Compute the size by computing the size of the bounding box of children.
No enumerate method => crash and burn.
No child => emptySize
BBox: BBoxProc;
Computes the bounding box of an object, in the context of an overlay.
CachedSizeFromEnumerate: SizeProc;
Computes the size by enumeration and caches its result.
CachedBBoxFromEnumerate: BBoxProc;
Computes the bbox by enumeration and caches its result.
AbutBox Method
abutBoxMethod: Pipal.Method;
AbutBoxProc: TYPE = PROC [object: Pipal.Object] RETURNS [abutBox: Rectangle];
AbutBox: AbutBoxProc;
Short cut for applying the abutBox method.
Default when no abutBox method is found is:
Computes the abutBox by computing the bounding box of children.
No enumerate method => crash and burn.
No child => emptyRectangle
AbutBoxFromSize: AbutBoxProc;
Returns [[0, 0], ObjectSize[object]].
For use by atomic classes which do not fiddle the abutBox.
CachedAbutBoxFromEnumerate: AbutBoxProc;
Computes the abutbox by enumeration and caches its result.
Geometrical Classes
General Transform
transformClass: Pipal.Class;
Transform: TYPE = REF TransformRec;
TransformRec: TYPE = RECORD [
transformation: Transformation,
child: Pipal.Object];
CreateTransform: PROC [transformation: Transformation, child: Pipal.Object] RETURNS [transform: Transform];
Translation
translationClass: Pipal.Class;
Translation: TYPE = REF TranslationRec;
TranslationRec: TYPE = RECORD [
vector: Vector,
child: Pipal.Object];
CreateTranslation: PROC [vector: Vector, child: Pipal.Object] RETURNS [translation: Translation];
Orient
orientClass: Pipal.Class;
Orient: TYPE = REF OrientRec;
OrientRec: TYPE = RECORD [
orientation: Orientation,
child: Pipal.Object];
CreateOrient: PROC [orientation: Orientation, child: Pipal.Object] RETURNS [orient: Orient];
Compacted creation of objects
TransformObject: PROC [transformation: Transformation, child: Pipal.Object] RETURNS [Pipal.Object];
Creates the densest object possible.
Might even return child itself if the transformation is the identity.
Abut-related Annotations and Classes
Abut Box Annotation
Annotation for specifying an Abut Box for an object. Key of the annotation is abutBoxProp and value is a REF Rectangle.
abutBoxProp: ATOM;
CreateAbutBoxAnnotation: PROC [child: Pipal.Object, rectangle: Rectangle] RETURNS [annotation: Pipal.Annotation];
Abut
abutClass: Pipal.Class;
Abut: TYPE = REF AbutRec;
AbutRec: TYPE = RECORD [
inX: BOOL,
children: SEQUENCE size: NAT OF Pipal.Object
];
Abut children are guaranteed to be enumerated in increasing order (left to right and bottom to top).
CreateAbut: PROC [inX: BOOL, children: Pipal.Objects] RETURNS [abut: Abut];
Abuts differ from overlay by the fact they contain an ordered list of children abutted one next to the other. The order of children is important and the leftmost (resp. bottommost) is the first one.
Abutted cells are checked for compatible sizes.
Miscellaneous
HashByEnumeration: Pipal.HashProc;
Uses Enumerate on children to compute hash.
CachedHashByEnumeration: Pipal.HashProc;
Same as previous, but caches its result.
HashObjectSize: Pipal.HashProc;
HashVector: PROC [vector: Vector] RETURNS [hash: CARD];
HashRectangle: PROC [rectangle: Rectangle] RETURNS [hash: CARD];
HashTransformation: PROC [transformation: Transformation] RETURNS [hash: CARD];
EqualByEnumeration: Pipal.EqualProc;
Uses Enumerate on children to decide whether equal.
AtEdge: PROC [abutBox: Rectangle, trans: Transformation, object: Pipal.Object] RETURNS [BOOL];
Returns TRUE iff transformed object touches or extends beyond abutBox.
END.