DIRECTORY Basics USING [bitsPerWord, RawWords], CountedVM USING [Handle], PrincOps USING [BitAddress, SrcFunc, DstFunc]; SampleMapOps: CEDAR DEFINITIONS ~ BEGIN SampleMap: TYPE ~ REF SampleMapRep; SampleMapRep: TYPE ~ RECORD [ sSize: NAT, -- number of scan lines fSize: NAT, -- number of samples per scan line bitsPerSample: [0..bitsPerWord], -- number of bits per sample base: PrincOps.BitAddress, -- starting bit address bitsPerLine: NAT, -- bits per scan line ref: REF -- for garbage collection ]; SubMap: TYPE ~ RECORD [sampleMap: SampleMap, start: CVEC _ [0,0], size: CVEC _ lastCVEC]; bitsPerWord: NAT ~ Basics.bitsPerWord; CVEC: TYPE ~ RECORD [s, f: CARDINAL]; zeroCVEC: CVEC ~ [0, 0]; lastCVEC: CVEC ~ [CARDINAL.LAST, CARDINAL.LAST]; Function: TYPE ~ RECORD [dstFunc: PrincOps.DstFunc, srcFunc: PrincOps.SrcFunc]; nullFunction: Function ~ [null, null]; MultipleReleaseOfScratch: ERROR; ComputeWords: PROC [sSize: CARDINAL, fSize: CARDINAL, bitsPerSample: [0..Basics.bitsPerWord]] RETURNS [LONG CARDINAL]; UnsafeCreate: UNSAFE PROC [sSize: CARDINAL, fSize: CARDINAL, bitsPerSample: [0..Basics.bitsPerWord], bitsPerLine: NAT, base: PrincOps.BitAddress, nWords: LONG CARDINAL, ref: REF, scratchDescriptor: SampleMap _ NIL] RETURNS [SampleMap]; Create: PROC [sSize: CARDINAL, fSize: CARDINAL, bitsPerSample: [0..Basics.bitsPerWord]] RETURNS [SampleMap]; FromVM: PROC [sSize: CARDINAL, fSize: CARDINAL, bitsPerSample: [0..Basics.bitsPerWord], vm: CountedVM.Handle] RETURNS [SampleMap]; FromSubMap: PROC [subMap: SubMap] RETURNS [SampleMap]; Copy: PROC [subMap: SubMap] RETURNS [SampleMap]; ObtainScratch: PROC [sSize: CARDINAL, fSize: CARDINAL, bitsPerSample: [0..Basics.bitsPerWord]] RETURNS [SampleMap]; ReleaseScratch: PROC [sampleMap: SampleMap]; DoWithScratch: PROC [sSize: CARDINAL, fSize: CARDINAL, bitsPerSample: [0..Basics.bitsPerWord], action: PROC[SampleMap]]; Size: PROC [sampleMap: SampleMap] RETURNS [CVEC]; Clear: PROC [sampleMap: SampleMap]; GetSample: PROC [sampleMap: SampleMap, index: CVEC] RETURNS [CARDINAL]; PutSample: PROC [sampleMap: SampleMap, index: CVEC, value: CARDINAL, function: Function _ nullFunction]; Transfer: PROC [dest: SampleMap, destStart: CVEC _ zeroCVEC, source: SubMap, function: Function _ nullFunction]; Move: PROC [sampleMap: SampleMap, destStart: CVEC _ zeroCVEC, sourceStart: CVEC _ zeroCVEC, size: CVEC _ lastCVEC, function: Function _ nullFunction]; Fill: PROC [dest: SubMap, value: CARDINAL, function: Function _ nullFunction]; TileFromStipple: PROC [stipple: CARDINAL, bitsPerSample: [0..Basics.bitsPerWord] _ 1, sample0: CARDINAL _ 0, sample1: CARDINAL _ 1, obtainScratch: BOOL _ FALSE] RETURNS [SampleMap]; TileBox: PROC [dest: SampleMap, start: CVEC, size: CVEC, source: SampleMap, s0, f0: INTEGER, phase: NAT, function: Function _ nullFunction]; BoxProc: TYPE ~ PROC [smin, fmin, smax, fmax: CARDINAL]; TileBoxes: PROC [dest: SampleMap, boxes: PROC[BoxProc], source: SampleMap, s0, f0: INTEGER, phase: NAT, function: Function _ nullFunction]; Trim: PROC [subMap: SubMap, background: CARDINAL _ 0] RETURNS [SubMap]; Equal: PROC [a, b: SubMap] RETURNS [BOOL]; IsAll: PROC [subMap: SubMap, value: CARDINAL _ 0] RETURNS [BOOL]; Buffer: TYPE ~ REF BufferRep; BufferRep: TYPE ~ RECORD [length: NAT, samples: SEQUENCE maxLength: NAT OF CARDINAL]; Apply: PROC [dest, source: SampleMap, op: PROC [a, b: CARDINAL] RETURNS [CARDINAL]]; maxCount: NAT ~ LAST[NAT]; Get: PROC [buffer: Buffer, start: NAT _ 0, count: NAT _ maxCount, sampleMap: SampleMap, s, f: NAT _ 0, ds: NAT _ 0, df: NAT _ 1]; Put: PROC [buffer: Buffer, start: NAT _ 0, count: NAT _ maxCount, sampleMap: SampleMap, s, f: NAT _ 0, ds: NAT _ 0, df: NAT _ 1, function: Function _ nullFunction]; Flip: PROC [buffer: Buffer]; ObtainBuffer: PROC [length: NAT] RETURNS [Buffer]; ReleaseBuffer: PROC [buffer: Buffer]; GetPointer: PROC [buffer: Buffer, start: NAT, count: NAT] RETURNS [LONG POINTER TO Basics.RawWords]; END. ZSampleMapOps.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Michael Plass, December 4, 1985 11:31:32 am PST Provides a safe set of operations on two-dimensional arrays of small unsigned integers. This interface provides most of the functionality of BitBlt, without the attendant risk of smashing the world. To avoid confusion no matter how the represented image is oriented, 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. Some of the operations in this interface are documented by code fragments; note that in case of unsuccessful completion (due to bounds fault, for instance), the set of samples moved by the implementation may differ from that implied by the documentation. SampleMap: TYPE ~ Basics.SampleMap; It is unsafe for clients to alter these fields. [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. Creation procedures Computes the number of words of storage needed, assuming each scanline is padded to a word boundary. It is the client's responsibility to ensure that an appropriate block of storage is provided; the parameters will be checked for internal consistency. nWords is the size of the block in words, used for a consistency check. scratchDescriptor may be provided to avoid the need to allocate a new descriptor. Allocates counted storage or counted VM, as needed. Uses a client-supplied counted VM handle. Bounds check if unsufficent storage is supplied. Pads each scanline to a word boundary. Creates a new descriptor on the same sample storage. Allocates a new SampleMap and copies the samples. Operations A fast way to clear a sampleMap to zero. Clears the padding bits on both ends of the scan lines as well as the actual samples. Does not clear words that are entirely unused. Stores modified value into the SampleMap at indexed location, dropping extra high-order bits. Bounds fault if index is out of range. size _ MIN[source.size, Size[dest]-destStart, Size[source.sampleMap]-source.start]; FOR s: CARDINAL IN [0..size.s) DO FOR f: NAT IN [0..size.f) DO sample: CARDINAL ~ GetSample[source.sampleMap, [source.start.s+s, source.start.f+f]]; PutSample[dest, [destStart.s+s, destStart.f+f], sample, function]; ENDLOOP; ENDLOOP; Transfers a rectangular region of the sampleMap, ordering it so ripple does not occur even if the rectangles overlap. Makes a tile from a 4-by-4 pattern. If obtainScratch, gets space with ObtainScratch and client should call ReleaseScratch. Tiles the rectangle designated by (start, size) with the tile designated by (source, s0, f0, phase). start, size, s0, and f0 all work in the dest coordinate system. The DIV and MOD functions in the following take the sign of the remainder equal to the sign of the divisor, rather than of the dividend as is usual. FOR s: NAT IN [start.s..start.s+size.s) DO FOR f: NAT IN [start.f..start.f+size.f) DO sSource: CARDINAL ~ (s-s0) MOD source.sSize; fSource: CARDINAL ~ (f-f0 - ((s-s0)/source.sSize)*phase) MOD source.fSize; sample: CARDINAL ~ GetSample[source, [sSource, fSource]]; PutSample[dest, [s, f], sample, function]; ENDLOOP; ENDLOOP; Effectively calls TileBox for each of the boxes. For removing a constant border. All of the pixels in subMap not in the result will be equal to background. Client must keep track of the origin. Predicates Tests for equality. Tests for a constant. Sample Buffers When performing operations on many contiguous samples, it is usually a good idea to unpack them into a one-word-per-sample buffer, work on them, and pack them up again into the output. This works well because whole-word access is typically much faster than partial word access (although byte access is not too bad). The following operations will help to do this kind of processing. This is here primarily as an example of how to use the other procedures in this section; look at the implementation. The semantics are: FOR s: NAT IN [0..MIN[dest.sSize, source.sSize]) DO FOR f: NAT IN [0..MIN[dest.fSize, source.fSize]) DO sample: CARDINAL ~ op[GetSample[dest, [s, f]], GetSample[source, [s, f]]]; PutSample[dest, [s, f], sample]; ENDLOOP; ENDLOOP; FOR j: NAT IN [0..MIN[count, NAT[buffer.length-start]]) DO buffer[start+j] _ GetSample[sampleMap, [s+j*ds, f+j*df]]; ENDLOOP; FOR j: NAT IN [0..MIN[count, NAT[buffer.length-start]]) DO PutSample[sampleMap, [s+j*ds, f+j*df], buffer[start+j], function]; ENDLOOP; Reverses the order of the samples in the buffer. Useful for changing scan order. FOR j: NAT IN [0..buffer.length/2) DO t: CARDINAL _ buffer[j]; buffer[j] _ buffer[buffer.length-1-j]; buffer[buffer.length-1-j] _ t; ENDLOOP; Resulting buffer has buffer.length = length and buffer.maxLength >= length. Returns a long pointer to buffer[start], after making sure start and start+count do not exceed buffer.maxLength ÊƘ™Icodešœ Ïmœ1™