DIRECTORY FunctionCache USING [Cache, GlobalCache, CompareProc, Insert, Lookup], ImagerColor, ImagerDeviceColor24Private, ImagerDevice, ImagerRaster USING [], ImagerSample, ImagerTransformation, SF, Terminal USING [FrameBuffer, GetColorFrameBufferA, GetColorFrameBufferB, ModifyColorFrame, Virtual], Vector2 USING [VEC]; ImagerDeviceColor24Impl: CEDAR PROGRAM IMPORTS FunctionCache, ImagerColor, ImagerDevice, ImagerSample, ImagerTransformation, SF, Terminal EXPORTS ImagerRaster ~ BEGIN OPEN ImagerDevice, ImagerDeviceColor24Private; Transformation: TYPE ~ ImagerTransformation.Transformation; PixelProc: TYPE ~ ImagerSample.PixelProc; PixelBuffer: TYPE ~ ImagerSample.PixelBuffer; PixelMap: TYPE ~ ImagerSample.PixelMap; outputRGB: ImagerColor.ColorOutput _ NIL; classColor24: DeviceClass ~ NewClass[ type: $FullColorDisplay, SetColor: SetColorColor24, MaskBoxes: MaskBoxesColor24, MoveBoxes: MoveBoxesColor24 ]; NewColor24Device: PUBLIC PROC [terminal: Terminal.Virtual] RETURNS [Device] ~ { frameBufferA: Terminal.FrameBuffer ~ Terminal.GetColorFrameBufferA[terminal]; frameBufferB: Terminal.FrameBuffer ~ Terminal.GetColorFrameBufferB[terminal]; IF frameBufferA=NIL OR frameBufferA.bitsPerPixel#bitsPerPixelA OR frameBufferB=NIL OR frameBufferB.bitsPerPixel#bitsPerPixelB THEN RETURN[NIL] ELSE { frameA: SampleMap ~ ImagerSample.MapFromFrameBuffer[frameBufferA]; frameB: SampleMap ~ ImagerSample.MapFromFrameBuffer[frameBufferB]; data: Data ~ NEW[DataRep _ [terminal: terminal, frameA: frameA, frameB: frameB]]; pixelsPerInch: REAL ~ terminal.colorPixelsPerInch; surfaceToDevice: Transformation ~ ImagerTransformation.XYToSF[ scanMode: [slow: down, fast: right], sSize: frameA.size.s, fSize: frameA.size.f]; TRUSTED { data.frameRG _ ImagerSample.UnsafeNewSampleMap[ size: [s: frameA.size.s, f: frameA.size.f*2], bitsPerSample: frameA.bitsPerSample/2, bitsPerLine: frameA.bitsPerLine, base: frameA.base, ref: frameBufferA.vm, words: frameBufferA.vm.words] }; RETURN[NEW[ImagerDevice.DeviceRep _ [class: classColor24, box: [min: [s: 0, f: 0], max: frameA.size], surfaceToDevice: surfaceToDevice, surfaceUnitsPerInch: [pixelsPerInch, pixelsPerInch], surfaceUnitsPerPixel: 1, data: data]]]; }; }; me: REF TEXT ~ "DeviceColor24"; -- a globally unique REF for use a key in the global cache. SetColorColor24: SetColorProc ~ { data: Data ~ NARROW[self.data]; WITH color SELECT FROM color: ImagerColor.ConstantColor => { maxOut: PixelProc ~ { check: [0..3) ~ i; RETURN[255] }; pixelAction: PROC [pixelOut: PixelProc] ~ { data.valueA _ pixelOut[0]*256+pixelOut[1]; data.valueB _ pixelOut[2]; }; color.PixelFromColor[output: outputRGB, maxOut: maxOut, pixelAction: pixelAction]; data.function _ [null, null]; data.case _ fill; }; color: ImagerColor.SampledColor => { pm: ImagerSample.PixelMap _ NIL; cache: FunctionCache.Cache ~ FunctionCache.GlobalCache[]; compare: FunctionCache.CompareProc ~ { WITH argument SELECT FROM arg: ImagerColor.SampledColor => RETURN[arg.pa=color.pa AND arg.colorOperator=color.colorOperator]; ENDCASE => RETURN[FALSE]; }; WITH cache.Lookup[compare: compare, clientID: me].value SELECT FROM value: ImagerSample.PixelMap => pm _ value; ENDCASE => { maxOut: PixelProc ~ { check: [0..3) ~ i; RETURN[255] }; pm _ ImagerColor.Translate[self: color.colorOperator, output: outputRGB, pa: color.pa, maxOut: maxOut]; IF color.pa.immutable THEN cache.Insert[argument: color, value: pm, size: 3*INT[pm.size.s]*INT[pm.size.f]/2, clientID: me]; }; data.pm _ pm; data.pmToDevice.ApplyCat[color.pa.m, color.um, viewToDevice]; data.case _ sampledColor; }; color: ImagerColor.SpecialColor => SELECT color.type FROM $Invert => { data.valueA _ 377B*400B+377B; data.valueB _ 377B; data.function _ [xor, null]; data.case _ fill; }; ENDCASE => SetColorColor24[self, color.substitute, viewToDevice]; ENDCASE => ERROR; -- unknown color variant }; ModifyColorFrame: PROC [data: Data, action: PROC, bounds: Box] ~ INLINE { IF data.terminal=NIL THEN action[] ELSE Terminal.ModifyColorFrame[vt: data.terminal, action: action, xmin: bounds.min.f, ymin: bounds.min.s, xmax: bounds.max.f, ymax: bounds.max.s]; }; interpolate: BOOL _ TRUE; MaskBoxesColor24: MaskBoxesProc ~ { data: Data ~ NARROW[self.data]; actionMaskBoxesColor24: PROC ~ { SELECT data.case FROM nil => ERROR; -- color not initialized fill => { data.frameA.FillBoxes[boxes: boxes, value: data.valueA, function: data.function]; data.frameB.FillBoxes[boxes: boxes, value: data.valueB, function: data.function]; }; tile => { data.frameA.TileBoxes[boxes: boxes, tile: data.tileA, s0: data.s0, f0: data.f0, phase: data.phase, function: data.function]; data.frameB.TileBoxes[boxes: boxes, tile: data.tileB, s0: data.s0, f0: data.f0, phase: data.phase, function: data.function]; }; sampledColor => { sampledColorAction: PROC [pixels: PixelBuffer, min: Vec] ~ { s: NAT ~ min.s; f: NAT ~ min.f; data.frameRG.PutSamples[min: [s: s, f: f*2], delta: [s: 0, f: 2], samples: pixels[0], function: data.function]; data.frameRG.PutSamples[min: [s: s, f: f*2+1], delta: [s: 0, f: 2], samples: pixels[1], function: data.function]; data.frameB.PutSamples[min: [s: s, f: f], delta: [s: 0, f: 1], samples: pixels[2], function: data.function]; }; data.pm.Resample[m: data.pmToDevice, interpolate: interpolate, boxes: boxes, bounds: bounds, action: sampledColorAction]; }; ENDCASE => ERROR; -- bogus case }; ModifyColorFrame[data: data, action: actionMaskBoxesColor24, bounds: bounds]; }; MoveBoxesColor24: MoveBoxesProc ~ { data: Data ~ NARROW[self.data]; actionMoveBoxesColor24: PROC ~ { data.frameA.MoveBoxes[boxes: boxes, srcOffset: offset]; data.frameB.MoveBoxes[boxes: boxes, srcOffset: offset]; }; dmin: Vec ~ bounds.min; dmax: Vec ~ bounds.max; smin: Vec ~ dmin.Add[offset]; smax: Vec ~ dmax.Add[offset]; moveBounds: Box ~ [min: dmin.Min[smin], max: dmax.Max[smax]]; ModifyColorFrame[data: data, action: actionMoveBoxesColor24, bounds: moveBounds]; }; END. ImagerDeviceColor24Impl.mesa Copyright c 1984, 1985, 1986 by Xerox Corporation. All rights reserved. Michael Plass, August 13, 1985 10:50:50 am PDT Doug Wyatt, March 6, 1986 9:29:27 pm PST color: ImagerColor.SampledBlack => { data.tile _ color.pa.MapFromLayer[0]; data.paToDevice.ApplyCat[color.pa.m, color.um, viewToDevice]; data.function _ IF color.clear THEN [or, null] ELSE [null, null]; IF data.srcToDevice.form=3 THEN { data.s0 _ data.f0 _ 0; data.phase _ 0; data.case _ tile; } ELSE data.case _ sampledBlack; }; $Stipple => { stipple: StippleData ~ NARROW[color.data]; data.tile _ stipple.tile; data.function _ stipple.function; data.s0 _ data.f0 _ 0; data.phase _ 0; data.case _ tile; }; sampledBlack => { sampledBlackAction: PROC [samples: SampleBuffer, min: Vec] ~ { ImagerSample.PutSamples[self: data.frame, min: min, samples: samples, function: data.function]; }; ImagerSample.Resample[self: data.tile, m: data.srcToDevice, interpolate: FALSE, boxes: boxes, bounds: bounds, action: sampledBlackAction]; }; Κ ˜codešœ™Kšœ Οmœ=™HK™.K™(—K˜šΟk ˜ Kšœžœ3˜FKšœ ˜ Kšœ˜Kšœ ˜ Kšœ žœ˜Kšœ ˜ Kšœ˜Kšžœ˜Kšœ žœV˜dKšœžœžœ˜—K˜KšΠblœžœž˜&KšžœOžœ ˜bKšžœ ˜Kšœžœžœ*˜6K˜Kšœžœ'˜;Kšœ žœ˜)Kšœ žœ˜-Kšœ žœ˜'K˜šœ%žœ˜)K˜—šœ%˜%Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜K˜—šΟnœžœžœžœ ˜OKšœM˜MKšœM˜MKšžœžœžœ)žœžœžœ)žœžœžœ˜šžœ˜KšœB˜BKšœB˜BKšœ žœA˜QKšœžœ˜2šœ>˜>KšœQ˜Q—šžœ2˜9K˜UK˜4Kšœ6˜6—šžœžœ/˜9Kšœ+˜+Kšœ!˜!Kšœ4˜4Kšœ˜Kšœ˜—K˜—K˜K˜—šœžœžœΟc;˜[K˜—š œ˜!Kšœ žœ ˜šžœžœž˜˜%Kšœ)žœ˜7šœ žœ˜+K˜*K˜K˜—K˜RKšœ˜Kšœ˜K˜—šœ$™$Kšœ%™%Kšœ=™=Kšœžœ žœ žœ™Ašžœžœ™!K™K™Kšœ™K™—Kšžœ™K™—šœ$˜$Kšœžœ˜ Kšœ9˜9šœ&˜&šžœ žœžœ"˜;Kšžœžœ(˜BKšžœžœžœ˜—Kšœ˜—šžœ4žœž˜CKšœ+˜+šžœ˜ Kšœ)žœ˜7Kšœh˜hKšžœžœ3žœ žœ˜|K˜——Kšœ ˜ Kšœ=˜=K˜K˜—šœ#žœ ž˜9˜ K˜K˜K˜K˜K˜—™ Kšœžœ ™*K™K™!K™&K™K™—Kšžœ:˜A—Kšžœžœ‘˜*—Kšœ˜K˜—•StartOfExpansiont[vt: Terminal.Virtual, action: PROC, xmin: NAT _ 0, ymin: NAT _ 0, xmax: NAT _ 32767, ymax: NAT _ 32767]š œžœžœžœ˜IKšžœžœžœ ˜"Kšžœ˜“Kšœ˜K˜—šœ žœžœ˜K˜—š œ˜#Kšœ žœ ˜šœžœ˜ šžœ ž˜Kšœžœ‘˜&˜ K˜RK˜RK˜—˜ K˜}K˜}K˜—™šœžœ&™>K™`K™—KšœIžœ<™ŠK™—˜šœžœ$˜