undefect. CWE-407 — 63 sites patched across 27 ecosystems

Authors: russell@unturf.com · brackishbert@gmail.com · foxhop.net · TimeHexOn.com

Patches, unit tests, benchmarks, whitepaper, and outreach briefs.
Public domain — no copyright claimed. Use freely.
This commit is contained in:
russell@unturf.com 2026-03-26 17:11:57 -04:00
commit 0a580b313d
70422 changed files with 17213626 additions and 0 deletions

View file

@ -0,0 +1,161 @@
/*
* Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* 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.
*/
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import static java.awt.Transparency.TRANSLUCENT;
/**
* @test
* @bug 8255722 8255724
* @key headful
*/
public class BlitRotateClippedArea {
/**
* The test use case:
* 1. The destination image is created of size 1000x1000
* 2. The source image is created of size 2000x2000
* 3. The source image is painted by the pattern outsize of 1000x1000
* 4. If the source image is painted as-is to the destination then the
* pattern in the source will be ignored, but the test sets some
* specific rotation that the pattern will hit the source.
* Note that rotation is used not a scale/translate.
*/
public static void main(String[] args) throws Exception {
// the test check the exact pixels location
System.setProperty("sun.java2d.uiScale", "1");
var ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
var gc = ge.getDefaultScreenDevice().getDefaultConfiguration();
var className = gc.getClass().getSimpleName();
var gold = gc.createCompatibleImage(1000, 1000, TRANSLUCENT);
var dstVI2BI = gc.createCompatibleImage(1000, 1000, TRANSLUCENT);
var dstVI2VI = gc.createCompatibleVolatileImage(1000, 1000, TRANSLUCENT);
var dstBI2VI = gc.createCompatibleVolatileImage(1000, 1000, TRANSLUCENT);
var srcBI = gc.createCompatibleImage(2000, 2000, TRANSLUCENT);
var srcVI = gc.createCompatibleVolatileImage(2000, 2000, TRANSLUCENT);
int attempt = 0;
BufferedImage snapshotVI2VI;
BufferedImage snapshotBI2VI;
do {
if (++attempt > 10) {
throw new RuntimeException("Too many attempts: " + attempt);
}
dstVI2VI.validate(gc);
dstBI2VI.validate(gc);
srcVI.validate(gc);
fill(srcBI);
fill(srcVI);
init(gold);
init(dstVI2BI);
init(dstVI2VI);
init(dstBI2VI);
draw(gold, srcBI);
draw(dstVI2BI, srcVI);
draw(dstVI2VI, srcVI);
draw(dstBI2VI, srcBI);
snapshotVI2VI = dstVI2VI.getSnapshot();
snapshotBI2VI = dstBI2VI.getSnapshot();
} while (dstVI2VI.contentsLost() || dstBI2VI.contentsLost()
|| srcVI.contentsLost());
validate(gold, snapshotVI2VI, className);
validate(gold, snapshotBI2VI, className);
validate(gold, dstVI2BI, className);
}
private static void validate(BufferedImage gold, BufferedImage img,
String className) throws IOException {
if (!(className.equals("XRGraphicsConfig"))) {
for (int x = 0; x < gold.getWidth(); ++x) {
for (int y = 0; y < gold.getHeight(); ++y) {
if (gold.getRGB(x, y) != img.getRGB(x, y)) {
ImageIO.write(gold, "png", new File("gold.png"));
ImageIO.write(img, "png", new File("snapshot.png"));
throw new RuntimeException("Test failed.");
}
}
}
} else {
// In Linux where we use XRender pipeline there is
// little deviation because of less arithmetic precision
for (int x = 0; x < gold.getWidth(); ++x) {
for (int y = 0; y < gold.getHeight(); ++y) {
Color goldColor = new Color(gold.getRGB(x, y));
Color actualColor = new Color(img.getRGB(x, y));
if ((Math.abs(goldColor.getRed() - actualColor.getRed()) > 1) ||
(Math.abs(goldColor.getGreen() - actualColor.getGreen()) > 1) ||
(Math.abs(goldColor.getBlue() - actualColor.getBlue()) > 1)) {
ImageIO.write(gold, "png", new File("gold.png"));
ImageIO.write(img, "png", new File("snapshot.png"));
throw new RuntimeException("Test failed for pixel :"
+ x + "/" + y);
}
}
}
}
}
private static void draw(Image dstBI, Image src) {
Graphics2D g = (Graphics2D) dstBI.getGraphics();
g.rotate(Math.toRadians(180), 1250, 1150);
g.drawImage(src, 0, 0, null);
g.dispose();
}
private static void init(Image image) {
Graphics2D graphics = (Graphics2D) image.getGraphics();
graphics.setComposite(AlphaComposite.Src);
graphics.setColor(Color.YELLOW);
graphics.fillRect(0, 0, image.getWidth(null), image.getHeight(null));
graphics.dispose();
}
private static void fill(Image image) {
Graphics2D graphics = (Graphics2D) image.getGraphics();
graphics.setComposite(AlphaComposite.Src);
for (int x = 1000; x < image.getWidth(null); ++x) {
for (int y = 1000; y < image.getHeight(null); ++y) {
graphics.setColor(new Color(x % 256, 0, y % 256, 125));
graphics.fillRect(x, y, 1, 1);
}
}
graphics.dispose();
}
}

View file

@ -0,0 +1,83 @@
/*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* 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.
*/
/**
* @test
* @bug 8280964
* @summary Tests that drawing to a ByteIndexed image dithers correctly.
*/
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
public class ByteIndexedDitherTest {
public static void main(String[] args) {
BufferedImage bgr = createBGRImage();
BufferedImage indexed = createIndexedImage(bgr);
checkImage(indexed);
}
static BufferedImage createBGRImage() {
int sz = 8;
BufferedImage img;
img = new BufferedImage(sz, sz, BufferedImage.TYPE_3BYTE_BGR);
Graphics2D g = img.createGraphics();
Color c = new Color(0, 0, 254);
g.setColor(c);
g.fillRect(0, 0, sz, sz);
g.dispose();
return img;
}
static BufferedImage createIndexedImage(BufferedImage srcImage) {
int w = srcImage.getWidth(null);
int h = srcImage.getHeight(null);
BufferedImage
indexedImg = new BufferedImage(w, h, BufferedImage.TYPE_BYTE_INDEXED);
Graphics2D g = indexedImg.createGraphics();
g.drawImage(srcImage, 0, 0, w, h, null);
g.dispose();
return indexedImg;
}
static void checkImage(BufferedImage image) {
int wid = image.getWidth();
int hgt = image.getHeight();
for (int y=0; y<hgt; y++) {
for (int x=0; x<wid; x++) {
int v = image.getRGB(x, y);
if ((v & 0x00ffff00) != 0) {
System.err.println("("+x+","+y+") = " +
Integer.toHexString(v));
throw new RuntimeException("Unexpected Red or Green");
}
}
}
}
}

View file

@ -0,0 +1,166 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* 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.
*/
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.Image;
import java.awt.ImageCapabilities;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.awt.image.ImageObserver;
import java.awt.image.ImageProducer;
import java.awt.image.VolatileImage;
import static java.awt.image.BufferedImage.TYPE_INT_ARGB_PRE;
/**
* @test
* @bug 7183828
* @summary Tests that no exceptions are thrown when we draw the custom image
*/
public final class CustomImage extends Image {
public static void main(String[] args) {
Image ci = new CustomImage();
VolatileImage cvi = new CustomVolatileImage();
BufferedImage bi = generateImage();
Graphics2D g2d = bi.createGraphics();
// Custom Image
test(g2d.drawImage(ci, 0, 0, null), bi);
test(g2d.drawImage(ci, 0, 0, 5, 5, 0, 0, 5, 5, Color.BLUE, null), bi);
test(g2d.drawImage(ci, 0, 0, 9, 9, Color.BLUE, null), bi);
test(g2d.drawImage(ci, 0, 0, 5, 5, 0, 0, 9, 9, Color.BLUE, null), bi);
test(g2d.drawImage(ci, AffineTransform.getRotateInstance(30), null), bi);
// Custom VolatileImage
test(g2d.drawImage(cvi, 0, 0, null), bi);
test(g2d.drawImage(cvi, 0, 0, 5, 5, 0, 0, 5, 5, Color.BLUE, null), bi);
test(g2d.drawImage(cvi, 0, 0, 9, 9, Color.BLUE, null), bi);
test(g2d.drawImage(cvi, 0, 0, 5, 5, 0, 0, 9, 9, Color.BLUE, null), bi);
test(g2d.drawImage(cvi, AffineTransform.getRotateInstance(30), null), bi);
g2d.dispose();
}
private static BufferedImage generateImage() {
BufferedImage bi = new BufferedImage(100, 100, TYPE_INT_ARGB_PRE);
Graphics g = bi.createGraphics();
g.setColor(Color.GREEN);
g.fillRect(0, 0, 100, 100);
g.dispose();
return bi;
}
private static void test(boolean complete, BufferedImage bi) {
if (complete) {
throw new RuntimeException("Custom image successfully drawn");
}
for (int y = 0; y < bi.getHeight(); ++y) {
for (int x = 0; x < bi.getWidth(); ++x) {
if (bi.getRGB(x, y) != Color.GREEN.getRGB()) {
throw new RuntimeException("The image was changed");
}
}
}
}
@Override
public int getWidth(ImageObserver observer) {
return 100;
}
@Override
public int getHeight(ImageObserver observer) {
return 100;
}
@Override
public ImageProducer getSource() {
return null;
}
@Override
public Graphics getGraphics() {
return null;
}
@Override
public Object getProperty(String name, ImageObserver observer) {
return null;
}
private static final class CustomVolatileImage extends VolatileImage {
@Override
public BufferedImage getSnapshot() {
return null;
}
@Override
public int getWidth() {
return 100;
}
@Override
public int getHeight() {
return 100;
}
@Override
public Graphics2D createGraphics() {
return null;
}
@Override
public int validate(GraphicsConfiguration gc) {
return 0;
}
@Override
public boolean contentsLost() {
return false;
}
@Override
public ImageCapabilities getCapabilities() {
return null;
}
@Override
public int getWidth(ImageObserver observer) {
return 100;
}
@Override
public int getHeight(ImageObserver observer) {
return 100;
}
@Override
public Object getProperty(String name, ImageObserver observer) {
return null;
}
}
}

View file

@ -0,0 +1,68 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* 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.
*/
/*
* @test
* @bug 8028539
* @summary Test that drawing a scaled image terminates.
* @run main/othervm/timeout=60 DrawImageCoordsTest
*/
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
public class DrawImageCoordsTest {
public static void main(String[] args) {
/* Create an image to draw, filled in solid red. */
BufferedImage srcImg =
new BufferedImage(200, 200, BufferedImage.TYPE_INT_RGB);
Graphics srcG = srcImg.createGraphics();
srcG.setColor(Color.red);
int w = srcImg.getWidth(null);
int h = srcImg.getHeight(null);
srcG.fillRect(0, 0, w, h);
/* Create a destination image */
BufferedImage dstImage =
new BufferedImage(200, 200, BufferedImage.TYPE_INT_RGB);
Graphics2D dstG = dstImage.createGraphics();
/* draw image under a scaling transform that overflows int */
AffineTransform tx = new AffineTransform(0.5, 0, 0, 0.5,
0, 5.8658460197478485E9);
dstG.setTransform(tx);
dstG.drawImage(srcImg, 0, 0, null );
/* draw image under the same overflowing transform, cancelling
* out the 0.5 scale on the graphics
*/
dstG.drawImage(srcImg, 0, 0, 2*w, 2*h, null);
if (Color.red.getRGB() == dstImage.getRGB(w/2, h/2)) {
throw new RuntimeException("Unexpected color: clipping failed.");
}
System.out.println("Test Thread Completed");
}
}

