The fix provides ability to print Black & White pages on macOS.

Cocoa API has 
[PMSetColorMode](https://developer.apple.com/documentation/applicationservices/core_printing/1805783-pmsetcolormode)
 function but it is marked as deprecated and really does nothing.

There is no replacement; this function was included to facilitate porting 
legacy applications to macOS, 
but it serves no useful purpose.

Dumping `NSPrintInfo` print settings which were set by the native print dialog 
on macOS shows that the keys and values used for Black & White printing depend 
on the used printer type.
For example, the tested 
`HP Color LaserJet MFP M180n` printer uses `ColorModel` key and`Gray` value, and
`HP Ink Tank 110 series` uses `HPColorMode` key and `grayscale` value.

Printing all `NSPrintInfo` presets shows that they do not contain key/value 
pairs  for Black&White settings.
This is the code snippet used to print `NSPrintInfo` presets:

    PMPrinter pr;
    PMPrintSession printSession = (PMPrintSession)[printInfo PMPrintSession];
    OSStatus status = PMSessionGetCurrentPrinter(printSession, &pr);
    CFArrayRef presetsList = nil;
    status = PMPrinterCopyPresets(pr, &presetsList);
    CFIndex arrayCount = CFArrayGetCount(presetsList);

    for (CFIndex index = 0; index < arrayCount; index++) {
        PMPreset preset = (PMPreset)CFArrayGetValueAtIndex(presetsList, index);
        CFStringRef presetName = nil;
        if (PMPresetCopyName(preset, &presetName) == noErr && 
CFStringGetLength(presetName) > 0) {
            NSLog(@"  presetName: '%@'", presetName);
            NSDictionary* dict = nil;
            if (PMPresetGetAttributes(preset, (CFDictionaryRef*)(&dict)) == 
noErr) {
                   // print preset dict


The idea of the proposed fix is to store printer dependent key/value pairs in 
the `<jdk-home>/conf/printer.properties` property file.

The property file has the format:

print-attribute.print-attribute-value.key=value

where `print-attribute` is the java print attribute, `print-attribute-value` is 
the corresponding attribute value, and `key` and `value` is the key/value pair 
used by a specific printer.

For example, for `Chromaticity` attribute the property file could look like:

Chromaticity.MONOCHROME.ColorModel=Gray
Chromaticity.COLOR.ColorModel=CMYK
Chromaticity.MONOCHROME.HPColorMode=grayscale
Chromaticity.COLOR.HPColorMode=color

where `Chromaticity.MONOCHROME` key prefix corresponds to 
`Chromaticity.MONOCHOROME` print attribute constant  with  (`ColorModel`, 
`Gray`) and (`HPColorMode`, `grayscale`) key/value pairs.
Similarly `Chromaticity.COLOR` key prefix with  (`ColorModel`, `CMYK`) and 
(`HPColorMode`, `color`) key/value pairs correspond to `Chromaticity.COLOR` 
print attribute.

https://www.openprinting.org/download/PPD/ site has been used to collect 
`monochrome` and `color` constants from ppd files and save them in 
`<jdk-home>/conf/printer.properties` file.

For example, for the Brother printer the 
https://www.openprinting.org/download/PPD/Brother/BR9440_2_GPL.ppd ppd file 
defines `BRPrintQuality` option:

*OpenUI *BRPrintQuality/Color/Mono: PickOne
*OrderDependency: 15 AnySetup *BRPrintQuality
*DefaultBRPrintQuality: Auto
*BRPrintQuality Auto/Auto: "
        <</BRProcessColor 4 /BRHrc 0>>setpagedevice
        <</BRColorAdapt true>>setpagedevice
        <</BRRenderMode false>>setpagedevice"
*BRPrintQuality Color/Color: "
        <</BRProcessColor 4 /BRHrc 0>>setpagedevice
        <</BRColorAdapt false>>setpagedevice
        <</BRRenderMode false>>setpagedevice"
*BRPrintQuality Black/Mono: "
        <</BRProcessColor 1>>setpagedevice
        <</BRColorAdapt false>>setpagedevice
        <</BRRenderMode true>>setpagedevice"
...
*CloseUI: *BRPrintQuality


which is listed in the `printer.properties` file as:

Chromaticity.MONOCHROME.BRPrintQuality=Black
Chromaticity.COLOR.BRPrintQuality=Color


and for the Epson printer the 
https://www.openprinting.org/download/PPD/Epson/epal2600.ppd ppd file defines 
`EPRendering` option:

*OpenUI *EPRendering/Color Mode: PickOne
*% EPRendering must be after EPColorModel
*OrderDependency: 50 AnySetup *EPRendering
*DefaultEPRendering: None
*EPRendering None/Mono: "
        <</ProcessColorModel (DeviceGray)
        /DeviceRenderingInfo <</Type 29 /ValuesPerColorComponent 256>> >>
        setpagedevice"
*End
*% ProcessColorModel is already set in EPColorModel
*EPRendering RGB/Color: "
        << /ProcessColorModel (DeviceRGB) >> setpagedevice
        <</DeviceRenderingInfo <</Type 29 /ValuesPerColorComponent 256>> >>
        setpagedevice"
...
*CloseUI: *EPRendering


which is listed in the `printer.properties` file as:

Chromaticity.MONOCHROME.EPRendering=None
Chromaticity.COLOR.EPRendering=RGB


The full list of constants from https://www.openprinting.org/download/PPD/ used 
in `printer.properties` is

# Brother
Chromaticity.MONOCHROME.BRPrintQuality=Black
Chromaticity.COLOR.BRPrintQuality=Color

# Dell
Chromaticity.MONOCHROME.DLColorMode=Black
Chromaticity.COLOR.DLColorMode=Color

# Epson
Chromaticity.MONOCHROME.EPRendering=None
Chromaticity.COLOR.EPRendering=RGB

# Gestener
# Kyocera
# Lanier
# NRG
# Ricoh
# Savin
# Utax
Chromaticity.MONOCHROME.ColorModel=Gray
Chromaticity.COLOR.ColorModel=CMYK

# HP
Chromaticity.MONOCHROME.HPColorAsGray=Yes
Chromaticity.COLOR.HPColorAsGray=No

# KONICA_MINOLTA
Chromaticity.MONOCHROME.SelectColor=Grayscale
Chromaticity.COLOR.SelectColor=Color

# Lexmark
Chromaticity.MONOCHROME.ColorMode=FalseM
Chromaticity.COLOR.ColorMode=TrueM
Chromaticity.MONOCHROME.BLW=FalseM
Chromaticity.COLOR.BLW=TrueM

# Oki
Chromaticity.MONOCHROME.OKControl=Gray
Chromaticity.COLOR.OKControl=Auto

# Sharp
Chromaticity.MONOCHROME.ARCMode=CMBW
Chromaticity.COLOR.ARCMode=CMColor

# Xerox
Chromaticity.MONOCHROME.XRXColor=BW
Chromaticity.COLOR.XRXColor=Automatic

Chromaticity.MONOCHROME.XRColorMode=Black
Chromaticity.COLOR.XRColorMode=Color

Chromaticity.MONOCHROME.XRColorModeSetting=Black
Chromaticity.COLOR.XRColorModeSetting=Color

Chromaticity.MONOCHROME.EFColorMode=GRAY
Chromaticity.COLOR.EFColorMode=CMYK


There are printers with the same color attributes and different values.

For example, Kyocera defines `ColorModel` Color option as `CMYK` in 
https://www.openprinting.org/download/PPD/Kyocera/en/Kyocera_CS-C4035E_en.ppd 
file:

*OpenUI *ColorModel/Color Mode: PickOne
*OrderDependency: 10 AnySetup *ColorModel
*DefaultColorModel: CMYK
*ColorModel CMYK/Color (CMYK): "<< /ProcessColorModel /DeviceCMYK >> 
setpagedevice"
*ColorModel Gray/Monochrome: "<< /ProcessColorModel /DeviceGray >> 
setpagedevice"
...
*CloseUI: *ColorModel


and Samsung defines the same `ColorModel` Color option as `Color`  in 
https://www.openprinting.org/download/PPD/Samsung/PS/Samsung_C2670_Series.ppd

*OrderDependency: 70 AnySetup *ColorModel
*DefaultColorModel: Color
*ColorModel Gray/Grayscale:  "<</ProcessColorModel /DeviceGray>> setpagedevice"
*ColorModel Color/Color:       "<</ProcessColorModel /DeviceCMYK>> 
setpagedevice"
*CloseUI: *ColorModel


The fix has been tested with 2 color printers `HP Color LaserJet MFP M180n` and 
`HP Ink Tank 110 series`.

`HP Color LaserJet MFP M180n` uses `ColorModel` key and `Gray` value for black 
& white printing.
`HP Ink Tank 110 series` uses `HPColorMode` key and `grayscale` value.

Only `HPColorAsGray` option with `Yes` and `No` values  is listed in 
https://www.openprinting.org/download/PPD/HP files.
For example, 
https://www.openprinting.org/download/PPD/HP/HP_DesignJet_3500CP_PS3.ppd

*OpenUI *HPColorAsGray/Print Color as Gray: PickOne
*OrderDependency: 5.0 AnySetup *HPColorAsGray
*DefaultHPColorAsGray: No
*HPColorAsGray Yes/Yes: "<< /ProcessColorModel /DeviceGray >> setpagedevice"
*HPColorAsGray No/No: "<< /ProcessColorModel /DeviceCMYK >> setpagedevice"
...
*CloseUI: *HPColorAsGray


Both `HPColorAsGray` and `HPColorMode` options are added to the 
`printer.properties` file as:

Chromaticity.MONOCHROME.HPColorAsGray=Yes
Chromaticity.COLOR.HPColorAsGray=No
Chromaticity.MONOCHROME.HPColorMode=grayscale
Chromaticity.COLOR.HPColorMode=color

-------------

Commit messages:
 - 8315113: Print request Chromaticity.MONOCHROME attribute does not work on 
macOS

Changes: https://git.openjdk.org/jdk/pull/18195/files
 Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=18195&range=00
  Issue: https://bugs.openjdk.org/browse/JDK-8315113
  Stats: 431 lines in 6 files changed: 429 ins; 1 del; 1 mod
  Patch: https://git.openjdk.org/jdk/pull/18195.diff
  Fetch: git fetch https://git.openjdk.org/jdk.git pull/18195/head:pull/18195

PR: https://git.openjdk.org/jdk/pull/18195

Reply via email to