/*
 * Copyright (c) 1998, 2025, 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.Color;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.HeadlessException;
import java.awt.KeyboardFocusManager;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.awt.print.Book;
import java.awt.print.Pageable;
import java.awt.print.PageFormat;
import java.awt.print.Paper;
import java.awt.print.Printable;
import java.awt.print.PrinterAbortException;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import java.awt.Window;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Locale;
import sun.awt.image.ByteInterleavedRaster;

import javax.print.Doc;
import javax.print.DocFlavor;
import javax.print.DocPrintJob;
import javax.print.PrintException;
import javax.print.PrintService;
import javax.print.PrintServiceLookup;
import javax.print.ServiceUI;
import javax.print.StreamPrintService;
import javax.print.StreamPrintServiceFactory;
import javax.print.attribute.Attribute;
import javax.print.attribute.AttributeSet;
import javax.print.attribute.HashPrintRequestAttributeSet;
import javax.print.attribute.PrintRequestAttributeSet;
import javax.print.attribute.ResolutionSyntax;
import javax.print.attribute.Size2DSyntax;
import javax.print.attribute.standard.Copies;
import javax.print.attribute.standard.Destination;
import javax.print.attribute.standard.DialogTypeSelection;
import javax.print.attribute.standard.DialogOwner;
import javax.print.attribute.standard.Fidelity;
import javax.print.attribute.standard.JobName;
import javax.print.attribute.standard.JobSheets;
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.OutputBin;
import javax.print.attribute.standard.PageRanges;
import javax.print.attribute.standard.PrinterResolution;
import javax.print.attribute.standard.PrinterState;
import javax.print.attribute.standard.PrinterStateReason;
import javax.print.attribute.standard.PrinterStateReasons;
import javax.print.attribute.standard.PrinterIsAcceptingJobs;
import javax.print.attribute.standard.RequestingUserName;
import javax.print.attribute.standard.SheetCollate;
import javax.print.attribute.standard.Sides;

import static sun.font.FontUtilities.isIgnorableWhitespace;

/**
 * A class which rasterizes a printer job.
 *
 * @author Richard Blanchard
 */
public abstract class RasterPrinterJob extends PrinterJob {

 /* Class Constants */

     /* Printer destination type. */
    protected static final int PRINTER = 0;

     /* File destination type.  */
    protected static final int FILE = 1;

    /* Stream destination type.  */
    protected static final int STREAM = 2;

    /**
     * Pageable MAX pages
     */
    protected static final int MAX_UNKNOWN_PAGES = 9999;

    protected static final int PD_ALLPAGES = 0x00000000;
    protected static final int PD_SELECTION = 0x00000001;
    protected static final int PD_PAGENUMS = 0x00000002;
    protected static final int PD_NOSELECTION = 0x00000004;

    /**
     * Maximum amount of memory in bytes to use for the
     * buffered image "band". 4Mb is a compromise between
     * limiting the number of bands on hi-res printers and
     * not using too much of the Java heap or causing paging
     * on systems with little RAM.
     */
    private static final int MAX_BAND_SIZE = (1024 * 1024 * 4);

    /* Dots Per Inch */
    private static final float DPI = 72.0f;

    /**
     * Useful mainly for debugging, this system property
     * can be used to force the printing code to print
     * using a particular pipeline. The two currently
     * supported values are FORCE_RASTER and FORCE_PDL.
     */
    private static final String FORCE_PIPE_PROP = "sun.java2d.print.pipeline";

    /**
     * When the system property FORCE_PIPE_PROP has this value
     * then each page of a print job will be rendered through
     * the raster pipeline.
     */
    private static final String FORCE_RASTER = "raster";

    /**
     * When the system property FORCE_PIPE_PROP has this value
     * then each page of a print job will be rendered through
     * the PDL pipeline.
     */
    private static final String FORCE_PDL = "pdl";

    /**
     * When the system property SHAPE_TEXT_PROP has this value
     * then text is always rendered as a shape, and no attempt is made
     * to match the font through GDI
     */
    private static final String SHAPE_TEXT_PROP = "sun.java2d.print.shapetext";

    /**
     * values obtained from System properties in static initialiser block
     */
    public static boolean forcePDL = false;
    public static boolean forceRaster = false;
    public static boolean shapeTextProp = false;

    static {
        /* The system property FORCE_PIPE_PROP
         * can be used to force the printing code to
         * use a particular pipeline. Either the raster
         * pipeline or the pdl pipeline can be forced.
         */
        String forceStr = System.getProperty(FORCE_PIPE_PROP);

        if (forceStr != null) {
            if (forceStr.equalsIgnoreCase(FORCE_PDL)) {
                forcePDL = true;
            } else if (forceStr.equalsIgnoreCase(FORCE_RASTER)) {
                forceRaster = true;
            }
        }

        String shapeTextStr = System.getProperty(SHAPE_TEXT_PROP);

        if (shapeTextStr != null) {
            shapeTextProp = true;
        }
    }

    /* Instance Variables */

    /**
     * Used to minimize GC & reallocation of band when printing
     */
    private int cachedBandWidth = 0;
    private int cachedBandHeight = 0;
    private BufferedImage cachedBand = null;

    /**
     * The number of book copies to be printed.
     */
    private int mNumCopies = 1;

    /**
     * Collation effects the order of the pages printed
     * when multiple copies are requested. For two copies
     * of a three page document the page order is:
     *  mCollate true: 1, 2, 3, 1, 2, 3
     *  mCollate false: 1, 1, 2, 2, 3, 3
     */
    private boolean mCollate = false;

    /**
     * The zero based indices of the first and last
     * pages to be printed. If 'mFirstPage' is
     * UNDEFINED_PAGE_NUM then the first page to
     * be printed is page 0. If 'mLastPage' is
     * UNDEFINED_PAGE_NUM then the last page to
     * be printed is the last one in the book.
     */
    private int mFirstPage = Pageable.UNKNOWN_NUMBER_OF_PAGES;
    private int mLastPage = Pageable.UNKNOWN_NUMBER_OF_PAGES;

    /**
     * The previous print stream Paper
     * Used to check if the paper size has changed such that the
     * implementation needs to emit the new paper size information
     * into the print stream.
     * Since we do our own rotation, and the margins aren't relevant,
     * Its strictly the dimensions of the paper that we will check.
     */
    private Paper previousPaper;

    /**
     * The document to be printed. It is initialized to an
     * empty (zero pages) book.
     */
// MacOSX - made protected so subclasses can reference it.
    protected Pageable mDocument = new Book();

    /**
     * The name of the job being printed.
     */
    private String mDocName = "Java Printing";


    /**
     * Printing cancellation flags
     */
 // MacOSX - made protected so subclasses can reference it.
    protected boolean performingPrinting = false;
 // MacOSX - made protected so subclasses can reference it.
    protected boolean userCancelled = false;

    /**
     * List of areas & the graphics state for redrawing
     */
    private ArrayList<GraphicsState> redrawList = new ArrayList<>();


    /* variables representing values extracted from an attribute set.
     * These take precedence over values set on a printer job
     */
    private int copiesAttr;
    private String jobNameAttr;
    private String userNameAttr;
    private PageRanges pageRangesAttr;
    protected PrinterResolution printerResAttr;
    protected Sides sidesAttr;
    protected OutputBin outputBinAttr;
    protected String destinationAttr;
    protected boolean noJobSheet = false;
    protected int mDestType = RasterPrinterJob.FILE;
    protected String mDestination = "";
    protected boolean collateAttReq = false;

    /**
     * Device rotation flag, if it support 270, this is set to true;
     */
    protected boolean landscapeRotates270 = false;

   /**
     * attributes used by no-args page and print dialog and print method to
     * communicate state
     */
    protected PrintRequestAttributeSet attributes = null;

    /**
     * Class to keep state information for redrawing areas
     * "region" is an area at as a high a resolution as possible.
     * The redrawing code needs to look at sx, sy to calculate the scale
     * to device resolution.
     */
    private static class GraphicsState {
        Rectangle2D region;  // Area of page to repaint
        Shape theClip;       // image drawing clip.
        AffineTransform theTransform; // to transform clip to dev coords.
        double sx;           // X scale from region to device resolution
        double sy;           // Y scale from region to device resolution
    }

    /**
     * Service for this job
     */
    protected PrintService myService;

 /* Constructors */

    public RasterPrinterJob()
    {
    }

/* Abstract Methods */

    /**
     * Returns the resolution in dots per inch across the width
     * of the page.
     */
    protected abstract double getXRes();

    /**
     * Returns the resolution in dots per inch down the height
     * of the page.
     */
    protected abstract double getYRes();

    /**
     * Must be obtained from the current printer.
     * Value is in device pixels.
     * Not adjusted for orientation of the paper.
     */
    protected abstract double getPhysicalPrintableX(Paper p);

    /**
     * Must be obtained from the current printer.
     * Value is in device pixels.
     * Not adjusted for orientation of the paper.
     */
    protected abstract double getPhysicalPrintableY(Paper p);

    /**
     * Must be obtained from the current printer.
     * Value is in device pixels.
     * Not adjusted for orientation of the paper.
     */
    protected abstract double getPhysicalPrintableWidth(Paper p);

    /**
     * Must be obtained from the current printer.
     * Value is in device pixels.
     * Not adjusted for orientation of the paper.
     */
    protected abstract double getPhysicalPrintableHeight(Paper p);

    /**
     * Must be obtained from the current printer.
     * Value is in device pixels.
     * Not adjusted for orientation of the paper.
     */
    protected abstract double getPhysicalPageWidth(Paper p);

    /**
     * Must be obtained from the current printer.
     * Value is in device pixels.
     * Not adjusted for orientation of the paper.
     */
    protected abstract double getPhysicalPageHeight(Paper p);

    /**
     * Begin a new page.
     */
    protected abstract void startPage(PageFormat format, Printable painter,
                                      int index, boolean paperChanged)
        throws PrinterException;

    /**
     * End a page.
     */
    protected abstract void endPage(PageFormat format, Printable painter,
                                    int index)
        throws PrinterException;

