1 /* 2 * Copyright (c) 2003, 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 41 /* 42 * (C) Copyright IBM Corp. 2003, All Rights Reserved. 43 * This technology is protected by multiple US and International 44 * patents. This notice and attribution to IBM may not be removed. 45 */ 46 47 package j2dbench.tests.text; 48 49 import java.awt.Font; 50 import java.awt.FontMetrics; 51 import java.awt.Rectangle; 52 import java.awt.Shape; 53 import java.awt.font.GlyphMetrics; 54 import java.awt.font.GlyphVector; 55 import java.awt.font.TextHitInfo; 56 import java.awt.font.TextLayout; 57 import java.awt.geom.AffineTransform; 58 import java.awt.geom.Rectangle2D; 59 import java.text.Bidi; 60 import java.util.ArrayList; 61 62 import j2dbench.Group; 63 import j2dbench.Result; 64 import j2dbench.TestEnvironment; 65 66 public abstract class TextMeasureTests extends TextTests { 67 static Group measureroot; 68 static Group measuretestroot; 69 70 public static void init() { 71 measureroot = new Group(textroot, "Measuring", "Measuring Benchmarks"); 72 measuretestroot = new Group(measureroot, "tests", "Measuring Tests"); 73 74 new StringWidth(); 75 new StringBounds(); 76 new CharsWidth(); 77 new CharsBounds(); 78 new FontCanDisplay(); 79 80 if (hasGraphics2D) { 81 new GVWidth(); 82 new GVLogicalBounds(); 83 new GVVisualBounds(); 84 new GVPixelBounds(); 85 new GVOutline(); 86 new GVGlyphLogicalBounds(); 87 new GVGlyphVisualBounds(); 88 new GVGlyphPixelBounds(); 89 new GVGlyphOutline(); 90 new GVGlyphTransform(); 91 new GVGlyphMetrics(); 92 93 new TLAdvance(); 94 new TLAscent(); 95 new TLBounds(); 96 new TLGetCaretInfo(); 97 new TLGetNextHit(); 98 new TLGetCaretShape(); 99 new TLGetLogicalHighlightShape(); 100 new TLHitTest(); 101 new TLOutline(); 102 103 /* 104 new FontLineMetrics(); 105 new FontStringBounds(); 106 */ 107 } 108 } 109 110 public TextMeasureTests(Group parent, String nodeName, String description) { 111 super(parent, nodeName, description); 112 } 113 114 static class SWContext extends TextContext { 115 FontMetrics fm; 116 117 public void init(TestEnvironment env, Result results) { 118 super.init(env, results); 119 fm = graphics.getFontMetrics(font); 120 } 121 } 122 123 public Context createContext() { 124 return new SWContext(); 125 } 126 127 public static class StringWidth extends TextMeasureTests { 128 public StringWidth() { 129 super(measuretestroot, "stringWidth", "Measuring String Width"); 130 } 131 132 public void runTest(Object ctx, int numReps) { 133 SWContext swctx = (SWContext)ctx; 134 String text = swctx.text; 135 FontMetrics fm = swctx.fm; 136 int wid = 0; 137 do { 138 wid += fm.stringWidth(text); 139 } while (--numReps >= 0); 140 } 141 } 142 143 public static class StringBounds extends TextMeasureTests { 144 public StringBounds() { 145 super(measuretestroot, "stringBounds", "Measuring String Bounds"); 146 } 147 148 public void runTest(Object ctx, int numReps) { 149 SWContext swctx = (SWContext)ctx; 150 String text = swctx.text; 151 FontMetrics fm = swctx.fm; 152 int wid = 0; 153 Rectangle r = null; 154 do { 155 r = null; 156 int dx = fm.stringWidth(text); 157 int dy = fm.getAscent() + fm.getDescent() + fm.getLeading(); 158 int x = 0; 159 int y = -fm.getAscent(); 160 r = new Rectangle(x, y, dx, dy); 161 } while (--numReps >= 0); 162 } 163 } 164 165 public static class CharsWidth extends TextMeasureTests { 166 public CharsWidth() { 167 super(measuretestroot, "charsWidth", "Measuring Chars Width"); 168 } 169 170 public void runTest(Object ctx, int numReps) { 171 SWContext swctx = (SWContext)ctx; 172 FontMetrics fm = swctx.fm; 173 char[] chars = swctx.chars; 174 int wid = 0; 175 do { 176 wid += fm.charsWidth(chars, 0, chars.length); 177 } while (--numReps >= 0); 178 } 179 } 180 181 public static class CharsBounds extends TextMeasureTests { 182 public CharsBounds() { 183 super(measuretestroot, "charsBounds", "Measuring Chars Bounds"); 184 } 185 186 public void runTest(Object ctx, int numReps) { 187 SWContext swctx = (SWContext)ctx; 188 FontMetrics fm = swctx.fm; 189 char[] chars = swctx.chars; 190 int wid = 0; 191 Rectangle r = null; 192 do { 193 r = null; 194 int dx = fm.charsWidth(chars, 0, chars.length); 195 int dy = fm.getAscent() + fm.getDescent() + fm.getLeading(); 196 int x = 0; 197 int y = -fm.getAscent(); 198 r = new Rectangle(x, y, dx, dy); 199 } while (--numReps >= 0); 200 } 201 } 202 203 public static class FontCanDisplay extends TextMeasureTests { 204 public FontCanDisplay() { 205 super(measuretestroot, "fontcandisplay", "Font canDisplay(char)"); 206 } 207 208 public void runTest(Object ctx, int numReps) { 209 Font font = ((TextContext)ctx).font; 210 boolean b = false; 211 do { 212 for (int i = 0; i < 0x10000; i += 0x64) { 213 b ^= font.canDisplay((char)i); 214 } 215 } while (--numReps >= 0); 216 } 217 } 218 219 public static class GVContext extends G2DContext { 220 GlyphVector gv; 221 222 public void init(TestEnvironment env, Result results) { 223 super.init(env, results); 224 225 int flags = Font.LAYOUT_LEFT_TO_RIGHT; 226 if (Bidi.requiresBidi(chars, 0, chars.length)) { // assume rtl 227 flags = Font.LAYOUT_RIGHT_TO_LEFT; 228 } 229 gv = font.layoutGlyphVector(frc, chars, 0, chars.length, flags); 230 231 // gv options 232 } 233 } 234 235 public static abstract class GVMeasureTest extends TextMeasureTests { 236 protected GVMeasureTest(Group parent, String nodeName, String description) { 237 super(parent, nodeName, description); 238 } 239 240 public Context createContext() { 241 return new GVContext(); 242 } 243 } 244 245 public static class GVWidth extends GVMeasureTest { 246 public GVWidth() { 247 super(measuretestroot, "gvWidth", "Measuring GV Width"); 248 } 249 250 public void runTest(Object ctx, int numReps) { 251 GVContext gvctx = (GVContext)ctx; 252 GlyphVector gv = gvctx.gv; 253 double wid = 0; 254 do { 255 wid += gv.getGlyphPosition(gv.getNumGlyphs()).getX(); 256 } while (--numReps >= 0); 257 } 258 } 259 260 public static class GVLogicalBounds extends GVMeasureTest { 261 public GVLogicalBounds() { 262 super(measuretestroot, "gvLogicalBounds", "Measuring GV Logical Bounds"); 263 } 264 265 public void runTest(Object ctx, int numReps) { 266 GVContext gvctx = (GVContext)ctx; 267 GlyphVector gv = gvctx.gv; 268 Rectangle2D r; 269 do { 270 r = gv.getLogicalBounds(); 271 } while (--numReps >= 0); 272 } 273 } 274 275 public static class GVVisualBounds extends GVMeasureTest { 276 public GVVisualBounds() { 277 super(measuretestroot, "gvVisualBounds", "Measuring GV Visual Bounds"); 278 } 279 280 public void runTest(Object ctx, int numReps) { 281 GVContext gvctx = (GVContext)ctx; 282 GlyphVector gv = gvctx.gv; 283 Rectangle2D r; 284 do { 285 r = gv.getVisualBounds(); 286 } while (--numReps >= 0); 287 } 288 } 289 290 public static class GVPixelBounds extends GVMeasureTest { 291 public GVPixelBounds() { 292 super(measuretestroot, "gvPixelBounds", "Measuring GV Pixel Bounds"); 293 } 294 295 public void runTest(Object ctx, int numReps) { 296 GVContext gvctx = (GVContext)ctx; 297 GlyphVector gv = gvctx.gv; 298 Rectangle2D r; 299 do { 300 r = gv.getPixelBounds(null, 0, 0); // !!! add opt to provide different frc? 301 } while (--numReps >= 0); 302 } 303 } 304 305 public static class GVOutline extends GVMeasureTest { 306 public GVOutline() { 307 super(measuretestroot, "gvOutline", "Getting GV Outline"); 308 } 309 310 public void runTest(Object ctx, int numReps) { 311 GVContext gvctx = (GVContext)ctx; 312 GlyphVector gv = gvctx.gv; 313 Shape s; 314 do { 315 s = gv.getOutline(); 316 } while (--numReps >= 0); 317 } 318 } 319 320 public static class GVGlyphLogicalBounds extends GVMeasureTest { 321 public GVGlyphLogicalBounds() { 322 super(measuretestroot, "gvGlyphLogicalBounds", "Measuring GV Glyph Logical Bounds"); 323 } 324 325 public void runTest(Object ctx, int numReps) { 326 GVContext gvctx = (GVContext)ctx; 327 GlyphVector gv = gvctx.gv; 328 Shape s; 329 do { 330 for (int i = 0, e = gv.getNumGlyphs(); i < e; ++i) { 331 s = gv.getGlyphLogicalBounds(i); 332 } 333 } while (--numReps >= 0); 334 } 335 } 336 337 public static class GVGlyphVisualBounds extends GVMeasureTest { 338 public GVGlyphVisualBounds() { 339 super(measuretestroot, "gvGlyphVisualBounds", "Measuring GV Glyph Visual Bounds"); 340 } 341 342 public void runTest(Object ctx, int numReps) { 343 GVContext gvctx = (GVContext)ctx; 344 GlyphVector gv = gvctx.gv; 345 Shape s; 346 do { 347 for (int i = 0, e = gv.getNumGlyphs(); i < e; ++i) { 348 s = gv.getGlyphVisualBounds(i); 349 } 350 } while (--numReps >= 0); 351 } 352 } 353 354 355 public static class GVGlyphPixelBounds extends GVMeasureTest { 356 public GVGlyphPixelBounds() { 357 super(measuretestroot, "gvGlyphPixelBounds", "Measuring GV Glyph Pixel Bounds"); 358 } 359 360 public void runTest(Object ctx, int numReps) { 361 GVContext gvctx = (GVContext)ctx; 362 GlyphVector gv = gvctx.gv; 363 Rectangle2D r; 364 do { 365 for (int i = 0, e = gv.getNumGlyphs(); i < e; ++i) { 366 r = gv.getGlyphPixelBounds(i, null, 0, 0); // !!! add opt to provide different frc? 367 } 368 } while (--numReps >= 0); 369 } 370 } 371 372 public static class GVGlyphOutline extends GVMeasureTest { 373 public GVGlyphOutline() { 374 super(measuretestroot, "gvGlyphOutline", "Getting GV Glyph Outline"); 375 } 376 377 public void runTest(Object ctx, int numReps) { 378 GVContext gvctx = (GVContext)ctx; 379 GlyphVector gv = gvctx.gv; 380 Shape s; 381 do { 382 for (int i = 0, e = gv.getNumGlyphs(); i < e; ++i) { 383 s = gv.getGlyphOutline(i); 384 } 385 } while (--numReps >= 0); 386 } 387 } 388 389 public static class GVGlyphTransform extends GVMeasureTest { 390 public GVGlyphTransform() { 391 super(measuretestroot, "gvGlyphTransform", "Getting GV Glyph Transform"); 392 } 393 394 public void runTest(Object ctx, int numReps) { 395 GVContext gvctx = (GVContext)ctx; 396 GlyphVector gv = gvctx.gv; 397 AffineTransform tx; 398 do { 399 for (int i = 0, e = gv.getNumGlyphs(); i < e; ++i) { 400 tx = gv.getGlyphTransform(i); 401 } 402 } while (--numReps >= 0); 403 } 404 } 405 406 public static class GVGlyphMetrics extends GVMeasureTest { 407 public GVGlyphMetrics() { 408 super(measuretestroot, "gvGlyphMetrics", "Getting GV Glyph Metrics"); 409 } 410 411 public void runTest(Object ctx, int numReps) { 412 GVContext gvctx = (GVContext)ctx; 413 GlyphVector gv = gvctx.gv; 414 GlyphMetrics gm; 415 do { 416 for (int i = 0, e = gv.getNumGlyphs(); i < e; ++i) { 417 gm = gv.getGlyphMetrics(i); 418 } 419 } while (--numReps >= 0); 420 } 421 } 422 423 public static class TLContext extends G2DContext { 424 TextLayout tl; 425 426 public void init(TestEnvironment env, Result results) { 427 super.init(env, results); 428 429 // need more tl options here 430 tl = new TextLayout(text, font, frc); 431 } 432 } 433 434 public static abstract class TLMeasureTest extends TextMeasureTests { 435 protected TLMeasureTest(Group parent, String nodeName, String description) { 436 super(parent, nodeName, description); 437 } 438 439 public Context createContext() { 440 return new TLContext(); 441 } 442 } 443 444 public static class TLAdvance extends TLMeasureTest { 445 public TLAdvance() { 446 super(measuretestroot, "tlAdvance", "Measuring TL advance"); 447 } 448 449 public void runTest(Object ctx, int numReps) { 450 TLContext tlctx = (TLContext)ctx; 451 TextLayout tl = tlctx.tl; 452 double wid = 0; 453 do { 454 wid += tl.getAdvance(); 455 } while (--numReps >= 0); 456 } 457 } 458 459 public static class TLAscent extends TLMeasureTest { 460 public TLAscent() { 461 super(measuretestroot, "tlAscent", "Measuring TL ascent"); 462 } 463 464 public void runTest(Object ctx, int numReps) { 465 TLContext tlctx = (TLContext)ctx; 466 TextLayout tl = tlctx.tl; 467 float ht = 0; 468 do { 469 ht += tl.getAscent(); 470 } while (--numReps >= 0); 471 } 472 } 473 474 public static class TLBounds extends TLMeasureTest { 475 public TLBounds() { 476 super(measuretestroot, "tlBounds", "Measuring TL advance"); 477 } 478 479 public void runTest(Object ctx, int numReps) { 480 TLContext tlctx = (TLContext)ctx; 481 TextLayout tl = tlctx.tl; 482 Rectangle2D r; 483 do { 484 r = tl.getBounds(); 485 } while (--numReps >= 0); 486 } 487 } 488 489 static class TLExContext extends TLContext { 490 TextHitInfo[] hits; 491 Rectangle2D lb; 492 493 public void init(TestEnvironment env, Result results) { 494 super.init(env, results); 495 496 ArrayList list = new ArrayList(text.length() * 2 + 2); 497 TextHitInfo hit = TextHitInfo.trailing(-1); 498 do { 499 list.add(hit); 500 hit = tl.getNextRightHit(hit); 501 } while (hit != null); 502 hits = (TextHitInfo[])list.toArray(new TextHitInfo[list.size()]); 503 504 lb = tl.getBounds(); 505 lb.setRect(lb.getMinX() - 10, lb.getMinY(), lb.getWidth() + 20, lb.getHeight()); 506 } 507 } 508 509 public static abstract class TLExtendedMeasureTest extends TLMeasureTest { 510 protected TLExtendedMeasureTest(Group parent, String nodeName, String description) { 511 super(parent, nodeName, description); 512 } 513 514 public Context createContext() { 515 return new TLExContext(); 516 } 517 } 518 519 public static class TLGetCaretInfo extends TLExtendedMeasureTest { 520 public TLGetCaretInfo() { 521 super(measuretestroot, "tlGetCaretInfo", "Measuring TL caret info"); 522 } 523 524 public void runTest(Object ctx, int numReps) { 525 TLExContext tlctx = (TLExContext)ctx; 526 TextLayout tl = tlctx.tl; 527 TextHitInfo[] hits = tlctx.hits; 528 do { 529 for (int i = 0; i < hits.length; ++i) { 530 tl.getCaretInfo(hits[i]); 531 } 532 } while (--numReps >= 0); 533 } 534 } 535 536 public static class TLGetNextHit extends TLExtendedMeasureTest { 537 public TLGetNextHit() { 538 super(measuretestroot, "tlGetNextHit", "Measuring TL getNextRight/LeftHit"); 539 } 540 541 public void runTest(Object ctx, int numReps) { 542 TLExContext tlctx = (TLExContext)ctx; 543 TextLayout tl = tlctx.tl; 544 TextHitInfo[] hits = tlctx.hits; 545 TextHitInfo hit; 546 do { 547 for (int i = 0; i < hits.length; ++i) { 548 hit = tl.getNextLeftHit(hits[i]); 549 } 550 } while (--numReps >= 0); 551 } 552 } 553 554 public static class TLGetCaretShape extends TLExtendedMeasureTest { 555 public TLGetCaretShape() { 556 super(measuretestroot, "tlGetCaretShape", "Measuring TL getCaretShape"); 557 } 558 559 public void runTest(Object ctx, int numReps) { 560 TLExContext tlctx = (TLExContext)ctx; 561 TextLayout tl = tlctx.tl; 562 TextHitInfo[] hits = tlctx.hits; 563 Shape s; 564 do { 565 for (int i = 0; i < hits.length; ++i) { 566 s = tl.getCaretShape(hits[i]); 567 } 568 } while (--numReps >= 0); 569 } 570 } 571 572 public static class TLGetLogicalHighlightShape extends TLExtendedMeasureTest { 573 public TLGetLogicalHighlightShape() { 574 super(measuretestroot, "tlGetLogicalHighlightShape", "Measuring TL getLogicalHighlightShape"); 575 } 576 577 public void runTest(Object ctx, int numReps) { 578 TLExContext tlctx = (TLExContext)ctx; 579 TextLayout tl = tlctx.tl; 580 int len = tlctx.text.length(); 581 Rectangle2D lb = tlctx.lb; 582 Shape s; 583 if (len < 3) { 584 do { 585 s = tl.getLogicalHighlightShape(0, len, lb); 586 } while (--numReps >= 0); 587 } else { 588 do { 589 for (int i = 3; i < len; ++i) { 590 s = tl.getLogicalHighlightShape(i-3, i, lb); 591 } 592 } while (--numReps >= 0); 593 } 594 } 595 } 596 597 public static class TLGetVisualHighlightShape extends TLExtendedMeasureTest { 598 public TLGetVisualHighlightShape() { 599 super(measuretestroot, "tlGetVisualHighlightShape", "Measuring TL getVisualHighlightShape"); 600 } 601 602 public void runTest(Object ctx, int numReps) { 603 TLExContext tlctx = (TLExContext)ctx; 604 TextLayout tl = tlctx.tl; 605 TextHitInfo[] hits = tlctx.hits; 606 Rectangle2D lb = tlctx.lb; 607 Shape s; 608 if (hits.length < 3) { 609 do { 610 s = tl.getVisualHighlightShape(hits[0], hits[hits.length - 1], lb); 611 } while (--numReps >= 0); 612 } else { 613 do { 614 for (int i = 3; i < hits.length; ++i) { 615 s = tl.getVisualHighlightShape(hits[i-3], hits[i], lb); 616 } 617 } while (--numReps >= 0); 618 } 619 } 620 } 621 622 public static class TLHitTest extends TLExtendedMeasureTest { 623 public TLHitTest() { 624 super(measuretestroot, "tlHitTest", "Measuring TL hitTest"); 625 } 626 627 public void runTest(Object ctx, int numReps) { 628 TLExContext tlctx = (TLExContext)ctx; 629 TextLayout tl = tlctx.tl; 630 int numhits = tlctx.hits.length; 631 Rectangle2D lb = tlctx.lb; 632 TextHitInfo hit; 633 for (int i = 0; i <= numhits; ++i) { 634 float x = (float)(lb.getMinX() + lb.getWidth() * i / numhits); 635 float y = (float)(lb.getMinY() + lb.getHeight() * i / numhits); 636 hit = tl.hitTestChar(x, y, lb); 637 } 638 } 639 } 640 641 public static class TLOutline extends TLMeasureTest { 642 public TLOutline() { 643 super(measuretestroot, "tlOutline", "Measuring TL outline"); 644 } 645 646 public void runTest(Object ctx, int numReps) { 647 TLContext tlctx = (TLContext)ctx; 648 TextLayout tl = tlctx.tl; 649 Shape s; 650 do { 651 s = tl.getOutline(null); 652 } while (--numReps >= 0); 653 } 654 } 655 }