/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* 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.
*/
/**
* Support for defining the visual characteristics of
* HTML views being rendered. The StyleSheet is used to
* translate the HTML model into visual characteristics.
* This enables views to be customized by a look-and-feel,
* multiple views over the same model can be rendered
* differently, etc. This can be thought of as a CSS
* rule repository. The key for CSS attributes is an
* object of type CSS.Attribute. The type of the value
* is up to the StyleSheet implementation, but the
* <code>toString</code> method is required
* to return a string representation of CSS value.
* <p>
* The primary entry point for HTML View implementations
* to get their attributes is the
* {@link #getViewAttributes getViewAttributes}
* method. This should be implemented to establish the
* desired policy used to associate attributes with the view.
* Each HTMLEditorKit (i.e. and therefore each associated
* JEditorPane) can have its own StyleSheet, but by default one
* sheet will be shared by all of the HTMLEditorKit instances.
* HTMLDocument instance can also have a StyleSheet, which
* holds the document-specific CSS specifications.
* <p>
* 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. This allows
* implementations to determine what they want to cache
* and have the sharing potentially at the level that a
* selector is common to multiple views. Since the StyleSheet
* may be used by views over multiple documents and typically
* the HTML attributes don't effect the selector being used,
* the potential for sharing is significant.
* <p>
* The rules are stored as named styles, and other information
* is stored to translate the context of an element to a
* rule quickly. The following code fragment will display
* the named styles, and therefore the CSS rules contained.
* <code><pre>
*
* import java.util.*;
* import javax.swing.text.*;
* import javax.swing.text.html.*;
*
* public class ShowStyles {
*
* public static void main(String[] args) {
* HTMLEditorKit kit = new HTMLEditorKit();
* HTMLDocument doc = (HTMLDocument) kit.createDefaultDocument();
* StyleSheet styles = doc.getStyleSheet();
*
* Enumeration rules = styles.getStyleNames();
* while (rules.hasMoreElements()) {
* String name = (String) rules.nextElement();
* Style rule = styles.getStyle(name);
* System.out.println(rule.toString());
* }
* System.exit(0);
* }
* }
*
* </pre></code>
* <p>
* The semantics for when a CSS style should overide visual attributes
* defined by an element are not well defined. For example, the html
* <code><body bgcolor=red></code> makes the body have a red
* background. But if the html file also contains the CSS rule
* <code>body { background: blue }</code> it becomes less clear as to
* what color the background of the body should be. The current
* implemention gives visual attributes defined in the element the
* highest precedence, that is they are always checked before any styles.
* Therefore, in the previous example the background would have a
* red color as the body element defines the background color to be red.
* <p>
* As already mentioned this supports CSS. We don't support the full CSS
* spec. Refer to the javadoc of the CSS class to see what properties
* we support. The two major CSS parsing related
* concepts we do not currently
* support are pseudo selectors, such as <code>A:link { color: red }</code>,
* and the <code>important</code> modifier.
* <p>
* <font color="red">Note: This implementation is currently
* incomplete. It can be replaced with alternative implementations
* that are complete. Future versions of this class will provide
* better CSS support.</font>
*
* @author Timothy Prinzing
* @author Sunita Mani
* @author Sara Swanson
* @author Jill Nakata
*/
// As the javadoc states, this class maintains a mapping between
// a CSS selector (such as p.bar) and a Style.
// This consists of a number of parts:
// . Each selector is broken down into its constituent simple selectors,
// and stored in an inverted graph, for example:
// p { color: red } ol p { font-size: 10pt } ul p { font-size: 12pt }
// results in the graph:
// root
// |
// p
// / \
// ol ul
// each node (an instance of SelectorMapping) has an associated
// specificity and potentially a Style.
// . Every rule that is asked for (either by way of getRule(String) or
// getRule(HTML.Tag, Element)) results in a unique instance of
// ResolvedStyle. ResolvedStyles contain the AttributeSets from the
// SelectorMapping.
// . When a new rule is created it is inserted into the graph, and
// the AttributeSets of each ResolvedStyles are updated appropriately.
// . This class creates special AttributeSets, LargeConversionSet and
// SmallConversionSet, that maintain a mapping between StyleConstants
// and CSS so that developers that wish to use the StyleConstants
// methods can do so.
// . When one of the AttributeSets is mutated by way of a
// StyleConstants key, all the associated CSS keys are removed. This is
// done so that the two representations don't get out of sync. For
// example, if the developer adds StyleConsants.BOLD, FALSE to an
// AttributeSet that contains HTML.Tag.B, the HTML.Tag.B entry will
// be removed.
/**
* Construct a StyleSheet
*/
public StyleSheet() {
super();
}
}
/**
* Fetches the style to use to render the given type
* of HTML tag. The element given is representing
* the tag and can be used to determine the nesting
* for situations where the attributes will differ
* if nesting inside of elements.
*
* @param t the type to translate to visual attributes
* @param e the element representing the tag; the element
* can be used to determine the nesting for situations where
* the attributes will differ if nested inside of other
* elements
* @return the set of CSS attributes to use to render
* the tag
*/
try {
// Build an array of all the parent elements.
}
// Build a fully qualified selector.
int n = searchContext.size();
// >= 1 as the HTML.Tag for the 0th element is passed in.
attr = e.getAttributes();
}
}
}
}
attr = e.getAttributes();
if (e.isLeaf()) {
// For leafs, we use the second tier attributes.
if (testAttr instanceof AttributeSet) {
}
else {
}
}
}
}
}
searchContext, t);
return style;
}
finally {
}
}
/**
* Fetches the rule that best matches the selector given
* in string form. Where <code>selector</code> is a space separated
* String of the element names. For example, <code>selector</code>
* might be 'html body tr td''<p>
* The attributes of the returned Style will change
* as rules are added and removed. That is if you to ask for a rule
* with a selector "table p" and a new rule was added with a selector
* of "p" the returned Style would include the new attributes from
* the rule "p".
*/
return style;
}
return null;
}
/**
* Adds a set of rules to the sheet. The rules are expected to
* be in valid CSS format. Typically this would be called as
* a result of parsing a <style> tag.
*/
//tweaks to control display properties
//see BasicEditorPaneUI
if (rule == baseUnitsDisable) {
} else if (rule == w3cLengthUnitsEnable) {
w3cLengthUnits = true;
} else if (rule == w3cLengthUnitsDisable) {
w3cLengthUnits = false;
} else {
try {
} catch (IOException ioe) { }
}
}
}
/**
* Translates a CSS declaration to an AttributeSet that represents
* the CSS declaration. Typically this would be called as a
* result of encountering an HTML style attribute.
*/
return SimpleAttributeSet.EMPTY;
}
}
/**
* Loads a set of rules that have been specified in terms of
* CSS1 grammar. If there are collisions with existing rules,
* the newly specified rule will win.
*
* @param in the stream to read the CSS grammar from
* @param ref the reference URL. This value represents the
* location of the stream and may be null. All relative
* URLs specified in the stream will be based upon this
* parameter.
*/
}
/**
* Fetches a set of attributes to use in the view for
* displaying. This is basically a set of attributes that
* can be used for View.getAttributes.
*/
return new ViewAttributeSet(v);
}
/**
* Removes a named style previously added to the document.
*
* @param nm the name of the style to remove
*/
synchronized(this) {
true);
}
while (values.hasMoreElements()) {
}
}
}
}
}
super.removeStyle(nm);
}
/**
* Adds the rules from the StyleSheet <code>ss</code> to those of
* the receiver. <code>ss's</code> rules will override the rules of
* any previously added style sheets. An added StyleSheet will never
* override the rules of the receiving style sheet.
*
* @since 1.3
*/
synchronized(this) {
if (linkedStyleSheets == null) {
}
int index = 0;
}
}
}
}
/**
* Removes the StyleSheet <code>ss</code> from those of the receiver.
*
* @since 1.3
*/
synchronized(this) {
if (linkedStyleSheets != null) {
if (index != -1) {
}
}
}
}
}
//
// The following is used to import style sheets.
//
/**
* Returns an array of the linked StyleSheets. Will return null
* if there are no linked StyleSheets.
*
* @since 1.3
*/
synchronized(this) {
if (linkedStyleSheets != null) {
}
else {
}
}
return retValue;
}
/**
* Imports a style sheet from <code>url</code>. The resulting rules
* are directly added to the receiver. If you do not want the rules
* to become part of the receiver, create a new StyleSheet and use
* addStyleSheet to link it in.
*
* @since 1.3
*/
try {
r.close();
} catch (Throwable e) {
// on error we simply have no styles... the html
// will look mighty wrong but still function.
}
}
/**
* Sets the base. All import statements that are relative, will be
* relative to <code>base</code>.
*
* @since 1.3
*/
}
/**
* Returns the base.
*
* @since 1.3
*/
return base;
}
/**
* Adds a CSS attribute to the given set.
*
* @since 1.3
*/
}
/**
* Adds a CSS attribute to the given set.
*
* @since 1.3
*/
return true;
}
return false;
}
// ---- Conversion functionality ---------------------------------
/**
* Converts a set of HTML attributes to an equivalent
* set of CSS attributes.
*
* @param htmlAttrSet AttributeSet containing the HTML attributes.
*/
return cssStyleSet;
}
/**
* Adds an attribute to the given set, and returns
* the new representative set. This is reimplemented to
* convert StyleConstant attributes to CSS prior to forwarding
* to the superclass behavior. The StyleConstants attribute
* has no corresponding CSS entry, the StyleConstants attribute
* is stored (but will likely be unused).
*
* @param old the old attribute set
* @param key the non-null attribute key
* @param value the attribute value
* @return the updated attribute set
* @see MutableAttributeSet#addAttribute
*/
// supers constructor will call this before returning,
// and we need to make sure CSS is non null.
}
if (key instanceof StyleConstants) {
}
((StyleConstants)key);
}
}
}
}
/**
* Adds a set of attributes to the element. If any of these attributes
* are StyleConstants attributes, they will be converted to CSS prior
* to forwarding to the superclass behavior.
*
* @param old the old attribute set
* @param attr the attributes to add
* @return the updated attribute set
* @see MutableAttributeSet#addAttribute
*/
}
}
/**
* Removes an attribute from the set. If the attribute is a StyleConstants
* attribute, the request will be converted to a CSS attribute prior to
* forwarding to the superclass behavior.
*
* @param old the old set of attributes
* @param key the non-null attribute name
* @return the updated attribute set
* @see MutableAttributeSet#removeAttribute
*/
if (key instanceof StyleConstants) {
}
}
}
}
/**
* Removes a set of attributes for the element. If any of the attributes
* is a StyleConstants attribute, the request will be converted to a CSS
* attribute prior to forwarding to the superclass behavior.
*
* @param old the old attribute set
* @param names the attribute names
* @return the updated attribute set
* @see MutableAttributeSet#removeAttributes
*/
// PENDING: Should really be doing something similar to
// removeHTMLTags here, but it is rather expensive to have to
// clone names
}
/**
* Removes a set of attributes. If any of the attributes
* is a StyleConstants attribute, the request will be converted to a CSS
* attribute prior to forwarding to the superclass behavior.
*
* @param old the old attribute set
* @param attrs the attributes
* @return the updated attribute set
* @see MutableAttributeSet#removeAttributes
*/
}
}
/**
* Creates a compact set of attributes that might be shared.
* This is a hook for subclasses that want to alter the
* behavior of SmallAttributeSet. This can be reimplemented
* to return an AttributeSet that provides some sort of
* attribute conversion.
*
* @param a The set of attributes to be represented in the
* the compact form.
*/
return new SmallConversionSet(a);
}
/**
* Creates a large set of attributes that should trade off
* space for time. This set will not be shared. This is
* a hook for subclasses that want to alter the behavior
* of the larger attribute storage format (which is
* SimpleAttributeSet by default). This can be reimplemented
* to return a MutableAttributeSet that provides some sort of
* attribute conversion.
*
* @param a The set of attributes to be represented in the
* the larger form.
*/
return new LargeConversionSet(a);
}
/**
* For any StyleConstants key in attr that has an associated HTML.Tag,
* it is removed from old. The resulting AttributeSet is then returned.
*/
if (!(attr instanceof LargeConversionSet) &&
!(attr instanceof SmallConversionSet)) {
while (names.hasMoreElements()) {
if (key instanceof StyleConstants) {
}
}
}
}
return old;
}
/**
* Converts a set of attributes (if necessary) so that
* any attributes that were specified as StyleConstants
* attributes and have a CSS mapping, will be converted
* to CSS attributes.
*/
if ((a instanceof LargeConversionSet) ||
(a instanceof SmallConversionSet)) {
// known to be converted.
return a;
}
// in most cases, there are no StyleConstants attributes
// so we iterate the collection of keys to avoid creating
// a new set.
while (names.hasMoreElements()) {
if (name instanceof StyleConstants) {
// we really need to do a conversion, iterate again
// building a new set.
while (keys.hasMoreElements()) {
if (key instanceof StyleConstants) {
// convert the StyleConstants attribute if possible
((StyleConstants)key);
}
}
}
}
}
return converted;
}
}
return a;
}
/**
* Large set of attributes that does conversion of requests
* for attributes of type StyleConstants.
*/
/**
* Creates a new attribute set based on a supplied set of attributes.
*
* @param source the set of attributes
*/
super(source);
}
public LargeConversionSet() {
super();
}
/**
* Checks whether a given attribute is defined.
*
* @param key the attribute key
* @return true if the attribute is defined
* @see AttributeSet#isDefined
*/
if (key instanceof StyleConstants) {
((StyleConstants)key);
}
}
}
/**
* Gets the value of an attribute.
*
* @param key the attribute name
* @return the attribute value
* @see AttributeSet#getAttribute
*/
if (key instanceof StyleConstants) {
((StyleConstants)key);
return css.cssValueToStyleConstantsValue
}
}
}
return super.getAttribute(key);
}
}
/**
* Small set of attributes that does conversion of requests
* for attributes of type StyleConstants.
*/
/**
* Creates a new attribute set based on a supplied set of attributes.
*
* @param attrs the set of attributes
*/
super(attrs);
}
/**
* Checks whether a given attribute is defined.
*
* @param key the attribute key
* @return true if the attribute is defined
* @see AttributeSet#isDefined
*/
if (key instanceof StyleConstants) {
((StyleConstants)key);
}
}
}
/**
* Gets the value of an attribute.
*
* @param key the attribute name
* @return the attribute value
* @see AttributeSet#getAttribute
*/
if (key instanceof StyleConstants) {
((StyleConstants)key);
return css.cssValueToStyleConstantsValue
}
}
}
return super.getAttribute(key);
}
}
// ---- Resource handling ----------------------------------------
/**
* Fetches the font to use for the given set of attributes.
*/
}
/**
* Takes a set of attributes and turn it into a foreground color
* specification. This might be used to specify things
* like brighter, more hue, etc.
*
* @param a the set of attributes
* @return the color
*/
if (c == null) {
}
return c;
}
/**
* Takes a set of attributes and turn it into a background color
* specification. This might be used to specify things
* like brighter, more hue, etc.
*
* @param a the set of attributes
* @return the color
*/
}
/**
* Fetches the box formatter to use for the given set
* of CSS attributes.
*/
return new BoxPainter(a, css, this);
}
/**
* Fetches the list formatter to use for the given set
* of CSS attributes.
*/
return new ListPainter(a, this);
}
/**
* Sets the base font size, with valid values between 1 and 7.
*/
}
/**
* Sets the base font size from the passed in String. The string
* can either identify a specific font size, with legal values between
* 1 and 7, or identifiy a relative font size such as +1 or -2.
*/
}
}
/**
* Returns the point size, given a size index.
*/
}
/**
* Given a string such as "+2", "-2", or "2",
* returns a point size value.
*/
}
/**
* Converts a color string such as "RED" or "#NNNNNN" to a Color.
* Note: This will only convert the HTML3.2 color strings
* or a string of length 7;
* otherwise, it will return null.
*/
}
/**
* Returns the ImageIcon to draw in the background for
* <code>attr</code>.
*/
}
return null;
}
/**
* Adds a rule into the StyleSheet.
*
* @param selector the selector to use for the rule.
* This will be a set of simple selectors, and must
* be a length of 1 or greater.
* @param declaration the set of CSS attributes that
* make up the rule.
*/
boolean isLinked) {
}
// Notice how the rule is first created, and it not part of
// the synchronized block. It is done like this as creating
// a new rule will fire a ChangeEvent. We do not want to be
// holding the lock when calling to other objects, it can
// result in deadlock.
synchronized(this) {
for (int i = n - 1; i >= 0; i--) {
(selector[i], true);
}
}
}
}
if (isLinked) {
}
}
//
// The following gaggle of methods is used in maintaing the rules from
// the sheet.
//
/**
* Updates the attributes of the rules to reference any related
* rules in <code>ss</code>.
*/
while (values.hasMoreElements()) {
index);
}
}
}
/**
* Removes references to the rules in <code>ss</code>.
* <code>index</code> gives the index the StyleSheet was at, that is
* how many StyleSheets had been added before it.
*/
while (values.hasMoreElements()) {
}
}
}
/**
* Returns the simple selectors that comprise selector.
*/
/* protected */
int lastIndex = 0;
while (lastIndex != -1) {
if (newIndex != -1) {
lastIndex = -1;
}
else {
}
}
else {
lastIndex = -1;
}
}
return retValue;
}
/**
* Returns a string that only has one space between simple selectors,
* which may be the passed in String.
*/
boolean lastWasSpace = true;
case ' ':
if (lastWasSpace) {
return _cleanSelectorString(selector);
}
lastWasSpace = true;
break;
case '\n':
case '\r':
case '\t':
return _cleanSelectorString(selector);
default:
lastWasSpace = false;
}
}
if (lastWasSpace) {
return _cleanSelectorString(selector);
}
// It was fine.
return selector;
}
/**
* Returns a new String that contains only one space between non
* white space characters.
*/
boolean lastWasSpace = true;
int lastIndex = 0;
try {
case ' ':
if (!lastWasSpace) {
lastWasSpace = true;
}
}
break;
case '\n':
case '\r':
case '\t':
if (!lastWasSpace) {
lastWasSpace = true;
}
}
break;
default:
lastWasSpace = false;
break;
}
}
// Remove last space.
}
}
}
finally {
}
return retValue;
}
/**
* Returns the root selector mapping that all selectors are relative
* to. This is an inverted graph of the selectors.
*/
return selectorMapping;
}
/**
* Returns the specificity of the passed in String. It assumes the
* passed in string doesn't contain junk, that is each selector is
* separated by a space and each selector at most contains one . or one
* #. A simple selector has a weight of 1, an id selector has a weight
* of 100, and a class selector has a weight of 10000.
*/
int specificity = 0;
boolean lastWasSpace = true;
case '.':
specificity += 100;
break;
case '#':
specificity += 10000;
break;
case ' ':
lastWasSpace = true;
break;
default:
if (lastWasSpace) {
lastWasSpace = false;
specificity += 1;
}
}
}
return specificity;
}
/**
* Returns the style that linked attributes should be added to. This
* will create the style if necessary.
*/
// NOTE: This is not synchronized, and the caller of this does
// not synchronize. There is the chance for one of the callers to
// overwrite the existing resolved parent, but it is quite rare.
// The reason this is left like this is because setResolveParent
// will fire a ChangeEvent. It is really, REALLY bad for us to
// hold a lock when calling outside of us, it may cause a deadlock.
}
return retStyle;
}
/**
* Returns the resolved style for <code>selector</code>. This will
* create the resolved style, if necessary.
*/
}
return retStyle;
}
/**
* Returns the resolved style for <code>selector</code>. This will
* create the resolved style, if necessary.
*/
}
return retStyle;
}
/**
* Adds <code>mapping</code> to <code>elements</code>. It is added
* such that <code>elements</code> will remain ordered by
* specificity.
*/
if (size > 0) {
return;
}
}
}
}
/**
* Adds <code>parentMapping</code> to <code>styles</code>, and
* recursively calls this method if <code>parentMapping</code> has
* any child mappings for any of the Elements in <code>elements</code>.
*/
int index, int numElements,
// Avoid desending the same mapping twice.
return;
}
}
getChildSelectorMapping(tagString, false);
if (childMapping != null) {
}
if (childMapping != null) {
}
"." + className, false);
if (childMapping != null) {
}
}
if (childMapping != null) {
}
"#" + idName, false);
if (childMapping != null) {
}
}
}
}
}
/**
* Creates and returns a Style containing all the rules that match
* <code>selector</code>.
*/
// Determine all the Styles that are appropriate, placing them
// in tempVector
try {
tagString, false);
if (childMapping != null) {
}
if (childMapping != null) {
}
"." + className, false);
if (childMapping != null) {
}
}
if (childMapping != null) {
}
"#" + idName, false);
if (childMapping != null) {
}
}
// Create a new Style that will delegate to all the matching
// Styles.
}
// Get the AttributeSet from linked style sheets.
}
else {
}
}
return retStyle;
}
finally {
}
}
/**
* Creates and returns a Style containing all the rules that
* matches <code>selector</code>.
*
* @param elements a Vector of all the Elements
* the style is being asked for. The
* first Element is the deepest Element, with the last Element
* representing the root.
* @param t the Tag to use for
* the first Element in <code>elements</code>
*/
// Build three arrays, one for tags, one for class's, and one for
// id's
// For leafs, we use the second tier attributes.
if (testAttr instanceof AttributeSet) {
}
else {
}
}
}
else {
}
}
else {
}
toString();
}
else {
}
}
else {
}
}
}
/**
* Creates and returns a Style containing all the rules that match
* <code>selector</code>. It is assumed that each simple selector
* in <code>selector</code> is separated by a space.
*/
// Will contain the tags, ids, and classes, in that order.
try {
boolean done;
int dotIndex = 0;
int spaceIndex;
int poundIndex = 0;
int lastIndex = 0;
}
if (poundIndex == lastIndex) {
}
if (spaceIndex == -1) {
spaceIndex = length;
}
if (poundIndex < dotIndex) {
// #.
if (lastIndex == poundIndex) {
}
else {
poundIndex));
}
}
else {
}
}
else {
}
}
else if(poundIndex < spaceIndex) {
// .#
}
else {
dotIndex));
}
}
else {
}
}
else {
}
}
}
// .
}
else {
dotIndex));
}
}
else {
spaceIndex));
}
}
// #
if (poundIndex == lastIndex) {
}
else {
poundIndex));
}
}
else {
spaceIndex));
}
}
else {
// id
spaceIndex));
}
}
// Create the tag, id, and class arrays.
}
}
finally {
}
}
/**
* Should be invoked when a new rule is added that did not previously
* exist. Goes through and refreshes the necessary resolved
* rules.
*/
int specificity) {
while (values.hasMoreElements()) {
}
}
}
}
/**
* A temporary class used to hold a Vector, a StringBuffer and a
* Hashtable. This is used to avoid allocing a lot of garbage when
* searching for rules. Use the static method obtainSearchBuffer and
* releaseSearchBuffer to get a SearchBuffer, and release it when
* done.
*/
private static class SearchBuffer {
/** A stack containing instances of SearchBuffer. Used in getting
* rules. */
// A set of temporary variables that can be used in whatever way.
/**
* Returns an instance of SearchBuffer. Be sure and issue
* a releaseSearchBuffer when done with it.
*/
try {
if(!searchBuffers.empty()) {
} else {
sb = new SearchBuffer();
}
} catch (EmptyStackException ese) {
sb = new SearchBuffer();
}
return sb;
}
/**
* Adds <code>sb</code> to the stack of SearchBuffers that can
* be used.
*/
}
if (stringBuffer == null) {
stringBuffer = new StringBuffer();
}
return stringBuffer;
}
}
return vector;
}
}
return hashtable;
}
void empty() {
if (stringBuffer != null) {
}
}
}
}
}
/**
* Class to carry out some of the duties of
* CSS formatting. Implementations of this
* class enable views to present the CSS formatting
* while not knowing anything about how the CSS values
* are being cached.
* <p>
* As a delegate of Views, this object is responsible for
* the insets of a View and making sure the background
* is maintained according to the CSS attributes.
*/
}
}
/**
* Fetches a border to render for the given attributes.
* PENDING(prinz) This is pretty badly hacked at the
* moment.
*/
return new CSSBorder(a);
}
/**
* Fetches the color to use for borders. This will either be
* the value specified by the border-color attribute (which
* is not inherited), or it will default to the color attribute
* (which is inherited).
*/
}
}
return color;
}
/**
* Fetches the inset needed on a given side to
* account for the margin, border, and padding.
*
* @param side The size of the box to fetch the
* inset for. This can be View.TOP,
* View.LEFT, View.BOTTOM, or View.RIGHT.
* @param v the view making the request. This is
* used to get the AttributeSet, and may be used to
* resolve percentage arguments.
* @exception IllegalArgumentException for an invalid direction
*/
AttributeSet a = v.getAttributes();
float inset = 0;
switch(side) {
leftMargin, a, isLeftToRight(v));
break;
rightMargin, a, isLeftToRight(v));
break;
break;
inset += bottomMargin;
break;
default:
}
return inset;
}
/**
* Paints the CSS box according to the attributes
* given. This should paint the border, padding,
* and background.
*
* @param g the rendering surface.
* @param x the x coordinate of the allocated area to
* render into.
* @param y the y coordinate of the allocated area to
* render into.
* @param w the width of the allocated area to render into.
* @param h the height of the allocated area to render into.
* @param v the view making the request. This is
* used to get the AttributeSet, and may be used to
* resolve percentage arguments.
*/
// PENDING(prinz) implement real rendering... which would
// do full set of border and background capabilities.
// remove margin
float dx = 0;
float dy = 0;
float dw = 0;
float dh = 0;
AttributeSet a = v.getAttributes();
boolean isLeftToRight = isLeftToRight(v);
a, isLeftToRight);
a, isLeftToRight);
}
(int) (y + dy),
(int) (w + dw),
(int) (h + dh));
}
}
x += localLeftMargin;
y += topMargin;
w -= localLeftMargin + localRightMargin;
h -= topMargin + bottomMargin;
if (border instanceof BevelBorder) {
//BevelBorder does not support border width
(int) w - 2 * i, (int) h - 2 * i);
}
} else {
}
}
}
boolean ret = true;
if (isOrientationAware(v)) {
}
}
return ret;
}
/*
* only certain tags are concerned about orientation
* <dir>, <menu>, <ul>, <ol>
* for all others we return true. It is implemented this way
* for performance purposes
*/
boolean ret = false;
if (v != null
ret = true;
}
return ret;
}
/**
* for <dir>, <menu>, <ul> etc.
* margins are Left-To-Right/Right-To-Left depended.
* see 5088268 for more details
* margin-(left|right)-(ltr|rtl) were introduced to describe it
* if margin-(left|right) is present we are to use it.
*
* @param side The horizontal side to fetch margin for
* This can be HorizontalMargin.LEFT or HorizontalMargin.RIGHT
* @param cssMargin margin from css
* @param a AttributeSet for the View we getting margin for
* @param isLeftToRight
* @return orientation depended margin
*/
AttributeSet a, boolean isLeftToRight) {
float orientationMargin = cssMargin;
switch (side) {
case RIGHT:
{
}
break;
case LEFT :
{
}
break;
}
if (cssMarginValue == null
}
return margin;
}
float topMargin;
float bottomMargin;
float leftMargin;
float rightMargin;
// Bitmask, used to indicate what margins are relative:
// bit 0 for top, 1 for bottom, 2 for left and 3 for right.
short marginFlags;
}
/**
* Class to carry out some of the duties of CSS list
* formatting. Implementations of this
* class enable views to present the CSS formatting
* while not knowing anything about how the CSS values
* are being cached.
*/
/* Get the image to use as a list bullet */
try {
if (st.hasMoreTokens())
if (st.hasMoreTokens())
} catch (MalformedURLException e) {
try {
} catch (MalformedURLException murle) {
}
}
else {
}
}
}
/* Get the type of bullet to use in the list */
}
start = 1;
}
/**
* Returns a string that represents the value
* of the HTML.Attribute.TYPE attribute.
* If this attributes is not defined, then
* then the type defaults to "disc" unless
* the tag is on Ordered list. In the case
* of the latter, the default type is "decimal".
*/
// Parent view.
} else {
}
} else {
}
}
return childtype;
}
/**
* Obtains the starting index from <code>parent</code>.
*/
checkedForStart = true;
(startValue instanceof String)) {
try {
}
catch (NumberFormatException nfe) {}
}
}
}
/**
* Returns an integer that should be used to render the child at
* <code>childIndex</code> with. The retValue will usually be
* <code>childIndex</code> + 1, unless <code>parentView</code>
* has some Views that do not represent LI's, or one of the views
* has a HTML.Attribute.START specified.
*/
if (!checkedForStart) {
}
int retIndex = childIndex;
retIndex--;
try {
}
catch (NumberFormatException nfe) {}
}
}
}
}
/**
* Paints the CSS list decoration according to the
* attributes given.
*
* @param g the rendering surface.
* @param x the x coordinate of the list item allocation
* @param y the y coordinate of the list item allocation
* @param w the width of the list item allocation
* @param h the height of the list item allocation
* @param v the allocated area to paint into.
* @param item which list item is being painted. This
* is a number greater than or equal to 0.
*/
// Only draw something if the View is a list item. This won't
// be the case for comments.
return;
}
// deside on what side draw bullets, etc.
// How the list indicator is aligned is not specified, it is
// left up to the UA. IE and NS differ on this behavior.
// This is closer to NS where we align to the first line of text.
// If the child is not text we draw the indicator at the
// origin (0).
float align = 0;
y = rect.y;
}
}
}
// set the color of a decoration
: host.getForeground())
g.setColor(c);
return;
}
}
(int) w, (int) h, align);
getRenderIndex(v, item));
getRenderIndex(v, item));
getRenderIndex(v, item));
getRenderIndex(v, item));
getRenderIndex(v, item));
}
}
/**
* Draws the bullet icon specified by the list-style-image argument.
*
* @param g the graphics context
* @param ax x coordinate to place the bullet
* @param ay y coordinate to place the bullet
* @param aw width of the container the bullet is placed in
* @param ah height of the container the bullet is placed in
* @param align preferred alignment factor for the child view
*/
// Align to bottom of icon.
}
/**
* Draws the graphical bullet item specified by the type argument.
*
* @param g the graphics context
* @param type type of bullet to draw (circle, square, disc)
* @param ax x coordinate to place the bullet
* @param ay y coordinate to place the bullet
* @param aw width of the container the bullet is placed in
* @param ah height of the container the bullet is placed in
* @param align preferred alignment factor for the child view
*/
// Align to bottom of shape.
} else {
}
}
/**
* Draws the letter or number for an ordered list.
*
* @param g the graphics context
* @param letter type of ordered list to draw
* @param ax x coordinate to place the bullet
* @param ay y coordinate to place the bullet
* @param aw width of the container the bullet is placed in
* @param ah height of the container the bullet is placed in
* @param index position of the list item in the list
*/
}
/**
* Converts the item number into the ordered list number
* (i.e. 1 2 3, i ii iii, a b c, etc.
*
* @param itemNum number to format
* @param type type of ordered list
*/
boolean uppercase = false;
switch (type) {
case '1':
default:
break;
case 'A':
uppercase = true;
// fall through
case 'a':
break;
case 'I':
uppercase = true;
// fall through
case 'i':
}
if (uppercase) {
}
return formattedNum;
}
/**
* Converts the item number into an alphabetic character
*
* @param itemNum number to format
*/
if (itemNum > 26) {
} else {
// -1 because item is 1 based.
}
return result;
}
/* list of roman numerals */
static final char romanChars[][] = {
{'i', 'v'},
{'x', 'l' },
{'c', 'd' },
{'m', '?' },
};
/**
* Converts the item number into a roman numeral
*
* @param num number to format
*/
}
/**
* Converts the item number into a roman numeral
*
* @param num number to format
*/
if (num < 10) {
} else {
}
}
/**
* Converts the item number into a roman numeral
*
* @param level position
* @param digit digit to format
*/
if (digit == 9) {
return result;
} else if (digit == 4) {
return result;
} else if (digit >= 5) {
digit -= 5;
}
for (int i = 0; i < digit; i++) {
}
return result;
}
private boolean checkedForStart;
private int start;
private boolean isLeftToRight;
}
/**
* Paints the background image.
*/
float hPosition;
float vPosition;
// bit mask: 0 for repeat x, 1 for repeat y, 2 for horiz relative,
// 3 for vert relative
short flags;
// These are used when painting, updatePaintCoordinates updates them.
private int paintX;
private int paintY;
private int paintMaxX;
private int paintMaxY;
// Determine the position.
if (pos.isHorizontalPositionRelativeToSize()) {
flags |= 4;
}
else if (pos.isHorizontalPositionRelativeToSize()) {
}
if (pos.isVerticalPositionRelativeToSize()) {
flags |= 8;
}
else if (pos.isVerticalPositionRelativeToFontSize()) {
}
}
// Determine any repeating values.
flags |= 3;
}
flags |= 1;
}
flags |= 2;
}
}
// Constrain the clip so that images don't draw outside the
// legal bounds.
g.clipRect((int)x, (int)y, (int)w, (int)h);
}
// no repeating
}
else {
}
}
else {
}
}
}
else {
paintX = (int)x;
paintY = (int)y;
paintMaxX = (int)(x + w);
paintMaxY = (int)(y + h);
ySpot);
}
}
}
}
}
// Reset clip.
}
}
private boolean updatePaintCoordinates
}
}
// not visible.
return false;
}
// not visible.
return false;
}
}
else {
}
}
}
}
}
else {
}
}
}
}
}
// Valid
return true;
}
}
/**
* A subclass of MuxingAttributeSet that translates between
* CSS and HTML and StyleConstants. The AttributeSets used are
* the CSS rules that match the Views Elements.
*/
host = v;
// PENDING(prinz) fix this up to be a more realistic
// implementation.
try {
if (doc instanceof HTMLDocument) {
}
while (keys.hasMoreElements()) {
/**
In the case of an A tag, the css rules
apply only for tags that have their
href attribute defined and not for
anchors that only have their name attributes
defined, i.e anchors that function as
destinations. Hence we do not add the
attributes for that latter kind of
anchors. When CSS2 support is added,
it will be possible to specificity this
kind of conditional behaviour in the
stylesheet.
**/
if (o != null && o instanceof AttributeSet) {
continue;
}
}
}
}
}
}
} else {
}
}
}
}
finally {
}
}
// --- AttributeSet methods ----------------------------
/**
* Checks whether a given attribute is defined.
* This will convert the key over to CSS if the
* key is a StyleConstants key that has a CSS
* mapping.
*
* @param key the attribute key
* @return true if the attribute is defined
* @see AttributeSet#isDefined
*/
if (key instanceof StyleConstants) {
((StyleConstants)key);
}
}
}
/**
* Gets the value of an attribute. If the requested
* attribute is a StyleConstants attribute that has
* a CSS mapping, the request will be converted.
*
* @param key the attribute name
* @return the attribute value
* @see AttributeSet#getAttribute
*/
if (key instanceof StyleConstants) {
((StyleConstants)key);
}
}
}
return doGetAttribute(key);
}
return retValue;
}
// didn't find it... try parent if it's a css attribute
// that is inherited.
if (css.isInherited()) {
}
}
return null;
}
/**
* If not overriden, the resolving parent defaults to
* the parent element.
*
* @return the attributes from the parent
* @see AttributeSet#getResolveParent
*/
return null;
}
}
/** View created for. */
}
/**
* A subclass of MuxingAttributeSet that implements Style. Currently
* the MutableAttributeSet methods are unimplemented, that is they
* do nothing.
*/
// PENDING(sky): Decide what to do with this. Either make it
// contain a SimpleAttributeSet that modify methods are delegated to,
// or change getRule to return an AttributeSet and then don't make this
// implement Style.
super(attrs);
this.extendedIndex = extendedIndex;
}
/**
* Inserts a Style into the receiver so that the styles the
* receiver represents are still ordered by specificity.
* <code>style</code> will be added before any extended styles, that
* is before extendedIndex.
*/
int counter = 0;
getName())) {
break;
}
}
}
/**
* Removes a previously added style. This will do nothing if
* <code>style</code> is not referenced by the receiver.
*/
if (counter < extendedIndex) {
}
break;
}
}
}
/**
* Adds <code>s</code> as one of the Attributesets to look up
* attributes in.
*/
}
/**
* Adds <code>s</code> as one of the AttributeSets to look up
* attributes in. It will be the AttributeSet last checked.
*/
}
/**
* Removes the style at <code>index</code> +
* <code>extendedIndex</code>.
*/
}
/**
* Returns true if the receiver matches <code>selector</code>, where
* a match is defined by the CSS rule matching.
* Each simple selector must be separated by a single space.
*/
if (sLast == 0) {
return false;
}
if (sCurrent >= 0) {
sCurrent++;
}
if (thisCurrent >= 0) {
thisCurrent++;
}
return false;
}
while (sCurrent != -1) {
if (sCurrent >= 0) {
sCurrent++;
}
boolean match = false;
if (thisCurrent >= 0) {
thisCurrent++;
}
thisLast);
}
if (!match) {
return false;
}
}
return true;
}
/**
* Returns true if the substring of the receiver, in the range
* thisCurrent, thisLast matches the substring of selector in
* the ranme sCurrent to sLast based on CSS selector matching.
*/
int thisCurrent, int thisLast) {
thisLast);
thisLast);
if (sDotIndex != -1) {
// Selector has a '.', which indicates name must match it,
// or if the '.' starts the selector than name must have
// the same class (doesn't matter what element name).
if (thisDotIndex == -1) {
return false;
}
(thisLast - thisDotIndex))) {
return false;
}
}
else {
// Has to fully match.
(thisLast - thisCurrent))) {
return false;
}
}
return true;
}
if (sPoundIndex != -1) {
// Selector has a '#', which indicates name must match it,
// or if the '#' starts the selector than name must have
// the same id (doesn't matter what element name).
if (thisPoundIndex == -1) {
return false;
}
if (sCurrent == sPoundIndex) {
(thisLast - thisPoundIndex))) {
return false;
}
}
else {
// Has to fully match.
(thisLast - thisCurrent))) {
return false;
}
}
return true;
}
if (thisDotIndex != -1) {
// Reciever references a class, just check element name.
thisDotIndex - thisCurrent));
}
if (thisPoundIndex != -1) {
// Reciever references an id, just check element name.
}
// Fail through, no classes or ides, just check string.
thisLast - thisCurrent));
}
/**
* Similiar to String.indexOf, but allows an upper bound
* (this is slower in that it will still check string starting at
* start.
*/
int end) {
return -1;
}
return retValue;
}
return new ChangeListener[0];
}
/** The name of the Style, which is the selector.
* This will NEVER change!
*/
/** Start index of styles coming from other StyleSheets. */
private int extendedIndex;
}
/**
* SelectorMapping contains a specifitiy, as an integer, and an associated
* Style. It can also reference children <code>SelectorMapping</code>s,
* so that it behaves like a tree.
* <p>
* This is not thread safe, it is assumed the caller will take the
* necessary precations if this is to be used in a threaded environment.
*/
this.specificity = specificity;
}
/**
* Returns the specificity this mapping represents.
*/
public int getSpecificity() {
return specificity;
}
/**
* Sets the Style associated with this mapping.
*/
}
/**
* Returns the Style associated with this mapping.
*/
return style;
}
/**
* Returns the child mapping identified by the simple selector
* <code>selector</code>. If a child mapping does not exist for
*<code>selector</code>, and <code>create</code> is true, a new
* one will be created.
*/
boolean create) {
}
else if (create) {
}
}
return retValue;
}
/**
* Creates a child <code>SelectorMapping</code> with the specified
* <code>specificity</code>.
*/
return new SelectorMapping(specificity);
}
/**
* Returns the specificity for the child selector
* <code>selector</code>.
*/
// class (.) 100
// id (#) 10000
int specificity = getSpecificity();
if (firstChar == '.') {
specificity += 100;
}
else if (firstChar == '#') {
specificity += 10000;
}
else {
specificity += 1;
specificity += 100;
}
specificity += 10000;
}
}
return specificity;
}
/**
* The specificity for this selector.
*/
private int specificity;
/**
* Style for this selector.
*/
/**
* Any sub selectors. Key will be String, and value will be
* another SelectorMapping.
*/
}
// ---- Variables ---------------------------------------------
/**
* An inverted graph of the selectors.
*/
/** Maps from selector (as a string) to Style that includes all
* relevant styles. */
/** Vector of StyleSheets that the rules are to reference.
*/
/** Where the style sheet was found. Used for relative imports. */
/**
* Default parser for CSS specifications that get loaded into
* the StyleSheet.<p>
* This class is NOT thread safe, do not ask it to parse while it is
* in the middle of parsing.
*/
/**
* Parses the passed in CSS declaration into an AttributeSet.
*/
try {
} catch (IOException ioe) {}
return null;
}
/**
* Parses the passed in CSS declaration into an AttributeSet.
*/
return declaration.copyAttributes();
}
/**
* Parse the given CSS stream
*/
boolean isLink) throws IOException {
this.parsingDeclaration = parseDeclaration;
propertyName = null;
}
//
// CSSParserCallback methods, public to implement the interface.
//
/**
* Invoked when a valid @import is encountered, will call
* <code>importStyleSheet</code> if a
* <code>MalformedURLException</code> is not thrown in creating
* the URL.
*/
}
}
/**
* A selector has been encountered.
*/
//class and index selectors are case sensitive
}
if (length > 1) {
}
addSelector();
}
else if (length > 0) {
}
}
/**
* Invoked when the start of a rule is encountered.
*/
public void startRule() {
addSelector();
}
propertyName = null;
}
/**
* Invoked when a property name is encountered.
*/
}
/**
* Invoked when a property value is encountered.
*/
// There is currently no mechanism to determine real
// base that style sheet was loaded from. For the time
// being, this maps for LIST_STYLE_IMAGE, which appear
// to be the only one that currently matters. A more
// general mechanism is definately needed.
}
}
}
}
propertyName = null;
}
}
/**
* Invoked when the end of a rule is encountered.
*/
public void endRule() {
for (int i = 0; i < n; i++) {
}
}
}
private void addSelector() {
}
/** Name of the current property. */
/** True if parsing a declaration, that is the Reader will not
* contain a selector. */
boolean parsingDeclaration;
boolean isLink;
/** Where the CSS stylesheet lives. */
}
final int minimalFontSize = 4;
}
}
int[] getSizeMap() {
return sizeMap;
}
boolean isW3CLengthUnits() {
return w3cLengthUnits;
}
/**
* that one can assign sizes to.
*/
private boolean w3cLengthUnits = false;
}