View file

@ -0,0 +1,93 @@
/*
* Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* 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.
*/
import java.awt.*;
import java.awt.image.*;
import java.util.*;
import javax.swing.*;
/**
* @test
* @key headful
* @bug 8024895
* @summary tests if changing extra alpha values are honored for transformed blits
* @author ceisserer
*/
public class EABlitTest extends Frame {
protected void test() {
BufferedImage srcImg = createSrcImage();
Image dstImg = getGraphicsConfiguration().createCompatibleVolatileImage(20, 50);
//be over-cautious and render twice to avoid BI caching issues
renderToVI(srcImg, dstImg);
renderToVI(srcImg, dstImg);
BufferedImage validationImg = new BufferedImage(20, 50, BufferedImage.TYPE_INT_RGB);
Graphics2D valG = (Graphics2D) validationImg.getGraphics();
valG.drawImage(dstImg, 0, 0, null);
//Loop over all pixel, and count the different pixel values encountered.
TreeSet<Integer> colorCntSet = new TreeSet<>();
for (int x=0; x < validationImg.getWidth(); x++) {
for (int y=0; y < validationImg.getHeight(); y++) {
int rgb = validationImg.getRGB(x, y);
colorCntSet.add(rgb);
}
}
//Check if we encountered 3 different color values in total
if (colorCntSet.size() == 3) {
System.out.println("Passed!");
} else {
throw new RuntimeException("Test FAILED!");
}
}
protected void renderToVI(BufferedImage src, Image dst) {
Graphics2D g = (Graphics2D) dst.getGraphics();
g.setColor(Color.WHITE);
g.fillRect(0, 0, 50, 50);
g.rotate(0.5f);
g.setRenderingHint(RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY);
g.setComposite(AlphaComposite.SrcOver.derive(1f));
g.drawImage(src, 10, 10, null);
g.setComposite(AlphaComposite.SrcOver.derive(0.5f));
g.drawImage(src, 20, 20, null);
}
protected BufferedImage createSrcImage() {
BufferedImage bi = new BufferedImage(10, 10, BufferedImage.TYPE_INT_RGB);
Graphics2D g = (Graphics2D) bi.getGraphics();
g.setColor(Color.YELLOW);
g.fillRect(0, 0, 10, 10);
return bi;
}
public static void main(String[] args) {
new EABlitTest().test();
}
}

View file

@ -0,0 +1,114 @@
/*
* Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* 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.
*/
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferByte;
import java.awt.image.DataBufferInt;
import java.awt.image.DataBufferShort;
import java.awt.image.VolatileImage;
import static java.awt.Transparency.TRANSLUCENT;
/**
* @test
* @key headful
* @bug 8062164
* @summary We should get correct alpha, when we draw to/from VolatileImage and
* bicubic interpolation is enabled
* @author Sergey Bylokhov
*/
public final class IncorrectAlphaConversionBicubic {
private static final Color RGB = new Color(200, 255, 7, 123);
private static final int SIZE = 100;
public static void main(final String[] args) {
final GraphicsEnvironment ge =
GraphicsEnvironment.getLocalGraphicsEnvironment();
final GraphicsDevice gd = ge.getDefaultScreenDevice();
final GraphicsConfiguration gc = gd.getDefaultConfiguration();
final VolatileImage vi =
gc.createCompatibleVolatileImage(SIZE, SIZE, TRANSLUCENT);
final BufferedImage bi = makeUnmanagedBI(gc, TRANSLUCENT);
final int expected = bi.getRGB(2, 2);
int attempt = 0;
BufferedImage snapshot;
while (true) {
if (++attempt > 10) {
throw new RuntimeException("Too many attempts: " + attempt);
}
vi.validate(gc);
final Graphics2D g2d = vi.createGraphics();
g2d.setComposite(AlphaComposite.Src);
g2d.scale(2, 2);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BICUBIC);
g2d.drawImage(bi, 0, 0, null);
g2d.dispose();
snapshot = vi.getSnapshot();
if (vi.contentsLost()) {
continue;
}
break;
}
final int actual = snapshot.getRGB(2, 2);
if (actual != expected) {
System.err.println("Actual: " + Integer.toHexString(actual));
System.err.println("Expected: " + Integer.toHexString(expected));
throw new RuntimeException("Test failed");
}
}
private static BufferedImage makeUnmanagedBI(GraphicsConfiguration gc,
int type) {
BufferedImage img = gc.createCompatibleImage(SIZE, SIZE, type);
Graphics2D g2d = img.createGraphics();
g2d.setColor(RGB);
g2d.fillRect(0, 0, SIZE, SIZE);
g2d.dispose();
final DataBuffer db = img.getRaster().getDataBuffer();
if (db instanceof DataBufferInt) {
((DataBufferInt) db).getData();
} else if (db instanceof DataBufferShort) {
((DataBufferShort) db).getData();
} else if (db instanceof DataBufferByte) {
((DataBufferByte) db).getData();
} else {
try {
img.setAccelerationPriority(0.0f);
} catch (final Throwable ignored) {
}
}
return img;
}
}

View file

@ -0,0 +1,165 @@
/*
* Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* 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.
*/
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.awt.image.VolatileImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import static java.awt.Transparency.TRANSLUCENT;
import static java.awt.image.BufferedImage.TYPE_4BYTE_ABGR;
import static java.awt.image.BufferedImage.TYPE_4BYTE_ABGR_PRE;
import static java.awt.image.BufferedImage.TYPE_INT_ARGB;
import static java.awt.image.BufferedImage.TYPE_INT_ARGB_PRE;
/**
* @test
* @key headful
* @bug 8017626
* @summary Tests drawing transparent volatile image to transparent BI.
* Results of the blit compatibleImage to transparent BI used for
* comparison.
* @run main/othervm -Dsun.java2d.uiScale=1 IncorrectAlphaSurface2SW
* @run main/othervm -Dsun.java2d.uiScale=2 IncorrectAlphaSurface2SW
* @run main/othervm -Dsun.java2d.uiScale=3 IncorrectAlphaSurface2SW
* @run main/othervm -Dsun.java2d.uiScale=4 IncorrectAlphaSurface2SW
*/
public final class IncorrectAlphaSurface2SW {
private static final int[] SCALES = {1, 2, 4, 8};
private static final int[] SIZES = {1, 2, 3, 127, 128, 254, 255, 256};
private static final int[] dstTypes = {TYPE_INT_ARGB, TYPE_INT_ARGB_PRE,
TYPE_4BYTE_ABGR, TYPE_4BYTE_ABGR_PRE};
private static final int[] srcTypes = {TRANSLUCENT};
public static void main(final String[] args) throws IOException {
GraphicsEnvironment ge = GraphicsEnvironment
.getLocalGraphicsEnvironment();
GraphicsConfiguration gc = ge.getDefaultScreenDevice()
.getDefaultConfiguration();
BufferedImage destVI;
BufferedImage destBI;
BufferedImage sourceBI;
VolatileImage sourceVI;
for (final int s : SIZES) {
for (final int srcType : srcTypes) {
for (final int dstType : dstTypes) {
for (final int scale : SCALES) {
int sw = s * scale;
destVI = new BufferedImage(sw, sw, dstType);
destBI = new BufferedImage(sw, sw, dstType);
sourceBI = gc.createCompatibleImage(sw, sw, srcType);
sourceVI = gc.createCompatibleVolatileImage(s, s, srcType);
// draw to dest BI using compatible image
fill(sourceBI, s);
Graphics2D big = destBI.createGraphics();
big.setComposite(AlphaComposite.Src);
big.drawImage(sourceBI, 0, 0, sw, sw, null);
big.dispose();
// draw to dest BI using compatible image
fill(sourceVI, s);
drawVItoBI(gc, destVI, sourceVI);
validate(destVI, destBI);
sourceVI.flush();
}
}
}
}
System.out.println("Test PASSED");
}
private static void drawVItoBI(GraphicsConfiguration gc,
BufferedImage bi, VolatileImage vi) {
while (true) {
vi.validate(gc);
fill(vi, vi.getHeight());
if (vi.validate(gc) != VolatileImage.IMAGE_OK) {
try {
Thread.sleep(100);
} catch (final InterruptedException ignored) {
}
continue;
}
Graphics2D big = bi.createGraphics();
big.setComposite(AlphaComposite.Src);
big.drawImage(vi, 0, 0, bi.getWidth(), bi.getHeight(), null);
big.dispose();
if (vi.contentsLost()) {
try {
Thread.sleep(100);
} catch (final InterruptedException ignored) {
}
continue;
}
break;
}
}
private static void validate(BufferedImage bi, BufferedImage gold)
throws IOException {
for (int x = 0; x < bi.getWidth(); ++x) {
for (int y = 0; y < bi.getHeight(); ++y) {
if (gold.getRGB(x, y) != bi.getRGB(x, y)) {
System.err.println("Expected color = " + gold.getRGB(x, y));
System.err.println("Actual color = " + bi.getRGB(x, y));
ImageIO.write(gold, "png", new File("gold.png"));
ImageIO.write(bi, "png", new File("bi.png"));
throw new RuntimeException("Test failed.");
}
}
}
}
/**
* Fills the whole image using different alpha for each row.
*
* @param image to fill
*/
private static void fill(final Image image, final int size) {
Graphics2D graphics = (Graphics2D) image.getGraphics();
graphics.setComposite(AlphaComposite.Src);
graphics.setColor(Color.GREEN);
graphics.fillRect(0, 0, image.getWidth(null), image.getHeight(null));
int row = image.getHeight(null) / size;
for (int i = 0; i < size; ++i) {
graphics.setColor(new Color(23, 127, 189, i));
graphics.fillRect(0, i * row, image.getWidth(null), row);
}
graphics.dispose();
}
}

View file

