ImagerPixelMaps.mesa
Michael Plass, September 6, 1983 9:12 am
Basic operations on two-dimensional arrays of pixels.
DIRECTORY BitBlt, Inline;
ImagerPixelMaps:
CEDAR
DEFINITIONS IMPORTS Inline ~
BEGIN
This interface provides most of the functionality of BitBlt, without the attendant risks of smashing the world. To avoid confusion no matter how the map is physically laid out, terms like height and width are avoided, and the coordinates are expressed in terms of s and f, for slow and fast. On a display, the s axis is normally vertical, and points down, but on a printer that scans in the long direction, the f axis will point up. The diagram below takes the latter point of view.
-- ^
-- f |
-- |
-- | +----------------------------+
-- | | |
-- | |rast * bitsPerWord / bitsPerPixel |
-- | | |
-- | | +------------+ |
-- | | | | |
-- | | | | |
-- | | |fSize | |
-- | | | | |
-- | | sMin | sSize | |
-- | |<-- -->+------------+ |
-- | | ^ |
-- | | |fMin |
-- | sOrigin | v lines |
-- |<---- ---->+----------------------------+
-- | ^origin of buffer
-- | |
-- | |fOrigin
-- | |
-- | |
-- | v
-- +-------------------------------------------->
-- Device space origin s
A PixelMap describes a window into a buffer, and the buffer itself may be positioned anywhere in a global device space. The windowing information is stored in the PixelMap record, so that it may be easily changed to accomplish translation and clipping by rectangles. The translation feature may be used for destination maps to conveniently implement band buffers.
PixelMap:
TYPE ~
RECORD [
These parameters define a window within the buffer, as well as where the buffer is positioned in device space; they are fair game for clients to modify.
sOrigin, fOrigin: INTEGER,
sMin, fMin: INTEGER,
sSize, fSize: NAT,
refRep: REF PixelMapRep
];
DeviceRectangle:
TYPE ~
RECORD [
sMin, fMin: INTEGER, sSize, fSize: NAT
];
Intersect:
PROC [a, b: DeviceRectangle]
RETURNS [DeviceRectangle];
Computes the intersection of device rectangles.
Create:
PROC [lgBitsPerPixel: [0..4], bounds: DeviceRectangle]
RETURNS [PixelMap];
Allocates a new pixel map.
CreateFrameBuffer:
UNSAFE
PROC [pointer:
LONG
POINTER, words:
LONG
CARDINAL, lgBitsPerPixel: [0..4], rast:
CARDINAL, lines:
CARDINAL, ref:
REF ←
NIL]
RETURNS [PixelMap];
To create a description of a pre-allocated frame buffer as a PixelMap. The ref may be used for finalization, if desired; otherwise the client is responsible for making sure the storage does not go away while the PixelMap is still in use.
Clear:
PROC [pixelMap: PixelMap];
A very fast way to clear a whole buffer. The effect is not limited to the windowed area.
Reshape:
PROC [refRep:
REF PixelMapRep, lgBitsPerPixel: [0..4], bounds: DeviceRectangle]
RETURNS [PixelMap];
Makes a PixelMap from recycled storage.
ShiftMap:
PROC [p: PixelMap, s, f:
INTEGER]
RETURNS [PixelMap];
Translates the pixelMap in device space.
ShiftWindow:
PROC [p: PixelMap, s, f:
INTEGER]
RETURNS [PixelMap];
Translates the window in device space.
Clip:
PROC [p: PixelMap, bounds: DeviceRectangle]
RETURNS [PixelMap];
Further restricts the window
SetWindow:
PROC [p: PixelMap, bounds: DeviceRectangle]
RETURNS [PixelMap];
Changes the window
Window: PROC [p: PixelMap] RETURNS [DeviceRectangle];
BufferBounds:
PROC [p: PixelMap]
RETURNS [DeviceRectangle];
Returns a rectangle describing the actual bounds of the buffer
GetPixel:
PROC [source: PixelMap, s, f:
INTEGER]
RETURNS [
CARDINAL];
Raises bounds fault if the point is not in the window.
The following inline versions of GetPixel assume that the client already knows the number of bits per pixel, and they do not do a bounds check, since the worst that can happen is an address fault.
GetBit:
PROC [source: PixelMap, s, f:
INTEGER]
RETURNS [
CARDINAL]
No bounds check; the worst that can happen is an address fault.
~ TRUSTED INLINE {RETURN [LOOPHOLE[source.refRep.pointer + Inline.LongMult[(s - source.sOrigin), source.refRep.rast], LONG POINTER TO PACKED ARRAY [0..0) OF [0..2)][f - source.fOrigin]]};
Get2Bits:
PROC [source: PixelMap, s, f:
INTEGER]
RETURNS [
CARDINAL]
~ TRUSTED INLINE {RETURN [LOOPHOLE[source.refRep.pointer + Inline.LongMult[(s - source.sOrigin), source.refRep.rast], LONG POINTER TO PACKED ARRAY [0..0) OF [0..4)][f - source.fOrigin]]};
Get4Bits:
PROC [source: PixelMap, s, f:
INTEGER]
RETURNS [
CARDINAL]
~ TRUSTED INLINE {RETURN [LOOPHOLE[source.refRep.pointer + Inline.LongMult[(s - source.sOrigin), source.refRep.rast], LONG POINTER TO PACKED ARRAY [0..0) OF [0..16)][f - source.fOrigin]]};
Get8Bits:
PROC [source: PixelMap, s, f:
INTEGER]
RETURNS [
CARDINAL]
~ TRUSTED INLINE {RETURN [LOOPHOLE[source.refRep.pointer + Inline.LongMult[(s - source.sOrigin), source.refRep.rast], LONG POINTER TO PACKED ARRAY [0..0) OF [0..256)][f - source.fOrigin]]};
Get16Bits:
PROC [source: PixelMap, s, f:
INTEGER]
RETURNS [
CARDINAL]
~ TRUSTED INLINE {RETURN [LOOPHOLE[source.refRep.pointer + Inline.LongMult[(s - source.sOrigin), source.refRep.rast], LONG POINTER TO PACKED ARRAY [0..0) OF CARDINAL][f - source.fOrigin]]};
Equal:
PROC [a, b: PixelMap]
RETURNS [
BOOLEAN];
Tests for equality.
IsAll:
PROC [pixelMap: PixelMap, value:
CARDINAL ← 0]
RETURNS [
BOOLEAN];
Tests for a constant.
Trim:
PROC [pixelMap: PixelMap, backround:
CARDINAL ← 0]
RETURNS [PixelMap];
Shrinks the bounding box to remove unneeded backround.
Fill: PROC [dest: PixelMap, area: DeviceRectangle, value: CARDINAL, function: Function ← [null, null]];
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.
Transfer:
PROC [dest, source: PixelMap, function: Function ← [null, null]];
Does a BITBLT from the source to the dest, through the intersection of the two windows. Does the right thing if the source and dest overlap in the same buffer.
Tile:
TYPE ~
RECORD [
sOrigin, fOrigin: INTEGER,
sSize, fSize: NAT,
phase: INTEGER,
refRep: REF PixelMapRep
];
A tile is similar to a PixelMap, but the window specifications are more primitive, and there is an additional phase specification. A tile is replicated to fill the plane, with tile shifted by phase pixels in the f direction every source.sSize lines.
CreateTile:
PROC [pixelMap: PixelMap, phase:
INTEGER ← 0, fSizeHint:
NAT ← 100, scratch:
REF PixelMapRep ←
NIL]
RETURNS [tile: Tile];
The pixelMap is turned into a tile. This may involve replicating the pattern to make a larger tile that will speed the coloring operation, so the size of the result will not in general be the same as the source. The fSizeHint is used to help decide how big to make the macro-tile. The client may supply some scratch storage for re-use.
TileFromStipple:
PROC [stipple:
CARDINAL, scratch:
REF PixelMapRep ←
NIL]
RETURNS [tile: Tile];
Makes a 4-by-4 one-bit-per-pixel tile from the stipple bits.
TransferTile:
PROC [dest: PixelMap, tile: Tile, function: Function ← [null, null]];
Transfers from the tiled plane to dest.
PixelMapRep:
TYPE ~
RECORD [
ref: REF, pointer: LONG POINTER, words: LONG CARDINAL,
lgBitsPerPixel: [0..4], -- logarithm base two of bitsPerPixel
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. Must have rast*lines <= words. Clients should try to avoid dealing directly with this record.
];
END.