Java Code Examples for java.awt.MultipleGradientPaint.ColorSpaceType#LINEAR_RGB

The following examples show how to use java.awt.MultipleGradientPaint.ColorSpaceType#LINEAR_RGB . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: D3DPaints.java    From jdk8u_jdk with GNU General Public License v2.0 6 votes vote down vote up
@Override
boolean isPaintValid(SunGraphics2D sg2d) {
    LinearGradientPaint paint = (LinearGradientPaint)sg2d.paint;

    if (paint.getFractions().length == 2 &&
        paint.getCycleMethod() != CycleMethod.REPEAT &&
        paint.getColorSpace() != ColorSpaceType.LINEAR_RGB)
    {
        D3DSurfaceData dstData = (D3DSurfaceData)sg2d.surfaceData;
        D3DGraphicsDevice gd = (D3DGraphicsDevice)
            dstData.getDeviceConfiguration().getDevice();
        if (gd.isCapPresent(CAPS_LCD_SHADER)) {
            // we can delegate to the optimized two-color gradient
            // codepath, which should be faster
            return true;
        }
    }

    return super.isPaintValid(sg2d);
}
 
Example 2
Source File: MultipleGradientPaintContext.java    From jdk-1.7-annotated with Apache License 2.0 5 votes vote down vote up
/**
 * SLOW LOOKUP METHOD
 *
 * This method calculates the gradient color values for each interval and
 * places each into its own 255 size array.  The arrays are stored in
 * gradients[][].  (255 is used because this is the maximum number of
 * unique colors between 2 arbitrary colors in a 24 bit color system.)
 *
 * This method uses the minimum amount of space (only 255 * number of
 * intervals), but it aggravates the lookup procedure, because now we
 * have to find out which interval to select, then calculate the index
 * within that interval.  This causes a significant performance hit,
 * because it requires this calculation be done for every point in
 * the rendering loop.
 *
 * For those of you who are interested, this is a classic example of the
 * time-space tradeoff.
 */
private void calculateMultipleArrayGradient(Color[] colors) {
    // set the flag so we know later it is a non-simple lookup
    isSimpleLookup = false;

    // 2 colors to interpolate
    int rgb1, rgb2;

    // for every interval (transition between 2 colors)
    for (int i = 0; i < gradients.length; i++){
        // create an array of the maximum theoretical size for
        // each interval
        gradients[i] = new int[GRADIENT_SIZE];

        // get the the 2 colors
        rgb1 = colors[i].getRGB();
        rgb2 = colors[i+1].getRGB();

        // fill this array with the colors in between rgb1 and rgb2
        interpolate(rgb1, rgb2, gradients[i]);

        // if the colors are opaque, transparency should still
        // be 0xff000000
        transparencyTest &= rgb1;
        transparencyTest &= rgb2;
    }

    // if interpolation occurred in Linear RGB space, convert the
    // gradients back to SRGB using the lookup table
    if (colorSpace == ColorSpaceType.LINEAR_RGB) {
        for (int j = 0; j < gradients.length; j++) {
            for (int i = 0; i < gradients[j].length; i++) {
                gradients[j][i] =
                    convertEntireColorLinearRGBtoSRGB(gradients[j][i]);
            }
        }
    }
}
 
Example 3
Source File: OGLPaints.java    From openjdk-8-source with GNU General Public License v2.0 5 votes vote down vote up
@Override
boolean isPaintValid(SunGraphics2D sg2d) {
    LinearGradientPaint paint = (LinearGradientPaint)sg2d.paint;

    if (paint.getFractions().length == 2 &&
        paint.getCycleMethod() != CycleMethod.REPEAT &&
        paint.getColorSpace() != ColorSpaceType.LINEAR_RGB)
    {
        // we can delegate to the optimized two-color gradient
        // codepath, which does not require fragment shader support
        return true;
    }

    return super.isPaintValid(sg2d);
}
 
Example 4
Source File: MultipleGradientPaintContext.java    From jdk8u-jdk with GNU General Public License v2.0 5 votes vote down vote up
/**
 * SLOW LOOKUP METHOD
 *
 * This method calculates the gradient color values for each interval and
 * places each into its own 255 size array.  The arrays are stored in
 * gradients[][].  (255 is used because this is the maximum number of
 * unique colors between 2 arbitrary colors in a 24 bit color system.)
 *
 * This method uses the minimum amount of space (only 255 * number of
 * intervals), but it aggravates the lookup procedure, because now we
 * have to find out which interval to select, then calculate the index
 * within that interval.  This causes a significant performance hit,
 * because it requires this calculation be done for every point in
 * the rendering loop.
 *
 * For those of you who are interested, this is a classic example of the
 * time-space tradeoff.
 */
private void calculateMultipleArrayGradient(Color[] colors) {
    // set the flag so we know later it is a non-simple lookup
    isSimpleLookup = false;

    // 2 colors to interpolate
    int rgb1, rgb2;

    // for every interval (transition between 2 colors)
    for (int i = 0; i < gradients.length; i++){
        // create an array of the maximum theoretical size for
        // each interval
        gradients[i] = new int[GRADIENT_SIZE];

        // get the the 2 colors
        rgb1 = colors[i].getRGB();
        rgb2 = colors[i+1].getRGB();

        // fill this array with the colors in between rgb1 and rgb2
        interpolate(rgb1, rgb2, gradients[i]);

        // if the colors are opaque, transparency should still
        // be 0xff000000
        transparencyTest &= rgb1;
        transparencyTest &= rgb2;
    }

    // if interpolation occurred in Linear RGB space, convert the
    // gradients back to SRGB using the lookup table
    if (colorSpace == ColorSpaceType.LINEAR_RGB) {
        for (int j = 0; j < gradients.length; j++) {
            for (int i = 0; i < gradients[j].length; i++) {
                gradients[j][i] =
                    convertEntireColorLinearRGBtoSRGB(gradients[j][i]);
            }
        }
    }
}
 
