From 6025b6016517c6d898d8957d1d7e03ba71431912 Mon Sep 17 00:00:00 2001 From: tknall Date: Fri, 1 Dec 2006 12:20:24 +0000 Subject: Initial import of release 2.2. git-svn-id: https://joinup.ec.europa.eu/svn/pdf-as/trunk@4 7b5415b0-85f9-ee4d-85bd-d5d0c3b42d1c --- .../java/com/lowagie/text/html/HtmlWriter.java | 1094 ++++++++++++++++++++ 1 file changed, 1094 insertions(+) create mode 100644 src/main/java/com/lowagie/text/html/HtmlWriter.java (limited to 'src/main/java/com/lowagie/text/html/HtmlWriter.java') diff --git a/src/main/java/com/lowagie/text/html/HtmlWriter.java b/src/main/java/com/lowagie/text/html/HtmlWriter.java new file mode 100644 index 0000000..69ce91c --- /dev/null +++ b/src/main/java/com/lowagie/text/html/HtmlWriter.java @@ -0,0 +1,1094 @@ +/* + * $Id: HtmlWriter.java,v 1.109 2005/11/01 12:27:05 psoares33 Exp $ + * $Name: $ + * + * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie. + * + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the License. + * + * The Original Code is 'iText, a free JAVA-PDF library'. + * + * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by + * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie. + * All Rights Reserved. + * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer + * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved. + * + * Contributor(s): all the names of the contributors are added in the source code + * where applicable. + * + * Alternatively, the contents of this file may be used under the terms of the + * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the + * provisions of LGPL are applicable instead of those above. If you wish to + * allow use of your version of this file only under the terms of the LGPL + * License and not to allow others to use your version of this file under + * the MPL, indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by the LGPL. + * If you do not delete the provisions above, a recipient may use your version + * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the MPL as stated above or under the terms of the GNU + * Library General Public License as published by the Free Software Foundation; + * either version 2 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU LIBRARY GENERAL PUBLIC LICENSE for more + * details. + * + * If you didn't download this code from the following link, you should check if + * you aren't using an obsolete version: + * http://www.lowagie.com/iText/ + */ + +package com.lowagie.text.html; + +import java.io.OutputStream; +import java.io.IOException; +import java.util.Date; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Properties; +import java.util.Stack; +import java.util.EmptyStackException; + +import com.lowagie.text.*; +import com.lowagie.text.markup.MarkupTags; + +/** + * A DocWriter class for HTML. + *

+ * An HtmlWriter can be added as a DocListener + * to a certain Document by getting an instance. + * Every Element added to the original Document + * will be written to the OutputStream of this HtmlWriter. + *

+ * Example: + *