@ -0,0 +1,103 @@
/*
* Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* 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.
*/
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.image.BufferedImage;
import java.awt.image.VolatileImage;
/**
* @test
* @key headful
* @bug 8000629
* @summary Temporary backbuffer in the DrawImage should not fill background
* outside of source image bounds.
* @author Sergey Bylokhov
*/
public final class IncorrectBounds {
private static final int width = 400;
private static final int height = 400;
public static void main(final String[] args) {
GraphicsEnvironment ge =
GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsConfiguration gc =
ge.getDefaultScreenDevice().getDefaultConfiguration();
VolatileImage vi = gc.createCompatibleVolatileImage(width / 4,
height / 4);
final BufferedImage bi = new BufferedImage(width, height,
BufferedImage.TYPE_INT_ARGB);
while (true) {
vi.validate(gc);
Graphics2D g2d = vi.createGraphics();
g2d.setColor(Color.green);
g2d.fillRect(0, 0, width / 4, height / 4);
g2d.dispose();
if (vi.validate(gc) != VolatileImage.IMAGE_OK) {
try {
Thread.sleep(100);
} catch (InterruptedException ignored) {
}
continue;
}
Graphics2D g = bi.createGraphics();
g.setComposite(AlphaComposite.Src);
g.setColor(Color.red);
g.fillRect(0, 0, width, height);
// Use sx and sy outside of VI bounds.
g.drawImage(vi, 0, 0, width / 2, height / 2, 0, 0, width * 2,
height * 2, null);
g.dispose();
if (vi.contentsLost()) {
try {
Thread.sleep(100);
} catch (InterruptedException ignored) {
}
continue;
}
for (int x = 0; x < width; ++x) {
for (int y = 0; y < height; ++y) {
if (x < width / 16 && y < height / 16) {
if (bi.getRGB(x, y) != Color.green.getRGB()) {
throw new RuntimeException("Test failed.");
}
} else {
if (bi.getRGB(x, y) != Color.red.getRGB()) {
throw new RuntimeException("Test failed.");
}
}
}
}
break;
}
}
}

View file