Example 5
Source File: OGLPaints.java    From jdk8u-jdk with GNU General Public License v2.0 5 votes vote down vote up
@Override
boolean isPaintValid(SunGraphics2D sg2d) {
    LinearGradientPaint paint = (LinearGradientPaint)sg2d.paint;

    if (paint.getFractions().length == 2 &&
        paint.getCycleMethod() != CycleMethod.REPEAT &&
        paint.getColorSpace() != ColorSpaceType.LINEAR_RGB)
    {
        // we can delegate to the optimized two-color gradient
        // codepath, which does not require fragment shader support
        return true;
    }

    return super.isPaintValid(sg2d);
}
 
Example 6
Source File: MultipleGradientPaintContext.java    From openjdk-jdk8u with GNU General Public License v2.0 5 votes vote down vote up
/**
 * SLOW LOOKUP METHOD
 *
 * This method calculates the gradient color values for each interval and
 * places each into its own 255 size array.  The arrays are stored in
 * gradients[][].  (255 is used because this is the maximum number of
 * unique colors between 2 arbitrary colors in a 24 bit color system.)
 *
 * This method uses the minimum amount of space (only 255 * number of
 * intervals), but it aggravates the lookup procedure, because now we
 * have to find out which interval to select, then calculate the index
 * within that interval.  This causes a significant performance hit,
 * because it requires this calculation be done for every point in
 * the rendering loop.
 *
 * For those of you who are interested, this is a classic example of the
 * time-space tradeoff.
 */
private void calculateMultipleArrayGradient(Color[] colors) {
    // set the flag so we know later it is a non-simple lookup
    isSimpleLookup = false;

    // 2 colors to interpolate
    int rgb1, rgb2;

    // for every interval (transition between 2 colors)
    for (int i = 0; i < gradients.length; i++){
        // create an array of the maximum theoretical size for
        // each interval
        gradients[i] = new int[GRADIENT_SIZE];

        // get the the 2 colors
        rgb1 = colors[i].getRGB();
        rgb2 = colors[i+1].getRGB();

        // fill this array with the colors in between rgb1 and rgb2
        interpolate(rgb1, rgb2, gradients[i]);

        // if the colors are opaque, transparency should still
        // be 0xff000000
        transparencyTest &= rgb1;
        transparencyTest &= rgb2;
    }

    // if interpolation occurred in Linear RGB space, convert the
    // gradients back to SRGB using the lookup table
    if (colorSpace == ColorSpaceType.LINEAR_RGB) {
        for (int j = 0; j < gradients.length; j++) {
            for (int i = 0; i < gradients[j].length; i++) {
                gradients[j][i] =
                    convertEntireColorLinearRGBtoSRGB(gradients[j][i]);
            }
        }
    }
}
 
Example 7
Source File: MultipleGradientPaintContext.java    From Bytecoder with Apache License 2.0 5 votes vote down vote up
/**
 * SLOW LOOKUP METHOD
 *
 * This method calculates the gradient color values for each interval and
 * places each into its own 255 size array.  The arrays are stored in
 * gradients[][].  (255 is used because this is the maximum number of
 * unique colors between 2 arbitrary colors in a 24 bit color system.)
 *
 * This method uses the minimum amount of space (only 255 * number of
 * intervals), but it aggravates the lookup procedure, because now we
 * have to find out which interval to select, then calculate the index
 * within that interval.  This causes a significant performance hit,
 * because it requires this calculation be done for every point in
 * the rendering loop.
 *
 * For those of you who are interested, this is a classic example of the
 * time-space tradeoff.
 */
private void calculateMultipleArrayGradient(Color[] colors) {
    // set the flag so we know later it is a non-simple lookup
    isSimpleLookup = false;

    // 2 colors to interpolate
    int rgb1, rgb2;

    // for every interval (transition between 2 colors)
    for (int i = 0; i < gradients.length; i++){
        // create an array of the maximum theoretical size for
        // each interval
        gradients[i] = new int[GRADIENT_SIZE];

        // get the 2 colors
        rgb1 = colors[i].getRGB();
        rgb2 = colors[i+1].getRGB();

        // fill this array with the colors in between rgb1 and rgb2
        interpolate(rgb1, rgb2, gradients[i]);

        // if the colors are opaque, transparency should still
        // be 0xff000000
        transparencyTest &= rgb1;
        transparencyTest &= rgb2;
    }

    // if interpolation occurred in Linear RGB space, convert the
    // gradients back to SRGB using the lookup table
    if (colorSpace == ColorSpaceType.LINEAR_RGB) {
        for (int j = 0; j < gradients.length; j++) {
            for (int i = 0; i < gradients[j].length; i++) {
                gradients[j][i] =
                    convertEntireColorLinearRGBtoSRGB(gradients[j][i]);
            }
        }
    }
}
 
