blob: 769b372f0d8ed12c72e48dd30ed5153be785884b [file] [log] [blame]
/*
* Copyright (c) 2002, 2007, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package j2dbench.tests;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.AlphaComposite;
import java.awt.Stroke;
import java.awt.BasicStroke;
import java.awt.GradientPaint;
import java.awt.LinearGradientPaint;
import java.awt.MultipleGradientPaint;
import java.awt.MultipleGradientPaint.CycleMethod;
import java.awt.MultipleGradientPaint.ColorSpaceType;
import java.awt.RadialGradientPaint;
import java.awt.RenderingHints;
import java.awt.TexturePaint;
import java.awt.geom.CubicCurve2D;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.PrintWriter;
import java.util.ArrayList;
import javax.swing.JComponent;
import j2dbench.Group;
import j2dbench.Node;
import j2dbench.Option;
import j2dbench.TestEnvironment;
public abstract class RenderTests extends GraphicsTests {
static Group renderroot;
static Group renderoptroot;
static Group rendertestroot;
static Group rendershaperoot;
static Option paintList;
static Option doAntialias;
static Option doAlphaColors;
static Option sizeList;
static Option strokeList;
static final int NUM_RANDOMCOLORS = 4096;
static final int NUM_RANDOMCOLORMASK = (NUM_RANDOMCOLORS - 1);
static Color randAlphaColors[];
static Color randOpaqueColors[];
static {
randOpaqueColors = new Color[NUM_RANDOMCOLORS];
randAlphaColors = new Color[NUM_RANDOMCOLORS];
for (int i = 0; i < NUM_RANDOMCOLORS; i++) {
int r = (int) (Math.random() * 255);
int g = (int) (Math.random() * 255);
int b = (int) (Math.random() * 255);
randOpaqueColors[i] = new Color(r, g, b);
randAlphaColors[i] = makeAlphaColor(randOpaqueColors[i], 32);
}
}
static boolean hasMultiGradient;
static {
try {
hasMultiGradient = (MultipleGradientPaint.class != null);
} catch (NoClassDefFoundError e) {
}
}
public static void init() {
renderroot = new Group(graphicsroot, "render", "Rendering Benchmarks");
renderoptroot = new Group(renderroot, "opts", "Rendering Options");
rendertestroot = new Group(renderroot, "tests", "Rendering Tests");
ArrayList paintStrs = new ArrayList();
ArrayList paintDescs = new ArrayList();
paintStrs.add("single");
paintDescs.add("Single Color");
paintStrs.add("random");
paintDescs.add("Random Color");
if (hasGraphics2D) {
paintStrs.add("gradient2");
paintDescs.add("2-color GradientPaint");
if (hasMultiGradient) {
paintStrs.add("linear2");
paintDescs.add("2-color LinearGradientPaint");
paintStrs.add("linear3");
paintDescs.add("3-color LinearGradientPaint");
paintStrs.add("radial2");
paintDescs.add("2-color RadialGradientPaint");
paintStrs.add("radial3");
paintDescs.add("3-color RadialGradientPaint");
}
paintStrs.add("texture20");
paintDescs.add("20x20 TexturePaint");
paintStrs.add("texture32");
paintDescs.add("32x32 TexturePaint");
}
String[] paintStrArr = new String[paintStrs.size()];
paintStrArr = (String[])paintStrs.toArray(paintStrArr);
String[] paintDescArr = new String[paintDescs.size()];
paintDescArr = (String[])paintDescs.toArray(paintDescArr);
paintList =
new Option.ObjectList(renderoptroot,
"paint", "Paint Type",
paintStrArr, paintStrArr,
paintStrArr, paintDescArr,
0x1);
((Option.ObjectList) paintList).setNumRows(5);
// add special RandomColorOpt for backwards compatibility with
// older options files
new RandomColorOpt();
if (hasGraphics2D) {
doAlphaColors =
new Option.Toggle(renderoptroot, "alphacolor",
"Set the alpha of the paint to 0.125",
Option.Toggle.Off);
doAntialias =
new Option.Toggle(renderoptroot, "antialias",
"Render shapes antialiased",
Option.Toggle.Off);
String strokeStrings[] = {
"width0",
"width1",
"width5",
"width20",
"dash0_5",
"dash1_5",
"dash5_20",
"dash20_50",
};
String strokeDescriptions[] = {
"Solid Thin lines",
"Solid Width 1 lines",
"Solid Width 5 lines",
"Solid Width 20 lines",
"Dashed Thin lines",
"Dashed Width 1 lines",
"Dashed Width 5 lines",
"Dashed Width 20 lines",
};
BasicStroke strokeObjects[] = {
new BasicStroke(0f),
new BasicStroke(1f),
new BasicStroke(5f),
new BasicStroke(20f),
new BasicStroke(0f, BasicStroke.CAP_SQUARE,
BasicStroke.JOIN_MITER, 10f,
new float[] { 5f, 5f }, 0f),
new BasicStroke(1f, BasicStroke.CAP_SQUARE,
BasicStroke.JOIN_MITER, 10f,
new float[] { 5f, 5f }, 0f),
new BasicStroke(5f, BasicStroke.CAP_SQUARE,
BasicStroke.JOIN_MITER, 10f,
new float[] { 20f, 20f }, 0f),
new BasicStroke(20f, BasicStroke.CAP_SQUARE,
BasicStroke.JOIN_MITER, 10f,
new float[] { 50f, 50f }, 0f),
};
strokeList =
new Option.ObjectList(renderoptroot,
"stroke", "Stroke Type",
strokeStrings, strokeObjects,
strokeStrings, strokeDescriptions,
0x2);
((Option.ObjectList) strokeList).setNumRows(4);
}
new DrawDiagonalLines();
new DrawHorizontalLines();
new DrawVerticalLines();
new FillRects();
new DrawRects();
new FillOvals();
new DrawOvals();
new FillPolys();
new DrawPolys();
if (hasGraphics2D) {
rendershaperoot = new Group(rendertestroot, "shape",
"Shape Rendering Tests");
new FillCubics();
new DrawCubics();
new FillEllipse2Ds();
new DrawEllipse2Ds();
}
}
/**
* This "virtual Node" implementation is here to maintain backward
* compatibility with older J2DBench releases, specifically those
* options files that were created before we added the gradient/texture
* paint options in JDK 6. This class will translate the color settings
* from the old "randomcolor" option into the new "paint" option.
*/
private static class RandomColorOpt extends Node {
public RandomColorOpt() {
super(renderoptroot, "randomcolor",
"Use random colors for each shape");
}
public JComponent getJComponent() {
return null;
}
public void restoreDefault() {
// no-op
}
public void write(PrintWriter pw) {
// no-op (the random/single choice will be saved as part of
// the new "paint" option added to J2DBench in JDK 6)
}
public String setOption(String key, String value) {
String opts;
if (value.equals("On")) {
opts = "random";
} else if (value.equals("Off")) {
opts = "single";
} else if (value.equals("Both")) {
opts = "random,single";
} else {
return "Bad value";
}
return ((Option.ObjectList)paintList).setValueFromString(opts);
}
}
public static class Context extends GraphicsTests.Context {
int colorindex;
Color colorlist[];
}
public RenderTests(Group parent, String nodeName, String description) {
super(parent, nodeName, description);
addDependencies(renderoptroot, true);
}
public GraphicsTests.Context createContext() {
return new RenderTests.Context();
}
public void initContext(TestEnvironment env, GraphicsTests.Context ctx) {
super.initContext(env, ctx);
RenderTests.Context rctx = (RenderTests.Context) ctx;
boolean alphacolor;
if (hasGraphics2D) {
Graphics2D g2d = (Graphics2D) rctx.graphics;
if (env.isEnabled(doAntialias)) {
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
}
alphacolor = env.isEnabled(doAlphaColors);
g2d.setStroke((Stroke) env.getModifier(strokeList));
} else {
alphacolor = false;
}
String paint = (String)env.getModifier(paintList);
if (paint.equals("single")) {
Color c = Color.darkGray;
if (alphacolor) {
c = makeAlphaColor(c, 32);
}
rctx.graphics.setColor(c);
} else if (paint.equals("random")) {
rctx.colorlist = alphacolor ? randAlphaColors : randOpaqueColors;
} else if (paint.equals("gradient2")) {
Color[] colors = makeGradientColors(2, alphacolor);
Graphics2D g2d = (Graphics2D)rctx.graphics;
g2d.setPaint(new GradientPaint(0.0f, 0.0f, colors[0],
10.0f, 10.0f, colors[1], true));
} else if (paint.equals("linear2")) {
Graphics2D g2d = (Graphics2D)rctx.graphics;
g2d.setPaint(makeLinear(2, alphacolor));
} else if (paint.equals("linear3")) {
Graphics2D g2d = (Graphics2D)rctx.graphics;
g2d.setPaint(makeLinear(3, alphacolor));
} else if (paint.equals("radial2")) {
Graphics2D g2d = (Graphics2D)rctx.graphics;
g2d.setPaint(makeRadial(2, alphacolor));
} else if (paint.equals("radial3")) {
Graphics2D g2d = (Graphics2D)rctx.graphics;
g2d.setPaint(makeRadial(3, alphacolor));
} else if (paint.equals("texture20")) {
Graphics2D g2d = (Graphics2D)rctx.graphics;
g2d.setPaint(makeTexturePaint(20, alphacolor));
} else if (paint.equals("texture32")) {
Graphics2D g2d = (Graphics2D)rctx.graphics;
g2d.setPaint(makeTexturePaint(32, alphacolor));
} else {
throw new InternalError("Invalid paint mode");
}
}
private Color[] makeGradientColors(int numColors, boolean alpha) {
Color[] colors = new Color[] {Color.red, Color.blue,
Color.green, Color.yellow};
Color[] ret = new Color[numColors];
for (int i = 0; i < numColors; i++) {
ret[i] = alpha ? makeAlphaColor(colors[i], 32) : colors[i];
}
return ret;
}
private LinearGradientPaint makeLinear(int numColors, boolean alpha) {
float interval = 1.0f / (numColors - 1);
float[] fractions = new float[numColors];
for (int i = 0; i < fractions.length; i++) {
fractions[i] = i * interval;
}
Color[] colors = makeGradientColors(numColors, alpha);
return new LinearGradientPaint(0.0f, 0.0f,
10.0f, 10.0f,
fractions, colors,
CycleMethod.REFLECT);
}
private RadialGradientPaint makeRadial(int numColors, boolean alpha) {
float interval = 1.0f / (numColors - 1);
float[] fractions = new float[numColors];
for (int i = 0; i < fractions.length; i++) {
fractions[i] = i * interval;
}
Color[] colors = makeGradientColors(numColors, alpha);
return new RadialGradientPaint(0.0f, 0.0f, 10.0f,
fractions, colors,
CycleMethod.REFLECT);
}
private TexturePaint makeTexturePaint(int size, boolean alpha) {
int s2 = size / 2;
int type =
alpha ? BufferedImage.TYPE_INT_ARGB : BufferedImage.TYPE_INT_RGB;
BufferedImage img = new BufferedImage(size, size, type);
Color[] colors = makeGradientColors(4, alpha);
Graphics2D g2d = img.createGraphics();
g2d.setComposite(AlphaComposite.Src);
g2d.setColor(colors[0]);
g2d.fillRect(0, 0, s2, s2);
g2d.setColor(colors[1]);
g2d.fillRect(s2, 0, s2, s2);
g2d.setColor(colors[3]);
g2d.fillRect(0, s2, s2, s2);
g2d.setColor(colors[2]);
g2d.fillRect(s2, s2, s2, s2);
g2d.dispose();
Rectangle2D bounds = new Rectangle2D.Float(0, 0, size, size);
return new TexturePaint(img, bounds);
}
public static class DrawDiagonalLines extends RenderTests {
public DrawDiagonalLines() {
super(rendertestroot, "drawLine", "Draw Diagonal Lines");
}
public int pixelsTouched(GraphicsTests.Context ctx) {
return Math.max(ctx.outdim.width, ctx.outdim.height);
}
public void runTest(Object ctx, int numReps) {
RenderTests.Context rctx = (RenderTests.Context) ctx;
int size = rctx.size - 1;
int x = rctx.initX;
int y = rctx.initY;
Graphics g = rctx.graphics;
g.translate(rctx.orgX, rctx.orgY);
Color rCArray[] = rctx.colorlist;
int ci = rctx.colorindex;
if (rctx.animate) {
do {
if (rCArray != null) {
g.setColor(rCArray[ci++ & NUM_RANDOMCOLORMASK]);
}
g.drawLine(x, y, x + size, y + size);
if ((x -= 3) < 0) x += rctx.maxX;
if ((y -= 1) < 0) y += rctx.maxY;
} while (--numReps > 0);
} else {
do {
if (rCArray != null) {
g.setColor(rCArray[ci++ & NUM_RANDOMCOLORMASK]);
}
g.drawLine(x, y, x + size, y + size);
} while (--numReps > 0);
}
rctx.colorindex = ci;
g.translate(-rctx.orgX, -rctx.orgY);
}
}
public static class DrawHorizontalLines extends RenderTests {
public DrawHorizontalLines() {
super(rendertestroot, "drawLineHoriz",
"Draw Horizontal Lines");
}
public int pixelsTouched(GraphicsTests.Context ctx) {
return ctx.outdim.width;
}
public Dimension getOutputSize(int w, int h) {
return new Dimension(w, 1);
}
public void runTest(Object ctx, int numReps) {
RenderTests.Context rctx = (RenderTests.Context) ctx;
int size = rctx.size - 1;
int x = rctx.initX;
int y = rctx.initY;
Graphics g = rctx.graphics;
g.translate(rctx.orgX, rctx.orgY);
Color rCArray[] = rctx.colorlist;
int ci = rctx.colorindex;
if (rctx.animate) {
do {
if (rCArray != null) {
g.setColor(rCArray[ci++ & NUM_RANDOMCOLORMASK]);
}
g.drawLine(x, y, x + size, y);
if ((x -= 3) < 0) x += rctx.maxX;
if ((y -= 1) < 0) y += rctx.maxY;
} while (--numReps > 0);
} else {
do {
if (rCArray != null) {
g.setColor(rCArray[ci++ & NUM_RANDOMCOLORMASK]);
}
g.drawLine(x, y, x + size, y);
} while (--numReps > 0);
}
rctx.colorindex = ci;
g.translate(-rctx.orgX, -rctx.orgY);
}
}
public static class DrawVerticalLines extends RenderTests {
public DrawVerticalLines() {
super(rendertestroot, "drawLineVert",
"Draw Vertical Lines");
}
public int pixelsTouched(GraphicsTests.Context ctx) {
return ctx.outdim.height;
}
public Dimension getOutputSize(int w, int h) {
return new Dimension(1, h);
}
public void runTest(Object ctx, int numReps) {
RenderTests.Context rctx = (RenderTests.Context) ctx;
int size = rctx.size - 1;
int x = rctx.initX;
int y = rctx.initY;
Graphics g = rctx.graphics;
g.translate(rctx.orgX, rctx.orgY);
Color rCArray[] = rctx.colorlist;
int ci = rctx.colorindex;
if (rctx.animate) {
do {
if (rCArray != null) {
g.setColor(rCArray[ci++ & NUM_RANDOMCOLORMASK]);
}
g.drawLine(x, y, x, y + size);
if ((x -= 3) < 0) x += rctx.maxX;
if ((y -= 1) < 0) y += rctx.maxY;
} while (--numReps > 0);
} else {
do {
if (rCArray != null) {
g.setColor(rCArray[ci++ & NUM_RANDOMCOLORMASK]);
}
g.drawLine(x, y, x, y + size);
} while (--numReps > 0);
}
rctx.colorindex = ci;
g.translate(-rctx.orgX, -rctx.orgY);
}
}
public static class FillRects extends RenderTests {
public FillRects() {
super(rendertestroot, "fillRect", "Fill Rectangles");
}
public void runTest(Object ctx, int numReps) {
RenderTests.Context rctx = (RenderTests.Context) ctx;
int size = rctx.size;
int x = rctx.initX;
int y = rctx.initY;
Graphics g = rctx.graphics;
g.translate(rctx.orgX, rctx.orgY);
Color rCArray[] = rctx.colorlist;
int ci = rctx.colorindex;
if (rctx.animate) {
do {
if (rCArray != null) {
g.setColor(rCArray[ci++ & NUM_RANDOMCOLORMASK]);
}
g.fillRect(x, y, size, size);
if ((x -= 3) < 0) x += rctx.maxX;
if ((y -= 1) < 0) y += rctx.maxY;
} while (--numReps > 0);
} else {
do {
if (rCArray != null) {
g.setColor(rCArray[ci++ & NUM_RANDOMCOLORMASK]);
}
g.fillRect(x, y, size, size);
} while (--numReps > 0);
}
rctx.colorindex = ci;
g.translate(-rctx.orgX, -rctx.orgY);
}
}
public static class DrawRects extends RenderTests {
public DrawRects() {
super(rendertestroot, "drawRect", "Draw Rectangles");
}
public int pixelsTouched(GraphicsTests.Context ctx) {
int w = ctx.outdim.width;
int h = ctx.outdim.height;
if (w < 2 || h < 2) {
// If one dimension is less than 2 then there is no
// gap in the middle, so we get a solid filled rectangle.
return w * h;
}
return (w * 2) + ((h - 2) * 2);
}
public void runTest(Object ctx, int numReps) {
RenderTests.Context rctx = (RenderTests.Context) ctx;
int size = rctx.size - 1;
int x = rctx.initX;
int y = rctx.initY;
Graphics g = rctx.graphics;
g.translate(rctx.orgX, rctx.orgY);
Color rCArray[] = rctx.colorlist;
int ci = rctx.colorindex;
if (rctx.animate) {
do {
if (rCArray != null) {
g.setColor(rCArray[ci++ & NUM_RANDOMCOLORMASK]);
}
g.drawRect(x, y, size, size);
if ((x -= 3) < 0) x += rctx.maxX;
if ((y -= 1) < 0) y += rctx.maxY;
} while (--numReps > 0);
} else {
do {
if (rCArray != null) {
g.setColor(rCArray[ci++ & NUM_RANDOMCOLORMASK]);
}
g.drawRect(x, y, size, size);
} while (--numReps > 0);
}
rctx.colorindex = ci;
g.translate(-rctx.orgX, -rctx.orgY);
}
}
public static class FillOvals extends RenderTests {
public FillOvals() {
super(rendertestroot, "fillOval", "Fill Ellipses");
}
public int pixelsTouched(GraphicsTests.Context ctx) {
// Approximated
double xaxis = ctx.outdim.width / 2.0;
double yaxis = ctx.outdim.height / 2.0;
return (int) (xaxis * yaxis * Math.PI);
}
public void runTest(Object ctx, int numReps) {
RenderTests.Context rctx = (RenderTests.Context) ctx;
int size = rctx.size;
int x = rctx.initX;
int y = rctx.initY;
Graphics g = rctx.graphics;
g.translate(rctx.orgX, rctx.orgY);
Color rCArray[] = rctx.colorlist;
int ci = rctx.colorindex;
if (rctx.animate) {
do {
if (rCArray != null) {
g.setColor(rCArray[ci++ & NUM_RANDOMCOLORMASK]);
}
g.fillOval(x, y, size, size);
if ((x -= 3) < 0) x += rctx.maxX;
if ((y -= 1) < 0) y += rctx.maxY;
} while (--numReps > 0);
} else {
do {
if (rCArray != null) {
g.setColor(rCArray[ci++ & NUM_RANDOMCOLORMASK]);
}
g.fillOval(x, y, size, size);
} while (--numReps > 0);
}
rctx.colorindex = ci;
g.translate(-rctx.orgX, -rctx.orgY);
}
}
public static class DrawOvals extends RenderTests {
public DrawOvals() {
super(rendertestroot, "drawOval", "Draw Ellipses");
}
public int pixelsTouched(GraphicsTests.Context ctx) {
/*
* Approximation: We figured that the vertical chord connecting
* the +45 deg and -45 deg points on the ellipse is about
* height/sqrt(2) pixels long. Likewise, the horizontal chord
* connecting the +45 deg and +135 deg points on the ellipse is
* about width/sqrt(2) pixels long. Each of these chords has
* a parallel on the opposite side of the respective axis (there
* are two horizontal chords and two vertical chords). Altogether
* this gives a reasonable approximation of the total number of
* pixels touched by the ellipse, so we have:
* 2*(w/sqrt(2)) + 2*(h/sqrt(2))
* == (2/sqrt(2))*(w+h)
* == (sqrt(2))*(w+h)
*/
return (int)(Math.sqrt(2.0)*(ctx.outdim.width+ctx.outdim.height));
}
public void runTest(Object ctx, int numReps) {
RenderTests.Context rctx = (RenderTests.Context) ctx;
int size = rctx.size - 1;
int x = rctx.initX;
int y = rctx.initY;
Graphics g = rctx.graphics;
g.translate(rctx.orgX, rctx.orgY);
Color rCArray[] = rctx.colorlist;
int ci = rctx.colorindex;
if (rctx.animate) {
do {
if (rCArray != null) {
g.setColor(rCArray[ci++ & NUM_RANDOMCOLORMASK]);
}
g.drawOval(x, y, size, size);
if ((x -= 3) < 0) x += rctx.maxX;
if ((y -= 1) < 0) y += rctx.maxY;
} while (--numReps > 0);
} else {
do {
if (rCArray != null) {
g.setColor(rCArray[ci++ & NUM_RANDOMCOLORMASK]);
}
g.drawOval(x, y, size, size);
} while (--numReps > 0);
}
rctx.colorindex = ci;
g.translate(-rctx.orgX, -rctx.orgY);
}
}
public static class FillPolys extends RenderTests {
public FillPolys() {
super(rendertestroot, "fillPoly", "Fill Hexagonal Polygons");
}
public int pixelsTouched(GraphicsTests.Context ctx) {
/*
* The polygon is a hexagon inscribed inside the square but
* missing a triangle at each of the four corners of size
* (w/4) by (h/2).
*
* Putting 2 of these triangles together gives a rectangle
* of size (w/4) by (h/2).
*
* Putting 2 of these rectangles together gives a total
* missing rectangle size of (w/2) by (h/2).
*
* Thus, exactly one quarter of the whole square is not
* touched by the filled polygon.
*/
int size = ctx.outdim.width * ctx.outdim.height;
return size - (size / 4);
}
public void runTest(Object ctx, int numReps) {
RenderTests.Context rctx = (RenderTests.Context) ctx;
int size = rctx.size;
int x = rctx.initX;
int y = rctx.initY;
int hexaX[] = new int[6];
int hexaY[] = new int[6];
Graphics g = rctx.graphics;
g.translate(rctx.orgX, rctx.orgY);
Color rCArray[] = rctx.colorlist;
int ci = rctx.colorindex;
do {
hexaX[0] = x;
hexaX[1] = hexaX[5] = x+size/4;
hexaX[2] = hexaX[4] = x+size-size/4;
hexaX[3] = x+size;
hexaY[1] = hexaY[2] = y;
hexaY[0] = hexaY[3] = y+size/2;
hexaY[4] = hexaY[5] = y+size;
if (rCArray != null) {
g.setColor(rCArray[ci++ & NUM_RANDOMCOLORMASK]);
}
g.fillPolygon(hexaX, hexaY, 6);
if ((x -= 3) < 0) x += rctx.maxX;
if ((y -= 1) < 0) y += rctx.maxY;
} while (--numReps > 0);
rctx.colorindex = ci;
g.translate(-rctx.orgX, -rctx.orgY);
}
}
public static class DrawPolys extends RenderTests {
public DrawPolys() {
super(rendertestroot, "drawPoly", "Draw Hexagonal Polygons");
}
public int pixelsTouched(GraphicsTests.Context ctx) {
/*
* The two horizontal segments have exactly two pixels per column.
* Since the diagonals are more vertical than horizontal, using
* h*2 would be a good way to count the pixels in those sections.
* We then have to figure out the size of the remainder of the
* horizontal lines at top and bottom to get the answer:
*
* (diagonals less endpoints)*2 + (horizontals)*2
*
* or:
*
* (h-2)*2 + ((x+w-1-w/4)-(x+w/4)+1)*2
*
* since (w == h == size), we then have:
*
* (size - size/4 - 1) * 4
*/
int size = ctx.size;
if (size <= 1) {
return 1;
} else {
return (size - (size / 4) - 1) * 4;
}
}
public void runTest(Object ctx, int numReps) {
RenderTests.Context rctx = (RenderTests.Context) ctx;
// subtract 1 to account for the fact that lines are drawn to
// and including the final coordinate...
int size = rctx.size - 1;
int x = rctx.initX;
int y = rctx.initY;
int hexaX[] = new int[6];
int hexaY[] = new int[6];
Graphics g = rctx.graphics;
g.translate(rctx.orgX, rctx.orgY);
Color rCArray[] = rctx.colorlist;
int ci = rctx.colorindex;
do {
hexaX[0] = x;
hexaX[1] = hexaX[5] = x+size/4;
hexaX[2] = hexaX[4] = x+size-size/4;
hexaX[3] = x+size;
hexaY[1] = hexaY[2] = y;
hexaY[0] = hexaY[3] = y+size/2;
hexaY[4] = hexaY[5] = y+size;
if (rCArray != null) {
g.setColor(rCArray[ci++ & NUM_RANDOMCOLORMASK]);
}
g.drawPolygon(hexaX, hexaY, 6);
if ((x -= 3) < 0) x += rctx.maxX;
if ((y -= 1) < 0) y += rctx.maxY;
} while (--numReps > 0);
rctx.colorindex = ci;
g.translate(-rctx.orgX, -rctx.orgY);
}
}
public static class FillCubics extends RenderTests {
static final double relTmax = .5 - Math.sqrt(3) / 6;
static final double relYmax = ((6*relTmax - 9)*relTmax + 3)*relTmax;
public FillCubics() {
super(rendershaperoot, "fillCubic", "Fill Bezier Curves");
}
public int pixelsTouched(GraphicsTests.Context ctx) {
/*
* The cubic only touches 2 quadrants in the square, thus
* at least half of the square is unfilled. The integrals
* to figure out the exact area are not trivial so for the
* other 2 quadrants, I'm going to guess that the cubic only
* encloses somewhere between 1/2 and 3/4ths of the pixels
* in those quadrants - we will say 5/8ths. Thus only
* 5/16ths of the total square is filled.
*/
// Note: 2x2 ends up hitting exactly 1 pixel...
int size = ctx.size;
if (size < 2) size = 2;
return size * size * 5 / 16;
}
public static class Context extends RenderTests.Context {
CubicCurve2D curve = new CubicCurve2D.Float();
}
public GraphicsTests.Context createContext() {
return new FillCubics.Context();
}
public void runTest(Object ctx, int numReps) {
FillCubics.Context cctx = (FillCubics.Context) ctx;
int size = cctx.size;
// Note: 2x2 ends up hitting exactly 1 pixel...
if (size < 2) size = 2;
int x = cctx.initX;
int y = cctx.initY;
int cpoffset = (int) (size/relYmax/2);
CubicCurve2D curve = cctx.curve;
Graphics2D g2d = (Graphics2D) cctx.graphics;
g2d.translate(cctx.orgX, cctx.orgY);
Color rCArray[] = cctx.colorlist;
int ci = cctx.colorindex;
do {
curve.setCurve(x, y+size/2.0,
x+size/2.0, y+size/2.0-cpoffset,
x+size/2.0, y+size/2.0+cpoffset,
x+size, y+size/2.0);
if (rCArray != null) {
g2d.setColor(rCArray[ci++ & NUM_RANDOMCOLORMASK]);
}
g2d.fill(curve);
if ((x -= 3) < 0) x += cctx.maxX;
if ((y -= 1) < 0) y += cctx.maxY;
} while (--numReps > 0);
cctx.colorindex = ci;
g2d.translate(-cctx.orgX, -cctx.orgY);
}
}
public static class DrawCubics extends RenderTests {
static final double relTmax = .5 - Math.sqrt(3) / 6;
static final double relYmax = ((6*relTmax - 9)*relTmax + 3)*relTmax;
public DrawCubics() {
super(rendershaperoot, "drawCubic", "Draw Bezier Curves");
}
public int pixelsTouched(GraphicsTests.Context ctx) {
// Gross approximation
int size = ctx.size;
if (size < 2) size = 2;
return size;
}
public static class Context extends RenderTests.Context {
CubicCurve2D curve = new CubicCurve2D.Float();
}
public GraphicsTests.Context createContext() {
return new DrawCubics.Context();
}
public void runTest(Object ctx, int numReps) {
DrawCubics.Context cctx = (DrawCubics.Context) ctx;
int size = cctx.size;
// Note: 2x2 ends up hitting exactly 1 pixel...
if (size < 2) size = 2;
int x = cctx.initX;
int y = cctx.initY;
int cpoffset = (int) (size/relYmax/2);
CubicCurve2D curve = cctx.curve;
Graphics2D g2d = (Graphics2D) cctx.graphics;
g2d.translate(cctx.orgX, cctx.orgY);
Color rCArray[] = cctx.colorlist;
int ci = cctx.colorindex;
do {
curve.setCurve(x, y+size/2.0,
x+size/2.0, y+size/2.0-cpoffset,
x+size/2.0, y+size/2.0+cpoffset,
x+size, y+size/2.0);
if (rCArray != null) {
g2d.setColor(rCArray[ci++ & NUM_RANDOMCOLORMASK]);
}
g2d.draw(curve);
if ((x -= 3) < 0) x += cctx.maxX;
if ((y -= 1) < 0) y += cctx.maxY;
} while (--numReps > 0);
cctx.colorindex = ci;
g2d.translate(-cctx.orgX, -cctx.orgY);
}
}
public static class FillEllipse2Ds extends RenderTests {
public FillEllipse2Ds() {
super(rendershaperoot, "fillEllipse2D", "Fill Ellipse2Ds");
}
public int pixelsTouched(GraphicsTests.Context ctx) {
// Approximated (copied from FillOvals.pixelsTouched())
double xaxis = ctx.outdim.width / 2.0;
double yaxis = ctx.outdim.height / 2.0;
return (int) (xaxis * yaxis * Math.PI);
}
public static class Context extends RenderTests.Context {
Ellipse2D ellipse = new Ellipse2D.Float();
}
public GraphicsTests.Context createContext() {
return new FillEllipse2Ds.Context();
}
public void runTest(Object ctx, int numReps) {
FillEllipse2Ds.Context cctx = (FillEllipse2Ds.Context) ctx;
int size = cctx.size;
int x = cctx.initX;
int y = cctx.initY;
Ellipse2D ellipse = cctx.ellipse;
Graphics2D g2d = (Graphics2D) cctx.graphics;
g2d.translate(cctx.orgX, cctx.orgY);
Color rCArray[] = cctx.colorlist;
int ci = cctx.colorindex;
do {
if (rCArray != null) {
g2d.setColor(rCArray[ci++ & NUM_RANDOMCOLORMASK]);
}
ellipse.setFrame(x, y, size, size);
g2d.fill(ellipse);
if ((x -= 3) < 0) x += cctx.maxX;
if ((y -= 1) < 0) y += cctx.maxY;
} while (--numReps > 0);
cctx.colorindex = ci;
g2d.translate(-cctx.orgX, -cctx.orgY);
}
}
public static class DrawEllipse2Ds extends RenderTests {
public DrawEllipse2Ds() {
super(rendershaperoot, "drawEllipse2D", "Draw Ellipse2Ds");
}
public int pixelsTouched(GraphicsTests.Context ctx) {
// Approximated (copied from DrawOvals.pixelsTouched())
return (int)(Math.sqrt(2.0)*(ctx.outdim.width+ctx.outdim.height));
}
public static class Context extends RenderTests.Context {
Ellipse2D ellipse = new Ellipse2D.Float();
}
public GraphicsTests.Context createContext() {
return new DrawEllipse2Ds.Context();
}
public void runTest(Object ctx, int numReps) {
DrawEllipse2Ds.Context cctx = (DrawEllipse2Ds.Context) ctx;
int size = cctx.size;
int x = cctx.initX;
int y = cctx.initY;
Ellipse2D ellipse = cctx.ellipse;
Graphics2D g2d = (Graphics2D) cctx.graphics;
g2d.translate(cctx.orgX, cctx.orgY);
Color rCArray[] = cctx.colorlist;
int ci = cctx.colorindex;
do {
if (rCArray != null) {
g2d.setColor(rCArray[ci++ & NUM_RANDOMCOLORMASK]);
}
ellipse.setFrame(x, y, size, size);
g2d.draw(ellipse);
if ((x -= 3) < 0) x += cctx.maxX;
if ((y -= 1) < 0) y += cctx.maxY;
} while (--numReps > 0);
cctx.colorindex = ci;
g2d.translate(-cctx.orgX, -cctx.orgY);
}
}
}