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,271 @@
/*
* Copyright (c) 2003, 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 4975116 7040022 8023577 8025447 8286624
* @key headful
* @summary verify the rounding of negative coordinates in Shape objects
* @run main/othervm CoordinateTruncationBug
*/
import java.awt.Frame;
import java.awt.Canvas;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Robot;
import java.awt.Rectangle;
import java.awt.Point;
import java.awt.Dimension;
import java.awt.Color;
import java.awt.AWTException;
import java.awt.geom.Line2D;
import java.awt.image.BufferedImage;
import java.awt.image.VolatileImage;
public class CoordinateTruncationBug {
static boolean failure;
static boolean verbose;
static final int W = 80;
static final int H = 80;
static final Line2D vertline = new Line2D.Float(-0.7f, 0f, -0.7f, H);
static final Line2D horizline = new Line2D.Float(0f, -0.7f, W, -0.7f);
public static void main(String argv[]) {
verbose = (argv.length > 0);
new Screen().test();
new BufImg().test();
new VolImg().test();
if (failure) {
throw new RuntimeException("Test failed due to 1 or more failures");
}
}
public static abstract class Test {
public abstract String getName();
public abstract void makeDest();
public abstract void runTest();
public abstract void dispose();
public abstract BufferedImage getSnapshot();
public void test() {
makeDest();
runTest();
dispose();
}
public void runTest(Graphics2D g2d) {
g2d.setColor(Color.white);
g2d.fillRect(0, 0, W, H);
if (!checkAllWhite()) {
System.err.println("Aborting test of "+getName()+
" due to readback failure!");
return;
}
g2d.setColor(Color.red);
g2d.draw(vertline);
g2d.draw(horizline);
if (!checkAllWhite()) {
System.err.println(getName()+" failed!");
failure = true;
}
}
public boolean checkAllWhite() {
BufferedImage bimg = getSnapshot();
if (bimg == null) {
System.err.println(getName()+" returned null snapshot!");
return false;
}
boolean ret = true;
for (int y = 0; y < H; y++) {
for (int x = 0; x < W; x++) {
int rgb = bimg.getRGB(x, y);
if (rgb != -1) {
System.err.println(getName()+"("+x+", "+y+") == "+
Integer.toHexString(rgb));
if (verbose) {
ret = false;
} else {
return false;
}
}
}
}
return ret;
}
}
public static class Screen extends Test {
Frame frame;
TestCanvas canvas;
public String getName() {
return "Screen";
}
public void makeDest() {
frame = new Frame("Screen test");
frame.setUndecorated(true);
canvas = new TestCanvas(this);
frame.add(canvas);
frame.pack();
frame.setLocationRelativeTo(null);
}
public void runTest() {
frame.show();
canvas.waitForTest();
}
public Graphics2D createGraphics() {
return null;
}
public BufferedImage getSnapshot() {
// bypass window animation
try {
Thread.sleep(500);
} catch (InterruptedException e) {
};
try {
Robot r = new Robot();
Point p = canvas.getLocationOnScreen();
return r.createScreenCapture(new Rectangle(p.x, p.y, W, H));
} catch (AWTException e) {
return null;
}
}
public void dispose() {
frame.hide();
frame.dispose();
}
public static class TestCanvas extends Canvas {
Test test;
boolean done;
public TestCanvas(Test test) {
this.test = test;
}
public Dimension getPreferredSize() {
return new Dimension(W, H);
}
public synchronized void waitForTest() {
while (!done) {
try {
wait();
} catch (InterruptedException e) {
System.err.println(getName()+" interrupted!");
failure = true;
break;
}
}
}
public void paint(Graphics g) {
if (!done) {
test.runTest((Graphics2D) g);
notifyDone();
}
}
public synchronized void notifyDone() {
done = true;
notifyAll();
}
}
}
public abstract static class Standalone extends Test {
public abstract Graphics2D createGraphics();
public void runTest() {
Graphics2D g2d = createGraphics();
runTest(g2d);
g2d.dispose();
}
}
public static class BufImg extends Standalone {
public BufferedImage bimg;
public String getName() {
return "BufferedImage";
}
public void makeDest() {
bimg = new BufferedImage(W, H, BufferedImage.TYPE_INT_RGB);
}
public Graphics2D createGraphics() {
return bimg.createGraphics();
}
public BufferedImage getSnapshot() {
return bimg;
}
public void dispose() {
}
}
public static class VolImg extends Standalone {
Frame frame;
VolatileImage vimg;
public String getName() {
return "VolatileImage";
}
public void makeDest() {
frame = new Frame();
frame.setSize(W, H);
frame.setLocationRelativeTo(null);
frame.show();
vimg = frame.createVolatileImage(W, H);
}
public Graphics2D createGraphics() {
return vimg.createGraphics();
}
public BufferedImage getSnapshot() {
return vimg.getSnapshot();
}
public void dispose() {
vimg.flush();
frame.hide();
frame.dispose();
}
}
}

View file

@ -0,0 +1,185 @@
/*
* Copyright (c) 2007, 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
* @key headful
* @bug 5009033 6603000 6666362 8159142 8198613
* @summary Verifies that images transformed with bilinear filtering do not
* leave artifacts at the edges.
* @run main/othervm -Dsun.java2d.uiScale=2.5 DrawImageBilinear
* @run main/othervm -Dsun.java2d.uiScale=2.5 -Dsun.java2d.d3d=false DrawImageBilinear
*/
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.awt.image.IndexColorModel;
import java.awt.image.VolatileImage;
public class DrawImageBilinear extends Canvas {
private static final int SIZE = 5;
private static boolean done;
private BufferedImage bimg1, bimg2;
private VolatileImage vimg;
private static BufferedImage capture;
private static DrawImageBilinear test;
private static Frame frame;
private void renderPattern(Graphics g) {
g.setColor(Color.red);
g.fillRect(0, 0, SIZE, SIZE);
g.dispose();
}
public void paint(Graphics g) {
Graphics2D g2d = (Graphics2D)g;
if (bimg1 == null) {
bimg1 = (BufferedImage)createImage(SIZE, SIZE);
bimg1.setAccelerationPriority(0.0f);
renderPattern(bimg1.createGraphics());
bimg2 = (BufferedImage)createImage(SIZE, SIZE);
renderPattern(bimg2.createGraphics());
vimg = createVolatileImage(SIZE, SIZE);
vimg.validate(getGraphicsConfiguration());
renderPattern(vimg.createGraphics());
}
do {
g2d.setColor(Color.white);
g2d.fillRect(0, 0, getWidth(), getHeight());
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
// first time will be a sw->surface blit
g2d.drawImage(bimg1, 10, 10, 40, 40, null);
// second time will be a texture->surface blit
g2d.drawImage(bimg2, 80, 10, 40, 40, null);
g2d.drawImage(bimg2, 80, 10, 40, 40, null);
// third time will be a pbuffer->surface blit
if (vimg.validate(getGraphicsConfiguration()) !=
VolatileImage.IMAGE_OK) {
renderPattern(vimg.createGraphics());
}
g2d.drawImage(vimg, 150, 10, 40, 40, null);
Toolkit.getDefaultToolkit().sync();
} while (vimg.contentsLost());
}
public Dimension getPreferredSize() {
return new Dimension(200, 100);
}
private static void testRegion(BufferedImage bi,
Rectangle affectedRegion)
{
int x1 = affectedRegion.x;
int y1 = affectedRegion.y;
int x2 = x1 + affectedRegion.width;
int y2 = y1 + affectedRegion.height;
for (int y = y1; y < y2; y++) {
for (int x = x1; x < x2; x++) {
int actual = bi.getRGB(x, y);
if ((actual != 0xfffe0000) && (actual != 0xffff0000)) {
throw new RuntimeException("Test failed at x="+x+" y="+y+
" (expected=0xffff0000"+
" actual=0x"+
Integer.toHexString(actual) +
")");
}
}
}
}
private static void createAndShowGUI() {
test = new DrawImageBilinear();
frame = new Frame();
frame.add(test);
frame.setUndecorated(true);
frame.setAlwaysOnTop(true);
frame.setLocationRelativeTo(null);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) throws Exception {
try {
EventQueue.invokeAndWait(() -> createAndShowGUI());
GraphicsConfiguration gc = frame.getGraphicsConfiguration();
if (gc.getColorModel() instanceof IndexColorModel) {
System.out.println("IndexColorModel detected: " +
"test considered PASSED");
return;
}
Robot robot = new Robot();
robot.setAutoDelay(100);
robot.mouseMove(0,0);
robot.waitForIdle();
Point pt1 = frame.getLocationOnScreen();
Rectangle rect =
new Rectangle(pt1.x, pt1.y,
frame.getWidth(), frame.getHeight());
capture = robot.createScreenCapture(rect);
robot.waitForIdle();
if (capture == null) {
throw new RuntimeException("Failed: capture is null");
}
// Test background color
int pixel = capture.getRGB(5, 5);
if (pixel != 0xffffffff) {
throw new RuntimeException("Failed: Incorrect color for " +
"background");
}
// Test pixels
testRegion(capture, new Rectangle(10, 10, 40, 40));
testRegion(capture, new Rectangle(80, 10, 40, 40));
testRegion(capture, new Rectangle(150, 10, 40, 40));
} finally {
if (frame != null) {
frame.dispose();
}
}
}
}

