<> <> <> <> 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.ysz.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.