1 /* 2 * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /* 25 * Copyright (C) 2013-2014 IBM Corporation and Others. All Rights Reserved. 26 */ 27 28 import java.awt.Color; 29 import java.awt.Composite; 30 import java.awt.Font; 31 import java.awt.FontFormatException; 32 import java.awt.FontMetrics; 33 import java.awt.Graphics; 34 import java.awt.Graphics2D; 35 import java.awt.GraphicsConfiguration; 36 import java.awt.Image; 37 import java.awt.Paint; 38 import java.awt.Rectangle; 39 import java.awt.RenderingHints; 40 import java.awt.RenderingHints.Key; 41 import java.awt.Shape; 42 import java.awt.Stroke; 43 import java.awt.font.FontRenderContext; 44 import java.awt.font.GlyphVector; 45 import java.awt.font.TextLayout; 46 import java.awt.geom.AffineTransform; 47 import java.awt.image.BufferedImage; 48 import java.awt.image.BufferedImageOp; 49 import java.awt.image.ImageObserver; 50 import java.awt.image.RenderedImage; 51 import java.awt.image.renderable.RenderableImage; 52 import java.io.BufferedInputStream; 53 import java.io.File; 54 import java.io.FileInputStream; 55 import java.io.FileNotFoundException; 56 import java.io.IOException; 57 import java.io.InputStream; 58 import java.text.AttributedCharacterIterator; 59 import java.util.ArrayList; 60 import java.util.List; 61 import java.util.Map; 62 import java.util.MissingResourceException; 63 import java.util.TreeMap; 64 65 import javax.xml.parsers.DocumentBuilder; 66 import javax.xml.parsers.DocumentBuilderFactory; 67 import javax.xml.parsers.ParserConfigurationException; 68 69 import org.w3c.dom.Document; 70 import org.w3c.dom.Element; 71 import org.w3c.dom.NamedNodeMap; 72 import org.w3c.dom.Node; 73 import org.w3c.dom.NodeList; 74 import org.xml.sax.SAXException; 75 76 /** 77 * This test runs against a test XML file. It opens the fonts and attempts 78 * to shape and layout glyphs. 79 * Note that the test is highly environment dependent- you must have 80 * the same versions of the same fonts available or the test will fail. 81 * 82 * It is similar to letest which is part of ICU. 83 * For reference, here are some reference items: 84 * ICU's test file: 85 * http://source.icu-project.org/repos/icu/icu/trunk/source/test/testdata/letest.xml 86 * ICU's readme for the similar test: 87 * http://source.icu-project.org/repos/icu/icu/trunk/source/test/letest/readme.html 88 * 89 * @bug 8054203 90 * @test 91 * @summary manual test of layout engine behavior. Takes an XML control file. 92 * @compile TestLayoutVsICU.java 93 * @author srl 94 * @run main/manual 95 */ 96 public class TestLayoutVsICU { 97 98 public static boolean OPT_DRAW = false; 99 public static boolean OPT_VERBOSE = false; 100 public static boolean OPT_FAILMISSING = false; 101 public static boolean OPT_NOTHROW= false; // if true - don't stop on failure 102 103 public static int docs = 0; // # docs processed 104 public static int skipped = 0; // cases skipped due to bad font 105 public static int total = 0; // cases processed 106 public static int bad = 0; // cases with errs 107 108 public static final String XML_LAYOUT_TESTS = "layout-tests"; // top level 109 public static final String XML_TEST_CASE = "test-case"; 110 public static final String XML_TEST_FONT = "test-font"; 111 public static final String XML_TEST_TEXT = "test-text"; 112 public static final String XML_RESULT_GLYPHS = "result-glyphs"; 113 public static final String XML_ID = "id"; 114 public static final String XML_SCRIPT = "script"; 115 public static final String XML_NAME = "name"; 116 public static final String XML_VERSION = "version"; 117 public static final String XML_CHECKSUM = "checksum"; 118 public static final String XML_RESULT_INDICES = "result-indices"; 119 public static final String XML_RESULT_POSITIONS = "result-positions"; 120 121 /** 122 * @param args 123 * @throws IOException 124 * @throws SAXException 125 * @throws ParserConfigurationException 126 */ main(String[] args)127 public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException { 128 System.out.println("Java " + System.getProperty("java.version") + " from " + System.getProperty("java.vendor")); 129 TestLayoutVsICU tlvi = null; 130 for(String arg : args) { 131 if(arg.equals("-d")) { 132 OPT_DRAW = true; 133 } else if(arg.equals("-n")) { 134 OPT_NOTHROW = true; 135 } else if(arg.equals("-v")) { 136 OPT_VERBOSE = true; 137 } else if(arg.equals("-f")) { 138 OPT_FAILMISSING = true; 139 } else { 140 if(tlvi == null) { 141 tlvi = new TestLayoutVsICU(); 142 } 143 try { 144 tlvi.show(arg); 145 } finally { 146 if(OPT_VERBOSE) { 147 System.out.println("# done with " + arg); 148 } 149 } 150 } 151 } 152 153 if(tlvi == null) { 154 throw new IllegalArgumentException("No XML input. Usage: " + TestLayoutVsICU.class.getSimpleName() + " [-d][-v][-f] letest.xml ..."); 155 } else { 156 System.out.println("\n\nRESULTS:\n"); 157 System.out.println(skipped+"\tskipped due to missing font"); 158 System.out.println(total+"\ttested of which:"); 159 System.out.println(bad+"\twere bad"); 160 161 if(bad>0) { 162 throw new InternalError("One or more failure(s)"); 163 } 164 } 165 } 166 167 String id; 168 show(String arg)169 private void show(String arg) throws ParserConfigurationException, SAXException, IOException { 170 id = "<none>"; 171 File xmlFile = new File(arg); 172 if(!xmlFile.exists()) { 173 throw new FileNotFoundException("Can't open input XML file " + arg); 174 } 175 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 176 DocumentBuilder db = dbf.newDocumentBuilder(); 177 if(OPT_VERBOSE) { 178 System.out.println("# Parsing " + xmlFile.getAbsolutePath()); 179 } 180 Document doc = db.parse(xmlFile); 181 Element e = doc.getDocumentElement(); 182 if(!XML_LAYOUT_TESTS.equals(e.getNodeName())) { 183 throw new IllegalArgumentException("Document " + xmlFile.getAbsolutePath() + " does not have <layout-tests> as its base"); 184 } 185 186 NodeList testCases = e.getElementsByTagName(XML_TEST_CASE); 187 for(int caseNo=0;caseNo<testCases.getLength();caseNo++) { 188 final Node testCase = testCases.item(caseNo); 189 final Map<String,String> testCaseAttrs = attrs(testCase); 190 id = testCaseAttrs.get(XML_ID); 191 final String script = testCaseAttrs.get(XML_SCRIPT); 192 String testText = null; 193 Integer[] expectGlyphs = null; 194 Integer[] expectIndices = null; 195 Map<String,String> fontAttrs = null; 196 if(OPT_VERBOSE) { 197 System.out.println("#"+caseNo+" id="+id + ", script="+script); 198 } 199 NodeList children = testCase.getChildNodes(); 200 for(int sub=0;sub<children.getLength();sub++) { 201 Node n = children.item(sub); 202 if(n.getNodeType()!=Node.ELEMENT_NODE) continue; 203 String nn = n.getNodeName(); 204 if(nn.equals(XML_TEST_FONT)) { 205 fontAttrs = attrs(n); 206 } else if(nn.equals(XML_TEST_TEXT)) { 207 testText = n.getTextContent(); 208 } else if(nn.equals(XML_RESULT_GLYPHS)) { 209 String hex = n.getTextContent(); 210 expectGlyphs = parseHexArray(hex); 211 } else if(nn.equals(XML_RESULT_INDICES)) { 212 String hex = n.getTextContent(); 213 expectIndices = parseHexArray(hex); 214 } else if(OPT_VERBOSE) { 215 System.out.println("Ignoring node " + nn); 216 } 217 } 218 if(fontAttrs == null) { 219 throw new IllegalArgumentException(id + " Missing node " + XML_TEST_FONT); 220 } 221 if(testText == null) { 222 throw new IllegalArgumentException(id + " Missing node " + XML_TEST_TEXT); 223 } 224 225 String fontName = fontAttrs.get(XML_NAME); 226 Font f = getFont(fontName, fontAttrs); 227 if(f==null) { 228 if(OPT_FAILMISSING) { 229 throw new MissingResourceException("Missing font, abort test", Font.class.getName(), fontName); 230 } 231 System.out.println("Skipping " + id + " because font is missing: " + fontName); 232 skipped++; 233 continue; 234 } 235 FontRenderContext frc = new FontRenderContext(null, true, true); 236 TextLayout tl = new TextLayout(testText,f,frc); 237 final List<GlyphVector> glyphs = new ArrayList<GlyphVector>(); 238 Graphics2D myg2 = new Graphics2D(){ 239 240 @Override 241 public void draw(Shape s) { 242 // TODO Auto-generated method stub 243 244 } 245 246 @Override 247 public boolean drawImage(Image img, AffineTransform xform, 248 ImageObserver obs) { 249 // TODO Auto-generated method stub 250 return false; 251 } 252 253 @Override 254 public void drawImage(BufferedImage img, 255 BufferedImageOp op, int x, int y) { 256 // TODO Auto-generated method stub 257 258 } 259 260 @Override 261 public void drawRenderedImage(RenderedImage img, 262 AffineTransform xform) { 263 // TODO Auto-generated method stub 264 265 } 266 267 @Override 268 public void drawRenderableImage(RenderableImage img, 269 AffineTransform xform) { 270 // TODO Auto-generated method stub 271 272 } 273 274 @Override 275 public void drawString(String str, int x, int y) { 276 // TODO Auto-generated method stub 277 278 } 279 280 @Override 281 public void drawString(String str, float x, float y) { 282 // TODO Auto-generated method stub 283 284 } 285 286 @Override 287 public void drawString( 288 AttributedCharacterIterator iterator, int x, int y) { 289 // TODO Auto-generated method stub 290 291 } 292 293 @Override 294 public void drawString( 295 AttributedCharacterIterator iterator, float x, 296 float y) { 297 // TODO Auto-generated method stub 298 299 } 300 301 @Override 302 public void drawGlyphVector(GlyphVector g, float x, float y) { 303 if(x!=0.0 || y!=0.0) { 304 throw new InternalError("x,y should be 0 but got " + x+","+y); 305 } 306 //System.err.println("dGV : " + g.toString() + " @ "+x+","+y); 307 glyphs.add(g); 308 } 309 310 @Override 311 public void fill(Shape s) { 312 // TODO Auto-generated method stub 313 314 } 315 316 @Override 317 public boolean hit(Rectangle rect, Shape s, boolean onStroke) { 318 // TODO Auto-generated method stub 319 return false; 320 } 321 322 @Override 323 public GraphicsConfiguration getDeviceConfiguration() { 324 // TODO Auto-generated method stub 325 return null; 326 } 327 328 @Override 329 public void setComposite(Composite comp) { 330 // TODO Auto-generated method stub 331 332 } 333 334 @Override 335 public void setPaint(Paint paint) { 336 // TODO Auto-generated method stub 337 338 } 339 340 @Override 341 public void setStroke(Stroke s) { 342 // TODO Auto-generated method stub 343 344 } 345 346 @Override 347 public void setRenderingHint(Key hintKey, Object hintValue) { 348 // TODO Auto-generated method stub 349 350 } 351 352 @Override 353 public Object getRenderingHint(Key hintKey) { 354 // TODO Auto-generated method stub 355 return null; 356 } 357 358 @Override 359 public void setRenderingHints(Map<?, ?> hints) { 360 // TODO Auto-generated method stub 361 362 } 363 364 @Override 365 public void addRenderingHints(Map<?, ?> hints) { 366 // TODO Auto-generated method stub 367 368 } 369 370 @Override 371 public RenderingHints getRenderingHints() { 372 // TODO Auto-generated method stub 373 return null; 374 } 375 376 @Override 377 public void translate(int x, int y) { 378 // TODO Auto-generated method stub 379 380 } 381 382 @Override 383 public void translate(double tx, double ty) { 384 // TODO Auto-generated method stub 385 386 } 387 388 @Override 389 public void rotate(double theta) { 390 // TODO Auto-generated method stub 391 392 } 393 394 @Override 395 public void rotate(double theta, double x, double y) { 396 // TODO Auto-generated method stub 397 398 } 399 400 @Override 401 public void scale(double sx, double sy) { 402 // TODO Auto-generated method stub 403 404 } 405 406 @Override 407 public void shear(double shx, double shy) { 408 // TODO Auto-generated method stub 409 410 } 411 412 @Override 413 public void transform(AffineTransform Tx) { 414 // TODO Auto-generated method stub 415 416 } 417 418 @Override 419 public void setTransform(AffineTransform Tx) { 420 // TODO Auto-generated method stub 421 422 } 423 424 @Override 425 public AffineTransform getTransform() { 426 // TODO Auto-generated method stub 427 return null; 428 } 429 430 @Override 431 public Paint getPaint() { 432 // TODO Auto-generated method stub 433 return null; 434 } 435 436 @Override 437 public Composite getComposite() { 438 // TODO Auto-generated method stub 439 return null; 440 } 441 442 @Override 443 public void setBackground(Color color) { 444 // TODO Auto-generated method stub 445 446 } 447 448 @Override 449 public Color getBackground() { 450 // TODO Auto-generated method stub 451 return null; 452 } 453 454 @Override 455 public Stroke getStroke() { 456 // TODO Auto-generated method stub 457 return null; 458 } 459 460 @Override 461 public void clip(Shape s) { 462 // TODO Auto-generated method stub 463 464 } 465 466 @Override 467 public FontRenderContext getFontRenderContext() { 468 // TODO Auto-generated method stub 469 return null; 470 } 471 472 @Override 473 public Graphics create() { 474 // TODO Auto-generated method stub 475 return null; 476 } 477 478 @Override 479 public Color getColor() { 480 // TODO Auto-generated method stub 481 return null; 482 } 483 484 @Override 485 public void setColor(Color c) { 486 // TODO Auto-generated method stub 487 488 } 489 490 @Override 491 public void setPaintMode() { 492 // TODO Auto-generated method stub 493 494 } 495 496 @Override 497 public void setXORMode(Color c1) { 498 // TODO Auto-generated method stub 499 500 } 501 502 @Override 503 public Font getFont() { 504 // TODO Auto-generated method stub 505 return null; 506 } 507 508 @Override 509 public void setFont(Font font) { 510 // TODO Auto-generated method stub 511 512 } 513 514 @Override 515 public FontMetrics getFontMetrics(Font f) { 516 // TODO Auto-generated method stub 517 return null; 518 } 519 520 @Override 521 public Rectangle getClipBounds() { 522 // TODO Auto-generated method stub 523 return null; 524 } 525 526 @Override 527 public void clipRect(int x, int y, int width, int height) { 528 // TODO Auto-generated method stub 529 530 } 531 532 @Override 533 public void setClip(int x, int y, int width, int height) { 534 // TODO Auto-generated method stub 535 536 } 537 538 @Override 539 public Shape getClip() { 540 // TODO Auto-generated method stub 541 return null; 542 } 543 544 @Override 545 public void setClip(Shape clip) { 546 // TODO Auto-generated method stub 547 548 } 549 550 @Override 551 public void copyArea(int x, int y, int width, int height, 552 int dx, int dy) { 553 // TODO Auto-generated method stub 554 555 } 556 557 @Override 558 public void drawLine(int x1, int y1, int x2, int y2) { 559 // TODO Auto-generated method stub 560 561 } 562 563 @Override 564 public void fillRect(int x, int y, int width, int height) { 565 // TODO Auto-generated method stub 566 567 } 568 569 @Override 570 public void clearRect(int x, int y, int width, int height) { 571 // TODO Auto-generated method stub 572 573 } 574 575 @Override 576 public void drawRoundRect(int x, int y, int width, 577 int height, int arcWidth, int arcHeight) { 578 // TODO Auto-generated method stub 579 580 } 581 582 @Override 583 public void fillRoundRect(int x, int y, int width, 584 int height, int arcWidth, int arcHeight) { 585 // TODO Auto-generated method stub 586 587 } 588 589 @Override 590 public void drawOval(int x, int y, int width, int height) { 591 // TODO Auto-generated method stub 592 593 } 594 595 @Override 596 public void fillOval(int x, int y, int width, int height) { 597 // TODO Auto-generated method stub 598 599 } 600 601 @Override 602 public void drawArc(int x, int y, int width, int height, 603 int startAngle, int arcAngle) { 604 // TODO Auto-generated method stub 605 606 } 607 608 @Override 609 public void fillArc(int x, int y, int width, int height, 610 int startAngle, int arcAngle) { 611 // TODO Auto-generated method stub 612 613 } 614 615 @Override 616 public void drawPolyline(int[] xPoints, int[] yPoints, 617 int nPoints) { 618 // TODO Auto-generated method stub 619 620 } 621 622 @Override 623 public void drawPolygon(int[] xPoints, int[] yPoints, 624 int nPoints) { 625 // TODO Auto-generated method stub 626 627 } 628 629 @Override 630 public void fillPolygon(int[] xPoints, int[] yPoints, 631 int nPoints) { 632 // TODO Auto-generated method stub 633 634 } 635 636 @Override 637 public boolean drawImage(Image img, int x, int y, 638 ImageObserver observer) { 639 // TODO Auto-generated method stub 640 return false; 641 } 642 643 @Override 644 public boolean drawImage(Image img, int x, int y, 645 int width, int height, ImageObserver observer) { 646 // TODO Auto-generated method stub 647 return false; 648 } 649 650 @Override 651 public boolean drawImage(Image img, int x, int y, 652 Color bgcolor, ImageObserver observer) { 653 // TODO Auto-generated method stub 654 return false; 655 } 656 657 @Override 658 public boolean drawImage(Image img, int x, int y, 659 int width, int height, Color bgcolor, 660 ImageObserver observer) { 661 // TODO Auto-generated method stub 662 return false; 663 } 664 665 @Override 666 public boolean drawImage(Image img, int dx1, int dy1, 667 int dx2, int dy2, int sx1, int sy1, int sx2, 668 int sy2, ImageObserver observer) { 669 // TODO Auto-generated method stub 670 return false; 671 } 672 673 @Override 674 public boolean drawImage(Image img, int dx1, int dy1, 675 int dx2, int dy2, int sx1, int sy1, int sx2, 676 int sy2, Color bgcolor, ImageObserver observer) { 677 // TODO Auto-generated method stub 678 return false; 679 } 680 681 @Override 682 public void dispose() { 683 // TODO Auto-generated method stub 684 685 } 686 687 }; 688 tl.draw(myg2, 0, 0); 689 if(glyphs.size() != 1) { 690 err("drew " + glyphs.size() + " times - expected 1"); 691 total++; 692 bad++; 693 continue; 694 } 695 boolean isBad = false; 696 GlyphVector gv = glyphs.get(0); 697 698 // GLYPHS 699 int gotGlyphs[] = gv.getGlyphCodes(0, gv.getNumGlyphs(), new int[gv.getNumGlyphs()]); 700 701 int count = Math.min(gotGlyphs.length, expectGlyphs.length); // go up to this count 702 703 for(int i=0;i<count;i++) { 704 if(gotGlyphs[i]!=expectGlyphs[i]) { 705 err("@"+i+" - got \tglyph 0x" + Integer.toHexString(gotGlyphs[i]) + " wanted 0x" + Integer.toHexString(expectGlyphs[i])); 706 isBad=true; 707 break; 708 } 709 } 710 711 // INDICES 712 int gotIndices[] = gv.getGlyphCharIndices(0, gv.getNumGlyphs(), new int[gv.getNumGlyphs()]); 713 for(int i=0;i<count;i++) { 714 if(gotIndices[i]!=expectIndices[i]) { 715 err("@"+i+" - got \tindex 0x" + Integer.toHexString(gotGlyphs[i]) + " wanted 0x" + Integer.toHexString(expectGlyphs[i])); 716 isBad=true; 717 break; 718 } 719 } 720 721 722 // COUNT 723 if(gotGlyphs.length != expectGlyphs.length) { 724 System.out.println("Got " + gotGlyphs.length + " wanted " + expectGlyphs.length + " glyphs"); 725 isBad=true; 726 } else { 727 if(OPT_VERBOSE) { 728 System.out.println(">> OK: " + gotGlyphs.length + " glyphs"); 729 } 730 } 731 732 733 if(isBad) { 734 bad++; 735 System.out.println("* FAIL: " + id + " /\t" + fontName); 736 } else { 737 System.out.println("* OK : " + id + " /\t" + fontName); 738 } 739 total++; 740 } 741 } 742 743 verifyFont(File f, Map<String, String> fontAttrs)744 private boolean verifyFont(File f, Map<String, String> fontAttrs) { 745 InputStream fis = null; 746 String fontName = fontAttrs.get(XML_NAME); 747 int count=0; 748 try { 749 fis = new BufferedInputStream(new FileInputStream(f)); 750 751 int i = 0; 752 int r; 753 try { 754 while((r=fis.read())!=-1) { 755 i+=(int)r; 756 count++; 757 } 758 } catch (IOException e) { 759 // TODO Auto-generated catch block 760 e.printStackTrace(); 761 return false; 762 } 763 if(OPT_VERBOSE) { 764 System.out.println("for " + f.getAbsolutePath() + " chks = 0x" + Integer.toHexString(i) + " size=" + count); 765 } 766 String theirStr = fontAttrs.get("rchecksum"); 767 768 String ourStr = Integer.toHexString(i).toLowerCase(); 769 770 if(theirStr!=null) { 771 if(theirStr.startsWith("0x")) { 772 theirStr = theirStr.substring(2).toLowerCase(); 773 } else { 774 theirStr = theirStr.toLowerCase(); 775 } 776 long theirs = Integer.parseInt(theirStr, 16); 777 if(theirs != i) { 778 err("WARNING: rchecksum for " + fontName + " was " + i + " (0x"+ourStr+") "+ " but file said " + theirs +" (0x"+theirStr+") - perhaps a different font?"); 779 return false; 780 } else { 781 if(OPT_VERBOSE) { 782 System.out.println(" rchecksum for " + fontName + " OK"); 783 } 784 return true; 785 } 786 } else { 787 //if(OPT_VERBOSE) { 788 System.err.println("WARNING: rchecksum for " + fontName + " was " + i + " (0x"+ourStr+") "+ " but rchecksum was MISSING. Old ICU data?"); 789 //} 790 } 791 } catch (FileNotFoundException e) { 792 // TODO Auto-generated catch block 793 e.printStackTrace(); 794 return false; 795 } finally { 796 try { 797 fis.close(); 798 } catch (IOException e) { 799 // TODO Auto-generated catch block 800 e.printStackTrace(); 801 } 802 } 803 return true; 804 } 805 806 parseHexArray(String hex)807 private Integer[] parseHexArray(String hex) { 808 List<Integer> ret = new ArrayList<Integer>(); 809 String items[] = hex.split("[\\s,]"); 810 for(String i : items) { 811 if(i.isEmpty()) continue; 812 if(i.startsWith("0x")) { 813 i = i.substring(2); 814 } 815 ret.add(Integer.parseInt(i, 16)); 816 } 817 return ret.toArray(new Integer[0]); 818 } 819 820 err(String string)821 private void err(String string) { 822 if(OPT_NOTHROW) { 823 System.out.println(id+" ERROR: " + string +" (continuing due to -n)"); 824 } else { 825 throw new InternalError(id+ ": " + string); 826 } 827 } 828 829 getFont(String fontName, Map<String, String> fontAttrs)830 private Font getFont(String fontName, Map<String, String> fontAttrs) { 831 Font f; 832 if(false) 833 try { 834 f = Font.getFont(fontName); 835 if(f!=null) { 836 if(OPT_VERBOSE) { 837 System.out.println("Loaded default path to " + fontName); 838 } 839 return f; 840 } 841 } catch(Throwable t) { 842 if(OPT_VERBOSE) { 843 t.printStackTrace(); 844 System.out.println("problem loading font " + fontName + " - " + t.toString()); 845 } 846 } 847 848 File homeDir = new File(System.getProperty("user.home")); 849 File fontDir = new File(homeDir, "fonts"); 850 File fontFile = new File(fontDir, fontName); 851 //System.out.println("## trying " + fontFile.getAbsolutePath()); 852 if(fontFile.canRead()) { 853 try { 854 if(!verifyFont(fontFile,fontAttrs)) { 855 System.out.println("Warning: failed to verify " + fontName); 856 } 857 f = Font.createFont(Font.TRUETYPE_FONT, fontFile); 858 if(f!=null & OPT_VERBOSE) { 859 System.out.println("> loaded from " + fontFile.getAbsolutePath() + " - " + f.toString()); 860 } 861 return f; 862 } catch (FontFormatException e) { 863 if(OPT_VERBOSE) { 864 e.printStackTrace(); 865 System.out.println("problem loading font " + fontName + " - " + e.toString()); 866 } 867 } catch (IOException e) { 868 if(OPT_VERBOSE) { 869 e.printStackTrace(); 870 System.out.println("problem loading font " + fontName + " - " + e.toString()); 871 } 872 } 873 } 874 return null; 875 } 876 877 attrs(Node testCase)878 private static Map<String, String> attrs(Node testCase) { 879 Map<String,String> rv = new TreeMap<String,String>(); 880 NamedNodeMap nnm = testCase.getAttributes(); 881 for(int i=0;i<nnm.getLength();i++) { 882 Node n = nnm.item(i); 883 String k = n.getNodeName(); 884 String v = n.getNodeValue(); 885 rv.put(k, v); 886 } 887 return rv; 888 } 889 } 890