View file

@ -0,0 +1,69 @@
/*
* Copyright (c) 2001, 2024, 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 4515761
* @summary verify that drawRoundRect produces correct output for 0 w/h
*/
import java.awt.Color;
import static java.awt.Color.*;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
public class DrawRoundRect0Bug {
public static void main(String argv[]) {
BufferedImage img = new BufferedImage(250, 250, BufferedImage.TYPE_INT_RGB);
Graphics2D g = img.createGraphics();
g.setColor(white);
g.fillRect(0, 0, img.getWidth(), img.getHeight());
g.setColor(green);
g.drawLine(150, 90, 150, 110);
if (img.getRGB(150, 100) != green.getRGB()) {
throw new RuntimeException("Vertical line not green");
}
g.setColor(blue);
g.drawRoundRect(160, 90, 0, 20, 4, 4);
if (img.getRGB(160, 100) != blue.getRGB()) {
throw new RuntimeException("Vertical (ie zero width) round rect not blue");
}
g.setColor(green);
g.drawLine(150, 140, 170, 140);
if (img.getRGB(160, 140) != green.getRGB()) {
throw new RuntimeException("Horizontal line not green");
}
g.setColor(blue);
g.drawRoundRect(150, 150, 20, 0, 4, 4);
if (img.getRGB(160, 150) != blue.getRGB()) {
throw new RuntimeException("Horizontal (ie zero height) round rect not blue");
}
}
}

View file

