DIRECTORY Basics USING [BITAND, BITSHIFT, bitsPerWord, logBitsPerWord, LongMult], CountedVM USING [Allocate, Handle, Pointer, Words], ImagerPixelMap USING [DeviceRectangle, Function, Get16Bits, Get2Bits, Get4Bits, Get8Bits, GetBit, PixelMap, PixelMapRep, Tile], PrincOps USING [BBTableSpace, BBptr, BitAddress, wordsPerPage], PrincOpsUtils USING [AlignedBBTable, BITBLT, ZERO], SafeStorage USING [ReclaimCollectibleObjects], VM USING [PageNumberForAddress, PageNumber, SwapIn]; ImagerPixelMapImpl: CEDAR PROGRAM IMPORTS Basics, CountedVM, ImagerPixelMap, PrincOpsUtils, SafeStorage, VM EXPORTS ImagerPixelMap ~ BEGIN PixelMap: TYPE ~ ImagerPixelMap.PixelMap; Tile: TYPE ~ ImagerPixelMap.Tile; PixelMapRep: TYPE ~ ImagerPixelMap.PixelMapRep; DeviceRectangle: TYPE ~ ImagerPixelMap.DeviceRectangle; Function: TYPE ~ ImagerPixelMap.Function; bitsPerWord: NAT ~ Basics.bitsPerWord; lgBitsPerWord: NAT ~ Basics.logBitsPerWord; wordsPerPage: NAT ~ PrincOps.wordsPerPage; BITAND: PROC [a, b: CARDINAL] RETURNS[CARDINAL] ~ INLINE {RETURN[Basics.BITAND[a, b]]}; Shift: PROC [a: CARDINAL, b: INTEGER] RETURNS [CARDINAL] ~ INLINE {RETURN[Basics.BITSHIFT[a, b]]}; Intersect: PUBLIC PROC [a, b: DeviceRectangle] RETURNS [DeviceRectangle] ~ { sMin: INTEGER _ MAX[a.sMin, b.sMin]; fMin: INTEGER _ MAX[a.fMin, b.fMin]; sMax: INTEGER _ MIN[INT[a.sMin]+a.sSize, INT[b.sMin]+b.sSize]; fMax: INTEGER _ MIN[INT[a.fMin]+a.fSize, INT[b.fMin]+b.fSize]; IF sMax <= sMin OR fMax <= fMin THEN RETURN [[0, 0, 0, 0]] ELSE RETURN [[sMin, fMin, sMax-sMin, fMax-fMin]] }; Create: PUBLIC PROC [lgBitsPerPixel: [0..4], bounds: DeviceRectangle] RETURNS [pixelMap: PixelMap] ~ { bitsPerPixel: CARDINAL ~ Shift[1, lgBitsPerPixel]; bitsPerLine: NAT ~ Basics.LongMult[bounds.fSize, bitsPerPixel]; wordsPerLine: CARDINAL ~ (bitsPerLine+(bitsPerWord-1)) / bitsPerWord; words: LONG CARDINAL ~ Basics.LongMult[wordsPerLine, bounds.sSize]; pixelMap.refRep _ NewRefRep[words]; pixelMap.refRep.lgBitsPerPixel _ lgBitsPerPixel; pixelMap.refRep.rast _ wordsPerLine; pixelMap.refRep.lines _ bounds.sSize; pixelMap.sMin _ pixelMap.fMin _ 0; [pixelMap.sOrigin, pixelMap.fOrigin, pixelMap.sSize, pixelMap.fSize] _ bounds; }; CreateFrameBuffer: PUBLIC UNSAFE PROC [pointer: LONG POINTER, words: LONG CARDINAL, lgBitsPerPixel: [0..4], rast: CARDINAL, lines: CARDINAL, ref: REF _ NIL] RETURNS [pixelMap: PixelMap] ~ { bitsPerLine: NAT ~ Basics.LongMult[rast, bitsPerWord]; fSize: NAT ~ Shift[bitsPerLine, -lgBitsPerPixel]; wastedWords: NAT _ INT[words]-INT[rast]*INT[lines]; pixelMap.refRep _ NEW[PixelMapRep _ [ref, pointer, words, lgBitsPerPixel, rast, lines]]; pixelMap.sOrigin _ pixelMap.fOrigin _ pixelMap.sMin _ pixelMap.fMin _ 0; pixelMap.sSize _ lines; pixelMap.fSize _ fSize; }; Clear: PUBLIC PROC [pixelMap: PixelMap] ~ TRUSTED { pointer: LONG POINTER _ pixelMap.refRep.pointer; words: LONG CARDINAL _ MIN[pixelMap.refRep.words, Basics.LongMult[pixelMap.refRep.lines, pixelMap.refRep.rast]]; WHILE words > 32768 DO PrincOpsUtils.ZERO[pointer, 32768]; pointer _ pointer + 32768; words _ words - 32768; ENDLOOP; PrincOpsUtils.ZERO[pointer, words]; }; Reshape: PUBLIC PROC [refRep: REF PixelMapRep, lgBitsPerPixel: [0..4], bounds: DeviceRectangle] RETURNS [pixelMap: PixelMap] ~ { bitsPerPixel: CARDINAL ~ Shift[1, lgBitsPerPixel]; bitsPerLine: NAT ~ Basics.LongMult[bounds.fSize, bitsPerPixel]; wordsPerLine: CARDINAL ~ (bitsPerLine+(bitsPerWord-1)) / bitsPerWord; words: LONG CARDINAL ~ Basics.LongMult[wordsPerLine, bounds.sSize]; IF refRep = NIL THEN refRep _ NewRefRep[words] ELSE IF words > refRep.words THEN { refRep.pointer _ NIL; refRep.ref _ NIL; IF refRep.words > 1000 THEN SafeStorage.ReclaimCollectibleObjects[]; refRep _ NewRefRep[words]; }; refRep.lgBitsPerPixel _ lgBitsPerPixel; refRep.rast _ wordsPerLine; refRep.lines _ bounds.sSize; pixelMap _ [bounds.sMin, bounds.fMin, 0, 0, bounds.sSize, bounds.fSize, refRep]; }; Copy: PUBLIC PROC [p: PixelMap, scratch: REF PixelMapRep _ NIL] RETURNS [pixelMap: PixelMap] ~ { pixelMap _ Reshape[scratch, p.refRep.lgBitsPerPixel, Window[p]]; Clear[pixelMap]; Transfer[pixelMap, p, [null,null]]; }; ShiftMap: PUBLIC PROC [p: PixelMap, s, f: INTEGER] RETURNS [PixelMap] ~ { RETURN [[p.sOrigin + s, p.fOrigin + f, p.sMin, p.fMin, p.sSize, p.fSize, p.refRep]] }; ShiftWindow: PUBLIC PROC [p: PixelMap, s, f: INTEGER] RETURNS [PixelMap] ~ { RETURN [[p.sOrigin, p.fOrigin, p.sMin + s, p.fMin + f, p.sSize, p.fSize, p.refRep]] }; Clip: PUBLIC PROC [p: PixelMap, bounds: DeviceRectangle] RETURNS [PixelMap] ~ { bounds _ Intersect[Window[p], bounds]; RETURN [[p.sOrigin, p.fOrigin, bounds.sMin-p.sOrigin, bounds.fMin-p.fOrigin, bounds.sSize, bounds.fSize, p.refRep]] }; SetWindow: PUBLIC PROC [p: PixelMap, bounds: DeviceRectangle] RETURNS [PixelMap] ~ { RETURN [[p.sOrigin, p.fOrigin, bounds.sMin-p.sOrigin, bounds.fMin-p.fOrigin, bounds.sSize, bounds.fSize, p.refRep]] }; Window: PUBLIC PROC [p: PixelMap] RETURNS [DeviceRectangle] ~ { RETURN [[p.sOrigin + p.sMin, p.fOrigin + p.fMin, p.sSize, p.fSize]] }; BufferBounds: PUBLIC PROC [p: PixelMap] RETURNS [DeviceRectangle] ~ { RETURN [[p.sOrigin, p.fOrigin, p.refRep.lines, Shift[p.refRep.rast, lgBitsPerWord-p.refRep.lgBitsPerPixel]]] }; BoundedWindow: PUBLIC PROC [p: PixelMap] RETURNS [DeviceRectangle] ~ { sMin: INTEGER _ MAX[p.sOrigin + p.sMin, p.sOrigin]; fMin: INTEGER _ MAX[p.fOrigin + p.fMin, p.fOrigin]; sMax: INTEGER _ MIN[p.sOrigin + p.sMin + p.sSize, p.sOrigin + p.refRep.lines]; fMax: INTEGER _ MIN[p.fOrigin + p.fMin + p.fSize, p.fOrigin + Shift[p.refRep.rast, lgBitsPerWord-p.refRep.lgBitsPerPixel]]; RETURN [[sMin, fMin, MAX[sMax-sMin, 0], MAX[fMax-fMin, 0]]] }; GetPixel: PUBLIC PROC [source: PixelMap, s, f: INTEGER] RETURNS [CARDINAL] ~ { bounds: DeviceRectangle _ BoundedWindow[source]; sCheck: NAT _ bounds.sSize-1-NAT[s-bounds.sMin]; fCheck: NAT _ bounds.fSize-1-NAT[f-bounds.fMin]; SELECT source.refRep.lgBitsPerPixel FROM 0 => RETURN [source.GetBit[s, f]]; 1 => RETURN [source.Get2Bits[s, f]]; 2 => RETURN [source.Get4Bits[s, f]]; 3 => RETURN [source.Get8Bits[s, f]]; 4 => RETURN [source.Get16Bits[s, f]]; ENDCASE => ERROR; }; Equal: PUBLIC PROC [a, b: PixelMap] RETURNS [BOOLEAN] ~ { window: DeviceRectangle _ BoundedWindow[a]; IF window # BoundedWindow[b] THEN RETURN [FALSE]; IF a.refRep = b.refRep THEN RETURN [TRUE]; IF a.refRep.lgBitsPerPixel # b.refRep.lgBitsPerPixel THEN RETURN [FALSE]; SELECT a.refRep.lgBitsPerPixel FROM 0 => TRUSTED { aPtr: LONG POINTER TO PACKED ARRAY [0..0) OF [0..2) _ a.refRep.pointer + Basics.LongMult[(window.sMin - a.sOrigin), a.refRep.rast]; bPtr: LONG POINTER TO PACKED ARRAY [0..0) OF [0..2) _ b.refRep.pointer + Basics.LongMult[(window.sMin - b.sOrigin), b.refRep.rast]; FOR s: INTEGER IN [window.sMin..window.sMin+window.sSize) DO FOR f: INTEGER IN [window.fMin..window.fMin+window.fSize) DO IF aPtr^[f-a.fOrigin] # bPtr^[f-b.fOrigin] THEN RETURN [FALSE]; ENDLOOP; aPtr _ aPtr+a.refRep.rast; bPtr _ bPtr+b.refRep.rast; ENDLOOP; }; 1 => TRUSTED { aPtr: LONG POINTER TO PACKED ARRAY [0..0) OF [0..4) _ a.refRep.pointer + Basics.LongMult[(window.sMin - a.sOrigin), a.refRep.rast]; bPtr: LONG POINTER TO PACKED ARRAY [0..0) OF [0..4) _ b.refRep.pointer + Basics.LongMult[(window.sMin - b.sOrigin), b.refRep.rast]; FOR s: INTEGER IN [window.sMin..window.sMin+window.sSize) DO FOR f: INTEGER IN [window.fMin..window.fMin+window.fSize) DO IF aPtr^[f-a.fOrigin] # bPtr^[f-b.fOrigin] THEN RETURN [FALSE]; ENDLOOP; aPtr _ aPtr+a.refRep.rast; bPtr _ bPtr+b.refRep.rast; ENDLOOP; }; 2 => TRUSTED { aPtr: LONG POINTER TO PACKED ARRAY [0..0) OF [0..16) _ a.refRep.pointer + Basics.LongMult[(window.sMin - a.sOrigin), a.refRep.rast]; bPtr: LONG POINTER TO PACKED ARRAY [0..0) OF [0..16) _ b.refRep.pointer + Basics.LongMult[(window.sMin - b.sOrigin), b.refRep.rast]; FOR s: INTEGER IN [window.sMin..window.sMin+window.sSize) DO FOR f: INTEGER IN [window.fMin..window.fMin+window.fSize) DO IF aPtr^[f-a.fOrigin] # bPtr^[f-b.fOrigin] THEN RETURN [FALSE]; ENDLOOP; aPtr _ aPtr+a.refRep.rast; bPtr _ bPtr+b.refRep.rast; ENDLOOP; }; 3 => TRUSTED { aPtr: LONG POINTER TO PACKED ARRAY [0..0) OF [0..256) _ a.refRep.pointer + Basics.LongMult[(window.sMin - a.sOrigin), a.refRep.rast]; bPtr: LONG POINTER TO PACKED ARRAY [0..0) OF [0..256) _ b.refRep.pointer + Basics.LongMult[(window.sMin - b.sOrigin), b.refRep.rast]; FOR s: INTEGER IN [window.sMin..window.sMin+window.sSize) DO FOR f: INTEGER IN [window.fMin..window.fMin+window.fSize) DO IF aPtr^[f-a.fOrigin] # bPtr^[f-b.fOrigin] THEN RETURN [FALSE]; ENDLOOP; aPtr _ aPtr+a.refRep.rast; bPtr _ bPtr+b.refRep.rast; ENDLOOP; }; 4 => TRUSTED { aPtr: LONG POINTER TO PACKED ARRAY [0..0) OF CARDINAL _ a.refRep.pointer + Basics.LongMult[(window.sMin - a.sOrigin), a.refRep.rast]; bPtr: LONG POINTER TO PACKED ARRAY [0..0) OF CARDINAL _ b.refRep.pointer + Basics.LongMult[(window.sMin - b.sOrigin), b.refRep.rast]; FOR s: INTEGER IN [window.sMin..window.sMin+window.sSize) DO FOR f: INTEGER IN [window.fMin..window.fMin+window.fSize) DO IF aPtr^[f-a.fOrigin] # bPtr^[f-b.fOrigin] THEN RETURN [FALSE]; ENDLOOP; aPtr _ aPtr+a.refRep.rast; bPtr _ bPtr+b.refRep.rast; ENDLOOP; }; ENDCASE => ERROR; RETURN [TRUE]; }; IsAll: PUBLIC PROC [pixelMap: PixelMap, value: CARDINAL _ 0] RETURNS [BOOLEAN] ~ { window: DeviceRectangle _ BoundedWindow[pixelMap]; SELECT pixelMap.refRep.lgBitsPerPixel FROM 0 => TRUSTED { p: LONG POINTER TO PACKED ARRAY [0..0) OF [0..2) _ pixelMap.refRep.pointer + Basics.LongMult[(window.sMin - pixelMap.sOrigin), pixelMap.refRep.rast]; FOR s: INTEGER IN [window.sMin..window.sMin+window.sSize) DO FOR f: INTEGER IN [window.fMin..window.fMin+window.fSize) DO IF p^[f-pixelMap.fOrigin] # value THEN RETURN [FALSE]; ENDLOOP; p _ p+pixelMap.refRep.rast; ENDLOOP; }; 1 => TRUSTED { p: LONG POINTER TO PACKED ARRAY [0..0) OF [0..4) _ pixelMap.refRep.pointer + Basics.LongMult[(window.sMin - pixelMap.sOrigin), pixelMap.refRep.rast]; FOR s: INTEGER IN [window.sMin..window.sMin+window.sSize) DO FOR f: INTEGER IN [window.fMin..window.fMin+window.fSize) DO IF p^[f-pixelMap.fOrigin] # value THEN RETURN [FALSE]; ENDLOOP; p _ p+pixelMap.refRep.rast; ENDLOOP; }; 2 => TRUSTED { p: LONG POINTER TO PACKED ARRAY [0..0) OF [0..16) _ pixelMap.refRep.pointer + Basics.LongMult[(window.sMin - pixelMap.sOrigin), pixelMap.refRep.rast]; FOR s: INTEGER IN [window.sMin..window.sMin+window.sSize) DO FOR f: INTEGER IN [window.fMin..window.fMin+window.fSize) DO IF p^[f-pixelMap.fOrigin] # value THEN RETURN [FALSE]; ENDLOOP; p _ p+pixelMap.refRep.rast; ENDLOOP; }; 3 => TRUSTED { p: LONG POINTER TO PACKED ARRAY [0..0) OF [0..256) _ pixelMap.refRep.pointer + Basics.LongMult[(window.sMin - pixelMap.sOrigin), pixelMap.refRep.rast]; FOR s: INTEGER IN [window.sMin..window.sMin+window.sSize) DO FOR f: INTEGER IN [window.fMin..window.fMin+window.fSize) DO IF p^[f-pixelMap.fOrigin] # value THEN RETURN [FALSE]; ENDLOOP; p _ p+pixelMap.refRep.rast; ENDLOOP; }; 4 => TRUSTED { p: LONG POINTER TO PACKED ARRAY [0..0) OF CARDINAL _ pixelMap.refRep.pointer + Basics.LongMult[(window.sMin - pixelMap.sOrigin), pixelMap.refRep.rast]; FOR s: INTEGER IN [window.sMin..window.sMin+window.sSize) DO FOR f: INTEGER IN [window.fMin..window.fMin+window.fSize) DO IF p^[f-pixelMap.fOrigin] # value THEN RETURN [FALSE]; ENDLOOP; p _ p+pixelMap.refRep.rast; ENDLOOP; }; ENDCASE => ERROR; RETURN [TRUE]; }; Trim: PUBLIC PROC [pixelMap: PixelMap, background: CARDINAL _ 0] RETURNS [PixelMap] ~ { temp: PixelMap _ pixelMap; WHILE pixelMap.sSize > 0 DO temp.sSize _ 1; temp.sMin _ pixelMap.sMin+pixelMap.sSize-1; IF IsAll[temp, background] THEN {pixelMap.sSize _ pixelMap.sSize - 1} ELSE EXIT; ENDLOOP; WHILE pixelMap.sSize > 0 DO temp.sSize _ 1; temp.sMin _ pixelMap.sMin; IF IsAll[temp, background] THEN {pixelMap.sSize _ pixelMap.sSize - 1; pixelMap.sMin _ pixelMap.sMin + 1} ELSE EXIT; ENDLOOP; IF pixelMap.sSize = 0 THEN pixelMap.fSize _ 0; temp _ pixelMap; WHILE pixelMap.fSize > 0 DO temp.fSize _ 1; temp.fMin _ pixelMap.fMin+pixelMap.fSize-1; IF IsAll[temp, background] THEN {pixelMap.fSize _ pixelMap.fSize - 1} ELSE EXIT; ENDLOOP; WHILE pixelMap.fSize > 0 DO temp.fSize _ 1; temp.fMin _ pixelMap.fMin; IF IsAll[temp, background] THEN {pixelMap.fSize _ pixelMap.fSize - 1; pixelMap.fMin _ pixelMap.fMin + 1} ELSE EXIT; ENDLOOP; IF pixelMap.fSize = 0 THEN pixelMap.sSize _ 0; RETURN [pixelMap] }; BitAddr: UNSAFE PROC [lineStart: LONG POINTER, pixel: CARDINAL, lgBitsPerPixel: INTEGER] RETURNS [PrincOps.BitAddress] ~ UNCHECKED { RETURN [[ word: lineStart + Shift[pixel, lgBitsPerPixel-lgBitsPerWord], bit: Basics.BITAND[Shift[pixel, lgBitsPerPixel], bitsPerWord-1] ]] }; replicator: ARRAY [0..4] OF CARDINAL ~ [0FFFFH, 05555H, 01111H, 00101H, 00001H]; Fill: PUBLIC PROC [dest: PixelMap, area: DeviceRectangle, value: CARDINAL, function: Function] ~ TRUSTED { lgBitsPerPixel: INTEGER ~ dest.refRep.lgBitsPerPixel; rast: CARDINAL ~ dest.refRep.rast; sMin: INTEGER ~ MAX[dest.sMin, 0, area.sMin-dest.sOrigin]; sMax: INTEGER ~ MIN[dest.sMin+dest.sSize, dest.refRep.lines, area.sMin+area.sSize-dest.sOrigin]; fMin: INTEGER ~ MAX[dest.fMin, 0, area.fMin-dest.fOrigin]; fMax: INTEGER ~ MIN[dest.fMin+dest.fSize, Shift[rast, lgBitsPerWord-lgBitsPerPixel], area.fMin+area.fSize-dest.fOrigin]; replicatedPixel: CARDINAL _ Basics.BITAND[value, Shift[1, Shift[1, lgBitsPerPixel]]-1] * replicator[lgBitsPerPixel]; bbTableSpace: PrincOps.BBTableSpace; bb: PrincOps.BBptr _ PrincOpsUtils.AlignedBBTable[@bbTableSpace]; IF sMin 32 AND sMax-sMin > 8 THEN { firstPage: VM.PageNumber ~ VM.PageNumberForAddress[source.refRep.pointer + Basics.LongMult[sStartSource, source.refRep.rast]]; lastPage: VM.PageNumber ~ VM.PageNumberForAddress[source.refRep.pointer + Basics.LongMult[sStartSource+sMax-sMin, source.refRep.rast] - 1]; VM.SwapIn[[page: firstPage, count: lastPage-firstPage+1]]; }; IF sMinfMinDest AND (fMinDest+fSize)>fMinSource AND (sStartSource+sSize)>sStartDest AND (sStartDest+sSize)>sStartSource THEN { bb.flags.disjoint _ FALSE; -- the rectangles overlap IF sStartDest=sStartSource THEN bb.flags.disjointItems _ FALSE; -- so do the items IF sStartDest>sStartSource OR (sStartDest=sStartSource AND fMinDest>fMinSource) THEN { -- reverse direction bb.flags.direction _ backward; bb.srcDesc.srcBpl _ bb.dstBpl _ -bb.dstBpl; sStartSource _ sStartSource + (sSize-1); sStartDest _ sStartDest + (sSize-1); }; }; }; bb.dst _ BitAddr[dest.refRep.pointer + Basics.LongMult[sStartDest, dest.refRep.rast], fMinDest, lgBitsPerPixel]; bb.src _ BitAddr[source.refRep.pointer + Basics.LongMult[sStartSource, source.refRep.rast], fMinSource, lgBitsPerPixel]; PrincOpsUtils.BITBLT[bb]; }; }; IsPowerOfTwo: PROC [c: CARDINAL] RETURNS [BOOLEAN] ~ INLINE { RETURN [BITAND[c, c-1] = 0] }; largeBitSize: INT _ 5000; CreateTile: PUBLIC PROC [pixelMap: PixelMap, phase: INTEGER _ 0, fSizeHint: NAT _ 100, scratch: REF PixelMapRep _ NIL] RETURNS [tile: Tile] ~ { lgBitsPerPixel: NAT _ pixelMap.refRep.lgBitsPerPixel; bitWidth: CARDINAL _ Shift[pixelMap.fSize, lgBitsPerPixel]; IF bitWidth <= 16 AND IsPowerOfTwo[bitWidth] AND pixelMap.sSize <= 16 AND phase = 0 THEN { small: PixelMap _ Reshape[scratch, lgBitsPerPixel, [pixelMap.sOrigin+pixelMap.sMin, pixelMap.fOrigin+pixelMap.fMin, pixelMap.sSize, Shift[16, -lgBitsPerPixel]]]; FOR fShift: NAT _ 0, fShift+pixelMap.fSize UNTIL fShift>=small.fSize DO Transfer[small, ShiftMap[pixelMap, 0, fShift], [null, null]]; ENDLOOP; tile _ [small.sOrigin, small.fOrigin, small.sSize, small.fSize, 0, small.refRep]; } ELSE { fSize: NAT _ (fSizeHint+pixelMap.fSize-1)/pixelMap.fSize*pixelMap.fSize; bitsPerLine: NAT _ Shift[fSize, lgBitsPerPixel]; sSize: NAT _ MAX[(((largeBitSize+bitsPerLine-1)/bitsPerLine)/pixelMap.sSize)*pixelMap.sSize, pixelMap.sSize]; large: PixelMap _ Reshape[scratch, lgBitsPerPixel, [pixelMap.sOrigin+pixelMap.sMin, pixelMap.fOrigin+pixelMap.fMin, sSize, fSize]]; finalPhase: CARDINAL; WHILE phase<0 DO phase _ phase + pixelMap.fSize ENDLOOP; phase _ phase MOD pixelMap.fSize; finalPhase _ (phase * (sSize/pixelMap.sSize)) MOD pixelMap.fSize; large.sSize _ pixelMap.sSize; large.fSize _ pixelMap.fSize; Transfer[large, pixelMap, [null, null]]; WHILE large.fSize pixelMap.fSize DO phase _ phase - pixelMap.fSize ENDLOOP; ENDLOOP; tile _ [large.sOrigin, large.fOrigin, sSize, fSize, finalPhase, large.refRep]; }; }; TileFromStipple: PUBLIC PROC [stipple: CARDINAL, scratch: REF PixelMapRep] RETURNS [tile: Tile] ~ TRUSTED { small: PixelMap _ Reshape[scratch, 0, [0, 0, 4, 16]]; p: LONG POINTER TO CARDINAL _ small.refRep.pointer+4*SIZE[CARDINAL]; IF small.refRep.words < 4*SIZE[CARDINAL] THEN ERROR; THROUGH [0..4) DO p _ p - SIZE[CARDINAL]; p^ _ 1111H * (stipple MOD 16); stipple _ stipple/16; ENDLOOP; tile _ [small.sOrigin, small.fOrigin, small.sSize, small.fSize, 0, small.refRep]; }; TileFromConstant: PUBLIC PROC [pixelValue: CARDINAL, lgBitsPerPixel: [0..4], scratch: REF PixelMapRep] RETURNS [tile: Tile] ~ TRUSTED { pixelsPerWord: NAT _ Shift[1, lgBitsPerWord-lgBitsPerPixel]; small: PixelMap _ Reshape[scratch, lgBitsPerPixel, [0, 0, 1, pixelsPerWord]]; p: LONG POINTER TO CARDINAL _ small.refRep.pointer; p^ _ replicator[lgBitsPerPixel] * Basics.BITAND[pixelValue, Shift[1, Shift[1, lgBitsPerPixel]]-1]; tile _ [small.sOrigin, small.fOrigin, small.sSize, small.fSize, 0, small.refRep]; }; TransferTile: PUBLIC PROC [dest: PixelMap, tile: Tile, function: Function _ [null, null]] ~ TRUSTED { lgBitsPerPixel: NAT ~ tile.refRep.lgBitsPerPixel; bitWidth: CARDINAL ~ Shift[tile.fSize, lgBitsPerPixel]; IF dest.refRep.lgBitsPerPixel # lgBitsPerPixel THEN ERROR; IF bitWidth = bitsPerWord AND tile.refRep.rast = 1 AND tile.sSize <= 16 AND tile.phase = 0 THEN { startLine: NAT _ MAX[dest.sMin, 0]; endLine: INTEGER _ MIN[dest.sMin+dest.sSize, dest.refRep.lines]; startPixel: NAT _ MAX[dest.fMin, 0]; endPixel: INTEGER _ MIN[dest.fMin+dest.fSize, Shift[dest.refRep.rast, lgBitsPerWord-lgBitsPerPixel]]; IF endLine>startLine AND endPixel>startPixel THEN { startBit: NAT _ Shift[startPixel, lgBitsPerPixel]; bbTableSpace: PrincOps.BBTableSpace; bb: PrincOps.BBptr ~ PrincOpsUtils.AlignedBBTable[@bbTableSpace]; sOffset: INTEGER _ (dest.sOrigin+dest.sMin-tile.sOrigin) MOD tile.sSize; fOffset: INTEGER _ (dest.fOrigin+dest.fMin-tile.fOrigin) MOD tile.fSize; WHILE sOffset < 0 DO sOffset _ sOffset + tile.sSize ENDLOOP; WHILE fOffset < 0 DO fOffset _ fOffset + tile.fSize ENDLOOP; bb^ _ [ dst: [word: dest.refRep.pointer + Basics.LongMult[startLine, dest.refRep.rast] + startBit/bitsPerWord, bit: startBit MOD bitsPerWord], dstBpl: dest.refRep.rast*bitsPerWord, src: [word: tile.refRep.pointer+sOffset, bit: Shift[fOffset, lgBitsPerPixel]], srcDesc: [gray[[yOffset: sOffset, widthMinusOne: 0, heightMinusOne: tile.sSize-1]]], height: endLine-startLine, width: Shift[endPixel-startPixel, lgBitsPerPixel], flags: [direction: forward, disjoint: TRUE, disjointItems: TRUE, gray: TRUE, srcFunc: function.srcFunc, dstFunc: function.dstFunc] ]; PrincOpsUtils.BITBLT[bb]; }; } ELSE { sMin: INT _ dest.sOrigin+dest.sMin; fMin: INT _ dest.fOrigin+dest.fMin; source: PixelMap; sOrigin: INT _ tile.sOrigin; fOrigin: INT _ tile.fOrigin; WHILE sOrigin < sMin DO sOrigin _ sOrigin + tile.sSize; fOrigin _ fOrigin + tile.phase; ENDLOOP; WHILE sOrigin > sMin DO sOrigin _ sOrigin - tile.sSize; fOrigin _ fOrigin - tile.phase; ENDLOOP; WHILE fOrigin < fMin DO fOrigin _ fOrigin + tile.fSize ENDLOOP; WHILE fOrigin > fMin DO fOrigin _ fOrigin - tile.fSize ENDLOOP; source _ [sOrigin, fOrigin, 0, 0, tile.sSize, tile.fSize, tile.refRep]; WHILE source.sOrigin < sMin+dest.sSize DO source.fOrigin _ fOrigin; WHILE source.fOrigin < fMin+dest.fSize DO Transfer[dest, source, function]; source.fOrigin _ source.fOrigin + source.fSize; ENDLOOP; source.sOrigin _ source.sOrigin + source.sSize; fOrigin _ fOrigin + tile.phase; WHILE fOrigin > fMin DO fOrigin _ fOrigin - source.fSize ENDLOOP; ENDLOOP; }; }; Rotate: PUBLIC PROC [pixelMap: PixelMap, scratch: REF PixelMapRep _ NIL] RETURNS [PixelMap] ~ TRUSTED { lgBitsPerPixel: INTEGER _ pixelMap.refRep.lgBitsPerPixel; bitsPerPixel: INTEGER _ Shift[1, lgBitsPerPixel]; window: DeviceRectangle _ BoundedWindow[pixelMap]; newWindow: DeviceRectangle _ [window.fMin, -(window.sMin+window.sSize), window.fSize, window.sSize]; new: PixelMap _ Reshape[scratch, lgBitsPerPixel, newWindow]; extraPixels: NAT _ new.refRep.rast*bitsPerWord/bitsPerPixel - window.sSize; lineBuffer: REF WordSeqRep _ NEW[WordSeqRep[MAX[window.sSize+extraPixels, 1]]]; lineBufferPtr: LONG POINTER _ @(lineBuffer[0]); sourceFirstLine: LONG POINTER _ pixelMap.refRep.pointer + Basics.LongMult[window.sMin-pixelMap.sOrigin, pixelMap.refRep.rast]; destLine: LONG POINTER _ new.refRep.pointer; bbTableSpace: PrincOps.BBTableSpace; bb: PrincOps.BBptr ~ PrincOpsUtils.AlignedBBTable[@bbTableSpace]; IF bitsPerWord # 16 THEN ERROR; bb^ _ [ dst: [word: lineBufferPtr + extraPixels, bit: bitsPerWord-bitsPerPixel], dstBpl: bitsPerWord, srcDesc: [srcBpl[pixelMap.refRep.rast*bitsPerWord]], height: window.sSize, width: bitsPerPixel, flags: [direction: forward, disjoint: TRUE, disjointItems: TRUE, gray: FALSE, srcFunc: null, dstFunc: null] ]; FOR fSource: INTEGER IN [window.fMin-pixelMap.fOrigin .. window.fMin-pixelMap.fOrigin+pixelMap.fSize) DO fSourceBit: NAT _ Shift[fSource, lgBitsPerPixel]; bb.src _ [word: sourceFirstLine + fSourceBit/bitsPerWord, bit: fSourceBit MOD bitsPerWord]; PrincOpsUtils.BITBLT[bb]; SELECT lgBitsPerPixel FROM 0 => { pixelsPerWord: NAT ~ bitsPerWord/1; w: NAT ~ 2; p: LONG POINTER TO ARRAY [0..pixelsPerWord) OF CARDINAL _ lineBufferPtr; q: LONG POINTER TO WORD _ destLine + new.refRep.rast; THROUGH [0..new.refRep.rast) DO q _ q - 1; q^ _ ((((((((((((((p[15]*w+p[14])*w+p[13])*w+p[12])*w+p[11])*w+p[10])*w+p[9])*w+p[8])*w+p[7])*w+p[6])*w+p[5])*w+p[4])*w+p[3])*w+p[2])*w+p[1])*w+p[0]; p _ p + pixelsPerWord; ENDLOOP; }; 1 => { pixelsPerWord: NAT ~ bitsPerWord/2; w: NAT ~ 4; p: LONG POINTER TO ARRAY [0..pixelsPerWord) OF CARDINAL _ lineBufferPtr; q: LONG POINTER TO WORD _ destLine + new.refRep.rast; THROUGH [0..new.refRep.rast) DO q _ q - 1; q^ _ ((((((p[7]*w+p[6])*w+p[5])*w+p[4])*w+p[3])*w+p[2])*w+p[1])*w+p[0]; p _ p + pixelsPerWord; ENDLOOP; }; 2 => { pixelsPerWord: NAT ~ bitsPerWord/4; w: NAT ~ 16; p: LONG POINTER TO ARRAY [0..pixelsPerWord) OF CARDINAL _ lineBufferPtr; q: LONG POINTER TO WORD _ destLine + new.refRep.rast; THROUGH [0..new.refRep.rast) DO q _ q - 1; q^ _ ((p[3]*w+p[2])*w+p[1])*w+p[0]; p _ p + pixelsPerWord; ENDLOOP; }; 3 => { pixelsPerWord: NAT ~ bitsPerWord/8; w: NAT ~ 256; p: LONG POINTER TO ARRAY [0..pixelsPerWord) OF CARDINAL _ lineBufferPtr; q: LONG POINTER TO WORD _ destLine + new.refRep.rast; THROUGH [0..new.refRep.rast) DO q _ q - 1; q^ _ p[1]*w+p[0]; p _ p + pixelsPerWord; ENDLOOP; }; 4 => { pixelsPerWord: NAT ~ bitsPerWord/16; p: LONG POINTER TO ARRAY [0..pixelsPerWord) OF CARDINAL _ lineBufferPtr; q: LONG POINTER TO WORD _ destLine + new.refRep.rast; THROUGH [0..new.refRep.rast) DO q _ q - 1; q^ _ p[0]; p _ p + pixelsPerWord; ENDLOOP; }; ENDCASE => ERROR; destLine _ destLine + new.refRep.rast; ENDLOOP; RETURN [new] }; Reflect: PUBLIC PROC [pixelMap: PixelMap, scratch: REF PixelMapRep _ NIL] RETURNS [PixelMap] ~ { window: DeviceRectangle _ BoundedWindow[pixelMap]; newWindow: DeviceRectangle _ [-window.sMin-window.sSize, window.fMin, window.sSize, window.fSize]; new: PixelMap _ Reshape[scratch, pixelMap.refRep.lgBitsPerPixel, newWindow]; FOR s: INTEGER IN [0..window.sSize) DO line: PixelMap _ Clip[ShiftMap[pixelMap, -window.sMin-s, 0], [0, window.fMin, 1, window.fSize]]; Transfer[new, ShiftMap[line, newWindow.sMin+newWindow.sSize-1-s, 0], [null, null]]; ENDLOOP; RETURN [new] }; WordSeqRep: TYPE ~ RECORD [SEQUENCE length: NAT OF WORD]; NewRefRep: PROC [words: LONG CARDINAL] RETURNS [refRep: REF PixelMapRep] ~ { ENABLE UNWIND => NULL; words _ MAX[words, 1]; refRep _ NEW[PixelMapRep]; IF words < 2000 THEN { wordSeq: REF WordSeqRep _ NEW[WordSeqRep[words]]; refRep.ref _ wordSeq; TRUSTED {refRep.pointer _ @wordSeq[0]}; refRep.words _ words; } ELSE TRUSTED { countedVM: CountedVM.Handle _ CountedVM.Allocate[words]; refRep.ref _ countedVM; refRep.pointer _ CountedVM.Pointer[countedVM]; refRep.words _ CountedVM.Words[countedVM]; }; }; END. VImagerPixelMapImpl.mesa Copyright c 1984, Xerox Corporation. All rights reserved. Michael Plass, January 19, 1984 9:12 am Doug Wyatt, August 15, 1984 7:06:16 pm PDT -- Some inlines for basic bit-hacking operations. Will raise a bounds fault if too many bits per line. Bounds check if `words' is too small or much too big. Will raise a bounds fault if too many bits per line. The following bounding box is calculated in terms of the destination buffer. more than a page, so a SwapIn is worthwhile dest is most likely to be a frame buffer, so don't worry about swapping it in. Space Managment Κg˜šœ™Jšœ Οmœ/™:J™'J™*—J˜šΟk ˜ Jšœžœžœžœ)˜GJšœ žœ$˜3Jšœžœk˜Jšœ žœ1˜?Jšœžœžœžœ˜3Jšœ žœ˜.Jšžœžœ,˜4—J˜Jšœžœž˜!Jšžœ@ž˜IJšžœ˜šœž˜J˜—Jšœ žœ˜)Jšœžœ˜!Jšœ žœ˜/Jšœžœ"˜7Jšœ žœ˜)Jšœ žœ˜&Jšœžœ˜+šœžœ˜*J˜—šœ1™1š Πknœžœžœžœžœ˜/Jšœžœžœžœ ˜'—š Οnœžœžœžœžœžœ˜8Jšœžœžœžœ ˜)—J˜—š  œžœžœžœ˜LJšœžœžœ˜$Jšœžœžœ˜$Jš œžœžœžœžœ˜>Jš œžœžœžœžœ˜>Jšžœžœžœžœ˜:Jšžœžœ%˜0Jšœ˜J˜—š œžœžœ3žœ˜fJšœžœ˜2šœ žœ/˜?J™4—Jšœžœ/˜EJšœžœžœ/˜CJšœ#˜#Jšœ0˜0Jšœ$˜$Jšœ%˜%Jšœ"˜"JšœO˜OJšœ˜J˜—š œžœžœžœ žœžœ ž œ žœ žœžœžœžœ˜½Jšœ žœ&˜6Jšœžœ'˜1š œ žœžœžœžœ˜3Jšœ5™5—JšœžœC˜XJšœH˜HJšœ˜Jšœ˜Jšœ˜J˜—š œžœžœžœ˜3Jšœ žœžœ˜0JšœžœžœžœV˜pšžœž˜Jšœžœ˜#Jšœ˜Jšœ˜Jšžœ˜—Jšœžœ˜#Jšœ˜J˜—š  œžœžœ žœ?žœ˜€Jšœžœ˜2šœ žœ/˜?J™4—Jšœžœ/˜EJšœžœžœ/˜CJšžœ žœžœ˜.šžœžœžœ˜#Jšœžœ˜Jšœ žœ˜Jšžœžœ)˜DJšœ˜Jšœ˜—Jšœ'˜'Jšœ˜Jšœ˜JšœP˜PJšœ˜J˜—š  œžœžœžœžœžœ˜`Jšœ@˜@Jšœ˜Jšœ#˜#Jšœ˜—š  œžœžœžœžœ˜IJšžœM˜SJšœ˜J˜—š   œžœžœžœžœ˜LJšžœM˜SJšœ˜J˜—š œžœžœ(žœ˜OJšœ'˜'Jšžœm˜sJšœ˜—š  œžœžœ(žœ˜TJšžœm˜sJšœ˜J˜—š œžœžœžœ˜?Jšžœ=˜CJšœ˜J˜—š  œžœžœžœ˜EJšžœf˜lJšœ˜J˜—š  œžœžœžœ˜FJšœžœžœ ˜3Jšœžœžœ ˜3Jšœžœžœ;˜NJšœžœžœh˜{Jšžœžœžœ˜;Jšœ˜J˜—š  œžœžœžœžœžœ˜NJšœ0˜0Jšœžœžœ˜0Jšœžœžœ˜0šžœž˜(Jšœžœ˜"Jšœžœ˜$Jšœžœ˜$Jšœžœ˜$Jšœžœ˜%Jšžœžœ˜—Jšœ˜J˜—š  œžœžœžœžœ˜9Jšœ+˜+Jšžœžœžœžœ˜1Jšžœžœžœžœ˜*Jšžœ3žœžœžœ˜Išžœž˜#šœžœ˜Jš œžœžœžœžœžœžœW˜ƒJš œžœžœžœžœžœžœW˜ƒšžœžœžœ)ž˜<šžœžœžœ)ž˜˜HJšœ žœ ˜0Jšœžœžœ]˜mJšœƒ˜ƒJšœ žœ˜Jšžœ žœ žœ˜8Jšœžœ˜!Jšœ.žœ˜AJšœ˜Jšœ˜Jšœ(˜(šžœž˜Jšœ žœ˜Jšœžœ˜&Jšœ=˜=Jšžœ˜—šžœž˜Jšœ žœ˜Jšœžœ˜&JšœA˜AšœH˜HJšœ!˜!Jšœ)˜)J˜—Jšœ˜Jšžœžœ žœ˜GJšžœ˜—JšœN˜NJšœ˜—Jšœ˜J˜—š œžœžœ žœ žœžœžœ˜kJšœ5˜5Jš œžœžœžœžœžœžœ˜DJš žœžœžœžœžœ˜4šžœž˜Jšœžœžœ˜Jšœžœ˜Jšœ˜Jšžœ˜—JšœQ˜QJšœ˜J˜—š œžœžœžœ#žœžœžœ˜‡Jšœžœ*˜