+ * // creation of the document with a certain size and certain margins
+ * Document document = new Document(PageSize.A4, 50, 50, 50, 50);
+ * try {
+ *    // this will write HTML to the Standard OutputStream
+ *    HtmlWriter.getInstance(document, System.out);
+ *    // this will write HTML to a file called text.html
+ *    HtmlWriter.getInstance(document, new FileOutputStream("text.html"));
+ *    // this will write HTML to for instance the OutputStream of a HttpServletResponse-object
+ *    HtmlWriter.getInstance(document, response.getOutputStream());
+ * }
+ * catch(DocumentException de) {
+ *    System.err.println(de.getMessage());
+ * }
+ * // this will close the document and all the OutputStreams listening to it
+ * document.close();
+ * 
+ */ + +public class HtmlWriter extends DocWriter implements DocListener { + + // static membervariables (tags) + +/** This is a possible HTML-tag. */ + public static final byte[] BEGINCOMMENT = getISOBytes(""); + +/** This is a possible HTML-tag. */ + public static final String NBSP = " "; + + // membervariables + +/** This is the current font of the HTML. */ + protected Stack currentfont = new Stack(); + +/** This is the standard font of the HTML. */ + protected Font standardfont = new Font(); + +/** This is a path for images. */ + protected String imagepath = null; + +/** Stores the page number. */ + protected int pageN = 0; + +/** This is the textual part of a header */ + protected HeaderFooter header = null; + +/** This is the textual part of the footer */ + protected HeaderFooter footer = null; + + // constructor + +/** + * Constructs a HtmlWriter. + * + * @param doc The Document that has to be written as HTML + * @param os The OutputStream the writer has to write to. + */ + + protected HtmlWriter(Document doc, OutputStream os) { + super(doc, os); + + document.addDocListener(this); + this.pageN = document.getPageNumber(); + try { + os.write(LT); + os.write(getISOBytes(HtmlTags.HTML)); + os.write(GT); + os.write(NEWLINE); + os.write(TAB); + os.write(LT); + os.write(getISOBytes(HtmlTags.HEAD)); + os.write(GT); + } + catch(IOException ioe) { + throw new ExceptionConverter(ioe); + } + } + + // get an instance of the HtmlWriter + +/** + * Gets an instance of the HtmlWriter. + * + * @param document The Document that has to be written + * @param os The OutputStream the writer has to write to. + * @return a new HtmlWriter + */ + + public static HtmlWriter getInstance(Document document, OutputStream os) { + return new HtmlWriter(document, os); + } + + // implementation of the DocListener methods + +/** + * Signals that an new page has to be started. + * + * @return true if this action succeeded, false if not. + * @throws DocumentException when a document isn't open yet, or has been closed + */ + + public boolean newPage() throws DocumentException { + try { + writeStart(HtmlTags.DIV); + write(" "); + write(HtmlTags.STYLE); + write("=\""); + writeCssProperty(MarkupTags.CSS_KEY_PAGE_BREAK_BEFORE, MarkupTags.CSS_VALUE_ALWAYS); + write("\" /"); + os.write(GT); + } + catch(IOException ioe) { + throw new DocumentException(ioe); + } + return true; + } + +/** + * Signals that an Element was added to the Document. + * + * @param element a high level object that has to be translated to HTML + * @return true if the element was added, false if not. + * @throws DocumentException when a document isn't open yet, or has been closed + */ + + public boolean add(Element element) throws DocumentException { + if (pause) { + return false; + } + try { + + switch(element.type()) { + case Element.HEADER: + try { + Header h = (Header) element; + if (HtmlTags.STYLESHEET.equals(h.name())) { + writeLink(h); + } + else if (HtmlTags.JAVASCRIPT.equals(h.name())) { + writeJavaScript(h); + } + else { + writeHeader(h); + } + } + catch(ClassCastException cce) { + } + return true; + case Element.SUBJECT: + case Element.KEYWORDS: + case Element.AUTHOR: + Meta meta = (Meta) element; + writeHeader(meta); + return true; + case Element.TITLE: + addTabs(2); + writeStart(HtmlTags.TITLE); + os.write(GT); + addTabs(3); + write(HtmlEncoder.encode(((Meta)element).content())); + addTabs(2); + writeEnd(HtmlTags.TITLE); + return true; + case Element.CREATOR: + writeComment("Creator: " + HtmlEncoder.encode(((Meta)element).content())); + return true; + case Element.PRODUCER: + writeComment("Producer: " + HtmlEncoder.encode(((Meta)element).content())); + return true; + case Element.CREATIONDATE: + writeComment("Creationdate: " + HtmlEncoder.encode(((Meta)element).content())); + return true; + default: + write(element, 2); + return true; + } + } + catch(IOException ioe) { + throw new ExceptionConverter(ioe); + } + } + +/** + * Signals that the Document has been opened and that + * Elements can be added. + *

+ * The HEAD-section of the HTML-document is written. + */ + + public void open() { + super.open(); + try { + writeComment(Document.getVersion()); + writeComment("CreationDate: " + new Date().toString()); + addTabs(1); + writeEnd(HtmlTags.HEAD); + addTabs(1); + writeStart(HtmlTags.BODY); + if (document.leftMargin() > 0) { + write(HtmlTags.LEFTMARGIN, String.valueOf(document.leftMargin())); + } + if (document.rightMargin() > 0) { + write(HtmlTags.RIGHTMARGIN, String.valueOf(document.rightMargin())); + } + if (document.topMargin() > 0) { + write(HtmlTags.TOPMARGIN, String.valueOf(document.topMargin())); + } + if (document.bottomMargin() > 0) { + write(HtmlTags.BOTTOMMARGIN, String.valueOf(document.bottomMargin())); + } + if (pageSize.backgroundColor() != null) { + write(HtmlTags.BACKGROUNDCOLOR, HtmlEncoder.encode(pageSize.backgroundColor())); + } + if (document.getJavaScript_onLoad() != null) { + write(HtmlTags.JAVASCRIPT_ONLOAD, HtmlEncoder.encode(document.getJavaScript_onLoad())); + } + if (document.getJavaScript_onUnLoad() != null) { + write(HtmlTags.JAVASCRIPT_ONUNLOAD, HtmlEncoder.encode(document.getJavaScript_onUnLoad())); + } + if (document.getHtmlStyleClass() != null) { + write(MarkupTags.HTML_ATTR_CSS_CLASS, document.getHtmlStyleClass()); + } + os.write(GT); + initHeader(); // line added by David Freels + } + catch(IOException ioe) { + throw new ExceptionConverter(ioe); + } + } + +/** + * Signals that the Document was closed and that no other + * Elements will be added. + */ + + public void close() { + try { + initFooter(); // line added by David Freels + addTabs(1); + writeEnd(HtmlTags.BODY); + os.write(NEWLINE); + writeEnd(HtmlTags.HTML); + super.close(); + } + catch(IOException ioe) { + throw new ExceptionConverter(ioe); + } + } + + // some protected methods + +/** + * Adds the header to the top of the Document + */ + + protected void initHeader() { + if (header != null) { + try { + add(header.paragraph()); + } + catch(Exception e) { + throw new ExceptionConverter(e); + } + } + } + +/** + * Adds the header to the top of the Document + */ + + protected void initFooter() { + if (footer != null) { + try { + // Set the page number. HTML has no notion of a page, so it should always + // add up to 1 + footer.setPageNumber(pageN + 1); + add(footer.paragraph()); + } + catch(Exception e) { + throw new ExceptionConverter(e); + } + } + } + +/** + * Writes a Metatag in the header. + * + * @param meta the element that has to be written + * @throws IOException + */ + + protected void writeHeader(Meta meta) throws IOException { + addTabs(2); + writeStart(HtmlTags.META); + switch(meta.type()) { + case Element.HEADER: + write(HtmlTags.NAME, ((Header) meta).name()); + break; + case Element.SUBJECT: + write(HtmlTags.NAME, HtmlTags.SUBJECT); + break; + case Element.KEYWORDS: + write(HtmlTags.NAME, HtmlTags.KEYWORDS); + break; + case Element.AUTHOR: + write(HtmlTags.NAME, HtmlTags.AUTHOR); + break; + } + write(HtmlTags.CONTENT, HtmlEncoder.encode(meta.content())); + writeEnd(); + } + +/** + * Writes a link in the header. + * + * @param header the element that has to be written + * @throws IOException + */ + + protected void writeLink(Header header) throws IOException { + addTabs(2); + writeStart(HtmlTags.LINK); + write(HtmlTags.REL, header.name()); + write(HtmlTags.TYPE, HtmlTags.TEXT_CSS); + write(HtmlTags.REFERENCE, header.content()); + writeEnd(); + } + +/** + * Writes a JavaScript section or, if the markup attribute HtmlTags.URL is set, a JavaScript reference in the header. + * + * @param header the element that has to be written + * @throws IOException + */ + + protected void writeJavaScript(Header header) throws IOException { + addTabs(2); + writeStart(HtmlTags.SCRIPT); + write(HtmlTags.LANGUAGE, HtmlTags.JAVASCRIPT); + if (header.getMarkupAttribute(HtmlTags.URL) != null) { + /* JavaScript reference example: + * + * + */ + write(HtmlTags.TYPE, MarkupTags.HTML_VALUE_JAVASCRIPT); + os.write(GT); + addTabs(2); + write(new String(BEGINCOMMENT) + "\n"); + write(header.content()); + addTabs(2); + write("//" + new String(ENDCOMMENT)); + addTabs(2); + writeEnd(HtmlTags.SCRIPT); + } + } + +/** + * Writes some comment. + *

+ * This method writes some comment. + * + * @param comment the comment that has to be written + * @throws IOException + */ + + protected void writeComment(String comment) throws IOException { + addTabs(2); + os.write(BEGINCOMMENT); + write(comment); + os.write(ENDCOMMENT); + } + + // public methods + +/** + * Changes the standardfont. + * + * @param standardfont The font + */ + + public void setStandardFont(Font standardfont) { + this.standardfont = standardfont; + } + +/** + * Checks if a given font is the same as the font that was last used. + * + * @param font the font of an object + * @return true if the font differs + */ + + public boolean isOtherFont(Font font) { + try { + Font cFont = (Font) currentfont.peek(); + if (cFont.compareTo(font) == 0) return false; + return true; + } + catch(EmptyStackException ese) { + if (standardfont.compareTo(font) == 0) return false; + return true; + } + } + +/** + * Sets the basepath for images. + *

+ * This is especially useful if you add images using a file, + * rather than an URL. In PDF there is no problem, since + * the images are added inline, but in HTML it is sometimes + * necessary to use a relative path or a special path to some + * images directory. + * + * @param imagepath the new imagepath + */ + + public void setImagepath(String imagepath) { + this.imagepath = imagepath; + } + +/** + * Resets the imagepath. + */ + + public void resetImagepath() { + imagepath = null; + } + +/** + * Changes the header of this document. + * + * @param header the new header + */ + + public void setHeader(HeaderFooter header) { + this.header = header; + } + +/** + * Changes the footer of this document. + * + * @param footer the new footer + */ + + public void setFooter(HeaderFooter footer) { + this.footer = footer; + } + +/** + * Signals that a String was added to the Document. + * + * @param string a String to add to the HTML + * @return true if the string was added, false if not. + * @throws DocumentException when a document isn't open yet, or has been closed + */ + + public boolean add(String string) throws DocumentException{ + if (pause) { + return false; + } + try + { + write(string); + return true; + } + catch(IOException ioe) { + throw new ExceptionConverter(ioe); + } + } + +/** + * Writes the HTML representation of an element. + * + * @param element the element + * @param indent the indentation + * @throws IOException + */ + + protected void write(Element element, int indent) throws IOException { + Properties styleAttributes = null; + switch(element.type()) { + case Element.CHUNK: + { + Chunk chunk = (Chunk) element; + // if the chunk contains an image, return the image representation + Image image = chunk.getImage(); + if (image != null) { + write(image, indent); + return; + } + + if (chunk.isEmpty()) return; + HashMap attributes = chunk.getAttributes(); + if (attributes != null && attributes.get(Chunk.NEWPAGE) != null) { + return; + } + // This doesn't seem to work: + //if (attributes != null && attributes.get(Chunk.SUBSUPSCRIPT) != null) { + // float p = (((Float)attributes.get(Chunk.SUBSUPSCRIPT)).floatValue() * 100f) / chunk.font().size(); + // styleAttributes = new Properties(); + // styleAttributes.setProperty(MarkupTags.CSS_VERTICALALIGN, "" + p + "%"); + //} + boolean tag = isOtherFont(chunk.font()) || hasMarkupAttributes(chunk) || styleAttributes != null; + if (tag) { + // start span tag + addTabs(indent); + writeStart(HtmlTags.SPAN); + if (isOtherFont(chunk.font())) { + write(chunk.font(), styleAttributes); + } + if (hasMarkupAttributes(chunk)) { + writeMarkupAttributes(chunk); + } + os.write(GT); + } + if (attributes != null && attributes.get(Chunk.SUBSUPSCRIPT) != null) { + // start sup or sub tag + if (((Float)attributes.get(Chunk.SUBSUPSCRIPT)).floatValue() > 0) { + writeStart(HtmlTags.SUP); + } + else { + writeStart(HtmlTags.SUB); + } + os.write(GT); + } + // contents + write(HtmlEncoder.encode(chunk.content())); + if (attributes != null && attributes.get(Chunk.SUBSUPSCRIPT) != null) { + // end sup or sub tag + os.write(LT); + os.write(FORWARD); + if (((Float)attributes.get(Chunk.SUBSUPSCRIPT)).floatValue() > 0) { + write(HtmlTags.SUP); + } + else { + write(HtmlTags.SUB); + } + os.write(GT); + } + if (tag) { + // end tag + writeEnd(MarkupTags.HTML_TAG_SPAN); + } + return; + } + case Element.PHRASE: + { + Phrase phrase = (Phrase) element; + styleAttributes = new Properties(); + if (phrase.leadingDefined()) styleAttributes.setProperty(MarkupTags.CSS_KEY_LINEHEIGHT, String.valueOf(phrase.leading()) + "pt"); + + // start tag + addTabs(indent); + writeStart(MarkupTags.HTML_TAG_SPAN); + if (hasMarkupAttributes(phrase)) { + writeMarkupAttributes(phrase); + } + write(phrase.font(), styleAttributes); + os.write(GT); + currentfont.push(phrase.font()); + // contents + for (Iterator i = phrase.iterator(); i.hasNext(); ) { + write((Element) i.next(), indent + 1); + } + // end tag + addTabs(indent); + writeEnd(MarkupTags.HTML_TAG_SPAN); + currentfont.pop(); + return; + } + case Element.ANCHOR: + { + Anchor anchor = (Anchor) element; + styleAttributes = new Properties(); + if (anchor.leadingDefined()) styleAttributes.setProperty(MarkupTags.CSS_KEY_LINEHEIGHT, String.valueOf(anchor.leading()) + "pt"); + + // start tag + addTabs(indent); + writeStart(HtmlTags.ANCHOR); + if (anchor.name() != null) { + write(HtmlTags.NAME, anchor.name()); + } + if (anchor.reference() != null) { + write(HtmlTags.REFERENCE, anchor.reference()); + } + if (hasMarkupAttributes(anchor)) { + writeMarkupAttributes(anchor); + } + write(anchor.font(), styleAttributes); + os.write(GT); + currentfont.push(anchor.font()); + // contents + for (Iterator i = anchor.iterator(); i.hasNext(); ) { + write((Element) i.next(), indent + 1); + } + // end tag + addTabs(indent); + writeEnd(HtmlTags.ANCHOR); + currentfont.pop(); + return; + } + case Element.PARAGRAPH: + { + Paragraph paragraph = (Paragraph) element; + styleAttributes = new Properties(); + if (paragraph.leadingDefined()) styleAttributes.setProperty(MarkupTags.CSS_KEY_LINEHEIGHT, String.valueOf(paragraph.leading()) + "pt"); + // start tag + addTabs(indent); + writeStart(HtmlTags.DIV); + if (hasMarkupAttributes(paragraph)) { + writeMarkupAttributes(paragraph); + } + String alignment = HtmlEncoder.getAlignment(paragraph.alignment()); + if (!"".equals(alignment)) { + write(HtmlTags.ALIGN, alignment); + } + write(paragraph.font(), styleAttributes); + os.write(GT); + currentfont.push(paragraph.font()); + // contents + for (Iterator i = paragraph.iterator(); i.hasNext(); ) { + write((Element) i.next(), indent + 1); + } + // end tag + addTabs(indent); + writeEnd(HtmlTags.DIV); + currentfont.pop(); + return; + } + case Element.SECTION: + case Element.CHAPTER: + { + // part of the start tag + contents + writeSection((Section) element, indent); + return; + } + case Element.LIST: + { + List list = (List) element; + // start tag + addTabs(indent); + if (list.isNumbered()) { + writeStart(HtmlTags.ORDEREDLIST); + } + else { + writeStart(HtmlTags.UNORDEREDLIST); + } + if (hasMarkupAttributes(list)) { + writeMarkupAttributes(list); + } + os.write(GT); + // contents + for (Iterator i = list.getItems().iterator(); i.hasNext(); ) { + write((Element) i.next(), indent + 1); + } + // end tag + addTabs(indent); + if (list.isNumbered()) { + writeEnd(HtmlTags.ORDEREDLIST); + } + else { + writeEnd(HtmlTags.UNORDEREDLIST); + } + return; + } + case Element.LISTITEM: + { + ListItem listItem = (ListItem) element; + styleAttributes = new Properties(); + if (listItem.leadingDefined()) styleAttributes.setProperty(MarkupTags.CSS_KEY_LINEHEIGHT, String.valueOf(listItem.leading()) + "pt"); + + // start tag + addTabs(indent); + writeStart(HtmlTags.LISTITEM); + if (hasMarkupAttributes(listItem)) { + writeMarkupAttributes(listItem); + } + write(listItem.font(), styleAttributes); + os.write(GT); + currentfont.push(listItem.font()); + // contents + for (Iterator i = listItem.iterator(); i.hasNext(); ) { + write((Element) i.next(), indent + 1); + } + // end tag + addTabs(indent); + writeEnd(HtmlTags.LISTITEM); + currentfont.pop(); + return; + } + case Element.CELL: + { + Cell cell = (Cell) element; + + // start tag + addTabs(indent); + if (cell.header()) { + writeStart(HtmlTags.HEADERCELL); + } + else { + writeStart(HtmlTags.CELL); + } + if (hasMarkupAttributes(cell)) { + writeMarkupAttributes(cell); + } + if (cell.borderWidth() != Rectangle.UNDEFINED) { + write(HtmlTags.BORDERWIDTH, String.valueOf(cell.borderWidth())); + } + if (cell.borderColor() != null) { + write(HtmlTags.BORDERCOLOR, HtmlEncoder.encode(cell.borderColor())); + } + if (cell.backgroundColor() != null) { + write(HtmlTags.BACKGROUNDCOLOR, HtmlEncoder.encode(cell.backgroundColor())); + } + String alignment = HtmlEncoder.getAlignment(cell.horizontalAlignment()); + if (!"".equals(alignment)) { + write(HtmlTags.HORIZONTALALIGN, alignment); + } + alignment = HtmlEncoder.getAlignment(cell.verticalAlignment()); + if (!"".equals(alignment)) { + write(HtmlTags.VERTICALALIGN, alignment); + } + if (cell.cellWidth() != null) { + write(HtmlTags.WIDTH, cell.cellWidth()); + } + if (cell.colspan() != 1) { + write(HtmlTags.COLSPAN, String.valueOf(cell.colspan())); + } + if (cell.rowspan() != 1) { + write(HtmlTags.ROWSPAN, String.valueOf(cell.rowspan())); + } + if (cell.noWrap()) { + write(HtmlTags.NOWRAP, String.valueOf(true)); + } + os.write(GT); + // contents + if (cell.isEmpty()) { + write(NBSP); + } else { + for (Iterator i = cell.getElements(); i.hasNext(); ) { + write((Element) i.next(), indent + 1); + } + } + // end tag + addTabs(indent); + if (cell.header()) { + writeEnd(HtmlTags.HEADERCELL); + } + else { + writeEnd(HtmlTags.CELL); + } + return; + } + case Element.ROW: + { + Row row = (Row) element; + + // start tag + addTabs(indent); + writeStart(HtmlTags.ROW); + if (hasMarkupAttributes(row)) { + writeMarkupAttributes(row); + } + os.write(GT); + // contents + Element cell; + for (int i = 0; i < row.columns(); i++) { + if ((cell = (Element)row.getCell(i)) != null) { + write(cell, indent + 1); + } + } + // end tag + addTabs(indent); + writeEnd(HtmlTags.ROW); + return; + } + case Element.TABLE: + { + Table table; + try { + table = (Table) element; + } + catch(ClassCastException cce) { + try { + table = ((SimpleTable)element).createTable(); + } catch (BadElementException e) { + throw new ExceptionConverter(e); + } + } + table.complete(); + // start tag + addTabs(indent); + writeStart(HtmlTags.TABLE); + if (hasMarkupAttributes(table)) { + writeMarkupAttributes(table); + } + os.write(SPACE); + write(HtmlTags.WIDTH); + os.write(EQUALS); + os.write(QUOTE); + if (! "".equals(table.absWidth())){ + write(table.absWidth()); + } + else{ + write(String.valueOf(table.widthPercentage())); + write("%"); + } + os.write(QUOTE); + String alignment = HtmlEncoder.getAlignment(table.alignment()); + if (!"".equals(alignment)) { + write(HtmlTags.ALIGN, alignment); + } + write(HtmlTags.CELLPADDING, String.valueOf(table.cellpadding())); + write(HtmlTags.CELLSPACING, String.valueOf(table.cellspacing())); + if (table.borderWidth() != Rectangle.UNDEFINED) { + write(HtmlTags.BORDERWIDTH, String.valueOf(table.borderWidth())); + } + if (table.borderColor() != null) { + write(HtmlTags.BORDERCOLOR, HtmlEncoder.encode(table.borderColor())); + } + if (table.backgroundColor() != null) { + write(HtmlTags.BACKGROUNDCOLOR, HtmlEncoder.encode(table.backgroundColor())); + } + os.write(GT); + // contents + Row row; + for (Iterator iterator = table.iterator(); iterator.hasNext(); ) { + row = (Row) iterator.next(); + write(row, indent + 1); + } + // end tag + addTabs(indent); + writeEnd(HtmlTags.TABLE); + return; + } + case Element.ANNOTATION: + { + Annotation annotation = (Annotation) element; + writeComment(annotation.title() + ": " + annotation.content()); + if (hasMarkupAttributes(annotation)) { + os.write(BEGINCOMMENT); + writeMarkupAttributes(annotation); + os.write(ENDCOMMENT); + } + return; + } + case Element.IMGRAW: + case Element.JPEG: + case Element.IMGTEMPLATE: + { + Image image = (Image) element; + if (image.url() == null) { + return; + } + + // start tag + addTabs(indent); + writeStart(HtmlTags.IMAGE); + String path = image.url().toString(); + if (imagepath != null) { + if (path.indexOf("/") > 0) { + path = imagepath + path.substring(path.lastIndexOf("/") + 1); + } + else { + path = imagepath + path; + } + } + write(HtmlTags.URL, path); + if ((image.alignment() & Image.LEFT) > 0) { + write(HtmlTags.ALIGN, HtmlTags.ALIGN_LEFT); + } + else if ((image.alignment() & Image.RIGHT) > 0) { + write(HtmlTags.ALIGN, HtmlTags.ALIGN_RIGHT); + } + else if ((image.alignment() & Image.MIDDLE) > 0) { + write(HtmlTags.ALIGN, HtmlTags.ALIGN_MIDDLE); + } + if (image.alt() != null) { + write(HtmlTags.ALT, image.alt()); + } + write(HtmlTags.PLAINWIDTH, String.valueOf(image.scaledWidth())); + write(HtmlTags.PLAINHEIGHT, String.valueOf(image.scaledHeight())); + if (hasMarkupAttributes(image)){ + writeMarkupAttributes(image); + } + writeEnd(); + return; + } + + default: + return; + } + } + +/** + * Writes the HTML representation of a section. + * + * @param section the section to write + * @param indent the indentation + * @throws IOException + */ + + protected void writeSection(Section section, int indent) throws IOException { + if (section.title() != null) { + int depth = section.depth() - 1; + if (depth > 5) { + depth = 5; + } + Properties styleAttributes = new Properties(); + if (section.title().leadingDefined()) styleAttributes.setProperty(MarkupTags.CSS_KEY_LINEHEIGHT, String.valueOf(section.title().leading()) + "pt"); + // start tag + addTabs(indent); + writeStart(HtmlTags.H[depth]); + write(section.title().font(), styleAttributes); + String alignment = HtmlEncoder.getAlignment(section.title().alignment()); + if (!"".equals(alignment)) { + write(HtmlTags.ALIGN, alignment); + } + if (hasMarkupAttributes(section.title())) { + writeMarkupAttributes(section.title()); + } + os.write(GT); + currentfont.push(section.title().font()); + // contents + for (Iterator i = section.title().iterator(); i.hasNext(); ) { + write((Element)i.next(), indent + 1); + } + // end tag + addTabs(indent); + writeEnd(HtmlTags.H[depth]); + currentfont.pop(); + } + for (Iterator i = section.iterator(); i.hasNext(); ) { + write((Element) i.next(), indent); + } + } + + /** + * Writes the representation of a Font. + * + * @param font a Font + * @param styleAttributes the style of the font + * @throws IOException + */ + + protected void write(Font font, Properties styleAttributes) throws IOException { + if (font == null || !isOtherFont(font) /* || styleAttributes == null*/) return; + write(" "); + write(HtmlTags.STYLE); + write("=\""); + if (styleAttributes != null) { + String key; + for (Enumeration e = styleAttributes.propertyNames(); e.hasMoreElements(); ) { + key = (String)e.nextElement(); + writeCssProperty(key, styleAttributes.getProperty(key)); + } + } + if (isOtherFont(font)) { + writeCssProperty(MarkupTags.CSS_KEY_FONTFAMILY, font.getFamilyname()); + + if (font.size() != Font.UNDEFINED) { + writeCssProperty(MarkupTags.CSS_KEY_FONTSIZE, String.valueOf(font.size()) + "pt"); + } + if (font.color() != null) { + writeCssProperty(MarkupTags.CSS_KEY_COLOR, HtmlEncoder.encode(font.color())); + } + + int fontstyle = font.style(); + if (fontstyle != Font.UNDEFINED && fontstyle != Font.NORMAL) { + switch (fontstyle & Font.BOLDITALIC) { + case Font.BOLD: + writeCssProperty(MarkupTags.CSS_KEY_FONTWEIGHT, MarkupTags.CSS_VALUE_BOLD); + break; + case Font.ITALIC: + writeCssProperty(MarkupTags.CSS_KEY_FONTSTYLE, MarkupTags.CSS_VALUE_ITALIC); + break; + case Font.BOLDITALIC: + writeCssProperty(MarkupTags.CSS_KEY_FONTWEIGHT, MarkupTags.CSS_VALUE_BOLD); + writeCssProperty(MarkupTags.CSS_KEY_FONTSTYLE, MarkupTags.CSS_VALUE_ITALIC); + break; + } + + // CSS only supports one decoration tag so if both are specified + // only one of the two will display + if ((fontstyle & Font.UNDERLINE) > 0) { + writeCssProperty(MarkupTags.CSS_KEY_TEXTDECORATION, MarkupTags.CSS_VALUE_UNDERLINE); + } + if ((fontstyle & Font.STRIKETHRU) > 0) { + writeCssProperty(MarkupTags.CSS_KEY_TEXTDECORATION, MarkupTags.CSS_VALUE_LINETHROUGH); + } + } + } + write("\""); + } + + /** + * Writes out a CSS property. + * @param prop a CSS property + * @param value the value of the CSS property + * @throws IOException + */ + protected void writeCssProperty(String prop, String value) throws IOException { + write(new StringBuffer(prop).append(": ").append(value).append("; ").toString()); + } +} \ No newline at end of file -- cgit v1.2.3