    /**
     * Prints the contents of the array of ints, 'data'
     * to the current page. The band is placed at the
     * location (x, y) in device coordinates on the
     * page. The width and height of the band is
     * specified by the caller.
     */
    protected abstract void printBand(byte[] data, int x, int y,
                                      int width, int height)
        throws PrinterException;

/* Instance Methods */

    /**
      * save graphics state of a PathGraphics for later redrawing
      * of part of page represented by the region in that state
      */

    public void saveState(AffineTransform at, Shape clip,
                          Rectangle2D region, double sx, double sy) {
        GraphicsState gstate = new GraphicsState();
        gstate.theTransform = at;
        gstate.theClip = clip;
        gstate.region = region;
        gstate.sx = sx;
        gstate.sy = sy;
        redrawList.add(gstate);
    }


    /*
     * A convenience method which returns the default service
     * for 2D {@code PrinterJob}s.
     * May return null if there is no suitable default (although there
     * may still be 2D services available).
     * @return default 2D print service, or null.
     * @since     1.4
     */
    protected static PrintService lookupDefaultPrintService() {
        PrintService service = PrintServiceLookup.lookupDefaultPrintService();

        /* Pageable implies Printable so checking both isn't strictly needed */
        if (service != null &&
            service.isDocFlavorSupported(
                                DocFlavor.SERVICE_FORMATTED.PAGEABLE) &&
            service.isDocFlavorSupported(
                                DocFlavor.SERVICE_FORMATTED.PRINTABLE)) {
            return service;
        } else {
           PrintService []services =
             PrintServiceLookup.lookupPrintServices(
                                DocFlavor.SERVICE_FORMATTED.PAGEABLE, null);
           if (services.length > 0) {
               return services[0];
           }
        }
        return null;
    }

   /**
     * Returns the service (printer) for this printer job.
     * Implementations of this class which do not support print services
     * may return null;
     * @return the service for this printer job.
     *
     */
    public PrintService getPrintService() {
        if (myService == null) {
            PrintService svc = PrintServiceLookup.lookupDefaultPrintService();
            if (svc != null &&
                svc.isDocFlavorSupported(
                     DocFlavor.SERVICE_FORMATTED.PAGEABLE)) {
                try {
                    setPrintService(svc);
                    myService = svc;
                } catch (PrinterException e) {
                }
            }
            if (myService == null) {
                PrintService[] svcs = PrintServiceLookup.lookupPrintServices(
                    DocFlavor.SERVICE_FORMATTED.PAGEABLE, null);
                if (svcs.length > 0) {
                    try {
                        setPrintService(svcs[0]);
                        myService = svcs[0];
                    } catch (PrinterException e) {
                    }
                }
            }
        }
        return myService;
    }

    /**
     * Associate this PrinterJob with a new PrintService.
     *
     * Throws {@code PrinterException} if the specified service
     * cannot support the {@code Pageable} and
     * {@code Printable} interfaces necessary to support 2D printing.
     * @param service print service which supports 2D printing.
     *
     * @throws PrinterException if the specified service does not support
     * 2D printing or no longer available.
     */
    public void setPrintService(PrintService service)
        throws PrinterException {
        if (service == null) {
            throw new PrinterException("Service cannot be null");
        } else if (!(service instanceof StreamPrintService) &&
                   service.getName() == null) {
            throw new PrinterException("Null PrintService name.");
        } else {
            // Check the list of services.  This service may have been
            // deleted already
            PrinterState prnState = service.getAttribute(PrinterState.class);
            if (prnState == PrinterState.STOPPED) {
                PrinterStateReasons prnStateReasons =
                    service.getAttribute(PrinterStateReasons.class);
                if ((prnStateReasons != null) &&
                    (prnStateReasons.containsKey(PrinterStateReason.SHUTDOWN)))
                {
                    throw new PrinterException("PrintService is no longer available.");
                }
            }


            if (service.isDocFlavorSupported(
                                             DocFlavor.SERVICE_FORMATTED.PAGEABLE) &&
                service.isDocFlavorSupported(
                                             DocFlavor.SERVICE_FORMATTED.PRINTABLE)) {
                myService = service;
            } else {
                throw new PrinterException("Not a 2D print service: " + service);
            }
        }
    }

    private PageFormat attributeToPageFormat(PrintService service,
                                               PrintRequestAttributeSet attSet) {
        PageFormat page = defaultPage();

        if (service == null) {
            return page;
        }

        OrientationRequested orient = (OrientationRequested)
                                      attSet.get(OrientationRequested.class);
        if (orient == null) {
            orient = (OrientationRequested)
                    service.getDefaultAttributeValue(OrientationRequested.class);
        }
        if (orient == OrientationRequested.REVERSE_LANDSCAPE) {
            page.setOrientation(PageFormat.REVERSE_LANDSCAPE);
        } else if (orient == OrientationRequested.LANDSCAPE) {
            page.setOrientation(PageFormat.LANDSCAPE);
        } else {
            page.setOrientation(PageFormat.PORTRAIT);
        }

        Media media = (Media)attSet.get(Media.class);
        MediaSize size = getMediaSize(media, service, page);

        Paper paper = new Paper();
        float[] dim = size.getSize(1); //units == 1 to avoid FP error
        double w = Math.rint((dim[0]*72.0)/Size2DSyntax.INCH);
        double h = Math.rint((dim[1]*72.0)/Size2DSyntax.INCH);
        paper.setSize(w, h);
        MediaPrintableArea area =
             (MediaPrintableArea)
             attSet.get(MediaPrintableArea.class);
        if (area == null) {
            area = getDefaultPrintableArea(page, w, h);
        }

        double ix, iw, iy, ih;
        // Should pass in same unit as updatePageAttributes
        // to avoid rounding off errors.
        ix = Math.rint(
                area.getX(MediaPrintableArea.INCH) * DPI);
        iy = Math.rint(
                area.getY(MediaPrintableArea.INCH) * DPI);
        iw = Math.rint(
                area.getWidth(MediaPrintableArea.INCH) * DPI);
        ih = Math.rint(
                area.getHeight(MediaPrintableArea.INCH) * DPI);
        paper.setImageableArea(ix, iy, iw, ih);
        page.setPaper(paper);
        return page;
    }
    protected MediaSize getMediaSize(Media media, PrintService service,
            PageFormat page) {
        if (media == null) {
            media = (Media)service.getDefaultAttributeValue(Media.class);
        }
        if (!(media instanceof MediaSizeName)) {
            media = MediaSizeName.NA_LETTER;
        }
        MediaSize size = MediaSize.getMediaSizeForName((MediaSizeName) media);
        return size != null ? size : MediaSize.NA.LETTER;
    }

    protected MediaPrintableArea getDefaultPrintableArea(PageFormat page,
            double w, double h) {
        double ix, iw, iy, ih;
        if (w >= 72.0 * 6.0) {
            ix = 72.0;
            iw = w - 2 * 72.0;
        } else {
            ix = w / 6.0;
            iw = w * 0.75;
        }
        if (h >= 72.0 * 6.0) {
            iy = 72.0;
            ih = h - 2 * 72.0;
        } else {
            iy = h / 6.0;
            ih = h * 0.75;
        }

        return new MediaPrintableArea((float) (ix / DPI), (float) (iy / DPI),
                (float) (iw / DPI), (float) (ih / DPI), MediaPrintableArea.INCH);
    }

    protected void updatePageAttributes(PrintService service,
                                        PageFormat page) {
        if (this.attributes == null) {
            this.attributes = new HashPrintRequestAttributeSet();
        }

        updateAttributesWithPageFormat(service, page, this.attributes);
    }

    protected void updateAttributesWithPageFormat(PrintService service,
                                        PageFormat page,
                                        PrintRequestAttributeSet pageAttributes) {
        if (service == null || page == null || pageAttributes == null) {
            return;
        }

        float x = (float)Math.rint(
                         (page.getPaper().getWidth()*Size2DSyntax.INCH)/
                         (72.0))/(float)Size2DSyntax.INCH;
        float y = (float)Math.rint(
                         (page.getPaper().getHeight()*Size2DSyntax.INCH)/
                         (72.0))/(float)Size2DSyntax.INCH;

        // We should limit the list where we search the matching
        // media, this will prevent mapping to wrong media ex. Ledger
        // can be mapped to B.  Especially useful when creating
        // custom MediaSize.
        Media[] mediaList = (Media[])service.getSupportedAttributeValues(
                                      Media.class, null, null);
        Media media = null;
        try {
            media = CustomMediaSizeName.findMedia(mediaList, x, y,
                                   Size2DSyntax.INCH);
        } catch (IllegalArgumentException iae) {
        }
        if ((media == null) ||
             !(service.isAttributeValueSupported(media, null, null))) {
            media = (Media)service.getDefaultAttributeValue(Media.class);
        }

        OrientationRequested orient;
        switch (page.getOrientation()) {
        case PageFormat.LANDSCAPE :
            orient = OrientationRequested.LANDSCAPE;
            break;
        case PageFormat.REVERSE_LANDSCAPE:
            orient = OrientationRequested.REVERSE_LANDSCAPE;
            break;
        default:
            orient = OrientationRequested.PORTRAIT;
        }

        if (media != null) {
            pageAttributes.add(media);
        }
        pageAttributes.add(orient);

        float ix = (float)(page.getPaper().getImageableX()/DPI);
        float iw = (float)(page.getPaper().getImageableWidth()/DPI);
        float iy = (float)(page.getPaper().getImageableY()/DPI);
        float ih = (float)(page.getPaper().getImageableHeight()/DPI);

        if (ix < 0) ix = 0; if (iy < 0) iy = 0;
        if (iw <= 0) iw = (float)(page.getPaper().getWidth()/DPI) - (ix*2);

        // If iw is still negative, it means ix is too large to print
        // anything inside printable area if we have to leave the same margin
        // in the right side of paper so we go back to default mpa values
        if (iw < 0) iw = 0;

        if (ih <= 0) ih = (float)(page.getPaper().getHeight()/DPI) - (iy*2);

        // If ih is still negative, it means iy is too large to print
        // anything inside printable area if we have to leave the same margin
        // in the bottom side of paper so we go back to default mpa values
        if (ih < 0) ih = 0;
        try {
            pageAttributes.add(new MediaPrintableArea(ix, iy, iw, ih,
                                                  MediaPrintableArea.INCH));
        } catch (IllegalArgumentException iae) {
        }
    }

