/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
public class BufferedPaints {
{
} else {
switch (sg2d.paintState) {
case SunGraphics2D.PAINT_GRADIENT:
break;
break;
break;
case SunGraphics2D.PAINT_TEXTURE:
break;
default:
break;
}
}
}
// assert rq.lock.isHeldByCurrentThread();
}
/****************************** Color support *******************************/
// assert rq.lock.isHeldByCurrentThread();
}
/************************* GradientPaint support ****************************/
/**
* Note: This code is factored out into a separate static method
* so that it can be shared by both the Gradient and LinearGradient
* implementations. LinearGradient uses this code (for the
* two-color sRGB case only) because it can be much faster than the
* equivalent implementation that uses fragment shaders.
*
* We use OpenGL's texture coordinate generator to automatically
* apply a smooth gradient (either cyclic or acyclic) to the geometry
* being rendered. This technique is almost identical to the one
* described in the comments for BufferedPaints.setTexturePaint(),
* except the calculations take place in one dimension instead of two.
* Instead of an anchor rectangle in the TexturePaint case, we use
* the vector between the two GradientPaint end points in our
* calculations. The generator uses a single plane equation that
* takes the (x,y) location (in device space) of the fragment being
* rendered to calculate a (u) texture coordinate for that fragment:
* u = Ax + By + Cz + Dw
*
* The gradient renderer uses a two-pixel 1D texture where the first
* pixel contains the first GradientPaint color, and the second pixel
* contains the second GradientPaint color. (Note that we use the
* GL_CLAMP_TO_EDGE wrapping mode for acyclic gradients so that we
* clamp the colors properly at the extremes.) The following diagram
* attempts to show the layout of the texture containing the two
* GradientPaint colors (C1 and C2):
*
* +-----------------+
* | C1 | C2 |
* | | |
* +-----------------+
* u=0 .25 .5 .75 1
*
* We calculate our plane equation constants (A,B,D) such that u=0.25
* corresponds to the first GradientPaint end point in user space and
* u=0.75 corresponds to the second end point. This is somewhat
* non-obvious, but since the gradient colors are generated by
* interpolating between C1 and C2, we want the pure color at the
* end points, and we will get the pure color only when u correlates
* to the center of a texel. The following chart shows the expected
* color for some sample values of u (where C' is the color halfway
* between C1 and C2):
*
* u value acyclic (GL_CLAMP) cyclic (GL_REPEAT)
* ------- ------------------ ------------------
* -0.25 C1 C2
* 0.0 C1 C'
* 0.25 C1 C1
* 0.5 C' C'
* 0.75 C2 C2
* 1.0 C2 C'
* 1.25 C2 C1
*
* Original inspiration for this technique came from UMD's Agile2D
* project (GradientManager.java).
*/
{
// convert gradient colors to IntArgbPre format
// calculate plane equation constants
// now gradient point 1 is at the origin
// now gradient point 2 is on the positive x-axis
// now gradient point 2 is at (0.5, 0)
// now gradient point 1 is at (0.25, 0), point 2 is at (0.75, 0)
try {
}
// assert rq.lock.isHeldByCurrentThread();
}
boolean useMask)
{
}
/************************** TexturePaint support ****************************/
/**
* We use OpenGL's texture coordinate generator to automatically
* map the TexturePaint image to the geometry being rendered. The
* generator uses two separate plane equations that take the (x,y)
* location (in device space) of the fragment being rendered to
* calculate (u,v) texture coordinates for that fragment:
* u = Ax + By + Cz + Dw
* v = Ex + Fy + Gz + Hw
*
* Since we use a 2D orthographic projection, we can assume that z=0
* and w=1 for any fragment. So we need to calculate appropriate
* values for the plane equation constants (A,B,D) and (E,F,H) such
* that {u,v}=0 for the top-left of the TexturePaint's anchor
* rectangle and {u,v}=1 for the bottom-right of the anchor rectangle.
* We can easily make the texture image repeat for {u,v} values
* outside the range [0,1] by specifying the GL_REPEAT texture wrap
* mode.
*
* Calculating the plane equation constants is surprisingly simple.
* We can think of it as an inverse matrix operation that takes
* device space coordinates and transforms them into user space
* coordinates that correspond to a location relative to the anchor
* rectangle. First, we translate and scale the current user space
* transform by applying the anchor rectangle bounds. We then take
* the inverse of this affine transform. The rows of the resulting
* inverse matrix correlate nicely to the plane equation constants
* we were seeking.
*/
boolean useMask)
{
boolean filter =
// calculate plane equation constants
try {
}
// assert rq.lock.isHeldByCurrentThread();
}
/****************** Shared MultipleGradientPaint support ********************/
/**
* The maximum number of gradient "stops" supported by our native
* fragment shader implementations.
*
* This value has been empirically determined and capped to allow
* our native shaders to run on all shader-level graphics hardware,
* even on the older, more limited GPUs. Even the oldest Nvidia
* hardware could handle 16, or even 32 fractions without any problem.
* But the first-generation boards from ATI would fall back into
* software mode (which is unusably slow) for values larger than 12;
* it appears that those boards do not have enough native registers
* to support the number of array accesses required by our gradient
* shaders. So for now we will cap this value at 12, but we can
* re-evaluate this in the future as hardware becomes more capable.
*/
/**
* Helper function to convert a color component in sRGB space to
* linear RGB space. Copied directly from the
* MultipleGradientPaintContext class.
*/
if (input <= 0.04045f) {
} else {
}
}
/**
* Helper function to convert a (non-premultiplied) Color in sRGB
* space to an IntArgbPre pixel value, optionally in linear RGB space.
* Based on the PixelConverter.ArgbPre.rgbToPixel() method.
*/
return rgb;
}
int a = rgb >>> 24;
int b = (rgb ) & 0xff;
if (linear) {
r = convertSRGBtoLinearRGB(r);
g = convertSRGBtoLinearRGB(g);
b = convertSRGBtoLinearRGB(b);
}
int a2 = a + (a >> 7);
r = (r * a2) >> 8;
g = (g * a2) >> 8;
b = (b * a2) >> 8;
return ((a << 24) | (r << 16) | (g << 8) | (b));
}
/**
* Converts the given array of Color objects into an int array
* containing IntArgbPre pixel values. If the linear parameter
* is true, the Color values will be converted into a linear RGB
* color space before being returned.
*/
boolean linear)
{
}
return pixels;
}
/********************** LinearGradientPaint support *************************/
/**
* 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).
*/
boolean useMask)
{
boolean linear =
{
// delegate to the optimized two-color gradient codepath
boolean isCyclic =
return;
}
// calculate plane equation constants
// now gradient point 1 is at the origin
// now gradient point 2 is on the positive x-axis
// now gradient point 1 is at (0.0, 0), point 2 is at (1.0, 0)
try {
}
// assert rq.lock.isHeldByCurrentThread();
}
/********************** RadialGradientPaint support *************************/
/**
* 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.
*/
boolean useMask)
{
boolean linear =
// save original (untransformed) center and focus points
// transform from gradient coords to device coords
// 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
// invert to get mapping from device coords to unit circle
try {
} catch (Exception e) {
}
// clamp the focus point so that it does not rest on, or outside
// of, the circumference of the gradient circle
// assert rq.lock.isHeldByCurrentThread();
}
}