1 4 5 9 10 package org.openlaszlo.compiler; 11 12 import java.io.*; 13 import java.text.DecimalFormat ; 14 import java.text.FieldPosition ; 15 import java.util.*; 16 17 import org.openlaszlo.css.CSSParser; 18 import org.openlaszlo.sc.ScriptCompiler; 19 import org.openlaszlo.server.LPS; 20 import org.openlaszlo.xml.internal.Schema; 21 import org.openlaszlo.xml.internal.MissingAttributeException; 22 import org.openlaszlo.utils.ChainedException; 23 import org.openlaszlo.xml.internal.XMLUtils; 24 import org.apache.log4j.*; 25 import org.apache.oro.text.regex.*; 26 import org.openlaszlo.compiler.ViewSchema.ColorFormatException; 27 import org.openlaszlo.utils.FileUtils; 28 29 import java.io.*; 30 import java.util.*; 31 import org.jdom.Attribute; 32 import org.jdom.Element; 33 34 45 public class ViewCompiler extends ElementCompiler { 46 private static final int INPUT_TEXTWIDTH_FUDGE_FACTOR = 2; 48 49 private static final String FONTSTYLE_ATTRIBUTE = "fontstyle"; 50 private static final String WHEN_IMMEDIATELY = "immediately"; 51 private static final String WHEN_ONCE = "once"; 52 private static final String WHEN_ALWAYS = "always"; 53 private static final String WHEN_PATH = "path"; 54 55 private ViewSchema mSchema; 56 57 private static Logger mLogger = Logger.getLogger(ViewCompiler.class); 58 private static Logger mTraceLogger = Logger.getLogger("trace.xml"); 59 60 public ViewCompiler(CompilationEnvironment env) { 61 super(env); 62 mSchema = env.getSchema(); 63 mTraceLogger.setLevel(Level.INFO); 64 } 65 66 67 private static final String SERVERLESS_WARNINGS_PROPERTY_FILE = ( 68 LPS.getMiscDirectory() + File.separator + "lzx-server-only-apis.properties" 69 ); 70 private static final Properties sServerOnlyTags = new Properties(); 71 72 static { 73 try { 74 InputStream is = new FileInputStream(SERVERLESS_WARNINGS_PROPERTY_FILE); 75 try { 76 sServerOnlyTags.load(is); 77 } finally { 78 is.close(); 79 } 80 } catch (java.io.IOException e) { 81 mLogger.warn("Can't find server-only APIs config file " + SERVERLESS_WARNINGS_PROPERTY_FILE); 82 } 83 } 84 85 public void compile(Element element) throws CompilationError 86 { 87 preprocess(element, mEnv); 88 FontInfo fontInfo; 89 90 String name = element.getName(); 91 if (name != null 92 && !mEnv.getCanvas().isProxied() 93 && sServerOnlyTags.containsKey(name)) { 94 mEnv.warn("The tag '"+name+"' will not work as expected when used in a serverless application."); 95 } 96 97 fontInfo = new FontInfo(mEnv.getCanvas().getFontInfo()); 101 if (mEnv.getSWFVersion().equals("swf5")) { 102 103 113 collectInputFonts(element, mEnv, fontInfo, new HashSet()); 114 } 115 116 compileXML(element, fontInfo); 117 } 118 119 125 static boolean isElement(Element element) { 126 return true; 127 } 128 129 130 static void collectElementNames(Element element, Set names) { 131 names.add(element.getName()); 132 collectLayoutElement(element, names); 133 for (Iterator iter = element.getChildren().iterator(); 134 iter.hasNext(); ) { 135 collectElementNames((Element) iter.next(), names); 136 } 137 } 138 139 static void collectLayoutElement(Element element, Set names) { 140 if (element.getAttributeValue("layout") != null) { 141 try { 142 Map properties = new CSSParser 143 (new AttributeStream(element, "layout")).Parse(); 144 String layoutClass = (String ) properties.get("class"); 145 if (layoutClass == null) 146 layoutClass = "simplelayout"; 147 names.add(layoutClass); 148 } catch (org.openlaszlo.css.ParseException e) { 149 } catch (org.openlaszlo.css.TokenMgrError e) { 150 } 152 } 153 } 154 155 162 void compileXML(Element element, FontInfo fontInfo) 163 { 164 boolean tracexml = mEnv.getBooleanProperty("trace.xml"); 166 if (tracexml) { 167 mTraceLogger.info("compiling XML:"); 168 org.jdom.output.XMLOutputter outputter = 169 new org.jdom.output.XMLOutputter(); 170 mTraceLogger.info(outputter.outputString(element)); 171 } 172 173 NodeModel model = NodeModel.elementAsModel(element, mSchema, mEnv); 174 model = model.expandClassDefinitions(); 175 String script = VIEW_INSTANTIATION_FNAME + "(" + 176 model.asJavascript() + ", " + model.totalSubnodes() + 177 ");"; 178 179 if (!element.getName().equals("class")) { 181 ((ElementWithLocationInfo) element).model = null; 182 } 183 184 if (tracexml) { 185 mLogger.debug("compiled to:\n" + script + "\n"); 186 } 187 try { 188 mEnv.compileScript(script, element); 189 } catch (CompilationError e) { 190 String solution = SolutionMessages.findSolution(e.getMessage()); 191 e.setSolution(solution); 192 throw e; 193 } 194 } 195 196 207 static void preprocess(Element elt, CompilationEnvironment env) { 208 compileResources(elt, env); 209 compileClickResources(elt, env); 210 compileAttributes(elt, env); 211 } 212 213 217 static void compileAttributes(Element elt, CompilationEnvironment env) { 218 if (elt.getName().equals("dataset")) { 219 String src = elt.getAttributeValue("src"); 220 if (src == null) { 221 return; 226 } 227 src = env.adjustRelativeURL(src, elt); 228 elt.setAttribute("src", src); 229 } 230 Iterator iter; 231 for (iter = elt.getChildren().iterator(); iter.hasNext(); ) { 232 compileAttributes((Element)iter.next(), env); 233 } 234 } 235 236 static HashMap sUnsupportedServerlessFiletypes = new HashMap(); 237 { 238 sUnsupportedServerlessFiletypes.put("gif", "true"); 239 sUnsupportedServerlessFiletypes.put("bmp", "true"); 240 sUnsupportedServerlessFiletypes.put("png", "true"); 241 sUnsupportedServerlessFiletypes.put("tiff", "true"); 242 sUnsupportedServerlessFiletypes.put("tif", "true"); 243 sUnsupportedServerlessFiletypes.put("wmf", "true"); 244 sUnsupportedServerlessFiletypes.put("wmv", "true"); 245 } 246 247 static void checkUnsupportedMediaTypes(CompilationEnvironment env, Element elt, String url) { 248 String suffix = FileUtils.getExtension(url); 249 if (sUnsupportedServerlessFiletypes.containsKey(suffix.toLowerCase())) { 250 env.warn("The runtime loadable resource type '"+url+" is not supported by the Flash runtime. Supported resource types are JPEG (non-interlaced), SWF, and MP3", elt); 251 } 252 } 253 254 260 static void compileResources(Element elt, 261 CompilationEnvironment env) { 262 final String RESOURCE_ATTR_NAME = "resource"; 263 264 for (Iterator iter = elt.getChildren().iterator(); 266 iter.hasNext(); ) { 267 Element child = (Element) iter.next(); 268 if (child.getName().equals("attribute") && 269 RESOURCE_ATTR_NAME.equals(child.getAttributeValue("name"))) { 270 String val = child.getAttributeValue("value"); 271 if (val == null) { 273 continue; 274 } else { 275 String val2 = elt.getAttributeValue(RESOURCE_ATTR_NAME); 276 if (val2 != null) { 277 env.warn("The resource attribute on this view was declared more than once, as '"+val2+"', and as '"+val+"'", elt); 278 } 279 280 String when = child.getAttributeValue("when"); 283 if (when != null) { 284 val = "$" + when + "{" + val + "}"; 285 } 286 287 elt.setAttribute(RESOURCE_ATTR_NAME, val); 288 iter.remove(); 292 } 293 } 294 } 295 296 String value = elt.getAttributeValue(RESOURCE_ATTR_NAME); 297 298 if (value != null) { 299 if (value.startsWith("$(")) { 300 env.warn( 301 "The syntax '$(...)' is not valid, " 302 + "you probably meant to use curly-braces instead '${...}'", elt); 303 } else if (value.startsWith("$") && value.endsWith("}")) { 304 } else if (ScriptCompiler.isIdentifier(value)) { 308 Set resourceNames = env.getResourceNames(); 310 if (!resourceNames.contains(value)) { 311 env.addResourceReference(value, elt); 314 } 315 } else if (XMLUtils.isURL(value)) { 316 if (!env.getCanvas().isProxied()) { 317 checkUnsupportedMediaTypes(env, elt, value); 318 } 319 value = env.adjustRelativeURL(value, elt); 321 try { 325 java.net.URL url = new java.net.URL (value); 326 if (url.getHost().equals("") && !url.getPath().startsWith("/")) { 327 value = url.getPath(); 328 if (url.getQuery() != null && url.getQuery().length() > 0) { 329 value += "?" + url.getQuery(); 330 } 331 } 332 } catch (java.net.MalformedURLException e) { 333 throw new ChainedException(e); 334 } 335 elt.removeAttribute(RESOURCE_ATTR_NAME); 336 elt.setAttribute("source", ScriptCompiler.quote(value)); 337 338 } else { 339 Element info = new Element("resolve"); 341 info.setAttribute("src", elt.getAttributeValue(RESOURCE_ATTR_NAME)); 342 343 File file = env.resolveReference(elt, RESOURCE_ATTR_NAME); 344 Element rinfo = new Element("resolve"); 345 rinfo.setAttribute("src", elt.getAttributeValue(RESOURCE_ATTR_NAME)); 346 rinfo.setAttribute("pathname", file.getPath()); 347 env.getCanvas().addInfo(rinfo); 348 try { 352 value = env.getResourceGenerator().importResource(file); 353 } catch (SWFWriter.ImportResourceError e) { 354 env.warn(e, elt); 355 } 356 elt.setAttribute(RESOURCE_ATTR_NAME, value); 357 358 try { 359 info.setAttribute("pathname", file.getCanonicalPath()); 360 } catch (java.io.IOException ioe) { 361 mLogger.warn("Can't canonicalize " + file.toString()); 362 } 363 env.getCanvas().addInfo(info); 364 } 365 } 366 367 Iterator iter; 369 for (iter = elt.getChildren().iterator(); 370 iter.hasNext(); ) { 371 compileResources((Element) iter.next(), env); 372 } 373 } 374 375 static void compileClickResources(Element elt, 376 CompilationEnvironment env) { 377 final String ATTR_NAME = "clickregion"; 378 String value = elt.getAttributeValue(ATTR_NAME); 379 380 if (value != null) { 381 if (value.startsWith("$(") || 382 (value.startsWith("$") && value.endsWith("}")) || 383 ScriptCompiler.isIdentifier(value) || 384 XMLUtils.isURL(value)) { 385 env.warn("The value of the " + ATTR_NAME + "attribute" + 386 "must be a file name.", elt); 387 } else { 388 File file = env.resolveReference(elt, ATTR_NAME); 390 try { 391 value = env.getResourceGenerator().importClickResource(file); 392 } catch (SWFWriter.ImportResourceError e) { 393 env.warn(e, elt); 394 } 395 elt.setAttribute(ATTR_NAME, value); 396 } 397 } 398 399 Iterator iter; 401 for (iter = elt.getChildren().iterator(); 402 iter.hasNext(); ) { 403 compileClickResources((Element) iter.next(), env); 404 } 405 } 406 407 static void checkUnresolvedResourceReferences (CompilationEnvironment env) { 408 Map refs = env.resourceReferences(); 409 Set resourceNames = env.getResourceNames(); 410 for (Iterator iter = refs.keySet().iterator(); 411 iter.hasNext(); ) { 412 String resourceId = (String ) iter.next(); 413 Element elt = (Element) refs.get(resourceId); 414 if (!resourceNames.contains(resourceId)) { 415 env.warn("The resource named '"+resourceId+"' has not been declared", elt); 416 } 417 } 418 } 419 420 423 protected static void mergeClassFontInfo (Element elt, FontInfo fontInfo, 424 CompilationEnvironment env) { 425 String classname = elt.getName(); 426 FontInfo cachedInfo = env.getClassFontInfo(classname); 428 if (cachedInfo != null) { 429 fontInfo.mergeFontInfoFrom(cachedInfo); 430 return; 431 } 432 433 ViewSchema schema = env.getSchema(); 434 ClassModel classinfo = schema.getClassModel(classname); 435 if (classinfo == null || classinfo.definition == null) { 436 return; 437 } 438 439 Vector parents = new Vector(); 441 ClassModel lzxclass = classinfo; 442 while (lzxclass != null) { 444 parents.insertElementAt(lzxclass, 0); 445 lzxclass = lzxclass.superclass; 446 } 447 448 FontInfo cinfo = FontInfo.blankFontInfo(); 450 451 while (parents.size() > 0) { 453 lzxclass = (ClassModel) parents.firstElement(); 454 parents.removeElementAt(0); mergeClassFontInfo(lzxclass, cinfo); 456 } 457 458 env.addClassFontInfo(classname, cinfo); 459 fontInfo.mergeFontInfoFrom(cinfo); 461 } 462 463 466 protected static void mergeClassFontInfo (ClassModel classinfo, 467 FontInfo fontInfo) { 468 if (classinfo != null && classinfo.definition != null) { 469 Element celt = classinfo.definition; 470 mergeFontInfo(celt, fontInfo); 471 mergeWidth(fontInfo, getAttributeValue(celt, "width")); 474 mergeHeight(fontInfo, getAttributeValue(celt, "height")); 475 } 476 } 477 478 492 protected void mapTextMetricsCompilation(Element elt, 493 CompilationEnvironment env, 494 FontInfo fontInfo, 495 Set classList) { 496 497 classList = new HashSet(classList); 498 499 fontInfo = new FontInfo(fontInfo); 501 502 mergeClassFontInfo (elt, fontInfo, env); 504 mergeFontInfo(elt, fontInfo); 506 507 FontManager fmgr = env.getGenerator().getFontManager(); 508 String fontName = fontInfo.getName(); 509 if (env.getSWFVersion().equals("swf5") && 510 (fmgr.getFontFamily(fontInfo.getName()) == null) && 511 (!env.getGenerator().isDeviceFont(fontName)) && 512 !(env.getCanvas().defaultFont.equals(fontName))) { 513 env.warn("Font '" 514 + fontName 515 + "' used but not defined", elt); 516 } 517 518 if ((fmgr.getFontFamily(fontInfo.getName()) != null) && 519 fontInfo.isFullySpecified() && 520 (mSchema.hasHTMLContent(elt) || mSchema.hasTextContent(elt))) { 521 compileTextMetrics(elt, env, fontInfo); 522 } 523 ClassModel classinfo = env.getSchema().getClassModel(elt.getName()); 524 525 if (classinfo != null && classinfo.definition != null) { 528 if (classList.contains(elt.getName().intern())) { 531 return; 532 } 533 for (Iterator iter = classinfo.definition.getChildren().iterator(); iter.hasNext(); 534 ) { 535 Element e = (Element) iter.next(); 536 String ename = e.getName(); 537 if (!(ename.equals("method") || ename.equals("attribute"))) { 538 classList.add(classinfo.className.intern()); 542 mapTextMetricsCompilation(e, env, fontInfo, classList); 543 } 544 } 545 } 546 547 for (Iterator iter = elt.getChildren().iterator(); iter.hasNext(); 549 ) { 550 Element e = (Element) iter.next(); 551 mapTextMetricsCompilation(e, env, fontInfo, classList); 552 } 553 } 554 555 557 protected static void mergeFontAttributes (Element elt, FontInfo fontInfo) { 558 String myfont = getAttributeValue(elt, "font"); 559 if (myfont != null) { 560 if (matchesPattern(myfont, sFontNamePat)) { 561 fontInfo.setName(myfont); 562 } else { 563 fontInfo.setName(FontInfo.NULL_FONT); 565 } 566 } 567 568 String mysize = getAttributeValue(elt, "fontsize"); 569 if (mysize != null) { 570 if (matchesPattern(mysize, sFontSizePat)) { 571 fontInfo.setSize(mysize); 572 } else { 573 fontInfo.setSize(FontInfo.NULL_SIZE); 576 } 577 } 578 579 String mystyle = getAttributeValue(elt, NodeModel.FONTSTYLE_ATTRIBUTE); 580 if (mystyle != null) { 581 if (matchesPattern(mystyle, sFontstylePat)) { 582 fontInfo.setStyle(mystyle); 583 } else { 584 fontInfo.setStyleBits(FontInfo.NULL_STYLE); 586 } 587 } 588 } 589 590 595 private static void mergeFontInfo(Element elt, FontInfo fontInfo) { 596 mergeFontAttributes(elt, fontInfo); 597 598 String resizable = getAttributeValue(elt, "resizable"); 600 if ("true".equals(resizable)) { 601 fontInfo.resizable = FontInfo.FONTINFO_TRUE; 602 } else if ("false".equals(resizable)) { 603 fontInfo.resizable = FontInfo.FONTINFO_FALSE; 604 } 605 606 String multiline = getAttributeValue(elt, "multiline"); 608 if ("true".equals(multiline)) { 609 fontInfo.multiline = FontInfo.FONTINFO_TRUE; 610 } else if ("false".equals(multiline)) { 611 fontInfo.multiline = FontInfo.FONTINFO_FALSE; 612 } 613 } 614 615 622 protected static void mergeWidth(FontInfo fontInfo, String width) { 623 if (width != null) { 624 int val = evalWidth(fontInfo, width); 625 fontInfo.setWidth(val); 626 } 627 } 628 629 protected static void mergeHeight(FontInfo fontInfo, String height) { 630 if (height != null) { 631 int val = evalHeight(fontInfo, height); 632 fontInfo.setHeight(val); 633 } 634 } 635 636 637 653 protected static int evalWidth(FontInfo fontInfo, String width) { 654 if (width == null) { 655 return FontInfo.NULL_SIZE; 656 } 657 658 if (matchesPattern(width, sConstPat)) { 659 return Integer.parseInt(width); 660 } else if (matchesPattern(width, sParentWidthPat)) { 661 if (fontInfo.getWidth() == FontInfo.NULL_SIZE) { 664 return FontInfo.NULL_SIZE; 665 } 666 String operator = sMatcher.getMatch().group(3); 668 if (operator.equals("")) { 669 operator = "+"; 670 } 671 672 int arg = 0; 673 String argstr = sMatcher.getMatch().group(4); 674 try { 675 if (argstr != null) { 676 arg = Integer.parseInt(argstr); 677 } 678 } catch (NumberFormatException e) {} 679 if (operator.equals("+")) { 680 return (fontInfo.getWidth() + arg); 681 } else if (operator.equals("-")) { 682 return (fontInfo.getWidth() - arg); 683 } else { 684 throw new CompilationError("Unknown operator in width attribute: "+operator); 685 } 686 } else { 687 return FontInfo.NULL_SIZE; 690 } 691 } 692 693 protected static int evalHeight(FontInfo fontInfo, String height) { 694 if (height == null) { 695 return FontInfo.NULL_SIZE; 696 } 697 698 if (matchesPattern(height, sConstPat)) { 699 return Integer.parseInt(height); 700 } else if (matchesPattern(height, sParentHeightPat)) { 701 if (fontInfo.getHeight() == FontInfo.NULL_SIZE) { 704 return FontInfo.NULL_SIZE; 705 } 706 String operator = sMatcher.getMatch().group(3); 708 if (operator.equals("")) { 709 operator = "+"; 710 } 711 712 int arg = 0; 713 String argstr = sMatcher.getMatch().group(4); 714 try { 715 if (argstr != null) { 716 arg = Integer.parseInt(argstr); 717 } 718 } catch (NumberFormatException e) {} 719 if (operator.equals("+")) { 720 return (fontInfo.getHeight() + arg); 721 } else if (operator.equals("-")) { 722 return (fontInfo.getHeight() - arg); 723 } else { 724 throw new CompilationError("Unknown operator in height attribute: "+operator); 725 } 726 } else { 727 return FontInfo.NULL_SIZE; 729 } 730 } 731 732 733 static final PatternMatcher sMatcher = new Perl5Matcher(); 734 735 static final Pattern sBooleanPat; static final Pattern sConstPat; static final Pattern sParentWidthPat; static final Pattern sParentHeightPat; 740 static final Pattern sFontstylePat; 741 static final Pattern sFontSizePat; 742 static final Pattern sFontNamePat; 743 static { 744 try { 745 Perl5Compiler compiler = new Perl5Compiler(); 746 sBooleanPat = compiler.compile("\\s*(true|false)\\s*"); 748 sConstPat = compiler.compile("\\s*(\\d*)\\s*"); 749 sParentWidthPat = compiler.compile("\\s*\\$(once|always)?\\s*{(parent.width)\\s*([+-]?)\\s*(\\d*)\\s*}\\s*"); 750 sParentHeightPat = compiler.compile("\\s*\\$(once|always)?\\s*{(parent.height)\\s*([+-]?)\\s*(\\d*)\\s*}\\s*"); 751 sFontstylePat = compiler.compile("\\s*(bold italic|bold-italic|bold|plain|italic)\\s*"); 752 sFontSizePat = compiler.compile("\\s*\\d*\\s*"); 753 sFontNamePat = compiler.compile("\\s*[^${}]*\\s*"); 754 } catch (MalformedPatternException e) { 755 throw new ChainedException(e); 756 } 757 } 758 759 760 762 protected static boolean matchesPattern (String str, Pattern pattern) { 763 return sMatcher.matches(str, pattern); 764 } 765 766 767 771 protected static boolean hasAttribute(Element elt, String attrName) { 772 if (elt.getAttributeValue(attrName) != null) { 773 return true; 774 } 775 776 Iterator iter; 777 for (iter = elt.getChildren().iterator(); iter.hasNext(); ) { 778 Element child = (Element)iter.next(); 779 if ((child.getName().equals("attribute")) && 780 (child.getAttribute(attrName) != null)) { 781 return true; 782 } 783 } 784 return false; 785 } 786 787 788 792 protected static String getAttributeValue(Element elt, String attrName) { 793 String attrval = elt.getAttributeValue(attrName); 794 if (attrval != null) { 795 return attrval; 796 } 797 798 Iterator iter; 799 for (iter = elt.getChildren().iterator(); iter.hasNext(); ) { 800 Element child = (Element)iter.next(); 801 if ((child.getName().equals("attribute")) && 802 attrName.equals(child.getAttributeValue("name"))) { 803 return child.getAttributeValue("value"); 804 } 805 } 806 return null; 807 } 808 809 810 818 protected static void collectInputFonts(Element elt, 819 CompilationEnvironment env, 820 FontInfo fontInfo, 821 Set classList) 822 { 823 ViewSchema schema = env.getSchema(); 825 826 fontInfo = new FontInfo(fontInfo); 828 mergeClassFontInfo (elt, fontInfo, env); 830 mergeFontInfo(elt, fontInfo); 831 832 if (schema.isInputTextElement(elt)) { 834 final SWFWriter generator = env.getGenerator(); 835 boolean password = elt.getAttributeValue("password", "false").equals("true"); 836 boolean multiline = (fontInfo.multiline == FontInfo.FONTINFO_TRUE); 837 int resizable = fontInfo.resizable; 838 839 int width = evalWidth(fontInfo, elt.getAttributeValue("width")); 840 String heightstr = elt.getAttributeValue("height"); 842 if (heightstr == null) { 843 heightstr = elt.getAttributeValue("textheight"); 844 } 845 int height = evalHeight(fontInfo, heightstr); 846 847 if (!multiline && (height == FontInfo.NULL_SIZE) && fontInfo.isFullySpecified()) { 850 height = (int) Math.ceil(generator.getLFCLineHeight(fontInfo, fontInfo.getSize())); 851 } 852 853 if (width == FontInfo.NULL_SIZE) { 856 width = env.getDefaultTextWidth(); 857 } 858 859 if ((width == FontInfo.NULL_SIZE) || (height == FontInfo.NULL_SIZE)) { 861 resizable = FontInfo.FONTINFO_TRUE; 862 } 863 boolean fixedsize = (resizable != FontInfo.FONTINFO_TRUE); 864 865 if (!fontInfo.isFullySpecified()) { 867 return; 869 } 870 871 if (fixedsize) { 872 generator.addCustomInputText(fontInfo, width, height, multiline, password); 873 } 874 if (hasAttribute(elt, "password")) { 878 generator.addInputText(fontInfo, true); 879 generator.addInputText(fontInfo, false); 880 } else { 881 generator.addInputText(fontInfo, false); 883 } 884 } 885 886 mergeWidth(fontInfo, getAttributeValue(elt, "width")); 888 mergeHeight(fontInfo, getAttributeValue(elt, "height")); 889 890 ClassModel classinfo = schema.getClassModel(elt.getName()); 891 892 Vector parents = new Vector(); 894 ClassModel lzxclass = classinfo; 895 while (lzxclass != null) { 897 parents.insertElementAt(lzxclass, 0); 898 lzxclass = lzxclass.superclass; 899 } 900 901 while (parents.size() > 0) { 903 lzxclass = (ClassModel) parents.firstElement(); 904 parents.removeElementAt(0); if (lzxclass.definition != null) { 907 if (classList.contains(elt.getName().intern())) { 909 return; 910 } 911 for (Iterator iter = lzxclass.definition.getChildren().iterator(); iter.hasNext(); 912 ) { 913 Element e = (Element) iter.next(); 914 String ename = e.getName(); 915 if (!(ename.equals("method") || ename.equals("attribute"))) { 916 HashSet nclassList = new HashSet(classList); 919 nclassList.add(lzxclass.className.intern()); 920 collectInputFonts(e, env, fontInfo, nclassList); 921 } 922 } 923 } 924 } 925 926 for (Iterator iter = elt.getChildren().iterator(); iter.hasNext(); 928 ) { 929 Element e = (Element) iter.next(); 930 String ename = e.getName(); 931 if (!(ename.equals("method") || ename.equals("attribute"))) { 932 collectInputFonts(e, env, fontInfo, classList); 933 } 934 } 935 } 936 937 944 private void compileTextMetrics(Element elt, 945 CompilationEnvironment env, 946 FontInfo fontInfo) { 947 SWFWriter generator = env.getGenerator(); 948 double wd = 0; 949 double textheight = 0; 950 ViewSchema schema = env.getSchema(); 951 boolean isInputTextElement = schema.isInputTextElement(elt); 952 953 String widthAttr = elt.getAttributeValue("width"); 954 String heightAttr = elt.getAttributeValue("height"); 955 try { 956 if (widthAttr != null) { 957 wd = Double.parseDouble(widthAttr); 958 } 959 } catch (NumberFormatException e) { 960 } 962 963 if (heightAttr == null) { 964 textheight = (int) Math.ceil(generator.getLFCLineHeight(fontInfo, fontInfo.getSize())); 965 } 966 967 LineMetrics lm; 969 lm = TextCompiler.getElementWidth(elt, fontInfo, generator); 970 971 if (widthAttr == null) { 975 String textattr = elt.getAttributeValue("text"); 978 if (textattr != null && textattr.length() != 0) { 979 wd = TextCompiler.computeTextWidth(textattr, fontInfo, generator); 980 } else { 981 if (!("".equals(lm.getText()))) { 982 wd = lm.maxw; 983 textheight = lm.nlines * (int) Math.ceil(generator.getLFCLineHeight(fontInfo, fontInfo.getSize())); 984 } 985 } 986 } 987 988 if (wd != 0) { 991 TextCompiler.checkFontExists(generator, fontInfo); 992 } 993 994 if (wd != 0 && widthAttr == null) { 997 DecimalFormat format = new DecimalFormat ("#.##"); 998 StringBuffer width = new StringBuffer (); 999 if (isInputTextElement) { 1000 wd += INPUT_TEXTWIDTH_FUDGE_FACTOR; 1002 } 1003 width = format.format(Math.ceil(wd), width, new FieldPosition (0)); 1004 elt.setAttribute("textwidth", width.toString()); 1005 } 1006 1007 if ((textheight != 0) && schema.hasTextContent(elt)) { 1008 DecimalFormat format = new DecimalFormat ("#.##"); 1009 StringBuffer height = new StringBuffer (); 1010 height = format.format(Math.ceil(textheight), height, new FieldPosition (0)); 1011 elt.setAttribute("textheight", height.toString()); 1012 } 1013 } 1014 1015 1016 static void setFontInfo(FontInfo info, Element elt) { 1017 String face = elt.getAttributeValue("face"); 1018 String size = elt.getAttributeValue("size"); 1019 1020 if (face != null) { 1021 info.setName(face); 1022 } 1023 if (size != null) { 1024 info.setSize(size); 1025 } 1026 } 1027} 1028 1029 1030 | Popular Tags |