<> <> <> <> DIRECTORY BrineIO, CD, CDAtomicObjects, CDCells, CDPrivate, CDRects, CDRoutingObjects, CDTexts, CDSymbolicObjects, Core, CoreIO, CoreProperties, CoreGeometry, CoreGeometryBackdoor, GList, IO, PW, RefTab, RefTabExtras, Rope; CoreGeometryIOImpl: CEDAR PROGRAM IMPORTS BrineIO, CD, CDAtomicObjects, CDCells, CDPrivate, CDRects, CDSymbolicObjects, CDRoutingObjects, CDTexts, CoreIO, CoreGeometry, CoreGeometryBackdoor, CoreProperties, GList, PW, RefTab, RefTabExtras, Rope EXPORTS CoreGeometryBackdoor SHARES CDCells, CDRects, CDTexts, CDSymbolicObjects, CoreGeometry = BEGIN OPEN BrineIO, CoreIO, CoreGeometry, CoreGeometryBackdoor; <> <> <> <> <> <> <> <> STREAM: TYPE = IO.STREAM; objectClassRegistry: RefTab.Ref _ RefTab.Create[]; ObjectClassData: TYPE = REF ObjectClassDataRec; ObjectClassDataRec: TYPE = RECORD [ write: ObjectClassWriteProc _ NIL, read: ObjectClassReadProc _ NIL]; ObjectClassWriteProc: TYPE = PROC [stream: STREAM, me: CD.Object]; ObjectClassReadProc: TYPE = PROC [stream: STREAM] RETURNS [obj: CD.Object]; RegisterObjectClass: PUBLIC PROC [objectClass: CD.ObjectClass, write: ObjectClassWriteProc, read: ObjectClassReadProc] = { data: ObjectClassData _ NEW[ObjectClassDataRec _ [write, read]]; IF write=NIL OR read=NIL THEN ERROR; -- if only one NIL then invariant for object write/read is broken [] _ RefTab.Store[objectClassRegistry, objectClass.objectType, data]; }; <> WritePosition: PUBLIC PROC [stream: STREAM, position: CD.Position] = { WriteInt[stream, position.x]; WriteInt[stream, position.y]; }; ReadPosition: PUBLIC PROC [stream: STREAM] RETURNS [position: CD.Position] = { position.x _ ReadInt[stream]; position.y _ ReadInt[stream]; }; WriteRect: PUBLIC PROC [stream: STREAM, rect: CD.Rect] = { WriteInt[stream, rect.x1]; WriteInt[stream, rect.y1]; WriteInt[stream, rect.x2]; WriteInt[stream, rect.y2]; }; ReadRect: PUBLIC PROC [stream: STREAM] RETURNS [rect: CD.Rect] = { rect.x1 _ ReadInt[stream]; rect.y1 _ ReadInt[stream]; rect.x2 _ ReadInt[stream]; rect.y2 _ ReadInt[stream]; }; WriteTechnology: PUBLIC PROC [stream: STREAM, technology: CD.Technology] = { WriteAtom[stream, IF technology=NIL THEN $NILTechnology ELSE technology.key]; }; ReadTechnology: PUBLIC PROC [stream: STREAM] RETURNS [technology: CD.Technology] = { atom: ATOM _ ReadAtom[stream]; technology _ IF atom=$NILTechnology THEN NIL ELSE CD.FetchTechnology[atom]; }; WriteLayer: PUBLIC PROC [stream: STREAM, layer: CD.Layer] = { WriteTechnology[stream, CDPrivate.layers[layer].technology]; WriteAtom[stream, CD.LayerKey[layer]]; }; ReadLayer: PUBLIC PROC [stream: STREAM] RETURNS [layer: CD.Layer] = { technology: CD.Technology _ ReadTechnology[stream]; layer _ CD.FetchLayer[technology, ReadAtom[stream]]; }; WriteOrient: PUBLIC PROC [stream: STREAM, orient: CD.Orientation] = { WriteInt[stream, ORD[orient]]; }; ReadOrient: PUBLIC PROC [stream: STREAM] RETURNS [orient: CD.Orientation] = { aux: NAT _ ReadInt[stream]; orient _ VAL [aux]; }; WriteTrans: PUBLIC PROC [stream: STREAM, trans: CD.Transformation] = { WritePosition[stream, trans.off]; WriteOrient[stream, trans.orient]; }; ReadTrans: PUBLIC PROC [stream: STREAM] RETURNS [trans: CD.Transformation] = { off: CD.Position _ ReadPosition[stream]; trans _ [off, ReadOrient[stream]]; }; WriteCDProperties: PUBLIC PROC [stream: STREAM, properties: CD.PropList] = { props: Core.Properties _ NIL; WHILE properties#NIL DO IF ISTYPE [properties.first.key, ATOM] THEN props _ CoreProperties.PutProp[props, NARROW [properties.first.key], properties.first.val]; properties _ properties.rest; ENDLOOP; WriteProperties[stream, props]; }; ReadCDProperties: PUBLIC PROC [stream: STREAM] RETURNS [properties: CD.PropList _ NIL] = { Consume: PROC [key: ATOM, val: REF] = { properties _ CONS [[key, val], properties]; }; CoreProperties.Enumerate[ReadProperties[stream], Consume]; }; <> WriteCDInstance: PUBLIC PROC [stream: STREAM, instance: CD.Instance] = { WriteObject[stream, instance.ob]; WriteTrans[stream, instance.trans]; WriteCDProperties[stream, instance.properties]; }; ReadCDInstance: PUBLIC PROC [stream: STREAM] RETURNS [instance: CD.Instance] = { instance _ NEW [CD.InstanceRep _ [ob: ReadObject[stream]]]; instance.trans _ ReadTrans[stream]; instance.properties _ ReadCDProperties[stream]; }; WriteCDInstances: PUBLIC PROC [stream: STREAM, instances: LIST OF CD.Instance] = { WriteInt[stream, GList.Length[instances]]; WHILE instances#NIL DO WriteCDInstance[stream, instances.first]; instances _ instances.rest; ENDLOOP; }; ReadCDInstances: PUBLIC PROC [stream: STREAM] RETURNS [instances: LIST OF CD.Instance _ NIL] = { THROUGH [1 .. ReadInt[stream]] DO instances _ CONS [ReadCDInstance[stream], instances]; ENDLOOP; }; WriteInstance: PUBLIC PROC [stream: STREAM, instance: Instance] = { WriteObject[stream, instance.obj]; WriteTrans[stream, instance.trans]; }; ReadInstance: PUBLIC PROC [stream: STREAM] RETURNS [instance: Instance] = { obj: CD.Object _ ReadObject[stream]; instance _ [obj, ReadTrans[stream]]; }; WriteInstances: PUBLIC PROC [stream: STREAM, instances: Instances] = { WriteInt[stream, Length[instances]]; WHILE instances#NIL DO WriteInstance[stream, instances.first]; instances _ instances.rest; ENDLOOP; }; ReadInstances: PUBLIC PROC [stream: STREAM] RETURNS [instances: Instances _ NIL] = { THROUGH [0 .. ReadInt[stream]) DO instances _ CONS [ReadInstance[stream], instances]; ENDLOOP; }; WriteObjectRef: PROC [stream: STREAM, ref: REF] = {WriteObject[stream, NARROW [ref]]}; ReadObjectRef: PROC [stream: STREAM] RETURNS [ref: REF] = {ref _ ReadObject[stream]}; <> WriteObject: PUBLIC PROC [stream: STREAM, obj: CD.Object] = { objects: RefTab.Ref _ GetRefTab[stream, $CoreGeometryIOObjects]; objectID: ROPE _ objectID _ NARROW [RefTab.Fetch[objects, obj].val]; IF objectID=NIL THEN { classData: ObjectClassData _ NARROW[RefTab.Fetch[objectClassRegistry, obj.class.objectType].val]; objectID _ MakeID["O", RefTab.GetSize[objects]]; IF NOT RefTab.Insert[objects, obj, objectID] THEN ERROR; WriteID[stream, objectID]; WriteAtom[stream, obj.class.objectType]; IF classData=NIL THEN { IF CDAtomicObjects.IsAtomicOb[obj] THEN { WriteTechnology[stream, obj.class.technology]; WritePosition[stream, CD.InterestSize[obj]]; WriteLayer[stream, obj.layer]; } ELSE ERROR; -- no write proc and not atomic } ELSE classData.write[stream, obj]; WriteCDProperties[stream, obj.properties]; } ELSE WriteID[stream, objectID]; }; ReadObject: PUBLIC PROC [stream: STREAM] RETURNS [obj: CD.Object] = { objects: RefTab.Ref _ GetRefTab[stream, $CoreGeometryIOObjects, RefTabExtras.EqualRope, RefTabExtras.HashRope]; objectID: ROPE _ ReadID[stream]; IF Rope.Fetch[objectID]#'O THEN ERROR; obj _ NARROW [RefTab.Fetch[objects, objectID].val]; IF obj=NIL THEN { classAtom: ATOM _ ReadAtom[stream]; classData: ObjectClassData _ NARROW [RefTab.Fetch[objectClassRegistry, classAtom].val]; IF classData=NIL THEN { technology: CD.Technology _ ReadTechnology[stream]; pos: CD.Position _ ReadPosition[stream]; layer: CD.Layer _ ReadLayer[stream]; obj _ CDAtomicObjects.CreateAtomicOb[classAtom, pos, technology, layer]; } ELSE obj _ classData.read[stream]; obj.properties _ ReadCDProperties[stream]; IF NOT RefTab.Insert[objects, objectID, obj] THEN ERROR; }; }; <> PinsInstancesPropWrite: PropWriteProc = { count: INT _ 0; Incr: EachInstanceProc = {count _ count+1}; Write: EachInstanceProc = {WriteInstance[stream, instance]}; [] _ RawEnumeratePins[prop, value, Incr]; WriteInt[stream, count]; [] _ RawEnumeratePins[prop, value, Write]; }; GeometryInstancesPropWrite: PropWriteProc = { count: INT _ 0; Incr: EachInstanceProc = {count _ count+1}; Write: EachInstanceProc = {WriteInstance[stream, instance]}; [] _ RawEnumerateGeometry[prop, value, Incr]; WriteInt[stream, count]; [] _ RawEnumeratePins[prop, value, Write]; }; InstancesPropRead: PropReadProc = { value _ ReadInstances[stream]; }; ObjectPropWrite: PropWriteProc = {WriteObject[stream, NARROW [value]]}; ObjectPropRead: PropReadProc = {value _ ReadObject[stream]}; TransPropWrite: PropWriteProc = {WriteTrans[stream, NARROW [value, REF CD.Transformation]^]}; TransPropRead: PropReadProc = {value _ NEW [CD.Transformation _ ReadTrans[stream]]}; WriteObjectsProp: PropWriteProc = { WriteRefTab[stream, NARROW [value], WriteIDRef, WriteObjectRef]; }; <<>> ReadObjectsProp: PropReadProc = { value _ ReadRefTab[stream, ReadIDRef, ReadObjectRef, RefTabExtras.EqualRope, RefTabExtras.HashRope]; }; <> <> WriteRectangle: ObjectClassWriteProc = { WritePosition[stream, CD.InterestSize[me]]; WriteLayer[stream, me.layer]; }; ReadRectangle: ObjectClassReadProc = { sz: CD.Position = ReadPosition[stream]; l: CD.Layer = ReadLayer[stream]; ob: CD.Object = CDRects.CreateRect[sz, l]; RETURN [ob] }; <> WriteCell: ObjectClassWriteProc = { ConsInstance: CDCells.InstEnumerator = {insts _ CONS [inst, insts]}; insts: LIST OF CD.Instance _ NIL; cellPtr: CD.CellSpecific _ NARROW [me.specific]; [] _ CDCells.EnumerateInstances[me, ConsInstance]; WriteRect[stream, me.bbox]; WriteCDInstances[stream, insts]; WriteRect[stream, cellPtr.ir]; WriteReal[stream, cellPtr.simplifyOn]; WriteBool[stream, cellPtr.drawBorder]; WriteBool[stream, cellPtr.specifiedIr]; }; ReadCell: ObjectClassReadProc = { cellPtr: CD.CellSpecific _ NEW [CD.CellRep]; obj _ NEW [CD.ObjectRep _ [class: CDCells.pCellClass]]; obj.bbox _ ReadRect[stream]; cellPtr.contents _ ReadCDInstances[stream]; cellPtr.ir _ ReadRect[stream]; cellPtr.simplifyOn _ ReadReal[stream]; cellPtr.drawBorder _ ReadBool[stream]; cellPtr.specifiedIr _ ReadBool[stream]; obj.specific _ cellPtr; CDCells.ToSequenceMode[obj]; }; <> WriteAbut: ObjectClassWriteProc = { Write: PW.EachSubObjectProc = {WriteObject[stream, subObject]}; WriteRect[stream, me.bbox]; WriteBool[stream, me.class=PW.abutXClass]; WriteInt[stream, PW.CountSubObjects[me]]; [] _ PW.EnumerateSubObjects[me, Write]; }; ReadAbut: ObjectClassReadProc = { bbox: CD.Rect _ ReadRect[stream]; inX: BOOL _ ReadBool[stream]; size: INT _ ReadInt[stream]; subObjects: LIST OF CD.Object _ NIL; THROUGH [0 .. size) DO subObjects _ CONS [ReadObject[stream], subObjects] ENDLOOP; obj _ (IF inX THEN PW.CreateNewAbutX ELSE PW.CreateNewAbutY)[NARROW [GList.Reverse[subObjects]]]; IF obj.bbox#bbox THEN ERROR; }; <> WriteRotation: ObjectClassWriteProc = { specific: PW.RotationSpecific = NARROW [me.specific]; WriteObject[stream, specific.obj]; WriteOrient[stream, specific.orientation]; }; ReadRotation: ObjectClassReadProc = { sub: CD.Object _ ReadObject[stream]; orient: CD.Orientation _ ReadOrient[stream]; obj _ PW.CreateRotation[sub, orient]; }; <> WriteRouting: ObjectClassWriteProc = { routing: CDRoutingObjects.RoutingSpecific _ NARROW [me.specific]; WriteRect[stream, me.bbox]; WriteInt[stream, routing.size]; WriteRect[stream, routing.ir]; WriteReal[stream, routing.scaleHint]; FOR i: NAT IN [0 .. routing.size) DO node: CDRoutingObjects.Node = routing[i]; WriteInt[stream, node.size]; WriteCDProperties[stream, node.properties]; FOR j: NAT IN [0 .. node.size) DO WriteObject[stream, node[j].object]; WritePosition[stream, node[j].position]; ENDLOOP; ENDLOOP; }; ReadRouting: ObjectClassReadProc = { bbox: CD.Rect _ ReadRect[stream]; size: NAT _ NAT [ReadInt[stream]]; routing: CDRoutingObjects.RoutingSpecific _ NEW [CDRoutingObjects.RoutingRep[size]]; routing.ir _ ReadRect[stream]; routing.scaleHint _ ReadReal[stream]; FOR i: NAT IN [0 .. size) DO nb: NAT _ NAT [ReadInt[stream]]; node: CDRoutingObjects.Node = NEW [CDRoutingObjects.NodeRep[nb]]; node.properties _ ReadCDProperties[stream]; FOR j: NAT IN [0 .. nb) DO object: CD.Object _ ReadObject[stream]; node[j] _ [object: object, position: ReadPosition[stream]]; ENDLOOP; routing[i] _ node; ENDLOOP; obj _ NEW [CD.ObjectRep _ [class: CDRoutingObjects.routingClass, specific: routing, bbox: bbox]]; }; <> TileArrayRec: TYPE = RECORD [c: SEQUENCE sizeY: NAT OF REF TileLinesRec]; TileLinesRec: TYPE = RECORD [c: SEQUENCE sizeX: NAT OF CD.Object]; WriteTiling: ObjectClassWriteProc = { sizeX, sizeY: NAT; [sizeX, sizeY] _ PW.GetTilingSize[me]; WriteRect[stream, me.bbox]; WriteInt[stream, sizeX]; WriteInt[stream, sizeY]; FOR y: NAT IN [0 .. sizeY) DO FOR x: NAT IN [0 .. sizeX) DO WriteObject[stream, PW.GetTile[me, x, y]] ENDLOOP; ENDLOOP; }; ReadTiling: ObjectClassReadProc = { Tiles: PROC [x, y: NAT] RETURNS [CD.Object] = {RETURN [tileArray[y][x]]}; bbox: CD.Rect _ ReadRect[stream]; sizeX: NAT _ NAT [ReadInt[stream]]; sizeY: NAT _ NAT [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] _ ReadObject[stream] ENDLOOP; ENDLOOP; obj _ PW.CreateTiling[sizeX, sizeY, Tiles]; IF obj.bbox#bbox THEN ERROR; }; <> WriteIndirect: ObjectClassWriteProc = { indirect: CD.Object _ NARROW [me.specific]; WriteRect[stream, me.bbox]; WriteObject[stream, indirect]; }; ReadIndirect: ObjectClassReadProc = { bbox: CD.Rect _ ReadRect[stream]; indirect: CD.Object _ ReadObject[stream]; IF indirect.bbox#bbox THEN ERROR; obj _ PW.CreateIndirect[indirect]; }; <> WriteMark: ObjectClassWriteProc = { }; ReadMark: ObjectClassReadProc = { RETURN[CDSymbolicObjects.CreateMark[]]; }; WriteSegment: ObjectClassWriteProc = { WritePosition[stream, CD.InterestSize[me]]; }; ReadSegment: ObjectClassReadProc = { p: CD.Position _ ReadPosition[stream]; RETURN [CDSymbolicObjects.CreateSegment[p.y, p.x]] }; WritePin: ObjectClassWriteProc = { WritePosition[stream, CD.InterestSize[me]]; }; ReadPin: ObjectClassReadProc = { RETURN [CDSymbolicObjects.CreatePin[ReadPosition[stream]]] }; <> WriteText: ObjectClassWriteProc = { text: CDTexts.TextSpecific _ NARROW [me.specific]; WriteRope[stream, text.text]; WriteRope[stream, text.cdFont.supposedName]; WriteInt[stream, text.cdFont.scaleI]; }; ReadText: ObjectClassReadProc = { text: ROPE _ ReadRope[stream]; fontName: ROPE _ ReadRope[stream]; scale: INT _ ReadInt[stream]; font: CDTexts.CDFont _ CDTexts.MakeFont[fontName, scale]; obj _ CDTexts.Create[text, font]; }; <> WriteLayerRef: PropWriteProc = { WriteLayer[stream, NARROW [value, CDPrivate.LayerRef].number]; }; ReadLayerRef: PropReadProc = { value _ CDPrivate.layers[ReadLayer[stream]]; }; <> RegisterDecorationIO: PUBLIC PROC [decoration: Decoration] = { [] _ RegisterProperty[decoration.objectProp, ObjectPropWrite, ObjectPropRead]; [] _ RegisterProperty[decoration.pinsProp, PinsInstancesPropWrite, InstancesPropRead]; [] _ RegisterProperty[decoration.geometryProp, GeometryInstancesPropWrite, InstancesPropRead]; [] _ RegisterProperty[decoration.transProp, TransPropWrite, TransPropRead]; }; [] _ RegisterProperty[$layerOfPin, WriteLayerRef, ReadLayerRef]; RegisterObjectClass[CDRects.bareRectClass, WriteRectangle, ReadRectangle]; RegisterObjectClass[CDRects.wellRectClass, WriteRectangle, ReadRectangle]; RegisterObjectClass[CDCells.pCellClass, WriteCell, ReadCell]; RegisterObjectClass[PW.abutXClass, WriteAbut, ReadAbut]; RegisterObjectClass[PW.abutYClass, WriteAbut, ReadAbut]; RegisterObjectClass[PW.rotationClass, WriteRotation, ReadRotation]; RegisterObjectClass[CDRoutingObjects.routingClass, WriteRouting, ReadRouting]; RegisterObjectClass[PW.tilingClass, WriteTiling, ReadTiling]; RegisterObjectClass[PW.indirectClass, WriteIndirect, ReadIndirect]; RegisterObjectClass[CDSymbolicObjects.markClass, WriteMark, ReadMark]; RegisterObjectClass[CDSymbolicObjects.segmentClass, WriteSegment, ReadSegment]; RegisterObjectClass[CDSymbolicObjects.pinClass, WritePin, ReadPin]; RegisterObjectClass[CDTexts.flipTextClass, WriteText, ReadText]; RegisterObjectClass[CDTexts.rigidTextClass, WriteText, ReadText]; END.