Example 8
Source File: MultipleGradientPaintContext.java    From dragonwell8_jdk with GNU General Public License v2.0 5 votes vote down vote up
/**
 * SLOW LOOKUP METHOD
 *
 * This method calculates the gradient color values for each interval and
 * places each into its own 255 size array.  The arrays are stored in
 * gradients[][].  (255 is used because this is the maximum number of
 * unique colors between 2 arbitrary colors in a 24 bit color system.)
 *
 * This method uses the minimum amount of space (only 255 * number of
 * intervals), but it aggravates the lookup procedure, because now we
 * have to find out which interval to select, then calculate the index
 * within that interval.  This causes a significant performance hit,
 * because it requires this calculation be done for every point in
 * the rendering loop.
 *
 * For those of you who are interested, this is a classic example of the
 * time-space tradeoff.
 */
private void calculateMultipleArrayGradient(Color[] colors) {
    // set the flag so we know later it is a non-simple lookup
    isSimpleLookup = false;

    // 2 colors to interpolate
    int rgb1, rgb2;

    // for every interval (transition between 2 colors)
    for (int i = 0; i < gradients.length; i++){
        // create an array of the maximum theoretical size for
        // each interval
        gradients[i] = new int[GRADIENT_SIZE];

        // get the the 2 colors
        rgb1 = colors[i].getRGB();
        rgb2 = colors[i+1].getRGB();

        // fill this array with the colors in between rgb1 and rgb2
        interpolate(rgb1, rgb2, gradients[i]);

        // if the colors are opaque, transparency should still
        // be 0xff000000
        transparencyTest &= rgb1;
        transparencyTest &= rgb2;
    }

    // if interpolation occurred in Linear RGB space, convert the
    // gradients back to SRGB using the lookup table
    if (colorSpace == ColorSpaceType.LINEAR_RGB) {
        for (int j = 0; j < gradients.length; j++) {
            for (int i = 0; i < gradients[j].length; i++) {
                gradients[j][i] =
                    convertEntireColorLinearRGBtoSRGB(gradients[j][i]);
            }
        }
    }
}
 
Example 9
Source File: OGLPaints.java    From hottub with GNU General Public License v2.0 5 votes vote down vote up
@Override
boolean isPaintValid(SunGraphics2D sg2d) {
    LinearGradientPaint paint = (LinearGradientPaint)sg2d.paint;

    if (paint.getFractions().length == 2 &&
        paint.getCycleMethod() != CycleMethod.REPEAT &&
        paint.getColorSpace() != ColorSpaceType.LINEAR_RGB)
    {
        // we can delegate to the optimized two-color gradient
        // codepath, which does not require fragment shader support
        return true;
    }

    return super.isPaintValid(sg2d);
}
 
Example 10
Source File: OGLPaints.java    From Bytecoder with Apache License 2.0 5 votes vote down vote up
@Override
boolean isPaintValid(SunGraphics2D sg2d) {
    LinearGradientPaint paint = (LinearGradientPaint)sg2d.paint;

    if (paint.getFractions().length == 2 &&
        paint.getCycleMethod() != CycleMethod.REPEAT &&
        paint.getColorSpace() != ColorSpaceType.LINEAR_RGB)
    {
        // we can delegate to the optimized two-color gradient
        // codepath, which does not require fragment shader support
        return true;
    }

    return super.isPaintValid(sg2d);
}
 
Example 11
Source File: OGLPaints.java    From openjdk-jdk9 with GNU General Public License v2.0 5 votes vote down vote up
@Override
boolean isPaintValid(SunGraphics2D sg2d) {
    LinearGradientPaint paint = (LinearGradientPaint)sg2d.paint;

    if (paint.getFractions().length == 2 &&
        paint.getCycleMethod() != CycleMethod.REPEAT &&
        paint.getColorSpace() != ColorSpaceType.LINEAR_RGB)
    {
        // we can delegate to the optimized two-color gradient
        // codepath, which does not require fragment shader support
        return true;
    }

    return super.isPaintValid(sg2d);
}
 
Example 12
Source File: MultipleGradientPaintContext.java    From JDKSourceCode1.8 with MIT License 4 votes vote down vote up
/**
 * FAST LOOKUP METHOD
 *
 * This method calculates the gradient color values and places them in a
 * single int array, gradient[].  It does this by allocating space for
 * each interval based on its size relative to the smallest interval in
 * the array.  The smallest interval is allocated 255 interpolated values
 * (the maximum number of unique in-between colors in a 24 bit color
 * system), and all other intervals are allocated
 * size = (255 * the ratio of their size to the smallest interval).
 *
 * This scheme expedites a speedy retrieval because the colors are
 * distributed along the array according to their user-specified
 * distribution.  All that is needed is a relative index from 0 to 1.
 *
 * The only problem with this method is that the possibility exists for
 * the array size to balloon in the case where there is a
 * disproportionately small gradient interval.  In this case the other
 * intervals will be allocated huge space, but much of that data is
 * redundant.  We thus need to use the space conserving scheme below.
 *
 * @param Imin the size of the smallest interval
 */
