3310 lines · 121.6 KB · Java
RawDownload
                }            }             // This is padding for anti-aliasing and such.  It may            // be more than is needed.            int x = (int)x0 - padX;            int w = (int)(x1 - x0 + 2*padX);            int y = (int)y0 - padY;            int h = (int)(y1 - y0 + 2*padY);             Rectangle clipRect = new Rectangle(x,y,w,h);            result = clipRect.intersection(imageRect);        } catch (NoninvertibleTransformException nte) {            // Worst case bounds are the bounds of the image.            result = imageRect;        }         return result;    }     /**     * Draws an image, applying a transform from image space into user space     * before drawing.     * The transformation from user space into device space is done with     * the current transform in the Graphics2D.     * The given transformation is applied to the image before the     * transform attribute in the Graphics2D state is applied.     * The rendering attributes applied include the clip, transform,     * and composite attributes. Note that the result is     * undefined, if the given transform is noninvertible.     * @param img The image to be drawn. Does nothing if img is null.     * @param xform The transformation from image space into user space.     * @see #transform     * @see #setTransform     * @see #setComposite     * @see #clip     * @see #setClip     */    public void drawRenderedImage(RenderedImage img,                                  AffineTransform xform) {         if (img == null) {            return;        }         // BufferedImage case: use a simple drawImage call        if (img instanceof BufferedImage) {            BufferedImage bufImg = (BufferedImage)img;            drawImage(bufImg,xform,null);            return;        }         // transformState tracks the state of transform and        // transX, transY contain the integer casts of the        // translation factors        boolean isIntegerTranslate =            (transformState <= TRANSFORM_INT_TRANSLATE) &&            isIntegerTranslation(xform);         // Include padding for interpolation/antialiasing if necessary        int pad = isIntegerTranslate ? 0 : 3;         // Determine the region of the image that may contribute to        // the clipped drawing area        Rectangle region = getImageRegion(img,                                          getCompClip(),                                          transform,                                          xform,                                          pad, pad);        if (region.width <= 0 || region.height <= 0) {            return;        }         // Attempt to optimize integer translation of tiled images.        // Although theoretically we are O.K. if the concatenation of        // the user transform and the device transform is an integer        // translation, we'll play it safe and only optimize the case        // where both are integer translations.        if (isIntegerTranslate) {            // Use optimized code            // Note that drawTranslatedRenderedImage calls copyImage            // which takes the user space to device space transform into            // account, but we need to provide the image space to user space            // translations.             drawTranslatedRenderedImage(img, region,                                        (int) xform.getTranslateX(),                                        (int) xform.getTranslateY());            return;        }         // General case: cobble the necessary region into a single Raster        Raster raster = img.getData(region);         // Make a new Raster with the same contents as raster        // but starting at (0, 0).  This raster is thus in the same        // coordinate system as the SampleModel of the original raster.        WritableRaster wRaster =              Raster.createWritableRaster(raster.getSampleModel(),                                          raster.getDataBuffer(),                                          null);         // If the original raster was in a different coordinate        // system than its SampleModel, we need to perform an        // additional translation in order to get the (minX, minY)        // pixel of raster to be pixel (0, 0) of wRaster.  We also        // have to have the correct width and height.        int minX = raster.getMinX();        int minY = raster.getMinY();        int width = raster.getWidth();        int height = raster.getHeight();        int px = minX - raster.getSampleModelTranslateX();        int py = minY - raster.getSampleModelTranslateY();        if (px != 0 || py != 0 || width != wRaster.getWidth() ||            height != wRaster.getHeight()) {            wRaster =                wRaster.createWritableChild(px,                                            py,                                            width,                                            height,                                            0, 0,                                            null);        }         // Now we have a BufferedImage starting at (0, 0)        // with the same contents that started at (minX, minY)        // in raster.  So we must draw the BufferedImage with a        // translation of (minX, minY).        AffineTransform transXform = (AffineTransform)xform.clone();        transXform.translate(minX, minY);         ColorModel cm = img.getColorModel();        BufferedImage bufImg = new BufferedImage(cm,                                                 wRaster,                                                 cm.isAlphaPremultiplied(),                                                 null);        drawImage(bufImg, transXform, null);    }     /**     * Intersects <code>destRect</code> with <code>clip</code> and     * overwrites <code>destRect</code> with the result.     * Returns false if the intersection was empty, true otherwise.     */    private boolean clipTo(Rectangle destRect, Rectangle clip) {        int x1 = Math.max(destRect.x, clip.x);        int x2 = Math.min(destRect.x + destRect.width, clip.x + clip.width);        int y1 = Math.max(destRect.y, clip.y);        int y2 = Math.min(destRect.y + destRect.height, clip.y + clip.height);        if (((x2 - x1) < 0) || ((y2 - y1) < 0)) {            destRect.width = -1; // Set both just to be safe            destRect.height = -1;            return false;        } else {            destRect.x = x1;            destRect.y = y1;            destRect.width = x2 - x1;            destRect.height = y2 - y1;            return true;        }    }     /**     * Draw a portion of a RenderedImage tile-by-tile with a given     * integer image to user space translation.  The user to     * device transform must also be an integer translation.     */    private void drawTranslatedRenderedImage(RenderedImage img,                                             Rectangle region,                                             int i2uTransX,                                             int i2uTransY) {        // Cache tile grid info        int tileGridXOffset = img.getTileGridXOffset();        int tileGridYOffset = img.getTileGridYOffset();        int tileWidth = img.getTileWidth();        int tileHeight = img.getTileHeight();         // Determine the tile index extrema in each direction        int minTileX =            getTileIndex(region.x, tileGridXOffset, tileWidth);        int minTileY =            getTileIndex(region.y, tileGridYOffset, tileHeight);        int maxTileX =            getTileIndex(region.x + region.width - 1,                         tileGridXOffset, tileWidth);        int maxTileY =            getTileIndex(region.y + region.height - 1,                         tileGridYOffset, tileHeight);         // Create a single ColorModel to use for all BufferedImages        ColorModel colorModel = img.getColorModel();         // Reuse the same Rectangle for each iteration        Rectangle tileRect = new Rectangle();         for (int ty = minTileY; ty <= maxTileY; ty++) {            for (int tx = minTileX; tx <= maxTileX; tx++) {                // Get the current tile.                Raster raster = img.getTile(tx, ty);                 // Fill in tileRect with the tile bounds                tileRect.x = tx*tileWidth + tileGridXOffset;                tileRect.y = ty*tileHeight + tileGridYOffset;                tileRect.width = tileWidth;                tileRect.height = tileHeight;                 // Clip the tile against the image bounds and                // backwards mapped clip region                // The result can't be empty                clipTo(tileRect, region);                 // Create a WritableRaster containing the tile                WritableRaster wRaster = null;                if (raster instanceof WritableRaster) {                    wRaster = (WritableRaster)raster;                } else {                    // Create a WritableRaster in the same coordinate system                    // as the original raster.                    wRaster =                        Raster.createWritableRaster(raster.getSampleModel(),                                                    raster.getDataBuffer(),                                                    null);                }                 // Translate wRaster to start at (0, 0) and to contain                // only the relevent portion of the tile                wRaster = wRaster.createWritableChild(tileRect.x, tileRect.y,                                                      tileRect.width,                                                      tileRect.height,                                                      0, 0,                                                      null);                 // Wrap wRaster in a BufferedImage                BufferedImage bufImg =                    new BufferedImage(colorModel,                                      wRaster,                                      colorModel.isAlphaPremultiplied(),                                      null);                // Now we have a BufferedImage starting at (0, 0) that                // represents data from a Raster starting at                // (tileRect.x, tileRect.y).  Additionally, it needs                // to be translated by (i2uTransX, i2uTransY).  We call                // copyImage to draw just the region of interest                // without needing to create a child image.                copyImage(bufImg, tileRect.x + i2uTransX,                          tileRect.y + i2uTransY, 0, 0, tileRect.width,                          tileRect.height, null, null);            }        }    }     public void drawRenderableImage(RenderableImage img,                                    AffineTransform xform) {         if (img == null) {            return;        }         AffineTransform pipeTransform = transform;        AffineTransform concatTransform = new AffineTransform(xform);        concatTransform.concatenate(pipeTransform);        AffineTransform reverseTransform;         RenderContext rc = new RenderContext(concatTransform);         try {            reverseTransform = pipeTransform.createInverse();        } catch (NoninvertibleTransformException nte) {            rc = new RenderContext(pipeTransform);            reverseTransform = new AffineTransform();        }         RenderedImage rendering = img.createRendering(rc);        drawRenderedImage(rendering,reverseTransform);    }       /*     * Transform the bounding box of the BufferedImage     */    protected Rectangle transformBounds(Rectangle rect,                                        AffineTransform tx) {        if (tx.isIdentity()) {            return rect;        }         Shape s = transformShape(tx, rect);        return s.getBounds();    }     // text rendering methods    public void drawString(String str, int x, int y) {        if (str == null) {            throw new NullPointerException("String is null");        }         if (font.hasLayoutAttributes()) {            if (str.length() == 0) {                return;            }            new TextLayout(str, font, getFontRenderContext()).draw(this, x, y);            return;        }         try {            textpipe.drawString(this, str, x, y);        } catch (InvalidPipeException e) {            revalidateAll();            try {                textpipe.drawString(this, str, x, y);            } catch (InvalidPipeException e2) {                // Still catching the exception; we are not yet ready to                // validate the surfaceData correctly.  Fail for now and                // try again next time around.            }        } finally {            surfaceData.markDirty();        }    }     public void drawString(String str, float x, float y) {        if (str == null) {            throw new NullPointerException("String is null");        }         if (font.hasLayoutAttributes()) {            if (str.length() == 0) {                return;            }            new TextLayout(str, font, getFontRenderContext()).draw(this, x, y);            return;        }         try {            textpipe.drawString(this, str, x, y);        } catch (InvalidPipeException e) {            revalidateAll();            try {                textpipe.drawString(this, str, x, y);            } catch (InvalidPipeException e2) {                // Still catching the exception; we are not yet ready to                // validate the surfaceData correctly.  Fail for now and                // try again next time around.            }        } finally {            surfaceData.markDirty();        }    }     public void drawString(AttributedCharacterIterator iterator,                           int x, int y) {        if (iterator == null) {            throw new NullPointerException("AttributedCharacterIterator is null");        }        if (iterator.getBeginIndex() == iterator.getEndIndex()) {            return; /* nothing to draw */        }        TextLayout tl = new TextLayout(iterator, getFontRenderContext());        tl.draw(this, (float) x, (float) y);    }     public void drawString(AttributedCharacterIterator iterator,                           float x, float y) {        if (iterator == null) {            throw new NullPointerException("AttributedCharacterIterator is null");        }        if (iterator.getBeginIndex() == iterator.getEndIndex()) {            return; /* nothing to draw */        }        TextLayout tl = new TextLayout(iterator, getFontRenderContext());        tl.draw(this, x, y);    }     public void drawGlyphVector(GlyphVector gv, float x, float y)    {        if (gv == null) {            throw new NullPointerException("GlyphVector is null");        }         try {            textpipe.drawGlyphVector(this, gv, x, y);        } catch (InvalidPipeException e) {            revalidateAll();            try {                textpipe.drawGlyphVector(this, gv, x, y);            } catch (InvalidPipeException e2) {                // Still catching the exception; we are not yet ready to                // validate the surfaceData correctly.  Fail for now and                // try again next time around.            }        } finally {            surfaceData.markDirty();        }    }     public void drawChars(char data[], int offset, int length, int x, int y) {         if (data == null) {            throw new NullPointerException("char data is null");        }        if (offset < 0 || length < 0 || offset + length > data.length) {            throw new ArrayIndexOutOfBoundsException("bad offset/length");        }        if (font.hasLayoutAttributes()) {            if (data.length == 0) {                return;            }            new TextLayout(new String(data, offset, length),                           font, getFontRenderContext()).draw(this, x, y);            return;        }         try {            textpipe.drawChars(this, data, offset, length, x, y);        } catch (InvalidPipeException e) {            revalidateAll();            try {                textpipe.drawChars(this, data, offset, length, x, y);            } catch (InvalidPipeException e2) {                // Still catching the exception; we are not yet ready to                // validate the surfaceData correctly.  Fail for now and                // try again next time around.            }        } finally {            surfaceData.markDirty();        }    }     public void drawBytes(byte data[], int offset, int length, int x, int y) {        if (data == null) {            throw new NullPointerException("byte data is null");        }        if (offset < 0 || length < 0 || offset + length > data.length) {            throw new ArrayIndexOutOfBoundsException("bad offset/length");        }        /* Byte data is interpreted as 8-bit ASCII. Re-use drawChars loops */        char chData[] = new char[length];        for (int i = length; i-- > 0; ) {            chData[i] = (char)(data[i+offset] & 0xff);        }        if (font.hasLayoutAttributes()) {            if (data.length == 0) {                return;            }            new TextLayout(new String(chData),                           font, getFontRenderContext()).draw(this, x, y);            return;        }         try {            textpipe.drawChars(this, chData, 0, length, x, y);        } catch (InvalidPipeException e) {            revalidateAll();            try {                textpipe.drawChars(this, chData, 0, length, x, y);            } catch (InvalidPipeException e2) {                // Still catching the exception; we are not yet ready to                // validate the surfaceData correctly.  Fail for now and                // try again next time around.            }        } finally {            surfaceData.markDirty();        }    }// end of text rendering methods     /**     * Draws an image scaled to x,y,w,h in nonblocking mode with a     * callback object.     */    public boolean drawImage(Image img, int x, int y, int width, int height,                             ImageObserver observer) {        return drawImage(img, x, y, width, height, null, observer);    }     /**     * Not part of the advertised API but a useful utility method     * to call internally.  This is for the case where we are     * drawing to/from given coordinates using a given width/height,     * but we guarantee that the weidth/height of the src and dest     * areas are equal (no scale needed).     */    public boolean copyImage(Image img, int dx, int dy, int sx, int sy,                             int width, int height, Color bgcolor,                             ImageObserver observer) {        try {            return imagepipe.copyImage(this, img, dx, dy, sx, sy,                                       width, height, bgcolor, observer);        } catch (InvalidPipeException e) {            revalidateAll();            try {                return imagepipe.copyImage(this, img, dx, dy, sx, sy,                                           width, height, bgcolor, observer);            } catch (InvalidPipeException e2) {                // Still catching the exception; we are not yet ready to                // validate the surfaceData correctly.  Fail for now and                // try again next time around.                return false;            }

Lines 2501–3000 of 3310. Previous lines