DIRECTORY CD USING [LayerKey, Object, Position, undefLayer], CDBasics USING [BaseOfRect, ComposeTransform, MapRect, NonEmpty, SizeOfRect], CDColors USING [ColorTable, DisplayMode, DisplayType, globalColors], Checksum USING [ComputeChecksum], Core USING [CellType, Wire], CoreClasses USING [CellInstance, recordCellClass, RecordCellType, transistorCellClass], CoreGeometry USING [BBox, CellInstance, CellType, Decoration, EachInstanceProc, EnumerateGeometry, FlattenInstance, GetObject, GetTrans, Instance, Layer, Transformation, Wire], CoreOps USING [GetCellTypeName], CoreView USING [CoreCell, Layout, Rect, Viewer], CStitching USING [all, Area, ChangeEnumerateArea, ChangeRect, DumpCache, EnumerateArea, NewTesselation, RectProc, Region, ResetTesselation, Tesselation, Tile, TileProc], Cursors USING [CursorType], HashTable USING [Create, EachPairAction, Fetch, Insert, Key, Pairs, Table], Icons USING [NewIconFromFile], Imager USING [black, ClipRectangle, Color, Context, ConstantColor, Font, MakeGray, MaskRectangle, MaskVectorI, Rectangle, ScaleT, SetColor, SetFont, SetPriorityImportant, SetStrokeEnd, SetStrokeJoint, SetStrokeWidth, SetXY, ShowRope, TranslateT, VEC, white], ImagerBackdoor USING [GetBounds], ImagerColor USING [ColorFromRGB, RGB], ImagerColorPrivate USING [ComponentFromColor], ImagerTransformation USING [Transformation], IO USING [card, int, PutR1], Menus USING [AppendMenuEntry, ClickProc, CreateEntry, CreateMenu, Menu, MenuEntry], MessageWindow USING [Append, Blink, Clear], Real USING [FixI, Float], Rope USING [Cat, ROPE], VFonts USING [defaultFont], ViewerClasses USING [DestroyProc, HScrollProc, PaintProc, ScrollProc, ViewerClass, ViewerClassRec, ViewerFlavor, ViewerRec], ViewerOps USING [CreateViewer, PaintViewer, RegisterViewerClass], WindowManager USING [colorDisplayOn]; CoreViewImpl: CEDAR PROGRAM IMPORTS CD, CDBasics, CDColors, Checksum, CoreGeometry, CoreOps, CoreClasses, CStitching, HashTable, Icons, Imager, ImagerBackdoor, ImagerColor, ImagerColorPrivate, IO, Menus, MessageWindow, Real, Rope, VFonts, ViewerOps, WindowManager EXPORTS CoreView ~ BEGIN OPEN CoreView, Real; break: SIGNAL ~ CODE; -- for debugging Font: TYPE ~ Imager.Font; Color: TYPE ~ Imager.Color; Context: TYPE ~ Imager.Context; Rectangle: TYPE ~ Imager.Rectangle; Transformation: TYPE ~ ImagerTransformation.Transformation; ROPE: TYPE ~ Rope.ROPE; Region: TYPE ~ LIST OF REF CStitching.Region; Tess: TYPE ~ CStitching.Tesselation; Tile: TYPE ~ CStitching.Tile; Transf: TYPE ~ CoreGeometry.Transformation; CoreInst: TYPE ~ CoreGeometry.CellInstance; FakeInst: TYPE ~ CoreGeometry.Instance; Wire: TYPE ~ CoreGeometry.Wire; Layer: TYPE ~ CoreGeometry.Layer; debugViewer: PUBLIC Viewer; identity: Transf; -- READONLY it is the default rectClass: ATOM ~ $Rect; markClass: ATOM ~ $AlignmentMarkOb; segmentClass: ATOM ~ $SymbolicSegment; pinClass: ATOM ~ $PinOb0; empty: REF ~ NIL; nothing: REF INT ~ NEW [INT]; State: TYPE = REF StateRec; StateRec: TYPE = RECORD [ previousColour: Color _ NIL, tess: Tess, boundingBox, window: Rectangle, translation: Imager.VEC _ [0.0, 0.0], -- initialization imporant for caches scale: REAL, bottomSB, rightSB: INTEGER _ 100, -- caches: initialization imporant topSB, leftSB: INTEGER _ 0, -- caches: initialization imporant resetPainting: BOOL _ TRUE, -- initialization imporant for caches attributes: Layout, abort: REF BOOL]; GeometryView: PUBLIC PROC [cell: CoreCell, geom: Layout, abortFlag: REF BOOL] RETURNS [viewer: Viewer] ~ BEGIN state: State ~ NEW [StateRec]; BEGIN OPEN state; abort _ IF (abortFlag # NIL) THEN abortFlag ELSE NEW [BOOL _ FALSE]; boundingBox _ window _ ImagerRect [CoreGeometry.BBox [[CoreGeometry.GetObject [geom, cell], identity]]]; tess _ CStitching.NewTesselation [stopFlag: abort]; previousColour _ NIL; attributes _ geom END; viewer _ InitializeViewer [cell, normal, state]; IF (EnumerateCore [cell, identity, EveryCell, state]) THEN RETURN; SetLayerColourTable; BlendAllColours; ViewerOps.PaintViewer [viewer: viewer, hint: client] END; -- GeometryView StartIncrementalView: PUBLIC PROC [cell: CoreCell, geom: Layout, abortFlag: REF BOOL] RETURNS [viewer: Viewer] ~ BEGIN state: State ~ NEW [StateRec]; BEGIN OPEN state; abort _ IF (abortFlag # NIL) THEN abortFlag ELSE NEW [BOOL _ FALSE]; boundingBox _ window _ ImagerRect [CoreGeometry.BBox [[CoreGeometry.GetObject [geom, cell], identity]]]; tess _ CStitching.NewTesselation [stopFlag: abort]; previousColour _ NIL; attributes _ geom END; viewer _ InitializeViewer [cell, labelled, state]; END; -- StartIncrementalView AddRectangle: PUBLIC PROC [viewer: Viewer, rect: Rect, label: REF ANY] ~ BEGIN state: State ~ NARROW [viewer.data]; InsertRect: CStitching.RectProc ~ BEGIN plane.ChangeRect [rect: rect, new: label] END; -- InsertRect IF state.abort^ THEN RETURN; state.tess.ChangeEnumerateArea [rect: rect, eachRect: InsertRect, skip: nothing]; ViewerOps.PaintViewer [viewer: viewer, hint: client] END; -- AddRectangle ComposedTransf: PROC [parent: Transf, child: CoreInst, state: State] RETURNS [Transf] ~ BEGIN RETURN [CDBasics.ComposeTransform [CoreGeometry.GetTrans [state.attributes, child], parent]] END; -- ComposedTransf EachCell: TYPE ~ PROC [cell: CoreCell, transf: Transf, state: State]; EnumerateCore: PROC [cell: CoreCell, transf: Transf, action: EachCell, state: State] RETURNS [quit: BOOL _ FALSE] ~ BEGIN IF state.abort^ THEN RETURN [TRUE]; SELECT cell.class FROM CoreClasses.recordCellClass => BEGIN cellData: CoreClasses.RecordCellType ~ NARROW [cell.data]; FOR sub: NAT IN [0 .. cellData.size) DO subTransf: Transf ~ ComposedTransf [transf, cellData.instances[sub], state]; IF (EnumerateCore [cellData.instances[sub].type, subTransf, action, state]) THEN RETURN [TRUE] ENDLOOP END; ENDCASE => NULL; action [cell, transf, state]; quit _ state.abort^ END; -- EnumerateCore EveryCell: EachCell ~ BEGIN SELECT cell.class FROM CoreClasses.recordCellClass => BEGIN cellData: CoreClasses.RecordCellType ~ NARROW [cell.data]; FOR i: NAT IN [0 .. cellData.internal.size) DO IF state.abort^ THEN RETURN; EveryWire [state: state, cell: cell, w: cellData.internal[i], transf: transf] ENDLOOP END; CoreClasses.transistorCellClass => EveryWire [cell, cell.public, transf, state]; ENDCASE => NULL; -- Print warning END; -- EveryCell EveryWire: PROC [cell: CoreCell, w: Wire, transf: Transf, state: State] ~ BEGIN EveryRect: CoreGeometry.EachInstanceProc ~ BEGIN rect: Rect ~ CDBasics.MapRect [CoreGeometry.BBox [instance], transf]; dec: Tess ~ state.tess; l: Layer ~ instance.obj.layer; InsertRect: CStitching.RectProc ~ BEGIN WITH oldValue SELECT FROM b: Blend => IF NOT b.flavours[l] THEN dec.ChangeRect [rect: rect, new: ColourTile [b, l]]; ENDCASE => BEGIN b: Blend _ NEW [BlendRec]; dec.ChangeRect [rect: rect, new: ColourTile [b, l]] END END; -- InsertRect IF state.abort^ THEN RETURN [state.abort^]; SELECT instance.obj.class.objectType FROM rectClass => IF (CDBasics.NonEmpty [rect]) THEN dec.ChangeEnumerateArea [rect: rect, eachRect: InsertRect, skip: nothing]; markClass, segmentClass, pinClass => NULL; ENDCASE => quit _ CoreGeometry.FlattenInstance [instance, EveryRect]; END; -- EveryRect [] _ state.attributes.EnumerateGeometry [w, EveryRect] END; -- EveryWire ViewerFlavor: TYPE ~ ViewerClasses.ViewerFlavor; normal: ViewerFlavor ~ $CoreView; labelled: ViewerFlavor ~ $LabelledCoreView; InitializeViewerClasses: PROC ~ BEGIN classN: ViewerClasses.ViewerClass _ NEW [ViewerClasses.ViewerClassRec]; classL: ViewerClasses.ViewerClass _ NEW [ViewerClasses.ViewerClassRec]; classMenu: Menus.Menu ~ Menus.CreateMenu []; abortButton: Menus.MenuEntry ~ Menus.CreateEntry [name: "Abort", proc: Abort, guarded: TRUE]; zoomInButton: Menus.MenuEntry ~ Menus.CreateEntry [name: "Zoom-In", proc: ZoomIn]; zoomOutButton: Menus.MenuEntry ~ Menus.CreateEntry [name: "Zoom-Out", proc: ZoomOut]; everythingButton: Menus.MenuEntry ~ Menus.CreateEntry [name: "Reset", proc: Everything]; classMenu.AppendMenuEntry [abortButton]; classMenu.AppendMenuEntry [zoomInButton]; classMenu.AppendMenuEntry [zoomOutButton]; classMenu.AppendMenuEntry [everythingButton]; BEGIN OPEN classN; flavor _ normal; paint _ Paint; destroy _ Destroy; scroll _ VerticalTranslation; hscroll _ HorizontalTranslation; menu _ classMenu; icon _ Icons.NewIconFromFile ["[DATools]CoreView>CoreView.Icon", 0]; cursor _ crossHairsCircle END; classL^ _ classN^; classL.flavor _ labelled; classL.icon _ Icons.NewIconFromFile ["[DATools]CoreView>CoreView.Icon", 1]; ViewerOps.RegisterViewerClass [normal, classN]; ViewerOps.RegisterViewerClass [labelled, classL] END; -- InitializeViewerClasses InitializeViewer: PROC [cell: CoreCell, flavor: ViewerFlavor, state: State] RETURNS [viewer: Viewer] ~ BEGIN info: ViewerClasses.ViewerRec; BEGIN OPEN info; label _ CoreOps.GetCellTypeName [cell]; name _ IF (flavor = normal) THEN label ELSE label.Cat [" debugging"]; column _ IF WindowManager.colorDisplayOn THEN color ELSE left; scrollable _ TRUE; hscrollable _ TRUE; iconic _ (flavor = labelled); guardDestroy _ TRUE; data _ state END; viewer _ ViewerOps.CreateViewer [flavor, info] END; -- InitializeViewer Paint: ViewerClasses.PaintProc ~ BEGIN state: State ~ NARROW [self.data]; ChangeColour: PROC [colour: Color] ~ INLINE BEGIN a: ImagerColor.RGB ~ RGBFromColour [colour]; b: ImagerColor.RGB ~ RGBFromColour [state.previousColour]; IF (a.R # b.R) OR (a.G # b.G) OR (a.B # b.B) OR (state.previousColour = NIL) THEN BEGIN IF (a.R = 0.0) AND (a.G = 0.0) AND (a.B = 0.0) THEN context.SetColor [blackBlack] ELSE context.SetColor [colour]; state.previousColour _ colour END END; -- ChangeColour PrintTile: CStitching.TileProc ~ BEGIN b: Blend ~ NARROW [tile.value]; r: Rect ~ CStitching.Area [tile]; -- not the area but the rectangle ! IF state.abort^ THEN RETURN; ChangeColour [b.blend]; context.MaskRectangle [ImagerRect [r]] END; -- PrintTile PrintLabeledTile: CStitching.TileProc ~ BEGIN r: Rect ~ CStitching.Area [tile]; -- not the area but the rectangle ! l: CARD; IF state.abort^ THEN RETURN; ChangeColour [lightGrey]; context.MaskRectangle [ImagerRect [r]]; ChangeColour [blackBlack]; context.SetStrokeWidth [0.0]; context.MaskVectorI [r.x1, r.y1, r.x2, r.y1]; -- South context.MaskVectorI [r.x2, r.y1, r.x2, r.y2]; -- East context.MaskVectorI [r.x2, r.y2, r.x1, r.y2]; -- North context.MaskVectorI [r.x1, r.y2, r.x1, r.y1]; -- West TRUSTED {l _ LOOPHOLE [tile.value, CARD]}; context.SetXY [[r.x1, r.y1]]; context.ShowRope [IO.PutR1 [IO.card [l]]] END; -- PrintLabeledTile state.abort^ _ FALSE; state.previousColour _ NIL; state.window _ ImagerBackdoor.GetBounds [context]; -- needed for scroll bars IF (self.class.flavor = normal) AND ((self.column = color) OR (NOT clear)) THEN BEGIN context.SetColor [IF (self.column = color) THEN grey ELSE whiteWhite]; context.MaskRectangle [state.window] END; IF state.abort^ THEN {state.abort^ _ FALSE; RETURN [TRUE]}; context.SetPriorityImportant [FALSE]; IF state.resetPainting THEN BEGIN -- important for initialization of caches state.translation _ [state.boundingBox.x, state.boundingBox.y]; state.scale _ MIN [(state.window.w / state.boundingBox.w), (state.window.h / state.boundingBox.h)]; state.resetPainting _ FALSE END; context.TranslateT [state.translation]; context.ScaleT [state.scale]; state.window _ ImagerBackdoor.GetBounds [context]; -- needed for scroll bars context.ClipRectangle [state.window]; context.SetStrokeJoint [mitered]; context.SetStrokeWidth [0]; context.SetStrokeEnd [square]; context.SetFont [VFonts.defaultFont]; SELECT self.class.flavor FROM normal => state.tess.EnumerateArea [rect: CStitching.all, eachTile: PrintTile, data: state, skip: empty]; labelled => state.tess.EnumerateArea [rect: CStitching.all, eachTile: PrintLabeledTile, data: state, skip: empty]; ENDCASE => ERROR END; -- Paint VerticalTranslation: ViewerClasses.ScrollProc ~ BEGIN state: State ~ NARROW [self.data]; BEGIN OPEN state; SELECT op FROM query => BEGIN top _ MAX [topSB, 0]; bottom _ MIN [bottomSB, 100]; RETURN END; up => IF (window.y < boundingBox.y+boundingBox.h) THEN BEGIN translation.y _ translation.y + (Float [amount] / Float [self.ch]) * window.h; topSB _ FixI [(window.y + window.h) / (boundingBox.y + boundingBox.h) * 100.0]; bottomSB _ topSB + FixI [(window.h / boundingBox.h) * 100.0] END; down => IF (window.y+window.h > boundingBox.y) THEN BEGIN translation.y _ translation.y - (Float [amount] / Float [self.ch]) * window.h; topSB _ FixI [(window.y + window.h) / (boundingBox.y + boundingBox.h) * 100.0]; bottomSB _ topSB + FixI [(window.h / boundingBox.h) * 100.0] END; thumb => SELECT TRUE FROM shift AND control => ImportantMessage ["Invalid command"]; shift => BEGIN -- scale up (window becomes relatively smaller) factor: REAL ~ 10.0 / Float [amount + 10]; scale _ scale * factor; topSB _ FixI [((window.y + window.h) * factor) / (boundingBox.y + boundingBox.h) * 100.0]; bottomSB _ topSB + FixI [(window.h / boundingBox.h) * 100.0] END; control => BEGIN -- reset painting resetPainting _ TRUE; bottomSB _ rightSB _ 100; topSB _ leftSB _ 0 END; ENDCASE => BEGIN -- thumb sign: INTEGER _ IF (boundingBox.h > window.h) THEN -1 ELSE 1; translation.y _ sign * (boundingBox.y + (boundingBox.h * Float [amount] / 100.0)); topSB _ amount; bottomSB _ amount + FixI [(window.h / boundingBox.h) * 100.0] END; ENDCASE => ERROR; Trace [amount]; ViewerOps.PaintViewer [viewer: self, hint: client]; -- op <> query top _ MAX [topSB, 0]; bottom _ MIN [bottomSB, 100] END -- OPEN state END; -- VerticalTranslation HorizontalTranslation: ViewerClasses.HScrollProc ~ BEGIN state: State ~ NARROW [self.data]; BEGIN OPEN state; SELECT op FROM query => BEGIN right _ MIN [rightSB, 100]; left _ MAX [leftSB, 0]; RETURN END; right => IF (window.x < boundingBox.x+boundingBox.w) THEN BEGIN translation.x _ translation.x + (Float [amount] / Float [self.cw]) * window.w; leftSB _ FixI [(window.x + window.w) / (boundingBox.x + boundingBox.w) * 100.0]; rightSB _ leftSB + FixI [(window.w / boundingBox.w) * 100.0] END; left => IF (window.x+window.w > boundingBox.x) THEN BEGIN translation.x _ translation.x - (Float [amount] / Float [self.cw]) * window.w; leftSB _ FixI [(window.x + window.w) / (boundingBox.x + boundingBox.w) * 100.0]; rightSB _ leftSB + FixI [(window.w / boundingBox.w) * 100.0] END; thumb => SELECT TRUE FROM shift AND control => ImportantMessage ["Invalid command"]; shift => BEGIN -- scale down (window becomes relatively larger) factor: REAL ~ Float [amount + 10] / 10.0; scale _ scale * factor; leftSB _ FixI [((window.x + window.w) * factor) / (boundingBox.x + boundingBox.w) * 100.0]; rightSB _ leftSB + FixI [(window.w / boundingBox.w) * 100.0] END; control => BEGIN -- reset painting resetPainting _ TRUE; bottomSB _ rightSB _ 100; topSB _ leftSB _ 0 END; ENDCASE => BEGIN -- thumb sign: INTEGER _ IF (boundingBox.w > window.w) THEN -1 ELSE 1; translation.x _ sign * (boundingBox.x + (boundingBox.w * Float [amount] / 100.0)); leftSB _ amount; rightSB _ amount + FixI [(window.w / boundingBox.w) * 100.0] END; ENDCASE => ERROR; Trace [amount]; ViewerOps.PaintViewer [viewer: self, hint: client]; -- op <> query right _ MIN [rightSB, 100]; left _ MAX [leftSB, 0] END -- OPEN state END; -- HorizontalTranslation Destroy: ViewerClasses.DestroyProc ~ BEGIN state: State ~ NARROW [self.data]; state.tess.ResetTesselation []; CStitching.DumpCache END; -- Destroy Abort: Menus.ClickProc ~ BEGIN IF NOT ISTYPE [parent, Viewer] THEN ImportantMessage ["Implementation error"] ELSE BEGIN state: State ~ NARROW [NARROW [parent, Viewer].data]; state.abort^ _ TRUE END END; -- Abort ZoomIn: Menus.ClickProc ~ BEGIN IF NOT ISTYPE [parent, Viewer] THEN ImportantMessage ["Implementation error"] ELSE BEGIN v: Viewer ~ NARROW [parent]; state: State ~ NARROW [v.data]; BEGIN OPEN state; scale _ scale * 1.5; ViewerOps.PaintViewer [viewer: v, hint: client]; topSB _ FixI [(window.y + window.h) / (boundingBox.y + boundingBox.h) * 100.0]; bottomSB _ topSB + FixI [(window.h / boundingBox.h) * 100.0]; leftSB _ FixI [(window.x + window.w) / (boundingBox.x + boundingBox.w) * 100.0]; rightSB _ leftSB + FixI [(window.w / boundingBox.w) * 100.0] END END END; -- ZoomIn ZoomOut: Menus.ClickProc ~ BEGIN IF NOT ISTYPE [parent, Viewer] THEN ImportantMessage ["Implementation error"] ELSE BEGIN v: Viewer ~ NARROW [parent]; state: State ~ NARROW [v.data]; BEGIN OPEN state; scale _ scale / 1.5; ViewerOps.PaintViewer [viewer: v, hint: client]; topSB _ FixI [(window.y + window.h) / (boundingBox.y + boundingBox.h) * 100.0]; bottomSB _ topSB + FixI [(window.h / boundingBox.h) * 100.0]; leftSB _ FixI [(window.x + window.w) / (boundingBox.x + boundingBox.w) * 100.0]; rightSB _ leftSB + FixI [(window.w / boundingBox.w) * 100.0] END END END; -- ZoomOut Everything: Menus.ClickProc ~ BEGIN IF NOT ISTYPE [parent, Viewer] THEN ImportantMessage ["Implementation error"] ELSE BEGIN v: Viewer ~ NARROW [parent]; state: State ~ NARROW [v.data]; state.resetPainting _ TRUE; SetLayerColourTable; BlendAllColours; state.bottomSB _ state.rightSB _ 100; state.topSB _ state.leftSB _ 0; ViewerOps.PaintViewer [viewer: v, hint: client] END END; -- Everything Bitset: TYPE ~ PACKED ARRAY Layer OF BOOLEAN _ ALL [FALSE]; BlendKey: TYPE ~ REF Bitset; Blend: TYPE ~ REF BlendRec; BlendRec: TYPE ~ RECORD [count: Layer _ 0, flavours: Bitset, blend: Color _ NIL, area: CARD _ 0]; colourTable: HashTable.Table ~ HashTable.Create [557, Match, Hash]; -- or 997 layerColorTable: ARRAY Layer OF Color; -- must be set for each task ColourTile: PROC [old: Blend, l: Layer] RETURNS [new: Blend] ~ BEGIN key: BlendKey ~ NEW [Bitset _ old.flavours]; key[l] _ TRUE; new _ NARROW [colourTable.Fetch[key].value, Blend]; IF (new = NIL) THEN BEGIN copy: Blend _ NEW [BlendRec _ [flavours: old.flavours]]; copy.count _ SUCC [old.count]; copy.flavours[l] _ TRUE; new _ copy; IF NOT colourTable.Insert [key, copy] THEN ERROR END END; -- ColourTile blackBlack: Color ~ Imager.black; whiteWhite: Color ~ Imager.white; grey: Color ~ Imager.MakeGray [0.36]; lightGrey: Color ~ Imager.MakeGray [0.18]; black: Color ~ ImagerColor.ColorFromRGB [[0.0, 0.0, 0.0]]; blue: Color ~ ImagerColor.ColorFromRGB [[0.0, 0.0, 1.0]]; unColour: ImagerColor.RGB ~ [0.0, 0.0, 0.0]; doubleYellowRGB: ImagerColor.RGB ~ [2.0, 2.0, 0.0]; magentaRGB: ImagerColor.RGB ~ [1.0, 0.0, 1.0]; cyan: Color ~ ImagerColor.ColorFromRGB [[0.0, 1.0, 1.0]]; lightYellow: Color ~ ImagerColor.ColorFromRGB [[6.0/7.0, 6.0/7.0, 3.0/7.0]]; lightMagenta: Color ~ ImagerColor.ColorFromRGB [[5.0/7.0, 0.0, 5.0/7.0]]; BlendColours: HashTable.EachPairAction ~ BEGIN components: Blend ~ NARROW [value]; n: REAL _ Float [components.count]; comp: PACKED ARRAY Layer OF BOOLEAN _ components.flavours; mix: ImagerColor.RGB _ unColour; IF (components.blend # NIL) THEN RETURN [FALSE]; -- caching across sessions SELECT n FROM 0 => ERROR; -- should never have been allocated 1 => BEGIN i: Layer _ 0; WHILE NOT comp[i] DO i _ SUCC [i] ENDLOOP; components.blend _ LayerColour [i] END; ENDCASE => BEGIN poly, diff, met, met2, cut, cut2, well: Layer _ 0; FOR i: Layer IN Layer DO IF comp[i] THEN SELECT CD.LayerKey[i] FROM $pol => poly _ i; $ndif, $pdif => diff _ i; $met => met _ i; $met2 => met2 _ i; $nwel => well _ i; $cut => cut _ i; $cut2 => {cut _ i; cut2 _ i}; ENDCASE => NULL ENDLOOP; IF (cut # 0) THEN components.blend _ IF (cut2 # 0) THEN blue ELSE black ELSE BEGIN -- Assume: all other colours have the same weight. IF (poly # 0) AND (diff # 0) THEN BEGIN -- Handle gates. mix _ doubleYellowRGB; comp[poly] _ comp[diff] _ FALSE END; IF (poly # 0) AND (met # 0) AND (diff = 0) THEN BEGIN -- Handle metal over poly. mix _ magentaRGB; n _ n - 1.0; comp[poly] _ comp[met] _ FALSE END; FOR i: Layer IN Layer DO -- Compute mean colour. IF comp[i] THEN BEGIN v: ImagerColor.RGB ~ RGBFromColour [LayerColour[i]]; mix.R _ mix.R + v.R; mix.G _ mix.G + v.G; mix.B _ mix.B + v.B END ENDLOOP; IF (met2 # 0) THEN BEGIN -- make metal-2 transparent mix.R _ mix.R - 4.0/7.0; mix.B _ mix.B - 4.0/7.0; n _ n - 4.0/7.0 END; IF (well # 0) THEN BEGIN -- make wells transparent mix.R _ mix.R - 5.0/7.0; mix.G _ mix.G - 5.0/7.0; n _ n - 5.0/7.0; mix.B _ mix.B - (3.0/7.0 * 2.0/7.0) -- take out well lightener END; mix.R _ mix.R / n; mix.G _ mix.G / n; mix.B _ mix.B / n; components.blend _ ImagerColor.ColorFromRGB [mix] END END; RETURN [FALSE] END; -- BlendColours LayerColour: PROC [l: Layer] RETURNS [Color] ~ INLINE BEGIN RETURN [layerColorTable[l]] END; -- LayerColour SetLayerColourTable: PROC ~ BEGIN FOR i: Layer IN Layer DO SELECT CD.LayerKey[i] FROM $nwel => layerColorTable[i] _ lightYellow; $met => layerColorTable[i] _cyan; $met2 => layerColorTable[i] _ lightMagenta; $cut => layerColorTable[i] _ black; $cut2 => layerColorTable[i] _ blue; ENDCASE => layerColorTable[i] _ CDColors.globalColors[bit8][normal].cols[i] ENDLOOP END; -- SetLayerColourTable BlendAllColours: PROC ~ BEGIN [] _ colourTable.Pairs [BlendColours] END; -- BlendAllColours Hash: PROC [k: HashTable.Key] RETURNS [CARDINAL] ~ BEGIN TRUSTED BEGIN RETURN [Checksum.ComputeChecksum [0, SIZE [BlendKey], LOOPHOLE [k]]] END END; -- Hash Match: PROC [a, b: HashTable.Key] RETURNS [BOOL] ~ BEGIN k1: BlendKey ~ NARROW [a, BlendKey]; k2: BlendKey ~ NARROW [b, BlendKey]; RETURN [(k1^ = k2^)] END; -- Match ImagerRect: PROC [r: Rect] RETURNS [Rectangle] ~ BEGIN base: CD.Position ~ CDBasics.BaseOfRect [r]; size: CD.Position ~ CDBasics.SizeOfRect [r]; RETURN [[Float[base.x], Float[base.y], Float[size.x], Float[size.y]]] END; -- ImagerRect ImagerVec: PROC [p: CD.Position] RETURNS [Imager.VEC] ~ BEGIN RETURN [[Float[p.x], Float[p.y]]] END; -- ImagerVec RGBFromColour: PROC [c: Color] RETURNS [rgb: ImagerColor.RGB] ~ INLINE BEGIN WITH c SELECT FROM constant: Imager.ConstantColor => BEGIN rgb.R _ ImagerColorPrivate.ComponentFromColor [constant, $Red]; rgb.G _ ImagerColorPrivate.ComponentFromColor [constant, $Green]; rgb.B _ ImagerColorPrivate.ComponentFromColor [constant, $Blue] END; ENDCASE => rgb _ unColour; RETURN [rgb] END; -- RGBFromColour ImportantMessage: PROC [msg: ROPE] ~ BEGIN MessageWindow.Clear []; MessageWindow.Append [msg]; MessageWindow.Blink [] END; -- ImportantMessage Trace: PROC [i: INTEGER] ~ BEGIN MessageWindow.Clear []; MessageWindow.Append [IO.PutR1 [IO.int [i]]] END; -- Trace InitializeViewerClasses END. 6CoreViewImpl.mesa Copyright Σ 1987 by Xerox Corporation. All rights reserved. Written by Giordano Bruno Beretta, January 22, 1987 10:44:14 am PST gbb March 26, 1987 12:01:24 pm PST Visualizes the Manhattan geometry in a Core layout. Interfaces Draws the geometry in a Core data structure in a viewer using the Imager. Initializes a viewer into which rectangles can be drawn one at a time in the context of a given cell. Adds a rectangle to a viewer started with StartIncrementalView. The label field is loopholed to label the rectangle. [plane: REF Tesselation, rect: Rect, oldValue: REF, data: REF] Core Returns the child's absolute coordinates. Enumerates the cell and does action on each subcell. [cell: CoreCell, transf: Transf, state: State] [instance: CdInsts] RETURNS [quit: BOOL _ FALSE] [plane: REF Tesselation, rect: Rect, oldValue: REF, data: REF] Note that merging works correctly because of the use of the colour table. IF (instance.obj.class.objectType # rectClass) THEN break; Viewers & Context Set-up Initializes and registers the viewer classes. Draws the geometry in a Core data structure in a viewer using the Imager. [self: Viewer, context: Imager.Context, whatChanged: REF, clear: BOOL] RETURNS [quit: BOOL _ FALSE] Called by the window manager when the client should repaint the data on the screen. The context is clipped to the client screen area. whatChanged is just passed from the call to ViewerOps.PaintViewer, but will be NIL when the window manager requires a full repaint after moving a viewer on the screen. clear is a hint that the client background is white, so that the client can paint on the black bits if it so chooses. See comments for paintRectangles bit in the viewer class. Return quit~TRUE to stop without painting children. At this point we know that only one colour representation is used. Must be fast as a bullet. Draw black using the grey colour model, so that it is placed in the black colour separation. PROC [tile: REF Tile, data: REF] PROC [tile: REF Tile, data: REF] [self: Viewer, op: ScrollOp, amount: INTEGER, shift, control: BOOL _ FALSE] RETURNS [top, bottom: INTEGER _ LAST[INTEGER]] ScrollOp = {query, up, down, thumb} Client scrolling and scrolling feedback. If op is 'query' the client should return the percentage of the scrollable document at the top and bottom of the screen, or default if unknown. If op is 'up' or 'down' then amount is number of pixels to glitch. If op is 'thumb' then amount is percentage into document to scroll. The shift and control information reflects the state of the shift and control keys during the up, down, and thumb ops and may be interpreted by the client as desired. viewport: [self.cx, cy, cw, ch] A query is performed each time the mouse is on a scroll bar, hence this must be faster than a bullet. Note that the cached values may exceed the diplayed values to avoid referring to the window when it is moved back into the viewer. Note also that topSB and bottomSB cannot be computed trivially from amount, because amount is in pixels, while I have to return a percentage. The scroll bar is viewed as a scale from 1 to 10. Note that the cached values may exceed the diplayed values to avoid referring to the window when it is moved back into the viewer. [self: Viewer, op: HScrollOp, amount: INTEGER, shift, control: BOOL _ FALSE] RETURNS [left, right: INTEGER _ LAST[INTEGER]] HScrollOp = {query, left, right, thumb} Client scrolling and scrolling feedback. If op is 'query' the client should return the percentage of the scrollable document at the top and bottom of the screen, or default if unknown. If op is 'up' or 'down' then amount is number of pixels to glitch. If op is 'thumb' then amount is percentage into document to scroll. The shift and control information reflects the state of the shift and control keys during the up, down, and thumb ops and may be interpreted by the client as desired. A query is performed each time the mouse is on a scroll bar, hence this must be faster than a bullet. Note that the cached values may exceed the diplayed values to avoid referring to the window when it is moved back into the viewer. Called when the viewer has been destroyed for some reason. [parent: REF ANY, clientData: REF ANY _ NIL, mouseButton: MouseButton _ red, shift, control: BOOL _ FALSE] [parent: REF ANY, clientData: REF ANY _ NIL, mouseButton: MouseButton _ red, shift, control: BOOL _ FALSE] [parent: REF ANY, clientData: REF ANY _ NIL, mouseButton: MouseButton _ red, shift, control: BOOL _ FALSE] [parent: REF ANY, clientData: REF ANY _ NIL, mouseButton: MouseButton _ red, shift, control: BOOL _ FALSE] Color Blending Data is global Sets up a blending record for a tile. Must be fast as a bullet. Takes the layers covering a tile and blend an RBG-colour out of them. [key: Key, value: Value] RETURNS [quit: BOOLEAN _ FALSE] Find exception layers. Cuts always win. Reinitialize mix by yellow and eliminate poly and diff. Since gates are very important, they are given double weight. Ensure that only one colour representation is used. Spread out hues & make "more subtractive". In ChipNdale 23 cut (cut-2) was always black (blue), but in rel. 24 was displayed black (blue) and printed blue (green). The logarithm of the number of colours is two, that of the rectangles is six. PROC [Key] RETURNS [CARDINAL] HashTable.EqualProc Conversions CdPos: PROC [v: Imager.VEC] RETURNS [CD.Position] ~ BEGIN RETURN [[Round[v.x], Round[v.y]]] END; -- CdPos Assume that LayerColour had previously been called. Writes a message in the ChipNDale terminal viewer and in the Message Window at the top of the LF screen and makes it blink. Initializations Κœ˜codešœ™Kšœ<™Kšœ)˜)KšœŸ ˜—Mšœœœ˜KšœQ˜QKšœ4˜4KšœŸ˜——™š œœ1œ ˜]Iabsolute™)KšœV˜\KšœŸ˜—Lšœ œœ0˜Eš   œœBœœœ˜yKšœ4™4Kšœœœœ˜#šœ ˜šœ˜$Kšœ'œ ˜:šœœœ˜'KšœL˜LKšœIœœœ˜^Kš˜—Kšœ˜—Kšœœ˜Kšœ˜Kšœ˜—KšœŸ˜—š  œ ˜Kšœ.™.šœ ˜šœ˜$Kšœ'œ ˜:šœœœ˜.šœœœ˜KšœM˜M—Kš˜—Kšœ˜—KšœP˜PKšœœŸ˜!—KšœŸ ˜—š  œœ;˜Oš  œ"˜0Kšœœœœ™0KšœE˜EKšœ˜Kšœ˜š  œ˜'Kšœœ$œœ™>KšœI™Išœ œ˜Kšœ œœœ5˜Zšœ˜Kšœ œ ˜Kšœ3˜3Kš˜——KšœŸ ˜—Mšœœœ˜+Kšœ-œ™:šœ˜)šœ œ˜/KšœJ˜J—Kšœ$Οtœ˜*Kšœ>˜E—KšœŸ ˜—Mšœ6˜6KšœŸ ˜——™Lšœœ˜0Kšœ!˜!Kšœ+˜+š œœ˜%K™.Kšœ$œ ˜GKšœ$œ ˜GKšœ,˜,KšœWœ˜]KšœR˜RKšœU˜UKšœX˜XMšœ(˜(Kšœ)˜)Kšœ*˜*Kšœ-˜-šœœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ ˜ Kšœ˜KšœP˜PKšœ˜Kšœ˜—Mšœ˜Kšœ˜KšœW˜WMšœ œ%˜/Kšœ œ&˜0KšœŸ˜—š œœ6œ˜lKšœI™IKšœ˜šœœ˜Kšœ'˜'Kšœœœœ˜EKšœ œœœ˜>Kšœ œ˜Kšœœ˜Kšœ˜Kšœœ˜Kšœ ˜ —Kšœ˜Kšœ.˜.KšœŸ˜—š œ˜&Kš œ5œ œœœœ™cKšŸΧΠckŸίœŸ'£Ÿ#™–Lšœœ ˜"š  œœœ˜1K™]Kšœœ˜,Kšœœ(˜:š œ œ œ œœœ˜WK™\Kšœ œ œ œ˜QKšœ˜Kšœ˜Kš˜—KšœŸ˜—š  œ˜&Kšœœ œ™ Kšœ œ˜Kšœ"Ÿ#˜EMšœœœ˜Kšœ˜Kšœ&˜&KšœŸ ˜—š œ˜-Kšœœ œ™ Kšœ"Ÿ#˜EKšœœ˜Mšœœœ˜Kšœ˜Kšœ'˜'Kšœ˜Kšœ˜Kšœ.Ÿ˜6Kšœ.Ÿ˜5Kšœ.Ÿ˜6Kšœ.Ÿ˜5Mšœœœ˜*Kšœ˜Kšœœœ ˜)KšœŸ˜—Mšœœ˜Kšœœ˜Kšœ3Ÿ˜Lš œœœœ œ˜UKšœœœœ ˜FKšœ$˜$Kšœ˜—Mš œœœœœ˜;Mšœœ˜%šœœœŸ)˜KKšœ?˜?KšœœR˜cKšœ˜Kšœ˜—KšœE˜EKšœ3Ÿ˜LKšœ%˜%Kšœ\˜\Kšœ%˜%šœ˜˜ Kšœ_˜_—˜ Kšœf˜f—Kšœ˜—KšœŸ˜ —š œ˜5Kšœ%œœœœœœœ™zKšœ#™#KšŸXΟz Ÿ€ΠczŸ-₯ ŸΑ™κLšœœ ˜"Lšœ™šœœ˜šœ˜šœ ˜K™eKšœœœΠbk˜:Kšœ˜—šœœ*œ˜K™1Kšœœ˜*Kšœ˜KšœZ˜ZKšœ<˜˜>Kšœ˜—Kšœ8˜8Kšœ1˜1Kš˜—Kš˜—Kšœœ˜—KšœŸ˜—š   œœ œ œ˜;K™3Kšœ˜KšœŸ˜—š œœ˜!J™*šœ œ˜šœœ ˜Kšœ*˜*Kšœ!˜!Kšœ+˜+Kšœz™zKšœ#˜#Kšœ#˜#KšœD˜K—Kš˜—KšœŸ˜—š œœ˜K™MKšœ%˜%KšœŸ˜—š  œœœœ˜8Kšœœœ™šœ˜ Kšœœ œ˜DKš˜—KšœŸ˜ —š  œœœœ˜8Lšœ™Kšœœœ˜IKšœ˜KšœŸ˜ ——™ š  œœ œ˜6Kšœœ$˜,Kšœœ$˜,Kšœ?˜EKšœŸ ˜—š   œœœ œ œ˜=Kšœ˜!KšœŸ ˜—š  œœ œœœ ™9Kšœ™!KšœŸ™ —š   œœ œœœ˜LKšœ ‘ œ™3šœ ˜šœ"˜'Kšœ?˜?KšœA˜AKšœ?˜?Kšœ˜—Kšœ˜—Kšœ˜ KšœŸ˜—š œœœ˜*Kšœ^œ™{KšœJ˜JKšœŸ˜—š œœœ˜ Kšœ.œœ ˜DKšœŸ˜ ——™Lšœ˜—Lšœ˜—…—W ‡ά