GGShapesImpl.mesa
Author: Eric Bier on June 7, 1985 5:45:52 pm PDT
Last edited by Bier on January 14, 1987 2:42:41 pm PST
Contents: Predefined shapes for use in Gargoyle (e.g. squares for control points).
Pier, November 5, 1986 10:02:27 am PST
DIRECTORY
Draw2d, GGBasicTypes, GGCaret, GGInterfaceTypes, GGLines, GGModelTypes, GGShapes, GGVector, Imager, ImagerBackdoor, ImagerTransformation, Real;
GGShapesImpl:
CEDAR
PROGRAM IMPORTS Draw2d, GGLines, GGVector, Imager, ImagerBackdoor, Real
EXPORTS GGShapes = BEGIN
bitmapSize: INTEGER = 16;
bitmapRange: TYPE = [0..bitmapSize);
bitmapArray: TYPE = ARRAY bitmapRange OF CARDINAL;
anchorBits:
REF bitmapArray ←
NEW[bitmapArray ← [
1700B, 140603B, 177777B, 177777B,
177777B, 140603B, 600B, 600B,
600B, 600B, 100601B,140603B,
160607B, 177777B, 77776B, 37774B
]];
anchorBits2:
REF bitmapArray ←
NEW[bitmapArray ← [
176077B, 163147B, 170017B, 134035B,
117771B, 146063B, 044022B, 004020B,
004020B, 044022B, 146063B, 117771B,
134035B, 170017B, 163147B, 176077B
]];
caretBits:
REF bitmapArray ←
NEW[bitmapArray ← [
030000B, 030000B, 030000B, 044000B, 044000B, 102000B, 102000B, 102000B,
0, 0, 0, 0, 0, 0, 0, 0
]];
jointBits:
REF bitmapArray ←
NEW[bitmapArray ← [
176000B, 102000B, 132000B, 132000B, 102000B, 176000B, 0, 0,
125252B, 125252B, 125252B, 125252B,
125252B, 125252B, 125252B, 125252B
]];
cpBits:
REF bitmapArray ←
NEW[bitmapArray ← [
176000B, 102000B, 102000B, 102000B, 102000B, 176000B, 0, 0,
125252B, 125252B, 125252B, 125252B,
125252B, 125252B, 125252B, 125252B
]];
normalBits:
REF bitmapArray ←
NEW[bitmapArray ← [
176000B, 176000B, 176000B, 176000B, 176000B, 176000B, 0, 0,
125252B, 125252B, 125252B, 125252B,
125252B, 125252B, 125252B, 125252B
]];
hotBits:
REF bitmapArray ←
NEW[bitmapArray ← [
177700B, 100100B, 100100B, 100100B,
100100B, 100100B, 100100B, 100100B,
100100B, 177700B, 0, 0,
125252B, 125252B, 125252B, 125252B
]];
Circle: TYPE = GGBasicTypes.Circle;
Line: TYPE = GGBasicTypes.Line;
Point: TYPE = GGBasicTypes.Point;
Ray: TYPE = GGBasicTypes.Ray;
Vector: TYPE = GGBasicTypes.Vector;
SelectionClass: TYPE = GGInterfaceTypes.SelectionClass;
jointSize: INTEGER = Real.RoundI[GGModelTypes.jointSize];
halfJointSize: REAL = GGModelTypes.halfJointSize;
hotJointSize: INTEGER = Real.RoundI[GGModelTypes.hotJointSize];
halfHotJointSize: REAL = GGModelTypes.halfHotJointSize;
DrawSquare:
PUBLIC
PROC [dc: Imager.Context, center: Point, side:
REAL, strokeWidth:
REAL ← 1.0] = {
halfSide: REAL ← side/2.0;
DoDrawSquare:
PROC = {
SquarePath: Imager.PathProc = {
moveTo[[- halfSide, - halfSide]];
lineTo[[- halfSide, halfSide]];
lineTo[[ halfSide, halfSide]];
lineTo[[ halfSide, - halfSide]];
lineTo[[- halfSide, - halfSide]];
};
Imager.SetXY[dc, [center.x, center.y]];
Imager.Trans[dc];
Imager.SetStrokeWidth[dc, strokeWidth];
Imager.SetStrokeEnd[dc, round];
Imager.SetStrokeJoint[dc, round];
Imager.MaskStroke[dc, SquarePath, TRUE];
};
Imager.DoSaveAll[dc, DoDrawSquare];
};
DrawPlus:
PUBLIC
PROC [dc: Imager.Context, center: Point] = {
halfSide: REAL = 5.0;
DoDrawPlus:
PROC = {
Horiz: Imager.PathProc = {
moveTo[[-halfSide, 0.0]];
lineTo[[halfSide, 0.0]];
};
Vert: Imager.PathProc = {
moveTo[[0.0, -halfSide]];
lineTo[[0.0, halfSide]];
};
Imager.SetXY[dc, [center.x, center.y]];
Imager.Trans[dc];
Imager.SetStrokeWidth[dc, 2.0];
Imager.SetStrokeEnd[dc, round];
Imager.MaskStroke[dc, Horiz, FALSE];
Imager.MaskStroke[dc, Vert, FALSE];
};
Imager.DoSaveAll[dc, DoDrawPlus];
};
DrawRectangle:
PUBLIC
PROC [dc: Imager.Context, loX, loY, hiX, hiY:
REAL, strokeWidth:
REAL ← 1.0] = {
Draws the indicated rectangle (not filled).
DoDrawRect:
PROC = {
RectanglePath: Imager.PathProc = {
moveTo[[loX, loY]];
lineTo[[loX, hiY]];
lineTo[[ hiX, hiY]];
lineTo[[ hiX, loY]];
lineTo[[loX, loY]];
};
Imager.SetStrokeWidth[dc, strokeWidth];
Imager.SetStrokeEnd[dc, round];
Imager.SetStrokeJoint[dc, round];
Imager.MaskStroke[dc, RectanglePath, TRUE];
};
Imager.DoSaveAll[dc, DoDrawRect];
};
DrawCaret:
PUBLIC
PROC [dc: Imager.Context, point: Point] = {
halfWidth: REAL = GGCaret.caretWidth/2.0;
DoDrawCaret:
PROC = {
Imager.MaskBits[context: dc, base: LOOPHOLE[caretBits], wordsPerLine: 1,
sMin: 0, fMin: 0, sSize: 8, fSize: 6 , tx: Real.RoundI[point.x-halfWidth], ty: Real.RoundI[point.y] ];
};
Imager.DoSaveAll[dc, DoDrawCaret];
};
DrawAnchor:
PUBLIC
PROC [dc: Imager.Context, point: Point] =
TRUSTED {
halfHeight: REAL = GGCaret.anchorHeight/2.0;
halfWidth: REAL = GGCaret.anchorWidth/2.0;
DoDrawAnchor:
PROC =
TRUSTED {
Imager.MaskBits[context: dc, base: LOOPHOLE[anchorBits2], wordsPerLine: 1,
sMin: 0, fMin: 0, sSize: 16, fSize: 16 , tx: Real.RoundI[point.x-halfWidth], ty: Real.RoundI[point.y+halfHeight] ];
};
Imager.DoSaveAll[dc, DoDrawAnchor];
};
DrawFilledSquare:
PROC [dc: Imager.Context, center: Point, side:
REAL] = {
halfSide: REAL ← side/2.0;
DoDrawFilledSquare:
PROC = {
Imager.SetXY[dc, [center.x, center.y]]; -- set the current position
Imager.Trans[dc];
Imager.Move[dc]; -- move the origin to the current position
Imager.SetColor[dc, Imager.black];
Imager.MaskRectangle[dc, [- halfSide, - halfSide, side, side]];
};
Imager.DoSaveAll[dc, DoDrawFilledSquare];
};
DrawEmptySquare:
PROC [dc: Imager.Context, center: Point, side:
REAL] = {
halfSide:
REAL ← side/2.0;
DoDrawEmptySquare:
PROC = {
Imager.SetXY[dc, [center.x, center.y]]; -- set the current position
Imager.Trans[dc];
Imager.Move[dc]; -- move the origin to the current position
Imager.SetColor[dc, Imager.black];
Imager.MaskRectangle[dc, [- halfSide, - halfSide, side, side]];
Imager.SetColor[dc, Imager.white];
Imager.MaskRectangle[dc, [- halfSide+1, - halfSide+1, side-2, side-2]];
};
Imager.DoSaveAll[dc, DoDrawEmptySquare];
};
DrawSpot:
PUBLIC
PROC [dc: Imager.Context, point: Point] = {
DoDrawSpot:
PROC = {
Imager.SetXY[dc, [point.x, point.y]];
Imager.Trans[dc];
Imager.MaskRectangle[dc, [0.0, 0.0, 1.0, 1.0]];
};
Imager.DoSaveAll[dc, DoDrawSpot];
};
DrawFilledRect:
PUBLIC
PROC [dc: Imager.Context, point: Point, side:
REAL] = {
DoDrawRect:
PROC = {
Imager.SetXY[dc, [point.x, point.y]];
Imager.Trans[dc];
Imager.MaskRectangle[dc, [0.0, 0.0, side, side]];
};
Imager.DoSaveAll[dc, DoDrawRect];
};
DrawLine:
PUBLIC
PROC [dc: Imager.Context, line: Line, clippedBy: ImagerTransformation.Rectangle, strokeWidth:
REAL ← 1.0] = {
count: NAT;
ray: Ray;
params: ARRAY[1..2] OF REAL;
p1, p2, basePoint: Point;
direction: Vector;
DoDrawLine:
PROC = {
Imager.SetXY[dc, [p1.x, p1.y]];
Imager.Trans[dc];
Imager.Move[dc];
Imager.SetStrokeEnd[dc, round];
Imager.SetStrokeWidth[dc, strokeWidth];
Imager.MaskVector[dc, [0.0, 0.0], [p2.x - p1.x, p2.y - p1.y]];
Draw2d.Line[dc, [0.0, 0.0], [p2.x - p1.x, p2.y - p1.y], solid];
};
p1 ← [clippedBy.x, clippedBy.y];
p2 ← [clippedBy.x + clippedBy.w, clippedBy.y + clippedBy.h];
basePoint ← GGLines.PointOnLine[line];
direction ← GGLines.DirectionOfLine[line];
ray ← GGLines.CreateRay[basePoint, direction];
[count, params] ← GGLines.LineRayMeetsBox[ray, p1.x, p1.y, p2.x, p2.y];
IF count = 2
THEN {
p1 ← GGLines.EvalRay[ray, params[1]];
p2 ← GGLines.EvalRay[ray, params[2]];
Imager.DoSaveAll[dc, DoDrawLine];
};
};
DrawLittleLine:
PUBLIC
PROC [dc: Imager.Context, line: Line, point: Point] = {
Draw a short line (1 inch) centered on point, parallel to line.
};
DrawCircle:
PUBLIC
PROC [dc: Imager.Context, circle: Circle] = {
leftSide, rightSide: Point;
DoDrawCircle:
PROC = {
CirclePath: Imager.PathProc = {
moveTo[[leftSide.x, leftSide.y]];
arcTo[[rightSide.x, rightSide.y], [ leftSide.x, leftSide.y]];
};
Imager.SetStrokeWidth[dc, 1.0];
Imager.SetStrokeEnd[dc, round];
Imager.MaskStroke[dc, CirclePath, TRUE];
};
leftSide ← [circle.origin.x - circle.radius, circle.origin.y];
rightSide ← [circle.origin.x + circle.radius, circle.origin.y];
Imager.DoSaveAll[dc, DoDrawCircle];
};
useBitmaps: BOOL ← FALSE; -- KAP. October 13, 1986
DrawCP:
PUBLIC
PROC [dc: Imager.Context, point: Point] = {
IF useBitmaps THEN ImagerBackdoor.DrawBits[context: dc, base: LOOPHOLE[cpBits], wordsPerLine: 1, sMin: 0, fMin: 0, sSize: jointSize, fSize: jointSize, tx: Real.RoundI[point.x-halfJointSize], ty: Real.RoundI[point.y+halfJointSize] ]
ELSE DrawEmptySquare[dc, point, jointSize];
};
DrawJoint:
PUBLIC
PROC [dc: Imager.Context, point: Point] = {
IF useBitmaps THEN ImagerBackdoor.DrawBits[context: dc, base: LOOPHOLE[jointBits], wordsPerLine: 1, sMin: 0, fMin: 0, sSize: jointSize, fSize: jointSize , tx: Real.RoundI[point.x-halfJointSize], ty: Real.RoundI[point.y+halfJointSize] ]
ELSE {
DrawEmptySquare[dc, point, jointSize];
DrawFilledSquare[dc, point, 2.0];
};
};
DrawSelectedJoint:
PUBLIC
PROC [dc: Imager.Context, point: Point, selectClass: SelectionClass] = {
IF useBitmaps
THEN
IF selectClass=hot THEN ImagerBackdoor.DrawBits[context: dc, base: LOOPHOLE[hotBits], wordsPerLine: 1, sMin: 0, fMin: 0, sSize: hotJointSize, fSize: hotJointSize , tx: Real.RoundI[point.x-halfHotJointSize], ty: Real.RoundI[point.y+halfHotJointSize] ]
ELSE IF selectClass=normal THEN ImagerBackdoor.DrawBits[context: dc, base: LOOPHOLE[normalBits], wordsPerLine: 1, sMin: 0, fMin: 0, sSize: jointSize, fSize: jointSize, tx: Real.RoundI[point.x-halfJointSize], ty: Real.RoundI[point.y+halfJointSize] ]
ELSE ImagerBackdoor.DrawBits[context: dc, base: LOOPHOLE[jointBits], wordsPerLine: 1, sMin: 0, fMin: 0, sSize: jointSize, fSize: jointSize , tx: Real.RoundI[point.x-halfJointSize], ty: Real.RoundI[point.y+halfJointSize] ]
ELSE
IF selectClass=hot THEN DrawEmptySquare[dc, point, hotJointSize]
ELSE IF selectClass=normal THEN DrawFilledSquare[dc, point, jointSize]
ELSE {DrawEmptySquare[dc, point, jointSize]; DrawFilledSquare[dc, point, 2.0]};
};
DrawArrow:
PUBLIC
PROC [dc: Imager.Context, tip: Point, base: Point, strokeWidth:
REAL] = {
OPEN GGVector;
DrawArrowAux: Imager.PathProc = {
moveTo[tip];
lineTo[Sub[tip, Add[Scale[axis, height], Scale[perp, halfWidth]]]];
lineTo[Sub[tip, Add[Scale[axis, height], Scale[perp, -halfWidth]]]];
lineTo[tip];
};
axis: Vector;
perp: Vector;
height: REAL ← strokeWidth+5.0;
halfWidth: REAL ← strokeWidth+3.0;
IF tip = base THEN RETURN;
axis ← GGVector.Normalize[GGVector.Sub[tip, base]];
perp ← [axis.y, -axis.x];
Imager.MaskFill[context: dc, path: DrawArrowAux, parity: FALSE]
};
ArrowSize:
PUBLIC
PROC [strokeWidth:
REAL]
RETURNS [height, halfWidth:
REAL] = {
The arrowhead will fit in a box of size height by (halfWidth*2).
height ← strokeWidth+5.0;
halfWidth ← strokeWidth+3.0;
};
END.