aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/com/lowagie/text/html
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com/lowagie/text/html')
-rw-r--r--src/main/java/com/lowagie/text/html/HtmlEncoder.java211
-rw-r--r--src/main/java/com/lowagie/text/html/HtmlParser.java206
-rw-r--r--src/main/java/com/lowagie/text/html/HtmlPeer.java112
-rw-r--r--src/main/java/com/lowagie/text/html/HtmlTagMap.java296
-rw-r--r--src/main/java/com/lowagie/text/html/HtmlTags.java331
-rw-r--r--src/main/java/com/lowagie/text/html/HtmlWriter.java1094
-rw-r--r--src/main/java/com/lowagie/text/html/SAXmyHtmlHandler.java293
-rw-r--r--src/main/java/com/lowagie/text/html/simpleparser/ALink.java57
-rw-r--r--src/main/java/com/lowagie/text/html/simpleparser/ChainedProperties.java127
-rw-r--r--src/main/java/com/lowagie/text/html/simpleparser/FactoryProperties.java244
-rw-r--r--src/main/java/com/lowagie/text/html/simpleparser/HTMLWorker.java623
-rw-r--r--src/main/java/com/lowagie/text/html/simpleparser/Img.java60
-rw-r--r--src/main/java/com/lowagie/text/html/simpleparser/IncCell.java124
-rw-r--r--src/main/java/com/lowagie/text/html/simpleparser/IncTable.java121
-rw-r--r--src/main/java/com/lowagie/text/html/simpleparser/StyleSheet.java112
15 files changed, 4011 insertions, 0 deletions
diff --git a/src/main/java/com/lowagie/text/html/HtmlEncoder.java b/src/main/java/com/lowagie/text/html/HtmlEncoder.java
new file mode 100644
index 0000000..2501815
--- /dev/null
+++ b/src/main/java/com/lowagie/text/html/HtmlEncoder.java
@@ -0,0 +1,211 @@
+/*
+ * $Id: HtmlEncoder.java,v 1.56 2005/05/04 14:33:47 blowagie 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.awt.Color;
+
+import com.lowagie.text.Element;
+
+/**
+ * This class converts a <CODE>String</CODE> to the HTML-format of a String.
+ * <P>
+ * To convert the <CODE>String</CODE>, each character is examined:
+ * <UL>
+ * <LI>ASCII-characters from 000 till 031 are represented as &amp;#xxx;<BR>
+ * (with xxx = the value of the character)
+ * <LI>ASCII-characters from 032 t/m 127 are represented by the character itself, except for:
+ * <UL>
+ * <LI>'\n' becomes &lt;BR&gt;\n
+ * <LI>&quot; becomes &amp;quot;
+ * <LI>&amp; becomes &amp;amp;
+ * <LI>&lt; becomes &amp;lt;
+ * <LI>&gt; becomes &amp;gt;
+ * </UL>
+ * <LI>ASCII-characters from 128 till 255 are represented as &amp;#xxx;<BR>
+ * (with xxx = the value of the character)
+ * </UL>
+ * <P>
+ * Example:
+ * <P><BLOCKQUOTE><PRE>
+ * String htmlPresentation = HtmlEncoder.encode("Marie-Th&#233;r&#232;se S&#248;rensen");
+ * </PRE></BLOCKQUOTE><P>
+ * for more info: see O'Reilly; "HTML: The Definitive Guide" (page 164)
+ *
+ * @author mario.maccarini@rug.ac.be
+ */
+
+public class HtmlEncoder {
+
+ // membervariables
+
+/** List with the HTML translation of all the characters. */
+ private static final String[] htmlCode = new String[256];
+
+ static {
+ for (int i = 0; i < 10; i++) {
+ htmlCode[i] = "&#00" + i + ";";
+ }
+
+ for (int i = 10; i < 32; i++) {
+ htmlCode[i] = "&#0" + i + ";";
+ }
+
+ for (int i = 32; i < 128; i++) {
+ htmlCode[i] = String.valueOf((char)i);
+ }
+
+ // Special characters
+ htmlCode['\t'] = "\t";
+ htmlCode['\n'] = "<" + HtmlTags.NEWLINE + " />\n";
+ htmlCode['\"'] = "&quot;"; // double quote
+ htmlCode['&'] = "&amp;"; // ampersand
+ htmlCode['<'] = "&lt;"; // lower than
+ htmlCode['>'] = "&gt;"; // greater than
+
+ for (int i = 128; i < 256; i++) {
+ htmlCode[i] = "&#" + i + ";";
+ }
+ }
+
+
+ // constructors
+
+/**
+ * This class will never be constructed.
+ * <P>
+ * HtmlEncoder only contains static methods.
+ */
+
+ private HtmlEncoder () { }
+
+ // methods
+
+/**
+ * Converts a <CODE>String</CODE> to the HTML-format of this <CODE>String</CODE>.
+ *
+ * @param string The <CODE>String</CODE> to convert
+ * @return a <CODE>String</CODE>
+ */
+
+ public static String encode(String string) {
+ int n = string.length();
+ char character;
+ StringBuffer buffer = new StringBuffer();
+ // loop over all the characters of the String.
+ for (int i = 0; i < n; i++) {
+ character = string.charAt(i);
+ // the Htmlcode of these characters are added to a StringBuffer one by one
+ if (character < 256) {
+ buffer.append(htmlCode[character]);
+ }
+ else {
+ // Improvement posted by Joachim Eyrich
+ buffer.append("&#").append((int)character).append(";");
+ }
+ }
+ return buffer.toString().trim();
+ }
+
+/**
+ * Converts a <CODE>Color</CODE> into a HTML representation of this <CODE>Color</CODE>.
+ *
+ * @param color the <CODE>Color</CODE> that has to be converted.
+ * @return the HTML representation of this <COLOR>Color</COLOR>
+ */
+
+ public static String encode(Color color) {
+ StringBuffer buffer = new StringBuffer("#");
+ if (color.getRed() < 16) {
+ buffer.append('0');
+ }
+ buffer.append(Integer.toString(color.getRed(), 16));
+ if (color.getGreen() < 16) {
+ buffer.append('0');
+ }
+ buffer.append(Integer.toString(color.getGreen(), 16));
+ if (color.getBlue() < 16) {
+ buffer.append('0');
+ }
+ buffer.append(Integer.toString(color.getBlue(), 16));
+ return buffer.toString();
+ }
+
+/**
+ * Translates the alignment value.
+ *
+ * @param alignment the alignment value
+ * @return the translated value
+ */
+
+ public static String getAlignment(int alignment) {
+ switch(alignment) {
+ case Element.ALIGN_LEFT:
+ return HtmlTags.ALIGN_LEFT;
+ case Element.ALIGN_CENTER:
+ return HtmlTags.ALIGN_CENTER;
+ case Element.ALIGN_RIGHT:
+ return HtmlTags.ALIGN_RIGHT;
+ case Element.ALIGN_JUSTIFIED:
+ case Element.ALIGN_JUSTIFIED_ALL:
+ return HtmlTags.ALIGN_JUSTIFIED;
+ case Element.ALIGN_TOP:
+ return HtmlTags.ALIGN_TOP;
+ case Element.ALIGN_MIDDLE:
+ return HtmlTags.ALIGN_MIDDLE;
+ case Element.ALIGN_BOTTOM:
+ return HtmlTags.ALIGN_BOTTOM;
+ case Element.ALIGN_BASELINE:
+ return HtmlTags.ALIGN_BASELINE;
+ default:
+ return "";
+ }
+ }
+} \ No newline at end of file
diff --git a/src/main/java/com/lowagie/text/html/HtmlParser.java b/src/main/java/com/lowagie/text/html/HtmlParser.java
new file mode 100644
index 0000000..ba46998
--- /dev/null
+++ b/src/main/java/com/lowagie/text/html/HtmlParser.java
@@ -0,0 +1,206 @@
+/*
+ * $Id: HtmlParser.java,v 1.12 2005/11/29 16:00:10 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 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.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+import com.lowagie.text.DocumentException;
+import com.lowagie.text.ExceptionConverter;
+import com.lowagie.text.DocListener;
+import com.lowagie.text.xml.XmlParser;
+
+/**
+ * This class can be used to parse some HTML files.
+ */
+
+public class HtmlParser extends XmlParser {
+
+/**
+ * Constructs an HtmlParser.
+ */
+
+ public HtmlParser() {
+ super();
+ }
+
+/**
+ * Parses a given file.
+ * @param document the document the parser will write to
+ * @param is the InputSource with the content
+ */
+
+ public void go(DocListener document, InputSource is) {
+ try {
+ parser.parse(is, new SAXmyHtmlHandler(document));
+ }
+ catch(SAXException se) {
+ throw new ExceptionConverter(se);
+ }
+ catch(IOException ioe) {
+ throw new ExceptionConverter(ioe);
+ }
+ catch(DocumentException de) {
+ throw new ExceptionConverter(de);
+ }
+ }
+
+/**
+ * Parses a given file that validates with the iText DTD and writes the content to a document.
+ * @param document the document the parser will write to
+ * @param is the InputSource with the content
+ */
+
+ public static void parse(DocListener document, InputSource is) {
+ HtmlParser p = new HtmlParser();
+ p.go(document, is);
+ }
+
+/**
+ * Parses a given file.
+ * @param document the document the parser will write to
+ * @param file the file with the content
+ */
+
+ public void go(DocListener document, String file) {
+ try {
+ parser.parse(file, new SAXmyHtmlHandler(document));
+ }
+ catch(SAXException se) {
+ throw new ExceptionConverter(se);
+ }
+ catch(IOException ioe) {
+ throw new ExceptionConverter(ioe);
+ }
+ catch(DocumentException de) {
+ throw new ExceptionConverter(de);
+ }
+ }
+
+/**
+ * Parses a given file that validates with the iText DTD and writes the content to a document.
+ * @param document the document the parser will write to
+ * @param file the file with the content
+ */
+
+ public static void parse(DocListener document, String file) {
+ HtmlParser p = new HtmlParser();
+ p.go(document, file);
+ }
+
+/**
+ * Parses a given file.
+ * @param document the document the parser will write to
+ * @param is the InputStream with the content
+ */
+
+ public void go(DocListener document, InputStream is) {
+ try {
+ parser.parse(new InputSource(is), new SAXmyHtmlHandler(document));
+ }
+ catch(SAXException se) {
+ throw new ExceptionConverter(se);
+ }
+ catch(IOException ioe) {
+ throw new ExceptionConverter(ioe);
+ }
+ catch(DocumentException de) {
+ throw new ExceptionConverter(de);
+ }
+ }
+
+/**
+ * Parses a given file that validates with the iText DTD and writes the content to a document.
+ * @param document the document the parser will write to
+ * @param is the InputStream with the content
+ */
+
+ public static void parse(DocListener document, InputStream is) {
+ HtmlParser p = new HtmlParser();
+ p.go(document, new InputSource(is));
+ }
+
+/**
+ * Parses a given file.
+ * @param document the document the parser will write to
+ * @param is the Reader with the content
+ */
+
+ public void go(DocListener document, Reader is) {
+ try {
+ parser.parse(new InputSource(is), new SAXmyHtmlHandler(document));
+ }
+ catch(SAXException se) {
+ throw new ExceptionConverter(se);
+ }
+ catch(IOException ioe) {
+ throw new ExceptionConverter(ioe);
+ }
+ catch(DocumentException de) {
+ throw new ExceptionConverter(de);
+ }
+ }
+
+/**
+ * Parses a given file that validates with the iText DTD and writes the content to a document.
+ * @param document the document the parser will write to
+ * @param is the Reader with the content
+ */
+
+ public static void parse(DocListener document, Reader is) {
+ HtmlParser p = new HtmlParser();
+ p.go(document, new InputSource(is));
+ }
+} \ No newline at end of file
diff --git a/src/main/java/com/lowagie/text/html/HtmlPeer.java b/src/main/java/com/lowagie/text/html/HtmlPeer.java
new file mode 100644
index 0000000..44a7a25
--- /dev/null
+++ b/src/main/java/com/lowagie/text/html/HtmlPeer.java
@@ -0,0 +1,112 @@
+/*
+ * $Id: HtmlPeer.java,v 1.9 2006/03/23 09:51:50 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 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.util.Properties;
+
+import org.xml.sax.Attributes;
+
+import com.lowagie.text.ElementTags;
+import com.lowagie.text.xml.XmlPeer;
+
+/**
+ * This interface is implemented by the peer of all the iText objects.
+ */
+
+public class HtmlPeer extends XmlPeer {
+
+ /**
+ * Creates a XmlPeer.
+ *
+ * @param name
+ * the iText name of the tag
+ * @param alias
+ * the Html name of the tag
+ */
+
+ public HtmlPeer(String name, String alias) {
+ super(name, alias.toLowerCase());
+ }
+
+ /**
+ * Sets an alias for an attribute.
+ *
+ * @param name
+ * the iText tagname
+ * @param alias
+ * the custom tagname
+ */
+
+ public void addAlias(String name, String alias) {
+ attributeAliases.put(alias.toLowerCase(), name);
+ }
+
+ /**
+ * @see com.lowagie.text.xml.XmlPeer#getAttributes(org.xml.sax.Attributes)
+ */
+ public Properties getAttributes(Attributes attrs) {
+ Properties attributes = new Properties();
+ attributes.putAll(attributeValues);
+ if (defaultContent != null) {
+ attributes.put(ElementTags.ITEXT, defaultContent);
+ }
+ if (attrs != null) {
+ String attribute, value;
+ for (int i = 0; i < attrs.getLength(); i++) {
+ attribute = getName(attrs.getQName(i).toLowerCase());
+ value = attrs.getValue(i).toLowerCase();
+ attributes.setProperty(attribute, value);
+ }
+ }
+ return attributes;
+ }
+}
+
diff --git a/src/main/java/com/lowagie/text/html/HtmlTagMap.java b/src/main/java/com/lowagie/text/html/HtmlTagMap.java
new file mode 100644
index 0000000..bd7ef81
--- /dev/null
+++ b/src/main/java/com/lowagie/text/html/HtmlTagMap.java
@@ -0,0 +1,296 @@
+/*
+ * $Id: HtmlTagMap.java,v 1.15 2005/05/03 14:43:59 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 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.util.HashMap;
+
+import com.lowagie.text.ElementTags;
+import com.lowagie.text.FontFactory;
+import com.lowagie.text.markup.MarkupTags;
+
+/**
+ * The <CODE>Tags</CODE>-class maps several XHTML-tags to iText-objects.
+ */
+
+public class HtmlTagMap extends HashMap {
+
+/**
+ * Constructs an HtmlTagMap.
+ */
+
+ public HtmlTagMap() {
+ super();
+ HtmlPeer peer;
+
+ peer = new HtmlPeer(ElementTags.ITEXT, HtmlTags.HTML);
+ put(peer.getAlias(), peer);
+
+ peer = new HtmlPeer(ElementTags.PHRASE, HtmlTags.SPAN);
+ put(peer.getAlias(), peer);
+
+ peer = new HtmlPeer(ElementTags.CHUNK, HtmlTags.CHUNK);
+ peer.addAlias(ElementTags.FONT, HtmlTags.FONT);
+ peer.addAlias(ElementTags.SIZE, HtmlTags.SIZE);
+ peer.addAlias(ElementTags.COLOR, HtmlTags.COLOR);
+ put(peer.getAlias(), peer);
+
+ peer = new HtmlPeer(ElementTags.ANCHOR, HtmlTags.ANCHOR);
+ peer.addAlias(ElementTags.NAME, HtmlTags.NAME);
+ peer.addAlias(ElementTags.REFERENCE, HtmlTags.REFERENCE);
+ put(peer.getAlias(), peer);
+
+ peer = new HtmlPeer(ElementTags.PARAGRAPH, HtmlTags.PARAGRAPH);
+ peer.addAlias(ElementTags.ALIGN, HtmlTags.ALIGN);
+ put(peer.getAlias(), peer);
+
+ peer = new HtmlPeer(ElementTags.PARAGRAPH, HtmlTags.DIV);
+ peer.addAlias(ElementTags.ALIGN, HtmlTags.ALIGN);
+ put(peer.getAlias(), peer);
+
+ peer = new HtmlPeer(ElementTags.PARAGRAPH, HtmlTags.H[0]);
+ peer.addValue(ElementTags.SIZE, "20");
+ put(peer.getAlias(), peer);
+
+ peer = new HtmlPeer(ElementTags.PARAGRAPH, HtmlTags.H[1]);
+ peer.addValue(ElementTags.SIZE, "18");
+ put(peer.getAlias(), peer);
+
+ peer = new HtmlPeer(ElementTags.PARAGRAPH, HtmlTags.H[2]);
+ peer.addValue(ElementTags.SIZE, "16");
+ put(peer.getAlias(), peer);
+
+ peer = new HtmlPeer(ElementTags.PARAGRAPH, HtmlTags.H[3]);
+ peer.addValue(ElementTags.SIZE, "14");
+ put(peer.getAlias(), peer);
+
+ peer = new HtmlPeer(ElementTags.PARAGRAPH, HtmlTags.H[4]);
+ peer.addValue(ElementTags.SIZE, "12");
+ put(peer.getAlias(), peer);
+
+ peer = new HtmlPeer(ElementTags.PARAGRAPH, HtmlTags.H[5]);
+ peer.addValue(ElementTags.SIZE, "10");
+ put(peer.getAlias(), peer);
+
+ peer = new HtmlPeer(ElementTags.LIST, HtmlTags.ORDEREDLIST);
+ peer.addValue(ElementTags.NUMBERED, "true");
+ peer.addValue(ElementTags.SYMBOLINDENT, "20");
+ put(peer.getAlias(), peer);
+
+ peer = new HtmlPeer(ElementTags.LIST, HtmlTags.UNORDEREDLIST);
+ peer.addValue(ElementTags.NUMBERED, "false");
+ peer.addValue(ElementTags.SYMBOLINDENT, "20");
+ put(peer.getAlias(), peer);
+
+ peer = new HtmlPeer(ElementTags.LISTITEM, HtmlTags.LISTITEM);
+ put(peer.getAlias(), peer);
+
+ peer = new HtmlPeer(ElementTags.PHRASE, HtmlTags.I);
+ peer.addValue(ElementTags.STYLE, MarkupTags.CSS_VALUE_ITALIC);
+ put(peer.getAlias(), peer);
+
+ peer = new HtmlPeer(ElementTags.PHRASE, HtmlTags.EM);
+ peer.addValue(ElementTags.STYLE, MarkupTags.CSS_VALUE_ITALIC);
+ put(peer.getAlias(), peer);
+
+ peer = new HtmlPeer(ElementTags.PHRASE, HtmlTags.B);
+ peer.addValue(ElementTags.STYLE, MarkupTags.CSS_VALUE_BOLD);
+ put(peer.getAlias(), peer);
+
+ peer = new HtmlPeer(ElementTags.PHRASE, HtmlTags.STRONG);
+ peer.addValue(ElementTags.STYLE, MarkupTags.CSS_VALUE_BOLD);
+ put(peer.getAlias(), peer);
+
+ peer = new HtmlPeer(ElementTags.PHRASE, HtmlTags.S);
+ peer.addValue(ElementTags.STYLE, MarkupTags.CSS_VALUE_LINETHROUGH);
+ put(peer.getAlias(), peer);
+
+ peer = new HtmlPeer(ElementTags.PHRASE, HtmlTags.CODE);
+ peer.addValue(ElementTags.FONT, FontFactory.COURIER);
+ put(peer.getAlias(), peer);
+
+ peer = new HtmlPeer(ElementTags.PHRASE, HtmlTags.VAR);
+ peer.addValue(ElementTags.FONT, FontFactory.COURIER);
+ peer.addValue(ElementTags.STYLE, MarkupTags.CSS_VALUE_ITALIC);
+ put(peer.getAlias(), peer);
+
+ peer = new HtmlPeer(ElementTags.PHRASE, HtmlTags.U);
+ peer.addValue(ElementTags.STYLE, MarkupTags.CSS_VALUE_UNDERLINE);
+ put(peer.getAlias(), peer);
+
+ peer = new HtmlPeer(ElementTags.CHUNK, HtmlTags.SUP);
+ peer.addValue(ElementTags.SUBSUPSCRIPT, "6.0");
+ put(peer.getAlias(), peer);
+
+ peer = new HtmlPeer(ElementTags.CHUNK, HtmlTags.SUB);
+ peer.addValue(ElementTags.SUBSUPSCRIPT, "-6.0");
+ put(peer.getAlias(), peer);
+
+ peer = new HtmlPeer(ElementTags.HORIZONTALRULE, HtmlTags.HORIZONTALRULE);
+ put(peer.getAlias(), peer);
+
+ peer = new HtmlPeer(ElementTags.TABLE, HtmlTags.TABLE);
+ peer.addAlias(ElementTags.WIDTH, HtmlTags.WIDTH);
+ peer.addAlias(ElementTags.BACKGROUNDCOLOR, HtmlTags.BACKGROUNDCOLOR);
+ peer.addAlias(ElementTags.BORDERCOLOR, HtmlTags.BORDERCOLOR);
+ peer.addAlias(ElementTags.COLUMNS, HtmlTags.COLUMNS);
+ peer.addAlias(ElementTags.CELLPADDING, HtmlTags.CELLPADDING);
+ peer.addAlias(ElementTags.CELLSPACING, HtmlTags.CELLSPACING);
+ peer.addAlias(ElementTags.BORDERWIDTH, HtmlTags.BORDERWIDTH);
+ peer.addAlias(ElementTags.ALIGN, HtmlTags.ALIGN);
+ put(peer.getAlias(), peer);
+
+ peer = new HtmlPeer(ElementTags.ROW, HtmlTags.ROW);
+ put(peer.getAlias(), peer);
+
+ peer = new HtmlPeer(ElementTags.CELL, HtmlTags.CELL);
+ peer.addAlias(ElementTags.WIDTH, HtmlTags.WIDTH);
+ peer.addAlias(ElementTags.BACKGROUNDCOLOR, HtmlTags.BACKGROUNDCOLOR);
+ peer.addAlias(ElementTags.BORDERCOLOR, HtmlTags.BORDERCOLOR);
+ peer.addAlias(ElementTags.COLSPAN, HtmlTags.COLSPAN);
+ peer.addAlias(ElementTags.ROWSPAN, HtmlTags.ROWSPAN);
+ peer.addAlias(ElementTags.NOWRAP, HtmlTags.NOWRAP);
+ peer.addAlias(ElementTags.HORIZONTALALIGN, HtmlTags.HORIZONTALALIGN);
+ peer.addAlias(ElementTags.VERTICALALIGN, HtmlTags.VERTICALALIGN);
+ peer.addValue(ElementTags.HEADER, "false");
+ put(peer.getAlias(), peer);
+
+ peer = new HtmlPeer(ElementTags.CELL, HtmlTags.HEADERCELL);
+ peer.addAlias(ElementTags.WIDTH, HtmlTags.WIDTH);
+ peer.addAlias(ElementTags.BACKGROUNDCOLOR, HtmlTags.BACKGROUNDCOLOR);
+ peer.addAlias(ElementTags.BORDERCOLOR, HtmlTags.BORDERCOLOR);
+ peer.addAlias(ElementTags.COLSPAN, HtmlTags.COLSPAN);
+ peer.addAlias(ElementTags.ROWSPAN, HtmlTags.ROWSPAN);
+ peer.addAlias(ElementTags.NOWRAP, HtmlTags.NOWRAP);
+ peer.addAlias(ElementTags.HORIZONTALALIGN, HtmlTags.HORIZONTALALIGN);
+ peer.addAlias(ElementTags.VERTICALALIGN, HtmlTags.VERTICALALIGN);
+ peer.addValue(ElementTags.HEADER, "true");
+ put(peer.getAlias(), peer);
+
+ peer = new HtmlPeer(ElementTags.IMAGE, HtmlTags.IMAGE);
+ peer.addAlias(ElementTags.URL, HtmlTags.URL);
+ peer.addAlias(ElementTags.ALT, HtmlTags.ALT);
+ peer.addAlias(ElementTags.PLAINWIDTH, HtmlTags.PLAINWIDTH);
+ peer.addAlias(ElementTags.PLAINHEIGHT, HtmlTags.PLAINHEIGHT);
+ put(peer.getAlias(), peer);
+
+ peer = new HtmlPeer(ElementTags.NEWLINE, HtmlTags.NEWLINE);
+ put(peer.getAlias(), peer);
+ }
+
+/**
+ * Checks if this is the root tag.
+ * @param tag a tagvalue
+ * @return true if tag is HTML or html
+ */
+
+ public boolean isHtml(String tag) {
+ return HtmlTags.HTML.equalsIgnoreCase(tag);
+ }
+
+/**
+ * Checks if this is the head tag.
+ * @param tag a tagvalue
+ * @return true if tag is HEAD or head
+ */
+
+ public boolean isHead(String tag) {
+ return HtmlTags.HEAD.equalsIgnoreCase(tag);
+ }
+
+/**
+ * Checks if this is the meta tag.
+ * @param tag a tagvalue
+ * @return true if tag is META or meta
+ */
+
+ public boolean isMeta(String tag) {
+ return HtmlTags.META.equalsIgnoreCase(tag);
+ }
+
+/**
+ * Checks if this is the linl tag.
+ * @param tag a tagvalue
+ * @return true if tag is LINK or link
+ */
+
+ public boolean isLink(String tag) {
+ return HtmlTags.LINK.equalsIgnoreCase(tag);
+ }
+
+/**
+ * Checks if this is the title tag.
+ * @param tag a tagvalue
+ * @return true if tag is TITLE or title
+ */
+
+ public boolean isTitle(String tag) {
+ return HtmlTags.TITLE.equalsIgnoreCase(tag);
+ }
+
+/**
+ * Checks if this is the root tag.
+ * @param tag a tagvalue
+ * @return true if tag is BODY or body
+ */
+
+ public boolean isBody(String tag) {
+ return HtmlTags.BODY.equalsIgnoreCase(tag);
+ }
+
+/**
+ * Checks if this is a special tag.
+ * @param tag a tagvalue
+ * @return true if tag is a HTML, HEAD, META, LINK or BODY tag (case insensitive)
+ */
+ public boolean isSpecialTag(String tag) {
+ return isHtml(tag) || isHead(tag) || isMeta(tag) || isLink(tag) || isBody(tag);
+ }
+} \ No newline at end of file
diff --git a/src/main/java/com/lowagie/text/html/HtmlTags.java b/src/main/java/com/lowagie/text/html/HtmlTags.java
new file mode 100644
index 0000000..43dbcc4
--- /dev/null
+++ b/src/main/java/com/lowagie/text/html/HtmlTags.java
@@ -0,0 +1,331 @@
+/*
+ * $Id: HtmlTags.java,v 1.69 2005/05/03 14:43:58 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 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;
+
+/**
+ * A class that contains all the possible tagnames and their attributes.
+ */
+
+public class HtmlTags {
+
+/** the root tag. */
+ public static final String HTML = "html";
+
+/** the head tag */
+ public static final String HEAD = "head";
+
+/** This is a possible HTML attribute for the HEAD tag. */
+ public static final String CONTENT = "content";
+
+/** the meta tag */
+ public static final String META = "meta";
+
+/** attribute of the root tag */
+ public static final String SUBJECT = "subject";
+
+/** attribute of the root tag */
+ public static final String KEYWORDS = "keywords";
+
+/** attribute of the root tag */
+ public static final String AUTHOR = "author";
+
+/** the title tag. */
+ public static final String TITLE = "title";
+
+/** the script tag. */
+ public static final String SCRIPT = "script";
+
+/** This is a possible HTML attribute for the SCRIPT tag. */
+ public static final String LANGUAGE = "language";
+
+/** This is a possible value for the LANGUAGE attribute. */
+ public static final String JAVASCRIPT = "JavaScript";
+
+/** the body tag. */
+ public static final String BODY = "body";
+
+/** This is a possible HTML attribute for the BODY tag */
+ public static final String JAVASCRIPT_ONLOAD = "onLoad";
+
+/** This is a possible HTML attribute for the BODY tag */
+ public static final String JAVASCRIPT_ONUNLOAD = "onUnLoad";
+
+/** This is a possible HTML attribute for the BODY tag. */
+ public static final String TOPMARGIN = "topmargin";
+
+/** This is a possible HTML attribute for the BODY tag. */
+ public static final String BOTTOMMARGIN = "bottommargin";
+
+/** This is a possible HTML attribute for the BODY tag. */
+ public static final String LEFTMARGIN = "leftmargin";
+
+/** This is a possible HTML attribute for the BODY tag. */
+ public static final String RIGHTMARGIN = "rightmargin";
+
+ // Phrases, Anchors, Lists and Paragraphs
+
+/** the chunk tag */
+ public static final String CHUNK = "font";
+
+/** the phrase tag */
+ public static final String CODE = "code";
+
+/** the phrase tag */
+ public static final String VAR = "var";
+
+/** the anchor tag */
+ public static final String ANCHOR = "a";
+
+/** the list tag */
+ public static final String ORDEREDLIST = "ol";
+
+/** the list tag */
+ public static final String UNORDEREDLIST = "ul";
+
+/** the listitem tag */
+ public static final String LISTITEM = "li";
+
+/** the paragraph tag */
+ public static final String PARAGRAPH = "p";
+
+/** attribute of anchor tag */
+ public static final String NAME = "name";
+
+/** attribute of anchor tag */
+ public static final String REFERENCE = "href";
+
+/** attribute of anchor tag */
+ public static final String[] H = new String[6];
+ static {
+ H[0] = "h1";
+ H[1] = "h2";
+ H[2] = "h3";
+ H[3] = "h4";
+ H[4] = "h5";
+ H[5] = "h6";
+ }
+
+ // Chunks
+
+/** attribute of the chunk tag */
+ public static final String FONT = "face";
+
+/** attribute of the chunk tag */
+ public static final String SIZE = "point-size";
+
+/** attribute of the chunk/table/cell tag */
+ public static final String COLOR = "color";
+
+/** some phrase tag */
+ public static final String EM = "em";
+
+/** some phrase tag */
+ public static final String I = "i";
+
+/** some phrase tag */
+ public static final String STRONG = "strong";
+
+/** some phrase tag */
+ public static final String B = "b";
+
+/** some phrase tag */
+ public static final String S = "s";
+
+/** some phrase tag */
+ public static final String U = "u";
+
+/** some phrase tag */
+ public static final String SUB = "sub";
+
+/** some phrase tag */
+ public static final String SUP = "sup";
+
+/** the possible value of a tag */
+ public static final String HORIZONTALRULE = "hr";
+
+ // tables/cells
+
+/** the table tag */
+ public static final String TABLE = "table";
+
+/** the cell tag */
+ public static final String ROW = "tr";
+
+/** the cell tag */
+ public static final String CELL = "td";
+
+/** attribute of the cell tag */
+ public static final String HEADERCELL = "th";
+
+/** attribute of the table tag */
+ public static final String COLUMNS = "cols";
+
+/** attribute of the table tag */
+ public static final String CELLPADDING = "cellpadding";
+
+/** attribute of the table tag */
+ public static final String CELLSPACING = "cellspacing";
+
+/** attribute of the cell tag */
+ public static final String COLSPAN = "colspan";
+
+/** attribute of the cell tag */
+ public static final String ROWSPAN = "rowspan";
+
+/** attribute of the cell tag */
+ public static final String NOWRAP = "nowrap";
+
+/** attribute of the table/cell tag */
+ public static final String BORDERWIDTH = "border";
+
+/** attribute of the table/cell tag */
+ public static final String WIDTH = "width";
+
+/** attribute of the table/cell tag */
+ public static final String BACKGROUNDCOLOR = "bgcolor";
+
+/** attribute of the table/cell tag */
+ public static final String BORDERCOLOR = "bordercolor";
+
+/** attribute of paragraph/image/table tag */
+ public static final String ALIGN = "align";
+
+/** attribute of chapter/section/paragraph/table/cell tag */
+ public static final String LEFT = "left";
+
+/** attribute of chapter/section/paragraph/table/cell tag */
+ public static final String RIGHT = "right";
+
+/** attribute of the cell tag */
+ public static final String HORIZONTALALIGN = "align";
+
+/** attribute of the cell tag */
+ public static final String VERTICALALIGN = "valign";
+
+/** attribute of the table/cell tag */
+ public static final String TOP = "top";
+
+/** attribute of the table/cell tag */
+ public static final String BOTTOM = "bottom";
+
+ // Misc
+
+/** the image tag */
+ public static final String IMAGE = "img";
+
+/** attribute of the image tag */
+ public static final String URL = "src";
+
+/** attribute of the image tag */
+ public static final String ALT = "alt";
+
+/** attribute of the image tag */
+ public static final String PLAINWIDTH = "width";
+
+/** attribute of the image tag */
+ public static final String PLAINHEIGHT = "height";
+
+/** the newpage tag */
+ public static final String NEWLINE = "br";
+
+ // alignment attribute values
+
+/** the possible value of an alignment attribute */
+ public static final String ALIGN_LEFT = "Left";
+
+/** the possible value of an alignment attribute */
+ public static final String ALIGN_CENTER = "Center";
+
+/** the possible value of an alignment attribute */
+ public static final String ALIGN_RIGHT = "Right";
+
+/** the possible value of an alignment attribute */
+ public static final String ALIGN_JUSTIFIED = "Justify";
+
+/** the possible value of an alignment attribute */
+ public static final String ALIGN_TOP = "Top";
+
+/** the possible value of an alignment attribute */
+ public static final String ALIGN_MIDDLE = "Middle";
+
+/** the possible value of an alignment attribute */
+ public static final String ALIGN_BOTTOM = "Bottom";
+
+/** the possible value of an alignment attribute */
+ public static final String ALIGN_BASELINE = "Baseline";
+
+/** the possible value of an alignment attribute */
+ public static final String DEFAULT = "Default";
+
+ /** The DIV tag. */
+ public static final String DIV = "div";
+
+ /** The SPAN tag. */
+ public static final String SPAN = "span";
+ /** The LINK tag. */
+ public static final String LINK = "link";
+
+ /** This is a possible HTML attribute for the LINK tag. */
+ public static final String TEXT_CSS = "text/css";
+
+ /** This is a possible HTML attribute for the LINK tag. */
+ public static final String REL = "rel";
+
+ /** This is used for inline css style information */
+ public static final String STYLE = "style";
+
+ /** This is a possible HTML attribute for the LINK tag. */
+ public static final String TYPE = "type";
+
+ /** This is a possible HTML attribute. */
+ public static final String STYLESHEET = "stylesheet";
+
+} \ No newline at end of file
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 <CODE>DocWriter</CODE> class for HTML.
+ * <P>
+ * An <CODE>HtmlWriter</CODE> can be added as a <CODE>DocListener</CODE>
+ * to a certain <CODE>Document</CODE> by getting an instance.
+ * Every <CODE>Element</CODE> added to the original <CODE>Document</CODE>
+ * will be written to the <CODE>OutputStream</CODE> of this <CODE>HtmlWriter</CODE>.
+ * <P>
+ * Example:
+ * <BLOCKQUOTE><PRE>
+ * // 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
+ * <STRONG>HtmlWriter.getInstance(document, System.out);</STRONG>
+ * // this will write HTML to a file called text.html
+ * <STRONG>HtmlWriter.getInstance(document, new FileOutputStream("text.html"));</STRONG>
+ * // this will write HTML to for instance the OutputStream of a HttpServletResponse-object
+ * <STRONG>HtmlWriter.getInstance(document, response.getOutputStream());</STRONG>
+ * }
+ * catch(DocumentException de) {
+ * System.err.println(de.getMessage());
+ * }
+ * // this will close the document and all the OutputStreams listening to it
+ * <STRONG>document.close();</CODE>
+ * </PRE></BLOCKQUOTE>
+ */
+
+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 byte[] ENDCOMMENT = getISOBytes(" -->");
+
+/** This is a possible HTML-tag. */
+ public static final String NBSP = "&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 <CODE>HtmlWriter</CODE>.
+ *
+ * @param doc The <CODE>Document</CODE> that has to be written as HTML
+ * @param os The <CODE>OutputStream</CODE> 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 <CODE>HtmlWriter</CODE>.
+ *
+ * @param document The <CODE>Document</CODE> that has to be written
+ * @param os The <CODE>OutputStream</CODE> the writer has to write to.
+ * @return a new <CODE>HtmlWriter</CODE>
+ */
+
+ 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 <CODE>true</CODE> if this action succeeded, <CODE>false</CODE> 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 <CODE>Element</CODE> was added to the <CODE>Document</CODE>.
+ *
+ * @param element a high level object that has to be translated to HTML
+ * @return <CODE>true</CODE> if the element was added, <CODE>false</CODE> 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 <CODE>Document</CODE> has been opened and that
+ * <CODE>Elements</CODE> can be added.
+ * <P>
+ * The <CODE>HEAD</CODE>-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 <CODE>Document</CODE> was closed and that no other
+ * <CODE>Elements</CODE> 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 </CODE>Document</CODE>
+ */
+
+ 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 </CODE>Document</CODE>
+ */
+
+ 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:
+ *
+ * <script language="JavaScript" src="/myPath/MyFunctions.js"/>
+ */
+ write(HtmlTags.URL, header.getMarkupAttribute(HtmlTags.URL));
+ os.write(GT);
+ writeEnd(HtmlTags.SCRIPT);
+ }
+ else {
+ /* JavaScript coding convention:
+ *
+ * <script language="JavaScript" type="text/javascript">
+ * <!--
+ * // ... JavaScript methods ...
+ * //-->
+ * </script>
+ */
+ 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.
+ * <P>
+ * 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.
+ * <P>
+ * 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 <CODE>String</CODE> was added to the <CODE>Document</CODE>.
+ *
+ * @param string a String to add to the HTML
+ * @return <CODE>true</CODE> if the string was added, <CODE>false</CODE> 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 <CODE>Font</CODE>.
+ *
+ * @param font a <CODE>Font</CODE>
+ * @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
diff --git a/src/main/java/com/lowagie/text/html/SAXmyHtmlHandler.java b/src/main/java/com/lowagie/text/html/SAXmyHtmlHandler.java
new file mode 100644
index 0000000..76c2e6a
--- /dev/null
+++ b/src/main/java/com/lowagie/text/html/SAXmyHtmlHandler.java
@@ -0,0 +1,293 @@
+/*
+ * $Id: SAXmyHtmlHandler.java,v 1.25 2006/03/23 09:51:50 blowagie Exp $
+ * $Name: $
+ *
+ * Copyright 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.IOException;
+import java.util.HashMap;
+import java.util.Properties;
+
+import org.xml.sax.Attributes;
+
+import com.lowagie.text.Cell;
+import com.lowagie.text.DocListener;
+import com.lowagie.text.DocumentException;
+import com.lowagie.text.Element;
+import com.lowagie.text.ElementTags;
+import com.lowagie.text.ExceptionConverter;
+import com.lowagie.text.Paragraph;
+import com.lowagie.text.Table;
+import com.lowagie.text.html.HtmlTagMap;
+import com.lowagie.text.html.HtmlTags;
+import com.lowagie.text.pdf.BaseFont;
+import com.lowagie.text.xml.SAXiTextHandler;
+import com.lowagie.text.xml.XmlPeer;
+
+/**
+ * The <CODE>Tags</CODE>-class maps several XHTML-tags to iText-objects.
+ */
+
+public class SAXmyHtmlHandler extends SAXiTextHandler // SAXmyHandler
+{
+
+ /** These are the properties of the body section. */
+ private Properties bodyAttributes = new Properties();
+
+ /** This is the status of the table border. */
+ private boolean tableBorder = false;
+
+ /**
+ * Constructs a new SAXiTextHandler that will translate all the events
+ * triggered by the parser to actions on the <CODE>Document</CODE>-object.
+ *
+ * @param document
+ * this is the document on which events must be triggered
+ * @throws IOException
+ * @throws DocumentException
+ */
+
+ public SAXmyHtmlHandler(DocListener document)
+ throws DocumentException, IOException {
+ super(document, new HtmlTagMap());
+ }
+ /**
+ * Constructs a new SAXiTextHandler that will translate all the events
+ * triggered by the parser to actions on the <CODE>Document</CODE>-object.
+ *
+ * @param document
+ * this is the document on which events must be triggered
+ * @param bf
+ * @throws IOException
+ * @throws DocumentException
+ */
+
+ public SAXmyHtmlHandler(DocListener document, BaseFont bf)
+ throws DocumentException, IOException {
+ super(document, new HtmlTagMap(), bf);
+ }
+
+ /**
+ * Constructs a new SAXiTextHandler that will translate all the events
+ * triggered by the parser to actions on the <CODE>Document</CODE>-object.
+ *
+ * @param document
+ * this is the document on which events must be triggered
+ * @param htmlTags
+ * a tagmap translating HTML tags to iText tags
+ * @throws IOException
+ * @throws DocumentException
+ */
+
+ public SAXmyHtmlHandler(DocListener document, HashMap htmlTags)
+ throws DocumentException, IOException {
+ super(document, htmlTags);
+ }
+
+ /**
+ * This method gets called when a start tag is encountered.
+ *
+ * @param uri
+ * the Uniform Resource Identifier
+ * @param lname
+ * the local name (without prefix), or the empty string if
+ * Namespace processing is not being performed.
+ * @param name
+ * the name of the tag that is encountered
+ * @param attrs
+ * the list of attributes
+ */
+
+ public void startElement(String uri, String lname, String name,
+ Attributes attrs) {
+ // System.err.println("Start: " + name);
+
+ // super.handleStartingTags is replaced with handleStartingTags
+ // suggestion by Vu Ngoc Tan/Hop
+ name = name.toLowerCase();
+ if (((HtmlTagMap) myTags).isHtml(name)) {
+ // we do nothing
+ return;
+ }
+ if (((HtmlTagMap) myTags).isHead(name)) {
+ // we do nothing
+ return;
+ }
+ if (((HtmlTagMap) myTags).isTitle(name)) {
+ // we do nothing
+ return;
+ }
+ if (((HtmlTagMap) myTags).isMeta(name)) {
+ // we look if we can change the body attributes
+ String meta = null;
+ String content = null;
+ if (attrs != null) {
+ for (int i = 0; i < attrs.getLength(); i++) {
+ String attribute = attrs.getQName(i);
+ if (attribute.equalsIgnoreCase(HtmlTags.CONTENT))
+ content = attrs.getValue(i);
+ else if (attribute.equalsIgnoreCase(HtmlTags.NAME))
+ meta = attrs.getValue(i);
+ }
+ }
+ if (meta != null && content != null) {
+ bodyAttributes.put(meta, content);
+ }
+ return;
+ }
+ if (((HtmlTagMap) myTags).isLink(name)) {
+ // we do nothing for the moment, in a later version we could extract
+ // the style sheet
+ return;
+ }
+ if (((HtmlTagMap) myTags).isBody(name)) {
+ // maybe we could extract some info about the document: color,
+ // margins,...
+ // but that's for a later version...
+ XmlPeer peer = new XmlPeer(ElementTags.ITEXT, name);
+ peer.addAlias(ElementTags.TOP, HtmlTags.TOPMARGIN);
+ peer.addAlias(ElementTags.BOTTOM, HtmlTags.BOTTOMMARGIN);
+ peer.addAlias(ElementTags.RIGHT, HtmlTags.RIGHTMARGIN);
+ peer.addAlias(ElementTags.LEFT, HtmlTags.LEFTMARGIN);
+ String content = null;
+ bodyAttributes.putAll(peer.getAttributes(attrs));
+ handleStartingTags(peer.getTag(), bodyAttributes);
+ return;
+ }
+ if (myTags.containsKey(name)) {
+ XmlPeer peer = (XmlPeer) myTags.get(name);
+ if (Table.isTag(peer.getTag()) || Cell.isTag(peer.getTag())) {
+ Properties p = peer.getAttributes(attrs);
+ String value;
+ if (Table.isTag(peer.getTag())
+ && (value = p.getProperty(ElementTags.BORDERWIDTH)) != null) {
+ if (Float.valueOf(value + "f").floatValue() > 0) {
+ tableBorder = true;
+ }
+ }
+ if (tableBorder) {
+ p.put(ElementTags.LEFT, String.valueOf(true));
+ p.put(ElementTags.RIGHT, String.valueOf(true));
+ p.put(ElementTags.TOP, String.valueOf(true));
+ p.put(ElementTags.BOTTOM, String.valueOf(true));
+ }
+ handleStartingTags(peer.getTag(), p);
+ return;
+ }
+ handleStartingTags(peer.getTag(), peer.getAttributes(attrs));
+ return;
+ }
+ Properties attributes = new Properties();
+ if (attrs != null) {
+ for (int i = 0; i < attrs.getLength(); i++) {
+ String attribute = attrs.getQName(i).toLowerCase();
+ attributes.setProperty(attribute, attrs.getValue(i).toLowerCase());
+ }
+ }
+ handleStartingTags(name, attributes);
+ }
+
+ /**
+ * This method gets called when an end tag is encountered.
+ *
+ * @param uri
+ * the Uniform Resource Identifier
+ * @param lname
+ * the local name (without prefix), or the empty string if
+ * Namespace processing is not being performed.
+ * @param name
+ * the name of the tag that ends
+ */
+
+ public void endElement(String uri, String lname, String name) {
+ // System.err.println("End: " + name);
+ name = name.toLowerCase();
+ if (Paragraph.isTag(name)) {
+ try {
+ document.add((Element) stack.pop());
+ return;
+ } catch (DocumentException e) {
+ throw new ExceptionConverter(e);
+ }
+ }
+ if (((HtmlTagMap) myTags).isHead(name)) {
+ // we do nothing
+ return;
+ }
+ if (((HtmlTagMap) myTags).isTitle(name)) {
+ if (currentChunk != null) {
+ bodyAttributes.put(ElementTags.TITLE, currentChunk.content());
+ }
+ return;
+ }
+ if (((HtmlTagMap) myTags).isMeta(name)) {
+ // we do nothing
+ return;
+ }
+ if (((HtmlTagMap) myTags).isLink(name)) {
+ // we do nothing
+ return;
+ }
+ if (((HtmlTagMap) myTags).isBody(name)) {
+ // we do nothing
+ return;
+ }
+ if (myTags.containsKey(name)) {
+ XmlPeer peer = (XmlPeer) myTags.get(name);
+ if (Table.isTag(peer.getTag())) {
+ tableBorder = false;
+ }
+ super.handleEndingTags(peer.getTag());
+ return;
+ }
+ // super.handleEndingTags is replaced with handleEndingTags
+ // suggestion by Ken Auer
+ handleEndingTags(name);
+ }
+} \ No newline at end of file
diff --git a/src/main/java/com/lowagie/text/html/simpleparser/ALink.java b/src/main/java/com/lowagie/text/html/simpleparser/ALink.java
new file mode 100644
index 0000000..a190e38
--- /dev/null
+++ b/src/main/java/com/lowagie/text/html/simpleparser/ALink.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2005 Paulo Soares
+ *
+ * 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.simpleparser;
+
+import com.lowagie.text.Paragraph;
+/**
+ *
+ * @author psoares
+ */
+public interface ALink {
+ boolean process(Paragraph current, ChainedProperties cprops);
+}
diff --git a/src/main/java/com/lowagie/text/html/simpleparser/ChainedProperties.java b/src/main/java/com/lowagie/text/html/simpleparser/ChainedProperties.java
new file mode 100644
index 0000000..c3e078a
--- /dev/null
+++ b/src/main/java/com/lowagie/text/html/simpleparser/ChainedProperties.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2004 Paulo Soares
+ *
+ * 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.simpleparser;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+public class ChainedProperties {
+
+ public final static int fontSizes[] = {8, 10, 12, 14, 18, 24, 36};
+ public ArrayList chain = new ArrayList();
+
+ /** Creates a new instance of ChainedProperties */
+ public ChainedProperties() {
+ }
+
+ public String getProperty(String key) {
+ for (int k = chain.size() - 1; k >= 0; --k) {
+ Object obj[] = (Object[])chain.get(k);
+ HashMap prop = (HashMap)obj[1];
+ String ret = (String)prop.get(key);
+ if (ret != null)
+ return ret;
+ }
+ return null;
+ }
+
+ public boolean hasProperty(String key) {
+ for (int k = chain.size() - 1; k >= 0; --k) {
+ Object obj[] = (Object[])chain.get(k);
+ HashMap prop = (HashMap)obj[1];
+ if (prop.containsKey(key))
+ return true;
+ }
+ return false;
+ }
+
+ public void addToChain(String key, HashMap prop) {
+ // adjust the font size
+ String value = (String)prop.get("size");
+ if (value != null) {
+ if (value.endsWith("px")) {
+ prop.put("size", value.substring(0, value.length() - 2));
+ }
+ else {
+ int s = 0;
+ if (value.startsWith("+") || value.startsWith("-")) {
+ String old = getProperty("basefontsize");
+ if (old == null)
+ old = "12";
+ float f = Float.valueOf(old).floatValue();
+ int c = (int)f;
+ for (int k = fontSizes.length - 1; k >= 0; --k) {
+ if (c >= fontSizes[k]) {
+ s = k;
+ break;
+ }
+ }
+ int inc = Integer.parseInt(value.startsWith("+") ? value.substring(1) : value);
+ s += inc;
+ }
+ else
+ s = Integer.parseInt(value) - 1;
+ if (s < 0)
+ s = 0;
+ else if (s >= fontSizes.length)
+ s = fontSizes.length - 1;
+ prop.put("size", Integer.toString(fontSizes[s]));
+ }
+ }
+ chain.add(new Object[]{key, prop});
+ }
+
+ public void removeChain(String key) {
+ for (int k = chain.size() - 1; k >= 0; --k) {
+ if (key.equals(((Object[])chain.get(k))[0])) {
+ chain.remove(k);
+ return;
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/lowagie/text/html/simpleparser/FactoryProperties.java b/src/main/java/com/lowagie/text/html/simpleparser/FactoryProperties.java
new file mode 100644
index 0000000..a017a1a
--- /dev/null
+++ b/src/main/java/com/lowagie/text/html/simpleparser/FactoryProperties.java
@@ -0,0 +1,244 @@
+/*
+ * Copyright 2004 Paulo Soares
+ *
+ * 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.simpleparser;
+
+import com.lowagie.text.*;
+import com.lowagie.text.pdf.*;
+import java.util.HashMap;
+import java.util.StringTokenizer;
+import java.awt.Color;
+
+/**
+ *
+ * @author psoares
+ */
+public class FactoryProperties {
+
+ private FontFactoryImp fontImp;
+
+ /** Creates a new instance of FactoryProperties */
+ public FactoryProperties() {
+ }
+
+ public Chunk createChunk(String text, ChainedProperties props) {
+ Chunk ck = new Chunk(text, getFont(props));
+ if (props.hasProperty("sub"))
+ ck.setTextRise(-6);
+ else if (props.hasProperty("sup"))
+ ck.setTextRise(6);
+ return ck;
+ }
+
+ private static void setParagraphLeading(Paragraph p, String leading) {
+ if (leading == null) {
+ p.setLeading(0, 1.5f);
+ return;
+ }
+ try {
+ StringTokenizer tk = new StringTokenizer(leading, " ,");
+ String v = tk.nextToken();
+ float v1 = Float.valueOf(v).floatValue();
+ if (!tk.hasMoreTokens()) {
+ p.setLeading(v1, 0);
+ return;
+ }
+ v = tk.nextToken();
+ float v2 = Float.valueOf(v).floatValue();
+ p.setLeading(v1, v2);
+ }
+ catch (Exception e) {
+ p.setLeading(0, 1.5f);
+ }
+
+ }
+
+ public static Paragraph createParagraph(HashMap props) {
+ Paragraph p = new Paragraph();
+ String value = (String)props.get("align");
+ if (value != null) {
+ if (value.equalsIgnoreCase("center"))
+ p.setAlignment(Element.ALIGN_CENTER);
+ else if (value.equalsIgnoreCase("right"))
+ p.setAlignment(Element.ALIGN_RIGHT);
+ else if (value.equalsIgnoreCase("justify"))
+ p.setAlignment(Element.ALIGN_JUSTIFIED);
+ }
+ setParagraphLeading(p, (String)props.get("leading"));
+ return p;
+ }
+
+ public static void createParagraph(Paragraph p, ChainedProperties props) {
+ String value = props.getProperty("align");
+ if (value != null) {
+ if (value.equalsIgnoreCase("center"))
+ p.setAlignment(Element.ALIGN_CENTER);
+ else if (value.equalsIgnoreCase("right"))
+ p.setAlignment(Element.ALIGN_RIGHT);
+ else if (value.equalsIgnoreCase("justify"))
+ p.setAlignment(Element.ALIGN_JUSTIFIED);
+ }
+ setParagraphLeading(p, props.getProperty("leading"));
+ value = props.getProperty("before");
+ if (value != null) {
+ try {
+ p.setSpacingBefore(Float.valueOf(value).floatValue());
+ }
+ catch (Exception e) {}
+ }
+ value = props.getProperty("after");
+ if (value != null) {
+ try {
+ p.setSpacingAfter(Float.valueOf(value).floatValue());
+ }
+ catch (Exception e) {}
+ }
+ value = props.getProperty("extraparaspace");
+ if (value != null) {
+ try {
+ p.setExtraParagraphSpace(Float.valueOf(value).floatValue());
+ }
+ catch (Exception e) {}
+ }
+ }
+
+ public static Paragraph createParagraph(ChainedProperties props) {
+ Paragraph p = new Paragraph();
+ createParagraph(p, props);
+ return p;
+ }
+
+ public static ListItem createListItem(ChainedProperties props) {
+ ListItem p = new ListItem();
+ createParagraph(p, props);
+ return p;
+ }
+
+ public Font getFont(ChainedProperties props) {
+ String face = props.getProperty("face");
+ if (face != null) {
+ StringTokenizer tok = new StringTokenizer(face, ",");
+ while (tok.hasMoreTokens()) {
+ face = tok.nextToken().trim();
+ if (FontFactory.isRegistered(face))
+ break;
+ }
+ }
+ int style = 0;
+ if (props.hasProperty("i"))
+ style |= Font.ITALIC;
+ if (props.hasProperty("b"))
+ style |= Font.BOLD;
+ if (props.hasProperty("u"))
+ style |= Font.UNDERLINE;
+ String value = props.getProperty("size");
+ float size = 12;
+ if (value != null)
+ size = Float.valueOf(value).floatValue();
+ Color color = decodeColor(props.getProperty("color"));
+ String encoding = props.getProperty("encoding");
+ if (encoding == null)
+ encoding = BaseFont.WINANSI;
+ FontFactoryImp ff = fontImp;
+ if (ff == null)
+ ff = FontFactory.getFontImp();
+ return ff.getFont(face, encoding, true, size, style, color);
+ }
+
+ public static Color decodeColor(String s) {
+ if (s == null)
+ return null;
+ s = s.toLowerCase().trim();
+ Color c = (Color)colorTable.get(s);
+ if (c != null)
+ return c;
+ try {
+ if (s.startsWith("#"))
+ return new Color(Integer.parseInt(s.substring(1), 16));
+ }
+ catch (Exception e) {
+ }
+ return null;
+ }
+
+ public FontFactoryImp getFontImp() {
+ return fontImp;
+ }
+
+ public void setFontImp(FontFactoryImp fontImp) {
+ this.fontImp = fontImp;
+ }
+
+ public static HashMap colorTable = new HashMap();
+ public static HashMap followTags = new HashMap();
+ static {
+ followTags.put("i", "i");
+ followTags.put("b", "b");
+ followTags.put("u", "u");
+ followTags.put("sub", "sub");
+ followTags.put("sup", "sup");
+ followTags.put("em", "i");
+ followTags.put("strong", "b");
+
+ colorTable.put("black", new Color(0x000000));
+ colorTable.put("green", new Color(0x008000));
+ colorTable.put("silver", new Color(0xC0C0C0));
+ colorTable.put("lime", new Color(0x00FF00));
+ colorTable.put("gray", new Color(0x808080));
+ colorTable.put("olive", new Color(0x808000));
+ colorTable.put("white", new Color(0xFFFFFF));
+ colorTable.put("yellow", new Color(0xFFFF00));
+ colorTable.put("maroon", new Color(0x800000));
+ colorTable.put("navy", new Color(0x000080));
+ colorTable.put("red", new Color(0xFF0000));
+ colorTable.put("blue", new Color(0x0000FF));
+ colorTable.put("purple", new Color(0x800080));
+ colorTable.put("teal", new Color(0x008080));
+ colorTable.put("fuchsia", new Color(0xFF00FF));
+ colorTable.put("aqua", new Color(0x00FFFF));
+ }
+}
diff --git a/src/main/java/com/lowagie/text/html/simpleparser/HTMLWorker.java b/src/main/java/com/lowagie/text/html/simpleparser/HTMLWorker.java
new file mode 100644
index 0000000..b28fe04
--- /dev/null
+++ b/src/main/java/com/lowagie/text/html/simpleparser/HTMLWorker.java
@@ -0,0 +1,623 @@
+/*
+ * Copyright 2004 Paulo Soares
+ *
+ * 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.simpleparser;
+
+import com.lowagie.text.*;
+import com.lowagie.text.pdf.*;
+import java.util.Stack;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.StringTokenizer;
+import java.io.IOException;
+import java.io.Reader;
+import java.io.File;
+
+public class HTMLWorker implements SimpleXMLDocHandler, DocListener {
+
+ protected ArrayList objectList;
+ protected DocListener document;
+ private Paragraph currentParagraph;
+ private ChainedProperties cprops = new ChainedProperties();
+ private Stack stack = new Stack();
+ private boolean pendingTR = false;
+ private boolean pendingTD = false;
+ private boolean pendingLI = false;
+ private StyleSheet style = new StyleSheet();
+ private boolean isPRE = false;
+ private Stack tableState = new Stack();
+ private boolean skipText = false;
+ private HashMap interfaceProps;
+ private FactoryProperties factoryProperties = new FactoryProperties();
+
+ /** Creates a new instance of HTMLWorker */
+ public HTMLWorker(DocListener document) {
+ this.document = document;
+ }
+
+ public void setStyleSheet(StyleSheet style) {
+ this.style = style;
+ }
+
+ public StyleSheet getStyleSheet() {
+ return style;
+ }
+
+ public void setInterfaceProps(HashMap interfaceProps) {
+ this.interfaceProps = interfaceProps;
+ FontFactoryImp ff = null;
+ if (interfaceProps != null)
+ ff = (FontFactoryImp)interfaceProps.get("font_factory");
+ factoryProperties.setFontImp(ff);
+ }
+
+ public HashMap getInterfaceProps() {
+ return interfaceProps;
+ }
+
+ public void parse(Reader reader) throws IOException {
+ SimpleXMLParser.parse(this, null, reader, true);
+ }
+
+ public static ArrayList parseToList(Reader reader, StyleSheet style) throws IOException {
+ return parseToList(reader, style, null);
+ }
+
+ public static ArrayList parseToList(Reader reader, StyleSheet style, HashMap interfaceProps) throws IOException {
+ HTMLWorker worker = new HTMLWorker(null);
+ if (style != null)
+ worker.style = style;
+ worker.document = worker;
+ worker.setInterfaceProps(interfaceProps);
+ worker.objectList = new ArrayList();
+ worker.parse(reader);
+ return worker.objectList;
+ }
+
+ public void endDocument() {
+ try {
+ for (int k = 0; k < stack.size(); ++k)
+ document.add((Element)stack.elementAt(k));
+ if (currentParagraph != null)
+ document.add(currentParagraph);
+ currentParagraph = null;
+ }
+ catch (Exception e) {
+ throw new ExceptionConverter(e);
+ }
+ }
+
+ public void startDocument() {
+ HashMap h = new HashMap();
+ style.applyStyle("body", h);
+ cprops.addToChain("body", h);
+ }
+
+ public void startElement(String tag, HashMap h) {
+ if (!tagsSupported.containsKey(tag))
+ return;
+ try {
+ style.applyStyle(tag, h);
+ String follow = (String)FactoryProperties.followTags.get(tag);
+ if (follow != null) {
+ HashMap prop = new HashMap();
+ prop.put(follow, null);
+ cprops.addToChain(follow, prop);
+ return;
+ }
+ if (tag.equals("a")) {
+ cprops.addToChain(tag, h);
+ if (currentParagraph == null)
+ currentParagraph = new Paragraph();
+ stack.push(currentParagraph);
+ currentParagraph = new Paragraph();
+ return;
+ }
+ if (tag.equals("br")) {
+ if (currentParagraph == null)
+ currentParagraph = new Paragraph();
+ currentParagraph.add(factoryProperties.createChunk("\n", cprops));
+ return;
+ }
+ if (tag.equals("font") || tag.equals("span")) {
+ cprops.addToChain(tag, h);
+ return;
+ }
+ if (tag.equals("img")) {
+ String src = (String)h.get("src");
+ if (src == null)
+ return;
+ cprops.addToChain(tag, h);
+ Image img = null;
+ if (interfaceProps != null) {
+ HashMap images = (HashMap)interfaceProps.get("img_static");
+ if (images != null) {
+ Image tim = (Image)images.get(src);
+ if (tim != null)
+ img = Image.getInstance(tim);
+ } else {
+ if (!src.startsWith("http")) { // relative src references only
+ String baseurl = (String)interfaceProps.get("img_baseurl");
+ if (baseurl != null) {
+ src = baseurl+src;
+ img = Image.getInstance(src);
+ }
+ }
+ }
+ }
+ if (img == null) {
+ if (!src.startsWith("http")) {
+ String path = cprops.getProperty("image_path");
+ if (path == null)
+ path = "";
+ src = new File(path, src).getPath();
+ }
+ img = Image.getInstance(src);
+ }
+ String align = (String)h.get("align");
+ String width = (String)h.get("width");
+ String height = (String)h.get("height");
+ String before = cprops.getProperty("before");
+ String after = cprops.getProperty("after");
+ if (before != null)
+ img.setSpacingBefore(Float.valueOf(before).floatValue());
+ if (after != null)
+ img.setSpacingAfter(Float.valueOf(after).floatValue());
+ float wp = lengthParse(width, (int)img.width());
+ float lp = lengthParse(height, (int)img.height());
+ if (wp > 0 && lp > 0)
+ img.scalePercent(wp > lp ? lp : wp);
+ else if (wp > 0)
+ img.scalePercent(wp);
+ else if (lp > 0)
+ img.scalePercent(lp);
+ img.setWidthPercentage(0);
+ if (align != null) {
+ endElement("p");
+ int ralign = Image.MIDDLE;
+ if (align.equalsIgnoreCase("left"))
+ ralign = Image.LEFT;
+ else if (align.equalsIgnoreCase("right"))
+ ralign = Image.RIGHT;
+ img.setAlignment(ralign);
+ Img i = null;
+ boolean skip = false;
+ if (interfaceProps != null) {
+ i = (Img)interfaceProps.get("img_interface");
+ if (i != null)
+ skip = i.process(img, h, cprops, document);
+ }
+ if (!skip)
+ document.add(img);
+ cprops.removeChain(tag);
+ }
+ else {
+ cprops.removeChain(tag);
+ if (currentParagraph == null)
+ currentParagraph = FactoryProperties.createParagraph(cprops);
+ currentParagraph.add(new Chunk(img, 0, 0));
+ }
+ return;
+ }
+ endElement("p");
+ if (tag.equals("h1") || tag.equals("h2") || tag.equals("h3") || tag.equals("h4") || tag.equals("h5") || tag.equals("h6")) {
+ if (!h.containsKey("size"))
+ h.put("size", tag.substring(1));
+ cprops.addToChain(tag, h);
+ return;
+ }
+ if (tag.equals("ul")) {
+ if (pendingLI)
+ endElement("li");
+ skipText = true;
+ cprops.addToChain(tag, h);
+ com.lowagie.text.List list = new com.lowagie.text.List(false, 10);
+ list.setListSymbol("\u2022");
+ stack.push(list);
+ return;
+ }
+ if (tag.equals("ol")) {
+ if (pendingLI)
+ endElement("li");
+ skipText = true;
+ cprops.addToChain(tag, h);
+ com.lowagie.text.List list = new com.lowagie.text.List(true, 10);
+ stack.push(list);
+ return;
+ }
+ if (tag.equals("li")) {
+ if (pendingLI)
+ endElement("li");
+ skipText = false;
+ pendingLI = true;
+ cprops.addToChain(tag, h);
+ stack.push(FactoryProperties.createListItem(cprops));
+ return;
+ }
+ if (tag.equals("div") || tag.equals("body")) {
+ cprops.addToChain(tag, h);
+ return;
+ }
+ if (tag.equals("pre")) {
+ if (!h.containsKey("face")) {
+ h.put("face", "Courier");
+ }
+ cprops.addToChain(tag, h);
+ isPRE = true;
+ return;
+ }
+ if (tag.equals("p")) {
+ cprops.addToChain(tag, h);
+ currentParagraph = FactoryProperties.createParagraph(h);
+ return;
+ }
+ if (tag.equals("tr")) {
+ if (pendingTR)
+ endElement("tr");
+ skipText = true;
+ pendingTR = true;
+ cprops.addToChain("tr", h);
+ return;
+ }
+ if (tag.equals("td") || tag.equals("th")) {
+ if (pendingTD)
+ endElement(tag);
+ skipText = false;
+ pendingTD = true;
+ cprops.addToChain("td", h);
+ stack.push(new IncCell(tag, cprops));
+ return;
+ }
+ if (tag.equals("table")) {
+ cprops.addToChain("table", h);
+ IncTable table = new IncTable(h);
+ stack.push(table);
+ tableState.push(new boolean[]{pendingTR, pendingTD});
+ pendingTR = pendingTD = false;
+ skipText = true;
+ return;
+ }
+ }
+ catch (Exception e) {
+ throw new ExceptionConverter(e);
+ }
+ }
+
+ public void endElement(String tag) {
+ if (!tagsSupported.containsKey(tag))
+ return;
+ try {
+ String follow = (String)FactoryProperties.followTags.get(tag);
+ if (follow != null) {
+ cprops.removeChain(follow);
+ return;
+ }
+ if (tag.equals("font") || tag.equals("span")) {
+ cprops.removeChain(tag);
+ return;
+ }
+ if (tag.equals("a")) {
+ if (currentParagraph == null)
+ currentParagraph = new Paragraph();
+ ALink i = null;
+ boolean skip = false;
+ if (interfaceProps != null) {
+ i = (ALink)interfaceProps.get("alink_interface");
+ if (i != null)
+ skip = i.process(currentParagraph, cprops);
+ }
+ if (!skip) {
+ String href = cprops.getProperty("href");
+ if (href != null) {
+ ArrayList chunks = currentParagraph.getChunks();
+ for (int k = 0; k < chunks.size(); ++k) {
+ Chunk ck = (Chunk)chunks.get(k);
+ ck.setAnchor(href);
+ }
+ }
+ }
+ Paragraph tmp = (Paragraph)stack.pop();
+ Phrase tmp2 = new Phrase();
+ tmp2.add(currentParagraph);
+ tmp.add(tmp2);
+ currentParagraph = tmp;
+ cprops.removeChain("a");
+ return;
+ }
+ if (tag.equals("br")) {
+ return;
+ }
+ if (currentParagraph != null) {
+ if (stack.empty())
+ document.add(currentParagraph);
+ else {
+ Object obj = stack.pop();
+ if (obj instanceof TextElementArray) {
+ TextElementArray current = (TextElementArray)obj;
+ current.add(currentParagraph);
+ }
+ stack.push(obj);
+ }
+ }
+ currentParagraph = null;
+ if (tag.equals("ul") || tag.equals("ol")) {
+ if (pendingLI)
+ endElement("li");
+ skipText = false;
+ cprops.removeChain(tag);
+ if (stack.empty())
+ return;
+ Object obj = stack.pop();
+ if (!(obj instanceof com.lowagie.text.List)) {
+ stack.push(obj);
+ return;
+ }
+ if (stack.empty())
+ document.add((Element)obj);
+ else
+ ((TextElementArray)stack.peek()).add(obj);
+ return;
+ }
+ if (tag.equals("li")) {
+ pendingLI = false;
+ skipText = true;
+ cprops.removeChain(tag);
+ if (stack.empty())
+ return;
+ Object obj = stack.pop();
+ if (!(obj instanceof ListItem)) {
+ stack.push(obj);
+ return;
+ }
+ if (stack.empty()) {
+ document.add((Element)obj);
+ return;
+ }
+ Object list = stack.pop();
+ if (!(list instanceof com.lowagie.text.List)) {
+ stack.push(list);
+ return;
+ }
+ ListItem item = (ListItem)obj;
+ ((com.lowagie.text.List)list).add(item);
+ ArrayList cks = item.getChunks();
+ if (cks.size() > 0)
+ item.listSymbol().setFont(((Chunk)cks.get(0)).font());
+ stack.push(list);
+ return;
+ }
+ if (tag.equals("div") || tag.equals("body")) {
+ cprops.removeChain(tag);
+ return;
+ }
+ if (tag.equals("pre")) {
+ cprops.removeChain(tag);
+ isPRE = false;
+ return;
+ }
+ if (tag.equals("p")) {
+ cprops.removeChain(tag);
+ return;
+ }
+ if (tag.equals("h1") || tag.equals("h2") || tag.equals("h3") || tag.equals("h4") || tag.equals("h5") || tag.equals("h6")) {
+ cprops.removeChain(tag);
+ return;
+ }
+ if (tag.equals("table")) {
+ if (pendingTR)
+ endElement("tr");
+ cprops.removeChain("table");
+ IncTable table = (IncTable) stack.pop();
+ PdfPTable tb = table.buildTable();
+ tb.setSplitRows(true);
+ if (stack.empty())
+ document.add(tb);
+ else
+ ((TextElementArray)stack.peek()).add(tb);
+ boolean state[] = (boolean[])tableState.pop();
+ pendingTR = state[0];
+ pendingTD = state[1];
+ skipText = false;
+ return;
+ }
+ if (tag.equals("tr")) {
+ if (pendingTD)
+ endElement("td");
+ pendingTR = false;
+ cprops.removeChain("tr");
+ ArrayList cells = new ArrayList();
+ IncTable table = null;
+ while (true) {
+ Object obj = stack.pop();
+ if (obj instanceof IncCell) {
+ cells.add(((IncCell)obj).getCell());
+ }
+ if (obj instanceof IncTable) {
+ table = (IncTable)obj;
+ break;
+ }
+ }
+ table.addCols(cells);
+ table.endRow();
+ stack.push(table);
+ skipText = true;
+ return;
+ }
+ if (tag.equals("td") || tag.equals("th")) {
+ pendingTD = false;
+ cprops.removeChain("td");
+ skipText = true;
+ return;
+ }
+ }
+ catch (Exception e) {
+ throw new ExceptionConverter(e);
+ }
+ }
+
+ public void text(String str) {
+ if (skipText)
+ return;
+ String content = str;
+ if (isPRE) {
+ if (currentParagraph == null)
+ currentParagraph = new Paragraph();
+ currentParagraph.add(factoryProperties.createChunk(content, cprops));
+ return;
+ }
+ if (content.trim().length() == 0 && content.indexOf(' ') < 0) {
+ return;
+ }
+
+ StringBuffer buf = new StringBuffer();
+ int len = content.length();
+ char character;
+ boolean newline = false;
+ for (int i = 0; i < len; i++) {
+ switch(character = content.charAt(i)) {
+ case ' ':
+ if (!newline) {
+ buf.append(character);
+ }
+ break;
+ case '\n':
+ if (i > 0) {
+ newline = true;
+ buf.append(' ');
+ }
+ break;
+ case '\r':
+ break;
+ case '\t':
+ break;
+ default:
+ newline = false;
+ buf.append(character);
+ }
+ }
+ if (currentParagraph == null)
+ currentParagraph = FactoryProperties.createParagraph(cprops);
+ currentParagraph.add(factoryProperties.createChunk(buf.toString(), cprops));
+ }
+
+ public boolean add(Element element) throws DocumentException {
+ objectList.add(element);
+ return true;
+ }
+
+ public boolean add(Watermark watermark) {
+ return true;
+ }
+
+ public void clearTextWrap() throws DocumentException {
+ }
+
+ public void close() {
+ }
+
+ public boolean newPage() throws DocumentException {
+ return true;
+ }
+
+ public void open() {
+ }
+
+ public void removeWatermark() {
+ }
+
+ public void resetFooter() {
+ }
+
+ public void resetHeader() {
+ }
+
+ public void resetPageCount() {
+ }
+
+ public void setFooter(HeaderFooter footer) {
+ }
+
+ public void setHeader(HeaderFooter header) {
+ }
+
+ public boolean setMarginMirroring(boolean marginMirroring) {
+ return true;
+ }
+
+ public boolean setMargins(float marginLeft, float marginRight, float marginTop, float marginBottom) {
+ return true;
+ }
+
+ public void setPageCount(int pageN) {
+ }
+
+ public boolean setPageSize(Rectangle pageSize) {
+ return true;
+ }
+
+ public static final String tagsSupportedString = "ol ul li a pre font span br p div body table td th tr i b u sub sup em strong"
+ + " h1 h2 h3 h4 h5 h6 img";
+
+ public static final HashMap tagsSupported = new HashMap();
+
+ static {
+ StringTokenizer tok = new StringTokenizer(tagsSupportedString);
+ while (tok.hasMoreTokens())
+ tagsSupported.put(tok.nextToken(), null);
+ }
+
+ private static float lengthParse(String txt, int c) {
+ if (txt == null)
+ return -1;
+ if (txt.endsWith("%")) {
+ float vf = Float.valueOf(txt.substring(0, txt.length() - 1)).floatValue();
+ return vf;
+ }
+ int v = Integer.parseInt(txt);
+ return (float)v / c * 100f;
+ }
+}
diff --git a/src/main/java/com/lowagie/text/html/simpleparser/Img.java b/src/main/java/com/lowagie/text/html/simpleparser/Img.java
new file mode 100644
index 0000000..a7c066c
--- /dev/null
+++ b/src/main/java/com/lowagie/text/html/simpleparser/Img.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2005 Paulo Soares
+ *
+ * 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.simpleparser;
+
+import com.lowagie.text.Image;
+import com.lowagie.text.DocListener;
+import java.util.HashMap;
+
+/**
+ *
+ * @author psoares
+ */
+public interface Img {
+ boolean process(Image img, HashMap h, ChainedProperties cprops, DocListener doc);
+}
diff --git a/src/main/java/com/lowagie/text/html/simpleparser/IncCell.java b/src/main/java/com/lowagie/text/html/simpleparser/IncCell.java
new file mode 100644
index 0000000..3f25e0c
--- /dev/null
+++ b/src/main/java/com/lowagie/text/html/simpleparser/IncCell.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2004 Paulo Soares
+ *
+ * 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.simpleparser;
+
+import com.lowagie.text.*;
+import com.lowagie.text.pdf.*;
+import java.util.ArrayList;
+/**
+ *
+ * @author psoares
+ */
+public class IncCell implements TextElementArray {
+
+ private ArrayList chunks = new ArrayList();
+ private PdfPCell cell;
+
+ /** Creates a new instance of IncCell */
+ public IncCell(String tag, ChainedProperties props) {
+ cell = new PdfPCell((Phrase)null);
+ String value = props.getProperty("colspan");
+ if (value != null)
+ cell.setColspan(Integer.parseInt(value));
+ value = props.getProperty("align");
+ if (tag.equals("th"))
+ cell.setHorizontalAlignment(Element.ALIGN_CENTER);
+ if (value != null) {
+ if ("center".equalsIgnoreCase(value))
+ cell.setHorizontalAlignment(Element.ALIGN_CENTER);
+ else if ("right".equalsIgnoreCase(value))
+ cell.setHorizontalAlignment(Element.ALIGN_RIGHT);
+ else if ("left".equalsIgnoreCase(value))
+ cell.setHorizontalAlignment(Element.ALIGN_LEFT);
+ else if ("justify".equalsIgnoreCase(value))
+ cell.setHorizontalAlignment(Element.ALIGN_JUSTIFIED);
+ }
+ value = props.getProperty("valign");
+ cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
+ if (value != null) {
+ if ("top".equalsIgnoreCase(value))
+ cell.setVerticalAlignment(Element.ALIGN_TOP);
+ else if ("bottom".equalsIgnoreCase(value))
+ cell.setVerticalAlignment(Element.ALIGN_BOTTOM);
+ }
+ value = props.getProperty("border");
+ float border = 0;
+ if (value != null)
+ border = Float.valueOf(value).floatValue();
+ cell.setBorderWidth(border);
+ value = props.getProperty("cellpadding");
+ if (value != null)
+ cell.setPadding(Float.valueOf(value).floatValue());
+ cell.setUseDescender(true);
+ value = props.getProperty("bgcolor");
+ cell.setBackgroundColor(FactoryProperties.decodeColor(value));
+ }
+
+ public boolean add(Object o) {
+ if (!(o instanceof Element))
+ return false;
+ cell.addElement((Element)o);
+ return true;
+ }
+
+ public ArrayList getChunks() {
+ return chunks;
+ }
+
+ public boolean process(ElementListener listener) {
+ return true;
+ }
+
+ public int type() {
+ return 0;
+ }
+
+ public PdfPCell getCell() {
+ return cell;
+ }
+} \ No newline at end of file
diff --git a/src/main/java/com/lowagie/text/html/simpleparser/IncTable.java b/src/main/java/com/lowagie/text/html/simpleparser/IncTable.java
new file mode 100644
index 0000000..92b569b
--- /dev/null
+++ b/src/main/java/com/lowagie/text/html/simpleparser/IncTable.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2004 Paulo Soares
+ *
+ * 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.simpleparser;
+
+import com.lowagie.text.pdf.*;
+import java.util.HashMap;
+import java.util.ArrayList;
+import java.util.Collections;
+
+/**
+ *
+ * @author psoares
+ */
+public class IncTable {
+ private HashMap props = new HashMap();
+ private ArrayList rows = new ArrayList();
+ private ArrayList cols;
+ /** Creates a new instance of IncTable */
+ public IncTable(HashMap props) {
+ this.props.putAll(props);
+ }
+
+ public void addCol(PdfPCell cell) {
+ if (cols == null)
+ cols = new ArrayList();
+ cols.add(cell);
+ }
+
+ public void addCols(ArrayList ncols) {
+ if (cols == null)
+ cols = new ArrayList(ncols);
+ else
+ cols.addAll(ncols);
+ }
+
+ public void endRow() {
+ if (cols != null) {
+ Collections.reverse(cols);
+ rows.add(cols);
+ cols = null;
+ }
+ }
+
+ public ArrayList getRows() {
+ return rows;
+ }
+
+ public PdfPTable buildTable() {
+ if (rows.size() == 0)
+ return new PdfPTable(1);
+ int ncol = 0;
+ ArrayList c0 = (ArrayList)rows.get(0);
+ for (int k = 0; k < c0.size(); ++k) {
+ ncol += ((PdfPCell)c0.get(k)).getColspan();
+ }
+ PdfPTable table = new PdfPTable(ncol);
+ String width = (String)props.get("width");
+ if (width == null)
+ table.setWidthPercentage(100);
+ else {
+ if (width.endsWith("%"))
+ table.setWidthPercentage(Float.valueOf(width.substring(0, width.length() - 1)).floatValue());
+ else {
+ table.setTotalWidth(Float.valueOf(width).floatValue());
+ table.setLockedWidth(true);
+ }
+ }
+ for (int row = 0; row < rows.size(); ++row) {
+ ArrayList col = (ArrayList)rows.get(row);
+ for (int k = 0; k < col.size(); ++k) {
+ table.addCell((PdfPCell)col.get(k));
+ }
+ }
+ return table;
+ }
+}
diff --git a/src/main/java/com/lowagie/text/html/simpleparser/StyleSheet.java b/src/main/java/com/lowagie/text/html/simpleparser/StyleSheet.java
new file mode 100644
index 0000000..a659715
--- /dev/null
+++ b/src/main/java/com/lowagie/text/html/simpleparser/StyleSheet.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2004 Paulo Soares
+ *
+ * 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.simpleparser;
+
+import java.util.HashMap;
+
+public class StyleSheet {
+
+ public HashMap classMap = new HashMap();
+ public HashMap tagMap = new HashMap();
+
+ /** Creates a new instance of StyleSheet */
+ public StyleSheet() {
+ }
+
+ public void applyStyle(String tag, HashMap props) {
+ HashMap map = (HashMap)tagMap.get(tag.toLowerCase());
+ if (map != null) {
+ HashMap temp = new HashMap(map);
+ temp.putAll(props);
+ props.putAll(temp);
+ }
+ String cm = (String)props.get("class");
+ if (cm == null)
+ return;
+ map = (HashMap)classMap.get(cm.toLowerCase());
+ if (map == null)
+ return;
+ props.remove("class");
+ HashMap temp = new HashMap(map);
+ temp.putAll(props);
+ props.putAll(temp);
+ }
+
+ private void applyMap(HashMap map, HashMap props) {
+
+ }
+
+ public void loadStyle(String style, HashMap props) {
+ classMap.put(style.toLowerCase(), props);
+ }
+
+ public void loadStyle(String style, String key, String value) {
+ style = style.toLowerCase();
+ HashMap props = (HashMap)classMap.get(style);
+ if (props == null) {
+ props = new HashMap();
+ classMap.put(style, props);
+ }
+ props.put(key, value);
+ }
+
+ public void loadTagStyle(String tag, HashMap props) {
+ tagMap.put(tag.toLowerCase(), props);
+ }
+
+ public void loadTagStyle(String tag, String key, String value) {
+ tag = tag.toLowerCase();
+ HashMap props = (HashMap)tagMap.get(tag);
+ if (props == null) {
+ props = new HashMap();
+ tagMap.put(tag, props);
+ }
+ props.put(key, value);
+ }
+
+} \ No newline at end of file