IIMaskCacheImpl.mesa
Copyright © 1985, 1986 by Xerox Corporation. All rights reserved.
Michael Plass, September 23, 1986 4:05:14 pm PDT
Doug Wyatt, May 20, 1985 11:40:49 am PDT
DIRECTORY
Basics USING [BITAND, BITSHIFT, bitsPerWord, BITXOR],
Checksum USING [ComputeChecksum],
IIFont USING [XChar],
IIMaskCache USING [CharMask, CharMaskRep, Run],
IISample USING [BoxesFromBitmap, Clear, Clip, FillBoxes, NewSampleMap, ObtainUnsafeDescriptor, ReleaseDescriptor, SampleMap],
RefTab USING [Create, Fetch, Pairs, Ref, Store],
SF USING [Add, Box, BoxAction, maxBox, Size, Vec, zeroVec];
IIMaskCacheImpl:
CEDAR
MONITOR
LOCKS x
USING x: MaskCache
IMPORTS Basics, IISample, Checksum, RefTab, SF
EXPORTS IIMaskCache
~ BEGIN
CharMask: TYPE ~ IIMaskCache.CharMask;
CharMaskRep: TYPE ~ IIMaskCache.CharMaskRep;
XChar: TYPE ~ IIFont.XChar;
bitsPerWord: NAT ~ Basics.bitsPerWord;
BitmapFromCharMask:
PUBLIC
PROC [charMask: CharMask]
RETURNS [IISample.SampleMap] ~ {
size: SF.Vec ~ SF.Size[charMask.box];
WITH charMask
SELECT
FROM
raster:
REF CharMaskRep.raster =>
TRUSTED {
wordsPerLine: CARDINAL ~ (size.f+(bitsPerWord-1))/bitsPerWord;
bitmap: IISample.SampleMap ~ IISample.ObtainUnsafeDescriptor[
size: size,
bitsPerSample: 1,
bitsPerLine: wordsPerLine*bitsPerWord,
base: [word: @raster[0], bit: 0],
ref: raster,
words: wordsPerLine*size.s,
delta: charMask.box.min
];
RETURN [bitmap]
};
ENDCASE => {
bitmap: IISample.SampleMap ~ IISample.NewSampleMap[box: charMask.box, bitsPerSample: 1];
boxGenerator:
-- SF.BoxGenerator --
PROC [boxAction:
SF.BoxAction] ~ {
BoxesFromCharMask[charMask, boxAction, SF.zeroVec, SF.maxBox];
};
IISample.Clear[bitmap];
IISample.FillBoxes[map: bitmap, boxes: boxGenerator, value: 1];
RETURN [bitmap]
};
};
BoxesFromCharMask:
PUBLIC
PROC [charMask: CharMask, boxAction:
SF.BoxAction, delta:
SF.Vec, clip:
SF.Box] ~ {
WITH charMask
SELECT
FROM
raster:
REF CharMaskRep.raster =>
TRUSTED {
size: SF.Vec ~ SF.Size[charMask.box];
wordsPerLine: CARDINAL ~ (size.f+(bitsPerWord-1))/bitsPerWord;
bitmap: IISample.SampleMap ~ IISample.ObtainUnsafeDescriptor[
size: size,
bitsPerSample: 1,
bitsPerLine: wordsPerLine*bitsPerWord,
base: [word: @raster[0], bit: 0],
ref: raster,
words: wordsPerLine*size.s,
delta: SF.Add[charMask.box.min, delta]
];
clipped: IISample.SampleMap ~ IISample.Clip[bitmap, clip];
IISample.BoxesFromBitmap[clipped, boxAction];
IISample.ReleaseDescriptor[bitmap];
IISample.ReleaseDescriptor[clipped];
};
runGroup:
REF CharMaskRep.runs => {
s0: INTEGER ~ INT[delta.s]+charMask.box.min.s;
f0: INTEGER ~ INT[delta.f]+charMask.box.min.f;
s: INTEGER ← s0;
FOR i:
NAT
IN [0..runGroup.nRuns)
WHILE s < clip.max.s
DO
r: IIMaskCache.Run ~ runGroup[i];
IF s >= clip.min.s
THEN {
fMin: INTEGER ~ MAX[NAT[r.fMin]+f0, clip.min.f];
fMax: INTEGER ~ MIN[NAT[r.fMin+r.fSize]+f0, clip.max.f];
IF fMax > fMin THEN boxAction[[min: [s, fMin], max: [s+1, fMax]]];
};
IF r.lastRun THEN s ← s + 1;
ENDLOOP;
};
ENDCASE => NULL;
};
MaskCache: TYPE ~ REF MaskCacheRep;
MaskCacheRep:
PUBLIC
TYPE ~
MONITORED
RECORD [
size: NAT,
lgMaxSize: NAT,
stuffCount: LONG CARDINAL ← 0,
seq: SEQUENCE maxSize: CARDINAL OF CharMask
];
Create:
PUBLIC
PROC [size:
NAT]
RETURNS [new: MaskCache] ~ {
maxSize: CARDINAL ← 1;
lgMaxSize: NAT ← 0;
UNTIL maxSize > size
DO
maxSize ← 2*maxSize;
lgMaxSize ← lgMaxSize + 1;
ENDLOOP;
new ← NEW[MaskCacheRep[maxSize]];
new.size ← 0;
new.lgMaxSize ← lgMaxSize;
};
Size:
PUBLIC
ENTRY
PROC [x: MaskCache]
RETURNS [
NAT] ~ {
RETURN [x.size] };
CharAndFont:
TYPE ~
MACHINE
DEPENDENT
RECORD [char: XChar, font:
REF];
Fetch:
PUBLIC
ENTRY
PROC [x: MaskCache, font:
REF, char: XChar]
RETURNS [CharMask] ~
TRUSTED {
last: CARDINAL ~ x.maxSize-1;
cf: CharAndFont ← [char, font];
cksum: CARDINAL ~ Checksum.ComputeChecksum[nWords: SIZE[CharAndFont], p: @cf];
hash: CARDINAL ← Basics.BITAND[last, Basics.BITXOR[cksum, Basics.BITSHIFT[cksum, -x.lgMaxSize]]];
probes: CARDINAL ← 0;
c: CharMask ← NIL;
UNTIL (c ← x[hash])=
NIL
OR (c.font=font
AND c.char=char)
DO
probes ← probes + 1;
IF probes < maxProbes
THEN { IF hash#0 THEN hash ← hash-1 ELSE hash ← last }
ELSE RETURN [NIL];
ENDLOOP;
RETURN [c];
};
Store:
PUBLIC
ENTRY
PROC [x: MaskCache, charMask: CharMask]
RETURNS [ok:
BOOL] ~
TRUSTED {
last: CARDINAL ~ x.maxSize-1;
cf: CharAndFont ← [charMask.char, charMask.font];
cksum: CARDINAL ~ Checksum.ComputeChecksum[nWords: SIZE[CharAndFont], p: @cf];
hash: CARDINAL ← Basics.BITAND[last, Basics.BITXOR[cksum, Basics.BITSHIFT[cksum, -x.lgMaxSize]]];
probes: CARDINAL ← 0;
c: CharMask ← NIL;
UNTIL (c ← x[hash]) =
NIL
OR (c.font=cf.font
AND c.char=cf.char)
DO
probes ← probes + 1;
IF probes < maxProbes
THEN { IF hash#0 THEN hash ← hash-1 ELSE hash ← last }
ELSE {
Replace an entry - this is a cache!
x[hash] ← charMask;
x.stuffCount ← x.stuffCount + 1;
};
ENDLOOP;
IF c = NIL AND x.size < x.maxSize THEN { x.size ← x.size + 1; c ← x[hash] ← charMask };
RETURN [c # NIL];
};
Flush:
PUBLIC
ENTRY
PROC [x: MaskCache] ~ {
FOR i: INT IN [0..x.maxSize) DO x[i] ← NIL ENDLOOP;
x.size ← 0;
};
GetList:
PUBLIC
ENTRY
PROC [x: MaskCache]
RETURNS [list:
LIST
OF CharMask ←
NIL] ~ {
FOR i:
INT
IN [0..x.maxSize)
DO
c: CharMask ← x[i];
IF c # NIL THEN list ← CONS[c, list];
ENDLOOP;
};
GetNamedCache:
PUBLIC
PROC [atom:
ATOM, createSize:
NAT]
RETURNS [r: MaskCache] ~ {
r ← NARROW[RefTab.Fetch[cacheTab, atom].val];
IF r =
NIL
OR r.maxSize < createSize
THEN {
IF r # NIL THEN Flush[r];
r ← Create[createSize];
[] ← RefTab.Store[cacheTab, atom, r];
};
};
cacheTab: RefTab.Ref ~ RefTab.Create[];
FlushAll:
PUBLIC
PROC [] ~ {
epa: PROC [key, val: REF] RETURNS [quit: BOOL ← FALSE] ~ {Flush[NARROW[val]]};
[] ← RefTab.Pairs[cacheTab, epa];
};
END.