001package jmri.util; 002 003import javax.print.PrintService; 004import javax.print.PrintServiceLookup; 005import javax.print.attribute.standard.Media; 006import javax.print.attribute.standard.MediaSize; 007import javax.print.attribute.standard.MediaSizeName; 008import javax.print.attribute.standard.OrientationRequested; 009 010import org.slf4j.Logger; 011import org.slf4j.LoggerFactory; 012 013import java.awt.Dimension; 014import java.awt.PageAttributes; 015import java.awt.PageAttributes.MediaType; 016import java.util.Locale; 017import java.util.Set; 018 019public class PaperUtils { 020 // Countries primarily using US Letter 021 private static final Set<String> LETTER_COUNTRIES = Set.of("US", "CA", "MX", "PH", "PR"); 022 023 private static Dimension cachedPaperSize = null; 024 025 private static final int pointsPerInch = 72; 026 027 /** 028 * Returns the default paper size as a Dimension object in points 029 * 030 * @return The Dimension object representing the default paper size in 031 * points 032 */ 033 public static Dimension getPaperSizeDimension() { 034 if (cachedPaperSize == null) { 035 cachedPaperSize = getAutomaticPaperSize(); 036 } 037 return cachedPaperSize; 038 } 039 040 /** 041 * Retrieves the default printer's paper size in points (1/72"), adjusted 042 * for the current default orientation. If this is not possible, returns 043 * null. 044 * 045 * @return The Dimension object representing the default paper size in 046 * points, or null if it is not possible to retrieve the paper size. 047 */ 048 public static Dimension getOrientedPaperSizeInPointsIfPossible() { 049 PrintService service = PrintServiceLookup.lookupDefaultPrintService(); 050 if (service == null) { 051 log.warn("No default printer found"); 052 return null; 053 } 054 055 // Get Physical Paper Dimensions 056 Media mediaName = (MediaSizeName) service.getDefaultAttributeValue(Media.class); 057 058 // Handle missing default media name 059 if (mediaName == null) { 060 Object supported = service.getSupportedAttributeValues(Media.class, null, null); 061 if (supported instanceof Media[] && ((Media[]) supported).length > 0) { 062 mediaName = ((Media[]) supported)[0]; 063 } 064 } 065 066 if (!(mediaName instanceof MediaSizeName)) { 067 return null; 068 } 069 070 MediaSize size = MediaSize.getMediaSizeForName((MediaSizeName) mediaName); 071 072 if (size == null) { 073 return null; 074 } 075 076 int finalWidth = (int) (size.getX(MediaSize.INCH) * 72); 077 int finalHeight = (int) (size.getY(MediaSize.INCH) * 72); 078 079 // Get Orientation and Swap if necessary 080 OrientationRequested orient = 081 (OrientationRequested) service.getDefaultAttributeValue(OrientationRequested.class); 082 083 // LANDSCAPE and REVERSE_LANDSCAPE mean we swap width and height 084 if (orient == OrientationRequested.LANDSCAPE || orient == OrientationRequested.REVERSE_LANDSCAPE) { 085 int temp = finalWidth; 086 finalWidth = finalHeight; 087 finalHeight = temp; 088 } 089 090 return new Dimension(finalWidth, finalHeight); 091 } 092 093 /** 094 * Returns the default paper size as a PaperSize enum. This interrogates the 095 * default printer and may be slow if the printer is not available. You 096 * should probably use {@link #getPaperSizeDimension()} instead as it caches 097 * the result. 098 * 099 * @return A Dimension object representing the default paper size in points. 100 */ 101 public static Dimension getAutomaticPaperSize() { 102 // Try Printer Discovery 103 Dimension size = getOrientedPaperSizeInPointsIfPossible(); 104 105 if (size != null) { 106 return size; 107 } 108 109 // Fallback to System Locale 110 String country = Locale.getDefault().getCountry().toUpperCase(); 111 if (LETTER_COUNTRIES.contains(country)) { 112 return new Dimension((int) (8.5 * pointsPerInch), (int) (11.0 * pointsPerInch)); 113 } 114 115 // Final Default (Global Standard) 116 return new Dimension((int) (8.27 * pointsPerInch), (int) (11.69 * pointsPerInch)); 117 } 118 119 /** 120 * Syncs the PageAttributes object to the default printer's settings. 121 * 122 * @param pageAttr The PageAttributes object to sync. 123 */ 124 public static void syncPageAttributesToPrinter(PageAttributes pageAttr) { 125 PrintService service = PrintServiceLookup.lookupDefaultPrintService(); 126 if (service != null) { 127 Media media = (Media) service.getDefaultAttributeValue(Media.class); 128 129 if (media != null && media instanceof MediaSizeName) { 130 // Map the javax.print MediaSizeName to AWT PageAttributes.MediaType 131 if (media.equals(MediaSizeName.NA_LETTER)) { 132 pageAttr.setMedia(MediaType.NA_LETTER); 133 } else if (media.equals(MediaSizeName.NA_LEGAL)) { 134 pageAttr.setMedia(MediaType.NA_LEGAL); 135 } else if (media.equals(MediaSizeName.ISO_A4)) { 136 pageAttr.setMedia(MediaType.ISO_A4); 137 } else { 138 log.warn("Unsupported media: {}", media); 139 } 140 } 141 } else { 142 log.warn("No default printer found"); 143 } 144 } 145 146 private final static Logger log = LoggerFactory.getLogger(PaperUtils.class); 147 148}