1/* 2 * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * - Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 11 * - Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * - Neither the name of Oracle nor the names of its 16 * contributors may be used to endorse or promote products derived 17 * from this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 20 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 26 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 27 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 28 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 29 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32/* 33 * This source code is provided to illustrate the usage of a given feature 34 * or technique and has been deliberately simplified. Additional steps 35 * required for a production-quality application, such as security checks, 36 * input validation and proper error handling, might not be present in 37 * this sample code. 38 */ 39 40 41package j2dbench.tests; 42 43import java.awt.Graphics; 44import java.awt.Graphics2D; 45import java.awt.Color; 46import java.awt.Dimension; 47import java.awt.AlphaComposite; 48import java.awt.Stroke; 49import java.awt.BasicStroke; 50import java.awt.GradientPaint; 51import java.awt.LinearGradientPaint; 52import java.awt.MultipleGradientPaint; 53import java.awt.MultipleGradientPaint.CycleMethod; 54import java.awt.MultipleGradientPaint.ColorSpaceType; 55import java.awt.RadialGradientPaint; 56import java.awt.RenderingHints; 57import java.awt.TexturePaint; 58import java.awt.geom.CubicCurve2D; 59import java.awt.geom.Ellipse2D; 60import java.awt.geom.Point2D; 61import java.awt.geom.Rectangle2D; 62import java.awt.image.BufferedImage; 63import java.io.PrintWriter; 64import java.util.ArrayList; 65import javax.swing.JComponent; 66 67import j2dbench.Group; 68import j2dbench.Node; 69import j2dbench.Option; 70import j2dbench.TestEnvironment; 71 72public abstract class RenderTests extends GraphicsTests { 73 static Group renderroot; 74 static Group renderoptroot; 75 static Group rendertestroot; 76 static Group rendershaperoot; 77 78 static Option paintList; 79 static Option doAntialias; 80 static Option doAlphaColors; 81 static Option sizeList; 82 static Option strokeList; 83 84 static final int NUM_RANDOMCOLORS = 4096; 85 static final int NUM_RANDOMCOLORMASK = (NUM_RANDOMCOLORS - 1); 86 static Color randAlphaColors[]; 87 static Color randOpaqueColors[]; 88 89 static { 90 randOpaqueColors = new Color[NUM_RANDOMCOLORS]; 91 randAlphaColors = new Color[NUM_RANDOMCOLORS]; 92 for (int i = 0; i < NUM_RANDOMCOLORS; i++) { 93 int r = (int) (Math.random() * 255); 94 int g = (int) (Math.random() * 255); 95 int b = (int) (Math.random() * 255); 96 randOpaqueColors[i] = new Color(r, g, b); 97 randAlphaColors[i] = makeAlphaColor(randOpaqueColors[i], 32); 98 } 99 } 100 101 static boolean hasMultiGradient; 102 103 static { 104 try { 105 hasMultiGradient = (MultipleGradientPaint.class != null); 106 } catch (NoClassDefFoundError e) { 107 } 108 } 109 110 public static void init() { 111 renderroot = new Group(graphicsroot, "render", "Rendering Benchmarks"); 112 renderoptroot = new Group(renderroot, "opts", "Rendering Options"); 113 rendertestroot = new Group(renderroot, "tests", "Rendering Tests"); 114 115 ArrayList paintStrs = new ArrayList(); 116 ArrayList paintDescs = new ArrayList(); 117 paintStrs.add("single"); 118 paintDescs.add("Single Color"); 119 paintStrs.add("random"); 120 paintDescs.add("Random Color"); 121 if (hasGraphics2D) { 122 paintStrs.add("gradient2"); 123 paintDescs.add("2-color GradientPaint"); 124 if (hasMultiGradient) { 125 paintStrs.add("linear2"); 126 paintDescs.add("2-color LinearGradientPaint"); 127 paintStrs.add("linear3"); 128 paintDescs.add("3-color LinearGradientPaint"); 129 paintStrs.add("radial2"); 130 paintDescs.add("2-color RadialGradientPaint"); 131 paintStrs.add("radial3"); 132 paintDescs.add("3-color RadialGradientPaint"); 133 } 134 paintStrs.add("texture20"); 135 paintDescs.add("20x20 TexturePaint"); 136 paintStrs.add("texture32"); 137 paintDescs.add("32x32 TexturePaint"); 138 } 139 String[] paintStrArr = new String[paintStrs.size()]; 140 paintStrArr = (String[])paintStrs.toArray(paintStrArr); 141 String[] paintDescArr = new String[paintDescs.size()]; 142 paintDescArr = (String[])paintDescs.toArray(paintDescArr); 143 paintList = 144 new Option.ObjectList(renderoptroot, 145 "paint", "Paint Type", 146 paintStrArr, paintStrArr, 147 paintStrArr, paintDescArr, 148 0x1); 149 ((Option.ObjectList) paintList).setNumRows(5); 150 151 // add special RandomColorOpt for backwards compatibility with 152 // older options files 153 new RandomColorOpt(); 154 155 if (hasGraphics2D) { 156 doAlphaColors = 157 new Option.Toggle(renderoptroot, "alphacolor", 158 "Set the alpha of the paint to 0.125", 159 Option.Toggle.Off); 160 doAntialias = 161 new Option.Toggle(renderoptroot, "antialias", 162 "Render shapes antialiased", 163 Option.Toggle.Off); 164 String strokeStrings[] = { 165 "width0", 166 "width1", 167 "width5", 168 "width20", 169 "dash0_5", 170 "dash1_5", 171 "dash5_20", 172 "dash20_50", 173 }; 174 String strokeDescriptions[] = { 175 "Solid Thin lines", 176 "Solid Width 1 lines", 177 "Solid Width 5 lines", 178 "Solid Width 20 lines", 179 "Dashed Thin lines", 180 "Dashed Width 1 lines", 181 "Dashed Width 5 lines", 182 "Dashed Width 20 lines", 183 }; 184 BasicStroke strokeObjects[] = { 185 new BasicStroke(0f), 186 new BasicStroke(1f), 187 new BasicStroke(5f), 188 new BasicStroke(20f), 189 new BasicStroke(0f, BasicStroke.CAP_SQUARE, 190 BasicStroke.JOIN_MITER, 10f, 191 new float[] { 5f, 5f }, 0f), 192 new BasicStroke(1f, BasicStroke.CAP_SQUARE, 193 BasicStroke.JOIN_MITER, 10f, 194 new float[] { 5f, 5f }, 0f), 195 new BasicStroke(5f, BasicStroke.CAP_SQUARE, 196 BasicStroke.JOIN_MITER, 10f, 197 new float[] { 20f, 20f }, 0f), 198 new BasicStroke(20f, BasicStroke.CAP_SQUARE, 199 BasicStroke.JOIN_MITER, 10f, 200 new float[] { 50f, 50f }, 0f), 201 }; 202 strokeList = 203 new Option.ObjectList(renderoptroot, 204 "stroke", "Stroke Type", 205 strokeStrings, strokeObjects, 206 strokeStrings, strokeDescriptions, 207 0x2); 208 ((Option.ObjectList) strokeList).setNumRows(4); 209 } 210 211 new DrawDiagonalLines(); 212 new DrawHorizontalLines(); 213 new DrawVerticalLines(); 214 new FillRects(); 215 new DrawRects(); 216 new FillOvals(); 217 new DrawOvals(); 218 new FillPolys(); 219 new DrawPolys(); 220 221 if (hasGraphics2D) { 222 rendershaperoot = new Group(rendertestroot, "shape", 223 "Shape Rendering Tests"); 224 225 new FillCubics(); 226 new DrawCubics(); 227 new FillEllipse2Ds(); 228 new DrawEllipse2Ds(); 229 } 230 } 231 232 /** 233 * This "virtual Node" implementation is here to maintain backward 234 * compatibility with older J2DBench releases, specifically those 235 * options files that were created before we added the gradient/texture 236 * paint options in JDK 6. This class will translate the color settings 237 * from the old "randomcolor" option into the new "paint" option. 238 */ 239 private static class RandomColorOpt extends Node { 240 public RandomColorOpt() { 241 super(renderoptroot, "randomcolor", 242 "Use random colors for each shape"); 243 } 244 245 public JComponent getJComponent() { 246 return null; 247 } 248 249 public void restoreDefault() { 250 // no-op 251 } 252 253 public void write(PrintWriter pw) { 254 // no-op (the random/single choice will be saved as part of 255 // the new "paint" option added to J2DBench in JDK 6) 256 } 257 258 public String setOption(String key, String value) { 259 String opts; 260 if (value.equals("On")) { 261 opts = "random"; 262 } else if (value.equals("Off")) { 263 opts = "single"; 264 } else if (value.equals("Both")) { 265 opts = "random,single"; 266 } else { 267 return "Bad value"; 268 } 269 return ((Option.ObjectList)paintList).setValueFromString(opts); 270 } 271 } 272 273 public static class Context extends GraphicsTests.Context { 274 int colorindex; 275 Color colorlist[]; 276 } 277 278 public RenderTests(Group parent, String nodeName, String description) { 279 super(parent, nodeName, description); 280 addDependencies(renderoptroot, true); 281 } 282 283 public GraphicsTests.Context createContext() { 284 return new RenderTests.Context(); 285 } 286 287 public void initContext(TestEnvironment env, GraphicsTests.Context ctx) { 288 super.initContext(env, ctx); 289 RenderTests.Context rctx = (RenderTests.Context) ctx; 290 boolean alphacolor; 291 292 if (hasGraphics2D) { 293 Graphics2D g2d = (Graphics2D) rctx.graphics; 294 if (env.isEnabled(doAntialias)) { 295 g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 296 RenderingHints.VALUE_ANTIALIAS_ON); 297 } 298 alphacolor = env.isEnabled(doAlphaColors); 299 g2d.setStroke((Stroke) env.getModifier(strokeList)); 300 } else { 301 alphacolor = false; 302 } 303 304 String paint = (String)env.getModifier(paintList); 305 if (paint.equals("single")) { 306 Color c = Color.darkGray; 307 if (alphacolor) { 308 c = makeAlphaColor(c, 32); 309 } 310 rctx.graphics.setColor(c); 311 } else if (paint.equals("random")) { 312 rctx.colorlist = alphacolor ? randAlphaColors : randOpaqueColors; 313 } else if (paint.equals("gradient2")) { 314 Color[] colors = makeGradientColors(2, alphacolor); 315 Graphics2D g2d = (Graphics2D)rctx.graphics; 316 g2d.setPaint(new GradientPaint(0.0f, 0.0f, colors[0], 317 10.0f, 10.0f, colors[1], true)); 318 } else if (paint.equals("linear2")) { 319 Graphics2D g2d = (Graphics2D)rctx.graphics; 320 g2d.setPaint(makeLinear(2, alphacolor)); 321 } else if (paint.equals("linear3")) { 322 Graphics2D g2d = (Graphics2D)rctx.graphics; 323 g2d.setPaint(makeLinear(3, alphacolor)); 324 } else if (paint.equals("radial2")) { 325 Graphics2D g2d = (Graphics2D)rctx.graphics; 326 g2d.setPaint(makeRadial(2, alphacolor)); 327 } else if (paint.equals("radial3")) { 328 Graphics2D g2d = (Graphics2D)rctx.graphics; 329 g2d.setPaint(makeRadial(3, alphacolor)); 330 } else if (paint.equals("texture20")) { 331 Graphics2D g2d = (Graphics2D)rctx.graphics; 332 g2d.setPaint(makeTexturePaint(20, alphacolor)); 333 } else if (paint.equals("texture32")) { 334 Graphics2D g2d = (Graphics2D)rctx.graphics; 335 g2d.setPaint(makeTexturePaint(32, alphacolor)); 336 } else { 337 throw new InternalError("Invalid paint mode"); 338 } 339 } 340 341 private Color[] makeGradientColors(int numColors, boolean alpha) { 342 Color[] colors = new Color[] {Color.red, Color.blue, 343 Color.green, Color.yellow}; 344 Color[] ret = new Color[numColors]; 345 for (int i = 0; i < numColors; i++) { 346 ret[i] = alpha ? makeAlphaColor(colors[i], 32) : colors[i]; 347 } 348 return ret; 349 } 350 351 private LinearGradientPaint makeLinear(int numColors, boolean alpha) { 352 float interval = 1.0f / (numColors - 1); 353 float[] fractions = new float[numColors]; 354 for (int i = 0; i < fractions.length; i++) { 355 fractions[i] = i * interval; 356 } 357 Color[] colors = makeGradientColors(numColors, alpha); 358 return new LinearGradientPaint(0.0f, 0.0f, 359 10.0f, 10.0f, 360 fractions, colors, 361 CycleMethod.REFLECT); 362 } 363 364 private RadialGradientPaint makeRadial(int numColors, boolean alpha) { 365 float interval = 1.0f / (numColors - 1); 366 float[] fractions = new float[numColors]; 367 for (int i = 0; i < fractions.length; i++) { 368 fractions[i] = i * interval; 369 } 370 Color[] colors = makeGradientColors(numColors, alpha); 371 return new RadialGradientPaint(0.0f, 0.0f, 10.0f, 372 fractions, colors, 373 CycleMethod.REFLECT); 374 } 375 376 private TexturePaint makeTexturePaint(int size, boolean alpha) { 377 int s2 = size / 2; 378 int type = 379 alpha ? BufferedImage.TYPE_INT_ARGB : BufferedImage.TYPE_INT_RGB; 380 BufferedImage img = new BufferedImage(size, size, type); 381 Color[] colors = makeGradientColors(4, alpha); 382 Graphics2D g2d = img.createGraphics(); 383 g2d.setComposite(AlphaComposite.Src); 384 g2d.setColor(colors[0]); 385 g2d.fillRect(0, 0, s2, s2); 386 g2d.setColor(colors[1]); 387 g2d.fillRect(s2, 0, s2, s2); 388 g2d.setColor(colors[3]); 389 g2d.fillRect(0, s2, s2, s2); 390 g2d.setColor(colors[2]); 391 g2d.fillRect(s2, s2, s2, s2); 392 g2d.dispose(); 393 Rectangle2D bounds = new Rectangle2D.Float(0, 0, size, size); 394 return new TexturePaint(img, bounds); 395 } 396 397 public static class DrawDiagonalLines extends RenderTests { 398 public DrawDiagonalLines() { 399 super(rendertestroot, "drawLine", "Draw Diagonal Lines"); 400 } 401 402 public int pixelsTouched(GraphicsTests.Context ctx) { 403 return Math.max(ctx.outdim.width, ctx.outdim.height); 404 } 405 406 public void runTest(Object ctx, int numReps) { 407 RenderTests.Context rctx = (RenderTests.Context) ctx; 408 int size = rctx.size - 1; 409 int x = rctx.initX; 410 int y = rctx.initY; 411 Graphics g = rctx.graphics; 412 g.translate(rctx.orgX, rctx.orgY); 413 Color rCArray[] = rctx.colorlist; 414 int ci = rctx.colorindex; 415 if (rctx.animate) { 416 do { 417 if (rCArray != null) { 418 g.setColor(rCArray[ci++ & NUM_RANDOMCOLORMASK]); 419 } 420 g.drawLine(x, y, x + size, y + size); 421 if ((x -= 3) < 0) x += rctx.maxX; 422 if ((y -= 1) < 0) y += rctx.maxY; 423 } while (--numReps > 0); 424 } else { 425 do { 426 if (rCArray != null) { 427 g.setColor(rCArray[ci++ & NUM_RANDOMCOLORMASK]); 428 } 429 g.drawLine(x, y, x + size, y + size); 430 } while (--numReps > 0); 431 } 432 rctx.colorindex = ci; 433 g.translate(-rctx.orgX, -rctx.orgY); 434 } 435 } 436 437 public static class DrawHorizontalLines extends RenderTests { 438 public DrawHorizontalLines() { 439 super(rendertestroot, "drawLineHoriz", 440 "Draw Horizontal Lines"); 441 } 442 443 public int pixelsTouched(GraphicsTests.Context ctx) { 444 return ctx.outdim.width; 445 } 446 447 public Dimension getOutputSize(int w, int h) { 448 return new Dimension(w, 1); 449 } 450 451 public void runTest(Object ctx, int numReps) { 452 RenderTests.Context rctx = (RenderTests.Context) ctx; 453 int size = rctx.size - 1; 454 int x = rctx.initX; 455 int y = rctx.initY; 456 Graphics g = rctx.graphics; 457 g.translate(rctx.orgX, rctx.orgY); 458 Color rCArray[] = rctx.colorlist; 459 int ci = rctx.colorindex; 460 if (rctx.animate) { 461 do { 462 if (rCArray != null) { 463 g.setColor(rCArray[ci++ & NUM_RANDOMCOLORMASK]); 464 } 465 g.drawLine(x, y, x + size, y); 466 if ((x -= 3) < 0) x += rctx.maxX; 467 if ((y -= 1) < 0) y += rctx.maxY; 468 } while (--numReps > 0); 469 } else { 470 do { 471 if (rCArray != null) { 472 g.setColor(rCArray[ci++ & NUM_RANDOMCOLORMASK]); 473 } 474 g.drawLine(x, y, x + size, y); 475 } while (--numReps > 0); 476 } 477 rctx.colorindex = ci; 478 g.translate(-rctx.orgX, -rctx.orgY); 479 } 480 } 481 482 public static class DrawVerticalLines extends RenderTests { 483 public DrawVerticalLines() { 484 super(rendertestroot, "drawLineVert", 485 "Draw Vertical Lines"); 486 } 487 488 public int pixelsTouched(GraphicsTests.Context ctx) { 489 return ctx.outdim.height; 490 } 491 492 public Dimension getOutputSize(int w, int h) { 493 return new Dimension(1, h); 494 } 495 496 public void runTest(Object ctx, int numReps) { 497 RenderTests.Context rctx = (RenderTests.Context) ctx; 498 int size = rctx.size - 1; 499 int x = rctx.initX; 500 int y = rctx.initY; 501 Graphics g = rctx.graphics; 502 g.translate(rctx.orgX, rctx.orgY); 503 Color rCArray[] = rctx.colorlist; 504 int ci = rctx.colorindex; 505 if (rctx.animate) { 506 do { 507 if (rCArray != null) { 508 g.setColor(rCArray[ci++ & NUM_RANDOMCOLORMASK]); 509 } 510 g.drawLine(x, y, x, y + size); 511 if ((x -= 3) < 0) x += rctx.maxX; 512 if ((y -= 1) < 0) y += rctx.maxY; 513 } while (--numReps > 0); 514 } else { 515 do { 516 if (rCArray != null) { 517 g.setColor(rCArray[ci++ & NUM_RANDOMCOLORMASK]); 518 } 519 g.drawLine(x, y, x, y + size); 520 } while (--numReps > 0); 521 } 522 rctx.colorindex = ci; 523 g.translate(-rctx.orgX, -rctx.orgY); 524 } 525 } 526 527 public static class FillRects extends RenderTests { 528 public FillRects() { 529 super(rendertestroot, "fillRect", "Fill Rectangles"); 530 } 531 532 public void runTest(Object ctx, int numReps) { 533 RenderTests.Context rctx = (RenderTests.Context) ctx; 534 int size = rctx.size; 535 int x = rctx.initX; 536 int y = rctx.initY; 537 Graphics g = rctx.graphics; 538 g.translate(rctx.orgX, rctx.orgY); 539 Color rCArray[] = rctx.colorlist; 540 int ci = rctx.colorindex; 541 if (rctx.animate) { 542 do { 543 if (rCArray != null) { 544 g.setColor(rCArray[ci++ & NUM_RANDOMCOLORMASK]); 545 } 546 g.fillRect(x, y, size, size); 547 if ((x -= 3) < 0) x += rctx.maxX; 548 if ((y -= 1) < 0) y += rctx.maxY; 549 } while (--numReps > 0); 550 } else { 551 do { 552 if (rCArray != null) { 553 g.setColor(rCArray[ci++ & NUM_RANDOMCOLORMASK]); 554 } 555 g.fillRect(x, y, size, size); 556 } while (--numReps > 0); 557 } 558 rctx.colorindex = ci; 559 g.translate(-rctx.orgX, -rctx.orgY); 560 } 561 } 562 563 public static class DrawRects extends RenderTests { 564 public DrawRects() { 565 super(rendertestroot, "drawRect", "Draw Rectangles"); 566 } 567 568 public int pixelsTouched(GraphicsTests.Context ctx) { 569 int w = ctx.outdim.width; 570 int h = ctx.outdim.height; 571 if (w < 2 || h < 2) { 572 // If one dimension is less than 2 then there is no 573 // gap in the middle, so we get a solid filled rectangle. 574 return w * h; 575 } 576 return (w * 2) + ((h - 2) * 2); 577 } 578 579 public void runTest(Object ctx, int numReps) { 580 RenderTests.Context rctx = (RenderTests.Context) ctx; 581 int size = rctx.size - 1; 582 int x = rctx.initX; 583 int y = rctx.initY; 584 Graphics g = rctx.graphics; 585 g.translate(rctx.orgX, rctx.orgY); 586 Color rCArray[] = rctx.colorlist; 587 int ci = rctx.colorindex; 588 if (rctx.animate) { 589 do { 590 if (rCArray != null) { 591 g.setColor(rCArray[ci++ & NUM_RANDOMCOLORMASK]); 592 } 593 g.drawRect(x, y, size, size); 594 if ((x -= 3) < 0) x += rctx.maxX; 595 if ((y -= 1) < 0) y += rctx.maxY; 596 } while (--numReps > 0); 597 } else { 598 do { 599 if (rCArray != null) { 600 g.setColor(rCArray[ci++ & NUM_RANDOMCOLORMASK]); 601 } 602 g.drawRect(x, y, size, size); 603 } while (--numReps > 0); 604 } 605 rctx.colorindex = ci; 606 g.translate(-rctx.orgX, -rctx.orgY); 607 } 608 } 609 610 public static class FillOvals extends RenderTests { 611 public FillOvals() { 612 super(rendertestroot, "fillOval", "Fill Ellipses"); 613 } 614 615 public int pixelsTouched(GraphicsTests.Context ctx) { 616 // Approximated 617 double xaxis = ctx.outdim.width / 2.0; 618 double yaxis = ctx.outdim.height / 2.0; 619 return (int) (xaxis * yaxis * Math.PI); 620 } 621 622 public void runTest(Object ctx, int numReps) { 623 RenderTests.Context rctx = (RenderTests.Context) ctx; 624 int size = rctx.size; 625 int x = rctx.initX; 626 int y = rctx.initY; 627 Graphics g = rctx.graphics; 628 g.translate(rctx.orgX, rctx.orgY); 629 Color rCArray[] = rctx.colorlist; 630 int ci = rctx.colorindex; 631 if (rctx.animate) { 632 do { 633 if (rCArray != null) { 634 g.setColor(rCArray[ci++ & NUM_RANDOMCOLORMASK]); 635 } 636 g.fillOval(x, y, size, size); 637 if ((x -= 3) < 0) x += rctx.maxX; 638 if ((y -= 1) < 0) y += rctx.maxY; 639 } while (--numReps > 0); 640 } else { 641 do { 642 if (rCArray != null) { 643 g.setColor(rCArray[ci++ & NUM_RANDOMCOLORMASK]); 644 } 645 g.fillOval(x, y, size, size); 646 } while (--numReps > 0); 647 } 648 rctx.colorindex = ci; 649 g.translate(-rctx.orgX, -rctx.orgY); 650 } 651 } 652 653 public static class DrawOvals extends RenderTests { 654 public DrawOvals() { 655 super(rendertestroot, "drawOval", "Draw Ellipses"); 656 } 657 658 public int pixelsTouched(GraphicsTests.Context ctx) { 659 /* 660 * Approximation: We figured that the vertical chord connecting 661 * the +45 deg and -45 deg points on the ellipse is about 662 * height/sqrt(2) pixels long. Likewise, the horizontal chord 663 * connecting the +45 deg and +135 deg points on the ellipse is 664 * about width/sqrt(2) pixels long. Each of these chords has 665 * a parallel on the opposite side of the respective axis (there 666 * are two horizontal chords and two vertical chords). Altogether 667 * this gives a reasonable approximation of the total number of 668 * pixels touched by the ellipse, so we have: 669 * 2*(w/sqrt(2)) + 2*(h/sqrt(2)) 670 * == (2/sqrt(2))*(w+h) 671 * == (sqrt(2))*(w+h) 672 */ 673 return (int)(Math.sqrt(2.0)*(ctx.outdim.width+ctx.outdim.height)); 674 } 675 676 public void runTest(Object ctx, int numReps) { 677 RenderTests.Context rctx = (RenderTests.Context) ctx; 678 int size = rctx.size - 1; 679 int x = rctx.initX; 680 int y = rctx.initY; 681 Graphics g = rctx.graphics; 682 g.translate(rctx.orgX, rctx.orgY); 683 Color rCArray[] = rctx.colorlist; 684 int ci = rctx.colorindex; 685 if (rctx.animate) { 686 do { 687 if (rCArray != null) { 688 g.setColor(rCArray[ci++ & NUM_RANDOMCOLORMASK]); 689 } 690 g.drawOval(x, y, size, size); 691 if ((x -= 3) < 0) x += rctx.maxX; 692 if ((y -= 1) < 0) y += rctx.maxY; 693 } while (--numReps > 0); 694 } else { 695 do { 696 if (rCArray != null) { 697 g.setColor(rCArray[ci++ & NUM_RANDOMCOLORMASK]); 698 } 699 g.drawOval(x, y, size, size); 700 } while (--numReps > 0); 701 } 702 rctx.colorindex = ci; 703 g.translate(-rctx.orgX, -rctx.orgY); 704 } 705 } 706 707 public static class FillPolys extends RenderTests { 708 public FillPolys() { 709 super(rendertestroot, "fillPoly", "Fill Hexagonal Polygons"); 710 } 711 712 public int pixelsTouched(GraphicsTests.Context ctx) { 713 /* 714 * The polygon is a hexagon inscribed inside the square but 715 * missing a triangle at each of the four corners of size 716 * (w/4) by (h/2). 717 * 718 * Putting 2 of these triangles together gives a rectangle 719 * of size (w/4) by (h/2). 720 * 721 * Putting 2 of these rectangles together gives a total 722 * missing rectangle size of (w/2) by (h/2). 723 * 724 * Thus, exactly one quarter of the whole square is not 725 * touched by the filled polygon. 726 */ 727 int size = ctx.outdim.width * ctx.outdim.height; 728 return size - (size / 4); 729 } 730 731 public void runTest(Object ctx, int numReps) { 732 RenderTests.Context rctx = (RenderTests.Context) ctx; 733 int size = rctx.size; 734 int x = rctx.initX; 735 int y = rctx.initY; 736 int hexaX[] = new int[6]; 737 int hexaY[] = new int[6]; 738 Graphics g = rctx.graphics; 739 g.translate(rctx.orgX, rctx.orgY); 740 Color rCArray[] = rctx.colorlist; 741 int ci = rctx.colorindex; 742 do { 743 hexaX[0] = x; 744 hexaX[1] = hexaX[5] = x+size/4; 745 hexaX[2] = hexaX[4] = x+size-size/4; 746 hexaX[3] = x+size; 747 hexaY[1] = hexaY[2] = y; 748 hexaY[0] = hexaY[3] = y+size/2; 749 hexaY[4] = hexaY[5] = y+size; 750 751 if (rCArray != null) { 752 g.setColor(rCArray[ci++ & NUM_RANDOMCOLORMASK]); 753 } 754 g.fillPolygon(hexaX, hexaY, 6); 755 if ((x -= 3) < 0) x += rctx.maxX; 756 if ((y -= 1) < 0) y += rctx.maxY; 757 } while (--numReps > 0); 758 rctx.colorindex = ci; 759 g.translate(-rctx.orgX, -rctx.orgY); 760 } 761 } 762 763 public static class DrawPolys extends RenderTests { 764 public DrawPolys() { 765 super(rendertestroot, "drawPoly", "Draw Hexagonal Polygons"); 766 } 767 768 public int pixelsTouched(GraphicsTests.Context ctx) { 769 /* 770 * The two horizontal segments have exactly two pixels per column. 771 * Since the diagonals are more vertical than horizontal, using 772 * h*2 would be a good way to count the pixels in those sections. 773 * We then have to figure out the size of the remainder of the 774 * horizontal lines at top and bottom to get the answer: 775 * 776 * (diagonals less endpoints)*2 + (horizontals)*2 777 * 778 * or: 779 * 780 * (h-2)*2 + ((x+w-1-w/4)-(x+w/4)+1)*2 781 * 782 * since (w == h == size), we then have: 783 * 784 * (size - size/4 - 1) * 4 785 */ 786 int size = ctx.size; 787 if (size <= 1) { 788 return 1; 789 } else { 790 return (size - (size / 4) - 1) * 4; 791 } 792 } 793 794 public void runTest(Object ctx, int numReps) { 795 RenderTests.Context rctx = (RenderTests.Context) ctx; 796 // subtract 1 to account for the fact that lines are drawn to 797 // and including the final coordinate... 798 int size = rctx.size - 1; 799 int x = rctx.initX; 800 int y = rctx.initY; 801 int hexaX[] = new int[6]; 802 int hexaY[] = new int[6]; 803 Graphics g = rctx.graphics; 804 g.translate(rctx.orgX, rctx.orgY); 805 Color rCArray[] = rctx.colorlist; 806 int ci = rctx.colorindex; 807 do { 808 hexaX[0] = x; 809 hexaX[1] = hexaX[5] = x+size/4; 810 hexaX[2] = hexaX[4] = x+size-size/4; 811 hexaX[3] = x+size; 812 hexaY[1] = hexaY[2] = y; 813 hexaY[0] = hexaY[3] = y+size/2; 814 hexaY[4] = hexaY[5] = y+size; 815 816 if (rCArray != null) { 817 g.setColor(rCArray[ci++ & NUM_RANDOMCOLORMASK]); 818 } 819 g.drawPolygon(hexaX, hexaY, 6); 820 if ((x -= 3) < 0) x += rctx.maxX; 821 if ((y -= 1) < 0) y += rctx.maxY; 822 } while (--numReps > 0); 823 rctx.colorindex = ci; 824 g.translate(-rctx.orgX, -rctx.orgY); 825 } 826 } 827 828 public static class FillCubics extends RenderTests { 829 static final double relTmax = .5 - Math.sqrt(3) / 6; 830 static final double relYmax = ((6*relTmax - 9)*relTmax + 3)*relTmax; 831 832 public FillCubics() { 833 super(rendershaperoot, "fillCubic", "Fill Bezier Curves"); 834 } 835 836 public int pixelsTouched(GraphicsTests.Context ctx) { 837 /* 838 * The cubic only touches 2 quadrants in the square, thus 839 * at least half of the square is unfilled. The integrals 840 * to figure out the exact area are not trivial so for the 841 * other 2 quadrants, I'm going to guess that the cubic only 842 * encloses somewhere between 1/2 and 3/4ths of the pixels 843 * in those quadrants - we will say 5/8ths. Thus only 844 * 5/16ths of the total square is filled. 845 */ 846 // Note: 2x2 ends up hitting exactly 1 pixel... 847 int size = ctx.size; 848 if (size < 2) size = 2; 849 return size * size * 5 / 16; 850 } 851 852 public static class Context extends RenderTests.Context { 853 CubicCurve2D curve = new CubicCurve2D.Float(); 854 } 855 856 public GraphicsTests.Context createContext() { 857 return new FillCubics.Context(); 858 } 859 860 public void runTest(Object ctx, int numReps) { 861 FillCubics.Context cctx = (FillCubics.Context) ctx; 862 int size = cctx.size; 863 // Note: 2x2 ends up hitting exactly 1 pixel... 864 if (size < 2) size = 2; 865 int x = cctx.initX; 866 int y = cctx.initY; 867 int cpoffset = (int) (size/relYmax/2); 868 CubicCurve2D curve = cctx.curve; 869 Graphics2D g2d = (Graphics2D) cctx.graphics; 870 g2d.translate(cctx.orgX, cctx.orgY); 871 Color rCArray[] = cctx.colorlist; 872 int ci = cctx.colorindex; 873 do { 874 curve.setCurve(x, y+size/2.0, 875 x+size/2.0, y+size/2.0-cpoffset, 876 x+size/2.0, y+size/2.0+cpoffset, 877 x+size, y+size/2.0); 878 879 if (rCArray != null) { 880 g2d.setColor(rCArray[ci++ & NUM_RANDOMCOLORMASK]); 881 } 882 g2d.fill(curve); 883 if ((x -= 3) < 0) x += cctx.maxX; 884 if ((y -= 1) < 0) y += cctx.maxY; 885 } while (--numReps > 0); 886 cctx.colorindex = ci; 887 g2d.translate(-cctx.orgX, -cctx.orgY); 888 } 889 } 890 891 public static class DrawCubics extends RenderTests { 892 static final double relTmax = .5 - Math.sqrt(3) / 6; 893 static final double relYmax = ((6*relTmax - 9)*relTmax + 3)*relTmax; 894 895 public DrawCubics() { 896 super(rendershaperoot, "drawCubic", "Draw Bezier Curves"); 897 } 898 899 public int pixelsTouched(GraphicsTests.Context ctx) { 900 // Gross approximation 901 int size = ctx.size; 902 if (size < 2) size = 2; 903 return size; 904 } 905 906 public static class Context extends RenderTests.Context { 907 CubicCurve2D curve = new CubicCurve2D.Float(); 908 } 909 910 public GraphicsTests.Context createContext() { 911 return new DrawCubics.Context(); 912 } 913 914 public void runTest(Object ctx, int numReps) { 915 DrawCubics.Context cctx = (DrawCubics.Context) ctx; 916 int size = cctx.size; 917 // Note: 2x2 ends up hitting exactly 1 pixel... 918 if (size < 2) size = 2; 919 int x = cctx.initX; 920 int y = cctx.initY; 921 int cpoffset = (int) (size/relYmax/2); 922 CubicCurve2D curve = cctx.curve; 923 Graphics2D g2d = (Graphics2D) cctx.graphics; 924 g2d.translate(cctx.orgX, cctx.orgY); 925 Color rCArray[] = cctx.colorlist; 926 int ci = cctx.colorindex; 927 do { 928 curve.setCurve(x, y+size/2.0, 929 x+size/2.0, y+size/2.0-cpoffset, 930 x+size/2.0, y+size/2.0+cpoffset, 931 x+size, y+size/2.0); 932 933 if (rCArray != null) { 934 g2d.setColor(rCArray[ci++ & NUM_RANDOMCOLORMASK]); 935 } 936 g2d.draw(curve); 937 if ((x -= 3) < 0) x += cctx.maxX; 938 if ((y -= 1) < 0) y += cctx.maxY; 939 } while (--numReps > 0); 940 cctx.colorindex = ci; 941 g2d.translate(-cctx.orgX, -cctx.orgY); 942 } 943 } 944 945 public static class FillEllipse2Ds extends RenderTests { 946 public FillEllipse2Ds() { 947 super(rendershaperoot, "fillEllipse2D", "Fill Ellipse2Ds"); 948 } 949 950 public int pixelsTouched(GraphicsTests.Context ctx) { 951 // Approximated (copied from FillOvals.pixelsTouched()) 952 double xaxis = ctx.outdim.width / 2.0; 953 double yaxis = ctx.outdim.height / 2.0; 954 return (int) (xaxis * yaxis * Math.PI); 955 } 956 957 public static class Context extends RenderTests.Context { 958 Ellipse2D ellipse = new Ellipse2D.Float(); 959 } 960 961 public GraphicsTests.Context createContext() { 962 return new FillEllipse2Ds.Context(); 963 } 964 965 public void runTest(Object ctx, int numReps) { 966 FillEllipse2Ds.Context cctx = (FillEllipse2Ds.Context) ctx; 967 int size = cctx.size; 968 int x = cctx.initX; 969 int y = cctx.initY; 970 Ellipse2D ellipse = cctx.ellipse; 971 Graphics2D g2d = (Graphics2D) cctx.graphics; 972 g2d.translate(cctx.orgX, cctx.orgY); 973 Color rCArray[] = cctx.colorlist; 974 int ci = cctx.colorindex; 975 do { 976 if (rCArray != null) { 977 g2d.setColor(rCArray[ci++ & NUM_RANDOMCOLORMASK]); 978 } 979 ellipse.setFrame(x, y, size, size); 980 g2d.fill(ellipse); 981 if ((x -= 3) < 0) x += cctx.maxX; 982 if ((y -= 1) < 0) y += cctx.maxY; 983 } while (--numReps > 0); 984 cctx.colorindex = ci; 985 g2d.translate(-cctx.orgX, -cctx.orgY); 986 } 987 } 988 989 public static class DrawEllipse2Ds extends RenderTests { 990 public DrawEllipse2Ds() { 991 super(rendershaperoot, "drawEllipse2D", "Draw Ellipse2Ds"); 992 } 993 994 public int pixelsTouched(GraphicsTests.Context ctx) { 995 // Approximated (copied from DrawOvals.pixelsTouched()) 996 return (int)(Math.sqrt(2.0)*(ctx.outdim.width+ctx.outdim.height)); 997 } 998 999 public static class Context extends RenderTests.Context { 1000 Ellipse2D ellipse = new Ellipse2D.Float(); 1001 } 1002 1003 public GraphicsTests.Context createContext() { 1004 return new DrawEllipse2Ds.Context(); 1005 } 1006 1007 public void runTest(Object ctx, int numReps) { 1008 DrawEllipse2Ds.Context cctx = (DrawEllipse2Ds.Context) ctx; 1009 int size = cctx.size; 1010 int x = cctx.initX; 1011 int y = cctx.initY; 1012 Ellipse2D ellipse = cctx.ellipse; 1013 Graphics2D g2d = (Graphics2D) cctx.graphics; 1014 g2d.translate(cctx.orgX, cctx.orgY); 1015 Color rCArray[] = cctx.colorlist; 1016 int ci = cctx.colorindex; 1017 do { 1018 if (rCArray != null) { 1019 g2d.setColor(rCArray[ci++ & NUM_RANDOMCOLORMASK]); 1020 } 1021 ellipse.setFrame(x, y, size, size); 1022 g2d.draw(ellipse); 1023 if ((x -= 3) < 0) x += cctx.maxX; 1024 if ((y -= 1) < 0) y += cctx.maxY; 1025 } while (--numReps > 0); 1026 cctx.colorindex = ci; 1027 g2d.translate(-cctx.orgX, -cctx.orgY); 1028 } 1029 } 1030} 1031