From 554fd8c5195424bdbcabf5de30fdc183aba391bd Mon Sep 17 00:00:00 2001 From: upstream source tree Date: Sun, 15 Mar 2015 20:14:05 -0400 Subject: obtained gcc-4.6.4.tar.bz2 from upstream website; verified gcc-4.6.4.tar.bz2.sig; imported gcc-4.6.4 source tree from verified upstream tarball. downloading a git-generated archive based on the 'upstream' tag should provide you with a source tree that is binary identical to the one extracted from the above tarball. if you have obtained the source via the command 'git clone', however, do note that line-endings of files in your working directory might differ from line-endings of the respective files in the upstream repository. --- .../javax/swing/text/html/StyleSheet.java | 1455 ++++++++++++++++++++ 1 file changed, 1455 insertions(+) create mode 100644 libjava/classpath/javax/swing/text/html/StyleSheet.java (limited to 'libjava/classpath/javax/swing/text/html/StyleSheet.java') diff --git a/libjava/classpath/javax/swing/text/html/StyleSheet.java b/libjava/classpath/javax/swing/text/html/StyleSheet.java new file mode 100644 index 000000000..5cf015bc5 --- /dev/null +++ b/libjava/classpath/javax/swing/text/html/StyleSheet.java @@ -0,0 +1,1455 @@ +/* StyleSheet.java -- + Copyright (C) 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.text.html; + +import gnu.javax.swing.text.html.css.BorderWidth; +import gnu.javax.swing.text.html.css.CSSColor; +import gnu.javax.swing.text.html.css.CSSParser; +import gnu.javax.swing.text.html.css.CSSParserCallback; +import gnu.javax.swing.text.html.css.FontSize; +import gnu.javax.swing.text.html.css.FontStyle; +import gnu.javax.swing.text.html.css.FontWeight; +import gnu.javax.swing.text.html.css.Length; +import gnu.javax.swing.text.html.css.Selector; + +import java.awt.Color; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.Rectangle; +import java.awt.Shape; +import java.awt.font.FontRenderContext; +import java.awt.geom.Rectangle2D; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.io.Serializable; +import java.io.StringReader; +import java.net.URL; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import javax.swing.border.Border; +import javax.swing.event.ChangeListener; +import javax.swing.text.AttributeSet; +import javax.swing.text.Element; +import javax.swing.text.MutableAttributeSet; +import javax.swing.text.SimpleAttributeSet; +import javax.swing.text.Style; +import javax.swing.text.StyleConstants; +import javax.swing.text.StyleContext; +import javax.swing.text.View; + + +/** + * This class adds support for defining the visual characteristics of HTML views + * being rendered. This enables views to be customized by a look-and-feel, mulitple + * views over the same model can be rendered differently. Each EditorPane has its + * own StyleSheet, but by default one sheet will be shared by all of the HTMLEditorKit + * instances. An HTMLDocument can also have a StyleSheet, which holds specific CSS + * specs. + * + * In order for Views to store less state and therefore be more lightweight, + * the StyleSheet can act as a factory for painters that handle some of the + * rendering tasks. Since the StyleSheet may be used by views over multiple + * documents the HTML attributes don't effect the selector being used. + * + * The rules are stored as named styles, and other information is stored to + * translate the context of an element to a rule. + * + * @author Lillian Angel (langel@redhat.com) + */ +public class StyleSheet extends StyleContext +{ + + /** + * Parses CSS stylesheets using the parser in gnu/javax/swing/html/css. + * + * This is package private to avoid accessor methods. + */ + class CSSStyleSheetParserCallback + implements CSSParserCallback + { + /** + * The current styles. + */ + private CSSStyle[] styles; + + /** + * The precedence of the stylesheet to be parsed. + */ + private int precedence; + + /** + * Creates a new CSS parser. This parser parses a CSS stylesheet with + * the specified precedence. + * + * @param prec the precedence, according to the constants defined in + * CSSStyle + */ + CSSStyleSheetParserCallback(int prec) + { + precedence = prec; + } + + /** + * Called at the beginning of a statement. + * + * @param sel the selector + */ + public void startStatement(Selector[] sel) + { + styles = new CSSStyle[sel.length]; + for (int i = 0; i < sel.length; i++) + styles[i] = new CSSStyle(precedence, sel[i]); + } + + /** + * Called at the end of a statement. + */ + public void endStatement() + { + for (int i = 0; i < styles.length; i++) + css.add(styles[i]); + styles = null; + } + + /** + * Called when a declaration is parsed. + * + * @param property the property + * @param value the value + */ + public void declaration(String property, String value) + { + CSS.Attribute cssAtt = CSS.getAttribute(property); + Object val = CSS.getValue(cssAtt, value); + for (int i = 0; i < styles.length; i++) + { + CSSStyle style = styles[i]; + CSS.addInternal(style, cssAtt, value); + if (cssAtt != null) + style.addAttribute(cssAtt, val); + } + } + + } + + /** + * Represents a style that is defined by a CSS rule. + */ + private class CSSStyle + extends SimpleAttributeSet + implements Style, Comparable + { + + static final int PREC_UA = 0; + static final int PREC_NORM = 100000; + static final int PREC_AUTHOR_NORMAL = 200000; + static final int PREC_AUTHOR_IMPORTANT = 300000; + static final int PREC_USER_IMPORTANT = 400000; + + /** + * The priority of this style when matching CSS selectors. + */ + private int precedence; + + /** + * The selector for this rule. + * + * This is package private to avoid accessor methods. + */ + Selector selector; + + CSSStyle(int prec, Selector sel) + { + precedence = prec; + selector = sel; + } + + public String getName() + { + // TODO: Implement this for correctness. + return null; + } + + public void addChangeListener(ChangeListener listener) + { + // TODO: Implement this for correctness. + } + + public void removeChangeListener(ChangeListener listener) + { + // TODO: Implement this for correctness. + } + + /** + * Sorts the rule according to the style's precedence and the + * selectors specificity. + */ + public int compareTo(CSSStyle other) + { + return other.precedence + other.selector.getSpecificity() + - precedence - selector.getSpecificity(); + } + + } + + /** The base URL */ + URL base; + + /** Base font size (int) */ + int baseFontSize; + + /** + * The linked style sheets stored. + */ + private ArrayList linked; + + /** + * Maps element names (selectors) to AttributSet (the corresponding style + * information). + */ + ArrayList css = new ArrayList(); + + /** + * Maps selectors to their resolved styles. + */ + private HashMap resolvedStyles; + + /** + * Constructs a StyleSheet. + */ + public StyleSheet() + { + super(); + baseFontSize = 4; // Default font size from CSS + resolvedStyles = new HashMap(); + } + + /** + * Gets the style used to render the given tag. The element represents the tag + * and can be used to determine the nesting, where the attributes will differ + * if there is nesting inside of elements. + * + * @param t - the tag to translate to visual attributes + * @param e - the element representing the tag + * @return the set of CSS attributes to use to render the tag. + */ + public Style getRule(HTML.Tag t, Element e) + { + // Create list of the element and all of its parents, starting + // with the bottommost element. + ArrayList path = new ArrayList(); + Element el; + AttributeSet atts; + for (el = e; el != null; el = el.getParentElement()) + path.add(el); + + // Create fully qualified selector. + StringBuilder selector = new StringBuilder(); + int count = path.size(); + // We append the actual element after this loop. + for (int i = count - 1; i > 0; i--) + { + el = path.get(i); + atts = el.getAttributes(); + Object name = atts.getAttribute(StyleConstants.NameAttribute); + selector.append(name.toString()); + if (atts.isDefined(HTML.Attribute.ID)) + { + selector.append('#'); + selector.append(atts.getAttribute(HTML.Attribute.ID)); + } + if (atts.isDefined(HTML.Attribute.CLASS)) + { + selector.append('.'); + selector.append(atts.getAttribute(HTML.Attribute.CLASS)); + } + if (atts.isDefined(HTML.Attribute.DYNAMIC_CLASS)) + { + selector.append(':'); + selector.append(atts.getAttribute(HTML.Attribute.DYNAMIC_CLASS)); + } + if (atts.isDefined(HTML.Attribute.PSEUDO_CLASS)) + { + selector.append(':'); + selector.append(atts.getAttribute(HTML.Attribute.PSEUDO_CLASS)); + } + selector.append(' '); + } + selector.append(t.toString()); + el = path.get(0); + atts = el.getAttributes(); + // For leaf elements, we have to fetch the tag specific attributes. + if (el.isLeaf()) + { + Object o = atts.getAttribute(t); + if (o instanceof AttributeSet) + atts = (AttributeSet) o; + else + atts = null; + } + if (atts != null) + { + if (atts.isDefined(HTML.Attribute.ID)) + { + selector.append('#'); + selector.append(atts.getAttribute(HTML.Attribute.ID)); + } + if (atts.isDefined(HTML.Attribute.CLASS)) + { + selector.append('.'); + selector.append(atts.getAttribute(HTML.Attribute.CLASS)); + } + if (atts.isDefined(HTML.Attribute.DYNAMIC_CLASS)) + { + selector.append(':'); + selector.append(atts.getAttribute(HTML.Attribute.DYNAMIC_CLASS)); + } + if (atts.isDefined(HTML.Attribute.PSEUDO_CLASS)) + { + selector.append(':'); + selector.append(atts.getAttribute(HTML.Attribute.PSEUDO_CLASS)); + } + } + return getResolvedStyle(selector.toString(), path, t); + } + + /** + * Fetches a resolved style. If there is no resolved style for the + * specified selector, the resolve the style using + * {@link #resolveStyle(String, List, HTML.Tag)}. + * + * @param selector the selector for which to resolve the style + * @param path the Element path, used in the resolving algorithm + * @param tag the tag for which to resolve + * + * @return the resolved style + */ + private Style getResolvedStyle(String selector, List path, HTML.Tag tag) + { + Style style = resolvedStyles.get(selector); + if (style == null) + style = resolveStyle(selector, path, tag); + return style; + } + + /** + * Resolves a style. This creates arrays that hold the tag names, + * class and id attributes and delegates the work to + * {@link #resolveStyle(String, String[], List>)}. + * + * @param selector the selector + * @param path the Element path + * @param tag the tag + * + * @return the resolved style + */ + private Style resolveStyle(String selector, List path, HTML.Tag tag) + { + int count = path.size(); + String[] tags = new String[count]; + List> attributes = + new ArrayList>(count); + for (int i = 0; i < count; i++) + { + Element el = path.get(i); + AttributeSet atts = el.getAttributes(); + if (i == 0 && el.isLeaf()) + { + Object o = atts.getAttribute(tag); + if (o instanceof AttributeSet) + atts = (AttributeSet) o; + else + atts = null; + } + if (atts != null) + { + HTML.Tag t = + (HTML.Tag) atts.getAttribute(StyleConstants.NameAttribute); + if (t != null) + tags[i] = t.toString(); + else + tags[i] = null; + attributes.set(i, attributeSetToMap(atts)); + } + else + { + tags[i] = null; + } + } + tags[0] = tag.toString(); + return resolveStyle(selector, tags, attributes); + } + + /** + * Performs style resolving. + * + * @param selector the selector + * @param tags the tags + * @param attributes the attributes of the tags + * + * @return the resolved style + */ + private Style resolveStyle(String selector, String[] tags, + List> attributes) + { + // FIXME: This style resolver is not correct. But it works good enough for + // the default.css. + ArrayList styles = new ArrayList(); + for (CSSStyle style : css) + { + if (style.selector.matches(tags, attributes)) + styles.add(style); + } + + // Add styles from linked stylesheets. + if (linked != null) + { + for (int i = linked.size() - 1; i >= 0; i--) + { + StyleSheet ss = linked.get(i); + for (int j = ss.css.size() - 1; j >= 0; j--) + { + CSSStyle style = ss.css.get(j); + if (style.selector.matches(tags, attributes)) + styles.add(style); + } + } + } + + // Sort selectors. + Collections.sort(styles); + Style[] styleArray = styles.toArray(new Style[styles.size()]); + Style resolved = new MultiStyle(selector, styleArray); + resolvedStyles.put(selector, resolved); + return resolved; + } + + /** + * Gets the rule that best matches the selector. selector is a space + * separated String of element names. The attributes of the returned + * Style will change as rules are added and removed. + * + * @param selector - the element names separated by spaces + * @return the set of CSS attributes to use to render + */ + public Style getRule(String selector) + { + CSSStyle best = null; + for (Iterator i = css.iterator(); i.hasNext();) + { + CSSStyle style = i.next(); + if (style.compareTo(best) < 0) + best = style; + } + return best; + } + + /** + * Adds a set of rules to the sheet. The rules are expected to be in valid + * CSS format. This is called as a result of parsing a