This example Java source code file (CSS.java) is included in the alvinalexander.com
"Java Source Code
Warehouse" project. The intent of this project is to help you "Learn
Java by Example" TM.
/*
* Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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 General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.swing.text.html;
import java.awt.Color;
import java.awt.Font;
import java.awt.GraphicsEnvironment;
import java.awt.Toolkit;
import java.awt.HeadlessException;
import java.awt.Image;
import java.io.*;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.MalformedURLException;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
import java.util.Locale;
import javax.swing.ImageIcon;
import javax.swing.SizeRequirements;
import javax.swing.text.*;
/**
* Defines a set of
* <a href="http://www.w3.org/TR/REC-CSS1">CSS attributes
* as a typesafe enumeration. The HTML View implementations use
* CSS attributes to determine how they will render. This also defines
* methods to map between CSS/HTML/StyleConstants. Any shorthand
* properties, such as font, are mapped to the intrinsic properties.
* <p>The following describes the CSS properties that are supported by the
* rendering engine:
* <ul>
font-family
* <li>font-style
* <li>font-size (supports relative units)
* <li>font-weight
* <li>font
* <li>color
* <li>background-color (with the exception of transparent)
* <li>background-image
* <li>background-repeat
* <li>background-position
* <li>background
* <li>text-decoration (with the exception of blink and overline)
* <li>vertical-align (only sup and super)
* <li>text-align (justify is treated as center)
* <li>margin-top
* <li>margin-right
* <li>margin-bottom
* <li>margin-left
* <li>margin
* <li>padding-top
* <li>padding-right
* <li>padding-bottom
* <li>padding-left
* <li>padding
* <li>border-top-style
* <li>border-right-style
* <li>border-bottom-style
* <li>border-left-style
* <li>border-style (only supports inset, outset and none)
* <li>border-top-color
* <li>border-right-color
* <li>border-bottom-color
* <li>border-left-color
* <li>border-color
* <li>list-style-image
* <li>list-style-type
* <li>list-style-position
* </ul>
* The following are modeled, but currently not rendered.
* <ul>
font-variant
* <li>background-attachment (background always treated as scroll)
* <li>word-spacing
* <li>letter-spacing
* <li>text-indent
* <li>text-transform
* <li>line-height
* <li>border-top-width (this is used to indicate if a border should be used)
* <li>border-right-width
* <li>border-bottom-width
* <li>border-left-width
* <li>border-width
* <li>border-top
* <li>border-right
* <li>border-bottom
* <li>border-left
* <li>border
* <li>width
* <li>height
* <li>float
* <li>clear
* <li>display
* <li>white-space
* <li>list-style
* </ul>
* <p>Note: for the time being we do not fully support relative units,
* unless noted, so that
* p { margin-top: 10% } will be treated as if no margin-top was specified.</b>
*
* @author Timothy Prinzing
* @author Scott Violet
* @see StyleSheet
*/
public class CSS implements Serializable {
/**
* Definitions to be used as a key on AttributeSet's
* that might hold CSS attributes. Since this is a
* closed set (i.e. defined exactly by the specification),
* it is final and cannot be extended.
*/
public static final class Attribute {
private Attribute(String name, String defaultValue, boolean inherited) {
this.name = name;
this.defaultValue = defaultValue;
this.inherited = inherited;
}
/**
* The string representation of the attribute. This
* should exactly match the string specified in the
* CSS specification.
*/
public String toString() {
return name;
}
/**
* Fetch the default value for the attribute.
* If there is no default value (such as for
* composite attributes), null will be returned.
*/
public String getDefaultValue() {
return defaultValue;
}
/**
* Indicates if the attribute should be inherited
* from the parent or not.
*/
public boolean isInherited() {
return inherited;
}
private String name;
private String defaultValue;
private boolean inherited;
public static final Attribute BACKGROUND =
new Attribute("background", null, false);
public static final Attribute BACKGROUND_ATTACHMENT =
new Attribute("background-attachment", "scroll", false);
public static final Attribute BACKGROUND_COLOR =
new Attribute("background-color", "transparent", false);
public static final Attribute BACKGROUND_IMAGE =
new Attribute("background-image", "none", false);
public static final Attribute BACKGROUND_POSITION =
new Attribute("background-position", null, false);
public static final Attribute BACKGROUND_REPEAT =
new Attribute("background-repeat", "repeat", false);
public static final Attribute BORDER =
new Attribute("border", null, false);
public static final Attribute BORDER_BOTTOM =
new Attribute("border-bottom", null, false);
public static final Attribute BORDER_BOTTOM_COLOR =
new Attribute("border-bottom-color", null, false);
public static final Attribute BORDER_BOTTOM_STYLE =
new Attribute("border-bottom-style", "none", false);
public static final Attribute BORDER_BOTTOM_WIDTH =
new Attribute("border-bottom-width", "medium", false);
public static final Attribute BORDER_COLOR =
new Attribute("border-color", null, false);
public static final Attribute BORDER_LEFT =
new Attribute("border-left", null, false);
public static final Attribute BORDER_LEFT_COLOR =
new Attribute("border-left-color", null, false);
public static final Attribute BORDER_LEFT_STYLE =
new Attribute("border-left-style", "none", false);
public static final Attribute BORDER_LEFT_WIDTH =
new Attribute("border-left-width", "medium", false);
public static final Attribute BORDER_RIGHT =
new Attribute("border-right", null, false);
public static final Attribute BORDER_RIGHT_COLOR =
new Attribute("border-right-color", null, false);
public static final Attribute BORDER_RIGHT_STYLE =
new Attribute("border-right-style", "none", false);
public static final Attribute BORDER_RIGHT_WIDTH =
new Attribute("border-right-width", "medium", false);
public static final Attribute BORDER_STYLE =
new Attribute("border-style", "none", false);
public static final Attribute BORDER_TOP =
new Attribute("border-top", null, false);
public static final Attribute BORDER_TOP_COLOR =
new Attribute("border-top-color", null, false);
public static final Attribute BORDER_TOP_STYLE =
new Attribute("border-top-style", "none", false);
public static final Attribute BORDER_TOP_WIDTH =
new Attribute("border-top-width", "medium", false);
public static final Attribute BORDER_WIDTH =
new Attribute("border-width", "medium", false);
public static final Attribute CLEAR =
new Attribute("clear", "none", false);
public static final Attribute COLOR =
new Attribute("color", "black", true);
public static final Attribute DISPLAY =
new Attribute("display", "block", false);
public static final Attribute FLOAT =
new Attribute("float", "none", false);
public static final Attribute FONT =
new Attribute("font", null, true);
public static final Attribute FONT_FAMILY =
new Attribute("font-family", null, true);
public static final Attribute FONT_SIZE =
new Attribute("font-size", "medium", true);
public static final Attribute FONT_STYLE =
new Attribute("font-style", "normal", true);
public static final Attribute FONT_VARIANT =
new Attribute("font-variant", "normal", true);
public static final Attribute FONT_WEIGHT =
new Attribute("font-weight", "normal", true);
public static final Attribute HEIGHT =
new Attribute("height", "auto", false);
public static final Attribute LETTER_SPACING =
new Attribute("letter-spacing", "normal", true);
public static final Attribute LINE_HEIGHT =
new Attribute("line-height", "normal", true);
public static final Attribute LIST_STYLE =
new Attribute("list-style", null, true);
public static final Attribute LIST_STYLE_IMAGE =
new Attribute("list-style-image", "none", true);
public static final Attribute LIST_STYLE_POSITION =
new Attribute("list-style-position", "outside", true);
public static final Attribute LIST_STYLE_TYPE =
new Attribute("list-style-type", "disc", true);
public static final Attribute MARGIN =
new Attribute("margin", null, false);
public static final Attribute MARGIN_BOTTOM =
new Attribute("margin-bottom", "0", false);
public static final Attribute MARGIN_LEFT =
new Attribute("margin-left", "0", false);
public static final Attribute MARGIN_RIGHT =
new Attribute("margin-right", "0", false);
/*
* made up css attributes to describe orientation depended
* margins. used for <dir>,
etc. see
* 5088268 for more details
*/
static final Attribute MARGIN_LEFT_LTR =
new Attribute("margin-left-ltr",
Integer.toString(Integer.MIN_VALUE), false);
static final Attribute MARGIN_LEFT_RTL =
new Attribute("margin-left-rtl",
Integer.toString(Integer.MIN_VALUE), false);
static final Attribute MARGIN_RIGHT_LTR =
new Attribute("margin-right-ltr",
Integer.toString(Integer.MIN_VALUE), false);
static final Attribute MARGIN_RIGHT_RTL =
new Attribute("margin-right-rtl",
Integer.toString(Integer.MIN_VALUE), false);
public static final Attribute MARGIN_TOP =
new Attribute("margin-top", "0", false);
public static final Attribute PADDING =
new Attribute("padding", null, false);
public static final Attribute PADDING_BOTTOM =
new Attribute("padding-bottom", "0", false);
public static final Attribute PADDING_LEFT =
new Attribute("padding-left", "0", false);
public static final Attribute PADDING_RIGHT =
new Attribute("padding-right", "0", false);
public static final Attribute PADDING_TOP =
new Attribute("padding-top", "0", false);
public static final Attribute TEXT_ALIGN =
new Attribute("text-align", null, true);
public static final Attribute TEXT_DECORATION =
new Attribute("text-decoration", "none", true);
public static final Attribute TEXT_INDENT =
new Attribute("text-indent", "0", true);
public static final Attribute TEXT_TRANSFORM =
new Attribute("text-transform", "none", true);
public static final Attribute VERTICAL_ALIGN =
new Attribute("vertical-align", "baseline", false);
public static final Attribute WORD_SPACING =
new Attribute("word-spacing", "normal", true);
public static final Attribute WHITE_SPACE =
new Attribute("white-space", "normal", true);
public static final Attribute WIDTH =
new Attribute("width", "auto", false);
/*public*/ static final Attribute BORDER_SPACING =
new Attribute("border-spacing", "0", true);
/*public*/ static final Attribute CAPTION_SIDE =
new Attribute("caption-side", "left", true);
// All possible CSS attribute keys.
static final Attribute[] allAttributes = {
BACKGROUND, BACKGROUND_ATTACHMENT, BACKGROUND_COLOR,
BACKGROUND_IMAGE, BACKGROUND_POSITION, BACKGROUND_REPEAT,
BORDER, BORDER_BOTTOM, BORDER_BOTTOM_WIDTH, BORDER_COLOR,
BORDER_LEFT, BORDER_LEFT_WIDTH, BORDER_RIGHT, BORDER_RIGHT_WIDTH,
BORDER_STYLE, BORDER_TOP, BORDER_TOP_WIDTH, BORDER_WIDTH,
BORDER_TOP_STYLE, BORDER_RIGHT_STYLE, BORDER_BOTTOM_STYLE,
BORDER_LEFT_STYLE,
BORDER_TOP_COLOR, BORDER_RIGHT_COLOR, BORDER_BOTTOM_COLOR,
BORDER_LEFT_COLOR,
CLEAR, COLOR, DISPLAY, FLOAT, FONT, FONT_FAMILY, FONT_SIZE,
FONT_STYLE, FONT_VARIANT, FONT_WEIGHT, HEIGHT, LETTER_SPACING,
LINE_HEIGHT, LIST_STYLE, LIST_STYLE_IMAGE, LIST_STYLE_POSITION,
LIST_STYLE_TYPE, MARGIN, MARGIN_BOTTOM, MARGIN_LEFT, MARGIN_RIGHT,
MARGIN_TOP, PADDING, PADDING_BOTTOM, PADDING_LEFT, PADDING_RIGHT,
PADDING_TOP, TEXT_ALIGN, TEXT_DECORATION, TEXT_INDENT, TEXT_TRANSFORM,
VERTICAL_ALIGN, WORD_SPACING, WHITE_SPACE, WIDTH,
BORDER_SPACING, CAPTION_SIDE,
MARGIN_LEFT_LTR, MARGIN_LEFT_RTL, MARGIN_RIGHT_LTR, MARGIN_RIGHT_RTL
};
private static final Attribute[] ALL_MARGINS =
{ MARGIN_TOP, MARGIN_RIGHT, MARGIN_BOTTOM, MARGIN_LEFT };
private static final Attribute[] ALL_PADDING =
{ PADDING_TOP, PADDING_RIGHT, PADDING_BOTTOM, PADDING_LEFT };
private static final Attribute[] ALL_BORDER_WIDTHS =
{ BORDER_TOP_WIDTH, BORDER_RIGHT_WIDTH, BORDER_BOTTOM_WIDTH,
BORDER_LEFT_WIDTH };
private static final Attribute[] ALL_BORDER_STYLES =
{ BORDER_TOP_STYLE, BORDER_RIGHT_STYLE, BORDER_BOTTOM_STYLE,
BORDER_LEFT_STYLE };
private static final Attribute[] ALL_BORDER_COLORS =
{ BORDER_TOP_COLOR, BORDER_RIGHT_COLOR, BORDER_BOTTOM_COLOR,
BORDER_LEFT_COLOR };
}
static final class Value {
private Value(String name) {
this.name = name;
}
/**
* The string representation of the attribute. This
* should exactly match the string specified in the
* CSS specification.
*/
public String toString() {
return name;
}
static final Value INHERITED = new Value("inherited");
static final Value NONE = new Value("none");
static final Value HIDDEN = new Value("hidden");
static final Value DOTTED = new Value("dotted");
static final Value DASHED = new Value("dashed");
static final Value SOLID = new Value("solid");
static final Value DOUBLE = new Value("double");
static final Value GROOVE = new Value("groove");
static final Value RIDGE = new Value("ridge");
static final Value INSET = new Value("inset");
static final Value OUTSET = new Value("outset");
// Lists.
static final Value DISC = new Value("disc");
static final Value CIRCLE = new Value("circle");
static final Value SQUARE = new Value("square");
static final Value DECIMAL = new Value("decimal");
static final Value LOWER_ROMAN = new Value("lower-roman");
static final Value UPPER_ROMAN = new Value("upper-roman");
static final Value LOWER_ALPHA = new Value("lower-alpha");
static final Value UPPER_ALPHA = new Value("upper-alpha");
// background-repeat
static final Value BACKGROUND_NO_REPEAT = new Value("no-repeat");
static final Value BACKGROUND_REPEAT = new Value("repeat");
static final Value BACKGROUND_REPEAT_X = new Value("repeat-x");
static final Value BACKGROUND_REPEAT_Y = new Value("repeat-y");
// background-attachment
static final Value BACKGROUND_SCROLL = new Value("scroll");
static final Value BACKGROUND_FIXED = new Value("fixed");
private String name;
static final Value[] allValues = {
INHERITED, NONE, DOTTED, DASHED, SOLID, DOUBLE, GROOVE,
RIDGE, INSET, OUTSET, DISC, CIRCLE, SQUARE, DECIMAL,
LOWER_ROMAN, UPPER_ROMAN, LOWER_ALPHA, UPPER_ALPHA,
BACKGROUND_NO_REPEAT, BACKGROUND_REPEAT,
BACKGROUND_REPEAT_X, BACKGROUND_REPEAT_Y,
BACKGROUND_FIXED, BACKGROUND_FIXED
};
}
public CSS() {
baseFontSize = baseFontSizeIndex + 1;
// setup the css conversion table
valueConvertor = new Hashtable<Object, Object>();
valueConvertor.put(CSS.Attribute.FONT_SIZE, new FontSize());
valueConvertor.put(CSS.Attribute.FONT_FAMILY, new FontFamily());
valueConvertor.put(CSS.Attribute.FONT_WEIGHT, new FontWeight());
Object bs = new BorderStyle();
valueConvertor.put(CSS.Attribute.BORDER_TOP_STYLE, bs);
valueConvertor.put(CSS.Attribute.BORDER_RIGHT_STYLE, bs);
valueConvertor.put(CSS.Attribute.BORDER_BOTTOM_STYLE, bs);
valueConvertor.put(CSS.Attribute.BORDER_LEFT_STYLE, bs);
Object cv = new ColorValue();
valueConvertor.put(CSS.Attribute.COLOR, cv);
valueConvertor.put(CSS.Attribute.BACKGROUND_COLOR, cv);
valueConvertor.put(CSS.Attribute.BORDER_TOP_COLOR, cv);
valueConvertor.put(CSS.Attribute.BORDER_RIGHT_COLOR, cv);
valueConvertor.put(CSS.Attribute.BORDER_BOTTOM_COLOR, cv);
valueConvertor.put(CSS.Attribute.BORDER_LEFT_COLOR, cv);
Object lv = new LengthValue();
valueConvertor.put(CSS.Attribute.MARGIN_TOP, lv);
valueConvertor.put(CSS.Attribute.MARGIN_BOTTOM, lv);
valueConvertor.put(CSS.Attribute.MARGIN_LEFT, lv);
valueConvertor.put(CSS.Attribute.MARGIN_LEFT_LTR, lv);
valueConvertor.put(CSS.Attribute.MARGIN_LEFT_RTL, lv);
valueConvertor.put(CSS.Attribute.MARGIN_RIGHT, lv);
valueConvertor.put(CSS.Attribute.MARGIN_RIGHT_LTR, lv);
valueConvertor.put(CSS.Attribute.MARGIN_RIGHT_RTL, lv);
valueConvertor.put(CSS.Attribute.PADDING_TOP, lv);
valueConvertor.put(CSS.Attribute.PADDING_BOTTOM, lv);
valueConvertor.put(CSS.Attribute.PADDING_LEFT, lv);
valueConvertor.put(CSS.Attribute.PADDING_RIGHT, lv);
Object bv = new BorderWidthValue(null, 0);
valueConvertor.put(CSS.Attribute.BORDER_TOP_WIDTH, bv);
valueConvertor.put(CSS.Attribute.BORDER_BOTTOM_WIDTH, bv);
valueConvertor.put(CSS.Attribute.BORDER_LEFT_WIDTH, bv);
valueConvertor.put(CSS.Attribute.BORDER_RIGHT_WIDTH, bv);
Object nlv = new LengthValue(true);
valueConvertor.put(CSS.Attribute.TEXT_INDENT, nlv);
valueConvertor.put(CSS.Attribute.WIDTH, lv);
valueConvertor.put(CSS.Attribute.HEIGHT, lv);
valueConvertor.put(CSS.Attribute.BORDER_SPACING, lv);
Object sv = new StringValue();
valueConvertor.put(CSS.Attribute.FONT_STYLE, sv);
valueConvertor.put(CSS.Attribute.TEXT_DECORATION, sv);
valueConvertor.put(CSS.Attribute.TEXT_ALIGN, sv);
valueConvertor.put(CSS.Attribute.VERTICAL_ALIGN, sv);
Object valueMapper = new CssValueMapper();
valueConvertor.put(CSS.Attribute.LIST_STYLE_TYPE,
valueMapper);
valueConvertor.put(CSS.Attribute.BACKGROUND_IMAGE,
new BackgroundImage());
valueConvertor.put(CSS.Attribute.BACKGROUND_POSITION,
new BackgroundPosition());
valueConvertor.put(CSS.Attribute.BACKGROUND_REPEAT,
valueMapper);
valueConvertor.put(CSS.Attribute.BACKGROUND_ATTACHMENT,
valueMapper);
Object generic = new CssValue();
int n = CSS.Attribute.allAttributes.length;
for (int i = 0; i < n; i++) {
CSS.Attribute key = CSS.Attribute.allAttributes[i];
if (valueConvertor.get(key) == null) {
valueConvertor.put(key, generic);
}
}
}
/**
* Sets the base font size. <code>sz is a CSS value, and is
* not necessarily the point size. Use getPointSize to determine the
* point size corresponding to <code>sz.
*/
void setBaseFontSize(int sz) {
if (sz < 1)
baseFontSize = 0;
else if (sz > 7)
baseFontSize = 7;
else
baseFontSize = sz;
}
/**
* Sets the base font size from the passed in string.
*/
void setBaseFontSize(String size) {
int relSize, absSize, diff;
if (size != null) {
if (size.startsWith("+")) {
relSize = Integer.valueOf(size.substring(1)).intValue();
setBaseFontSize(baseFontSize + relSize);
} else if (size.startsWith("-")) {
relSize = -Integer.valueOf(size.substring(1)).intValue();
setBaseFontSize(baseFontSize + relSize);
} else {
setBaseFontSize(Integer.valueOf(size).intValue());
}
}
}
/**
* Returns the base font size.
*/
int getBaseFontSize() {
return baseFontSize;
}
/**
* Parses the CSS property <code>key with value
* <code>value placing the result in att.
*/
void addInternalCSSValue(MutableAttributeSet attr,
CSS.Attribute key, String value) {
if (key == CSS.Attribute.FONT) {
ShorthandFontParser.parseShorthandFont(this, value, attr);
}
else if (key == CSS.Attribute.BACKGROUND) {
ShorthandBackgroundParser.parseShorthandBackground
(this, value, attr);
}
else if (key == CSS.Attribute.MARGIN) {
ShorthandMarginParser.parseShorthandMargin(this, value, attr,
CSS.Attribute.ALL_MARGINS);
}
else if (key == CSS.Attribute.PADDING) {
ShorthandMarginParser.parseShorthandMargin(this, value, attr,
CSS.Attribute.ALL_PADDING);
}
else if (key == CSS.Attribute.BORDER_WIDTH) {
ShorthandMarginParser.parseShorthandMargin(this, value, attr,
CSS.Attribute.ALL_BORDER_WIDTHS);
}
else if (key == CSS.Attribute.BORDER_COLOR) {
ShorthandMarginParser.parseShorthandMargin(this, value, attr,
CSS.Attribute.ALL_BORDER_COLORS);
}
else if (key == CSS.Attribute.BORDER_STYLE) {
ShorthandMarginParser.parseShorthandMargin(this, value, attr,
CSS.Attribute.ALL_BORDER_STYLES);
}
else if ((key == CSS.Attribute.BORDER) ||
(key == CSS.Attribute.BORDER_TOP) ||
(key == CSS.Attribute.BORDER_RIGHT) ||
(key == CSS.Attribute.BORDER_BOTTOM) ||
(key == CSS.Attribute.BORDER_LEFT)) {
ShorthandBorderParser.parseShorthandBorder(attr, key, value);
}
else {
Object iValue = getInternalCSSValue(key, value);
if (iValue != null) {
attr.addAttribute(key, iValue);
}
}
}
/**
* Gets the internal CSS representation of <code>value which is
* a CSS value of the CSS attribute named <code>key. The receiver
* should not modify <code>value, and the first count
* strings are valid.
*/
Object getInternalCSSValue(CSS.Attribute key, String value) {
CssValue conv = (CssValue) valueConvertor.get(key);
Object r = conv.parseCssValue(value);
return r != null ? r : conv.parseCssValue(key.getDefaultValue());
}
/**
* Maps from a StyleConstants to a CSS Attribute.
*/
Attribute styleConstantsKeyToCSSKey(StyleConstants sc) {
return styleConstantToCssMap.get(sc);
}
/**
* Maps from a StyleConstants value to a CSS value.
*/
Object styleConstantsValueToCSSValue(StyleConstants sc,
Object styleValue) {
Attribute cssKey = styleConstantsKeyToCSSKey(sc);
if (cssKey != null) {
CssValue conv = (CssValue)valueConvertor.get(cssKey);
return conv.fromStyleConstants(sc, styleValue);
}
return null;
}
/**
* Converts the passed in CSS value to a StyleConstants value.
* <code>key identifies the CSS attribute being mapped.
*/
Object cssValueToStyleConstantsValue(StyleConstants key, Object value) {
if (value instanceof CssValue) {
return ((CssValue)value).toStyleConstants(key, null);
}
return null;
}
/**
* Returns the font for the values in the passed in AttributeSet.
* It is assumed the keys will be CSS.Attribute keys.
* <code>sc is the StyleContext that will be messaged to get
* the font once the size, name and style have been determined.
*/
Font getFont(StyleContext sc, AttributeSet a, int defaultSize, StyleSheet ss) {
ss = getStyleSheet(ss);
int size = getFontSize(a, defaultSize, ss);
/*
* If the vertical alignment is set to either superscirpt or
* subscript we reduce the font size by 2 points.
*/
StringValue vAlignV = (StringValue)a.getAttribute
(CSS.Attribute.VERTICAL_ALIGN);
if ((vAlignV != null)) {
String vAlign = vAlignV.toString();
if ((vAlign.indexOf("sup") >= 0) ||
(vAlign.indexOf("sub") >= 0)) {
size -= 2;
}
}
FontFamily familyValue = (FontFamily)a.getAttribute
(CSS.Attribute.FONT_FAMILY);
String family = (familyValue != null) ? familyValue.getValue() :
Font.SANS_SERIF;
int style = Font.PLAIN;
FontWeight weightValue = (FontWeight) a.getAttribute
(CSS.Attribute.FONT_WEIGHT);
if ((weightValue != null) && (weightValue.getValue() > 400)) {
style |= Font.BOLD;
}
Object fs = a.getAttribute(CSS.Attribute.FONT_STYLE);
if ((fs != null) && (fs.toString().indexOf("italic") >= 0)) {
style |= Font.ITALIC;
}
if (family.equalsIgnoreCase("monospace")) {
family = Font.MONOSPACED;
}
Font f = sc.getFont(family, style, size);
if (f == null
|| (f.getFamily().equals(Font.DIALOG)
&& ! family.equalsIgnoreCase(Font.DIALOG))) {
family = Font.SANS_SERIF;
f = sc.getFont(family, style, size);
}
return f;
}
static int getFontSize(AttributeSet attr, int defaultSize, StyleSheet ss) {
// PENDING(prinz) this is a 1.1 based implementation, need to also
// have a 1.2 version.
FontSize sizeValue = (FontSize)attr.getAttribute(CSS.Attribute.
FONT_SIZE);
return (sizeValue != null) ? sizeValue.getValue(attr, ss)
: defaultSize;
}
/**
* Takes a set of attributes and turn it into a color
* specification. This might be used to specify things
* like brighter, more hue, etc.
* This will return null if there is no value for <code>key.
*
* @param key CSS.Attribute identifying where color is stored.
* @param a the set of attributes
* @return the color
*/
Color getColor(AttributeSet a, CSS.Attribute key) {
ColorValue cv = (ColorValue) a.getAttribute(key);
if (cv != null) {
return cv.getValue();
}
return null;
}
/**
* Returns the size of a font from the passed in string.
*
* @param size CSS string describing font size
* @param baseFontSize size to use for relative units.
*/
float getPointSize(String size, StyleSheet ss) {
int relSize, absSize, diff, index;
ss = getStyleSheet(ss);
if (size != null) {
if (size.startsWith("+")) {
relSize = Integer.valueOf(size.substring(1)).intValue();
return getPointSize(baseFontSize + relSize, ss);
} else if (size.startsWith("-")) {
relSize = -Integer.valueOf(size.substring(1)).intValue();
return getPointSize(baseFontSize + relSize, ss);
} else {
absSize = Integer.valueOf(size).intValue();
return getPointSize(absSize, ss);
}
}
return 0;
}
/**
* Returns the length of the attribute in <code>a with
* key <code>key.
*/
float getLength(AttributeSet a, CSS.Attribute key, StyleSheet ss) {
ss = getStyleSheet(ss);
LengthValue lv = (LengthValue) a.getAttribute(key);
boolean isW3CLengthUnits = (ss == null) ? false : ss.isW3CLengthUnits();
float len = (lv != null) ? lv.getValue(isW3CLengthUnits) : 0;
return len;
}
/**
* Convert a set of HTML attributes to an equivalent
* set of CSS attributes.
*
* @param htmlAttrSet AttributeSet containing the HTML attributes.
* @return AttributeSet containing the corresponding CSS attributes.
* The AttributeSet will be empty if there are no mapping
* CSS attributes.
*/
AttributeSet translateHTMLToCSS(AttributeSet htmlAttrSet) {
MutableAttributeSet cssAttrSet = new SimpleAttributeSet();
Element elem = (Element)htmlAttrSet;
HTML.Tag tag = getHTMLTag(htmlAttrSet);
if ((tag == HTML.Tag.TD) || (tag == HTML.Tag.TH)) {
// translate border width into the cells, if it has non-zero value.
AttributeSet tableAttr = elem.getParentElement().
getParentElement().getAttributes();
int borderWidth = getTableBorder(tableAttr);
if (borderWidth > 0) {
// If table contains the BORDER attribute cells should have border width equals 1
translateAttribute(HTML.Attribute.BORDER, "1", cssAttrSet);
}
String pad = (String)tableAttr.getAttribute(HTML.Attribute.CELLPADDING);
if (pad != null) {
LengthValue v =
(LengthValue)getInternalCSSValue(CSS.Attribute.PADDING_TOP, pad);
v.span = (v.span < 0) ? 0 : v.span;
cssAttrSet.addAttribute(CSS.Attribute.PADDING_TOP, v);
cssAttrSet.addAttribute(CSS.Attribute.PADDING_BOTTOM, v);
cssAttrSet.addAttribute(CSS.Attribute.PADDING_LEFT, v);
cssAttrSet.addAttribute(CSS.Attribute.PADDING_RIGHT, v);
}
}
if (elem.isLeaf()) {
translateEmbeddedAttributes(htmlAttrSet, cssAttrSet);
} else {
translateAttributes(tag, htmlAttrSet, cssAttrSet);
}
if (tag == HTML.Tag.CAPTION) {
/*
* Navigator uses ALIGN for caption placement and IE uses VALIGN.
*/
Object v = htmlAttrSet.getAttribute(HTML.Attribute.ALIGN);
if ((v != null) && (v.equals("top") || v.equals("bottom"))) {
cssAttrSet.addAttribute(CSS.Attribute.CAPTION_SIDE, v);
cssAttrSet.removeAttribute(CSS.Attribute.TEXT_ALIGN);
} else {
v = htmlAttrSet.getAttribute(HTML.Attribute.VALIGN);
if (v != null) {
cssAttrSet.addAttribute(CSS.Attribute.CAPTION_SIDE, v);
}
}
}
return cssAttrSet;
}
private static int getTableBorder(AttributeSet tableAttr) {
String borderValue = (String) tableAttr.getAttribute(HTML.Attribute.BORDER);
if (borderValue == HTML.NULL_ATTRIBUTE_VALUE || "".equals(borderValue)) {
// Some browsers accept <TABLE BORDER> and
with the same semantics as BORDER=1
return 1;
}
try {
return Integer.parseInt(borderValue);
} catch (NumberFormatException e) {
return 0;
}
}
private static final Hashtable<String, Attribute> attributeMap = new Hashtable();
private static final Hashtable<String, Value> valueMap = new Hashtable();
/**
* The hashtable and the static initalization block below,
* set up a mapping from well-known HTML attributes to
* CSS attributes. For the most part, there is a 1-1 mapping
* between the two. However in the case of certain HTML
* attributes for example HTML.Attribute.VSPACE or
* HTML.Attribute.HSPACE, end up mapping to two CSS.Attribute's.
* Therefore, the value associated with each HTML.Attribute.
* key ends up being an array of CSS.Attribute.* objects.
*/
private static final Hashtable<HTML.Attribute, CSS.Attribute[]> htmlAttrToCssAttrMap = new Hashtable(20);
/**
* The hashtable and static initialization that follows sets
* up a translation from StyleConstants (i.e. the <em>well known
* attributes) to the associated CSS attributes.
*/
private static final Hashtable<Object, Attribute> styleConstantToCssMap = new Hashtable