PipalMosImpl.mesa
Copyright Ó 1988 by Xerox Corporation. All rights reserved.
Created by Bertrand Serlet March 6, 1988 1:20:51 pm PST
Bertrand Serlet May 23, 1988 4:15:23 pm PDT
DIRECTORY
Ascii, BrineIO,
Imager, ImagerColor, ImagerFont, ImagerInterpress, ImagerMaskCapture, ImagerTransformation, ImagerTypeface, Interpress,
IO,
Pipal, PipalInt, PipalIO, PipalMos, PipalOps, PipalPaint, PipalReal,
Real, RefTab, Rope, RopeHash, SF;
PipalMosImpl: CEDAR PROGRAM
IMPORTS Ascii, BrineIO, Imager, ImagerColor, ImagerFont, ImagerInterpress, ImagerMaskCapture, ImagerTransformation, ImagerTypeface, Interpress, IO, Pipal, PipalInt, PipalIO, PipalOps, PipalPaint, PipalReal, Real, RefTab, Rope, RopeHash
EXPORTS PipalMos =
BEGIN OPEN PipalMos;
Short Cuts
ROPE: TYPE = Pipal.ROPE;
Object: TYPE = Pipal.Object;
Objects: TYPE = Pipal.Objects;
Transformation: TYPE = PipalInt.Transformation;
Rectangle: TYPE = PipalInt.Rectangle;
Layers
colorTable: RefTab.Ref ← RefTab.Create[];
errorLayer: PUBLIC Layer ← $Error;
commentLayer: PUBLIC Layer ← $Comment;
blueCommentLayer: PUBLIC Layer ← $BlueComment;
RopeToLayer: PUBLIC PROC [rope: ROPE] RETURNS [layer: Layer ← NIL] = {
EachPair: RefTab.EachPairAction = {
ll: Layer ← NARROW [key];
quit ← Rope.Equal[IO.PutR1[IO.atom[ll]], rope, FALSE];
IF quit THEN layer ← ll;
};
[] ← RefTab.Pairs[colorTable, EachPair];
};
LayerToRope: PUBLIC PROC [layer: Layer] RETURNS [rope: ROPE] = {
rope ← IO.PutR1[IO.atom[layer]];
};
RegisterLayerColor: PUBLIC PROC [layer: Layer, color: ImagerColor.ConstantColor] = {
[] ← RefTab.Store[colorTable, layer, color];
};
FetchLayerColor: PUBLIC PROC [layer: Layer] RETURNS [color: ImagerColor.ConstantColor] = {
color ← NARROW [RefTab.Fetch[colorTable, layer].val];
};
IsDifLayer: PUBLIC PROC [layer: Layer] RETURNS [BOOL] = {
RETURN [layer=$Pdif OR layer=$Ndif];
};
IsWellLayer: PUBLIC PROC [layer: Layer] RETURNS [BOOL] = {
RETURN [layer=$Pwell OR layer=$Nwell];
};
IsSchematicLayer: PUBLIC PROC [layer: Layer] RETURNS [BOOL] = {
RETURN [layer=$Comment OR layer=$BlueComment];
};
Box
boxClass: PUBLIC Pipal.Class ← Pipal.RegisterClass[name: "Box", type: CODE [BoxRec]];
SizeBox: PipalInt.SizeProc = {size ← NARROW [object, Box].size};
PaintBox: PipalPaint.PaintProc = {
box: Box ← NARROW [object];
color: ImagerColor.ConstantColor ← FetchLayerColor[box.layer];
PipalPaint.SetColor[context, color];
Imager.MaskRectangle[context, [0.0, 0.0, box.size.x, box.size.y]];
};
DescribeBox: Pipal.DescribeProc = {
box: Box ← NARROW [object];
Pipal.PutIndent[out, indent, cr];
IO.PutF[out, "Box %g %g", IO.atom[box.layer], IO.rope[PipalInt.VectorToRope[box.size]]];
};
HashBox: Pipal.HashProc = {
box: Box ← NARROW [object];
hash ← RopeHash.FromRope[IO.PutR1[IO.atom[box.layer]]] + PipalInt.HashVector[box.size];
};
EqualBox: Pipal.EqualProc = {
box1: Box ← NARROW [object1];
box2: Box ← NARROW [object2];
equal ← box1^=box2^;
};
CreateBox: PUBLIC PROC [size: PipalInt.Size, layer: Layer] RETURNS [box: Box] = {
IF size.x<=0 OR size.y<=0 THEN ERROR;
IF FetchLayerColor[layer]=NIL THEN ERROR;
box ← NEW [BoxRec ← [size: size, layer: layer]];
};
WriteBox: PipalIO.ClassWriteProc = {
box: Box = NARROW [object];
PipalIO.WriteIntVector[stream, box.size];
BrineIO.WriteAtom[stream, box.layer];
};
ReadBox: PipalIO.ClassReadProc = {
size: PipalInt.Size = PipalIO.ReadIntVector[stream];
layer: Layer = BrineIO.ReadAtom[stream];
RETURN [CreateBox[size, layer]]
};
Star
starClass: PUBLIC Pipal.Class ← Pipal.RegisterClass[name: "Star", type: CODE [StarRec]];
DescribeStar: Pipal.DescribeProc = {
star: Star ← NARROW [object];
Pipal.PutIndent[out, indent, cr];
IO.PutF[out, "%g [%g satellites] of ", IO.rope[IF star.overlayStar THEN "Overlay Star" ELSE "Star"], IO.int[star.size]];
Pipal.Describe[out, star.master, indent+1, level-1, cr];
};
EnumerateStar: PipalInt.EnumerateProc = {
star: Star ← NARROW [object];
IF each[transformation, star.master] THEN RETURN [TRUE];
FOR i: NAT IN [0 .. star.size) DO
quit ← each[transformation, star[i]];
IF quit THEN RETURN;
ENDLOOP;
};
GetSatelliteText: PUBLIC PROC [satellite: Object] RETURNS [text: Text ← NIL] = {
IF ISTYPE [satellite, Text] THEN RETURN [NARROW [satellite]];
IF PipalInt.CountChildren[satellite]#1 THEN ERROR;
text ← GetSatelliteText[PipalInt.NthChild[satellite].nthChild];
};
CreateStar: PUBLIC PROC [master: Object, satellites: Objects, overlayStar: BOOLFALSE] RETURNS [star: Star] = {
size: NAT ← 0;
FOR list: Objects ← satellites, list.rest WHILE list#NIL DO
size ← size+1;
[] ← GetSatelliteText[list.first];
ENDLOOP;
star ← NEW [StarRec[size]];
star.overlayStar ← overlayStar;
star.master ← master;
FOR i: NAT IN [0 .. size) DO star[i] ← satellites.first; satellites ← satellites.rest ENDLOOP;
};
GetStarTexts: PUBLIC PROC [star: Star] RETURNS [texts: LIST OF Text ← NIL] = {
FOR i: NAT IN [0 .. star.size) DO
texts ← CONS [GetSatelliteText[star[i]], texts];
ENDLOOP;
};
GetNonItalicRopes: PUBLIC PROC [star: Star] RETURNS [satellites: LIST OF Pipal.ROPENIL] = {
FOR i: NAT IN [0 .. star.size) DO
text: Text ← GetSatelliteText[star[i]];
IF NOT IsItalic[GetTextFontName[text]]
THEN satellites ← CONS [text.contents, satellites];
ENDLOOP;
};
ReplaceStar: PipalOps.ReplaceProc = {
star: Star ← NARROW [parent];
master: Pipal.Object ← map[star.master];
satellites: Pipal.Objects ← NIL;
FOR i: NAT DECREASING IN [0 .. star.size) DO
satellites ← CONS [map[star[i]], satellites];
ENDLOOP;
newParent ← CreateStar[master, satellites, star.overlayStar];
};
WriteStar: PipalIO.ClassWriteProc = {
star: Star ← NARROW [object];
BrineIO.WriteBool[stream, star.overlayStar];
PipalIO.WriteObject[stream, star.master];
BrineIO.WriteInt[stream, star.size];
FOR i: NAT IN [0 .. star.size) DO PipalIO.WriteObject[stream, star[i]] ENDLOOP;
};
ReadStar: PipalIO.ClassReadProc = {
overlayStar: BOOL ← BrineIO.ReadBool[stream];
master: Pipal.Object ← PipalIO.ReadObject[stream];
object ← CreateStar[master, PipalIO.ReadObjects[stream], overlayStar];
};
Routing
routingClass: PUBLIC Pipal.Class ← Pipal.RegisterClass[name: "Routing", type: CODE [RoutingRec]];
DescribeRouting: Pipal.DescribeProc = {
routing: Routing ← NARROW [object];
Pipal.PutIndent[out, indent, cr];
IO.PutF[out, "Routing: %g nodes", IO.int[routing.size]];
};
EnumerateRouting: PipalInt.EnumerateProc = {
routing: Routing ← NARROW [object];
FOR i: NAT IN [0 .. routing.size) DO
quit ← each[transformation, routing[i]];
IF quit THEN RETURN;
ENDLOOP;
};
CreateRouting: PUBLIC PROC [nodes: Objects] RETURNS [routing: Routing] = {
size: NAT ← Pipal.Length[nodes];
routing ← NEW [RoutingRec[size]];
FOR i: NAT IN [0 .. size) DO routing[i] ← nodes.first; nodes ← nodes.rest ENDLOOP;
};
ReplaceRouting: PipalOps.ReplaceProc = {
routing: Routing ← NARROW [parent];
nodes: Pipal.Objects ← NIL;
FOR i: NAT DECREASING IN [0 .. routing.size) DO
nodes ← CONS [map[routing[i]], nodes];
ENDLOOP;
newParent ← CreateRouting[nodes];
};
WriteRouting: PipalIO.ClassWriteProc = {
routing: Routing ← NARROW [object];
BrineIO.WriteInt[stream, routing.size];
FOR i: NAT IN [0 .. routing.size) DO PipalIO.WriteObject[stream, routing[i]] ENDLOOP;
};
ReadRouting: PipalIO.ClassReadProc = {
object ← CreateRouting[PipalIO.ReadObjects[stream]];
};
Tiling
tilingClass: PUBLIC Pipal.Class ← Pipal.RegisterClass[name: "Tiling", type: CODE [TilingRec]];
DescribeTiling: Pipal.DescribeProc = {
tiling: Tiling ← NARROW [object];
Pipal.PutIndent[out, indent, cr];
IO.PutF[out, "Tiling: [%g, %g]", IO.int[tiling.sizeX], IO.int[tiling.sizeY]];
};
EnumerateTiling: PipalInt.EnumerateProc = {
tiling: Tiling ← NARROW [object];
pos: PipalInt.Position;
pos.y ← 0;
FOR y: NAT IN [0 .. tiling.sizeY) DO
pos.x ← 0;
FOR x: NAT IN [0 .. tiling.sizeX) DO
sub: Object ← tiling.xyTile[x, y, tiling.data];
quit ← each[PipalInt.Compose[transformation, [pos]], sub];
IF quit THEN RETURN;
pos.x ← pos.x + PipalInt.AbutBox[sub].size.x;
ENDLOOP;
pos.y ← pos.y + PipalInt.AbutBox[tiling.xyTile[0, y, tiling.data]].size.y;
ENDLOOP;
};
CreateTiling: PUBLIC PROC [sizeX, sizeY: NAT, xyTile: XYTileProc, data: REFNIL] RETURNS [tiling: Tiling] = {
tiling ← NEW [TilingRec ← [sizeX: sizeX, sizeY: sizeY, xyTile: xyTile, data: data]];
Checking all right
IF sizeX=0 OR sizeY=0 THEN ERROR;
FOR y: NAT IN [0 .. sizeY) DO
height: INT ← PipalInt.AbutBox[tiling.xyTile[0, y, tiling.data]].size.y;
FOR x: NAT IN [1 .. sizeX) DO
IF PipalInt.AbutBox[tiling.xyTile[x, y, tiling.data]].size.y#height THEN ERROR; -- constraint of same height within a row not respected!
ENDLOOP;
ENDLOOP;
FOR x: NAT IN [0 .. sizeX) DO
width: INT ← PipalInt.AbutBox[tiling.xyTile[x, 0, tiling.data]].size.x;
FOR y: NAT IN [1 .. sizeY) DO
IF PipalInt.AbutBox[tiling.xyTile[x, y, tiling.data]].size.x#width THEN ERROR; -- constraint of same width within a column not respected!
ENDLOOP;
ENDLOOP;
};
EnumerateTiles: PUBLIC PROC [tiling: Tiling, each: EachTileProc] RETURNS [quit: BOOLFALSE] = {
pos: PipalInt.Position ← [0, 0];
FOR y: NAT IN [0 .. tiling.sizeY) DO
pos.x ← 0;
FOR x: NAT IN [0 .. tiling.sizeX) DO
tile: Object ← tiling.xyTile[x, y, tiling.data];
quit ← each[x, y, tile, pos];
IF quit THEN RETURN;
pos.x ← pos.x + PipalInt.AbutBox[tile].size.x;
ENDLOOP;
pos.y ← pos.y + PipalInt.AbutBox[tiling.xyTile[0, y, tiling.data]].size.y;
ENDLOOP;
};
WriteTiling: PipalIO.ClassWriteProc = {
tiling: Tiling ← NARROW [object];
BrineIO.WriteInt[stream, tiling.sizeX];
BrineIO.WriteInt[stream, tiling.sizeY];
FOR y: NAT IN [0 .. tiling.sizeY) DO
FOR x: NAT IN [0 .. tiling.sizeX) DO PipalIO.WriteObject[stream, tiling.xyTile[x, y, tiling.data]] ENDLOOP;
ENDLOOP;
};
TileArrayRec: TYPE = RECORD [SEQUENCE sizeY: NAT OF REF TileLinesRec];
TileLinesRec: TYPE = RECORD [SEQUENCE sizeX: NAT OF Pipal.Object];
TileArrayXY: XYTileProc = {
tileArray: REF TileArrayRec ← NARROW [data];
RETURN [tileArray[y][x]];
};
ReadTiling: PipalIO.ClassReadProc = {
sizeX: NATNAT [BrineIO.ReadInt[stream]];
sizeY: NATNAT [BrineIO.ReadInt[stream]];
tileArray: REF TileArrayRec ← NEW [TileArrayRec[sizeY]];
FOR y: NAT IN [0 .. sizeY) DO
tileArray[y] ← NEW [TileLinesRec[sizeX]];
FOR x: NAT IN [0 .. sizeX) DO tileArray[y][x] ← PipalIO.ReadObject[stream] ENDLOOP;
ENDLOOP;
object ← CreateTiling[sizeX, sizeY, TileArrayXY, tileArray];
};
Marker
markerClass: PUBLIC Pipal.Class ← Pipal.RegisterClass[name: "Marker", type: CODE [MarkerRec]];
SizeMarker: PipalInt.SizeProc = {
marker: Marker ← NARROW [object];
size ← marker.size;
};
PaintMarker: PipalPaint.PaintProc = {
marker: Marker ← NARROW [object];
color: ImagerColor.ConstantColor ← FetchLayerColor[marker.layer];
size: PipalInt.Size ← marker.size;
PipalPaint.SetColor[context, color];
Imager.MaskVector[context, [0, 0], [size.x, size.y]];
Imager.MaskVector[context, [0, size.y], [size.x, 0]];
};
DescribeMarker: Pipal.DescribeProc = {
marker: Marker ← NARROW [object];
Pipal.PutIndent[out, indent, cr];
IO.PutF[out, "Marker %g %g", IO.atom[marker.layer], IO.rope[PipalInt.VectorToRope[marker.size]]];
};
HashMarker: Pipal.HashProc = {
marker: Marker ← NARROW [object];
hash ← RopeHash.FromRope[IO.PutR1[IO.atom[marker.layer]]] + PipalInt.HashVector[marker.size];
};
EqualMarker: Pipal.EqualProc = {
marker1: Marker ← NARROW [object1];
marker2: Marker ← NARROW [object2];
equal ← marker1^=marker2^;
};
CreateMarker: PUBLIC PROC [size: PipalInt.Size, layer: Layer] RETURNS [marker: Marker] = {
IF FetchLayerColor[layer]=NIL THEN ERROR;
marker ← NEW [MarkerRec ← [size: size, layer: layer]];
};
WriteMarker: PipalIO.ClassWriteProc = {
marker: Marker = NARROW [object];
PipalIO.WriteIntVector[stream, marker.size];
BrineIO.WriteAtom[stream, marker.layer];
};
ReadMarker: PipalIO.ClassReadProc = {
size: PipalInt.Size = PipalIO.ReadIntVector[stream];
layer: Layer = BrineIO.ReadAtom[stream];
RETURN [CreateMarker[size, layer]]
};
Schematic Icons
schematicIconClass: PUBLIC Pipal.Class ← Pipal.RegisterClass[name: "SchematicIcon", type: CODE [SchematicIconRec]];
DescribeSchematicIcon: Pipal.DescribeProc = {
icon: SchematicIcon ← NARROW [object];
Pipal.PutIndent[out, indent, cr];
IO.PutF[out, "SchematicIcon: [%g, %g, %g]", IO.rope[icon.expression], IO.rope[IF icon.code THEN "code" ELSE "sch"], IO.rope[SELECT icon.type FROM cell => "cell", wire => "wire", unnamedWire => "unnamedWire", ENDCASE => ERROR]];
};
EqualSchematicIcon: Pipal.EqualProc = {
icon1: SchematicIcon ← NARROW [object1];
icon2: SchematicIcon ← NARROW [object2];
equal ← Rope.Equal[icon1.expression, icon2.expression] AND icon1.code=icon2.code AND icon1.type=icon2.type AND Pipal.Equal[icon1.child, icon2.child];
};
EnumerateSchematicIcon: PipalInt.EnumerateProc = {
icon: SchematicIcon ← NARROW [object];
quit ← each[transformation, icon.child];
};
CreateSchematicIcon: PUBLIC PROC [child: Pipal.Object, expression: Pipal.ROPE, code: BOOL, type: SchematicIconType] RETURNS [icon: SchematicIcon] = {
icon ← NEW [SchematicIconRec ← [child: child, expression: expression, code: code, type: type]];
};
ReplaceSchematicIcon: PipalOps.ReplaceProc = {
icon: SchematicIcon ← NARROW [parent];
child: Pipal.Object ← map[icon.child];
newParent ← CreateSchematicIcon[child, icon.expression, icon.code, icon.type];
};
WriteSchematicIcon: PipalIO.ClassWriteProc = {
icon: SchematicIcon = NARROW [object];
PipalIO.WriteObject[stream, icon.child];
BrineIO.WriteRope[stream, icon.expression];
BrineIO.WriteBool[stream, icon.code];
BrineIO.WriteInt[stream, ORD [icon.type]];
};
ReadSchematicIcon: PipalIO.ClassReadProc = {
child: Pipal.Object ← PipalIO.ReadObject[stream];
expression: Pipal.ROPE ← BrineIO.ReadRope[stream];
code: BOOL ← BrineIO.ReadBool[stream];
ord: NAT ← BrineIO.ReadInt[stream];
type: SchematicIconType ← VAL [ord];
RETURN [CreateSchematicIcon[child, expression, code, type]]
};
Schematic Sequences
schematicSequenceClass: PUBLIC Pipal.Class ← Pipal.RegisterClass[name: "SchematicSequence", type: CODE [SchematicSequenceRec]];
DescribeSchematicSequence: Pipal.DescribeProc = {
seq: SchematicSequence ← NARROW [object];
Pipal.PutIndent[out, indent, cr];
IO.PutF[out, "SchematicSequence: [%g]", IO.rope[seq.repetition]];
};
EqualSchematicSequence: Pipal.EqualProc = {
seq1: SchematicSequence ← NARROW [object1];
seq2: SchematicSequence ← NARROW [object2];
equal ← Rope.Equal[seq1.repetition, seq2.repetition] AND Pipal.Equal[seq1.child, seq2.child];
};
EnumerateSchematicSequence: PipalInt.EnumerateProc = {
seq: SchematicSequence ← NARROW [object];
quit ← each[transformation, seq.child];
};
CreateSchematicSequence: PUBLIC PROC [child: Pipal.Object, repetition: Pipal.ROPE] RETURNS [seq: SchematicSequence] = {
seq ← NEW [SchematicSequenceRec ← [child: child, repetition: repetition]];
};
ReplaceSchematicSequence: PipalOps.ReplaceProc = {
seq: SchematicSequence ← NARROW [parent];
child: Pipal.Object ← map[seq.child];
newParent ← CreateSchematicSequence[child, seq.repetition];
};
WriteSchematicSequence: PipalIO.ClassWriteProc = {
seq: SchematicSequence = NARROW [object];
PipalIO.WriteObject[stream, seq.child];
BrineIO.WriteRope[stream, seq.repetition];
};
ReadSchematicSequence: PipalIO.ClassReadProc = {
child: Pipal.Object ← PipalIO.ReadObject[stream];
repetition: Pipal.ROPE ← BrineIO.ReadRope[stream];
RETURN [CreateSchematicSequence[child, repetition]]
};
Text
textClass: PUBLIC Pipal.Class ← Pipal.RegisterClass[name: "Text", type: CODE [TextRec]];
ComputeBBoxText: PROC [text: Text] RETURNS [bbox: Rectangle] = {
fontExt: ImagerFont.Extents ← ImagerFont.FontBoundingBox[text.font];
ropeExt: ImagerFont.Extents ← ImagerFont.RopeBoundingBox[text.font, text.contents];
originX: INT ← Real.Ceiling[fontExt.leftExtent];
originY: INT ← Real.Ceiling[fontExt.descent];
endX: INT ← Real.Ceiling[ropeExt.rightExtent];
endY: INT ← Real.Ceiling[fontExt.ascent];
bbox ← [[-originX, -originY], [endX+originX, endY+originY]];
};
SizeText: PipalInt.SizeProc = {size ← ComputeBBoxText[NARROW [object]].size};
AbutBoxText: PipalInt.AbutBoxProc = {abutBox ← ComputeBBoxText[NARROW [object]]};
BBoxText: PipalInt.BBoxProc = {
bbox ← PipalInt.TransformRectangle[transformation, ComputeBBoxText[NARROW [object]]];
};
PaintText: PipalPaint.PaintProc = {
text: Text ← NARROW [object];
bbox: Rectangle ← ComputeBBoxText[text];
PipalPaint.PaintFlippedText[context, text.contents, text.font, bbox];
};
DescribeText: Pipal.DescribeProc = {
text: Text ← NARROW [object];
Pipal.PutIndent[out, indent, cr];
IO.PutF[out, "Text %g", IO.rope[text.contents]];
};
HashText: Pipal.HashProc = {
text: Text ← NARROW [object];
hash ← RopeHash.FromRope[text.contents] + PipalInt.HashObjectSize[object];
};
EqualText: Pipal.EqualProc = {
text1: Text ← NARROW [object1];
text2: Text ← NARROW [object2];
equal ← Rope.Equal[text1.contents, text2.contents] AND text1.font=text2.font;
};
CreateText: PUBLIC PROC [contents: ROPE, font: Imager.Font] RETURNS [text: Text] = {
IF font=NIL THEN ERROR;
text ← NEW [TextRec ← [contents: contents, font: font]];
};
GetTextFontName: PUBLIC PROC [text: Text] RETURNS [fontName: ROPE] = {
font: Imager.Font ← text.font;
typeface: REF ← font.typeface;
typeface2: ImagerTypeface.Typeface ← NARROW [typeface];
fontName ← typeface2.name;
};
IsItalic: PUBLIC PROC [fontName: ROPE] RETURNS [BOOLFALSE] = {
pressFontLeng: INT = 17; pressFontName: ROPE = "Xerox/PressFonts/";
tiogaFontLeng: INT = 17; tiogaFontName: ROPE = "Xerox/TiogaFonts/";
leng: INT ← Rope.Length[fontName];
IF leng>tiogaFontLeng THEN
IF Rope.Equal[Rope.Substr[fontName, 0, tiogaFontLeng], tiogaFontName, FALSE] THEN
RETURN [Ascii.Upper[Rope.Fetch[fontName, leng-1]]='I];
IF leng>pressFontLeng THEN
IF Rope.Equal[Rope.Substr[fontName, 0, pressFontLeng], pressFontName, FALSE] THEN
RETURN [Ascii.Upper[Rope.Fetch[fontName, leng-2]]='I]
};
WriteText: PipalIO.ClassWriteProc = {
text: Text = NARROW [object];
typeface: REF ← text.font.typeface;
BrineIO.WriteRope[stream, text.contents];
PipalIO.WriteRealTransformation[stream, text.font.charToClient];
BrineIO.WriteRope[stream, NARROW [typeface, ImagerTypeface.Typeface].name];
};
ReadText: PipalIO.ClassReadProc = {
contents: Pipal.ROPE ← BrineIO.ReadRope[stream];
transformation: PipalReal.Transformation ← PipalIO.ReadRealTransformation[stream];
name: Pipal.ROPE ← BrineIO.ReadRope[stream];
typeface: ImagerTypeface.Typeface ← ImagerTypeface.FindTypeface[name, noSubstitute];
font: Imager.Font ← ImagerTypeface.MakeFont[typeface, transformation];
RETURN [CreateText[contents, font]];
};
Picture
pictureClass: PUBLIC Pipal.Class ← Pipal.RegisterClass[name: "Picture", type: CODE [PictureRec]];
SizePicture: PipalInt.SizeProc = {
picture: Picture ← NARROW [object];
size ← picture.size;
};
PaintPicture: PipalPaint.PaintProc = {
picture: Picture ← NARROW [object];
Imager.DrawObject[context, picture.imagerObject, Imager.zeroVEC, TRUE];
};
CreatePicture: PUBLIC PROC [size: PipalInt.Size, imagerObject: Imager.Object] RETURNS [picture: Picture] = {
IF imagerObject=NIL THEN ERROR;
picture ← NEW [PictureRec ← [size: size, imagerObject: imagerObject]];
};
LogSignal: SIGNAL = CODE;
Log: Interpress.LogProc = {
SIGNAL LogSignal[];
};
metersPerPoint: REAL = Imager.metersPerInch / Imager.pointsPerInch;
MasterBounds: PROC [ipMaster: Interpress.Master] RETURNS [rect: PipalReal.Rectangle] = {
scale: REAL ← 150.0/0.0254; -- ~150 pixels/inch
m: Imager.Transformation ← ImagerTransformation.Scale[scale];
Operator: PROC [context: Imager.Context] ~ {
Imager.SetColor[context, Imager.black];
Imager.SetStrokeEnd[context, square];
Imager.SetStrokeWidth[context, 0.0];
Imager.SetAmplifySpace[context, 1.0];
Interpress.DoPage[ipMaster, 1, context, NIL];
};
box: SF.Box ← ImagerMaskCapture.CaptureBounds[Operator, m];
rect.base.x ← box.min.s/scale; rect.base.y ← box.min.f/scale;
rect.size.x ← (box.max.s-box.min.s)/scale; rect.size.y ← (box.max.f-box.min.f)/scale;
rect is in meters now!
};
ScaleIP: TYPE = REF ScaleIPRec;
ScaleIPRec: TYPE = RECORD [trans: Imager.Transformation, ipMaster: Interpress.Master];
InterpressDraw: PROC [self: Imager.Object, context: Imager.Context] = {
scaleIP: ScaleIP ← NARROW [self.data];
ipMaster: Interpress.Master ← scaleIP.ipMaster;
Imager.ConcatT[context, scaleIP.trans];
Interpress.DoPage[master: ipMaster, page: 1, context: context, log: Log];
};
CreatePictureFromInterpress: PUBLIC PROC [size: PipalInt.Size, master: Pipal.ROPE] RETURNS [picture: Picture] = {
ipMaster: Interpress.Master ← Interpress.FromRope[rope: master, log: Log];
rect: PipalReal.Rectangle ← MasterBounds[ipMaster];
trans: Imager.Transformation ← ImagerTransformation.Concat[
ImagerTransformation.Translate[[-rect.base.x, -rect.base.y]],
ImagerTransformation.Scale2[[IF rect.size.x=0 THEN 1 ELSE size.x / rect.size.x, IF rect.size.y=0 THEN 1 ELSE size.y / rect.size.y]]
];
picture ← CreatePicture[
size,
NEW [Imager.ObjectRep ← [draw: InterpressDraw, clip: [0, 0, size.x, size.y], data: NEW [ScaleIPRec ← [trans: trans, ipMaster: ipMaster]]]]
];
};
HashPicture: Pipal.HashProc = {
picture: Picture = NARROW [object];
hash ← Pipal.HashObjectClass[object] + PipalInt.HashVector[picture.size];
};
EqualPicture: Pipal.EqualProc = {
picture1: Picture ← NARROW [object1];
picture2: Picture ← NARROW [object2];
equal ← picture1.size=picture2.size AND Rope.Equal[PictureToRope[picture1], PictureToRope[picture2]];
};
PictureToRope: PROC [picture: Picture] RETURNS [rope: Pipal.ROPE] = {
DrawPicture: PROC [context: Imager.Context] = {
picture.imagerObject.draw[picture.imagerObject, context];
};
master: IO.STREAMIO.ROS[];
ipMaster: ImagerInterpress.Ref ← ImagerInterpress.CreateFromStream[master, "Interpress/Xerox/3.0 "];
ImagerInterpress.DoPage[ipMaster, DrawPicture, metersPerPoint];
ImagerInterpress.Finish[ipMaster];
rope ← IO.RopeFromROS[master];
};
Could be made denser!
WritePicture: PipalIO.ClassWriteProc = {
CodeChar: Rope.ActionType = {BrineIO.WriteInt[stream, ORD [c]]};
picture: Picture = NARROW [object];
rope: Pipal.ROPE ← PictureToRope[picture];
PipalIO.WriteIntVector[stream, picture.size];
BrineIO.WriteInt[stream, Rope.Length[rope]];
[] ← Rope.Map[base: rope, action: CodeChar];
};
ReadPicture: PipalIO.ClassReadProc = {
DecodeChar: PROC RETURNS [CHAR] = {
nat: NAT ← BrineIO.ReadInt[stream];
RETURN [VAL [nat]];
};
size: PipalInt.Size ← PipalIO.ReadIntVector[stream];
length: INT ← BrineIO.ReadInt[stream];
master: Pipal.ROPE ← Rope.FromProc[length, DecodeChar];
RETURN [CreatePictureFromInterpress[size, master]];
};
Annotations
indirectProp: PUBLIC ATOM ← $MosIndirect;
The annotation value is NIL
atomicProp: PUBLIC ATOM ← $MosAtomic;
biAtomicProp: PUBLIC ATOM ← $MosBiAtomic;
transistorProp: PUBLIC ATOM ← $MosTransistor;
IsAnnotationAtomic: IsAtomicProc = {
annotation: Pipal.Annotation ← NARROW [object];
RETURN [annotation.key=atomicProp OR annotation.key=biAtomicProp OR annotation.key=transistorProp];
};
Atomicity
isAtomicMethod: PUBLIC Pipal.Method ← Pipal.RegisterMethod["MosIsAtomic"];
IsAtomic: PUBLIC IsAtomicProc = {
refProc: REF IsAtomicProc = NARROW [Pipal.ObjectMethod[object, isAtomicMethod]];
RETURN [IF refProc=NIL THEN NOT PipalInt.HasEnumerate[object] ELSE refProc^[object]];
};
EnumerateAtomic: PUBLIC PipalInt.EnumerateProc = {
FilterAtomic: PipalInt.EachChildProc = {
quit ← IF IsAtomic[child]
THEN each[transformation, child]
ELSE PipalInt.Enumerate[child, FilterAtomic, transformation];
};
quit ← FilterAtomic[transformation, object];
};
clippedEnumerationClass: PUBLIC Pipal.Class ← Pipal.RegisterClass[name: "ClippedEnumeration", type: CODE [ClippedEnumerationRec]];
CreateClippedEnumeration: PUBLIC PROC [clipRect: Rectangle, child: Object] RETURNS [clippedEnumeration: ClippedEnumeration] = {
clippedEnumeration ← NEW [ClippedEnumerationRec ← [clipRect: clipRect, child: child]];
};
EnumerateClippedEnumeration: PipalInt.EnumerateProc = {
ClipEach: PipalInt.EachChildProc = {
IF PipalInt.AtEdge[ce.clipRect, transformation, child] THEN quit ← each[transformation, child];
};
ce: ClippedEnumeration ← NARROW [object];
quit ← EnumerateAtomic[ce.child, ClipEach, transformation];
};
CountAtomicChildren: PUBLIC PROC [object: Object] RETURNS [count: INT ← 0] = {
CountEach: PipalInt.EachChildProc = {count ← count + 1};
[] ← EnumerateAtomic[object, CountEach, []];
};
expandPortsCount: INT ← 5;
This function does not create a ClippedEnumeration, but rather creates the most appropriate representation. This is the key to space/time trade-offs.
CreateClipEnum: PUBLIC PROC [clipRect: Rectangle, child: Object] RETURNS [Object] = {
clippedEnumeration: ClippedEnumeration ← CreateClippedEnumeration[clipRect, child];
count: INT ← CountAtomicChildren[clippedEnumeration];
children: Objects ← NIL;
ConsEachChild: PipalInt.EachChildProc = {
IF child=Pipal.void THEN ERROR;
children ← CONS [PipalInt.TransformObject[transformation, child], children];
};
IF count>expandPortsCount THEN RETURN [clippedEnumeration];
IF EnumerateAtomic[clippedEnumeration, ConsEachChild] THEN ERROR;
RETURN [Pipal.CreateOv[children]];
};
Mask Layers
EnumerateRectangleLayers: PUBLIC PROC [object: Object, each: EachRectangleLayerProc, transformation: Transformation ← [], includeMarkers, includeSchematicLayer: BOOLTRUE] RETURNS [quit: BOOLFALSE] = {
InternalEach: PipalInt.EachChildProc = {
Of course, we should have a message here, instead of a type dispatch!
SELECT Pipal.ObjectClass[child] FROM
boxClass => {
box: Box ← NARROW [child];
IF includeSchematicLayer OR NOT IsSchematicLayer[box.layer] THEN quit ← each[PipalInt.TransformBBox[transformation, box.size], box.layer, FALSE];
};
markerClass => {
marker: Marker ← NARROW [child];
IF includeMarkers AND (includeSchematicLayer OR NOT IsSchematicLayer[marker.layer]) THEN quit ← each[PipalInt.TransformBBox[transformation, marker.size], marker.layer, TRUE];
};
pictureClass, textClass => {};
ENDCASE  => quit ← PipalInt.Enumerate[child, InternalEach, transformation];
};
quit ← InternalEach[transformation, object];
};
ContainsWell: PUBLIC PROC [object: Object] RETURNS [BOOL] = {
Each: EachRectangleLayerProc = {quit ← IsWellLayer[layer]};
RETURN [EnumerateRectangleLayers[object: object, each: Each, includeSchematicLayer: FALSE]];
};
Touch: PUBLIC TouchProc = {
GenericTouchInstance1: PipalInt.EachChildProc = {
quit ← touch[touch, transformation, child, trans1, object1];
};
GenericTouchInstance2: PipalInt.EachChildProc = {
quit ← touch[touch, trans2, object2, transformation, child];
};
RectTouchInstance2: EachRectangleLayerProc = {
RectTouchInstance12: EachRectangleLayerProc = {
quit ← PipalInt.DoRectanglesIntersect[rect, rect1] AND layer=layer1;
};
rect1: Rectangle ← rect;
layer1: Layer ← layer;
quit ← EnumerateRectangleLayers[object2, RectTouchInstance12, trans2];
};
IF NOT PipalInt.DoRectanglesIntersect[PipalInt.BBox[object1, trans1], PipalInt.BBox[object2, trans2]] THEN RETURN;
IF PipalInt.HasEnumerate[object1] THEN RETURN [PipalInt.Enumerate[object1, GenericTouchInstance2, trans1]];
IF PipalInt.HasEnumerate[object2] THEN RETURN [PipalInt.Enumerate[object2, GenericTouchInstance1, trans2]];
RETURN [EnumerateRectangleLayers[object1, RectTouchInstance2, trans1]];
};
LayoutTouch: PUBLIC TouchProc = {
IsRect: PROC [object: Object, layer: Layer] RETURNS [BOOL] = INLINE {
IF NOT ISTYPE [object, Box] THEN RETURN [FALSE];
RETURN [NARROW [object, Box].layer=layer];
};
ChangeRect: PROC [object: Object, layer: Layer] RETURNS [Object] = {
box: Box = NARROW [object];
RETURN [CreateBox[box.size, layer]];
};
IF IsRect[object1, $PwellCont] THEN RETURN [
touch[touch, trans1, ChangeRect[object1, $Pwell], trans2, object2] OR
touch[touch, trans1, ChangeRect[object1, $Pdif], trans2, object2]
];
IF IsRect[object1, $NwellCont] THEN RETURN [
touch[touch, trans1, ChangeRect[object1, $Nwell], trans2, object2] OR
touch[touch, trans1, ChangeRect[object1, $Ndif], trans2, object2]
];
IF IsRect[object2, $PwellCont] THEN RETURN [
touch[touch, trans2, ChangeRect[object2, $Pwell], trans1, object1] OR
touch[touch, trans2, ChangeRect[object2, $Pdif], trans1, object1]
];
IF IsRect[object2, $NwellCont] THEN RETURN [
touch[touch, trans2, ChangeRect[object2, $Nwell], trans1, object1] OR
touch[touch, trans2, ChangeRect[object2, $Ndif], trans1, object1]
];
IF IsRect[object1, $Met2] AND IsRect[object2, $Ovg] THEN RETURN [
PipalInt.IsInsideRectangle[PipalInt.BBox[object1, trans1], PipalInt.BBox[object2, trans2]]
];
IF IsRect[object1, $Ovg] AND IsRect[object2, $Met2] THEN RETURN [
PipalInt.IsInsideRectangle[PipalInt.BBox[object2, trans2], PipalInt.BBox[object1, trans1]]
];
RETURN Touch[touch, trans1, object1, trans2, object2];
};
SchematicTouch: PUBLIC TouchProc = {
GenericTouchInstance1: PipalInt.EachChildProc = {
quit ← touch[touch, transformation, child, trans1, object1];
};
GenericTouchInstance2: PipalInt.EachChildProc = {
quit ← touch[touch, trans2, object2, transformation, child];
};
IF NOT PipalInt.DoRectanglesIntersect[PipalInt.BBox[object1, trans1], PipalInt.BBox[object2, trans2]] THEN RETURN;
IF PipalInt.HasEnumerate[object1] THEN RETURN [PipalInt.Enumerate[object1, GenericTouchInstance2, trans1]];
IF PipalInt.HasEnumerate[object2] THEN RETURN [PipalInt.Enumerate[object2, GenericTouchInstance1, trans2]];
IF Pipal.ObjectClass[object1]#boxClass OR Pipal.ObjectClass[object2]#boxClass THEN ERROR; -- the only thing we know is Rectangles!
IF ~SilTouchRect[PipalInt.BBox[object1, trans1], PipalInt.BBox[object2, trans2]] THEN RETURN;
RETURN [NARROW [object1, Box].layer=NARROW [object2, Box].layer];
};
SilTouchRect: PROC [r1, r2: Rectangle] RETURNS [BOOL] = INLINE {
Intersect: PROC [i1min, i1max, i2min, i2max: PipalInt.Number] RETURNS [BOOL] = INLINE {
RETURN [(i1max >= i2min) AND (i2max >= i1min)];
};
Adjoin: PROC [i1min, i1max, i2min, i2max: PipalInt.Number] RETURNS [BOOL] = INLINE {
RETURN [(i2min >= i1min AND i2min <= i1max AND i2max >= i1max) OR
(i1min >= i2min AND i1min <= i2max AND i1max >= i2max)];
};
RETURN [
(Intersect[r1.base.x, r1.base.x+r1.size.x, r2.base.x, r2.base.x+r2.size.x] AND Adjoin[r1.base.y, r1.base.y+r1.size.y, r2.base.y, r2.base.y+r2.size.y])
OR
(Intersect[r1.base.y, r1.base.y+r1.size.y, r2.base.y, r2.base.y+r2.size.y] AND Adjoin[r1.base.x, r1.base.x+r1.size.x, r2.base.x, r2.base.x+r2.size.x])
OR PipalInt.IsInsideRectangle[r1, r2] OR PipalInt.IsInsideRectangle[r2, r1]
]
};
Transistors
extractTransistorMethod: PUBLIC Pipal.Method ← Pipal.RegisterMethod["MosExtractTransistor"];
ExtractTransistor: PUBLIC ExtractTransistorProc = {
RETURN (NARROW [Pipal.ObjectMethod[object, extractTransistorMethod], REF ExtractTransistorProc]^)[object];
};
Initialization
Layers
ShortRegisterLayerColor: PROC [layer: Layer, colorName: ROPE] = {
RegisterLayerColor[layer, ImagerColor.Find[Rope.Cat["Xerox/Research/ChipNDale/CMosB/", colorName]]];
};
RegisterLayerColor[$Error, Imager.white];
RegisterLayerColor[$Comment, Imager.black];
RegisterLayerColor[$Bond, Imager.white];
ShortRegisterLayerColor[$Pdif, "PDif"];
ShortRegisterLayerColor[$Ndif, "NDif"];
ShortRegisterLayerColor[$PwellCont, "PWelCont"];
ShortRegisterLayerColor[$NwellCont, "NWelCont"];
ShortRegisterLayerColor[$Pwell, "PWel"];
ShortRegisterLayerColor[$Nwell, "NWel"];
ShortRegisterLayerColor[$Pol, "Pol"];
ShortRegisterLayerColor[$Met, "Met"];
ShortRegisterLayerColor[$Met2, "Met2"];
ShortRegisterLayerColor[$Ovg, "Ovg"];
ShortRegisterLayerColor[$Cut, "Cut"];
ShortRegisterLayerColor[$Cut2, "Cut2"];
ShortRegisterLayerColor[$BlueComment, "Met"];
Box
Pipal.PutClassMethod[boxClass, PipalInt.sizeMethod, NEW [PipalInt.SizeProc ← SizeBox]];
Pipal.PutClassMethod[boxClass, PipalReal.sizeMethod, NEW [PipalReal.SizeProc ← PipalReal.UseIntSize]];
Pipal.PutClassMethod[boxClass, PipalInt.abutBoxMethod, NEW [PipalInt.AbutBoxProc ← PipalInt.AbutBoxFromSize]];
Pipal.PutClassMethod[boxClass, PipalPaint.paintMethod, NEW [PipalPaint.PaintProc ← PaintBox]];
Pipal.PutClassMethod[boxClass, Pipal.describeMethod, NEW [Pipal.DescribeProc ← DescribeBox]];
Pipal.PutClassMethod[boxClass, Pipal.hashMethod, NEW [Pipal.HashProc ← HashBox]];
Pipal.PutClassMethod[boxClass, Pipal.equalMethod, NEW [Pipal.EqualProc ← EqualBox]];
PipalIO.RegisterClass[boxClass, ReadBox, WriteBox];
Star
Pipal.PutClassMethod[starClass, Pipal.describeMethod, NEW [Pipal.DescribeProc ← DescribeStar]];
Pipal.PutClassMethod[starClass, Pipal.hashMethod, NEW [Pipal.HashProc ← PipalOps.HashByEnumeration]];
Pipal.PutClassMethod[starClass, Pipal.equalMethod, NEW [Pipal.EqualProc ← PipalOps.EqualByEnumeration]];
Pipal.PutClassMethod[starClass, PipalInt.sizeMethod, NEW [PipalInt.SizeProc ← PipalInt.CachedSizeFromEnumerate]];
Pipal.PutClassMethod[starClass, PipalInt.bboxMethod, NEW [PipalInt.BBoxProc ← PipalInt.CachedBBoxFromEnumerate]];
Pipal.PutClassMethod[starClass, PipalInt.abutBoxMethod, NEW [PipalInt.AbutBoxProc ← PipalInt.CachedAbutBoxFromEnumerate]];
Pipal.PutClassMethod[starClass, PipalInt.enumerateMethod, NEW [PipalInt.EnumerateProc ← EnumerateStar]];
Pipal.PutClassMethod[starClass, PipalOps.replaceMethod, NEW [PipalOps.ReplaceProc ← ReplaceStar]];
PipalIO.RegisterClass[starClass, ReadStar, WriteStar];
Routing
Pipal.PutClassMethod[routingClass, Pipal.describeMethod, NEW [Pipal.DescribeProc ← DescribeRouting]];
Pipal.PutClassMethod[routingClass, Pipal.hashMethod, NEW [Pipal.HashProc ← PipalOps.CachedHashByEnumeration]];
Pipal.PutClassMethod[routingClass, Pipal.equalMethod, NEW [Pipal.EqualProc ← PipalOps.EqualByEnumeration]];
Pipal.PutClassMethod[routingClass, PipalInt.sizeMethod, NEW [PipalInt.SizeProc ← PipalInt.CachedSizeFromEnumerate]];
Pipal.PutClassMethod[routingClass, PipalInt.bboxMethod, NEW [PipalInt.BBoxProc ← PipalInt.CachedBBoxFromEnumerate]];
Pipal.PutClassMethod[routingClass, PipalInt.abutBoxMethod, NEW [PipalInt.AbutBoxProc ← PipalInt.CachedAbutBoxFromEnumerate]];
Pipal.PutClassMethod[routingClass, PipalInt.enumerateMethod, NEW [PipalInt.EnumerateProc ← EnumerateRouting]];
Pipal.PutClassMethod[routingClass, PipalOps.replaceMethod, NEW [PipalOps.ReplaceProc ← ReplaceRouting]];
PipalIO.RegisterClass[routingClass, ReadRouting, WriteRouting];
Tiling
Pipal.PutClassMethod[tilingClass, Pipal.describeMethod, NEW [Pipal.DescribeProc ← DescribeTiling]];
Pipal.PutClassMethod[tilingClass, Pipal.hashMethod, NEW [Pipal.HashProc ← PipalOps.CachedHashByEnumeration]];
Pipal.PutClassMethod[tilingClass, Pipal.equalMethod, NEW [Pipal.EqualProc ← PipalOps.EqualByEnumeration]];
Pipal.PutClassMethod[tilingClass, PipalInt.sizeMethod, NEW [PipalInt.SizeProc ← PipalInt.CachedSizeFromEnumerate]];
Pipal.PutClassMethod[tilingClass, PipalInt.bboxMethod, NEW [PipalInt.BBoxProc ← PipalInt.CachedBBoxFromEnumerate]];
Pipal.PutClassMethod[tilingClass, PipalInt.abutBoxMethod, NEW [PipalInt.AbutBoxProc ← PipalInt.CachedAbutBoxFromEnumerate]];
Pipal.PutClassMethod[tilingClass, PipalInt.enumerateMethod, NEW [PipalInt.EnumerateProc ← EnumerateTiling]];
Pipal.PutClassMethod[tilingClass, PipalOps.replaceMethod, NEW [PipalOps.ReplaceProc ← PipalOps.ReplaceFromRecast]];
PipalIO.RegisterClass[tilingClass, ReadTiling, WriteTiling];
Marker
Pipal.PutClassMethod[markerClass, PipalInt.sizeMethod, NEW [PipalInt.SizeProc ← SizeMarker]];
Pipal.PutClassMethod[markerClass, PipalReal.sizeMethod, NEW [PipalReal.SizeProc ← PipalReal.UseIntSize]];
Pipal.PutClassMethod[markerClass, PipalInt.abutBoxMethod, NEW [PipalInt.AbutBoxProc ← PipalInt.AbutBoxFromSize]];
Pipal.PutClassMethod[markerClass, PipalPaint.paintMethod, NEW [PipalPaint.PaintProc ← PaintMarker]];
Pipal.PutClassMethod[markerClass, Pipal.describeMethod, NEW [Pipal.DescribeProc ← DescribeMarker]];
Pipal.PutClassMethod[markerClass, Pipal.hashMethod, NEW [Pipal.HashProc ← HashMarker]];
Pipal.PutClassMethod[markerClass, Pipal.equalMethod, NEW [Pipal.EqualProc ← EqualMarker]];
PipalIO.RegisterClass[markerClass, ReadMarker, WriteMarker];
Schematic Icons
Pipal.PutClassMethod[schematicIconClass, Pipal.describeMethod, NEW [Pipal.DescribeProc ← DescribeSchematicIcon]];
Pipal.PutClassMethod[schematicIconClass, Pipal.hashMethod, NEW [Pipal.HashProc ← PipalOps.HashByEnumeration]];
Pipal.PutClassMethod[schematicIconClass, Pipal.equalMethod, NEW [Pipal.EqualProc ← EqualSchematicIcon]];
Pipal.PutClassMethod[schematicIconClass, PipalInt.sizeMethod, NEW [PipalInt.SizeProc ← PipalInt.CachedSizeFromEnumerate]];
Pipal.PutClassMethod[schematicIconClass, PipalInt.enumerateMethod, NEW [PipalInt.EnumerateProc ← EnumerateSchematicIcon]];
Pipal.PutClassMethod[schematicIconClass, PipalOps.replaceMethod, NEW [PipalOps.ReplaceProc ← ReplaceSchematicIcon]];
PipalIO.RegisterClass[schematicIconClass, ReadSchematicIcon, WriteSchematicIcon];
Schematic Sequence
Pipal.PutClassMethod[schematicSequenceClass, Pipal.describeMethod, NEW [Pipal.DescribeProc ← DescribeSchematicSequence]];
Pipal.PutClassMethod[schematicSequenceClass, Pipal.hashMethod, NEW [Pipal.HashProc ← PipalOps.HashByEnumeration]];
Pipal.PutClassMethod[schematicSequenceClass, Pipal.equalMethod, NEW [Pipal.EqualProc ← EqualSchematicSequence]];
Pipal.PutClassMethod[schematicSequenceClass, PipalInt.sizeMethod, NEW [PipalInt.SizeProc ← PipalInt.CachedSizeFromEnumerate]];
Pipal.PutClassMethod[schematicSequenceClass, PipalInt.enumerateMethod, NEW [PipalInt.EnumerateProc ← EnumerateSchematicSequence]];
Pipal.PutClassMethod[schematicSequenceClass, PipalOps.replaceMethod, NEW [PipalOps.ReplaceProc ← ReplaceSchematicSequence]];
PipalIO.RegisterClass[schematicSequenceClass, ReadSchematicSequence, WriteSchematicSequence];
Text
Pipal.PutClassMethod[textClass, PipalInt.sizeMethod, NEW [PipalInt.SizeProc ← SizeText]];
Pipal.PutClassMethod[textClass, PipalInt.bboxMethod, NEW [PipalInt.BBoxProc ← BBoxText]];
Pipal.PutClassMethod[textClass, PipalReal.sizeMethod, NEW [PipalReal.SizeProc ← PipalReal.UseIntSize]];
Pipal.PutClassMethod[textClass, PipalInt.abutBoxMethod, NEW [PipalInt.AbutBoxProc ← AbutBoxText]];
Pipal.PutClassMethod[textClass, PipalPaint.paintMethod, NEW [PipalPaint.PaintProc ← PaintText]];
Pipal.PutClassMethod[textClass, Pipal.describeMethod, NEW [Pipal.DescribeProc ← DescribeText]];
Pipal.PutClassMethod[textClass, Pipal.hashMethod, NEW [Pipal.HashProc ← HashText]];
Pipal.PutClassMethod[textClass, Pipal.equalMethod, NEW [Pipal.EqualProc ← EqualText]];
PipalIO.RegisterClass[textClass, ReadText, WriteText];
Picture
Pipal.PutClassMethod[pictureClass, PipalInt.sizeMethod, NEW [PipalInt.SizeProc ← SizePicture]];
Pipal.PutClassMethod[pictureClass, PipalReal.sizeMethod, NEW [PipalReal.SizeProc ← PipalReal.UseIntSize]];
Pipal.PutClassMethod[pictureClass, PipalInt.abutBoxMethod, NEW [PipalInt.AbutBoxProc ← PipalInt.AbutBoxFromSize]];
Pipal.PutClassMethod[pictureClass, PipalPaint.paintMethod, NEW [PipalPaint.PaintProc ← PaintPicture]];
Pipal.PutClassMethod[pictureClass, Pipal.hashMethod, NEW [Pipal.HashProc ← HashPicture]];
Pipal.PutClassMethod[pictureClass, Pipal.equalMethod, NEW [Pipal.EqualProc ← EqualPicture]];
PipalIO.RegisterClass[pictureClass, ReadPicture, WritePicture];
Atomicity
Pipal.PutClassMethod[starClass, isAtomicMethod, NEW [IsAtomicProc ← Pipal.AlwaysTrue]];
Pipal.PutClassMethod[Pipal.annotationClass, isAtomicMethod, NEW [IsAtomicProc ← IsAnnotationAtomic]];
Pipal.PutClassMethod[clippedEnumerationClass, PipalInt.enumerateMethod, NEW [PipalInt.EnumerateProc ← EnumerateClippedEnumeration]];
END.