private void calculateSingleArrayGradient(Color[] colors, float Imin) {
    // set the flag so we know later it is a simple (fast) lookup
    isSimpleLookup = true;

    // 2 colors to interpolate
    int rgb1, rgb2;

    //the eventual size of the single array
    int gradientsTot = 1;

    // for every interval (transition between 2 colors)
    for (int i = 0; i < gradients.length; i++) {
        // create an array whose size is based on the ratio to the
        // smallest interval
        int nGradients = (int)((normalizedIntervals[i]/Imin)*255f);
        gradientsTot += nGradients;
        gradients[i] = new int[nGradients];

        // the 2 colors (keyframes) to interpolate between
        rgb1 = colors[i].getRGB();
        rgb2 = colors[i+1].getRGB();

        // fill this array with the colors in between rgb1 and rgb2
        interpolate(rgb1, rgb2, gradients[i]);

        // if the colors are opaque, transparency should still
        // be 0xff000000
        transparencyTest &= rgb1;
        transparencyTest &= rgb2;
    }

    // put all gradients in a single array
    gradient = new int[gradientsTot];
    int curOffset = 0;
    for (int i = 0; i < gradients.length; i++){
        System.arraycopy(gradients[i], 0, gradient,
                         curOffset, gradients[i].length);
        curOffset += gradients[i].length;
    }
    gradient[gradient.length-1] = colors[colors.length-1].getRGB();

    // if interpolation occurred in Linear RGB space, convert the
    // gradients back to sRGB using the lookup table
    if (colorSpace == ColorSpaceType.LINEAR_RGB) {
        for (int i = 0; i < gradient.length; i++) {
            gradient[i] = convertEntireColorLinearRGBtoSRGB(gradient[i]);
        }
    }

    fastGradientArraySize = gradient.length - 1;
}
 
Example 13
Source File: BufferedPaints.java    From jdk8u_jdk with GNU General Public License v2.0 4 votes vote down vote up
/**
 * This method uses techniques that are nearly identical to those
 * employed in setGradientPaint() above.  The primary difference
 * is that at the native level we use a fragment shader to manually
 * apply the plane equation constants to the current fragment position
 * to calculate the gradient position in the range [0,1] (the native
 * code for GradientPaint does the same, except that it uses OpenGL's
 * automatic texture coordinate generation facilities).
 *
 * One other minor difference worth mentioning is that
 * setGradientPaint() calculates the plane equation constants
 * such that the gradient end points are positioned at 0.25 and 0.75
 * (for reasons discussed in the comments for that method).  In
 * contrast, for LinearGradientPaint we setup the equation constants
 * such that the gradient end points fall at 0.0 and 1.0.  The
 * reason for this difference is that in the fragment shader we
 * have more control over how the gradient values are interpreted
 * (depending on the paint's CycleMethod).
 */
private static void setLinearGradientPaint(RenderQueue rq,
                                           SunGraphics2D sg2d,
                                           LinearGradientPaint paint,
                                           boolean useMask)
{
    boolean linear =
        (paint.getColorSpace() == ColorSpaceType.LINEAR_RGB);
    Color[] colors = paint.getColors();
    int numStops = colors.length;
    Point2D pt1 = paint.getStartPoint();
    Point2D pt2 = paint.getEndPoint();
    AffineTransform at = paint.getTransform();
    at.preConcatenate(sg2d.transform);

    if (!linear && numStops == 2 &&
        paint.getCycleMethod() != CycleMethod.REPEAT)
    {
        // delegate to the optimized two-color gradient codepath
        boolean isCyclic =
            (paint.getCycleMethod() != CycleMethod.NO_CYCLE);
        setGradientPaint(rq, at,
                         colors[0], colors[1],
                         pt1, pt2,
                         isCyclic, useMask);
        return;
    }

    int cycleMethod = paint.getCycleMethod().ordinal();
    float[] fractions = paint.getFractions();
    int[] pixels = convertToIntArgbPrePixels(colors, linear);

    // calculate plane equation constants
    double x = pt1.getX();
    double y = pt1.getY();
    at.translate(x, y);
    // now gradient point 1 is at the origin
    x = pt2.getX() - x;
    y = pt2.getY() - y;
    double len = Math.sqrt(x * x + y * y);
    at.rotate(x, y);
    // now gradient point 2 is on the positive x-axis
    at.scale(len, 1);
    // now gradient point 1 is at (0.0, 0), point 2 is at (1.0, 0)

    float p0, p1, p3;
    try {
        at.invert();
        p0 = (float)at.getScaleX();
        p1 = (float)at.getShearX();
        p3 = (float)at.getTranslateX();
    } catch (java.awt.geom.NoninvertibleTransformException e) {
        p0 = p1 = p3 = 0.0f;
    }

    // assert rq.lock.isHeldByCurrentThread();
    rq.ensureCapacity(20 + 12 + (numStops*4*2));
    RenderBuffer buf = rq.getBuffer();
    buf.putInt(SET_LINEAR_GRADIENT_PAINT);
    buf.putInt(useMask ? 1 : 0);
    buf.putInt(linear  ? 1 : 0);
    buf.putInt(cycleMethod);
    buf.putInt(numStops);
    buf.putFloat(p0);
    buf.putFloat(p1);
    buf.putFloat(p3);
    buf.put(fractions);
    buf.put(pixels);
}
 
Example 14
Source File: BufferedPaints.java    From dragonwell8_jdk with GNU General Public License v2.0 4 votes vote down vote up
/**
 * This method uses techniques that are nearly identical to those
 * employed in setGradientPaint() above.  The primary difference
 * is that at the native level we use a fragment shader to manually
 * apply the plane equation constants to the current fragment position
 * to calculate the gradient position in the range [0,1] (the native
 * code for GradientPaint does the same, except that it uses OpenGL's
 * automatic texture coordinate generation facilities).
 *
 * One other minor difference worth mentioning is that
 * setGradientPaint() calculates the plane equation constants
 * such that the gradient end points are positioned at 0.25 and 0.75
 * (for reasons discussed in the comments for that method).  In
 * contrast, for LinearGradientPaint we setup the equation constants
 * such that the gradient end points fall at 0.0 and 1.0.  The
 * reason for this difference is that in the fragment shader we
 * have more control over how the gradient values are interpreted
 * (depending on the paint's CycleMethod).
 */
