8048328: CUPS Printing does not report supported printer resolutions.
Reviewed-by: bae, jgodinez
--- a/jdk/make/mapfiles/libawt/mapfile-mawt-vers Fri Jul 11 18:46:47 2014 +0400
+++ b/jdk/make/mapfiles/libawt/mapfile-mawt-vers Fri Jul 11 11:12:59 2014 -0700
@@ -204,6 +204,7 @@
Java_sun_print_CUPSPrinter_canConnect;
Java_sun_print_CUPSPrinter_getMedia;
Java_sun_print_CUPSPrinter_getPageSizes;
+ Java_sun_print_CUPSPrinter_getResolutions;
Java_com_sun_java_swing_plaf_gtk_GTKEngine_native_1paint_1arrow;
Java_com_sun_java_swing_plaf_gtk_GTKEngine_native_1paint_1box;
--- a/jdk/make/mapfiles/libawt_headless/mapfile-vers Fri Jul 11 18:46:47 2014 +0400
+++ b/jdk/make/mapfiles/libawt_headless/mapfile-vers Fri Jul 11 11:12:59 2014 -0700
@@ -76,6 +76,7 @@
Java_sun_print_CUPSPrinter_canConnect;
Java_sun_print_CUPSPrinter_getMedia;
Java_sun_print_CUPSPrinter_getPageSizes;
+ Java_sun_print_CUPSPrinter_getResolutions;
# libfontmanager entry points
AWTIsHeadless;
--- a/jdk/make/mapfiles/libawt_xawt/mapfile-vers Fri Jul 11 18:46:47 2014 +0400
+++ b/jdk/make/mapfiles/libawt_xawt/mapfile-vers Fri Jul 11 11:12:59 2014 -0700
@@ -442,6 +442,7 @@
Java_sun_print_CUPSPrinter_canConnect;
Java_sun_print_CUPSPrinter_getMedia;
Java_sun_print_CUPSPrinter_getPageSizes;
+ Java_sun_print_CUPSPrinter_getResolutions;
awt_GetDrawingSurface;
awt_FreeDrawingSurface;
--- a/jdk/src/share/classes/sun/print/PSPrinterJob.java Fri Jul 11 18:46:47 2014 +0400
+++ b/jdk/src/share/classes/sun/print/PSPrinterJob.java Fri Jul 11 11:12:59 2014 -0700
@@ -168,13 +168,6 @@
private static final String IMAGE_STR = " string /imStr exch def";
private static final String IMAGE_RESTORE = "imSave restore";
- private static final String COORD_PREP = " 0 exch translate "
- + "1 -1 scale"
- + "[72 " + PS_XRES + " div "
- + "0 0 "
- + "72 " + PS_YRES + " div "
- + "0 0]concat";
-
private static final String SetFontName = "F";
private static final String DrawStringName = "S";
@@ -275,6 +268,9 @@
private AffineTransform mLastTransform;
+ private double xres = PS_XRES;
+ private double yres = PS_XRES;
+
/* non-null if printing EPS for Java Plugin */
private EPSPrinter epsPrinter = null;
@@ -796,6 +792,15 @@
}
}
+ private String getCoordPrep() {
+ return " 0 exch translate "
+ + "1 -1 scale"
+ + "[72 " + getXRes() + " div "
+ + "0 0 "
+ + "72 " + getYRes() + " div "
+ + "0 0]concat";
+ }
+
/**
* The RasterPrintJob super class calls this method
* at the start of each page.
@@ -852,7 +857,7 @@
mPSStream.println(" >> setpagedevice");
}
mPSStream.println(PAGE_SAVE);
- mPSStream.println(paperHeight + COORD_PREP);
+ mPSStream.println(paperHeight + getCoordPrep());
}
/**
@@ -1493,14 +1498,22 @@
* to be rendered.
*/
protected double getXRes() {
- return PS_XRES;
+ return xres;
}
/**
* Return the y resolution of the coordinates
* to be rendered.
*/
protected double getYRes() {
- return PS_YRES;
+ return yres;
+ }
+
+ /**
+ * Set the resolution at which to print.
+ */
+ protected void setXYRes(double x, double y) {
+ xres = x;
+ yres = y;
}
/**
--- a/jdk/src/share/classes/sun/print/RasterPrinterJob.java Fri Jul 11 18:46:47 2014 +0400
+++ b/jdk/src/share/classes/sun/print/RasterPrinterJob.java Fri Jul 11 11:12:59 2014 -0700
@@ -72,6 +72,7 @@
import javax.print.attribute.AttributeSet;
import javax.print.attribute.HashPrintRequestAttributeSet;
import javax.print.attribute.PrintRequestAttributeSet;
+import javax.print.attribute.ResolutionSyntax;
import javax.print.attribute.Size2DSyntax;
import javax.print.attribute.standard.Chromaticity;
import javax.print.attribute.standard.Copies;
@@ -86,6 +87,7 @@
import javax.print.attribute.standard.MediaSizeName;
import javax.print.attribute.standard.OrientationRequested;
import javax.print.attribute.standard.PageRanges;
+import javax.print.attribute.standard.PrinterResolution;
import javax.print.attribute.standard.PrinterState;
import javax.print.attribute.standard.PrinterStateReason;
import javax.print.attribute.standard.PrinterStateReasons;
@@ -283,6 +285,7 @@
private String jobNameAttr;
private String userNameAttr;
private PageRanges pageRangesAttr;
+ protected PrinterResolution printerResAttr;
protected Sides sidesAttr;
protected String destinationAttr;
protected boolean noJobSheet = false;
@@ -1064,6 +1067,14 @@
attrset));
}
+ /**
+ * Set the device resolution.
+ * Overridden and used only by the postscript code.
+ * Windows code pulls the information from the attribute set itself.
+ */
+ protected void setXYRes(double x, double y) {
+ }
+
/* subclasses may need to pull extra information out of the attribute set
* They can override this method & call super.setAttributes()
*/
@@ -1072,6 +1083,7 @@
/* reset all values to defaults */
setCollated(false);
sidesAttr = null;
+ printerResAttr = null;
pageRangesAttr = null;
copiesAttr = 0;
jobNameAttr = null;
@@ -1117,6 +1129,18 @@
sidesAttr = Sides.ONE_SIDED;
}
+ printerResAttr = (PrinterResolution)attributes.get(PrinterResolution.class);
+ if (service.isAttributeCategorySupported(PrinterResolution.class)) {
+ if (!isSupportedValue(printerResAttr, attributes)) {
+ printerResAttr = (PrinterResolution)
+ service.getDefaultAttributeValue(PrinterResolution.class);
+ }
+ double xr =
+ printerResAttr.getCrossFeedResolution(ResolutionSyntax.DPI);
+ double yr = printerResAttr.getFeedResolution(ResolutionSyntax.DPI);
+ setXYRes(xr, yr);
+ }
+
pageRangesAttr = (PageRanges)attributes.get(PageRanges.class);
if (!isSupportedValue(pageRangesAttr, attributes)) {
pageRangesAttr = null;
--- a/jdk/src/solaris/classes/sun/print/CUPSPrinter.java Fri Jul 11 18:46:47 2014 +0400
+++ b/jdk/src/solaris/classes/sun/print/CUPSPrinter.java Fri Jul 11 11:12:59 2014 -0700
@@ -39,6 +39,7 @@
import javax.print.attribute.standard.MediaSize;
import javax.print.attribute.standard.MediaTray;
import javax.print.attribute.standard.MediaPrintableArea;
+import javax.print.attribute.standard.PrinterResolution;
import javax.print.attribute.Size2DSyntax;
import javax.print.attribute.Attribute;
import javax.print.attribute.EnumSyntax;
@@ -57,6 +58,8 @@
// CUPS does not support multi-threading.
private static synchronized native String[] getMedia(String printer);
private static synchronized native float[] getPageSizes(String printer);
+ private static synchronized native void
+ getResolutions(String printer, ArrayList<Integer> resolutionList);
//public static boolean useIPPMedia = false; will be used later
private MediaPrintableArea[] cupsMediaPrintables;
@@ -68,6 +71,7 @@
public int nTrays = 0;
private String[] media;
private float[] pageSizes;
+ int[] resolutionsArray;
private String printer;
private static boolean libFound;
@@ -119,6 +123,12 @@
nTrays = media.length/2-nPageSizes;
assert (nTrays >= 0);
}
+ ArrayList<Integer> resolutionList = new ArrayList<>();
+ getResolutions(printer, resolutionList);
+ resolutionsArray = new int[resolutionList.size()];
+ for (int i=0; i < resolutionList.size(); i++) {
+ resolutionsArray[i] = resolutionList.get(i);
+ }
}
}
@@ -160,6 +170,12 @@
return cupsMediaTrays;
}
+ /**
+ * return the raw packed array of supported printer resolutions.
+ */
+ int[] getRawResolutions() {
+ return resolutionsArray;
+ }
/**
* Initialize media by translating PPD info to PrintService attributes.
--- a/jdk/src/solaris/classes/sun/print/IPPPrintService.java Fri Jul 11 18:46:47 2014 +0400
+++ b/jdk/src/solaris/classes/sun/print/IPPPrintService.java Fri Jul 11 11:12:59 2014 -0700
@@ -96,6 +96,8 @@
private MediaSizeName[] mediaSizeNames;
private CustomMediaSizeName[] customMediaSizeNames;
private int defaultMediaIndex;
+ private int[] rawResolutions = null;
+ private PrinterResolution[] printerResolutions = null;
private boolean isCupsPrinter;
private boolean init;
private Boolean isPS;
@@ -414,6 +416,7 @@
mediaTrays = cps.getMediaTrays();
customMediaSizeNames = cps.getCustomMediaSizeNames();
defaultMediaIndex = cps.getDefaultMediaIndex();
+ rawResolutions = cps.getRawResolutions();
urlConnection.disconnect();
init = true;
return;
@@ -765,6 +768,15 @@
return sidesSup;
}
}
+ } 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 null;
@@ -1043,6 +1055,14 @@
if (getAttMap != null && getAttMap.containsKey("color-supported")) {
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);
+ }
+
supportedCats = new Class<?>[catList.size()];
catList.toArray(supportedCats);
return supportedCats;
@@ -1362,6 +1382,10 @@
}
}
return false;
+ } if (attr.getCategory() == PrinterResolution.class) {
+ if (attr instanceof PrinterResolution) {
+ return isSupportedResolution((PrinterResolution)attr);
+ }
}
return true;
}
@@ -1523,11 +1547,48 @@
}
}
return Sides.ONE_SIDED;
+ } 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 null;
}
+ private PrinterResolution[] getPrintResolutions() {
+ 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;
+ }
+ }
+ return printerResolutions;
+ }
+
+ private boolean isSupportedResolution(PrinterResolution res) {
+ PrinterResolution[] supportedRes = getPrintResolutions();
+ if (supportedRes != null) {
+ for (int i=0; i<supportedRes.length; i++) {
+ if (res.equals(supportedRes[i])) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
public ServiceUIFactory getServiceUIFactory() {
return null;
}
--- a/jdk/src/solaris/native/sun/awt/CUPSfuncs.c Fri Jul 11 18:46:47 2014 +0400
+++ b/jdk/src/solaris/native/sun/awt/CUPSfuncs.c Fri Jul 11 11:12:59 2014 -0700
@@ -394,3 +394,112 @@
unlink(filename);
return sizeArray;
}
+
+/*
+ * Populates the supplied ArrayList<Integer> with resolutions.
+ * The first pair of elements will be the default resolution.
+ * If resolution isn't supported the list will be empty.
+ * If needed we can add a 2nd ArrayList<String> which would
+ * be populated with the corresponding UI name.
+ * PPD specifies the syntax for resolution as either "Ndpi" or "MxNdpi",
+ * eg 300dpi or 600x600dpi. The former is a shorthand where xres==yres.
+ * We will always expand to the latter as we use a single array list.
+ * Note: getMedia() and getPageSizes() both open the ppd file
+ * This is not going to scale forever so if we add anymore we
+ * should look to consolidate this.
+ */
+JNIEXPORT void JNICALL
+Java_sun_print_CUPSPrinter_getResolutions(JNIEnv *env,
+ jobject printObj,
+ jstring printer,
+ jobject arrayList)
+{
+ ppd_file_t *ppd = NULL;
+ ppd_option_t *resolution;
+ int defx = 0, defy = 0;
+ int resx = 0, resy = 0;
+ jclass intCls, cls;
+ jmethodID intCtr, arrListAddMID;
+ int i;
+
+ intCls = (*env)->FindClass(env, "java/lang/Integer");
+ CHECK_NULL(intCls);
+ intCtr = (*env)->GetMethodID(env, intCls, "<init>", "(I)V");
+ CHECK_NULL(intCtr);
+ cls = (*env)->FindClass(env, "java/util/ArrayList");
+ CHECK_NULL(cls);
+ arrListAddMID =
+ (*env)->GetMethodID(env, cls, "add", "(Ljava/lang/Object;)Z");
+ CHECK_NULL(arrListAddMID);
+
+ const char *name = (*env)->GetStringUTFChars(env, printer, NULL);
+ if (name == NULL) {
+ (*env)->ExceptionClear(env);
+ JNU_ThrowOutOfMemoryError(env, "Could not create printer name");
+ }
+ const char *filename;
+
+ // NOTE: cupsGetPPD returns a pointer to a filename of a temporary file.
+ // unlink() must be called to remove the file after using it.
+ filename = j2d_cupsGetPPD(name);
+ (*env)->ReleaseStringUTFChars(env, printer, name);
+ CHECK_NULL(filename);
+ if ((ppd = j2d_ppdOpenFile(filename)) == NULL) {
+ unlink(filename);
+ DPRINTF("unable to open PPD %s\n", filename)
+ }
+ resolution = j2d_ppdFindOption(ppd, "Resolution");
+ if (resolution != NULL) {
+ int matches = sscanf(resolution->defchoice, "%dx%ddpi", &defx, &defy);
+ if (matches == 2) {
+ if (defx <= 0 || defy <= 0) {
+ defx = 0;
+ defy = 0;
+ }
+ } else {
+ matches = sscanf(resolution->defchoice, "%ddpi", &defx);
+ if (matches == 1) {
+ if (defx <= 0) {
+ defx = 0;
+ } else {
+ defy = defx;
+ }
+ }
+ }
+ if (defx > 0) {
+ jobject rxObj = (*env)->NewObject(env, intCls, intCtr, defx);
+ jobject ryObj = (*env)->NewObject(env, intCls, intCtr, defy);
+ (*env)->CallBooleanMethod(env, arrayList, arrListAddMID, rxObj);
+ (*env)->CallBooleanMethod(env, arrayList, arrListAddMID, ryObj);
+ }
+
+ for (i = 0; i < resolution->num_choices; i++) {
+ char *resStr = resolution->choices[i].choice;
+ int matches = sscanf(resStr, "%dx%ddpi", &resx, &resy);
+ if (matches == 2) {
+ if (resx <= 0 || resy <= 0) {
+ resx = 0;
+ resy = 0;
+ }
+ } else {
+ matches = sscanf(resStr, "%ddpi", &resx);
+ if (matches == 1) {
+ if (resx <= 0) {
+ resx = 0;
+ } else {
+ resy = resx;
+ }
+ }
+ }
+ if (resx > 0 && (resx != defx || resy != defy )) {
+ jobject rxObj = (*env)->NewObject(env, intCls, intCtr, resx);
+ jobject ryObj = (*env)->NewObject(env, intCls, intCtr, resy);
+ (*env)->CallBooleanMethod(env, arrayList, arrListAddMID, rxObj);
+ (*env)->CallBooleanMethod(env, arrayList, arrListAddMID, ryObj);
+ }
+ }
+ }
+
+ j2d_ppdClose(ppd);
+ unlink(filename);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/print/attribute/PrintResAttr.java Fri Jul 11 11:12:59 2014 -0700
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2014, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8048328
+ * @summary CUPS Printing does not report supported printer resolutions.
+ * @run main PrintResAttr
+ */
+
+/*
+ * Since there is no guarantee you have any printers that support
+ * resolution this test can't verify that resolution is being
+ * reported when supported. But when they are it should test that
+ * the code behaves reasonably.
+ */
+import javax.print.*;
+import javax.print.attribute.*;
+import javax.print.attribute.standard.*;
+
+public class PrintResAttr {
+
+ public static void main(String args[]) throws Exception {
+
+ PrintService[] services =
+ PrintServiceLookup.lookupPrintServices(null,null);
+ for (int i=0; i<services.length; i++) {
+ if (services[i].isAttributeCategorySupported(PrinterResolution.class)) {
+ System.out.println("Testing " + services[i]);
+ PrinterResolution[] res = (PrinterResolution[])
+ services[i].getSupportedAttributeValues(PrinterResolution.class,
+ null,null);
+ System.out.println("# supp res= " + res.length);
+ for (int r=0;r<res.length;r++) System.out.println(res[r]);
+ }
+ }
+ }
+}