Search in sources :

Example 81 with Rectangle2D

use of java.awt.geom.Rectangle2D in project jdk8u_jdk by JetBrains.

the class PSPathGraphics method drawImageToPlatform.

/**
     * The various <code>drawImage()</code> methods for
     * <code>WPathGraphics</code> are all decomposed
     * into an invocation of <code>drawImageToPlatform</code>.
     * The portion of the passed in image defined by
     * <code>srcX, srcY, srcWidth, and srcHeight</code>
     * is transformed by the supplied AffineTransform and
     * drawn using PS to the printer context.
     *
     * @param   img     The image to be drawn.
     *                  This method does nothing if <code>img</code> is null.
     * @param   xform   Used to transform the image before drawing.
     *                  This can be null.
     * @param   bgcolor This color is drawn where the image has transparent
     *                  pixels. If this parameter is null then the
     *                  pixels already in the destination should show
     *                  through.
     * @param   srcX    With srcY this defines the upper-left corner
     *                  of the portion of the image to be drawn.
     *
     * @param   srcY    With srcX this defines the upper-left corner
     *                  of the portion of the image to be drawn.
     * @param   srcWidth    The width of the portion of the image to
     *                      be drawn.
     * @param   srcHeight   The height of the portion of the image to
     *                      be drawn.
     * @param   handlingTransparency if being recursively called to
     *                    print opaque region of transparent image
     */
