4673406: RFE: Java Printing: Provide a way to display win32 printer driver's dialog

Reviewed-by: jgodinez, bae
This commit is contained in:
Phil Race 2013-08-30 10:25:55 -07:00
parent 9811410a00
commit d5c4be9c65
10 changed files with 721 additions and 24 deletions

View File

@ -0,0 +1,62 @@
/*
* Copyright (c) 2013, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package sun.print;
import java.awt.Window;
import java.awt.print.PrinterJob;
import javax.print.PrintService;
import javax.print.ServiceUIFactory;
import javax.print.attribute.PrintRequestAttributeSet;
public abstract class DocumentPropertiesUI {
/**
* For Win32 doc properties sheet.
*/
public static final int
DOCUMENTPROPERTIES_ROLE = ServiceUIFactory.RESERVED_UIROLE +100;
/**
* Name of (this) abstract class for Document Properties.
*/
public static final String
DOCPROPERTIESCLASSNAME = DocumentPropertiesUI.class.getName();
/**
* Invokes whatever code is needed to display a native dialog
* with the specified owner. The owner should be the cross-platform
* dialog. If the user cancels the dialog the return value is null.
* A non-null return value is always a new attribute set (or is it?)
* The cross-platform dialog may need to be updated to reflect the
* updated properties.
*/
public abstract PrintRequestAttributeSet
showDocumentProperties(PrinterJob job,
Window owner,
PrintService service,
PrintRequestAttributeSet aset);
}

View File