@ -0,0 +1,167 @@
/*
* Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* 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.
*/
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D;
import java.awt.image.BufferedImage;
import java.awt.image.VolatileImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import static java.awt.geom.Rectangle2D.Double;
/**
* @test
* @key headful
* @bug 8041644 8044788
* @summary Tests drawing volatile image to BI using different clip.
* Results of the blit compatibleImage to BI used for comparison.
* @author Sergey Bylokhov
* @run main/othervm IncorrectClipSurface2SW
*/
public final class IncorrectClipSurface2SW {
private static int[] SCALES = {1, 2, 4};
private static int[] SIZES = {127, 3, 2, 1};
private static final Shape[] SHAPES = {new Rectangle(0, 0, 0, 0),
new Rectangle(0, 0, 1, 1),
new Rectangle(0, 1, 1, 1),
new Rectangle(1, 0, 1, 1),
new Rectangle(1, 1, 1, 1),
new Ellipse2D.Double(0, 0, 1, 1),
new Ellipse2D.Double(0, 1, 1, 1),
new Ellipse2D.Double(1, 0, 1, 1),
new Ellipse2D.Double(1, 1, 1, 1),
new Ellipse2D.Double(.25, .25, .5,
.5),
new Double(0, 0, 0.5, 0.5),
new Double(0, 0.5, 0.5, 0.5),
new Double(0.5, 0, 0.5, 0.5),
new Double(0.5, 0.5, 0.5, 0.5),
new Double(0.25, 0.25, 0.5, 0.5),
new Double(0, 0.25, 1, 0.5),
new Double(0.25, 0, 0.5, 1),
new Double(.10, .10, .20, .20),
new Double(.75, .75, .20, .20),
new Double(.75, .10, .20, .20),
new Double(.10, .75, .20, .20),};
public static void main(final String[] args) throws IOException {
GraphicsEnvironment ge = GraphicsEnvironment
.getLocalGraphicsEnvironment();
GraphicsConfiguration gc = ge.getDefaultScreenDevice()
.getDefaultConfiguration();
AffineTransform at;
for (final int size : SIZES) {
for (final int scale : SCALES) {
final int sw = size * scale;
at = AffineTransform.getScaleInstance(sw, sw);
for (Shape clip : SHAPES) {
clip = at.createTransformedShape(clip);
for (Shape to : SHAPES) {
to = at.createTransformedShape(to);
// Prepare test images
VolatileImage vi = getVolatileImage(gc, size);
BufferedImage bi = getBufferedImage(sw);
// Prepare gold images
BufferedImage goldvi = getCompatibleImage(gc, size);
BufferedImage goldbi = getBufferedImage(sw);
draw(clip, to, vi, bi, scale);
draw(clip, to, goldvi, goldbi, scale);
validate(bi, goldbi);
}
}
}
}
}
private static void draw(Shape clip, Shape to, Image vi, BufferedImage bi,
int scale) {
Graphics2D big = bi.createGraphics();
big.setComposite(AlphaComposite.Src);
big.setClip(clip);
Rectangle toBounds = to.getBounds();
int x1 = toBounds.x;
int y1 = toBounds.y;
int x2 = x1 + toBounds.width;
int y2 = y1 + toBounds.height;
big.drawImage(vi, x1, y1, x2, y2, 0, 0, toBounds.width / scale,
toBounds.height / scale, null);
big.dispose();
vi.flush();
}
private static BufferedImage getBufferedImage(int sw) {
BufferedImage bi = new BufferedImage(sw, sw,
BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = bi.createGraphics();
g2d.setColor(Color.RED);
g2d.fillRect(0, 0, sw, sw);
return bi;
}
private static VolatileImage getVolatileImage(GraphicsConfiguration gc,
int size) {
VolatileImage vi = gc.createCompatibleVolatileImage(size, size);
Graphics2D g2d = vi.createGraphics();
g2d.setColor(Color.GREEN);
g2d.fillRect(0, 0, size, size);
return vi;
}
private static BufferedImage getCompatibleImage(GraphicsConfiguration gc,
int size) {
BufferedImage image = gc.createCompatibleImage(size, size);
Graphics2D g2d = image.createGraphics();
g2d.setColor(Color.GREEN);
g2d.fillRect(0, 0, size, size);
return image;
}
private static void validate(BufferedImage bi, BufferedImage goldbi)
throws IOException {
for (int x = 0; x < bi.getWidth(); ++x) {
for (int y = 0; y < bi.getHeight(); ++y) {
if (goldbi.getRGB(x, y) != bi.getRGB(x, y)) {
ImageIO.write(bi, "png", new File("actual.png"));
ImageIO.write(goldbi, "png", new File("expected.png"));
throw new RuntimeException("Test failed.");
}
}
}
}
}

View file

@ -0,0 +1,182 @@
/*
* Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* 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.
*/
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferByte;
import java.awt.image.DataBufferInt;
import java.awt.image.DataBufferShort;
import java.awt.image.VolatileImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import static java.awt.geom.Rectangle2D.Double;
/**
* @test
* @key headful
* @bug 8061456
* @summary Tests drawing BI to volatile image using different clips + xor mode.
* Results of the blit BI to compatibleImage is used for comparison.
* @run main/othervm -Dsun.java2d.uiScale=1 IncorrectClipXorModeSW2Surface
* @run main/othervm -Dsun.java2d.uiScale=2 IncorrectClipXorModeSW2Surface
* @run main/othervm -Dsun.java2d.uiScale=4 IncorrectClipXorModeSW2Surface
*/
public final class IncorrectClipXorModeSW2Surface {
private static int[] SIZES = {2, 10, 100};
private static final Shape[] SHAPES = {
new Rectangle(0, 0, 0, 0),
new Rectangle(0, 0, 1, 1),
new Rectangle(0, 1, 1, 1),
new Rectangle(1, 0, 1, 1),
new Rectangle(1, 1, 1, 1),
new Double(0, 0, 0.5, 0.5),
new Double(0, 0.5, 0.5, 0.5),
new Double(0.5, 0, 0.5, 0.5),
new Double(0.5, 0.5, 0.5, 0.5),
new Double(0.25, 0.25, 0.5, 0.5),
new Double(0, 0.25, 1, 0.5),
new Double(0.25, 0, 0.5, 1),
new Double(.10, .10, .20, .20),
new Double(.75, .75, .20, .20),
new Double(.75, .10, .20, .20),
new Double(.10, .75, .20, .20),
};
public static void main(final String[] args) throws IOException {
GraphicsEnvironment ge = GraphicsEnvironment
.getLocalGraphicsEnvironment();
GraphicsConfiguration gc = ge.getDefaultScreenDevice()
.getDefaultConfiguration();
AffineTransform at;
for (int size : SIZES) {
at = AffineTransform.getScaleInstance(size, size);
for (Shape clip : SHAPES) {
clip = at.createTransformedShape(clip);
for (Shape to : SHAPES) {
to = at.createTransformedShape(to);
// Prepare test images
BufferedImage snapshot;
BufferedImage bi = getBufferedImage(size);
VolatileImage vi = getVolatileImage(gc, size);
while (true) {
vi.validate(gc);
Graphics2D g2d = vi.createGraphics();
g2d.setColor(Color.GREEN);
g2d.fillRect(0, 0, size, size);
g2d.dispose();
if (vi.validate(gc) != VolatileImage.IMAGE_OK) {
continue;
}
draw(clip, to, bi, vi);
snapshot = vi.getSnapshot();
if (vi.contentsLost()) {
continue;
}
break;
}
// Prepare gold images
BufferedImage goldvi = getCompatibleImage(gc, size);
BufferedImage goldbi = getBufferedImage(size);
draw(clip, to, goldbi, goldvi);
validate(snapshot, goldvi);
vi.flush();
}
}
}
}
private static void draw(Shape clip, Shape shape, Image from, Image to) {
Graphics2D g2d = (Graphics2D) to.getGraphics();
g2d.setXORMode(Color.BLACK);
g2d.setClip(clip);
Rectangle toBounds = shape.getBounds();
g2d.drawImage(from, toBounds.x, toBounds.y, toBounds.width,
toBounds.height, null);
g2d.dispose();
}
private static BufferedImage getBufferedImage(int sw) {
final BufferedImage bi = new BufferedImage(sw, sw, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = bi.createGraphics();
g2d.setColor(Color.RED);
g2d.fillRect(0, 0, sw, sw);
g2d.dispose();
final DataBuffer db = bi.getRaster().getDataBuffer();
if (db instanceof DataBufferInt) {
((DataBufferInt) db).getData();
} else if (db instanceof DataBufferShort) {
((DataBufferShort) db).getData();
} else if (db instanceof DataBufferByte) {
((DataBufferByte) db).getData();
} else {
try {
bi.setAccelerationPriority(0.0f);
} catch (final Throwable ignored) {
}
}
return bi;
}
private static VolatileImage getVolatileImage(GraphicsConfiguration gc,
int size) {
return gc.createCompatibleVolatileImage(size, size);
}
private static BufferedImage getCompatibleImage(GraphicsConfiguration gc,
int size) {
BufferedImage image = gc.createCompatibleImage(size, size);
Graphics2D g2d = image.createGraphics();
g2d.setColor(Color.GREEN);
g2d.fillRect(0, 0, size, size);
g2d.dispose();
return image;
}
private static void validate(BufferedImage bi, BufferedImage goldbi)
throws IOException {
for (int x = 0; x < bi.getWidth(); ++x) {
for (int y = 0; y < bi.getHeight(); ++y) {
if (goldbi.getRGB(x, y) != bi.getRGB(x, y)) {
ImageIO.write(bi, "png", new File("actual.png"));
ImageIO.write(goldbi, "png", new File("expected.png"));
throw new RuntimeException("Test failed.");
}
}
}
}
}

View file

@ -0,0 +1,182 @@
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* 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.
*/
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.awt.image.VolatileImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import static java.awt.geom.Rectangle2D.Double;
/**
* @test
* @key headful
* @bug 8061831 8130400
* @summary Tests drawing volatile image to volatile image using different
* clips + xor mode. Results of the blit compatibleImage to
* compatibleImage is used for comparison.
* @run main/othervm -Dsun.java2d.uiScale=1 IncorrectClipXorModeSurface2Surface
* @run main/othervm -Dsun.java2d.uiScale=2 IncorrectClipXorModeSurface2Surface
* @run main/othervm -Dsun.java2d.uiScale=4 IncorrectClipXorModeSurface2Surface
*/
public final class IncorrectClipXorModeSurface2Surface {
private static int[] SIZES = {2, 10, 100};
private static final Shape[] SHAPES = {
new Rectangle(0, 0, 0, 0),
new Rectangle(0, 0, 1, 1),
new Rectangle(0, 1, 1, 1),
new Rectangle(1, 0, 1, 1),
new Rectangle(1, 1, 1, 1),
new Double(0, 0, 0.5, 0.5),
new Double(0, 0.5, 0.5, 0.5),
new Double(0.5, 0, 0.5, 0.5),
new Double(0.5, 0.5, 0.5, 0.5),
new Double(0.25, 0.25, 0.5, 0.5),
new Double(0, 0.25, 1, 0.5),
new Double(0.25, 0, 0.5, 1),
new Double(.10, .10, .20, .20),
new Double(.75, .75, .20, .20),
new Double(.75, .10, .20, .20),
new Double(.10, .75, .20, .20),
};
public static void main(final String[] args) throws IOException {
GraphicsEnvironment ge = GraphicsEnvironment
.getLocalGraphicsEnvironment();
GraphicsConfiguration gc = ge.getDefaultScreenDevice()
.getDefaultConfiguration();
AffineTransform at;
for (int size : SIZES) {
at = AffineTransform.getScaleInstance(size, size);
for (Shape clip : SHAPES) {
clip = at.createTransformedShape(clip);
for (Shape to : SHAPES) {
to = at.createTransformedShape(to);
// Prepare test images
BufferedImage snapshot;
VolatileImage source = getVolatileImage(gc, size);
VolatileImage target = getVolatileImage(gc, size);
int attempt = 0;
while (true) {
if (++attempt > 10) {
throw new RuntimeException("Too many attempts: " + attempt);
}
// Prepare source images
source.validate(gc);
Graphics2D g2d = source.createGraphics();
g2d.setColor(Color.RED);
g2d.fillRect(0, 0, size, size);
g2d.dispose();
if (source.validate(gc) != VolatileImage.IMAGE_OK) {
continue;
}
// Prepare target images
target.validate(gc);
g2d = target.createGraphics();
g2d.setColor(Color.GREEN);
g2d.fillRect(0, 0, size, size);
g2d.dispose();
if (target.validate(gc) != VolatileImage.IMAGE_OK) {
continue;
}
draw(clip, to, source, target);
snapshot = target.getSnapshot();
if (source.contentsLost() || target.contentsLost()) {
continue;
}
break;
}
// Prepare gold images
BufferedImage goldS = getSourceGold(gc, size);
BufferedImage goldT = getTargetGold(gc, size);
draw(clip, to, goldS, goldT);
validate(snapshot, goldT);
source.flush();
target.flush();
}
}
}
}
private static void draw(Shape clip, Shape shape, Image from, Image to) {
Graphics2D g2d = (Graphics2D) to.getGraphics();
g2d.setXORMode(Color.BLACK);
g2d.setClip(clip);
Rectangle toBounds = shape.getBounds();
g2d.drawImage(from, toBounds.x, toBounds.y, toBounds.width,
toBounds.height, null);
g2d.dispose();
}
private static BufferedImage getSourceGold(GraphicsConfiguration gc,
int size) {
final BufferedImage bi = gc.createCompatibleImage(size, size);
Graphics2D g2d = bi.createGraphics();
g2d.setColor(Color.RED);
g2d.fillRect(0, 0, size, size);
g2d.dispose();
return bi;
}
private static BufferedImage getTargetGold(GraphicsConfiguration gc,
int size) {
BufferedImage image = gc.createCompatibleImage(size, size);
Graphics2D g2d = image.createGraphics();
g2d.setColor(Color.GREEN);
g2d.fillRect(0, 0, size, size);
g2d.dispose();
return image;
}
private static VolatileImage getVolatileImage(GraphicsConfiguration gc,
int size) {
return gc.createCompatibleVolatileImage(size, size);
}
private static void validate(BufferedImage bi, BufferedImage goldbi)
throws IOException {
for (int x = 0; x < bi.getWidth(); ++x) {
for (int y = 0; y < bi.getHeight(); ++y) {
if (goldbi.getRGB(x, y) != bi.getRGB(x, y)) {
ImageIO.write(bi, "png", new File("actual.png"));
ImageIO.write(goldbi, "png", new File("expected.png"));
throw new RuntimeException("Test failed.");
}
}
}
}
}

View file

@ -0,0 +1,165 @@
/*
* Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* 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.
*/
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.image.BufferedImage;
import java.awt.image.VolatileImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
/**
* @test
* @key headful
* @bug 8041129
* @summary Destination offset should be correct in case of Surface->SW blit.
* Destination outside of the drawing area should be untouched.
* @author Sergey Bylokhov
*/
public final class IncorrectDestinationOffset {
private static final int SIZE = 128;
private static final double[] SCALES = {0.25, 0.5, 1, 1.5, 2.0, 4};
public static void main(final String[] args) throws IOException {
GraphicsEnvironment ge = GraphicsEnvironment
.getLocalGraphicsEnvironment();
GraphicsConfiguration gc = ge.getDefaultScreenDevice()
.getDefaultConfiguration();
VolatileImage vi = gc.createCompatibleVolatileImage(SIZE, SIZE);
BufferedImage bi = new BufferedImage(SIZE, SIZE,
BufferedImage.TYPE_INT_ARGB);
for (double scale : SCALES) {
while (true) {
// initialize Volatile Image
vi.validate(gc);
Graphics2D g2d = vi.createGraphics();
g2d.setColor(Color.green);
g2d.fillRect(0, 0, SIZE, SIZE);
g2d.dispose();
if (vi.validate(gc) != VolatileImage.IMAGE_OK) {
try {
Thread.sleep(100);
} catch (InterruptedException ignored) {
}
continue;
}
// Draw the VolatileImage to BI with scale and offsets
Graphics2D g = bi.createGraphics();
g.setComposite(AlphaComposite.Src);
g.setColor(Color.RED);
g.fillRect(0, 0, SIZE / 2, SIZE / 2);
g.setColor(Color.BLUE);
g.fillRect(SIZE / 2, 0, SIZE / 2, SIZE / 2);
g.setColor(Color.ORANGE);
g.fillRect(0, SIZE / 2, SIZE / 2, SIZE / 2);
g.setColor(Color.MAGENTA);
g.fillRect(SIZE / 2, SIZE / 2, SIZE / 2, SIZE / 2);
int point2draw = (int) (100 * scale);
int size2draw = (int) (SIZE * scale);
g.drawImage(vi, point2draw, point2draw, size2draw, size2draw,
null);
g.dispose();
if (vi.contentsLost()) {
try {
Thread.sleep(100);
} catch (InterruptedException ignored) {
}
continue;
}
validate(bi, point2draw, size2draw);
break;
}
}
}
private static void validate(BufferedImage bi, int point2draw,
int size2draw)
throws IOException {
for (int x = 0; x < SIZE; ++x) {
for (int y = 0; y < SIZE; ++y) {
if (isInsideGreenArea(point2draw, size2draw, x, y)) {
if (bi.getRGB(x, y) != Color.green.getRGB()) {
ImageIO.write(bi, "png", new File("image.png"));
throw new RuntimeException("Test failed.");
}
} else {
if (isRedArea(x, y)) {
if (bi.getRGB(x, y) != Color.red.getRGB()) {
ImageIO.write(bi, "png", new File("image.png"));
throw new RuntimeException("Test failed.");
}
}
if (isBlueArea(x, y)) {
if (bi.getRGB(x, y) != Color.blue.getRGB()) {
ImageIO.write(bi, "png", new File("image.png"));
throw new RuntimeException("Test failed.");
}
}
if (isOrangeArea(x, y)) {
if (bi.getRGB(x, y) != Color.orange.getRGB()) {
ImageIO.write(bi, "png", new File("image.png"));
throw new RuntimeException("Test failed.");
}
}
if (isMagentaArea(x, y)) {
if (bi.getRGB(x, y) != Color.magenta.getRGB()) {
ImageIO.write(bi, "png", new File("image.png"));
throw new RuntimeException("Test failed.");
}
}
}
}
}
}
private static boolean isRedArea(int x, int y) {
return x < SIZE / 2 && y < SIZE / 2;
}
private static boolean isBlueArea(int x, int y) {
return x >= SIZE / 2 && y < SIZE / 2;
}
private static boolean isOrangeArea(int x, int y) {
return x < SIZE / 2 && y >= SIZE / 2;
}
private static boolean isMagentaArea(int x, int y) {
return x >= SIZE / 2 && y >= SIZE / 2;
}
private static boolean isInsideGreenArea(int point2draw, int size2draw,
int x, int y) {
return x >= point2draw && x < point2draw + size2draw && y >=
point2draw && y < point2draw + size2draw;
}
}

View file

@ -0,0 +1,188 @@
/*
* Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* 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.
*/
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.Transparency;
import java.awt.color.ColorSpace;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.ComponentColorModel;
import java.awt.image.DataBuffer;
import java.awt.image.Raster;
import java.awt.image.VolatileImage;
import java.awt.image.WritableRaster;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import sun.awt.image.SunWritableRaster;
import static java.awt.Transparency.BITMASK;
import static java.awt.Transparency.OPAQUE;
import static java.awt.Transparency.TRANSLUCENT;
import static java.awt.image.BufferedImage.TYPE_3BYTE_BGR;
import static java.awt.image.BufferedImage.TYPE_4BYTE_ABGR;
import static java.awt.image.BufferedImage.TYPE_4BYTE_ABGR_PRE;
import static java.awt.image.BufferedImage.TYPE_BYTE_BINARY;
import static java.awt.image.BufferedImage.TYPE_BYTE_INDEXED;
import static java.awt.image.BufferedImage.TYPE_CUSTOM;
import static java.awt.image.BufferedImage.TYPE_INT_ARGB;
import static java.awt.image.BufferedImage.TYPE_INT_ARGB_PRE;
import static java.awt.image.BufferedImage.TYPE_INT_BGR;
import static java.awt.image.BufferedImage.TYPE_INT_RGB;
/**
* @test
* @key headful
* @bug 8029253 6207877
* @summary Tests asymmetric source offsets when managed image is drawn to VI.
* Results of the blit to compatibleImage are used for comparison.
* @author Sergey Bylokhov
* @modules java.desktop/sun.awt.image
* @run main/othervm -Dsun.java2d.accthreshold=0 IncorrectManagedImageSourceOffset
* @run main/othervm -Dsun.java2d.accthreshold=0 -Dsun.java2d.uiScale=1 IncorrectManagedImageSourceOffset
* @run main/othervm -Dsun.java2d.accthreshold=0 -Dsun.java2d.uiScale=2 IncorrectManagedImageSourceOffset
*/
public final class IncorrectManagedImageSourceOffset {
// See the same test for unmanaged images: IncorrectUnmanagedImageSourceOffset
private static final int[] TYPES = {TYPE_INT_RGB, TYPE_INT_ARGB,
TYPE_INT_ARGB_PRE, TYPE_INT_BGR,
TYPE_3BYTE_BGR, TYPE_4BYTE_ABGR,
TYPE_4BYTE_ABGR_PRE,
/*TYPE_USHORT_565_RGB,
TYPE_USHORT_555_RGB, TYPE_BYTE_GRAY,
TYPE_USHORT_GRAY,*/ TYPE_BYTE_BINARY,
TYPE_BYTE_INDEXED, TYPE_CUSTOM};
private static final int[] TRANSPARENCIES = {OPAQUE, BITMASK, TRANSLUCENT};
public static void main(final String[] args) throws IOException {
for (final int viType : TRANSPARENCIES) {
for (final int biType : TYPES) {
BufferedImage bi = makeManagedBI(biType);
fill(bi);
test(bi, viType);
}
}
}
private static void test(BufferedImage bi, int type)
throws IOException {
GraphicsEnvironment ge = GraphicsEnvironment
.getLocalGraphicsEnvironment();
GraphicsConfiguration gc = ge.getDefaultScreenDevice()
.getDefaultConfiguration();
VolatileImage vi = gc.createCompatibleVolatileImage(511, 255, type);
BufferedImage gold = gc.createCompatibleImage(511, 255, type);
// draw to compatible Image
Graphics2D big = gold.createGraphics();
// force scaled blit
big.drawImage(bi, 7, 11, 127, 111, 7, 11, 127 * 2, 111, null);
big.dispose();
// draw to volatile image
BufferedImage snapshot;
while (true) {
vi.validate(gc);
if (vi.validate(gc) != VolatileImage.IMAGE_OK) {
try {
Thread.sleep(100);
} catch (final InterruptedException ignored) {
}
continue;
}
Graphics2D vig = vi.createGraphics();
// force scaled blit
vig.drawImage(bi, 7, 11, 127, 111, 7, 11, 127 * 2, 111, null);
vig.dispose();
snapshot = vi.getSnapshot();
if (vi.contentsLost()) {
try {
Thread.sleep(100);
} catch (final InterruptedException ignored) {
}
continue;
}
break;
}
// validate images
for (int x = 7; x < 127; ++x) {
for (int y = 11; y < 111; ++y) {
if (gold.getRGB(x, y) != snapshot.getRGB(x, y)) {
ImageIO.write(gold, "png", new File("gold.png"));
ImageIO.write(snapshot, "png", new File("bi.png"));
throw new RuntimeException("Test failed.");
}
}
}
}
private static BufferedImage makeManagedBI(final int type) {
final BufferedImage bi;
if (type == TYPE_CUSTOM) {
bi = makeCustomManagedBI();
} else {
bi = new BufferedImage(511, 255, type);
}
bi.setAccelerationPriority(1.0f);
return bi;
}
/**
* Returns the custom buffered image, which mostly identical to
* BufferedImage.(w,h,TYPE_3BYTE_BGR), but uses the bigger scanlineStride.
* This means that the raster will have gaps, between the rows.
*/
private static BufferedImage makeCustomManagedBI() {
int w = 511, h = 255;
ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
int[] nBits = {8, 8, 8};
int[] bOffs = {2, 1, 0};
ColorModel colorModel = new ComponentColorModel(cs, nBits, false, false,
Transparency.OPAQUE,
DataBuffer.TYPE_BYTE);
WritableRaster raster =
Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, w, h,
w * 3 + 2, 3, bOffs, null);
BufferedImage bi = new BufferedImage(colorModel, raster, true, null);
SunWritableRaster.makeTrackable(raster.getDataBuffer());
SunWritableRaster.markDirty(bi);
return bi;
}
private static void fill(final Image image) {
final Graphics2D graphics = (Graphics2D) image.getGraphics();
graphics.setComposite(AlphaComposite.Src);
for (int i = 0; i < image.getHeight(null); ++i) {
graphics.setColor(new Color(i, 0, 0));
graphics.fillRect(0, i, image.getWidth(null), 1);
}
graphics.dispose();
}
}

View file

@ -0,0 +1,94 @@
/*
* Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* 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.
*/
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.image.BufferedImage;
import java.awt.image.VolatileImage;
/**
* @test
* @key headful
* @bug 8000629
* @summary Temporary backbuffer in the DrawImage should have correct offset.
* @author Sergey Bylokhov
*/
public final class IncorrectOffset {
private static final int width = 400;
private static final int height = 400;
public static void main(final String[] args) {
GraphicsEnvironment ge =
GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsConfiguration gc =
ge.getDefaultScreenDevice().getDefaultConfiguration();
VolatileImage vi = gc.createCompatibleVolatileImage(width, height);
BufferedImage bi = new BufferedImage(width / 4, height / 4,
BufferedImage.TYPE_INT_ARGB);
while (true) {
vi.validate(gc);
Graphics2D g2d = vi.createGraphics();
g2d.setColor(Color.black);
g2d.fillRect(0, 0, width, height);
g2d.setColor(Color.green);
g2d.fillRect(width / 4, height / 4, width / 2, height / 2);
g2d.dispose();
if (vi.validate(gc) != VolatileImage.IMAGE_OK) {
try {
Thread.sleep(100);
} catch (InterruptedException ignored) {
}
continue;
}
Graphics2D g = bi.createGraphics();
g.setComposite(AlphaComposite.Src);
// Scale part of VI to BI. Only green area should be copied.
g.drawImage(vi, 0, 0, width / 4, height / 4, width / 4, height / 4,
width / 4 + width / 2, height / 4 + height / 2, null);
g.dispose();
if (vi.contentsLost()) {
try {
Thread.sleep(100);
} catch (InterruptedException ignored) {
}
continue;
}
for (int x = 0; x < width / 4; ++x) {
for (int y = 0; y < height / 4; ++y) {
if (bi.getRGB(x, y) != Color.green.getRGB()) {
throw new RuntimeException("Test failed.");
}
}
}
break;
}
}
}

View file

@ -0,0 +1,104 @@
/*
* Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* 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.
*/
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.awt.image.VolatileImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
/**
* @test
* @key headful
* @bug 8041129
* @summary Tests asymmetric source offsets.
* @run main/othervm -Dsun.java2d.uiScale=1 IncorrectSourceOffset
* @run main/othervm -Dsun.java2d.uiScale=2 IncorrectSourceOffset
* @run main/othervm -Dsun.java2d.uiScale=3 IncorrectSourceOffset
* @run main/othervm -Dsun.java2d.uiScale=4 IncorrectSourceOffset
*/
public final class IncorrectSourceOffset {
public static void main(final String[] args) throws IOException {
GraphicsEnvironment ge = GraphicsEnvironment
.getLocalGraphicsEnvironment();
GraphicsConfiguration gc = ge.getDefaultScreenDevice()
.getDefaultConfiguration();
VolatileImage vi = gc.createCompatibleVolatileImage(511, 255);
BufferedImage bi = new BufferedImage(511, 255,
BufferedImage.TYPE_INT_ARGB);
BufferedImage gold = new BufferedImage(511, 255,
BufferedImage.TYPE_INT_ARGB);
fill(gold);
while (true) {
vi.validate(gc);
fill(vi);
if (vi.validate(gc) != VolatileImage.IMAGE_OK) {
try {
Thread.sleep(100);
} catch (final InterruptedException ignored) {
}
continue;
}
Graphics2D big = bi.createGraphics();
big.drawImage(vi, 7, 11, 127, 111, 7, 11, 127, 111, null);
big.dispose();
if (vi.contentsLost()) {
try {
Thread.sleep(100);
} catch (final InterruptedException ignored) {
}
continue;
}
break;
}
for (int x = 7; x < 127; ++x) {
for (int y = 11; y < 111; ++y) {
if (gold.getRGB(x, y) != bi.getRGB(x, y)) {
ImageIO.write(gold, "png", new File("gold.png"));
ImageIO.write(bi, "png", new File("bi.png"));
throw new RuntimeException("Test failed.");
}
}
}
}
private static void fill(Image image) {
Graphics2D graphics = (Graphics2D) image.getGraphics();
graphics.setComposite(AlphaComposite.Src);
for (int i = 0; i < image.getHeight(null); ++i) {
graphics.setColor(new Color(i, 0, 0));
graphics.fillRect(0, i, image.getWidth(null), 1);
}
graphics.dispose();
}
}

View file

@ -0,0 +1,141 @@
/*
* Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* 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.
*/
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferByte;
import java.awt.image.DataBufferInt;
import java.awt.image.DataBufferShort;
import java.awt.image.VolatileImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import static java.awt.Transparency.TRANSLUCENT;
import static java.awt.image.BufferedImage.TYPE_INT_ARGB;
/**
* @test
* @key headful
* @bug 8059942 8264317
* @summary Tests rotated clip when unmanaged image is drawn to VI.
* Results of the blit to compatibleImage are used for comparison.
* @run main/othervm -Dsun.java2d.uiScale=1 IncorrectUnmanagedImageRotatedClip
* @run main/othervm -Dsun.java2d.uiScale=2 IncorrectUnmanagedImageRotatedClip
* @run main/othervm -Dsun.java2d.uiScale=3 IncorrectUnmanagedImageRotatedClip
*/
public final class IncorrectUnmanagedImageRotatedClip {
public static void main(final String[] args) throws IOException {
BufferedImage bi = makeUnmanagedBI();
fill(bi);
test(bi);
}
private static void test(final BufferedImage bi) throws IOException {
GraphicsEnvironment ge = GraphicsEnvironment
.getLocalGraphicsEnvironment();
GraphicsConfiguration gc = ge.getDefaultScreenDevice()
.getDefaultConfiguration();
VolatileImage vi = gc.createCompatibleVolatileImage(500, 200,
TRANSLUCENT);
BufferedImage gold = gc.createCompatibleImage(500, 200, TRANSLUCENT);
// draw to compatible Image
draw(bi, gold);
// draw to volatile image
int attempt = 0;
BufferedImage snapshot;
while (true) {
if (++attempt > 10) {
throw new RuntimeException("Too many attempts: " + attempt);
}
vi.validate(gc);
if (vi.validate(gc) != VolatileImage.IMAGE_OK) {
continue;
}
draw(bi, vi);
snapshot = vi.getSnapshot();
if (vi.contentsLost()) {
continue;
}
break;
}
// validate images
for (int x = 0; x < gold.getWidth(); ++x) {
for (int y = 0; y < gold.getHeight(); ++y) {
if (gold.getRGB(x, y) != snapshot.getRGB(x, y)) {
ImageIO.write(gold, "png", new File("gold.png"));
ImageIO.write(snapshot, "png", new File("bi.png"));
throw new RuntimeException("Test failed.");
}
}
}
}
private static void draw(final BufferedImage from,final Image to) {
final Graphics2D g2d = (Graphics2D) to.getGraphics();
g2d.setComposite(AlphaComposite.Src);
g2d.setColor(Color.ORANGE);
g2d.fillRect(0, 0, to.getWidth(null), to.getHeight(null));
g2d.rotate(Math.toRadians(45));
g2d.clip(new Rectangle(41, 42, 43, 44));
g2d.drawImage(from, 50, 50, Color.blue, null);
g2d.dispose();
}
private static BufferedImage makeUnmanagedBI() {
final BufferedImage bi = new BufferedImage(500, 200, TYPE_INT_ARGB);
final DataBuffer db = bi.getRaster().getDataBuffer();
if (db instanceof DataBufferInt) {
((DataBufferInt) db).getData();
} else if (db instanceof DataBufferShort) {
((DataBufferShort) db).getData();
} else if (db instanceof DataBufferByte) {
((DataBufferByte) db).getData();
} else {
try {
bi.setAccelerationPriority(0.0f);
} catch (final Throwable ignored) {
}
}
return bi;
}
private static void fill(final Image image) {
final Graphics2D graphics = (Graphics2D) image.getGraphics();
graphics.setComposite(AlphaComposite.Src);
for (int i = 0; i < image.getHeight(null); ++i) {
graphics.setColor(new Color(i, 0, 0));
graphics.fillRect(0, i, image.getWidth(null), 1);
}
graphics.dispose();
}
}

View file

@ -0,0 +1,193 @@
/*
* Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* 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.
*/
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.Transparency;
import java.awt.color.ColorSpace;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.ComponentColorModel;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferByte;
import java.awt.image.DataBufferInt;
import java.awt.image.DataBufferShort;
import java.awt.image.Raster;
import java.awt.image.VolatileImage;
import java.awt.image.WritableRaster;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import static java.awt.Transparency.BITMASK;
import static java.awt.Transparency.OPAQUE;
import static java.awt.Transparency.TRANSLUCENT;
import static java.awt.image.BufferedImage.TYPE_3BYTE_BGR;
import static java.awt.image.BufferedImage.TYPE_4BYTE_ABGR;
import static java.awt.image.BufferedImage.TYPE_4BYTE_ABGR_PRE;
import static java.awt.image.BufferedImage.TYPE_BYTE_BINARY;
import static java.awt.image.BufferedImage.TYPE_BYTE_INDEXED;
import static java.awt.image.BufferedImage.TYPE_CUSTOM;
import static java.awt.image.BufferedImage.TYPE_INT_ARGB;
import static java.awt.image.BufferedImage.TYPE_INT_ARGB_PRE;
import static java.awt.image.BufferedImage.TYPE_INT_BGR;
import static java.awt.image.BufferedImage.TYPE_INT_RGB;
/**
* @test
* @key headful
* @bug 8029253 6207877
* @summary Tests asymmetric source offsets when unmanaged image is drawn to VI.
* Results of the blit to compatibleImage are used for comparison.
* @author Sergey Bylokhov
* @run main/othervm IncorrectUnmanagedImageSourceOffset
* @run main/othervm -Dsun.java2d.uiScale=1 IncorrectUnmanagedImageSourceOffset
* @run main/othervm -Dsun.java2d.uiScale=2 IncorrectUnmanagedImageSourceOffset
*/
public final class IncorrectUnmanagedImageSourceOffset {
// See the same test for managed images: IncorrectManagedImageSourceOffset
private static final int[] TYPES = {TYPE_INT_RGB, TYPE_INT_ARGB,
TYPE_INT_ARGB_PRE, TYPE_INT_BGR,
TYPE_3BYTE_BGR, TYPE_4BYTE_ABGR,
TYPE_4BYTE_ABGR_PRE,
/*TYPE_USHORT_565_RGB,
TYPE_USHORT_555_RGB, TYPE_BYTE_GRAY,
TYPE_USHORT_GRAY,*/ TYPE_BYTE_BINARY,
TYPE_BYTE_INDEXED, TYPE_CUSTOM};
private static final int[] TRANSPARENCIES = {OPAQUE, BITMASK, TRANSLUCENT};
public static void main(final String[] args) throws IOException {
for (final int viType : TRANSPARENCIES) {
for (final int biType : TYPES) {
BufferedImage bi = makeUnmanagedBI(biType);
fill(bi);
test(bi, viType);
}
}
}
private static void test(BufferedImage bi, int type)
throws IOException {
GraphicsEnvironment ge = GraphicsEnvironment
.getLocalGraphicsEnvironment();
GraphicsConfiguration gc = ge.getDefaultScreenDevice()
.getDefaultConfiguration();
VolatileImage vi = gc.createCompatibleVolatileImage(511, 255, type);
BufferedImage gold = gc.createCompatibleImage(511, 255, type);
// draw to compatible Image
Graphics2D big = gold.createGraphics();
// force scaled blit
big.drawImage(bi, 7, 11, 127, 111, 7, 11, 127 * 2, 111, null);
big.dispose();
// draw to volatile image
BufferedImage snapshot;
while (true) {
vi.validate(gc);
if (vi.validate(gc) != VolatileImage.IMAGE_OK) {
try {
Thread.sleep(100);
} catch (final InterruptedException ignored) {
}
continue;
}
Graphics2D vig = vi.createGraphics();
// force scaled blit
vig.drawImage(bi, 7, 11, 127, 111, 7, 11, 127 * 2, 111, null);
vig.dispose();
snapshot = vi.getSnapshot();
if (vi.contentsLost()) {
try {
Thread.sleep(100);
} catch (final InterruptedException ignored) {
}
continue;
}
break;
}
// validate images
for (int x = 7; x < 127; ++x) {
for (int y = 11; y < 111; ++y) {
if (gold.getRGB(x, y) != snapshot.getRGB(x, y)) {
ImageIO.write(gold, "png", new File("gold.png"));
ImageIO.write(snapshot, "png", new File("bi.png"));
throw new RuntimeException("Test failed.");
}
}
}
}
private static BufferedImage makeUnmanagedBI(final int type) {
final BufferedImage bi;
if (type == TYPE_CUSTOM) {
bi = makeCustomUnmanagedBI();
} else {
bi = new BufferedImage(511, 255, type);
}
final DataBuffer db = bi.getRaster().getDataBuffer();
if (db instanceof DataBufferInt) {
((DataBufferInt) db).getData();
} else if (db instanceof DataBufferShort) {
((DataBufferShort) db).getData();
} else if (db instanceof DataBufferByte) {
((DataBufferByte) db).getData();
}
bi.setAccelerationPriority(0.0f);
return bi;
}
/**
* Returns the custom buffered image, which mostly identical to
* BufferedImage.(w,h,TYPE_3BYTE_BGR), but uses the bigger scanlineStride.
* This means that the raster will have gaps, between the rows.
*/
private static BufferedImage makeCustomUnmanagedBI() {
int w = 511, h = 255;
ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
int[] nBits = {8, 8, 8};
int[] bOffs = {2, 1, 0};
ColorModel colorModel = new ComponentColorModel(cs, nBits, false, false,
Transparency.OPAQUE,
DataBuffer.TYPE_BYTE);
WritableRaster raster =
Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, w, h,
w * 3 + 2, 3, bOffs, null);
return new BufferedImage(colorModel, raster, true, null);
}
private static void fill(final Image image) {
final Graphics2D graphics = (Graphics2D) image.getGraphics();
graphics.setComposite(AlphaComposite.Src);
for (int i = 0; i < image.getHeight(null); ++i) {
graphics.setColor(new Color(i, 0, 0));
graphics.fillRect(0, i, image.getWidth(null), 1);
}
graphics.dispose();
}
}

