createfont.mesa
Last Edited by: Kimr, September 28, 1984 10:24:52 am PDT
DIRECTORY
Basics,
CD,
CDApplications,
CDCells,
CDDirectory,
CDInline,
CDInterestRects,
CDOps,
CDRects,
CDSequencer,
CDX,
CornerStitching,
Graphics,
GraphicsBasic,
GraphicsOps,
Real,
Rope,
TerminalIO;
CreateFont: CEDAR PROGRAM
IMPORTS Basics, CD, CDApplications, CDCells, CDDirectory, CDInline, CDInterestRects, CDOps, CDSequencer, CDRects, CDX, CornerStitching, Graphics, GraphicsOps, Real, Rope, TerminalIO =
BEGIN
l: CD.DesignNumber = CD.lambda;
scale: INT ; -- arbitrary choice, if font is defined as n pixels high, unscaled chars will be n/2 designNumbers high
design: CD.Design;
unitSize: CD.DesignPosition;
metal, poly: CD.Level;
baseLine, finalBaseLine: CD.ApplicationPtr;
tes: REF CornerStitching.Tesselation;
CellInfoRef: TYPE = REF CellInfo;
CellInfo: TYPE = RECORD [
cell: CD.ObPtr,
relOrigin: CD.ApplicationPtr
] ;
cellArray: ARRAY CHAR OF Rope.ROPEALL[NIL] ;
IncludeRect: PROC [ x, y: LONG CARDINAL, cell: CD.ObPtr, relOrigin: CD.ApplicationPtr] =
BEGIN
cdx, cdy: INT;
rect: CD.ObPtr ← CDRects.CreateRect[ size: unitSize, l: metal] ;
apPtr: CD.ApplicationPtr;
cdx ← x; cdy ← y;
apPtr ← CDApplications.NewApplicationI[ob: rect, location: [x: cdx*scale, y: y*scale] ] ;
[] ← CDCells.IncludeApplication[design: design, cell: cell, aptr: apPtr, draw: FALSE, relativeTo: relOrigin] ;
END; -- IncludeRect
IncludeTile: CornerStitching.PerTileProc =
PROCEDURE [tile: TilePtr, data: REF ANY] ;
BEGIN
rect: CD.ObPtr ← CDRects.CreateRect[
size: [x: (tile.EastEdge - tile.WestEdge), y: (tile.NorthEdge - tile.SouthEdge)] ,
l: metal] ;
cellInfo: CellInfoRef ← NARROW[data, CellInfoRef] ;
apPtr: CD.ApplicationPtr ←
CDApplications.NewApplicationI[ob: rect, location: [x: tile.WestEdge, y: tile.SouthEdge ] ] ;
[] ← CDCells.IncludeApplication[design: design, cell: cellInfo.cell, aptr: apPtr, draw: FALSE, relativeTo: cellInfo.relOrigin] ;
END; -- IncludeTile
NoteMetalRectangle: PROC [ r: CD.DesignRect, l: CD.Level, pr: CD.DrawRef ] =
BEGIN
IF CDInline.NonEmpty[r] THEN
BEGIN
IF CD.LevelKey[l] = $met THEN
tes.ChangeRect[rect: r, newValue: $covered] ;
END;
END; -- NoteMetalRectangle
DrawCell: PROC [cell: CD.ObPtr] RETURNS [CD.ApplicationPtr] =
BEGIN
app: CD.ApplicationPtr;
name: Rope.ROPE;
cellptr: CD.CellPtr;
DO
cellptr ← NARROW[cell.specificRef, CD.CellPtr] ;
name ← cellptr.name;
app ← CDX.IncludeRelative[design: design,
ob: cell,
cellPosition: [0,0] ,
obPosition: CDInline.BaseOfRect[CDInterestRects.GetInterestRect[cell] .r] ,
orientation: 0,
coordSystem: outerCoordinates
] ;
RETURN [app]
ENDLOOP
END; -- DrawCell
PlaceAndCornerStitch: PROC[cell: CD.ObPtr] =
BEGIN
data: CellInfoRef ← NEW[CellInfo] ;
ap: CD.ApplicationPtr;
cornerCell: CD.ObPtr;
cellPtr: CD.CellPtr;
dr: CD.DrawRef = CD.NewNullDeviceDrawRef[design] ;
tes ← CornerStitching.NewTesselation[] ;
dr.minimalSize ← 0;
dr.drawRect ← dr.saveRect ← NoteMetalRectangle;
dr.worldClip ← CDInline.universe;
place cell in design so that it can be cornerstitched
ap ← DrawCell[cell] ;
mark all the metal rectangles for stitching
CDOps.DrawDesign[design, dr] ;
create and include new cell, with baseLine
{
cornerCell ← CDCells.CreateEmptyCell[];
cellPtr ← NARROW[cornerCell.specificRef, CD.CellPtr] ;
cellPtr.name ← Rope.Replace[ base: NARROW[cell.specificRef, CD.CellPtr].name, start: 0, len: 1, with: NIL];
cornerCell.size ← [x: l, y: l] ;
[] ← CDDirectory.Include[design: design, object: cornerCell] ;
[] ← CDCells.IncludeApplication[design: design, cell: cornerCell, aptr: baseLine, draw: FALSE] ;
};
include new cornerstitched applications for cell
data.cell ← cornerCell;
data.relOrigin ← baseLine;
[] ← tes.EnumerateArea[rect: [x1: 0, y1: 0, x2: cell.size.x, y2: cell.size.y] , perTile: IncludeTile, data: data] ;
CornerStitching.FreeTesselation[plane: tes] ;
move baseLine of new cell
[] ← CDCells.IncludeApplication[design: design, cell: cornerCell,
aptr: finalBaseLine,
draw: FALSE, relativeTo: baseLine] ;
[] ← CDCells.RemoveApplication[design: design, cell: cornerCell, aptr: baseLine, draw: FALSE] ;
remove old cell from design
CDOps.RemoveApplication[design: design, aptr: ap, draw: FALSE] ;
END; -- PlaceAndCornerStitch
MakeCDFont: PROC [ fontName: Rope.ROPE] =
BEGIN
xmin,ymin,xmax,ymax: REAL;
xw,yw: REAL;
bitsRef: LONG POINTER TO CARDINAL;
j, k, i: LONG CARDINAL;
width, bits: CARDINAL;
bitmap: GraphicsOps.BitmapRef;
pixContext: Graphics.Context;
fontRef: Graphics.FontRef ← Graphics.MakeFont[fontName] ;
get box which will hold all characters in font
[xmin,ymin,xmax,ymax] ← Graphics.FontBox[fontRef] ;
bitmap ← GraphicsOps.NewBitmap[width: Real.RoundC[(xmax - xmin)] , height: Real.RoundC[(ymax - ymin)] ] ;
pixContext ← GraphicsOps.NewContextFromBitmap[bitmap] ;
FOR char: CHAR IN CHAR DO {
set context such that character will not be clipped when written in bitmap
Graphics.SetCP[self: pixContext, x: 0-xmin, y: 0-ymin] ;
clear the bitmap
[] ← pixContext.SetPaintMode[opaque] ;
pixContext.SetColor[Graphics.white] ;
pixContext.DrawBox[[xmin: 0, ymin: 0, xmax: (xmax - xmin), ymax: (ymax - ymin)] ] ;
[] ← pixContext.SetPaintMode[transparent] ;
pixContext.SetColor[Graphics.black] ;
IF cellArray[char] # NIL THEN {
charCell: CD.ObPtr ← CDCells.CreateEmptyCell[] ;
cellPtr: CD.CellPtr ← NARROW[charCell.specificRef, CD.CellPtr] ;
charCell.size ← [x: Real.RoundI[(xmax - xmin)] , y: Real.RoundI[(ymax - ymin)] ] ;
[] ← CDDirectory.Include[design: design, object: charCell] ;
cellPtr.name ← cellArray[char];
[xw: xw, yw: yw] ← Graphics.CharWidth[font: fontRef, char: char] ;
Graphics.DrawChar[self: pixContext, char: char, font: fontRef] ;
Create poly line to serve as reference origin for the character;
Since Chipndale will automatically make the first application's position [0,0] ,
it does no matter where it is placed in the empty cell
baseLine ← CDApplications.NewApplicationI[
ob: CDRects.CreateRect[size: [x: Real.RoundI[xw] , y: 1] , l: poly] ,
location: [x: 0, y: 0 ] ] ;
[] ← CDCells.IncludeApplication[design: design, cell: charCell, aptr: baseLine, draw: FALSE] ;
step through bitmap putting down a rectangle wherever there is a 1
FOR j IN [0..bitmap.height) DO {
FOR k IN [0..bitmap.raster) DO TRUSTED {
bitsRef ← LOOPHOLE[bitmap.base, LONG POINTER TO CARDINAL] + (INT[bitmap.raster] *j + k);
bits ← bitsRef^;
width ← MIN[Basics.bitsPerWord, bitmap.width-(Basics.LowHalf[k] *Basics.bitsPerWord)] ;
FOR i IN [0..width) DO {
IF Basics.BITAND[bits, 32768] = 32768 THEN
IncludeRect[k*Basics.bitsPerWord + i, bitmap.height - j, charCell, baseLine] ;
bits ← Basics.BITSHIFT[value: bits, count: 1] ;
};
ENDLOOP;
};
ENDLOOP;
};
ENDLOOP;
move the base line to account for descending characters
finalBaseLine ← CDApplications.NewApplicationI[
ob: CDRects.CreateRect[size: [x: (Real.RoundI[xw] +1)*scale, y: 1+scale] , l: poly] ,
location: [x: Real.RoundI[-xmin] *scale, y: Real.RoundI[-ymin] *scale] ] ;
[] ← CDCells.IncludeApplication[design: design, cell: charCell,
aptr: finalBaseLine,
draw: FALSE, relativeTo: baseLine] ;
[] ← CDCells.RemoveApplication[design: design, cell: charCell, aptr: baseLine, draw: FALSE] ;
cornerstitch cell
PlaceAndCornerStitch[cell: charCell] ;
remove uncornerstitched cell from cell directory
[] ← CDDirectory.Remove[design: design, name: cellArray[char]];
};
};
ENDLOOP;
END; -- MakeCDFont
CreateCDFont: PROC[ comm: CDSequencer.Command] =
BEGIN
fontName: Rope.ROPE ← TerminalIO.RequestRope["Input font name -> "] ;
scale ← TerminalIO.RequestInt["Input scale (INT) -> "];
unitSize ← [x: 1+scale, y: 1+scale];
design ← comm.design;
metal ← CD.FetchLevel[t: design.technology, uniqueKey: $met] ;
poly ← CD.FetchLevel[t: design.technology, uniqueKey: $pol] ;
MakeCDFont[fontName] ;
TerminalIO.WriteRope["Done with font\n"] ;
TerminalIO.WriteRope["*************\n"] ;
END; -- CreateCDFont
Init: PROC[] =
BEGIN
cellArray['a] ← "#LA";
cellArray['b] ← "#LB";
cellArray['c] ← "#LC";
cellArray['d] ← "#LD";
cellArray['e] ← "#LE";
cellArray['f] ← "#LF";
cellArray['g] ← "#LG";
cellArray['h] ← "#LH";
cellArray['i] ← "#LI";
cellArray['j] ← "#LJ";
cellArray['k] ← "#LK";
cellArray['l] ← "#LL";
cellArray['m] ← "#LM";
cellArray['n] ← "#LN";
cellArray['o] ← "#LO";
cellArray['p] ← "#LP";
cellArray['q] ← "#LQ";
cellArray['r] ← "#LR";
cellArray['s] ← "#LS";
cellArray['t] ← "#LT";
cellArray['u] ← "#LU";
cellArray['v] ← "#LV";
cellArray['w] ← "#LW";
cellArray['x] ← "#LX";
cellArray['y] ← "#LY";
cellArray['z] ← "#LZ";
cellArray['A] ← "#UA";
cellArray['B] ← "#UB";
cellArray['C] ← "#UC";
cellArray['D] ← "#UD";
cellArray['E] ← "#UE";
cellArray['F] ← "#UF";
cellArray['G] ← "#UG";
cellArray['H] ← "#UH";
cellArray['I] ← "#UI";
cellArray['J] ← "#UJ";
cellArray['K] ← "#UK";
cellArray['L] ← "#UL";
cellArray['M] ←"#UM";
cellArray['N] ← "#UN";
cellArray['O] ← "#UO";
cellArray['P] ← "#UP";
cellArray['Q] ←"#UQ";
cellArray['R] ← "#UR";
cellArray['S] ← "#US";
cellArray['T] ← "#UT";
cellArray['U] ← "#UU";
cellArray['V] ← "#UV";
cellArray['W] ←"#UW";
cellArray['X] ← "#UX";
cellArray['Y] ← "#UY";
cellArray['Z] ←"#UZ";
cellArray['1] ←"#N1";
cellArray['2] ←"#N2";
cellArray['3] ←"#N3";
cellArray['4] ← "#N4";
cellArray['5] ← "#N5";
cellArray['6] ← "#N6";
cellArray['7] ← "#N7";
cellArray['8] ← "#N8";
cellArray['9] ← "#N9";
cellArray['0] ← "#N0";
cellArray['/ ] ← "#SLASH";
cellArray['(] ← "#LEFTPAREN";
cellArray[':] ← "#COLON";
cellArray[')] ← "#RIGHTPAREN";
cellArray[',] ← "#COMMA";
cellArray['.] ← "#PERIOD";
cellArray['#] ← "#SPLAT";
cellArray['$] ← "#DOLLARSIGN";
cellArray['!] ← "#EXCLMARK";
cellArray['%] ← "#PERCENT";
cellArray['&] ← "#AMPERSAND";
cellArray['*] ← "#ASTERISK";
cellArray['?] ← "#QUESTIONMARK";
CDSequencer.ImplementCommand[$MirrorS, CreateCDFont] ;
END;
module initialization
Init[];
END.