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, December 18, 1984 9:57:58 am PST
some code from "ChipOrient" E. McCreight, February 22, 1982 10:00 AM
DIRECTORY
PrincOpsUtils,
CD,
Graphics;
CDOrient: CEDAR DEFINITIONS
IMPORTS Graphics, 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: Graphics.Context, size: CD.DesignPosition, 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
{Graphics.Scale[cont, -1, 1]; Graphics.Translate[cont, -size.x, 0]};
rotate90 =>
BEGIN
Graphics.Rotate[cont, 90]; Graphics.Translate[cont, 0, -size.y];
IF IncludesMirrorX[orient] THEN
{Graphics.Scale[cont, 1, -1]; Graphics.Translate[cont, 0, -size.y]};
END;
rotate180 =>
BEGIN
Graphics.Rotate[cont, 180]; Graphics.Translate[cont, -size.x, -size.y];
IF IncludesMirrorX[orient] THEN
{Graphics.Scale[cont, -1, 1]; Graphics.Translate[cont, -size.x, 0]};
END;
rotate270 =>
BEGIN
Graphics.Rotate[cont, 270]; Graphics.Translate[cont, -size.x, 0];
IF IncludesMirrorX[orient] THEN
{Graphics.Scale[cont, 1, -1]; Graphics.Translate[cont, 0, -size.y]};
END;
ENDCASE =>ERROR;
END;
END.