protected boolean drawImageToPlatform(Image image, AffineTransform xform, Color bgcolor, int srcX, int srcY, int srcWidth, int srcHeight, boolean handlingTransparency) {
    BufferedImage img = getBufferedImage(image);
    if (img == null) {
        return true;
    }
    PSPrinterJob psPrinterJob = (PSPrinterJob) getPrinterJob();
    /* The full transform to be applied to the image is the
         * caller's transform concatenated on to the transform
         * from user space to device space. If the caller didn't
         * supply a transform then we just act as if they passed
         * in the identify transform.
         */
    AffineTransform fullTransform = getTransform();
    if (xform == null) {
        xform = new AffineTransform();
    }
    fullTransform.concatenate(xform);
    /* Split the full transform into a pair of
         * transforms. The first transform holds effects
         * such as rotation and shearing. The second transform
         * is setup to hold only the scaling effects.
         * These transforms are created such that a point,
         * p, in user space, when transformed by 'fullTransform'
         * lands in the same place as when it is transformed
         * by 'rotTransform' and then 'scaleTransform'.
         *
         * The entire image transformation is not in Java in order
         * to minimize the amount of memory needed in the VM. By
         * dividing the transform in two, we rotate and shear
         * the source image in its own space and only go to
         * the, usually, larger, device space when we ask
         * PostScript to perform the final scaling.
         */
    double[] fullMatrix = new double[6];
    fullTransform.getMatrix(fullMatrix);
    /* Calculate the amount of scaling in the x
         * and y directions. This scaling is computed by
         * transforming a unit vector along each axis
         * and computing the resulting magnitude.
         * The computed values 'scaleX' and 'scaleY'
         * represent the amount of scaling PS will be asked
         * to perform.
         * Clamp this to the device scale for better quality printing.
         */
    Point2D.Float unitVectorX = new Point2D.Float(1, 0);
    Point2D.Float unitVectorY = new Point2D.Float(0, 1);
    fullTransform.deltaTransform(unitVectorX, unitVectorX);
    fullTransform.deltaTransform(unitVectorY, unitVectorY);
    Point2D.Float origin = new Point2D.Float(0, 0);
    double scaleX = unitVectorX.distance(origin);
    double scaleY = unitVectorY.distance(origin);
    double devResX = psPrinterJob.getXRes();
    double devResY = psPrinterJob.getYRes();
    double devScaleX = devResX / DEFAULT_USER_RES;
    double devScaleY = devResY / DEFAULT_USER_RES;
    /* check if rotated or sheared */
    int transformType = fullTransform.getType();
    boolean clampScale = ((transformType & (AffineTransform.TYPE_GENERAL_ROTATION | AffineTransform.TYPE_GENERAL_TRANSFORM)) != 0);
    if (clampScale) {
        if (scaleX > devScaleX)
            scaleX = devScaleX;
        if (scaleY > devScaleY)
            scaleY = devScaleY;
    }
    /* We do not need to draw anything if either scaling
         * factor is zero.
         */
    if (scaleX != 0 && scaleY != 0) {
        /* Here's the transformation we will do with Java2D,
            */
        AffineTransform rotTransform = new AffineTransform(//m00
        fullMatrix[0] / scaleX, //m10
        fullMatrix[1] / scaleY, //m01
        fullMatrix[2] / scaleX, //m11
        fullMatrix[3] / scaleY, //m02
        fullMatrix[4] / scaleX, //m12
        fullMatrix[5] / scaleY);
        /* The scale transform is not used directly: we instead
             * directly multiply by scaleX and scaleY.
             *
             * Conceptually here is what the scaleTransform is:
             *
             * AffineTransform scaleTransform = new AffineTransform(
             *                      scaleX,                     //m00
             *                      0,                          //m10
             *                      0,                          //m01
             *                      scaleY,                     //m11
             *                      0,                          //m02
             *                      0);                         //m12
             */
        /* Convert the image source's rectangle into the rotated
             * and sheared space. Once there, we calculate a rectangle
             * that encloses the resulting shape. It is this rectangle
             * which defines the size of the BufferedImage we need to
             * create to hold the transformed image.
             */
        Rectangle2D.Float srcRect = new Rectangle2D.Float(srcX, srcY, srcWidth, srcHeight);
        Shape rotShape = rotTransform.createTransformedShape(srcRect);
        Rectangle2D rotBounds = rotShape.getBounds2D();
        /* add a fudge factor as some fp precision problems have
             * been observed which caused pixels to be rounded down and
             * out of the image.
             */
        rotBounds.setRect(rotBounds.getX(), rotBounds.getY(), rotBounds.getWidth() + 0.001, rotBounds.getHeight() + 0.001);
        int boundsWidth = (int) rotBounds.getWidth();
        int boundsHeight = (int) rotBounds.getHeight();
        if (boundsWidth > 0 && boundsHeight > 0) {
            /* If the image has transparent or semi-transparent
                 * pixels then we'll have the application re-render
                 * the portion of the page covered by the image.
                 * This will be done in a later call to print using the
                 * saved graphics state.
                 * However several special cases can be handled otherwise:
                 * - bitmask transparency with a solid background colour
                 * - images which have transparency color models but no
                 * transparent pixels
                 * - images with bitmask transparency and an IndexColorModel
                 * (the common transparent GIF case) can be handled by
                 * rendering just the opaque pixels.
                 */
            boolean drawOpaque = true;
            if (!handlingTransparency && hasTransparentPixels(img)) {
                drawOpaque = false;
                if (isBitmaskTransparency(img)) {
                    if (bgcolor == null) {
                        if (drawBitmaskImage(img, xform, bgcolor, srcX, srcY, srcWidth, srcHeight)) {
                            // image drawn, just return.
                            return true;
                        }
                    } else if (bgcolor.getTransparency() == Transparency.OPAQUE) {
                        drawOpaque = true;
                    }
                }
                if (!canDoRedraws()) {
                    drawOpaque = true;
                }
            } else {
                // if there's no transparent pixels there's no need
                // for a background colour. This can avoid edge artifacts
                // in rotation cases.
                bgcolor = null;
            }
            // may blit b/g colour (including white) where it shoudn't.
            if ((srcX + srcWidth > img.getWidth(null) || srcY + srcHeight > img.getHeight(null)) && canDoRedraws()) {
                drawOpaque = false;
            }
            if (drawOpaque == false) {
                fullTransform.getMatrix(fullMatrix);
                AffineTransform tx = new AffineTransform(//m00
                fullMatrix[0] / devScaleX, //m10
                fullMatrix[1] / devScaleY, //m01
                fullMatrix[2] / devScaleX, //m11
                fullMatrix[3] / devScaleY, //m02
                fullMatrix[4] / devScaleX, //m12
                fullMatrix[5] / devScaleY);
                Rectangle2D.Float rect = new Rectangle2D.Float(srcX, srcY, srcWidth, srcHeight);
                Shape shape = fullTransform.createTransformedShape(rect);
                // Region isn't user space because its potentially
                // been rotated for landscape.
                Rectangle2D region = shape.getBounds2D();
                region.setRect(region.getX(), region.getY(), region.getWidth() + 0.001, region.getHeight() + 0.001);
                // Try to limit the amount of memory used to 8Mb, so
                // if at device resolution this exceeds a certain
                // image size then scale down the region to fit in
                // that memory, but never to less than 72 dpi.
                int w = (int) region.getWidth();
                int h = (int) region.getHeight();
                int nbytes = w * h * 3;
                int maxBytes = 8 * 1024 * 1024;
                double origDpi = (devResX < devResY) ? devResX : devResY;
                int dpi = (int) origDpi;
                double scaleFactor = 1;
                double maxSFX = w / (double) boundsWidth;
                double maxSFY = h / (double) boundsHeight;
                double maxSF = (maxSFX > maxSFY) ? maxSFY : maxSFX;
                int minDpi = (int) (dpi / maxSF);
                if (minDpi < DEFAULT_USER_RES)
                    minDpi = DEFAULT_USER_RES;
                while (nbytes > maxBytes && dpi > minDpi) {
                    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;
}
Also used : Shape(java.awt.Shape) Rectangle2D(java.awt.geom.Rectangle2D) BufferedImage(java.awt.image.BufferedImage) Graphics2D(java.awt.Graphics2D) Area(java.awt.geom.Area) Point2D(java.awt.geom.Point2D) ByteComponentRaster(sun.awt.image.ByteComponentRaster) AffineTransform(java.awt.geom.AffineTransform)

Example 82 with Rectangle2D

use of java.awt.geom.Rectangle2D in project jdk8u_jdk by JetBrains.

the class PSPrinterJob method textOut.

protected boolean textOut(Graphics g, String str, float x, float y, Font mLastFont, FontRenderContext frc, float width) {
    boolean didText = true;
    if (mFontProps == null) {
        return false;
    } else {
        prepDrawing();
        /* 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.
             * Postscript handles control chars mostly as a missing glyph.
             * But we use 'ashow' specifying a width for the string which
             * assumes zero-width for those three exceptions, and Postscript
             * tries to squeeze the extra char in, with the result that the
             * glyphs look compressed or even overlap.
             * So exclude those control chars from the string sent to PS.
             */
        str = removeControlChars(str);
        if (str.length() == 0) {
            return true;
        }
        CharsetString[] acs = ((PlatformFont) (mLastFont.getPeer())).makeMultiCharsetString(str, false);
        if (acs == null) {
            /* AWT can't convert all chars so use 2D path */
            return false;
        }
        /* Get an array of indices into our PostScript name
             * table. If all of the runs can not be converted
             * to PostScript fonts then null is returned and
             * we'll want to fall back to printing the text
             * as shapes.
             */
        int[] psFonts = getPSFontIndexArray(mLastFont, acs);
        if (psFonts != null) {
            for (int i = 0; i < acs.length; i++) {
                CharsetString cs = acs[i];
                CharsetEncoder fontCS = cs.fontDescriptor.encoder;
                StringBuffer nativeStr = new StringBuffer();
                byte[] strSeg = new byte[cs.length * 2];
                int len = 0;
                try {
                    ByteBuffer bb = ByteBuffer.wrap(strSeg);
                    fontCS.encode(CharBuffer.wrap(cs.charsetChars, cs.offset, cs.length), bb, true);
                    bb.flip();
                    len = bb.limit();
                } catch (IllegalStateException xx) {
                    continue;
                } catch (CoderMalfunctionError xx) {
                    continue;
                }
                /* The width to fit to may either be specified,
                     * or calculated. Specifying by the caller is only
                     * valid if the text does not need to be decomposed
                     * into multiple calls.
                     */
                float desiredWidth;
                if (acs.length == 1 && width != 0f) {
                    desiredWidth = width;
                } else {
                    Rectangle2D r2d = mLastFont.getStringBounds(cs.charsetChars, cs.offset, cs.offset + cs.length, frc);
                    desiredWidth = (float) r2d.getWidth();
                }
                /* unprintable chars had width of 0, causing a PS error
                     */
                if (desiredWidth == 0) {
                    return didText;
                }
                nativeStr.append('<');
                for (int j = 0; j < len; j++) {
                    byte b = strSeg[j];
                    // to avoid encoding conversion with println()
                    String hexS = Integer.toHexString(b);
                    int length = hexS.length();
                    if (length > 2) {
                        hexS = hexS.substring(length - 2, length);
                    } else if (length == 1) {
                        hexS = "0" + hexS;
                    } else if (length == 0) {
                        hexS = "00";
                    }
                    nativeStr.append(hexS);
                }
                nativeStr.append('>');
                /* This comment costs too much in output file size */
                //                  mPSStream.println("% Font[" + mLastFont.getName() + ", " +
                //                             FontConfiguration.getStyleString(mLastFont.getStyle()) + ", "
                //                             + mLastFont.getSize2D() + "]");
                getGState().emitPSFont(psFonts[i], mLastFont.getSize2D());
                // out String
                mPSStream.println(nativeStr.toString() + " " + desiredWidth + " " + x + " " + y + " " + DrawStringName);
                x += desiredWidth;
            }
        } else {
            didText = false;
        }
    }
    return didText;
}
Also used : PlatformFont(sun.awt.PlatformFont) Rectangle2D(java.awt.geom.Rectangle2D) CharsetString(sun.awt.CharsetString) ByteBuffer(java.nio.ByteBuffer) CharsetString(sun.awt.CharsetString)

Example 83 with Rectangle2D

use of java.awt.geom.Rectangle2D in project jdk8u_jdk by JetBrains.

the class PeekGraphics method drawString.

/**
     * Draws a string of text.
     * The rendering attributes applied include the clip, transform,
     * paint or color, font and composite attributes.
     * @param s The string to be drawn.
     * @param x,y The coordinates where the string should be drawn.
     * @see #setPaint
     * @see java.awt.Graphics#setColor
     * @see java.awt.Graphics#setFont
     * @see #transform
     * @see #setTransform
     * @see #setComposite
     * @see #clip
     * @see #setClip
     */
public void drawString(String str, float x, float y) {
    if (str.length() == 0) {
        return;
    }
    /* Logical bounds close enough and is used for GlyphVector */
    FontRenderContext frc = getFontRenderContext();
    Rectangle2D bbox = getFont().getStringBounds(str, frc);
    addDrawingRect(bbox, x, y);
    mPrintMetrics.drawText(this);
}
Also used : Rectangle2D(java.awt.geom.Rectangle2D) RoundRectangle2D(java.awt.geom.RoundRectangle2D) FontRenderContext(java.awt.font.FontRenderContext)

Example 84 with Rectangle2D

use of java.awt.geom.Rectangle2D in project jdk8u_jdk by JetBrains.

the class RasterPrinterJob method printPage.

/**
     * 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 = (int) (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 = (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;
}
Also used : ByteInterleavedRaster(sun.awt.image.ByteInterleavedRaster) Rectangle2D(java.awt.geom.Rectangle2D) Rectangle(java.awt.Rectangle) PrinterException(java.awt.print.PrinterException) PrinterAbortException(java.awt.print.PrinterAbortException) HeadlessException(java.awt.HeadlessException) PrintException(javax.print.PrintException) PrinterException(java.awt.print.PrinterException) IOException(java.io.IOException) BufferedImage(java.awt.image.BufferedImage) Graphics2D(java.awt.Graphics2D) PageFormat(java.awt.print.PageFormat) Paper(java.awt.print.Paper) AffineTransform(java.awt.geom.AffineTransform) Printable(java.awt.print.Printable)

Example 85 with Rectangle2D

use of java.awt.geom.Rectangle2D in project jdk8u_jdk by JetBrains.

the class ExtendedTextSourceLabel method createItalicBounds.

public Rectangle2D createItalicBounds() {
    float ia = cm.italicAngle;
    Rectangle2D lb = getLogicalBounds();
    float l = (float) lb.getMinX();
    float t = -cm.ascent;
    float r = (float) lb.getMaxX();
    float b = cm.descent;
    if (ia != 0) {
        if (ia > 0) {
            l -= ia * (b - cm.ssOffset);
            r -= ia * (t - cm.ssOffset);
        } else {
            l -= ia * (t - cm.ssOffset);
            r -= ia * (b - cm.ssOffset);
        }
    }
    return new Rectangle2D.Float(l, t, r - l, b - t);
}
Also used : Rectangle2D(java.awt.geom.Rectangle2D)

Aggregations

Rectangle2D (java.awt.geom.Rectangle2D)262 Graphics2D (java.awt.Graphics2D)42 AffineTransform (java.awt.geom.AffineTransform)34 Color (java.awt.Color)33 Paint (java.awt.Paint)28 Point2D (java.awt.geom.Point2D)26 BufferedImage (java.awt.image.BufferedImage)23 Font (java.awt.Font)21 FontMetrics (java.awt.FontMetrics)20 Dimension (java.awt.Dimension)19 RoundRectangle2D (java.awt.geom.RoundRectangle2D)18 Rectangle (java.awt.Rectangle)16 FontRenderContext (java.awt.font.FontRenderContext)15 Point (java.awt.Point)11 BasicStroke (java.awt.BasicStroke)10 ArrayList (java.util.ArrayList)10 GradientPaint (java.awt.GradientPaint)9 TextLayout (java.awt.font.TextLayout)9 RadialGradientPaint (java.awt.RadialGradientPaint)8 Shape (java.awt.Shape)7