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.Color; 50 import java.awt.Font; 51 import java.awt.Graphics; 52 import java.awt.Graphics2D; 53 import java.awt.GraphicsEnvironment; 54 import java.awt.RenderingHints; 55 import java.awt.font.NumericShaper; 56 import java.awt.font.TextAttribute; 57 import java.awt.font.FontRenderContext; 58 import java.awt.geom.AffineTransform; 59 import java.io.InputStream; 60 import java.io.BufferedReader; 61 import java.io.InputStreamReader; 62 import java.io.IOException; 63 import java.io.PrintWriter; 64 import java.util.HashMap; 65 import java.util.HashSet; 66 import java.util.Map; 67 import java.util.Set; 68 import javax.swing.JComponent; 69 70 import j2dbench.Destinations; 71 import j2dbench.Group; 72 import j2dbench.Node; 73 import j2dbench.Option; 74 import j2dbench.Option.ObjectList; 75 import j2dbench.Result; 76 import j2dbench.Test; 77 import j2dbench.TestEnvironment; 78 79 public abstract class TextTests extends Test { 80 public static boolean hasGraphics2D; 81 82 static { 83 try { 84 hasGraphics2D = (Graphics2D.class != null); 85 } catch (NoClassDefFoundError e) { 86 } 87 } 88 89 // core data 90 static final int[] tlengths = { 91 1, 2, 4, 8, 16, 32, 64, 128, 256, 512 92 }; 93 94 static final String[] tscripts = { 95 // german, vietnamese, surrogate, dingbats 96 "english", "arabic", "greek", "hebrew", "hindi", "japanese", "korean", "thai", 97 "english-arabic", "english-greek", "english-hindi", "english-arabic-hindi" 98 }; 99 100 static final float[] fsizes = { 101 1f, 6f, 8f, 10f, 12f, 12.5f, 13f, 13.5f, 16f, 20f, 36f, 72f, 128f 102 }; 103 104 static final float[] fintsizes = { 105 1f, 6f, 8f, 10f, 12f, 13f, 16f, 20f, 36f, 72f, 128f 106 }; 107 108 // utilties floatObjectList(float[] input)109 static Float[] floatObjectList(float[] input) { 110 Float[] result = new Float[input.length]; 111 for (int i = 0; i < result.length; ++i) { 112 result[i] = new Float(input[i]); 113 } 114 return result; 115 } 116 floatStringList(float[] input)117 static String[] floatStringList(float[] input) { 118 return floatStringList("", input, ""); 119 } 120 floatStringList(float[] input, String sfx)121 static String[] floatStringList(float[] input, String sfx) { 122 return floatStringList("", input, sfx); 123 } 124 floatStringList(String pfx, float[] input, String sfx)125 static String[] floatStringList(String pfx, float[] input, String sfx) { 126 String[] result = new String[input.length]; 127 for (int i = 0; i < result.length; ++i) { 128 result[i] = pfx + input[i] + sfx; 129 } 130 return result; 131 } 132 intStringList(int[] input)133 static String[] intStringList(int[] input) { 134 return intStringList("", input, ""); 135 } 136 intStringList(int[] input, String sfx)137 static String[] intStringList(int[] input, String sfx) { 138 return intStringList("", input, sfx); 139 } 140 intStringList(String pfx, int[] input, String sfx)141 static String[] intStringList(String pfx, int[] input, String sfx) { 142 String[] result = new String[input.length]; 143 for (int i = 0; i < result.length; ++i) { 144 result[i] = pfx + input[i] + sfx; 145 } 146 return result; 147 } 148 149 static final String[] txNames; 150 static final String[] txDescNames; 151 static final AffineTransform[] txList; 152 static final Map[] maps; 153 static { 154 AffineTransform identity = new AffineTransform(); 155 AffineTransform sm_scale = AffineTransform.getScaleInstance(.5, .5); 156 AffineTransform lg_scale = AffineTransform.getScaleInstance(2, 2); 157 AffineTransform wide = AffineTransform.getScaleInstance(2, .8); 158 AffineTransform tall = AffineTransform.getScaleInstance(.8, 2); 159 AffineTransform x_trans = AffineTransform.getTranslateInstance(50, 0); 160 AffineTransform y_trans = AffineTransform.getTranslateInstance(0, -30); 161 AffineTransform xy_trans = AffineTransform.getTranslateInstance(50, -30); 162 AffineTransform sm_rot = AffineTransform.getRotateInstance(Math.PI / 3); 163 AffineTransform lg_rot = AffineTransform.getRotateInstance(Math.PI * 4 / 3); 164 AffineTransform pi2_rot = AffineTransform.getRotateInstance(Math.PI / 2); 165 AffineTransform x_shear = AffineTransform.getShearInstance(.4, 0); 166 AffineTransform y_shear = AffineTransform.getShearInstance(0, -.4); 167 AffineTransform xy_shear = AffineTransform.getShearInstance(.3, .3); 168 AffineTransform x_flip = AffineTransform.getScaleInstance(-1, 1); 169 AffineTransform y_flip = AffineTransform.getScaleInstance(1, -1); 170 AffineTransform xy_flip = AffineTransform.getScaleInstance(-1, -1); 171 AffineTransform w_rot = AffineTransform.getRotateInstance(Math.PI / 3); 172 w_rot.scale(2, .8); 173 AffineTransform w_y_shear = AffineTransform.getShearInstance(0, -.4); 174 w_y_shear.scale(2, .8); 175 AffineTransform w_r_trans = AffineTransform.getTranslateInstance(3, -7); 176 w_r_trans.rotate(Math.PI / 3); 177 w_r_trans.scale(2, .8); 178 AffineTransform w_t_rot = AffineTransform.getRotateInstance(Math.PI / 3); 179 w_t_rot.translate(3, -7); 180 w_t_rot.scale(2, .8); 181 AffineTransform w_y_s_r_trans = AffineTransform.getTranslateInstance(3, -7); 182 w_y_s_r_trans.rotate(Math.PI / 3); 183 w_y_s_r_trans.shear(0, -.4); 184 w_y_s_r_trans.scale(2, .8); 185 186 txNames = new String[] { 187 "ident", 188 "smsc", "lgsc", "wide", "tall", 189 "xtrn", "ytrn", "xytrn", 190 "srot", "lrot", "hrot", 191 "xshr", "yshr", "xyshr", 192 "flx", "fly", "flxy", 193 "wr", "wys", "wrt", 194 "wtr", "wysrt" 195 }; 196 197 txDescNames = new String[] { 198 "Identity", 199 "Sm Scale", "Lg Scale", "Wide", "Tall", 200 "X Trans", "Y Trans", "XY Trans", 201 "Sm Rot", "Lg Rot", "PI/2 Rot", 202 "X Shear", "Y Shear", "XY Shear", 203 "FlipX", "FlipY", "FlipXY", 204 "WRot", "WYShear", "WRTrans", 205 "WTRot", "WYSRTrans" 206 }; 207 208 txList = new AffineTransform[] { 209 identity, 210 sm_scale, lg_scale, wide, tall, 211 x_trans, y_trans, xy_trans, 212 sm_rot, lg_rot, pi2_rot, 213 x_shear, y_shear, xy_shear, 214 x_flip, y_flip, xy_flip, 215 w_rot, w_y_shear, w_r_trans, 216 w_t_rot, w_y_s_r_trans, 217 }; 218 219 // maps 220 HashMap fontMap = new HashMap(); fontMap.put(TextAttribute.FONT, new Font(R, Font.ITALIC, 18))221 fontMap.put(TextAttribute.FONT, new Font("Dialog", Font.ITALIC, 18)); 222 223 HashMap emptyMap = new HashMap(); 224 225 HashMap simpleMap = new HashMap(); simpleMap.put(TextAttribute.FAMILY, R)226 simpleMap.put(TextAttribute.FAMILY, "Lucida Sans"); simpleMap.put(TextAttribute.SIZE, new Float(14))227 simpleMap.put(TextAttribute.SIZE, new Float(14)); simpleMap.put(TextAttribute.FOREGROUND, Color.blue)228 simpleMap.put(TextAttribute.FOREGROUND, Color.blue); 229 230 HashMap complexMap = new HashMap(); complexMap.put(TextAttribute.FAMILY, R)231 complexMap.put(TextAttribute.FAMILY, "Serif"); complexMap.put(TextAttribute.TRANSFORM, tall)232 complexMap.put(TextAttribute.TRANSFORM, tall); complexMap.put(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON)233 complexMap.put(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON); complexMap.put(TextAttribute.RUN_DIRECTION, TextAttribute.RUN_DIRECTION_RTL)234 complexMap.put(TextAttribute.RUN_DIRECTION, 235 TextAttribute.RUN_DIRECTION_RTL); 236 try { complexMap.put(TextAttribute.NUMERIC_SHAPING, NumericShaper.getContextualShaper(NumericShaper.ALL_RANGES))237 complexMap.put(TextAttribute.NUMERIC_SHAPING, 238 NumericShaper.getContextualShaper(NumericShaper.ALL_RANGES)); 239 } catch (NoSuchFieldError e) { 240 } 241 242 maps = new Map[] { 243 fontMap, 244 emptyMap, 245 simpleMap, 246 complexMap, 247 }; 248 } 249 getString(Object key, int len)250 static String getString(Object key, int len) { 251 String keyString = key.toString(); 252 String[] strings = new String[4]; // leave room for index == 3 to return null 253 int span = Math.min(32, len); 254 int n = keyString.indexOf('-'); 255 if (n == -1) { 256 strings[0] = getSimpleString(keyString); 257 } else { 258 strings[0] = getSimpleString(keyString.substring(0, n)); 259 int m = keyString.indexOf('-', n+1); 260 if (m == -1) { 261 strings[1] = getSimpleString(keyString.substring(n+1)); 262 // 2 to 1 ratio, short spans between 1 and 16 chars long 263 span = Math.max(1, Math.min(16, len / 3)); 264 } else { 265 strings[1] = getSimpleString(keyString.substring(n+1, m)); 266 strings[2] = getSimpleString(keyString.substring(m+1)); 267 span = Math.max(1, Math.min(16, len / 4)); 268 } 269 } 270 String s = ""; 271 int pos = 0; 272 int strx = 0; 273 while (s.length() < len) { 274 String src; 275 if (strings[strx] == null) { 276 src = strings[0]; // use strings[0] twice for each other string 277 strx = 0; 278 } else { 279 src = strings[strx++]; 280 } 281 if (pos + span > src.length()) { 282 pos = 0; // we know all strings are longer than span 283 } 284 s += src.substring(pos, pos+span); 285 pos += span; 286 } 287 return s.substring(0, len); 288 } 289 290 291 static HashMap strcache = new HashMap(tscripts.length); getSimpleString(Object key)292 private static String getSimpleString(Object key) { 293 String s = (String)strcache.get(key); 294 if (s == null) { 295 String fname = "textdata/" + key + ".ut8.txt"; 296 try { 297 InputStream is = TextTests.class.getResourceAsStream(fname); 298 if (is == null) { 299 throw new IOException("Can't load resource " + fname); 300 } 301 BufferedReader r = 302 new BufferedReader(new InputStreamReader(is, "utf8")); 303 StringBuffer buf = new StringBuffer(r.readLine()); 304 while (null != (s = r.readLine())) { 305 buf.append(" "); 306 buf.append(s); 307 } 308 s = buf.toString(); 309 if (s.charAt(0) == '\ufeff') { 310 s = s.substring(1); 311 } 312 } 313 catch (IOException e) { 314 s = "This is a dummy ascii string because " + 315 fname + " was not found."; 316 } 317 strcache.put(key, s); 318 } 319 return s; 320 } 321 322 static Group textroot; 323 static Group txoptroot; 324 static Group txoptdataroot; 325 static Group txoptfontroot; 326 static Group txoptgraphicsroot; 327 static Group advoptsroot; 328 329 static Option tlengthList; 330 static Option tscriptList; 331 static Option fnameList; 332 static Option fstyleList; 333 static Option fsizeList; 334 static Option ftxList; 335 static Option taaList; 336 static Option tfmTog; 337 static Option gaaTog; 338 static Option gtxList; 339 static Option gvstyList; 340 static Option tlrunList; 341 static Option tlmapList; 342 343 // core is textlength, text script, font name/style/size/tx, frc 344 345 // drawing 346 // drawString, drawChars, drawBytes, drawGlyphVector, TextLayout.draw, drawAttributedString 347 // length of text 348 // 1, 2, 4, 8, 16, 32, 64, 128, 256 chars 349 // script of text 350 // simple: latin-1, japanese, arabic, hebrew, indic, thai, surrogate, dingbats 351 // mixed: latin-1 + x (1, 2, 3, 4 pairs) 352 // font of text 353 // name (composite, not), style, size (6, 12, 18, 24, 30, 36, 42, 48, 54, 60), transform (full set) 354 // text rendering hints 355 // aa, fm, gaa 356 // graphics transform (full set) 357 // (gv) gtx, gpos 358 // (tl, as) num style runs 359 // 360 // querying/measuring 361 // ascent/descent/leading 362 // advance 363 // (gv) lb, vb, pb, glb, gvb, glb, gp, gjust, gmet, gtx 364 // (tl) bounds, charpos, cursor 365 // 366 // construction/layout 367 // (bidi) no controls, controls, styles 368 // (gv) createGV, layoutGV 369 // (tl) TL constructors 370 // (tm) line break 371 init()372 public static void init() { 373 textroot = new Group("text", "Text Benchmarks"); 374 textroot.setTabbed(); 375 376 txoptroot = new Group(textroot, "opts", "Text Options"); 377 txoptroot.setTabbed(); 378 379 txoptdataroot = new Group(txoptroot, "data", "Text Data"); 380 381 tlengthList = new Option.IntList(txoptdataroot, "tlength", 382 "Text Length", 383 tlengths, 384 intStringList(tlengths), 385 intStringList(tlengths, " chars"), 386 0x10); 387 ((Option.ObjectList) tlengthList).setNumRows(5); 388 389 tscriptList = new Option.ObjectList(txoptdataroot, "tscript", 390 "Text Script", 391 tscripts, 392 tscripts, 393 tscripts, 394 tscripts, 395 0x1); 396 ((Option.ObjectList) tscriptList).setNumRows(4); 397 398 txoptfontroot = new Group(txoptroot, "font", "Font"); 399 400 fnameList = new FontOption(txoptfontroot, "fname", "Family Name"); 401 402 fstyleList = new Option.IntList(txoptfontroot, "fstyle", 403 "Style", 404 new int[] { 405 Font.PLAIN, Font.BOLD, Font.ITALIC, Font.BOLD + Font.ITALIC, 406 }, 407 new String[] { 408 "plain", "bold", "italic", "bolditalic", 409 }, 410 new String[] { 411 "Plain", "Bold", "Italic", "Bold Italic", 412 }, 413 0x1); 414 415 float[] fsl = hasGraphics2D ? fsizes : fintsizes; 416 fsizeList = new Option.ObjectList(txoptfontroot, "fsize", 417 "Size", 418 floatStringList(fsl), 419 floatObjectList(fsl), 420 floatStringList(fsl), 421 floatStringList(fsl, "pt"), 422 0x40); 423 ((Option.ObjectList) fsizeList).setNumRows(5); 424 425 if (hasGraphics2D) { 426 ftxList = new Option.ObjectList(txoptfontroot, "ftx", 427 "Transform", 428 txDescNames, 429 txList, 430 txNames, 431 txDescNames, 432 0x1); 433 ((Option.ObjectList) ftxList).setNumRows(6); 434 435 txoptgraphicsroot = new Group(txoptroot, "graphics", "Graphics"); 436 437 String[] taaNames; 438 Object[] taaHints; 439 try { 440 taaNames = new String[] { 441 "Off", "On", 442 "LCD_HRGB", "LCD_HBGR", "LCD_VRGB", "LCD_VBGR" 443 }; 444 taaHints = new Object[] { 445 RenderingHints.VALUE_TEXT_ANTIALIAS_OFF, 446 RenderingHints.VALUE_TEXT_ANTIALIAS_ON, 447 RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB, 448 RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HBGR, 449 RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_VRGB, 450 RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_VBGR, 451 }; 452 } catch (NoSuchFieldError e) { 453 taaNames = new String[] { 454 "Off", "On" 455 }; 456 taaHints = new Object[] { 457 RenderingHints.VALUE_TEXT_ANTIALIAS_OFF, 458 RenderingHints.VALUE_TEXT_ANTIALIAS_ON, 459 }; 460 } 461 taaList = new Option.ObjectList(txoptgraphicsroot, "textaa", 462 "Text AntiAlias", 463 taaNames, taaHints, 464 taaNames, taaNames, 465 0x1); 466 ((Option.ObjectList) taaList).setNumRows(6); 467 // add special TextAAOpt for backwards compatibility with 468 // older options files 469 new TextAAOpt(); 470 471 tfmTog = new Option.Toggle(txoptgraphicsroot, "tfm", 472 "Fractional Metrics", Option.Toggle.Off); 473 gaaTog = new Option.Toggle(txoptgraphicsroot, "gaa", 474 "Graphics AntiAlias", Option.Toggle.Off); 475 476 gtxList = new Option.ObjectList(txoptgraphicsroot, "gtx", 477 "Transform", 478 txDescNames, 479 txList, 480 txNames, 481 txDescNames, 482 0x1); 483 ((Option.ObjectList) gtxList).setNumRows(6); 484 485 advoptsroot = new Group(txoptroot, "advopts", "Advanced Options"); 486 gvstyList = new Option.IntList(advoptsroot, "gvstyle", "Style", 487 new int[] { 0, 1, 2, 3 }, 488 new String[] { "std", "wave", "twist", "circle" }, 489 new String[] { "Standard", 490 "Positions adjusted", 491 "Glyph angles adjusted", 492 "Layout to circle" 493 }, 494 0x1); 495 496 int[] runs = { 1, 2, 4, 8 }; 497 tlrunList = new Option.IntList(advoptsroot, "tlruns", "Attribute Runs", 498 runs, 499 intStringList(runs), 500 intStringList(runs, " runs"), 501 0x1); 502 503 String[] tlmapnames = new String[] { "FONT", "Empty", "Simple", "Complex" }; 504 tlmapList = new Option.ObjectList(advoptsroot, "maptype", "Map", 505 tlmapnames, 506 maps, 507 new String[] { "font", "empty", "simple", "complex" }, 508 tlmapnames, 509 0x1); 510 } 511 } 512 513 /** 514 * This "virtual Node" implementation is here to maintain backward 515 * compatibility with older J2DBench releases, specifically those 516 * options files that were created before we added LCD-optimized text 517 * hints in JDK 6. This class will translate the text antialias settings 518 * from the old "taa" On/Off/Both choice into the new expanded version. 519 */ 520 private static class TextAAOpt extends Node { TextAAOpt()521 public TextAAOpt() { 522 super(txoptgraphicsroot, "taa", "Text AntiAlias"); 523 } 524 getJComponent()525 public JComponent getJComponent() { 526 return null; 527 } 528 restoreDefault()529 public void restoreDefault() { 530 // no-op 531 } 532 write(PrintWriter pw)533 public void write(PrintWriter pw) { 534 // no-op (the old "taa" choice will be saved as part of the 535 // new "textaa" option) 536 } 537 setOption(String key, String value)538 public String setOption(String key, String value) { 539 String opts; 540 if (value.equals("On")) { 541 opts = "On"; 542 } else if (value.equals("Off")) { 543 opts = "Off"; 544 } else if (value.equals("Both")) { 545 opts = "On,Off"; 546 } else { 547 return "Bad value"; 548 } 549 return ((Option.ObjectList)taaList).setValueFromString(opts); 550 } 551 } 552 553 public static class Context { init(TestEnvironment env, Result result)554 void init(TestEnvironment env, Result result) {} cleanup(TestEnvironment env)555 void cleanup(TestEnvironment env) {} 556 } 557 558 public static class TextContext extends Context { 559 Graphics graphics; 560 String text; 561 char[] chars; 562 Font font; 563 init(TestEnvironment env, Result result)564 public void init(TestEnvironment env, Result result) { 565 // graphics 566 graphics = env.getGraphics(); 567 568 // text 569 String sname = (String)env.getModifier(tscriptList); 570 int slen = env.getIntValue(tlengthList); 571 text = getString(sname, slen); 572 573 // chars 574 chars = text.toCharArray(); 575 576 // font 577 String fname = (String)env.getModifier(fnameList); 578 if ("Physical".equals(fname)) { 579 fname = physicalFontNameFor(sname, slen, text); 580 } 581 int fstyle = env.getIntValue(fstyleList); 582 float fsize = ((Float)env.getModifier(fsizeList)).floatValue(); 583 AffineTransform ftx = (AffineTransform)env.getModifier(ftxList); 584 font = new Font(fname, fstyle, (int)fsize); 585 if (hasGraphics2D) { 586 if (fsize != Math.floor(fsize)) { 587 font = font.deriveFont(fsize); 588 } 589 if (!ftx.isIdentity()) { 590 font = font.deriveFont(ftx); 591 } 592 } 593 594 // graphics 595 if (hasGraphics2D) { 596 Graphics2D g2d = (Graphics2D)graphics; 597 g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, 598 env.getModifier(taaList)); 599 g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, 600 env.isEnabled(tfmTog) 601 ? RenderingHints.VALUE_FRACTIONALMETRICS_ON 602 : RenderingHints.VALUE_FRACTIONALMETRICS_OFF); 603 g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 604 env.isEnabled(gaaTog) 605 ? RenderingHints.VALUE_ANTIALIAS_ON 606 : RenderingHints.VALUE_ANTIALIAS_OFF); 607 g2d.transform((AffineTransform)env.getModifier(gtxList)); 608 } 609 610 // set result 611 result.setUnits(text.length()); 612 result.setUnitName("char"); 613 } 614 cleanup(TestEnvironment env)615 public void cleanup(TestEnvironment env) { 616 graphics.dispose(); 617 graphics = null; 618 } 619 } 620 621 public static class G2DContext extends TextContext { 622 Graphics2D g2d; 623 FontRenderContext frc; 624 init(TestEnvironment env, Result results)625 public void init(TestEnvironment env, Result results){ 626 super.init(env, results); 627 g2d = (Graphics2D)graphics; 628 frc = g2d.getFontRenderContext(); 629 } 630 } 631 TextTests(Group parent, String nodeName, String description)632 public TextTests(Group parent, String nodeName, String description) { 633 super(parent, nodeName, description); 634 addDependency(Destinations.destroot); 635 addDependencies(txoptroot, true); 636 } 637 createContext()638 public Context createContext() { 639 return new TextContext(); 640 } 641 initTest(TestEnvironment env, Result result)642 public Object initTest(TestEnvironment env, Result result) { 643 Context ctx = createContext(); 644 ctx.init(env, result); 645 return ctx; 646 } 647 cleanupTest(TestEnvironment env, Object ctx)648 public void cleanupTest(TestEnvironment env, Object ctx) { 649 ((Context)ctx).cleanup(env); 650 } 651 652 static Map physicalMap = new HashMap(); physicalFontNameFor(String textname, int textlen, String text)653 public static String physicalFontNameFor(String textname, int textlen, String text) { 654 Map lenMap = (Map)physicalMap.get(textname); 655 if (lenMap == null) { 656 lenMap = new HashMap(); 657 physicalMap.put(textname, lenMap); 658 } 659 Integer key = new Integer(textlen); 660 Font textfont = (Font)lenMap.get(key); 661 if (textfont == null) { 662 Font[] fontsToTry = null; 663 if (lenMap.isEmpty()) { 664 fontsToTry = GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts(); 665 } else { 666 Set fontset = new HashSet(); 667 java.util.Iterator iter = lenMap.entrySet().iterator(); 668 while (iter.hasNext()) { 669 Map.Entry e = (Map.Entry)iter.next(); 670 fontset.add(e.getValue()); 671 } 672 fontsToTry = (Font[])fontset.toArray(new Font[fontset.size()]); 673 } 674 675 Font bestFont = null; 676 int bestCount = 0; 677 for (int i = 0; i < fontsToTry.length; ++i) { 678 Font font = fontsToTry[i]; 679 int count = 0; 680 for (int j = 0, limit = text.length(); j < limit; ++j) { 681 if (font.canDisplay(text.charAt(j))) { 682 ++count; 683 } 684 } 685 if (count > bestCount) { 686 bestFont = font; 687 bestCount = count; 688 } 689 } 690 691 textfont = bestFont; 692 lenMap.put(key, textfont); 693 } 694 return textfont.getName(); 695 } 696 697 static class FontOption extends ObjectList { 698 static String[] optionnames = { 699 "default", "serif", "lucida", "physical" 700 }; 701 static String[] descnames = { 702 "Default", "Serif", "Lucida Sans", "Physical" 703 }; 704 FontOption(Group parent, String nodeName, String description)705 public FontOption(Group parent, String nodeName, String description) { 706 super(parent, nodeName, description, 707 optionnames, descnames, optionnames, descnames, 0xa); 708 } 709 getValString(Object value)710 public String getValString(Object value) { 711 return value.toString(); 712 } 713 getAbbreviatedModifierDescription(Object value)714 public String getAbbreviatedModifierDescription(Object value) { 715 return value.toString(); 716 } 717 } 718 } 719 720