   /**
     * Display a dialog to the user allowing the modification of a
     * PageFormat instance.
     * The {@code page} argument is used to initialize controls
     * in the page setup dialog.
     * If the user cancels the dialog, then the method returns the
     * original {@code page} object unmodified.
     * If the user okays the dialog then the method returns a new
     * PageFormat object with the indicated changes.
     * In either case the original {@code page} object will
     * not be modified.
     * @param     page    the default PageFormat presented to the user
     *                    for modification
     * @return    the original {@code page} object if the dialog
     *            is cancelled, or a new PageFormat object containing
     *            the format indicated by the user if the dialog is
     *            acknowledged
     * @throws HeadlessException if GraphicsEnvironment.isHeadless()
     * returns true.
     * @see java.awt.GraphicsEnvironment#isHeadless
     * @since     1.2
     */
    public PageFormat pageDialog(PageFormat page)
        throws HeadlessException {
        if (GraphicsEnvironment.isHeadless()) {
            throw new HeadlessException();
        }

        final GraphicsConfiguration gc =
          GraphicsEnvironment.getLocalGraphicsEnvironment().
          getDefaultScreenDevice().getDefaultConfiguration();

        PrintService service = getPrintService();
        if (service == null) {
            ServiceDialog.showNoPrintService(gc);
            return page;
        }
        updatePageAttributes(service, page);

        PageFormat newPage = null;
        DialogTypeSelection dts =
            (DialogTypeSelection)attributes.get(DialogTypeSelection.class);
        if (dts == DialogTypeSelection.NATIVE) {
            // Remove DialogTypeSelection.NATIVE to prevent infinite loop in
            // RasterPrinterJob.
            attributes.remove(DialogTypeSelection.class);
            newPage = pageDialog(attributes);
            // restore attribute
            attributes.add(DialogTypeSelection.NATIVE);
        } else {
            newPage = pageDialog(attributes);
        }

        if (newPage == null) {
            return page;
        } else {
            return newPage;
        }
    }

    /**
     * return a PageFormat corresponding to the updated attributes,
     * or null if the user cancelled the dialog.
     */
    @SuppressWarnings("deprecation")
    public PageFormat pageDialog(final PrintRequestAttributeSet attributes)
        throws HeadlessException {
        if (GraphicsEnvironment.isHeadless()) {
            throw new HeadlessException();
        }

        DialogTypeSelection dlg =
            (DialogTypeSelection)attributes.get(DialogTypeSelection.class);

        // Check for native, note that default dialog is COMMON.
        if (dlg == DialogTypeSelection.NATIVE) {
            PrintService pservice = getPrintService();
            PageFormat pageFrmAttrib = attributeToPageFormat(pservice,
                                                             attributes);
            setParentWindowID(attributes);
            PageFormat page = pageDialog(pageFrmAttrib);
            clearParentWindowID();

            // If user cancels the dialog, pageDialog() will return the original
            // page object and as per spec, we should return null in that case.
            if (page == pageFrmAttrib) {
                return null;
            }
            updateAttributesWithPageFormat(pservice, page, attributes);
            return page;
        }

        GraphicsConfiguration grCfg = null;
        Window w = KeyboardFocusManager.getCurrentKeyboardFocusManager().getActiveWindow();
        if (w != null) {
            grCfg = w.getGraphicsConfiguration();
        } else {
            grCfg = GraphicsEnvironment.getLocalGraphicsEnvironment().
                        getDefaultScreenDevice().getDefaultConfiguration();
        }
        final GraphicsConfiguration gc = grCfg;

        PrintService service = getPrintService();
        if (service == null) {
            ServiceDialog.showNoPrintService(gc);
            return null;
        }

        // we position the dialog a little beyond the upper-left corner of the window
        // which is consistent with the NATIVE page dialog
        Rectangle gcBounds = gc.getBounds();
        int x = gcBounds.x+50;
        int y = gcBounds.y+50;
        ServiceDialog pageDialog;
        boolean setOnTop = false;
        if (onTop != null) {
            attributes.add(onTop);
            Window owner = onTop.getOwner();
            if (owner != null) {
                w = owner; // use the one specified by the app
            } else if (DialogOwnerAccessor.getID(onTop) == 0) {
                setOnTop = true;
            }
        }
            pageDialog = new ServiceDialog(gc, x, y, service,
                                           DocFlavor.SERVICE_FORMATTED.PAGEABLE,
                                           attributes, w);
        if (setOnTop) {
            pageDialog.setAlwaysOnTop(true);
        }

        Rectangle dlgBounds = pageDialog.getBounds();

        // if portion of dialog is not within the gc boundary
        if (!gcBounds.contains(dlgBounds)) {
            // check if dialog exceed window bounds at left or bottom
            // Then position the dialog by moving it by the amount it exceeds
            // the window bounds
            // If it results in dialog moving beyond the window bounds at top/left
            // then position it at window top/left
            if (dlgBounds.x + dlgBounds.width > gcBounds.x + gcBounds.width) {
                if ((gcBounds.x + gcBounds.width - dlgBounds.width) > gcBounds.x) {
                    x = (gcBounds.x + gcBounds.width) - dlgBounds.width;
                } else {
                    x = gcBounds.x;
                }
            }
            if (dlgBounds.y + dlgBounds.height > gcBounds.y + gcBounds.height) {
                if ((gcBounds.y + gcBounds.height - dlgBounds.height) > gcBounds.y) {
                    y = (gcBounds.y + gcBounds.height) - dlgBounds.height;
                } else {
                    y = gcBounds.y;
                }
            }
            pageDialog.setBounds(x, y, dlgBounds.width, dlgBounds.height);
        }
        pageDialog.show();

        if (pageDialog.getStatus() == ServiceDialog.APPROVE) {
            PrintRequestAttributeSet newas =
                pageDialog.getAttributes();
            Class<?> amCategory = SunAlternateMedia.class;

            if (attributes.containsKey(amCategory) &&
                !newas.containsKey(amCategory)) {
                attributes.remove(amCategory);
            }
            attributes.addAll(newas);
            return attributeToPageFormat(service, attributes);
        } else {
            return null;
        }
   }

    protected PageFormat getPageFormatFromAttributes() {
        Pageable pageable = null;
        if (attributes == null || attributes.isEmpty() ||
            !((pageable = getPageable()) instanceof OpenBook)) {
            return null;
        }

        PageFormat newPf = attributeToPageFormat(
            getPrintService(), attributes);
        PageFormat oldPf = null;
        if ((oldPf = pageable.getPageFormat(0)) != null) {
            // If orientation, media, imageable area attributes are not in
            // "attributes" set, then use respective values of the existing
            // page format "oldPf".
            if (attributes.get(OrientationRequested.class) == null) {
                newPf.setOrientation(oldPf.getOrientation());
            }

            Paper newPaper = newPf.getPaper();
            Paper oldPaper = oldPf.getPaper();
            boolean oldPaperValWasSet = false;
            if (attributes.get(MediaSizeName.class) == null) {
                newPaper.setSize(oldPaper.getWidth(), oldPaper.getHeight());
                oldPaperValWasSet = true;
            }
            if (attributes.get(MediaPrintableArea.class) == null) {
                newPaper.setImageableArea(
                    oldPaper.getImageableX(), oldPaper.getImageableY(),
                    oldPaper.getImageableWidth(),
                    oldPaper.getImageableHeight());
                oldPaperValWasSet = true;
            }
            if (oldPaperValWasSet) {
                newPf.setPaper(newPaper);
            }
        }
        return newPf;
    }


