jdk/src/share/classes/sun/java2d/pipe/BufferedPaints.java
author dxu
Thu, 04 Apr 2013 15:39:17 -0700
changeset 16734 da1901d79073
parent 12813 c10ab96dcf41
permissions -rw-r--r--
8000406: change files using @GenerateNativeHeader to use @Native Summary: Use @Native annotation to mark constants interested by native codes Reviewed-by: alanb, anthony, prr
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     1
/*
16734
da1901d79073 8000406: change files using @GenerateNativeHeader to use @Native
dxu
parents: 12813
diff changeset
     2
 * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
90ce3da70b43 Initial load
duke
parents:
diff changeset
     4
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
90ce3da70b43 Initial load
duke
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    10
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
90ce3da70b43 Initial load
duke
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
90ce3da70b43 Initial load
duke
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
90ce3da70b43 Initial load
duke
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
90ce3da70b43 Initial load
duke
parents:
diff changeset
    15
 * accompanied this code).
90ce3da70b43 Initial load
duke
parents:
diff changeset
    16
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
90ce3da70b43 Initial load
duke
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    20
 *
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
    23
 * questions.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    24
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    25
90ce3da70b43 Initial load
duke
parents:
diff changeset
    26
package sun.java2d.pipe;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    27
90ce3da70b43 Initial load
duke
parents:
diff changeset
    28
import java.awt.Color;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    29
import java.awt.GradientPaint;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    30
import java.awt.LinearGradientPaint;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    31
import java.awt.MultipleGradientPaint;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    32
import java.awt.MultipleGradientPaint.ColorSpaceType;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    33
import java.awt.MultipleGradientPaint.CycleMethod;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    34
import java.awt.Paint;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    35
import java.awt.RadialGradientPaint;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    36
import java.awt.TexturePaint;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    37
import java.awt.geom.AffineTransform;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    38
import java.awt.geom.Point2D;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    39
import java.awt.geom.Rectangle2D;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    40
import java.awt.image.AffineTransformOp;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    41
import java.awt.image.BufferedImage;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    42
import sun.awt.image.PixelConverter;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    43
import sun.java2d.SunGraphics2D;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    44
import sun.java2d.SurfaceData;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    45
import sun.java2d.loops.CompositeType;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    46
import sun.java2d.loops.SurfaceType;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    47
import static sun.java2d.pipe.BufferedOpCodes.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    48
16734
da1901d79073 8000406: change files using @GenerateNativeHeader to use @Native
dxu
parents: 12813
diff changeset
    49
import java.lang.annotation.Native;
12813
c10ab96dcf41 7170969: Add @GenerateNativeHeader to classes whose fields need to be exported for JNI
erikj
parents: 11080
diff changeset
    50
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    51
public class BufferedPaints {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    52
90ce3da70b43 Initial load
duke
parents:
diff changeset
    53
    static void setPaint(RenderQueue rq, SunGraphics2D sg2d,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    54
                         Paint paint, int ctxflags)
90ce3da70b43 Initial load
duke
parents:
diff changeset
    55
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    56
        if (sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    57
            setColor(rq, sg2d.pixel);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    58
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    59
            boolean useMask = (ctxflags & BufferedContext.USE_MASK) != 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    60
            switch (sg2d.paintState) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    61
            case SunGraphics2D.PAINT_GRADIENT:
90ce3da70b43 Initial load
duke
parents:
diff changeset
    62
                setGradientPaint(rq, sg2d,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    63
                                 (GradientPaint)paint, useMask);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    64
                break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    65
            case SunGraphics2D.PAINT_LIN_GRADIENT:
90ce3da70b43 Initial load
duke
parents:
diff changeset
    66
                setLinearGradientPaint(rq, sg2d,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    67
                                       (LinearGradientPaint)paint, useMask);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    68
                break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    69
            case SunGraphics2D.PAINT_RAD_GRADIENT:
90ce3da70b43 Initial load
duke
parents:
diff changeset
    70
                setRadialGradientPaint(rq, sg2d,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    71
                                       (RadialGradientPaint)paint, useMask);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    72
                break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    73
            case SunGraphics2D.PAINT_TEXTURE:
90ce3da70b43 Initial load
duke
parents:
diff changeset
    74
                setTexturePaint(rq, sg2d,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    75
                                (TexturePaint)paint, useMask);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    76
                break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    77
            default:
90ce3da70b43 Initial load
duke
parents:
diff changeset
    78
                break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    79
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    80
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    81
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    82
90ce3da70b43 Initial load
duke
parents:
diff changeset
    83
    static void resetPaint(RenderQueue rq) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    84
        // assert rq.lock.isHeldByCurrentThread();
90ce3da70b43 Initial load
duke
parents:
diff changeset
    85
        rq.ensureCapacity(4);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    86
        RenderBuffer buf = rq.getBuffer();
90ce3da70b43 Initial load
duke
parents:
diff changeset
    87
        buf.putInt(RESET_PAINT);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    88
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    89
90ce3da70b43 Initial load
duke
parents:
diff changeset
    90
/****************************** Color support *******************************/
90ce3da70b43 Initial load
duke
parents:
diff changeset
    91
