CDCreateLabelsImpl.mesa
Copyright (C) 1984, 1985, 1986 by Xerox Corporation. All rights reserved.
Created by: Christian Jacobi, March 1, 1985 4:52:57 pm PST
Last edited by: Christian Jacobi, August 25, 1986 11:19:04 am PDT
DIRECTORY
Basics,
CD,
CDCells,
CDCreateLabels,
CDDirectory,
CDBasics,
CDSymbolicObjects,
CDOps,
CDPanelFonts,
CDProperties,
CDRects,
CDSequencer,
CDTexts,
CStitching,
Imager,
ImagerBackdoor,
ImagerFont,
IO,
Real,
Rope,
TerminalIO;
CDCreateLabelsImpl:
CEDAR
PROGRAM
IMPORTS Basics, CD, CDBasics, CDSymbolicObjects, CDCells, CDDirectory, CDOps, CDPanelFonts, CDProperties, CDSequencer, CDRects, CStitching, Imager, ImagerBackdoor, ImagerFont, IO, Real, Rope, TerminalIO
EXPORTS CDCreateLabels =
BEGIN
IntValue:
PROC [ob:
CD.Object, a:
ATOM]
RETURNS [i:
INT𡤀] =
BEGIN
WITH CDProperties.GetObjectProp[ob, a]
SELECT
FROM
ri: REF INT => i ← ri^;
ENDCASE => NULL;
END;
PutIntValue:
PROC [ob:
CD.Object, a:
ATOM, i:
INT𡤀] =
BEGIN
CDProperties.PutObjectProp[ob, a, (IF i=0 THEN NIL ELSE NEW[INT ← i])];
END;
HashT:
PROC [t: Imager.Transformation]
RETURNS [Rope.
ROPE] =
BEGIN
r: Rope.ROPE ← IO.PutFR["%g,%g,%g,%g", IO.real[t.a], IO.real[t.b], IO.real[t.c], IO.real[t.d]];
RETURN [IO.PutFR["%g,%g,%g", IO.rope[r], IO.real[t.e], IO.real[t.f]]]
END;
MakeName:
PROC [font: Imager.Font, ch:
CHAR, scale:
INT, lev:
CD.Layer]
RETURNS [n: Rope.
ROPE←
NIL] =
--A NIL name should not be hashed
BEGIN
h: Rope.ROPE ← HashT[font.charToClient];
n ←
IO.PutFR["#%g[%g|%d|%g|%g]",
IO.char[ch], IO.rope[font.name], IO.int[scale], IO.atom[CD.LayerKey[lev]], IO.rope[h]
];
END;
BitmapToCornerstitching:
PROC [bitmap: ImagerBackdoor.Bitmap]
RETURNS [plane: CStitching.Tesselation] =
BEGIN
plane ← CStitching.NewTesselation[];
FOR y:
CARDINAL
IN [0..bitmap.height)
DO
FOR x:
CARDINAL
IN [0..bitmap.width)
DO
TRUSTED {
bitsRef:
LONG
POINTER
TO
CARDINAL
← LOOPHOLE[bitmap.base, LONG POINTER TO CARDINAL]
+ LONG[y]*bitmap.wordsPerLine
+ LONG[x/Basics.bitsPerWord];
IF Basics.
BITAND[8000h, Basics.
BITSHIFT[bitsRef^, x
MOD Basics.bitsPerWord]]#0
THEN
CStitching.ChangeRect[
plane: plane,
rect: [x1: x, x2: x+1, y1: bitmap.height-y-1, y2: bitmap.height-y],
new: $covered
];
}
ENDLOOP;
ENDLOOP;
END;
CornerstitchingToCell:
PROC [plane: CStitching.Tesselation, layer:
CD.Layer, csOrigin: CStitching.Pos ← [0, 0], scale:
INT ← 1]
RETURNS [cell:
CD.Object] =
--does not yet include cell into a design
--csOrigin: in CStitching coords; will be origin of cell
--scale: applied after offset for csOrigin
BEGIN
offset: CD.Position ← [-csOrigin.x*scale, -csOrigin.y*scale];
IncludeRectangle: CStitching.TileProc =
BEGIN
r: CD.Rect ~ CStitching.Area[tile];
IF CDBasics.NonEmpty[r]
THEN
[] ← CDCells.IncludeOb[cell: cell,
ob: CDRects.CreateRect[size: [x: (r.x2-r.x1)*scale, y: (r.y2-r.y1)*scale], l: layer],
position: CDBasics.AddPoints[[x: r.x1*scale, y: r.y1*scale], offset],
cellCSystem: cdCoords,
obCSystem: cdCoords,
mode: dontPropagate
];
END;
cell ← CDCells.CreateEmptyCell[];
[] ← CStitching.EnumerateArea[plane: plane, rect: CDBasics.universe, eachTile: IncludeRectangle, data: NIL];
--prevent empty cell
IF
NARROW[cell.specificRef,
CD.CellPtr].contents=
NIL
THEN
[] ← CDCells.IncludeOb[cell: cell, ob: CDSymbolicObjects.CreateMark[], mode: dontPropagate];
[] ← CDCells.RepositionCell[cell, NIL];
END;
Up:
PROC [r:
REAL]
RETURNS [i:
INT] = {
-- returns integer i: i >= r; there exists no integer j such that j < i and j >= r
i ← Real.Fix[r];
IF Real.Float[i]#r THEN i ← i+1;
};
MakeChar:
PROC [font: Imager.Font, char:
CHAR, scale:
INT𡤁, lev: CD.Layer]
RETURNS [cell:
CD.Object] =
BEGIN
vec: Imager.VEC;
bitmap: ImagerBackdoor.Bitmap;
context: Imager.Context;
plane: CStitching.Tesselation;
ext: ImagerFont.Extents ← ImagerFont.FontBoundingBox[font];
p1: CD.Position ← [Up[ext.leftExtent], Up[ext.descent]];
p2: CD.Position ← [Up[ext.rightExtent], Up[ext.ascent]];
--paint character in bitmap
bitmap ← ImagerBackdoor.NewBitmap[width: p1.x+p2.x, height: p1.y+p2.y];
context ← ImagerBackdoor.BitmapContext[bitmap];
Imager.SetColor[context, Imager.white];
Imager.MaskRectangleI[context, 0, 0, bitmap.width, bitmap.height];
Imager.SetColor[context, Imager.black];
Imager.SetXY[context, [x: p1.x, y: p1.y]];
Imager.SetFont[context, font];
Imager.ShowChar[context, char];
--create cell from bitmap
plane ← BitmapToCornerstitching[bitmap];
cell ← CornerstitchingToCell[plane, lev, p1, scale];
--positioning and spacing
vec ← ImagerFont.RopeWidth[font, Rope.FromChar[char]];
PutIntValue[cell, $CDxWidth, scale*Real.RoundI[vec.x]];
PutIntValue[cell, $CDxHeight, scale*Real.RoundI[vec.y]];
FindOrCreateCharCell:
PUBLIC
PROC [design:
CD.Design, font: Imager.Font, char:
CHAR, scale:
INT, lev:
CD.Layer]
RETURNS [cell:
CD.Object←
NIL] =
BEGIN
hashName: Rope.ROPE;
IF scale<=0 THEN scale ← design.technology.lambda;
hashName ← MakeName[font, char, scale, lev];
IF design#
NIL
AND hashName#
NIL
THEN
cell ← CDDirectory.Fetch[design, hashName].object;
IF cell=
NIL
THEN {
cell ← MakeChar[font, char, scale, lev];
IF design#
NIL
THEN {
IF hashName=NIL THEN hashName ← Rope.Cat["#", Rope.FromChar[char]];
[] ← CDDirectory.Include[design, cell, hashName];
};
}
END;
CreateTextCell:
PUBLIC
PROC [design:
CD.Design, text: Rope.
ROPE, font: Imager.Font, scale:
INT𡤁, lev:
CD.Layer]
RETURNS [cell:
CD.Object] =
--NIL if not done
BEGIN
IncludeChar:
PROC [c:
CHAR]
RETURNS [quit:
BOOL ←
FALSE] =
BEGIN
IF c='
THEN {
vec: Imager.VEC ← ImagerFont.RopeWidth[font, Rope.FromChar[' ]];
x ← x + scale*Real.RoundI[vec.x];
y ← y + scale*Real.RoundI[vec.y];
}
ELSE {
charCell: CD.Object ← FindOrCreateCharCell[design, font, c, scale, lev];
IF charCell#
NIL
THEN {
[] ← CDCells.IncludeOb[cell: cell, ob: charCell,
position: [x, y],
cellCSystem: originCoords,
obCSystem: originCoords
];
x ← x + IntValue[charCell, $CDxWidth];
y ← y + IntValue[charCell, $CDxHeight];
}
}
END;
x: CD.Number𡤀
y: CD.Number𡤀
IF scale<=0 THEN scale ← design.technology.lambda;
cell ← CDCells.CreateEmptyCell[];
[] ← Rope.Map[base: text, action: IncludeChar];
IF NARROW[cell.specificRef, CD.CellPtr].contents=NIL THEN RETURN [NIL];
IF design#NIL THEN [] ← CDDirectory.Include[design, cell, Rope.Cat["Label[", text, "]"]];
END;
CreateTextCellComm:
PROC[comm: CDSequencer.Command] =
BEGIN
SelectFont:
PROC [design:
CD.Design]
RETURNS [font: Imager.Font←
NIL] =
BEGIN
IF TerminalIO.RequestSelection[label: "font", choice:
LIST["from control panel", "type in"]]=1
THEN {
cdFont: CDTexts.CDFont ← CDPanelFonts.CurrentFont[design];
IF cdFont#NIL THEN font ← cdFont.font
}
ELSE {
fontName: Rope.ROPE ← TerminalIO.RequestRope[" font name -> "];
font ← ImagerFont.Find[fontName !
Imager.Error => {
TerminalIO.WriteRope[Rope.Cat["font not loaded: ", error.explanation]];
GOTO oops
};
];
};
EXITS oops => NULL
END;
ScaleHelp:
PROC [lambda:
INT] =
BEGIN
TerminalIO.WriteRope[" normal scaling\n scale applied after scan conversion\n"];
TerminalIO.WriteRope[" makes text larger by blowing up the rectangles\n"];
TerminalIO.WriteRope[" PRE scaling\n scale applied before scan conversion\n"];
TerminalIO.WriteRope[" different for spline fonts only!\n"];
TerminalIO.WriteRope[" makes text larger by using more rectangles for font\n"];
TerminalIO.WriteF[" text height ← scale*preScale*fontHeight*lambda/%g", IO.int[lambda]];
TerminalIO.WriteLn[];
END;
SelectPostScaling:
PROC []
RETURNS [scale:
INT𡤁] =
BEGIN
IF TerminalIO.RequestSelection[label: "normal scale factor", choice:
LIST["yes, type in", "no, use 1"]]=1
THEN {
scale ← MAX[1, TerminalIO.RequestInt[" normal scale factor > "]];
}
END;
SelectPreScaling:
PROC [font: Imager.Font]
RETURNS [Imager.Font] =
BEGIN
IF TerminalIO.RequestSelection[label: "pre scale factor", choice:
LIST["yes, type in", "no, use 1"]]=1
THEN {
scale: INT ← MAX[1, TerminalIO.RequestInt[" pre scale factor -> "]];
font ← ImagerFont.Scale[font, scale];
};
RETURN [font]
END;
text: Rope.ROPE;
font: Imager.Font;
layer: CD.Layer;
scale: INT;
cell: CD.Object;
layer ← comm.l;
TerminalIO.WriteRopes["create a label (on layer ", CDOps.LayerName[layer], ")\n"];
ScaleHelp[comm.design.technology.lambda];
font ← SelectFont[comm.design];
IF font=
NIL
THEN {
TerminalIO.WriteRope["font not found\n"];
RETURN
};
scale ← SelectPostScaling[];
font ← SelectPreScaling[font];
text ← TerminalIO.RequestRope[" text -> "];
IF Rope.IsEmpty[text]
THEN {
TerminalIO.WriteRope["empty text\n"];
RETURN
};
cell ← CreateTextCell[comm.design, text, font, scale, layer];
IF cell=NIL THEN TerminalIO.WriteRope["not done\n"]
ELSE {
CDOps.IncludeObjectI[comm.design, cell, comm.pos];
TerminalIO.WriteRope["done\n"];
}
CDSequencer.ImplementCommand[$CreateTextCell, CreateTextCellComm];