View file

@ -0,0 +1,155 @@
/*
* Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* 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.
*/
/*
* @test
* @key headful
* @bug 8139183
* @summary Test verifies whether alpha channel of a translucent
* image is proper or not after scaling through drawImage.
* @run main ScaledImageAlphaTest
*/
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.Transparency;
import java.awt.image.BufferedImage;
import java.awt.image.VolatileImage;
public class ScaledImageAlphaTest {
static final int translucentAlpha = 128, opaqueAlpha = 255;
static final int[] translucentVariants = new int[] {
BufferedImage.TYPE_INT_ARGB,
BufferedImage.TYPE_INT_ARGB_PRE,
BufferedImage.TYPE_4BYTE_ABGR,
BufferedImage.TYPE_4BYTE_ABGR_PRE
};
static final int[] alphaValues = new int[] {
translucentAlpha,
opaqueAlpha
};
static int width = 50, height = 50;
static int scaleX = 5, scaleY = 5, scaleWidth = 40, scaleHeight = 40;
private static void verifyAlpha(Color color, int alpha) {
/* if extracted alpha value is equal alpha that we set
* for background color, alpha channel is not lost
* while scaling otherwise we have lost alpha channel.
*/
int extractedAlpha = color.getAlpha();
if (extractedAlpha != alpha) {
throw new RuntimeException("Alpha channel for background"
+ " is lost while scaling");
}
}
private static void validateBufferedImageAlpha() {
Color backgroundColor, extractedColor;
// verify for all translucent buffered image types
for (int type : translucentVariants) {
// verify for both opaque and translucent background color
for (int alpha : alphaValues) {
// create BufferedImage of dimension (50,50)
BufferedImage img = new
BufferedImage(width, height, type);
Graphics2D imgGraphics = (Graphics2D)img.getGraphics();
/* scale image to smaller dimension and set any
* background color with alpha.
*/
backgroundColor = new Color(0, 255, 0, alpha);
imgGraphics.
drawImage(img, scaleX, scaleY, scaleWidth, scaleHeight,
backgroundColor, null);
imgGraphics.dispose();
/* get pixel information for background color with
* scaled coordinates.
*/
extractedColor = new Color(img.getRGB(scaleX, scaleY), true);
verifyAlpha(extractedColor, alpha);
}
}
}
private static void validateVolatileImageAlpha() {
Color backgroundColor, extractedColor;
VolatileImage img;
BufferedImage bufImg = new
BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
for (int alpha : alphaValues) {
backgroundColor = new Color(0, 255, 0, alpha);
do {
img = createVolatileImage(width, height,
Transparency.TRANSLUCENT);
Graphics2D imgGraphics = (Graphics2D)img.getGraphics();
// clear VolatileImage as by default it has white opaque image
imgGraphics.setComposite(AlphaComposite.Clear);
imgGraphics.fillRect(0,0, width, height);
imgGraphics.setComposite(AlphaComposite.SrcOver);
/* scale image to smaller dimension and set background color
* to green with translucent alpha.
*/
imgGraphics.
drawImage(img, scaleX, scaleY, scaleWidth, scaleHeight,
backgroundColor, null);
//get BufferedImage out of VolatileImage
bufImg = img.getSnapshot();
imgGraphics.dispose();
} while (img.contentsLost());
/* get pixel information for background color with
* scaled coordinates.
*/
extractedColor = new Color(bufImg.getRGB(scaleX, scaleY), true);
verifyAlpha(extractedColor, alpha);
}
}
private static VolatileImage createVolatileImage(int width, int height,
int transparency) {
GraphicsEnvironment ge = GraphicsEnvironment.
getLocalGraphicsEnvironment();
GraphicsConfiguration gc = ge.getDefaultScreenDevice().
getDefaultConfiguration();
VolatileImage image = gc.createCompatibleVolatileImage(width, height,
transparency);
return image;
}
public static void main(String[] args) {
// test alpha channel with different types of BufferedImage
validateBufferedImageAlpha();
// test alpha channel with VolatileImage
validateVolatileImageAlpha();
}
}