   /**
     * Presents the user a dialog for changing properties of the
     * print job interactively.
     * The services browsable here are determined by the type of
     * service currently installed.
     * If the application installed a StreamPrintService on this
     * PrinterJob, only the available StreamPrintService (factories) are
     * browsable.
     *
     * @param attributes to store changed properties.
     * @return false if the user cancels the dialog and true otherwise.
     * @throws HeadlessException if GraphicsEnvironment.isHeadless()
     * returns true.
     * @see java.awt.GraphicsEnvironment#isHeadless
     */
    public boolean printDialog(final PrintRequestAttributeSet attributes)
        throws HeadlessException {
        if (GraphicsEnvironment.isHeadless()) {
            throw new HeadlessException();
        }

        DialogTypeSelection dlg =
            (DialogTypeSelection)attributes.get(DialogTypeSelection.class);

        // Check for native, note that default dialog is COMMON.
        if (dlg == DialogTypeSelection.NATIVE) {
            this.attributes = attributes;
            try {
                debug_println("calling setAttributes in printDialog");
                setAttributes(attributes);

            } catch (PrinterException e) {

            }

            setParentWindowID(attributes);
            boolean ret = printDialog();
            clearParentWindowID();
            this.attributes = attributes;
            return ret;

        }

        GraphicsConfiguration grCfg = null;
        Window w = KeyboardFocusManager.getCurrentKeyboardFocusManager().getActiveWindow();
        if (w != null) {
            grCfg = w.getGraphicsConfiguration();
             /* Add DialogOwner attribute to set the owner of this print dialog
              * only if it is not set already
              * (it might be set in java.awt.PrintJob.printDialog)
              */
            if (attributes.get(DialogOwner.class) == null) {
                attributes.add(new DialogOwner(w));
            }
        } else {
            grCfg = GraphicsEnvironment.getLocalGraphicsEnvironment().
                        getDefaultScreenDevice().getDefaultConfiguration();
        }
        final GraphicsConfiguration gc = grCfg;

        PrintService service = getPrintService();
        if (service == null) {
            ServiceDialog.showNoPrintService(gc);
            return false;
        }

        PrintService[] services;
        StreamPrintServiceFactory[] spsFactories = null;
        if (service instanceof StreamPrintService) {
            spsFactories = lookupStreamPrintServices(null);
            services = new StreamPrintService[spsFactories.length];
            for (int i=0; i<spsFactories.length; i++) {
                services[i] = spsFactories[i].getPrintService(null);
            }
        } else {
            services = PrinterJob.lookupPrintServices();

            if ((services == null) || (services.length == 0)) {
                /*
                 * No services but default PrintService exists?
                 * Create services using defaultService.
                 */
                services = new PrintService[1];
                services[0] = service;
            }
        }

        // we position the dialog a little beyond the upper-left corner of the window
        // which is consistent with the NATIVE print dialog
        int x = 50;
        int y = 50;
        PrintService newService;
        // temporarily add an attribute pointing back to this job.
        PrinterJobWrapper jobWrapper = new PrinterJobWrapper(this);
        attributes.add(jobWrapper);
        PageRanges pgRng = (PageRanges)attributes.get(PageRanges.class);
        if (pgRng == null && mDocument.getNumberOfPages() > 1) {
            attributes.add(new PageRanges(1, mDocument.getNumberOfPages()));
        }
        try {
            newService =
            ServiceUI.printDialog(gc, x, y,
                                  services, service,
                                  DocFlavor.SERVICE_FORMATTED.PAGEABLE,
                                  attributes);
        } catch (IllegalArgumentException iae) {
            newService = ServiceUI.printDialog(gc, x, y,
                                  services, services[0],
                                  DocFlavor.SERVICE_FORMATTED.PAGEABLE,
                                  attributes);
        }
        attributes.remove(PrinterJobWrapper.class);
        attributes.remove(DialogOwner.class);

        if (newService == null) {
            return false;
        }

        this.attributes = attributes;

        if (!service.equals(newService)) {
            try {
                setPrintService(newService);
            } catch (PrinterException e) {
                /*
                 * The only time it would throw an exception is when
                 * newService is no longer available but we should still
                 * select this printer.
                 */
                myService = newService;
            }
        }
        return true;
    }

   /**
     * Presents the user a dialog for changing properties of the
     * print job interactively.
     * @return false if the user cancels the dialog and
     *         true otherwise.
     * @throws HeadlessException if GraphicsEnvironment.isHeadless()
     * returns true.
     * @see java.awt.GraphicsEnvironment#isHeadless
     */
    public boolean printDialog() throws HeadlessException {

        if (GraphicsEnvironment.isHeadless()) {
            throw new HeadlessException();
        }

        PrintRequestAttributeSet attributes =
          new HashPrintRequestAttributeSet();
        attributes.add(new Copies(getCopies()));
        attributes.add(new JobName(getJobName(), null));
        boolean doPrint = printDialog(attributes);
        if (doPrint) {
            JobName jobName = (JobName)attributes.get(JobName.class);
            if (jobName != null) {
                setJobName(jobName.getValue());
            }
            Copies copies = (Copies)attributes.get(Copies.class);
            if (copies != null) {
                setCopies(copies.getValue());
            }

            Destination dest = (Destination)attributes.get(Destination.class);

            if (dest != null) {
                try {
                    mDestType = RasterPrinterJob.FILE;
                    mDestination = (new File(dest.getURI())).getPath();
                } catch (Exception e) {
                    mDestination = "out.prn";
                    PrintService ps = getPrintService();
                    if (ps != null) {
                        Destination defaultDest = (Destination)ps.
                            getDefaultAttributeValue(Destination.class);
                        if (defaultDest != null) {
                            mDestination = (new File(defaultDest.getURI())).getPath();
                        }
                    }
                }
            } else {
                mDestType = RasterPrinterJob.PRINTER;
                PrintService ps = getPrintService();
                if (ps != null) {
                    mDestination = ps.getName();
                }
            }
        }

        return doPrint;
    }

    /**
     * The pages in the document to be printed by this PrinterJob
     * are drawn by the Printable object 'painter'. The PageFormat
     * for each page is the default page format.
     * @param painter Called to render each page of the document.
     */
    public void setPrintable(Printable painter) {
        setPageable(new OpenBook(defaultPage(new PageFormat()), painter));
    }

    /**
     * The pages in the document to be printed by this PrinterJob
     * are drawn by the Printable object 'painter'. The PageFormat
     * of each page is 'format'.
     * @param painter Called to render each page of the document.
     * @param format  The size and orientation of each page to
     *                be printed.
     */
    public void setPrintable(Printable painter, PageFormat format) {
        setPageable(new OpenBook(format, painter));
        updatePageAttributes(getPrintService(), format);
    }

    /**
     * The pages in the document to be printed are held by the
     * Pageable instance 'document'. 'document' will be queried
     * for the number of pages as well as the PageFormat and
     * Printable for each page.
     * @param document The document to be printed. It may not be null.
     * @throws NullPointerException the Pageable passed in was null.
     * @see PageFormat
     * @see Printable
     */
    public void setPageable(Pageable document) throws NullPointerException {
        if (document != null) {
            mDocument = document;

        } else {
            throw new NullPointerException();
        }
    }

    protected void initPrinter() {
        return;
    }

    protected boolean isSupportedValue(Attribute attrval,
                                     PrintRequestAttributeSet attrset) {
        PrintService ps = getPrintService();
        return
            (attrval != null && ps != null &&
             ps.isAttributeValueSupported(attrval,
                                          DocFlavor.SERVICE_FORMATTED.PAGEABLE,
                                          attrset));
    }

    /**
     * Set the device resolution.
     * Overridden and used only by the postscript code.
     * Windows code pulls the information from the attribute set itself.
     */
    protected void setXYRes(double x, double y) {
    }

    /* subclasses may need to pull extra information out of the attribute set
     * They can override this method & call super.setAttributes()
     */
    protected  void setAttributes(PrintRequestAttributeSet attributes)
        throws PrinterException {
        /*  reset all values to defaults */
        setCollated(false);
        sidesAttr = null;
        outputBinAttr = null;
        printerResAttr = null;
        pageRangesAttr = null;
        copiesAttr = 0;
        jobNameAttr = null;
        userNameAttr = null;
        destinationAttr = null;
        collateAttReq = false;

        PrintService service = getPrintService();
        if (attributes == null  || service == null) {
            return;
        }

        boolean fidelity = false;
        Fidelity attrFidelity = (Fidelity)attributes.get(Fidelity.class);
        if (attrFidelity != null && attrFidelity == Fidelity.FIDELITY_TRUE) {
            fidelity = true;
        }

        if (fidelity == true) {
           AttributeSet unsupported =
               service.getUnsupportedAttributes(
                                         DocFlavor.SERVICE_FORMATTED.PAGEABLE,
                                         attributes);
           if (unsupported != null) {
               throw new PrinterException("Fidelity cannot be satisfied");
           }
        }

        /*
         * Since we have verified supported values if fidelity is true,
         * we can either ignore unsupported values, or substitute a
         * reasonable alternative
         */

        SheetCollate collateAttr =
            (SheetCollate)attributes.get(SheetCollate.class);
        if (isSupportedValue(collateAttr,  attributes)) {
            setCollated(collateAttr == SheetCollate.COLLATED);
        }

        sidesAttr = (Sides)attributes.get(Sides.class);
        if (!isSupportedValue(sidesAttr,  attributes)) {
            sidesAttr = Sides.ONE_SIDED;
        }

        outputBinAttr = (OutputBin)attributes.get(OutputBin.class);
        if (!isSupportedValue(outputBinAttr,  attributes)) {
            outputBinAttr = null;
        }

        printerResAttr = (PrinterResolution)attributes.get(PrinterResolution.class);
        if (service.isAttributeCategorySupported(PrinterResolution.class)) {
            if (!isSupportedValue(printerResAttr,  attributes)) {
               printerResAttr = (PrinterResolution)
                   service.getDefaultAttributeValue(PrinterResolution.class);
            }
            if (printerResAttr != null) {
                double xr =
                        printerResAttr.getCrossFeedResolution(ResolutionSyntax.DPI);
                double yr = printerResAttr.getFeedResolution(ResolutionSyntax.DPI);
                setXYRes(xr, yr);
            }
        }

        pageRangesAttr =  (PageRanges)attributes.get(PageRanges.class);
        if (!isSupportedValue(pageRangesAttr, attributes)) {
            pageRangesAttr = null;
            setPageRange(-1, -1);
        } else {
            if ((SunPageSelection)attributes.get(SunPageSelection.class)
                     == SunPageSelection.RANGE) {
                // get to, from, min, max page ranges
                int[][] range = pageRangesAttr.getMembers();
                // setPageRanges uses 0-based indexing so we subtract 1
                setPageRange(range[0][0] - 1, range[0][1] - 1);
            } else {
               setPageRange(-1, - 1);
            }
        }

        Copies copies = (Copies)attributes.get(Copies.class);
        if (isSupportedValue(copies,  attributes) ||
            (!fidelity && copies != null)) {
            copiesAttr = copies.getValue();
            setCopies(copiesAttr);
        } else {
            copiesAttr = getCopies();
        }

        Destination destination =
            (Destination)attributes.get(Destination.class);

        if (isSupportedValue(destination,  attributes)) {
            try {
                // Old code (new File(destination.getURI())).getPath()
                // would generate a "URI is not hierarchical" IAE
                // for "file:out.prn" so we use getSchemeSpecificPart instead
                destinationAttr = "" + new File(destination.getURI().
                                                getSchemeSpecificPart());
            } catch (Exception e) { // paranoid exception
                Destination defaultDest = (Destination)service.
                    getDefaultAttributeValue(Destination.class);
                if (defaultDest != null) {
                    destinationAttr = "" + new File(defaultDest.getURI().
                                                getSchemeSpecificPart());
                }
            }
        }

        JobSheets jobSheets = (JobSheets)attributes.get(JobSheets.class);
        if (jobSheets != null) {
            noJobSheet = jobSheets == JobSheets.NONE;
        }

        JobName jobName = (JobName)attributes.get(JobName.class);
        if (isSupportedValue(jobName,  attributes) ||
            (!fidelity && jobName != null)) {
            jobNameAttr = jobName.getValue();
            setJobName(jobNameAttr);
        } else {
            jobNameAttr = getJobName();
        }

        RequestingUserName userName =
            (RequestingUserName)attributes.get(RequestingUserName.class);
        if (isSupportedValue(userName,  attributes) ||
            (!fidelity && userName != null)) {
            userNameAttr = userName.getValue();
        } else {
            userNameAttr = getUserName();
        }

        /* OpenBook is used internally only when app uses Printable.
         * This is the case when we use the values from the attribute set.
         */
        Media media = (Media)attributes.get(Media.class);
        OrientationRequested orientReq =
           (OrientationRequested)attributes.get(OrientationRequested.class);
        MediaPrintableArea mpa =
            (MediaPrintableArea)attributes.get(MediaPrintableArea.class);

        if ((orientReq != null || media != null || mpa != null) &&
            getPageable() instanceof OpenBook) {

            /* We could almost(!) use PrinterJob.getPageFormat() except
             * here we need to start with the PageFormat from the OpenBook :
             */
            Pageable pageable = getPageable();
            Printable printable = pageable.getPrintable(0);
            PageFormat pf = (PageFormat)pageable.getPageFormat(0).clone();
            Paper paper = pf.getPaper();

            /* If there's a media but no media printable area, we can try
             * to retrieve the default value for mpa and use that.
             */
            if (mpa == null && media != null &&
                service.
                isAttributeCategorySupported(MediaPrintableArea.class)) {
                Object mpaVals = service.
                    getSupportedAttributeValues(MediaPrintableArea.class,
                                                null, attributes);
                if (mpaVals instanceof MediaPrintableArea[] &&
                    ((MediaPrintableArea[])mpaVals).length > 0) {
                    mpa = ((MediaPrintableArea[])mpaVals)[0];
                }
            }

            if (isSupportedValue(orientReq, attributes) ||
                (!fidelity && orientReq != null)) {
                int orient;
                if (orientReq.equals(OrientationRequested.REVERSE_LANDSCAPE)) {
                    orient = PageFormat.REVERSE_LANDSCAPE;
                } else if (orientReq.equals(OrientationRequested.LANDSCAPE)) {
                    orient = PageFormat.LANDSCAPE;
                } else {
                    orient = PageFormat.PORTRAIT;
                }
                pf.setOrientation(orient);
            }

            if (isSupportedValue(media, attributes) ||
                (!fidelity && media != null)) {
                if (media instanceof MediaSizeName) {
                    MediaSizeName msn = (MediaSizeName)media;
                    MediaSize msz = MediaSize.getMediaSizeForName(msn);
                    if (msz != null) {
                        float paperWid =  msz.getX(MediaSize.INCH) * 72.0f;
                        float paperHgt =  msz.getY(MediaSize.INCH) * 72.0f;
                        paper.setSize(paperWid, paperHgt);
                        if (mpa == null) {
                            paper.setImageableArea(72.0, 72.0,
                                                   paperWid-144.0,
                                                   paperHgt-144.0);
                        }
                    }
                }
            }

            if (isSupportedValue(mpa, attributes) ||
                (!fidelity && mpa != null)) {
                float [] printableArea =
                    mpa.getPrintableArea(MediaPrintableArea.INCH);
                for (int i=0; i < printableArea.length; i++) {
                    printableArea[i] = printableArea[i]*72.0f;
                }
                paper.setImageableArea(printableArea[0], printableArea[1],
                                       printableArea[2], printableArea[3]);
            }

            pf.setPaper(paper);
            pf = validatePage(pf);
            setPrintable(printable, pf);
        } else {
            // for AWT where pageable is not an instance of OpenBook,
            // we need to save paper info
            this.attributes = attributes;
        }

    }

