DIRECTORY Basics USING [BITAND, BITSHIFT, bitsPerWord, BoundsCheck, CARD, DoubleShiftRight, logBitsPerWord, LongDivMod, LongMult, LongNumber, NonNegative, RawWords, ShortNumber], CountedVM USING [Handle, SimpleAllocate], FunctionCache USING [Cache, CacheInfo, GetInfo, GlobalCache, SetLimits], IISample USING [BitsPerSample, EdgeAction, Function, maxBox, maxCount, maxSample, maxVec, nullFunction, RawAction, RawArray, rawArraySize, RawDescriptor, RawGenerator, RawSamples, Sample, SampleBuffer, SampleBufferRep, SampleMap, SampleMapRep, zeroVec], PrincOps USING [BBptr, BBTableSpace, BitAddress, BitBltFlags, BitBltTable], PrincOpsUtils USING [AlignedBBTable, BITBLT, LongCopy, LongZero], Scaled USING [Value, PLUS, zero], SF USING [Add, Box, BoxAction, BoxGenerator, Displace, Empty, Intersect, Neg, Nonempty, Size, SizeF, SizeS, Sub, Vec], Terminal USING [FrameBuffer], VM USING [CantAllocate, wordsPerPage]; IISampleImpl: CEDAR MONITOR IMPORTS Basics, CountedVM, FunctionCache, PrincOpsUtils, Scaled, SF, VM EXPORTS IISample ~ BEGIN OPEN IISample; Box: TYPE ~ SF.Box; BoxAction: TYPE ~ SF.BoxAction; BoxGenerator: TYPE ~ SF.BoxGenerator; Vec: TYPE ~ SF.Vec; MultipleReleaseOfScratch: PUBLIC ERROR ~ CODE; NewSamples: PUBLIC PROC [length: NAT, scratch: SampleBuffer _ NIL] RETURNS [SampleBuffer] ~ { new: SampleBuffer _ scratch; IF new=NIL OR new.maxLength= length THEN { scratchSampleBuffers[i] _ NIL; buf.length _ length; RETURN [buf]; }; ENDLOOP; RETURN [NEW[SampleBufferRep[length] _ [length: length, samples:]]] }; ReleaseScratchSamples: PUBLIC ENTRY PROC [buffer: SampleBuffer] ~ { slot: NAT _ 0; buffer.length _ 0; FOR i: NAT IN [0..nScratchSampleBuffers) DO t: SampleBuffer _ scratchSampleBuffers[i]; IF t = NIL THEN slot _ i ELSE IF buffer = t THEN RETURN WITH ERROR MultipleReleaseOfScratch; ENDLOOP; scratchSampleBuffers[slot] _ buffer; }; DoWithScratchSamples: PUBLIC PROC [length: NAT, action: PROC [SampleBuffer]] ~ { scratch: SampleBuffer ~ ObtainScratchSamples[length]; action[scratch ! UNWIND => ReleaseScratchSamples[scratch]]; ReleaseScratchSamples[scratch]; }; InlinePointerToSamples: PROC [buffer: SampleBuffer, start: NAT, count: NAT] RETURNS [LONG POINTER TO RawSamples] ~ TRUSTED INLINE { check: NAT ~ NAT[buffer.maxLength-start]-count; RETURN[LOOPHOLE[buffer, LONG POINTER]+SIZE[SampleBufferRep[start]]]; }; PointerToSamples: PUBLIC PROC [buffer: SampleBuffer, start: NAT, count: NAT] RETURNS [LONG POINTER TO RawSamples] ~ { RETURN [InlinePointerToSamples[buffer, start, count]] }; FlipSamples: PUBLIC PROC [buffer: SampleBuffer, start, count: NAT] ~ { size: NAT ~ MIN[buffer.length-start, count]; IF size>0 THEN TRUSTED { pointer: LONG POINTER TO RawSamples ~ InlinePointerToSamples[buffer, start, size]; last: NAT ~ size-1; FOR j: NAT IN [0..size/2) DO k: NAT ~ last-j; t: Sample ~ pointer[j]; pointer[j] _ pointer[k]; pointer[k] _ t; ENDLOOP; }; }; FillSamples: PUBLIC PROC [buffer: SampleBuffer, value: Sample, start, count: NAT] ~ { size: NAT ~ MIN[buffer.length-start, count]; IF size>0 THEN TRUSTED { pointer: LONG POINTER TO RawSamples ~ InlinePointerToSamples[buffer, start, size]; pointer[0] _ value; PrincOpsUtils.LongCopy[from: pointer, nwords: size-1, to: pointer+1]; }; }; CopySamples: PUBLIC PROC [dst, src: SampleBuffer, dstStart, srcStart, count: NAT] ~ { size: NAT ~ MIN[NAT[dst.length-dstStart], NAT[src.length-dstStart], count]; IF size > 0 THEN TRUSTED { dstPointer: LONG POINTER TO RawSamples ~ InlinePointerToSamples[dst, dstStart, size]; srcPointer: LONG POINTER TO RawSamples ~ InlinePointerToSamples[src, srcStart, size]; PrincOpsUtils.LongCopy[from: srcPointer, nwords: size, to: dstPointer]; }; }; ClearSamples: PUBLIC PROC [buffer: SampleBuffer, start, count: NAT] ~ { size: NAT ~ MIN[buffer.length-start, count]; IF size>0 THEN TRUSTED { pointer: LONG POINTER TO RawSamples ~ InlinePointerToSamples[buffer, start, size]; PrincOpsUtils.LongZero[where: pointer, nwords: size]; }; }; bitsPerWord: NAT ~ Basics.bitsPerWord; logBitsPerWord: NAT ~ Basics.logBitsPerWord; nullBitBltTable: PrincOps.BitBltTable ~ [ dst: [word: NIL, bit: 0], dstBpl: 0, src: [word: NIL, bit: 0], srcDesc: [srcBpl[0]], width: 0, height: 0, flags: [] ]; IsPowerOfTwo: PROC [c: CARDINAL] RETURNS [BOOL] ~ INLINE { RETURN[Basics.BITAND[c, c-1]=0]; }; WordsForBits: PROC [bitCount: CARD] RETURNS [CARD] ~ INLINE { RETURN[Basics.DoubleShiftRight[[lc[bitCount+(bitsPerWord-1)]], logBitsPerWord].lc] }; Lg: PROC [a: NAT] RETURNS [lg: NAT _ 0] ~ { b: CARDINAL _ 1; UNTIL b >= a DO lg _ lg + 1; b _ b*2; ENDLOOP; }; IndexBit: PROC [addr: PrincOps.BitAddress, offset: CARD] RETURNS [PrincOps.BitAddress] ~ TRUSTED INLINE { Addr: TYPE ~ MACHINE DEPENDENT RECORD [pointer: LONG POINTER, offset: CARDINAL]; pointer: LONG POINTER ~ LOOPHOLE[addr, Addr].pointer; index: Basics.LongNumber ~ [lc[LOOPHOLE[addr, Addr].offset+offset]]; RETURN[LOOPHOLE[Addr[ pointer: pointer+Basics.DoubleShiftRight[index, logBitsPerWord].lc, offset: index.lo MOD bitsPerWord ]]]; }; BitsForSamples: PUBLIC PROC [fSize: NAT, bitsPerSample: NAT] RETURNS [NAT] ~ { RETURN[Basics.BITAND[Basics.LongMult[fSize, bitsPerSample]+(bitsPerWord-1), WORD.LAST-(bitsPerWord-1)]]; }; WordsForLines: PUBLIC PROC [sSize: NAT, bitsPerLine: NAT] RETURNS [INT] ~ { IF (bitsPerLine MOD bitsPerWord)=0 THEN RETURN[Basics.LongMult[sSize, bitsPerLine/bitsPerWord]] ELSE RETURN[WordsForBits[Basics.LongMult[sSize, bitsPerLine]]]; }; WordsForMap: PUBLIC PROC [size: Vec, bitsPerSample: BitsPerSample, bitsPerLine: NAT _ 0] RETURNS [INT] ~ { IF bitsPerLine=0 THEN bitsPerLine _ BitsForSamples[size.f, bitsPerSample]; RETURN[WordsForLines[size.s, bitsPerLine]]; }; CleanBox: PROC [box: Box] RETURNS [Box] ~ INLINE { IF box.min.s > box.max.s THEN box.max.s _ box.min.s; IF box.min.f > box.max.f THEN box.max.f _ box.min.f; RETURN [box]; }; InlineSize: PROC [map: SampleMap] RETURNS [Vec] ~ INLINE { RETURN [[s: map.box.max.s-map.box.min.s, f: map.box.max.f-map.box.min.f]] }; UnsafeNewSampleMap: PUBLIC UNSAFE PROC [box: Box, bitsPerSample: BitsPerSample, bitsPerLine: NAT, base: PrincOps.BitAddress, ref: REF, words: INT, scratchDescriptor: SampleMap _ NIL] RETURNS [SampleMap] ~ { size: Vec ~ SF.Size[box]; dataBitsPerLine: INT ~ Basics.LongMult[NAT[size.f], bitsPerSample]; fillBits: INT ~ Basics.NonNegative[bitsPerLine-dataBitsPerLine]; -- check sufficient bitsPerLine totalBits: INT ~ INT[base.bit]+Basics.LongMult[NAT[size.s], bitsPerLine]-fillBits; totalWords: INT ~ WordsForBits[totalBits]; spareWords: INT ~ Basics.NonNegative[words-totalWords]; -- check sufficient words s: SampleMap _ scratchDescriptor; IF s=NIL THEN s _ NEW[SampleMapRep]; s^ _ [box: CleanBox[box], bitsPerSample: bitsPerSample, bitsPerLine: bitsPerLine, base: base, ref: ref]; RETURN[s]; }; WordSeqRep: TYPE ~ RECORD [SEQUENCE length: NAT OF WORD]; maxWordSeqWords: INT _ VM.wordsPerPage-VM.wordsPerPage/10-SIZE[WordSeqRep[0]]; NewSampleMap: PUBLIC PROC [box: Box, bitsPerSample: BitsPerSample, bitsPerLine: NAT _ 0] RETURNS [SampleMap] ~ { size: Vec ~ SF.Size[box]; actualBitsPerLine: NAT ~ SELECT bitsPerLine FROM 0 => BitsForSamples[size.f, bitsPerSample], ENDCASE => bitsPerLine; words: INT ~ WordsForLines[size.s, actualBitsPerLine]; IF words <= maxWordSeqWords THEN { wordSeq: REF WordSeqRep ~ NEW[WordSeqRep[words]]; TRUSTED { RETURN[UnsafeNewSampleMap[ box: box, bitsPerSample: bitsPerSample, bitsPerLine: actualBitsPerLine, base: [word: @wordSeq[0], bit: 0], ref: wordSeq, words: wordSeq.length ]] }; } ELSE RETURN[MapFromVM[vm: Allocate[words], box: box, bitsPerSample: bitsPerSample, bitsPerLine: actualBitsPerLine]]; }; Allocate: PROC [nWords: CARD] RETURNS [vm: CountedVM.Handle _ NIL] ~ { nWords _ MAX[nWords, 256]; vm _ CountedVM.SimpleAllocate[nWords ! VM.CantAllocate => CONTINUE]; IF vm = NIL THEN { cache: FunctionCache.Cache ~ FunctionCache.GlobalCache[]; info: FunctionCache.CacheInfo ~ FunctionCache.GetInfo[cache]; FunctionCache.SetLimits[cache, 0, 0]; FunctionCache.SetLimits[x: cache, maxEntries: info.maxEntries, maxTotalSize: info.maxTotalSize]; ClearScratchMaps[]; vm _ CountedVM.SimpleAllocate[nWords]; }; }; MapFromVM: PUBLIC PROC [vm: CountedVM.Handle, box: Box, bitsPerSample: BitsPerSample _ 1, bitsPerLine: NAT _ 0 ] RETURNS [SampleMap] ~ { size: Vec ~ SF.Size[box]; actualBitsPerLine: NAT ~ SELECT bitsPerLine FROM 0 => BitsForSamples[size.f, bitsPerSample], ENDCASE => bitsPerLine; TRUSTED { RETURN[UnsafeNewSampleMap[ box: box, bitsPerSample: bitsPerSample, bitsPerLine: actualBitsPerLine, base: [word: vm.pointer, bit: 0], ref: vm, words: vm.words ]] }; }; MapFromFrameBuffer: PUBLIC PROC [frameBuffer: Terminal.FrameBuffer] RETURNS [SampleMap] ~ { bitsPerLine: NAT ~ Basics.LongMult[frameBuffer.wordsPerLine, bitsPerWord]; vm: CountedVM.Handle ~ frameBuffer.vm; base: LONG POINTER ~ frameBuffer.base; baseOffset: INT ~ LOOPHOLE[base, INT]-LOOPHOLE[vm.pointer, INT]; words: INT ~ vm.words-Basics.NonNegative[baseOffset]; TRUSTED { RETURN[UnsafeNewSampleMap[ box: [min: [0, 0], max: [s: frameBuffer.height, f: frameBuffer.width]], bitsPerSample: frameBuffer.bitsPerPixel, bitsPerLine: bitsPerLine, base: [word: base, bit: 0], ref: vm, words: words ]] }; }; nScratchDescs: NAT ~ 5; scratchDescsTop: [0..nScratchDescs] _ 0; scratchDescs: ARRAY [0..nScratchDescs) OF SampleMap _ ALL[NIL]; NewDescriptor: ENTRY PROC [map: SampleMap _ NIL] RETURNS [new: SampleMap _ NIL] ~ { IF map # NIL THEN { IF scratchDescsTop = 0 THEN new _ NEW[SampleMapRep] ELSE { scratchDescsTop _ scratchDescsTop - 1; new _ scratchDescs[scratchDescsTop]; scratchDescs[scratchDescsTop] _ NIL; }; IF map # NIL THEN new^ _ map^; }; }; ReleaseDescriptor: PUBLIC ENTRY PROC [map: SampleMap] ~ { FOR i: NAT IN [0..scratchDescsTop) DO IF map = scratchDescs[i] THEN RETURN WITH ERROR MultipleReleaseOfScratch; ENDLOOP; IF map # NIL AND scratchDescsTop < nScratchDescs THEN { map.base.word _ NIL; map.ref _ NIL; scratchDescs[scratchDescsTop] _ map; scratchDescsTop _ scratchDescsTop + 1; }; }; InlineClip: UNSAFE PROC [map: SampleMap, box: Box] ~ INLINE { newBox: Box ~ SF.Intersect[map.box, box]; skipBits: CARD ~ Basics.LongMult[NAT[newBox.min.s-map.box.min.s], map.bitsPerLine] + Basics.LongMult[NAT[newBox.min.f-map.box.min.f], map.bitsPerSample]; map.box _ CleanBox[newBox]; map.base _ IndexBit[map.base, skipBits]; }; InlineShift: UNSAFE PROC [map: SampleMap, delta: Vec] ~ INLINE { map.box.min _ SF.Add[map.box.min, delta]; map.box.max _ SF.Add[map.box.max, delta]; }; ObtainUnsafeDescriptor: PUBLIC UNSAFE PROC [size: Vec, bitsPerSample: BitsPerSample, bitsPerLine: NAT, base: PrincOps.BitAddress, ref: REF, words: INT, rawMin, delta: Vec _ zeroVec] RETURNS [SampleMap] ~ UNCHECKED { new: SampleMap ~ UnsafeNewSampleMap[box: [[0, 0], SF.Add[rawMin, size]], bitsPerSample: bitsPerSample, bitsPerLine: bitsPerLine, base: base, ref: ref, words: words, scratchDescriptor: NewDescriptor[]]; InlineShift[new, SF.Neg[rawMin]]; InlineClip[new, [[0, 0], size]]; InlineShift[new, delta]; RETURN [new]; }; ReIndex: PUBLIC PROC [map: SampleMap, delta: Vec, box: Box] RETURNS [SampleMap] ~ TRUSTED { new: SampleMap _ NewDescriptor[map]; InlineShift[new, delta]; InlineClip[new, box]; RETURN [new] }; Clip: PUBLIC PROC [map: SampleMap, box: Box] RETURNS [SampleMap] ~ { RETURN[ReIndex[map: map, delta: zeroVec, box: box]]; }; Shift: PUBLIC PROC [map: SampleMap, delta: Vec] RETURNS [SampleMap] ~ { RETURN[ReIndex[map: map, delta: delta, box: maxBox]]; }; ZeroOrigin: PUBLIC PROC [map: SampleMap] RETURNS [SampleMap] ~ { RETURN[ReIndex[map: map, delta: SF.Neg[map.box.min], box: maxBox]]; }; Copy: PUBLIC PROC [map: SampleMap, delta: Vec, box: Box] RETURNS [SampleMap] ~ { temp: SampleMap _ ReIndex[map, delta, box]; new: SampleMap ~ NewSampleMap[box: temp.box, bitsPerSample: map.bitsPerSample]; Transfer[dst: new, src: temp]; ReleaseDescriptor[temp]; RETURN[new]; }; nScratchMaps: NAT ~ 5; scratchMaps: ARRAY [0..nScratchMaps) OF SampleMap _ ALL[NIL]; ObtainScratchMap: PUBLIC PROC [box: Box, bitsPerSample: BitsPerSample] RETURNS [SampleMap] ~ { size: Vec ~ SF.Size[box]; bitsPerLine: NAT ~ BitsForSamples[fSize: size.f, bitsPerSample: bitsPerSample]; nWords: INT ~ WordsForLines[sSize: size.s, bitsPerLine: bitsPerLine]; TryObtainScratch: ENTRY PROC RETURNS [SampleMap] ~ TRUSTED { FOR i: NAT IN [0..nScratchMaps) DO s: SampleMap _ scratchMaps[i]; IF s # NIL THEN WITH s.ref SELECT FROM vm: CountedVM.Handle => { IF vm.words >= nWords THEN { scratchMaps[i] _ NIL; s.box _ box; s.bitsPerSample _ bitsPerSample; s.bitsPerLine _ bitsPerLine; s.base _ [word: vm.pointer, bit: 0]; RETURN [s] }; }; ENDCASE => NULL; ENDLOOP; RETURN [NIL] }; s: SampleMap _ TryObtainScratch[]; IF s = NIL THEN { vm: CountedVM.Handle ~ Allocate[WordsForMap[size, bitsPerSample]]; s _ MapFromVM[vm: vm, box: box, bitsPerSample: bitsPerSample]; }; RETURN [s] }; ReleaseScratchMap: PUBLIC ENTRY PROC [map: SampleMap] ~ { r: SampleMap _ map; slot: NAT _ 0; IF map = NIL THEN RETURN; WITH map.ref SELECT FROM vm: CountedVM.Handle => NULL ENDCASE => RETURN; FOR i: NAT IN [0..nScratchMaps) DO t: SampleMap _ scratchMaps[i]; IF t = NIL THEN slot _ i ELSE IF map = t OR map.ref = t.ref THEN RETURN WITH ERROR MultipleReleaseOfScratch; ENDLOOP; scratchMaps[slot] _ map; }; ClearScratchMaps: ENTRY PROC ~ { FOR i: NAT IN [0..nScratchMaps) DO scratchMaps[i] _ NIL; ENDLOOP; }; DoWithScratchMap: PUBLIC PROC [box: Box, bitsPerSample: BitsPerSample, action: PROC [SampleMap]] ~ { scratch: SampleMap ~ ObtainScratchMap[box, bitsPerSample]; action[scratch ! UNWIND => ReleaseScratchMap[scratch]]; ReleaseScratchMap[scratch]; }; Clear: PUBLIC PROC [map: SampleMap] ~ TRUSTED { size: Vec ~ InlineSize[map]; bitsPerLine: NAT ~ map.bitsPerLine; pointer: LONG POINTER _ map.base.word; fillBitsPerLine: NAT ~ bitsPerLine - map.bitsPerSample*size.f; IF fillBitsPerLine < bitsPerWord THEN { nBits: CARD ~ Basics.LongMult[bitsPerLine, size.s]+map.base.bit-fillBitsPerLine; nWords: CARD _ WordsForBits[nBits]; WHILE nWords > 32768 DO PrincOpsUtils.LongZero[pointer, 32768]; pointer _ pointer + 32768; nWords _ nWords - 32768; ENDLOOP; PrincOpsUtils.LongZero[pointer, nWords]; } ELSE { dataBitsPlus: NAT ~ map.bitsPerSample*size.f + (bitsPerWord-1); bit: CARDINAL _ map.base.bit; FOR i: NAT IN [0..size.s) DO PrincOpsUtils.LongZero[where: pointer, nwords: (bit + dataBitsPlus)/bitsPerWord]; bit _ bit + bitsPerLine; pointer _ pointer + bit/bitsPerWord; bit _ bit MOD bitsPerWord; ENDLOOP; }; }; Get: PUBLIC PROC [map: SampleMap, index: Vec] RETURNS [Sample] ~ TRUSTED { size: Vec ~ InlineSize[map]; v: Vec ~ SF.Sub[index, map.box.min]; bitsPerSample: NAT ~ map.bitsPerSample; bitIndex: CARD ~ Basics.LongMult[Basics.BoundsCheck[v.s, size.s], map.bitsPerLine] + Basics.LongMult[Basics.BoundsCheck[v.f, size.f], bitsPerSample]; bitAddress: PrincOps.BitAddress ~ IndexBit[map.base, bitIndex]; IF bitsPerSample=1 THEN TRUSTED { pointer: LONG POINTER TO Basics.ShortNumber ~ bitAddress.word; RETURN[LOOPHOLE[pointer.bits[bitAddress.bit]]]; } ELSE TRUSTED { pointer: LONG POINTER TO Basics.RawWords ~ bitAddress.word; shiftAmt: INTEGER ~ bitAddress.bit + bitsPerSample - bitsPerWord; mask: WORD ~ Basics.BITSHIFT[1, bitsPerSample]-1; shiftedBits: WORD ~ IF shiftAmt <= 0 THEN Basics.BITSHIFT[pointer[0], shiftAmt] ELSE Basics.BITSHIFT[pointer[0], shiftAmt] + Basics.BITSHIFT[pointer[1], shiftAmt-16]; RETURN[Basics.BITAND[shiftedBits, mask]]; }; }; Put: PUBLIC PROC [map: SampleMap, index: Vec, value: Sample, function: Function _ nullFunction] ~ { size: Vec ~ InlineSize[map]; v: Vec ~ SF.Sub[index, map.box.min]; bitsPerSample: NAT ~ map.bitsPerSample; bitIndex: CARD ~ Basics.LongMult[Basics.BoundsCheck[v.s, size.s], map.bitsPerLine] + Basics.LongMult[Basics.BoundsCheck[v.f, size.f], bitsPerSample]; bitAddress: PrincOps.BitAddress ~ IndexBit[map.base, bitIndex]; IF bitsPerSample=1 AND function=nullFunction THEN TRUSTED { pointer: LONG POINTER TO Basics.ShortNumber ~ bitAddress.word; pointer.bits[bitAddress.bit] _ LOOPHOLE[value MOD 2]; } ELSE TRUSTED { bbTableSpace: PrincOps.BBTableSpace; bb: PrincOps.BBptr ~ PrincOpsUtils.AlignedBBTable[@bbTableSpace]; bb^ _ nullBitBltTable; bb.dst _ bitAddress; bb.src.word _ @value; bb.src.bit _ bitsPerWord-bitsPerSample; bb.height _ 1; bb.width _ bitsPerSample; bb.flags _ [disjoint: TRUE, disjointItems: TRUE, gray: FALSE]; bb.flags.srcFunc _ function.srcFunc; bb.flags.dstFunc _ function.dstFunc; PrincOpsUtils.BITBLT[bb]; }; }; GetSamples: PUBLIC PROC [map: SampleMap, initIndex: Vec _ zeroVec, delta: Vec _ [s: 0, f: 1], buffer: SampleBuffer, start: NAT _ 0, count: NAT _ maxCount] ~ { size: NAT ~ MIN[buffer.length-start, count]; boxSize: Vec ~ InlineSize[map]; v0: Vec ~ SF.Sub[initIndex, map.box.min]; IF size#0 THEN TRUSTED { bitsPerLine: NAT ~ map.bitsPerLine; bitsPerSample: NAT ~ map.bitsPerSample; bb: PrincOps.BBptr ~ PrincOpsUtils.AlignedBBTable[@bbTableSpace]; bbTableSpace: PrincOps.BBTableSpace; bufferPointer: LONG POINTER ~ InlinePointerToSamples[buffer, start, size]; srcBitIndex: CARD _ Basics.LongMult[Basics.BoundsCheck[v0.s, boxSize.s], bitsPerLine] + Basics.LongMult[Basics.BoundsCheck[v0.f, boxSize.f], bitsPerSample]; srcBitDelta: NAT ~ Basics.LongMult[delta.s, bitsPerLine] + Basics.LongMult[delta.f, bitsPerSample]; srcBitSkipDelta: NAT _ srcBitDelta; lgSkip: NAT _ 0; skipMinusOne: NAT _ 0; IF delta.s#0 THEN []_Basics.BoundsCheck[v0.s+Basics.LongMult[size-1, delta.s], boxSize.s]; IF delta.f#0 THEN []_Basics.BoundsCheck[v0.f+Basics.LongMult[size-1, delta.f], boxSize.f]; WHILE srcBitSkipDelta<=NAT.LAST/2 AND CARDINAL[srcBitSkipDelta] MOD bitsPerWord#0 DO srcBitSkipDelta _ srcBitSkipDelta*2; lgSkip _ lgSkip+1; ENDLOOP; skipMinusOne _ Basics.BITSHIFT[1, lgSkip]-1; PrincOpsUtils.LongZero[where: bufferPointer, nwords: size]; bb^ _ nullBitBltTable; bb.dst.bit _ bitsPerWord-bitsPerSample; bb.dstBpl _ Basics.BITSHIFT[bitsPerWord, lgSkip]; bb.srcDesc _ [srcBpl[srcBitSkipDelta]]; bb.width _ bitsPerSample; bb.flags _ [disjoint: TRUE, disjointItems: TRUE, gray: FALSE]; FOR i: NAT IN [0..Basics.BITSHIFT[1, lgSkip]) DO bb.src _ IndexBit[map.base, srcBitIndex]; bb.height _ Basics.BITSHIFT[size-i+skipMinusOne, -lgSkip]; bb.dst.word _ bufferPointer+i; PrincOpsUtils.BITBLT[bb]; srcBitIndex _ srcBitIndex + srcBitDelta; ENDLOOP; }; }; PutSamples: PUBLIC PROC [map: SampleMap, initIndex: Vec _ zeroVec, delta: Vec _ [s: 0, f: 1], buffer: SampleBuffer, start: NAT _ 0, count: NAT _ maxCount, function: Function _ nullFunction] ~ { size: NAT ~ MIN[buffer.length-start, count]; boxSize: Vec ~ InlineSize[map]; v0: Vec ~ SF.Sub[initIndex, map.box.min]; IF size # 0 THEN TRUSTED { bitsPerLine: NAT ~ map.bitsPerLine; bitsPerSample: NAT ~ map.bitsPerSample; bb: PrincOps.BBptr ~ PrincOpsUtils.AlignedBBTable[@bbTableSpace]; bbTableSpace: PrincOps.BBTableSpace; bufferPointer: LONG POINTER ~ InlinePointerToSamples[buffer, start, size]; dstBitIndex: CARD _ Basics.LongMult[Basics.BoundsCheck[v0.s, boxSize.s], bitsPerLine] + Basics.LongMult[Basics.BoundsCheck[v0.f, boxSize.f], bitsPerSample]; dstBitDelta: NAT _ Basics.LongMult[delta.s, bitsPerLine] + Basics.LongMult[delta.f, bitsPerSample]; dstBitSkipDelta: NAT _ dstBitDelta; lgSkip: NAT _ 0; skipMinusOne: NAT _ 0; IF delta.s#0 THEN []_Basics.BoundsCheck[v0.s+Basics.LongMult[size-1, delta.s], boxSize.s]; IF delta.f#0 THEN []_Basics.BoundsCheck[v0.f+Basics.LongMult[size-1, delta.f], boxSize.f]; WHILE dstBitSkipDelta<=NAT.LAST/2 AND CARDINAL[dstBitSkipDelta] MOD bitsPerWord#0 DO dstBitSkipDelta _ dstBitSkipDelta*2; lgSkip _ lgSkip+1; ENDLOOP; skipMinusOne _ Basics.BITSHIFT[1, lgSkip]-1; bb^ _ nullBitBltTable; bb.flags _ [disjoint: TRUE, disjointItems: TRUE, gray: FALSE]; bb.flags.srcFunc _ function.srcFunc; bb.flags.dstFunc _ function.dstFunc; bb.dstBpl _ dstBitSkipDelta; bb.src.bit _ bitsPerWord-bitsPerSample; bb.srcDesc _ [srcBpl[Basics.BITSHIFT[bitsPerWord, lgSkip]]]; bb.width _ bitsPerSample; FOR i: NAT IN [0..Basics.BITSHIFT[1, lgSkip]) DO bb.dst _ IndexBit[map.base, dstBitIndex]; bb.height _ Basics.BITSHIFT[size-i+skipMinusOne, -lgSkip]; bb.src.word _ bufferPointer+i; PrincOpsUtils.BITBLT[bb]; dstBitIndex _ dstBitIndex + dstBitDelta; ENDLOOP; }; }; DumbBasicTransfer: PROC [dst: SampleMap, src: SampleMap, dstMin: Vec _ zeroVec, srcMin: Vec _ zeroVec, size: Vec _ maxVec, function: Function _ nullFunction] ~ { 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; }; Check: PROC [value: INTEGER, bound: NAT] RETURNS [INTEGER] ~ INLINE { RETURN [LOOPHOLE[Basics.BoundsCheck[LOOPHOLE[value], CARDINAL[bound]+1]]] }; BufferTransfer: PROC [dst: SampleMap, src: SampleMap, dstMin: Vec _ zeroVec, srcMin: Vec _ zeroVec, size: Vec _ maxVec, function: Function _ nullFunction] ~ { dstSize: Vec ~ InlineSize[dst]; srcSize: Vec ~ InlineSize[src]; sDst0: NAT ~ dstMin.s - dst.box.min.s; fDst0: NAT ~ dstMin.f - dst.box.min.f; sSrc0: NAT ~ srcMin.s - src.box.min.s; fSrc0: NAT ~ srcMin.f - src.box.min.f; sSize: NAT ~ Check[Check[size.s, dstSize.s-sDst0], srcSize.s-sSrc0]; fSize: NAT ~ Check[Check[size.f, dstSize.f-fDst0], srcSize.f-fSrc0]; transferAction: PROC [buffer: SampleBuffer] ~ { FOR s: NAT IN [0..sSize) DO GetSamples[map: src, initIndex: [s: srcMin.s+s, f: srcMin.f], buffer: buffer]; PutSamples[map: dst, initIndex: [s: dstMin.s+s, f: dstMin.f], buffer: buffer, function: function]; ENDLOOP; }; DoWithScratchSamples[length: fSize, action: transferAction]; }; BasicTransfer: PUBLIC PROC [dst: SampleMap, src: SampleMap, dstMin: Vec _ zeroVec, srcMin: Vec _ zeroVec, size: Vec, function: Function _ nullFunction] ~ { bitsPerSample: NAT ~ dst.bitsPerSample; IF src.bitsPerSample=bitsPerSample THEN TRUSTED { dstSize: Vec ~ InlineSize[dst]; srcSize: Vec ~ InlineSize[src]; sDst0: NAT ~ dstMin.s - dst.box.min.s; fDst0: NAT ~ dstMin.f - dst.box.min.f; sSrc0: NAT ~ srcMin.s - src.box.min.s; fSrc0: NAT ~ srcMin.f - src.box.min.f; sSize: NAT ~ Check[Check[size.s, dstSize.s-sDst0], srcSize.s-sSrc0]; fSize: NAT ~ Check[Check[size.f, dstSize.f-fDst0], srcSize.f-fSrc0]; bbTableSpace: PrincOps.BBTableSpace; bb: PrincOps.BBptr ~ PrincOpsUtils.AlignedBBTable[@bbTableSpace]; dstBitIndex: CARD ~ Basics.LongMult[sDst0, dst.bitsPerLine] + Basics.LongMult[fDst0, bitsPerSample]; srcBitIndex: CARD ~ Basics.LongMult[sSrc0, src.bitsPerLine] + Basics.LongMult[fSrc0, bitsPerSample]; bb^ _ nullBitBltTable; bb.dst _ IndexBit[dst.base, dstBitIndex]; bb.dstBpl _ dst.bitsPerLine; bb.src _ IndexBit[src.base, srcBitIndex]; bb.srcDesc _ [srcBpl[src.bitsPerLine]]; bb.width _ fSize*bitsPerSample; bb.height _ sSize; bb.flags _ [disjoint: TRUE, disjointItems: TRUE, gray: FALSE]; bb.flags.srcFunc _ function.srcFunc; bb.flags.dstFunc _ function.dstFunc; PrincOpsUtils.BITBLT[bb]; } ELSE BufferTransfer[dst, src, dstMin, srcMin, size, function]; }; RawTransfer: PUBLIC PROC [dst: SampleMap, rawGenerator: RawGenerator, function: Function _ nullFunction] ~ TRUSTED { bitsPerSample: [1..1] ~ dst.bitsPerSample; bbTableSpace: PrincOps.BBTableSpace; bbPtr: PrincOps.BBptr ~ PrincOpsUtils.AlignedBBTable[@bbTableSpace]; fastTransfer: RawAction ~ TRUSTED { sCheck: NAT ~ dst.box.max.s-box.max.s; fCheck: NAT ~ dst.box.max.f-box.max.f; dstBitIndex: CARD ~ Basics.LongMult[NAT[box.min.s-dst.box.min.s], dst.bitsPerLine] + NAT[box.min.f-dst.box.min.f]; -- (know bitsPerSample = 1) bb: PrincOps.BBptr ~ bbPtr; bb.dst _ IndexBit[dst.base, dstBitIndex]; bb.src _ base; bb.srcDesc _ [srcBpl[bitsPerLine]]; bb.width _ SF.SizeF[box]; -- (know bitsPerSample = 1) bb.height _ SF.SizeS[box]; PrincOpsUtils.BITBLT[bb]; }; bbPtr^ _ nullBitBltTable; bbPtr.dstBpl _ dst.bitsPerLine; bbPtr.flags _ [disjoint: TRUE, disjointItems: TRUE, gray: FALSE]; bbPtr.flags.srcFunc _ function.srcFunc; bbPtr.flags.dstFunc _ function.dstFunc; rawGenerator[fastTransfer]; }; MultipleTransfer: PUBLIC PROC [dst: SampleMap, n: [0..rawArraySize], a: POINTER TO RawArray, function: Function _ nullFunction] ~ TRUSTED { bitsPerSample: [1..1] ~ dst.bitsPerSample; bbTableSpace: PrincOps.BBTableSpace; bb: PrincOps.BBptr ~ PrincOpsUtils.AlignedBBTable[@bbTableSpace]; r: POINTER TO RawDescriptor _ @(a[0]); bb^ _ nullBitBltTable; bb.dstBpl _ dst.bitsPerLine; bb.flags _ [disjoint: TRUE, disjointItems: TRUE, gray: FALSE]; bb.flags.srcFunc _ function.srcFunc; bb.flags.dstFunc _ function.dstFunc; FOR i: NAT IN [0..n) DO sCheck: NAT ~ dst.box.max.s-r.box.max.s; fCheck: NAT ~ dst.box.max.f-r.box.max.f; dstBitIndex: CARD ~ Basics.LongMult[NAT[r.box.min.s-dst.box.min.s], dst.bitsPerLine] + NAT[r.box.min.f-dst.box.min.f]; -- (know bitsPerSample = 1) bb.dst _ IndexBit[dst.base, dstBitIndex]; bb.src.word _ r.basePointer; bb.srcDesc _ [srcBpl[r.bitsPerLine]]; bb.width _ SF.SizeF[r.box]; -- (know bitsPerSample = 1) bb.height _ SF.SizeS[r.box]; PrincOpsUtils.BITBLT[bb]; r _ r + SIZE[RawDescriptor]; ENDLOOP; }; Transfer: PUBLIC PROC [dst: SampleMap, src: SampleMap, delta: Vec _ zeroVec, function: Function _ nullFunction] ~ { box: Box ~ SF.Intersect[dst.box, SF.Displace[src.box, delta]]; IF SF.Nonempty[box] THEN BasicTransfer[dst: dst, src: src, dstMin: box.min, srcMin: SF.Sub[box.min, delta], size: SF.Size[box], function: function]; }; tb: Box _ [[0, 0], [100, 100]]; TestBoxes: BoxGenerator ~ { boxAction[[[tb.min.s, (tb.min.f+tb.max.f)/2], [(tb.min.s+tb.max.s)/2, tb.max.f]]]; FOR i: NAT IN [0..tb.SizeS) DO boxAction[[[tb.min.s+i, tb.min.f], [tb.min.s+i+1, MIN[tb.max.f, tb.min.f+i+1]]]] ENDLOOP; }; TransferBoxes: PUBLIC PROC [dst: SampleMap, src: SampleMap, delta: Vec _ zeroVec, boxes: BoxGenerator, function: Function _ nullFunction] ~ { bitsPerSample: NAT ~ dst.bitsPerSample; IF src.bitsPerSample=bitsPerSample THEN TRUSTED { dstBox: Box ~ dst.box; srcBox: Box ~ SF.Displace[src.box, delta]; bounds: Box ~ SF.Intersect[dstBox, srcBox]; bbTableSpace: PrincOps.BBTableSpace; bb: PrincOps.BBptr ~ PrincOpsUtils.AlignedBBTable[@bbTableSpace]; fastTransfer: BoxAction ~ TRUSTED { IF box.max.s > box.min.s AND box.max.f > box.min.f THEN { sSpaceLo: NAT ~ box.min.s-bounds.min.s; -- for bounds check fSpaceLo: NAT ~ box.min.f-bounds.min.f; sSpaceHi: NAT ~ bounds.max.s-box.max.s; fSpaceHi: NAT ~ bounds.max.f-box.max.f; dstBitIndex: CARD ~ Basics.LongMult[LOOPHOLE[box.min.s-dstBox.min.s], dst.bitsPerLine] + Basics.LongMult[LOOPHOLE[box.min.f-dstBox.min.f], bitsPerSample]; srcBitIndex: CARD ~ Basics.LongMult[LOOPHOLE[box.min.s-srcBox.min.s], src.bitsPerLine] + Basics.LongMult[LOOPHOLE[box.min.f-srcBox.min.f], bitsPerSample]; bb.dst _ IndexBit[dst.base, dstBitIndex]; bb.src _ IndexBit[src.base, srcBitIndex]; bb.width _ LOOPHOLE[box.max.f-box.min.f, CARDINAL]*bitsPerSample; bb.height _ LOOPHOLE[box.max.s-box.min.s]; PrincOpsUtils.BITBLT[bb]; }; }; bb^ _ nullBitBltTable; bb.dstBpl _ dst.bitsPerLine; bb.srcDesc _ [srcBpl[src.bitsPerLine]]; bb.flags _ [disjoint: TRUE, disjointItems: TRUE, gray: FALSE]; bb.flags.srcFunc _ function.srcFunc; bb.flags.dstFunc _ function.dstFunc; boxes[fastTransfer]; } ELSE { slowTransfer: BoxAction ~ { dstMin: Vec ~ box.min; srcMin: Vec ~ box.min.Sub[delta]; BufferTransfer[dst, src, dstMin, srcMin, box.max.Sub[box.min], function]; }; boxes[slowTransfer]; }; }; Move: PUBLIC PROC [map: SampleMap, dstMin: Vec _ zeroVec, srcMin: Vec _ zeroVec, size: Vec _ maxVec, function: Function _ nullFunction] ~ TRUSTED { selfSize: Vec ~ InlineSize[map]; sDst0: NAT ~ dstMin.s - map.box.min.s; fDst0: NAT ~ dstMin.f - map.box.min.f; sSrc0: NAT ~ srcMin.s - map.box.min.s; fSrc0: NAT ~ srcMin.f - map.box.min.f; sSize: NAT ~ Check[Check[size.s, selfSize.s-sDst0], selfSize.s-sSrc0]; fSize: NAT ~ Check[Check[size.f, selfSize.f-fDst0], selfSize.f-fSrc0]; bitsPerSample: NAT ~ map.bitsPerSample; bitsPerLine: NAT ~ map.bitsPerLine; dstBitIndex: CARD _ Basics.LongMult[dstMin.s, bitsPerLine] + Basics.LongMult[dstMin.f, bitsPerSample]; srcBitIndex: CARD _ Basics.LongMult[srcMin.s, bitsPerLine] + Basics.LongMult[srcMin.f, bitsPerSample]; bbTableSpace: PrincOps.BBTableSpace; bb: PrincOps.BBptr ~ PrincOpsUtils.AlignedBBTable[@bbTableSpace]; IF sSize=0 OR fSize = 0 THEN RETURN; bb^ _ nullBitBltTable; bb.dstBpl _ bitsPerLine; bb.srcDesc _ [srcBpl[bitsPerLine]]; bb.height _ sSize; bb.width _ bitsPerSample * fSize; bb.flags _ [disjoint: TRUE, disjointItems: TRUE, gray: FALSE]; bb.flags.srcFunc _ function.srcFunc; bb.flags.dstFunc _ function.dstFunc; IF (srcMin.f+fSize) > dstMin.f AND (dstMin.f+fSize) > srcMin.f AND (srcMin.s+sSize) > dstMin.s AND (dstMin.s+sSize) > srcMin.s THEN { bb.flags.disjoint _ FALSE; -- the rectangles overlap IF srcMin.s=dstMin.s THEN bb.flags.disjointItems _ FALSE; -- so do the items IF dstMin.s>srcMin.s OR (dstMin.s=srcMin.s AND dstMin.f>srcMin.f) THEN { delta: CARD ~ Basics.LongMult[sSize-1, bitsPerLine]; bb.flags.direction _ backward; -- reverse direction bb.srcDesc.srcBpl _ bb.dstBpl _ -bitsPerLine; dstBitIndex _ dstBitIndex + delta; srcBitIndex _ srcBitIndex + delta; }; }; bb.dst _ IndexBit[map.base, dstBitIndex]; bb.src _ IndexBit[map.base, srcBitIndex]; PrincOpsUtils.BITBLT[bb]; }; DumbFill: PROC [map: SampleMap, box: Box _ maxBox, value: Sample, function: Function _ nullFunction] ~ { actualBox: Box ~ SF.Intersect[map.box, box]; FOR s: NAT IN [actualBox.min.s..actualBox.max.s) DO FOR f: NAT IN [actualBox.min.f..actualBox.max.f) DO Put[map, [s, f], value, function]; ENDLOOP; ENDLOOP; }; replicator: ARRAY [0..4] OF Sample ~ [0FFFFH, 05555H, 01111H, 00101H, 00001H]; Fill: PUBLIC PROC [map: SampleMap, box: Box, value: Sample, function: Function _ nullFunction] ~ { bitsPerSample: NAT ~ map.bitsPerSample; bitsPerLine: NAT ~ map.bitsPerLine; IF (bitsPerWord MOD bitsPerSample)=0 THEN TRUSTED { actualBox: Box ~ SF.Intersect[map.box, box]; sSize: CARDINAL ~ SF.SizeS[actualBox]; fSize: CARDINAL ~ SF.SizeF[actualBox]; dstBitIndex: CARD ~ Basics.LongMult[actualBox.min.s-map.box.min.s, bitsPerLine] + Basics.LongMult[actualBox.min.f-map.box.min.f, bitsPerSample]; bbTableSpace: PrincOps.BBTableSpace; bb: PrincOps.BBptr ~ PrincOpsUtils.AlignedBBTable[@bbTableSpace]; bitMask: WORD ~ Basics.BITSHIFT[1, bitsPerSample]-1; replicatedPixel: WORD _ Basics.BITAND[value, bitMask] * replicator[Lg[bitsPerSample]]; IF function = [null, complement] THEN { -- Bug in Dorado BITBLT microcode (as of December 4, 1985) -- replicatedPixel _ WORD.LAST-replicatedPixel; function _ [null, null]; }; bb^ _ nullBitBltTable; bb.dst _ IndexBit[map.base, dstBitIndex]; bb.dstBpl _ bitsPerLine; bb.src.word _ @replicatedPixel; bb.srcDesc.gray _ [yOffset: 0, widthMinusOne: 0, heightMinusOne: 0]; bb.width _ fSize*bitsPerSample; bb.height _ sSize; bb.flags _ [disjoint: TRUE, disjointItems: TRUE, gray: TRUE]; bb.flags.srcFunc _ function.srcFunc; bb.flags.dstFunc _ function.dstFunc; PrincOpsUtils.BITBLT[bb]; } ELSE DumbFill[map: map, box: box, value: value, function: function]; }; FillBoxes: PUBLIC PROC [map: SampleMap, boxes: BoxGenerator, value: Sample _ maxSample, function: Function _ nullFunction] ~ { bitsPerSample: NAT ~ map.bitsPerSample; IF (bitsPerWord MOD bitsPerSample)=0 THEN TRUSTED { lgBitsPerSample: NAT ~ Lg[bitsPerSample]; bitsPerLine: NAT ~ map.bitsPerLine; bbTableSpace: PrincOps.BBTableSpace; bb: PrincOps.BBptr ~ PrincOpsUtils.AlignedBBTable[@bbTableSpace]; dstBox: Box ~ map.box; fastFill: BoxAction ~ TRUSTED { IF box.max.s > box.min.s AND box.max.f > box.min.f THEN { sSpaceHi: NAT ~ dstBox.max.s-box.max.s; -- for bounds check fSpaceHi: NAT ~ dstBox.max.f-box.max.f; dstBitIndex: CARD ~ Basics.LongMult[NAT[box.min.s-dstBox.min.s], bitsPerLine] + Basics.BITSHIFT[NAT[box.min.f-dstBox.min.f], lgBitsPerSample]; bb.dst _ IndexBit[map.base, dstBitIndex]; bb.width _ Basics.BITSHIFT[LOOPHOLE[box.max.f-box.min.f], lgBitsPerSample]; bb.height _ LOOPHOLE[box.max.s-box.min.s]; PrincOpsUtils.BITBLT[bb]; }; }; bitMask: WORD ~ Basics.BITSHIFT[1, bitsPerSample]-1; replicatedPixel: WORD _ Basics.BITAND[value, bitMask] * replicator[lgBitsPerSample]; IF function = [null, complement] THEN { -- Bug in Dorado BITBLT microcode (as of December 4, 1985) -- replicatedPixel _ WORD.LAST-replicatedPixel; function _ [null, null]; }; bb^ _ nullBitBltTable; bb.dstBpl _ bitsPerLine; bb.src.word _ @replicatedPixel; bb.srcDesc.gray _ [yOffset: 0, widthMinusOne: 0, heightMinusOne: 0]; bb.flags _ [disjoint: TRUE, disjointItems: TRUE, gray: TRUE]; bb.flags.srcFunc _ function.srcFunc; bb.flags.dstFunc _ function.dstFunc; boxes[fastFill]; } ELSE { slowFill: BoxAction ~ { DumbFill[map, box, value, function] }; boxes[slowFill]; }; }; RegionFill: PUBLIC PROC [dst: SampleMap, edgeGenerator: PROC [EdgeAction], value: Sample, function: Function] ~ TRUSTED { Edge: TYPE ~ RECORD [sMin: INTEGER, sMax: INTEGER, f0: Scaled.Value, df: Scaled.Value]; edges: ARRAY [0..1] OF Edge _ ALL[[0, 0, [0, 0], [0, 0]]]; bitsPerSample: NAT ~ dst.bitsPerSample; zero: [0..0] ~ bitsPerWord MOD bitsPerSample; -- not implemented for strange bps . . . lgBitsPerSample: NAT ~ Lg[bitsPerSample]; -- so we can shift rather than multiply bbTableSpace: PrincOps.BBTableSpace; bbPtr: PrincOps.BBptr ~ PrincOpsUtils.AlignedBBTable[@bbTableSpace]; edgeAction: SAFE PROC [which: [0..1], sMin: INTEGER, sCount: NAT, f0, df: Scaled.Value] ~ TRUSTED { e: ARRAY [0..1] OF Edge _ [ IF which = 0 THEN [sMin: sMin, sMax: sMin+sCount, f0: f0, df: df] ELSE edges[0], IF which = 1 THEN [sMin: sMin, sMax: sMin+sCount, f0: f0, df: df] ELSE edges[1] ]; IF (e[0].sMin < e[0].sMax) AND (e[1].sMin < e[1].sMax) AND (e[0].sMin < dst.box.max.s) THEN { s: INTEGER _ e[0].sMin; zero: [0..0] ~ s - e[1].sMin; box: Box ~ dst.box; sMax: INTEGER ~ MIN[e[0].sMax, e[1].sMax, box.max.s]; currentBox: SF.Box _ []; bb: PrincOps.BBptr ~ bbPtr; Addr: TYPE ~ MACHINE DEPENDENT RECORD [pointer: LONG POINTER, offset: CARDINAL]; line: Addr _ LOOPHOLE[IndexBit[dst.base, Basics.LongMult[NAT[s-box.min.s], dst.bitsPerLine]]]; addrp: POINTER TO Addr ~ LOOPHOLE[@(bb^.dst)]; bitsPerLine: NAT ~ dst.bitsPerLine; IF e[0].df = Scaled.zero AND e[1].df = Scaled.zero AND s >= box.min.s THEN { f0: INTEGER _ e[0].f0.integerPart; f1: INTEGER _ e[1].f0.integerPart; IF f0 > f1 THEN {t: INTEGER _ f0; f0 _ f1; f1 _ t}; IF f0 < box.min.f THEN f0 _ box.min.f; IF f1 > box.max.f THEN f1 _ box.max.f; IF f0 < f1 THEN { offset: CARDINAL ~ line.offset+LOOPHOLE[f0-box.min.f, CARDINAL]; addrp^.pointer _ offset/bitsPerWord+line.pointer; addrp^.offset _ offset MOD bitsPerWord; bb.height _ sMax-s; bb.width _ Basics.BITSHIFT[LOOPHOLE[f1-f0], lgBitsPerSample]; PrincOpsUtils.BITBLT[bb]; }; s _ sMax; } ELSE { bb.height _ 1; WHILE s < sMax DO f0: INTEGER _ e[0].f0.integerPart; f1: INTEGER _ e[1].f0.integerPart; IF f0 > f1 THEN {t: INTEGER _ f0; f0 _ f1; f1 _ t}; IF f0 < box.min.f THEN f0 _ box.min.f; IF f1 > box.max.f THEN f1 _ box.max.f; IF s >= box.min.s AND f0 < f1 THEN { offset: CARDINAL ~ line.offset+LOOPHOLE[f0-box.min.f, CARDINAL]; addrp^.pointer _ offset/bitsPerWord+line.pointer; addrp^.offset _ offset MOD bitsPerWord; bb.width _ Basics.BITSHIFT[LOOPHOLE[f1-f0], lgBitsPerSample]; PrincOpsUtils.BITBLT[bb]; }; e[0].f0 _ e[0].f0.PLUS[e[0].df]; e[1].f0 _ e[1].f0.PLUS[e[1].df]; {offset: CARDINAL ~ line.offset+bitsPerLine; line.pointer _ line.pointer + offset/bitsPerWord; line.offset _ offset MOD bitsPerWord; }; s _ s + 1; ENDLOOP; }; e[0].sMin _ e[1].sMin _ s; bb.height _ 0; }; edges _ e; }; bitMask: WORD ~ Basics.BITSHIFT[1, bitsPerSample]-1; replicatedPixel: WORD _ Basics.BITAND[value, bitMask] * replicator[lgBitsPerSample]; IF function = [null, complement] THEN { -- Bug in Dorado BITBLT microcode (as of December 4, 1985) -- replicatedPixel _ WORD.LAST-replicatedPixel; function _ [null, null]; }; bbPtr^ _ nullBitBltTable; bbPtr.dstBpl _ dst.bitsPerLine; bbPtr.src.word _ @replicatedPixel; bbPtr.srcDesc.gray _ [yOffset: 0, widthMinusOne: 0, heightMinusOne: 0]; bbPtr.flags _ [disjoint: TRUE, disjointItems: TRUE, gray: TRUE]; bbPtr.flags.srcFunc _ function.srcFunc; bbPtr.flags.dstFunc _ function.dstFunc; bbPtr.height _ 0; edgeGenerator[edgeAction]; }; Zeros: PROC [pointer: LONG POINTER, count: NAT] RETURNS [BOOL] ~ TRUSTED { chomp: NAT ~ 8; scratch: ARRAY [0..chomp) OF WORD _ ALL[0]; bbTableSpace: PrincOps.BBTableSpace; bb: PrincOps.BBptr ~ PrincOpsUtils.AlignedBBTable[@bbTableSpace]; bb^ _ nullBitBltTable; bb.dstBpl _ 0; bb.srcDesc _ [srcBpl[chomp*bitsPerWord]]; bb.height _ count/chomp; bb.width _ chomp*bitsPerWord; bb.flags _ [disjoint: TRUE, disjointItems: TRUE, dstFunc: or]; bb.dst.word _ @scratch; bb.src.word _ pointer; IF bb.height # 0 THEN PrincOpsUtils.BITBLT[bb]; bb.src.word _ pointer + Basics.LongMult[bb.height, chomp]; bb.height _ 1; bb.width _ count MOD chomp; IF bb.width # 0 THEN PrincOpsUtils.BITBLT[bb]; FOR i: NAT IN [0..MIN[chomp, count]) DO IF scratch[i]#0 THEN RETURN [FALSE] ENDLOOP; RETURN [TRUE]; }; Equal: PUBLIC PROC [s1, s2: SampleMap] RETURNS [equal: BOOL _ TRUE] ~ { bandAction: PROC [band: SampleMap] ~ { boxSize: NAT ~ SF.SizeS[s1.box]; bandSize: NAT ~ SF.SizeS[band.box]; bandWords: NAT ~ WordsForLines[bandSize, band.bitsPerLine]; Clear[band]; FOR s: INTEGER _ 0, s+bandSize WHILE s < boxSize DO Transfer[dst: band, src: s1, delta: [s: -s, f: 0]]; Transfer[dst: band, src: s2, delta: [s: -s, f: 0], function: [xor, null]]; IF NOT Zeros[band.base.word, bandWords] THEN { equal _ FALSE; EXIT }; ENDLOOP; }; IF SF.Empty[s1.box] AND SF.Empty[s2.box] THEN NULL ELSE IF s1.box # s2.box THEN equal _ FALSE ELSE { bandBitsPerSample: NAT ~ MAX[s1.bitsPerSample, s2.bitsPerSample]; bandLines: NAT ~ MIN[MAX[4096/SF.SizeF[s1.box], 1], SF.SizeS[s1.box]]; bandBox: Box _ s1.box; bandBox.max.s _ bandBox.min.s + bandLines; DoWithScratchMap[bandBox, bandBitsPerSample, bandAction]; }; }; IsAll: PUBLIC PROC [map: SampleMap, box: Box _ maxBox, value: Sample _ 0] RETURNS [equal: BOOL _ TRUE] ~ { clipped: SampleMap ~ Clip[map, box]; bandAction: PROC [band: SampleMap] ~ { boxSize: NAT ~ SF.SizeS[clipped.box]; bandSize: NAT ~ SF.SizeS[band.box]; bandWords: NAT ~ WordsForLines[bandSize, band.bitsPerLine]; Clear[band]; FOR s: INTEGER _ 0, s+bandSize WHILE s < boxSize DO Transfer[dst: band, src: clipped, delta: [s: -s, f: 0]]; IF value # 0 THEN Fill[map: band, box: maxBox, value: value, function: [xor, null]]; IF NOT Zeros[band.base.word, bandWords] THEN { equal _ FALSE; EXIT }; ENDLOOP; }; IF SF.Empty[clipped.box]THEN NULL ELSE { bandLines: NAT ~ MIN[MAX[4096/SF.SizeF[clipped.box], 1], SF.SizeS[clipped.box]]; bandBox: Box _ clipped.box; bandBox.max.s _ bandBox.min.s + bandLines; DoWithScratchMap[bandBox, clipped.bitsPerSample, bandAction]; }; ReleaseDescriptor[clipped]; }; Trim: PUBLIC PROC [map: SampleMap, box: Box, background: Sample] RETURNS [Box] ~ { actualBox: Box ~ SF.Intersect[map.box, box]; min: Vec _ actualBox.min; max: Vec _ actualBox.max; bandAction: PROC [band: SampleMap] ~ { bandWords: NAT ~ WordsForLines[band.box.max.s, band.bitsPerLine]; Clear[band]; WHILE min.s < max.s -- OR EXIT below -- DO BasicTransfer[dst: band, src: map, srcMin: [s: max.s-1, f: min.f], size: band.box.max]; IF background#0 THEN Fill[map: band, box: band.box, value: background, function: [xor, null]]; IF Zeros[band.base.word, bandWords] THEN max.s _ max.s-1 ELSE EXIT; ENDLOOP; WHILE min.s < max.s -- OR EXIT below -- DO BasicTransfer[dst: band, src: map, srcMin: [s: min.s, f: min.f], size: band.box.max]; IF background#0 THEN Fill[map: band, box: band.box, value: background, function: [xor, null]]; IF Zeros[band.base.word, bandWords] THEN min.s _ min.s+1 ELSE EXIT; ENDLOOP; }; DoWithScratchMap[box: [zeroVec, [s: 1, f: SF.SizeF[actualBox]]], bitsPerSample: map.bitsPerSample, action: bandAction]; IF min.s=max.s THEN max.f _ min.f ELSE { FOR delta: NAT _ 16, delta/4 UNTIL delta=0 DO WHILE min.f+delta <= max.f -- OR EXIT below -- DO margin: Box ~ [min: [s: min.s, f: max.f-delta], max: max]; IF IsAll[map, margin, background] THEN max.f _ max.f-delta ELSE EXIT; ENDLOOP; WHILE min.f+delta <= max.f -- OR EXIT below -- DO margin: Box ~ [min: min, max: [s: max.s, f: min.f+delta]]; IF IsAll[map, margin, background] THEN min.f _ min.f+delta ELSE EXIT; ENDLOOP; ENDLOOP; }; RETURN [[min: min, max: max]]; }; TileFromStipple: PUBLIC PROC [stipple: WORD, bitsPerSample: BitsPerSample _ 1, value0: Sample _ 0, value1: Sample _ Sample.LAST, scratch: SampleMap _ NIL] RETURNS [SampleMap] ~ { easy: BOOL ~ (16 MOD (bitsPerSample*4) = 0) OR (bitsPerSample=8 AND Basics.BITAND[stipple, 3333H] = Basics.BITAND[stipple/4, 3333H]); size: Vec ~ IF easy THEN [s: 4, f: 16/bitsPerSample] ELSE [s: 8, f: 16]; temp: SampleMap ~ ObtainScratchMap[[[0, 0], [4, 4]], bitsPerSample]; tile: SampleMap ~ NewSampleMap[box: [zeroVec, size], bitsPerSample: bitsPerSample]; Clear[tile]; FOR s: NAT DECREASING IN [0..4) DO FOR f: NAT DECREASING IN [0..4) DO Put[temp, [s: s, f: f], (IF (stipple MOD 2)=0 THEN value0 ELSE value1)]; stipple _ stipple/2; ENDLOOP; ENDLOOP; Tile[map: tile, tile: temp]; ReleaseScratchMap[temp]; RETURN[tile]; }; QR: TYPE ~ RECORD [quotient: INTEGER, remainder: NAT]; DivMod: PROC [n: INT, d: NAT] RETURNS [qr: QR] ~ { IF d#1 THEN { nn: Basics.LongNumber _ [li[n]]; qq: Basics.LongNumber _ [lc[0]]; IF nn.li < 0 THEN {nn.highbits _ nn.highbits + d; -- qq.highbits _ CARDINAL.LAST --}; [quotient: qq.lowbits, remainder: qr.remainder] _ Basics.LongDivMod[nn.lc, d]; -- quotient _ qq.li; -- qr.quotient _ LOOPHOLE[qq.lowbits]; } ELSE RETURN [[quotient: n, remainder: 0]]; }; Mod: PROC [n: INT, d: NAT] RETURNS [remainder: NAT] ~ { IF d#1 THEN { nn: Basics.LongNumber _ [li[n]]; WHILE nn.li < 0 DO nn.highbits _ nn.highbits + d ENDLOOP; WHILE nn.highbits >= d DO nn.highbits _ nn.highbits - d ENDLOOP; RETURN [Basics.LongDivMod[nn.lc, d].remainder]; } ELSE RETURN [remainder: 0]; }; QMul: PROC [a: INTEGER, b: CARDINAL] RETURNS [INT] ~ INLINE { IF a >= 0 THEN RETURN [LOOPHOLE[Basics.LongMult[a, b]]] ELSE RETURN [-LOOPHOLE[Basics.LongMult[-a, b], INT]] }; DumbTile: PROC [map: SampleMap, box: Box _ maxBox, tile: SampleMap, phase: NAT _ 0, function: Function _ nullFunction] ~ { actualBox: Box ~ SF.Intersect[map.box, box]; tileSize: Vec ~ SF.Size[tile.box]; s0: INT ~ tile.box.min.s; f0: INT ~ tile.box.min.f; FOR s: NAT IN [actualBox.min.s..actualBox.max.s) DO sTile: INT ~ s-s0; qr: QR ~ DivMod[sTile, tileSize.s]; fTile: INT ~ actualBox.min.f-(f0+QMul[qr.quotient, phase]); fOffset: NAT _ Mod[fTile, tileSize.f]; FOR f: NAT IN [actualBox.min.f..actualBox.max.f) DO value: Sample ~ Get[tile, [s0 + qr.remainder, f0 + fOffset]]; Put[map, [s, f], value, function]; fOffset _ fOffset+1; IF fOffset=tileSize.f THEN fOffset _ 0; ENDLOOP; ENDLOOP; }; GeneralTile: PROC [map: SampleMap, box: Box _ maxBox, tile: SampleMap, phase: NAT _ 0, function: Function _ nullFunction] ~ { boxes: BoxGenerator ~ { boxAction[SF.Intersect[map.box, box]] }; GeneralTileBoxes[map, boxes, tile, phase, function]; }; GetTileSamples: PUBLIC PROC [tile: SampleMap, phase: NAT, initIndex: SF.Vec, buffer: SampleBuffer] ~ { s0: INT ~ tile.box.min.s; f0: INT ~ tile.box.min.f; sOffset: INT ~ initIndex.s-s0; tileSize: Vec ~ SF.Size[tile.box]; qr: QR ~ DivMod[sOffset, tileSize.s]; fOffset: INT ~ initIndex.f-(f0+QMul[qr.quotient, phase]); srcIndexRel: Vec ~ [s: qr.remainder, f: Mod[fOffset, tileSize.f]]; srcIndex: Vec ~ SF.Add[srcIndexRel, tile.box.min]; count1: NAT ~ MIN[buffer.length, tileSize.f-srcIndexRel.f]; count2: NAT ~ MIN[buffer.length-count1, srcIndexRel.f]; count3: NAT ~ buffer.length-count1-count2; GetSamples[map: tile, initIndex: srcIndex, delta: [0, 1], buffer: buffer, start: 0, count: count1]; IF count2 # 0 THEN GetSamples[map: tile, initIndex: [srcIndex.s, tile.box.min.f], delta: [0, 1], buffer: buffer, start: count1, count: count2]; IF count3 # 0 THEN CopySamples[dst: buffer, src: buffer, dstStart: count1+count2, srcStart: 0, count: count3]; }; dumb: BOOL _ FALSE; GeneralTileBoxes: PROC [map: SampleMap, boxes: BoxGenerator, tile: SampleMap, phase: NAT _ 0, function: Function _ nullFunction] ~ { dumbGeneralTile: BoxAction ~ { DumbTile[map, box, tile, phase, function]; }; generalTile: BoxAction ~ { s0: INT ~ tile.box.min.s; f0: INT ~ tile.box.min.f; actualBox: Box ~ SF.Intersect[map.box, box]; sOffset: INT ~ actualBox.min.s-s0; tileSize: Vec ~ SF.Size[tile.box]; qr: QR ~ DivMod[sOffset, tileSize.s]; fOffset: INT ~ actualBox.min.f-(f0+QMul[qr.quotient, phase]); dstRow: Vec _ actualBox.min; srcRow: Vec _ [s: qr.remainder, f: Mod[fOffset, tileSize.f]]; WHILE dstRow.s < actualBox.max.s DO sSize: NAT ~ MIN[tileSize.s-srcRow.s, actualBox.max.s-dstRow.s]; dstCol: Vec _ dstRow; srcCol: Vec _ srcRow; WHILE dstCol.f < actualBox.max.f DO fSize: NAT ~ MIN[tileSize.f-srcCol.f, actualBox.max.f-dstCol.f]; BasicTransfer[dst: map, src: tile, dstMin: dstCol, srcMin: SF.Add[tile.box.min, srcCol], size: [s: sSize, f: fSize], function: function]; dstCol.f _ dstCol.f+fSize; srcCol.f _ 0; ENDLOOP; dstRow.s _ dstRow.s+sSize; srcRow.s _ 0; srcRow.f _ IF srcRow.f=SF.SizeF[tile.box] THEN phase _ phase MOD SF.SizeF[tile.box]; boxes[IF dumb THEN dumbGeneralTile ELSE generalTile]; }; Tile: PUBLIC PROC [map: SampleMap, box: Box _ maxBox, tile: SampleMap, phase: NAT _ 0, function: Function _ nullFunction] ~ { boxes: BoxGenerator ~ { boxAction[box] }; TileBoxes[map, boxes, tile, phase, function]; }; smallWidth: NAT _ 128; TileBoxes: PUBLIC PROC [map: SampleMap, boxes: BoxGenerator, tile: SampleMap, phase: NAT _ 0, function: Function _ nullFunction] ~ { bitsPerSample: NAT ~ map.bitsPerSample; sSizeTile: NAT ~ tile.box.max.s-tile.box.min.s; fSizeTile: NAT ~ tile.box.max.f-tile.box.min.f; selfBox: Box ~ map.box; sSizeSelf: NAT ~ selfBox.max.s-selfBox.min.s; fSizeSelf: NAT ~ selfBox.max.f-selfBox.min.f; IF phase=0 AND tile.bitsPerSample=bitsPerSample AND tile.bitsPerLine=bitsPerWord AND tile.base.bit=0 AND fSizeTile*bitsPerSample=bitsPerWord AND sSizeTile IN [1..16] AND IsPowerOfTwo[sSizeTile] AND function#[null, complement] THEN TRUSTED { bbTableSpace: PrincOps.BBTableSpace; bb: PrincOps.BBptr ~ PrincOpsUtils.AlignedBBTable[@bbTableSpace]; sTileMask: CARDINAL ~ sSizeTile-1; -- sSizeTile is a power of 2 fTileMask: CARDINAL ~ fSizeTile-1; -- So is fSizeTile (it divides the wordsize) sOffset: CARDINAL ~ Basics.BITAND[LOOPHOLE[-tile.box.min.s], sTileMask]; fOffset: CARDINAL ~ Basics.BITAND[LOOPHOLE[-tile.box.min.f], fTileMask]; lgBitsPerSample: NAT ~ Lg[bitsPerSample]; fastTile: BoxAction ~ TRUSTED { IF box.max.s > box.min.s AND box.max.f > box.min.f THEN { sDst: NAT ~ box.min.s - selfBox.min.s; fDst: NAT ~ box.min.f - selfBox.min.f; sSpace: NAT ~ selfBox.max.s - box.max.s; -- for bounds check fSpace: NAT ~ selfBox.max.f - box.max.f; dstBitIndex: CARD ~ Basics.LongMult[sDst, map.bitsPerLine] + Basics.BITSHIFT[fDst, lgBitsPerSample]; yOffset: CARDINAL ~ Basics.BITAND[sOffset+LOOPHOLE[box.min.s, CARDINAL], sTileMask]; bb.dst _ IndexBit[map.base, dstBitIndex]; bb.src.word _ tile.base.word+yOffset; bb.src.bit _ Basics.BITSHIFT[fOffset+LOOPHOLE[box.min.f, CARDINAL], lgBitsPerSample] MOD bitsPerWord; bb.srcDesc.gray.yOffset _ yOffset; bb.height _ box.max.s - box.min.s; bb.width _ Basics.BITSHIFT[box.max.f-box.min.f, lgBitsPerSample]; PrincOpsUtils.BITBLT[bb]; }; }; bb^ _ nullBitBltTable; bb.dstBpl _ map.bitsPerLine; bb.srcDesc.gray _ [yOffset: 0, widthMinusOne: 0, heightMinusOne: sSizeTile-1]; bb.flags _ [disjoint: TRUE, disjointItems: TRUE, gray: TRUE]; bb.flags.srcFunc _ function.srcFunc; bb.flags.dstFunc _ function.dstFunc; boxes[fastTile]; } ELSE IF tile.bitsPerSample#bitsPerSample OR fSizeTile*bitsPerSample < MIN[smallWidth, fSizeSelf*bitsPerSample] THEN { ns: CARDINAL ~ 1; nf: CARDINAL ~ ((smallWidth+fSizeTile-1)/fSizeTile+bitsPerSample-1)/bitsPerSample; macroTileSize: Vec ~ [s: ns*sSizeTile, f: nf*fSizeTile]; macroTileAction: PROC [macroTile: SampleMap] ~ { GeneralTile[map: macroTile, tile: tile, phase: phase]; GeneralTileBoxes[map: map, boxes: boxes, tile: macroTile, phase: ns*phase, function: function]; }; DoWithScratchMap[[tile.box.min, SF.Add[tile.box.min, macroTileSize]], bitsPerSample, macroTileAction]; } ELSE GeneralTileBoxes[map, boxes, tile, phase, function]; }; BoxesFromBitmap: PUBLIC PROC [map: SampleMap, boxAction: BoxAction] ~ { IF map.bitsPerSample = 1 THEN TRUSTED { sMin: INTEGER ~ map.box.min.s; fMin: INTEGER ~ map.box.min.f; fMax: INTEGER ~ map.box.max.f; lineStart: PrincOps.BitAddress _ map.base; IF map.box.min.f>=map.box.max.f THEN RETURN; FOR sRel: NAT IN [0..map.box.max.s-map.box.min.s) DO f: INTEGER _ map.box.min.f; wordPtr: LONG POINTER TO CARDINAL _ lineStart.word; wordsWorth: CARDINAL _ Basics.BITSHIFT[wordPtr^, lineStart.bit]; remainingBitsInWord: INTEGER _ bitsPerWord-lineStart.bit; ScanFor: UNSAFE PROC [bit: [0..1]] ~ UNCHECKED INLINE { skip: CARDINAL ~ IF bit = 0 THEN LAST[CARDINAL] ELSE 0; hiBitMask: CARDINAL ~ LAST[CARDINAL]/2+1; bitAtHigh: CARDINAL ~ IF bit = 0 THEN 0 ELSE hiBitMask; WHILE f < fMax -- or EXIT below -- DO IF remainingBitsInWord = bitsPerWord AND wordsWorth = skip THEN { f _ f + remainingBitsInWord } ELSE { f _ f + remainingBitsInWord; WHILE remainingBitsInWord > 0 AND Basics.BITAND[wordsWorth, hiBitMask] # bitAtHigh DO remainingBitsInWord _ remainingBitsInWord-1; wordsWorth _ wordsWorth*2; ENDLOOP; f _ f - remainingBitsInWord; IF remainingBitsInWord > 0 THEN EXIT; remainingBitsInWord _ bitsPerWord; }; wordPtr _ wordPtr + 1; IF f < fMax THEN wordsWorth _ wordPtr^; ENDLOOP; }; WHILE f < fMax DO fStart: INTEGER; ScanFor[1]; fStart _ f; ScanFor[0]; f _ MIN[f, fMax]; IF f > fStart THEN boxAction[[ min: [s: sMin+sRel, f: fStart], max: [s: sMin+sRel+1, f: f] ]]; ENDLOOP; lineStart _ IndexBit[lineStart, map.bitsPerLine]; ENDLOOP; } ELSE ERROR; -- Only need 1 bpp case for the Imager }; Halftone: PUBLIC PROC [map: SampleMap, min: Vec, sampleBuffer, thresholdBuffer: SampleBuffer, function: Function] ~ TRUSTED { unitsPerBuffer: NAT ~ 8*16; bitsPerBuffer: NAT ~ unitsPerBuffer*16; BitBuffer: TYPE ~ PACKED ARRAY [0..unitsPerBuffer) OF [0..65535]; bitBuffer: BitBuffer; bitBufferMap: SampleMap ~ ObtainUnsafeDescriptor[size: [s: 1, f: bitsPerBuffer], bitsPerSample: 1, bitsPerLine: bitsPerBuffer, base: [word: @bitBuffer, bit: 0], ref: NIL, words: SIZE[BitBuffer]]; count: NAT ~ MIN[sampleBuffer.length, thresholdBuffer.length]; index: SF.Vec _ min; residual: NAT _ count; s: LONG POINTER TO ARRAY [0..16) OF CARDINAL _ LOOPHOLE[InlinePointerToSamples[buffer: sampleBuffer, start: 0, count: count]]; b: LONG POINTER TO ARRAY [0..16) OF CARDINAL _ LOOPHOLE[InlinePointerToSamples[buffer: thresholdBuffer, start: 0, count: count]]; Bit: UNSAFE PROC [j: NAT] RETURNS [CARDINAL] ~ UNCHECKED INLINE {RETURN [Basics.BITSHIFT[s[j]-b[j]-1, 1-Basics.bitsPerWord]]}; WHILE residual # 0 DO chunkSize: NAT ~ MIN[bitsPerBuffer, residual]; bitBufferIndex: NAT _ 0; chunkResidual: NAT _ chunkSize; WHILE chunkResidual >= 16 DO bitBuffer[bitBufferIndex] _ ((((((((((((((Bit[0]*2+Bit[1])*2+Bit[2])*2+Bit[3])*2+Bit[4])*2+Bit[5])*2+Bit[6])*2+Bit[7])*2+Bit[8])*2+Bit[9])*2+Bit[10])*2+Bit[11])*2+Bit[12])*2+Bit[13])*2+Bit[14])*2+Bit[15]; bitBufferIndex _ bitBufferIndex + 1; chunkResidual _ chunkResidual - 16; s _ s + SIZE[ARRAY [0..16) OF CARDINAL]; b _ b + SIZE[ARRAY [0..16) OF CARDINAL]; ENDLOOP; IF chunkResidual # 0 THEN { w: CARDINAL _ 0; IF chunkSize # residual THEN ERROR; -- must be last time through FOR i: NAT IN [0..chunkResidual) DO w _ w*2 + Bit[i] ENDLOOP; bitBuffer[bitBufferIndex] _ Basics.BITSHIFT[w, 16-chunkResidual]; }; BasicTransfer[dst: map, src: bitBufferMap, dstMin: index, size: [s: 1, f: chunkSize], function: function]; index.f _ index.f + chunkSize; residual _ residual - chunkSize; ENDLOOP; ReleaseDescriptor[bitBufferMap]; }; END. IISampleImpl.mesa Copyright c 1984, 1985, 1986 by Xerox Corporation. All rights reserved. Michael Plass, December 12, 1986 2:26:47 pm PST Doug Wyatt, March 6, 1986 4:09:53 pm PST This record is to designed to avoid the need for partial-word access to the bit offset field, since the BITBLT format has carefully made this field word-aligned, and PrincOps.BitAddress has just as carefully made it hard to take advantage of this fact. Returns required number of bits, rounded up to a whole number of words. -- Eliminates crossover of the boundaries; we maintain this invariant to simplify the size calculations. -- Assumes there is no crossover. Try flushing the global function cache to get some space back. *** test for excessive size here ? *** -- Contiguous, except perhaps for some padding. -- -- Discontiguous, so do pieces (could BITBLT here; which is cheaper?) -- This is just a rectangle - do it with one BITBLT -- Checks for (pointer+i)^ = 0 for i IN [0..count) -- Number-theoretic: 0 <= remainder < d, n = quotient*d + remainder Number-theoretic: 0 <= remainder < d DumbGetTileSamples: PROC [tile: SampleMap, phase: NAT, initIndex: SF.Vec, buffer: SampleBuffer] ~ { 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] }; At exit, either f>=fMax or (high bit of wordsWorth) = bit. Note; although the number 16 appears here, we don't rely on having 16 bits per word, only that the wordsize is a multiple of 16; we do, however, assume big-endian layout. Κ>η˜codešœ™Kšœ Οmœ=™HK™/K™(—K˜šΟk ˜ Jš œžœžœžœžœj˜¨Jšœ žœ˜)Jšœžœ5˜HJšœ žœο˜ύJšœ žœ=˜KJšœžœžœ˜AJšœžœ žœ˜!Jšžœžœn˜vJšœ žœ˜Jšžœžœ˜&—K˜KšΠbl œžœž˜Kšžœ:žœž˜GKšžœ ˜Kšœžœžœ ˜˜Kšœžœžœ˜Kšœ žœžœ ˜Kšœžœžœ˜%šœžœžœ˜K˜—šœžœžœžœ˜.K˜—š Οn œžœžœ žœžœžœ˜]Kšœ˜Kš žœžœžœžœžœ˜KK˜Kšžœ˜ K˜K˜—Kšœžœ˜š œžœžœžœžœ˜RK˜—š  œžœžœžœ žœžœ˜Pšžœžœžœž˜+Kšœ,˜,šžœžœžœžœ˜/Kšœžœ˜Kšœ˜Kšžœ˜ Kšœ˜—Kšžœ˜—Kšžœžœ7˜BKšœ˜K˜—š œžœžœžœ˜CKšœžœ˜Kšœ˜šžœžœžœž˜+Jšœ*˜*Kšžœžœžœ ˜Kš žœžœ žœžœžœžœ˜CKšžœ˜—Kšœ$˜$Kšœ˜K˜—š  œžœžœ žœ žœ˜PKšœ5˜5Kšœžœ$˜;Kšœ˜Kšœ˜K˜—K˜š œžœžœ žœžœžœžœžœžœžœ˜„Jšœžœžœ˜/Kš žœžœ žœžœžœ˜DKšœ˜K˜—š œžœžœžœ žœžœžœžœžœ˜vKšžœ/˜5Kšœ˜K˜—š  œžœžœ&žœ˜FKšœžœžœ˜,šžœžœžœ˜Kšœ žœžœžœ:˜RKšœžœ ˜šžœžœžœ ž˜Kšœžœ ˜Kšœ˜Kšœ˜Kšœ˜Kšžœ˜—K˜—Kšœ˜K˜—š  œžœžœ5žœ˜UKšœžœžœ˜,šžœžœžœ˜Kšœ žœžœžœ:˜RK˜K˜EK˜—Kšœ˜K˜—š  œžœžœ5žœ˜UKš œžœžœžœžœ˜Kšžœ žœžœ˜Kšœ žœžœžœ:˜UKšœ žœžœžœ:˜UKšœG˜GK˜—Kšœ˜K˜—š  œžœžœ&žœ˜GKšœžœžœ˜,šžœžœžœ˜Kšœ žœžœžœ:˜RKšœ5˜5K˜—Kšœ˜K˜—K˜Kšœ žœ˜&Kšœžœ˜,šœ)˜)Kšœ žœ˜$Kšœ žœ ˜/Kšœ˜Kšœ˜K˜—š   œžœžœžœžœžœ˜:Kšžœžœ ˜ Kšœ˜K˜—š   œžœ žœžœžœžœ˜=KšžœL˜RKšœ˜K˜—š  œžœžœžœžœ ˜+Kšœžœ˜šžœž˜Kšœ ˜ Kšœ˜Kšžœ˜—Kšœ˜K˜—š  œžœ%žœžœžœžœ˜jšœžœžœž œžœ žœžœ žœ˜PKšœό™ό—Kšœ žœžœžœ˜5Kšœžœ˜Dšžœžœ˜KšœD˜DKšœžœ ˜ Kšœ˜—Kšœ˜K˜—K˜š œžœžœ žœžœžœžœ˜NK™GKšžœžœ8žœžœ˜hKšœ˜K˜—š  œžœžœ žœžœžœžœ˜Kšžœžœ˜#Kšžœžœ1˜Kšœ9˜9Kšœ=˜=Kšœ%˜%Kšœ`˜`K˜Kšœ&˜&Kšœ˜—Kšœ˜K˜—š   œžœžœRžœžœ˜‰Kšœ žœ ˜šœžœžœ ž˜0Kšœ,žœ˜C—šžœžœ˜$KšœG˜GKšœ:˜:Kšœ˜—Kšœ˜K˜—š œžœžœ&žœ˜\Kšœ žœ:˜JK˜&Kšœžœžœ˜&Kš œ žœžœžœžœ žœ˜@Kšœžœ+˜5šžœžœ˜$KšœG˜GKšœB˜BKšœ1˜1Kšœ˜—K˜K˜—Kšœžœ˜Kšœ(˜(š œžœžœ žœžœ˜?K˜—š   œžœžœžœžœžœ˜Sšžœžœžœ˜šžœ˜Kšžœžœ˜šžœ˜Kšœ&˜&Kšœ$˜$Kšœ žœ˜$Kšœ˜——Kšžœžœžœ ˜Kšœ˜—Kšœ˜K˜—š œžœžœžœ˜9šžœžœžœž˜%Kš žœžœžœžœžœ˜IKšžœ˜—šžœžœžœ!žœ˜7Kšœžœ˜Kšœ žœ˜Kšœ$˜$Kšœ&˜&Kšœ˜—Kšœ˜K˜—K˜š  œžœžœžœ˜=Jšœžœ˜)šœ žœ˜Kšœžœ1˜DKšœžœ1˜D—Kšœ˜Kšœ(˜(Kšœ˜K˜—š  œžœžœ žœ˜@Kšœžœ˜)Kšœžœ˜)Kšœ˜K˜—š œžœžœžœ9žœ"žœ žœ žœž œ˜ΨJšœ2žœ•˜ΙKšœžœ˜!Kšœ ˜ Kšœ˜Kšžœ˜ Kšœ˜K˜—š  œžœžœ(žœžœ˜[Kšœ$˜$Kšœ˜Kšœ˜Kšžœ˜ Kšœ˜K˜—š œžœžœžœ˜DKšžœ.˜4Kšœ˜K˜—š œžœžœžœ˜GKšžœ/˜5Kšœ˜K˜—š  œžœžœžœ˜@Kšžœžœ!˜CKšœ˜K˜—š œžœžœ(žœ˜PJšœ+˜+JšœO˜OJšœ˜Jšœ˜Kšžœ˜ Kšœ˜K˜—K˜Kšœžœ˜š œ žœžœ žœžœ˜=K˜—š œžœžœ+žœ˜_Kšœ žœ ˜Kšœ žœ?˜OKšœžœ:˜Eš  œžœžœžœžœ˜<šžœžœžœž˜"Jšœ˜š žœžœžœžœžœž˜&šœ˜šžœžœ˜Kšœžœ˜Kšœ ˜ Kšœ ˜ Kšœ˜K˜$Kšžœ˜ Kšœ˜—K˜—Kšžœžœ˜—Kšžœ˜—Kšžœžœ˜ Kšœ˜—Kšœ"˜"šžœžœžœ˜KšœB˜BKšœ>˜>Kšœ˜—Kšžœ˜ Kšœ˜K˜—š œžœžœžœ˜9Kšœ˜Kšœžœ˜K™&Kšžœžœžœžœ˜Kš žœ žœžœžœžœžœ˜Hšžœžœžœž˜"Jšœ˜Kšžœžœžœ ˜Kšžœžœ žœžœžœžœžœ˜SKšžœ˜—Kšœ˜Kšœ˜K˜—š œžœžœ˜ šžœžœžœž˜"Jšœžœ˜Kšžœ˜—Kšœ˜K˜—š œžœžœ3žœ˜eKšœ:˜:Kšœžœ ˜7Kšœ˜Kšœ˜K˜—K˜š œžœžœžœ˜/Kšœ˜Kšœ žœ˜#Kšœ žœžœ˜&Kšœžœ*˜>šžœžœ˜'K™2KšœžœE˜PKšœžœ˜#šžœž˜Kšœ'˜'Kšœ˜Kšœ˜Kšžœ˜—Kšœ(˜(Kšœ˜—šžœ˜K™HKšœžœ.˜?Kšœžœ˜šžœžœžœ ž˜KšœQ˜QKšœ˜Kšœ$˜$Kšœ žœ ˜Kšžœ˜—Kšœ˜—Kšœ˜K™—K˜š  œžœžœžœ žœ˜JKšœ˜Kšœ žœ˜$Kšœžœ˜'šœ žœ˜KšœD˜DKšœ@˜@—Kšœ?˜?šžœžœžœ˜!Kšœ žœžœžœ&˜>Kšžœžœ ˜/K˜—šžœžœ˜Kšœ žœžœžœ#˜;Kšœ žœ0˜AKšœžœ žœ˜1šœ žœžœ˜$Kšžœžœ˜*Kšžœžœ žœ˜V—Kšžœžœ˜)K˜—Kšœ˜K˜—š œžœžœT˜dKšœ˜Kšœ žœ˜$Kšœžœ˜'šœ žœ˜KšœD˜DKšœ@˜@—Kšœ?˜?šžœžœžœžœ˜;Kšœ žœžœžœ&˜>Kšœžœžœ˜5K˜—šžœžœ˜K˜$KšœA˜AK˜Kšœ˜Kšœ˜Kšœ'˜'K˜Kšœ˜Kšœžœžœžœ˜>Kšœ$˜$Kšœ$˜$Kšœžœ˜K˜—Kšœ˜K˜—K˜š   œžœžœdžœ žœ˜žJšœžœžœ˜,Kšœ˜Kšœ žœ˜)šžœžœžœ˜Jšœ žœ˜#Jšœžœ˜'JšœA˜AJ˜$Kšœžœžœ/˜Jšœ žœ˜KšœD˜DKšœD˜D—šœ žœ˜Kšœ(˜(Kšœ(˜(—Kšœžœ˜#Kšœžœ˜Kšœžœ˜Kšžœ žœI˜ZKšžœ žœI˜Zš žœžœžœžœžœžœž˜TKšœ7˜7Kšžœ˜—Jšœžœ˜,Jšœ;˜;Kšœ˜Kšœ'˜'Kšœžœ˜1Kšœ'˜'Kšœ˜Kšœžœžœžœ˜>š žœžœžœ žœ ž˜0Kšœ)˜)Kšœžœ˜:Kšœ˜Jšœžœ˜Kšœ(˜(Kšžœ˜—K˜—Kšœ˜K˜—š   œžœžœdžœ žœ3˜ΑJšœžœžœ˜,Kšœ˜Kšœ žœ˜)šžœ žœžœ˜Jšœ žœ˜#Jšœžœ˜'JšœA˜AJ˜$Kšœžœžœ/˜Jšœ žœ˜KšœD˜DKšœD˜D—šœ žœ˜Kšœ(˜(Kšœ(˜(—Kšœžœ˜#Kšœžœ˜Kšœžœ˜Kšžœ žœI˜ZKšžœ žœI˜Zš žœžœžœžœžœžœž˜TKšœ7˜7Kšžœ˜—Jšœžœ˜,Kšœ˜Kšœžœžœžœ˜>Kšœ$˜$Kšœ$˜$Kšœ˜Kšœ'˜'Kšœžœ˜Kšœ$˜$Kšœ$˜$Kšœžœ˜Kšœ˜—Kšžœ:˜>Kšœ˜K˜—š  œžœžœSžœ˜tKšœ*˜*K˜$KšœD˜Dšœžœ˜#Kšœžœ˜&Kšœžœ˜&Kšœ žœžœ.žœ‘˜ŽKšœ˜Kšœ)˜)Kšœ˜Kšœ#˜#Kšœ žœ ‘˜5Kšœ žœ ˜Kšœžœ˜Kšœ˜—Kšœ˜Kšœ˜Kšœžœžœžœ˜AKšœ'˜'Kšœ'˜'Kšœ˜Kšœ˜K˜—š  œžœžœ+žœžœ0žœ˜‹Kšœ*˜*K˜$KšœA˜AKšœžœžœ˜&Kšœ˜Kšœ˜Kšœžœžœžœ˜>Kšœ$˜$Kšœ$˜$šžœžœžœž˜Kšœžœ˜(Kšœžœ˜(Kšœ žœžœ0žœ‘˜’Kšœ)˜)Kšœ˜Kšœ%˜%Kšœ žœ‘˜7Kšœ žœ˜Kšœžœ˜Kšœžœ˜Kšžœ˜—Kšœ˜K˜—š œžœžœ^˜sKšœ žœžœ˜>Kš žœžœžœ<žœžœ ˜”Kšœ˜K˜—K˜š  œ˜K˜Ršžœžœžœž˜Kšœ2žœ˜PKšžœ˜—Kšœ˜K˜—š  œžœžœt˜ŽKšœžœ˜'šžœ!žœžœ˜1Kšœ˜Kšœžœ˜*Kšœžœ˜+K˜$KšœA˜Ašœžœ˜#šžœžœžœ˜9Kšœ žœ‘˜;Kšœ žœ˜'Kšœ žœ˜'Kšœ žœ˜'šœ žœ˜Kšœžœ-˜EKšœžœ)˜A—šœ žœ˜Kšœžœ-˜EKšœžœ)˜A—Kšœ)˜)Kšœ)˜)Kšœ žœžœ˜AKšœ žœ˜*Kšœžœ˜Kšœ˜—K˜—Kšœ˜Kšœ˜Kšœ'˜'Kšœžœžœžœ˜>Kšœ$˜$Kšœ$˜$Kšœ˜Kšœ˜—šžœ˜šœ˜Kšœ˜Kšœ!˜!KšœI˜IKšœ˜—Kšœ˜K˜—Kšœ˜K˜—K™š œžœžœ{žœ˜•Kšœ ˜ Kšœžœ˜&Kšœžœ˜&Kšœžœ˜&Kšœžœ˜&Kšœžœ’œ’œ˜FKš œžœ’œ’œ ’œ˜FKšœžœ˜'Kšœ žœ˜#šœ žœ˜Kšœ)˜)Kšœ)˜)—šœ žœ˜Kšœ)˜)Kšœ)˜)—K˜$KšœA˜AKšžœ žœ žœžœ˜$Kšœ˜Kšœ˜Kšœ#˜#Kšœ˜Kšœžœ˜!Kšœžœžœžœ˜>Kšœ$˜$Kšœ$˜$š žœ#žœžœžœžœ˜‹Kšœžœ‘˜4Kšžœžœžœ‘˜Lšžœžœžœžœ˜HKšœžœ)˜4Kšœ‘˜3Kšœ-˜-Kšœ"˜"Kšœ"˜"K˜—Kšœ˜—Kšœ)˜)Kšœ)˜)Kšœžœ˜Kšœ˜K˜—K™š œžœZ˜hKšœžœ˜,šžœžœžœ$ž˜3šžœžœžœ$ž˜3Kšœ"˜"Kšžœ˜—Kšžœ˜—Kšœ˜K˜—šœ žœžœ Οf&œ˜NK˜—š œžœžœQ˜bKšœžœ˜'Kšœ žœ˜#šžœžœžœžœ˜3Kšœžœ˜,Kšœžœžœ˜&Kšœžœžœ˜&šœ žœ˜Kšœ>˜>Kšœ>˜>—K˜$KšœA˜AKšœ žœ žœ˜4Kšœžœ žœ1˜Všžœžœ˜'Kš‘Πbc‘˜=Kšœžœžœ˜,Kšœ˜Kšœ˜—Kšœ˜Kšœ)˜)Kšœ˜Kšœ˜KšœD˜DKšœ˜Kšœ˜Kšœžœžœžœ˜=Kšœ$˜$Kšœ$˜$Kšœžœ˜Kšœ˜—Kšžœ@˜DKšœ˜K˜—š  œžœžœi˜Kšœžœ˜'šžœžœžœžœ˜3Kšœžœ˜)Kšœ žœ˜#K˜$KšœA˜AKšœ˜šœžœ˜šžœžœžœ˜9Kšœ žœ‘˜;Kšœ žœ˜'šœ žœ˜Kšœžœ)˜—Kšœ)˜)Kšœžœžœ(˜KKšœ žœ˜*Kšœžœ˜Kšœ˜—K˜—Kšœ žœ žœ˜4Kšœžœ žœ/˜Tšžœžœ˜'Kš‘€‘˜=Kšœžœžœ˜,Kšœ˜Kšœ˜—Kšœ˜Kšœ˜Kšœ˜KšœD˜DKšœžœžœžœ˜=Kšœ$˜$Kšœ$˜$Kšœ˜Kšœ˜—šžœ˜Kšœ>˜>Kšœ˜K˜—Kšœ˜K˜—š   œžœžœ!žœ4žœ˜yKš œžœžœžœžœ&˜WKšœžœžœžœ˜:Kšœžœ˜'Kšœžœ‘(˜VKšœžœ‘'˜QK˜$KšœD˜Dš œ žœžœžœ žœžœ˜cšœžœžœ ˜Kšžœ žœ1žœ ˜PKšžœ žœ1žœ ˜OK˜—šžœžœžœžœ˜]Kšœžœ ˜Kšœ˜Kšœ˜Kšœžœžœ"˜5Kšœ žœ ˜Kšœ˜Kšœžœžœž œžœ žœžœ žœ˜PKšœ žœ$žœ"˜^Kšœžœžœžœ ˜.Kšœ žœ˜#šžœžœžœ˜Ešžœ˜Kšœ*ž™0Kšœžœ˜"Kšœžœ˜"Kšžœ žœžœ˜3Kšžœžœ˜&Kšžœžœ˜&šžœ žœ˜Kšœžœžœžœ˜@Kšœ1˜1Kšœžœ ˜'Kšœ˜Kšœžœžœ˜=Kšœžœ˜Kšœ˜—Kšœ ˜ Kšœ˜—šžœ˜Kšœ˜šžœ ž˜Kšœžœ˜"Kšœžœ˜"Kšžœ žœžœ˜3Kšžœžœ˜&Kšžœžœ˜&šžœžœ žœ˜$Kšœžœžœžœ˜@Kšœ1˜1Kšœžœ ˜'Kšœžœžœ˜=Kšœžœ˜Kšœ˜—Kšœžœ ˜ Kšœžœ ˜ šœ žœ˜,Kšœ1˜1Kšœžœ ˜%K˜—Kšœ ˜ Kšžœ˜—Kšœ˜——Kšœ˜Kšœ˜Kšœ˜—Kšœ ˜ Kšœ˜—Kšœ žœ žœ˜4Kšœžœ žœ/˜Tšžœžœ˜'Kš‘€‘˜=Kšœžœžœ˜,Kšœ˜Kšœ˜—Kšœ˜Kšœ˜Kšœ"˜"KšœG˜GKšœžœžœžœ˜@Kšœ'˜'Kšœ'˜'Kšœ˜Kšœ˜Kšœ˜K˜—K™š œžœ žœžœ žœžœžœžœ˜JKšœ%žœ™5Kšœžœ˜Kš œ žœ žœžœžœ˜+K˜$KšœA˜AKšœ˜Kšœ˜Kšœ)˜)Kšœ˜Kšœ˜Kšœžœžœ˜>Kšœ˜Kšœ˜Kšžœžœžœ˜/Kšœ:˜:Kšœ˜Kšœžœ˜Kšžœžœžœ˜.Kšžœžœžœžœžœžœžœžœžœžœ˜TKšžœžœ˜Kšœ˜K˜—š  œžœžœžœ žœžœ˜Gšœ žœ˜&Kšœ žœžœ˜ Kšœ žœžœ˜#Kšœ žœ-˜;Kšœ ˜ šžœžœžœ ž˜3Kšœ3˜3KšœJ˜JKš žœžœ"žœ žœžœ˜EKšžœ˜—K˜—Kš žœžœžœžœžœž˜2Kšžœžœ ž˜*šžœ˜Kšœžœžœ%˜AKš œ žœžœžœžœžœ˜FKšœ˜Kšœ*˜*Kšœ9˜9K˜—Kšœ˜K˜—š  œžœžœ9žœ žœžœ˜kKšœ$˜$šœ žœ˜&Kšœ žœžœ˜%Kšœ žœžœ˜#Kšœ žœ-˜;Kšœ ˜ šžœžœžœ ž˜3Kšœ8˜8Kšžœ žœC˜TKš žœžœ"žœ žœžœ˜EKšžœ˜—K˜—Kšžœžœžœž˜!šžœ˜Kš œ žœžœžœžœžœ˜PKšœ˜Kšœ*˜*Kšœ=˜=K˜—Kšœ˜Kšœ˜K˜—š œžœžœ0žœ ˜RKšœžœ˜,Kšœ3˜3šœ žœ˜&Kšœ žœ3˜AKšœ ˜ šžœ‘œž˜*J•StartOfExpansionu[dest: SampleMapOps.SampleMap, destStart: CVEC, source: SampleMapOps.SubMap, function: SampleMapOps.Function]šœW˜WJ–S[dest: SampleMapOps.SubMap, value: CARDINAL, function: SampleMapOps.Function]šžœžœJ˜^Kšžœ"žœžœžœ˜CKšžœ˜—šžœ‘œž˜*J–u[dest: SampleMapOps.SampleMap, destStart: CVEC, source: SampleMapOps.SubMap, function: SampleMapOps.Function]šœU˜UJ–S[dest: SampleMapOps.SubMap, value: CARDINAL, function: SampleMapOps.Function]šžœžœJ˜^Kšžœ"žœžœžœ˜CKšžœ˜—K˜—Kšœ*žœK˜wšžœ ˜Kšžœ˜šžœ˜šžœžœžœ ž˜-šžœ‘œž˜1Kšœ:˜:Kšžœ žœžœžœ˜EKšžœ˜—šžœ‘œž˜1Kšœ:˜:Kšžœ žœžœžœ˜EKšžœ˜—Kšžœ˜—Kšœ˜——Kšžœ˜Kšœ˜K˜—K™š œžœžœ žœPžœžœžœ˜²Kš œžœžœžœžœžœžœ˜…Kšœ žœžœžœ˜HKšœD˜DKšœS˜SK˜ š žœžœž œžœž˜"š žœžœž œžœž˜"Kš œžœ žœžœžœ ˜HKšœ˜Kšžœ˜—Kšžœ˜—Kšœ˜Kšœ˜Kšžœ˜ Kšœ˜K˜—K™š žœžœžœ žœ žœ˜6K˜—š  œžœžœžœžœžœ˜2Kšœ@™@šžœžœ˜ Kšœ ˜ Kšœ ˜ Kšžœ žœ!‘!œ˜UKšœN˜NKšœ˜Kšœžœ ˜#Kšœ˜—Kšžœžœ˜*Kšœ˜K˜—š  œžœžœžœžœ žœ˜7Kšœ$™$šžœžœ˜ Kšœ ˜ Kšžœ žœžœ˜9Kšžœžœžœ˜@Kšžœ)˜/Kšœ˜—Kšžœžœ˜Kšœ˜K˜—š œžœžœžœžœžœžœ˜=Kšžœžœžœžœ˜7Kšžœžœžœžœ˜4Kšœ˜K˜—K˜š œžœ=žœ,˜zKšœžœ˜,Kšœžœ˜"Kšœžœ˜Kšœžœ˜šžœžœžœ$ž˜3Kšœžœ˜Kšœžœ˜#Kšœžœ1˜;Kšœ žœ˜&šžœžœžœ$ž˜3Kšœ=˜=Kšœ"˜"Kšœ˜Kšžœžœ ˜'Kšžœ˜—Kšžœ˜—Kšœ˜K˜—š  œžœ=žœ,˜}Kšœ"žœ˜@K˜4K˜K˜—š œžœžœ žœ™cK–T[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™K™—š  œžœžœžœ žœ˜fKšœžœ˜Kšœžœ˜Kšœ žœ˜Kšœžœ˜"Kšœžœ˜%Kšœ žœ-˜9KšœB˜BKšœžœ ˜2K–²[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–²[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]šœžœžœ&˜7K–²[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šœc˜cKšžœ žœ}˜Kšžœ žœ\˜nK˜K˜—Kšœžœžœ˜š œžœ?žœ,˜„šœ˜K˜*K˜—˜Kšœžœ˜Kšœžœ˜Kšœžœ˜,Kšœ žœ˜"Kšœžœ˜"Kšœžœ˜%Kšœ žœ1˜=Kšœ˜Kšœ=˜=šžœž˜#Kšœžœžœ0˜@K˜K˜šžœž˜#Kšœžœžœ0˜@Kšœ;žœL˜‰K˜K˜ Kšžœ˜—K˜K˜ Kšœ žœžœžœ˜RKšžœ˜—K˜—Kš žœžœžœžœžœ˜GKšœžœžœžœ˜5Kšœ˜K˜—š œžœžœ=žœ,˜}K˜)K˜-K˜K˜—šœ žœ˜K˜—š  œžœžœ?žœ,˜„Kšœžœ˜'Kšœ žœ!˜/Kšœ žœ!˜/K˜Kšœ žœ˜-Kšœ žœ˜-šžœ žœ"žœžœžœ%žœ žœ žœžœžœžœ˜πK˜$KšœA˜AKšœ žœ‘˜?Kšœ žœ‘,˜OKšœ žœ žœžœ˜HKšœ žœ žœžœ˜HKšœžœ˜)šœžœ˜šžœžœžœ˜9Kšœžœ˜&Kšœžœ˜&Kšœžœ‘˜=Kšœžœ˜(šœ žœ˜Kšœ(˜(Kšœžœ˜'—Kš œ žœ žœ žœ žœ˜TKšœ)˜)Kšœ%˜%Kš œžœ žœ žœžœ ˜eKšœ"˜"Kšœ"˜"Kšœžœ'˜AKšœžœ˜Kšœ˜—Kšœ˜—Kšœ˜Kšœ˜KšœN˜NKšœžœžœžœ˜=Kšœ$˜$Kšœ$˜$Kšœ˜Kšœ˜—š žœžœ#žœžœ&žœ˜vKšœžœ˜KšœžœF˜RKšœ8˜8šœžœ˜0Kšœ6˜6Kšœ_˜_Kšœ˜—Kšœ žœD˜fK˜—Kšžœ5˜9Kšœ˜K˜—š œžœžœ+˜Gšžœ˜šžœžœ˜Kšœžœ˜Kšœžœ˜Kšœžœ˜Kšœ*˜*Kšžœžœžœ˜,šžœžœžœ"ž˜4Kšœžœ˜Kš œ žœžœžœžœ˜3Kšœ žœ žœ˜@Kšœžœ˜9š  œžœžœž œžœ˜7Kšœ:™:Kš œžœžœ žœžœžœžœ˜7Kšœ žœžœžœ˜)Kš œ žœžœ žœžœ ˜7šžœ ‘œž˜%šžœ#žœ˜:Kšžœ ˜$šžœ˜Kšœ˜šžœžœžœ$ž˜UKšœ,˜,Kšœ˜Kšžœ˜—Kšœ˜Kšžœžœžœ˜%Kšœ"˜"Kšœ˜——Kšœ˜Kšžœ žœ˜'Kšžœ˜—Kšœ˜—šžœ ž˜Kšœžœ˜Kšœ ˜ Kšœ ˜ Kšœ ˜ Kšœžœ ˜šžœ žœ ˜Kšœ˜Kšœ˜Kšœ˜—Kšžœ˜—Kšœ1˜1Kšžœ˜—Kšœ˜—Kšžœžœ‘&˜2—Kšœ˜—K˜š œžœžœ_žœ˜}K™ͺKšœžœ˜Kšœžœ˜'Kš œ žœžœžœžœ ˜AKšœ˜Kšœ¦žœ žœ ˜ΓKšœžœžœ.˜>Kšœžœ ˜Kšœ žœ ˜Jšœžœžœžœžœ žœžœžœG˜~Jšœžœžœžœžœ žœžœžœJ˜Jš œž œžœžœžœžœžœžœ žœ&˜~šžœž˜Kšœ žœžœ˜.Jšœžœ˜Jšœžœ ˜šžœž˜KšœΜ˜ΜKšœ$˜$Kšœ#˜#Kš œžœžœ žœžœ˜(Kš œžœžœ žœžœ˜(Kšžœ˜—šžœžœ˜Jšœžœ˜Kšžœžœžœ‘˜@Kš žœžœžœžœžœ˜=Kšœ#žœ˜AKšœ˜—Kšœj˜jKšœ˜Kšœ ˜ Kšžœ˜—Kšœ ˜ Kšœ˜J˜——Kšžœ˜—…—ΛTΛ