- From: Yves Lafon via cvs-syncmail <cvsmail@w3.org>
- Date: Tue, 04 Oct 2011 13:05:27 +0000
- To: www-validator-cvs@w3.org
Update of /sources/public/2002/css-validator/org/w3c/css/properties/css3 In directory hutz:/tmp/cvs-serv17942/org/w3c/css/properties/css3 Modified Files: Css3Style.java Added Files: CssBackground.java CssBackgroundAttachment.java CssBackgroundClip.java CssBackgroundColor.java CssBackgroundImage.java CssBackgroundOrigin.java CssBackgroundPosition.java CssBackgroundRepeat.java CssBackgroundSize.java CssColor.java Log Message: some reordering to have only one background-color to check in checkConflicts (like what was done for CssColors Index: Css3Style.java =================================================================== RCS file: /sources/public/2002/css-validator/org/w3c/css/properties/css3/Css3Style.java,v retrieving revision 1.12 retrieving revision 1.13 diff -u -d -r1.12 -r1.13 --- Css3Style.java 27 Sep 2011 08:15:46 -0000 1.12 +++ Css3Style.java 4 Oct 2011 13:05:25 -0000 1.13 @@ -112,8 +112,6 @@ public CssBackgroundClip cssBackgroundClip; public CssBackgroundSize cssBackgroundSize; public CssBackgroundOrigin cssBackgroundOrigin; - CssBackgroundQuantity cssBackgroundQuantity; - CssBackgroundSpacing cssBackgroundSpacing; CssTextDecorationCSS3 cssTextDecoration; CssWhiteSpaceCSS3 cssWhiteSpace; CssWordSpacingCSS3 cssWordSpacing; @@ -1001,24 +999,6 @@ return cssBackgroundOrigin; } - public CssBackgroundQuantity getCssBackgroundQuantity() { - if (cssBackgroundQuantity == null) { - cssBackgroundQuantity = - (CssBackgroundQuantity) style.CascadingOrder( - new CssBackgroundQuantity(), style, selector); - } - return cssBackgroundQuantity; - } - - public CssBackgroundSpacing getCssBackgroundSpacing() { - if (cssBackgroundSpacing == null) { - cssBackgroundSpacing = - (CssBackgroundSpacing) style.CascadingOrder( - new CssBackgroundSpacing(), style, selector); - } - return cssBackgroundSpacing; - } - public CssTextDecorationCSS3 getCssTextDecoration() { if (cssTextDecoration == null) { cssTextDecoration = --- NEW FILE: CssBackgroundRepeat.java --- // $Id: CssBackgroundRepeat.java,v 1.1 2011/10/04 13:05:25 ylafon Exp $ // @author Yves Lafon <ylafon@w3.org> // // (c) COPYRIGHT MIT, ERCIM and Keio, 2010. // Please first read the full copyright statement in file COPYRIGHT.html package org.w3c.css.properties.css3; import org.w3c.css.properties.css.CssProperty; import org.w3c.css.util.ApplContext; import org.w3c.css.util.InvalidParamException; import org.w3c.css.values.CssExpression; import org.w3c.css.values.CssIdent; import org.w3c.css.values.CssTypes; import org.w3c.css.values.CssValue; import org.w3c.css.values.CssValueList; import java.util.ArrayList; import java.util.HashMap; import static org.w3c.css.values.CssOperator.COMMA; import static org.w3c.css.values.CssOperator.SPACE; /** * http://www.w3.org/TR/2009/CR-css3-background-20091217/#the-background-repeat * <p/> * Name: background-repeat * Value: <repeat-style> [ , <repeat-style> ]* * Initial: repeat * Applies to: all elements * Inherited: no * Percentages: N/A * Media: visual * Computed value: as specified * <p/> * Specifies how background images are tiled after they have been sized and * positioned. Where * <p/> * <repeat-style> = repeat-x | repeat-y | [repeat | space | * round | no-repeat]{1,2} */ public class CssBackgroundRepeat extends org.w3c.css.properties.css.CssBackgroundRepeat { public final static CssIdent repeat; private static HashMap<String, CssIdent> allowed_simple_values; private static HashMap<String, CssIdent> allowed_double_values; static { allowed_simple_values = new HashMap<String, CssIdent>(); allowed_double_values = new HashMap<String, CssIdent>(); String[] REPEAT = {"repeat", "space", "round", "no-repeat"}; allowed_simple_values.put("repeat-x", CssIdent.getIdent("repeat-x")); allowed_simple_values.put("repeat-y", CssIdent.getIdent("repeat-y")); for (String aREPEAT : REPEAT) { allowed_double_values.put(aREPEAT, CssIdent.getIdent(aREPEAT)); } repeat = CssIdent.getIdent("repeat"); } public static boolean isMatchingIdent(CssIdent ident) { String id = ident.toString(); return (allowed_simple_values.containsKey(id) || allowed_double_values.containsKey(id)); } public Object value; /** * Create a new CssBackgroundRepeat */ public CssBackgroundRepeat() { value = repeat; } /** * Set the value of the property * * @param ac the context * @param expression The expression for this property * @param check is length checking needed * @throws org.w3c.css.util.InvalidParamException The expression is incorrect */ public CssBackgroundRepeat(ApplContext ac, CssExpression expression, boolean check) throws InvalidParamException { ArrayList<CssValue> values = new ArrayList<CssValue>(); boolean is_complete = true; CssValue val; CssValueList vl = null; char op; setByUser(); while (!expression.end()) { val = expression.getValue(); op = expression.getOperator(); // not an ident? fail if (val.getType() != CssTypes.CSS_IDENT) { throw new InvalidParamException("value", expression.getValue(), getPropertyName(), ac); } CssIdent id_val = (CssIdent) val; if (inherit.equals(id_val)) { // if we got inherit after other values, fail // if we got more than one value... fail if ((values.size() > 0) || (expression.getCount() > 1)) { throw new InvalidParamException("value", val, getPropertyName(), ac); } values.add(inherit); } else { String id_value = id_val.toString(); CssIdent new_val; // check values that must be alone new_val = allowed_simple_values.get(id_value); if (new_val != null) { // if we already have a double value... it's an error if (!is_complete) { throw new InvalidParamException("value", val, getPropertyName(), ac); } values.add(new_val); is_complete = true; } else { // the the one that may come in pairs new_val = allowed_double_values.get(id_value); // not an allowed value ! if (new_val == null) { throw new InvalidParamException("value", val, getPropertyName(), ac); } if (is_complete) { vl = new CssValueList(); vl.add(new_val); } else { vl.add(new_val); values.add(vl); } is_complete = !is_complete; } } expression.next(); if (!expression.end()) { // incomplete value followed by a comma... it's complete! if (!is_complete && (op == COMMA)) { values.add(vl); is_complete = true; } // complete values are separated by a comma, otherwise space if ((is_complete && (op != COMMA)) || (!is_complete && (op != SPACE))) { throw new InvalidParamException("operator", ((new Character(op)).toString()), ac); } } } // if we reach the end in a value that can come in pair if (!is_complete) { values.add(vl); } if (values.size() == 1) { value = values.get(0); } else { value = values; } } public CssBackgroundRepeat(ApplContext ac, CssExpression expression) throws InvalidParamException { this(ac, expression, false); } /** * Returns the value of this property */ public Object get() { return value; } public void set(Object val) { value = val; } /** * Returns true if this property is "softly" inherited * e.g. his value equals inherit */ public boolean isSoftlyInherited() { return (inherit == value); } /** * Returns a string representation of the object. */ public String toString() { if (value instanceof ArrayList) { ArrayList values = (ArrayList) value; StringBuilder sb = new StringBuilder(); for (Object aValue : values) { sb.append(aValue.toString()).append(", "); } sb.setLength(sb.length() - 2); return sb.toString(); } return value.toString(); } /** * Compares two properties for equality. * * @param property The other property. */ public boolean equals(CssProperty property) { return (property instanceof CssBackgroundRepeat && value == ((CssBackgroundRepeat) property).value); } /** * Is the value of this property is a default value. * It is used by all macro for the function <code>print</code> */ public boolean isDefault() { return (repeat == value); } } --- NEW FILE: CssBackgroundColor.java --- // $Id: CssBackgroundColor.java,v 1.1 2011/10/04 13:05:25 ylafon Exp $ // From Philippe Le Hegaret (Philippe.Le_Hegaret@sophia.inria.fr) // Rewritten 2010 Yves Lafon <ylafon@w3.org> // // (c) COPYRIGHT MIT, ERCIM and Keio, 1997-2010. // Please first read the full copyright statement in file COPYRIGHT.html package org.w3c.css.properties.css3; import org.w3c.css.properties.css.CssProperty; import org.w3c.css.util.ApplContext; import org.w3c.css.util.InvalidParamException; import org.w3c.css.values.CssExpression; import org.w3c.css.values.CssValue; /** * http://www.w3.org/TR/2009/CR-css3-background-20091217/#the-background-color * * Name: background-color * Value: <color> * Initial: transparent * Applies to: all elements * Inherited: no * Percentages: N/A * Media: visual * Computed value: the computed color(s) * * This property sets the background color of an element. The color is drawn * behind any background images. */ public class CssBackgroundColor extends org.w3c.css.properties.css.CssBackgroundColor { CssValue color; /** * Create a new CssBackgroundColor */ public CssBackgroundColor() { } /** * Create a new CssBackgroundColor * * @param expression The expression for this property * @throws org.w3c.css.util.InvalidParamException Values are incorrect */ public CssBackgroundColor(ApplContext ac, CssExpression expression, boolean check) throws InvalidParamException { setByUser(); CssValue val = expression.getValue(); if (check && expression.getCount() > 1) { throw new InvalidParamException("unrecognize", ac); } if (inherit.equals(val)) { color = inherit; expression.next(); } else { try { // we use the latest version of CssColor, aka CSS3 // instead of using CSS21 colors + transparent per spec. CssColor tcolor = new CssColor(ac, expression, check); color = tcolor.getColor(); } catch (InvalidParamException e) { throw new InvalidParamException("value", expression.getValue(), getPropertyName(), ac); } } } public CssBackgroundColor(ApplContext ac, CssExpression expression) throws InvalidParamException { this(ac, expression, false); } /** * Returns the value of this property */ public Object get() { return color; } public void set(CssValue col) { color = col; } /** * Returns the color */ public CssValue getColor() { return color; } /** * Returns true if this property is "softly" inherited * e.g. his value equals inherit */ public boolean isSoftlyInherited() { return color.equals(inherit); } /** * Returns a string representation of the object. */ public String toString() { return color.toString(); } /** * Compares two properties for equality. * * @param property The other property. */ public boolean equals(CssProperty property) { return (property instanceof CssBackgroundColor && color.equals(((CssBackgroundColor) property).color)); } /** * Is the value of this property is a default value. * It is used by all macro for the function <code>print</code> */ public boolean isDefault() { return (color == transparent); } } --- NEW FILE: CssBackgroundAttachment.java --- // $Id: CssBackgroundAttachment.java,v 1.1 2011/10/04 13:05:25 ylafon Exp $ // @author Yves Lafon <ylafon@w3.org> // (c) COPYRIGHT MIT, ERCIM and Keio, 2010. // Please first read the full copyright statement in file COPYRIGHT.html package org.w3c.css.properties.css3; import org.w3c.css.properties.css.CssProperty; import org.w3c.css.util.ApplContext; import org.w3c.css.util.InvalidParamException; import org.w3c.css.values.CssExpression; import org.w3c.css.values.CssIdent; import org.w3c.css.values.CssTypes; import org.w3c.css.values.CssValue; import java.util.ArrayList; import java.util.HashMap; import static org.w3c.css.values.CssOperator.COMMA; /** * http://www.w3.org/TR/2009/CR-css3-background-20091217/#the-background-attachment * Name: background-attachment * Value: <attachment> [ , <attachment> ]* * Initial: scroll * Applies to: all elements * Inherited: no * Percentages: N/A * Media: visual * Computed value: as specified * * If background images are specified, this property specifies whether they * are fixed with regard to the viewport ('fixed') or scroll along with the * element ('scroll') or its contents ('local'). The property's value is given * as a comma-separated list of <attachment> keywords where * * <attachment> = scroll | fixed | local */ public class CssBackgroundAttachment extends org.w3c.css.properties.css.CssBackgroundAttachment { private static HashMap<String, CssIdent> allowed_values; public static CssIdent scroll; static { allowed_values = new HashMap<String, CssIdent>(); scroll = CssIdent.getIdent("scroll"); allowed_values.put("scroll", scroll); allowed_values.put("fixed", CssIdent.getIdent("fixed")); allowed_values.put("local", CssIdent.getIdent("local")); } public static boolean isMatchingIdent(CssIdent ident) { return allowed_values.containsKey(ident.toString()); } Object value; /** * Create a new CssBackgroundAttachment */ public CssBackgroundAttachment() { value = scroll; } public void set(Object val) { value = val; } /** * Creates a new CssBackgroundAttachment * * @param ac the context * @param expression The expression for this property * @param check if some length checking is required * @throws org.w3c.css.util.InvalidParamException Values are incorrect */ public CssBackgroundAttachment(ApplContext ac, CssExpression expression, boolean check) throws InvalidParamException { ArrayList<CssValue> values = new ArrayList<CssValue>(); char op; CssValue val; setByUser(); while (!expression.end()) { val = expression.getValue(); op = expression.getOperator(); if (val.getType() != CssTypes.CSS_IDENT) { throw new InvalidParamException("value", val, getPropertyName(), ac); } if (inherit.equals(val)) { // if we got inherit after other values, fail // if we got more than one value... fail if ((values.size() > 0) || (expression.getCount() > 1)) { throw new InvalidParamException("value", val, getPropertyName(), ac); } values.add(inherit); } else { // check that it's in the allowed values CssValue new_val = allowed_values.get(val.toString()); if (new_val == null) { throw new InvalidParamException("value", val, getPropertyName(), ac); } values.add(new_val); } expression.next(); // and check that values are separated by commas if (!expression.end() && (op != COMMA)) { throw new InvalidParamException("operator", ((new Character(op)).toString()), ac); } } if (values.size() == 1) { value = values.get(0); } else { value = values; } } public CssBackgroundAttachment(ApplContext ac, CssExpression expression) throws InvalidParamException { this(ac, expression, false); } /** * Returns the value of this property */ public Object get() { return value; } /** * Returns true if this property is "softly" inherited * e.g. his value equals inherit */ public boolean isSoftlyInherited() { return (inherit == value); } /** * Returns a string representation of the object. */ public String toString() { if (value instanceof ArrayList) { ArrayList values = (ArrayList) value; StringBuilder sb = new StringBuilder(); for (Object aValue : values) { sb.append(aValue.toString()).append(", "); } sb.setLength(sb.length() - 2); return sb.toString(); } return value.toString(); } /** * Compares two properties for equality. * * @param property The other property. */ public boolean equals(CssProperty property) { return (property instanceof CssBackgroundAttachment && value.equals(((CssBackgroundAttachment) property).value)); } /** * Is the value of this property is a default value. * It is used by all macro for the function <code>print</code> */ public boolean isDefault() { return (scroll == value); } } --- NEW FILE: CssBackground.java --- // $Id: CssBackground.java,v 1.1 2011/10/04 13:05:25 ylafon Exp $ // From Philippe Le Hegaret (Philippe.Le_Hegaret@sophia.inria.fr) // Rewritten 2010 Yves Lafon <ylafon@w3.org> // (c) COPYRIGHT MIT, ERCIM and Keio, 1997-2010. // Please first read the full copyright statement in file COPYRIGHT.html package org.w3c.css.properties.css3; import org.w3c.css.parser.CssSelectors; import org.w3c.css.parser.CssStyle; import org.w3c.css.properties.css.CssProperty; import org.w3c.css.properties.css1.Css1Style; import org.w3c.css.util.ApplContext; import org.w3c.css.util.InvalidParamException; import org.w3c.css.values.CssColor; import org.w3c.css.values.CssExpression; import org.w3c.css.values.CssIdent; import org.w3c.css.values.CssTypes; import org.w3c.css.values.CssValue; import org.w3c.css.values.CssValueList; import java.util.ArrayList; import static org.w3c.css.values.CssOperator.COMMA; import static org.w3c.css.values.CssOperator.SLASH; import static org.w3c.css.values.CssOperator.SPACE; /** * http://www.w3.org/TR/2009/CR-css3-background-20091217/#the-background * <p/> * Name: background * Value: [ <bg-layer> , ]* <final-bg-layer> * Initial: see individual properties * Applies to: all elements * Inherited: no * Percentages: see individual properties * Media: visual * Computed value: see individual properties * <p/> * Where * <p/> * <bg-layer> = <bg-image> || <bg-position> || * / <bg-size> || <repeat-style> || <attachment> || * <bg-origin> * <p/> * where ‘<bg-position>’ must occur before ‘/ <bg-size>’ if both * are present. * <p/> * <final-bg-layer> = <bg-image> || <bg-position> || * / <bg-size> || <repeat-style> || <attachment> || * <bg-origin> || <'background-color'> * <p/> * where ‘<bg-position>’ must not occur before ‘/ <bg-size>’ if * both are present. * <p/> * Note that a color is permitted in <final-bg-layer>, but * not in <bg-layer>. * * @see org.w3c.css.properties.css.CssBackgroundColor * @see org.w3c.css.properties.css.CssBackgroundImage * @see org.w3c.css.properties.css.CssBackgroundRepeat * @see org.w3c.css.properties.css.CssBackgroundAttachment * @see org.w3c.css.properties.css.CssBackgroundPosition * @see org.w3c.css.properties.css.CssBackgroundSize */ public class CssBackground extends org.w3c.css.properties.css.CssBackground { Object value; public CssColor _color; // TODO get rid of those or reformat them public CssBackgroundColor color; public CssBackgroundImage image; public CssBackgroundRepeat repeat; public CssBackgroundAttachment attachment; public CssBackgroundPosition position; public CssBackgroundSize size; public boolean same; /** * Create a new CssBackground */ public CssBackground() { } /** * Set the value of the property<br/> * Does not check the number of values * * @param expression The expression for this property * @throws org.w3c.css.util.InvalidParamException The expression is incorrect */ public CssBackground(ApplContext ac, CssExpression expression) throws InvalidParamException { this(ac, expression, false); } /** * Set the value of the property * * @param expression The expression for this property * @param check set it to true to check the number of values * @throws org.w3c.css.util.InvalidParamException The expression is incorrect */ public CssBackground(ApplContext ac, CssExpression expression, boolean check) throws InvalidParamException { setByUser(); CssValue val; ArrayList<CssBackgroundValue> values; CssExpression single_layer = null; CssBackgroundValue b_val = null; char op; values = new ArrayList<CssBackgroundValue>(); // we just accumulate values and check at validation while (!expression.end()) { val = expression.getValue(); op = expression.getOperator(); if (inherit.equals(val)) { if (expression.getCount() > 1) { throw new InvalidParamException("value", val, getPropertyName(), ac); } value = inherit; expression.next(); return; } if (single_layer == null) { single_layer = new CssExpression(); } // we will check later single_layer.addValue(val); single_layer.setOperator(op); expression.next(); if (!expression.end()) { // incomplete value followed by a comma... it's complete! if (op == COMMA) { single_layer.setOperator(SPACE); b_val = check(ac, single_layer, check, false); values.add(b_val); single_layer = null; } else if ((op != SPACE) && (op != SLASH)) { throw new InvalidParamException("operator", ((new Character(op)).toString()), ac); } } } // if we reach the end in a value that can come in pair if (single_layer != null) { b_val = check(ac, single_layer, check, true); values.add(b_val); } if (values.size() == 1) { value = values.get(0); } else { value = values; } transform_into_individual_values(); } private Object getCssBackgroundRepeatValue(ApplContext ac, CssExpression expression, boolean check) throws InvalidParamException { char op = expression.getOperator(); CssExpression exp = new CssExpression(); exp.addValue(expression.getValue()); CssBackgroundRepeat bg_size; repeat = new CssBackgroundRepeat(ac, exp, check); // now check if we can add a second value ;) if ((op == SPACE) && !expression.end()) { expression.next(); if (!expression.end()) { CssValue val = expression.getValue(); if ((val.getType() == CssTypes.CSS_IDENT) && (CssBackgroundRepeat.isMatchingIdent((CssIdent) val))) { exp.addValue(expression.getValue()); exp.starts(); try { repeat = new CssBackgroundRepeat(ac, exp, check); } catch (InvalidParamException ipe) { expression.precedent(); } } else { expression.precedent(); } } } return repeat.get(); } private Object getCssBackgroundSizeValue(ApplContext ac, CssExpression expression, boolean check) throws InvalidParamException { char op = expression.getOperator(); CssExpression exp = new CssExpression(); exp.addValue(expression.getValue()); CssBackgroundSize bg_size; bg_size = new CssBackgroundSize(ac, exp, check); // now check if we can add a second value ;) // TODO really dirty.. must check the use of 'check' // here, and possibly adjust the parsing model in // other classes :( if ((op == SPACE) && !expression.end()) { expression.next(); if (!expression.end()) { exp.addValue(expression.getValue()); exp.starts(); try { bg_size = new CssBackgroundSize(ac, exp, check); } catch (InvalidParamException ipe) { // roll back expression.precedent(); } } } return bg_size.get(); } private Object getCssBackgroundPositionValue(ApplContext ac, CssExpression expression, boolean check) throws InvalidParamException { CssExpression exp = new CssExpression(); char op = expression.getOperator(); exp.addValue(expression.getValue()); int last_val = -1; CssBackgroundPosition bg_pos; bg_pos = new CssBackgroundPosition(ac, exp, check); // good we have a valid value, try something better.. expression.mark(); // we MUST try all the cases, as we can have something // invalid using 3 values (incompatible definitions) // but valid using 4 values... // example top 12% is invalid, top 12% center is valid... for (int i = 0; i < 3; i++) { if ((op == SPACE) && !expression.end()) { expression.next(); if (expression.end()) { break; } exp.addValue(expression.getValue()); exp.starts(); try { bg_pos = new CssBackgroundPosition(ac, exp, check); last_val = i; } catch (InvalidParamException ipe) { } } } expression.reset(); while (last_val >= 0) { expression.next(); last_val--; } return bg_pos.get(); } public CssBackgroundValue check(ApplContext ac, CssExpression expression, boolean check, boolean is_final) throws InvalidParamException { // <bg-layer> = <bg-image> || <bg-position> || / <bg-size> || <repeat-style> || // <attachment> || <bg-origin> // bg_image is CSS_URL | IDENT // bg-position is IDENT | NUMBER | LENGTH | PERCENTAGE // bg-size is IDENT | NUMBER | LENGTH | PERCENTAGE // repeat-style is IDENT // attachment is IDENT // bg-origin is IDENT // + color as CSS_COLOR or IDENT on final-layer CssValue val; char op; CssExpression exp; CssBackgroundValue v = new CssBackgroundValue(); boolean next_is_size, got_size; Object res; next_is_size = false; got_size = false; while (!expression.end()) { val = expression.getValue(); op = expression.getOperator(); switch (val.getType()) { case CssTypes.CSS_COLOR: // we already got one, fail... if (v.color != null || next_is_size || !is_final) { throw new InvalidParamException("value", val, getPropertyName(), ac); } exp = new CssExpression(); exp.addValue(val); CssBackgroundColor bg_color; bg_color = new CssBackgroundColor(ac, exp, check); v.color = (CssValue) bg_color.get(); break; case CssTypes.CSS_URL: // we already got one, fail... if (v.bg_image != null || next_is_size) { throw new InvalidParamException("value", val, getPropertyName(), ac); } exp = new CssExpression(); exp.addValue(val); CssBackgroundImage bg_image; bg_image = new CssBackgroundImage(ac, exp, check); res = bg_image.get(); // we only have one vale so it should always be the case if (res instanceof CssValue) { v.bg_image = (CssValue) res; } else { throw new InvalidParamException("value", val, getPropertyName(), ac); } break; case CssTypes.CSS_NUMBER: case CssTypes.CSS_LENGTH: case CssTypes.CSS_PERCENTAGE: // ok, so now we have a background position or size. // and... // in <bg_layer>: where '<bg-position>' must occur before // '/ <bg-size>' if both are present. if (next_is_size) { // size, we have up to two values if (v.bg_size != null) { throw new InvalidParamException("value", val, getPropertyName(), ac); } res = getCssBackgroundSizeValue(ac, expression, check); op = expression.getOperator(); // we only have one vale so it should always be the case if (res instanceof CssValue) { v.bg_size = (CssValue) res; } else { throw new InvalidParamException("value", val, getPropertyName(), ac); } got_size = true; next_is_size = false; } else { // position with it's up to 4 values... if (got_size) { throw new InvalidParamException("bg_order", val, getPropertyName(), ac); } if (v.bg_position != null) { throw new InvalidParamException("value", val, getPropertyName(), ac); } res = getCssBackgroundPositionValue(ac, expression, check); op = expression.getOperator(); // we only have one vale so it should always be the case if (res instanceof CssValue) { v.bg_position = (CssValue) res; } else { throw new InvalidParamException("value", val, getPropertyName(), ac); } } break; case CssTypes.CSS_IDENT: // inherit is already taken care of... CssIdent ident_val = (CssIdent) val; if (CssBackgroundAttachment.isMatchingIdent(ident_val)) { if (v.attachment != null || next_is_size) { throw new InvalidParamException("value", val, getPropertyName(), ac); } exp = new CssExpression(); exp.addValue(val); CssBackgroundAttachment attachment; attachment = new CssBackgroundAttachment(ac, exp, check); res = attachment.get(); // we only have one vale so it should always be the case if (res instanceof CssValue) { v.attachment = (CssValue) res; } else { throw new InvalidParamException("value", val, getPropertyName(), ac); } break; } if (CssBackgroundImage.isMatchingIdent(ident_val)) { if (v.bg_image != null || next_is_size) { throw new InvalidParamException("value", val, getPropertyName(), ac); } // a bit of an overkill, as we know it can be only // 'none'.. but it is more flexible if ever it changes exp = new CssExpression(); exp.addValue(val); bg_image = new CssBackgroundImage(ac, exp, check); res = bg_image.get(); // we only have one vale so it should always be the case if (res instanceof CssValue) { v.bg_image = (CssValue) res; } else { throw new InvalidParamException("value", val, getPropertyName(), ac); } break; } if (CssBackgroundOrigin.isMatchingIdent(ident_val)) { if (v.origin != null || next_is_size) { throw new InvalidParamException("value", val, getPropertyName(), ac); } exp = new CssExpression(); exp.addValue(val); CssBackgroundOrigin origin; origin = new CssBackgroundOrigin(ac, exp, check); res = origin.get(); // we only have one vale so it should always be the case if (res instanceof CssValue) { v.origin = (CssValue) res; } else { throw new InvalidParamException("value", val, getPropertyName(), ac); } break; } if (CssBackgroundRepeat.isMatchingIdent(ident_val)) { if (v.repeat_style != null || next_is_size) { throw new InvalidParamException("value", val, getPropertyName(), ac); } res = getCssBackgroundRepeatValue(ac, expression, check); op = expression.getOperator(); // we only have one vale so it should always be the case if (res instanceof CssValue) { v.repeat_style = (CssValue) res; } else { throw new InvalidParamException("value", val, getPropertyName(), ac); } break; } if (next_is_size) { if (CssBackgroundSize.isMatchingIdent(ident_val)) { // size, we have up to two values if (v.bg_size != null) { throw new InvalidParamException("value", val, getPropertyName(), ac); } res = getCssBackgroundSizeValue(ac, expression, check); op = expression.getOperator(); // we only have one vale so it should always be the case if (res instanceof CssValue) { v.bg_size = (CssValue) res; } else { throw new InvalidParamException("value", val, getPropertyName(), ac); } got_size = true; next_is_size = false; break; } } else { if (CssBackgroundPosition.isMatchingIdent(ident_val)) { // position with it's up to 4 values... if (got_size) { throw new InvalidParamException("bg_order", val, getPropertyName(), ac); } if (v.bg_position != null) { throw new InvalidParamException("value", val, getPropertyName(), ac); } res = getCssBackgroundPositionValue(ac, expression, check); op = expression.getOperator(); // we only have one vale so it should always be the case if (res instanceof CssValue) { v.bg_position = (CssValue) res; } else { throw new InvalidParamException("value", val, getPropertyName(), ac); } break; } } // last one remaining... color! // or else, it will fail :) if (is_final) { if (v.color != null || next_is_size) { throw new InvalidParamException("value", val, getPropertyName(), ac); } exp = new CssExpression(); exp.addValue(val); bg_color = new CssBackgroundColor(ac, exp, check); v.color = (CssValue) bg_color.get(); break; } // unrecognized or unwanted ident // let it fail now default: throw new InvalidParamException("value", val, getPropertyName(), ac); } if (op == SLASH) { next_is_size = true; } else if (op != SPACE) { throw new InvalidParamException("operator", val, getPropertyName(), ac); } expression.next(); } align_bg_values(v); return v; } private void align_bg_values(CssBackgroundValue v) { // <bg-layer> = <bg-image> || <bg-position> || / <bg-size> || <repeat-style> || // <attachment> || <bg-origin> Object value; if (v.bg_image == null) { value = (new CssBackgroundImage()).get(); if (value instanceof CssValue) { v.bg_image_value = (CssValue) value; } } else { v.bg_image_value = v.bg_image; } if (v.bg_position == null) { value = (new CssBackgroundPosition()).get(); if (value instanceof CssValue) { v.bg_position_value = (CssValue) value; } } else { v.bg_position_value = v.bg_position; } if (v.bg_size == null) { value = (new CssBackgroundSize()).get(); if (value instanceof CssValue) { v.bg_size_value = (CssValue) value; } } else { v.bg_size_value = v.bg_size; } if (v.repeat_style == null) { value = (new CssBackgroundRepeat()).get(); if (value instanceof CssValue) { v.repeat_style_value = (CssValue) value; } } else { v.repeat_style_value = v.repeat_style; } if (v.attachment == null) { value = (new CssBackgroundAttachment()).get(); if (value instanceof CssValue) { v.attachment_value = (CssValue) value; } } else { v.attachment_value = v.attachment; } if (v.origin == null) { value = (new CssBackgroundOrigin()).get(); if (value instanceof CssValue) { CssValue css_val = (CssValue) value; v.origin_value = (CssValue) value; // If 'background-origin' is present and its value matches a // possible value for 'background-clip' then it also sets // 'background-clip' to that value. if ((css_val.getType() == CssTypes.CSS_IDENT) && CssBackgroundClip.isMatchingIdent((CssIdent) css_val)) { v.clip_value = v.origin_value; } } } else { v.origin_value = v.origin; } if (v.color == null) { v.color_value = (new CssBackgroundColor()).getColor(); } else { v.color_value = v.color; } } /** * Transform the compound value into the equivalent individual * values (used for conflict check, like color and background-color * Note that the value verification already took place, so no need * for extra check */ private void transform_into_individual_values() { if (value instanceof CssBackgroundValue) { CssBackgroundValue v = (CssBackgroundValue) value; if (v.color != null) { color = new CssBackgroundColor(); color.set(v.color_value); } if (v.bg_image != null) { image = new CssBackgroundImage(); image.set(v.bg_image_value); } if (v.repeat_style != null) { repeat = new CssBackgroundRepeat(); repeat.set(v.repeat_style_value); } if (v.attachment != null) { attachment = new CssBackgroundAttachment(); attachment.set(v.attachment_value); } if (v.bg_position != null) { position = new CssBackgroundPosition(); position.set(v.bg_position_value); } if (v.bg_size != null) { size = new CssBackgroundSize(); size.set(v.bg_size_value); } } else if (value instanceof ArrayList) { ArrayList vlist = (ArrayList) value; int len = vlist.size(); ArrayList<CssValue> images = new ArrayList<CssValue>(len); ArrayList<CssValue> repeats = new ArrayList<CssValue>(len); ArrayList<CssValue> positions = new ArrayList<CssValue>(len); ArrayList<CssValue> attachments = new ArrayList<CssValue>(len); ArrayList<CssValue> sizes = new ArrayList<CssValue>(len); for (int i = 0; i < len; i++) { CssBackgroundValue v = (CssBackgroundValue) vlist.get(i); images.add(v.bg_image_value); repeats.add(v.repeat_style_value); positions.add(v.bg_position_value); attachments.add(v.attachment_value); sizes.add(v.bg_size_value); if (v.color != null) { color = new CssBackgroundColor(); color.set(v.color_value); } } image = new CssBackgroundImage(); image.set(images); repeat = new CssBackgroundRepeat(); repeat.set(repeats); attachment = new CssBackgroundAttachment(); attachment.set(attachments); position = new CssBackgroundPosition(); position.set(sizes); size = new CssBackgroundSize(); size.set(sizes); } else { // FIXME TODO use inherit? image = null; repeat = null; attachment = null; color = null; size = null; position = null; } } /** * @return Returns the image. */ public CssBackgroundImage getImage() { return image; } /** * Returns the value of this property */ public Object get() { return color; } /** * Returns the color */ public CssValue getColor() { if (color == null) { return null; } else { return color.getColor(); } } /** * Returns a string representation of the object. */ public String toString() { if (value instanceof ArrayList) { ArrayList v_list; v_list = (ArrayList) value; StringBuilder sb = new StringBuilder(); for (Object val : v_list) { sb.append(val.toString()).append(", "); } sb.setLength(sb.length() - 2); return sb.toString(); } return value.toString(); } /** * Set this property to be important. * Overrides this method for a macro */ public void setImportant() { super.setImportant(); if (color != null) { color.important = true; } if (image != null) { image.important = true; } if (repeat != null) { repeat.important = true; } if (attachment != null) { attachment.important = true; } if (position != null) { position.important = true; } if (size != null) { size.important = true; } } /** * Set the context. * Overrides this method for a macro * * @see org.w3c.css.css.CssCascadingOrder#order * @see org.w3c.css.css.StyleSheetParser#handleRule */ public void setSelectors(CssSelectors selector) { super.setSelectors(selector); if (color != null) { color.setSelectors(selector); } if (image != null) { image.setSelectors(selector); } if (repeat != null) { repeat.setSelectors(selector); } if (attachment != null) { attachment.setSelectors(selector); } if (position != null) { position.setSelectors(selector); } if (size != null) { size.setSelectors(selector); } } /** * Add this property to the CssStyle * * @param style The CssStyle */ public void addToStyle(ApplContext ac, CssStyle style) { ((Css1Style) style).cssBackground.same = same; ((Css1Style) style).cssBackground.byUser = byUser; if (color != null) { color.addToStyle(ac, style); } if (image != null) { image.addToStyle(ac, style); } if (repeat != null) { repeat.addToStyle(ac, style); } if (attachment != null) { attachment.addToStyle(ac, style); } if (position != null) { position.addToStyle(ac, style); } if (size != null) { size.addToStyle(ac, style); } } /** * Get this property in the style. * * @param style The style where the property is * @param resolve if true, resolve the style to find this property */ public CssProperty getPropertyInStyle(CssStyle style, boolean resolve) { if (resolve) { return ((Css1Style) style).getBackground(); } else { return ((Css1Style) style).cssBackground; } } /** * Compares two properties for equality. * * @param property The other property. */ public boolean equals(CssProperty property) { return false; // FIXME } /** * Update the source file and the line. * Overrides this method for a macro * * @param line The line number where this property is defined * @param source The source file where this property is defined */ public void setInfo(int line, String source) { super.setInfo(line, source); if (color != null) { color.setInfo(line, source); } if (image != null) { image.setInfo(line, source); } if (repeat != null) { repeat.setInfo(line, source); } if (attachment != null) { attachment.setInfo(line, source); } if (position != null) { position.setInfo(line, source); } if (size != null) { size.setInfo(line, source); } } // placeholder for the different values public class CssBackgroundValue extends CssValueList { CssValue bg_image = null; CssValue bg_position = null; CssValue bg_size = null; CssValue repeat_style = null; CssValue attachment = null; CssValue origin = null; CssValue color = null; CssValue bg_image_value = null; CssValue bg_position_value = null; CssValue bg_size_value = null; CssValue repeat_style_value = null; CssValue attachment_value = null; CssValue origin_value = null; // If 'background-origin' is present and its value matches a possible // value for 'background-clip' then it also sets 'background-clip' to // that value. CssValue clip_value = null; CssValue color_value = null; public boolean equals(CssBackgroundValue v) { if (bg_image_value == null) { if (v.bg_image_value != null) { return false; } } else if (!bg_image_value.equals(v.bg_image_value)) { return false; } if (bg_position_value == null) { if (v.bg_position_value != null) { return false; } } else if (!bg_position_value.equals(v.bg_position_value)) { return false; } if (bg_size_value == null) { if (v.bg_size_value != null) { return false; } } else if (!bg_size_value.equals(v.bg_size_value)) { return false; } if (repeat_style_value == null) { if (v.repeat_style_value != null) { return false; } } else if (!repeat_style_value.equals(v.repeat_style_value)) { return false; } if (attachment_value == null) { if (v.attachment_value != null) { return false; } } else if (!attachment_value.equals(v.attachment_value)) { return false; } if (origin_value == null) { if (v.origin_value != null) { return false; } } else if (!origin_value.equals(v.origin_value)) { return false; } if (clip_value == null) { if (v.clip_value != null) { return false; } } else if (!clip_value.equals(v.clip_value)) { return false; } if (color_value == null) { if (v.color_value != null) { return false; } } else if (!color_value.equals(v.color_value)) { return false; } // at last! return true; } public String toString() { StringBuilder sb = new StringBuilder(); if (bg_image != null) { sb.append(bg_image).append(' '); } if (bg_position != null) { sb.append(bg_position).append(' '); } if (bg_size != null) { sb.append('/').append(bg_size).append(' '); } if (repeat_style != null) { sb.append(repeat_style).append(' '); } if (attachment != null) { sb.append(attachment).append(' '); } if (origin != null) { sb.append(origin).append(' '); } if (color != null) { sb.append(color); } else { int sb_length = sb.length(); if (sb_length > 0) { sb.setLength(sb_length - 1); } } return sb.toString(); } } } --- NEW FILE: CssBackgroundPosition.java --- // $Id: CssBackgroundPosition.java,v 1.1 2011/10/04 13:05:25 ylafon Exp $ // From Philippe Le Hegaret (Philippe.Le_Hegaret@sophia.inria.fr) // Rewritten by Yves Lafon <ylafon@w3.org> // (c) COPYRIGHT MIT, Keio and ERCIM, 1997-2010. // Please first read the full copyright statement in file COPYRIGHT.html package org.w3c.css.properties.css3; import org.w3c.css.parser.CssStyle; import org.w3c.css.properties.css.CssBackground; import org.w3c.css.properties.css.CssProperty; import org.w3c.css.properties.css1.Css1Style; import org.w3c.css.util.ApplContext; import org.w3c.css.util.InvalidParamException; import org.w3c.css.values.CssExpression; import org.w3c.css.values.CssIdent; import org.w3c.css.values.CssNumber; import org.w3c.css.values.CssPercentage; import org.w3c.css.values.CssTypes; import org.w3c.css.values.CssValue; import org.w3c.css.values.CssValueList; import java.util.ArrayList; import java.util.HashMap; import static org.w3c.css.values.CssOperator.COMMA; import static org.w3c.css.values.CssOperator.SPACE; /** * http://www.w3.org/TR/2009/CR-css3-background-20091217/#background-position * <p/> * Name: background-position * Value: <bg-position> [ , <bg-position> ]* * Initial: 0% 0% * Applies to: all elements * Inherited: no * Percentages: refer to size of background positioning area minus size of * background image; see text * Media: visual * Computed value: If one or two values are specified, for a <length> * the absolute value, otherwise a percentage. If three or * four values are specified, two pairs of a keyword plus a * length or percentage. * <p/> * <p/> * If background images have been specified, this property specifies their * initial position (after any resizing) within their corresponding * background positioning area. * <p/> * Where * <p/> * <bg-position> = [ * [ [ <percentage> | <length> | left | center | right ] ] * [ [ <percentage> | <length> | top | center | bottom ] ]? * | * [ center | [ left | right ] [ <percentage> | <length> ]? ] || * [ center | [ top | bottom ] [ <percentage> | <length> ]? ] * ] */ public class CssBackgroundPosition extends org.w3c.css.properties.css.CssBackgroundPosition { private static HashMap<String, CssIdent> allowed_values; private static final CssIdent center, top, bottom, left, right; private static final CssPercentage defaultPercent0, defaultPercent50; private static final CssPercentage defaultPercent100; static { top = CssIdent.getIdent("top"); bottom = CssIdent.getIdent("bottom"); left = CssIdent.getIdent("left"); right = CssIdent.getIdent("right"); center = CssIdent.getIdent("center"); allowed_values = new HashMap<String, CssIdent>(); allowed_values.put("top", top); allowed_values.put("bottom", bottom); allowed_values.put("left", left); allowed_values.put("right", right); allowed_values.put("center", center); defaultPercent0 = new CssPercentage(0); defaultPercent50 = new CssPercentage(50); defaultPercent100 = new CssPercentage(100); } public static boolean isMatchingIdent(CssIdent ident) { return allowed_values.containsKey(ident.toString()); } Object value; /** * Create a new CssBackgroundPosition */ public CssBackgroundPosition() { value = new CssBackgroundPositionValue(); } /** * Creates a new CssBackgroundPosition * * @param expression The expression for this property * @throws org.w3c.css.util.InvalidParamException Values are incorrect */ public CssBackgroundPosition(ApplContext ac, CssExpression expression, boolean check) throws InvalidParamException { setByUser(); CssValue val; ArrayList<CssBackgroundPositionValue> values; CssBackgroundPositionValue b_val = null; char op; values = new ArrayList<CssBackgroundPositionValue>(); // we just accumulate values and check at validation while (!expression.end()) { val = expression.getValue(); op = expression.getOperator(); if (inherit.equals(val)) { if (expression.getCount() > 1) { throw new InvalidParamException("value", val, getPropertyName(), ac); } value = inherit; expression.next(); return; } if (b_val == null) { b_val = new CssBackgroundPositionValue(); } // we will check later b_val.add(val); expression.next(); if (!expression.end()) { // incomplete value followed by a comma... it's complete! if (op == COMMA) { check(b_val, ac); values.add(b_val); b_val = null; } else if (op != SPACE) { throw new InvalidParamException("operator", ((new Character(op)).toString()), ac); } } } // if we reach the end in a value that can come in pair if (b_val != null) { check(b_val, ac); values.add(b_val); } if (values.size() == 1) { value = values.get(0); } else { value = values; } } public CssBackgroundPosition(ApplContext ac, CssExpression expression) throws InvalidParamException { this(ac, expression, false); } /** * Returns the value of this property */ public Object get() { return value; } public void set(Object val) { value = val; } /** * Returns true if this property is "softly" inherited * e.g. his value equals inherit */ public boolean isSoftlyInherited() { return (inherit == value); } /** * Returns a string representation of the object. */ public String toString() { if (value instanceof ArrayList) { ArrayList v_list; v_list = (ArrayList) value; StringBuilder sb = new StringBuilder(); for (Object val : v_list) { sb.append(val.toString()).append(", "); } sb.setLength(sb.length() - 2); return sb.toString(); } return value.toString(); } /** * Add this property to the CssStyle. * * @param style The CssStyle */ public void addToStyle(ApplContext ac, CssStyle style) { CssBackground cssBackground = ((Css1Style) style).cssBackground; if (cssBackground.position != null) style.addRedefinitionWarning(ac, this); cssBackground.position = this; } /** * Get this property in the style. * * @param style The style where the property is * @param resolve if true, resolve the style to find this property */ public CssProperty getPropertyInStyle(CssStyle style, boolean resolve) { if (resolve) { return ((Css1Style) style).getBackgroundPosition(); } else { return ((Css1Style) style).cssBackground.position; } } /** * Compares two properties for equality. * * @param property The other property. */ public boolean equals(CssProperty property) { return ((property != null) && (property instanceof CssBackgroundPosition) && (value.equals(((CssBackgroundPosition) property).value))); } /** * Is the value of this property is a default value. * It is used by all macro for the function <code>print</code> */ public boolean isDefault() { if (!(value instanceof CssBackgroundPositionValue)) { return false; } CssBackgroundPositionValue v = (CssBackgroundPositionValue) value; return ((v.val_vertical == defaultPercent0) && (v.val_horizontal == defaultPercent0) && (v.vertical_offset == null) && (v.horizontal_offset == null)); } public void check(CssBackgroundPositionValue v, ApplContext ac) throws InvalidParamException { int nb_keyword = 0; int nb_percentage = 0; int nb_length = 0; int nb_values = v.value.size(); if (nb_values > 4) { throw new InvalidParamException("unrecognize", ac); } // basic check for (CssValue aValue : v.value) { switch (aValue.getType()) { case CssTypes.CSS_NUMBER: aValue = ((CssNumber) aValue).getLength(); case CssTypes.CSS_LENGTH: nb_length++; break; case CssTypes.CSS_PERCENTAGE: nb_percentage++; break; case CssTypes.CSS_IDENT: nb_keyword++; break; default: throw new InvalidParamException("unrecognize", aValue, ac); } } if ((nb_keyword > 2) || (nb_length > 2) || (nb_percentage > 2)) { throw new InvalidParamException("unrecognize", ac); } // this is unnecessary complex, blame it on the CSS3 spec. switch (nb_keyword) { case 0: // no keyword, so it's easy, it depends on the number // of values :) switch (nb_values) { case 1: // If only one value is specified, the second value // is assumed to be 'center'. v.horizontal = v.value.get(0); if (v.horizontal.getType() == CssTypes.CSS_NUMBER) { v.horizontal = defaultPercent0; } v.val_horizontal = v.horizontal; v.val_vertical = defaultPercent50; break; case 2: v.horizontal = v.value.get(0); if (v.horizontal.getType() == CssTypes.CSS_NUMBER) { v.horizontal = defaultPercent0; } v.val_horizontal = v.horizontal; v.vertical = v.value.get(1); if (v.vertical.getType() == CssTypes.CSS_NUMBER) { v.vertical = defaultPercent0; } v.val_vertical = v.vertical; break; default: // If three or four values are given, then each // <percentage> or<length> represents an offset and // must be preceded by a keyword throw new InvalidParamException("unrecognize", ac); } break; // we got one keyword... let's have fun... case 1: switch (nb_values) { case 1: CssIdent ident = (CssIdent) v.value.get(0); // ugly as we need to set values for equality tests v.val_vertical = defaultPercent50; v.val_horizontal = defaultPercent50; ident = allowed_values.get(ident.toString()); if (ident != null) { if (isVertical(ident)) { v.vertical = ident; v.val_vertical = identToPercent(ident); } else { // horizontal || center v.horizontal = ident; v.val_horizontal = identToPercent(ident); } break; } throw new InvalidParamException("unrecognize", ident, getPropertyName(), ac); case 2: // one ident, two values... first MUST be horizontal // and second vertical CssValue val0 = v.value.get(0); if (val0.getType() == CssTypes.CSS_IDENT) { ident = allowed_values.get(val0.toString()); if (ident == null) { throw new InvalidParamException("unrecognize", ident, getPropertyName(), ac); } if (isVertical(ident)) { throw new InvalidParamException("incompatible", ident, v.value.get(1), ac); } v.horizontal = ident; v.val_horizontal = identToPercent(ident); // and the vertical value... v.vertical = v.value.get(1); if (v.vertical.getType() == CssTypes.CSS_NUMBER) { v.vertical = defaultPercent0; } v.val_vertical = v.vertical; } else { ident = allowed_values.get(v.value.get(1).toString()); if (ident == null) { throw new InvalidParamException("unrecognize", ident, getPropertyName(), ac); } if (isHorizontal(ident)) { throw new InvalidParamException("incompatible", val0, v.value.get(1), ac); } v.vertical = ident; v.val_vertical = identToPercent(ident); // and the first value v.horizontal = val0; if (v.horizontal.getType() == CssTypes.CSS_NUMBER) { v.horizontal = defaultPercent0; } v.val_horizontal = v.horizontal; } break; default: // one ident, 3 or 4 values is not allowed throw new InvalidParamException("unrecognize", ac); } break; default: // ok so we have two keywords, with possible offsets // we must check that every possible offset is right // after a keyword and also that the two keywords are // not incompatible boolean got_ident = false; CssIdent id1 = null; CssIdent id2 = null; CssValue off1 = null; CssValue off2 = null; for (CssValue aValue : v.value) { switch (aValue.getType()) { case CssTypes.CSS_IDENT: aValue = allowed_values.get(aValue.toString()); if (aValue == null) { throw new InvalidParamException("unrecognize", aValue, getPropertyName(), ac); } got_ident = true; if (id1 == null) { id1 = (CssIdent) aValue; } else { id2 = (CssIdent) aValue; // we got both, let's check. if (((isVertical(id1) && isVertical(id2))) || (isHorizontal(id1) && isHorizontal(id2))) { throw new InvalidParamException("incompatible", id1, id2, ac); } } break; case CssTypes.CSS_NUMBER: aValue = ((CssNumber) aValue).getPercentage(); case CssTypes.CSS_PERCENTAGE: case CssTypes.CSS_LENGTH: if (!got_ident) { throw new InvalidParamException("unrecognize", aValue, getPropertyName(), ac); } if (id2 == null) { off1 = aValue; } else { off2 = aValue; } got_ident = false; break; default: // should never happen } } if (isVertical(id1) || isHorizontal(id2)) { // if an offset is present and value is 'center' if (((off1 != null) && !isVertical(id1)) || ((off2 != null) && !isHorizontal(id2))) { throw new InvalidParamException("incompatible", id1, id2, ac); } v.horizontal = id2; v.val_horizontal = identToPercent(id2); v.horizontal_offset = off2; v.vertical = id1; v.val_vertical = identToPercent(id1); v.vertical_offset = off1; } else { if (((off2 != null) && !isVertical(id2)) || ((off1 != null) && !isHorizontal(id1))) { throw new InvalidParamException("incompatible", id1, id2, ac); } v.horizontal = id1; v.val_horizontal = identToPercent(id1); v.horizontal_offset = off1; v.vertical = id2; v.val_vertical = identToPercent(id2); v.vertical_offset = off2; } } } public static CssPercentage identToPercent(CssIdent ident) { if (center.equals(ident)) { return defaultPercent50; } else if (top.equals(ident) || left.equals(ident)) { return defaultPercent0; } else if (bottom.equals(ident) || right.equals(ident)) { return defaultPercent100; } return defaultPercent0; // FIXME throw an exception ? } public static boolean isHorizontal(CssIdent ident) { return (left.equals(ident) || right.equals(ident)); } public static boolean isVertical(CssIdent ident) { return (top.equals(ident) || bottom.equals(ident)); } // placeholder for the different values public class CssBackgroundPositionValue extends CssValueList { public CssValue vertical = null; public CssValue horizontal = null; public CssValue vertical_offset = null; public CssValue horizontal_offset = null; public CssValue val_vertical = defaultPercent0; public CssValue val_horizontal = defaultPercent0; public boolean equals(CssBackgroundPositionValue v) { // check vertical compatibility (with optional values) if (!val_vertical.equals(v.val_vertical)) { return false; } if (vertical_offset != null) { if (!vertical_offset.equals(v.vertical_offset)) { return false; } } else if (v.vertical_offset != null) { return false; } if (!val_horizontal.equals(v.val_horizontal)) { return false; } if (horizontal_offset != null) { if (!horizontal_offset.equals(v.horizontal_offset)) { return false; } } else if (v.horizontal_offset != null) { return false; } // yeah! return true; } public String toString() { StringBuilder sb = new StringBuilder(); if (horizontal != null) { sb.append(horizontal); if (horizontal_offset != null) { sb.append(' ').append(horizontal_offset); } if (vertical != null) { sb.append(' '); } } if (vertical != null) { sb.append(vertical); if (vertical_offset != null) { sb.append(' ').append(vertical_offset); } } return sb.toString(); } } } --- NEW FILE: CssColor.java --- // $Id: CssColor.java,v 1.1 2011/10/04 13:05:25 ylafon Exp $ // // (c) COPYRIGHT MIT, ERCIM and Keio University, 2011 // Please first read the full copyright statement in file COPYRIGHT.html package org.w3c.css.properties.css3; import org.w3c.css.properties.css.CssProperty; import org.w3c.css.util.ApplContext; import org.w3c.css.util.InvalidParamException; import org.w3c.css.values.CssExpression; import org.w3c.css.values.CssFunction; import org.w3c.css.values.CssIdent; import org.w3c.css.values.CssTypes; import org.w3c.css.values.CssValue; /** * @spec http://www.w3.org/TR/2011/REC-css3-color-20110607/#color0 * @version $Revision: 1.1 $ */ public class CssColor extends org.w3c.css.properties.css.CssColor { private static CssIdent same = CssIdent.getIdent("currentColor"); CssValue color; org.w3c.css.values.CssColor tempcolor = new org.w3c.css.values.CssColor(); String attrvalue = null; /** * Create a new CssColor */ public CssColor() { color = inherit; } /** * Set the value of the property * * @param expression The expression for this property * @throws org.w3c.css.util.InvalidParamException * Values are incorrect */ public CssColor(ApplContext ac, CssExpression expression, boolean check) throws InvalidParamException { if (check && expression.getCount() > 1) { throw new InvalidParamException("unrecognize", ac); } CssValue val = expression.getValue(); setByUser(); switch (val.getType()) { case CssTypes.CSS_IDENT: if (inherit.equals(val)) { color = inherit; } else if (same.equals(val)) { color = same; } else { color = new org.w3c.css.values.CssColor(ac, (String) val.get()); } break; case CssTypes.CSS_COLOR: color = val; break; case CssTypes.CSS_FUNCTION: CssFunction attr = (CssFunction) val; CssExpression params = attr.getParameters(); String fname = attr.getName(); if (fname.equals("attr")) { CssValue v1 = params.getValue(); params.next(); CssValue v2 = params.getValue(); if ((params.getCount() != 2)) { throw new InvalidParamException("value", params.getValue(), getPropertyName(), ac); } else if (v1.getType() != CssTypes.CSS_IDENT) { throw new InvalidParamException("value", params.getValue(), getPropertyName(), ac); } else if (!(v2.toString().equals("color"))) { throw new InvalidParamException("value", params.getValue(), getPropertyName(), ac); } else { attrvalue = "attr(" + v1 + ", " + v2 + ')'; } } else if (fname.equals("rgba")) { tempcolor.setRGBAColor(params, ac); color = tempcolor; } else if (fname.equals("hsl")) { tempcolor.setHSLColor(params, ac); color = tempcolor; } else if (fname.equals("hsla")) { tempcolor.setHSLAColor(params, ac); color = tempcolor; } else { throw new InvalidParamException("value", params.getValue(), getPropertyName(), ac); } break; default: throw new InvalidParamException("value", expression.getValue(), getPropertyName(), ac); } expression.next(); } public CssColor(ApplContext ac, CssExpression expression) throws InvalidParamException { this(ac, expression, false); } /** * Returns the value of this property */ public Object get() { return color; } /** * Returns the color */ public org.w3c.css.values.CssColor getColor() { if (inherit.equals(color) || same.equals(color)) { /* System.err.println("[ERROR] org.w3c.css.properties.CssColor"); System.err.println("[ERROR] value is inherited"); */ return null; } else { return (org.w3c.css.values.CssColor) color; } } /** * Returns true if this property is "softly" inherited * e.g. his value equals inherit */ public boolean isSoftlyInherited() { return inherit.equals(color) || same.equals(color); } /** * Returns a string representation of the object. */ public String toString() { if (attrvalue != null) { return attrvalue; } else { return color.toString(); } } /** * Compares two properties for equality. * * @param property The other property. */ public boolean equals(CssProperty property) { return (property instanceof CssColor && color.equals(((CssColor) property).color)); } } --- NEW FILE: CssBackgroundImage.java --- // $Id: CssBackgroundImage.java,v 1.1 2011/10/04 13:05:25 ylafon Exp $ // @author Yves Lafon <ylafon@w3.org> // // (c) COPYRIGHT MIT, ERCIM and Keio, 2010. // Please first read the full copyright statement in file COPYRIGHT.html package org.w3c.css.properties.css3; import org.w3c.css.properties.css.CssProperty; import org.w3c.css.util.ApplContext; import org.w3c.css.util.InvalidParamException; import org.w3c.css.values.CssExpression; import org.w3c.css.values.CssIdent; import org.w3c.css.values.CssTypes; import org.w3c.css.values.CssValue; import java.util.ArrayList; import static org.w3c.css.values.CssOperator.COMMA; /** * http://www.w3.org/TR/2009/CR-css3-background-20091217/#the-background-image * <p/> * Name: background-image * Value: <bg-image> [ , <bg-image> ]* * Initial: none * Applies to: all elements * Inherited: no * Percentages: N/A * Media: visual * Computed value: as specified, but with URIs made absolute * <p/> * This property sets the background image(s) of an element. Images are drawn * with the first specified one on top (closest to the user) and each * subsequent image behind the previous one. Where * <p/> * <bg-image> = <image> | none */ public class CssBackgroundImage extends org.w3c.css.properties.css.CssBackgroundImage { Object url = null; public static boolean isMatchingIdent(CssIdent ident) { return none.equals(ident); } /** * Create a new CssBackgroundImage */ public CssBackgroundImage() { } /** * Creates a new CssBackgroundImage * * @param ac the context * @param expression The expression for this property * @param check boolean * @throws org.w3c.css.util.InvalidParamException Values are incorrect */ public CssBackgroundImage(ApplContext ac, CssExpression expression, boolean check) throws InvalidParamException { ArrayList<CssValue> values = new ArrayList<CssValue>(); setByUser(); CssValue val; char op; while (!expression.end()) { val = expression.getValue(); op = expression.getOperator(); switch (val.getType()) { case CssTypes.CSS_URL: values.add(val); break; case CssTypes.CSS_IDENT: if (inherit.equals(val)) { // if we got inherit after other values, fail // if we got more than one value... fail if ((values.size() > 0) || (expression.getCount() > 1)) { throw new InvalidParamException("value", val, getPropertyName(), ac); } values.add(inherit); break; } else if (none.equals(val)) { values.add(none); break; } default: throw new InvalidParamException("value", val, getPropertyName(), ac); } expression.next(); if (!expression.end() && (op != COMMA)) { throw new InvalidParamException("operator", ((new Character(op)).toString()), ac); } } if (values.size() == 1) { url = values.get(0); } else { url = values; } } public CssBackgroundImage(ApplContext ac, CssExpression expression) throws InvalidParamException { this(ac, expression, false); } /** * Returns the value of this property */ public Object get() { return url; } public void set(Object val) { url = val; } /** * Returns true if this property is "softly" inherited * e.g. his value equals inherit */ public boolean isSoftlyInherited() { return (inherit == url); } /** * Returns a string representation of the object. */ public String toString() { if (url instanceof ArrayList) { ArrayList values = (ArrayList) url; StringBuilder sb = new StringBuilder(); for (Object aValue : values) { sb.append(aValue.toString()).append(", "); } sb.setLength(sb.length() - 2); return sb.toString(); } return url.toString(); } /** * Compares two properties for equality. * * @param property The other property. */ public boolean equals(CssProperty property) { return (property instanceof CssBackgroundImage && url != null && url.equals(((CssBackgroundImage) property).url)); } /** * Is the value of this property is a default value. * It is used by all macro for the function <code>print</code> */ public boolean isDefault() { return (url == none); } } --- NEW FILE: CssBackgroundSize.java --- // $Id: CssBackgroundSize.java,v 1.4 2011/10/04 13:05:25 ylafon Exp $ // @author Yves Lafon <ylafon@w3.org> // // (c) COPYRIGHT MIT, ERCIM and Keio University, 2010. // Please first read the full copyright statement in file COPYRIGHT.html package org.w3c.css.properties.css3; import org.w3c.css.properties.css.CssProperty; import org.w3c.css.util.ApplContext; import org.w3c.css.util.InvalidParamException; import org.w3c.css.values.CssExpression; import org.w3c.css.values.CssIdent; import org.w3c.css.values.CssNumber; import org.w3c.css.values.CssTypes; import org.w3c.css.values.CssValue; import org.w3c.css.values.CssValueList; import java.util.ArrayList; import java.util.HashMap; import static org.w3c.css.values.CssOperator.COMMA; import static org.w3c.css.values.CssOperator.SPACE; /** * http://www.w3.org/TR/2009/CR-css3-background-20091217/#the-background-size * <p/> * <p/> * Name: background-size * Value: <bg-size> [ , <bg-size> ]* * Initial: auto * Applies to: all elements * Inherited: no * Percentages: see text * Media: visual * Computed value: for <length> the absolute value, otherwise as * specified * <p/> * Specifies the size of the background images. Where * <p/> * <bg-size> = [ <length> | <percentage> | auto ]{1,2} | * cover | contain */ public class CssBackgroundSize extends org.w3c.css.properties.css.CssBackgroundSize { private static CssIdent auto; private static HashMap<String, CssIdent> allowed_values; static { auto = CssIdent.getIdent("auto"); allowed_values = new HashMap<String, CssIdent>(); allowed_values.put("auto", auto); allowed_values.put("cover", CssIdent.getIdent("cover")); allowed_values.put("contain", CssIdent.getIdent("contain")); } public static boolean isMatchingIdent(CssIdent ident) { return allowed_values.containsKey(ident.toString()); } Object value; /** * Create a new CssBackgroundSize */ public CssBackgroundSize() { value = auto; } /** * Create a new CssBackgroundSize * * @param ac The context * @param expression The expression for this property * @param check if arguments count must be checked. * @throws org.w3c.css.util.InvalidParamException Values are incorrect */ public CssBackgroundSize(ApplContext ac, CssExpression expression, boolean check) throws InvalidParamException { ArrayList<CssValue> values = new ArrayList<CssValue>(); char op; CssValue val; CssValueList vl = null; boolean is_complete = true; setByUser(); while (!expression.end()) { val = expression.getValue(); op = expression.getOperator(); switch (val.getType()) { case CssTypes.CSS_NUMBER: val = ((CssNumber) val).getLength(); case CssTypes.CSS_LENGTH: case CssTypes.CSS_PERCENTAGE: // per spec only non-negative values are allowed float f = ((Float) val.get()).floatValue(); if (f < 0) { throw new InvalidParamException("negative-value", val.toString(), ac); } if (is_complete) { vl = new CssValueList(); vl.add(val); } else { vl.add(val); values.add(vl); } is_complete = !is_complete; break; case CssTypes.CSS_IDENT: if (inherit.equals(val)) { // if we got inherit after other values, fail // if we got more than one value... fail if ((values.size() > 0) || (expression.getCount() > 1)) { throw new InvalidParamException("value", val, getPropertyName(), ac); } values.add(inherit); break; } else if (auto.equals(val)) { if (is_complete) { vl = new CssValueList(); vl.add(auto); } else { vl.add(auto); values.add(vl); } is_complete = !is_complete; break; } else { CssValue v = allowed_values.get(val.toString()); // if ok, and if we are not in a middle of a compound // value... if (v != null && is_complete) { values.add(v); break; } } default: throw new InvalidParamException("value", val, getPropertyName(), ac); } expression.next(); if (!expression.end()) { // incomplete value followed by a comma... it's complete! if (!is_complete && (op == COMMA)) { values.add(vl); is_complete = true; } // complete values are separated by a comma, otherwise space if ((is_complete && (op != COMMA)) || (!is_complete && (op != SPACE))) { throw new InvalidParamException("operator", ((new Character(op)).toString()), ac); } } } // if we reach the end in a value that can come in pair if (!is_complete) { values.add(vl); } if (values.size() == 1) { value = values.get(0); } else { value = values; } } public CssBackgroundSize(ApplContext ac, CssExpression expression) throws InvalidParamException { this(ac, expression, false); } /** * Compares two properties for equality. * * @param property The other property. */ public boolean equals(CssProperty property) { return (property instanceof CssBackgroundSize && value.equals(((CssBackgroundSize) property).value)); } /** * Returns the value of this property */ public Object get() { return value; } public void set(Object val) { value = val; } /** * Returns true if this property is "softly" inherited */ public boolean isSoftlyInherited() { return (inherit == value); } /** * Returns a string representation of the object */ public String toString() { if (value instanceof ArrayList) { ArrayList values = (ArrayList) value; StringBuilder sb = new StringBuilder(); for (Object aValue : values) { sb.append(aValue.toString()).append(", "); } sb.setLength(sb.length() - 2); return sb.toString(); } return value.toString(); } /** * Is the value of this property a default value * It is used by all macro for the function <code>print</code> */ public boolean isDefault() { return (auto == value); } } --- NEW FILE: CssBackgroundOrigin.java --- // // $Id: CssBackgroundOrigin.java,v 1.4 2011/10/04 13:05:25 ylafon Exp $ // @author Yves Lafon <ylafon@w3.org> // // (c) COPYRIGHT 2010 World Wide Web Consortium (MIT, ERCIM, Keio University) // Please first read the full copyright statement at // http://www.w3.org/Consortium/Legal/copyright-software-19980720 package org.w3c.css.properties.css3; import org.w3c.css.parser.CssStyle; import org.w3c.css.properties.css.CssProperty; import org.w3c.css.util.ApplContext; import org.w3c.css.util.InvalidParamException; import org.w3c.css.values.CssExpression; import org.w3c.css.values.CssIdent; import org.w3c.css.values.CssTypes; import org.w3c.css.values.CssValue; import java.util.ArrayList; import static org.w3c.css.values.CssOperator.COMMA; /** * http://www.w3.org/TR/2009/CR-css3-background-20091217/#the-background-origin * <p/> * Name: background-origin * Value: <bg-origin> [ , <bg-origin> ]* * Initial: padding-box * Applies to: all elements * Inherited: no * Percentages: N/A * Media: visual * Computed value: same as specified value * <p/> * For elements rendered as a single box, specifies the background positioning * area. For elements rendered as multiple boxes (e.g., inline boxes on several * lines, boxes on several pages) specifies which boxes 'box-decoration-break' * operates on to determine the background positioning area(s). * <p/> * <bg-origin> = border-box | padding-box | content-box */ public class CssBackgroundOrigin extends org.w3c.css.properties.css.CssBackgroundOrigin { private static CssIdent border_box; private static CssIdent padding_box; private static CssIdent content_box; Object value; static { border_box = CssIdent.getIdent("border-box"); padding_box = CssIdent.getIdent("padding-box"); content_box = CssIdent.getIdent("content-box"); } public static boolean isMatchingIdent(CssIdent ident) { return (border_box.equals(ident) || padding_box.equals(ident) || content_box.equals(ident)); } /** * Create a new CssBackgroundClip */ public CssBackgroundOrigin() { value = padding_box; } /** * Create a new CssBackgroundClip * * @param expression The expression for this property * @throws org.w3c.css.util.InvalidParamException * Incorrect value */ public CssBackgroundOrigin(ApplContext ac, CssExpression expression, boolean check) throws InvalidParamException { ArrayList<CssValue> values = new ArrayList<CssValue>(); CssValue val = expression.getValue(); char op; while (!expression.end()) { val = expression.getValue(); op = expression.getOperator(); switch (val.getType()) { case CssTypes.CSS_IDENT: if (inherit.equals(val)) { // if we got inherit after other values, fail // if we got more than one value... fail if ((values.size() > 0) || (expression.getCount() > 1)) { throw new InvalidParamException("value", val, getPropertyName(), ac); } values.add(inherit); break; } else if (border_box.equals(val)) { values.add(border_box); break; } else if (content_box.equals(val)) { values.add(content_box); break; } else if (padding_box.equals(val)) { values.add(padding_box); break; } default: throw new InvalidParamException("value", val, getPropertyName(), ac); } expression.next(); if (!expression.end() && (op != COMMA)) { throw new InvalidParamException("operator", ((new Character(op)).toString()), ac); } } if (values.size() == 1) { value = values.get(0); } else { value = values; } } public CssBackgroundOrigin(ApplContext ac, CssExpression expression) throws InvalidParamException { this(ac, expression, false); } /** * Add this property to the CssStyle * * @param style The CssStyle */ public void addToStyle(ApplContext ac, CssStyle style) { // TODO FIXME -> in CssStyle if (((Css3Style) style).cssBackgroundOrigin != null) style.addRedefinitionWarning(ac, this); ((Css3Style) style).cssBackgroundOrigin = this; } /** * Get this property in the style. * * @param style The style where the property is * @param resolve if true, resolve the style to find this property */ public CssProperty getPropertyInStyle(CssStyle style, boolean resolve) { if (resolve) { return ((Css3Style) style).getCssBackgroundOrigin(); } else { return ((Css3Style) style).cssBackgroundOrigin; } } /** * Compares two properties for equality. * * @param property The other property. */ public boolean equals(CssProperty property) { return (property instanceof CssBackgroundOrigin && value.equals(((CssBackgroundOrigin) property).value)); } /** * Returns the value of this property */ public Object get() { return value; } public void set(Object val) { value = val; } /** * Returns true if this property is "softly" inherited */ public boolean isSoftlyInherited() { return inherit.equals(value); } /** * Returns a string representation of the object */ public String toString() { if (value instanceof ArrayList) { ArrayList values = (ArrayList) value; StringBuilder sb = new StringBuilder(); for (Object aValue : values) { sb.append(aValue.toString()).append(", "); } sb.setLength(sb.length() - 2); return sb.toString(); } return value.toString(); } /** * Is the value of this property a default value * It is used by all macro for the function <code>print</code> */ public boolean isDefault() { return (padding_box == value); } } --- NEW FILE: CssBackgroundClip.java --- // $Id: CssBackgroundClip.java,v 1.4 2011/10/04 13:05:25 ylafon Exp $ // @author Yves Lafon <ylafon@w3.org> // // (c) COPYRIGHT 2010 World Wide Web Consortium (MIT, ERCIM, Keio University) // Please first read the full copyright statement at // http://www.w3.org/Consortium/Legal/copyright-software-19980720 package org.w3c.css.properties.css3; import org.w3c.css.parser.CssStyle; import org.w3c.css.properties.css.CssProperty; import org.w3c.css.util.ApplContext; import org.w3c.css.util.InvalidParamException; import org.w3c.css.values.CssExpression; import org.w3c.css.values.CssIdent; import org.w3c.css.values.CssTypes; import org.w3c.css.values.CssValue; import java.util.ArrayList; import static org.w3c.css.values.CssOperator.COMMA; /** * http://www.w3.org/TR/2009/CR-css3-background-20091217/#the-background-clip * Name: background-clip * Value: [border-box | padding-box ] [ , [border-box | padding-box ] ]* * Initial: border-box * Applies to: all elements * Inherited: no * Percentages: N/A * Media: visual * Computed value: same as specified value * <p/> * Determines the background painting area. */ public class CssBackgroundClip extends org.w3c.css.properties.css.CssBackgroundClip { public final static CssIdent border_box; public final static CssIdent padding_box; Object value; static { border_box = CssIdent.getIdent("border-box"); padding_box = CssIdent.getIdent("padding-box"); } public static boolean isMatchingIdent(CssIdent ident) { return (border_box.equals(ident) || padding_box.equals(ident)); } /** * Create a new CssBackgroundClip */ public CssBackgroundClip() { } /** * Create a new CssBackgroundClip * * @param expression The expression for this property * @throws org.w3c.css.util.InvalidParamException Incorrect value */ public CssBackgroundClip(ApplContext ac, CssExpression expression, boolean check) throws InvalidParamException { ArrayList<CssValue> values = new ArrayList<CssValue>(); CssValue val; char op; while (!expression.end()) { val = expression.getValue(); op = expression.getOperator(); switch (val.getType()) { case CssTypes.CSS_IDENT: if (inherit.equals(val)) { // if we got inherit after other values, fail // if we got more than one value... fail if ((values.size() > 0) || (expression.getCount() > 1)) { throw new InvalidParamException("value", val, getPropertyName(), ac); } values.add(inherit); break; } else if (border_box.equals(val)) { values.add(border_box); break; } else if (padding_box.equals(val)) { values.add(padding_box); break; } default: throw new InvalidParamException("value", val, getPropertyName(), ac); } expression.next(); if (!expression.end() && (op != COMMA)) { throw new InvalidParamException("operator", ((new Character(op)).toString()), ac); } } if (values.size() == 1) { value = values.get(0); } else { value = values; } } public CssBackgroundClip(ApplContext ac, CssExpression expression) throws InvalidParamException { this(ac, expression, false); } public void set(Object val) { value = val; } /** * Add this property to the CssStyle * * @param style The CssStyle */ public void addToStyle(ApplContext ac, CssStyle style) { // TODO FIXME -> in CssStyle if (((Css3Style) style).cssBackgroundClip != null) style.addRedefinitionWarning(ac, this); ((Css3Style) style).cssBackgroundClip = this; } /** * Get this property in the style. * * @param style The style where the property is * @param resolve if true, resolve the style to find this property */ public CssProperty getPropertyInStyle(CssStyle style, boolean resolve) { if (resolve) { return ((Css3Style) style).getCssBackgroundClip(); } else { return ((Css3Style) style).cssBackgroundClip; } } /** * Compares two properties for equality. * * @param property The other property. */ public boolean equals(CssProperty property) { return (property instanceof CssBackgroundClip && value.equals(((CssBackgroundClip) property).value)); } /** * Returns a string representation of the object */ public String toString() { if (value instanceof ArrayList) { ArrayList values = (ArrayList) value; StringBuilder sb = new StringBuilder(); for (Object aValue : values) { sb.append(aValue.toString()).append(", "); } sb.setLength(sb.length() - 2); return sb.toString(); } return value.toString(); } /** * Is the value of this property a default value * It is used by all macro for the function <code>print</code> */ public boolean isDefault() { return (border_box == value); } }
Received on Tuesday, 4 October 2011 13:05:39 UTC