scaleFactor *= 2; dpi /= 2; nbytes /= 4; } if (dpi < minDpi) { scaleFactor = (origDpi / minDpi); } region.setRect(region.getX()/scaleFactor, region.getY()/scaleFactor, region.getWidth()/scaleFactor, region.getHeight()/scaleFactor); /* * We need to have the clip as part of the saved state, * either directly, or all the components that are * needed to reconstitute it (image source area, * image transform and current graphics transform). * The clip is described in user space, so we need to * save the current graphics transform anyway so just * save these two. */ psPrinterJob.saveState(getTransform(), getClip(), region, scaleFactor, scaleFactor); return true; /* The image can be rendered directly by PS so we * copy it into a BufferedImage (this takes care of * ColorSpace and BufferedImageOp issues) and then * send that to PS. */ } else { /* Create a buffered image big enough to hold the portion * of the source image being printed. */ BufferedImage deepImage = new BufferedImage( (int) rotBounds.getWidth(), (int) rotBounds.getHeight(), BufferedImage.TYPE_3BYTE_BGR); /* Setup a Graphics2D on to the BufferedImage so that the * source image when copied, lands within the image buffer. */ Graphics2D imageGraphics = deepImage.createGraphics(); imageGraphics.clipRect(0, 0, deepImage.getWidth(), deepImage.getHeight()); imageGraphics.translate(-rotBounds.getX(), -rotBounds.getY()); imageGraphics.transform(rotTransform); /* Fill the BufferedImage either with the caller supplied * color, 'bgColor' or, if null, with white. */ if (bgcolor == null) { bgcolor = Color.white; } /* REMIND: no need to use scaling here. */ imageGraphics.drawImage(img, srcX, srcY, srcX + srcWidth, srcY + srcHeight, srcX, srcY, srcX + srcWidth, srcY + srcHeight, bgcolor, null); /* In PSPrinterJob images are printed in device space * and therefore we need to set a device space clip. * FIX: this is an overly tight coupling of these * two classes. * The temporary clip set needs to be an intersection * with the previous user clip. * REMIND: two xfms may lose accuracy in clip path. */ Shape holdClip = getClip(); Shape oldClip = getTransform().createTransformedShape(holdClip); AffineTransform sat = AffineTransform.getScaleInstance( scaleX, scaleY); Shape imgClip = sat.createTransformedShape(rotShape); Area imgArea = new Area(imgClip); Area oldArea = new Area(oldClip); imgArea.intersect(oldArea); psPrinterJob.setClip(imgArea); /* Scale the bounding rectangle by the scale transform. * Because the scaling transform has only x and y * scaling components it is equivalent to multiply * the x components of the bounding rectangle by * the x scaling factor and to multiply the y components * by the y scaling factor. */ Rectangle2D.Float scaledBounds = new Rectangle2D.Float( (float) (rotBounds.getX() * scaleX), (float) (rotBounds.getY() * scaleY), (float) (rotBounds.getWidth() * scaleX), (float) (rotBounds.getHeight() * scaleY)); /* Pull the raster data from the buffered image * and pass it along to PS. */ ByteComponentRaster tile = (ByteComponentRaster)deepImage.getRaster(); psPrinterJob.drawImageBGR(tile.getDataStorage(), scaledBounds.x, scaledBounds.y, (float)Math.rint(scaledBounds.width+0.5), (float)Math.rint(scaledBounds.height+0.5), 0f, 0f, deepImage.getWidth(), deepImage.getHeight(), deepImage.getWidth(), deepImage.getHeight()); /* Reset the device clip to match user clip */ psPrinterJob.setClip( getTransform().createTransformedShape(holdClip)); imageGraphics.dispose(); } } } return true; } /** Redraw a rectanglular area using a proxy graphics * To do this we need to know the rectangular area to redraw and * the transform & clip in effect at the time of the original drawImage * */ public void redrawRegion(Rectangle2D region, double scaleX, double scaleY, Shape savedClip, AffineTransform savedTransform) throws PrinterException { PSPrinterJob psPrinterJob = (PSPrinterJob)getPrinterJob(); Printable painter = getPrintable(); PageFormat pageFormat = getPageFormat(); int pageIndex = getPageIndex(); /* Create a buffered image big enough to hold the portion * of the source image being printed. */ BufferedImage deepImage = new BufferedImage( (int) region.getWidth(), (int) region.getHeight(), BufferedImage.TYPE_3BYTE_BGR); /* Get a graphics for the application to render into. * We initialize the buffer to white in order to * match the paper and then we shift the BufferedImage * so that it covers the area on the page where the * caller's Image will be drawn. */ Graphics2D g = deepImage.createGraphics(); ProxyGraphics2D proxy = new ProxyGraphics2D(g, psPrinterJob); proxy.setColor(Color.white); proxy.fillRect(0, 0, deepImage.getWidth(), deepImage.getHeight()); proxy.clipRect(0, 0, deepImage.getWidth(), deepImage.getHeight()); proxy.translate(-region.getX(), -region.getY()); /* Calculate the resolution of the source image. */ float sourceResX = (float)(psPrinterJob.getXRes() / scaleX); float sourceResY = (float)(psPrinterJob.getYRes() / scaleY); /* The application expects to see user space at 72 dpi. * so change user space from image source resolution to * 72 dpi. */ proxy.scale(sourceResX / DEFAULT_USER_RES, sourceResY / DEFAULT_USER_RES); proxy.translate( -psPrinterJob.getPhysicalPrintableX(pageFormat.getPaper()) / psPrinterJob.getXRes() * DEFAULT_USER_RES, -psPrinterJob.getPhysicalPrintableY(pageFormat.getPaper()) / psPrinterJob.getYRes() * DEFAULT_USER_RES); /* NB User space now has to be at 72 dpi for this calc to be correct */ proxy.transform(new AffineTransform(getPageFormat().getMatrix())); proxy.setPaint(Color.black); painter.print(proxy, pageFormat, pageIndex); g.dispose(); /* In PSPrinterJob images are printed in device space * and therefore we need to set a device space clip. */ psPrinterJob.setClip(savedTransform.createTransformedShape(savedClip)); /* Scale the bounding rectangle by the scale transform. * Because the scaling transform has only x and y * scaling components it is equivalent to multiply * the x components of the bounding rectangle by * the x scaling factor and to multiply the y components * by the y scaling factor. */ Rectangle2D.Float scaledBounds = new Rectangle2D.Float( (float) (region.getX() * scaleX), (float) (region.getY() * scaleY), (float) (region.getWidth() * scaleX), (float) (region.getHeight() * scaleY)); /* Pull the raster data from the buffered image * and pass it along to PS. */ ByteComponentRaster tile = (ByteComponentRaster)deepImage.getRaster(); psPrinterJob.drawImageBGR(tile.getDataStorage(), scaledBounds.x, scaledBounds.y, scaledBounds.width, scaledBounds.height, 0f, 0f, deepImage.getWidth(), deepImage.getHeight(), deepImage.getWidth(), deepImage.getHeight()); } /* * Fill the path defined by <code>pathIter</code> * with the specified color. * The path is provided in current user space. */ protected void deviceFill(PathIterator pathIter, Color color) { PSPrinterJob psPrinterJob = (PSPrinterJob) getPrinterJob(); psPrinterJob.deviceFill(pathIter, color, getTransform(), getClip()); } /* * Draw the bounding rectangle using path by calling draw() * function and passing a rectangle shape. */ protected void deviceFrameRect(int x, int y, int width, int height, Color color) { draw(new Rectangle2D.Float(x, y, width, height)); } /* * Draw a line using path by calling draw() function and passing * a line shape. */ protected void deviceDrawLine(int xBegin, int yBegin, int xEnd, int yEnd, Color color) { draw(new Line2D.Float(xBegin, yBegin, xEnd, yEnd)); } /* * Fill the rectangle with the specified color by calling fill(). */ protected void deviceFillRect(int x, int y, int width, int height, Color color) { fill(new Rectangle2D.Float(x, y, width, height)); } /* * This method should not be invoked by PSPathGraphics. * FIX: Rework PathGraphics so that this method is * not an abstract method there. */ protected void deviceClip(PathIterator pathIter) { } }Lines 501–780 of 780. Previous lines
scaleFactor *= 2; dpi /= 2; nbytes /= 4; } if (dpi < minDpi) { scaleFactor = (origDpi / minDpi); } region.setRect(region.getX()/scaleFactor, region.getY()/scaleFactor, region.getWidth()/scaleFactor, region.getHeight()/scaleFactor); /* * We need to have the clip as part of the saved state, * either directly, or all the components that are * needed to reconstitute it (image source area, * image transform and current graphics transform). * The clip is described in user space, so we need to * save the current graphics transform anyway so just * save these two. */ psPrinterJob.saveState(getTransform(), getClip(), region, scaleFactor, scaleFactor); return true; /* The image can be rendered directly by PS so we * copy it into a BufferedImage (this takes care of * ColorSpace and BufferedImageOp issues) and then * send that to PS. */ } else { /* Create a buffered image big enough to hold the portion * of the source image being printed. */ BufferedImage deepImage = new BufferedImage( (int) rotBounds.getWidth(), (int) rotBounds.getHeight(), BufferedImage.TYPE_3BYTE_BGR); /* Setup a Graphics2D on to the BufferedImage so that the * source image when copied, lands within the image buffer. */ Graphics2D imageGraphics = deepImage.createGraphics(); imageGraphics.clipRect(0, 0, deepImage.getWidth(), deepImage.getHeight()); imageGraphics.translate(-rotBounds.getX(), -rotBounds.getY()); imageGraphics.transform(rotTransform); /* Fill the BufferedImage either with the caller supplied * color, 'bgColor' or, if null, with white. */ if (bgcolor == null) { bgcolor = Color.white; } /* REMIND: no need to use scaling here. */ imageGraphics.drawImage(img, srcX, srcY, srcX + srcWidth, srcY + srcHeight, srcX, srcY, srcX + srcWidth, srcY + srcHeight, bgcolor, null); /* In PSPrinterJob images are printed in device space * and therefore we need to set a device space clip. * FIX: this is an overly tight coupling of these * two classes. * The temporary clip set needs to be an intersection * with the previous user clip. * REMIND: two xfms may lose accuracy in clip path. */ Shape holdClip = getClip(); Shape oldClip = getTransform().createTransformedShape(holdClip); AffineTransform sat = AffineTransform.getScaleInstance( scaleX, scaleY); Shape imgClip = sat.createTransformedShape(rotShape); Area imgArea = new Area(imgClip); Area oldArea = new Area(oldClip); imgArea.intersect(oldArea); psPrinterJob.setClip(imgArea); /* Scale the bounding rectangle by the scale transform. * Because the scaling transform has only x and y * scaling components it is equivalent to multiply * the x components of the bounding rectangle by * the x scaling factor and to multiply the y components * by the y scaling factor. */ Rectangle2D.Float scaledBounds = new Rectangle2D.Float( (float) (rotBounds.getX() * scaleX), (float) (rotBounds.getY() * scaleY), (float) (rotBounds.getWidth() * scaleX), (float) (rotBounds.getHeight() * scaleY)); /* Pull the raster data from the buffered image * and pass it along to PS. */ ByteComponentRaster tile = (ByteComponentRaster)deepImage.getRaster(); psPrinterJob.drawImageBGR(tile.getDataStorage(), scaledBounds.x, scaledBounds.y, (float)Math.rint(scaledBounds.width+0.5), (float)Math.rint(scaledBounds.height+0.5), 0f, 0f, deepImage.getWidth(), deepImage.getHeight(), deepImage.getWidth(), deepImage.getHeight()); /* Reset the device clip to match user clip */ psPrinterJob.setClip( getTransform().createTransformedShape(holdClip)); imageGraphics.dispose(); } } } return true; } /** Redraw a rectanglular area using a proxy graphics * To do this we need to know the rectangular area to redraw and * the transform & clip in effect at the time of the original drawImage * */ public void redrawRegion(Rectangle2D region, double scaleX, double scaleY, Shape savedClip, AffineTransform savedTransform) throws PrinterException { PSPrinterJob psPrinterJob = (PSPrinterJob)getPrinterJob(); Printable painter = getPrintable(); PageFormat pageFormat = getPageFormat(); int pageIndex = getPageIndex(); /* Create a buffered image big enough to hold the portion * of the source image being printed. */ BufferedImage deepImage = new BufferedImage( (int) region.getWidth(), (int) region.getHeight(), BufferedImage.TYPE_3BYTE_BGR); /* Get a graphics for the application to render into. * We initialize the buffer to white in order to * match the paper and then we shift the BufferedImage * so that it covers the area on the page where the * caller's Image will be drawn. */ Graphics2D g = deepImage.createGraphics(); ProxyGraphics2D proxy = new ProxyGraphics2D(g, psPrinterJob); proxy.setColor(Color.white); proxy.fillRect(0, 0, deepImage.getWidth(), deepImage.getHeight()); proxy.clipRect(0, 0, deepImage.getWidth(), deepImage.getHeight()); proxy.translate(-region.getX(), -region.getY()); /* Calculate the resolution of the source image. */ float sourceResX = (float)(psPrinterJob.getXRes() / scaleX); float sourceResY = (float)(psPrinterJob.getYRes() / scaleY); /* The application expects to see user space at 72 dpi. * so change user space from image source resolution to * 72 dpi. */ proxy.scale(sourceResX / DEFAULT_USER_RES, sourceResY / DEFAULT_USER_RES); proxy.translate( -psPrinterJob.getPhysicalPrintableX(pageFormat.getPaper()) / psPrinterJob.getXRes() * DEFAULT_USER_RES, -psPrinterJob.getPhysicalPrintableY(pageFormat.getPaper()) / psPrinterJob.getYRes() * DEFAULT_USER_RES); /* NB User space now has to be at 72 dpi for this calc to be correct */ proxy.transform(new AffineTransform(getPageFormat().getMatrix())); proxy.setPaint(Color.black); painter.print(proxy, pageFormat, pageIndex); g.dispose(); /* In PSPrinterJob images are printed in device space * and therefore we need to set a device space clip. */ psPrinterJob.setClip(savedTransform.createTransformedShape(savedClip)); /* Scale the bounding rectangle by the scale transform. * Because the scaling transform has only x and y * scaling components it is equivalent to multiply * the x components of the bounding rectangle by * the x scaling factor and to multiply the y components * by the y scaling factor. */ Rectangle2D.Float scaledBounds = new Rectangle2D.Float( (float) (region.getX() * scaleX), (float) (region.getY() * scaleY), (float) (region.getWidth() * scaleX), (float) (region.getHeight() * scaleY)); /* Pull the raster data from the buffered image * and pass it along to PS. */ ByteComponentRaster tile = (ByteComponentRaster)deepImage.getRaster(); psPrinterJob.drawImageBGR(tile.getDataStorage(), scaledBounds.x, scaledBounds.y, scaledBounds.width, scaledBounds.height, 0f, 0f, deepImage.getWidth(), deepImage.getHeight(), deepImage.getWidth(), deepImage.getHeight()); } /* * Fill the path defined by <code>pathIter</code> * with the specified color. * The path is provided in current user space. */ protected void deviceFill(PathIterator pathIter, Color color) { PSPrinterJob psPrinterJob = (PSPrinterJob) getPrinterJob(); psPrinterJob.deviceFill(pathIter, color, getTransform(), getClip()); } /* * Draw the bounding rectangle using path by calling draw() * function and passing a rectangle shape. */ protected void deviceFrameRect(int x, int y, int width, int height, Color color) { draw(new Rectangle2D.Float(x, y, width, height)); } /* * Draw a line using path by calling draw() function and passing * a line shape. */ protected void deviceDrawLine(int xBegin, int yBegin, int xEnd, int yEnd, Color color) { draw(new Line2D.Float(xBegin, yBegin, xEnd, yEnd)); } /* * Fill the rectangle with the specified color by calling fill(). */ protected void deviceFillRect(int x, int y, int width, int height, Color color) { fill(new Rectangle2D.Float(x, y, width, height)); } /* * This method should not be invoked by PSPathGraphics. * FIX: Rework PathGraphics so that this method is * not an abstract method there. */ protected void deviceClip(PathIterator pathIter) { } }