View file

@ -0,0 +1,196 @@
/*
* Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* 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.
*/
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.Transparency;
import java.awt.color.ColorSpace;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.ComponentColorModel;
import java.awt.image.DataBuffer;
import java.awt.image.Raster;
import java.awt.image.VolatileImage;
import java.awt.image.WritableRaster;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import sun.awt.image.SunWritableRaster;
import static java.awt.Transparency.BITMASK;
import static java.awt.Transparency.OPAQUE;
import static java.awt.Transparency.TRANSLUCENT;
import static java.awt.image.BufferedImage.TYPE_3BYTE_BGR;
import static java.awt.image.BufferedImage.TYPE_4BYTE_ABGR;
import static java.awt.image.BufferedImage.TYPE_4BYTE_ABGR_PRE;
import static java.awt.image.BufferedImage.TYPE_BYTE_BINARY;
import static java.awt.image.BufferedImage.TYPE_BYTE_INDEXED;
import static java.awt.image.BufferedImage.TYPE_CUSTOM;
import static java.awt.image.BufferedImage.TYPE_INT_ARGB;
import static java.awt.image.BufferedImage.TYPE_INT_ARGB_PRE;
import static java.awt.image.BufferedImage.TYPE_INT_BGR;
import static java.awt.image.BufferedImage.TYPE_INT_RGB;
/**
* @test
* @key headful
* @bug 8029253 6207877
* @summary Tests the case when managed image is drawn to VI.
* Results of the blit to compatibleImage are used for comparison.
* @author Sergey Bylokhov
* @modules java.desktop/sun.awt.image
* @run main/othervm -Dsun.java2d.accthreshold=0 SimpleManagedImage
* @run main/othervm -Dsun.java2d.accthreshold=0 -Dsun.java2d.uiScale=1 SimpleManagedImage
* @run main/othervm -Dsun.java2d.accthreshold=0 -Dsun.java2d.uiScale=2 SimpleManagedImage
*/
public final class SimpleManagedImage {
// See the same test for unmanaged images: SimpleUnmanagedImage
private static final int[] TYPES = {TYPE_INT_RGB, TYPE_INT_ARGB,
TYPE_INT_ARGB_PRE, TYPE_INT_BGR,
TYPE_3BYTE_BGR, TYPE_4BYTE_ABGR,
TYPE_4BYTE_ABGR_PRE,
/*TYPE_USHORT_565_RGB,
TYPE_USHORT_555_RGB, TYPE_BYTE_GRAY,
TYPE_USHORT_GRAY,*/ TYPE_BYTE_BINARY,
TYPE_BYTE_INDEXED, TYPE_CUSTOM};
private static final int[] TRANSPARENCIES = {OPAQUE, BITMASK, TRANSLUCENT};
public static void main(final String[] args) throws IOException {
for (final int viType : TRANSPARENCIES) {
for (final int biType : TYPES) {
BufferedImage bi = makeManagedBI(biType);
fill(bi);
test(bi, viType);
}
}
}
private static void test(BufferedImage bi, int type)
throws IOException {
GraphicsEnvironment ge = GraphicsEnvironment
.getLocalGraphicsEnvironment();
GraphicsConfiguration gc = ge.getDefaultScreenDevice()
.getDefaultConfiguration();
VolatileImage vi = gc.createCompatibleVolatileImage(1000, 1000, type);
BufferedImage gold = gc.createCompatibleImage(1000, 1000, type);
// draw to compatible Image
init(gold);
Graphics2D big = gold.createGraphics();
big.drawImage(bi, 7, 11, null);
big.dispose();
// draw to volatile image
BufferedImage snapshot;
while (true) {
vi.validate(gc);
if (vi.validate(gc) != VolatileImage.IMAGE_OK) {
try {
Thread.sleep(100);
} catch (final InterruptedException ignored) {
}
continue;
}
init(vi);
Graphics2D vig = vi.createGraphics();
vig.drawImage(bi, 7, 11, null);
vig.dispose();
snapshot = vi.getSnapshot();
if (vi.contentsLost()) {
try {
Thread.sleep(100);
} catch (final InterruptedException ignored) {
}
continue;
}
break;
}
// validate images
for (int x = 0; x < 1000; ++x) {
for (int y = 0; y < 1000; ++y) {
if (gold.getRGB(x, y) != snapshot.getRGB(x, y)) {
ImageIO.write(gold, "png", new File("gold.png"));
ImageIO.write(snapshot, "png", new File("bi.png"));
throw new RuntimeException("Test failed.");
}
}
}
}
private static BufferedImage makeManagedBI(final int type) {
final BufferedImage bi;
if (type == TYPE_CUSTOM) {
bi = makeCustomManagedBI();
} else {
bi = new BufferedImage(511, 255, type);
}
bi.setAccelerationPriority(1.0f);
return bi;
}
/**
* Returns the custom buffered image, which mostly identical to
* BufferedImage.(w,h,TYPE_3BYTE_BGR), but uses the bigger scanlineStride.
* This means that the raster will have gaps, between the rows.
*/
private static BufferedImage makeCustomManagedBI() {
int w = 511, h = 255;
ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
int[] nBits = {8, 8, 8};
int[] bOffs = {2, 1, 0};
ColorModel colorModel = new ComponentColorModel(cs, nBits, false, false,
Transparency.OPAQUE,
DataBuffer.TYPE_BYTE);
WritableRaster raster =
Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, w, h,
w * 3 + 2, 3, bOffs, null);
BufferedImage bi = new BufferedImage(colorModel, raster, true, null);
SunWritableRaster.makeTrackable(raster.getDataBuffer());
SunWritableRaster.markDirty(bi);
return bi;
}
private static void init(final Image image) {
final Graphics2D graphics = (Graphics2D) image.getGraphics();
graphics.setComposite(AlphaComposite.Src);
graphics.setColor(new Color(0, 0, 0, 0));
graphics.fillRect(0, 0, image.getWidth(null), image.getHeight(null));
graphics.dispose();
}
private static void fill(final Image image) {
final Graphics2D graphics = (Graphics2D) image.getGraphics();
graphics.setComposite(AlphaComposite.Src);
for (int i = 0; i < image.getHeight(null); ++i) {
graphics.setColor(new Color(i, 0, 0));
graphics.fillRect(0, i, image.getWidth(null), 1);
}
graphics.dispose();
}
}