    /*
     * Services we don't recognize as built-in services can't be
     * implemented as subclasses of PrinterJob, therefore we create
     * a DocPrintJob from their service and pass a Doc representing
     * the application's printjob
     */
// MacOSX - made protected so subclasses can reference it.
    protected void spoolToService(PrintService psvc,
                                PrintRequestAttributeSet attributes)
        throws PrinterException {

        if (psvc == null) {
            throw new PrinterException("No print service found.");
        }

        DocPrintJob job = psvc.createPrintJob();
        Doc doc = new PageableDoc(getPageable());
        if (attributes == null) {
            attributes = new HashPrintRequestAttributeSet();
            attributes.add(new Copies(getCopies()));
            attributes.add(new JobName(getJobName(), null));
        }
        try {
            job.print(doc, attributes);
        } catch (PrintException e) {
            throw new PrinterException(e.toString());
        }
    }

    /**
     * Prints a set of pages.
     * @throws java.awt.print.PrinterException an error in the print system
     *                                          caused the job to be aborted
     * @see java.awt.print.Book
     * @see java.awt.print.Pageable
     * @see java.awt.print.Printable
     */
    public void print() throws PrinterException {
        print(attributes);
    }

    public static boolean debugPrint = false;
    protected void debug_println(String str) {
        if (debugPrint) {
            System.out.println("RasterPrinterJob "+str+" "+this);
        }
    }

    public void print(PrintRequestAttributeSet attributes)
        throws PrinterException {

        /*
         * In the future PrinterJob will probably always dispatch
         * the print job to the PrintService.
         * This is how third party 2D Print Services will be invoked
         * when applications use the PrinterJob API.
         * However the JRE's concrete PrinterJob implementations have
         * not yet been re-worked to be implemented as standalone
         * services, and are implemented only as subclasses of PrinterJob.
         * So here we dispatch only those services we do not recognize
         * as implemented through platform subclasses of PrinterJob
         * (and this class).
         */
        PrintService psvc = getPrintService();
        debug_println("psvc = "+psvc);
        if (psvc == null) {
            throw new PrinterException("No print service found.");
        }

        // Check the list of services.  This service may have been
        // deleted already
        PrinterState prnState = psvc.getAttribute(PrinterState.class);
        if (prnState == PrinterState.STOPPED) {
            PrinterStateReasons prnStateReasons =
                    psvc.getAttribute(PrinterStateReasons.class);
                if ((prnStateReasons != null) &&
                    (prnStateReasons.containsKey(PrinterStateReason.SHUTDOWN)))
                {
                    throw new PrinterException("PrintService is no longer available.");
                }
        }

        if ((psvc.getAttribute(PrinterIsAcceptingJobs.class)) ==
                         PrinterIsAcceptingJobs.NOT_ACCEPTING_JOBS) {
            throw new PrinterException("Printer is not accepting job.");
        }

        /*
         * Check the default job-sheet value on underlying platform. If IPP
         * reports job-sheets=none, then honour that and modify noJobSheet since
         * by default, noJobSheet is false which mean jdk will print banner page.
         * This is because if "attributes" is null (if user directly calls print()
         * without specifying any attributes and without showing printdialog) then
         * setAttribute will return without changing noJobSheet value.
         * Also, we do this before setAttributes() call so as to allow the user
         * to override this via explicitly adding JobSheets attributes to
         * PrintRequestAttributeSet while calling print(attributes)
         */
        JobSheets js = (JobSheets)psvc.getDefaultAttributeValue(JobSheets.class);
        if (JobSheets.NONE.equals(js)) {
            noJobSheet = true;
        }

        if ((psvc instanceof SunPrinterJobService) &&
            ((SunPrinterJobService)psvc).usesClass(getClass())) {
            setAttributes(attributes);
            // throw exception for invalid destination
            if (destinationAttr != null) {
                validateDestination(destinationAttr);
            }
        } else {
            spoolToService(psvc, attributes);
            return;
        }
        /* We need to make sure that the collation and copies
         * settings are initialised */
        initPrinter();

        int numCollatedCopies = getCollatedCopies();
        int numNonCollatedCopies = getNoncollatedCopies();
        debug_println("getCollatedCopies()  "+numCollatedCopies
              + " getNoncollatedCopies() "+ numNonCollatedCopies);

        /* Get the range of pages we are to print. If the
         * last page to print is unknown, then we print to
         * the end of the document. Note that firstPage
         * and lastPage are 0 based page indices.
         */
        int numPages = mDocument.getNumberOfPages();
        if (numPages == 0) {
            return;
        }

        int firstPage = getFirstPage();
        int lastPage = getLastPage();
        if(lastPage == Pageable.UNKNOWN_NUMBER_OF_PAGES){
            int totalPages = mDocument.getNumberOfPages();
            if (totalPages != Pageable.UNKNOWN_NUMBER_OF_PAGES) {
                lastPage = mDocument.getNumberOfPages() - 1;
            }
        }

        try {
            synchronized (this) {
                performingPrinting = true;
                userCancelled = false;
            }

            startDoc();
            if (isCancelled()) {
                cancelDoc();
            }

            // PageRanges can be set even if RANGE is not selected
            // so we need to check if it is selected.
            boolean rangeIsSelected = true;
            if (attributes != null) {
                SunPageSelection pages =
                    (SunPageSelection)attributes.get(SunPageSelection.class);
                if ((pages != null) && (pages != SunPageSelection.RANGE)) {
                    rangeIsSelected = false;
                }
            }


            debug_println("after startDoc rangeSelected? "+rangeIsSelected
                      + " numNonCollatedCopies "+ numNonCollatedCopies);


            /* Three nested loops iterate over the document. The outer loop
             * counts the number of collated copies while the inner loop
             * counts the number of nonCollated copies. Normally, one of
             * these two loops will only execute once; that is we will
             * either print collated copies or noncollated copies. The
             * middle loop iterates over the pages.
             * If a PageRanges attribute is used, it constrains the pages
             * that are imaged. If a platform subclass (though a user dialog)
             * requests a page range via setPageRange(). it too can
             * constrain the page ranges that are imaged.
             * It is expected that only one of these will be used in a
             * job but both should be able to co-exist.
             */
            for(int collated = 0; collated < numCollatedCopies; collated++) {
                for(int i = firstPage, pageResult = Printable.PAGE_EXISTS;
                    (i <= lastPage ||
                     lastPage == Pageable.UNKNOWN_NUMBER_OF_PAGES)
                    && pageResult == Printable.PAGE_EXISTS;
                    i++)
                {

                    if ((pageRangesAttr != null) && rangeIsSelected ){
                        int nexti = pageRangesAttr.next(i);
                        if (nexti == -1) {
                            break;
                        } else if (nexti != i+1) {
                            continue;
                        }
                    }

                    for(int nonCollated = 0;
                        nonCollated < numNonCollatedCopies
                        && pageResult == Printable.PAGE_EXISTS;
                        nonCollated++)
                    {
                        if (isCancelled()) {
                            cancelDoc();
                        }
                        debug_println("printPage "+i);
                        pageResult = printPage(mDocument, i);

                    }
                }
            }

            if (isCancelled()) {
                cancelDoc();
            }

        } finally {
            // reset previousPaper in case this job is invoked again.
            previousPaper = null;
            synchronized (this) {
                if (performingPrinting) {
                    endDoc();
                }
                performingPrinting = false;
                notify();
            }
        }
    }

