From e08fb3a914ac348dc691ae3fc46c6bdbc34faf46 Mon Sep 17 00:00:00 2001 From: Phil Race Date: Fri, 23 Jan 2026 18:19:23 +0000 Subject: [PATCH] 8375221: Update code to get PrinterResolution from CUPS/IPP print service Reviewed-by: serb, psadhukhan --- .../classes/sun/print/AttributeClass.java | 24 +++++++ .../classes/sun/print/IPPPrintService.java | 67 ++++++++++--------- .../unix/native/common/awt/CUPSfuncs.c | 57 +++++++++++++++- test/jdk/javax/print/PrintablePrintDPI.java | 8 ++- 4 files changed, 120 insertions(+), 36 deletions(-) diff --git a/src/java.desktop/unix/classes/sun/print/AttributeClass.java b/src/java.desktop/unix/classes/sun/print/AttributeClass.java index 10d0714a059..3db6e310dd2 100644 --- a/src/java.desktop/unix/classes/sun/print/AttributeClass.java +++ b/src/java.desktop/unix/classes/sun/print/AttributeClass.java @@ -174,6 +174,30 @@ public final class AttributeClass { } + /** + * Returns 3 int values. + * xres, yres, resolution as either dpi or dpcm + * The resolution is just a single byte of data. + */ + public int[] getIntResolutionValue() { + int[] res = {0, 0, 0}; + byte[] bufArray = (byte[])myValue; + if (bufArray != null) { + int nBytes = 4; // 32-bit signed integer + for (int j=0; j<2; j++) { // 2 set of integers + byte[] intBytes = new byte[nBytes]; + // REMIND: # bytes should be 8 + for (int i=0; i< nBytes; i++) { + //+ 1 because the 1st byte is length + intBytes[i] = bufArray[i+(4*j)+1]; + } + res[j] = convertToInt(intBytes); + } + res[2] = (int)bufArray[9]; + } + return res; + } + /** * Returns String value. */ diff --git a/src/java.desktop/unix/classes/sun/print/IPPPrintService.java b/src/java.desktop/unix/classes/sun/print/IPPPrintService.java index 2bf326fca57..8a3b872b107 100644 --- a/src/java.desktop/unix/classes/sun/print/IPPPrintService.java +++ b/src/java.desktop/unix/classes/sun/print/IPPPrintService.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -141,7 +141,7 @@ public final class IPPPrintService implements PrintService, SunPrinterJobService private MediaSizeName[] mediaSizeNames; private CustomMediaSizeName[] customMediaSizeNames; private int defaultMediaIndex; - private int[] rawResolutions = null; + private int[] ppdResolutions = null; private PrinterResolution[] printerResolutions = null; private boolean isCupsPrinter; private boolean init; @@ -205,8 +205,7 @@ public final class IPPPrintService implements PrintService, SunPrinterJobService OrientationRequested.PORTRAIT, new PageRanges(1), //PresentationDirection, - // CUPS does not supply printer-resolution attribute - //new PrinterResolution(300, 300, PrinterResolution.DPI), + new PrinterResolution(300, 300, PrinterResolution.DPI), //PrintQuality.NORMAL, new RequestingUserName("", Locale.getDefault()), //SheetCollate.UNCOLLATED, //CUPS has no sheet collate? @@ -467,7 +466,9 @@ public final class IPPPrintService implements PrintService, SunPrinterJobService : getSupportedOutputBins(); customMediaSizeNames = cps.getCustomMediaSizeNames(); defaultMediaIndex = cps.getDefaultMediaIndex(); - rawResolutions = cps.getRawResolutions(); + if (ppdResolutions == null) { + ppdResolutions = cps.getRawResolutions(); + } } urlConnection.disconnect(); init = true; @@ -821,14 +822,7 @@ public final class IPPPrintService implements PrintService, SunPrinterJobService } } } else if (category == PrinterResolution.class) { - PrinterResolution[] supportedRes = getPrintResolutions(); - if (supportedRes == null) { - return null; - } - PrinterResolution []arr = - new PrinterResolution[supportedRes.length]; - System.arraycopy(supportedRes, 0, arr, 0, supportedRes.length); - return arr; + return getPrintResolutions(); } else if (category == OutputBin.class) { return Arrays.copyOf(outputBins, outputBins.length); } @@ -1137,8 +1131,6 @@ public final class IPPPrintService implements PrintService, SunPrinterJobService catList.add(Chromaticity.class); } - // CUPS does not report printer resolution via IPP but it - // may be gleaned from the PPD. PrinterResolution[] supportedRes = getPrintResolutions(); if (supportedRes != null && (supportedRes.length > 0)) { catList.add(PrinterResolution.class); @@ -1264,7 +1256,6 @@ public final class IPPPrintService implements PrintService, SunPrinterJobService } } - @Override public synchronized PrintServiceAttributeSet getAttributes() { if (!init) { @@ -1684,9 +1675,7 @@ public final class IPPPrintService implements PrintService, SunPrinterJobService } else if (category == PrinterResolution.class) { PrinterResolution[] supportedRes = getPrintResolutions(); if ((supportedRes != null) && (supportedRes.length > 0)) { - return supportedRes[0]; - } else { - return new PrinterResolution(300, 300, PrinterResolution.DPI); + return supportedRes[0]; } } else if (category == OutputBin.class) { if (attribClass != null) { @@ -1697,26 +1686,40 @@ public final class IPPPrintService implements PrintService, SunPrinterJobService return null; } + /* Called only from contexts that have called initAttributes(). + * Try IPP first, and if that produces nothing, fall back to the PPD + */ private PrinterResolution[] getPrintResolutions() { + int[] rawResolutions = null; if (printerResolutions == null) { - if (rawResolutions == null) { - printerResolutions = new PrinterResolution[0]; - } else { - int numRes = rawResolutions.length / 2; - PrinterResolution[] pres = new PrinterResolution[numRes]; - for (int i=0; i < numRes; i++) { - pres[i] = new PrinterResolution(rawResolutions[i*2], - rawResolutions[i*2+1], - PrinterResolution.DPI); - } - printerResolutions = pres; + AttributeClass attribClass = (getAttMap != null) ? + getAttMap.get("printer-resolution-supported") + : null; + if (attribClass != null) { + rawResolutions = attribClass.getIntResolutionValue(); } + if (rawResolutions == null) { + rawResolutions = ppdResolutions; + } + if (rawResolutions == null) { + rawResolutions = new int[] { 300, 300, 3 } ; + } + int numRes = rawResolutions.length / 3; + PrinterResolution[] pres = new PrinterResolution[numRes]; + for (int i = 0; i < numRes; i++) { + int units = (rawResolutions[i*3+2] == 4) ? PrinterResolution.DPCM : PrinterResolution.DPI; + pres[i] = new PrinterResolution(rawResolutions[i*3], + rawResolutions[i*3+1], + units); + } + printerResolutions = pres; } - return printerResolutions; + return printerResolutions.clone(); } private boolean isSupportedResolution(PrinterResolution res) { - PrinterResolution[] supportedRes = getPrintResolutions(); + PrinterResolution[] supportedRes = + (PrinterResolution[])getSupportedAttributeValues(PrinterResolution.class, null, null); if (supportedRes != null) { for (int i=0; iNewObject(env, intCls, intCtr, 3); + CHECK_NULL(dpi); // NOTE: cupsGetPPD returns a pointer to a filename of a temporary file. // unlink() must be called to remove the file after using it. @@ -672,6 +691,7 @@ Java_sun_print_CUPSPrinter_getResolutions(JNIEnv *env, CHECK_NULL(ryObj); (*env)->CallBooleanMethod(env, arrayList, arrListAddMID, rxObj); (*env)->CallBooleanMethod(env, arrayList, arrListAddMID, ryObj); + (*env)->CallBooleanMethod(env, arrayList, arrListAddMID, dpi); } for (i = 0; i < resolution->num_choices; i++) { @@ -700,6 +720,41 @@ Java_sun_print_CUPSPrinter_getResolutions(JNIEnv *env, CHECK_NULL(ryObj); (*env)->CallBooleanMethod(env, arrayList, arrListAddMID, rxObj); (*env)->CallBooleanMethod(env, arrayList, arrListAddMID, ryObj); + (*env)->CallBooleanMethod(env, arrayList, arrListAddMID, dpi); + } + } + + } else { + ppd_attr_t *defresolution = j2d_ppdFindAttr(ppd, "DefaultResolution", NULL); + if (defresolution == NULL) { + defresolution = j2d_ppdFindAttr(ppd, "Resolution", NULL); + } + if (defresolution != NULL) { + int matches = sscanf(defresolution->value, "%dx%ddpi", &defx, &defy); + if (matches == 2) { + if (defx <= 0 || defy <= 0) { + defx = 0; + defy = 0; + } + } else { + matches = sscanf(defresolution->value, "%ddpi", &defx); + if (matches == 1) { + if (defx <= 0) { + defx = 0; + } else { + defy = defx; + } + } + } + if (defx > 0) { + jobject rxObj, ryObj; + rxObj = (*env)->NewObject(env, intCls, intCtr, defx); + CHECK_NULL(rxObj); + ryObj = (*env)->NewObject(env, intCls, intCtr, defy); + CHECK_NULL(ryObj); + (*env)->CallBooleanMethod(env, arrayList, arrListAddMID, rxObj); + (*env)->CallBooleanMethod(env, arrayList, arrListAddMID, ryObj); + (*env)->CallBooleanMethod(env, arrayList, arrListAddMID, dpi); } } } diff --git a/test/jdk/javax/print/PrintablePrintDPI.java b/test/jdk/javax/print/PrintablePrintDPI.java index 6cae2be532c..6b5e83df233 100644 --- a/test/jdk/javax/print/PrintablePrintDPI.java +++ b/test/jdk/javax/print/PrintablePrintDPI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2025, BELLSOFT. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -54,7 +54,7 @@ import java.awt.print.PrinterJob; /* * @test - * @bug 8251928 + * @bug 8251928 8375221 * @key printer * @summary Printable.print method should reflect printer's DPI * @library /java/awt/regtesthelpers @@ -201,7 +201,9 @@ public class PrintablePrintDPI implements Printable { attributeSet.add(OrientationRequested.PORTRAIT); job.setPrintService(printService); job.setPrintable(this); - job.print(attributeSet); + if (job.printDialog(attributeSet)) { + job.print(attributeSet); + } } catch (PrinterException ex) { throw new RuntimeException(ex); }