90ce3da70b43 Initial load
duke
parents:
diff changeset
    92
    private static void setColor(RenderQueue rq, int pixel) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    93
        // assert rq.lock.isHeldByCurrentThread();
90ce3da70b43 Initial load
duke
parents:
diff changeset
    94
        rq.ensureCapacity(8);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    95
        RenderBuffer buf = rq.getBuffer();
90ce3da70b43 Initial load
duke
parents:
diff changeset
    96
        buf.putInt(SET_COLOR);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    97
        buf.putInt(pixel);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    98
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    99
90ce3da70b43 Initial load
duke
parents:
diff changeset
   100
/************************* GradientPaint support ****************************/
90ce3da70b43 Initial load
duke
parents:
diff changeset
   101
90ce3da70b43 Initial load
duke
parents:
diff changeset
   102
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   103
     * Note: This code is factored out into a separate static method
90ce3da70b43 Initial load
duke
parents:
diff changeset
   104
     * so that it can be shared by both the Gradient and LinearGradient
90ce3da70b43 Initial load
duke
parents:
diff changeset
   105
     * implementations.  LinearGradient uses this code (for the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   106
     * two-color sRGB case only) because it can be much faster than the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   107
     * equivalent implementation that uses fragment shaders.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   108
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   109
     * We use OpenGL's texture coordinate generator to automatically
90ce3da70b43 Initial load
duke
parents:
diff changeset
   110
     * apply a smooth gradient (either cyclic or acyclic) to the geometry
90ce3da70b43 Initial load
duke
parents:
diff changeset
   111
     * being rendered.  This technique is almost identical to the one
90ce3da70b43 Initial load
duke
parents:
diff changeset
   112
     * described in the comments for BufferedPaints.setTexturePaint(),
90ce3da70b43 Initial load
duke
parents:
diff changeset
   113
     * except the calculations take place in one dimension instead of two.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   114
     * Instead of an anchor rectangle in the TexturePaint case, we use
90ce3da70b43 Initial load
duke
parents:
diff changeset
   115
     * the vector between the two GradientPaint end points in our
90ce3da70b43 Initial load
duke
parents:
diff changeset
   116
     * calculations.  The generator uses a single plane equation that
90ce3da70b43 Initial load
duke
parents:
diff changeset
   117
     * takes the (x,y) location (in device space) of the fragment being
90ce3da70b43 Initial load
duke
parents:
diff changeset
   118
     * rendered to calculate a (u) texture coordinate for that fragment:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   119
     *     u = Ax + By + Cz + Dw
90ce3da70b43 Initial load
duke
parents:
diff changeset
   120
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   121
     * The gradient renderer uses a two-pixel 1D texture where the first
90ce3da70b43 Initial load
duke
parents:
diff changeset
   122
     * pixel contains the first GradientPaint color, and the second pixel
90ce3da70b43 Initial load
duke
parents:
diff changeset
   123
     * contains the second GradientPaint color.  (Note that we use the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   124
     * GL_CLAMP_TO_EDGE wrapping mode for acyclic gradients so that we
90ce3da70b43 Initial load
duke
parents:
diff changeset
   125
     * clamp the colors properly at the extremes.)  The following diagram
90ce3da70b43 Initial load
duke
parents:
diff changeset
   126
     * attempts to show the layout of the texture containing the two
90ce3da70b43 Initial load
duke
parents:
diff changeset
   127
     * GradientPaint colors (C1 and C2):
90ce3da70b43 Initial load
duke
parents:
diff changeset
   128
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   129
     *                        +-----------------+
90ce3da70b43 Initial load
duke
parents:
diff changeset
   130
     *                        |   C1   |   C2   |
90ce3da70b43 Initial load
duke
parents:
diff changeset
   131
     *                        |        |        |
90ce3da70b43 Initial load
duke
parents:
diff changeset
   132
     *                        +-----------------+
90ce3da70b43 Initial load
duke
parents:
diff changeset
   133
     *                      u=0  .25  .5   .75  1