    protected void validateDestination(String dest) throws PrinterException {
        if (dest == null) {
            return;
        }
        // dest is null for Destination(new URI(""))
        // because isAttributeValueSupported returns false in setAttributes

        // Destination(new URI(" ")) throws URISyntaxException
        File f = new File(dest);
        try {
            // check if this is a new file and if filename chars are valid
            if (f.createNewFile()) {
                f.delete();
            }
        } catch (IOException ioe) {
            throw new PrinterException("Cannot write to file:"+
                                       dest);
        }

        File pFile = f.getParentFile();
        if ((f.exists() &&
             (!f.isFile() || !f.canWrite())) ||
            ((pFile != null) &&
             (!pFile.exists() || (pFile.exists() && !pFile.canWrite())))) {
            if (f.exists()) {
                f.delete();
            }
            throw new PrinterException("Cannot write to file:"+
                                       dest);
        }
    }

    /**
     * updates a Paper object to reflect the current printer's selected
     * paper size and imageable area for that paper size.
     * Default implementation copies settings from the original, applies
     * applies some validity checks, changes them only if they are
     * clearly unreasonable, then sets them into the new Paper.
     * Subclasses are expected to override this method to make more
     * informed decisions.
     */
    protected void validatePaper(Paper origPaper, Paper newPaper) {
        if (origPaper == null || newPaper == null) {
            return;
        } else {
            double wid = origPaper.getWidth();
            double hgt = origPaper.getHeight();
            double ix = origPaper.getImageableX();
            double iy = origPaper.getImageableY();
            double iw = origPaper.getImageableWidth();
            double ih = origPaper.getImageableHeight();

            /* Assume any +ve values are legal. Overall paper dimensions
             * take precedence. Make sure imageable area fits on the paper.
             */
            Paper defaultPaper = new Paper();
            wid = ((wid > 0.0) ? wid : defaultPaper.getWidth());
            hgt = ((hgt > 0.0) ? hgt : defaultPaper.getHeight());
            ix = ((ix > 0.0) ? ix : defaultPaper.getImageableX());
            iy = ((iy > 0.0) ? iy : defaultPaper.getImageableY());
            iw = ((iw > 0.0) ? iw : defaultPaper.getImageableWidth());
            ih = ((ih > 0.0) ? ih : defaultPaper.getImageableHeight());
            /* full width/height is not likely to be imageable, but since we
             * don't know the limits we have to allow it
             */
            if (iw > wid) {
                iw = wid;
            }
            if (ih > hgt) {
                ih = hgt;
            }
            if ((ix + iw) > wid) {
                ix = wid - iw;
            }
            if ((iy + ih) > hgt) {
                iy = hgt - ih;
            }
            newPaper.setSize(wid, hgt);
            newPaper.setImageableArea(ix, iy, iw, ih);
        }
    }

    /**
     * The passed in PageFormat will be copied and altered to describe
     * the default page size and orientation of the PrinterJob's
     * current printer.
     * Platform subclasses which can access the actual default paper size
     * for a printer may override this method.
     */
    public PageFormat defaultPage(PageFormat page) {
        PageFormat newPage = (PageFormat)page.clone();
        newPage.setOrientation(PageFormat.PORTRAIT);
        Paper newPaper = new Paper();
        double ptsPerInch = 72.0;
        double w, h;
        Media media = null;

        PrintService service = getPrintService();
        if (service != null) {
            MediaSize size;
            media =
                (Media)service.getDefaultAttributeValue(Media.class);

            if (media instanceof MediaSizeName &&
               ((size = MediaSize.getMediaSizeForName((MediaSizeName)media)) !=
                null)) {
                w =  size.getX(MediaSize.INCH) * ptsPerInch;
                h =  size.getY(MediaSize.INCH) * ptsPerInch;
                newPaper.setSize(w, h);
                newPaper.setImageableArea(ptsPerInch, ptsPerInch,
                                          w - 2.0*ptsPerInch,
                                          h - 2.0*ptsPerInch);
                newPage.setPaper(newPaper);
                return newPage;

            }
        }

        /* Default to A4 paper outside North America.
         */
        String defaultCountry = Locale.getDefault().getCountry();
        if (!Locale.getDefault().equals(Locale.ENGLISH) && // ie "C"
            defaultCountry != null &&
            !defaultCountry.equals(Locale.US.getCountry()) &&
            !defaultCountry.equals(Locale.CANADA.getCountry())) {

            double mmPerInch = 25.4;
            w = Math.rint((210.0*ptsPerInch)/mmPerInch);
            h = Math.rint((297.0*ptsPerInch)/mmPerInch);
            newPaper.setSize(w, h);
            newPaper.setImageableArea(ptsPerInch, ptsPerInch,
                                      w - 2.0*ptsPerInch,
                                      h - 2.0*ptsPerInch);
        }

        newPage.setPaper(newPaper);

        return newPage;
    }

    /**
     * The passed in PageFormat is cloned and altered to be usable on
     * the PrinterJob's current printer.
     */
    public PageFormat validatePage(PageFormat page) {
        PageFormat newPage = (PageFormat)page.clone();
        Paper newPaper = new Paper();
        validatePaper(newPage.getPaper(), newPaper);
        newPage.setPaper(newPaper);

        return newPage;
    }

    /**
     * Set the number of copies to be printed.
     */
    public void setCopies(int copies) {
        mNumCopies = copies;
    }

    /**
     * Get the number of copies to be printed.
     */
    public int getCopies() {
        return mNumCopies;
    }

   /* Used when executing a print job where an attribute set may
     * over ride API values.
     */
    protected int getCopiesInt() {
        return (copiesAttr > 0) ? copiesAttr : getCopies();
    }

    /**
     * Get the name of the printing user.
     */
    public String getUserName() {
        return System.getProperty("user.name");
    }

   /* Used when executing a print job where an attribute set may
     * over ride API values.
     */
    protected String getUserNameInt() {
        if  (userNameAttr != null) {
            return userNameAttr;
        } else {
            return getUserName();
        }
    }

    /**
     * Set the name of the document to be printed.
     * The document name can not be null.
     */
    public void setJobName(String jobName) {
        if (jobName != null) {
            mDocName = jobName;
        } else {
            throw new NullPointerException();
        }
    }

    /**
     * Get the name of the document to be printed.
     */
    public String getJobName() {
        return mDocName;
    }

    /* Used when executing a print job where an attribute set may
     * over ride API values.
     */
    protected String getJobNameInt() {
        return (jobNameAttr != null) ? jobNameAttr : getJobName();
    }

    /**
     * Set the range of pages from a Book to be printed.
     * Both 'firstPage' and 'lastPage' are zero based
     * page indices. If either parameter is less than
     * zero then the page range is set to be from the
     * first page to the last.
     */
    protected void setPageRange(int firstPage, int lastPage) {
        if(firstPage >= 0 && lastPage >= 0) {
            mFirstPage = firstPage;
            mLastPage = lastPage;
            if(mLastPage < mFirstPage) mLastPage = mFirstPage;
        } else {
            mFirstPage = Pageable.UNKNOWN_NUMBER_OF_PAGES;
            mLastPage = Pageable.UNKNOWN_NUMBER_OF_PAGES;
        }
    }

    /**
     * Return the zero based index of the first page to
     * be printed in this job.
     */
    protected int getFirstPage() {
        return mFirstPage == Book.UNKNOWN_NUMBER_OF_PAGES ? 0 : mFirstPage;
    }

    /**
     * Return the zero based index of the last page to
     * be printed in this job.
     */
    protected int getLastPage() {
        return mLastPage;
    }

    /**
     * Set whether copies should be collated or not.
     * Two collated copies of a three page document
     * print in this order: 1, 2, 3, 1, 2, 3 while
     * uncollated copies print in this order:
     * 1, 1, 2, 2, 3, 3.
     * This is set when request is using an attribute set.
     */
    protected void setCollated(boolean collate) {
        mCollate = collate;
        collateAttReq = true;
    }

    /**
     * Return true if collated copies will be printed as determined
     * in an attribute set.
     */
    protected boolean isCollated() {
            return mCollate;
    }

    protected final int getSelectAttrib() {
        if (attributes != null) {
            SunPageSelection pages =
                (SunPageSelection)attributes.get(SunPageSelection.class);
            if (pages == SunPageSelection.RANGE) {
                return PD_PAGENUMS;
            } else if (pages == SunPageSelection.SELECTION) {
                return PD_SELECTION;
            } else if (pages ==  SunPageSelection.ALL) {
                return PD_ALLPAGES;
            }
        }
        return PD_NOSELECTION;
    }

    //returns 1-based index for "From" page
    protected final int getFromPageAttrib() {
        if (attributes != null) {
            PageRanges pageRangesAttr =
                (PageRanges)attributes.get(PageRanges.class);
            if (pageRangesAttr != null) {
                int[][] range = pageRangesAttr.getMembers();
                return range[0][0];
            }
        }
        return getMinPageAttrib();
    }

