ImagerExamplesImpl.mesa
Copyright (C) 1985, Xerox Corporation. All rights reserved.
Michael Plass, September 6, 1985 10:32:36 am PDT
DIRECTORY Vector2, Imager, ImagerFont, Rope, ImagerPath, Interpress, ImagerColor, ImagerViewer, ImagerInterpress, ImagerPixelArray, ImagerColorOperator, ImagerTransformation;
ImagerExamplesImpl: CEDAR PROGRAM
IMPORTS Imager, ImagerColor, ImagerFont, ImagerPath, ImagerViewer, ImagerInterpress, ImagerPixelArray, ImagerColorOperator, ImagerTransformation
~ BEGIN
Context: TYPE ~ Imager.Context;
VEC: TYPE ~ Vector2.VEC;
Font: TYPE ~ ImagerFont.Font;
ROPE: TYPE ~ Rope.ROPE;
helveticaI: Imager.Font ~ ImagerFont.Scale[ImagerFont.Find["xerox/pressfonts/helvetica-mir"], 0.01];
timesRomanBI: Imager.Font ~ ImagerFont.Scale[ImagerFont.Find["xerox/pressfonts/timesroman-bir"], 0.01];
This is how to make a font, and scale it to the desired size. To find the fonts that are available, list files matching the pattern
 []<>Fonts>Xerox>*
The filename extension (.sd, .ks, etc.) of these files tell the Imager what kind of file to expect and are not part of the font name. The PressFonts end in three-letter suffixes to designate the face, i.e.,
 -mrr Medium Roman
 -mir Medium Italic
 -brr Bold Roman
 -bir Bold Italic