private static void setLinearGradientPaint(RenderQueue rq,
                                           SunGraphics2D sg2d,
                                           LinearGradientPaint paint,
                                           boolean useMask)
{
    boolean linear =
        (paint.getColorSpace() == ColorSpaceType.LINEAR_RGB);
    Color[] colors = paint.getColors();
    int numStops = colors.length;
    Point2D pt1 = paint.getStartPoint();
    Point2D pt2 = paint.getEndPoint();
    AffineTransform at = paint.getTransform();
    at.preConcatenate(sg2d.transform);

    if (!linear && numStops == 2 &&
        paint.getCycleMethod() != CycleMethod.REPEAT)
    {
        // delegate to the optimized two-color gradient codepath
        boolean isCyclic =
            (paint.getCycleMethod() != CycleMethod.NO_CYCLE);
        setGradientPaint(rq, at,
                         colors[0], colors[1],
                         pt1, pt2,
                         isCyclic, useMask);
        return;
    }

    int cycleMethod = paint.getCycleMethod().ordinal();
    float[] fractions = paint.getFractions();
    int[] pixels = convertToIntArgbPrePixels(colors, linear);

    // calculate plane equation constants
    double x = pt1.getX();
    double y = pt1.getY();
    at.translate(x, y);
    // now gradient point 1 is at the origin
    x = pt2.getX() - x;
    y = pt2.getY() - y;
    double len = Math.sqrt(x * x + y * y);
    at.rotate(x, y);
    // now gradient point 2 is on the positive x-axis
    at.scale(len, 1);
    // now gradient point 1 is at (0.0, 0), point 2 is at (1.0, 0)

    float p0, p1, p3;
    try {
        at.invert();
        p0 = (float)at.getScaleX();
        p1 = (float)at.getShearX();
        p3 = (float)at.getTranslateX();
    } catch (java.awt.geom.NoninvertibleTransformException e) {
        p0 = p1 = p3 = 0.0f;
    }

    // assert rq.lock.isHeldByCurrentThread();
    rq.ensureCapacity(20 + 12 + (numStops*4*2));
    RenderBuffer buf = rq.getBuffer();
    buf.putInt(SET_LINEAR_GRADIENT_PAINT);
    buf.putInt(useMask ? 1 : 0);
    buf.putInt(linear  ? 1 : 0);
    buf.putInt(cycleMethod);
    buf.putInt(numStops);
    buf.putFloat(p0);
    buf.putFloat(p1);
    buf.putFloat(p3);
    buf.put(fractions);
    buf.put(pixels);
}
 
Example 15
Source File: BufferedPaints.java    From openjdk-jdk8u with GNU General Public License v2.0 4 votes vote down vote up
/**
 * This method calculates six m** values and a focusX value that
 * are used by the native fragment shader.  These techniques are
 * based on a whitepaper by Daniel Rice on radial gradient performance
 * (attached to the bug report for 6521533).  One can refer to that
 * document for the complete set of formulas and calculations, but
 * the basic goal is to compose a transform that will convert an
 * (x,y) position in device space into a "u" value that represents
 * the relative distance to the gradient focus point.  The resulting
 * value can be used to look up the appropriate color by linearly
 * interpolating between the two nearest colors in the gradient.
 */
private static void setRadialGradientPaint(RenderQueue rq,
                                           SunGraphics2D sg2d,
                                           RadialGradientPaint paint,
                                           boolean useMask)
{
    boolean linear =
        (paint.getColorSpace() == ColorSpaceType.LINEAR_RGB);
    int cycleMethod = paint.getCycleMethod().ordinal();
    float[] fractions = paint.getFractions();
    Color[] colors = paint.getColors();
    int numStops = colors.length;
    int[] pixels = convertToIntArgbPrePixels(colors, linear);
    Point2D center = paint.getCenterPoint();
    Point2D focus = paint.getFocusPoint();
    float radius = paint.getRadius();

    // save original (untransformed) center and focus points
    double cx = center.getX();
    double cy = center.getY();
    double fx = focus.getX();
    double fy = focus.getY();

    // transform from gradient coords to device coords
    AffineTransform at = paint.getTransform();
    at.preConcatenate(sg2d.transform);
    focus = at.transform(focus, focus);

    // transform unit circle to gradient coords; we start with the
    // unit circle (center=(0,0), focus on positive x-axis, radius=1)
    // and then transform into gradient space
    at.translate(cx, cy);
    at.rotate(fx - cx, fy - cy);
    at.scale(radius, radius);

    // invert to get mapping from device coords to unit circle
    try {
        at.invert();
    } catch (Exception e) {
        at.setToScale(0.0, 0.0);
    }
    focus = at.transform(focus, focus);

    // clamp the focus point so that it does not rest on, or outside
    // of, the circumference of the gradient circle
    fx = Math.min(focus.getX(), 0.99);

    // assert rq.lock.isHeldByCurrentThread();
    rq.ensureCapacity(20 + 28 + (numStops*4*2));
    RenderBuffer buf = rq.getBuffer();
    buf.putInt(SET_RADIAL_GRADIENT_PAINT);
    buf.putInt(useMask ? 1 : 0);
    buf.putInt(linear  ? 1 : 0);
    buf.putInt(numStops);
    buf.putInt(cycleMethod);
    buf.putFloat((float)at.getScaleX());
    buf.putFloat((float)at.getShearX());
    buf.putFloat((float)at.getTranslateX());
    buf.putFloat((float)at.getShearY());
    buf.putFloat((float)at.getScaleY());
    buf.putFloat((float)at.getTranslateY());
    buf.putFloat((float)fx);
    buf.put(fractions);
    buf.put(pixels);
}
 