    //returns 1-based index for "To" page
    protected final int getToPageAttrib() {
        if (attributes != null) {
            PageRanges pageRangesAttr =
                (PageRanges)attributes.get(PageRanges.class);
            if (pageRangesAttr != null) {
                int[][] range = pageRangesAttr.getMembers();
                return range[range.length-1][1];
            }
        }
        return getMaxPageAttrib();
    }

    protected final int getMinPageAttrib() {
        if (attributes != null) {
            SunMinMaxPage s =
                (SunMinMaxPage)attributes.get(SunMinMaxPage.class);
            if (s != null) {
                return s.getMin();
            }
        }
        return 1;
    }

    protected final int getMaxPageAttrib() {
        if (attributes != null) {
            SunMinMaxPage s =
                (SunMinMaxPage)attributes.get(SunMinMaxPage.class);
            if (s != null) {
                return s.getMax();
            }
        }

        Pageable pageable = getPageable();
        if (pageable != null) {
            int numPages = pageable.getNumberOfPages();
            if (numPages <= Pageable.UNKNOWN_NUMBER_OF_PAGES) {
                numPages = MAX_UNKNOWN_PAGES;
            }
            return  ((numPages == 0) ? 1 : numPages);
        }

        return Integer.MAX_VALUE;
    }
    /**
     * Called by the print() method at the start of
     * a print job.
     */
    protected abstract void startDoc() throws PrinterException;

    /**
     * Called by the print() method at the end of
     * a print job.
     */
    protected abstract void endDoc() throws PrinterException;

    /* Called by cancelDoc */
    protected abstract void abortDoc();

// MacOSX - made protected so subclasses can reference it.
    protected void cancelDoc() throws PrinterAbortException {
        abortDoc();
        synchronized (this) {
            userCancelled = false;
            performingPrinting = false;
            notify();
        }
        throw new PrinterAbortException();
    }

    /**
     * Returns how many times the entire book should
     * be printed by the PrintJob. If the printer
     * itself supports collation then this method
     * should return 1 indicating that the entire
     * book need only be printed once and the copies
     * will be collated and made in the printer.
     */
    protected int getCollatedCopies() {
        return isCollated() ? getCopiesInt() : 1;
    }

    /**
     * Returns how many times each page in the book
     * should be consecutively printed by PrintJob.
     * If the printer makes copies itself then this
     * method should return 1.
     */
    protected int getNoncollatedCopies() {
        return isCollated() ? 1 : getCopiesInt();
    }


    /* The printer graphics config is cached on the job, so that it can
     * be created once, and updated only as needed (for now only to change
     * the bounds if when using a Pageable the page sizes changes).
     */

    private int deviceWidth, deviceHeight;
    private AffineTransform defaultDeviceTransform;
    private PrinterGraphicsConfig pgConfig;

    protected synchronized void setGraphicsConfigInfo(AffineTransform at,
                                                      double pw, double ph) {
        Point2D.Double pt = new Point2D.Double(pw, ph);
        at.transform(pt, pt);

        if (pgConfig == null ||
            defaultDeviceTransform == null ||
            !at.equals(defaultDeviceTransform) ||
            deviceWidth != (int)pt.getX() ||
            deviceHeight != (int)pt.getY()) {

                deviceWidth = (int)pt.getX();
                deviceHeight = (int)pt.getY();
                defaultDeviceTransform = at;
                pgConfig = null;
        }
    }

    synchronized PrinterGraphicsConfig getPrinterGraphicsConfig() {
        if (pgConfig != null) {
            return pgConfig;
        }
        String deviceID = "Printer Device";
        PrintService service = getPrintService();
        if (service != null) {
            deviceID = service.toString();
        }
        pgConfig = new PrinterGraphicsConfig(deviceID,
                                             defaultDeviceTransform,
                                             deviceWidth, deviceHeight);
        return pgConfig;
    }

    /**
     * Print a page from the provided document.
     * @return int Printable.PAGE_EXISTS if the page existed and was drawn and
     *             Printable.NO_SUCH_PAGE if the page did not exist.
     * @see java.awt.print.Printable
     */
    protected int printPage(Pageable document, int pageIndex)
        throws PrinterException
    {
        PageFormat page;
        PageFormat origPage;
        Printable painter;
        try {
            origPage = document.getPageFormat(pageIndex);
            page = (PageFormat)origPage.clone();
            painter = document.getPrintable(pageIndex);
        } catch (Exception e) {
            PrinterException pe =
                    new PrinterException("Error getting page or printable.[ " +
                                          e +" ]");
            pe.initCause(e);
            throw pe;
        }

        /* Get the imageable area from Paper instead of PageFormat
         * because we do not want it adjusted by the page orientation.
         */
        Paper paper = page.getPaper();
        // if non-portrait and 270 degree landscape rotation
        if (page.getOrientation() != PageFormat.PORTRAIT &&
            landscapeRotates270) {

            double left = paper.getImageableX();
            double top = paper.getImageableY();
            double width = paper.getImageableWidth();
            double height = paper.getImageableHeight();
            paper.setImageableArea(paper.getWidth()-left-width,
                                   paper.getHeight()-top-height,
                                   width, height);
            page.setPaper(paper);
            if (page.getOrientation() == PageFormat.LANDSCAPE) {
                page.setOrientation(PageFormat.REVERSE_LANDSCAPE);
            } else {
                page.setOrientation(PageFormat.LANDSCAPE);
            }
        }

        double xScale = getXRes() / 72.0;
        double yScale = getYRes() / 72.0;

        /* The deviceArea is the imageable area in the printer's
         * resolution.
         */
        Rectangle2D deviceArea =
            new Rectangle2D.Double(paper.getImageableX() * xScale,
                                   paper.getImageableY() * yScale,
                                   paper.getImageableWidth() * xScale,
                                   paper.getImageableHeight() * yScale);

        /* Build and hold on to a uniform transform so that
         * we can get back to device space at the beginning
         * of each band.
         */
        AffineTransform uniformTransform = new AffineTransform();

        /* The scale transform is used to switch from the
         * device space to the user's 72 dpi space.
         */
        AffineTransform scaleTransform = new AffineTransform();
        scaleTransform.scale(xScale, yScale);

        /* bandwidth is multiple of 4 as the data is used in a win32 DIB and
         * some drivers behave badly if scanlines aren't multiples of 4 bytes.
         */
        int bandWidth = (int) deviceArea.getWidth();
        if (bandWidth % 4 != 0) {
            bandWidth += (4 - (bandWidth % 4));
        }
        if (bandWidth <= 0) {
            throw new PrinterException("Paper's imageable width is too small.");
        }

        int deviceAreaHeight = (int)deviceArea.getHeight();
        if (deviceAreaHeight <= 0) {
            throw new PrinterException("Paper's imageable height is too small.");
        }

        /* Figure out the number of lines that will fit into
         * our maximum band size. The hard coded 3 reflects the
         * fact that we can only create 24 bit per pixel 3 byte BGR
         * BufferedImages. FIX.
         */
        int bandHeight = (MAX_BAND_SIZE / bandWidth / 3);

        int deviceLeft = (int)Math.rint(paper.getImageableX() * xScale);
        int deviceTop  = (int)Math.rint(paper.getImageableY() * yScale);

        /* The device transform is used to move the band down
         * the page using translates. Normally this is all it
         * would do, but since, when printing, the Window's
         * DIB format wants the last line to be first (lowest) in
         * memory, the deviceTransform moves the origin to the
         * bottom of the band and flips the origin. This way the
         * app prints upside down into the band which is the DIB
         * format.
         */
        AffineTransform deviceTransform = new AffineTransform();
        deviceTransform.translate(-deviceLeft, deviceTop);
        deviceTransform.translate(0, bandHeight);
        deviceTransform.scale(1, -1);

        /* Create a BufferedImage to hold the band. We set the clip
         * of the band to be tight around the bits so that the
         * application can use it to figure what part of the
         * page needs to be drawn. The clip is never altered in
         * this method, but we do translate the band's coordinate
         * system so that the app will see the clip moving down the
         * page though it s always around the same set of pixels.
         */
        BufferedImage pBand = new BufferedImage(1, 1,
                                                BufferedImage.TYPE_3BYTE_BGR);

        /* Have the app draw into a PeekGraphics object so we can
         * learn something about the needs of the print job.
         */

        PeekGraphics peekGraphics = createPeekGraphics(pBand.createGraphics(),
                                                       this);

        Rectangle2D.Double pageFormatArea =
            new Rectangle2D.Double(page.getImageableX(),
                                   page.getImageableY(),
                                   page.getImageableWidth(),
                                   page.getImageableHeight());
        peekGraphics.transform(scaleTransform);
        peekGraphics.translate(-getPhysicalPrintableX(paper) / xScale,
                               -getPhysicalPrintableY(paper) / yScale);
        peekGraphics.transform(new AffineTransform(page.getMatrix()));
        initPrinterGraphics(peekGraphics, pageFormatArea);
        AffineTransform pgAt = peekGraphics.getTransform();

        /* Update the information used to return a GraphicsConfiguration
         * for this printer device. It needs to be updated per page as
         * not all pages in a job may be the same size (different bounds)
         * The transform is the scaling transform as this corresponds to
         * the default transform for the device. The width and height are
         * those of the paper, not the page format, as we want to describe
         * the bounds of the device in its natural coordinate system of
         * device coordinate whereas a page format may be in a rotated context.
         */
        setGraphicsConfigInfo(scaleTransform,
                              paper.getWidth(), paper.getHeight());
        int pageResult = painter.print(peekGraphics, origPage, pageIndex);
        debug_println("pageResult "+pageResult);
        if (pageResult == Printable.PAGE_EXISTS) {
            debug_println("startPage "+pageIndex);

            /* We need to check if the paper size is changed.
             * Note that it is not sufficient to ask for the pageformat
             * of "pageIndex-1", since PageRanges mean that pages can be
             * skipped. So we have to look at the actual last paper size used.
             */
            Paper thisPaper = page.getPaper();
            boolean paperChanged =
                previousPaper == null ||
                thisPaper.getWidth() != previousPaper.getWidth() ||
                thisPaper.getHeight() != previousPaper.getHeight();
            previousPaper = thisPaper;

            startPage(page, painter, pageIndex, paperChanged);
            Graphics2D pathGraphics = createPathGraphics(peekGraphics, this,
                                                         painter, page,
                                                         pageIndex);

            /* If we can convert the page directly to the
             * underlying graphics system then we do not
             * need to rasterize. We also may not need to
             * create the 'band' if all the pages can take
             * this path.
             */
            if (pathGraphics != null) {
                pathGraphics.transform(scaleTransform);
                // user (0,0) should be origin of page, not imageable area
                pathGraphics.translate(-getPhysicalPrintableX(paper) / xScale,
                                       -getPhysicalPrintableY(paper) / yScale);
                pathGraphics.transform(new AffineTransform(page.getMatrix()));
                initPrinterGraphics(pathGraphics, pageFormatArea);

                redrawList.clear();

                AffineTransform initialTx = pathGraphics.getTransform();

                painter.print(pathGraphics, origPage, pageIndex);

                for (int i=0;i<redrawList.size();i++) {
                   GraphicsState gstate = redrawList.get(i);
                   pathGraphics.setTransform(initialTx);
                   ((PathGraphics)pathGraphics).redrawRegion(
                                                         gstate.region,
                                                         gstate.sx,
                                                         gstate.sy,
                                                         gstate.theClip,
                                                         gstate.theTransform);
                }

            /* This is the banded-raster printing loop.
             * It should be moved into its own method.
             */
            } else {
                BufferedImage band = cachedBand;
                if (cachedBand == null ||
                    bandWidth != cachedBandWidth ||
                    bandHeight != cachedBandHeight) {
                    band = new BufferedImage(bandWidth, bandHeight,
                                             BufferedImage.TYPE_3BYTE_BGR);
                    cachedBand = band;
                    cachedBandWidth = bandWidth;
                    cachedBandHeight = bandHeight;
                }
                Graphics2D bandGraphics = band.createGraphics();

                Rectangle2D.Double clipArea =
                    new Rectangle2D.Double(0, 0, bandWidth, bandHeight);

                initPrinterGraphics(bandGraphics, clipArea);

                ProxyGraphics2D painterGraphics =
                    new ProxyGraphics2D(bandGraphics, this);

                Graphics2D clearGraphics = band.createGraphics();
                clearGraphics.setColor(Color.white);

                /* We need the actual bits of the BufferedImage to send to
                 * the native Window's code. 'data' points to the actual
                 * pixels. Right now these are in ARGB format with 8 bits
                 * per component. We need to use a monochrome BufferedImage
                 * for monochrome printers when this is supported by
                 * BufferedImage. FIX
                 */
                ByteInterleavedRaster tile = (ByteInterleavedRaster)band.getRaster();
                byte[] data = tile.getDataStorage();

                /* Loop over the page moving our band down the page,
                 * calling the app to render the band, and then send the band
                 * to the printer.
                 */
                int deviceBottom = deviceTop + deviceAreaHeight;

                /* device's printable x,y is really addressable origin
                 * we address relative to media origin so when we print a
                 * band we need to adjust for the different methods of
                 * addressing it.
                 */
                int deviceAddressableX = (int)getPhysicalPrintableX(paper);
                int deviceAddressableY = (int)getPhysicalPrintableY(paper);

                for (int bandTop = 0; bandTop <= deviceAreaHeight;
                     bandTop += bandHeight)
                {

                    /* Put the band back into device space and
                     * erase the contents of the band.
                     */
                    clearGraphics.fillRect(0, 0, bandWidth, bandHeight);

                    /* Put the band into the correct location on the
                     * page. Once the band is moved we translate the
                     * device transform so that the band will move down
                     * the page on the next iteration of the loop.
                     */
                    bandGraphics.setTransform(uniformTransform);
                    bandGraphics.translate(-deviceAddressableX, deviceAddressableY);
                    bandGraphics.transform(deviceTransform);
                    deviceTransform.translate(0, -bandHeight);

                    /* Switch the band from device space to user,
                     * 72 dpi, space.
                     */
                    bandGraphics.transform(scaleTransform);
                    bandGraphics.transform(new AffineTransform(page.getMatrix()));

                    Rectangle clip = bandGraphics.getClipBounds();
                    clip = pgAt.createTransformedShape(clip).getBounds();

                    if ((clip == null) || peekGraphics.hitsDrawingArea(clip) &&
                        (bandWidth > 0 && bandHeight > 0)) {

                        /* if the client has specified an imageable X or Y
                         * which is off than the physically addressable
                         * area of the page, then we need to adjust for that
                         * here so that we pass only non -ve band coordinates
                         * We also need to translate by the adjusted amount
                         * so that printing appears in the correct place.
                         */
                        int bandX = deviceLeft;
                        if (bandX < 0) {
                            bandGraphics.translate(bandX/xScale,0);
                            bandX = 0;
                        }
                        int bandY = deviceTop;
                        if (bandY < 0) {
                            bandGraphics.translate(0,bandY/yScale);
                            bandY = 0;
                        }
                        /* Have the app's painter image into the band
                         * and then send the band to the printer.
                         */
                        painterGraphics.setDelegate((Graphics2D) bandGraphics.create());
                        painter.print(painterGraphics, origPage, pageIndex);
                        painterGraphics.dispose();
                        printBand(data, bandX, bandTop + bandY, bandWidth, bandHeight);
                    }
                }

                clearGraphics.dispose();
                bandGraphics.dispose();

            }
            debug_println("calling endPage "+pageIndex);
            endPage(page, painter, pageIndex);
        }

        return pageResult;
    }

