From 8270a2d62e35751aaba2f73c10816cf3865c262a Mon Sep 17 00:00:00 2001 From: smallsql Date: Wed, 15 Dec 2010 14:53:33 +0000 Subject: Some fixes on the printing API from Karsten Heinrich --- awt/printing.cs | 114 ++++++++- openjdk/sun/print/Win32PrintJob.java | 58 ++++- openjdk/sun/print/Win32PrintService.java | 385 +++++++++++++++++++++++++++++-- 3 files changed, 530 insertions(+), 27 deletions(-) diff --git a/awt/printing.cs b/awt/printing.cs index 7d5983ec..1cce4826 100644 --- a/awt/printing.cs +++ b/awt/printing.cs @@ -1,5 +1,6 @@ /* Copyright (C) 2009 Volker Berlin (i-net software) + Copyright (C) 2010 Karsten Heinrich (i-net software) This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -115,12 +116,31 @@ namespace ikvm.awt.printing private const int ERROR_INSUFFICIENT_BUFFER = 122; - private const int PRINTER_STATUS_DOOR_OPEN = 0x400000; - private const int PRINTER_STATUS_ERROR = 0x2; - private const int PRINTER_STATUS_NO_TONER = 0x40000; - private const int PRINTER_STATUS_OFFLINE = 0x80; - private const int PRINTER_STATUS_OUT_OF_MEMORY = 0x200000; + private const int PRINTER_STATUS_PAUSED = 0x1; + private const int PRINTER_STATUS_ERROR = 0x2; // MSDN says that this value is not used + private const int PRINTER_STATUS_PENDING_DELETION = 0x4; + private const int PRINTER_STATUS_PAPER_JAM = 0x8; + private const int PRINTER_STATUS_PAPER_OUT = 0x10; + private const int PRINTER_STATUS_MANUAL_FEED = 0x20; + private const int PRINTER_STATUS_PAPER_PROBLEM = 0x40; + private const int PRINTER_STATUS_OFFLINE = 0x80; + private const int PRINTER_STATUS_IO_ACTIVE = 0x100; + private const int PRINTER_STATUS_BUSY = 0x200; + private const int PRINTER_STATUS_PRINTING = 0x400; + private const int PRINTER_STATUS_OUTPUT_BIN_FULL = 0x800; + private const int PRINTER_STATUS_NOT_AVAILABLE = 0x1000; + private const int PRINTER_STATUS_WAITING = 0x2000; + private const int PRINTER_STATUS_PROCESSING = 0x4000; + private const int PRINTER_STATUS_INITIALIZING = 0x8000; + private const int PRINTER_STATUS_WARMING_UP = 0x10000; + private const int PRINTER_STATUS_TONER_LOW = 0x20000; + private const int PRINTER_STATUS_NO_TONER = 0x40000; + private const int PRINTER_STATUS_PAGE_PUNT = 0x80000; private const int PRINTER_STATUS_USER_INTERVENTION = 0x100000; + private const int PRINTER_STATUS_OUT_OF_MEMORY = 0x200000; + private const int PRINTER_STATUS_DOOR_OPEN = 0x400000; + private const int PRINTER_STATUS_SERVER_UNKNOWN = 0x800000; + private const int PRINTER_STATUS_POWER_SAVE = 0x1000000; /// /// Get a printer status @@ -134,6 +154,27 @@ namespace ikvm.awt.printing int status; if (GetPrinterInfo2(printerName, out cJobs, out status)) { + if (category == (java.lang.Class)typeof(javax.print.attribute.standard.PrinterState)) + { + if ((status & + (PRINTER_STATUS_ERROR | PRINTER_STATUS_NO_TONER | PRINTER_STATUS_OUT_OF_MEMORY | + PRINTER_STATUS_OFFLINE | PRINTER_STATUS_USER_INTERVENTION | + PRINTER_STATUS_DOOR_OPEN | PRINTER_STATUS_NOT_AVAILABLE )) > 0) + { + return javax.print.attribute.standard.PrinterState.STOPPED; + } + if( (status & (PRINTER_STATUS_BUSY | PRINTER_STATUS_PRINTING ))> 0 ) + { + return javax.print.attribute.standard.PrinterState.PROCESSING; + } + return null; + // null seems to be the default instead of unknown - UNKOWN ist not used in the reference RT + // javax.print.attribute.standard.PrinterState.UNKNOWN; + } + if (category == (java.lang.Class)typeof(javax.print.attribute.standard.PrinterStateReasons)) + { + return extractResions(status); + } if (category == (java.lang.Class)typeof(javax.print.attribute.standard.QueuedJobCount)) { return new javax.print.attribute.standard.QueuedJobCount(cJobs); @@ -159,6 +200,65 @@ namespace ikvm.awt.printing return null; } + private javax.print.attribute.standard.PrinterStateReasons extractResions(int status) + { + javax.print.attribute.standard.PrinterStateReasons reasons = new javax.print.attribute.standard.PrinterStateReasons(); + if ((status & PRINTER_STATUS_PAUSED) > 0) + { + reasons.put(javax.print.attribute.standard.PrinterStateReason.PAUSED, javax.print.attribute.standard.Severity.REPORT); + } + if ((status & PRINTER_STATUS_ERROR) > 0) + { + reasons.put(javax.print.attribute.standard.PrinterStateReason.OTHER, javax.print.attribute.standard.Severity.ERROR); + } + if ((status & PRINTER_STATUS_PENDING_DELETION) > 0) { } + if ((status & PRINTER_STATUS_PAPER_JAM) > 0) + { + reasons.put(javax.print.attribute.standard.PrinterStateReason.MEDIA_JAM, javax.print.attribute.standard.Severity.WARNING); + } + if ((status & PRINTER_STATUS_PAPER_OUT) > 0) + { + reasons.put(javax.print.attribute.standard.PrinterStateReason.MEDIA_EMPTY, javax.print.attribute.standard.Severity.WARNING); + } + if ((status & PRINTER_STATUS_MANUAL_FEED) > 0) { } + if ((status & PRINTER_STATUS_PAPER_PROBLEM) > 0) {} + if ((status & PRINTER_STATUS_OFFLINE) > 0) { + reasons.put(javax.print.attribute.standard.PrinterStateReason.TIMED_OUT, javax.print.attribute.standard.Severity.ERROR); + } + if ((status & PRINTER_STATUS_IO_ACTIVE) > 0) { } + if ((status & PRINTER_STATUS_BUSY) > 0) { } + if ((status & PRINTER_STATUS_PRINTING) > 0) { } + if ((status & PRINTER_STATUS_OUTPUT_BIN_FULL) > 0) { + reasons.put(javax.print.attribute.standard.PrinterStateReason.OUTPUT_AREA_FULL, javax.print.attribute.standard.Severity.WARNING); + } + if ((status & PRINTER_STATUS_NOT_AVAILABLE) > 0) { } + if ((status & PRINTER_STATUS_WAITING) > 0) { } + if ((status & PRINTER_STATUS_PROCESSING) > 0) { } + if ((status & PRINTER_STATUS_INITIALIZING) > 0) { } + if ((status & PRINTER_STATUS_WARMING_UP) > 0) { } + if ((status & PRINTER_STATUS_TONER_LOW) > 0) { + reasons.put(javax.print.attribute.standard.PrinterStateReason.TONER_LOW, javax.print.attribute.standard.Severity.WARNING); + } + if ((status & PRINTER_STATUS_NO_TONER) > 0) { + reasons.put(javax.print.attribute.standard.PrinterStateReason.TONER_EMPTY, javax.print.attribute.standard.Severity.ERROR); + } + if ((status & PRINTER_STATUS_PAGE_PUNT) > 0) { } + if ((status & PRINTER_STATUS_USER_INTERVENTION) > 0) { + reasons.put(javax.print.attribute.standard.PrinterStateReason.OTHER, javax.print.attribute.standard.Severity.ERROR); + } + if ((status & PRINTER_STATUS_OUT_OF_MEMORY) > 0) { + reasons.put(javax.print.attribute.standard.PrinterStateReason.OTHER, javax.print.attribute.standard.Severity.ERROR); + } + if ((status & PRINTER_STATUS_DOOR_OPEN) > 0) { + reasons.put(javax.print.attribute.standard.PrinterStateReason.DOOR_OPEN, javax.print.attribute.standard.Severity.ERROR); + } + if ((status & PRINTER_STATUS_SERVER_UNKNOWN) > 0) { } + if ((status & PRINTER_STATUS_POWER_SAVE) > 0) { + reasons.put(javax.print.attribute.standard.PrinterStateReason.PAUSED, javax.print.attribute.standard.Severity.REPORT); + } + return reasons.isEmpty() ? null : reasons; + } + /// /// Get infos from the PRINTER_INFO_2 struc /// @@ -228,4 +328,8 @@ namespace ikvm.awt.printing return ClosePrinter(handle); } } + + class Win32Print + { + } } diff --git a/openjdk/sun/print/Win32PrintJob.java b/openjdk/sun/print/Win32PrintJob.java index 5d315d06..f0bff15d 100644 --- a/openjdk/sun/print/Win32PrintJob.java +++ b/openjdk/sun/print/Win32PrintJob.java @@ -1,5 +1,6 @@ /* Copyright (C) 2009 Volker Berlin (i-net software) + Copyright (C) 2010 Karsten Heinrich (i-net software) This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -24,6 +25,9 @@ package sun.print; import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.GraphicsConfiguration; +import java.awt.HeadlessException; import java.awt.image.BufferedImage; import java.awt.print.PageFormat; import java.awt.print.Pageable; @@ -75,6 +79,7 @@ import javax.print.event.PrintJobEvent; import javax.print.event.PrintJobListener; import sun.awt.windows.WPrinterJob; +import sun.reflect.generics.reflectiveObjects.NotImplementedException; import cli.System.Drawing.Printing.*; @@ -100,7 +105,7 @@ public class Win32PrintJob implements CancelablePrintJob{ private PrintJobAttributeSet jobAttrSet; - private PrinterJob job; + private PrinterJob job = new WPrinterJob(); private Doc doc; private String mDestination; @@ -437,17 +442,15 @@ public class Win32PrintJob implements CancelablePrintJob{ public void pageableJob(Pageable pageable) throws PrintException { try { - System.err.println("pageableJob"); PrintDocument printDocument = createPrintDocument(); //TODO Attribute set in printDocument + printDocument.add_QueryPageSettings(new QueryPageSettingsEventHandler(new QueryPage( pageable ) ) ); printDocument.add_PrintPage(new PrintPageEventHandler(new PrintPage(pageable))); - System.err.println("Print"); printDocument.Print(); if(printerException != null){ throw printerException; } - System.err.println("after Print"); //TODO throw exception on Cancel notifyEvent(PrintJobEvent.DATA_TRANSFER_COMPLETE); return; @@ -467,7 +470,8 @@ public class Win32PrintJob implements CancelablePrintJob{ Attribute destination = reqAttrSet.get(Destination.class); if(destination instanceof Destination){ - settings.set_PrintFileName(((Destination)destination).getURI().toString()); + File destFile = new File(((Destination)destination).getURI()); + settings.set_PrintFileName(destFile.getAbsolutePath()); } settings.set_Copies((short)copies); @@ -664,10 +668,13 @@ public class Win32PrintJob implements CancelablePrintJob{ Printable printable = pageable.getPrintable(pageIndex); PageFormat pageFormat = pageable.getPageFormat(pageIndex); + BufferedImage pBand = new BufferedImage(1, 1, BufferedImage.TYPE_3BYTE_BGR); - PeekGraphics peekGraphics = new PeekGraphics(pBand.createGraphics(), job); + Graphics2D imageGraphics = pBand.createGraphics(); + ((RasterPrinterJob)job).setGraphicsConfigInfo(imageGraphics.getTransform(), pageFormat.getWidth(), pageFormat.getHeight()); + PeekGraphics peekGraphics = new PeekGraphics(imageGraphics, job ); - /* + /* * Because Sun is calling first with a PeekGraphics that we do it else for compatibility */ if(pageIndex == 0){ @@ -694,5 +701,42 @@ public class Win32PrintJob implements CancelablePrintJob{ } } + + private class QueryPage implements QueryPageSettingsEventHandler.Method{ + + private final Pageable pageable; + private int pageIndex; + + QueryPage(Pageable pageable){ + this.pageable = pageable; + //TODO firstPage + //TODO lastPage + //TODO PageRange + //TODO Num Copies + //TODO collatedCopies + } + + @Override + public void Invoke(Object source, QueryPageSettingsEventArgs e) { + // apply page settings to the current page + PageFormat format = pageable.getPageFormat(pageIndex); + PageSettings pageSettings = e.get_PageSettings(); + pageSettings.set_Landscape(format.getOrientation() == PageFormat.LANDSCAPE); + + PaperSize ps = new PaperSize(); + ps.set_Height( (int)Math.round( format.getHeight() ) ); + ps.set_Width( (int)Math.round( format.getWidth() ) ); + pageSettings.set_PaperSize( ps ); + + Margins margins = new Margins(); + margins.set_Left( (int) format.getImageableX() ); + margins.set_Top( (int)format.getImageableY() ); + margins.set_Right( (int) (format.getWidth() - format.getImageableX() - format.getImageableWidth() ) ); + margins.set_Bottom( (int)(format.getHeight() - format.getImageableY() - format.getImageableHeight() ) ); + pageSettings.set_Margins( margins ); + pageIndex++; + } + + } } diff --git a/openjdk/sun/print/Win32PrintService.java b/openjdk/sun/print/Win32PrintService.java index d028d4b0..b1667e96 100644 --- a/openjdk/sun/print/Win32PrintService.java +++ b/openjdk/sun/print/Win32PrintService.java @@ -1,5 +1,6 @@ /* Copyright (C) 2009 Volker Berlin (i-net software) + Copyright (C) 2010 Karsten Heinrich (i-net software) This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -21,9 +22,39 @@ jeroen@frijters.net */ +/* + * Copyright 2000-2007 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ package sun.print; +import java.io.File; +import java.net.URI; +import java.net.URISyntaxException; import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; import javax.print.DocFlavor; import javax.print.DocPrintJob; @@ -38,11 +69,14 @@ import javax.print.attribute.PrintServiceAttributeSet; import javax.print.attribute.standard.Chromaticity; import javax.print.attribute.standard.ColorSupported; import javax.print.attribute.standard.Copies; +import javax.print.attribute.standard.CopiesSupported; import javax.print.attribute.standard.Destination; import javax.print.attribute.standard.Fidelity; import javax.print.attribute.standard.JobName; import javax.print.attribute.standard.Media; import javax.print.attribute.standard.MediaPrintableArea; +import javax.print.attribute.standard.MediaSize; +import javax.print.attribute.standard.MediaSizeName; import javax.print.attribute.standard.OrientationRequested; import javax.print.attribute.standard.PageRanges; import javax.print.attribute.standard.PrintQuality; @@ -57,7 +91,16 @@ import javax.print.attribute.standard.SheetCollate; import javax.print.attribute.standard.Sides; import javax.print.event.PrintServiceAttributeListener; +import cli.System.Type; +import cli.System.Collections.IEnumerator; +import cli.System.Drawing.RectangleF; +import cli.System.Drawing.Printing.Duplex; +import cli.System.Drawing.Printing.PaperKind; +import cli.System.Drawing.Printing.PaperSize; +import cli.System.Drawing.Printing.PrintDocument; import cli.System.Drawing.Printing.PrinterSettings; +import cli.System.Drawing.Printing.PrinterSettings.PaperSizeCollection; +import cli.System.Net.Mime.MediaTypeNames; /** * @author Volker Berlin @@ -69,6 +112,9 @@ public class Win32PrintService implements PrintService{ DocFlavor.SERVICE_FORMATTED.PRINTABLE, }; + /** Mapping for PageSize.RawKind to predefined MediaSizeName */ + private static final MediaSizeName[] MEDIA_NAMES = new MediaSizeName[44]; + /* it turns out to be inconvenient to store the other categories * separately because many attributes are in multiple categories. */ @@ -87,6 +133,82 @@ public class Win32PrintService implements PrintService{ SunAlternateMedia.class, Chromaticity.class }; + + // conversion from 1/100 Inch (.NET) to µm (Java) + private static final int INCH100_TO_MYM = 254; + private static final int MATCH_DIFF = 500; // 0.5 mm + + static { + MEDIA_NAMES[0] = MediaSizeName.NA_LETTER; + MEDIA_NAMES[1] = MediaSizeName.NA_LETTER ; + MEDIA_NAMES[2] = MediaSizeName.TABLOID ; + MEDIA_NAMES[3] = MediaSizeName.LEDGER ; + MEDIA_NAMES[4] = MediaSizeName.NA_LEGAL ; + MEDIA_NAMES[5] = MediaSizeName.INVOICE ; // Statement + MEDIA_NAMES[6] = MediaSizeName.EXECUTIVE ; + MEDIA_NAMES[7] = MediaSizeName.ISO_A3 ; + MEDIA_NAMES[8] = MediaSizeName.ISO_A4 ; + MEDIA_NAMES[9] = MediaSizeName.ISO_A4 ; // A4Small, 10 + MEDIA_NAMES[10] = MediaSizeName.ISO_A5 ; + MEDIA_NAMES[11] = MediaSizeName.JIS_B4 ; + MEDIA_NAMES[12] = MediaSizeName.JIS_B5 ; + MEDIA_NAMES[13] = MediaSizeName.FOLIO ; + MEDIA_NAMES[14] = MediaSizeName.QUARTO ; + MEDIA_NAMES[15] = MediaSizeName.NA_10X14_ENVELOPE ; + MEDIA_NAMES[16] = MediaSizeName.B ; // 10x17 Envelope + MEDIA_NAMES[17] = MediaSizeName.NA_LETTER ; // Note + MEDIA_NAMES[18] = MediaSizeName.NA_NUMBER_9_ENVELOPE ; + MEDIA_NAMES[19] = MediaSizeName.NA_NUMBER_10_ENVELOPE ; // 20 + MEDIA_NAMES[20] = MediaSizeName.NA_NUMBER_11_ENVELOPE ; + MEDIA_NAMES[21] = MediaSizeName.NA_NUMBER_12_ENVELOPE ; + MEDIA_NAMES[22] = MediaSizeName.NA_NUMBER_14_ENVELOPE ; + MEDIA_NAMES[23] = MediaSizeName.C ; + MEDIA_NAMES[24] = MediaSizeName.D ; + MEDIA_NAMES[25] = MediaSizeName.E ; + MEDIA_NAMES[26] = MediaSizeName.ISO_DESIGNATED_LONG ; + MEDIA_NAMES[27] = MediaSizeName.ISO_C5 ; + MEDIA_NAMES[28] = MediaSizeName.ISO_C3 ; + MEDIA_NAMES[29] = MediaSizeName.ISO_C4 ; // 30 + MEDIA_NAMES[30] = MediaSizeName.ISO_C6 ; + MEDIA_NAMES[31] = MediaSizeName.ITALY_ENVELOPE ; + MEDIA_NAMES[32] = MediaSizeName.ISO_B4 ; + MEDIA_NAMES[33] = MediaSizeName.ISO_B5 ; + MEDIA_NAMES[34] = MediaSizeName.ISO_B6 ; + MEDIA_NAMES[35] = MediaSizeName.ITALY_ENVELOPE ; + MEDIA_NAMES[36] = MediaSizeName.MONARCH_ENVELOPE ; + MEDIA_NAMES[37] = MediaSizeName.PERSONAL_ENVELOPE ; + MEDIA_NAMES[38] = MediaSizeName.NA_10X15_ENVELOPE ; // USStandardFanfold + MEDIA_NAMES[39] = MediaSizeName.NA_9X12_ENVELOPE ; // GermanStandardFanfold, 40 + MEDIA_NAMES[40] = MediaSizeName.FOLIO ; // GermanLegalFanfold + MEDIA_NAMES[41] = MediaSizeName.ISO_B4 ; + MEDIA_NAMES[42] = MediaSizeName.JAPANESE_POSTCARD ; + MEDIA_NAMES[43] = MediaSizeName.NA_9X11_ENVELOPE ; + +// // augment the media size with the .NET default sizes available on the printer +// PrinterSettings ps = new PrinterSettings(); +// IEnumerator printers = PrinterSettings.get_InstalledPrinters().GetEnumerator(); +// printers.Reset(); +// while( printers.MoveNext() ){ +// ps.set_PrinterName( (String) printers.get_Current() ); +// IEnumerator sizes = ps.get_PaperSizes().GetEnumerator(); +// sizes.Reset(); +// while( sizes.MoveNext() ){ +// PaperSize size = (PaperSize) sizes.get_Current(); +// int kind = size.get_RawKind(); +// if( kind >= 0 && kind < MEDIA_NAMES.length && MEDIA_NAMES[kind] == null ){ +// MEDIA_NAMES[kind] = new CustomMediaSizeName( size.get_PaperName() ); +// int x = size.get_Width(); +// int y = size.get_Height(); +// if( x > y ){ // not allowed by MediaSize +// int tmp = x; +// x = y; +// y = tmp; +// } +// new MediaSize(x, y, INCH100_TO_MYM, MEDIA_NAMES[kind]); // cache entry in map +// } +// } +// } + } private final PrintPeer peer; @@ -102,7 +224,7 @@ public class Win32PrintService implements PrintService{ } this.peer = peer; printer = name; - settings = new PrinterSettings(); + settings = new PrintDocument().get_PrinterSettings(); settings.set_PrinterName(printer); } @@ -175,21 +297,18 @@ public class Win32PrintService implements PrintService{ throw new NullPointerException("category"); } if(!(PrintServiceAttribute.class.isAssignableFrom(category))){ - throw new IllegalArgumentException("Not a PrintServiceAttribute"); + throw new IllegalArgumentException("The categhory '" + category + "' is not a valid PrintServiceAttribute"); } if(category == ColorSupported.class){ - if(settings.get_SupportsColor()){ + // works better than settings.get_SupportsColor(); + if(settings.get_DefaultPageSettings().get_Color()){ return (T)ColorSupported.SUPPORTED; }else{ return (T)ColorSupported.NOT_SUPPORTED; } }else if(category == PrinterName.class){ return (T)getPrinterName(); - }else if(category == PrinterState.class){ - return (T)PrinterState.UNKNOWN; // TODO - }else if(category == PrinterStateReasons.class){ - return null; // TODO - }else{ + } else { // QueuedJobCount and PrinterIsAcceptingJobs return (T)peer.getPrinterStatus(printer, category); } @@ -216,7 +335,8 @@ public class Win32PrintService implements PrintService{ if(jobCount != null){ attrs.add(jobCount); } - if(settings.get_SupportsColor()){ + // TODO: Seems to be more accurate than settings.get_SupportsColor(), which doesn't work for CutePDF + if(settings.get_DefaultPageSettings().get_Color()){ attrs.add(ColorSupported.SUPPORTED); }else{ attrs.add(ColorSupported.NOT_SUPPORTED); @@ -228,14 +348,101 @@ public class Win32PrintService implements PrintService{ @Override public Object getDefaultAttributeValue(Class category){ - // TODO Auto-generated method stub + if (category == null) { + throw new NullPointerException("category must not be null"); + } + if ( !Attribute.class.isAssignableFrom( category ) ) { + throw new IllegalArgumentException( category +" has to be an " + Attribute.class.getName() ); + } + if ( !isAttributeCategorySupported( category ) ) { + return null; + } + if (category == Copies.class) { + short copies = settings.get_Copies(); + return new Copies( copies > 0 ? copies : 1 ); + } + if (category == Chromaticity.class) { + // NOTE: this works for CutePDF, settings.get_SupportsColor() does not + return settings.get_DefaultPageSettings().get_Color() ? Chromaticity.COLOR : Chromaticity.MONOCHROME; + } + if (category == JobName.class) { + return new JobName( "Java Printing", null ); // TODO this is Java-Default, use another one for IKVM? + } + if (category == OrientationRequested.class) { + return settings.get_DefaultPageSettings().get_Landscape() ? OrientationRequested.LANDSCAPE : OrientationRequested.PORTRAIT; + } + if (category == PageRanges.class) { + return new PageRanges(1, Integer.MAX_VALUE ); + } + if (category == Media.class) { + int rawKind = settings.get_DefaultPageSettings().get_PaperSize().get_RawKind(); + if( rawKind > MEDIA_NAMES.length || rawKind < 1 || MEDIA_NAMES[ rawKind - 1 ] == null ){ // custom page format + return settings.get_DefaultPageSettings().get_PaperSize().get_PaperName(); + } else { + return MEDIA_NAMES[ rawKind - 1 ]; + } + } + if (category == MediaPrintableArea.class) { + RectangleF area = settings.get_DefaultPageSettings().get_PrintableArea(); + // get_PrintableArea is in 1/100 inch, see http://msdn.microsoft.com/de-de/library/system.drawing.printing.pagesettings.printablearea(v=VS.90).aspx + return new MediaPrintableArea(area.get_X()/100, area.get_Y()/100, area.get_Width()/100, area.get_Height()/100, MediaPrintableArea.INCH); + } + if (category == Destination.class) { + String path = "out.prn"; + try { + return new Destination( ( new File( path ) ).toURI() ); + } catch (SecurityException se) { + try { + return new Destination( new URI( "file:" + path) ); + } catch (URISyntaxException e) { + return null; + } + } + } + if (category == Sides.class) { + switch( settings.get_Duplex().Value ){ + case cli.System.Drawing.Printing.Duplex.Default: // MSDN: 'The printer's default duplex setting.' - what ever that might be + case cli.System.Drawing.Printing.Duplex.Simplex: + return Sides.ONE_SIDED; + case cli.System.Drawing.Printing.Duplex.Horizontal: + return Sides.TWO_SIDED_LONG_EDGE; + case cli.System.Drawing.Printing.Duplex.Vertical: + return Sides.TWO_SIDED_SHORT_EDGE; + } + } + if (category == PrinterResolution.class) { + cli.System.Drawing.Printing.PrinterResolution res = settings.get_DefaultPageSettings().get_PrinterResolution(); + return new PrinterResolution( res.get_X(), res.get_Y(), PrinterResolution.DPI); + } + if (category == ColorSupported.class) { + if ( settings.get_SupportsColor() ) { + return ColorSupported.SUPPORTED; + } else { + return ColorSupported.NOT_SUPPORTED; + } + } + if( category == PrintQuality.class ){ + return PrintQuality.NORMAL; // TODO not correct, only available when using a PrintServer instance? + } + if (category == RequestingUserName.class) { + try{ + return new RequestingUserName( System.getProperty("user.name", ""), null); + } catch( SecurityException e ){ + return new RequestingUserName( "", null); + } + } + if (category == SheetCollate.class){ + return settings.get_Collate() ? SheetCollate.COLLATED : SheetCollate.UNCOLLATED; + } + if (category == Fidelity.class) { + return Fidelity.FIDELITY_FALSE; + } return null; } @Override public ServiceUIFactory getServiceUIFactory(){ - // TODO Auto-generated method stub return null; } @@ -260,9 +467,93 @@ public class Win32PrintService implements PrintService{ @Override - public Object getSupportedAttributeValues(Class category, DocFlavor flavor, - AttributeSet attributes){ - // TODO Auto-generated method stub + public Object getSupportedAttributeValues(Class category, DocFlavor flavor, AttributeSet attributes){ + if ( category == null || !Attribute.class.isAssignableFrom( category ) ) { + throw new IllegalArgumentException( "The category '" + category + "' is not an Attribute" ); + } + if( !isAttributeCategorySupported(category) ){ + return null; + } + if (category == JobName.class || category == RequestingUserName.class || category == ColorSupported.class + || category == Destination.class ) { + return getDefaultAttributeValue(category); + } + if( category == Copies.class ){ + return new CopiesSupported(1, settings.get_MaximumCopies() ); + } + if( category == Media.class ){ + PaperSizeCollection sizes = settings.get_PaperSizes(); + List medias = new ArrayList(); + for( int i = 0; i < sizes.get_Count(); i++ ){ + PaperSize media = sizes.get_Item(i); + MediaSizeName mediaName = findMatchingMedia( sizes.get_Item(i) ); + if( mediaName != null + && !medias.contains( mediaName )){ // slow but better than creating a HashSet here + medias.add( mediaName); + } + } + return medias.size() > 0 ? medias.toArray( new Media[medias.size() ] ) : null; + } + if (category == PageRanges.class) { + if (flavor == null|| flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) + || flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE)) { + PageRanges[] arr = new PageRanges[1]; + arr[0] = new PageRanges(1, Integer.MAX_VALUE); + return arr; + } else { + return null; + } + } + if (category == Fidelity.class) { + return new Fidelity[]{ Fidelity.FIDELITY_FALSE, Fidelity.FIDELITY_TRUE}; + } + if (category == PrintQuality.class) { + return new PrintQuality[]{ PrintQuality.DRAFT, PrintQuality.HIGH, PrintQuality.NORMAL }; + } + + boolean printPageAble = flavor == null|| flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) + || flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE); + if (category == Sides.class) { + if ( printPageAble ) { + return new Sides[]{ Sides.ONE_SIDED, Sides.TWO_SIDED_LONG_EDGE, Sides.TWO_SIDED_SHORT_EDGE}; + } else { + return null; + } + } + if (category == SheetCollate.class) { + if ( printPageAble ) { + return new SheetCollate[]{ SheetCollate.COLLATED, SheetCollate.UNCOLLATED} ; + } else { + return null; + } + } + boolean imageBased = printPageAble || flavor.equals(DocFlavor.INPUT_STREAM.GIF) + || flavor.equals(DocFlavor.INPUT_STREAM.JPEG) + || flavor.equals(DocFlavor.INPUT_STREAM.PNG) + || flavor.equals(DocFlavor.BYTE_ARRAY.GIF) + || flavor.equals(DocFlavor.BYTE_ARRAY.JPEG) + || flavor.equals(DocFlavor.BYTE_ARRAY.PNG) + || flavor.equals(DocFlavor.URL.GIF) + || flavor.equals(DocFlavor.URL.JPEG) + || flavor.equals(DocFlavor.URL.PNG); + if (category == OrientationRequested.class) { + if( imageBased ){ + return new OrientationRequested[]{ OrientationRequested.PORTRAIT, OrientationRequested.LANDSCAPE, OrientationRequested.REVERSE_LANDSCAPE }; + } else { + return null; + } + } + if (category == Chromaticity.class) { + if( imageBased ){ + if( settings.get_DefaultPageSettings().get_Color() ){ + return new Chromaticity[]{ Chromaticity.MONOCHROME, Chromaticity.COLOR }; + } else { + return new Chromaticity[]{ Chromaticity.MONOCHROME }; + } + } else { + return null; + } + } return null; } @@ -285,7 +576,15 @@ public class Win32PrintService implements PrintService{ @Override public boolean isAttributeCategorySupported(Class category){ - // TODO Auto-generated method stub + if ( category == null || !Attribute.class.isAssignableFrom( category ) ) { + throw new IllegalArgumentException( "The category '" + category + "' is not an Attribute" ); + } + Class[] supported = getSupportedAttributeCategories(); + for( int i=0; i < supported.length; i++ ){ + if( category == supported[i] ){ + return true; + } + } return false; } @@ -325,4 +624,60 @@ public class Win32PrintService implements PrintService{ public int hashCode(){ return this.getClass().hashCode() + getName().hashCode(); } + + /** + * Tries to find a matching {@link MediaSizeName} for a paper by it's size + * @param paper + * @return + */ + private MediaSizeName findMatchingMedia( PaperSize paper ){ + if( paper.get_RawKind() > 0 && paper.get_RawKind() <= MEDIA_NAMES.length ){ + // match to predefined size + return MEDIA_NAMES[ paper.get_RawKind() - 1 ]; + } + int x = paper.get_Width() * INCH100_TO_MYM; + int y = paper.get_Height() * INCH100_TO_MYM; + if( x > y ){ // MediaSizes are always portrait! + int tmp = x; + x = y; + y = tmp; + } + for( MediaSizeName name : MEDIA_NAMES ){ + MediaSize media = MediaSize.getMediaSizeForName(name); + if( media != null ){ + if( Math.abs( x - media.getX(1) ) < MATCH_DIFF && Math.abs( y - media.getY(1) ) < MATCH_DIFF ){ + return name; + } + } + } + return null; + } + +// /** +// * A simple MediaSizeName implementation. This is required since some programs only query the +// * attributes for MediaSizeName instances - which is not correct, since all {@link Media} implementations +// * are allowed here! Anyways, we have to deal with this an provide the additional formats of .NET as well. +// */ +// private static class CustomMediaSizeName extends MediaSizeName { +// +// private final String name; +// +// /** +// * Creates the instance for a media name +// * @param name the name of the paper format +// */ +// protected CustomMediaSizeName( String name) { +// super(-1); +// this.name = name; +// } +// +// /** +// * Returns the paper format name +// * @return the paper format name +// */ +// @Override +// public String toString() { +// return name; +// } +// } } -- cgit v1.2.3