<> <> <> <> DIRECTORY Basics USING [bitsPerWord, BYTE, LongMult], FunctionCache USING [Cache, GlobalCache, CompareProc, Insert, Lookup], ImagerColorDefs USING [Color, ColorOperator, ConstantColor, ConstantColorImplRep, SampledColor], ImagerColorOperator USING [GetColorOperatorClass, Mapper, MapPixels, NewMapper], ImagerColorPrivate USING [ConstantColorClass, ConstantColorClassRep, ConstantColorImpl, ConstantColorImplRep], ImagerColor24DevicePrivate USING [Case, StippleArray, Channel, bitsPerPixelA, bitsPerPixelB, Data, DataRep, SampledColorData, SampledColorDataRep], ImagerDevice USING [BoxProc, Class, ClassRep, Device, DeviceBox, DeviceRep, HalftoneParameters, RunProc], ImagerPixelArray USING [GetPixels, MaxSampleValue], ImagerPixelArrayDefs USING [PixelArray], ImagerPixelMap USING [Create, PixelMap], ImagerRaster USING [], ImagerSample USING [GetPointer, GetPointSamples, NewBuffer, Sample, SampleBuffer, Sampler, SamplerRep, SetSamplerIncrements, SetSamplerPosition, UnsafePutF, UnsafePutS, UnsafeSamples], ImagerTransformation USING [ApplyPreRotate, Cat, Transformation, Translate], PrincOps USING [BBTableSpace, BitBltFlags, BitBltTable, BitBltTablePtr, DstFunc, op, zBNDCK, zINC], PrincOpsUtils USING [AlignedBBTable, BITBLT, ByteBlt, LongCopy], Real USING [RoundC], Terminal USING [FrameBuffer, GetColorFrameBufferA, GetColorFrameBufferB, ModifyColorFrame, Virtual], Vector2 USING [VEC]; ImagerColor24DeviceImpl: CEDAR PROGRAM IMPORTS Basics, FunctionCache, ImagerColorOperator, ImagerPixelArray, ImagerPixelMap, ImagerSample, ImagerTransformation, PrincOpsUtils, Real, Terminal EXPORTS ImagerColorDefs, ImagerRaster ~ BEGIN OPEN ImagerDevice, ImagerColor24DevicePrivate; BYTE: TYPE ~ Basics.BYTE; VEC: TYPE ~ Vector2.VEC; Transformation: TYPE ~ ImagerTransformation.Transformation; Color: TYPE ~ ImagerColorDefs.Color; ConstantColor: TYPE ~ ImagerColorDefs.ConstantColor; SampledColor: TYPE ~ ImagerColorDefs.SampledColor; ColorOperator: TYPE ~ ImagerColorDefs.ColorOperator; PixelArray: TYPE ~ ImagerPixelArrayDefs.PixelArray; Sample: TYPE ~ ImagerSample.Sample; SampleBuffer: TYPE ~ ImagerSample.SampleBuffer; UnsafeSamples: TYPE ~ ImagerSample.UnsafeSamples; ConstantColorImpl: TYPE ~ ImagerColorPrivate.ConstantColorImpl; ConstantColorImplRep: PUBLIC TYPE ~ ImagerColorPrivate.ConstantColorImplRep; ConstantColorClass: TYPE ~ ImagerColorPrivate.ConstantColorClass; ConstantColorClassRep: PUBLIC TYPE ~ ImagerColorPrivate.ConstantColorClassRep; bitsPerWord: NAT ~ Basics.bitsPerWord; class: ImagerDevice.Class ~ NEW[ImagerDevice.ClassRep _ [ type: $FullColorDisplay, SetColor: Color24SetColor, SetPriority: Color24SetPriority, SetHalftone: Color24SetHalftone, MaskRuns: Color24MaskRuns, MaskBoxes: Color24MaskBoxes, MaskBits: Color24MaskBits, MoveBoxes: Color24MoveBoxes ]]; NewColor24Device: PUBLIC PROC [terminal: Terminal.Virtual] RETURNS[Device] ~ { frameA: Terminal.FrameBuffer ~ Terminal.GetColorFrameBufferA[terminal]; frameB: Terminal.FrameBuffer ~ Terminal.GetColorFrameBufferB[terminal]; IF frameA=NIL OR frameA.bitsPerPixel#bitsPerPixelA OR frameB=NIL OR frameB.bitsPerPixel#bitsPerPixelB THEN RETURN[NIL] ELSE { data: Data ~ NEW[DataRep _ [terminal: terminal, frame: [A: frameA, B: frameB]]]; pixelsPerInch: REAL ~ terminal.colorPixelsPerInch; surfaceToDevice: Transformation ~ ImagerTransformation.Translate[[frameA.height, 0]]; surfaceToDevice.ApplyPreRotate[90]; RETURN[NEW[ImagerDevice.DeviceRep _ [class: class, box: [smin: 0, fmin: 0, smax: frameA.height, fmax: frameA.width], surfaceToDevice: surfaceToDevice, surfaceUnitsPerInch: [pixelsPerInch, pixelsPerInch], surfaceUnitsPerPixel: 1, data: data]]]; }; }; nullBitBltTable: PrincOps.BitBltTable ~ [ dst: [word: NIL, bit: 0], dstBpl: 0, src: [word: NIL, bit: 0], srcDesc: [srcBpl[0]], width: 0, height: 0, flags: [] ]; StippleArrayFromWord: PROC[t: WORD] RETURNS[array: StippleArray _ ALL[0]] ~ { bits: PACKED ARRAY [0..16) OF BOOL ~ LOOPHOLE[t]; FOR i: [0..16) IN [0..16) DO IF bits[i] THEN array[i] _ WORD.LAST ENDLOOP; }; PixelFromIntensity: PROC[i: REAL] RETURNS[BYTE] ~ { IF i<=0 THEN RETURN[0]; IF i>=1 THEN RETURN[BYTE.LAST]; RETURN[Real.RoundC[i*BYTE.LAST]]; }; Color24SetColor: PROC [device: Device, color: Color, viewToDevice: Transformation] ~ { data: Data ~ NARROW[device.data]; WITH color SELECT FROM color: ConstantColor => { impl: ConstantColorImpl ~ color.impl; data.case _ constant; data.flags _ [disjoint: TRUE, gray: TRUE, srcFunc: null, dstFunc: null]; WITH impl: impl SELECT FROM stipple => { word: WORD ~ impl.word; SELECT impl.function FROM replace => { data.flags.srcFunc _ complement }; paint => { data.flags.srcFunc _ complement; data.flags.dstFunc _ and }; invert => { data.flags.dstFunc _ xor }; erase => { data.flags.dstFunc _ or }; ENDCASE => ERROR; IF word=WORD.LAST THEN data.grayWordA _ data.grayWordB _ word ELSE { data.stipple _ StippleArrayFromWord[word]; data.case _ stipple }; }; rgb => { pixelR: BYTE ~ PixelFromIntensity[impl.val.R]; pixelG: BYTE ~ PixelFromIntensity[impl.val.G]; pixelB: BYTE ~ PixelFromIntensity[impl.val.B]; data.grayWordA _ pixelR*400B+pixelG; data.grayWordB _ pixelB*400B+pixelB; }; ENDCASE => { pixel: BYTE ~ PixelFromIntensity[impl.Y]; data.grayWordA _ data.grayWordB _ pixel*400B+pixel; }; }; color: SampledColor => { pa: PixelArray ~ color.pa; um: Transformation ~ color.um; colorOperator: ColorOperator ~ color.colorOperator; data.sampledColor _ color; data.case _ sampled; data.zerosAreClear _ ImagerColorOperator.GetColorOperatorClass[colorOperator] = $SampledBlackClear; data.paToDevice _ ImagerTransformation.Cat[pa.m, color.um, viewToDevice]; IF data.buffer=NIL THEN data.buffer _ ImagerSample.NewBuffer[1, data.frame[A].width]; }; ENDCASE => ERROR; -- unknown color variant }; Color24SetPriority: PROC[device: Device, priorityImportant: BOOL] ~ { }; Color24SetHalftone: PROC[device: Device, halftone: HalftoneParameters] ~ { data: Data ~ NARROW[device.data]; <> }; Check: PROC[x: CARDINAL, max: NAT] RETURNS[NAT] ~ TRUSTED MACHINE CODE { PrincOps.zINC; PrincOps.zBNDCK }; <> --ImagerMask.--RunsFromBox: PROC[box: DeviceBox, run: RunProc] ~ { fMin: INTEGER ~ box.fmin; fSize: NAT ~ box.fmax-box.fmin; FOR s: CARDINAL IN[box.smin..box.smax) DO run[sMin: s, fMin: fMin, fSize: fSize]; ENDLOOP; }; --ImagerMask.--RunsFromBits: PROC[base: LONG POINTER, wordsPerLine: NAT, sBits, fBits, sRuns, fRuns, sSize, fSize: NAT, run: RunProc] ~ TRUSTED { FOR s: NAT IN[0..sSize) DO Bit: TYPE ~ [0..1]; BitSequence: TYPE ~ RECORD[PACKED SEQUENCE COMPUTED CARDINAL OF Bit]; bits: LONG POINTER TO BitSequence ~ base+Basics.LongMult[sBits+s, wordsPerLine]; state: {off, on} _ off; f0: NAT _ 0; FOR f: NAT IN[0..fSize) DO bit: Bit ~ bits[fBits+f]; SELECT state FROM off => IF bit=1 THEN { f0 _ f; state _ on }; on => IF bit=0 THEN { run[sMin: sRuns+s, fMin: fRuns+f0, fSize: f-f0]; state _ off }; ENDCASE => ERROR; ENDLOOP; IF state=on THEN run[sMin: sRuns+s, fMin: fRuns+f0, fSize: fSize-f0]; ENDLOOP; }; Color24MaskRunsInternal: PROC[data: Data, bounds: DeviceBox, runs: PROC[RunProc]] ~ { frameA: Terminal.FrameBuffer ~ data.frame[A]; baseA: LONG POINTER ~ frameA.base; wordsPerLineA: NAT ~ frameA.wordsPerLine; frameB: Terminal.FrameBuffer ~ data.frame[B]; baseB: LONG POINTER ~ frameB.base; wordsPerLineB: NAT ~ frameB.wordsPerLine; SELECT data.case FROM nil => ERROR; -- color not initialized constant => TRUSTED { bbspace: PrincOps.BBTableSpace; bb: PrincOps.BitBltTablePtr ~ PrincOpsUtils.AlignedBBTable[@bbspace]; color24ConstantRun: PROC[sMin, fMin: INTEGER, fSize: NAT] ~ TRUSTED { fmin: NAT ~ Check[fMin, frameA.width]; fmax: NAT ~ Check[fmin+fSize, frameA.width]; smin: NAT ~ Check[sMin, frameA.height]; smax: NAT ~ Check[smin+1, frameA.height]; bb.dst.word _ baseA+Basics.LongMult[smin, wordsPerLineA]+fmin; bb.dst.bit _ 0; bb.dstBpl _ wordsPerLineA*bitsPerWord; bb.src.word _ LOOPHOLE[@data.grayWordA]; bb.width _ (fmax-fmin)*16; PrincOpsUtils.BITBLT[bb]; bb.dst.word _ baseB+Basics.LongMult[smin, wordsPerLineB]+fmin/2; bb.dst.bit _ (fmin MOD 2)*8; bb.dstBpl _ wordsPerLineB*bitsPerWord; bb.src.word _ LOOPHOLE[@data.grayWordB]; bb.width _ (fmax-fmin)*8; PrincOpsUtils.BITBLT[bb]; }; bb^ _ nullBitBltTable; bb.srcDesc.gray _ [yOffset: 0, widthMinusOne: 0, heightMinusOne: 0]; bb.height _ 1; bb.flags _ data.flags; runs[color24ConstantRun]; }; stipple => TRUSTED { bbspace: PrincOps.BBTableSpace; bb: PrincOps.BitBltTablePtr ~ PrincOpsUtils.AlignedBBTable[@bbspace]; srcBase: LONG POINTER ~ @data.stipple; color24StippleRun: PROC[sMin, fMin: INTEGER, fSize: NAT] ~ TRUSTED { fmin: NAT ~ Check[fMin, frameA.width]; fmax: NAT ~ Check[fmin+fSize, frameA.width]; smin: NAT ~ Check[sMin, frameA.height]; smax: NAT ~ Check[smin+1, frameA.height]; dstLineA: LONG POINTER ~ baseA+Basics.LongMult[smin, wordsPerLineA]; dstLineB: LONG POINTER ~ baseB+Basics.LongMult[smin, wordsPerLineB]; srcLine: LONG POINTER ~ srcBase+(smin MOD 4)*4; FOR f: NAT IN [fmin..MIN[fmin+4, fmax]) DO bb.src.word _ srcLine+(f MOD 4); bb.height _ (fmax-f+3)/4; bb.dst.word _ dstLineA+f; bb.dst.bit _ 0; bb.dstBpl _ 4*16; bb.width _ 16; PrincOpsUtils.BITBLT[bb]; bb.dst.word _ dstLineB+f/2; bb.dst.bit _ (f MOD 2)*8; bb.dstBpl _ 4*8; bb.width _ 8; PrincOpsUtils.BITBLT[bb]; ENDLOOP; }; bb^ _ nullBitBltTable; bb.srcDesc.gray _ [yOffset: 0, widthMinusOne: 0, heightMinusOne: 0]; bb.flags _ data.flags; runs[color24StippleRun]; }; sampled => { scd: SampledColorData ~ GetSampledColorData[data]; dstFunc: PrincOps.DstFunc ~ IF data.zerosAreClear THEN and ELSE null; heightLimit: NAT _ NAT.LAST; widthLimit: NAT _ NAT.LAST; base: ARRAY Channel OF LONG POINTER _ ALL[NIL]; wordsPerLine: ARRAY Channel OF NAT; FOR c: Channel IN Channel DO heightLimit _ MIN[heightLimit, data.frame[c].height]; widthLimit _ MIN[widthLimit, data.frame[c].width]; base[c] _ data.frame[c].base; wordsPerLine[c] _ data.frame[c].wordsPerLine; ENDLOOP; IF dstFunc=null AND data.paToDevice.form = 3 AND data.paToDevice.integerTrans THEN { sSizeSource: NAT ~ scd.source[A].sSize; fSizeSource: NAT ~ scd.source[A].fSize; color24FastSampledRun: PROC[sMin, fMin: INTEGER, fSize: NAT] ~ TRUSTED { smin: NAT ~ Check[sMin, heightLimit]; fmin: NAT _ Check[fMin, widthLimit]; count: NAT _ Check[fSize, widthLimit-fmin]; sMinSource: INTEGER _ INT[smin]-data.paToDevice.tx; fMinSource: INTEGER _ INT[fmin]-data.paToDevice.ty; dstLine: ARRAY Channel OF LONG POINTER; srcLine: ARRAY Channel OF LONG POINTER; WHILE sMinSource < 0 DO sMinSource _ sMinSource + (NAT.LAST/sSizeSource)*sSizeSource ENDLOOP; sMinSource _ NAT[sMinSource] MOD sSizeSource; WHILE fMinSource < 0 DO fMinSource _ fMinSource + (NAT.LAST/fSizeSource)*fSizeSource ENDLOOP; fMinSource _ NAT[fMinSource] MOD fSizeSource; FOR c: Channel IN Channel DO source: ImagerPixelMap.PixelMap ~ scd.source[c]; dstLine[c] _ base[c]+Basics.LongMult[smin, wordsPerLine[c]]; srcLine[c] _ source.refRep.pointer+Basics.LongMult[NAT[sMinSource], source.refRep.rast]; ENDLOOP; UNTIL count = 0 DO delta: NAT ~ MIN[count, fSizeSource-fMinSource]; PrincOpsUtils.LongCopy[from: srcLine[A]+fMinSource, nwords: delta, to: dstLine[A]+fmin]; [] _ PrincOpsUtils.ByteBlt[from: [srcLine[B], fMinSource, fMinSource+delta], to: [dstLine[B], fmin, widthLimit]]; fMinSource _ fMinSource + delta; IF fMinSource >= fSizeSource THEN fMinSource _ fMinSource-fSizeSource; fmin _ fmin + delta; count _ count - delta; ENDLOOP; }; runs[color24FastSampledRun]; } ELSE { buffer: SampleBuffer ~ data.buffer; color24SampledRun: PROC[sMin, fMin: INTEGER, fSize: NAT] ~ CHECKED { s: NAT ~ Check[sMin, heightLimit]; f: NAT ~ Check[fMin, widthLimit]; count: NAT ~ Check[fSize, widthLimit-f]; FOR c: Channel IN Channel DO sampler: ImagerSample.Sampler ~ data.sampler[c]; bufferPointer: ImagerSample.UnsafeSamples ~ buffer.GetPointer[0, f, count]; ImagerSample.GetPointSamples[sampler: sampler, s: s, f: f, buffer: buffer, bi: 0, bj: f, count: count]; TRUSTED { ImagerSample.UnsafePutF[samples: bufferPointer, count: count, base: base[c], wordsPerLine: wordsPerLine[c], bitsPerSample: sampler.bitsPerSample, s: s, f: f, dstFunc: dstFunc]}; ENDLOOP; }; FOR c: Channel IN Channel DO t: ImagerPixelMap.PixelMap ~ scd.source[c]; sampler: ImagerSample.Sampler ~ IF data.sampler[c] = NIL THEN (data.sampler[c] _ NEW[ImagerSample.SamplerRep _ []]) ELSE data.sampler[c]; sampler.base _ t.refRep.pointer; sampler.wordsPerLine _ t.refRep.rast; sampler.bitsPerSample _ data.frame[c].bitsPerPixel; sampler.sMin _ t.sMin; sampler.fMin _ t.fMin; sampler.sSize _ t.sSize; sampler.fSize _ t.fSize; ImagerSample.SetSamplerIncrements[sampler, data.paToDevice]; ImagerSample.SetSamplerPosition[sampler: data.sampler[c], m: data.paToDevice, s: bounds.smin, f: bounds.fmin]; ENDLOOP; runs[color24SampledRun]; }; }; ENDCASE => ERROR; -- illegal case }; me: REF TEXT ~ "color24"; -- a globally unique REF for use a key in the global cache. GetSampledColorData: PROC [data: Data] RETURNS [scd: SampledColorData] ~ { cache: FunctionCache.Cache _ FunctionCache.GlobalCache[]; compare: FunctionCache.CompareProc ~ {RETURN [argument=data.sampledColor.pa]}; scd _ NARROW[FunctionCache.Lookup[cache, compare, me].value]; IF scd = NIL THEN { color: SampledColor ~ data.sampledColor; pa: PixelArray ~ color.pa; colorOperator: ColorOperator ~ color.colorOperator; samplesPerPixel: NAT ~ pa.samplesPerPixel; sSize: NAT ~ pa.sSize; fSize: NAT ~ pa.fSize; maxIn: Sample ~ ImagerPixelArray.MaxSampleValue[pa, 0]; pixels: SampleBuffer ~ ImagerSample.NewBuffer[samplesPerPixel, fSize]; buffer: SampleBuffer ~ ImagerSample.NewBuffer[1, fSize]; bufferPointer: UnsafeSamples ~ buffer.GetPointer[0, 0, fSize]; mapperR: ImagerColorOperator.Mapper ~ ImagerColorOperator.NewMapper[ op: colorOperator, component: $Red, maxIn: maxIn, maxOut: 255]; mapperG: ImagerColorOperator.Mapper ~ ImagerColorOperator.NewMapper[ op: colorOperator, component: $Green, maxIn: maxIn, maxOut: 255]; mapperB: ImagerColorOperator.Mapper ~ ImagerColorOperator.NewMapper[ op: colorOperator, component: $Blue, maxIn: maxIn, maxOut: 255]; base: ARRAY Channel OF LONG POINTER _ ALL[NIL]; lineA: LONG POINTER _ NIL; rast: ARRAY Channel OF NAT _ ALL[0]; sampledColorDataSize: INT _ 0; scd _ NEW[SampledColorDataRep]; FOR c: Channel IN Channel DO bpp: CARDINAL ~ data.frame[c].bitsPerPixel; lgbpp: CARDINAL ~ SELECT bpp FROM 8 => 3, 16 => 4, ENDCASE => ERROR; t: ImagerPixelMap.PixelMap ~ ImagerPixelMap.Create[lgbpp, [0, 0, sSize, fSize]]; sampledColorDataSize _ sampledColorDataSize + t.refRep.words; base[c] _ t.refRep.pointer; rast[c] _ t.refRep.rast; scd.source[c] _ t; ENDLOOP; lineA _ base[A]; FOR s: NAT IN[0..sSize) DO ImagerPixelArray.GetPixels[pa: pa, s: s, f: 0, buffer: pixels, count: fSize]; ImagerColorOperator.MapPixels[mapper: mapperG, pixels: pixels, buffer: buffer, count: fSize]; TRUSTED { ImagerSample.UnsafePutF[samples: bufferPointer, count: fSize, base: base[A], wordsPerLine: rast[A], bitsPerSample: 16, s: s, f: 0] }; ImagerColorOperator.MapPixels[mapper: mapperR, pixels: pixels, buffer: buffer, count: fSize]; TRUSTED { ImagerSample.UnsafePutS[samples: bufferPointer, count: fSize, base: lineA, wordsPerLine: 1, bitsPerSample: 8, s: 0, f: 0]; lineA _ lineA + rast[A]; }; ImagerColorOperator.MapPixels[mapper: mapperB, pixels: pixels, buffer: buffer, count: fSize]; TRUSTED { ImagerSample.UnsafePutF[samples: bufferPointer, count: fSize, base: base[B], wordsPerLine: rast[B], bitsPerSample: 8, s: s, f: 0] }; ENDLOOP; FunctionCache.Insert[cache, data.sampledColor.pa, scd, sampledColorDataSize, me]; }; }; Color24MaskBoxesInternal: PROC[data: Data, bounds: DeviceBox, boxes: PROC[BoxProc]] ~ { IF data.case=constant THEN TRUSTED { frameA: Terminal.FrameBuffer ~ data.frame[A]; baseA: LONG POINTER ~ frameA.base; wordsPerLineA: NAT ~ frameA.wordsPerLine; frameB: Terminal.FrameBuffer ~ data.frame[B]; baseB: LONG POINTER ~ frameB.base; wordsPerLineB: NAT ~ frameB.wordsPerLine; bbspace: PrincOps.BBTableSpace; bb: PrincOps.BitBltTablePtr ~ PrincOpsUtils.AlignedBBTable[@bbspace]; color24ConstantBox: PROC[box: DeviceBox] ~ TRUSTED { fmin: NAT ~ Check[box.fmin, frameA.width]; fmax: NAT ~ Check[box.fmax, frameA.width]; smin: NAT ~ Check[box.smin, frameA.height]; smax: NAT ~ Check[box.smax, frameA.height]; bb.height _ smax-smin; bb.dst.word _ baseA+Basics.LongMult[smin, wordsPerLineA]+fmin; bb.dst.bit _ 0; bb.dstBpl _ wordsPerLineA*bitsPerWord; bb.src.word _ LOOPHOLE[@data.grayWordA]; bb.width _ (fmax-fmin)*16; PrincOpsUtils.BITBLT[bb]; bb.dst.word _ baseB+Basics.LongMult[smin, wordsPerLineB]+fmin/2; bb.dst.bit _ (fmin MOD 2)*8; bb.dstBpl _ wordsPerLineB*bitsPerWord; bb.src.word _ LOOPHOLE[@data.grayWordB]; bb.width _ (fmax-fmin)*8; PrincOpsUtils.BITBLT[bb]; }; bb^ _ nullBitBltTable; bb.srcDesc.gray _ [yOffset: 0, widthMinusOne: 0, heightMinusOne: 0]; bb.flags _ data.flags; boxes[color24ConstantBox]; } ELSE { color24NonConstantBox: PROC[box: DeviceBox] ~ { runs: PROC[run: RunProc] ~ { --ImagerMask.--RunsFromBox[box: box, run: run] }; Color24MaskRunsInternal[data: data, bounds: box, runs: runs]; }; boxes[color24NonConstantBox]; }; }; ModifyColorFrame: PROC [vt: Terminal.Virtual, action: PROC, xmin: NAT, ymin: NAT, xmax: NAT, ymax: NAT] ~ INLINE { IF vt = NIL THEN action[] ELSE Terminal.ModifyColorFrame[vt: vt, action: action, xmin: xmin, ymin: ymin, xmax: xmax, ymax: ymax]; }; Color24MaskRuns: PROC[device: Device, bounds: DeviceBox, runs: PROC[RunProc]] ~ { data: Data ~ NARROW[device.data]; color24MaskRunsAction: PROC ~ { Color24MaskRunsInternal[data, bounds, runs] }; ModifyColorFrame[vt: data.terminal, action: color24MaskRunsAction, xmin: bounds.fmin, ymin: bounds.smin, xmax: bounds.fmax, ymax: bounds.smax]; }; Color24MaskBoxes: PROC[device: Device, bounds: DeviceBox, boxes: PROC[BoxProc]] ~ { data: Data ~ NARROW[device.data]; color24MaskBoxesAction: PROC ~ { Color24MaskBoxesInternal[data, bounds, boxes] }; ModifyColorFrame[vt: data.terminal, action: color24MaskBoxesAction, xmin: bounds.fmin, ymin: bounds.smin, xmax: bounds.fmax, ymax: bounds.smax]; }; Color24MaskBits: PROC[device: Device, srcBase: LONG POINTER, srcWordsPerLine: NAT, ts, tf: INTEGER, boxes: PROC[BoxProc]] ~ { data: Data ~ NARROW[device.data]; color24MaskBitsBox: PROC[box: DeviceBox] ~ { color24MaskBitsBoxAction: PROC ~ { runs: PROC[run: RunProc] ~ { --ImagerMask.--RunsFromBits[ base: srcBase, wordsPerLine: srcWordsPerLine, sBits: box.smin-ts, fBits: box.fmin-tf, sRuns: box.smin, fRuns: box.fmin, sSize: box.smax-box.smin, fSize: box.fmax-box.fmin, run: run]; }; Color24MaskRunsInternal[data: data, bounds: box, runs: runs]; }; ModifyColorFrame[vt: data.terminal, action: color24MaskBitsBoxAction, xmin: box.fmin, ymin: box.smin, xmax: box.fmax, ymax: box.smax]; }; boxes[color24MaskBitsBox]; }; Color24MoveBoxes: PROC [device: Device, ts, tf: INTEGER, boxes: PROC[BoxProc]] ~ TRUSTED { data: Data ~ NARROW[device.data]; frameA: Terminal.FrameBuffer ~ data.frame[A]; baseA: LONG POINTER ~ frameA.base; wordsPerLineA: NAT ~ frameA.wordsPerLine; frameB: Terminal.FrameBuffer ~ data.frame[B]; baseB: LONG POINTER ~ frameB.base; wordsPerLineB: NAT ~ frameB.wordsPerLine; bbspace: PrincOps.BBTableSpace; bb: PrincOps.BitBltTablePtr ~ PrincOpsUtils.AlignedBBTable[@bbspace]; moveBox: PROC[box: DeviceBox] ~ TRUSTED { dfmin: NAT ~ Check[box.fmin, frameA.width]; dsmin: NAT ~ Check[box.smin, frameA.height]; dfmax: NAT ~ Check[box.fmax, frameA.width]; dsmax: NAT ~ Check[box.smax, frameA.height]; sfmin: NAT ~ dfmin-tf; ssmin: NAT ~ dsmin-ts; sfmax: NAT ~ dfmax-tf; ssmax: NAT ~ dsmax-ts; bplA: INTEGER _ wordsPerLineA*bitsPerWord; bplB: INTEGER _ wordsPerLineB*bitsPerWord; ss: NAT _ ssmin; ds: NAT _ dsmin; action: SAFE PROC ~ TRUSTED { bb.dst.word _ baseA+Basics.LongMult[ds, wordsPerLineA]+dfmin; bb.dst.bit _ 0; bb.dstBpl _ bplA; bb.src.word _ baseA+Basics.LongMult[ss, wordsPerLineA]+sfmin; bb.src.bit _ 0; bb.srcDesc.srcBpl _ bplA; bb.width _ (dfmax-dfmin)*16; PrincOpsUtils.BITBLT[bb]; bb.dst.word _ baseB+Basics.LongMult[ds, wordsPerLineB]+dfmin/2; bb.dst.bit _ (dfmin MOD 2)*8; bb.dstBpl _ bplB; bb.src.word _ baseB+Basics.LongMult[ss, wordsPerLineB]+sfmin/2; bb.src.bit _ (sfmin MOD 2)*8; bb.srcDesc.srcBpl _ bplB; bb.width _ (dfmax-dfmin)*8; PrincOpsUtils.BITBLT[bb]; }; bb.flags _ [disjoint: TRUE, disjointItems: TRUE, direction: forward, gray: FALSE]; IF dsminssmin THEN { bb.flags.disjoint _ FALSE; IF dsmin=ssmin AND dfminsfmin THEN bb.flags.disjointItems _ FALSE; IF dsmin>ssmin OR (dsmin=ssmin AND dfmin>sfmin) THEN { bb.flags.direction _ backward; ss _ ssmax-1; ds _ dsmax-1; bplA _ -bplA; bplB _ -bplB; }; }; bb.height _ dsmax-dsmin; ModifyColorFrame[vt: data.terminal, action: action, xmin: MIN[dfmin, sfmin], ymin: MIN[dsmin, ssmin], xmax: MAX[dfmax, sfmax], ymax: MAX[dsmax, ssmax]]; }; bb^ _ nullBitBltTable; boxes[moveBox]; }; <<>> END.