DIRECTORY DragonBitBlt, DragOpsCross, DragOpsCrossUtils, Basics, CountedVM, FunctionCache, PrincOps, PrincOpsUtils, VM, SampleMapOps, SlowSampleMapOps; DragonSampleMapOpsImpl: CEDAR MONITOR IMPORTS DragonBitBlt, DragOpsCrossUtils, Basics, CountedVM, FunctionCache, PrincOpsUtils, VM, SampleMapOps EXPORTS SlowSampleMapOps ~ BEGIN bitsPerWord: NAT ~ Basics.bitsPerWord; Buffer: TYPE ~ SampleMapOps.Buffer; BufferRep: TYPE ~ SampleMapOps.BufferRep; maxCount: NAT ~ SampleMapOps.maxCount; CVEC: TYPE ~ SampleMapOps.CVEC; Function: TYPE ~ SampleMapOps.Function; nullFunction: Function ~ SampleMapOps.nullFunction; lastCVEC: CVEC ~ SampleMapOps.lastCVEC; logBitsPerWord: NAT ~ Basics.logBitsPerWord; SampleMap: TYPE ~ SampleMapOps.SampleMap; SampleMapRep: TYPE ~ SampleMapOps.SampleMapRep; SubMap: TYPE ~ SampleMapOps.SubMap; seedWord: WORD _ 123456B; 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]]}; Check: PROC[x: CARDINAL, max: NAT] RETURNS [NAT] ~ TRUSTED MACHINE CODE { PrincOps.zINC; PrincOps.zBNDCK }; IsPowerOfTwo: PROC [c: CARDINAL] RETURNS [BOOLEAN] ~ INLINE { RETURN [BITAND[c, c-1] = 0] }; WordCountFromBit: PROC [bitCount: LONG CARDINAL] RETURNS [LONG CARDINAL] ~ { 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; }; RoundUp: PROC [a: NAT] RETURNS [x: NAT] ~ INLINE { x _ BITAND[a+(DragOpsCross.bitsPerWord-1), CARDINAL.LAST-(DragOpsCross.bitsPerWord-1)]; }; ConvertToDragonBitAddress: PROC[ba: PrincOps.BitAddress] RETURNS[da: DragonBitBlt.DragonBitAddress] = TRUSTED { da.word _ LOOPHOLE[LOOPHOLE[ba.word, INT]/2, DragonBitBlt.DragonPointer]; da.bit _ ba.bit; IF Basics.BITAND[LOOPHOLE[ba.word, Basics.LongNumber].lo, 1B] = 0 THEN RETURN; da.bit _ da.bit + bitsPerWord; }; SpecialConvertToDragonBitAddress: PROC[ba: PrincOps.BitAddress] RETURNS[da: DragonBitBlt.DragonBitAddress] = TRUSTED { da.word _ LOOPHOLE[LOOPHOLE[ba.word, INT]/2, DragonBitBlt.DragonPointer]; da.bit _ ba.bit; IF Basics.BITAND[LOOPHOLE[ba.word, Basics.LongNumber].lo, 1B] = 0 THEN RETURN; da.word _ LOOPHOLE[da.word+1]; }; DstFunc: PROC[function: Function] RETURNS[dstFunc: DragonBitBlt.DstFunc] = { SELECT function.dstFunc FROM null => dstFunc _ null; and => dstFunc _ and; or => dstFunc _ or; xor => dstFunc _ xor; ENDCASE => NULL; }; SrcFunc: PROC[function: Function] RETURNS[srcFunc: DragonBitBlt.SrcFunc] = { srcFunc _ IF function.srcFunc = null THEN null ELSE complement; }; smallSize: NAT _ 511; WordSeqRep: TYPE ~ RECORD [SEQUENCE length: NAT OF WORD]; Create: PUBLIC PROC [sSize: CARDINAL, fSize: CARDINAL, bitsPerSample: [0..Basics.bitsPerWord]] RETURNS [s: SampleMap] ~ { RETURN[CreateSampleMap[sSize, fSize, bitsPerSample, none]] }; CreateZ: PUBLIC PROC [sSize: CARDINAL, fSize: CARDINAL, bitsPerSample: [0..Basics.bitsPerWord]] RETURNS [s: SampleMap] ~ { RETURN[CreateSampleMap[sSize, fSize, bitsPerSample, zeros]] }; CreateO: PUBLIC PROC [sSize: CARDINAL, fSize: CARDINAL, bitsPerSample: [0..Basics.bitsPerWord]] RETURNS [s: SampleMap] ~ { RETURN[CreateSampleMap[sSize, fSize, bitsPerSample, ones]] }; HowToInit: TYPE = {none, zeros, ones}; CreateSampleMap: PROC [ sSize: CARDINAL, fSize: CARDINAL, bitsPerSample: [0..Basics.bitsPerWord], how: HowToInit] RETURNS [s: SampleMap] ~ { bitsPerLine: NAT ~ RoundUp[Basics.LongMult[fSize, bitsPerSample]]; nWords: LONG CARDINAL ~ Basics.LongMult[sSize, bitsPerLine/bitsPerWord]; IF nWords <= smallSize THEN TRUSTED { words: NAT _ MAX[NAT[nWords], 1]; wordSeq: REF WordSeqRep _ NEW[WordSeqRep[words]]; s _ UnsafeCreate[ sSize: sSize, fSize: fSize, bitsPerSample: bitsPerSample, bitsPerLine: bitsPerLine, base: [word: @wordSeq[0], bit: 0], nWords: words, ref: wordSeq ]; } ELSE TRUSTED { vm: CountedVM.Handle ~ Allocate[nWords]; s _ UnsafeCreate[ sSize: sSize, fSize: fSize, bitsPerSample: bitsPerSample, bitsPerLine: bitsPerLine, base: [word: vm.pointer, bit: 0], nWords: vm.words, ref: vm ]; }; TRUSTED { lp: LONG POINTER TO WORD _ LOOPHOLE[s.base.word]; initVal: WORD; SELECT how FROM none => initVal _ seedWord; zeros => initVal _ 0; ones => initVal _ 177777B; ENDCASE => initVal _ seedWord; FOR i: LONG CARDINAL IN [0..nWords) DO IF how # none THEN lp^ _ initVal ELSE IF lp^ = 0 THEN lp^ _ initVal _ Basics.BITNOT[initVal]; lp _ LOOPHOLE[lp + 1]; ENDLOOP; }; }; Allocate: PROC [nWords: LONG CARDINAL] 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]; vm _ CountedVM.SimpleAllocate[nWords]; }; }; Copy: PUBLIC PROC [subMap: SubMap] RETURNS [SampleMap] ~ { s: SampleMap ~ subMap.sampleMap; sMin: NAT ~ Check[subMap.start.s, s.sSize]; fMin: NAT ~ Check[subMap.start.f, s.fSize]; sSize: NAT ~ MIN[subMap.size.s, LOOPHOLE[s.sSize-sMin, NAT]]; fSize: NAT ~ MIN[subMap.size.f, LOOPHOLE[s.fSize-fMin, NAT]]; new: SampleMap ~ CreateO[sSize: sSize, fSize: fSize, bitsPerSample: s.bitsPerSample]; Transfer[dest: new, destStart: [0, 0], source: subMap, function: [null, null], goodDest: NIL]; RETURN [new]; }; DoubleCopy: PUBLIC PROC [to, slowTo, from: SampleMap, destStart: CVEC] = { SampleMapOps.Transfer[dest: to, destStart: destStart, source: [from], function: [null, null]]; Transfer[dest: slowTo, destStart: destStart, source: [from], function: [null, null], goodDest: to]; }; ComputeWords: PROC [sSize: CARDINAL, fSize: CARDINAL, bitsPerSample: [0..bitsPerWord]] RETURNS [LONG CARDINAL] ~ { bitsPerLine: NAT ~ RoundUp[Basics.LongMult[fSize, bitsPerSample]]; RETURN [Basics.LongMult[sSize, bitsPerLine/bitsPerWord]] }; nullBitBltTable: DragonBitBlt.BitBltTable ~ [ dst: [word: NIL, bit: 0], dstBpl: 0, src: [word: NIL, bit: 0], srcDesc: [srcBpl[0]], width: 0, height: 0, flags: [] ]; disjointBitBltTable: DragonBitBlt.BitBltTable ~ [ dst: [word: NIL, bit: 0], dstBpl: 0, src: [word: NIL, bit: 0], srcDesc: [srcBpl[0]], width: 0, height: 0, flags: [disjoint: TRUE, disjointItems: TRUE] ]; grayBitBltTable: DragonBitBlt.BitBltTable ~ [ dst: [word: NIL, bit: 0], dstBpl: 0, src: [word: NIL, bit: 0], srcDesc: [srcBpl[0]], width: 0, height: 0, flags: [disjoint: TRUE, disjointItems: TRUE, gray: TRUE] ]; UnsafeCreate: PUBLIC UNSAFE PROC [sSize: CARDINAL, fSize: CARDINAL, bitsPerSample: [0..Basics.bitsPerWord], bitsPerLine: NAT, base: PrincOps.BitAddress, nWords: LONG CARDINAL, ref: REF, scratchDescriptor: SampleMap _ NIL] RETURNS [SampleMap] ~ { dataBitsPerLine: LONG CARDINAL ~ Basics.LongMult[fSize, bitsPerSample]; fillBits: NAT ~ bitsPerLine-dataBitsPerLine; totalBits: LONG CARDINAL ~ Basics.LongMult[sSize, bitsPerLine]-fillBits+base.bit; wrds: LONG CARDINAL ~ WordCountFromBit[totalBits]; check: BOOL[FALSE..FALSE] ~ (nWords < wrds); s: SampleMap ~ IF scratchDescriptor#NIL THEN scratchDescriptor ELSE NEW[SampleMapRep]; s^ _ [ sSize: sSize, fSize: fSize, bitsPerSample: bitsPerSample, base: base, bitsPerLine: bitsPerLine, ref: ref ]; RETURN [s]; }; GetSample: PUBLIC PROC [sampleMap: SampleMap, index: CVEC] RETURNS [CARDINAL] ~ TRUSTED { s: CARDINAL ~ Basics.BoundsCheck[index.s, sampleMap.sSize]; f: CARDINAL ~ Basics.BoundsCheck[index.f, sampleMap.fSize]; bitsPerSample: NAT ~ sampleMap.bitsPerSample; bitIndex: LONG CARDINAL ~ sampleMap.base.bit + Basics.LongMult[s, sampleMap.bitsPerLine] + Basics.LongMult[f, bitsPerSample]; bitAddress: PrincOps.BitAddress ~ IndexBit[sampleMap.base.word, [lc[bitIndex]]]; pointer: LONG POINTER TO ARRAY [0..1] OF WORD ~ bitAddress.word; shiftAmt: INTEGER ~ bitAddress.bit + bitsPerSample - bitsPerWord; mask: CARDINAL ~ Shift[1, bitsPerSample]-1; shiftedBits: CARDINAL ~ IF shiftAmt <= 0 THEN Shift[pointer^[0], shiftAmt] ELSE Shift[pointer^[0], shiftAmt] + Shift[pointer^[1], shiftAmt-16]; RETURN [BITAND[shiftedBits, mask]] }; PutSample: PUBLIC PROC [sampleMap: SampleMap, index: CVEC, value: CARDINAL, function: Function, goodDest: SampleMap] ~ TRUSTED { s: CARDINAL ~ Basics.BoundsCheck[index.s, sampleMap.sSize]; f: CARDINAL ~ Basics.BoundsCheck[index.f, sampleMap.fSize]; bitsPerSample: NAT ~ sampleMap.bitsPerSample; bitIndex: LONG CARDINAL ~ sampleMap.base.bit + Basics.LongMult[s, sampleMap.bitsPerLine] + Basics.LongMult[f, bitsPerSample]; bbPtr: DragonBitBlt.BitBltTable; bb: DragonBitBlt.BitBltTablePtr _ @bbPtr; bb^ _ [ dst: ConvertToDragonBitAddress[IndexBit[sampleMap.base.word, [lc[bitIndex]]]], dstBpl: 0, src: ConvertToDragonBitAddress[[word: @value, bit: bitsPerWord-bitsPerSample]], srcDesc: [srcBpl[0]], height: 1, width: bitsPerSample, flags: [direction: forward, disjoint: TRUE, disjointItems: TRUE, gray: FALSE, srcFunc: SrcFunc[function], dstFunc: DstFunc[function]] ]; DragonBitBlt.BITBLT[bb]; }; DumbTransfer: PROC [dest: SampleMap, destStart: CVEC, source: SubMap, function: Function, goodDest: SampleMap] ~ { sSize: NAT ~ MIN[source.size.s, dest.sSize-destStart.s, source.sampleMap.sSize-source.start.s]; fSize: NAT ~ MIN[source.size.f, dest.fSize-destStart.f, source.sampleMap.fSize-source.start.f]; FOR s: NAT IN [0..sSize) DO FOR f: NAT IN [0..fSize) DO sample: CARDINAL ~ GetSample[source.sampleMap, [source.start.s+s, source.start.f+f]]; PutSample[dest, [destStart.s+s, destStart.f+f], sample, function, goodDest]; ENDLOOP; ENDLOOP; }; BitAddressOverlay: TYPE ~ MACHINE DEPENDENT RECORD [ SELECT OVERLAID * FROM ba => [bitAddress: PrincOps.BitAddress], ov => [pointer: LONG POINTER, offset: CARDINAL], ENDCASE ]; IndexBit: UNSAFE PROC [pointer: LONG POINTER, bitOffset: Basics.LongNumber] RETURNS [PrincOps.BitAddress] ~ UNCHECKED INLINE { addr: BitAddressOverlay ~ [ov[ pointer: pointer + Basics.DoubleShiftRight[bitOffset, logBitsPerWord].lc, offset: bitOffset.lo MOD bitsPerWord ]]; RETURN [addr.bitAddress] }; Transfer: PUBLIC PROC [dest: SampleMap, destStart: CVEC, source: SubMap, function: Function, goodDest: SampleMap] ~ TRUSTED { bps: NAT ~ dest.bitsPerSample; src: SampleMap ~ source.sampleMap; sSize: NAT ~ MIN[source.size.s, dest.sSize-destStart.s, source.sampleMap.sSize-source.start.s]; fSize: NAT ~ MIN[source.size.f, src.fSize-source.start.f, dest.fSize-destStart.f]; SELECT TRUE FROM source.sampleMap.bitsPerSample = bps => { bbPtr: DragonBitBlt.BitBltTable; bb: DragonBitBlt.BitBltTablePtr _ @bbPtr; dstBitIndex: LONG CARDINAL ~ dest.base.bit + Basics.LongMult[Check[destStart.s, dest.sSize], dest.bitsPerLine] + Basics.LongMult[Check[destStart.f, dest.fSize], bps]; srcBitIndex: LONG CARDINAL ~ src.base.bit + Basics.LongMult[Check[source.start.s, src.sSize], src.bitsPerLine] + Basics.LongMult[Check[source.start.f, src.fSize], bps]; bb^ _ disjointBitBltTable; bb.dst _ ConvertToDragonBitAddress[ IndexBit[dest.base.word, [lc[dstBitIndex]]] ]; bb.dstBpl _ dest.bitsPerLine; bb.src _ ConvertToDragonBitAddress[ IndexBit[src.base.word, [lc[srcBitIndex]]] ]; bb.srcDesc _ [srcBpl[src.bitsPerLine]]; bb.height _ sSize; bb.width _ fSize * bps; bb.flags.srcFunc _ SrcFunc[function]; bb.flags.dstFunc _ DstFunc[function]; DragonBitBlt.BITBLT[bb]; }; ENDCASE => DumbTransfer[dest, destStart, source, function, goodDest]; }; Move: PUBLIC PROC [sampleMap: SampleMap, destStart: CVEC, sourceStart: CVEC, size: CVEC, function: Function, goodDest: SampleMap] ~ TRUSTED { bps: NAT ~ sampleMap.bitsPerSample; bpl: NAT ~ sampleMap.bitsPerLine; sSize: NAT ~ sampleMap.sSize; fSize: NAT ~ sampleMap.fSize; bbPtr: DragonBitBlt.BitBltTable; bb: DragonBitBlt.BitBltTablePtr _ @bbPtr; dstBitIndex: LONG CARDINAL _ sampleMap.base.bit + Basics.LongMult[Check[destStart.s, sSize], bpl] + Basics.LongMult[Check[destStart.f, fSize], bps]; srcBitIndex: LONG CARDINAL _ sampleMap.base.bit + Basics.LongMult[Check[sourceStart.s, sSize], bpl] + Basics.LongMult[Check[sourceStart.f, fSize], bps]; sSamples: NAT ~ MIN[size.s, sSize-sourceStart.s, sSize-destStart.s]; fSamples: NAT ~ MIN[size.f, fSize-sourceStart.f, fSize-destStart.f]; bb^ _ disjointBitBltTable; bb.dstBpl _ bpl; bb.srcDesc _ [srcBpl[bpl]]; bb.height _ sSamples; bb.width _ bps * fSamples; bb.flags.srcFunc _ SrcFunc[function]; bb.flags.dstFunc _ DstFunc[function]; IF sSamples > 0 AND (sourceStart.f+fSamples) > destStart.f AND (destStart.f+fSamples) > sourceStart.f AND (sourceStart.s+sSamples) > destStart.s AND (destStart.s+sSamples) > sourceStart.s THEN { bb.flags.disjoint _ FALSE; -- the rectangles overlap IF sourceStart.s=destStart.s THEN bb.flags.disjointItems _ FALSE; -- so do the items IF destStart.s>sourceStart.s OR (destStart.s=sourceStart.s AND destStart.f>sourceStart.f) THEN { -- reverse direction delta: LONG CARDINAL _ Basics.LongMult[sSamples-1, bpl]; bb.flags.direction _ backward; bb.srcDesc.srcBpl _ bb.dstBpl _ -bb.dstBpl; dstBitIndex _ dstBitIndex + delta; srcBitIndex _ srcBitIndex + delta; }; }; bb.dst _ ConvertToDragonBitAddress[ IndexBit[sampleMap.base.word, [lc[dstBitIndex]]] ]; bb.src _ ConvertToDragonBitAddress[ IndexBit[sampleMap.base.word, [lc[srcBitIndex]]] ]; DragonBitBlt.BITBLT[bb]; }; DumbFill: PROC [dest: SubMap, value: CARDINAL, function: Function, goodDest: SubMap] ~ { sSize: NAT ~ MIN[dest.size.s, dest.sampleMap.sSize-dest.start.s]; fSize: NAT ~ MIN[dest.size.f, dest.sampleMap.fSize-dest.start.f]; FOR s: NAT IN [0..sSize) DO FOR f: NAT IN [0..fSize) DO PutSample[dest.sampleMap, [dest.start.s+s, dest.start.f+f], value, function, goodDest.sampleMap]; ENDLOOP; ENDLOOP; }; replicator: ARRAY [0..4] OF CARDINAL ~ [0FFFFH, 05555H, 01111H, 00101H, 00001H]; Fill: PUBLIC PROC [dest: SubMap, value: CARDINAL, function: Function, goodDest: SubMap] ~ { bps: NAT ~ dest.sampleMap.bitsPerSample; IF bitsPerWord MOD bps = 0 THEN TRUSTED { dstBitIndex: LONG CARDINAL ~ dest.sampleMap.base.bit + Basics.LongMult[Check[dest.start.s, dest.sampleMap.sSize], dest.sampleMap.bitsPerLine] + Basics.LongMult[Check[dest.start.f, dest.sampleMap.fSize], bps]; sSize: NAT ~ MIN[dest.size.s, dest.sampleMap.sSize-dest.start.s]; fSize: NAT ~ MIN[dest.size.f, dest.sampleMap.fSize-dest.start.f]; bbPtr: DragonBitBlt.BitBltTable; bb: DragonBitBlt.BitBltTablePtr _ @bbPtr; replicatedPixel: CARDINAL _ BITAND[value, Shift[1, bps]-1] * replicator[Lg[bps]]; pixelToUse: ARRAY [0..2] OF DragOpsCross.Half _ ALL[DragOpsCrossUtils.CardToHalf[replicatedPixel]]; bb^ _ grayBitBltTable; bb.dst _ ConvertToDragonBitAddress[ IndexBit[dest.sampleMap.base.word, [lc[dstBitIndex]]] ]; bb.dstBpl _ dest.sampleMap.bitsPerLine; bb.src _ SpecialConvertToDragonBitAddress[ [word: @pixelToUse, bit: 0] ]; bb.height _ MIN[dest.size.s, dest.sampleMap.sSize-dest.start.s]; bb.width _ bps*MIN[dest.size.f, dest.sampleMap.fSize-dest.start.f]; bb.flags.srcFunc _ SrcFunc[function]; bb.flags.dstFunc _ DstFunc[function]; DragonBitBlt.BITBLT[bb]; } ELSE DumbFill[dest, value, function, goodDest]; }; TileBox: PUBLIC PROC [dest: SampleMap, start: CVEC, size: CVEC, source: SampleMap, s0, f0: INTEGER, phase: NAT, function: Function, goodDest: SampleMap] ~ { boxes: PROC[box: BoxProc] ~ {box[start.s, start.f, start.s+size.s, start.f+size.f]}; TileBoxes[dest, boxes, source, s0, f0, phase, function, goodDest]; }; QR: TYPE ~ RECORD [quotient: INTEGER, remainder: NAT]; DivMod: PROC [n: INTEGER, 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]; 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]; }; EnlargedSize: PROC [fSize: NAT, bps: NAT] RETURNS [NAT] ~ { n: CARDINAL ~ ((smallWidth+fSize-1)/fSize+bps-1)/bps; RETURN [Basics.LongMult[n, fSize]] }; smallWidth: NAT _ 128; BoxProc: TYPE ~ SampleMapOps.BoxProc; TileBoxes: PUBLIC PROC [dest: SampleMap, boxes: PROC[BoxProc], source: SampleMap, s0, f0: INTEGER, phase: NAT, function: Function, goodDest: SampleMap] ~ { sSize: NAT ~ dest.sSize; fSize: NAT ~ dest.fSize; bps: NAT ~ dest.bitsPerSample; MacroBrickAction: PROC [scratch: SampleMap] ~ { scratchBoxes: PROC[box: BoxProc] ~ {box[0, 0, scratch.sSize, scratch.fSize]}; GeneralTileBoxes[scratch, scratchBoxes, source, 0, 0, phase, [null, null], NIL]; GeneralTileBoxes[dest, boxes, scratch, s0, f0, phase, function, goodDest]; }; IF bps=source.bitsPerSample AND source.fSize*bps = bitsPerWord AND source.bitsPerLine = bitsPerWord AND source.sSize IN (0..16] AND phase = 0 AND source.base.bit = 0 AND function # [null, complement] THEN TRUSTED { bbPtr: DragonBitBlt.BitBltTable; bb: DragonBitBlt.BitBltTablePtr _ @bbPtr; destBPL: CARDINAL ~ dest.bitsPerLine; easyBox: SAFE PROC [smin, fmin, smax, fmax: CARDINAL] ~ TRUSTED { dstBitIndex: LONG CARDINAL ~ dest.base.bit + Basics.LongMult[Check[smin, smax], destBPL] + Basics.LongMult[Check[fmin, fmax], bps]; yOffset: CARDINAL ~ LOOPHOLE[smin-s0, CARDINAL] MOD source.sSize; bb.dst _ ConvertToDragonBitAddress[ IndexBit[dest.base.word, [lc[dstBitIndex]]] ]; bb.src _ ConvertToDragonBitAddress[ [word: source.base.word+yOffset, bit: LOOPHOLE[fmin-f0, CARDINAL] MOD 16] ]; bb.srcDesc.gray.yOffset _ yOffset; bb.height _ Check[smax, sSize]-smin; bb.width _ Basics.LongMult[Check[fmax, fSize]-fmin, bps]; DragonBitBlt.BITBLT[bb]; }; bb^ _ grayBitBltTable; bb.dstBpl _ dest.bitsPerLine; bb.srcDesc.gray.heightMinusOne _ source.sSize-1; bb.flags.srcFunc _ SrcFunc[function]; bb.flags.dstFunc _ DstFunc[function]; boxes[easyBox]; RETURN }; IF bps#source.bitsPerSample OR source.fSize*bps < MIN[smallWidth, dest.fSize] THEN SampleMapOps.DoWithScratch[sSize: source.sSize, fSize: EnlargedSize[source.fSize, bps], bitsPerSample: bps, action: MacroBrickAction] ELSE GeneralTileBoxes[dest, boxes, source, s0, f0, phase, function, goodDest]; }; 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]] }; GeneralTileBoxes: PROC [dest: SampleMap, boxes: PROC[BoxProc], source: SampleMap, s0, f0: INTEGER, phase: NAT, function: Function, goodDest: SampleMap] ~ { bps: NAT ~ dest.bitsPerSample; sSize: NAT ~ dest.sSize; fSize: NAT ~ dest.fSize; box: SAFE PROC [smin, fmin, smax, fmax: CARDINAL] ~ TRUSTED { sBrickSize: NAT ~ source.sSize; fBrickSize: NAT ~ source.fSize; qr: QR ~ DivMod[(INTEGER[smin]-s0), sBrickSize]; s: CARDINAL _ smin; sDelta: CARDINAL _ sBrickSize - qr.remainder; fSource: CARDINAL _ Mod[fmin-f0 - QMul[qr.quotient, phase], fBrickSize]; WHILE s < smax DO sBrick: NAT ~ sBrickSize-sDelta; sClipSize: NAT ~ MIN[sBrickSize+s, smax]-s; f: NAT _ fmin; fDelta: NAT _ fBrickSize-fSource; WHILE f < fmax DO IF goodDest = NIL THEN SampleMapOps.Transfer[dest: dest, destStart: [s, f], source: [source, [sBrick, fBrickSize-fDelta], [sClipSize, MIN[fBrickSize+f, fmax]-f]], function: function] ELSE Transfer[dest: dest, destStart: [s, f], source: [source, [sBrick, fBrickSize-fDelta], [sClipSize, MIN[fBrickSize+f, fmax]-f]], function: function, goodDest: goodDest]; f _ f + fDelta; fDelta _ fBrickSize; ENDLOOP; s _ s + sDelta; sDelta _ sBrickSize; WHILE fSource < phase DO fSource _ fSource + fBrickSize ENDLOOP; fSource _ fSource - phase; ENDLOOP; }; boxes[box]; }; Get: PUBLIC PROC [buffer: Buffer, start: NAT _ 0, count: NAT _ maxCount, sampleMap: SampleMap, s, f: NAT _ 0, ds: NAT _ 0, df: NAT _ 1] ~ TRUSTED { size: NAT ~ MIN[count, buffer.length-start]; IF size # 0 THEN { sSize: NAT ~ sampleMap.sSize; fSize: NAT ~ sampleMap.fSize; bpl: NAT ~ sampleMap.bitsPerLine; bps: NAT ~ sampleMap.bitsPerSample; bbPtr: DragonBitBlt.BitBltTable; bb: DragonBitBlt.BitBltTablePtr _ @bbPtr; bufferPointer: LONG POINTER ~ InlineGetPointer[buffer, start, size]; srcBitIndex: LONG CARDINAL _ sampleMap.base.bit + Basics.LongMult[Basics.BoundsCheck[s, sSize], bpl] + Basics.LongMult[Basics.BoundsCheck[f, fSize], bps]; srcBitDelta: NAT ~ Basics.LongMult[ds, bpl] + Basics.LongMult[df, bps]; srcBitSkipDelta: NAT _ srcBitDelta; lgSkip: NAT _ 0; skipMinusOne: NAT _ 0; IF ds > 0 THEN [] _ Basics.BoundsCheck[s+Basics.LongMult[size-1, ds], sSize]; IF df > 0 THEN [] _ Basics.BoundsCheck[f+Basics.LongMult[size-1, df], fSize]; WHILE srcBitSkipDelta <= NAT.LAST/2 AND LOOPHOLE[srcBitSkipDelta, CARDINAL] MOD bitsPerWord # 0 DO srcBitSkipDelta _ srcBitSkipDelta * 2; lgSkip _ lgSkip + 1; ENDLOOP; skipMinusOne _ Shift[1, lgSkip]-1; PrincOpsUtils.LongZero[where: bufferPointer, nwords: size]; bb^ _ disjointBitBltTable; bb.dstBpl _ Shift[bitsPerWord, lgSkip]; bb.srcDesc _ [srcBpl[srcBitSkipDelta]]; bb.width _ bps; FOR i: NAT IN [0..Shift[1, lgSkip]) DO bb.src _ ConvertToDragonBitAddress[ IndexBit[sampleMap.base.word, [lc[srcBitIndex]]] ]; bb.height _ Shift[size-i+skipMinusOne, -lgSkip]; bb.dst _ ConvertToDragonBitAddress[ [word: bufferPointer+i, bit: bitsPerWord-bps] ]; DragonBitBlt.BITBLT[bb]; srcBitIndex _ srcBitIndex + srcBitDelta; ENDLOOP; DragonBitBlt.BITBLT[bb]; }; }; Put: PUBLIC PROC [buffer: Buffer, start: NAT _ 0, count: NAT _ maxCount, sampleMap: SampleMap, s, f: NAT _ 0, ds: NAT _ 0, df: NAT _ 1, function: Function _ nullFunction, goodDest: SampleMap] ~ TRUSTED { size: NAT ~ MIN[count, buffer.length-start]; IF size # 0 THEN { sSize: NAT ~ sampleMap.sSize; fSize: NAT ~ sampleMap.fSize; bpl: NAT ~ sampleMap.bitsPerLine; bps: NAT ~ sampleMap.bitsPerSample; bbPtr: DragonBitBlt.BitBltTable; bb: DragonBitBlt.BitBltTablePtr _ @bbPtr; bufferPointer: LONG POINTER ~ InlineGetPointer[buffer, start, size]; dstBitIndex: LONG CARDINAL _ sampleMap.base.bit + Basics.LongMult[Basics.BoundsCheck[s, sSize], bpl] + Basics.LongMult[Basics.BoundsCheck[f, fSize], bps]; dstBitDelta: NAT _ Basics.LongMult[ds, bpl] + Basics.LongMult[df, bps]; dstBitSkipDelta: NAT _ dstBitDelta; lgSkip: NAT _ 0; skipMinusOne: NAT _ 0; bufferFirst: LONG POINTER _ bufferPointer; IF ds > 0 THEN [] _ Basics.BoundsCheck[s+Basics.LongMult[size-1, ds], sSize]; IF df > 0 THEN [] _ Basics.BoundsCheck[f+Basics.LongMult[size-1, df], fSize]; WHILE dstBitSkipDelta <= NAT.LAST/2 AND LOOPHOLE[dstBitSkipDelta, CARDINAL] MOD bitsPerWord # 0 DO dstBitSkipDelta _ dstBitSkipDelta * 2; lgSkip _ lgSkip + 1; ENDLOOP; skipMinusOne _ Shift[1, lgSkip]-1; bb^ _ disjointBitBltTable; bb.flags.srcFunc _ SrcFunc[function]; bb.flags.dstFunc _ DstFunc[function]; bb.dstBpl _ dstBitSkipDelta; bb.srcDesc _ [srcBpl[Shift[bitsPerWord, lgSkip]]]; bb.width _ bps; FOR i: NAT IN [0..Shift[1, lgSkip]) DO bb.dst _ ConvertToDragonBitAddress[ IndexBit[sampleMap.base.word, [lc[dstBitIndex]]] ]; bb.height _ Shift[size-i+skipMinusOne, -lgSkip]; bb.src _ ConvertToDragonBitAddress[ [word: bufferPointer+i, bit: bitsPerWord-bps] ]; DragonBitBlt.BITBLT[bb]; dstBitIndex _ dstBitIndex + dstBitDelta; ENDLOOP; }; }; Flip: PUBLIC PROC [buffer: Buffer] ~ TRUSTED { size: NAT ~ buffer.length; last: INTEGER ~ size-1; s: LONG POINTER TO Basics.RawWords ~ InlineGetPointer[buffer, 0, size]; k: NAT _ size; FOR j: NAT IN [0..size/2) DO t: CARDINAL _ s[j]; s[j] _ s[k _ k-1]; s[k] _ t; ENDLOOP; }; InlineGetPointer: PROC [buffer: Buffer, start: NAT, count: NAT] RETURNS [LONG POINTER TO Basics.RawWords] ~ TRUSTED INLINE { [] _ Check[start+count, buffer.maxLength]; TRUSTED {RETURN [LOOPHOLE[buffer, LONG POINTER TO Basics.RawWords]+SIZE[BufferRep[start]]]} }; END. (DragonSampleMapOpsImpl.mesa Copyright c 1985, 1986 by Xerox Corporation. All rights reserved. Michael Plass, December 13, 1985 1:30:00 pm PST Willie-Sue, September 15, 1986 11:12:07 am PDT IF x IN[0..max] THEN RETURN[x] ELSE ERROR RuntimeError.BoundsFault Round a bit size up to a whole number of (dragon) words. round up to the next 32-bit address make sure the words are not simply zeroes Try flushing the global function cache to get some space back. 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. must make sure than pixelToUse is on a 32-bit boundary IF function = [null, complement] THEN { Bug in Dorado BITBLT microcode (as of December 4, 1985) replicatedPixel _ CARDINAL.LAST-replicatedPixel; function _ [null, null]; }; Number-theoretic: 0 <= remainder < d, n = quotient*d + remainder quotient _ qq.li; Number-theoretic: 0 <= remainder < d Ê®˜™Icodešœ Ïmœ7™BK™/K™.K™—šÏk ˜ K˜ K˜ K˜Kšœ;žœ˜>Kšœ ˜ Kšœ˜K˜—K˜šÐlnœž ˜%šž˜K˜ Kšœ1žœ˜4Kšœ ˜ —Kšžœ˜—šœž˜K˜Kšœ žœ˜&Kšœžœ˜#Kšœ žœ˜)Kšœ žœ˜&Kšžœžœžœ˜Kšœ žœ˜'Kšœ3˜3Kšœ žœ˜'Kšœžœ˜,Kšœ žœ˜)Kšœžœ˜/Kšœžœ˜#K˜šœ žœ ˜K˜—š Ðknœžœžœžœžœ˜0Kšœžœžœžœ ˜'K˜—š Ïnœžœžœžœžœžœ˜8Kšœžœžœžœ ˜)K˜—š ¡œžœžœžœžœžœ˜2Kšžœžœžœ$˜8Kš žœžœ žœžœžœžœ™BK˜—š ¡ œžœžœžœžœžœ˜=Kšžœžœ ˜Kšœ˜K˜—š¡œžœ žœžœžœžœžœ˜LKšžœM˜SKšœ˜K˜—š ¡œžœžœžœžœ ˜+Kšœžœ˜šžœž˜Kšœ ˜ Kšœ˜Kšžœ˜—Kšœ˜K˜—š ¡œžœžœžœžœžœ˜2K™8Kšœžœ!žœžœ˜WKšœ˜—K˜š¡œžœ˜8Kšžœ&žœ˜7Kšœ žœžœ žœ!˜IK˜Kš žœžœžœ)žœžœ˜NKšœ˜K˜—K˜š¡ œžœ˜?Kšžœ&žœ˜7Kšœ#™#Kšœ žœžœ žœ!˜IK˜Kš žœžœžœ)žœžœ˜NKšœ žœ ˜K˜—K˜š¡œžœžœ#˜Lšžœž˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšžœžœ˜—K˜—K˜š¡œžœžœ#˜LKšœ žœžœžœ ˜?K˜—K˜Kšœ žœ˜š œ žœžœžœ žœžœžœ˜9K˜—š ¡œžœžœ žœ žœ*žœ˜wKšœžœ7˜?—K˜š ¡œžœžœ žœ žœ*žœ˜xKšœžœ8˜@K˜—š ¡œžœžœ žœ žœ*žœ˜xKšœžœ7˜?—K˜Kšœ žœ˜&K˜š¡œžœ˜Kšœžœ žœ˜!Kšœ8žœ˜RK˜Kšœ žœ2˜BKšœžœžœ3˜Hšžœžœžœ˜%Kšœžœžœžœ ˜!Kšœ žœžœ˜1šœ˜Kšœ ˜ Kšœ ˜ Kšœ˜Kšœ˜Kšœ"˜"Kšœ˜Kšœ ˜ Kšœ˜—Kšœ˜—šžœžœ˜Kšœ(˜(šœ˜Kšœ˜Kšœ7˜7Kšœ3˜3Kšœ˜Kšœ˜—Kšœ˜—Kšœ)™)šžœ˜ Kš œžœžœžœžœžœ˜1Kšœ žœ˜šžœž˜Kšœ˜Kšœ˜Kšœ˜Kšžœ˜—š žœžœžœžœ ž˜&Kšžœ žœ˜!Kšžœžœ žœžœ ˜Kšœ9˜9Kšœ=˜=Kšœ%˜%Kšœ`˜`Kšœ&˜&Kšœ˜—Kšœ˜K˜—š¡œžœžœžœ˜:Kšœ ˜ Kšœžœ"˜+Kšœžœ"˜+Kš œžœžœžœžœ˜=Kš œžœžœžœžœ˜=KšœU˜UKšœYžœ˜^Kšžœ˜ Kšœ˜—K˜š¡ œžœžœ*žœ˜JKšœ^˜^Kšœc˜cK˜—K˜š¡ œžœ žœ žœ#žœžœžœ˜rKšœ žœ2˜BKšžœ2˜8Kšœ˜K˜—šœ-˜-Kšœ žœ˜$Kšœ žœ ˜/Kšœ˜Kšœ˜K˜—šœ1˜1Kšœ žœ˜$Kšœ žœ ˜/Kšœ'žœžœ˜AKšœ˜K˜—šœ-˜-Kšœ žœ˜$Kšœ žœ ˜/Kšœ'žœžœžœ˜MKšœ˜K˜—š¡ œžœžœžœ žœ žœ7žœ%žœžœžœ!žœžœ˜õKšœžœžœ)˜GKšœ žœ˜,Kšœ žœžœ9˜QKšœžœžœ˜2Kšœžœžœžœ˜,Kš œžœžœžœžœžœ˜Všœ˜Kšœ ˜ Kšœ ˜ Kšœ˜Kšœ ˜ Kšœ˜Kšœ˜Kšœ˜—Kšžœ˜ Kšœ˜K˜—š¡ œžœžœžœžœžœžœ˜YKšœžœ0˜;Kšœžœ0˜;Kšœžœ˜-Kšœ žœžœf˜}KšœP˜PKš œ žœžœžœžœžœžœ˜@Kšœ žœ0˜AKšœžœ˜+šœ žœžœ˜(Kšžœ˜!Kšžœ@˜D—Kšžœžœ˜"Kšœ˜K˜—Kš ¡ œžœžœžœ žœ˜Kšœ,žœ˜5Kšœžœ0˜;Kšœžœ0˜;Kšœžœ˜-Kšœ žœžœf˜}Kšœ ˜ Kšœ)˜)šœ˜KšœN˜NKšœ ˜ KšœO˜OKšœ˜Kšœ ˜ Kšœ˜Kšœ&žœžœžœ9˜…K˜—Kšœ žœ˜Kšœ˜K˜—Kš¡ œžœžœ%˜Yšœ˜KšœžœžœO˜_KšœžœžœO˜_šžœžœžœ ž˜šžœžœžœ ž˜KšœžœE˜UKšœL˜LKšžœ˜—Kšžœ˜—Kšœ˜K˜—š œžœžœž œžœ˜4Kšœü™üšžœžœž˜Kšœ(˜(Kšœžœžœ žœ˜0Kšž˜—K˜K˜—š¡œžœžœ žœžœ žœž œžœ˜~šœ˜KšœI˜IKšœžœ ˜$Kšœ˜—Kšžœ˜Kšœ˜K˜—Kš¡œžœžœžœ%˜\šœžœ˜!Kšœžœ˜Kšœ"˜"KšœžœžœO˜_KšœžœžœB˜Ršžœžœž˜šœ)˜)Kšœ ˜ Kšœ)˜)šœ žœžœ˜,KšœC˜CKšœ5˜5—šœ žœžœ˜+KšœD˜DKšœ7˜7—Kšœ˜KšœR˜RKšœ˜KšœQ˜QKšœ'˜'Kšœ˜Kšœžœ˜Kšœ%˜%Kšœ%˜%Kšœ žœ˜Kšœ˜—Kšžœ>˜E—Kšœ˜K˜—š¡œžœžœ#žœžœžœ-žœ˜Kšœžœ˜#Kšœžœ˜!Kšœžœ˜Kšœžœ˜Kšœ ˜ Kšœ)˜)šœ žœžœ˜1Kšœ1˜1Kšœ0˜0—šœ žœžœ˜1Kšœ3˜3Kšœ2˜2—Kšœ žœžœ1˜DKšœ žœžœ1˜DKšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœžœ ˜Kšœ%˜%Kšœ%˜%š žœžœ(žœ(žœ(žœ(žœ˜ÂKšœžœÏc˜4Kšžœžœžœ¢˜Tš žœžœžœžœ¢˜uKšœžœžœ$˜8KšœJ˜JKšœ"˜"Kšœ"˜"K˜—Kšœ˜—KšœW˜WKšœW˜WKšœ žœ˜Kšœ˜K˜—š¡œžœžœ+˜XKšœžœžœ1˜AKšœžœžœ1˜Ašžœžœžœ ž˜šžœžœžœ ž˜Kšœa˜aKšžœ˜—Kšžœ˜—Kšœ˜K˜—š œ žœžœžœÏf&œ˜PK˜—š¡œžœžœžœ+˜[Kšœžœ ˜(šžœ žœ žœžœ˜)šœ žœžœ˜6KšœX˜XKšœ@˜@—Kšœžœžœ1˜AKšœžœžœ1˜AKšœ ˜ Kšœ)˜)Kšœžœžœ/˜QKšœ6™6šœ žœžœ˜/Kšžœ0˜3—šžœžœ™'K™7Kšœžœžœ™0Kšœ™Kšœ™—Kšœ˜šœ˜KšœS˜S—Kšœ'˜'KšœI˜IKšœ žœ1˜@Kšœžœ1˜CKšœ%˜%Kšœ%˜%Kšœ žœ˜Kšœ˜—Kšžœ+˜/Kšœ˜K˜—š¡œžœžœžœžœžœ žœ.˜œKšœžœI˜TKšœB˜BKšœ˜K˜—Kš žœžœžœ žœ žœ˜6š ¡œžœžœžœžœžœ˜6Kšœ@™@šžœžœ˜ Kšœ ˜ Kšœ ˜ Kšžœ žœ!¢!œ˜UKšœN˜NKšœ™Kšœžœ ˜#Kšœ˜—Kšžœžœ˜*Kšœ˜K˜—š ¡œžœžœžœžœ žœ˜7Kšœ$™$šžœžœ˜ Kšœ ˜ Kšžœ žœžœ˜9Kšžœžœžœ˜@Kšžœ)˜/Kšœ˜—Kšžœžœ˜Kšœ˜K˜—š ¡ œžœ žœžœžœžœ˜;Kšœžœ*˜5Kšžœ˜"Kšœ˜K˜—Kšœ žœ˜Kšœ žœ˜%š ¡ œžœžœžœ&žœ žœ.˜›Kšœžœ˜Kšœžœ˜Kšœžœ˜š¡œžœ˜/Kšœžœ;˜MKšœKžœ˜PKšœJ˜JKšœ˜—šžœžœ žœ"žœžœ žœ žœžœžœžœ˜ÖKšœ ˜ Kšœ)˜)Kšœ žœ˜%š œ žœžœžœžœ˜Ašœ žœžœ˜,Kšœ-˜-Kšœ(˜(—Kš œ žœžœ žœžœ˜AKšœR˜Ršœ#˜#Kšœ&žœ žœžœ˜L—Kšœ"˜"Kšœ$˜$Kšœ9˜9Kšœ žœ˜Kšœ˜—Kšœ˜Kšœ˜Kšœ0˜0Kšœ%˜%Kšœ%˜%Kšœ˜Kšž˜Kšœ˜—šžœžœžœ˜MKšžœ†˜ŠKšžœJ˜N—Kšœ˜K˜—š¡œžœžœžœžœžœžœ˜=Kšžœžœžœžœ˜7Kšžœžœžœžœ˜4Kšœ˜K˜—š ¡œžœžœ&žœ žœ.˜›Kšœžœ˜Kšœžœ˜Kšœžœ˜š œžœžœžœžœ˜=Kšœ žœ˜Kšœ žœ˜Kšœžœ žœ˜0Kšœžœ˜Kšœžœ˜-Kšœ žœ7˜Hšžœ ž˜Kšœžœ˜ Kšœ žœžœ˜+Kšœžœ˜Kšœžœ˜!šžœ ž˜šžœ žœž˜Kšœožœ-˜ŸKšžœcžœB˜¬—Kšœ˜Kšœ˜Kšžœ˜—Kšœ˜Kšœ˜Kšžœžœ žœ˜@Kšœ˜Kšžœ˜—Kšœ˜—Kšœ ˜ Kšœ˜K˜—š¡œžœžœžœ žœ)žœ žœ žœžœ˜“Jšœžœžœ˜,šžœ žœ˜Jšœžœ˜Jšœžœ˜Jšœžœ˜!Jšœžœ˜#Kšœ ˜ Kšœ)˜)Kšœžœžœ)˜Dšœ žœžœ˜1Kšœ4˜4Kšœ3˜3—Kšœ žœ7˜GKšœžœ˜#Kšœžœ˜Kšœžœ˜Kšžœžœ?˜MKšžœžœ?˜Mšžœžœžœžœžœžœžœž˜bKšœ&˜&Kšœ˜Kšžœ˜—Jšœ"˜"Jšœ;˜;Kšœ˜Kšœ'˜'Kšœ'˜'Kšœ˜šžœžœžœž˜&šœ˜KšœN˜N—Kšœ0˜0KšœT˜TKšœ žœ˜Kšœ(˜(Kšžœ˜—Kšœ žœ˜K˜—Kšœ˜K˜—š¡œžœžœžœ žœ)žœ žœ žœ@žœ˜ËJšœžœžœ˜,šžœ žœ˜Jšœžœ˜Jšœžœ˜Jšœžœ˜!Jšœžœ˜#Kšœ ˜ Kšœ)˜)Kšœžœžœ)˜Dšœ žœžœ˜1Kšœ4˜4Kšœ3˜3—Kšœ žœ7˜GKšœžœ˜#Kšœžœ˜Kšœžœ˜Kšœ žœžœ˜*Kšžœžœ?˜MKšžœžœ?˜Mšžœžœžœžœžœžœžœž˜bKšœ&˜&Kšœ˜Kšžœ˜—Jšœ"˜"Kšœ˜Kšœ%˜%Kšœ%˜%Kšœ˜Kšœ2˜2Kšœ˜šžœžœžœž˜&šœ˜KšœN˜N—Kšœ0˜0KšœT˜TKšœ žœ˜Kšœ(˜(Kšžœ˜—Kšœ˜—Kšœ˜K˜—š¡œžœžœžœ˜.Kšœžœ˜Kšœžœ ˜Kšœžœžœžœ5˜GKšœžœ˜šžœžœžœ ž˜Kšœžœ˜Kšœ˜Kšœ ˜ Kšžœ˜—Kšœ˜K˜—š¡œžœžœ žœžœžœžœžœžœžœ˜|Jšœ*˜*Kšžœžœžœ žœžœžœžœ˜[Kšœ˜—K˜—K˜Kšžœ˜K˜J˜—…—\ö{Ì