DIRECTORY ImagerFontCache; ImagerFontCacheImpl: CEDAR MONITOR EXPORTS ImagerFontCache = BEGIN FontCache: PUBLIC TYPE ~ REF FontCacheRep; FontCacheRep: PUBLIC TYPE ~ RECORD [ firstFontCode: NAT, seq: REF Seq ]; Seq: TYPE ~ RECORD [ SEQUENCE length: NAT OF REF Array ]; Array: TYPE ~ RECORD [ bc: CHAR, seq: SEQUENCE length: [0..256) OF REF ]; FontCode: TYPE ~ ImagerFontCache.FontCode; FontFileCode: TYPE ~ ImagerFontCache.FontFileCode; fontCodeTableHeaders: NAT ~ 101; FontKeyRec: TYPE ~ MACHINE DEPENDENT RECORD [r0, r1, r2, r3, r4, r5: REAL, fontFileCode: FontFileCode, fill: BOOLEAN _ FALSE]; fontCodeTable: REF FontCodeTableRep _ NEW[FontCodeTableRep]; FontCodeTableRep: TYPE ~ ARRAY [0..fontCodeTableHeaders) OF CollisionList; CollisionList: TYPE ~ REF CollisionListItem; CollisionListItem: TYPE ~ RECORD [ next: CollisionList, fontCode: FontCode, fontKeyRec: FontKeyRec ]; fontCodeInverse: REF FontCodeInverseRep; FontCodeInverseRep: TYPE ~ RECORD [SEQUENCE length: NAT OF CollisionList]; nextFontCode: CARDINAL _ 0; GetFontCode: PUBLIC ENTRY PROC [r0, r1, r2, r3, r4, r5: REAL, fontFileCode: FontFileCode] RETURNS [fontCode: FontCode] ~ TRUSTED { ENABLE UNWIND => NULL; fontKeyRec: FontKeyRec _ [r0, r1, r2, r3, r4, r5, fontFileCode]; p: POINTER TO CARDINAL _ LOOPHOLE[@fontKeyRec]; hash: CARDINAL _ 0; IF SIZE[FontKeyRec] MOD SIZE[CARDINAL] # 0 THEN ERROR; THROUGH [0..SIZE[FontKeyRec]/SIZE[CARDINAL]) DO t: CARDINAL _ 2*hash; hash _ 2*t+hash+p^; -- Depend on overflow not to raise a signal; p _ p + SIZE[CARDINAL]; ENDLOOP; hash _ hash MOD fontCodeTableHeaders; FOR c: CollisionList _ fontCodeTable[hash], c.next UNTIL c=NIL DO IF c.fontKeyRec = fontKeyRec THEN RETURN [c.fontCode]; ENDLOOP; fontCodeTable[hash] _ NEW[CollisionListItem _ [fontCodeTable[hash], [nextFontCode], fontKeyRec]]; IF fontCodeInverse = NIL OR fontCodeInverse.length <= nextFontCode THEN { old: REF FontCodeInverseRep _ fontCodeInverse; newLength: NAT _ IF old = NIL THEN 6 ELSE old.length + old.length/3 + 1; fontCodeInverse _ NEW[FontCodeInverseRep[newLength]]; IF old # NIL THEN FOR i: NAT IN [0..old.length) DO fontCodeInverse[i] _ old[i]; ENDLOOP; old _ NIL; }; fontCodeInverse[nextFontCode] _ fontCodeTable[hash]; fontCode _ [nextFontCode]; nextFontCode _ nextFontCode + 1; }; InterpretFontCode: PUBLIC ENTRY PROC [fontCode: FontCode] RETURNS [r0, r1, r2, r3, r4, r5: REAL, fontFileCode: FontFileCode] ~ { ENABLE UNWIND => NULL; IF fontCodeInverse = NIL OR fontCodeInverse.length <= fontCode.key OR fontCodeInverse[fontCode.key] = NIL THEN ERROR InvalidFontCode[]; [r0: r0, r1: r1, r2: r2, r3: r3, r4: r4, r5: r5, fontFileCode: fontFileCode] _ fontCodeInverse[fontCode.key].fontKeyRec; }; InvalidFontCode: PUBLIC ERROR ~ CODE; Flush: PUBLIC ENTRY PROC [fontFileCode: FontFileCode] ~ { ENABLE UNWIND => NULL; FOR i: NAT IN [0..fontCodeTableHeaders) DO c: CollisionList _ fontCodeTable[i]; prev: CollisionList _ NIL; WHILE c#NIL DO IF c.fontKeyRec.fontFileCode = fontFileCode THEN { fontCodeInverse[c.fontCode.key] _ NIL; IF prev = NIL THEN fontCodeTable[i] _ c.next ELSE prev.next _ c.next; } ELSE prev _ c; c _ IF prev = NIL THEN fontCodeTable[i] ELSE prev.next; ENDLOOP; ENDLOOP; }; Create: PUBLIC PROC RETURNS [FontCache] ~ { RETURN [NEW[FontCacheRep]]; }; GetCharData: PUBLIC PROC [fontCache: FontCache, fontCode: FontCode, char: CHAR] RETURNS [data: REF] ~ { code: NAT ~ fontCode.key; LockedGetSuccess: ENTRY PROC RETURNS [BOOLEAN] ~ INLINE { ENABLE UNWIND => NULL; IF fontCache.seq = NIL OR code < fontCache.firstFontCode OR code-fontCache.firstFontCode >= fontCache.seq.length THEN RETURN [FALSE] ELSE { a: REF Array _ fontCache.seq[code-fontCache.firstFontCode]; IF a = NIL OR char < a.bc OR char-a.bc >= a.length THEN RETURN [FALSE]; data _ a[char-a.bc]; IF data = NIL THEN RETURN [FALSE]; }; RETURN [TRUE]; }; IF NOT LockedGetSuccess[] THEN {SIGNAL CacheMiss; data _ NIL}; }; CacheMiss: PUBLIC SIGNAL ~ CODE; LoadCharData: PUBLIC ENTRY PROC [fontCache: FontCache, fontCode: FontCode, char: CHAR, data: REF] ~ { ENABLE UNWIND => NULL; code: NAT ~ fontCode.key; a: REF Array; IF fontCache.seq = NIL THEN {fontCache.seq _ NEW[Seq[6]]; fontCache.firstFontCode _ code}; IF code < fontCache.firstFontCode THEN { additionalLength: NAT ~ fontCache.firstFontCode - code; newLength: NAT ~ additionalLength + fontCache.seq.length; old: REF Seq ~ fontCache.seq; fontCache.seq _ NEW[Seq[newLength]]; FOR i: NAT IN [0..old.length) DO fontCache.seq[additionalLength + i] _ old[i] ENDLOOP; fontCache.firstFontCode _ code; }; IF code-fontCache.firstFontCode >= fontCache.seq.length THEN { newLength: NAT ~ code - fontCache.firstFontCode + 1 + fontCache.seq.length/3; old: REF Seq ~ fontCache.seq; fontCache.seq _ NEW[Seq[newLength]]; FOR i: NAT IN [0..old.length) DO fontCache.seq[i] _ old[i] ENDLOOP; }; a _ fontCache.seq[code-fontCache.firstFontCode]; IF fontCache.seq[code-fontCache.firstFontCode] = NIL THEN { bc: CHAR ~ MIN[char, ' ]; ec: CHAR ~ MAX[char, '~]; a _ NEW[Array[ec-bc+1]]; a.bc _ bc; }; IF char < a.bc THEN { additionalLength: NAT ~ a.bc - char; newLength: NAT ~ additionalLength + a.length; old: REF Array _ a; a _ NEW[Array[newLength]]; FOR i: NAT IN [0..old.length) DO a[additionalLength + i] _ old[i] ENDLOOP; a.bc _ char; }; IF char-a.bc >= a.length THEN { newLength: NAT ~ char-a.bc + 1; old: REF Array _ a; a _ NEW[Array[newLength]]; FOR i: NAT IN [0..old.length) DO a[i] _ old[i] ENDLOOP; a.bc _ old.bc; }; a[char-a.bc] _ data; fontCache.seq[code-fontCache.firstFontCode] _ a; }; END. RImagerFontCacheImpl.mesa Michael Plass, August 15, 1983 12:11 pm Michael Plass, July 18, 1983 10:20 am: Fixed bug in GetFontCode; was checking fontCodeInverse.length against fontCode.key instead of nextFontCode. Michael Plass, July 22, 1983 2:07 pm: Put monitor in GetCharData and LoadCharData so a global font cache could be used. Κ"˜J™J™'IunitšΟk œ˜Kšœœ˜BJšœ œœœ˜*šœœœœ˜$Jšœœ˜Jšœœ˜ Jšœ˜—šœœœ˜Jšœ œœœ˜!Jšœ˜—šœœœ˜Jšœœ˜ Jšœœœ˜%Jšœ˜—Jšœ œœ ˜*Jšœœ ˜2Kšœœ˜ Kšœ œœ œœœ$œœ˜~Kšœœœ˜J˜—Kšž œœœœ˜ š ž œœœœ2œœ˜eJšœœœ˜Jšœœ˜Jšœœ˜ Jšœœœœ*˜Zšœ œ˜(Jšœœ"˜7Jšœ œ+˜9Jšœœ˜Jšœœ˜$Jš œœœœ.œ˜VJšœ˜Jšœ˜—šœ6œ˜>Jšœ œ?˜MJšœœ˜Jšœœ˜$Jš œœœœœ˜CJšœ˜—Jšœ0˜0šœ/œœ˜;Jšœœœ ˜Jšœœœ ˜Jšœœ˜Jšœ ˜ Jšœ˜—šœ œ˜Jšœœ˜$Jšœ œ˜-Jšœœ ˜Jšœœ˜Jš œœœœ"œ˜JJšœ ˜ Jšœ˜—šœœ˜Jšœ œ˜Jšœœ ˜Jšœœ˜Jš œœœœœ˜7Jšœ˜Jšœ˜—Jšœ˜Jšœ0˜0J˜—Kšœ˜Jšœ4ž œS™’Jšœ5ž œž œ&™w—…—vκ