(The third letter can designate condensed or expanded fonts, but we don't have any of these.) A PressFont is by default one unit high in whatever coordinate system your program is working in; in this case, we will be working in the initial meters coordinate system, so we scale it by a factor of 0.01 to get a font 1 cm high.
The TiogaFonts end in a size and face designation, with no dashes, i.e., Xerox/TiogaFonts/Helvetica8BI. These are bitmap fonts and assume you are working in a one-unit-per-pixel upright coordinate system; if this is the case, you do not need to scale the fonts before use. You may, of course, still scale or the fonts, if you so desire.
Note that these font names are not part of the accepted Xerox Network Systems font naming scheme. We will be moving in that direction, but this is what we have for now.
Text: PROC [context: Imager.Context] ~ {
A simple example of text; just say what font you want, where you want to say it, and what you want to say. The Imager remembers the current position after the first piece of text, so to continue the same line, a second SetXY is not needed.
Imager.SetFont[context, timesRomanBI];
Imager.SetXY[context, [0.02, 0.0375]];
Imager.ShowRope[context, "Here is some "];
Imager.SetFont[context, helveticaI];
Imager.ShowRope[context, "text"];
};
Rectangles: PROC [context: Imager.Context] ~ {
Three ways of saying the same thing; note the use of DoSaveAll to save and restore the transformation around the section of code that modifies it.
Imager.MaskRectangle[context, [x: 0.04, y: 0.06, w: 0.03, h: 0.01]];
Imager.MaskBox[context, [xmin: 0.04, ymin: 0.06, xmax: 0.07, ymax: 0.07]];
{proc: PROC ~ {
Imager.ScaleT[context, 0.01];
Imager.MaskRectangleI[context, 4, 6, 3, 1];
}; Imager.DoSaveAll[context, proc]};
};
Path: Imager.PathProc ~ {
Here is a procedure that encodes a path consisting of two pieces; a straigh line and an arc, and two straight lines. Since everything is constant here, this is a global procedure, but it could just as well have been a local procedure if the client needed to compute the coordinates dynamically.
moveTo[[0,0]];
lineTo[[100, 0]];
arcTo[[70.7, 70.7], [0,100]];
moveTo[[60, 60]];
lineTo[[100, 80]];
lineTo[[90, 100]];
};
Fills: PROC [context: Imager.Context] ~ {
Uses the PathProc to do a filled area.
p: Vector2.VEC ← [0,0];
proc: PROC ~ {
Imager.ScaleT[context, 0.0005];
Imager.TranslateT[context, p];
Imager.MaskFill[context, Path];
};
p ← [200, 75];
Imager.DoSave[context, proc];
};
joints: Imager.StrokeJoint ← mitered;
Strokes: PROC [context: Imager.Context] ~ {
This does four instances of the path, generating wide strokes.
p: Vector2.VEC ← [0,0];
closed: BOOLFALSE;
proc: PROC ~ {
Imager.ScaleT[context, 0.0005];
Imager.TranslateT[context, p];
Imager.MaskStroke[context, Path, closed];
};
p ← [50, 200];
Imager.SetStrokeJoint[context, joints];
Imager.SetStrokeWidth[context, 8];
Imager.SetStrokeEnd[context, butt];
Imager.DoSave[context, proc];
p ← [200, 200];
Imager.SetStrokeEnd[context, round];
Imager.DoSave[context, proc];
p ← [50, 325];
Imager.SetStrokeEnd[context, square];
Imager.DoSave[context, proc];
p ← [200, 325];
closed ← TRUE;
Imager.DoSave[context, proc];
};
Bits: PROC [context: Imager.Context] ~ {
This does a bitmap example.
MaskPixel is another way to do bitmaps, if you have a PixelArray handy.
The approach here is useful if you have some raw bits handy.
The bitmap is interpreted in row-major order, so in an upright coordinate system, they will appear in the same orientation as they do here in the declaration.
proc: PROC ~ {
o: [0..1] ~ 0;
x, X: [0..1] ~ 1;
The bitmap is interpreted in row-major order, so in an upright coordinate system, they will appear in the same orientation as they do here in the declaration. With the MaskBits parameters used below, the big X bit should just touch corners with the lower right part of the reference rectangle.
bits: ARRAY [0..10) OF PACKED ARRAY [0..16) OF [0..1] ← [
[ x, x, x, x, o, o, o, o, o, o, o, o, o, o, o, x ],
[ x, x, x, x, o, o, o, o, o, o, o, o, o, o, o, x ],
[ x, X, o, o, o, o, o, o, o, o, o, o, o, o, o, x ],
[ x, o, x, x, x, o, o, x, o, o, x, o, o, o, o, x ],
[ x, o, x, o, o, x, o, o, o, x, x, x, o, o, o, x ],
[ o, o, x, o, x, o, x, x, o, o, x, o, o, x, x, o ],
[ o, o, x, x, x, o, o, x, o, o, x, o, x, o, o, o ],
[ o, o, x, o, o, x, o, x, o, o, x, o, o, x, o, o ],
[ o, o, x, o, o, x, o, x, o, o, x, o, o, o, x, o ],
[ o, o, x, x, x, o, x, x, x, o, o, x, x, x, x, o ]
];
Imager.ScaleT[context, 0.0254/72]; -- 72-per-inch points;
Imager.TranslateT[context, [72, (11-1)*72]]; -- origin at 1 inch in from top and left margins
Imager.ScaleT[context, 5]; -- talk in 5 point units
Imager.MaskRectangleI[context, 0, 0, 3, -2]; -- put down a rectangle as a reference
TRUSTED {
base: LONG POINTER ~ @bits;
Imager.MaskBits[
context: context,
base: base,
wordsPerLine: SIZE[PACKED ARRAY [0..16) OF [0..1]],
sMin: 2, -- The number of lines to skip (from the top)
fMin: 1, -- The number of bits to skip (from the left)
sSize: 8, -- The number of lines to use
fSize: 14, -- The number of bits to use
tx: 3, ty: -2 -- tells where the reference point of the bitmap goes, in client coordinates
];
};
};
Imager.DoSave[context, proc];
};
Masks: PROC [context: Imager.Context] ~ {
Does this example page (shown here reduced by a factor of 5):
Interpress Artwork: []<>Plass>6.0>ImagerExamples.ip!13 scale: 0.2
(Say "ArtworkInterpress on" to a command tool if the above just looks like text).
font: Font ~ ImagerFont.Find["xerox/pressfonts/helvetica-brr"];
inner1: PROC ~ {
rope: ROPE ~ "Mask Examples";
scaledFont: Font ~ ImagerFont.Scale[font, 0.3];
ropeWidth: VEC ~ ImagerFont.RopeWidth[scaledFont, rope];
Imager.ScaleT[context, 0.0254];
Imager.SetColor[context, Imager.black];
Imager.SetXY[context, [8.5/2-ropeWidth.x/2, 9.5]];
Imager.SetFont[context, scaledFont];
Imager.ShowRope[context, rope];
};
inner2: PROC ~ {
Imager.TranslateT[context, [8.5*0.0254/2-0.0005*(50+300)/2, 0]];
Text[context];
Rectangles[context];
Fills[context];
Strokes[context];
Bits[context];
};
Imager.DoSave[context, inner1];
Imager.DoSave[context, inner2];
};
TriangleX: PROC [context: Context, p0, p1, p2: VEC, w: REAL] ~ {
One way of making a triangle, using a Trajectory.
t: ImagerPath.Trajectory ← ImagerPath.MoveTo[p0];
t ← ImagerPath.LineTo[t, p1];
t ← ImagerPath.LineTo[t, p2];
Imager.SetStrokeWidth[context, w];
Imager.MaskStrokeTrajectory[context: context, trajectory: t, closed: TRUE];
};
Triangle: PROC [context: Context, p0, p1, p2: VEC, w: REAL] ~ {
A better way to do the same thing, using a PathProc.
Path: Imager.PathProc ~ {moveTo[p0]; lineTo[p1]; lineTo[p2]};
Imager.SetStrokeWidth[context, w];
Imager.MaskStroke[context: context, path: Path, closed: TRUE];
};
TriangleSpiral: PROC [context: Context, p0, p1, p2, center: VEC, w: REAL] ~ {
Does a spiral of triangles.
inner: PROC ~ {
Imager.TranslateT[context, center];
FOR i: NAT IN [0..10) DO
Triangle[context, p0, p1, p2, w];
Imager.RotateT[context, -40];
Imager.ScaleT[context, 0.8];
w ← w/0.8;
ENDLOOP;
};
Imager.DoSave[context, inner];
};
TitledSpiral: PROC [context: Imager.Context] ~ {
Does this page (shown here reduced by a factor of 5):
Interpress Artwork: []<>Plass>6.0>ImagerExamples.ip!1 scale: 0.2
font: Font ~ ImagerFont.Find["xerox/pressfonts/helvetica-brr"];
inner: PROC ~ {
rope: ROPE ~ "Spiral of Triangles";
scaledFont: Font ~ ImagerFont.Scale[font, 0.3];
ropeWidth: VEC ~ ImagerFont.RopeWidth[scaledFont, rope];
Imager.ScaleT[context, 0.0254];
Imager.SetColor[context, Imager.black];
TriangleSpiral[context, [1.0, 0.25], [1.25, -0.5], [1.75, 2.0], [8.5/2, 11.0/2], 0.05];
Imager.SetXY[context, [8.5/2-ropeWidth.x/2, 9.5]];
Imager.SetFont[context, scaledFont];
Imager.ShowRope[context, rope];
};
Imager.DoSave[context, inner];
};
ColorSpiral: PROC [context: Imager.Context] ~ {
Does this page (shown here reduced by a factor of 5):
inner: PROC ~ {
w: REAL ← 0.1;
Imager.ScaleT[context, 0.0254];
Imager.TranslateT[context, [8.5/2, 11.0/2]];
FOR i: NAT IN [0..10) DO
hsv: ImagerColor.HSV ~ [H: i/9.0, S: 0.8, V: 1.0];
rgb: ImagerColor.RGB ~ ImagerColor.RGBFromHSV[hsv];
Imager.SetColor[context, ImagerColor.ColorFromRGB[rgb]];
Triangle[context, [1.0, 0.25], [1.25, -0.5], [1.75, 2.0], w];
Imager.RotateT[context, -40];
Imager.ScaleT[context, 0.8];
w ← w/0.8;
ENDLOOP;
};
Imager.DoSave[context, inner];
};
rgbLinear: Imager.ColorOperator ~ ImagerColorOperator.RGBLinearColorModel[255];
Drip: PROC [context: Imager.Context] ~ {
inner: PROC ~ {
Imager.ScaleT[context, 0.0254/72];
Imager.SetSampledColor[context: context, pa: dripPA, m: ImagerTransformation.Scale[2], colorOperator: rgbLinear];
Imager.ScaleT[context, 72];
Imager.MaskBox[context, [1, 1, 7.5, 10]];
};
Imager.DoSave[context, inner];
};
dripPA: Imager.PixelArray ← ImagerPixelArray.Join3AIS["Umbrella-red.ais", "Umbrella-grn.ais", "Umbrella-blu.ais"];
Run: PROC ~ {
viewerContext: Context ← ImagerViewer.Create[[name: "Imager Example", column: left, iconic: FALSE], meters];
A way of getting a context that will go to a viewer without any re-display logic, useful for debugging paint procedures.
interpress: ImagerInterpress.Ref ← ImagerInterpress.Create["ImagerExamples.ip"];
This is where the output will go.
ImagerInterpress.DeclareColorOperator[interpress, rgbLinear];
ImagerInterpress.DeclarePixelArray[interpress, dripPA];
Putting things in the preamble is often a good idea (unless, of course, they are not used!)
joints ← mitered;
ImagerViewer.Erase[viewerContext]; Masks[viewerContext];
ImagerInterpress.DoPage[interpress, Masks];
joints ← round;
ImagerViewer.Erase[viewerContext]; Masks[viewerContext];
ImagerInterpress.DoPage[interpress, Masks];
ImagerViewer.Erase[viewerContext]; TitledSpiral[viewerContext];
ImagerInterpress.DoPage[interpress, TitledSpiral];
ImagerViewer.Erase[viewerContext]; ColorSpiral[viewerContext];
ImagerInterpress.DoPage[interpress, ColorSpiral];
ImagerViewer.Erase[viewerContext]; Drip[viewerContext];
ImagerInterpress.DoPage[interpress, Drip];
ImagerInterpress.Close[interpress];
};
END.