90ce3da70b43 Initial load
duke
parents:
diff changeset
   134
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   135
     * We calculate our plane equation constants (A,B,D) such that u=0.25
90ce3da70b43 Initial load
duke
parents:
diff changeset
   136
     * corresponds to the first GradientPaint end point in user space and
90ce3da70b43 Initial load
duke
parents:
diff changeset
   137
     * u=0.75 corresponds to the second end point.  This is somewhat
90ce3da70b43 Initial load
duke
parents:
diff changeset
   138
     * non-obvious, but since the gradient colors are generated by
90ce3da70b43 Initial load
duke
parents:
diff changeset
   139
     * interpolating between C1 and C2, we want the pure color at the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   140
     * end points, and we will get the pure color only when u correlates
90ce3da70b43 Initial load
duke
parents:
diff changeset
   141
     * to the center of a texel.  The following chart shows the expected
90ce3da70b43 Initial load
duke
parents:
diff changeset
   142
     * color for some sample values of u (where C' is the color halfway
90ce3da70b43 Initial load
duke
parents:
diff changeset
   143
     * between C1 and C2):
90ce3da70b43 Initial load
duke
parents:
diff changeset
   144
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   145
     *       u value      acyclic (GL_CLAMP)      cyclic (GL_REPEAT)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   146
     *       -------      ------------------      ------------------
90ce3da70b43 Initial load
duke
parents:
diff changeset
   147
     *        -0.25              C1                       C2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   148
     *         0.0               C1                       C'
90ce3da70b43 Initial load
duke
parents:
diff changeset
   149
     *         0.25              C1                       C1
90ce3da70b43 Initial load
duke
parents:
diff changeset
   150
     *         0.5               C'                       C'
90ce3da70b43 Initial load
duke
parents:
diff changeset
   151
     *         0.75              C2                       C2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   152
     *         1.0               C2                       C'
90ce3da70b43 Initial load
duke
parents:
diff changeset
   153
     *         1.25              C2                       C1
90ce3da70b43 Initial load
duke
parents:
diff changeset
   154
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   155
     * Original inspiration for this technique came from UMD's Agile2D
90ce3da70b43 Initial load
duke
parents:
diff changeset
   156
     * project (GradientManager.java).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   157
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   158
    private static void setGradientPaint(RenderQueue rq, AffineTransform at,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   159
                                         Color c1, Color c2,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   160
                                         Point2D pt1, Point2D pt2,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   161
                                         boolean isCyclic, boolean useMask)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   162
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   163
        // convert gradient colors to IntArgbPre format
90ce3da70b43 Initial load
duke
parents:
diff changeset
   164
        PixelConverter pc = PixelConverter.ArgbPre.instance;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   165
        int pixel1 = pc.rgbToPixel(c1.getRGB(), null);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   166
        int pixel2 = pc.rgbToPixel(c2.getRGB(), null);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   167
90ce3da70b43 Initial load
duke
parents:
diff changeset
   168
        // calculate plane equation constants
90ce3da70b43 Initial load
duke
parents:
diff changeset
   169
        double x = pt1.getX();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   170
        double y = pt1.getY();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   171
        at.translate(x, y);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   172
        // now gradient point 1 is at the origin
90ce3da70b43 Initial load
duke
parents:
diff changeset
   173
        x = pt2.getX() - x;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   174
        y = pt2.getY() - y;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   175
        double len = Math.sqrt(x * x + y * y);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   176
        at.rotate(x, y);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   177
        // now gradient point 2 is on the positive x-axis