View file

@ -0,0 +1,201 @@
/*
* Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* 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.
*/
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.Transparency;
import java.awt.color.ColorSpace;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.ComponentColorModel;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferByte;
import java.awt.image.DataBufferInt;
import java.awt.image.DataBufferShort;
import java.awt.image.Raster;
import java.awt.image.VolatileImage;
import java.awt.image.WritableRaster;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import static java.awt.Transparency.BITMASK;
import static java.awt.Transparency.OPAQUE;
import static java.awt.Transparency.TRANSLUCENT;
import static java.awt.image.BufferedImage.TYPE_3BYTE_BGR;
import static java.awt.image.BufferedImage.TYPE_4BYTE_ABGR;
import static java.awt.image.BufferedImage.TYPE_4BYTE_ABGR_PRE;
import static java.awt.image.BufferedImage.TYPE_BYTE_BINARY;
import static java.awt.image.BufferedImage.TYPE_BYTE_INDEXED;
import static java.awt.image.BufferedImage.TYPE_CUSTOM;
import static java.awt.image.BufferedImage.TYPE_INT_ARGB;
import static java.awt.image.BufferedImage.TYPE_INT_ARGB_PRE;
import static java.awt.image.BufferedImage.TYPE_INT_BGR;
import static java.awt.image.BufferedImage.TYPE_INT_RGB;
/**
* @test
* @key headful
* @bug 8029253 6207877
* @summary Tests the case when unmanaged image is drawn to VI.
* Results of the blit to compatibleImage are used for comparison.
* @author Sergey Bylokhov
* @run main/othervm SimpleUnmanagedImage
* @run main/othervm -Dsun.java2d.uiScale=1 SimpleUnmanagedImage
* @run main/othervm -Dsun.java2d.uiScale=2 SimpleUnmanagedImage
*/
public final class SimpleUnmanagedImage {
// See the same test for managed images: SimpleManagedImage
private static final int[] TYPES = {TYPE_INT_RGB, TYPE_INT_ARGB,
TYPE_INT_ARGB_PRE, TYPE_INT_BGR,
TYPE_3BYTE_BGR, TYPE_4BYTE_ABGR,
TYPE_4BYTE_ABGR_PRE,
/*TYPE_USHORT_565_RGB,
TYPE_USHORT_555_RGB, TYPE_BYTE_GRAY,
TYPE_USHORT_GRAY,*/ TYPE_BYTE_BINARY,
TYPE_BYTE_INDEXED, TYPE_CUSTOM};
private static final int[] TRANSPARENCIES = {OPAQUE, BITMASK, TRANSLUCENT};
public static void main(final String[] args) throws IOException {
for (final int viType : TRANSPARENCIES) {
for (final int biType : TYPES) {
BufferedImage bi = makeUnmanagedBI(biType);
fill(bi);
test(bi, viType);
}
}
}
private static void test(BufferedImage bi, int type)
throws IOException {
GraphicsEnvironment ge = GraphicsEnvironment
.getLocalGraphicsEnvironment();
GraphicsConfiguration gc = ge.getDefaultScreenDevice()
.getDefaultConfiguration();
VolatileImage vi = gc.createCompatibleVolatileImage(1000, 1000, type);
BufferedImage gold = gc.createCompatibleImage(1000, 1000, type);
// draw to compatible Image
init(gold);
Graphics2D big = gold.createGraphics();
big.drawImage(bi, 7, 11, null);
big.dispose();
// draw to volatile image
BufferedImage snapshot;
while (true) {
vi.validate(gc);
if (vi.validate(gc) != VolatileImage.IMAGE_OK) {
try {
Thread.sleep(100);
} catch (final InterruptedException ignored) {
}
continue;
}
init(vi);
Graphics2D vig = vi.createGraphics();
vig.drawImage(bi, 7, 11, null);
vig.dispose();
snapshot = vi.getSnapshot();
if (vi.contentsLost()) {
try {
Thread.sleep(100);
} catch (final InterruptedException ignored) {
}
continue;
}
break;
}
// validate images
for (int x = 0; x < 1000; ++x) {
for (int y = 0; y < 1000; ++y) {
if (gold.getRGB(x, y) != snapshot.getRGB(x, y)) {
ImageIO.write(gold, "png", new File("gold.png"));
ImageIO.write(snapshot, "png", new File("bi.png"));
throw new RuntimeException("Test failed.");
}
}
}
}
private static BufferedImage makeUnmanagedBI(final int type) {
final BufferedImage bi;
if (type == TYPE_CUSTOM) {
bi = makeCustomUnmanagedBI();
} else {
bi = new BufferedImage(511, 255, type);
}
final DataBuffer db = bi.getRaster().getDataBuffer();
if (db instanceof DataBufferInt) {
((DataBufferInt) db).getData();
} else if (db instanceof DataBufferShort) {
((DataBufferShort) db).getData();
} else if (db instanceof DataBufferByte) {
((DataBufferByte) db).getData();
}
bi.setAccelerationPriority(0.0f);
return bi;
}
/**
* Returns the custom buffered image, which mostly identical to
* BufferedImage.(w,h,TYPE_3BYTE_BGR), but uses the bigger scanlineStride.
* This means that the raster will have gaps, between the rows.
*/
private static BufferedImage makeCustomUnmanagedBI() {
int w = 511, h = 255;
ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
int[] nBits = {8, 8, 8};
int[] bOffs = {2, 1, 0};
ColorModel colorModel = new ComponentColorModel(cs, nBits, false, false,
Transparency.OPAQUE,
DataBuffer.TYPE_BYTE);
WritableRaster raster =
Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, w, h,
w * 3 + 2, 3, bOffs, null);
return new BufferedImage(colorModel, raster, true, null);
}
private static void init(final Image image) {
final Graphics2D graphics = (Graphics2D) image.getGraphics();
graphics.setComposite(AlphaComposite.Src);
graphics.setColor(new Color(0, 0, 0, 0));
graphics.fillRect(0, 0, image.getWidth(null), image.getHeight(null));
graphics.dispose();
}
private static void fill(final Image image) {
final Graphics2D graphics = (Graphics2D) image.getGraphics();
graphics.setComposite(AlphaComposite.Src);
for (int i = 0; i < image.getHeight(null); ++i) {
graphics.setColor(new Color(i, 0, 0));
graphics.fillRect(0, i, image.getWidth(null), 1);
}
graphics.dispose();
}
}