Example 16
Source File: BufferedPaints.java    From openjdk-8 with GNU General Public License v2.0 4 votes vote down vote up
/**
 * This method uses techniques that are nearly identical to those
 * employed in setGradientPaint() above.  The primary difference
 * is that at the native level we use a fragment shader to manually
 * apply the plane equation constants to the current fragment position
 * to calculate the gradient position in the range [0,1] (the native
 * code for GradientPaint does the same, except that it uses OpenGL's
 * automatic texture coordinate generation facilities).
 *
 * One other minor difference worth mentioning is that
 * setGradientPaint() calculates the plane equation constants
 * such that the gradient end points are positioned at 0.25 and 0.75
 * (for reasons discussed in the comments for that method).  In
 * contrast, for LinearGradientPaint we setup the equation constants
 * such that the gradient end points fall at 0.0 and 1.0.  The
 * reason for this difference is that in the fragment shader we
 * have more control over how the gradient values are interpreted
 * (depending on the paint's CycleMethod).
 */
private static void setLinearGradientPaint(RenderQueue rq,
                                           SunGraphics2D sg2d,
                                           LinearGradientPaint paint,
                                           boolean useMask)
{
    boolean linear =
        (paint.getColorSpace() == ColorSpaceType.LINEAR_RGB);
    Color[] colors = paint.getColors();
    int numStops = colors.length;
    Point2D pt1 = paint.getStartPoint();
    Point2D pt2 = paint.getEndPoint();
    AffineTransform at = paint.getTransform();
    at.preConcatenate(sg2d.transform);

    if (!linear && numStops == 2 &&
        paint.getCycleMethod() != CycleMethod.REPEAT)
    {
        // delegate to the optimized two-color gradient codepath
        boolean isCyclic =
            (paint.getCycleMethod() != CycleMethod.NO_CYCLE);
        setGradientPaint(rq, at,
                         colors[0], colors[1],
                         pt1, pt2,
                         isCyclic, useMask);
        return;
    }

    int cycleMethod = paint.getCycleMethod().ordinal();
    float[] fractions = paint.getFractions();
    int[] pixels = convertToIntArgbPrePixels(colors, linear);

    // calculate plane equation constants
    double x = pt1.getX();
    double y = pt1.getY();
    at.translate(x, y);
    // now gradient point 1 is at the origin
    x = pt2.getX() - x;
    y = pt2.getY() - y;
    double len = Math.sqrt(x * x + y * y);
    at.rotate(x, y);
    // now gradient point 2 is on the positive x-axis
    at.scale(len, 1);
    // now gradient point 1 is at (0.0, 0), point 2 is at (1.0, 0)

    float p0, p1, p3;
    try {
        at.invert();
        p0 = (float)at.getScaleX();
        p1 = (float)at.getShearX();
        p3 = (float)at.getTranslateX();
    } catch (java.awt.geom.NoninvertibleTransformException e) {
        p0 = p1 = p3 = 0.0f;
    }

    // assert rq.lock.isHeldByCurrentThread();
    rq.ensureCapacity(20 + 12 + (numStops*4*2));
    RenderBuffer buf = rq.getBuffer();
    buf.putInt(SET_LINEAR_GRADIENT_PAINT);
    buf.putInt(useMask ? 1 : 0);
    buf.putInt(linear  ? 1 : 0);
    buf.putInt(cycleMethod);
    buf.putInt(numStops);
    buf.putFloat(p0);
    buf.putFloat(p1);
    buf.putFloat(p3);
    buf.put(fractions);
    buf.put(pixels);
}
 
Example 17
Source File: BufferedPaints.java    From openjdk-8 with GNU General Public License v2.0 4 votes vote down vote up
/**
 * This method calculates six m** values and a focusX value that
 * are used by the native fragment shader.  These techniques are
 * based on a whitepaper by Daniel Rice on radial gradient performance
 * (attached to the bug report for 6521533).  One can refer to that
 * document for the complete set of formulas and calculations, but
 * the basic goal is to compose a transform that will convert an
 * (x,y) position in device space into a "u" value that represents
 * the relative distance to the gradient focus point.  The resulting
 * value can be used to look up the appropriate color by linearly
 * interpolating between the two nearest colors in the gradient.
 */
