PipalRealImpl.mesa
Copyright Ó 1985, 1987 by Xerox Corporation. All rights reserved.
Bertrand Serlet May 17, 1988 2:19:43 pm PDT
Louis Monier January 15, 1988 11:30:47 pm PST
Barth, January 27, 1988 11:30:23 am PST
PipalRealImpl:
CEDAR
PROGRAM
IMPORTS ImagerTransformation, IO, Pipal, PipalInt, PipalRealInline, RefTab
EXPORTS PipalReal, PipalRealInline =
BEGIN OPEN PipalReal;
Printing Utilities
VectorToRope:
PUBLIC
PROC [v: Vector]
RETURNS [rope: Pipal.
ROPE] = {
rope ← IO.PutFR["[%g, %g]", IO.real[v.x], IO.real[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]]];
};
TransformationToRope:
PUBLIC
PROC [t: Transformation]
RETURNS [rope: Pipal.
ROPE] = {
rope ← IO.PutFR["[...Transformation...]"];
};
Operations on Vectors
Add:
PUBLIC
PROC [v1, v2: Vector]
RETURNS [Vector] = {
RETURN [PipalRealInline.Add[v1, v2]] };
Sub:
PUBLIC
PROC [v1, v2: Vector]
RETURNS [Vector] = {
RETURN [PipalRealInline.Sub[v1, v2]] };
Min:
PUBLIC
PROC [v1, v2: Vector]
RETURNS [Vector] = {
RETURN [PipalRealInline.Min[v1, v2]] };
Max:
PUBLIC
PROC [v1, v2: Vector]
RETURNS [Vector] = {
RETURN [PipalRealInline.Max[v1, v2]] };
Neg:
PUBLIC
PROC [v: Vector]
RETURNS [Vector] = {
RETURN [PipalRealInline.Neg[v]] };
IsDegeneratedSize:
PUBLIC
PROC [s: Size]
RETURNS [
BOOL] = {
RETURN [PipalRealInline.IsDegeneratedSize[s]] };
IsEmptySize:
PUBLIC
PROC [s: Size]
RETURNS [
BOOL] = {
RETURN [PipalRealInline.IsEmptySize[s]] };
Operations on Intervals
IntersectionIntervals:
PUBLIC
PROC [i1, i2: Interval]
RETURNS [Interval]
= { RETURN [PipalRealInline.IntersectionIntervals[i1, i2]] };
UnionIntervals:
PUBLIC
PROC [i1, i2: Interval]
RETURNS [Interval]
= { RETURN [PipalRealInline.UnionIntervals[i1, i2]] };
DoIntervalsIntersect:
PUBLIC
PROC [i1, i2: Interval]
RETURNS [
BOOL]
= { RETURN [PipalRealInline.DoIntervalsIntersect[i1, i2]] };
IsInsideInterval:
PUBLIC
PROC [container, candidate: Interval]
RETURNS [
BOOL]
= { RETURN [PipalRealInline.IsInsideInterval[container, candidate]] };
IsInsideIntervalNumber:
PUBLIC
PROC [container: Interval, candidate: Number]
RETURNS [
BOOL] = {
RETURN [PipalRealInline.IsInsideIntervalNumber[container, candidate]] };
Operations on Transformations
TransformVector:
PUBLIC
PROC [t: Transformation, v: Vector]
RETURNS [Vector] = {
Can be inlined!!!!
RETURN [ImagerTransformation.Transform[t, 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 [rr: Rectangle] = {
Can be optimized and inlined!!!!
ir: ImagerBox.Rectangle = ImagerTransformation.TransformRectangle[t, [r.base.x, r.base.y, r.size.x, r.size.y]];
rr ← [[ir.x, ir.y], [ir.w, ir.h]];
};
Compose:
PUBLIC
PROC [t1, t2: Transformation]
RETURNS [Transformation] = {
Can be inlined!!!!
RETURN [ImagerTransformation.Concat[t2, t1]];
};
Apply:
PUBLIC
PROC [t1, t2: Transformation] = {
Can be inlined!!!!
ImagerTransformation.ApplyPreConcat[t1, t2];
};
CreateTransformation:
PUBLIC
PROC
RETURNS [Transformation] = {
RETURN [ImagerTransformation.Create[1, 0, 0, 0, 1, 0]]};
CopyTransformation:
PUBLIC
PROC [t: Transformation]
RETURNS [Transformation] = {
RETURN [ImagerTransformation.Copy[t]]};
DestroyTransformation:
PUBLIC
PROC [t: Transformation] = {ImagerTransformation.Destroy[t]};
EqualTransformation: PUBLIC PROC [t1, t2: Transformation] RETURNS [BOOL] = {RETURN [ImagerTransformation.CloseEnough[t1, t2]]};
Enumeration Method
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 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["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];
};
Coercion with PipalInt Types
IntToRealVector:
PUBLIC
PROC [v: PipalInt.Vector]
RETURNS [Vector]
= {RETURN [PipalRealInline.IntToRealVector[v]]};
IntToRealRectangle:
PUBLIC
PROC [r: PipalInt.Rectangle]
RETURNS [Rectangle]
= {RETURN [PipalRealInline.IntToRealRectangle[r]]};
IntToRealTransformation:
PUBLIC
PROC [t: PipalInt.Transformation]
RETURNS [Transformation]
= {RETURN [PipalRealInline.IntToRealTransformation[t]]};
ApplyRealInt:
PUBLIC
PROC [t1: Transformation, t2: PipalInt.Transformation] = {
Can be optimized!
rt: Transformation ← PipalRealInline.IntToRealTransformation[t2];
Apply[t1, rt];
DestroyTransformation[rt];
};
Initialization
Pipal classes functions
EnumerateOverlay: EnumerateProc ~ {
overlay: Pipal.Overlay ← NARROW [object];
FOR i:
NAT
IN [0..overlay.size)
DO
IF each[transformation, overlay[i]] THEN RETURN[TRUE];
ENDLOOP;
};
BBoxAnnotation: BBoxProc = {
annotation: Pipal.Annotation ← NARROW [object];
bbox ← BBox[annotation.child, transformation];
IF annotation.key=PipalInt.abutBoxProp
THEN bbox ← BoundingBox[
bbox,
TransformRectangle[transformation, PipalRealInline.IntToRealRectangle[(NARROW [annotation.value, REF PipalInt.Rectangle]^)]]
];
};
Pipal classes
Pipal.PutClassMethod[Pipal.overlayClass, enumerateMethod, NEW [EnumerateProc ← EnumerateOverlay]]; -- speed up only
Pipal.PutClassMethod[Pipal.overlayClass, sizeMethod, NEW [SizeProc ← CachedSizeFromEnumerate]]; -- speed up only
Pipal.PutClassMethod[Pipal.overlayClass, bboxMethod, NEW [BBoxProc ← CachedBBoxFromEnumerate]]; -- speed up only
Pipal.PutClassMethod[Pipal.annotationClass, bboxMethod, NEW [BBoxProc ← BBoxAnnotation]];
Classes defined in this interface
Pipal.PutClassMethod[transformClass, enumerateMethod, NEW [EnumerateProc ← EnumerateTransform]];
Pipal.PutClassMethod[transformClass, Pipal.describeMethod, NEW [Pipal.DescribeProc ← DescribeTransform]];