@ -0,0 +1,60 @@
/*
* Copyright (c) 2013, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package sun.print;
import java.awt.print.PrinterJob;
import javax.print.attribute.PrintRequestAttribute;
public class PrinterJobWrapper implements PrintRequestAttribute {
private static final long serialVersionUID = -8792124426995707237L;
private PrinterJob job;
public PrinterJobWrapper(PrinterJob job) {
this.job = job;
}
public PrinterJob getPrinterJob() {
return job;
}
public final Class getCategory() {
return PrinterJobWrapper.class;
}
public final String getName() {
return "printerjob-wrapper";
}
public String toString() {
return "printerjob-wrapper: " + job.toString();
}
public int hashCode() {
return job.hashCode();
}
}

View File

@ -903,6 +903,9 @@ public abstract class RasterPrinterJob extends PrinterJob {
int x = bounds.x+bounds.width/3;
int y = bounds.y+bounds.height/3;
PrintService newService;
// temporarily add an attribute pointing back to this job.
PrinterJobWrapper jobWrapper = new PrinterJobWrapper(this);
attributes.add(jobWrapper);
try {
newService =
ServiceUI.printDialog(gc, x, y,
@ -915,6 +918,7 @@ public abstract class RasterPrinterJob extends PrinterJob {
DocFlavor.SERVICE_FORMATTED.PAGEABLE,
attributes);
}
attributes.remove(PrinterJobWrapper.class);
if (newService == null) {
return false;

View File

@ -46,6 +46,7 @@ import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowAdapter;
import java.awt.print.PrinterJob;
import java.io.File;
import java.io.FilePermission;
import java.io.IOException;
@ -119,8 +120,6 @@ public class ServiceDialog extends JDialog implements ActionListener {
private AppearancePanel pnlAppearance;
private boolean isAWT = false;
static {
initResource();
}
@ -801,9 +800,32 @@ public class ServiceDialog extends JDialog implements ActionListener {
if (dialog != null) {
dialog.show();
} else {
// REMIND: may want to notify the user why we're
// disabling the button
btnProperties.setEnabled(false);
DocumentPropertiesUI docPropertiesUI = null;
try {
docPropertiesUI =
(DocumentPropertiesUI)uiFactory.getUI
(DocumentPropertiesUI.DOCUMENTPROPERTIES_ROLE,
DocumentPropertiesUI.DOCPROPERTIESCLASSNAME);
} catch (Exception ex) {
}
if (docPropertiesUI != null) {
PrinterJobWrapper wrapper = (PrinterJobWrapper)
asCurrent.get(PrinterJobWrapper.class);
if (wrapper == null) {
return; // should not happen, defensive only.
}
PrinterJob job = wrapper.getPrinterJob();
if (job == null) {
return; // should not happen, defensive only.
}
PrintRequestAttributeSet newAttrs =
docPropertiesUI.showDocumentProperties
(job, ServiceDialog.this, psCurrent, asCurrent);
if (newAttrs != null) {
asCurrent.addAll(newAttrs);
updatePanels();
}
}
}
}
}

View File

@ -179,6 +179,7 @@ public class WPrinterJob extends RasterPrinterJob implements DisposerTarget {
private static final int SET_RES_LOW = 0x00000080;
private static final int SET_COLOR = 0x00000200;
private static final int SET_ORIENTATION = 0x00004000;
private static final int SET_COLLATED = 0x00008000;
/**
* Values must match those defined in wingdi.h & commdlg.h
@ -189,10 +190,33 @@ public class WPrinterJob extends RasterPrinterJob implements DisposerTarget {
private static final int PD_NOSELECTION = 0x00000004;
private static final int PD_COLLATE = 0x00000010;
private static final int PD_PRINTTOFILE = 0x00000020;
private static final int DM_ORIENTATION = 0x00000001;
private static final int DM_PRINTQUALITY = 0x00000400;
private static final int DM_COLOR = 0x00000800;
private static final int DM_DUPLEX = 0x00001000;
private static final int DM_ORIENTATION = 0x00000001;
private static final int DM_PAPERSIZE = 0x00000002;
private static final int DM_COPIES = 0x00000100;
private static final int DM_DEFAULTSOURCE = 0x00000200;
private static final int DM_PRINTQUALITY = 0x00000400;
private static final int DM_COLOR = 0x00000800;
private static final int DM_DUPLEX = 0x00001000;
private static final int DM_YRESOLUTION = 0x00002000;
private static final int DM_COLLATE = 0x00008000;
private static final short DMCOLLATE_FALSE = 0;
private static final short DMCOLLATE_TRUE = 1;
private static final short DMORIENT_PORTRAIT = 1;
private static final short DMORIENT_LANDSCAPE = 2;
private static final short DMCOLOR_MONOCHROME = 1;
private static final short DMCOLOR_COLOR = 2;
private static final short DMRES_DRAFT = -1;
private static final short DMRES_LOW = -2;
private static final short DMRES_MEDIUM = -3;
private static final short DMRES_HIGH = -4;
private static final short DMDUP_SIMPLEX = 1;
private static final short DMDUP_VERTICAL = 2;
private static final short DMDUP_HORIZONTAL = 3;
/**
* Pageable MAX pages
@ -592,13 +616,23 @@ public class WPrinterJob extends RasterPrinterJob implements DisposerTarget {
}
driverDoesMultipleCopies = false;
driverDoesCollation = false;
setNativePrintService(service.getName());
setNativePrintServiceIfNeeded(service.getName());
}
/* associates this job with the specified native service */
private native void setNativePrintService(String name)
throws PrinterException;
private String lastNativeService = null;
private void setNativePrintServiceIfNeeded(String name)
throws PrinterException {
if (name != null && !(name.equals(lastNativeService))) {
setNativePrintService(name);
lastNativeService = name;
}
}
public PrintService getPrintService() {
if (myService == null) {
String printerName = getNativePrintService();
@ -616,7 +650,7 @@ public class WPrinterJob extends RasterPrinterJob implements DisposerTarget {
myService = PrintServiceLookup.lookupDefaultPrintService();
if (myService != null) {
try {
setNativePrintService(myService.getName());
setNativePrintServiceIfNeeded(myService.getName());
} catch (Exception e) {
myService = null;
}
@ -1754,8 +1788,13 @@ public class WPrinterJob extends RasterPrinterJob implements DisposerTarget {
mAttMediaSizeName = ((Win32PrintService)myService).findPaperID(msn);
}
private void setWin32MediaAttrib(int dmIndex, int width, int length) {
MediaSizeName msn =
private void addPaperSize(PrintRequestAttributeSet aset,
int dmIndex, int width, int length) {
if (aset == null) {
return;
}
MediaSizeName msn =
((Win32PrintService)myService).findWin32Media(dmIndex);
if (msn == null) {
msn = ((Win32PrintService)myService).
@ -1763,10 +1802,12 @@ public class WPrinterJob extends RasterPrinterJob implements DisposerTarget {
}
if (msn != null) {
if (attributes != null) {
attributes.add(msn);
}
aset.add(msn);
}
}
private void setWin32MediaAttrib(int dmIndex, int width, int length) {
addPaperSize(attributes, dmIndex, width, length);
mAttMediaSizeName = dmIndex;
}
@ -1788,7 +1829,7 @@ public class WPrinterJob extends RasterPrinterJob implements DisposerTarget {
// no equivalent predefined value
mAttMediaTray = 7; // DMBIN_AUTO
} else if (attr == MediaTray.TOP) {
mAttMediaTray =1; // DMBIN_UPPER
mAttMediaTray = 1; // DMBIN_UPPER
} else {
if (attr instanceof Win32MediaTray) {
mAttMediaTray = ((Win32MediaTray)attr).winID;
@ -1914,6 +1955,254 @@ public class WPrinterJob extends RasterPrinterJob implements DisposerTarget {
}
}
private static final class DevModeValues {
int dmFields;
short copies;
short collate;
short color;
short duplex;
short orient;
short paper;
short bin;
short xres_quality;
short yres;
}
private void getDevModeValues(PrintRequestAttributeSet aset,
DevModeValues info) {
Copies c = (Copies)aset.get(Copies.class);
if (c != null) {
info.dmFields |= DM_COPIES;
info.copies = (short)c.getValue();
}
SheetCollate sc = (SheetCollate)aset.get(SheetCollate.class);
if (sc != null) {
info.dmFields |= DM_COLLATE;
info.collate = (sc == SheetCollate.COLLATED) ?
DMCOLLATE_TRUE : DMCOLLATE_FALSE;
}
Chromaticity ch = (Chromaticity)aset.get(Chromaticity.class);
if (ch != null) {
info.dmFields |= DM_COLOR;
if (ch == Chromaticity.COLOR) {
info.color = DMCOLOR_COLOR;
} else {
info.color = DMCOLOR_MONOCHROME;
}
}
Sides s = (Sides)aset.get(Sides.class);
if (s != null) {
info.dmFields |= DM_DUPLEX;
if (s == Sides.TWO_SIDED_LONG_EDGE) {
info.duplex = DMDUP_VERTICAL;
} else if (s == Sides.TWO_SIDED_SHORT_EDGE) {
info.duplex = DMDUP_HORIZONTAL;
} else { // Sides.ONE_SIDED
info.duplex = DMDUP_SIMPLEX;
}
}
OrientationRequested or =
(OrientationRequested)aset.get(OrientationRequested.class);
if (or != null) {
info.dmFields |= DM_ORIENTATION;
info.orient = (or == OrientationRequested.LANDSCAPE)
? DMORIENT_LANDSCAPE : DMORIENT_PORTRAIT;
}
Media m = (Media)aset.get(Media.class);
if (m instanceof MediaSizeName) {
info.dmFields |= DM_PAPERSIZE;
MediaSizeName msn = (MediaSizeName)m;
info.paper =
(short)((Win32PrintService)myService).findPaperID(msn);
}
MediaTray mt = null;
if (m instanceof MediaTray) {
mt = (MediaTray)m;
}
if (mt == null) {
SunAlternateMedia sam =
(SunAlternateMedia)aset.get(SunAlternateMedia.class);
if (sam != null && (sam.getMedia() instanceof MediaTray)) {
mt = (MediaTray)sam.getMedia();
}
}
if (mt != null) {
info.dmFields |= DM_DEFAULTSOURCE;
info.bin = (short)(((Win32PrintService)myService).findTrayID(mt));
}
PrintQuality q = (PrintQuality)aset.get(PrintQuality.class);
if (q != null) {
info.dmFields |= DM_PRINTQUALITY;
if (q == PrintQuality.DRAFT) {
info.xres_quality = DMRES_DRAFT;
} else if (q == PrintQuality.HIGH) {
info.xres_quality = DMRES_HIGH;
} else {
info.xres_quality = DMRES_MEDIUM;
}
}
PrinterResolution r =
(PrinterResolution)aset.get(PrinterResolution.class);
if (r != null) {
info.dmFields |= DM_PRINTQUALITY | DM_YRESOLUTION;
info.xres_quality =
(short)r.getCrossFeedResolution(PrinterResolution.DPI);
info.yres = (short)r.getFeedResolution(PrinterResolution.DPI);
}
}
/* This method is called from native to update the values in the
* attribute set which originates from the cross-platform dialog,
* but updated by the native DocumentPropertiesUI which updates the
* devmode. This syncs the devmode back in to the attributes so that
* we can update the cross-platform dialog.
* The attribute set here is a temporary one installed whilst this
* happens,
*/
private final void setJobAttributes(PrintRequestAttributeSet attributes,
int fields, int values,
short copies,
short dmPaperSize,
short dmPaperWidth,
short dmPaperLength,
short dmDefaultSource,
short xRes,
short yRes) {
if (attributes == null) {
return;
}
if ((fields & DM_COPIES) != 0) {
attributes.add(new Copies(copies));
}
if ((fields & DM_COLLATE) != 0) {
if ((values & SET_COLLATED) != 0) {
attributes.add(SheetCollate.COLLATED);
} else {
attributes.add(SheetCollate.UNCOLLATED);
}
}
if ((fields & DM_ORIENTATION) != 0) {
if ((values & SET_ORIENTATION) != 0) {
attributes.add(OrientationRequested.LANDSCAPE);
} else {
attributes.add(OrientationRequested.PORTRAIT);
}
}
if ((fields & DM_COLOR) != 0) {
if ((values & SET_COLOR) != 0) {
attributes.add(Chromaticity.COLOR);
} else {
attributes.add(Chromaticity.MONOCHROME);
}
}
if ((fields & DM_PRINTQUALITY) != 0) {
/* value < 0 indicates quality setting.
* value > 0 indicates X resolution. In that case
* hopefully we will also find y-resolution specified.
* If its not, assume its the same as x-res.
* Maybe Java code should try to reconcile this against
* the printers claimed set of supported resolutions.
*/
if (xRes < 0) {
PrintQuality quality;
if ((values & SET_RES_LOW) != 0) {
quality = PrintQuality.DRAFT;
} else if ((fields & SET_RES_HIGH) != 0) {
quality = PrintQuality.HIGH;
} else {
quality = PrintQuality.NORMAL;
}
attributes.add(quality);
} else if (xRes > 0 && yRes > 0) {
attributes.add(
new PrinterResolution(xRes, yRes, PrinterResolution.DPI));
}
}
if ((fields & DM_DUPLEX) != 0) {
Sides sides;
if ((values & SET_DUP_VERTICAL) != 0) {
sides = Sides.TWO_SIDED_LONG_EDGE;
} else if ((values & SET_DUP_HORIZONTAL) != 0) {
sides = Sides.TWO_SIDED_SHORT_EDGE;
} else {
sides = Sides.ONE_SIDED;
}
attributes.add(sides);
}
if ((fields & DM_PAPERSIZE) != 0) {
addPaperSize(attributes, dmPaperSize, dmPaperWidth, dmPaperLength);
}
if ((fields & DM_DEFAULTSOURCE) != 0) {
MediaTray tray =
((Win32PrintService)myService).findMediaTray(dmDefaultSource);
attributes.add(new SunAlternateMedia(tray));
}
}
private native boolean showDocProperties(long hWnd,
PrintRequestAttributeSet aset,
int dmFields,
short copies,
short collate,
short color,
short duplex,
short orient,
short paper,
short bin,
short xres_quality,
short yres);
@SuppressWarnings("deprecation")
public PrintRequestAttributeSet
showDocumentProperties(Window owner,
PrintService service,
PrintRequestAttributeSet aset)
{
try {
setNativePrintServiceIfNeeded(service.getName());
} catch (PrinterException e) {
}
long hWnd = ((WWindowPeer)(owner.getPeer())).getHWnd();
DevModeValues info = new DevModeValues();
getDevModeValues(aset, info);
boolean ok =
showDocProperties(hWnd, aset,
info.dmFields,
info.copies,
info.collate,
info.color,
info.duplex,
info.orient,
info.paper,
info.bin,
info.xres_quality,
info.yres);
if (ok) {
return aset;
} else {
return null;
}
}
/* Printer Resolution. See also getXRes() and getYRes() */
private final void setResolutionDPI(int xres, int yres) {
@ -1956,7 +2245,7 @@ public class WPrinterJob extends RasterPrinterJob implements DisposerTarget {
}
//** END Functions called by native code for querying/updating attributes
}
}
class PrintToFileErrorDialog extends Dialog implements ActionListener{
public PrintToFileErrorDialog(Frame parent, String title, String message,

View File

@ -70,6 +70,10 @@ public class Win32MediaTray extends MediaTray {
winEnumTable.add(this);
}
public int getDMBinID() {
return winID;
}
private static final String[] myStringTable ={
"Manual-Envelope",
"Automatic-Feeder",

View File

@ -25,6 +25,8 @@
package sun.print;
import java.awt.Window;
import java.awt.print.PrinterJob;
import java.io.File;
import java.net.URI;
import java.net.URISyntaxException;
@ -39,6 +41,7 @@ import javax.print.attribute.AttributeSet;
import javax.print.attribute.AttributeSetUtilities;
import javax.print.attribute.EnumSyntax;
import javax.print.attribute.HashAttributeSet;
import javax.print.attribute.PrintRequestAttributeSet;
import javax.print.attribute.PrintServiceAttribute;
import javax.print.attribute.PrintServiceAttributeSet;
import javax.print.attribute.HashPrintServiceAttributeSet;
@ -69,6 +72,7 @@ import javax.print.attribute.standard.PrintQuality;
import javax.print.attribute.standard.PrinterResolution;
import javax.print.attribute.standard.SheetCollate;
import javax.print.event.PrintServiceAttributeListener;
import sun.awt.windows.WPrinterJob;
public class Win32PrintService implements PrintService, AttributeUpdater,
SunPrinterJobService {
@ -282,6 +286,22 @@ public class Win32PrintService implements PrintService, AttributeUpdater,
return 0;
}
public int findTrayID(MediaTray tray) {
getMediaTrays(); // make sure they are initialised.
if (tray instanceof Win32MediaTray) {
Win32MediaTray winTray = (Win32MediaTray)tray;
return winTray.getDMBinID();
}
for (int id=0; id<dmPaperBinToPrintService.length; id++) {
if (tray.equals(dmPaperBinToPrintService[id])) {
return id+1; // DMBIN_FIRST = 1;
}
}
return 0; // didn't find the tray
}
public MediaTray findMediaTray(int dmBin) {
if (dmBin >= 1 && dmBin <= dmPaperBinToPrintService.length) {
return dmPaperBinToPrintService[dmBin-1];
@ -673,7 +693,6 @@ public class Win32PrintService implements PrintService, AttributeUpdater,
return arr2;
}
private PrinterIsAcceptingJobs getPrinterIsAcceptingJobs() {
if (getJobStatus(printer, 2) != 1) {
return PrinterIsAcceptingJobs.NOT_ACCEPTING_JOBS;
@ -1596,8 +1615,76 @@ public class Win32PrintService implements PrintService, AttributeUpdater,
}
}
public ServiceUIFactory getServiceUIFactory() {
return null;
private Win32DocumentPropertiesUI docPropertiesUI = null;
private static class Win32DocumentPropertiesUI
extends DocumentPropertiesUI {
Win32PrintService service;
private Win32DocumentPropertiesUI(Win32PrintService s) {
service = s;
}
public PrintRequestAttributeSet
showDocumentProperties(PrinterJob job,
Window owner,
PrintService service,
PrintRequestAttributeSet aset) {
if (!(job instanceof WPrinterJob)) {
return null;
}
WPrinterJob wJob = (WPrinterJob)job;
return wJob.showDocumentProperties(owner, service, aset);
}
}
private synchronized DocumentPropertiesUI getDocumentPropertiesUI() {
return new Win32DocumentPropertiesUI(this);
}
private static class Win32ServiceUIFactory extends ServiceUIFactory {
Win32PrintService service;
Win32ServiceUIFactory(Win32PrintService s) {
service = s;
}
public Object getUI(int role, String ui) {
if (role <= ServiceUIFactory.MAIN_UIROLE) {
return null;
}
if (role == DocumentPropertiesUI.DOCUMENTPROPERTIES_ROLE &&
DocumentPropertiesUI.DOCPROPERTIESCLASSNAME.equals(ui))
{
return service.getDocumentPropertiesUI();
}
throw new IllegalArgumentException("Unsupported role");
}
public String[] getUIClassNamesForRole(int role) {
if (role <= ServiceUIFactory.MAIN_UIROLE) {
return null;
}
if (role == DocumentPropertiesUI.DOCUMENTPROPERTIES_ROLE) {
String[] names = new String[0];
names[0] = DocumentPropertiesUI.DOCPROPERTIESCLASSNAME;
return names;
}
throw new IllegalArgumentException("Unsupported role");
}
}
private Win32ServiceUIFactory uiFactory = null;
public synchronized ServiceUIFactory getServiceUIFactory() {
if (uiFactory == null) {
uiFactory = new Win32ServiceUIFactory(this);
}
return uiFactory;
}
public String toString() {

View File

@ -81,6 +81,7 @@ jmethodID AwtPrintControl::setToPageID;
jmethodID AwtPrintControl::setNativeAttID;
jmethodID AwtPrintControl::setRangeCopiesID;
jmethodID AwtPrintControl::setResID;
jmethodID AwtPrintControl::setJobAttributesID;
BOOL AwtPrintControl::IsSupportedLevel(HANDLE hPrinter, DWORD dwLevel) {
@ -297,6 +298,10 @@ void AwtPrintControl::initIDs(JNIEnv *env, jclass cls)
AwtPrintControl::setPrinterID =
env->GetMethodID(cls, "setPrinterNameAttrib", "(Ljava/lang/String;)V");
AwtPrintControl::setJobAttributesID =
env->GetMethodID(cls, "setJobAttributes",
"(Ljavax/print/attribute/PrintRequestAttributeSet;IISSSSSSS)V");
DASSERT(AwtPrintControl::driverDoesMultipleCopiesID != NULL);
DASSERT(AwtPrintControl::getPrintDCID != NULL);
DASSERT(AwtPrintControl::setPrintDCID != NULL);
@ -327,6 +332,7 @@ void AwtPrintControl::initIDs(JNIEnv *env, jclass cls)
DASSERT(AwtPrintControl::getSidesID != NULL);
DASSERT(AwtPrintControl::getSelectID != NULL);
DASSERT(AwtPrintControl::getPrintToFileEnabledID != NULL);
DASSERT(AwtPrintControl::setJobAttributesID != NULL);
CATCH_BAD_ALLOC;

View File

@ -47,7 +47,6 @@ public:
static jmethodID setDevmodeID;
static jmethodID getDevnamesID;
static jmethodID setDevnamesID;
static jmethodID getWin32MediaID;
static jmethodID setWin32MediaID;
static jmethodID getWin32MediaTrayID;
@ -73,6 +72,7 @@ public:
static jmethodID setNativeAttID;
static jmethodID setRangeCopiesID;
static jmethodID setResID;
static jmethodID setJobAttributesID;
static void initIDs(JNIEnv *env, jclass cls);
static BOOL FindPrinter(jstring printerName, LPBYTE pPrinterEnum,

View File

@ -329,6 +329,156 @@ static int CALLBACK fontEnumProcA(ENUMLOGFONTEXA *logfont,
static int embolden(int currentWeight);
static BOOL getPrintableArea(HDC pdc, HANDLE hDevMode, RectDouble *margin);
/************************************************************************
* DocumentProperties native support
*/
/* Values must match those defined in WPrinterJob.java */
static const DWORD SET_COLOR = 0x00000200;
static const DWORD SET_ORIENTATION = 0x00004000;
static const DWORD SET_COLLATED = 0x00008000;
static const DWORD SET_DUP_VERTICAL = 0x00000010;
static const DWORD SET_DUP_HORIZONTAL = 0x00000020;
static const DWORD SET_RES_HIGH = 0x00000040;
static const DWORD SET_RES_LOW = 0x00000080;
/*
* Copy DEVMODE state back into JobAttributes.
*/
static void UpdateJobAttributes(JNIEnv *env,
jobject wJob,
jobject attrSet,
DEVMODE *devmode) {
DWORD dmValues = 0;
int xRes = 0, yRes = 0;
if (devmode->dmFields & DM_COLOR) {
if (devmode->dmColor == DMCOLOR_COLOR) {
dmValues |= SET_COLOR;
}
}
if (devmode->dmFields & DM_ORIENTATION) {
if (devmode->dmOrientation == DMORIENT_LANDSCAPE) {
dmValues |= SET_ORIENTATION;
}
}
if (devmode->dmFields & DM_COLLATE &&
devmode->dmCollate == DMCOLLATE_TRUE) {
dmValues |= SET_COLLATED;
}
if (devmode->dmFields & DM_PRINTQUALITY) {
/* value < 0 indicates quality setting.
* value > 0 indicates X resolution. In that case
* hopefully we will also find y-resolution specified.
* If its not, assume its the same as x-res.
* Maybe Java code should try to reconcile this against
* the printers claimed set of supported resolutions.
*/
if (devmode->dmPrintQuality < 0) {
if (devmode->dmPrintQuality == DMRES_HIGH) {
dmValues |= SET_RES_HIGH;
} else if ((devmode->dmPrintQuality == DMRES_LOW) ||
(devmode->dmPrintQuality == DMRES_DRAFT)) {
dmValues |= SET_RES_LOW;
}
/* else if (devmode->dmPrintQuality == DMRES_MEDIUM)
* will set to NORMAL.
*/
} else {
xRes = devmode->dmPrintQuality;
yRes = (devmode->dmFields & DM_YRESOLUTION) ?
devmode->dmYResolution : devmode->dmPrintQuality;
}
}
if (devmode->dmFields & DM_DUPLEX) {
if (devmode->dmDuplex == DMDUP_HORIZONTAL) {
dmValues |= SET_DUP_HORIZONTAL;
} else if (devmode->dmDuplex == DMDUP_VERTICAL) {
dmValues |= SET_DUP_VERTICAL;
}
}
env->CallVoidMethod(wJob, AwtPrintControl::setJobAttributesID, attrSet,
devmode->dmFields, dmValues, devmode->dmCopies,
devmode->dmPaperSize, devmode->dmPaperWidth,
devmode->dmPaperLength, devmode->dmDefaultSource,
xRes, yRes);
}
JNIEXPORT jboolean JNICALL
Java_sun_awt_windows_WPrinterJob_showDocProperties(JNIEnv *env,
jobject wJob,
jlong hWndParent,
jobject attrSet,
jint dmFields,
jshort copies,
jshort collate,
jshort color,
jshort duplex,
jshort orient,
jshort paper,
jshort bin,
jshort xres_quality,
jshort yres)
{
TRY;
HGLOBAL hDevMode = AwtPrintControl::getPrintHDMode(env, wJob);
HGLOBAL hDevNames = AwtPrintControl::getPrintHDName(env, wJob);
DEVMODE *devmode = NULL;
DEVNAMES *devnames = NULL;
LONG rval = IDCANCEL;
jboolean ret = JNI_FALSE;
if (hDevMode != NULL && hDevNames != NULL) {
devmode = (DEVMODE *)::GlobalLock(hDevMode);
devnames = (DEVNAMES *)::GlobalLock(hDevNames);
LPTSTR lpdevnames = (LPTSTR)devnames;
// No need to call _tcsdup as we won't unlock until we are done.
LPTSTR printerName = lpdevnames+devnames->wDeviceOffset;
LPTSTR portName = lpdevnames+devnames->wOutputOffset;
HANDLE hPrinter;
if (::OpenPrinter(printerName, &hPrinter, NULL) == TRUE) {
devmode->dmFields |= dmFields;
devmode->dmCopies = copies;
devmode->dmCollate = collate;
devmode->dmColor = color;
devmode->dmDuplex = duplex;
devmode->dmOrientation = orient;
devmode->dmPrintQuality = xres_quality;
devmode->dmYResolution = yres;
devmode->dmPaperSize = paper;
devmode->dmDefaultSource = bin;
rval = ::DocumentProperties((HWND)hWndParent,
hPrinter, printerName, devmode, devmode,
DM_IN_BUFFER | DM_OUT_BUFFER | DM_IN_PROMPT);
if (rval == IDOK) {
UpdateJobAttributes(env, wJob, attrSet, devmode);
ret = JNI_TRUE;
}
VERIFY(::ClosePrinter(hPrinter));
}
::GlobalUnlock(hDevNames);
::GlobalUnlock(hDevMode);
}
return ret;
CATCH_BAD_ALLOC_RET(0);
}
/************************************************************************
* WPageDialog native methods
*/
@ -732,7 +882,6 @@ Java_sun_awt_windows_WPrinterJob_validatePaper(JNIEnv *env, jobject self,
memset(&pd, 0, sizeof(PRINTDLG));
pd.lStructSize = sizeof(PRINTDLG);
pd.Flags = PD_RETURNDEFAULT | PD_RETURNDC;
if (::PrintDlg(&pd)) {
printDC = pd.hDC;
hDevMode = pd.hDevMode;
@ -792,8 +941,19 @@ Java_sun_awt_windows_WPrinterJob_validatePaper(JNIEnv *env, jobject self,
jint imgPixelWid = GetDeviceCaps(printDC, HORZRES);
jint imgPixelHgt = GetDeviceCaps(printDC, VERTRES);
// The DC may be obtained when we first selected the printer as a
// result of a call to setNativePrintService.
// If the Devmode was obtained later on from the DocumentProperties dialog
// the DC won't have been updated and its settings may be for PORTRAIT.
// This may happen in other cases too, but was observed for the above.
// To get a DC compatible with this devmode we should really call
// CreateDC() again to get a DC for the devmode we are using.
// The changes for that are a lot more risk, so to minimise that
// risk, assume its not LANDSCAPE unless width > height, even if the
// devmode says its LANDSCAPE.
// if the values were obtained from a rotated device, swap.
if (getOrientationFromDevMode2(hDevMode) == DMORIENT_LANDSCAPE) {
if ((getOrientationFromDevMode2(hDevMode) == DMORIENT_LANDSCAPE) &&
(imgPixelWid > imgPixelHgt)) {
jint tmp;
tmp = xPixelRes;
xPixelRes = yPixelRes;
@ -941,6 +1101,9 @@ Java_sun_awt_windows_WPrinterJob_initPrinter(JNIEnv *env, jobject self) {
setBooleanField(env, self, DRIVER_COLLATE_STR, JNI_FALSE);
}
if (dmFields & DM_COPIES) {
setBooleanField(env, self, DRIVER_COPIES_STR, JNI_TRUE);
}
}
CATCH_BAD_ALLOC;