private static void setRadialGradientPaint(RenderQueue rq,
                                           SunGraphics2D sg2d,
                                           RadialGradientPaint paint,
                                           boolean useMask)
{
    boolean linear =
        (paint.getColorSpace() == ColorSpaceType.LINEAR_RGB);
    int cycleMethod = paint.getCycleMethod().ordinal();
    float[] fractions = paint.getFractions();
    Color[] colors = paint.getColors();
    int numStops = colors.length;
    int[] pixels = convertToIntArgbPrePixels(colors, linear);
    Point2D center = paint.getCenterPoint();
    Point2D focus = paint.getFocusPoint();
    float radius = paint.getRadius();

    // save original (untransformed) center and focus points
    double cx = center.getX();
    double cy = center.getY();
    double fx = focus.getX();
    double fy = focus.getY();

    // transform from gradient coords to device coords
    AffineTransform at = paint.getTransform();
    at.preConcatenate(sg2d.transform);
    focus = at.transform(focus, focus);

    // transform unit circle to gradient coords; we start with the
    // unit circle (center=(0,0), focus on positive x-axis, radius=1)
    // and then transform into gradient space
    at.translate(cx, cy);
    at.rotate(fx - cx, fy - cy);
    at.scale(radius, radius);

    // invert to get mapping from device coords to unit circle
    try {
        at.invert();
    } catch (Exception e) {
        at.setToScale(0.0, 0.0);
    }
    focus = at.transform(focus, focus);

    // clamp the focus point so that it does not rest on, or outside
    // of, the circumference of the gradient circle
    fx = Math.min(focus.getX(), 0.99);

    // assert rq.lock.isHeldByCurrentThread();
    rq.ensureCapacity(20 + 28 + (numStops*4*2));
    RenderBuffer buf = rq.getBuffer();
    buf.putInt(SET_RADIAL_GRADIENT_PAINT);
    buf.putInt(useMask ? 1 : 0);
    buf.putInt(linear  ? 1 : 0);
    buf.putInt(numStops);
    buf.putInt(cycleMethod);
    buf.putFloat((float)at.getScaleX());
    buf.putFloat((float)at.getShearX());
    buf.putFloat((float)at.getTranslateX());
    buf.putFloat((float)at.getShearY());
    buf.putFloat((float)at.getScaleY());
    buf.putFloat((float)at.getTranslateY());
    buf.putFloat((float)fx);
    buf.put(fractions);
    buf.put(pixels);
}
 
Example 18
Source File: MultipleGradientPaintContext.java    From dragonwell8_jdk with GNU General Public License v2.0 4 votes vote down vote up
/**
 * This function is the meat of this class.  It calculates an array of
 * gradient colors based on an array of fractions and color values at
 * those fractions.
 */
private void calculateLookupData(Color[] colors) {
    Color[] normalizedColors;
    if (colorSpace == ColorSpaceType.LINEAR_RGB) {
        // create a new colors array
        normalizedColors = new Color[colors.length];
        // convert the colors using the lookup table
        for (int i = 0; i < colors.length; i++) {
            int argb = colors[i].getRGB();
            int a = argb >>> 24;
            int r = SRGBtoLinearRGB[(argb >> 16) & 0xff];
            int g = SRGBtoLinearRGB[(argb >>  8) & 0xff];
            int b = SRGBtoLinearRGB[(argb      ) & 0xff];
            normalizedColors[i] = new Color(r, g, b, a);
        }
    } else {
        // we can just use this array by reference since we do not
        // modify its values in the case of SRGB
        normalizedColors = colors;
    }

    // this will store the intervals (distances) between gradient stops
    normalizedIntervals = new float[fractions.length-1];

    // convert from fractions into intervals
    for (int i = 0; i < normalizedIntervals.length; i++) {
        // interval distance is equal to the difference in positions
        normalizedIntervals[i] = this.fractions[i+1] - this.fractions[i];
    }

    // initialize to be fully opaque for ANDing with colors
    transparencyTest = 0xff000000;

    // array of interpolation arrays
    gradients = new int[normalizedIntervals.length][];

    // find smallest interval
    float Imin = 1;
    for (int i = 0; i < normalizedIntervals.length; i++) {
        Imin = (Imin > normalizedIntervals[i]) ?
            normalizedIntervals[i] : Imin;
    }

    // Estimate the size of the entire gradients array.
    // This is to prevent a tiny interval from causing the size of array
    // to explode.  If the estimated size is too large, break to using
    // separate arrays for each interval, and using an indexing scheme at
    // look-up time.
    int estimatedSize = 0;
    for (int i = 0; i < normalizedIntervals.length; i++) {
        estimatedSize += (normalizedIntervals[i]/Imin) * GRADIENT_SIZE;
    }

    if (estimatedSize > MAX_GRADIENT_ARRAY_SIZE) {
        // slow method
        calculateMultipleArrayGradient(normalizedColors);
    } else {
        // fast method
        calculateSingleArrayGradient(normalizedColors, Imin);
    }

    // use the most "economical" model
    if ((transparencyTest >>> 24) == 0xff) {
        model = xrgbmodel;
    } else {
        model = ColorModel.getRGBdefault();
    }
}
 
Example 19
Source File: BufferedPaints.java    From jdk8u60 with GNU General Public License v2.0 4 votes vote down vote up
/**
 * This method uses techniques that are nearly identical to those
 * employed in setGradientPaint() above.  The primary difference
 * is that at the native level we use a fragment shader to manually
 * apply the plane equation constants to the current fragment position
 * to calculate the gradient position in the range [0,1] (the native
 * code for GradientPaint does the same, except that it uses OpenGL's
 * automatic texture coordinate generation facilities).
 *
 * One other minor difference worth mentioning is that
 * setGradientPaint() calculates the plane equation constants
 * such that the gradient end points are positioned at 0.25 and 0.75
 * (for reasons discussed in the comments for that method).  In
 * contrast, for LinearGradientPaint we setup the equation constants
 * such that the gradient end points fall at 0.0 and 1.0.  The
 * reason for this difference is that in the fragment shader we
 * have more control over how the gradient values are interpreted
 * (depending on the paint's CycleMethod).
 */
