3310 lines · 121.6 KB · Java
RawDownload
/* * Copyright (c) 1996, 2008, 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.java2d; import java.awt.Graphics;import java.awt.Graphics2D;import java.awt.RenderingHints;import java.awt.RenderingHints.Key;import java.awt.geom.Area;import java.awt.geom.AffineTransform;import java.awt.geom.NoninvertibleTransformException;import java.awt.AlphaComposite;import java.awt.BasicStroke;import java.awt.image.BufferedImage;import java.awt.image.BufferedImageOp;import java.awt.image.RenderedImage;import java.awt.image.renderable.RenderableImage;import java.awt.image.renderable.RenderContext;import java.awt.image.AffineTransformOp;import java.awt.image.Raster;import java.awt.image.WritableRaster;import java.awt.Image;import java.awt.Composite;import java.awt.Color;import java.awt.image.ColorModel;import java.awt.GraphicsConfiguration;import java.awt.Paint;import java.awt.GradientPaint;import java.awt.LinearGradientPaint;import java.awt.RadialGradientPaint;import java.awt.TexturePaint;import java.awt.geom.Rectangle2D;import java.awt.geom.PathIterator;import java.awt.geom.GeneralPath;import java.awt.Shape;import java.awt.Stroke;import java.awt.FontMetrics;import java.awt.Rectangle;import java.text.AttributedCharacterIterator;import java.awt.Font;import java.awt.image.ImageObserver;import java.awt.Transparency;import java.awt.font.GlyphVector;import java.awt.font.TextLayout;import sun.font.FontDesignMetrics;import sun.font.FontUtilities;import sun.java2d.pipe.PixelDrawPipe;import sun.java2d.pipe.PixelFillPipe;import sun.java2d.pipe.ShapeDrawPipe;import sun.java2d.pipe.ValidatePipe;import sun.java2d.pipe.ShapeSpanIterator;import sun.java2d.pipe.Region;import sun.java2d.pipe.TextPipe;import sun.java2d.pipe.DrawImagePipe;import sun.java2d.pipe.LoopPipe;import sun.java2d.loops.FontInfo;import sun.java2d.loops.RenderLoops;import sun.java2d.loops.CompositeType;import sun.java2d.loops.SurfaceType;import sun.java2d.loops.Blit;import sun.java2d.loops.MaskFill;import sun.font.FontManager;import java.awt.font.FontRenderContext;import sun.java2d.loops.XORComposite;import sun.awt.ConstrainableGraphics;import sun.awt.SunHints;import java.util.Map;import java.util.Iterator;import sun.java2d.DestSurfaceProvider;import sun.misc.PerformanceLogger; /** * This is a the master Graphics2D superclass for all of the Sun * Graphics implementations.  This class relies on subclasses to * manage the various device information, but provides an overall * general framework for performing all of the requests in the * Graphics and Graphics2D APIs. * * @author Jim Graham */public final class SunGraphics2D    extends Graphics2D    implements ConstrainableGraphics, Cloneable, DestSurfaceProvider{    /*     * Attribute States     */    /* Paint */    public static final int PAINT_CUSTOM       = 6; /* Any other Paint object */    public static final int PAINT_TEXTURE      = 5; /* Tiled Image */    public static final int PAINT_RAD_GRADIENT = 4; /* Color RadialGradient */    public static final int PAINT_LIN_GRADIENT = 3; /* Color LinearGradient */    public static final int PAINT_GRADIENT     = 2; /* Color Gradient */    public static final int PAINT_ALPHACOLOR   = 1; /* Non-opaque Color */    public static final int PAINT_OPAQUECOLOR  = 0; /* Opaque Color */     /* Composite*/    public static final int COMP_CUSTOM = 3;/* Custom Composite */    public static final int COMP_XOR    = 2;/* XOR Mode Composite */    public static final int COMP_ALPHA  = 1;/* AlphaComposite */    public static final int COMP_ISCOPY = 0;/* simple stores into destination,                                             * i.e. Src, SrcOverNoEa, and other                                             * alpha modes which replace                                             * the destination.                                             */     /* Stroke */    public static final int STROKE_CUSTOM = 3; /* custom Stroke */    public static final int STROKE_WIDE   = 2; /* BasicStroke */    public static final int STROKE_THINDASHED   = 1; /* BasicStroke */    public static final int STROKE_THIN   = 0; /* BasicStroke */     /* Transform */    public static final int TRANSFORM_GENERIC = 4; /* any 3x2 */    public static final int TRANSFORM_TRANSLATESCALE = 3; /* scale XY */    public static final int TRANSFORM_ANY_TRANSLATE = 2; /* non-int translate */    public static final int TRANSFORM_INT_TRANSLATE = 1; /* int translate */    public static final int TRANSFORM_ISIDENT = 0; /* Identity */     /* Clipping */    public static final int CLIP_SHAPE       = 2; /* arbitrary clip */    public static final int CLIP_RECTANGULAR = 1; /* rectangular clip */    public static final int CLIP_DEVICE      = 0; /* no clipping set */     /* The following fields are used when the current Paint is a Color. */    public int eargb;  // ARGB value with ExtraAlpha baked in    public int pixel;  // pixel value for eargb     public SurfaceData surfaceData;     public PixelDrawPipe drawpipe;    public PixelFillPipe fillpipe;    public DrawImagePipe imagepipe;    public ShapeDrawPipe shapepipe;    public TextPipe textpipe;    public MaskFill alphafill;     public RenderLoops loops;     public CompositeType imageComp;     /* Image Transparency checked on fly */     public int paintState;    public int compositeState;    public int strokeState;    public int transformState;    public int clipState;     public Color foregroundColor;    public Color backgroundColor;     public AffineTransform transform;    public int transX;    public int transY;     protected static final Stroke defaultStroke = new BasicStroke();    protected static final Composite defaultComposite = AlphaComposite.SrcOver;    private static final Font defaultFont =        new Font(Font.DIALOG, Font.PLAIN, 12);     public Paint paint;    public Stroke stroke;    public Composite composite;    protected Font font;    protected FontMetrics fontMetrics;     public int renderHint;    public int antialiasHint;    public int textAntialiasHint;    private int fractionalMetricsHint;     /* A gamma adjustment to the colour used in lcd text blitting */    public int lcdTextContrast;    private static int lcdTextContrastDefaultValue = 140;     private int interpolationHint;      // raw value of rendering Hint    public int strokeHint;     public int interpolationType;       // algorithm choice based on                                        // interpolation and render Hints     public RenderingHints hints;     public Region constrainClip;                // lightweight bounds    public int constrainX;    public int constrainY;     public Region clipRegion;    public Shape usrClip;    protected Region devClip;           // Actual physical drawable     // cached state for text rendering    private boolean validFontInfo;    private FontInfo fontInfo;    private FontInfo glyphVectorFontInfo;    private FontRenderContext glyphVectorFRC;     private final static int slowTextTransformMask =                            AffineTransform.TYPE_GENERAL_TRANSFORM                        |   AffineTransform.TYPE_MASK_ROTATION                        |   AffineTransform.TYPE_FLIP;     static {        if (PerformanceLogger.loggingEnabled()) {            PerformanceLogger.setTime("SunGraphics2D static initialization");        }    }     public SunGraphics2D(SurfaceData sd, Color fg, Color bg, Font f) {        surfaceData = sd;        foregroundColor = fg;        backgroundColor = bg;         transform = new AffineTransform();        stroke = defaultStroke;        composite = defaultComposite;        paint = foregroundColor;         imageComp = CompositeType.SrcOverNoEa;         renderHint = SunHints.INTVAL_RENDER_DEFAULT;        antialiasHint = SunHints.INTVAL_ANTIALIAS_OFF;        textAntialiasHint = SunHints.INTVAL_TEXT_ANTIALIAS_DEFAULT;        fractionalMetricsHint = SunHints.INTVAL_FRACTIONALMETRICS_OFF;        lcdTextContrast = lcdTextContrastDefaultValue;        interpolationHint = -1;        strokeHint = SunHints.INTVAL_STROKE_DEFAULT;         interpolationType = AffineTransformOp.TYPE_NEAREST_NEIGHBOR;         validateColor();         font = f;        if (font == null) {            font = defaultFont;        }         setDevClip(sd.getBounds());        invalidatePipe();    }     protected Object clone() {        try {            SunGraphics2D g = (SunGraphics2D) super.clone();            g.transform = new AffineTransform(this.transform);            if (hints != null) {                g.hints = (RenderingHints) this.hints.clone();            }            /* FontInfos are re-used, so must be cloned too, if they             * are valid, and be nulled out if invalid.             * The implied trade-off is that there is more to be gained             * from re-using these objects than is lost by having to             * clone them when the SG2D is cloned.             */            if (this.fontInfo != null) {                if (this.validFontInfo) {                    g.fontInfo = (FontInfo)this.fontInfo.clone();                } else {                    g.fontInfo = null;                }            }            if (this.glyphVectorFontInfo != null) {                g.glyphVectorFontInfo =                    (FontInfo)this.glyphVectorFontInfo.clone();                g.glyphVectorFRC = this.glyphVectorFRC;            }            //g.invalidatePipe();            return g;        } catch (CloneNotSupportedException e) {        }        return null;    }     /**     * Create a new SunGraphics2D based on this one.     */    public Graphics create() {        return (Graphics) clone();    }     public void setDevClip(int x, int y, int w, int h) {        Region c = constrainClip;        if (c == null) {            devClip = Region.getInstanceXYWH(x, y, w, h);        } else {            devClip = c.getIntersectionXYWH(x, y, w, h);        }        validateCompClip();    }     public void setDevClip(Rectangle r) {        setDevClip(r.x, r.y, r.width, r.height);    }     /**     * Constrain rendering for lightweight objects.     *     * REMIND: This method will back off to the "workaround"     * of using translate and clipRect if the Graphics     * to be constrained has a complex transform.  The     * drawback of the workaround is that the resulting     * clip and device origin cannot be "enforced".     *     * @exception IllegalStateException If the Graphics     * to be constrained has a complex transform.     */    public void constrain(int x, int y, int w, int h) {        if ((x|y) != 0) {            translate(x, y);        }        if (transformState >= TRANSFORM_TRANSLATESCALE) {            clipRect(0, 0, w, h);            return;        }        x = constrainX = transX;        y = constrainY = transY;        w = Region.dimAdd(x, w);        h = Region.dimAdd(y, h);        Region c = constrainClip;        if (c == null) {            c = Region.getInstanceXYXY(x, y, w, h);        } else {            c = c.getIntersectionXYXY(x, y, w, h);            if (c == constrainClip) {                // Common case to ignore                return;            }        }        constrainClip = c;        if (!devClip.isInsideQuickCheck(c)) {            devClip = devClip.getIntersection(c);            validateCompClip();        }    }     protected static ValidatePipe invalidpipe = new ValidatePipe();     /*     * Invalidate the pipeline     */    protected void invalidatePipe() {        drawpipe = invalidpipe;        fillpipe = invalidpipe;        shapepipe = invalidpipe;        textpipe = invalidpipe;        imagepipe = invalidpipe;        loops = null;    }     public void validatePipe() {        surfaceData.validatePipe(this);    }     /*     * Intersect two Shapes by the simplest method, attempting to produce     * a simplified result.     * The boolean arguments keep1 and keep2 specify whether or not     * the first or second shapes can be modified during the operation     * or whether that shape must be "kept" unmodified.     */    Shape intersectShapes(Shape s1, Shape s2, boolean keep1, boolean keep2) {        if (s1 instanceof Rectangle && s2 instanceof Rectangle) {            return ((Rectangle) s1).intersection((Rectangle) s2);        }        if (s1 instanceof Rectangle2D) {            return intersectRectShape((Rectangle2D) s1, s2, keep1, keep2);        } else if (s2 instanceof Rectangle2D) {            return intersectRectShape((Rectangle2D) s2, s1, keep2, keep1);        }        return intersectByArea(s1, s2, keep1, keep2);    }     /*     * Intersect a Rectangle with a Shape by the simplest method,     * attempting to produce a simplified result.     * The boolean arguments keep1 and keep2 specify whether or not     * the first or second shapes can be modified during the operation     * or whether that shape must be "kept" unmodified.     */    Shape intersectRectShape(Rectangle2D r, Shape s,                             boolean keep1, boolean keep2) {        if (s instanceof Rectangle2D) {            Rectangle2D r2 = (Rectangle2D) s;            Rectangle2D outrect;            if (!keep1) {                outrect = r;            } else if (!keep2) {                outrect = r2;            } else {                outrect = new Rectangle2D.Float();            }            double x1 = Math.max(r.getX(), r2.getX());            double x2 = Math.min(r.getX()  + r.getWidth(),                                 r2.getX() + r2.getWidth());            double y1 = Math.max(r.getY(), r2.getY());            double y2 = Math.min(r.getY()  + r.getHeight(),                                 r2.getY() + r2.getHeight());             if (((x2 - x1) < 0) || ((y2 - y1) < 0))                // Width or height is negative. No intersection.                outrect.setFrameFromDiagonal(0, 0, 0, 0);            else                outrect.setFrameFromDiagonal(x1, y1, x2, y2);            return outrect;        }        if (r.contains(s.getBounds2D())) {            if (keep2) {                s = cloneShape(s);            }            return s;        }        return intersectByArea(r, s, keep1, keep2);    }     protected static Shape cloneShape(Shape s) {        return new GeneralPath(s);    }     /*     * Intersect two Shapes using the Area class.  Presumably other     * attempts at simpler intersection methods proved fruitless.     * The boolean arguments keep1 and keep2 specify whether or not     * the first or second shapes can be modified during the operation     * or whether that shape must be "kept" unmodified.     * @see #intersectShapes     * @see #intersectRectShape     */    Shape intersectByArea(Shape s1, Shape s2, boolean keep1, boolean keep2) {        Area a1, a2;         // First see if we can find an overwriteable source shape        // to use as our destination area to avoid duplication.        if (!keep1 && (s1 instanceof Area)) {            a1 = (Area) s1;        } else if (!keep2 && (s2 instanceof Area)) {            a1 = (Area) s2;            s2 = s1;        } else {            a1 = new Area(s1);        }         if (s2 instanceof Area) {            a2 = (Area) s2;        } else {            a2 = new Area(s2);        }         a1.intersect(a2);        if (a1.isRectangular()) {            return a1.getBounds();        }         return a1;    }     /*     * Intersect usrClip bounds and device bounds to determine the composite     * rendering boundaries.     */    public Region getCompClip() {        if (!surfaceData.isValid()) {            // revalidateAll() implicitly recalculcates the composite clip            revalidateAll();        }         return clipRegion;    }     public Font getFont() {        if (font == null) {            font = defaultFont;        }        return font;    }     private static final double[] IDENT_MATRIX = {1, 0, 0, 1};    private static final AffineTransform IDENT_ATX =        new AffineTransform();

Lines 1–500 of 3310.