@ -0,0 +1,300 @@
/*
* Copyright (c) 2014, 2018, 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.AWTException;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.HeadlessException;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.awt.image.VolatileImage;
import java.io.File;
import java.io.IOException;
import java.util.HashSet;
import javax.imageio.ImageIO;
import sun.awt.ConstrainableGraphics;
/**
* @test
* @key headful
* @bug 6335200 6419610 8198613
* @summary Tests that we don't render anything if specific empty clip is set
* @author Dmitri.Trembovetski@Sun.COM: area=Graphics
* @modules java.desktop/sun.awt
* @run main EmptyClipRenderingTest
* @run main/othervm -Dsun.java2d.noddraw=true EmptyClipRenderingTest
* @run main/othervm -Dsun.java2d.pmoffscreen=true EmptyClipRenderingTest
*/
public class EmptyClipRenderingTest {
static final int IMG_W = 400;
static final int IMG_H = 400;
// generated rectangles
static HashSet<Rectangle> rects;
volatile boolean isActivated = false;
volatile boolean isPainted;
private static boolean showErrors = false;
public EmptyClipRenderingTest() {
// initialize clip/render region rectangles
initClips();
HashSet<RuntimeException> errors = new HashSet<RuntimeException>();
BufferedImage screenResult = testOnscreen();
try {
testResult(screenResult, "Screen");
} catch (RuntimeException e) {
errors.add(e);
}
BufferedImage destBI =
new BufferedImage(IMG_W, IMG_H, BufferedImage.TYPE_INT_RGB);
runTest((Graphics2D)destBI.getGraphics());
try {
testResult(destBI, "BufferedImage");
} catch (RuntimeException e) {
errors.add(e);
}
GraphicsConfiguration gc =
GraphicsEnvironment.getLocalGraphicsEnvironment().
getDefaultScreenDevice().getDefaultConfiguration();
VolatileImage destVI = gc.createCompatibleVolatileImage(IMG_W, IMG_H);
destVI.validate(gc);
runTest((Graphics2D)destVI.getGraphics());
try {
testResult(destVI.getSnapshot(), "VolatileImage");
} catch (RuntimeException e) {
errors.add(e);
}
if (errors.isEmpty()) {
System.err.println("Test PASSED.");
} else {
for (RuntimeException re : errors) {
re.printStackTrace();
}
if (showErrors) {
System.err.println("Test FAILED: "+ errors.size() +
" subtest failures.");
} else {
throw new RuntimeException("Test FAILED: "+ errors.size() +
" subtest failures.");
}
}
}
/**
* Recursively adds 4 new rectangles: two vertical and two horizontal
* based on the passed rectangle area. The area is then shrunk and the
* process repeated for smaller area.
*/
private static void add4Rects(HashSet<Rectangle> rects, Rectangle area) {
if (area.width < 10 || area.height < 10) {
rects.add(area);
return;
}
// two vertical rects
rects.add(new Rectangle(area.x, area.y, 5, area.height));
rects.add(new Rectangle(area.x + area.width - 5, area.y, 5, area.height));
// two horizontal rects
int width = area.width - 2*(5 + 1);
rects.add(new Rectangle(area.x+6, area.y, width, 5));
rects.add(new Rectangle(area.x+6, area.y + area.height - 5, width, 5));
// reduce the area and repeat
area.grow(-6, -6);
add4Rects(rects, area);
}
/**
* Generate a bunch of non-intersecting rectangles
*/
private static void initClips() {
rects = new HashSet<Rectangle>();
add4Rects(rects, new Rectangle(0, 0, IMG_W, IMG_H));
System.err.println("Total number of test rects: " + rects.size());
}
/**
* Render the pattern to the screen, capture the output with robot and
* return it.
*/
private BufferedImage testOnscreen() throws HeadlessException {
final Canvas destComponent;
final Object lock = new Object();
Frame f = new Frame("Test Frame");
f.setUndecorated(true);
f.add(destComponent = new Canvas() {
public void paint(Graphics g) {
isPainted = true;
}
public Dimension getPreferredSize() {
return new Dimension(IMG_W, IMG_H);
}
});
f.addWindowListener(new WindowAdapter() {
public void windowActivated(WindowEvent e) {
if (!isActivated) {
synchronized (lock) {
isActivated = true;
lock.notify();
}
}
}
});
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
synchronized(lock) {
while (!isActivated) {
try {
lock.wait(100);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
Robot r;
try {
r = new Robot();
} catch (AWTException ex) {
throw new RuntimeException("Can't create Robot");
}
BufferedImage bi;
int attempt = 0;
do {
if (++attempt > 10) {
throw new RuntimeException("Too many attempts: " + attempt);
}
isPainted = false;
runTest((Graphics2D) destComponent.getGraphics());
r.waitForIdle();
Toolkit.getDefaultToolkit().sync();
bi = r.createScreenCapture(
new Rectangle(destComponent.getLocationOnScreen().x,
destComponent.getLocationOnScreen().y,
destComponent.getWidth(),
destComponent.getHeight()));
} while (isPainted);
f.setVisible(false);
f.dispose();
return bi;
}
/**
* Run the test: cycle through all the rectangles, use one as clip and
* another as the area to render to.
* Set the clip in the same way Swing does it when repainting:
* first constrain the graphics to the damaged area, and repaint everything
*/
void runTest(Graphics2D destGraphics) {
destGraphics.setColor(Color.black);
destGraphics.fillRect(0, 0, IMG_W, IMG_H);
destGraphics.setColor(Color.red);
for (Rectangle clip : rects) {
Graphics2D g2d = (Graphics2D)destGraphics.create();
g2d.setColor(Color.red);
// mimic what swing does in BufferStrategyPaintManager
if (g2d instanceof ConstrainableGraphics) {
((ConstrainableGraphics)g2d).constrain(clip.x, clip.y,
clip.width, clip.height);
}
g2d.setClip(clip);
for (Rectangle renderRegion : rects) {
if (renderRegion != clip) {
// from CellRendererPane's paintComponent
Graphics2D rG = (Graphics2D)
g2d.create(renderRegion.x, renderRegion.y,
renderRegion.width, renderRegion.height);
rG.fillRect(0,0, renderRegion.width, renderRegion.height);
}
}
}
}
void testResult(final BufferedImage bi, final String desc) {
for (int y = 0; y < bi.getHeight(); y++) {
for (int x = 0; x < bi.getWidth(); x++) {
if (bi.getRGB(x, y) != Color.black.getRGB()) {
if (showErrors) {
Frame f = new Frame("Error: " + desc);
f.add(new Component() {
public void paint(Graphics g) {
g.drawImage(bi, 0, 0, null);
}
public Dimension getPreferredSize() {
return new Dimension(bi.getWidth(),
bi.getHeight());
}
});
f.pack();
f.setVisible(true);
}
try {
String fileName =
"EmptyClipRenderingTest_"+desc+"_res.png";
System.out.println("Writing resulting image: "+fileName);
ImageIO.write(bi, "png", new File(fileName));
} catch (IOException ex) {
ex.printStackTrace();
}
throw new RuntimeException("Dest: "+desc+
" was rendered to at x="+
x + " y=" + y +
" pixel="+Integer.toHexString(bi.getRGB(x,y)));
}
}
}
}
public static void main(String argv[]) {
for (String arg : argv) {
if (arg.equals("-show")) {
showErrors = true;
} else {
usage("Incorrect argument:" + arg);
}
}
new EmptyClipRenderingTest();
}
private static void usage(String string) {
System.out.println(string);
System.out.println("Usage: EmptyClipRenderingTest [-show]");
}
}

View file

@ -0,0 +1,661 @@
/*
* Copyright (c) 2002, 2018, 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 4678208 4771101 6328481 6588884 8198613
* @summary verify the pixelization of degenerate polylines and polygons
* @run main PolyVertTest
* @run main/othervm -Dsun.java2d.d3d=True PolyVertTest -hwonly
*/
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.awt.image.*;
public class PolyVertTest {
static int TESTWIDTH;
static int TESTHEIGHT;
static final int REG_TEST_WIDTH = 10;
static final int REG_TEST_HEIGHT = 10;
static final int FULL_TEST_WIDTH = 50;
static final int FULL_TEST_HEIGHT = 200;
static final int FRINGE = 2;
static final int GREEN = Color.green.getRGB();
static final int RED = Color.red.getRGB();
static BufferedImage refImg;
static BufferedImage errorImg;
static Graphics errorG;
static Component testCanvas;
static int totalbadpixels;
static int totalfuzzypixels;
static int numbadtests;
static int numfuzzytests;
static int numframes;
static int fuzzystarty;
static boolean counting;
static boolean showerrors;
static boolean showresults;
static boolean fringe;
static boolean forceerror;
static boolean fulltest = true;
static boolean hwonly;
static WindowListener windowCloser = new WindowAdapter() {
public void windowClosing(WindowEvent e) {
e.getWindow().hide();
if (--numframes <= 0) {
System.exit(0);
}
}
};
public PolyVertTest() {
/*
setBackground(Color.white);
setForeground(Color.black);
*/
}
static int polypts[][][] = {
{
// void polygon (no points)
{}, {},
},
{
// one point
{ 0 }, { 0 },
},
{
// two points
{ 0, 5 }, { 0, 0 },
{ 0, 0, 6, 1,
10, 0, 6, 1,
20, 0, 6, 1 },
{ 0, 0, 6, 1,
10, 0, 1, 1, 15, 0, 1, 1,
20, 0, 1, 1, 25, 0, 1, 1 },
{ 10, 0, 1, 1,
20, 0, 1, 1 },
},
{
// open triangle
{ 0, 5, 5 }, { 0, 0, 5 },
{ 0, 0, 6, 1, 5, 1, 1, 5,
10, 0, 6, 1, 15, 1, 1, 5, 11, 1, 1, 1,
12, 2, 1, 1, 13, 3, 1, 1, 14, 4, 1, 1,
20, 0, 6, 1, 25, 1, 1, 5, 21, 1, 1, 1,
22, 2, 1, 1, 23, 3, 1, 1, 24, 4, 1, 1 },
{ 0, 0, 6, 1, 5, 1, 1, 5,
10, 0, 6, 1, 15, 1, 1, 5, 11, 1, 1, 1,
12, 2, 1, 1, 13, 3, 1, 1, 14, 4, 1, 1,
20, 0, 6, 1, 25, 1, 1, 5, 21, 1, 1, 1,
22, 2, 1, 1, 23, 3, 1, 1, 24, 4, 1, 1 },
{ 10, 0, 1, 1,
20, 0, 1, 1 },
},
{
// closed triangle
{ 0, 5, 5, 0 }, { 0, 0, 5, 0 },
{ 0, 0, 6, 1, 5, 1, 1, 5, 1, 1, 1, 1,
2, 2, 1, 1, 3, 3, 1, 1, 4, 4, 1, 1,
10, 0, 6, 1, 15, 1, 1, 5, 11, 1, 1, 1,
12, 2, 1, 1, 13, 3, 1, 1, 14, 4, 1, 1,
20, 0, 6, 1, 25, 1, 1, 5, 21, 1, 1, 1,
22, 2, 1, 1, 23, 3, 1, 1, 24, 4, 1, 1 },
{ 1, 0, 5, 1, 5, 1, 1, 5, 1, 1, 1, 1,
2, 2, 1, 1, 3, 3, 1, 1, 4, 4, 1, 1,
10, 0, 6, 1, 15, 1, 1, 5, 11, 1, 1, 1,
12, 2, 1, 1, 13, 3, 1, 1, 14, 4, 1, 1,
20, 0, 6, 1, 25, 1, 1, 5, 21, 1, 1, 1,
22, 2, 1, 1, 23, 3, 1, 1, 24, 4, 1, 1 },
{ 0, 0, 1, 1,
10, 0, 1, 1,
20, 0, 1, 1 },
},
{
// empty line
{ 0, 0 }, { 0, 0 },
{ 0, 0, 1, 1,
10, 0, 1, 1,
20, 0, 1, 1 },
},
{
// empty triangle
{ 0, 0, 0 }, { 0, 0, 0 },
{ 0, 0, 1, 1,
10, 0, 1, 1,
20, 0, 1, 1 },
},
};
public static void render(Graphics2D g2d) {
g2d.setColor(Color.white);
g2d.fillRect(0, 0, TESTWIDTH, TESTHEIGHT);
g2d.setColor(Color.black);
if (forceerror) {
g2d.fillRect(2, 2, 2, 2);
g2d.fillRect(15, 5, 1, 1);
}
if (!fulltest) {
g2d.draw(new Rectangle2D.Double(5, 5, 0, 0));
return;
}
g2d.drawLine(10, 10, 10, 10);
g2d.draw(new Line2D.Double(20, 10, 20, 10));
g2d.drawRect(10, 20, 0, 0);
g2d.draw(new Rectangle2D.Double(20, 20, 0, 0));
g2d.setXORMode(Color.white);
g2d.drawLine(10, 30, 10, 30);
g2d.draw(new Line2D.Double(20, 30, 20, 30));
g2d.drawRect(10, 40, 0, 0);
g2d.draw(new Rectangle2D.Double(20, 40, 0, 0));
g2d.setPaintMode();
int y = 50;
for (int i = 0; i < polypts.length; i++) {
int data[][] = polypts[i];
int xpoints[] = data[0];
int ypoints[] = data[1];
int npoints = xpoints.length;
g2d.translate(10, y);
g2d.drawPolyline(xpoints, ypoints, npoints);
g2d.translate(10, 0);
g2d.drawPolygon(xpoints, ypoints, npoints);
g2d.translate(10, 0);
g2d.draw(new Polygon(xpoints, ypoints, npoints));
g2d.translate(-30, -y);
y += 10;
}
g2d.setXORMode(Color.white);
for (int i = 0; i < polypts.length; i++) {
int data[][] = polypts[i];
int xpoints[] = data[0];
int ypoints[] = data[1];
int npoints = xpoints.length;
g2d.translate(10, y);
g2d.drawPolyline(xpoints, ypoints, npoints);
g2d.translate(10, 0);
g2d.drawPolygon(xpoints, ypoints, npoints);
g2d.translate(10, 0);
g2d.draw(new Polygon(xpoints, ypoints, npoints));
g2d.translate(-30, -y);
y += 10;
}
g2d.setPaintMode();
}
public Dimension getPreferredSize() {
return new Dimension(500, 500);
}
public static void usage(int exitcode) {
System.err.println("usage: java PolyVertTest [<option>]*");
System.err.println(" -usage "+
"print this usage summary");
System.err.println(" -count "+
"run all tests and accumulate error counts");
System.err.println(" -forceerror "+
"force at least one error in each test");
System.err.println(" -fringe "+
"draw a yellow fringe around problems");
System.err.println(" -showerrors "+
"display results window for tests with problems");
System.err.println(" -showresults "+
"display results window for all tests");
System.err.println(" -quicktest "+
"only run test cases reported in bug reports");
System.err.println(" -fulltest "+
"run full suite of test cases for a 'unit test'");
System.err.println(" -hwonly "+
"only run tests for screen and VolatileImage");
System.exit(exitcode);
}
public static void main(String argv[]) {
for (int i = 0; i < argv.length; i++) {
String arg = argv[i];
if (arg.equalsIgnoreCase("-count")) {
counting = true;
} else if (arg.equalsIgnoreCase("-forceerror")) {
forceerror = true;
} else if (arg.equalsIgnoreCase("-fringe")) {
fringe = true;
} else if (arg.equalsIgnoreCase("-showerrors")) {
showerrors = true;
} else if (arg.equalsIgnoreCase("-showresults")) {
showresults = true;
} else if (arg.equalsIgnoreCase("-quicktest")) {
fulltest = false;
} else if (arg.equalsIgnoreCase("-fulltest")) {
fulltest = true;
} else if (arg.equalsIgnoreCase("-hwonly")) {
hwonly = true;
} else if (arg.equalsIgnoreCase("-usage")) {
usage(0);
} else {
System.err.println("unknown option: "+arg);
usage(1);
}
}
if (fulltest) {
TESTWIDTH = FULL_TEST_WIDTH;
TESTHEIGHT = FULL_TEST_HEIGHT;
} else {
TESTWIDTH = REG_TEST_WIDTH;
TESTHEIGHT = REG_TEST_HEIGHT;
}
// Prevents premature exit by the WindowAdapter if the user
// closes the last visible results window before we've
// finished our tests.
numframes++;
makeReferenceImage();
testScreen();
testVolatileImage();
if (!hwonly) {
testBufferedImage();
testOffscreen();
testCompatibleImages();
}
if (totalfuzzypixels > 0) {
System.err.println(totalfuzzypixels+" fuzzy pixels found in "+
numfuzzytests+" tests");
}
if (totalbadpixels > 0) {
throw new RuntimeException(totalbadpixels+" bad pixels found in "+
numbadtests+" tests");
}
System.out.println("Test done - no bad pixels found");
--numframes;
if (counting || ((showresults || showerrors) && numframes == 0)) {
System.exit(0);
}
}
public static void makeReferenceImage() {
refImg = new BufferedImage(TESTWIDTH, TESTHEIGHT,
BufferedImage.TYPE_INT_RGB);
Graphics g = refImg.getGraphics();
g.setColor(Color.white);
g.fillRect(0, 0, TESTWIDTH, TESTHEIGHT);
g.setColor(Color.black);
if (!fulltest) {
g.fillRect(5, 5, 1, 1);
g.dispose();
return;
}
for (int y = 10; y < 50; y += 10) {
g.fillRect(10, y, 1, 1);
g.fillRect(20, y, 1, 1);
}
int y = 50;
for (int i = 0; i < polypts.length; i++) {
int data[][] = polypts[i];
g.translate(10, y);
if (data.length > 2) {
int rectvals[] = data[2];
for (int j = 0; j < rectvals.length; j += 4) {
g.fillRect(rectvals[j+0], rectvals[j+1],
rectvals[j+2], rectvals[j+3]);
}
}
g.translate(-10, -y);
y += 10;
}
fuzzystarty = y;
for (int i = 0; i < polypts.length; i++) {
int data[][] = polypts[i];
g.translate(10, y);
if (data.length > 2) {
int rectvals[] = data.length > 3 ? data[3] : data[2];
for (int j = 0; j < rectvals.length; j += 4) {
g.fillRect(rectvals[j+0], rectvals[j+1],
rectvals[j+2], rectvals[j+3]);
}
}
g.translate(-10, -y);
y += 10;
}
g.dispose();
}
public static void initerrorbuf() {
if (errorImg == null) {
droperrorbuf();
errorImg = new BufferedImage(TESTWIDTH, TESTHEIGHT,
BufferedImage.TYPE_INT_RGB);
}
if (errorG == null) {
errorG = errorImg.getGraphics();
}
errorG.setColor(Color.green);
errorG.fillRect(0, 0, TESTWIDTH, TESTHEIGHT);
errorG.setColor(Color.red);
}
public static void droperrorbuf() {
errorImg = null;
if (errorG != null) {
errorG.dispose();
}
errorG = null;
}
public static void test(Image img, String name) {
Graphics2D g2d = (Graphics2D) img.getGraphics();
render(g2d);
g2d.dispose();
verify(img, name);
}
public static void test(BufferedImage bimg, String name) {
Graphics2D g2d = bimg.createGraphics();
render(g2d);
g2d.dispose();
verify(bimg, name);
}
public static void verify(Image img, String name) {
BufferedImage bimg;
if (img instanceof BufferedImage) {
bimg = (BufferedImage) img;
} else {
bimg = new BufferedImage(TESTWIDTH, TESTHEIGHT,
BufferedImage.TYPE_INT_RGB);
Graphics g = bimg.getGraphics();
g.drawImage(img, 0, 0, null);
g.dispose();
}
verify(bimg, name);
}
public static boolean isFuzzyPixel(int X, int Y) {
int ytrans = fuzzystarty;
if (!fulltest || Y < ytrans) {
return false;
}
for (int i = 0; i < polypts.length; i++) {
int data[][] = polypts[i];
if (data.length > 4) {
int rectvals[] = data[4];
for (int j = 0; j < rectvals.length; j += 4) {
int rectx = rectvals[j+0] + 10;
int recty = rectvals[j+1] + ytrans;
int rectw = rectvals[j+2];
int recth = rectvals[j+3];
if (X >= rectx && Y >= recty &&
X < rectx + rectw && Y < recty + recth)
{
return true;
}
}
}
ytrans += 10;
}
return false;
}
public static void verify(BufferedImage bimg, String name) {
int numbadpixels = 0;
int numfuzzypixels = 0;
for (int y = 0; y < TESTHEIGHT; y++) {
for (int x = 0; x < TESTWIDTH; x++) {
if (refImg.getRGB(x, y) != bimg.getRGB(x, y)) {
boolean isfuzzy = isFuzzyPixel(x, y);
if (showerrors || showresults) {
if (errorG == null) {
initerrorbuf();
}
errorG.setColor(isfuzzy ? Color.blue : Color.red);
errorG.fillRect(x, y, 1, 1);
} else if (!counting && !isfuzzy) {
throw new RuntimeException("Error at "+x+", "+y+
" while testing: "+name);
}
if (isfuzzy) {
numfuzzypixels++;
} else {
numbadpixels++;
}
}
}
}
if (numbadpixels > 0 || numfuzzypixels > 0) {
if (numbadpixels > 0) {
totalbadpixels += numbadpixels;
numbadtests++;
}
if (numfuzzypixels > 0) {
totalfuzzypixels += numfuzzypixels;
numfuzzytests++;
}
System.out.println(numbadpixels+" bad pixels and "+
numfuzzypixels+" questionable pixels "+
"found while testing "+name);
if (showerrors || showresults) {
displaydiffs(bimg, name);
}
} else if (showresults) {
if (errorG == null) {
initerrorbuf();
}
displaydiffs(bimg, name);
}
}
public static void displaydiffs(BufferedImage bimg, String name) {
if (fringe) {
errorG.setColor(Color.yellow);
for (int y = 0; y < TESTHEIGHT; y++) {
for (int x = 0; x < TESTWIDTH; x++) {
if (errorImg.getRGB(x, y) == RED) {
for (int iy = y-FRINGE; iy <= y+FRINGE; iy++) {
for (int ix = x-FRINGE; ix <= x+FRINGE; ix++) {
if (ix >= 0 && ix < TESTWIDTH &&
iy >= 0 && iy < TESTHEIGHT &&
errorImg.getRGB(ix, iy) == GREEN)
{
errorG.fillRect(ix, iy, 1, 1);
}
}
}
}
}
}
}
Frame f = new Frame("Results for "+name);
f.setLayout(new BorderLayout());
f.addWindowListener(windowCloser);
++numframes;
Panel p = new Panel();
p.add(new ImageCanvas(bimg));
p.add(new ImageCanvas(errorImg));
p.add(new ImageCanvas(refImg));
f.add(p, "Center");
droperrorbuf();
f.pack();
f.show();
}
public static void testBufferedImage() {
testBufferedImage(BufferedImage.TYPE_INT_RGB, "IntXrgb");
testBufferedImage(BufferedImage.TYPE_INT_ARGB, "IntArgb");
testBufferedImage(BufferedImage.TYPE_3BYTE_BGR, "ThreeByte");
testBufferedImage(BufferedImage.TYPE_4BYTE_ABGR, "FourByte");
testBufferedImage(BufferedImage.TYPE_USHORT_555_RGB, "UShort555");
testBufferedImage(BufferedImage.TYPE_BYTE_GRAY, "ByteGray");
testBufferedImage(BufferedImage.TYPE_BYTE_INDEXED, "Indexed");
}
public static void testBufferedImage(int type, String name) {
BufferedImage bimg = new BufferedImage(TESTWIDTH, TESTHEIGHT, type);
test(bimg, name);
}
public static void testScreen() {
Frame f = new Frame("PolyVertTest");
TestCanvas child = new TestCanvas();
testCanvas = child;
f.add(child);
f.pack();
f.show();
BufferedImage bimg = child.getImage();
f.hide();
verify(bimg, "Screen");
}
public static void testOffscreen() {
Image img = testCanvas.createImage(TESTWIDTH, TESTHEIGHT);
test(img, "Offscreen");
}
public static void testCompatibleImages() {
GraphicsEnvironment genv =
GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice gdevs[] = genv.getScreenDevices();
for (int i = 0; i < gdevs.length; i++) {
testCompatibleImages(gdevs[i]);
}
}
public static void testCompatibleImages(GraphicsDevice gdev) {
GraphicsConfiguration gconfigs[] = gdev.getConfigurations();
for (int i = 0; i < gconfigs.length; i++) {
testCompatibleImages(gconfigs[i]);
}
}
public static void testCompatibleImages(GraphicsConfiguration gconfig) {
test(gconfig.createCompatibleImage(TESTWIDTH, TESTHEIGHT),
gconfig+".createCompat()");
test(gconfig.createCompatibleImage(TESTWIDTH, TESTHEIGHT,
Transparency.OPAQUE),
gconfig+".createCompat(OPAQUE)");
test(gconfig.createCompatibleImage(TESTWIDTH, TESTHEIGHT,
Transparency.BITMASK),
gconfig+".createCompat(BITMASK)");
test(gconfig.createCompatibleImage(TESTWIDTH, TESTHEIGHT,
Transparency.TRANSLUCENT),
gconfig+".createCompat(TRANSLUCENT)");
test(gconfig.createCompatibleVolatileImage(TESTWIDTH, TESTHEIGHT),
gconfig+".createCompatVolatile()");
}
public static void testVolatileImage() {
Image img = testCanvas.createVolatileImage(TESTWIDTH, TESTHEIGHT);
test(img, "Volatile");
}
public static class ImageCanvas extends Canvas {
BufferedImage bimg;
public ImageCanvas(BufferedImage bimg) {
this.bimg = bimg;
}
public Dimension getPreferredSize() {
return new Dimension(bimg.getWidth(), bimg.getHeight());
}
public void paint(Graphics g) {
g.drawImage(bimg, 0, 0, null);
}
}
public static class TestCanvas extends Canvas {
BufferedImage bimg;
public Dimension getPreferredSize() {
return new Dimension(TESTWIDTH, TESTHEIGHT);
}
public void paint(Graphics g) {
if (bimg != null ||
getWidth() < TESTWIDTH ||
getHeight() < TESTHEIGHT)
{
return;
}
render((Graphics2D) g);
Toolkit.getDefaultToolkit().sync();
Point p = getLocationOnScreen();
Rectangle r = new Rectangle(p.x, p.y, TESTWIDTH, TESTHEIGHT);
try {
bimg = new Robot().createScreenCapture(r);
} catch (AWTException e) {
e.printStackTrace();
}
synchronized (this) {
notifyAll();
}
}
public synchronized BufferedImage getImage() {
while (bimg == null) {
try {
wait();
} catch (InterruptedException e) {
return null;
}
}
return bimg;
}
}
}

View file

@ -0,0 +1,104 @@
/*
* Copyright (c) 2002, 2024, 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 4652373
* @summary verify that SunGraphics2D survives surface revalidation
* @library /java/awt/regtesthelpers
* @build PassFailJFrame
* @run main/manual RevalidateBug
* @requires (os.family == "windows")
*/
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.Rectangle;
import javax.swing.JComponent;
import javax.swing.JFrame;
public class RevalidateBug {
private static final String INSTRUCTIONS = """
This bug only reproduces on Windows systems with a task manager that can lock the computer.
This test draws a grayscale gradient in a window.
After the gradient becomes visible above, use ctrl-alt-del to bring up
the task manager and lock the computer.
Then unlock the computer and the gradient should be repainted to pass.
If the gradient does not appear after unlocking (or if the test gets
an error on its own after unlocking the computer) then it fails.
""";
public static void main(String[] argv) throws Exception {
PassFailJFrame.builder()
.title("RevalidateBug")
.instructions(INSTRUCTIONS)
.testTimeOut(5)
.rows(12)
.columns(50)
.testUI(RevalidateBug::createUI)
.build()
.awaitAndCheck();
}
private static JFrame createUI() {
JComponent comp = new JComponent() {
protected void paintComponent(Graphics g) {
super.paintComponent(g);
System.out.println("paintComponent");
Graphics2D g2d = (Graphics2D) g;
Insets insets = getInsets();
Rectangle rect =
new Rectangle(insets.left, insets.top,
getWidth() - insets.right - insets.left,
getHeight() - insets.top - insets.bottom);
g2d.setPaint(new GradientPaint(rect.x, rect.y, Color.white,
rect.x + rect.width, rect.y, Color.black));
System.out.println(rect + " w:" + getWidth() + " h:"+getHeight());
g2d.fillRect(0, 0, getWidth(), getHeight());
}
public Dimension getPreferredSize() {
return new Dimension(500, 500);
}
};
JFrame f = new JFrame("RevalidateTest");
f.add(comp);
f.pack();
return f;
}
}

View file

@ -0,0 +1,95 @@
/*
* Copyright (c) 2001, 2024, 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 4516037
* @summary verify that scaled Polygons honor the transform
*/
import java.awt.Color;
import static java.awt.Color.*;
import java.awt.Graphics2D;
import java.awt.Polygon;
import java.awt.image.BufferedImage;
public class ScaledPolyTest {
public static void main(String[] args) {
Polygon poly = new Polygon();
poly.addPoint(20, 10);
poly.addPoint(30, 30);
poly.addPoint(10, 30);
poly.addPoint(20, 10);
int height = 300;
int width = 300;
BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = bi.createGraphics();
g2d.setColor(Color.white);
g2d.fillRect(0, 0, bi.getWidth(), bi.getHeight());
g2d.translate(10, 10);
g2d.scale(2, 2);
g2d.setColor(Color.yellow);
g2d.fill(poly);
g2d.setColor(Color.blue);
g2d.draw(poly);
/*
* Examine each row of the image.
* If the stroked polygon is correctly aligned on the filled polygon,
* if there is anything except white on the line,
* the transition will always be white+->blue+->yellow*->blue*->white+
*/
int bluePix = blue.getRGB();
int yellowPix = yellow.getRGB();
int whitePix = white.getRGB();
for (int y = 0; y < height; y++ ) {
int x = 0;
int pix = whitePix;
while (pix == whitePix && x < width) pix = bi.getRGB(x++, y);
if (pix == whitePix && x == width) continue; // all white row.
if (pix != bluePix) throw new RuntimeException("Expected blue");
while (pix == bluePix) pix = bi.getRGB(x++, y);
if (pix == yellowPix) {
while (pix == yellowPix) pix = bi.getRGB(x++, y);
if (pix != bluePix) throw new RuntimeException("Expected blue");
while (pix == bluePix) pix = bi.getRGB(x++, y);
if (pix != whitePix) throw new RuntimeException("Expected white");
}
while (pix == whitePix && x < width) pix = bi.getRGB(x++, y);
if (pix == whitePix && x == width) {
continue;
} else {
throw new RuntimeException("Expected white to finish the row");
}
}
}
}

View file

@ -0,0 +1,281 @@
/*
* Copyright (c) 2005, 2018, 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 4832224 6322584 6328478 6328481 6322580 6588884 6587863 8198613
* @summary Verifies that the pixelization of simple primitives (drawLine,
* fillRect, drawRect, fill, draw) with the OGL pipeline enabled
* matches that produced by our software loops. (The primitives tested here
* are simple enough that the OGL results should match the software results
* exactly.) There is some overlap with PolyVertTest as we test both
* solid and XOR rendering here, but this testcase is a bit simpler and
* more appropriate for quick OGL testing. This test is also useful for
* comparing quality between our X11/GDI and software pipelines.
* @run main/othervm SimplePrimQuality
* @author campbelc
*/
import java.awt.*;
import java.awt.geom.*;
import java.awt.image.*;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class SimplePrimQuality extends Canvas {
private static final int SIZE = 300;
private static boolean done;
private static boolean testVI;
private static volatile BufferedImage capture;
private static void doCapture(Component test) {
// Grab the screen region
try {
Robot robot = new Robot();
Point pt1 = test.getLocationOnScreen();
Rectangle rect =
new Rectangle(pt1.x, pt1.y, test.getWidth(), test.getHeight());
capture = robot.createScreenCapture(rect);
} catch (Exception e) {
e.printStackTrace();
}
}
private static final int[][] rpts = {
{2, 0, 0, 0},
{12, 0, 1, 0},
{22, 0, 0, 1},
{32, 0, 1, 1},
{42, 0, 2, 1},
{52, 0, 1, 2},
{62, 0, 2, 2},
{72, 0, 5, 5},
{82, 0, 10, 10},
{97, 0, 15, 15},
};
private void drawLine(Graphics2D g, int x, int y, int dx, int dy) {
g.drawLine(x, y, x + dx, y + dy);
}
private void drawLines(Graphics2D g, int s) {
drawLine(g, 2, 0, 0, 0);
drawLine(g, 12, 0, 0, s);
drawLine(g, 22, 0, s, 0);
drawLine(g, 32, 0, s, s);
drawLine(g, 42, 0, 0, -s);
drawLine(g, 52, 0, -s, 0);
drawLine(g, 62, 0, -s, -s);
drawLine(g, 72, 0, -s, s);
drawLine(g, 82, 0, s, -s);
}
private void fillRects(Graphics2D g) {
for (int i = 0; i < rpts.length; i++) {
g.fillRect(rpts[i][0], rpts[i][1], rpts[i][2], rpts[i][3]);
}
}
private void drawRects(Graphics2D g) {
for (int i = 0; i < rpts.length; i++) {
g.drawRect(rpts[i][0], rpts[i][1], rpts[i][2], rpts[i][3]);
}
}
private void fillOvals(Graphics2D g) {
for (int i = 0; i < rpts.length; i++) {
// use fill() instead of fillOval(), since the former is more
// likely to be consistent with our software loops when the
// OGL pipeline cannot be enabled
g.fill(new Ellipse2D.Float(rpts[i][0], rpts[i][1],
rpts[i][2], rpts[i][3]));
}
}
private void drawOvals(Graphics2D g) {
for (int i = 0; i < rpts.length; i++) {
// use draw() instead of drawOval(), since the former is more
// likely to be consistent with our software loops when the
// OGL pipeline cannot be enabled
g.draw(new Ellipse2D.Float(rpts[i][0], rpts[i][1],
rpts[i][2], rpts[i][3]));
}
}
private void renderShapes(Graphics2D g) {
// drawLine tests...
g.translate(0, 5);
drawLines(g, 1);
g.translate(0, 10);
drawLines(g, 4);
// fillRect tests...
g.translate(0, 10);
fillRects(g);
// drawRect tests...
g.translate(0, 20);
drawRects(g);
// fillOval tests...
g.translate(0, 20);
fillOvals(g);
// drawOval tests...
g.translate(0, 20);
drawOvals(g);
}
private void renderTest(Graphics2D g, int w, int h) {
// on the left side, render the shapes in solid mode
g.setColor(Color.black);
g.fillRect(0, 0, w, h);
g.setColor(Color.green);
renderShapes(g);
// on the right side, render the shapes in XOR mode
g.setTransform(AffineTransform.getTranslateInstance(SIZE/2, 0));
g.setXORMode(Color.black);
renderShapes(g);
g.setTransform(AffineTransform.getTranslateInstance(SIZE/2, 0));
renderShapes(g);
}
public void paint(Graphics g) {
Graphics2D g2d = (Graphics2D)g;
renderTest(g2d, SIZE, SIZE);
Toolkit.getDefaultToolkit().sync();
synchronized (this) {
if (!done) {
doCapture(this);
done = true;
}
notifyAll();
}
}
public Dimension getPreferredSize() {
return new Dimension(SIZE, SIZE);
}
public static void main(String[] args) {
boolean show = false;
for (String arg : args) {
if (arg.equals("-testvi")) {
System.out.println("Testing VolatileImage, not screen");
testVI = true;
} else if (arg.equals("-show")) {
show = true;
}
}
SimplePrimQuality test = new SimplePrimQuality();
Frame frame = new Frame();
frame.add(test);
frame.pack();
frame.setVisible(true);
// Wait until the component's been painted
synchronized (test) {
while (!done) {
try {
test.wait();
} catch (InterruptedException e) {
throw new RuntimeException("Failed: Interrupted");
}
}
}
// REMIND: We will allow this test to pass silently on Windows
// (when OGL is not enabled) until we fix the GDI pipeline so that
// its stroked/filled GeneralPaths match our software loops (see
// 6322554). This check should be removed when 6322554 is fixed.
GraphicsConfiguration gc = frame.getGraphicsConfiguration();
if (gc.getClass().getSimpleName().startsWith("Win")) {
System.out.println("GDI pipeline detected: " +
"test considered PASSED");
frame.dispose();
return;
}
if (testVI) {
// render to a VI instead of the screen
VolatileImage vi = frame.createVolatileImage(SIZE, SIZE);
do {
vi.validate(frame.getGraphicsConfiguration());
Graphics2D g1 = vi.createGraphics();
test.renderTest(g1, SIZE, SIZE);
g1.dispose();
capture = vi.getSnapshot();
} while (vi.contentsLost());
frame.dispose();
}
if (!show) {
frame.dispose();
}
if (capture == null) {
throw new RuntimeException("Error capturing the rendering");
}
// Create reference image
int w = SIZE, h = SIZE;
BufferedImage refimg = new BufferedImage(w, h,
BufferedImage.TYPE_INT_RGB);
Graphics2D g = refimg.createGraphics();
test.renderTest(g, w, h);
g.dispose();
// Test pixels
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
int actual = capture.getRGB(x, y);
int expected = refimg.getRGB(x, y);
if (actual != expected) {
String expectedName = "SimplePrimQuality_expected.png";
String actualName = "SimplePrimQuality_actual.png";
try {
System.out.println("Writing expected image to: "+
expectedName);
ImageIO.write(refimg, "png", new File(expectedName));
System.out.println("Writing actual image to: "+
actualName);
ImageIO.write(capture, "png", new File(actualName));
} catch (IOException ex) {}
throw new RuntimeException("Test failed at x="+x+" y="+y+
" (expected="+
Integer.toHexString(expected) +
" actual="+
Integer.toHexString(actual) +
")");
}
}
}
}
}

View file

@ -0,0 +1,299 @@
/*
* Copyright (c) 2005, 2010, 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 6244574
@bug 6258142
@bug 6395165
@bug 6588884
@summary Tests that source is clipped correctly when blitting
different types of images to the screen
@author Dmitri.Trembovetski: area=Graphics2D
@run main SourceClippingBlitTest
*/
import java.awt.AWTException;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.GraphicsConfiguration;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.Transparency;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.awt.image.VolatileImage;
public class SourceClippingBlitTest extends Canvas {
static final int TESTW = 300;
static final int TESTH = 300;
static final int IMAGEW = 50;
static final int IMAGEH = 50;
static final Rectangle IMAGE_BOUNDS = new Rectangle(0, 0, IMAGEW, IMAGEH);
static Robot robot;
static private boolean showErrors;
private static final Object lock = new Object();
private static volatile boolean done = false;
BufferedImage grabbedBI;
public static void main(String[] args) {
// allow user to override the properties if needed
if (System.getProperty("sun.java2d.pmoffscreen") == null) {
System.setProperty("sun.java2d.pmoffscreen", "true");
}
if (args.length > 0 && args[0].equals("-showerrors")) {
showErrors = true;
}
try {
robot = new Robot();
} catch (AWTException e) {
throw new RuntimeException(e);
}
Frame f = new Frame(SourceClippingBlitTest.class.getName());
final SourceClippingBlitTest test = new SourceClippingBlitTest();
f.add(test);
f.addWindowListener(new WindowAdapter() {
public void windowActivated(WindowEvent e) {
if (!done) {
test.runTests();
}
}
});
f.pack();
f.setLocation(100, 100);
f.setVisible(true);
synchronized (lock) {
while (!done) {
try {
lock.wait();
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
if (!showErrors) {
f.dispose();
}
}
public Dimension getPreferredSize() {
return new Dimension(TESTW, TESTH);
}
public void paint(Graphics g) {
if (showErrors && done && grabbedBI != null) {
g.drawImage(grabbedBI, 0, 0, null);
}
}
public void runTests() {
GraphicsConfiguration gc = getGraphicsConfiguration();
for (Image srcIm :
new Image[] {
getBufferedImage(gc, IMAGEW, IMAGEH,
BufferedImage.TYPE_INT_RGB, true),
getBufferedImage(gc, IMAGEW, IMAGEH,
BufferedImage.TYPE_INT_RGB, false),
// commented out due to 6593406
// getBMImage(gc, IMAGEW, IMAGEH),
// getBufferedImage(gc, IMAGEW, IMAGEH,
// BufferedImage.TYPE_INT_ARGB, true),
// getBufferedImage(gc, IMAGEW, IMAGEH,
// BufferedImage.TYPE_INT_ARGB, false),
getVImage(gc, IMAGEW, IMAGEH),
})
{
System.out.println("Testing source: " + srcIm);
// wiggle the source and dest rectangles
try {
for (int locationVar = -10; locationVar < 20; locationVar += 10)
{
for (int sizeVar = -10; sizeVar < 20; sizeVar += 10) {
Rectangle srcRect = (Rectangle)IMAGE_BOUNDS.clone();
srcRect.translate(locationVar, locationVar);
srcRect.grow(sizeVar, sizeVar);
Rectangle dstRect =
new Rectangle(sizeVar, sizeVar,
srcRect.width, srcRect.height);
System.out.println("testing blit rect src: " + srcRect);
System.out.println(" dst: " + dstRect);
render(getGraphics(), srcIm, srcRect, dstRect);
test(srcRect, dstRect);
}
}
System.out.println("Test passed.");
} finally {
synchronized (lock) {
done = true;
lock.notifyAll();
}
}
}
}
public void render(Graphics g, Image image,
Rectangle srcRect, Rectangle dstRect)
{
int w = getWidth();
int h = getHeight();
g.setColor(Color.green);
g.fillRect(0, 0, w, h);
int bltWidth = srcRect.width;
int bltHeight = srcRect.height;
VolatileImage vi = null;
if (image instanceof VolatileImage) {
vi = (VolatileImage)image;
}
do {
if (vi != null) {
GraphicsConfiguration gc = getGraphicsConfiguration();
if (vi.validate(gc) != VolatileImage.IMAGE_OK) {
initImage(gc, vi);
}
}
g.drawImage(image,
dstRect.x, dstRect.y,
dstRect.x + bltWidth, dstRect.y + bltHeight,
srcRect.x, srcRect.y,
srcRect.x + bltWidth, srcRect.y + bltHeight,
Color.red,
null);
} while (vi != null && vi.contentsLost());
}
public void test(Rectangle srcRect, Rectangle dstRect) {
int w = getWidth();
int h = getHeight();
Toolkit.getDefaultToolkit().sync();
try {
Thread.sleep(2000);
} catch (InterruptedException ex) {}
Point p = getLocationOnScreen();
grabbedBI = robot.createScreenCapture(new Rectangle(p.x, p.y, w, h));
// calculate the destination rectangle
Rectangle srcBounds = srcRect.intersection(IMAGE_BOUNDS);
int trX = dstRect.x - srcRect.x;
int trY = dstRect.y - srcRect.y;
Rectangle newDstRect = (Rectangle)dstRect.clone();
newDstRect.translate(-trX, -trY);
Rectangle.intersect(newDstRect, srcBounds, newDstRect);
newDstRect.translate(trX, trY);
Rectangle.intersect(newDstRect, new Rectangle(0, 0, w, h), newDstRect);
System.out.println("calculated dest rect:" + newDstRect);
// we do implicit clipping of the destination surface
// by only checking pixels within its bounds
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
int rgb = 0;
if (newDstRect.contains(x, y)) {
rgb = Color.red.getRGB();
} else {
rgb = Color.green.getRGB();
}
if (grabbedBI.getRGB(x, y) != rgb) {
String msg1 = "Test failed at x="+x+" y="+y;
System.out.println(msg1);
System.out.println(" expected: "+Integer.toHexString(rgb)+
" got:"+Integer.toHexString(grabbedBI.getRGB(x, y)));
throw new RuntimeException(msg1);
}
}
}
System.out.println("subtest passed");
}
static VolatileImage dstImage;
static void initImage(GraphicsConfiguration gc, Image image) {
Graphics g = image.getGraphics();
g.setColor(Color.RED);
int w = image.getWidth(null);
int h = image.getHeight(null);
g.fillRect(0, 0, w, h);
g.dispose();
// need to 'accelerate' the image
if (dstImage == null) {
dstImage =
gc.createCompatibleVolatileImage(TESTW, TESTH,
Transparency.OPAQUE);
}
dstImage.validate(gc);
g = dstImage.getGraphics();
g.drawImage(image, 0, 0, null);
g.drawImage(image, 0, 0, null);
g.drawImage(image, 0, 0, null);
}
static VolatileImage getVImage(GraphicsConfiguration gc,
int w, int h)
{
VolatileImage image =
gc.createCompatibleVolatileImage(w, h, Transparency.OPAQUE);
image.validate(gc);
initImage(gc, image);
return image;
}
static Image getBMImage(GraphicsConfiguration gc,
int w, int h)
{
Image image =
gc.createCompatibleImage(w, h, Transparency.BITMASK);
initImage(gc, image);
return image;
}
static Image getBufferedImage(GraphicsConfiguration gc,
int w, int h, int type, boolean acceleratable)
{
BufferedImage image = new BufferedImage(w, h, type);
if (!acceleratable) {
image.setAccelerationPriority(0.0f);
}
initImage(gc, image);
return image;
}
}

View file

@ -0,0 +1,85 @@
/*
* 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.Component;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.Window;
import java.awt.image.BufferedImage;
import sun.java2d.SunGraphics2D;
import static java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment;
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_INT_ARGB;
/**
* @test
* @key headful
* @bug 8134603
* @modules java.desktop/sun.java2d
* @run main/othervm SurfaceDestination
*/
public final class SurfaceDestination {
public static void main(final String[] args) {
final GraphicsEnvironment lge = getLocalGraphicsEnvironment();
final GraphicsDevice dev = lge.getDefaultScreenDevice();
final GraphicsConfiguration config = dev.getDefaultConfiguration();
test(config.createCompatibleImage(10, 10).getGraphics());
test(config.createCompatibleImage(10, 10, OPAQUE).getGraphics());
test(config.createCompatibleImage(10, 10, BITMASK).getGraphics());
test(config.createCompatibleImage(10, 10, TRANSLUCENT).getGraphics());
test(new BufferedImage(10, 10, TYPE_INT_ARGB).getGraphics());
final Window frame = new Frame();
frame.pack();
try {
test(frame.getGraphics());
test(frame.createImage(10, 10).getGraphics());
} finally {
frame.dispose();
}
}
private static void test(final Graphics graphics) {
try {
if (graphics instanceof SunGraphics2D) {
final Object dst = ((SunGraphics2D) graphics).getDestination();
if (!(dst instanceof Image) && !(dst instanceof Component)) {
throw new RuntimeException("Wrong type:" + dst);
}
}
} finally {
graphics.dispose();
}
}
}