private static void setLinearGradientPaint(RenderQueue rq,
                                           SunGraphics2D sg2d,
                                           LinearGradientPaint paint,
                                           boolean useMask)
{
    boolean linear =
        (paint.getColorSpace() == ColorSpaceType.LINEAR_RGB);
    Color[] colors = paint.getColors();
    int numStops = colors.length;
    Point2D pt1 = paint.getStartPoint();
    Point2D pt2 = paint.getEndPoint();
    AffineTransform at = paint.getTransform();
    at.preConcatenate(sg2d.transform);

    if (!linear && numStops == 2 &&
        paint.getCycleMethod() != CycleMethod.REPEAT)
    {
        // delegate to the optimized two-color gradient codepath
        boolean isCyclic =
            (paint.getCycleMethod() != CycleMethod.NO_CYCLE);
        setGradientPaint(rq, at,
                         colors[0], colors[1],
                         pt1, pt2,
                         isCyclic, useMask);
        return;
    }

    int cycleMethod = paint.getCycleMethod().ordinal();
    float[] fractions = paint.getFractions();
    int[] pixels = convertToIntArgbPrePixels(colors, linear);

    // calculate plane equation constants
    double x = pt1.getX();
    double y = pt1.getY();
    at.translate(x, y);
    // now gradient point 1 is at the origin
    x = pt2.getX() - x;
    y = pt2.getY() - y;
    double len = Math.sqrt(x * x + y * y);
    at.rotate(x, y);
    // now gradient point 2 is on the positive x-axis
    at.scale(len, 1);
    // now gradient point 1 is at (0.0, 0), point 2 is at (1.0, 0)

    float p0, p1, p3;
    try {
        at.invert();
        p0 = (float)at.getScaleX();
        p1 = (float)at.getShearX();
        p3 = (float)at.getTranslateX();
    } catch (java.awt.geom.NoninvertibleTransformException e) {
        p0 = p1 = p3 = 0.0f;
    }

    // assert rq.lock.isHeldByCurrentThread();
    rq.ensureCapacity(20 + 12 + (numStops*4*2));
    RenderBuffer buf = rq.getBuffer();
    buf.putInt(SET_LINEAR_GRADIENT_PAINT);
    buf.putInt(useMask ? 1 : 0);
    buf.putInt(linear  ? 1 : 0);
    buf.putInt(cycleMethod);
    buf.putInt(numStops);
    buf.putFloat(p0);
    buf.putFloat(p1);
    buf.putFloat(p3);
    buf.put(fractions);
    buf.put(pixels);
}
 
Example 20
Source File: MultipleGradientPaintContext.java    From openjdk-jdk9 with GNU General Public License v2.0 4 votes vote down vote up
/**
 * This function is the meat of this class.  It calculates an array of
 * gradient colors based on an array of fractions and color values at
 * those fractions.
 */
private void calculateLookupData(Color[] colors) {
    Color[] normalizedColors;
    if (colorSpace == ColorSpaceType.LINEAR_RGB) {
        // create a new colors array
        normalizedColors = new Color[colors.length];
        // convert the colors using the lookup table
        for (int i = 0; i < colors.length; i++) {
            int argb = colors[i].getRGB();
            int a = argb >>> 24;
            int r = SRGBtoLinearRGB[(argb >> 16) & 0xff];
            int g = SRGBtoLinearRGB[(argb >>  8) & 0xff];
            int b = SRGBtoLinearRGB[(argb      ) & 0xff];
            normalizedColors[i] = new Color(r, g, b, a);
        }
    } else {
        // we can just use this array by reference since we do not
        // modify its values in the case of SRGB
        normalizedColors = colors;
    }

    // this will store the intervals (distances) between gradient stops
    normalizedIntervals = new float[fractions.length-1];

    // convert from fractions into intervals
    for (int i = 0; i < normalizedIntervals.length; i++) {
        // interval distance is equal to the difference in positions
        normalizedIntervals[i] = this.fractions[i+1] - this.fractions[i];
    }

    // initialize to be fully opaque for ANDing with colors
    transparencyTest = 0xff000000;

    // array of interpolation arrays
    gradients = new int[normalizedIntervals.length][];

    // find smallest interval
    float Imin = 1;
    for (int i = 0; i < normalizedIntervals.length; i++) {
        Imin = (Imin > normalizedIntervals[i]) ?
            normalizedIntervals[i] : Imin;
    }

    // Estimate the size of the entire gradients array.
    // This is to prevent a tiny interval from causing the size of array
    // to explode.  If the estimated size is too large, break to using
    // separate arrays for each interval, and using an indexing scheme at
    // look-up time.
    int estimatedSize = 0;
    for (int i = 0; i < normalizedIntervals.length; i++) {
        estimatedSize += (normalizedIntervals[i]/Imin) * GRADIENT_SIZE;
    }

    if (estimatedSize > MAX_GRADIENT_ARRAY_SIZE) {
        // slow method
        calculateMultipleArrayGradient(normalizedColors);
    } else {
        // fast method
        calculateSingleArrayGradient(normalizedColors, Imin);
    }

    // use the most "economical" model
    if ((transparencyTest >>> 24) == 0xff) {
        model = xrgbmodel;
    } else {
        model = ColorModel.getRGBdefault();
    }
}