Open Source Repository

Home /itextpdf/itextpdf-5.1.2 | Repository Home



com/itextpdf/text/html/HtmlUtilities.java
/*
 * $Id: Markup.java 4672 2011-01-30 10:38:33Z blowagie $
 *
 * This file is part of the iText (R) project.
 * Copyright (c) 1998-2011 1T3XT BVBA
 * Authors: Bruno Lowagie, Paulo Soares, et al.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License version 3
 * as published by the Free Software Foundation with the addition of the
 * following permission added to Section 15 as permitted in Section 7(a):
 * FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY 1T3XT,
 * 1T3XT DISCLAIMS THE WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
 *
 * This program 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 Affero General Public License for more details.
 * You should have received a copy of the GNU Affero General Public License
 * along with this program; if not, see http://www.gnu.org/licenses or write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA, 02110-1301 USA, or download the license from the following URL:
 * http://itextpdf.com/terms-of-use/
 *
 * The interactive user interfaces in modified source and object code versions
 * of this program must display Appropriate Legal Notices, as required under
 * Section 5 of the GNU Affero General Public License.
 *
 * In accordance with Section 7(b) of the GNU Affero General Public License,
 * a covered work must retain the producer line in every PDF that is created
 * or manipulated using iText.
 *
 * You can be released from the requirements of the license by purchasing
 * a commercial license. Buying such a license is mandatory as soon as you
 * develop commercial activities involving the iText software without
 * disclosing the source code of your own applications.
 * These activities include: offering paid services to customers as an ASP,
 * serving PDFs on the fly in a web application, shipping iText with a closed
 * source product.
 *
 * For more information, please contact iText Software Corp. at this
 * address: [email protected]
 */
package com.itextpdf.text.html;

import java.util.Properties;
import java.util.StringTokenizer;
import java.util.HashMap;
import com.itextpdf.text.BaseColor;
import com.itextpdf.text.Element;

/**
 * A class that contains some utilities to parse HTML attributes and content.
 @since 5.0.6 (some of these methods used to be in the Markup class)
 */

public class HtmlUtilities {

  /**
   * a default value for font-size 
     @since 2.1.3
     */
  public static final float DEFAULT_FONT_SIZE = 12f;

    private static HashMap<String,Float> sizes = new HashMap<String,Float>();
    static {
        sizes.put("xx-small"new Float(4));
        sizes.put("x-small"new Float(6));
        sizes.put("small"new Float(8));
        sizes.put("medium"new Float(10));
        sizes.put("large"new Float(13));
        sizes.put("x-large"new Float(18));
        sizes.put("xx-large"new Float(26));
    }

  /**
   * Parses a length.
   
   @param string
   *            a length in the form of an optional + or -, followed by a
   *            number and a unit.
   @return a float
   */

  public static float parseLength(String string) {
    return parseLength(string, DEFAULT_FONT_SIZE);
  }

  /**
   * New method contributed by: Lubos Strapko
   
   @since 2.1.3
   */
  public static float parseLength(String string, float actualFontSize) {
    if (string == null)
      return 0f;
        Float fl = sizes.get(string.toLowerCase());
        if (fl != null)
            return fl.floatValue();
    int pos = 0;
    int length = string.length();
    boolean ok = true;
    while (ok && pos < length) {
      switch (string.charAt(pos)) {
      case '+':
      case '-':
      case '0':
      case '1':
      case '2':
      case '3':
      case '4':
      case '5':
      case '6':
      case '7':
      case '8':
      case '9':
      case '.':
        pos++;
        break;
      default:
        ok = false;
      }
    }
    if (pos == 0)
      return 0f;
    if (pos == length)
      return Float.parseFloat(string + "f");
    float f = Float.parseFloat(string.substring(0, pos"f");
    string = string.substring(pos);
    // inches
    if (string.startsWith("in")) {
      return f * 72f;
    }
    // centimeters
    if (string.startsWith("cm")) {
      return (f / 2.54f72f;
    }
    // millimeters
    if (string.startsWith("mm")) {
      return (f / 25.4f72f;
    }
    // picas
    if (string.startsWith("pc")) {
      return f * 12f;
    }
    // 1em is equal to the current font size
    if (string.startsWith("em")) {
      return f * actualFontSize;
    }
    // one ex is the x-height of a font (x-height is usually about half the
    // font-size)
    if (string.startsWith("ex")) {
      return f * actualFontSize / 2;
    }
    // default: we assume the length was measured in points
    return f;
  }

  /**
   * Converts a <CODE>BaseColor</CODE> into a HTML representation of this <CODE>
   * BaseColor</CODE>.
   
   @param s
   *            the <CODE>BaseColor</CODE> that has to be converted.
   @return the HTML representation of this <COLOR>BaseColor </COLOR>
   */

  public static BaseColor decodeColor(String s) {
    if (s == null)
      return null;
    s = s.toLowerCase().trim();
    try {
      return WebColors.getRGBColor(s);
    }
    catch(IllegalArgumentException iae) {
      return null;
    }
  }

  /**
   * This method parses a String with attributes and returns a Properties
   * object.
   
   @param string
   *            a String of this form: 'key1="value1"; key2="value2";...
   *            keyN="valueN" '
   @return a Properties object
   */
  public static Properties parseAttributes(String string) {
    Properties result = new Properties();
    if (string == null)
      return result;
    StringTokenizer keyValuePairs = new StringTokenizer(string, ";");
    StringTokenizer keyValuePair;
    String key;
    String value;
    while (keyValuePairs.hasMoreTokens()) {
      keyValuePair = new StringTokenizer(keyValuePairs.nextToken()":");
      if (keyValuePair.hasMoreTokens())
        key = keyValuePair.nextToken().trim();
      else
        continue;
      if (keyValuePair.hasMoreTokens())
        value = keyValuePair.nextToken().trim();
      else
        continue;
      if (value.startsWith("\""))
        value = value.substring(1);
      if (value.endsWith("\""))
        value = value.substring(0, value.length() 1);
      result.setProperty(key.toLowerCase(), value);
    }
    return result;
  }

  /**
   * Removes the comments sections of a String.
   
   @param string
   *            the original String
   @param startComment
   *            the String that marks the start of a Comment section
   @param endComment
   *            the String that marks the end of a Comment section.
   @return the String stripped of its comment section
   */
  public static String removeComment(String string, String startComment,
      String endComment) {
    StringBuffer result = new StringBuffer();
    int pos = 0;
    int end = endComment.length();
    int start = string.indexOf(startComment, pos);
    while (start > -1) {
      result.append(string.substring(pos, start));
      pos = string.indexOf(endComment, start+ end;
      start = string.indexOf(startComment, pos);
    }
    result.append(string.substring(pos));
    return result.toString();
  }
  
  /**
   * Helper class that reduces the white space in a String
   @param content content containing whitespace
   @return the content without all unnecessary whitespace
   */
  public static String eliminateWhiteSpace(String content) {
    // multiple spaces are reduced to one,
    // newlines are treated as spaces,
    // tabs, carriage returns are ignored.
    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);
      }
    }
    return buf.toString();
  }

  /**
   * A series of predefined font sizes.
   @since 5.0.6 (renamed)
   */
  public final static int FONTSIZES[] 8101214182436 };
  