90ce3da70b43 Initial load
duke
parents:
diff changeset
   178
        at.scale(2*len, 1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   179
        // now gradient point 2 is at (0.5, 0)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   180
        at.translate(-0.25, 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   181
        // now gradient point 1 is at (0.25, 0), point 2 is at (0.75, 0)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   182
90ce3da70b43 Initial load
duke
parents:
diff changeset
   183
        double p0, p1, p3;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   184
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   185
            at.invert();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   186
            p0 = at.getScaleX();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   187
            p1 = at.getShearX();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   188
            p3 = at.getTranslateX();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   189
        } catch (java.awt.geom.NoninvertibleTransformException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   190
            p0 = p1 = p3 = 0.0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   191
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   192
90ce3da70b43 Initial load
duke
parents:
diff changeset
   193
        // assert rq.lock.isHeldByCurrentThread();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   194
        rq.ensureCapacityAndAlignment(44, 12);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   195
        RenderBuffer buf = rq.getBuffer();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   196
        buf.putInt(SET_GRADIENT_PAINT);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   197
        buf.putInt(useMask ? 1 : 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   198
        buf.putInt(isCyclic ? 1 : 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   199
        buf.putDouble(p0).putDouble(p1).putDouble(p3);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   200
        buf.putInt(pixel1).putInt(pixel2);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   201
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   202
90ce3da70b43 Initial load
duke
parents:
diff changeset
   203
    private static void setGradientPaint(RenderQueue rq,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   204
                                         SunGraphics2D sg2d,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   205
                                         GradientPaint paint,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   206
                                         boolean useMask)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   207
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   208
        setGradientPaint(rq, (AffineTransform)sg2d.transform.clone(),
90ce3da70b43 Initial load
duke
parents:
diff changeset
   209
                         paint.getColor1(), paint.getColor2(),
90ce3da70b43 Initial load
duke
parents:
diff changeset
   210
                         paint.getPoint1(), paint.getPoint2(),
90ce3da70b43 Initial load
duke
parents:
diff changeset
   211
                         paint.isCyclic(), useMask);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   212
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   213
90ce3da70b43 Initial load
duke
parents:
diff changeset
   214
/************************** TexturePaint support ****************************/
90ce3da70b43 Initial load
duke
parents:
diff changeset
   215
90ce3da70b43 Initial load
duke
parents:
diff changeset
   216
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   217
     * We use OpenGL's texture coordinate generator to automatically
90ce3da70b43 Initial load
duke
parents:
diff changeset
   218
     * map the TexturePaint image to the geometry being rendered.  The
90ce3da70b43 Initial load
duke
parents:
diff changeset
   219
     * generator uses two separate plane equations that take the (x,y)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   220
     * location (in device space) of the fragment being rendered to
90ce3da70b43 Initial load
duke
parents:
diff changeset
   221
     * calculate (u,v) texture coordinates for that fragment:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   222
     *     u = Ax + By + Cz + Dw
90ce3da70b43 Initial load
duke
parents:
diff changeset
   223
     *     v = Ex + Fy + Gz + Hw
90ce3da70b43 Initial load
duke
parents:
diff changeset
   224
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   225
     * Since we use a 2D orthographic projection, we can assume that z=0
90ce3da70b43 Initial load
duke
parents:
diff changeset
   226
     * and w=1 for any fragment.  So we need to calculate appropriate
90ce3da70b43 Initial load
duke
parents:
diff changeset
   227
     * values for the plane equation constants (A,B,D) and (E,F,H) such
90ce3da70b43 Initial load
duke
parents:
diff changeset
   228
     * that {u,v}=0 for the top-left of the TexturePaint's anchor
90ce3da70b43 Initial load
duke
parents:
diff changeset
   229
     * rectangle and {u,v}=1 for the bottom-right of the anchor rectangle.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   230
     * We can easily make the texture image repeat for {u,v} values
90ce3da70b43 Initial load
duke
parents:
diff changeset
   231
     * outside the range [0,1] by specifying the GL_REPEAT texture wrap
90ce3da70b43 Initial load
duke
parents:
diff changeset
   232
     * mode.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   233
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   234
     * Calculating the plane equation constants is surprisingly simple.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   235
     * We can think of it as an inverse matrix operation that takes
90ce3da70b43 Initial load
duke
parents:
diff changeset
   236
     * device space coordinates and transforms them into user space
90ce3da70b43 Initial load
duke
parents:
diff changeset
   237
     * coordinates that correspond to a location relative to the anchor
90ce3da70b43 Initial load
duke
parents:
diff changeset
   238
     * rectangle.  First, we translate and scale the current user space
90ce3da70b43 Initial load
duke
parents:
diff changeset
   239
     * transform by applying the anchor rectangle bounds.  We then take
90ce3da70b43 Initial load
duke
parents:
diff changeset
   240
     * the inverse of this affine transform.  The rows of the resulting
90ce3da70b43 Initial load
duke
parents:
diff changeset
   241
     * inverse matrix correlate nicely to the plane equation constants
90ce3da70b43 Initial load
duke
parents:
diff changeset
   242
     * we were seeking.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   243
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   244
    private static void setTexturePaint(RenderQueue rq,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   245
                                        SunGraphics2D sg2d,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   246
                                        TexturePaint paint,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   247
                                        boolean useMask)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   248
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   249
        BufferedImage bi = paint.getImage();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   250
        SurfaceData dstData = sg2d.surfaceData;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   251
        SurfaceData srcData =
11080
7e18e343964e 7117914: Fix javac warnings in src/share/classes/sun/java2d
neugens
parents: 7668
diff changeset
   252
            dstData.getSourceSurfaceData(bi, SunGraphics2D.TRANSFORM_ISIDENT,
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   253
                                         CompositeType.SrcOver, null);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   254
        boolean filter =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   255
            (sg2d.interpolationType !=
90ce3da70b43 Initial load
duke
parents:
diff changeset
   256
             AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   257
90ce3da70b43 Initial load
duke
parents:
diff changeset
   258
        // calculate plane equation constants
90ce3da70b43 Initial load
duke
parents:
diff changeset
   259
        AffineTransform at = (AffineTransform)sg2d.transform.clone();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   260
        Rectangle2D anchor = paint.getAnchorRect();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   261
        at.translate(anchor.getX(), anchor.getY());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   262
        at.scale(anchor.getWidth(), anchor.getHeight());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   263
90ce3da70b43 Initial load
duke
parents:
diff changeset
   264
        double xp0, xp1, xp3, yp0, yp1, yp3;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   265
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   266
            at.invert();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   267
            xp0 = at.getScaleX();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   268
            xp1 = at.getShearX();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   269
            xp3 = at.getTranslateX();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   270
            yp0 = at.getShearY();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   271
            yp1 = at.getScaleY();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   272
            yp3 = at.getTranslateY();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   273
        } catch (java.awt.geom.NoninvertibleTransformException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   274
            xp0 = xp1 = xp3 = yp0 = yp1 = yp3 = 0.0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   275
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   276
90ce3da70b43 Initial load
duke
parents:
diff changeset
   277
        // assert rq.lock.isHeldByCurrentThread();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   278
        rq.ensureCapacityAndAlignment(68, 12);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   279
        RenderBuffer buf = rq.getBuffer();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   280
        buf.putInt(SET_TEXTURE_PAINT);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   281
        buf.putInt(useMask ? 1 : 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   282
        buf.putInt(filter ? 1 : 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   283
        buf.putLong(srcData.getNativeOps());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   284
        buf.putDouble(xp0).putDouble(xp1).putDouble(xp3);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   285
        buf.putDouble(yp0).putDouble(yp1).putDouble(yp3);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   286
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   287
90ce3da70b43 Initial load
duke
parents:
diff changeset
   288
/****************** Shared MultipleGradientPaint support ********************/
90ce3da70b43 Initial load
duke
parents:
diff changeset
   289
90ce3da70b43 Initial load
duke
parents:
diff changeset
   290
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   291
     * The maximum number of gradient "stops" supported by our native
90ce3da70b43 Initial load
duke
parents:
diff changeset
   292
     * fragment shader implementations.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   293
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   294
     * This value has been empirically determined and capped to allow
90ce3da70b43 Initial load
duke
parents:
diff changeset
   295
     * our native shaders to run on all shader-level graphics hardware,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   296
     * even on the older, more limited GPUs.  Even the oldest Nvidia
90ce3da70b43 Initial load
duke
parents:
diff changeset
   297
     * hardware could handle 16, or even 32 fractions without any problem.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   298
     * But the first-generation boards from ATI would fall back into
90ce3da70b43 Initial load
duke
parents:
diff changeset
   299
     * software mode (which is unusably slow) for values larger than 12;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   300
     * it appears that those boards do not have enough native registers
90ce3da70b43 Initial load
duke
parents:
diff changeset
   301
     * to support the number of array accesses required by our gradient
90ce3da70b43 Initial load
duke
parents:
diff changeset
   302
     * shaders.  So for now we will cap this value at 12, but we can
90ce3da70b43 Initial load
duke
parents:
diff changeset
   303
     * re-evaluate this in the future as hardware becomes more capable.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   304
     */
16734
da1901d79073 8000406: change files using @GenerateNativeHeader to use @Native
dxu
parents: 12813
diff changeset
   305
    @Native public static final int MULTI_MAX_FRACTIONS = 12;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   306
90ce3da70b43 Initial load
duke
parents:
diff changeset
   307
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   308
     * Helper function to convert a color component in sRGB space to
90ce3da70b43 Initial load
duke
parents:
diff changeset
   309
     * linear RGB space.  Copied directly from the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   310
     * MultipleGradientPaintContext class.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   311
     */
5579
1a5e995a710b 6307603: [X11] Use RENDER extension for complex operations done in software
ceisserer
parents: 2
diff changeset
   312
    public static int convertSRGBtoLinearRGB(int color) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   313
        float input, output;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   314
90ce3da70b43 Initial load
duke
parents:
diff changeset
   315
        input = color / 255.0f;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   316
        if (input <= 0.04045f) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   317
            output = input / 12.92f;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   318
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   319
            output = (float)Math.pow((input + 0.055) / 1.055, 2.4);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   320
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   321
90ce3da70b43 Initial load
duke
parents:
diff changeset
   322
        return Math.round(output * 255.0f);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   323
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   324
90ce3da70b43 Initial load
duke
parents:
diff changeset
   325
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   326
     * Helper function to convert a (non-premultiplied) Color in sRGB
90ce3da70b43 Initial load
duke
parents:
diff changeset
   327
     * space to an IntArgbPre pixel value, optionally in linear RGB space.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   328
     * Based on the PixelConverter.ArgbPre.rgbToPixel() method.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   329
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   330
    private static int colorToIntArgbPrePixel(Color c, boolean linear) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   331
        int rgb = c.getRGB();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   332
        if (!linear && ((rgb >> 24) == -1)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   333
            return rgb;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   334
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   335
        int a = rgb >>> 24;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   336
        int r = (rgb >> 16) & 0xff;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   337
        int g = (rgb >>  8) & 0xff;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   338
        int b = (rgb      ) & 0xff;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   339
        if (linear) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   340
            r = convertSRGBtoLinearRGB(r);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   341
            g = convertSRGBtoLinearRGB(g);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   342
            b = convertSRGBtoLinearRGB(b);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   343
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   344
        int a2 = a + (a >> 7);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   345
        r = (r * a2) >> 8;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   346
        g = (g * a2) >> 8;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   347
        b = (b * a2) >> 8;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   348
        return ((a << 24) | (r << 16) | (g << 8) | (b));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   349
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   350
90ce3da70b43 Initial load
duke
parents:
diff changeset
   351
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   352
     * Converts the given array of Color objects into an int array
90ce3da70b43 Initial load
duke
parents:
diff changeset
   353
     * containing IntArgbPre pixel values.  If the linear parameter
90ce3da70b43 Initial load
duke
parents:
diff changeset
   354
     * is true, the Color values will be converted into a linear RGB
90ce3da70b43 Initial load
duke
parents:
diff changeset
   355
     * color space before being returned.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   356
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   357
    private static int[] convertToIntArgbPrePixels(Color[] colors,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   358
                                                   boolean linear)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   359
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   360
        int[] pixels = new int[colors.length];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   361
        for (int i = 0; i < colors.length; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   362
            pixels[i] = colorToIntArgbPrePixel(colors[i], linear);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   363
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   364
        return pixels;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   365
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   366
90ce3da70b43 Initial load
duke
parents:
diff changeset
   367
/********************** LinearGradientPaint support *************************/
90ce3da70b43 Initial load
duke
parents:
diff changeset
   368
90ce3da70b43 Initial load
duke
parents:
diff changeset
   369
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   370
     * This method uses techniques that are nearly identical to those
90ce3da70b43 Initial load
duke
parents:
diff changeset
   371
     * employed in setGradientPaint() above.  The primary difference
90ce3da70b43 Initial load
duke
parents:
diff changeset
   372
     * is that at the native level we use a fragment shader to manually
90ce3da70b43 Initial load
duke
parents:
diff changeset
   373
     * apply the plane equation constants to the current fragment position
90ce3da70b43 Initial load
duke
parents:
diff changeset
   374
     * to calculate the gradient position in the range [0,1] (the native
90ce3da70b43 Initial load
duke
parents:
diff changeset
   375
     * code for GradientPaint does the same, except that it uses OpenGL's
90ce3da70b43 Initial load
duke
parents:
diff changeset
   376
     * automatic texture coordinate generation facilities).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   377
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   378
     * One other minor difference worth mentioning is that
90ce3da70b43 Initial load
duke
parents:
diff changeset
   379
     * setGradientPaint() calculates the plane equation constants
90ce3da70b43 Initial load
duke
parents:
diff changeset
   380
     * such that the gradient end points are positioned at 0.25 and 0.75
90ce3da70b43 Initial load
duke
parents:
diff changeset
   381
     * (for reasons discussed in the comments for that method).  In
90ce3da70b43 Initial load
duke
parents:
diff changeset
   382
     * contrast, for LinearGradientPaint we setup the equation constants
90ce3da70b43 Initial load
duke
parents:
diff changeset
   383
     * such that the gradient end points fall at 0.0 and 1.0.  The
90ce3da70b43 Initial load
duke
parents:
diff changeset
   384
     * reason for this difference is that in the fragment shader we
90ce3da70b43 Initial load
duke
parents:
diff changeset
   385
     * have more control over how the gradient values are interpreted
90ce3da70b43 Initial load
duke
parents:
diff changeset
   386
     * (depending on the paint's CycleMethod).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   387
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   388
    private static void setLinearGradientPaint(RenderQueue rq,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   389
                                               SunGraphics2D sg2d,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   390
                                               LinearGradientPaint paint,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   391
                                               boolean useMask)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   392
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   393
        boolean linear =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   394
            (paint.getColorSpace() == ColorSpaceType.LINEAR_RGB);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   395
        Color[] colors = paint.getColors();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   396
        int numStops = colors.length;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   397
        Point2D pt1 = paint.getStartPoint();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   398
        Point2D pt2 = paint.getEndPoint();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   399
        AffineTransform at = paint.getTransform();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   400
        at.preConcatenate(sg2d.transform);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   401
90ce3da70b43 Initial load
duke
parents:
diff changeset
   402
        if (!linear && numStops == 2 &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   403
            paint.getCycleMethod() != CycleMethod.REPEAT)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   404
        {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   405
            // delegate to the optimized two-color gradient codepath
90ce3da70b43 Initial load
duke
parents:
diff changeset
   406
            boolean isCyclic =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   407
                (paint.getCycleMethod() != CycleMethod.NO_CYCLE);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   408
            setGradientPaint(rq, at,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   409
                             colors[0], colors[1],
90ce3da70b43 Initial load
duke
parents:
diff changeset
   410
                             pt1, pt2,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   411
                             isCyclic, useMask);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   412
            return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   413
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   414
90ce3da70b43 Initial load
duke
parents:
diff changeset
   415
        int cycleMethod = paint.getCycleMethod().ordinal();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   416
        float[] fractions = paint.getFractions();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   417
        int[] pixels = convertToIntArgbPrePixels(colors, linear);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   418
90ce3da70b43 Initial load
duke
parents:
diff changeset
   419
        // calculate plane equation constants
90ce3da70b43 Initial load
duke
parents:
diff changeset
   420
        double x = pt1.getX();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   421
        double y = pt1.getY();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   422
        at.translate(x, y);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   423
        // now gradient point 1 is at the origin
90ce3da70b43 Initial load
duke
parents:
diff changeset
   424
        x = pt2.getX() - x;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   425
        y = pt2.getY() - y;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   426
        double len = Math.sqrt(x * x + y * y);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   427
        at.rotate(x, y);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   428
        // now gradient point 2 is on the positive x-axis
90ce3da70b43 Initial load
duke
parents:
diff changeset
   429
        at.scale(len, 1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   430
        // now gradient point 1 is at (0.0, 0), point 2 is at (1.0, 0)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   431
90ce3da70b43 Initial load
duke
parents:
diff changeset
   432
        float p0, p1, p3;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   433
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   434
            at.invert();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   435
            p0 = (float)at.getScaleX();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   436
            p1 = (float)at.getShearX();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   437
            p3 = (float)at.getTranslateX();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   438
        } catch (java.awt.geom.NoninvertibleTransformException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   439
            p0 = p1 = p3 = 0.0f;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   440
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   441
90ce3da70b43 Initial load
duke
parents:
diff changeset
   442
        // assert rq.lock.isHeldByCurrentThread();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   443
        rq.ensureCapacity(20 + 12 + (numStops*4*2));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   444
        RenderBuffer buf = rq.getBuffer();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   445
        buf.putInt(SET_LINEAR_GRADIENT_PAINT);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   446
        buf.putInt(useMask ? 1 : 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   447
        buf.putInt(linear  ? 1 : 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   448
        buf.putInt(cycleMethod);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   449
        buf.putInt(numStops);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   450
        buf.putFloat(p0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   451
        buf.putFloat(p1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   452
        buf.putFloat(p3);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   453
        buf.put(fractions);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   454
        buf.put(pixels);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   455
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   456
90ce3da70b43 Initial load
duke
parents:
diff changeset
   457
/********************** RadialGradientPaint support *************************/
90ce3da70b43 Initial load
duke
parents:
diff changeset
   458
90ce3da70b43 Initial load
duke
parents:
diff changeset
   459
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   460
     * This method calculates six m** values and a focusX value that
90ce3da70b43 Initial load
duke
parents:
diff changeset
   461
     * are used by the native fragment shader.  These techniques are
90ce3da70b43 Initial load
duke
parents:
diff changeset
   462
     * based on a whitepaper by Daniel Rice on radial gradient performance
90ce3da70b43 Initial load
duke
parents:
diff changeset
   463
     * (attached to the bug report for 6521533).  One can refer to that
90ce3da70b43 Initial load
duke
parents:
diff changeset
   464
     * document for the complete set of formulas and calculations, but
90ce3da70b43 Initial load
duke
parents:
diff changeset
   465
     * the basic goal is to compose a transform that will convert an
90ce3da70b43 Initial load
duke
parents:
diff changeset
   466
     * (x,y) position in device space into a "u" value that represents
90ce3da70b43 Initial load
duke
parents:
diff changeset
   467
     * the relative distance to the gradient focus point.  The resulting
90ce3da70b43 Initial load
duke
parents:
diff changeset
   468
     * value can be used to look up the appropriate color by linearly
90ce3da70b43 Initial load
duke
parents:
diff changeset
   469
     * interpolating between the two nearest colors in the gradient.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   470
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   471
    private static void setRadialGradientPaint(RenderQueue rq,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   472
                                               SunGraphics2D sg2d,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   473
                                               RadialGradientPaint paint,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   474
                                               boolean useMask)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   475
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   476
        boolean linear =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   477
            (paint.getColorSpace() == ColorSpaceType.LINEAR_RGB);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   478
        int cycleMethod = paint.getCycleMethod().ordinal();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   479
        float[] fractions = paint.getFractions();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   480
        Color[] colors = paint.getColors();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   481
        int numStops = colors.length;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   482
        int[] pixels = convertToIntArgbPrePixels(colors, linear);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   483
        Point2D center = paint.getCenterPoint();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   484
        Point2D focus = paint.getFocusPoint();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   485
        float radius = paint.getRadius();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   486
90ce3da70b43 Initial load
duke
parents:
diff changeset
   487
        // save original (untransformed) center and focus points
90ce3da70b43 Initial load
duke
parents:
diff changeset
   488
        double cx = center.getX();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   489
        double cy = center.getY();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   490
        double fx = focus.getX();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   491
        double fy = focus.getY();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   492
90ce3da70b43 Initial load
duke
parents:
diff changeset
   493
        // transform from gradient coords to device coords
90ce3da70b43 Initial load
duke
parents:
diff changeset
   494
        AffineTransform at = paint.getTransform();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   495
        at.preConcatenate(sg2d.transform);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   496
        focus = at.transform(focus, focus);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   497
90ce3da70b43 Initial load
duke
parents:
diff changeset
   498
        // transform unit circle to gradient coords; we start with the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   499
        // unit circle (center=(0,0), focus on positive x-axis, radius=1)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   500
        // and then transform into gradient space
90ce3da70b43 Initial load
duke
parents:
diff changeset
   501
        at.translate(cx, cy);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   502
        at.rotate(fx - cx, fy - cy);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   503
        at.scale(radius, radius);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   504
90ce3da70b43 Initial load
duke
parents:
diff changeset
   505
        // invert to get mapping from device coords to unit circle
90ce3da70b43 Initial load
duke
parents:
diff changeset
   506
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   507
            at.invert();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   508
        } catch (Exception e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   509
            at.setToScale(0.0, 0.0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   510
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   511
        focus = at.transform(focus, focus);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   512
90ce3da70b43 Initial load
duke
parents:
diff changeset
   513
        // clamp the focus point so that it does not rest on, or outside
90ce3da70b43 Initial load
duke
parents:
diff changeset
   514
        // of, the circumference of the gradient circle
90ce3da70b43 Initial load
duke
parents:
diff changeset
   515
        fx = Math.min(focus.getX(), 0.99);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   516
90ce3da70b43 Initial load
duke
parents:
diff changeset
   517
        // assert rq.lock.isHeldByCurrentThread();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   518
        rq.ensureCapacity(20 + 28 + (numStops*4*2));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   519
        RenderBuffer buf = rq.getBuffer();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   520
        buf.putInt(SET_RADIAL_GRADIENT_PAINT);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   521
        buf.putInt(useMask ? 1 : 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   522
        buf.putInt(linear  ? 1 : 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   523
        buf.putInt(numStops);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   524
        buf.putInt(cycleMethod);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   525
        buf.putFloat((float)at.getScaleX());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   526
        buf.putFloat((float)at.getShearX());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   527
        buf.putFloat((float)at.getTranslateX());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   528
        buf.putFloat((float)at.getShearY());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   529
        buf.putFloat((float)at.getScaleY());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   530
        buf.putFloat((float)at.getTranslateY());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   531
        buf.putFloat((float)fx);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   532
        buf.put(fractions);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   533
        buf.put(pixels);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   534
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   535
}