DIRECTORY ImagerFourColorContext USING [Toner], Imager USING [Context], ImagerBrick USING [HalftoneProperties], ImagerColor USING [Color], ImagerDevice USING [AllowedMasks, Device, DeviceClass, DeviceClassRep, DeviceParm, MakeDeviceParm], ImagerDeviceColor, ImagerMaskCache USING [GetNamedCache, SetNamedCacheParameters], ImagerPrintColor USING [DeviceColorData, MaskBoxes, NewDeviceColorData, SetDeviceColorData, SetSeparation], ImagerPrintColorPrivate, ImagerPrivate USING [Class], ImagerRaster USING [Create, CreateClass, GetDevice, SetDeviceClipBox], ImagerSample USING [BasicTransfer, Box, Function, GetBox, RasterSampleMap, RawDescriptor, RawListTransfer, SampleMap], ImagerTransformation USING [Transformation, ScanMode], PrintColor USING [ColorCorrection, HalftoneProperties, LogicalDevice, Toner], SF USING [Box, BoxAction, BoxGenerator, Vec], SFInline USING [Size, Sub], Vector2 USING [VEC]; ImagerFourColorContextImpl: CEDAR PROGRAM IMPORTS ImagerDevice, ImagerDeviceColor, ImagerMaskCache, ImagerPrintColor, ImagerPrintColorPrivate, ImagerRaster, ImagerSample, SFInline EXPORTS ImagerFourColorContext ~ BEGIN Color: TYPE ~ ImagerColor.Color; Context: TYPE ~ Imager.Context; Transformation: TYPE ~ ImagerTransformation.Transformation; Toner: TYPE ~ ImagerFourColorContext.Toner; -- {black, cyan, magenta, yellow}; toners: ARRAY Toner OF PrintColor.Toner ~ [black, cyan, magenta, yellow]; Data: TYPE ~ REF DataRep; DataRep: TYPE ~ RECORD [ bitmaps: ARRAY Toner OF ImagerSample.SampleMap ¬ ALL[NIL], deviceColorData: ARRAY Toner OF ImagerPrintColor.DeviceColorData ¬ ALL[NIL] ]; fontCacheName: ATOM ~ $FourColorPrint; fontCacheMaxSize: INT ¬ 8000; Create: PUBLIC PROC [deviceSpaceSize: SF.Vec, scanMode: ImagerTransformation.ScanMode, surfaceUnitsPerInch: Vector2.VEC, logicalDevice: PrintColor.LogicalDevice, halftoneProperties: PrintColor.HalftoneProperties, correction: PrintColor.ColorCorrection, interpolate: BOOL, bitmaps: ARRAY Toner OF ImagerSample.SampleMap] RETURNS [Imager.Context] ~ { box: ImagerSample.Box ~ ImagerSample.GetBox[map: bitmaps[black]]; data: Data ~ NEW[DataRep ¬ [ bitmaps: bitmaps, deviceColorData: ALL[NIL] ]]; deviceParm: ImagerDevice.DeviceParm ~ ImagerDevice.MakeDeviceParm[ class: deviceClass, sSize: deviceSpaceSize.s, fSize: deviceSpaceSize.f, scanMode: scanMode, surfaceUnitsPerInch: surfaceUnitsPerInch, surfaceUnitsPerPixel: 1, fontCache: ImagerMaskCache.GetNamedCache[fontCacheName] ]; context: Imager.Context ~ ImagerRaster.Create[class: contextClass, deviceClass: deviceClass, deviceParm: deviceParm, data: data, pixelUnits: FALSE]; device: ImagerDevice.Device ~ ImagerRaster.GetDevice[context]; ImagerRaster.SetDeviceClipBox[context: context, clipBox: box]; FOR t: Toner IN Toner DO deviceColorData: ImagerPrintColor.DeviceColorData = ImagerPrintColor.NewDeviceColorData[logicalDevice: logicalDevice, halftoneProperties: halftoneProperties, correction: correction, interpolate: interpolate]; ImagerPrintColorPrivate.SetDeviceColorControl[deviceColorData, ImagerDeviceColor.GetDeviceColorControl[device]]; ImagerPrintColor.SetSeparation[deviceColorData, toners[t]]; data.deviceColorData[t] ¬ deviceColorData; ENDLOOP; RETURN [context] }; SetBitmaps: PUBLIC PROC [context: Imager.Context, bitmaps: ARRAY Toner OF ImagerSample.SampleMap] ~ { device: ImagerDevice.Device = ImagerRaster.GetDevice[context]; data: Data ~ NARROW[device.data]; box: ImagerSample.Box ~ ImagerSample.GetBox[map: bitmaps[black]]; ImagerRaster.SetDeviceClipBox[context: context, clipBox: box]; FOR t: Toner IN Toner DO data.bitmaps[t] ¬ bitmaps[t]; ENDLOOP; }; MySetColor: PROC [device: ImagerDevice.Device, color: Color, viewToDevice: Transformation] ~ { data: Data ~ NARROW[device.data]; constant: BOOL ¬ TRUE; allowFunnyBoxes: BOOL ¬ TRUE; allRasterSampleMaps: BOOL ¬ TRUE; FOR t: Toner IN Toner DO deviceColorData: ImagerPrintColor.DeviceColorData ~ data.deviceColorData[t]; ImagerPrintColor.SetDeviceColorData[deviceColorData, color, viewToDevice]; IF deviceColorData.case # constant THEN constant ¬ FALSE; IF deviceColorData.case >= sampledColor THEN allowFunnyBoxes ¬ FALSE; IF NOT ISTYPE[data.bitmaps[t], ImagerSample.RasterSampleMap] THEN allRasterSampleMaps ¬ FALSE ENDLOOP; device.state.allow ¬ [ unorderedBoxes: allowFunnyBoxes, multipleCoverage: allowFunnyBoxes, bitmap: constant, rawBitmaps: (constant AND allRasterSampleMaps) ]; }; TranslateHalftoneProperties: PROC [h: ImagerBrick.HalftoneProperties] RETURNS [PrintColor.HalftoneProperties] ~ { RETURN[ IF h = NIL THEN NIL ELSE CONS[ [type: h.first.type, toner: LOOPHOLE[h.first.toner], brick: h.first.brick], TranslateHalftoneProperties[h.rest]]] }; MySetHalftoneProperties: PROC [device: ImagerDevice.Device, halftoneProperties: ImagerBrick.HalftoneProperties] ~ { data: Data ~ NARROW[device.data]; h: PrintColor.HalftoneProperties ~ TranslateHalftoneProperties[halftoneProperties]; FOR which: Toner IN Toner DO data.deviceColorData[which].halftoneProperties ¬ h; ENDLOOP; }; MyMaskBoxes: PROC [device: ImagerDevice.Device, bounds: SF.Box, boxes: SF.BoxGenerator] ~ { data: Data ~ NARROW[device.data]; FOR which: Toner IN Toner DO ImagerPrintColor.MaskBoxes[data.bitmaps[which], data.deviceColorData[which], bounds, boxes]; ENDLOOP; }; MyMaskBitmap: PROC [device: ImagerDevice.Device, bitmap: ImagerSample.SampleMap, delta: SF.Vec, bounds: SF.Box, boxes: SF.BoxGenerator] ~ { data: Data ~ NARROW[device.data]; function: ARRAY Toner OF ImagerSample.Function ¬ ALL[[null, null]]; Box: SF.BoxAction = { FOR t: Toner IN Toner DO ImagerSample.BasicTransfer[dst: data.bitmaps[t], src: bitmap, dstMin: box.min, srcMin: SFInline.Sub[box.min, delta], size: SFInline.Size[box], function: function[t]]; ENDLOOP; }; FOR t: Toner IN Toner DO IF data.deviceColorData[t].case # constant THEN ERROR; SELECT data.deviceColorData[t].ink FROM nop => NULL; set => function[t] ¬ [or, null]; remove => function[t] ¬ [and, complement]; ENDCASE => ERROR; ENDLOOP; boxes[Box]; }; MyMaskRawBitmaps: PROC [device: ImagerDevice.Device, list: LIST OF ImagerSample.RawDescriptor] = { data: Data = NARROW[device.data]; function: ImagerSample.Function ¬ [null, null]; FOR t: Toner IN Toner DO local: ImagerSample.RasterSampleMap ~ NARROW [data.bitmaps[t]]; IF data.deviceColorData[t].case # constant THEN ERROR; SELECT data.deviceColorData[t].ink FROM nop => NULL; set => function ¬ [or, null]; remove => function ¬ [and, complement]; ENDCASE => ERROR; ImagerSample.RawListTransfer[dst: local, src: list, function: function]; ENDLOOP; }; deviceClass: ImagerDevice.DeviceClass ~ NEW[ImagerDevice.DeviceClassRep ¬ [ SetColor: MySetColor, SetHalftoneProperties: MySetHalftoneProperties, MaskBoxes: MyMaskBoxes, MaskBitmap: MyMaskBitmap, MaskRawBitmaps: MyMaskRawBitmaps ]]; contextClass: ImagerPrivate.Class ~ ImagerRaster.CreateClass[type: $FourColor]; ImagerMaskCache.SetNamedCacheParameters[fontCacheName, [sizeLimit: fontCacheMaxSize, runsCost: [slope: 2, offset: 3]]]; END. R ImagerFourColorContextImpl.mesa Copyright Σ 1989, 1990, 1991, 1992, 1993 by Xerox Corporation. All rights reserved. Tim Diebert: January 6, 1993 12:04 pm PST Doug Wyatt, September 14, 1989 2:34:44 pm PDT Dave Rumph, May 25, 1990 12:43:50 pm PDT Michael Plass, October 25, 1993 1:42 pm PDT Copied types Local types Local variables Exported procedures Imager procedures The following is nifty, but unfortunately, it doesn't work for transparent sampled blacks, in which the non-black toners' action is a nop, breaking the recursion. -- Dave Rumph, May 25, 1990 12:40:46 pm PDT MyMaskBoxes: PROC [device: ImagerDevice.Device, bounds: SF.Box, boxes: SF.BoxGenerator] ~ { data: Data ~ NARROW[device.data]; Here's a good one for you... Inner: PROC [which: Toner, prevBoxAction: SF.BoxAction _ NIL] ~ { NextGen: SF.BoxGenerator = { [boxAction: SF.BoxAction] ThisAction: SF.BoxAction = { prevBoxAction[box]; boxAction[box] }; IF which = Toner.LAST THEN boxes[ThisAction] ELSE Inner[which.SUCC, IF prevBoxAction = NIL THEN boxAction ELSE ThisAction]; }; ImagerPrintColor.MaskBoxes[data.bitmaps[which], data.deviceColorData[which], bounds, NextGen]; }; Inner[Toner.FIRST]; }; Eliminate this when PrintColor.HalftoneProperties becomes the same as ImagerBrick.HalftoneProperties Note that a SetColor should be done before further masking. [box: SF.Box] Start trap Κ ™–(cedarcode) style•NewlineDelimiter ™šœ™Icodešœ ΟeœI™TK™)K™-K™(K™+—K˜šΟk ˜ Kšœžœ ˜%Kšœžœ ˜Kšœ žœ˜'Kšœ žœ ˜Kšœ žœQ˜cK˜Kšœžœ*˜?KšœžœU˜kK˜Kšœžœ ˜Kšœ žœ4˜FKšœ žœd˜vKšœžœ˜6Kšœ žœ=˜MKšžœžœ%˜-Kšœ žœ ˜Kšœžœžœ˜—K˜K˜KšΠlnœž ˜)Kšžœ‚˜‰Kšžœ˜Kšœž˜head2™ Kšœžœ˜ Kšœ žœ˜Kšœžœ'˜;—™ Kšœžœ!Οc"˜NKšœžœžœ3˜IK˜Kšœžœžœ ˜šœ žœžœ˜Kš œ žœžœžœžœ˜:Kš œžœžœ$žœžœ˜KKšœ˜——™Kšœžœ˜&Kšœžœ˜—™šΟnœžœžœžœLžœ“žœ žœžœžœ˜άKšœA˜Ašœ žœ ˜Kšœ˜Kšœžœžœ˜Kšœ˜—šœB˜BKšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ)˜)Kšœ˜Kšœ7˜7Kšœ˜—Kšœžœ˜”K˜>K•StartOfExpansion.[context: Imager.Context, clipBox: SF.Box]šœ>˜>šžœ žœž˜K˜ΠK˜pK˜;K˜*Kšžœ˜—Kšžœ ˜Kšœ˜—K˜š ‘ œžœžœ$žœžœ˜eK˜>Kšœ žœ˜!KšœA˜AK–.[context: Imager.Context, clipBox: SF.Box]šœ>˜>šžœ žœž˜K˜Kšžœ˜—Kšœ˜——™š‘ œžœN˜^Kšœ žœ˜!Kšœ žœžœ˜Kšœžœžœ˜Kšœžœžœ˜!šžœ žœž˜KšœL˜LKšœJ˜JKšžœ!žœ žœ˜9Kšžœ&žœžœ˜EKš žœžœžœ0žœž˜]Kšžœ˜—šœ˜Kšœ ˜ Kšœ"˜"Kšœ˜Kšœžœ˜.Kšœ˜—Kšœ˜K˜—K™Οš‘ œžœ'žœ žœ™[Kšœ žœ™!K– -- [boxAction: SF.BoxAction]™š‘œžœžœ žœ™A– -- [boxAction: SF.BoxAction]š‘œžœ™Kšœ žœ ™Kš‘ œžœ4™Bšžœž™Kšžœ™Kš žœ žœžœžœžœ žœ ™N—K™—Kšœ^™^Kšœ™—Kšœ žœ™Kšœ™K™—š‘œžœ%žœ$˜qJ™dšžœ˜šžœž˜ Kšžœž˜šžœžœ˜ Kšœžœ'˜KK˜%———Kšœ˜K˜—š‘œžœV˜sKšœ žœ˜!K˜S– -- [boxAction: SF.BoxAction]šžœžœž˜K˜3Kšžœ˜—K™;K˜K˜—š‘ œžœ'žœ žœ˜[Kšœ žœ˜!– -- [boxAction: SF.BoxAction]šžœžœž˜Kšœ\˜\Kšžœ˜—Kšœ˜K˜—š ‘ œžœFžœžœ žœ˜‹Kšœ žœ˜!Kšœ žœžœžœ˜C– -- [box: SF.Box]š‘œžœ˜KšΠck ™ šžœ žœž˜K–ΰ[dst: ImagerSample.SampleMap, src: ImagerSample.SampleMap, dstMin: SF.Vec _ [s: 0, f: 0], srcMin: SF.Vec _ [s: 0, f: 0], size: SF.Vec, function: ImagerSample.Function _ [dstFunc: null, srcFunc: null]]šœ¦˜¦Kšžœ˜—K˜—šžœ žœž˜Kšžœ)žœžœ˜6šžœž˜'Kšœžœ˜ K˜ K˜*Kšžœžœ˜—Kšžœ˜—Kšœ ˜ Kšœ˜K˜—š‘œžœ%žœžœ ˜bKšœ žœ˜!K˜/šžœ žœž˜Kšœ&žœ˜?Kšžœ)žœžœ˜6šžœž˜'Kšœžœ˜ K˜K˜'Kšžœžœ˜—KšœH˜HKšžœ˜—K˜——™ šœ)žœ ˜LKš‘œ ˜Kš‘œ˜/Kš‘ œ˜Kš‘ œ˜Kš‘œ˜ Kšœ˜K˜—KšœO˜OK˜Kšœw˜w—K˜K˜Kšžœ˜—…—&*