/*
* 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.
*/
{
int x, int y,
{
if (isSimpleTranslate(sg)) {
}
if ((x | y) != 0) {
}
return true;
}
{
if (isSimpleTranslate(sg)) {
}
return true;
}
{
// Only accelerate scale if:
// - w/h positive values
// - no bgColor in operation
{
return true;
}
}
}
return true;
}
/*
* This method is only called in those circumstances where the
* operation has a non-null secondary transform specfied. Its
* role is to check for various optimizations based on the types
* of both the secondary and SG2D transforms and to do some
* quick calculations to avoid having to combine the transforms
*/
{
boolean checkfinalxform;
{
// First optimization - both are some kind of translate
// Combine the translations and check if interpolation is necessary.
{
return;
}
checkfinalxform = false;
{
// Second optimization - both are some kind of translate or scale
// Combine the scales and check if interpolation is necessary.
// Transform source bounds by extraAT,
// then translate the bounds again by x, y
// then transform the bounds again by sg.transform
double coords[] = new double[] {
};
coords[0] += x;
coords[1] += y;
coords[2] += x;
coords[3] += y;
{
return;
}
checkfinalxform = false;
} else {
checkfinalxform = true;
}
// Begin Transform
// Do not try any more optimizations if either of the cases
// above was tried as we have already verified that the
// resulting transform will not simplify.
if (checkfinalxform) {
// In this case neither of the above simple transform
// pairs was found so we will do some final tests on
// the final rendering transform which may be the
// simple product of two complex transforms.
} else {
}
}
/*
* This method is called with a final rendering transform that
* has combined all of the information about the Graphics2D
* transform attribute with the transformations specified by
* the arguments to the drawImage call.
* Its role is to see if the combined transform ends up being
* acceleratable by either a renderImageCopy or renderImageScale
* once all of the math is done.
*
* Note: The transform supplied here has an origin that is
* already adjusted to point to the device location where
* the (sx1, sy1) location of the source image should be placed.
*/
{
// Transform 3 source corners by tx and analyze them
// for simplified operations (Copy or Scale). Using
// 3 points lets us analyze any kind of transform,
// even transforms that involve very tiny amounts of
// rotation or skew to see if they degenerate to a
// simple scale or copy operation within the allowable
// error bounds.
// Note that we use (0,0,w,h) instead of (sx1,sy1,sx2,sy2)
// because the transform is already translated such that
// the origin is where sx1, sy1 should go.
double coords[] = new double[6];
/* index: 0 1 2 3 4 5 */
/* coord: (0, 0), (w, h), (0, h) */
// First test if the X coords of the transformed UL
// and LL points match and that the Y coords of the
// transformed LR and LL points also match.
// If they do then it is a "rectilinear" transform and
// tryCopyOrScale will make sure it is upright and
// integer-based.
{
return;
}
}
/*
* Check the bounding coordinates of the transformed source
* image to see if they fall on integer coordinates such
* that they will cause no interpolation anomalies if we
* use our simplified Blit or ScaledBlit operations instead
* of a full transform operation.
*/
double coords[])
{
// First check if width and height are very close to img w&h.
// Round location to nearest pixel and then test
// if it will cause interpolation anomalies.
{
return true;
}
}
// (For now) We can only use our ScaledBlits if the image
// is upright (i.e. dw & dh both > 0)
{
return true;
}
}
return false;
}
/*
* Return a BufferedImage of the requested type with the indicated
* subimage of the original image located at 0,0 in the new image.
* If a bgColor is supplied, composite the original image over that
* color with a SrcOver operation, otherwise make a SrcNoEa copy.
*/
{
}
return bimg;
}
{
bgColor);
bgColor);
// REMIND: Is this correct? Can this happen?
return;
}
}
// We cannot perform bg operations during transform so make
// an opaque temp image with the appropriate background
// and work from there.
// Temp image has appropriate subimage at 0,0 now.
bgColor);
}
/* We have no helper for this source image type.
* But we know that we do have helpers for both RGB and ARGB,
* so convert to one of those types depending on transparency.
* ARGB_PRE might be a better choice if the source image has
* alpha, but it may cause some recursion here since we only
* tend to have converters that convert to ARGB.
*/
// Temp image has appropriate subimage at 0,0 now.
null);
// assert(helper != null);
}
try {
} catch (NoninvertibleTransformException e) {
// Non-invertible transform means no output
return;
}
/*
* Find the maximum bounds on the destination that will be
* affected by the transformed source. First, transform all
* four corners of the source and then min and max the resulting
* destination coordinates of the transformed corners.
* Note that tx already has the offset to sx1,sy1 accounted
* for so we use the box (0, 0, sx2-sx1, sy2-sy1) as the
* source coordinates.
*/
double coords[] = new double[8];
/* corner: UL UR LL LR */
/* index: 0 1 2 3 4 5 6 7 */
/* coord: (0, 0), (w, 0), (0, h), (w, h) */
double d = coords[i];
d = coords[i+1];
}
/* NOTE: We either have, or we can make,
* a MaskBlit for any alpha composite type
*/
dstType);
/* NOTE: We can only use the native TransformHelper
* func to go directly to the dest if both the helper
* and the MaskBlit are native.
* All helpers are native at this point, but some MaskBlit
* objects are implemented in Java, so we need to check.
*/
// We can render directly.
return;
}
} else {
/* NOTE: We either have, or we can make,
* a Blit for any composite type, even Custom
*/
dstType);
}
// We need to transform to a temp image and then copy
// just the pieces that are valid data to the dest.
tmpType);
/*
* The helper function fills a temporary edges buffer
* for us with the bounding coordinates of each scanline
* in the following format:
*
* edges[0, 1] = [top y, bottom y)
* edges[2, 3] = [left x, right x) of top row
* ...
* edges[h*2, h*2+1] = [left x, right x) of bottom row
*
* all coordinates in the edges array will be relative to dx1, dy1
*
* edges thus has to be h*2+2 in length
*/
// It is important that edges[0]=edges[1]=0 when we call
// Transform in case it must return early and we would
// not want to render anything on an error condition.
/*
* Now copy the results, scanline by scanline, into the dest.
* The edges array helps us minimize the work.
*/
int index = 2;
continue;
}
relx1, y,
} else {
relx1, y,
}
}
}
// Render an image using only integer translation
// (no scale or transform or sub-pixel interpolated translations).
int w, int h)
{
int attempts = 0;
// Loop up to twice through; this gives us a chance to
// revalidate the surfaceData objects in case of an exception
// and try it once more
while (true) {
bgColor);
return false;
}
try {
return true;
} catch (NullPointerException e) {
{
// Something else caused the exception, throw it...
throw e;
}
return false;
// NOP if we have been disposed
} catch (InvalidPipeException e) {
// Always catch the exception; try this a couple of times
// and fail silently if the system is not yet ready to
// revalidate the source or dest surfaceData objects.
++attempts;
{
return false;
}
}
}
}
// Render an image using only integer scaling (no transform).
{
// Currently only NEAREST_NEIGHBOR interpolation is implemented
// for ScaledBlit operations.
return false;
}
int attempts = 0;
// Loop up to twice through; this gives us a chance to
// revalidate the surfaceData objects in case of an exception
// and try it once more
while (true) {
bgColor);
return false;
}
try {
} catch (NullPointerException e) {
// Something else caused the exception, throw it...
throw e;
}
return false;
// NOP if we have been disposed
} catch (InvalidPipeException e) {
// Always catch the exception; try this a couple of times
// and fail silently if the system is not yet ready to
// revalidate the source or dest surfaceData objects.
++attempts;
{
return false;
}
}
}
}
{
boolean srcWidthFlip = false;
boolean srcHeightFlip = false;
boolean dstWidthFlip = false;
boolean dstHeightFlip = false;
} else {
srcWidthFlip = true;
}
} else {
srcHeightFlip = true;
}
} else {
dstWidthFlip = true;
}
} else {
dstHeightFlip = true;
}
return true;
}
// Only accelerate scale if it does not involve a flip or transform
if ((srcWidthFlip == dstWidthFlip) &&
(srcHeightFlip == dstHeightFlip) &&
{
{
return true;
}
}
// Make sure we are not out of bounds
}
}
if (srcX < 0) {
srcX = 0;
}
if (srcY < 0) {
srcY = 0;
}
return true;
}
// Note: src[WH] are currently the right and bottom coordinates.
// The following two lines would adjust src[WH] back to being
// dimensions.
// srcW -= srcX;
// srcH -= srcY;
// Since transformImage needs right and bottom coords we will
// omit this adjustment.
return true;
}
/**
** Utilities
** The following methods are used by the public methods above
** for performing various operations
**/
/*
* This constant represents a tradeoff between the
* need to make sure that image transformations are
* "very close" to integer device coordinates before
* we decide to use an integer scale or copy operation
* as a substitute and the fact that roundoff errors
* in AffineTransforms are frequently introduced by
* performing multiple sequential operations on them.
*
* The evaluation of bug 4990624 details the potential
* for this error cutoff to result in display anomalies
* in different types of image operations and how this
* value represents a good compromise here.
*/
public static boolean closeToInteger(int i, double d) {
}
// Integer translates are always "simple"
return true;
}
// Scales and beyond are always "not simple"
return false;
}
// non-integer translates are only simple when not interpolating
return true;
}
return false;
}
// If we cannot get the srcData, then cannot assume anything about
// the image
}
if (img instanceof BufferedImage) {
return (BufferedImage)img;
}
// Must be VolatileImage; get BufferedImage representation
}
/*
* Return the color model to be used with this BufferedImage and
* transform.
*/
if (tx.isIdentity()) {
return dstCM;
}
boolean needTrans =
{
double[] mtx = new double[4];
// Check out the matrix. A non-integral scale will force ARGB
// since the edge conditions cannot be guaranteed.
}
if (cm instanceof IndexColorModel) {
// Just need to make sure that we have a transparent pixel
// Fix 4221407
}
else {
double[] matrix = new double[6];
// Only scaling so do not need to create
}
else {
if (mapSize < 256) {
dstCM = new
mapSize+1,
}
else {
}
} /* if (matrix[0] < 1.f ...) */
} /* raster instanceof sun.awt.image.BytePackedRaster */
} /* if (cm.getTransparency() == cm.OPAQUE) */
} /* if (cm instanceof IndexColorModel) */
// Need a bitmask transparency
// REMIND: for now, use full transparency since no loops
// for bitmask
}
} /* if (sg.renderHint == RENDER_QUALITY) */
else {
if (cm instanceof IndexColorModel ||
{
// Need a bitmask transparency
// REMIND: for now, use full transparency since no loops
// for bitmask
}
}
return dstCM;
}
int w, int h,
{
if (w <= 0 || h <= 0) {
/*
* Fix for bugid 4783274 - BlitBg throws an exception for
* a particular set of anomalous parameters.
* REMIND: The native loops do proper clipping and would
* detect this situation themselves, but the Java loops
* all seem to trust their parameters a little too well
* to the point where they will try to process a negative
* area of pixels and throw exceptions. The real fix is
* to modify the Java loops to do proper clipping so that
* they can deal with negative dimensions as well as
* improperly large dimensions, but that fix is too risky
* to integrate for Mantis at this point. In the meantime
* eliminating the negative or zero dimensions here is
* "correct" and saves them from some nasty exceptional
* conditions, one of which is the test case of 4783274.
*/
return;
}
{
}
} else {
}
}
{
{
}
return true;
}
return false;
}
{
-1, -1, -1, -1);
}
return false;
}
return true;
}
int x, int y,
if (!(img instanceof ToolkitImage)) {
} else {
return false;
}
}
}
if (!(img instanceof ToolkitImage)) {
} else {
return false;
}
}
}
int x, int y,
if (!(img instanceof ToolkitImage)) {
} else {
return false;
}
observer);
}
}
if (!(img instanceof ToolkitImage)) {
} else {
return false;
}
}
}
if (!(img instanceof ToolkitImage)) {
return true;
} else {
return false;
}
}
}
BufferedImageOp op, int x, int y)
{
if (op instanceof AffineTransformOp) {
atop.getTransform(),
return;
} else {
}
}
}
}