gt:            if (services.length > 0) {
context: /*
   * Copyright (c) 1998, 2014, 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.io.FilePermission;
  
  import java.awt.Color;
  import java.awt.Dialog;
  import java.awt.Frame;
  import java.awt.Graphics;
  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.Area;
  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.Enumeration;
  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.Size2DSyntax;
  import javax.print.attribute.standard.Chromaticity;
  import javax.print.attribute.standard.Copies;
  import javax.print.attribute.standard.Destination;
  import javax.print.attribute.standard.DialogTypeSelection;
  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.PageRanges;
  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 sun.print.PageableDoc;
  import sun.print.ServiceDialog;
  import sun.print.SunPrinterJobService;
  import sun.print.SunPageSelection;
  
  /**
   * 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 = java.security.AccessController.doPrivileged(
                     new sun.security.action.GetPropertyAction(FORCE_PIPE_PROP));
  
          if (forceStr != null) {
              if (forceStr.equalsIgnoreCase(FORCE_PDL)) {
                  forcePDL = true;
              } else if (forceStr.equalsIgnoreCase(FORCE_RASTER)) {
                  forceRaster = true;
              }
          }
  
          String shapeTextStr =java.security.AccessController.doPrivileged(
                     new sun.security.action.GetPropertyAction(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;
  
     /**
      * Print to file permission variables.
      */
      private FilePermission printToFilePermission;
  
      /**
       * 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 Sides sidesAttr;
      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 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.
       */
      abstract protected double getXRes();
  
      /**
       * Returns the resolution in dots per inch down the height
       * of the page.
       */
      abstract protected double getYRes();
  
      /**
       * Must be obtained from the current printer.
       * Value is in device pixels.
       * Not adjusted for orientation of the paper.
       */
      abstract protected double getPhysicalPrintableX(Paper p);
  
      /**
       * Must be obtained from the current printer.
       * Value is in device pixels.
       * Not adjusted for orientation of the paper.
       */
      abstract protected double getPhysicalPrintableY(Paper p);
  
      /**
       * Must be obtained from the current printer.
       * Value is in device pixels.
       * Not adjusted for orientation of the paper.
       */
      abstract protected double getPhysicalPrintableWidth(Paper p);
  
      /**
       * Must be obtained from the current printer.
       * Value is in device pixels.
       * Not adjusted for orientation of the paper.
       */
      abstract protected double getPhysicalPrintableHeight(Paper p);
  
      /**
       * Must be obtained from the current printer.
       * Value is in device pixels.
       * Not adjusted for orientation of the paper.
       */
      abstract protected double getPhysicalPageWidth(Paper p);
  
      /**
       * Must be obtained from the current printer.
       * Value is in device pixels.
       * Not adjusted for orientation of the paper.
       */
      abstract protected double getPhysicalPageHeight(Paper p);
  
      /**
       * Begin a new page.
       */
      abstract protected void startPage(PageFormat format, Printable painter,
                                        int index, boolean paperChanged)
          throws PrinterException;
  
      /**
       * End a page.
       */
      abstract protected 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.
       */
      abstract protected 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</code>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);
  