View file

@ -0,0 +1,225 @@
/*
* Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* 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.
*/
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import java.awt.image.BandedSampleModel;
import java.awt.image.BufferedImage;
import java.awt.image.Raster;
import java.awt.image.ColorModel;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferByte;
import java.awt.image.RenderedImage;
import java.awt.image.SampleModel;
import java.awt.image.WritableRaster;
import java.util.Objects;
import java.util.Vector;
/**
* @test
* @bug 8275345
* @summary RasterFormatException when drawing a tiled image made of non-writable rasters.
*
* Test drawing a tiled image made of non-writable {@link Raster} tiles.
* Drawing works when tiles are instances of {@link WritableRaster}.
* But if tiles are instances of {@link Raster} only, then the following
* exception is thrown:
*
* Exception in thread "main" java.awt.image.RasterFormatException: (parentX + width) is outside raster
* at java.desktop/java.awt.image.WritableRaster.createWritableChild(WritableRaster.java:228)
* at java.desktop/sun.java2d.SunGraphics2D.drawTranslatedRenderedImage(SunGraphics2D.java:2852)
* at java.desktop/sun.java2d.SunGraphics2D.drawRenderedImage(SunGraphics2D.java:2711)
*
* The bug is demonstrated by drawing the same image twice:
* once with {@link WritableRaster} tiles (which succeed),
* then the same operation but with {@link Raster} tiles.
*
* The bug is caused by the following code in {@code SunGraphics2D}:
*
* // Create a WritableRaster containing the tile
* WritableRaster wRaster = null;
* if (raster instanceof WritableRaster) {
* wRaster = (WritableRaster)raster;
* } else {
* // Create a WritableRaster in the same coordinate system
* // as the original raster.
* wRaster =
* Raster.createWritableRaster(raster.getSampleModel(),
* raster.getDataBuffer(),
* null);
* }
* // Translate wRaster to start at (0, 0) and to contain
* // only the relevant portion of the tile
* wRaster = wRaster.createWritableChild(tileRect.x, tileRect.y,
* tileRect.width,
* tileRect.height,
* 0, 0,
* null);
*
* If {@code raster} is not an instance of {@link WritableRaster},
* then a new {@link WritableRaster} is created wrapping the same
* buffer <strong>but with a location of (0,0)</strong>, because
* the {@code location} argument of {@code createWritableRaster}
* is null. Consequently the call to {@code createWritableChild}
* shall not be done in that case, because the raster is already
* translated. The current code applies translation twice.
*
* This bug is largely unnoticed because most {@code Raster.create}
* methods actually create {@link WritableRaster} instances, even
* when the user did not asked for writable raster. To make this
* bug apparent, we need to invoke {@code Raster.createRaster(...)}
* with a sample model for which no optimization is provided.
*/
public class TiledImage implements RenderedImage {
/**
* Run the test using writable tiles first, then read-only tiles.
*/
public static void main(String[] args) {
draw(true); // Pass.
draw(false); // Fail if 8275345 is not fixed.
}
private static final int NUM_X_TILES = 2, NUM_Y_TILES = 3;
private static final int TILE_WIDTH = 16, TILE_HEIGHT = 12;
/**
* Tests rendering a tiled image.
*
* @param writable whether the image shall use writable raster.
*/
private static void draw(final boolean writable) {
final BufferedImage target = new BufferedImage(
TILE_WIDTH * NUM_X_TILES,
TILE_HEIGHT * NUM_Y_TILES,
BufferedImage.TYPE_BYTE_GRAY);
final RenderedImage source = new TiledImage(writable,
target.getColorModel());
Graphics2D g = target.createGraphics();
g.drawRenderedImage(source, new AffineTransform());
g.dispose();
}
private final ColorModel colorModel;
private final Raster[] tiles;
/**
* Creates a tiled image. The image is empty,
* but pixel values are not the purpose of this test.
*
* @param writable whether the image shall use writable raster.
*/
private TiledImage(boolean writable, ColorModel cm) {
/*
* We need a sample model class for which Raster.createRaster
* do not provide a special case. That method has optimizations
* for most SampleModel sub-types, except BandedSampleModel.
*/
SampleModel sm = new BandedSampleModel(DataBuffer.TYPE_BYTE, TILE_WIDTH, TILE_HEIGHT, 1);
tiles = new Raster[NUM_X_TILES * NUM_Y_TILES];
final Point location = new Point();
for (int tileY = 0; tileY < NUM_Y_TILES; tileY++) {
for (int tileX = 0; tileX < NUM_X_TILES; tileX++) {
location.x = tileX * TILE_WIDTH;
location.y = tileY * TILE_HEIGHT;
DataBufferByte db = new DataBufferByte(TILE_WIDTH * TILE_HEIGHT);
Raster r;
if (writable) {
r = Raster.createWritableRaster(sm, db, location);
} else {
// Case causing RasterFormatException later.
r = Raster.createRaster(sm, db, location);
}
tiles[tileX + tileY * NUM_X_TILES] = r;
}
}
colorModel = cm;
}
@Override
public ColorModel getColorModel() {
return colorModel;
}
@Override
public SampleModel getSampleModel() {
return tiles[0].getSampleModel();
}
@Override
public Vector<RenderedImage> getSources() {
return new Vector<>();
}
@Override
public Object getProperty(String key) {
return Image.UndefinedProperty;
}
@Override
public String[] getPropertyNames() {
return null;
}
@Override public int getMinX() {return 0;}
@Override public int getMinY() {return 0;}
@Override public int getMinTileX() {return 0;}
@Override public int getMinTileY() {return 0;}
@Override public int getTileGridXOffset() {return 0;}
@Override public int getTileGridYOffset() {return 0;}
@Override public int getNumXTiles() {return NUM_X_TILES;}
@Override public int getNumYTiles() {return NUM_Y_TILES;}
@Override public int getTileWidth() {return TILE_WIDTH;}
@Override public int getTileHeight() {return TILE_HEIGHT;}
@Override public int getWidth() {return TILE_WIDTH * NUM_X_TILES;}
@Override public int getHeight() {return TILE_HEIGHT * NUM_Y_TILES;}
@Override
public Raster getTile(final int tileX, final int tileY) {
Objects.checkIndex(tileX, NUM_X_TILES);
Objects.checkIndex(tileY, NUM_Y_TILES);
return tiles[tileX + tileY * NUM_X_TILES];
}
@Override
public Raster getData() {
throw new UnsupportedOperationException("Not needed for this test.");
}
@Override
public Raster getData(Rectangle rect) {
throw new UnsupportedOperationException("Not needed for this test.");
}
@Override
public WritableRaster copyData(WritableRaster raster) {
throw new UnsupportedOperationException("Not needed for this test.");
}
}

View file

@ -0,0 +1,126 @@
/*
* Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* 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.
*/
import java.awt.AlphaComposite;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.Polygon;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferByte;
import java.awt.image.DataBufferInt;
import java.awt.image.DataBufferShort;
import java.awt.image.VolatileImage;
import static java.awt.Transparency.*;
import static java.awt.image.BufferedImage.*;
/*
* @test
* @key headful
* @bug 8029253 8059941
* @summary Unmanaged images should be drawn fast.
* @author Sergey Bylokhov
*/
public final class UnmanagedDrawImagePerformance {
private static final int[] TYPES = {TYPE_INT_RGB, TYPE_INT_ARGB,
TYPE_INT_ARGB_PRE, TYPE_INT_BGR,
TYPE_3BYTE_BGR, TYPE_4BYTE_ABGR,
TYPE_4BYTE_ABGR_PRE,
TYPE_USHORT_565_RGB,
TYPE_USHORT_555_RGB, TYPE_BYTE_GRAY,
TYPE_USHORT_GRAY, TYPE_BYTE_BINARY,
TYPE_BYTE_INDEXED};
private static final int[] TRANSPARENCIES = {OPAQUE, BITMASK, TRANSLUCENT};
private static final int SIZE = 1000;
private static final AffineTransform[] TRANSFORMS = {
AffineTransform.getScaleInstance(.5, .5),
AffineTransform.getScaleInstance(1, 1),
AffineTransform.getScaleInstance(2, 2),
AffineTransform.getShearInstance(7, 11)};
public static void main(final String[] args) {
for (final AffineTransform atfm : TRANSFORMS) {
for (final int viType : TRANSPARENCIES) {
for (final int biType : TYPES) {
final BufferedImage bi = makeUnmanagedBI(biType);
final VolatileImage vi = makeVI(viType);
final long time = test(bi, vi, atfm) / 1000000000;
if (time > 1) {
throw new RuntimeException(String.format(
"drawImage is slow: %d seconds", time));
}
}
}
}
}
private static long test(Image bi, Image vi, AffineTransform atfm) {
final Polygon p = new Polygon();
p.addPoint(0, 0);
p.addPoint(SIZE, 0);
p.addPoint(0, SIZE);
p.addPoint(SIZE, SIZE);
p.addPoint(0, 0);
Graphics2D g2d = (Graphics2D) vi.getGraphics();
g2d.clip(p);
g2d.transform(atfm);
g2d.setComposite(AlphaComposite.SrcOver);
final long start = System.nanoTime();
g2d.drawImage(bi, 0, 0, null);
final long time = System.nanoTime() - start;
g2d.dispose();
return time;
}
private static VolatileImage makeVI(final int type) {
final GraphicsEnvironment ge = GraphicsEnvironment
.getLocalGraphicsEnvironment();
final GraphicsDevice gd = ge.getDefaultScreenDevice();
final GraphicsConfiguration gc = gd.getDefaultConfiguration();
return gc.createCompatibleVolatileImage(SIZE, SIZE, type);
}
private static BufferedImage makeUnmanagedBI(final int type) {
final BufferedImage img = new BufferedImage(SIZE, SIZE, type);
final DataBuffer db = img.getRaster().getDataBuffer();
if (db instanceof DataBufferInt) {
((DataBufferInt) db).getData();
} else if (db instanceof DataBufferShort) {
((DataBufferShort) db).getData();
} else if (db instanceof DataBufferByte) {
((DataBufferByte) db).getData();
} else {
try {
img.setAccelerationPriority(0.0f);
} catch (final Throwable ignored) {
}
}
return img;
}
}