/* * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved. * Copyright (C) 2009, 2012 Volker Berlin (i-net software) * Copyright (C) 2010, 2011 Karsten Heinrich (i-net software) * 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.io.File; import java.net.URI; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.Hashtable; import java.util.List; import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; import javax.print.DocFlavor; import javax.print.DocPrintJob; import javax.print.PrintService; import javax.print.ServiceUIFactory; import javax.print.attribute.Attribute; import javax.print.attribute.AttributeSet; import javax.print.attribute.AttributeSetUtilities; import javax.print.attribute.HashPrintServiceAttributeSet; import javax.print.attribute.PrintServiceAttribute; 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.MediaTray; import javax.print.attribute.standard.OrientationRequested; import javax.print.attribute.standard.PageRanges; import javax.print.attribute.standard.PrintQuality; import javax.print.attribute.standard.PrinterIsAcceptingJobs; import javax.print.attribute.standard.PrinterName; import javax.print.attribute.standard.PrinterResolution; import javax.print.attribute.standard.PrinterState; import javax.print.attribute.standard.PrinterStateReasons; import javax.print.attribute.standard.QueuedJobCount; import javax.print.attribute.standard.RequestingUserName; import javax.print.attribute.standard.SheetCollate; import javax.print.attribute.standard.Sides; import javax.print.event.PrintServiceAttributeListener; import cli.System.NewsStyleUriParser; 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.PaperSource; import cli.System.Drawing.Printing.PrintDocument; import cli.System.Drawing.Printing.PrinterSettings; import cli.System.Drawing.Printing.PrinterSettings.PaperSizeCollection; import cli.System.Drawing.Printing.PrinterSettings.PaperSourceCollection; import cli.System.Drawing.Printing.PrinterSettings.PrinterResolutionCollection; import cli.System.Net.Mime.MediaTypeNames; /** * @author Volker Berlin */ public class Win32PrintService implements PrintService { // note: the Win32PrintService is implemented as foreign service (doesn't implement SunPrinterJobService) // to avoid implementing the WPrinterJob private static final DocFlavor[] supportedFlavors = { DocFlavor.SERVICE_FORMATTED.PAGEABLE, DocFlavor.SERVICE_FORMATTED.PRINTABLE, }; /** Mapping for PageSize.RawKind to predefined MediaSizeName */ private static final MediaSizeName[] MEDIA_NAMES = new MediaSizeName[70]; private static final Hashtable CUSTOM_MEDIA_NAME = new Hashtable<>(); /* it turns out to be inconvenient to store the other categories * separately because many attributes are in multiple categories. */ private static Class[] otherAttrCats = { JobName.class, RequestingUserName.class, Copies.class, Destination.class, OrientationRequested.class, PageRanges.class, Media.class, MediaPrintableArea.class, Fidelity.class, // We support collation on 2D printer jobs, even if the driver can't. SheetCollate.class, SunAlternateMedia.class, Chromaticity.class }; // conversion from 1/100 Inch (.NET) to um (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 ; MEDIA_NAMES[65] = MediaSizeName.ISO_A2 ; MEDIA_NAMES[69] = MediaSizeName.ISO_A6 ; // // 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; private final String printer; private final PrinterSettings settings; private PrinterName name; private MediaTray[] mediaTrays; transient private ServiceNotifier notifier = null; public Win32PrintService(String name, PrintPeer peer){ if(name == null){ throw new IllegalArgumentException("null printer name"); } this.peer = peer; printer = name; settings = new PrintDocument().get_PrinterSettings(); settings.set_PrinterName(printer); } @Override public String getName(){ return printer; } private PrinterName getPrinterName(){ if(name == null){ name = new PrinterName(printer, null); } return name; } public void wakeNotifier() { synchronized (this) { if (notifier != null) { notifier.wake(); } } } @Override public void addPrintServiceAttributeListener(PrintServiceAttributeListener listener){ synchronized (this) { if (listener == null) { return; } if (notifier == null) { notifier = new ServiceNotifier(this); } notifier.addListener(listener); } } @Override public void removePrintServiceAttributeListener(PrintServiceAttributeListener listener){ synchronized (this) { if (listener == null || notifier == null ) { return; } notifier.removeListener(listener); if (notifier.isEmpty()) { notifier.stopNotifier(); notifier = null; } } } @Override public DocPrintJob createPrintJob(){ SecurityManager security = System.getSecurityManager(); if(security != null){ security.checkPrintJobAccess(); } return new Win32PrintJob(this, peer); } @Override public T getAttribute(Class category){ if(category == null){ throw new NullPointerException("category"); } if(!(PrintServiceAttribute.class.isAssignableFrom(category))){ throw new IllegalArgumentException("The categhory '" + category + "' is not a valid PrintServiceAttribute"); } if(category == ColorSupported.class){ // 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 { // QueuedJobCount and PrinterIsAcceptingJobs return (T)peer.getPrinterStatus(printer, category); } } @Override public PrintServiceAttributeSet getAttributes(){ PrintServiceAttributeSet attrs = new HashPrintServiceAttributeSet(); attrs.add(getPrinterName()); PrinterIsAcceptingJobs acptJobs = getAttribute(PrinterIsAcceptingJobs.class); if(acptJobs != null){ attrs.add(acptJobs); } PrinterState prnState = getAttribute(PrinterState.class); if(prnState != null){ attrs.add(prnState); } PrinterStateReasons prnStateReasons = getAttribute(PrinterStateReasons.class); if(prnStateReasons != null){ attrs.add(prnStateReasons); } QueuedJobCount jobCount = getAttribute(QueuedJobCount.class); if(jobCount != null){ attrs.add(jobCount); } // 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); } return AttributeSetUtilities.unmodifiableView(attrs); } @Override public Object getDefaultAttributeValue(Class category){ 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 ); } else if (category == Chromaticity.class) { // NOTE: this works for CutePDF, settings.get_SupportsColor() does not return settings.get_DefaultPageSettings().get_Color() ? Chromaticity.COLOR : Chromaticity.MONOCHROME; } else if (category == JobName.class) { return new JobName( "Java Printing", null ); // TODO this is Java-Default, use another one for IKVM? } else if (category == OrientationRequested.class) { return settings.get_DefaultPageSettings().get_Landscape() ? OrientationRequested.LANDSCAPE : OrientationRequested.PORTRAIT; } else if (category == PageRanges.class) { return new PageRanges(1, Integer.MAX_VALUE ); } else 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 findMatchingMedia( settings.get_DefaultPageSettings().get_PaperSize() ); } else { return MEDIA_NAMES[ rawKind - 1 ]; } } else 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); } else 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; } } } else 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; } } else if (category == PrinterResolution.class) { cli.System.Drawing.Printing.PrinterResolution pRes = settings.get_DefaultPageSettings().get_PrinterResolution(); int xRes = pRes.get_X(); int yRes = pRes.get_Y(); if ((xRes <= 0) || (yRes <= 0)) { int res = (yRes > xRes) ? yRes : xRes; if (res > 0) { return new PrinterResolution(res, res, PrinterResolution.DPI); } } else { return new PrinterResolution(xRes, yRes, PrinterResolution.DPI); } } else if (category == ColorSupported.class) { if ( settings.get_SupportsColor() ) { return ColorSupported.SUPPORTED; } else { return ColorSupported.NOT_SUPPORTED; } } else if( category == PrintQuality.class ){ cli.System.Drawing.Printing.PrinterResolutionKind kind = settings.get_DefaultPageSettings().get_PrinterResolution().get_Kind(); switch (kind.Value) { case cli.System.Drawing.Printing.PrinterResolutionKind.High: return PrintQuality.HIGH; case cli.System.Drawing.Printing.PrinterResolutionKind.Medium: case cli.System.Drawing.Printing.PrinterResolutionKind.Low: return PrintQuality.NORMAL; case cli.System.Drawing.Printing.PrinterResolutionKind.Draft: return PrintQuality.DRAFT; } } else if (category == RequestingUserName.class) { try{ return new RequestingUserName( System.getProperty("user.name", ""), null); } catch( SecurityException e ){ return new RequestingUserName( "", null); } } else if (category == SheetCollate.class){ return settings.get_Collate() ? SheetCollate.COLLATED : SheetCollate.UNCOLLATED; } else if (category == Fidelity.class) { return Fidelity.FIDELITY_FALSE; } return null; } @Override public ServiceUIFactory getServiceUIFactory(){ return null; } @Override public Class[] getSupportedAttributeCategories(){ ArrayList categList = new ArrayList(otherAttrCats.length+3); for (int i=0; i < otherAttrCats.length; i++) { categList.add(otherAttrCats[i]); } if (settings.get_CanDuplex()) { categList.add(Sides.class); } if (settings.get_PrinterResolutions().get_Count() > 0) { categList.add(PrinterResolution.class); } return categList.toArray(new Class[categList.size()]); } @Override 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); } } // add media trays MediaTray[] trays = getMediaTrays(); for( MediaTray tray : trays ){ medias.add( tray ); } 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; } private MediaTray[] getMediaTrays(){ if( mediaTrays != null ){ // the print service is a singleton per printer so we only do this once return mediaTrays; } PaperSourceCollection trays = settings.get_PaperSources(); int count = trays.get_Count(); List trayList = new ArrayList(); for( int i=0; i < count; i++ ){ PaperSource tray = trays.get_Item(i); MediaTray javaTray = getDefaultTray(tray); if( javaTray != null ){ trayList.add( javaTray ); } else { trayList.add( new NetMediaTray( tray ) ); } } mediaTrays = trayList.toArray( new MediaTray[trayList.size()]); return mediaTrays; } @Override public DocFlavor[] getSupportedDocFlavors(){ int len = supportedFlavors.length; DocFlavor[] result = new DocFlavor[len]; System.arraycopy(supportedFlavors, 0, result, 0, len); return result; } @Override public AttributeSet getUnsupportedAttributes(DocFlavor flavor, AttributeSet attributes){ // TODO Auto-generated method stub return null; } @Override public boolean isAttributeCategorySupported(Class category){ 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; } private boolean isPostScriptFlavor(DocFlavor flavor) { if (flavor.equals(DocFlavor.BYTE_ARRAY.POSTSCRIPT) || flavor.equals(DocFlavor.INPUT_STREAM.POSTSCRIPT) || flavor.equals(DocFlavor.URL.POSTSCRIPT)) { return true; } else { return false; } } private boolean isPSDocAttr(Class category) { if (category == OrientationRequested.class || category == Copies.class) { return true; } else { return false; } } private boolean isAutoSense(DocFlavor flavor) { if (flavor.equals(DocFlavor.BYTE_ARRAY.AUTOSENSE) || flavor.equals(DocFlavor.INPUT_STREAM.AUTOSENSE) || flavor.equals(DocFlavor.URL.AUTOSENSE)) { return true; } else { return false; } } @Override public boolean isAttributeValueSupported(Attribute attr, DocFlavor flavor, AttributeSet attributes){ if (attr == null) { throw new NullPointerException("null attribute"); } Class category = attr.getCategory(); if (flavor != null) { if (!isDocFlavorSupported(flavor)) { throw new IllegalArgumentException(flavor + " is an unsupported flavor"); // if postscript & category is already specified within the PostScript data // we return false } else if (isAutoSense(flavor) || (isPostScriptFlavor(flavor) && (isPSDocAttr(category)))) { return false; } } if (!isAttributeCategorySupported(category)) { return false; } else if (category == Chromaticity.class) { if ((flavor == null) || flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) || flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE) || flavor.equals(DocFlavor.BYTE_ARRAY.GIF) || flavor.equals(DocFlavor.INPUT_STREAM.GIF) || flavor.equals(DocFlavor.URL.GIF) || flavor.equals(DocFlavor.BYTE_ARRAY.JPEG) || flavor.equals(DocFlavor.INPUT_STREAM.JPEG) || flavor.equals(DocFlavor.URL.JPEG) || flavor.equals(DocFlavor.BYTE_ARRAY.PNG) || flavor.equals(DocFlavor.INPUT_STREAM.PNG) || flavor.equals(DocFlavor.URL.PNG)) { if (settings.get_DefaultPageSettings().get_Color()) { return true; } else { return attr == Chromaticity.MONOCHROME; } } else { return false; } } else if (category == Copies.class) { return ((Copies)attr).getValue() >= 1 && ((Copies)attr).getValue() <= settings.get_MaximumCopies(); } else if (category == Destination.class) { URI uri = ((Destination)attr).getURI(); if ("file".equals(uri.getScheme()) && !(uri.getSchemeSpecificPart().equals(""))) { return true; } else { return false; } } else if (category == Media.class) { Media[] medias = (Media[])getSupportedAttributeValues( Media.class, flavor, attributes ); if( medias != null ) { return Arrays.asList( medias ).contains( attr ); } } else if (category == MediaPrintableArea.class) { //TODO return true; } else if (category == SunAlternateMedia.class) { Media media = ((SunAlternateMedia)attr).getMedia(); return isAttributeValueSupported(media, flavor, attributes); } else if (category == PageRanges.class || category == SheetCollate.class || category == Sides.class) { if (flavor != null && !(flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) || flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE))) { return false; } } else if (category == PrinterResolution.class) { if (attr instanceof PrinterResolution) { int[] jRes = ((PrinterResolution)attr).getResolution( PrinterResolution.DPI ); PrinterResolutionCollection resolutions = settings.get_PrinterResolutions(); for( int i=0; i< resolutions.get_Count(); i++ ) { cli.System.Drawing.Printing.PrinterResolution nRes = resolutions.get_Item( i ); if( nRes.get_X() == jRes[0] && nRes.get_Y() == jRes[1] ) { return true; } } return false; } } else if (category == OrientationRequested.class) { if (attr == OrientationRequested.REVERSE_PORTRAIT || (flavor != null) && !(flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) || flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE) || 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))) { return false; } } else if (category == ColorSupported.class) { boolean isColorSup = settings.get_DefaultPageSettings().get_Color(); if ((!isColorSup && (attr == ColorSupported.SUPPORTED)) || (isColorSup && (attr == ColorSupported.NOT_SUPPORTED))) { return false; } } return true; } @Override public boolean isDocFlavorSupported(DocFlavor flavor){ for (int f=0; f 0 && rawKind <= MEDIA_NAMES.length ){ // match to predefined size MediaSizeName media = MEDIA_NAMES[ rawKind - 1 ]; if( media != null ) { return media; } } 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; } } } MediaSizeName media = CUSTOM_MEDIA_NAME.get(paper.get_PaperName()); if (media == null) { media = new CustomMediaSizeName(paper.get_PaperName()); CUSTOM_MEDIA_NAME.put(paper.get_PaperName(), media); new MediaSize( x, y, MediaSize.INCH/100, media); } return media; } /** * Returns the Java-default {@link MediaTray} for a paper source. This is required since these default * trays are public constants which can be used without checking for the actually present media trays * @param source the .NET paper source to get the predefined source for * @return the media tray or null, in case there is no mapping for the paper source */ private MediaTray getDefaultTray( PaperSource source ){ // convert from .NET kind to java's pre defined MediaTrays switch( source.get_RawKind() ){ case 1 : return MediaTray.TOP; case 2 : return MediaTray.BOTTOM; case 3 : return MediaTray.MIDDLE; case 4 : return MediaTray.MANUAL; case 5 : return MediaTray.ENVELOPE; case 6 : return Win32MediaTray.ENVELOPE_MANUAL; case 7 : return Win32MediaTray.AUTO; case 8 : return Win32MediaTray.TRACTOR; case 9 : return Win32MediaTray.SMALL_FORMAT; case 10 : return Win32MediaTray.LARGE_FORMAT; case 11 : return MediaTray.LARGE_CAPACITY; case 14 : return MediaTray.MAIN; case 15 : return Win32MediaTray.FORMSOURCE; // FIXME which PaperSourceKind is MediaTray.SIDE ??? } return null; } /** * Returns the .NET {@link PaperSource} for a media tray. This will be done either by mapping or * directly in case the tray is a {@link NetMediaTray} * @param tray the tray to get the paper source for, must not be null * @return the selected {@link PaperSource} or null, in case there is no matching {@link PaperSource} */ public PaperSource getPaperSourceForTray( MediaTray tray ){ if( tray instanceof NetMediaTray ){ return ((NetMediaTray)tray).getPaperSource( this ); } // try to find the appropriate paper source for the Java-Defined tray PaperSourceCollection trays = settings.get_PaperSources(); int count = trays.get_Count(); for( int i=0; i < count; i++ ){ PaperSource paperSource = trays.get_Item(i); if( getDefaultTray( paperSource ) == tray ){ return paperSource; } } return null; } public static class NetMediaTray extends MediaTray{ private static final long serialVersionUID = 1L; /** Not really used but required by the EnumSyntax super class */ private static AtomicInteger idCounter = new AtomicInteger(8); private int rawKind; private String name; private transient PaperSource netSource; public NetMediaTray( PaperSource netSource ) { super( idCounter.getAndIncrement() ); this.rawKind = netSource.get_RawKind(); this.name = netSource.get_SourceName(); this.netSource = netSource; } public PaperSource getPaperSource( Win32PrintService service ){ if( netSource == null ){ PaperSourceCollection sources = service.settings.get_PaperSources(); int count = sources.get_Count(); for( int i=0; i < count; i++ ){ PaperSource source = sources.get_Item(i); if( source.get_RawKind() == rawKind ){ netSource = source; break; } } } return netSource; } @Override public String toString() { return netSource != null ? netSource.get_SourceName() : name; } } }