DIRECTORY Basics USING [bitsPerWord, RawWords], CountedVM USING [Handle], PrincOps USING [BitAddress, SrcFunc, DstFunc], Scaled USING [Value], SF USING [Box, BoxAction, BoxGenerator, maxVec, minVec, Vec, zeroVec], Terminal USING [FrameBuffer]; IISample: CEDAR DEFINITIONS ~ BEGIN Vec: TYPE ~ SF.Vec; minVec: Vec ~ SF.minVec; zeroVec: Vec ~ SF.zeroVec; maxVec: Vec ~ SF.maxVec; Box: TYPE ~ SF.Box; maxBox: Box ~ [min: minVec, max: maxVec]; BoxAction: TYPE ~ SF.BoxAction; BoxGenerator: TYPE ~ SF.BoxGenerator; maxCount: NAT ~ NAT.LAST; MultipleReleaseOfScratch: ERROR; Sample: TYPE ~ WORD; maxSample: Sample ~ Sample.LAST; RawSamples: TYPE ~ Basics.RawWords; maxBitsPerSample: NAT ~ Basics.bitsPerWord; BitsPerSample: TYPE ~ NAT[0..maxBitsPerSample]; SampleBuffer: TYPE ~ REF SampleBufferRep; SampleBufferRep: TYPE ~ RECORD [ length: NAT, samples: SEQUENCE maxLength: NAT OF Sample ]; NewSamples: PROC [length: NAT, scratch: SampleBuffer _ NIL] RETURNS [SampleBuffer]; ObtainScratchSamples: PROC [length: NAT] RETURNS [SampleBuffer]; ReleaseScratchSamples: PROC [buffer: SampleBuffer]; DoWithScratchSamples: PROC [length: NAT, action: PROC [SampleBuffer]]; PointerToSamples: PROC [buffer: SampleBuffer, start, count: NAT] RETURNS [LONG POINTER TO RawSamples]; FlipSamples: PROC [buffer: SampleBuffer, start: NAT _ 0, count: NAT _ maxCount]; FillSamples: PROC [buffer: SampleBuffer, value: Sample, start: NAT _ 0, count: NAT _ maxCount]; CopySamples: PROC [dst, src: SampleBuffer, dstStart, srcStart: NAT _ 0, count: NAT _ maxCount]; ClearSamples: PROC [buffer: SampleBuffer, start: NAT _ 0, count: NAT _ maxCount]; SampleMap: TYPE ~ REF SampleMapRep; SampleMapRep: TYPE ~ PRIVATE RECORD [ box: Box, -- lower and upper bounds in each direction bitsPerSample: NAT, -- number of bits per sample bitsPerLine: NAT, -- bits per scan line base: PrincOps.BitAddress, -- starting bit address ref: REF -- for retaining the underlying storage ]; UnsafeNewSampleMap: UNSAFE PROC [box: Box, bitsPerSample: BitsPerSample, bitsPerLine: NAT, base: PrincOps.BitAddress, ref: REF, words: INT, scratchDescriptor: SampleMap _ NIL] RETURNS [SampleMap]; BitsForSamples: PROC [fSize: NAT, bitsPerSample: NAT] RETURNS [NAT]; WordsForLines: PROC [sSize: NAT, bitsPerLine: NAT] RETURNS [INT]; WordsForMap: PROC [size: Vec, bitsPerSample: BitsPerSample _ 1, bitsPerLine: NAT _ 0] RETURNS [INT]; NewSampleMap: PROC [box: Box, bitsPerSample: BitsPerSample _ 1, bitsPerLine: NAT _ 0] RETURNS [SampleMap]; MapFromVM: PROC [vm: CountedVM.Handle, box: Box, bitsPerSample: BitsPerSample _ 1, bitsPerLine: NAT _ 0 ] RETURNS [SampleMap]; MapFromFrameBuffer: PROC [frameBuffer: Terminal.FrameBuffer] RETURNS [SampleMap]; Copy: PROC [map: SampleMap, delta: Vec _ zeroVec, box: Box _ maxBox] RETURNS [SampleMap]; ObtainScratchMap: PROC [box: Box, bitsPerSample: BitsPerSample _ 1] RETURNS [SampleMap]; ReleaseScratchMap: PROC [map: SampleMap]; DoWithScratchMap: PROC [box: Box, bitsPerSample: BitsPerSample _ 1, action: PROC [SampleMap]]; ObtainUnsafeDescriptor: UNSAFE PROC [size: Vec, bitsPerSample: BitsPerSample, bitsPerLine: NAT, base: PrincOps.BitAddress, ref: REF, words: INT, rawMin, delta: Vec _ zeroVec] RETURNS [SampleMap]; ReIndex: PROC [map: SampleMap, delta: Vec _ zeroVec, box: Box _ maxBox] RETURNS [SampleMap]; Clip: PROC [map: SampleMap, box: Box _ maxBox] RETURNS [SampleMap]; Shift: PROC [map: SampleMap, delta: Vec _ zeroVec] RETURNS [SampleMap]; ZeroOrigin: PROC [map: SampleMap] RETURNS [SampleMap]; ReleaseDescriptor: UNSAFE PROC [map: SampleMap]; GetBox: PROC [map: SampleMap] RETURNS [Box] ~ INLINE {RETURN [map.box]}; GetSize: PROC [map: SampleMap] RETURNS [Vec] ~ INLINE {b: Box ~ map.box; RETURN [[s: b.max.s-b.min.s, f: b.max.f-b.min.f]]}; GetBitsPerSample: PROC [map: SampleMap] RETURNS [BitsPerSample] ~ INLINE {RETURN [map.bitsPerSample]}; GetBase: PROC [map: SampleMap] RETURNS [PrincOps.BitAddress] ~ INLINE {RETURN [map.base]}; Function: TYPE ~ RECORD [dstFunc: PrincOps.DstFunc, srcFunc: PrincOps.SrcFunc]; nullFunction: Function ~ [dstFunc: null, srcFunc: null]; Get: PROC [map: SampleMap, index: Vec] RETURNS [Sample]; Put: PROC [map: SampleMap, index: Vec, value: Sample, function: Function _ nullFunction]; GetSamples: PROC [map: SampleMap, initIndex: Vec _ zeroVec, delta: Vec _ [s: 0, f: 1], buffer: SampleBuffer, start: NAT _ 0, count: NAT _ maxCount]; GetTileSamples: PROC [tile: SampleMap, phase: NAT _ 0, initIndex: SF.Vec _ zeroVec, buffer: SampleBuffer]; Halftone: PROC [map: SampleMap, min: SF.Vec, sampleBuffer, thresholdBuffer: SampleBuffer, function: Function]; PutSamples: PROC [map: SampleMap, initIndex: Vec _ zeroVec, delta: Vec _ [s: 0, f: 1], buffer: SampleBuffer, start: NAT _ 0, count: NAT _ maxCount, function: Function _ nullFunction]; Clear: PROC [map: SampleMap]; BasicTransfer: PROC [dst: SampleMap, src: SampleMap, dstMin: Vec _ zeroVec, srcMin: Vec _ zeroVec, size: Vec, function: Function _ nullFunction]; Transfer: PROC [dst: SampleMap, src: SampleMap, delta: Vec _ zeroVec, function: Function _ nullFunction]; Move: PROC [map: SampleMap, dstMin: Vec _ zeroVec, srcMin: Vec _ zeroVec, size: Vec _ maxVec, function: Function _ nullFunction]; Fill: PROC [map: SampleMap, box: Box _ maxBox, value: Sample _ maxSample, function: Function _ nullFunction]; RawGenerator: TYPE ~ PROC [rawAction: RawAction]; RawAction: TYPE ~ PROC [box: Box, bitsPerLine: NAT, base: PrincOps.BitAddress]; RawTransfer: PROC [dst: SampleMap, rawGenerator: RawGenerator, function: Function _ nullFunction]; RawDescriptor: TYPE ~ RECORD [box: Box, bitsPerLine: NAT, basePointer: LONG POINTER]; rawArraySize: NAT ~ 32; RawArray: TYPE ~ ARRAY [0..rawArraySize) OF RawDescriptor; MultipleTransfer: PROC [dst: SampleMap, n: [0..rawArraySize], a: POINTER TO RawArray, function: Function _ nullFunction]; TileFromStipple: PROC [stipple: WORD, bitsPerSample: BitsPerSample _ 1, value0: Sample _ 0, value1: Sample _ maxSample, scratch: SampleMap _ NIL] RETURNS [SampleMap]; Tile: PROC [map: SampleMap, box: Box _ maxBox, tile: SampleMap, phase: NAT _ 0, function: Function _ nullFunction]; TileBoxes: PROC [map: SampleMap, boxes: BoxGenerator, tile: SampleMap, phase: NAT _ 0, function: Function _ nullFunction]; TransferBoxes: PROC [dst: SampleMap, src: SampleMap, delta: Vec _ zeroVec, boxes: BoxGenerator, function: Function _ nullFunction]; FillBoxes: PROC [map: SampleMap, boxes: BoxGenerator, value: Sample _ maxSample, function: Function _ nullFunction]; EdgeAction: TYPE ~ PROC [ which: [0..1], -- Which side this specifies sMin: INTEGER, -- First scan line touched sCount: NAT, -- Number of scan lines touched f0: Scaled.Value, -- Initial value of f, offset by 1/2 pixel df: Scaled.Value -- df/ds ]; RegionFill: PROC [dst: SampleMap, edgeGenerator: PROC [EdgeAction], value: Sample _ maxSample, function: Function _ nullFunction]; BoxesFromBitmap: PROC [map: SampleMap, boxAction: BoxAction]; Trim: PROC [map: SampleMap, box: Box _ maxBox, background: Sample _ 0] RETURNS [Box]; IsAll: PROC [map: SampleMap, box: Box _ maxBox, value: Sample _ 0] RETURNS [BOOL]; Equal: PROC [s1, s2: SampleMap] RETURNS [BOOL]; END. ฆIISample.mesa Copyright c 1985, 1986 by Xerox Corporation. All rights reserved. Michael Plass, November 21, 1986 10:03:54 am PST Doug Wyatt, March 7, 1986 2:41:21 pm PST Samples and SampleBuffers Reverses the order of the samples in the buffer. SampleMap creation -- It is UNSAFE to alter these fields. -- This type defines a two-dimensional array of samples. 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. The samples are indexed by s in the range [box.min.s..box.max.s) and f in the range [box.min.f..box.max.f). It is the client's responsibility to ensure that an appropriate block of storage is provided; the parameters will be checked for internal consistency; words declares the number of words of storage supplied, starting at base.word; scratchDescriptor may be provided to avoid the need to allocate a new descriptor. Returns number of bits for fSize samples, rounded up to a whole number of words. Returns number of words for sSize scan lines, starting at a word boundary. Returns number of words required for a new sample map of given size. If bitsPerLine=0, bitsPerLine _ BitsForSamples[size.f, bitsPerSample]. Allocates counted storage or counted VM, as needed. If bitsPerLine=0, bitsPerLine _ BitsForSamples[size.f, bitsPerSample]. Like NewSampleMap, but uses client-supplied VM. BoundsFault if insufficent storage is supplied. Creates a descriptor for the frame buffer. Allocates a new map and copies the samples. Get[map, p] = Get[result, SF.Add[p, delta]] result.box = SF.Intersect[box, SF.Displace[map.box, delta]] SampleMap descriptor operations The same caveats apply as for UnsafeNewSampleMap the descriptor is allocated from the scratch pool words declares the number of words of storage supplied, starting at base.word rawMin tells which sample in the raw storage is to be the first actual sample delta will become result.box.min Creates a new descriptor on all or part of the same sample storage the descriptor is allocated from the scratch pool Get[map, p] = Get[result, SF.Add[p, delta]] result.box = SF.Intersect[box, SF.Displace[map.box, delta]] ReIndex[map: map, box: box] ReIndex[map: map, delta: delta] ReIndex[map: temp, delta: SF.Neg[map.box.min]] Releases descriptor to a small pool. Unsafe to use the SampleMap any more after this is called. SampleMap selectors [null, null] dst _ src [or, null] dst _ BITOR[dst, src] [and, null] dst _ BITAND[dst, src] [and, complement] dst _ BITAND[dst, BITNOT[src]] [xor, null] dst _ BITXOR[dst, src] et cetera. SampleMap sample access Gets the indexed sample from the map. BoundsFault if NOT SF.In[index, map.box] Puts modified value into the map at indexed location, dropping extra high-order bits. BoundsFault if NOT SF.In[index, map.box] Gets a run of samples from the map into a buffer. The effect is: FOR j: NAT IN [0..MIN[buffer.length-start, count]) DO p: Vec ~ [s: j*delta.s, f: j*delta.f]; buffer[start+j] _ map.Get[initIndex.Add[p]]; ENDLOOP; except that any BoundsFault may be raised before any samples are moved. tempBox: Box ~ [min: initIndex, max: initIndex.Add[[1, buffer.length]]]; temp: SampleMap ~ NewSampleMap[box: tempBox, bitsPerSample: tile.bitsPerSample]; Tile[map: temp, tile: tile, phase: phase]; GetSamples[map: temp, initIndex: initIndex, buffer: buffer] FOR j: NAT IN [0..MIN[samples.length, thresholds.length]) DO bit: [0..1] ~ IF sampleBuffer[j] > thresholdBuffer[j] THEN 0 ELSE 1; Put[map, min.Add[[0, j]], bit, function]; ENDLOOP; Stores a run of samples from a buffer into the map. The effect is: FOR j: NAT IN [0..MIN[buffer.length-start, count]) DO p: Vec ~ [s: j*delta.s, f: j*delta.f]; map.Put[initIndex.Add[p], buffer[start+j], function]; ENDLOOP; except that any BoundsFault may be raised before any samples are moved. SampleMap block operations A fast way to clear a map 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. Transfers samples to dst from src. The effect is: FOR s: INTEGER IN [0..size.s) DO FOR f: INTEGER IN [0..size.f) DO p: Vec ~ [s: s, f: f]; value: Sample ~ Get[src, p.Add[srcMin]]; Put[dst, p.Add[dstMin], value, function]; ENDLOOP; ENDLOOP; except that if a bounds fault occurs, it occurs before any samples are moved. Transfers samples to dst from src. The effect is: box: Box ~ SF.Intersect[dst.box, SF.Displace[src.box, delta]]; BasicTransfer[dst: dst, src: src, dstMin: box.min, srcMin: SF.Sub[box.min, delta], size: SF.Size[box], function: function]; The effect is: BasicTransfer[dst: map, src: Copy[map], dstMin: dstMin, srcMin: srcMin, size: size, function: function]; (avoids ripple if the source and destination overlap) Fills a box with a constant sample value. The effect is: actualBox: Box ~ Intersect[map.box, box]; FOR s: INTEGER IN [actualBox.min.s..actualBox.max.s) DO FOR f: INTEGER IN [actualBox.min.f..actualBox.max.f) DO Put[map, [s, f], value, function]; ENDLOOP; ENDLOOP; SampleMap raw transfer operations Must have bits per sample = 1 in both source and dst. Tile operations Makes a tile from a 4-by-4 pattern. Tiles the box with the pattern designated by (tile, phase). The effect is: actualBox: Box ~ Intersect[map.box, box]; tileSize: Vec ~ Size[tile.box]; s0: INT ~ tile.box.min.s; f0: INT ~ tile.box.min.f; FOR s: INTEGER IN [actualBox.min.s..actualBox.max.s) DO FOR f: INTEGER IN [actualBox.min.f..actualBox.max.f) DO sTile: INT ~ s-s0; fTile: INT ~ f-(f0+phase*(sTile div tileSize.s)); value: Sample ~ tile.Get[[s0 + sTile mod tileSize.s, f0 + fTile mod tileSize.f]]; map.Put[[s, f], value, function]; ENDLOOP; ENDLOOP; For div and mod, the sign of the remainder is the sign of the divisor, not the dividend. Tiles each of the boxes. The effect is: tileBox: PROC [box: Box] ~ { true: [TRUE..TRUE] ~ SF.Inside[box, map.box] Tile[map, box, tile, phase, function] }; boxes[tileBox]; SampleMap area operations Transfers several boxes. The effect is: transferBox: PROC [box: Box] ~ { BasicTransfer[dst: dst, src: src, dstMin: box.min, srcMin: SF.Sub[box.min, delta], size: Size[box], function: function]; }; boxes[transferBox]; Note a bounds fault occurs if the BoxGenerator provides a box that is not inside the bounds of both dst and the displaced src, the assumption being that the client has already clipped the boxes. Fills several boxes. The effect is: fillBox: PROC [box: Box] ~ { true: [TRUE..TRUE] ~ SF.Inside[box, map.box]; Fill[map, box, value, function]; }; boxes[fillBox]; Fills a monotone region designated by the edges. The edgeGenerator must specify the edges in nondecreasing sMin order. Clips to the destination bounds. Generates boxes that cover all of the non-zero samples in the SampleMap, and none of the zeros. SampleMap scanning operations For removing a constant border. All of the samples inside Intersect[map.box, box] and outside the resulting box will be equal to background. Tests for a constant. Tests for equality. Equal if s1.box = s2.box and Get[s1, p] = Get[s2, p] for all p in the common box. Note bitsPerSample need not match. ส ฿˜codešœ ™ Kšœ ฯmœ7™BK™0K™(—K˜šฯk ˜ Kšœžœ˜%Kšœ žœ ˜Kšœ žœ ˜.Kšœžœ ˜Kšžœžœ>˜FKšœ žœ˜—K˜Kšะblœžœž ˜šœž˜K˜Kšœžœžœ˜Kšœžœ˜Kšœžœ ˜Kšœžœ˜Kšœžœžœ˜Kšœ)˜)Kšœ žœžœ ˜Kšœžœžœ˜%Kšœ žœžœžœ˜K˜šœžœ˜ K˜——head™Kšœžœžœ˜Kšœžœ˜ Kšœ žœ˜#Kšœžœ˜+Kšœžœžœ˜/K˜Kšœžœžœ˜)šœžœžœ˜ Kšœžœ˜ Kšœ žœ žœžœ˜*Kšœ˜K˜—K˜š ฯn œžœ žœžœžœ˜SK˜—š œžœ žœžœ˜@K™—š œžœ˜3K˜—š œžœ žœ žœ˜FK˜—š œžœ&žœžœžœžœžœ ˜gK˜—š  œžœžœ žœ ˜PK™0K˜—š  œžœ/žœ žœ ˜`K˜—š  œžœ.žœ žœ ˜_K˜—š  œžœžœ žœ ˜QK˜——™Kšœ žœžœ˜#šœžœžœžœ˜%K™)Kšœ ฯc+˜5Kšœžœก˜0Kšœ žœก˜'Kšœก˜2Kšœžœก'˜0Kšœ˜Kš œาฯbœขœ(ขœdขœ1ขœ)ขœ%™่K˜—K˜š œžœžœ8žœ"žœ žœ"žœžœ ˜ฦKšœท™ทK˜—K˜š  œžœ žœžœžœžœ˜DK™PK˜—š   œžœ žœžœžœžœ˜AK™JK˜—š   œžœ=žœžœžœ˜eK™DKšœG™GK™—K˜š  œžœ;žœžœ ˜jK™3KšœG™GK˜—š  œžœRžœžœ ˜Kšœ/™/Kšœ/™/K˜—š œžœ%žœ ˜QK™*K˜—K˜š œžœ;žœ ˜YKšœ+™+Kšœ+™+Kšœ žœžœ™;K˜—K˜š œžœ/žœ ˜YK˜—š œžœ˜)K˜—š œžœ7žœ˜_K˜——šœ™š œžœžœ9žœ"žœ žœ žœ ˜ฤšœ0™0Kšœ1™1KšœM™MKšœM™MKšœ ™ —K˜—š œžœ;žœ ˜\šœB™BKšœ1™1—Kšœ+™+Kšœ žœžœ™;K˜—š œžœ%žœ ˜CKšœ™K˜—š œžœ(žœ ˜GKšœ™K˜—š  œžœžœ ˜6Kšœžœ™.K˜—š œžœžœ˜0K™$Kšœ:™:K˜K˜——Lšœ™™š  œžœžœ žœžœ ˜HK˜—š  œžœžœ žœžœ-˜|K˜—š  œžœžœžœžœ˜fK˜—š  œžœžœžœžœ ˜ZK˜—K˜Kšœ žœžœ8˜Ošœ8˜8Kšœ™Kšœžœ ™!Kšœžœ ™#Kšœžœžœ™1Kšœžœ ™#K™ K™—K˜—šœ™š œžœžœ ˜8K™%Kšœžœžœ™(K˜—š œžœP˜YKšœU™UKšœžœžœ™(K˜—K˜š  œžœdžœ žœ ˜”™Aš žœžœžœžœž™5Kšœ&™&Kšœ,™,Kšžœ™—KšœG™G—K˜—š œžœžœžœ&˜jK•StartOfExpansionT[box: SF.Box, bitsPerSample: IISample.BitsPerSample _ 1, bitsPerLine: NAT _ 0]šœI™IKšœP™PKšœ*™*K–ฒ[self: IISample.SampleMap, initIndex: SF.Vec _ [s: 0, f: 0], delta: SF.Vec _ [s: 0, f: 1], samples: IISample.SampleBuffer, start: NAT _ 0, count: NAT _ 32767]šœ;™;K˜—š œžœžœG˜nš žœžœžœžœ%ž™Kšœ;žœžœ ™{—K˜—š œžœy˜ƒ™Kšœh™h—Kšœ5™5K˜—š œžœd˜n™9Kšœ)™)šžœžœžœ$ž™7šžœžœžœ$ž™7Kšœ"™"Kšžœ™—Kšžœ™——K˜——šœ!™!Kšœžœžœ˜1Kšœ žœžœžœ˜Oš  œžœQ˜bK˜—Kš œžœžœžœžœžœ˜UKšœžœ˜Kšœ žœžœžœ˜:š œžœ+žœžœ.˜yK™5K˜——š œ ™š  œžœ žœkžœžœ ˜จKšœ#™#K˜—š œžœ>žœ*˜ušœK™KKšœ)™)Kšœ™Kšœžœ™Kšœžœ™šžœžœžœ$ž™7šžœžœžœ$ž™7Kšœžœ™Kšœžœขœ™1Kšœ%ขœขœ™QKšœ!™!Kšžœ™—Kšžœ™—KšœขœขœI™X—K˜—š  œžœ?žœ*˜{šœ(™(šœ žœ™Kšœžœžœžœ™,Kšœ%™%Kšœ™—Kšœ™—K™——šœ™š  œžœq˜„™(šœ žœ™ Kšœ;žœ;™xKšœ™—Kšœ™—Kšœย™ยK˜—š  œžœf˜u™$šœ žœ™Kšœžœžœžœ™-Kšœ ™ Kšœ™—Kšœ™—K˜—šœ žœžœ˜Kšœก˜+Kšœžœก˜)Kšœžœก˜,Kšœก*˜