/******************************************************************************* * Copyright (c) 2016 Weasis Team and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Nicolas Roduit - initial API and implementation *******************************************************************************/ package org.weasis.core.ui.util; import java.awt.Component; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Point; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import java.awt.image.RenderedImage; import java.awt.print.PageFormat; import java.awt.print.Printable; import java.awt.print.PrinterException; import java.awt.print.PrinterJob; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; import javax.print.attribute.HashPrintRequestAttributeSet; import javax.print.attribute.PrintRequestAttributeSet; import javax.swing.JComponent; import javax.swing.JOptionPane; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.weasis.core.api.gui.util.MathUtil; import org.weasis.core.api.image.LayoutConstraints; import org.weasis.core.api.media.data.ImageElement; import org.weasis.core.ui.Messages; import org.weasis.core.ui.editor.image.ExportImage; public class ImagePrint implements Printable { private static final Logger LOGGER = LoggerFactory.getLogger(ImagePrint.class); private Point printLoc; private PrintOptions printOptions; private ExportLayout<? extends ImageElement> layout; public ImagePrint(ExportLayout<? extends ImageElement> layout, PrintOptions printOptions) { this.layout = layout; this.printLoc = new Point(0, 0); this.printOptions = printOptions == null ? new PrintOptions() : printOptions; } public void setPrintLocation(Point d) { printLoc = d; } public Point getPrintLocation() { return printLoc; } public void print() { PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet(); PrinterJob pj = PrinterJob.getPrinterJob(); pj.setPrintable(this); // Get page format from the printer if (pj.printDialog(aset)) { try { pj.print(aset); } catch (Exception e) { // check for the annoying 'Printer is not accepting job' error. if (e.getMessage().indexOf("accepting job") != -1) { //$NON-NLS-1$ // recommend prompting the user at this point if they want to force it // so they'll know there may be a problem. int response = JOptionPane.showConfirmDialog(null, Messages.getString("ImagePrint.issue_desc"), //$NON-NLS-1$ Messages.getString("ImagePrint.status"), JOptionPane.YES_NO_OPTION, //$NON-NLS-1$ JOptionPane.WARNING_MESSAGE); if (response == 0) { try { // try printing again but ignore the not-accepting-jobs attribute ForcedAcceptPrintService.setupPrintJob(pj); // add secret ingredient pj.print(aset); LOGGER.info("Bypass Printer is not accepting job"); //$NON-NLS-1$ } catch (PrinterException ex) { LOGGER.error("Printer exception", ex); //$NON-NLS-1$ } } } else { LOGGER.error("Print exception", e); //$NON-NLS-1$ } } } } public static boolean disableDoubleBuffering(JComponent c) { if (c == null) { return false; } c.setDoubleBuffered(false); return c.isDoubleBuffered(); } public static void restoreDoubleBuffering(JComponent c, boolean wasBuffered) { if (c != null) { c.setDoubleBuffered(wasBuffered); } } @Override public int print(Graphics g, PageFormat f, int pageIndex) { if (pageIndex >= 1) { return Printable.NO_SUCH_PAGE; } printImage((Graphics2D) g, f); return Printable.PAGE_EXISTS; } public void printImage(Graphics2D g2d, PageFormat f) { if ((layout == null) || (g2d == null)) { return; } Dimension dimGrid = layout.layoutModel.getGridSize(); Point2D.Double placeholder = new Point2D.Double(f.getImageableWidth() - (dimGrid.width - 1) * 5, f.getImageableHeight() - (dimGrid.height - 1) * 5); int lastx = 0; double lastwx = 0.0; double[] lastwy = new double[dimGrid.width]; double wx = 0.0; final Map<LayoutConstraints, Component> elements = layout.layoutModel.getConstraints(); Iterator<Entry<LayoutConstraints, Component>> enumVal = elements.entrySet().iterator(); while (enumVal.hasNext()) { Entry<LayoutConstraints, Component> e = enumVal.next(); LayoutConstraints key = e.getKey(); Component value = e.getValue(); ExportImage<? extends ImageElement> image = null; Point2D.Double pad = new Point2D.Double(0.0, 0.0); if (value instanceof ExportImage) { image = (ExportImage) value; formatImage(image, key, placeholder, pad); } if (key.gridx == 0) { wx = 0.0; } else if (lastx < key.gridx) { wx += lastwx; } double wy = lastwy[key.gridx]; double x = printLoc.x + f.getImageableX() + (placeholder.x * wx) + (MathUtil.isEqualToZero(wx) ? 0 : key.gridx * 5) + pad.x; double y = printLoc.y + f.getImageableY() + (placeholder.y * wy) + (MathUtil.isEqualToZero(wy) ? 0 : key.gridy * 5) + pad.y; lastx = key.gridx; lastwx = key.weightx; for (int i = key.gridx; i < key.gridx + key.gridwidth; i++) { lastwy[i] += key.weighty; } if (image != null) { // Set us to the upper left corner g2d.translate(x, y); boolean wasBuffered = disableDoubleBuffering(image); g2d.setClip(image.getBounds()); image.draw(g2d); restoreDoubleBuffering(image, wasBuffered); g2d.translate(-x, -y); } } } private void formatImage(ExportImage<? extends ImageElement> image, LayoutConstraints key, Point2D.Double placeholder, Point2D.Double pad) { if (!printOptions.isShowingAnnotations() && image.getInfoLayer().getVisible()) { image.getInfoLayer().setVisible(false); } Rectangle2D originSize = (Rectangle2D) image.getActionValue("origin.image.bound"); //$NON-NLS-1$ Point2D originCenter = (Point2D) image.getActionValue("origin.center"); //$NON-NLS-1$ Double originZoom = (Double) image.getActionValue("origin.zoom"); //$NON-NLS-1$ RenderedImage img = image.getSourceImage(); if (img != null && originCenter != null && originZoom != null) { boolean bestfit = originZoom <= 0.0; double canvasWidth; double canvasHeight; if (bestfit || originSize == null) { canvasWidth = img.getWidth() * image.getImage().getRescaleX(); canvasHeight = img.getHeight() * image.getImage().getRescaleY(); } else { canvasWidth = originSize.getWidth() / originZoom; canvasHeight = originSize.getHeight() / originZoom; } double scaleCanvas = Math.min(placeholder.x * key.weightx / canvasWidth, placeholder.y * key.weighty / canvasHeight); // Set the print area in pixel double cw = canvasWidth * scaleCanvas; double ch = canvasHeight * scaleCanvas; image.setSize((int) (cw + 0.5), (int) (ch + 0.5)); if (printOptions.isCenter()) { pad.x = (placeholder.x * key.weightx - cw) * 0.5; pad.y = (placeholder.y * key.weighty - ch) * 0.5; } else { pad.x = 0.0; pad.y = 0.0; } double scaleFactor = Math.min(cw / canvasWidth, ch / canvasHeight); // Resize in best fit window image.zoom(scaleFactor); if (bestfit) { image.center(); } else { image.setCenter(originCenter.getX(), originCenter.getY()); } int dpi = printOptions.getDpi() == null ? 150 : printOptions.getDpi().getDpi(); double ratioFromDPI = dpi * scaleFactor / 72.0; image.setImagePrintingResolution(ratioFromDPI); } } }