jdk/src/solaris/classes/sun/java2d/xr/XRPaints.java
author ceisserer
Tue, 22 Oct 2013 13:47:45 -0700
changeset 21233 a36ed36d3209
parent 6374 e214162c907e
child 22584 eed64ee05369
permissions -rw-r--r--
8023483: sun/java2d/DirectX/TransformedPaintTest/TransformedPaintTest.java failed with jdk8 on linux platforms Reviewed-by: prr, bae

/*
 * Copyright (c) 2010, 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.xr;

import java.awt.*;
import java.awt.MultipleGradientPaint.*;
import java.awt.geom.*;
import java.awt.image.*;
import sun.java2d.*;
import sun.java2d.loops.*;
import sun.java2d.xr.XRSurfaceData.XRInternalSurfaceData;

abstract class XRPaints {
    static XRCompositeManager xrCompMan;

    static final XRGradient xrGradient = new XRGradient();
    static final XRLinearGradient xrLinearGradient = new XRLinearGradient();
    static final XRRadialGradient xrRadialGradient = new XRRadialGradient();
    static final XRTexture xrTexture = new XRTexture();

    public static void register(XRCompositeManager xrComp) {
        xrCompMan = xrComp;
    }

    private static XRPaints getXRPaint(SunGraphics2D sg2d) {
        switch (sg2d.paintState) {
        case SunGraphics2D.PAINT_GRADIENT:
            return xrGradient;

        case SunGraphics2D.PAINT_LIN_GRADIENT:
            return xrLinearGradient;

        case SunGraphics2D.PAINT_RAD_GRADIENT:
            return xrRadialGradient;

        case SunGraphics2D.PAINT_TEXTURE:
            return xrTexture;

        default:
            return null;
        }
    }

    /**
     * Attempts to locate an implementation corresponding to the paint state of
     * the provided SunGraphics2D object. If no implementation can be found, or
     * if the paint cannot be accelerated under the conditions of the
     * SunGraphics2D, this method returns false; otherwise, returns true.
     */
    static boolean isValid(SunGraphics2D sg2d) {
        XRPaints impl = getXRPaint(sg2d);
        return (impl != null && impl.isPaintValid(sg2d));
    }

    static void setPaint(SunGraphics2D sg2d, Paint paint) {
        XRPaints impl = getXRPaint(sg2d);
        if (impl != null) {
            impl.setXRPaint(sg2d, paint);
        }
    }

    /**
     * Returns true if this implementation is able to accelerate the Paint
     * object associated with, and under the conditions of, the provided
     * SunGraphics2D instance; otherwise returns false.
     */
    abstract boolean isPaintValid(SunGraphics2D sg2d);

    abstract void setXRPaint(SunGraphics2D sg2d, Paint paint);

    private static class XRGradient extends XRPaints {
        private XRGradient() {
        }

        /**
         * There are no restrictions for accelerating GradientPaint, so this
         * method always returns true.
         */
        @Override
        boolean isPaintValid(SunGraphics2D sg2d) {
            return true;
        }

        void setXRPaint(SunGraphics2D sg2d, Paint pt) {
            GradientPaint paint = (GradientPaint) pt;

            int repeat = paint.isCyclic() ? XRUtils.RepeatReflect : XRUtils.RepeatPad;
            float fractions[] = {0, 1};
            int[] pixels = convertToIntArgbPixels(new Color[] { paint.getColor1(), paint.getColor2() });

            Point2D pt1 = paint.getPoint1();
            Point2D pt2 = paint.getPoint2();

            XRBackend con = xrCompMan.getBackend();
            int gradient = con.createLinearGradient(pt1, pt2, fractions, pixels, repeat);
            xrCompMan.setGradientPaint(new XRSurfaceData.XRInternalSurfaceData(con, gradient));
        }
    }

    public int getGradientLength(Point2D pt1, Point2D pt2) {
           double xDiff = Math.max(pt1.getX(), pt2.getX()) - Math.min(pt1.getX(), pt2.getX());
           double yDiff = Math.max(pt1.getY(), pt2.getY()) - Math.min(pt1.getY(), pt2.getY());
           return (int) Math.ceil(Math.sqrt(xDiff*xDiff + yDiff*yDiff));
    }

    private static class XRLinearGradient extends XRPaints {

        @Override
        boolean isPaintValid(SunGraphics2D sg2d) {
            return ((LinearGradientPaint) sg2d.getPaint()).getColorSpace() == ColorSpaceType.SRGB;
        }

        @Override
        void setXRPaint(SunGraphics2D sg2d, Paint pt) {
            LinearGradientPaint paint = (LinearGradientPaint) pt;

            Color[] colors = paint.getColors();
            Point2D pt1 = paint.getStartPoint();
            Point2D pt2 = paint.getEndPoint();

            int repeat = XRUtils.getRepeatForCycleMethod(paint.getCycleMethod());
            float[] fractions = paint.getFractions();
            int[] pixels = convertToIntArgbPixels(colors);

            AffineTransform at = paint.getTransform();
            try {
                at.invert();
            } catch (NoninvertibleTransformException ex) {
                ex.printStackTrace();
            }

            XRBackend con = xrCompMan.getBackend();
            int gradient = con.createLinearGradient(pt1, pt2, fractions, pixels, repeat);
            XRInternalSurfaceData x11sd = new XRSurfaceData.XRInternalSurfaceData(con, gradient);
            x11sd.setStaticSrcTx(at);
            xrCompMan.setGradientPaint(x11sd);
        }
    }

    private static class XRRadialGradient extends XRPaints {

        @Override
        boolean isPaintValid(SunGraphics2D sg2d) {
            RadialGradientPaint grad = (RadialGradientPaint) sg2d.paint;
            return grad.getFocusPoint().equals(grad.getCenterPoint())
                   && grad.getColorSpace() == ColorSpaceType.SRGB;
        }

        @Override
        void setXRPaint(SunGraphics2D sg2d, Paint pt) {
            RadialGradientPaint paint = (RadialGradientPaint) pt;
            Color[] colors = paint.getColors();
            Point2D center = paint.getCenterPoint();

            int repeat = XRUtils.getRepeatForCycleMethod(paint.getCycleMethod());
            float[] fractions = paint.getFractions();
            int[] pixels = convertToIntArgbPixels(colors);
            float radius = paint.getRadius();

            float cx = (float) center.getX();
            float cy = (float) center.getY();

            AffineTransform at = paint.getTransform();
            try {
                at.invert();
            } catch (NoninvertibleTransformException ex) {
                ex.printStackTrace();
            }

            XRBackend con = xrCompMan.getBackend();
            int gradient = con.createRadialGradient(cx, cy, 0, radius, fractions, pixels, repeat);
            XRInternalSurfaceData x11sd = new XRSurfaceData.XRInternalSurfaceData(con, gradient);
            x11sd.setStaticSrcTx(at);
            xrCompMan.setGradientPaint(x11sd);
        }
    }

    private static class XRTexture extends XRPaints {

        private XRSurfaceData getAccSrcSurface(XRSurfaceData dstData, BufferedImage bi) {
            // REMIND: this is a hack that attempts to cache the system
            // memory image from the TexturePaint instance into an
            // XRender pixmap...
            SurfaceData srcData = dstData.getSourceSurfaceData(bi, SunGraphics2D.TRANSFORM_ISIDENT, CompositeType.SrcOver, null);
            if (!(srcData instanceof XRSurfaceData)) {
                srcData = dstData.getSourceSurfaceData(bi, SunGraphics2D.TRANSFORM_ISIDENT, CompositeType.SrcOver, null);
                if (!(srcData instanceof XRSurfaceData)) {
                    throw new InternalError("Surface not cachable");
                }
            }

            return (XRSurfaceData) srcData;
        }

        @Override
        boolean isPaintValid(SunGraphics2D sg2d) {
            TexturePaint paint = (TexturePaint) sg2d.paint;
            BufferedImage bi = paint.getImage();
            XRSurfaceData dstData = (XRSurfaceData) sg2d.getDestSurface();

            return getAccSrcSurface(dstData, bi) != null;
        }

        @Override
        void setXRPaint(SunGraphics2D sg2d, Paint pt) {
            TexturePaint paint = (TexturePaint) pt;
            BufferedImage bi = paint.getImage();
            Rectangle2D anchor = paint.getAnchorRect();

            XRSurfaceData dstData = (XRSurfaceData) sg2d.surfaceData;
            XRSurfaceData srcData = (XRSurfaceData) getAccSrcSurface(dstData, bi);

            AffineTransform at = new AffineTransform();
            at.translate(anchor.getX(), anchor.getY());
            at.scale(anchor.getWidth() / ((double) bi.getWidth()), anchor.getHeight() / ((double) bi.getHeight()));

            try {
                at.invert();
            } catch (NoninvertibleTransformException ex) {
                at.setToIdentity();
            }
            srcData.setStaticSrcTx(at);

            srcData.validateAsSource(at, XRUtils.RepeatNormal, XRUtils.ATransOpToXRQuality(sg2d.interpolationType));
            xrCompMan.setTexturePaint(srcData);
        }
    }

    public int[] convertToIntArgbPixels(Color[] colors) {
        int[] pixels = new int[colors.length];
        for (int i = 0; i < colors.length; i++) {
            pixels[i] = colorToIntArgbPixel(colors[i]);
        }
        return pixels;
    }

    public int colorToIntArgbPixel(Color c) {
        int rgb = c.getRGB();
        int a = (int) Math.round(xrCompMan.getExtraAlpha() * (rgb >>> 24));
        return ((a << 24) | (rgb & 0x00FFFFFF));
    }
}