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 = (GraphicsState)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.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 - deviceAddressableX; if (bandX < 0) { bandGraphics.translate(bandX/xScale,0); bandX = 0; } int bandY = deviceTop + bandTop - deviceAddressableY; 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, 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(); } } /** * Returns true is a print job is ongoing but will * be cancelled and the next opportunity. false is * returned otherwise. */ 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</code> 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</code> to perform * that conversion. If there is not an object * capable of the conversion then return * <code>null</code>. Returning <code>null</code> * 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</code> * 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</code>. */ 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> */ void initPrinterGraphics(Graphics2D g, Rectangle2D clip) { g.setClip(clip); g.setPaint(Color.black); } /** * User dialogs should disable "File" buttons if this returns false. * */ public boolean checkAllowedToPrintToFile() { try { throwPrintToFile(); return true; } catch (SecurityException e) { return false; } } /** * Break this out as it may be useful when we allow API to * specify printing to a file. In that case its probably right * to throw a SecurityException if the permission is not granted */ private void throwPrintToFile() { SecurityManager security = System.getSecurityManager(); if (security != null) { if (printToFilePermission == null) { printToFilePermission = new FilePermission("<<ALL FILES>>", "read,write"); } security.checkPermission(printToFilePermission); } } /* 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 (c > '\r' || c < '\t' || c == '\u000b' || c == '\u000c') { out_chars[pos++] = c; } } if (pos == len) { return s; // no need to make a new String. } else { return new String(out_chars, 0, pos); } }}Lines 2001–2283 of 2283. Previous lines
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 = (GraphicsState)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.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 - deviceAddressableX; if (bandX < 0) { bandGraphics.translate(bandX/xScale,0); bandX = 0; } int bandY = deviceTop + bandTop - deviceAddressableY; 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, 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(); } } /** * Returns true is a print job is ongoing but will * be cancelled and the next opportunity. false is * returned otherwise. */ 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</code> 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</code> to perform * that conversion. If there is not an object * capable of the conversion then return * <code>null</code>. Returning <code>null</code> * 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</code> * 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</code>. */ 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> */ void initPrinterGraphics(Graphics2D g, Rectangle2D clip) { g.setClip(clip); g.setPaint(Color.black); } /** * User dialogs should disable "File" buttons if this returns false. * */ public boolean checkAllowedToPrintToFile() { try { throwPrintToFile(); return true; } catch (SecurityException e) { return false; } } /** * Break this out as it may be useful when we allow API to * specify printing to a file. In that case its probably right * to throw a SecurityException if the permission is not granted */ private void throwPrintToFile() { SecurityManager security = System.getSecurityManager(); if (security != null) { if (printToFilePermission == null) { printToFilePermission = new FilePermission("<<ALL FILES>>", "read,write"); } security.checkPermission(printToFilePermission); } } /* 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 (c > '\r' || c < '\t' || c == '\u000b' || c == '\u000c') { out_chars[pos++] = c; } } if (pos == len) { return s; // no need to make a new String. } else { return new String(out_chars, 0, pos); } } }