ImagerMasks.mesa
Michael Plass, July 6, 1983 9:05 am
Provides operations on device-resolution masks, in various representations. The coordinates are given in terms of s and f (for slow and fast).
DIRECTORY
BitBlt USING [DstFunc, SrcFunc],
ImagerBasic USING [Visibility]
;
ImagerMasks: CEDAR DEFINITIONS ~ BEGIN
Data types
Visibility: TYPE ~ ImagerBasic.Visibility;
Mask: TYPE ~ RECORD [
sMin, fMin: INTEGER,
sSize, fSize: NAT,
refRep: REF MaskRep
];
Making new Masks from scratch
Create: PROC [
runs: PROC[ -- Create calls this back
run: PROC[s, fMin: INTEGER, fSize: NAT], -- client calls this from inside runs.
repeat: PROC[timesToRepeatScanline: NAT] -- client calls this to repeat a scanline
]
] RETURNS [Mask];
The runs proc should call run for each run, in non-descreasing s. It may call repeat to duplicate a scanline just entered.
NewBitmap: PROC [sMin, fMin: INTEGER, sSize, fSize: NAT] RETURNS [Mask];
Allocates new space for a bitmap representation.
Box: PROC [sMin, fMin: INTEGER, sSize, fSize: NAT] RETURNS [Mask];
InlineBox: PROC [sMin, fMin: INTEGER, sSize, fSize: NAT] RETURNS [Mask] ~ INLINE {RETURN[[sMin, fMin, sSize, fSize, NIL]]};
Making new masks from old
And: PROC [a, b: Mask] RETURNS [Mask];
Or: PROC [a, b: Mask] RETURNS [Mask];
Difference: PROC [a, b: Mask] RETURNS [Mask];
Shift: PROC [mask: Mask, s, f: INTEGER] RETURNS [Mask];
InlineShift: PROC [mask: Mask, s, f: INTEGER] RETURNS [Mask] ~ INLINE {RETURN[[mask.sMin+s, mask.fMin+f, mask.sSize, mask.fSize, mask.refRep]]};
Bitmap: PROC [mask: Mask] RETURNS [Mask];
Forces a bitmap representation. Does NOT copy if it is already a bitmap.
Extracting info from masks
SMin: PROC [mask: Mask] RETURNS [INTEGER] ~ INLINE {RETURN[mask.sMin]};
FMin: PROC [mask: Mask] RETURNS [INTEGER] ~ INLINE {RETURN[mask.fMin]};
SSize: PROC [mask: Mask] RETURNS [CARDINAL] ~ INLINE {RETURN[mask.sSize]};
FSize: PROC [mask: Mask] RETURNS [CARDINAL] ~ INLINE {RETURN[mask.fSize]};
MapRuns: PROC [mask: Mask, run: PROC [s, fMin: INTEGER, fSize: CARDINAL]];
MapBoxes: PROC [mask: Mask, box: PROC [sMin, fMin: INTEGER, sSize, fSize: CARDINAL]];
MapClippedRuns: PROC [mask, clipper: Mask, run: PROC [s, fMin: INTEGER, fSize: CARDINAL]];
MapClippedBoxes: PROC [mask, clipper: Mask, box: PROC [sMin, fMin: INTEGER, sSize, fSize: CARDINAL]];
IsVisible: PROC [mask, clipper: Mask] RETURNS [Visibility];
SELECT And[mask, clipper] FROM
= empty => invisible,
= mask => visible,
ENDCASE => partlyVisible;
N. B. will return invisible if mask = empty.
Applying masks
Function: TYPE ~ RECORD [dstFunc: BitBlt.DstFunc, srcFunc: BitBlt.SrcFunc];
[null, null] makes zero bits white, one bits black
[or, null] makes zero bits transparent, one bits black
[and, null] makes zero bits white, one bits black
[and, complement] makes zero bits transparent, one bits white
[xor, null] makes zero bits transparent, one bits inverted
etcetera.
MaskConstant: PROC [dest: Mask, mask: Mask, tile: Mask, phase: NAT, function: Function ← [null, null]];
dest must be a bitmap variant, and is modified.
mask can be in any representation; dest is unmodified outside of the mask.
tile must be a bitmap variant, and must have an fSize of 16, and sSize in the range [1..16].
phase tells how far to move the tile in the f direction for each row.
MaskSampled: PROC [dest: Mask, mask: Mask, source: Mask, function: Function ← [null, null]];
The source is pressed through the mask onto the dest. The dest is unmodified outside of the bounding box of the source.
Miscellaneous
LFDisplay: PROC RETURNS [Mask]; -- a bitmap variant describing the LF display.
inkTile: Mask;
for painting black.
Representations
MaskRep: TYPE ~ RECORD [
SELECT rep: * FROM
bitmap => [ref: REF, pointer: LONG POINTER, rast: CARDINAL, lines: CARDINAL],
Stored contiguously, with each line padded to a word boundary, rast words per line. The ref is for garbage collection hacks; the long pointer points to the actual bits. The value of lines should be the same as sSize, and is used for error checking.
pdruns => [runCount: INT, runGroup: PDRunGroup],
compatible with pd file representation.
runs => [index: SEQUENCE length: NAT OF RunBlock],
ENDCASE
];
PDRunGroup: TYPE ~ REF PDRunGroupRep;
PDRunGroupRep: TYPE ~ RECORD [
rest: PDRunGroup,
In case the run group won't all fit into one record.
firstPart: SEQUENCE length: NAT OF PDRunRep
];
Note: the run representation is chosen so that run groups may be moved into PD files in large blocks.
PDRunRep: TYPE ~ MACHINE DEPENDENT RECORD [
fMin(0): CARDINAL,
lastRun(1:0..0): BOOLEAN,
fSize(1:1..15): NAT
];
RunBlock: TYPE ~ REF RunBlockRep;
RunBlockRep: TYPE ~ RECORD [
seq: SEQUENCE length: NAT OF RunRep
];
RunRep: TYPE ~ MACHINE DEPENDENT RECORD [
newLineRepeatCount: CARDINAL, -- zero if the run does not start a new scanline
fMin: CARDINAL,
fSize: CARDINAL
];
END.