RFR: 8315113: Print request Chromaticity.MONOCHROME attribute does not work on macOS [v4]

Phil Race prr at openjdk.org
Wed Dec 4 22:57:49 UTC 2024


On Thu, 28 Nov 2024 07:28:25 GMT, GennadiyKrivoshein <duke at openjdk.org> wrote:

>> This update allows users to print with grayscale using color printers.
>> Actually, it is not possible to use the "Monochrome" option from the "Color Appearance" panel. Also Chromaticity.MONOCHROME can't be used to print grayscale on color printers ([JDK-8315113](https://bugs.openjdk.org/browse/JDK-8315113)).
>> 
>> **Fix description**
>> When a printer supports color printing and a user adds Chromaticity.MONOCHROME attribute to a PrintRequestAttributeSet, then the final printing raster is transformed to the grayscale color using java.awt.image.ColorConvertOp. When the job is a PostScript job, then the "setColor" and "setPaint" methods of the Graphics are overridden, and user colors (paints) are transformed to the grayscale form using the new proxy class GrayscaleProxyGraphics2D.
>> 
>> This approach is assumed to be platform, CUPS, and IPP protocol independent.
>> 
>> **Tests**
>> The fix was tested on Ubuntu 22.04 and MacOS 12.6.1.
>
> GennadiyKrivoshein has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains eight commits:
> 
>  - Merge remote-tracking branch 'openjdk/master' into monochrome-printing
>    
>    # Conflicts:
>    #	src/java.desktop/share/classes/sun/print/RasterPrinterJob.java
>  - Merge remote-tracking branch 'openjdk/master' into monochrome-printing
>  - move grayscale methods to PSPathGraphics
>  - Update src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterJob.java
>    
>    Co-authored-by: Andrey Turbanov <turbanoff at gmail.com>
>  - update copyright
>  - formatting
>  - grammar fixes
>  - 8315113: Print request Chromaticity.MONOCHROME attribute does not work on macOS

I've pointed out some issues. That does not mean these are the only issues.

src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterJob.java line 794:

> 792:                     BufferedImage bufferedImage = new BufferedImage((int)page.getWidth(), (int)page.getHeight(),
> 793:                             BufferedImage.TYPE_INT_ARGB);
> 794:                     Graphics2D g2 = bufferedImage.createGraphics();

The problem here is that the image is not at printer resolution.
So it will be VERY grainy when printed.
If you are doing this band printing you need to do something like what is happening in RasterPrinterJob.
In fact probably defer to that.
And this is definitely a "mis-use" of path graphics.
On top of that I think it odd to create an image of BufferedImage.TYPE_INT_ARGB and then convert it to greyscale. Why not just create a BI of type BufferedImage.TYPE_USHORT_GRAY ? And then the conversion is done by 2D when drawing into it and there's no need to filter the image.
I tested that but for whatever reason I needed to clear the image to white first.
But I don't think you should be "here" if the only way you can do monochrome on mac is by printing a greyscale image. It should go to the existing code in RasterPrinterJob which will handle the resolution. It would be wrong to replicate that code here. I am not sure that code is used today in the mac printing path,. but it is the code that does what you need .. mostly.

src/java.desktop/share/classes/sun/print/PSPathGraphics.java line 858:

> 856:      * @return grayscale BufferedImage
> 857:      */
> 858:     private BufferedImage getGrayscaleImage(Image img) {

This code is bizarre. Why not just draw to a grayscale image ?

src/java.desktop/share/classes/sun/print/PSPrinterJob.java line 2:

> 1: /*
> 2:  * Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved.

Nothing changed here!

src/java.desktop/share/classes/sun/print/RasterPrinterJob.java line 1173:

> 1171:     }
> 1172: 
> 1173:     protected boolean isAttributeCategorySupported(Class<? extends Attribute> category) {

hmm. Not sure why this isn't private, and why it has the same name as the PrintService method which can be confusing.
It has one purpose and one use which is to ask if Chromaticity is supported so it can be clearer.

src/java.desktop/share/classes/sun/print/RasterPrinterJob.java line 2413:

> 2411:                         painterGraphics.dispose();
> 2412:                         if (monochrome) {
> 2413:                             monochromeConverter.filter(band, band);

Like I mentioned elsewhere, I think a greyscale image would mean you don't need to do this.
However the code that sends the image to the printer  needs a version that handles that format.
Currently the Postscript code handles only BGR .. 

Also, this code is used on WINDOWS as well as other platforms, and monochrome is handled natively by the printer, so this looks like it is doing things that are unnecessary on that platform.

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

Changes requested by prr (Reviewer).

PR Review: https://git.openjdk.org/jdk/pull/21930#pullrequestreview-2480062758
PR Review Comment: https://git.openjdk.org/jdk/pull/21930#discussion_r1870376113
PR Review Comment: https://git.openjdk.org/jdk/pull/21930#discussion_r1870379822
PR Review Comment: https://git.openjdk.org/jdk/pull/21930#discussion_r1870376422
PR Review Comment: https://git.openjdk.org/jdk/pull/21930#discussion_r1870385907
PR Review Comment: https://git.openjdk.org/jdk/pull/21930#discussion_r1870377584


More information about the client-libs-dev mailing list