CDRectsImpl.mesa (part of ChipNDale)
Copyright © 1983 by Xerox Corporation. All rights reserved.
Christian Jacobi, June 24, 1983 4:58 pm
last edited Christian Jacobi, October 7, 1985 11:14:13 am PDT
DIRECTORY
CD,
CDBasics,
CDCallSpecific,
CDIO,
CDIOExtras,
CDLRUCache,
CDOrient,
CDProperties,
CDRects,
CDLayers,
CDOps,
Rope,
SafeStorage;
CDRectsImpl: CEDAR MONITOR
IMPORTS CD, CDCallSpecific, CDBasics, CDIO, CDIOExtras, CDLRUCache, CDOrient, CDOps, CDProperties, CDLayers, Rope, SafeStorage
EXPORTS CDRects
SHARES CD =
BEGIN
permanent: ZONE = SafeStorage.GetPermanentZone[];
dummyRectPtr: CD.RectPtr = permanent.NEW[CD.RectRep ← [filler: NIL]];
b1Cache: CDLRUCache.LRUCache = CDLRUCache.Create[size: 41, newProc: New];
b2Cache: CDLRUCache.LRUCache = CDLRUCache.Create[size: 41, newProc: New];
b3Cache: CDLRUCache.LRUCache = CDLRUCache.Create[size: 41, newProc: New];
-- any number of caches; simply for speed up; Yes I know, one big cache could be better
-- but this is faster, and the distribution is crazy, such that not all caches have similar
-- hit rates
New: PROC [] RETURNS [CD.Object] = {
ob: CD.Object ← NEW[CD.ObjectRep];
ob.specificRef ← dummyRectPtr;
RETURN [ob]
};
CreateRectProc: TYPE = PROC [size: CD.Position, l: CD.Layer] RETURNS [CD.Object] ← CreateBareRect;
createRectArray: REF ARRAY CD.Layer OF CreateRectProc =
permanent.NEW[ARRAY CD.Layer OF CreateRectProc]; -- initialized by default
CreateRect: PUBLIC PROC [size: CD.Position, l: CD.Layer] RETURNS [CD.Object] =
BEGIN
RETURN [createRectArray[l][size, l]]
END;
HangExtensionsOn: PROC[on: REF CD.ObjectClass] =
BEGIN
CDCallSpecific.Register[$Lengthen, on, Lengthen];
CDCallSpecific.Register[$Default, on, Defaulten];
END;
UseAsCreateRect: PUBLIC PROC [
l: CD.Layer,
createRect: PROC [size: CD.Position, l: CD.Layer] RETURNS [CD.Object],
hangExtensionsOn: REF CD.ObjectClass
] =
BEGIN
IF createRect=NIL THEN createRect ← CreateBareRect;
createRectArray[l] ← createRect;
IF hangExtensionsOn#NIL THEN HangExtensionsOn[hangExtensionsOn];
CDProperties.PutPropOnLayer[onto: l, prop: $CDxRectCreation, val: $CDxUser];
END;
CreateBareRect: PUBLIC PROC [size: CD.Position, l: CD.Layer] RETURNS [CD.Object] =
BEGIN
usedCache: CDLRUCache.LRUCache =
IF size.y<37 THEN b1Cache ELSE IF size.x<16 THEN b2Cache ELSE b3Cache;
rp: CD.Object = usedCache.UnusedOrNew[];
rp.class ← bareRectClass;
rp.size ← CDBasics.MaxPoint[size, [1, 1]];
rp.layer ← l;
RETURN [usedCache.ReplaceByAequivalent[rp]]
END;
bareRectClass: PUBLIC REF CD.ObjectClass;
oldSaveRectClass: REF CD.ObjectClass; --for compatibility only
Init: PROC [] =
BEGIN
bareRectClass ← CD.RegisterObjectClass[$Rect];
bareRectClass.drawMe ← bareRectClass.quickDrawMe ← DrawMeForRects;
bareRectClass.internalRead ← ReadRect;
bareRectClass.internalWrite ← WriteRect;
bareRectClass.describe ← Describe;
bareRectClass.wireTyped ← TRUE;
HangExtensionsOn[bareRectClass];
oldSaveRectClass ← CD.RegisterObjectClass[$SaveRect];
oldSaveRectClass.internalRead ← ReadRect;
END;
Describe: PROC[me: CD.Object] RETURNS [Rope.ROPE] =
BEGIN
RETURN [Rope.Concat["rect ", CDOps.LayerName[me.layer]]]
END;
DrawMeForRects: PROC [inst: CD.Instance, pos: CD.Position, orient: CD.Orientation,
pr: CD.DrawRef] =
BEGIN
pr.drawRect[CDOrient.RectAt[pos, inst.ob.size, orient], inst.ob.layer, pr]
END;
Lengthen: CDCallSpecific.CallProc =
BEGIN
sz: CD.Position ← CD.InterestSize[inst.ob];
amount: CD.Position;
IF x=NIL THEN amount ← [0, design.technology.lambda]
ELSE IF ISTYPE [x, REF CD.Position] THEN amount ← NARROW[x, REF CD.Position]^
ELSE {done←FALSE; RETURN};
sz ← CDBasics.AddPoints[sz, amount];
IF sz.x<=0 OR sz.y<=0 THEN {done ← FALSE; RETURN};
inst.ob ← CreateRect[sz, inst.ob.layer];
repaintMe ← TRUE;
END;
Defaulten: CDCallSpecific.CallProc =
BEGIN
sz: CD.Position ← CD.InterestSize[inst.ob];
w: CD.Number ← CDLayers.LayerWidth[design, inst.ob.layer];
IF w<=0 THEN {done ← FALSE; RETURN};
sz.x ← w;
inst.ob ← CreateRect[sz, inst.ob.layer];
repaintMe ←TRUE;
END;
SetLength: CDCallSpecific.CallProc =
BEGIN
newLength: CD.Number ← NARROW[x, REF CD.Number]^;
sz: CD.Position ← inst.ob.size;
IF sz.y<sz.x THEN sz.x ← newLength
ELSE sz.y ← newLength;
inst.ob ← CreateRect[sz, inst.ob.layer];
repaintMe ← TRUE;
END;
SetWidth: CDCallSpecific.CallProc =
BEGIN
newWidth: CD.Number ← NARROW[x, REF CD.Number]^;
sz: CD.Position ← inst.ob.size;
IF sz.y>sz.x THEN sz.x ← newWidth
ELSE sz.y ← newWidth;
inst.ob ← CreateRect[sz, inst.ob.layer];
repaintMe ← TRUE;
END;
WriteRect: CD.InternalWriteProc -- PROC [me: Object] -- =
BEGIN
CDIOExtras.WritePos[CD.InterestSize[me]];
CDIO.WriteLayer[me.layer];
END;
ReadRect: CD.InternalReadProc --PROC [] RETURNS [Object]-- =
BEGIN
sz: CD.Position = CDIOExtras.ReadPos[];
l: CD.Layer = CDIO.ReadLayer[];
ob: CD.Object = CreateRect[sz, l];
RETURN [ob]
END;
Init[];
END.