File: SVDrawImpl.mesa
Last edited by Bier on May 31, 1984 4:10:03 pm PDT
Author: Eric Bier on February 23, 1987 2:08:14 pm PST
Contents: Some convenience functions to draw shapes not directly available in Cedar Imager
DIRECTORY
Imager, ImagerBackdoor, ImagerPath, Real, SV2d, SVDraw, SVLines2d, SVVector2d;
SVDrawImpl: CEDAR PROGRAM
IMPORTS Imager, ImagerBackdoor, ImagerPath, Real, SVLines2d, SVVector2d
EXPORTS SVDraw =
BEGIN
Point2d: TYPE = SV2d.Point2d;
Polygon: TYPE = SV2d.Polygon;
globalSandwich: ImagerPath.Trajectory;
DrawLine: PROC [dc: Imager.Context, fromX, fromY, toX, toY: REAL] = {
Imager.MaskVector[dc, [fromX, fromY], [toX, toY]];
};
Cross: PUBLIC PROC [dc: Imager.Context, originX, originY, length: REAL] = {
halfLength: REAL ← length/2.0;
DrawLine[dc, originX-halfLength, originY, originX+halfLength, originY];
DrawLine[dc, originX, originY-halfLength, originX, originY+halfLength];
};
centerLine: SV2d.TrigLine ← SVLines2d.CreateEmptyTrigLine[];
LineSandwich: PUBLIC PROC [dc: Imager.Context, fromX, fromY, toX, toY: REAL] = {
leftFirst, leftSecond, rightFirst, rightSecond: Point2d;
Draw two parallel lines, so that the total width is three screen dots. This requires that we calculate the points with are 1 unit from the given central line segment and normal to that line segment.
Find the left and right segments given the center segment
path: ImagerPath.Trajectory;
SVLines2d.FillTrigLineFromPoints[[fromX, fromY], [toX, toY], centerLine];
leftFirst ← SVLines2d.PointLeftOfTrigLine[1, [fromX, fromY], centerLine];
leftSecond ← SVLines2d.PointLeftOfTrigLine[1, [toX, toY], centerLine];
rightFirst ← SVVector2d.Add[SVVector2d.Sub[[fromX, fromY], leftFirst], [fromX, fromY]];
rightSecond ← SVVector2d.Add[SVVector2d.Sub[[toX, toY], leftSecond], [toX, toY]];
Now draw the left line
path ← ImagerPath.MoveTo[[leftFirst[1], leftFirst[2]]];
path ← ImagerPath.LineTo[path, [leftSecond[1], leftSecond[2]]];
Imager.SetStrokeWidth[dc, 1.0];
Imager.SetStrokeEnd[dc, square];
Imager.MaskStrokeTrajectory[dc, path];
Finally, draw the right line
path ← ImagerPath.MoveTo[[rightFirst[1], rightFirst[2]]];
path ← ImagerPath.LineTo[path, [rightSecond[1], rightSecond[2]]];
Imager.MaskStrokeTrajectory[dc, path];
};
LineSandwich: PUBLIC PROC [dc: Imager.Context, fromX, fromY, toX, toY: REAL] = {
leftFirst, leftSecond, rightFirst, rightSecond: Point2d;
Draw three parallel lines, 2 black with 1 white in between so that the total width is three screen dots. This requires that we calculate the points with are 1 unit from the given central line segment and normal to that line segment.
Find the left and right segments given the center segment
path: ImagerPath.Trajectory;
SVLines2d.FillTrigLineFromPoints[[fromX, fromY], [toX, toY], centerLine];
leftFirst ← SVLines2d.PointLeftOfTrigLine[1, [fromX, fromY], centerLine];
leftSecond ← SVLines2d.PointLeftOfTrigLine[1, [toX, toY], centerLine];
rightFirst ← SVVector2d.Add[SVVector2d.Sub[[fromX, fromY], leftFirst], [fromX, fromY]];
rightSecond ← SVVector2d.Add[SVVector2d.Sub[[toX, toY], leftSecond], [toX, toY]];
Now draw the left line
Imager.SetColor[dc, Imager.black]; -- black
path ← ImagerPath.MoveTo[[leftFirst[1], leftFirst[2]]];
path ← ImagerPath.LineTo[path, [leftSecond[1], leftSecond[2]]];
Imager.SetStrokeWidth[dc, 1.0];
Imager.SetStrokeEnd[dc, square];
Imager.MaskStrokeTrajectory[dc, path];
Now draw the center line
Imager.SetColor[dc, Imager.white]; -- white
path ← ImagerPath.MoveTo[[fromX, fromY]];
path ← ImagerPath.LineTo[path, [toX, toY]];
Imager.MaskStrokeTrajectory[dc, path];
Finally, draw the right line
Imager.SetColor[dc, Imager.black]; -- black
path ← ImagerPath.MoveTo[[rightFirst[1], rightFirst[2]]];
path ← ImagerPath.LineTo[path, [rightSecond[1], rightSecond[2]]];
Imager.MaskStrokeTrajectory[dc, path];
};