    /**
     * If a print job is in progress, print() has been
     * called but has not returned, then this signals
     * that the job should be cancelled and the next
     * chance. If there is no print job in progress then
     * this call does nothing.
     */
    public void cancel() {
        synchronized (this) {
            if (performingPrinting) {
                userCancelled = true;
            }
            notify();
        }
    }

    @Override
    public boolean isCancelled() {

        boolean cancelled = false;

        synchronized (this) {
            cancelled = (performingPrinting && userCancelled);
            notify();
        }

        return cancelled;
    }

    /**
     * Return the Pageable describing the pages to be printed.
     */
    protected Pageable getPageable() {
        return mDocument;
    }

    /**
     * Examine the metrics captured by the
     * {@code PeekGraphics} instance and
     * if capable of directly converting this
     * print job to the printer's control language
     * or the native OS's graphics primitives, then
     * return a {@code PathGraphics} to perform
     * that conversion. If there is not an object
     * capable of the conversion then return
     * {@code null}. Returning {@code null}
     * causes the print job to be rasterized.
     */
    protected Graphics2D createPathGraphics(PeekGraphics graphics,
                                            PrinterJob printerJob,
                                            Printable painter,
                                            PageFormat pageFormat,
                                            int pageIndex) {

        return null;
    }

    /**
     * Create and return an object that will
     * gather and hold metrics about the print
     * job. This method is passed a {@code Graphics2D}
     * object that can be used as a proxy for the
     * object gathering the print job matrics. The
     * method is also supplied with the instance
     * controlling the print job, {@code printerJob}.
     */
    protected PeekGraphics createPeekGraphics(Graphics2D graphics,
                                              PrinterJob printerJob) {

        return new PeekGraphics(graphics, printerJob);
    }

    /**
     * Configure the passed in Graphics2D so that
     * is contains the defined initial settings
     * for a print job. These settings are:
     *      color:  black.
     *      clip:   <as passed in>
     */
// MacOSX - made protected so subclasses can reference it.
    protected void initPrinterGraphics(Graphics2D g, Rectangle2D clip) {

        g.setClip(clip);
        g.setPaint(Color.black);
    }

    /* On-screen drawString renders most control chars as the missing glyph
     * and have the non-zero advance of that glyph.
     * Exceptions are \t, \n and \r which are considered zero-width.
     * This is a utility method used by subclasses to remove them so we
     * don't have to worry about platform or font specific handling of them.
     */
    protected String removeControlChars(String s) {
        char[] in_chars = s.toCharArray();
        int len = in_chars.length;
        char[] out_chars = new char[len];
        int pos = 0;

        for (int i = 0; i < len; i++) {
            char c = in_chars[i];
            if (!isIgnorableWhitespace(c)) {
               out_chars[pos++] = c;
            }
        }
        if (pos == len) {
            return s; // no need to make a new String.
        } else {
            return new String(out_chars, 0, pos);
        }
    }

    private DialogOwner onTop = null;

    private long parentWindowID = 0L;

    /* Called from native code */
    private long getParentWindowID() {
        return parentWindowID;
    }

    private void clearParentWindowID() {
        parentWindowID = 0L;
        onTop = null;
    }

    private void setParentWindowID(PrintRequestAttributeSet attrs) {
        parentWindowID = 0L;
        onTop = (DialogOwner)attrs.get(DialogOwner.class);
        if (onTop != null) {
            parentWindowID = DialogOwnerAccessor.getID(onTop);
        }
    }

    protected String getOutputBinValue(Attribute attr) {
        if (attr instanceof CustomOutputBin customOutputBin) {
            return customOutputBin.getChoiceName();
        } else if (attr instanceof OutputBin) {
            PrintService ps = getPrintService();
            if (ps == null) {
                return null;
            }
            String name = attr.toString();
            OutputBin[] outputBins = (OutputBin[]) ps
                    .getSupportedAttributeValues(OutputBin.class, null, null);
            for (OutputBin outputBin : outputBins) {
                String choice = ((CustomOutputBin) outputBin).getChoiceName();
                if (name.equalsIgnoreCase(choice) || name.replaceAll("-", "").equalsIgnoreCase(choice)) {
                    return choice;
                }
            }
            return null;
        }
        return null;
    }
}
