diff --git a/org/w3c/css/properties/CSS3Properties.properties b/org/w3c/css/properties/CSS3Properties.properties index c4ea382f9..05c0232b6 100644 --- a/org/w3c/css/properties/CSS3Properties.properties +++ b/org/w3c/css/properties/CSS3Properties.properties @@ -330,6 +330,7 @@ cursor: org.w3c.css.properties.css3.CssCursor caret: org.w3c.css.properties.css3.CssCaret caret-color: org.w3c.css.properties.css3.CssCaretColor caret-shape: org.w3c.css.properties.css3.CssCaretShape +aspect-ratio: org.w3c.css.properties.css3.CssAspectRatio word-spacing: org.w3c.css.properties.css3.CssWordSpacing letter-spacing: org.w3c.css.properties.css3.CssLetterSpacing diff --git a/org/w3c/css/properties/css/CssAspectRatio.java b/org/w3c/css/properties/css/CssAspectRatio.java new file mode 100644 index 000000000..76d42d3e7 --- /dev/null +++ b/org/w3c/css/properties/css/CssAspectRatio.java @@ -0,0 +1,112 @@ +// +// Author: Yves Lafon +// +// (c) COPYRIGHT MIT, ERCIM, Keio, Beihang, 2021. +// Please first read the full copyright statement in file COPYRIGHT.html +package org.w3c.css.properties.css; + +import org.w3c.css.parser.CssStyle; +import org.w3c.css.properties.css3.Css3Style; +import org.w3c.css.util.ApplContext; +import org.w3c.css.util.InvalidParamException; +import org.w3c.css.values.CssExpression; +import org.w3c.css.values.CssValue; + +/** + * @since CSS3 + */ +public class CssAspectRatio extends CssProperty { + + public CssValue value; + + /** + * Create a new CssAspectRatio + */ + public CssAspectRatio() { + } + + /** + * Creates a new CssAspectRatio + * + * @param expression The expression for this property + * @throws InvalidParamException Expressions are incorrect + */ + public CssAspectRatio(ApplContext ac, CssExpression expression, boolean check) + throws InvalidParamException { + throw new InvalidParamException("value", + expression.getValue().toString(), + getPropertyName(), ac); + } + + public CssAspectRatio(ApplContext ac, CssExpression expression) + throws InvalidParamException { + this(ac, expression, false); + } + + /** + * Returns the value of this property + */ + public Object get() { + return value; + } + + + /** + * Returns the name of this property + */ + public final String getPropertyName() { + return "aspect-ratio"; + } + + /** + * Returns true if this property is "softly" inherited + * e.g. his value is equals to inherit + */ + public boolean isSoftlyInherited() { + return inherit.equals(value); + } + + /** + * Returns a string representation of the object. + */ + public String toString() { + return value.toString(); + } + + /** + * Add this property to the CssStyle. + * + * @param style The CssStyle + */ + public void addToStyle(ApplContext ac, CssStyle style) { + if (((Css3Style) style).cssAspectRatio != null) + style.addRedefinitionWarning(ac, this); + ((Css3Style) style).cssAspectRatio = this; + } + + /** + * Compares two properties for equality. + * + * @param property The other property. + */ + public boolean equals(CssProperty property) { + return (property instanceof CssAspectRatio && + value.equals(((CssAspectRatio) property).value)); + } + + + /** + * 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).getAspectRatio(); + } else { + return ((Css3Style) style).cssAspectRatio; + } + } +} + diff --git a/org/w3c/css/properties/css3/Css3Style.java b/org/w3c/css/properties/css3/Css3Style.java index 60c4ebda7..18a7d06f6 100644 --- a/org/w3c/css/properties/css3/Css3Style.java +++ b/org/w3c/css/properties/css3/Css3Style.java @@ -25,6 +25,7 @@ import org.w3c.css.properties.css.CssAnimationPlayState; import org.w3c.css.properties.css.CssAnimationTimingFunction; import org.w3c.css.properties.css.CssAppearance; +import org.w3c.css.properties.css.CssAspectRatio; import org.w3c.css.properties.css.CssBackfaceVisibility; import org.w3c.css.properties.css.CssBackgroundBlendMode; import org.w3c.css.properties.css.CssBackgroundClip; @@ -603,7 +604,17 @@ public class Css3Style extends ATSCStyle { public CssBorderStartEndRadius cssBorderStartEndRadius; public CssBorderEndStartRadius cssBorderEndStartRadius; public CssBorderEndEndRadius cssBorderEndEndRadius; + public CssAspectRatio cssAspectRatio; + public CssAspectRatio getAspectRatio() { + if (cssAspectRatio == null) { + cssAspectRatio = + (CssAspectRatio) style.CascadingOrder(new CssAspectRatio(), + style, selector); + } + return cssAspectRatio; + } + public CssBorderEndEndRadius getBorderEndEndRadius() { if (cssBorderEndEndRadius == null) { cssBorderEndEndRadius = diff --git a/org/w3c/css/properties/css3/CssAspectRatio.java b/org/w3c/css/properties/css3/CssAspectRatio.java new file mode 100644 index 000000000..fe909d41e --- /dev/null +++ b/org/w3c/css/properties/css3/CssAspectRatio.java @@ -0,0 +1,129 @@ +// +// Author: Yves Lafon +// +// (c) COPYRIGHT MIT, ERCIM, Keio, Beihang, 2021. +// Please first read the full copyright statement in file COPYRIGHT.html +package org.w3c.css.properties.css3; + +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.CssRatio; +import org.w3c.css.values.CssTypes; +import org.w3c.css.values.CssValue; +import org.w3c.css.values.CssValueList; + +import java.math.BigDecimal; +import java.util.ArrayList; + +import static org.w3c.css.values.CssOperator.SPACE; + +/** + * @spec https://www.w3.org/TR/2021/WD-css-sizing-4-20210520/#propdef-aspect-ratio + */ +public class CssAspectRatio extends org.w3c.css.properties.css.CssAspectRatio { + + public static final CssIdent auto = CssIdent.getIdent("auto"); + + /** + * Create a new CssAspectRatio + */ + public CssAspectRatio() { + value = initial; + } + + /** + * Creates a new CssAspectRatio + * + * @param expression The expression for this property + * @throws InvalidParamException Expressions are incorrect + */ + public CssAspectRatio(ApplContext ac, CssExpression expression, boolean check) + throws InvalidParamException { + if (check && expression.getCount() > 4) { + throw new InvalidParamException("unrecognize", ac); + } + CssValue val; + ArrayList v = new ArrayList<>(); + char op; + int ratio_state = 0; + setByUser(); + BigDecimal dividend = null; + BigDecimal divisor = null; + + while (!expression.end()) { + val = expression.getValue(); + op = expression.getOperator(); + + switch (val.getType()) { + // so we are cheating and create a CssRatio when needed. + case CssTypes.CSS_NUMBER: + if (ratio_state == 0) { + dividend = val.getNumber().getBigDecimalValue(); + ratio_state++; + break; + } else if (ratio_state == 2) { + divisor = val.getNumber().getBigDecimalValue(); + ratio_state++; + v.add(new CssRatio(dividend, divisor)) ; + break; + } + throw new InvalidParamException("value", val.toString(), + getPropertyName(), ac); + case CssTypes.CSS_SWITCH: + if (ratio_state == 1) { + ratio_state++; + break; + } + throw new InvalidParamException("value", val.toString(), + getPropertyName(), ac); + case CssTypes.CSS_IDENT: + if (inherit.equals(val)) { + if (expression.getCount() > 1) { + throw new InvalidParamException("value", val.toString(), + getPropertyName(), ac); + } + v.add(inherit); + break; + } + if (auto.equals(val)) { + v.add(auto); + break; + } + // unrecognize ident, let it fail + default: + throw new InvalidParamException("value", + val.toString(), + getPropertyName(), ac); + } + if (op != SPACE) { + throw new InvalidParamException("operator", + Character.toString(op), ac); + } + expression.next(); + } + // if things are not entirely parsed + if (v.size() == 0) { + throw new InvalidParamException("value", + expression.toString(), + getPropertyName(), ac); + } + if (v.size() > 1) { + if (v.get(0).getType() == v.get(1).getType()) { + throw new InvalidParamException("value", v.get(1).toString(), + getPropertyName(), ac); + } + value = new CssValueList(v); + } else { + value = v.get(0); + } + } + + + public CssAspectRatio(ApplContext ac, CssExpression expression) + throws InvalidParamException { + this(ac, expression, false); + } +} + diff --git a/org/w3c/css/values/CssRatio.java b/org/w3c/css/values/CssRatio.java index 70c28b645..761f7df4f 100644 --- a/org/w3c/css/values/CssRatio.java +++ b/org/w3c/css/values/CssRatio.java @@ -8,7 +8,9 @@ import org.w3c.css.util.ApplContext; import org.w3c.css.util.InvalidParamException; -import org.w3c.css.util.Util; + +import java.math.BigDecimal; +import java.math.RoundingMode; /** * @spec http://www.w3.org/TR/2010/CR-css3-mediaqueries-20100727/#values @@ -22,10 +24,7 @@ public final int getType() { return type; } - float w; - boolean isWInt; - float h; - boolean isHInt; + BigDecimal w, h; /** @@ -34,17 +33,20 @@ public final int getType() { public CssRatio() { } + public CssRatio(BigDecimal w, BigDecimal h) { + this.w = w; + this.h = h; + } + /** * Set the value of this ratio. * * @param s the string representation of the ratio. * @param ac For errors and warnings reports. - * @throws org.w3c.css.util.InvalidParamException - * (incorrect format) + * @throws org.w3c.css.util.InvalidParamException (incorrect format) */ public void set(String s, ApplContext ac) throws InvalidParamException { String sw, sh; - s = s.toLowerCase(); int slash = s.indexOf('/'); if (slash == -1) { @@ -56,37 +58,25 @@ public void set(String s, ApplContext ac) throws InvalidParamException { sw = s.substring(0, slash).trim(); sh = s.substring(slash + 1).trim(); try { - w = Integer.parseInt(sw); - isWInt = true; + w = new BigDecimal(sw); } catch (NumberFormatException nex) { - try { - w = Float.parseFloat(sw); - } catch (NumberFormatException ne) { - // not an int, not a float... bail out - throw new InvalidParamException("value", s, ac); - } + // not an int, not a float... bail out + throw new InvalidParamException("value", s, ac); } // sanity check - if (w <= 0.f) { + if (w.signum() != 1) { throw new InvalidParamException("strictly-positive", s, ac); } try { - h = Integer.parseInt(sh); - isHInt = true; + h = new BigDecimal(sh); } catch (NumberFormatException nex) { - try { - h = Float.parseFloat(sh); - } catch (NumberFormatException ne) { - // not an int, not a float... bail out - throw new InvalidParamException("value", s, ac); - } + throw new InvalidParamException("value", s, ac); } // sanity check - if (h <= 0.f) { + if (h.signum() != 1) { throw new InvalidParamException("strictly-positive", s, ac); } - } /** @@ -101,9 +91,7 @@ public Object get() { */ public String toString() { StringBuilder sb = new StringBuilder(); - sb.append((isWInt) ? Integer.toString((int) w) : Util.displayFloat(w)); - sb.append('/'); - sb.append((isHInt) ? Integer.toString((int) h) : Util.displayFloat(h)); + sb.append(w.toPlainString()).append('/').append(h.toPlainString()); return sb.toString(); } @@ -116,7 +104,10 @@ public boolean equals(Object value) { try { CssRatio other = (CssRatio) value; // check that the ratio are the same - return (Float.compare(w / h, other.w / other.h) == 0); + BigDecimal ratio, other_ratio; + ratio = w.divide(h, RoundingMode.CEILING); + other_ratio = other.w.divide(other.h, RoundingMode.CEILING); + return (ratio.compareTo(other_ratio) == 0); } catch (ClassCastException cce) { return false; }