PadToScreen: PUBLIC PROC [padPoint: Point2d, origin: Point2d, scalar: REAL ← 1] RETURNS [screenPoint: Point2d] = {
padPoint ← SVVector2d.Scale[padPoint, scalar];
screenPoint[1] ← padPoint[1] + origin[1];
screenPoint[2] ← padPoint[2] + origin[2];
};
CrossHairs: PUBLIC PROC [dc: Imager.Context, origin: Point2d] = {
leftPoint, rightPoint, topPoint, bottomPoint, screenPoint: Point2d;
leftPoint ← [-1000, 0];
rightPoint ← [1000, 0];
topPoint ← [0, 1000];
bottomPoint ← [0, -1000];
screenPoint ← PadToScreen[leftPoint, origin];
globalSandwich ← ImagerPath.MoveTo[[screenPoint[1], screenPoint[2]]];
screenPoint ← PadToScreen[rightPoint, origin];
globalSandwich ← ImagerPath.LineTo[globalSandwich, [screenPoint[1], screenPoint[2]]];
Imager.SetStrokeWidth[dc, 0];
Imager.SetStrokeEnd[dc, square];
Imager.MaskStrokeTrajectory[dc, globalSandwich, FALSE];
screenPoint ← PadToScreen[topPoint, origin];
globalSandwich ← ImagerPath.MoveTo[[screenPoint[1], screenPoint[2]]];
screenPoint ← PadToScreen[bottomPoint, origin];
globalSandwich ← ImagerPath.LineTo[globalSandwich, [screenPoint[1], screenPoint[2]]];
Imager.SetStrokeWidth[dc, 0];
Imager.SetStrokeEnd[dc, square];
Imager.MaskStrokeTrajectory[dc, globalSandwich, FALSE];
};
DrawPolygon: PUBLIC PROC [dc: Imager.Context, poly: Polygon, origin: Point2d, scalar: REAL ← 1] = {
poly is in Pad coordinates
transform each point to screen coordinates and draw using Imager.
screenPoint0, screenPoint1, screenPoint2: Point2d;
IF poly.len <= 1 THEN RETURN;
screenPoint0 ← screenPoint1 ← PadToScreen[poly[0], origin, scalar];
FOR i: NAT IN [1..poly.len) DO
screenPoint2 ← PadToScreen[poly[i], origin, scalar];
LineSandwich[dc, screenPoint1[1], screenPoint1[2], screenPoint2[1], screenPoint2[2]];
screenPoint1 ← screenPoint2;
ENDLOOP;
LineSandwich[dc, screenPoint1[1], screenPoint1[2], screenPoint0[1], screenPoint0[2]];
};
bitmapArray: TYPE = ARRAY bitmapRange OF CARDINAL;
bitmapRange: TYPE = [0..bitmapSize);
bitmapSize: INTEGER = 16;
caretBits: REF bitmapArray ← NEW[bitmapArray ← [
030000B, 030000B, 030000B, 044000B, 044000B, 102000B, 102000B, 102000B,
0, 0, 0, 0, 0, 0, 0, 0
]];
DrawCaret: PUBLIC PROC [dc: Imager.Context, point: Point2d] = {
halfWidth: REAL = 3.0;
DoDrawCaret: PROC = {
ImagerBackdoor.MaskBits[context: dc, base: LOOPHOLE[caretBits], wordsPerLine: 1,
sMin: 0, fMin: 0, sSize: 8, fSize: 6, tx: Real.Round[point[1]-halfWidth], ty: Real.Round[point[2]] ];
};
Imager.DoSaveAll[dc, DoDrawCaret];
};
END.