  /**
   * Picks a font size from a series of predefined font sizes.
   @param value    the new value of a font, expressed as an index
   @param previous  the previous value of the font size
   @return  a new font size.
   */
  public static int getIndexedFontSize(String value, String previous) {
    // the font is expressed as an index in a series of predefined font sizes
    int sIndex = 0;
    // the font is defined as a relative size
    if (value.startsWith("+"|| value.startsWith("-")) {
      // fetch the previous value
      if (previous == null)
        previous = "12";
      int c = (int)Float.parseFloat(previous);
      // look for the nearest font size in the predefined series
      for (int k = FONTSIZES.length - 1; k >= 0; --k) {
        if (c >= FONTSIZES[k]) {
          sIndex = k;
          break;
        }
      }
      // retrieve the difference
      int diff =
        Integer.parseInt(value.startsWith("+"?
          value.substring(1: value);
      // apply the difference
      sIndex += diff;
    }
    // the font is defined as an index
    else {
      try {
        sIndex = Integer.parseInt(value1;
      catch (NumberFormatException nfe) {
        sIndex = 0;
      }
    }
    if (sIndex < 0)
      sIndex = 0;
    else if (sIndex >= FONTSIZES.length)
      sIndex = FONTSIZES.length - 1;
    return FONTSIZES[sIndex];
  }

  /**
   * Translates a String value to an alignment value.
   * (written by Norman Richards, integrated into iText by Bruno)
   @param  alignment a String (one of the ALIGN_ constants of this class)
   @return  an alignment value (one of the ALIGN_ constants of the Element interface) 
   */
  public static int alignmentValue(String alignment) {
    if (alignment == nullreturn Element.ALIGN_UNDEFINED;
      if (HtmlTags.ALIGN_CENTER.equalsIgnoreCase(alignment)) {
          return Element.ALIGN_CENTER;
      }
      if (HtmlTags.ALIGN_LEFT.equalsIgnoreCase(alignment)) {
          return Element.ALIGN_LEFT;
      }
      if (HtmlTags.ALIGN_RIGHT.equalsIgnoreCase(alignment)) {
          return Element.ALIGN_RIGHT;
      }
      if (HtmlTags.ALIGN_JUSTIFY.equalsIgnoreCase(alignment)) {
          return Element.ALIGN_JUSTIFIED;
      }
      if (HtmlTags.ALIGN_JUSTIFIED_ALL.equalsIgnoreCase(alignment)) {
          return Element.ALIGN_JUSTIFIED_ALL;
      }
      if (HtmlTags.ALIGN_TOP.equalsIgnoreCase(alignment)) {
          return Element.ALIGN_TOP;
      }
      if (HtmlTags.ALIGN_MIDDLE.equalsIgnoreCase(alignment)) {
          return Element.ALIGN_MIDDLE;
      }
      if (HtmlTags.ALIGN_BOTTOM.equalsIgnoreCase(alignment)) {
          return Element.ALIGN_BOTTOM;
      }
      if (HtmlTags.ALIGN_BASELINE.equalsIgnoreCase(alignment)) {
          return Element.ALIGN_BASELINE;
      }
      return Element.ALIGN_UNDEFINED;
  }
}