ImagerImpl.mesa
Michael Plass, May 3, 1984 5:15:47 pm PDT
Doug Wyatt, November 23, 1983 1:54 pm
DIRECTORY
Atom USING [GetProp, PutProp, PropList, DottedPairNode],
Basics USING [bitsPerWord],
Font USING [CreateScaled],
Imager USING [Context, ContextRep, defaultStrokeEnd, defaultStrokeWidth, ErrorCode, FONT, Outline, OutlineRep, Polygon, RopeOrRefText, Trajectory, TrajectoryRep],
ImagerBasic USING [Color, ColorRep, ConstantColor, IntPair, IntRectangle, Pair, PathMapType, PixelArray, StrokeEnd, Transformation, Visibility],
ImagerConic USING [FromArc],
ImagerMasks USING [PixelArrayFromPixelMap],
ImagerPixelMaps USING [Create, PixelMap],
ImagerPrivate USING [Class],
ImagerTransform,
PrincOps USING [BBTableSpace, BBptr],
PrincOpsUtils USING [AlignedBBTable, BITBLT],
Real USING [RoundLI],
Rope USING [ROPE];
ImagerImpl: CEDAR PROGRAM
IMPORTS Atom, Font, ImagerConic, ImagerMasks, ImagerPixelMaps, ImagerTransform, PrincOpsUtils, Real
EXPORTS Imager, ImagerPrivate
= BEGIN OPEN Imager, ImagerBasic;
Types
Class: TYPE = ImagerPrivate.Class;
Errors
Error: PUBLIC ERROR [errorCode: ErrorCode] ~ CODE;
Creation
imagerRegistrationKey: ATOM ~ $ImagerDeviceClass;
RegisterDevice: PUBLIC PROC [class: ImagerPrivate.Class] ~ {
Atom.PutProp[class.deviceType, imagerRegistrationKey, class];
};
Create: PUBLIC PROC[deviceType: ATOM, data: REF] RETURNS [context: Context] ~ {
WITH Atom.GetProp[deviceType, imagerRegistrationKey] SELECT FROM
class: Class => {
context ← NEW[ContextRep ← [class: class, data: NIL]];
class.Init[context, data];
};
ENDCASE => Error[$UnimplementedDevice];
};
Imager state
DoSave: PUBLIC PROC[context: Context, body: PROC] = {
class: Class = NARROW[context.class];
class.DoSave[context, body];
};
DoSaveAll: PUBLIC PROC[context: Context, body: PROC] = {
class: Class = NARROW[context.class];
class.DoSaveAll[context, body];
};
SetPriorityImportant: PUBLIC PROC[context: Context, priorityImportant: BOOL] = {
class: Class = NARROW[context.class];
class.ISetInt[context, $priorityImportant, IF priorityImportant THEN 1 ELSE 0];
};
Transformations
pointsToMeters: PUBLIC Transformation ← ImagerTransform.Scale[0.0254/72.27];
micasToMeters: PUBLIC Transformation ← ImagerTransform.Scale[0.00001];
MakeT: PUBLIC PROC[a, b, c, d, e, f: REAL] RETURNS[Transformation] ~ {
RETURN [ImagerTransform.Create[a, b, c, d, e, f]]
};
OpenT: PUBLIC PROC[m: Transformation] RETURNS[a, b, c, d, e, f: REAL] ~ {
[[a, b, c, d, e, f]] ← ImagerTransform.Contents[m];
};
Translate: PUBLIC PROC[x, y: REAL] RETURNS[Transformation] ~ {
RETURN [ImagerTransform.Translate[x, y]]
};
Scale: PUBLIC PROC[s: REAL] RETURNS[Transformation] ~ {
RETURN [ImagerTransform.Scale[s]];
};
Scale2: PUBLIC PROC[sx, sy: REAL] RETURNS[Transformation] ~ {
RETURN [ImagerTransform.Scale2[sx, sy]];
};
Rotate: PUBLIC PROC[a: REAL] RETURNS[Transformation] ~ {
RETURN [ImagerTransform.Rotate[a]]
};
Concat: PUBLIC PROC[m, n: Transformation] RETURNS[Transformation] ~ {
RETURN [ImagerTransform.Concat[m, n]]
};
Invert: PUBLIC PROC[m: Transformation] RETURNS[Transformation] ~ {
RETURN [ImagerTransform.Invert[m]]
};
Transform: PUBLIC PROC[m: Transformation, p: Pair] RETURNS[Pair] ~ {
RETURN [ImagerTransform.Transform[p, m]]
};
TransformVec: PUBLIC PROC[m: Transformation, p: Pair] RETURNS[Pair] ~ {
RETURN [ImagerTransform.TransformVec[p, m]]
};
RoundXY: PUBLIC PROC[m: Transformation, p: Pair] RETURNS[Pair] ~ {
RETURN [ImagerTransform.InverseTransform[DRound[ImagerTransform.Transform[p, m]], m]]
};
RoundXYVec: PUBLIC PROC[m: Transformation, p: Pair] RETURNS[Pair] ~ {
RETURN [ImagerTransform.InverseTransformVec[DRound[ImagerTransform.TransformVec[p, m]], m]]
};
ConcatT: PUBLIC PROC[context: Context, m: Transformation] = {
class: Class = NARROW[context.class];
class.ConcatT[context, m];
};
TranslateT: PUBLIC PROC[context: Context, x, y: REAL] = {
class: Class = NARROW[context.class];
class.TranslateT[context, x, y];
};
RotateT: PUBLIC PROC[context: Context, a: REAL] = {
class: Class = NARROW[context.class];
class.RotateT[context, a];
};
ScaleT: PUBLIC PROC[context: Context, s: REAL] = {
class: Class = NARROW[context.class];
class.ScaleT[context, s];
};
Scale2T: PUBLIC PROC[context: Context, sx, sy: REAL] = {
class: Class = NARROW[context.class];
class.Scale2T[context, sx, sy];
};
Move: PUBLIC PROC[context: Context] = {
class: Class = NARROW[context.class];
class.Move[context];
};
Trans: PUBLIC PROC[context: Context] = {
class: Class = NARROW[context.class];
class.Trans[context];
};
Current position operators
SetXY: PUBLIC PROC[context: Context, p: Pair] = {
class: Class = NARROW[context.class];
class.SetXY[context, p];
};
IntegerSetXY: PUBLIC PROC[context: Context, x, y: INTEGER] = {
class: Class = NARROW[context.class];
class.IntegerSetXY[context, x, y];
};
SetXYRel: PUBLIC PROC[context: Context, v: Pair] = {
class: Class = NARROW[context.class];
class.SetXYRel[context, v];
};
IntegerSetXYRel: PUBLIC PROC[context: Context, x, y: INTEGER] = {
class: Class = NARROW[context.class];
class.IntegerSetXYRel[context, x, y];
};
SetXRel: PUBLIC PROC[context: Context, x: REAL] = {
class: Class = NARROW[context.class];
class.SetXYRel[context, [x, 0]];
};
IntegerSetXRel: PUBLIC PROC[context: Context, x: INTEGER] = {
class: Class = NARROW[context.class];
class.IntegerSetXYRel[context, x, 0];
};
SetYRel: PUBLIC PROC[context: Context, y: REAL] = {
class: Class = NARROW[context.class];
class.SetXYRel[context, [0, y]];
};
IntegerSetYRel: PUBLIC PROC[context: Context, y: INTEGER] = {
class: Class = NARROW[context.class];
class.IntegerSetXYRel[context, 0, y];
};
GetCP: PUBLIC PROC[context: Context] RETURNS[Pair] = {
class: Class = NARROW[context.class];
RETURN [class.GetCP[context]];
};
GetCPRounded: PUBLIC PROC[context: Context] RETURNS[Pair] = {
class: Class = NARROW[context.class];
RETURN [class.GetCPRounded[context]];
};
Color
Card: PROC [real: REAL] RETURNS [card: CARDINAL] ~ {
int: INT ← Real.RoundLI[real*LAST[CARDINAL]];
card ← MAX[MIN[int, LAST[CARDINAL]], 0];
};
MakeGray: PUBLIC PROC[f: REAL] RETURNS[ConstantColor] = {
IF f<0 OR f>1 THEN Error[$GrayParameterOutOfRange];
RETURN[NEW[ColorRep[constant] ←
[constant[x: Card[0.3101], y: Card[0.3163], Y: Card[1-f]]]]];
};
black: PUBLIC ConstantColor ← MakeGray[1];
white: PUBLIC ConstantColor ← MakeGray[0];
SetColor: PUBLIC PROC[context: Context, color: Color] = {
class: Class = NARROW[context.class];
class.ISet[context, $color, color];
};
SetSampledColor: PUBLIC PROC[context: Context, pa: PixelArray, pixelT: Transformation, colorOperator: ATOM] = {
class: Class = NARROW[context.class];
class.SetSampledColor[context, pa, pixelT, colorOperator];
};
SetSampledBlack: PUBLIC PROC[context: Context, pa: PixelArray, pixelT: Transformation, transparent: BOOLEAN] = {
class: Class = NARROW[context.class];
class.SetSampledBlack[context, pa, pixelT, transparent];
};
Mask operators
LastPoint: PUBLIC PROC[t: Trajectory] RETURNS[Pair] = {
RETURN[t.lp];
};
MoveTo: PUBLIC PROC[p: Pair] RETURNS[Trajectory] = {
RETURN[NEW[TrajectoryRep[move] ← [prev: NIL, lp: p, variant: move[]]]];
};
LineTo: PUBLIC PROC[t: Trajectory, p: Pair] RETURNS[Trajectory] = {
RETURN[NEW[TrajectoryRep[line] ← [prev: t, lp: p, variant: line[]]]];
};
LineToX: PUBLIC PROC[t: Trajectory, x: REAL] RETURNS[Trajectory] = {
RETURN[NEW[TrajectoryRep[line] ← [prev: t, lp: [x, t.lp.y], variant: line[]]]];
};
LineToY: PUBLIC PROC[t: Trajectory, y: REAL] RETURNS[Trajectory] = {
RETURN[NEW[TrajectoryRep[line] ← [prev: t, lp: [t.lp.x, y], variant: line[]]]];
};
CurveTo: PUBLIC PROC[t: Trajectory, p1, p2, p3: Pair] RETURNS[Trajectory] = {
RETURN[NEW[TrajectoryRep[curve] ← [prev: t, lp: p3, variant: curve[p1, p2]]]];
};
ConicTo: PUBLIC PROC[t: Trajectory, p1, p2: Pair, r: REAL] RETURNS[Trajectory] = {
RETURN[NEW[TrajectoryRep[conic] ← [prev: t, lp: p2, variant: conic[p1, r]]]];
};
ArcTo: PUBLIC PROC[t: Trajectory, p1, p2: Pair] RETURNS[Trajectory] = {
conic: PROC[p1, p2: Pair, r: REAL] ~ {t ← ConicTo[t, p1, p2, r]};
ImagerConic.FromArc[LastPoint[t], p1, p2, conic];
RETURN [t]
};
MakeOutline: PUBLIC PROC[list: LIST OF Trajectory] RETURNS[Outline] = {
RETURN[NEW[OutlineRep ← [list]]];
};
MapTrajectory: PathMapType = {
t: Trajectory = NARROW[data];
move[t.lp];
FOR x: Trajectory ← t, x.prev UNTIL x.prev=NIL DO
p0: Pair = x.prev.lp;
WITH x SELECT FROM
x: REF TrajectoryRep[line] => line[p0];
x: REF TrajectoryRep[curve] => curve[x.p2, x.p1, p0];
x: REF TrajectoryRep[conic] => conic[x.p1, p0, x.r];
x: REF TrajectoryRep[move] => ERROR;
ENDCASE => ERROR;
ENDLOOP;
};
MapTrajectoryList: PathMapType = {
FOR x: LIST OF Trajectory ← NARROW[data], x.rest UNTIL x = NIL DO
MapTrajectory[x.first, move, line, curve, conic]
ENDLOOP;
};
MapPolygon: PathMapType = {
p: Polygon = NARROW[data];
IF p.length>0 THEN {
move[p[0]];
FOR i: NAT IN[1..MIN[p.length, p.maxLength]) DO line[p[i]] ENDLOOP;
};
};
MapPolygonList: PathMapType = {
FOR plist: LIST OF Polygon ← NARROW[data], plist.rest UNTIL plist = NIL DO
MapPolygon[plist.first, move, line, curve, conic];
ENDLOOP;
};
MakePixelArrayFromBits: PUBLIC PROC[
bitPointer: LONG POINTER TO PACKED ARRAY [0..0) OF [0..1],
bitsPerLine, samplesPerLine, numberOfLines: NAT
] RETURNS [pixelArray: PixelArray] = TRUSTED {
pixelMap: ImagerPixelMaps.PixelMap ← ImagerPixelMaps.Create[0, [0, 0, numberOfLines, samplesPerLine]];
bbTableSpace: PrincOps.BBTableSpace;
bb: PrincOps.BBptr ~ PrincOpsUtils.AlignedBBTable[@bbTableSpace];
bb^ ← [
dst: [word: pixelMap.refRep.pointer, bit: 0],
dstBpl: pixelMap.refRep.rast*Basics.bitsPerWord,
src: [word: bitPointer, bit: 0],
srcDesc: [srcBpl[bitsPerLine]],
height: numberOfLines,
width: samplesPerLine,
flags: [direction: forward, disjoint: TRUE, disjointItems: TRUE, gray: FALSE, srcFunc: null, dstFunc: null]
];
PrincOpsUtils.BITBLT[bb];
pixelArray ← ImagerMasks.PixelArrayFromPixelMap[pixelMap];
pixelArray.m ← pixelArray.m.Concat[ImagerTransform.Rotate[-90]].Concat[ImagerTransform.Translate[0, numberOfLines]];
};
MaskFill: PUBLIC PROC[context: Context, outline: REF] = {
class: Class = NARROW[context.class];
WITH outline SELECT FROM
o: Outline => class.MaskFill[context, MapTrajectoryList, o.list];
list: LIST OF Trajectory => class.MaskFill[context, MapTrajectoryList, list];
t: Trajectory => class.MaskFill[context, MapTrajectory, t];
p: Polygon => class.MaskFill[context, MapPolygon, p];
plist: LIST OF Polygon => class.MaskFill[context, MapPolygonList, plist];
ENDCASE => Error[$UnknownPathType];
};
SetStrokeWidth: PUBLIC PROC[context: Context, strokeWidth: REAL] = {
class: Class = NARROW[context.class];
class.ISetReal[context, $strokeWidth, strokeWidth];
};
SetStrokeEnd: PUBLIC PROC[context: Context, strokeEnd: StrokeEnd] = {
class: Class = NARROW[context.class];
class.ISetInt[context, $strokeEnd, SELECT strokeEnd FROM
square => 0, butt => 1, round => 2, ENDCASE => ERROR];
};
MaskStroke: PUBLIC PROC[context: Context, t: Trajectory,
strokeWidth: REAL ← defaultStrokeWidth, strokeEnd: StrokeEnd ← defaultStrokeEnd] = {
class: Class = NARROW[context.class];
class.MaskStroke[context, MapTrajectory, t, strokeWidth, strokeEnd];
};
MaskStrokeClosed: PUBLIC PROC[context: Context, t: Trajectory,
strokeWidth: REAL ← defaultStrokeWidth] = {
class: Class = NARROW[context.class];
class.MaskStrokeClosed[context, MapTrajectory, t, strokeWidth];
};
MaskVector: PUBLIC PROC[context: Context, p1, p2: Pair,
strokeWidth: REAL ← defaultStrokeWidth, strokeEnd: StrokeEnd ← defaultStrokeEnd] = {
class: Class = NARROW[context.class];
IF LOOPHOLE[strokeWidth, LONG CARDINAL] = LOOPHOLE[defaultStrokeWidth, LONG CARDINAL] AND strokeEnd=defaultStrokeEnd THEN
class.MaskVector[context, p1.x, p1.y, p2.x, p2.y]
ELSE {
MapVector: PathMapType = { move[p1]; line[p2] };
class.MaskStroke[context, MapVector, NIL, strokeWidth, strokeEnd];
};
};
MaskRectangle: PUBLIC PROC[context: Context, x, y, w, h: REAL] = {
class: Class = NARROW[context.class];
class.MaskRectangle[context, x, y, w, h];
};
IntegerMaskRectangle: PUBLIC PROC[context: Context, x, y, w, h: INTEGER] = {
class: Class = NARROW[context.class];
class.IntegerMaskRectangle[context, x, y, w, h];
};
StartUnderline: PUBLIC PROC[context: Context] = {
class: Class = NARROW[context.class];
class.StartUnderline[context];
};
MaskUnderline: PUBLIC PROC[context: Context, dy, h: REAL] = {
class: Class = NARROW[context.class];
class.MaskUnderline[context, dy, h];
};
IntegerMaskUnderline: PUBLIC PROC[context: Context, dy, h: INTEGER] = {
class: Class = NARROW[context.class];
class.IntegerMaskUnderline[context, dy, h];
};
MaskPixel: PUBLIC PROC[context: Context, pa: PixelArray] = {
class: Class = NARROW[context.class];
class.MaskPixel[context, pa];
};
ClipOutline: PUBLIC PROC[context: Context, outline: REF] = {
class: Class = NARROW[context.class];
WITH outline SELECT FROM
o: Outline => class.ClipOutline[context, MapTrajectoryList, o.list];
list: LIST OF Trajectory => class.ClipOutline[context, MapTrajectoryList, list];
t: Trajectory => class.ClipOutline[context, MapTrajectory, t];
p: Polygon => class.ClipOutline[context, MapPolygon, p];
ENDCASE => Error[$UnknownPathType];
};
ExcludeOutline: PUBLIC PROC[context: Context, outline: REF] = {
class: Class = NARROW[context.class];
WITH outline SELECT FROM
o: Outline => class.ExcludeOutline[context, MapTrajectoryList, o.list];
list: LIST OF Trajectory => class.ExcludeOutline[context, MapTrajectoryList, list];
t: Trajectory => class.ExcludeOutline[context, MapTrajectory, t];
p: Polygon => class.ExcludeOutline[context, MapPolygon, p];
ENDCASE => Error[$UnknownPathType];
};
ClipRectangle: PUBLIC PROC[context: Context, x, y, w, h: REAL] = {
class: Class = NARROW[context.class];
class.ClipRectangle[context, x, y, w, h];
};
ExcludeRectangle: PUBLIC PROC[context: Context, x, y, w, h: REAL] = {
class: Class = NARROW[context.class];
class.ExcludeRectangle[context, x, y, w, h];
};
IntegerClipRectangle: PUBLIC PROC[context: Context, x, y, w, h: INTEGER] = {
class: Class = NARROW[context.class];
class.IntegerClipRectangle[context, x, y, w, h];
};
IntegerExcludeRectangle: PUBLIC PROC[context: Context, x, y, w, h: INTEGER] = {
class: Class = NARROW[context.class];
class.IntegerExcludeRectangle[context, x, y, w, h];
};
Character operators
MakeFont: PUBLIC PROC[name: Rope.ROPE, size: REAL] RETURNS[FONT] = {
RETURN[Font.CreateScaled[name, size]];
};
SetFont: PUBLIC PROC[context: Context, font: FONT] = {
class: Class = NARROW[context.class];
class.ISet[context, $showVec, font];
};
ShowChar: PUBLIC PROC[context: Context, char: CHAR, font: FONTNIL] = {
class: Class = NARROW[context.class];
class.ShowChar[context, char, font];
};
ShowCharacters: PUBLIC PROC[context: Context, characters: RopeOrRefText, font: FONTNIL,
start: INT ← 0, length: INTLAST[INT]] = {
class: Class = NARROW[context.class];
class.ShowCharacters[context, characters, font, start, length];
};
SetAmplifySpace: PUBLIC PROC[context: Context, amplifySpace: REAL] = {
class: Class = NARROW[context.class];
class.ISetReal[context, $amplifySpace, amplifySpace];
};
Spacing correction
CorrectMask: PUBLIC PROC[context: Context] = {
class: Class = NARROW[context.class];
class.CorrectMask[context];
};
CorrectSpace: PUBLIC PROC[context: Context, v: Pair] = {
class: Class = NARROW[context.class];
class.CorrectSpace[context, v];
};
Correct: PUBLIC PROC[context: Context, body: PROC] = {
class: Class = NARROW[context.class];
class.Correct[context, body];
};
SetCorrectMeasure: PUBLIC PROC[context: Context, v: Pair] = {
class: Class = NARROW[context.class];
class.SetCorrectMeasure[context, v];
};
SetCorrectTolerance: PUBLIC PROC[context: Context, v: Pair] = {
class: Class = NARROW[context.class];
class.SetCorrectTolerance[context, v];
};
SetCorrectShrink: PUBLIC PROC[context: Context, correctShrink: REAL] = {
class: Class = NARROW[context.class];
class.ISetReal[context, $correctShrink, correctShrink];
};
Space: PUBLIC PROC[context: Context, x: REAL] = {
class: Class = NARROW[context.class];
class.Space[context, x];
};
IntegerSpace: PUBLIC PROC[context: Context, x: INTEGER] = {
class: Class = NARROW[context.class];
class.IntegerSpace[context, x];
};
Reset: PUBLIC PROC[context: Context] = {
class: Class = NARROW[context.class];
class.Reset[context];
};
SetViewOrigin: PUBLIC PROC[context: Context, viewOrigin: IntPair] = {
class: Class = NARROW[context.class];
class.SetViewOrigin[context, viewOrigin];
};
GetViewOrigin: PUBLIC PROC[context: Context] RETURNS[viewOrigin: IntPair] = {
class: Class = NARROW[context.class];
RETURN[class.GetViewOrigin[context]];
};
SetViewBox: PUBLIC PROC[context: Context, viewBox: IntRectangle] = {
class: Class = NARROW[context.class];
class.SetViewBox[context, viewBox];
};
GetViewBox: PUBLIC PROC[context: Context] RETURNS[viewBox: IntRectangle] = {
class: Class = NARROW[context.class];
RETURN[class.GetViewBox[context]];
};
ClipView: PUBLIC PROC[context: Context, clipBox: IntRectangle, exclude: BOOL] = {
class: Class = NARROW[context.class];
class.ClipView[context, clipBox, exclude];
};
PutProp: PUBLIC PROC[context: Context, key: REF, value: REF] = {
pList: Atom.PropList ← NARROW[context.state.propertyList];
RemoveKeyFrom: PROC[p: Atom.PropList] RETURNS [Atom.PropList] = {
IF p = NIL THEN RETURN [NIL]
ELSE IF p.first.key = key THEN RETURN [p.rest]
ELSE {
rest: Atom.PropList ← RemoveKeyFrom[p.rest];
IF rest # p.rest THEN RETURN [CONS[p.first, rest]]
ELSE RETURN [p]
}
};
pList ← RemoveKeyFrom[pList];
IF value # NIL THEN pList ← CONS[NEW[Atom.DottedPairNode ← [key, value]], pList];
context.state.propertyList ← pList;
};
GetProp: PUBLIC PROC[context: Context, key: REF] RETURNS [value: REF] = {
pList: Atom.PropList ← NARROW[context.state.propertyList];
WHILE pList # NIL DO
IF pList.first.key = key THEN RETURN [pList.first.val];
pList ← pList.rest;
ENDLOOP;
RETURN [NIL]
};
Round: PROC[r: REAL] RETURNS[REAL] = INLINE {
IF ABS[r]>= LAST[INT] THEN RETURN [r]
ELSE RETURN [Real.RoundLI[r]]
};
DRound: PUBLIC PROC[v: Pair] RETURNS[Pair] = {
RETURN [[Round[v.x], Round[v.y]]]
};
MoveSurfaceRectangle: PUBLIC PROC[context: Context, source: IntRectangle, dest: IntPair] = {
class: Class = NARROW[context.class];
class.MoveSurfaceRectangle[context, source, dest];
};
XOR: PUBLIC Color ← NEW[ImagerBasic.ColorRep[special] ← [special[$XOR]]];
MakeStipple: PUBLIC PROC[stipple: CARDINAL] RETURNS[Color] = {
ref: REF CARDINAL = NEW[CARDINAL ← stipple];
RETURN[NEW[ImagerBasic.ColorRep[special] ← [special[ref]]]]
};
TestRectangle: PUBLIC PROC[context: Context, x, y, w, h: REAL] RETURNS[Visibility] = {
class: Class = NARROW[context.class];
RETURN[class.TestRectangle[context, x, y, w, h]];
};
GetSurfaceBounds: PUBLIC PROC[context: Context] RETURNS[IntRectangle] = {
class: Class = NARROW[context.class];
RETURN[class.GetSurfaceBounds[context]];
};
SpecialOp: PUBLIC PROC[context: Context, op: ATOM, data: REF] RETURNS[REF] = {
class: Class = NARROW[context.class];
RETURN[class.SpecialOp[context, op, data]];
};
END.