1 7 8 package javax.swing.text.html; 9 10 import java.io.Writer ; 11 import java.io.IOException ; 12 import java.util.*; 13 import java.awt.Color ; 14 import javax.swing.text.*; 15 16 50 51 public class MinimalHTMLWriter extends AbstractWriter { 52 53 59 private static final int BOLD = 0x01; 60 private static final int ITALIC = 0x02; 61 private static final int UNDERLINE = 0x04; 62 63 private static final CSS css = new CSS (); 65 66 private int fontMask = 0; 67 68 int startOffset = 0; 69 int endOffset = 0; 70 71 77 private AttributeSet fontAttributes; 78 79 83 private Hashtable styleNameMapping; 84 85 92 public MinimalHTMLWriter(Writer w, StyledDocument doc) { 93 super(w, doc); 94 } 95 96 106 public MinimalHTMLWriter(Writer w, StyledDocument doc, int pos, int len) { 107 super(w, doc, pos, len); 108 } 109 110 119 public void write() throws IOException , BadLocationException { 120 styleNameMapping = new Hashtable(); 121 writeStartTag("<html>"); 122 writeHeader(); 123 writeBody(); 124 writeEndTag("</html>"); 125 } 126 127 128 140 protected void writeAttributes(AttributeSet attr) throws IOException { 141 Enumeration attributeNames = attr.getAttributeNames(); 142 while (attributeNames.hasMoreElements()) { 143 Object name = attributeNames.nextElement(); 144 if ((name instanceof StyleConstants.ParagraphConstants) || 145 (name instanceof StyleConstants.CharacterConstants) || 146 (name instanceof StyleConstants.FontConstants) || 147 (name instanceof StyleConstants.ColorConstants)) { 148 indent(); 149 write(name.toString()); 150 write(':'); 151 write(css.styleConstantsValueToCSSValue 152 ((StyleConstants)name, attr.getAttribute(name)). 153 toString()); 154 write(';'); 155 write(NEWLINE); 156 } 157 } 158 } 159 160 161 166 protected void text(Element elem) throws IOException , BadLocationException { 167 String contentStr = getText(elem); 168 if ((contentStr.length() > 0) && 169 (contentStr.charAt(contentStr.length()-1) == NEWLINE)) { 170 contentStr = contentStr.substring(0, contentStr.length()-1); 171 } 172 if (contentStr.length() > 0) { 173 write(contentStr); 174 } 175 } 176 177 183 protected void writeStartTag(String tag) throws IOException { 184 indent(); 185 write(tag); 186 write(NEWLINE); 187 incrIndent(); 188 } 189 190 191 197 protected void writeEndTag(String endTag) throws IOException { 198 decrIndent(); 199 indent(); 200 write(endTag); 201 write(NEWLINE); 202 } 203 204 205 216 protected void writeHeader() throws IOException { 217 writeStartTag("<head>"); 218 writeStartTag("<style>"); 219 writeStartTag("<!--"); 220 writeStyles(); 221 writeEndTag("-->"); 222 writeEndTag("</style>"); 223 writeEndTag("</head>"); 224 } 225 226 227 228 234 protected void writeStyles() throws IOException { 235 240 DefaultStyledDocument styledDoc = ((DefaultStyledDocument)getDocument()); 241 Enumeration styleNames = styledDoc.getStyleNames(); 242 243 while (styleNames.hasMoreElements()) { 244 Style s = styledDoc.getStyle((String )styleNames.nextElement()); 245 246 248 if (s.getAttributeCount() == 1 && 249 s.isDefined(StyleConstants.NameAttribute)) { 250 continue; 251 } 252 indent(); 253 write("p." + addStyleName(s.getName())); 254 write(" {\n"); 255 incrIndent(); 256 writeAttributes(s); 257 decrIndent(); 258 indent(); 259 write("}\n"); 260 } 261 } 262 263 264 272 protected void writeBody() throws IOException , BadLocationException { 273 ElementIterator it = getElementIterator(); 274 275 280 it.current(); 281 282 Element next = null; 283 284 writeStartTag("<body>"); 285 286 boolean inContent = false; 287 288 while((next = it.next()) != null) { 289 if (!inRange(next)) { 290 continue; 291 } 292 if (next instanceof AbstractDocument.BranchElement) { 293 if (inContent) { 294 writeEndParagraph(); 295 inContent = false; 296 fontMask = 0; 297 } 298 writeStartParagraph(next); 299 } else if (isText(next)) { 300 writeContent(next, !inContent); 301 inContent = true; 302 } else { 303 writeLeaf(next); 304 inContent = true; 305 } 306 } 307 if (inContent) { 308 writeEndParagraph(); 309 } 310 writeEndTag("</body>"); 311 } 312 313 314 322 protected void writeEndParagraph() throws IOException { 323 writeEndMask(fontMask); 324 if (inFontTag()) { 325 endSpanTag(); 326 } else { 327 write(NEWLINE); 328 } 329 writeEndTag("</p>"); 330 } 331 332 333 342 protected void writeStartParagraph(Element elem) throws IOException { 343 AttributeSet attr = elem.getAttributes(); 344 Object resolveAttr = attr.getAttribute(StyleConstants.ResolveAttribute); 345 if (resolveAttr instanceof StyleContext.NamedStyle) { 346 writeStartTag("<p class=" + mapStyleName(((StyleContext.NamedStyle)resolveAttr).getName()) + ">"); 347 } else { 348 writeStartTag("<p>"); 349 } 350 } 351 352 353 359 protected void writeLeaf(Element elem) throws IOException { 360 indent(); 361 if (elem.getName() == StyleConstants.IconElementName) { 362 writeImage(elem); 363 } else if (elem.getName() == StyleConstants.ComponentElementName) { 364 writeComponent(elem); 365 } 366 } 367 368 369 380 protected void writeImage(Element elem) throws IOException { 381 } 382 383 384 389 protected void writeComponent(Element elem) throws IOException { 390 } 391 392 393 397 protected boolean isText(Element elem) { 398 return (elem.getName() == AbstractDocument.ContentElementName); 399 } 400 401 402 410 protected void writeContent(Element elem, boolean needsIndenting) 411 throws IOException , BadLocationException { 412 413 AttributeSet attr = elem.getAttributes(); 414 writeNonHTMLAttributes(attr); 415 if (needsIndenting) { 416 indent(); 417 } 418 writeHTMLTags(attr); 419 text(elem); 420 } 421 422 423 430 431 protected void writeHTMLTags(AttributeSet attr) throws IOException { 432 433 int oldMask = fontMask; 434 setFontMask(attr); 435 436 int endMask = 0; 437 int startMask = 0; 438 if ((oldMask & BOLD) != 0) { 439 if ((fontMask & BOLD) == 0) { 440 endMask |= BOLD; 441 } 442 } else if ((fontMask & BOLD) != 0) { 443 startMask |= BOLD; 444 } 445 446 if ((oldMask & ITALIC) != 0) { 447 if ((fontMask & ITALIC) == 0) { 448 endMask |= ITALIC; 449 } 450 } else if ((fontMask & ITALIC) != 0) { 451 startMask |= ITALIC; 452 } 453 454 if ((oldMask & UNDERLINE) != 0) { 455 if ((fontMask & UNDERLINE) == 0) { 456 endMask |= UNDERLINE; 457 } 458 } else if ((fontMask & UNDERLINE) != 0) { 459 startMask |= UNDERLINE; 460 } 461 writeEndMask(endMask); 462 writeStartMask(startMask); 463 } 464 465 466 472 private void setFontMask(AttributeSet attr) { 473 if (StyleConstants.isBold(attr)) { 474 fontMask |= BOLD; 475 } 476 477 if (StyleConstants.isItalic(attr)) { 478 fontMask |= ITALIC; 479 } 480 481 if (StyleConstants.isUnderline(attr)) { 482 fontMask |= UNDERLINE; 483 } 484 } 485 486 487 488 489 495 private void writeStartMask(int mask) throws IOException { 496 if (mask != 0) { 497 if ((mask & UNDERLINE) != 0) { 498 write("<u>"); 499 } 500 if ((mask & ITALIC) != 0) { 501 write("<i>"); 502 } 503 if ((mask & BOLD) != 0) { 504 write("<b>"); 505 } 506 } 507 } 508 509 515 private void writeEndMask(int mask) throws IOException { 516 if (mask != 0) { 517 if ((mask & BOLD) != 0) { 518 write("</b>"); 519 } 520 if ((mask & ITALIC) != 0) { 521 write("</i>"); 522 } 523 if ((mask & UNDERLINE) != 0) { 524 write("</u>"); 525 } 526 } 527 } 528 529 530 541 protected void writeNonHTMLAttributes(AttributeSet attr) throws IOException { 542 543 String style = ""; 544 String separator = "; "; 545 546 if (inFontTag() && fontAttributes.isEqual(attr)) { 547 return; 548 } 549 550 boolean first = true; 551 Color color = (Color )attr.getAttribute(StyleConstants.Foreground); 552 if (color != null) { 553 style += "color: " + css.styleConstantsValueToCSSValue 554 ((StyleConstants)StyleConstants.Foreground, 555 color); 556 first = false; 557 } 558 Integer size = (Integer )attr.getAttribute(StyleConstants.FontSize); 559 if (size != null) { 560 if (!first) { 561 style += separator; 562 } 563 style += "font-size: " + size.intValue() + "pt"; 564 first = false; 565 } 566 567 String family = (String )attr.getAttribute(StyleConstants.FontFamily); 568 if (family != null) { 569 if (!first) { 570 style += separator; 571 } 572 style += "font-family: " + family; 573 first = false; 574 } 575 576 if (style.length() > 0) { 577 if (fontMask != 0) { 578 writeEndMask(fontMask); 579 fontMask = 0; 580 } 581 startSpanTag(style); 582 fontAttributes = attr; 583 } 584 else if (fontAttributes != null) { 585 writeEndMask(fontMask); 586 fontMask = 0; 587 endSpanTag(); 588 } 589 } 590 591 592 595 protected boolean inFontTag() { 596 return (fontAttributes != null); 597 } 598 599 606 protected void endFontTag() throws IOException { 607 write(NEWLINE); 608 writeEndTag("</font>"); 609 fontAttributes = null; 610 } 611 612 613 624 protected void startFontTag(String style) throws IOException { 625 boolean callIndent = false; 626 if (inFontTag()) { 627 endFontTag(); 628 callIndent = true; 629 } 630 writeStartTag("<font style=\"" + style + "\">"); 631 if (callIndent) { 632 indent(); 633 } 634 } 635 636 645 private void startSpanTag(String style) throws IOException { 646 boolean callIndent = false; 647 if (inFontTag()) { 648 endSpanTag(); 649 callIndent = true; 650 } 651 writeStartTag("<span style=\"" + style + "\">"); 652 if (callIndent) { 653 indent(); 654 } 655 } 656 657 662 private void endSpanTag() throws IOException { 663 write(NEWLINE); 664 writeEndTag("</span>"); 665 fontAttributes = null; 666 } 667 668 673 private String addStyleName(String style) { 674 if (styleNameMapping == null) { 675 return style; 676 } 677 StringBuffer sb = null; 678 for (int counter = style.length() - 1; counter >= 0; counter--) { 679 if (!isValidCharacter(style.charAt(counter))) { 680 if (sb == null) { 681 sb = new StringBuffer (style); 682 } 683 sb.setCharAt(counter, 'a'); 684 } 685 } 686 String mappedName = (sb != null) ? sb.toString() : style; 687 while (styleNameMapping.get(mappedName) != null) { 688 mappedName = mappedName + 'x'; 689 } 690 styleNameMapping.put(style, mappedName); 691 return mappedName; 692 } 693 694 697 private String mapStyleName(String style) { 698 if (styleNameMapping == null) { 699 return style; 700 } 701 String retValue = (String )styleNameMapping.get(style); 702 return (retValue == null) ? style : retValue; 703 } 704 705 private boolean isValidCharacter(char character) { 706 return ((character >= 'a' && character <= 'z') || 707 (character >= 'A' && character <= 'Z')); 708 } 709 } 710 | Popular Tags |