CDOrient.mesa (part of ChipNDale)
Copyright © 1983, 1984 by Xerox Corporation. All rights reserved.
Ch. Jacobi, November 21, 1983 8:55 pm
last edited by Ch. Jacobi, May 21, 1985 10:54:49 am PDT
some code from "ChipOrient" E. McCreight, May 16, 1985 12:00:54 pm PDT
DIRECTORY
PrincOpsUtils,
CD,
Imager;
CDOrient: CEDAR DEFINITIONS
IMPORTS Imager, PrincOpsUtils =
BEGIN
Orientation: TYPE = CD.Orientation;
--If your program depends on the representation of Orientation, it
--is probably wrong.
--An orientation idx is composed of two parts:
--an anticlockwise rotation of (idx/2)*90 degrees,
--followed by a reflection in x if (idx MOD 2)#0
original: Orientation = 0;
mirrorX: Orientation = 1;
rotate90: Orientation = 2;
rotate90X: Orientation = 3;
rotate180: Orientation = 4;
rotate180X: Orientation = 5;
mirrorY: Orientation = 5;
rotate270: Orientation = 6;
rotate270X: Orientation = 7;
MapRect: PROC [itemInCell: CD.Rect, cellSize: CD.Position,
cellInstOrient: Orientation, cellInstPos: CD.Position ← [0,0]]
RETURNS [itemInWorld: CD.Rect];
--Given an item in a prototype cell, and the
--size of the prototype cell, both in "cell" co-ordinates, and
--the position and orientation index of an instance of that cell in "world"
--co-ordinates, this procedure returns the world
--co-ordinates of the instance of the item.
DeMapRect: PROC [itemInWorld: CD.Rect, cellSize: CD.Position,
cellInstOrient: Orientation, cellInstPos: CD.Position ← [0,0]]
RETURNS [itemInCell: CD.Rect];
--Given an item in world co-ordinates, and the
--size of a prototype cell, in "cell" co-ordinates, and
--the position and orientation index of an instance of that cell in "world"
--co-ordinates, this procedure returns the cell prototype
--co-ordinates of that item.
MapPoint: PROC [pointInCell: CD.Position, cellSize: CD.Position,
cellInstOrient: Orientation, cellInstPos: CD.Position ← [0,0]]
RETURNS [pointInWorld: CD.Position];
--Given an point in a prototype cell,
--the size of the prototype cell, both in "cell" co-ordinates, and
--the position and orientation index of an instance of that cell in "world"
--co-ordinates, this procedure returns the world
--co-ordinates of the point.
--WARNING: a position of a rect can not be mapped with MapPoint
DeMapPoint: PROC [pointInWorld: CD.Position, cellSize: CD.Position,
cellInstOrient: Orientation, cellInstPos: CD.Position ← [0,0]]
RETURNS [pointInCell: CD.Position];
--Given a point in world co-ordinates
--the size of the prototype cell, in "cell" co-ordinates, and
--the position and orientation index of an instance of that cell in "world"
--co-ordinates, this procedure returns the cell
--co-ordinates of the point.
--WARNING: a position of a rect can not be mapped with DeMapPoint
ComposeOrient: PROC [
itemOrientInCell, cellOrientInWorld: Orientation]
RETURNS [itemOrientInWorld: Orientation];
--This procedure produces the composite orientation
--obtained by first doing itemInCell and then
--doing cellInWorld.
InverseOrient: PROC [orient: Orientation]
RETURNS [inverse: Orientation];
--For all orientationIndexes o1, ComposeOrient[o1, InverseOrient[o1]] = 0.
DecomposeOrient: PROCEDURE[
itemOrientInWorld, cellOrientInWorld: Orientation]
RETURNS [itemOrientInCell: Orientation];
For all orientationIndexes o1 and o2,
--DecomposeOrient[cellOrientInWorld: o1, itemOrientInWorld:
--ComposeOrient[cellOrientInWorld: o1, itemOrientInCell: o2]] = o2.
OrientedSize: PROC [size: CD.Position, orient: Orientation] RETURNS [CD.Position] =
--returns the size transformed by transformation "orient"
INLINE {RETURN
[IF IncludesOddRot90[orient] THEN [x: size.y, y: size.x] ELSE size]};
OrientedRect: PROC [rect: CD.Rect, orient: Orientation] RETURNS [CD.Rect] =
--returns the rect "rect" transformed by transformation "orient"
INLINE {RETURN
[IF IncludesOddRot90[orient] THEN
[x1: rect.x1, y1: rect.y1, x2: rect.x1+rect.y2-rect.y1, y2: rect.y1+rect.x2-rect.x1]
ELSE rect]};
RectAt: PROC [pos, size: CD.Position, orient: Orientation←original] RETURNS [CD.Rect] =
--returns a rect of size "size" at position "pos" and orientation "orient"
INLINE {RETURN [
IF IncludesOddRot90[orient] THEN CD.Rect[x1: pos.x, y1: pos.y, x2: pos.x+size.y, y2: pos.y+size.x]
ELSE CD.Rect[x1: pos.x, y1: pos.y, x2: pos.x+size.x, y2: pos.y+size.y]]};
IncludesOddRot90: PROC [orient: Orientation] RETURNS [BOOLEAN] =
--returns orient includes an odd multiple of 90 degree
TRUSTED INLINE {RETURN [PrincOpsUtils.BITAND[orient, rotate90]#0]};
IncludesOddRot45: PROC [orient: Orientation] RETURNS [BOOLEAN] =
--returns orient includes an odd multiple of 45 degree
TRUSTED INLINE {RETURN [FALSE]};
IncludesMirrorX: PROC [orient: Orientation] RETURNS [BOOLEAN] =
--returns orient includes some mirroring
TRUSTED INLINE {RETURN [PrincOpsUtils.BITAND[orient, mirrorX]#0]};
MirrorX: PROC [orient: Orientation] RETURNS [Orientation] =
--returns the orientation composed with mirror in x
TRUSTED INLINE {RETURN [PrincOpsUtils.BITXOR[orient, mirrorX]]};
Rotate90: PROC [orient: Orientation] RETURNS [Orientation] =
--returns the orientation composed with a clockwise rotation of 90 degree
TRUSTED INLINE {RETURN [PrincOpsUtils.BITAND[orient+rotate90, 7]]};
ConcentrateOnRotate90: PROC [orient: Orientation] RETURNS [Orientation] =
--discard mirroring
TRUSTED INLINE {RETURN [PrincOpsUtils.BITAND[orient, 6]]};
OrientateContext: PROC [cont: Imager.Context, size: CD.Position, orient: Orientation] =
-- if cont is an context drawing in object coordinates of an un-transformed object,
-- transforms cont such that it draws into an oriented object. (size=size of object)
INLINE BEGIN
SELECT ConcentrateOnRotate90[orient] FROM
-- ChipNDale rotates clockwise but graphics anticlockwise
-- but we do still not reverse rotation, because viewerpackage does
original =>
IF IncludesMirrorX[orient] THEN
{Imager.Scale2T[cont, [-1, 1]]; Imager.TranslateT[cont, [-size.x, 0]]};
rotate90 =>
BEGIN
Imager.RotateT[cont, 90]; Imager.TranslateT[cont, [0, -size.y]];
IF IncludesMirrorX[orient] THEN
{Imager.Scale2T[cont, [1, -1]]; Imager.TranslateT[cont, [0, -size.y]]};
END;
rotate180 =>
BEGIN
Imager.RotateT[cont, 180]; Imager.TranslateT[cont, [-size.x, -size.y]];
IF IncludesMirrorX[orient] THEN
{Imager.Scale2T[cont, [-1, 1]]; Imager.TranslateT[cont, [-size.x, 0]]};
END;
rotate270 =>
BEGIN
Imager.RotateT[cont, 270]; Imager.TranslateT[cont, [-size.x, 0]];
IF IncludesMirrorX[orient] THEN
{Imager.Scale2T[cont, [1, -1]]; Imager.TranslateT[cont, [0, -size.y]]};
END;
ENDCASE =>ERROR;
END;
CreateTransform: PROC [
cellSize: CD.Position,
cellInstOrient: CD.Orientation,
cellInstPos: CD.Position ← [0,0]]
RETURNS [Imager.Transformation];
-- Given the size of a cell,
-- the position and orientation of an instance of that cell in "world"
-- co-ordinates, returns the transformation to be applied to
-- cell points to get world points.
END.