diff --git a/echosvg-bridge/src/main/java/io/sf/carte/echosvg/bridge/SVGAnimationEngine.java b/echosvg-bridge/src/main/java/io/sf/carte/echosvg/bridge/SVGAnimationEngine.java index cc91c3b18..48ba03649 100644 --- a/echosvg-bridge/src/main/java/io/sf/carte/echosvg/bridge/SVGAnimationEngine.java +++ b/echosvg-bridge/src/main/java/io/sf/carte/echosvg/bridge/SVGAnimationEngine.java @@ -29,6 +29,7 @@ import java.util.Set; import org.w3c.css.om.unit.CSSUnit; +import org.w3c.dom.DOMException; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.css.CSSStyleDeclaration; @@ -37,6 +38,7 @@ import org.w3c.dom.svg.SVGLength; import org.w3c.dom.svg.SVGPreserveAspectRatio; +import io.sf.carte.doc.style.css.property.NumberValue; import io.sf.carte.echosvg.anim.AnimationEngine; import io.sf.carte.echosvg.anim.AnimationException; import io.sf.carte.echosvg.anim.dom.AnimationTarget; @@ -1815,8 +1817,14 @@ protected AnimatableValue createAnimatableValue(AnimationTarget target, String p unit = SVGAngle.SVG_ANGLETYPE_GRAD; break; default: - // XXX Do something better than returning null. - return null; + try { + float f = NumberValue.floatValueConversion(v.getFloatValue(), v.getCSSUnit(), + CSSUnit.CSS_DEG); + return new AnimatableAngleOrIdentValue(target, f, SVGAngle.SVG_ANGLETYPE_DEG); + } catch (DOMException e) { + // XXX Do something better than returning null. + return null; + } } return new AnimatableAngleValue(target, v.getFloatValue(), unit); } @@ -1846,8 +1854,14 @@ protected AnimatableValue createAnimatableValue(AnimationTarget target, String p unit = SVGAngle.SVG_ANGLETYPE_GRAD; break; default: - // XXX Do something better than returning null. - return null; + try { + float f = NumberValue.floatValueConversion(v.getFloatValue(), v.getCSSUnit(), + CSSUnit.CSS_DEG); + return new AnimatableAngleOrIdentValue(target, f, SVGAngle.SVG_ANGLETYPE_DEG); + } catch (DOMException e) { + // XXX Do something better than returning null. + return null; + } } return new AnimatableAngleOrIdentValue(target, v.getFloatValue(), unit); } diff --git a/echosvg-css/src/main/java/io/sf/carte/echosvg/css/dom/CSSOMValue.java b/echosvg-css/src/main/java/io/sf/carte/echosvg/css/dom/CSSOMValue.java index 03d08efef..fe3109d44 100644 --- a/echosvg-css/src/main/java/io/sf/carte/echosvg/css/dom/CSSOMValue.java +++ b/echosvg-css/src/main/java/io/sf/carte/echosvg/css/dom/CSSOMValue.java @@ -22,6 +22,7 @@ import org.w3c.css.om.unit.CSSUnit; import org.w3c.dom.DOMException; +import io.sf.carte.doc.style.css.property.NumberValue; import io.sf.carte.echosvg.css.engine.value.ColorValue; import io.sf.carte.echosvg.css.engine.value.RectValue; import io.sf.carte.echosvg.css.engine.value.Value; @@ -108,16 +109,24 @@ public float getFloatValue() throws DOMException { * Converts the actual float value to the given unit type. */ public static float convertFloatValue(short unitType, Value value) { + if (value.getCSSUnit() == unitType) { + return value.getFloatValue(); + } switch (unitType) { case CSSUnit.CSS_NUMBER: case CSSUnit.CSS_PERCENTAGE: case CSSUnit.CSS_EM: case CSSUnit.CSS_EX: - case CSSUnit.CSS_OTHER: case CSSUnit.CSS_PX: - if (value.getCSSUnit() == unitType) { - return value.getFloatValue(); - } + case CSSUnit.CSS_REM: + case CSSUnit.CSS_REX: + case CSSUnit.CSS_LH: + case CSSUnit.CSS_RLH: + case CSSUnit.CSS_VW: + case CSSUnit.CSS_VH: + case CSSUnit.CSS_VMIN: + case CSSUnit.CSS_VMAX: + case CSSUnit.CSS_OTHER: break; case CSSUnit.CSS_CM: return toCentimeters(value); @@ -143,6 +152,9 @@ public static float convertFloatValue(short unitType, Value value) { return toHertz(value); case CSSUnit.CSS_KHZ: return tokHertz(value); + default: + return NumberValue.floatValueConversion(value.getFloatValue(), value.getCSSUnit(), + unitType); } throw new DOMException(DOMException.INVALID_ACCESS_ERR, ""); } diff --git a/echosvg-css/src/main/java/io/sf/carte/echosvg/css/dom/CSSValue.java b/echosvg-css/src/main/java/io/sf/carte/echosvg/css/dom/CSSValue.java index fd021a246..c7471969b 100644 --- a/echosvg-css/src/main/java/io/sf/carte/echosvg/css/dom/CSSValue.java +++ b/echosvg-css/src/main/java/io/sf/carte/echosvg/css/dom/CSSValue.java @@ -21,9 +21,9 @@ import org.w3c.css.om.typed.CSSKeywordValue; import org.w3c.css.om.typed.CSSStringValue; import org.w3c.css.om.typed.CSSStyleValue; +import org.w3c.css.om.unit.CSSUnit; import org.w3c.dom.DOMException; -import org.w3c.css.om.unit.CSSUnit; import io.sf.carte.doc.style.css.property.KeywordValue; import io.sf.carte.echosvg.css.engine.value.ListValue; import io.sf.carte.echosvg.css.engine.value.NumericValue; diff --git a/echosvg-css/src/main/java/io/sf/carte/echosvg/css/engine/CSSEngine.java b/echosvg-css/src/main/java/io/sf/carte/echosvg/css/engine/CSSEngine.java index 386b621b6..bba9949bd 100644 --- a/echosvg-css/src/main/java/io/sf/carte/echosvg/css/engine/CSSEngine.java +++ b/echosvg-css/src/main/java/io/sf/carte/echosvg/css/engine/CSSEngine.java @@ -1249,9 +1249,9 @@ protected void parseStyleSheet(StyleSheet ss, InputSource is, ParsedURL uri) thr /** * Puts an author property from a style-map in another style-map, if possible. */ - protected void putAuthorProperty(StyleMap dest, int idx, Value sval, boolean imp, short origin) { + protected void putAuthorProperty(StyleMap dest, int idx, Value sval, boolean imp, int origin) { Value dval = dest.getValue(idx); - short dorg = dest.getOrigin(idx); + int dorg = dest.getOrigin(idx); boolean dimp = dest.isImportant(idx); boolean cond = dval == null; @@ -1313,7 +1313,7 @@ protected void addMatchingRules(List rules, StyleSheet ss, SelectorMatcher /** * Adds the rules contained in the given list to a stylemap. */ - protected void addRules(SelectorMatcher matcher, StyleMap sm, ArrayList rules, short origin) { + protected void addRules(SelectorMatcher matcher, StyleMap sm, ArrayList rules, int origin) { sortRules(rules, matcher); if (origin == StyleMap.AUTHOR_ORIGIN) { @@ -2007,7 +2007,7 @@ protected void inlineStyleAttributeUpdated(CSSStylableElement elt, StyleMap styl // come from the inline style attribute or override style. for (int i = getNumberOfProperties() - 1; i >= 0; --i) { if (style.isComputed(i) && !updated[i]) { - short origin = style.getOrigin(i); + int origin = style.getOrigin(i); if (origin >= StyleMap.INLINE_AUTHOR_ORIGIN) { // ToDo Jlint says: always same result ?? removed = true; updated[i] = true; @@ -2024,12 +2024,14 @@ protected void inlineStyleAttributeUpdated(CSSStylableElement elt, StyleMap styl boolean fs = (fontSizeIndex == -1) ? false : updated[fontSizeIndex]; boolean lh = (lineHeightIndex == -1) ? false : updated[lineHeightIndex]; boolean cl = (colorIndex == -1) ? false : updated[colorIndex]; + boolean isRoot = elt.getOwnerDocument().getDocumentElement() == elt; for (int i = getNumberOfProperties() - 1; i >= 0; --i) { if (updated[i]) { count++; } else if ((fs && style.isFontSizeRelative(i)) || (lh && style.isLineHeightRelative(i)) - || (cl && style.isColorRelative(i))) { + || (cl && style.isColorRelative(i)) || (fs && isRoot && style.isRootFontSizeRelative(i)) + || (lh && isRoot && style.isRootLineHeightRelative(i))) { updated[i] = true; clearComputedValue(style, i); count++; @@ -2170,13 +2172,14 @@ protected void propagateChanges(Node node, int[] props, boolean recascade) { boolean fs = (fontSizeIndex == -1) ? false : updated[fontSizeIndex]; boolean lh = (lineHeightIndex == -1) ? false : updated[lineHeightIndex]; boolean cl = (colorIndex == -1) ? false : updated[colorIndex]; + boolean isRootFs = fs && elt.getOwnerDocument().getDocumentElement() == elt; int count = 0; for (int i = getNumberOfProperties() - 1; i >= 0; --i) { if (updated[i]) { count++; } else if ((fs && style.isFontSizeRelative(i)) || (lh && style.isLineHeightRelative(i)) - || (cl && style.isColorRelative(i))) { + || (cl && style.isColorRelative(i)) || (isRootFs && style.isRootFontSizeRelative(i))) { updated[i] = true; clearComputedValue(style, i); count++; @@ -2265,7 +2268,7 @@ public void property(String name, LexicalUnit value, boolean important) { updatedProperties[i] = true; Value v = valueManagers[i].createValue(value, CSSEngine.this); - styleMap.putMask(i, (short) 0); + styleMap.putMask(i, 0); styleMap.putValue(i, v); styleMap.putOrigin(i, StyleMap.INLINE_AUTHOR_ORIGIN); } @@ -2300,7 +2303,7 @@ protected void nonCSSPresentationalHintUpdated(CSSStylableElement elt, StyleMap lu = parser.parsePropertyValue(new StringReader(newValue)); ValueManager vm = valueManagers[idx]; Value v = vm.createValue(lu, CSSEngine.this); - style.putMask(idx, (short) 0); + style.putMask(idx, 0); style.putValue(idx, v); style.putOrigin(idx, StyleMap.NON_CSS_ORIGIN); } catch (Exception e) { @@ -2338,13 +2341,14 @@ protected void nonCSSPresentationalHintUpdated(CSSStylableElement elt, StyleMap boolean fs = idx == fontSizeIndex; boolean lh = idx == lineHeightIndex; boolean cl = idx == colorIndex; + boolean isRootFs = fs && elt.getOwnerDocument().getDocumentElement() == elt; int count = 0; for (int i = getNumberOfProperties() - 1; i >= 0; --i) { if (updated[i]) { count++; } else if ((fs && style.isFontSizeRelative(i)) || (lh && style.isLineHeightRelative(i)) - || (cl && style.isColorRelative(i))) { + || (cl && style.isColorRelative(i)) || (isRootFs && style.isRootFontSizeRelative(i))) { updated[i] = true; clearComputedValue(style, i); count++; diff --git a/echosvg-css/src/main/java/io/sf/carte/echosvg/css/engine/StyleMap.java b/echosvg-css/src/main/java/io/sf/carte/echosvg/css/engine/StyleMap.java index a77c1ac32..634ae5a8f 100644 --- a/echosvg-css/src/main/java/io/sf/carte/echosvg/css/engine/StyleMap.java +++ b/echosvg-css/src/main/java/io/sf/carte/echosvg/css/engine/StyleMap.java @@ -29,34 +29,33 @@ */ public class StyleMap { - // - // The masks, still have 2 free bits: 0x0800, & 0x1000, could also - // go to int if needed. - // - public static final short IMPORTANT_MASK = 0x0001; - public static final short COMPUTED_MASK = 0x0002; - public static final short NULL_CASCADED_MASK = 0x0004; - public static final short INHERITED_MASK = 0x0008; - - public static final short LINE_HEIGHT_RELATIVE_MASK = 0x0010; - public static final short FONT_SIZE_RELATIVE_MASK = 0x0020; - public static final short COLOR_RELATIVE_MASK = 0x0040; - public static final short PARENT_RELATIVE_MASK = 0x0080; - public static final short BLOCK_WIDTH_RELATIVE_MASK = 0x0100; - public static final short BLOCK_HEIGHT_RELATIVE_MASK = 0x0200; - public static final short BOX_RELATIVE_MASK = 0x0400; - - public static final short ORIGIN_MASK = (short) 0xE000; // 3 last bits + public static final int IMPORTANT_MASK = 0x0001; + public static final int COMPUTED_MASK = 0x0002; + public static final int NULL_CASCADED_MASK = 0x0004; + public static final int INHERITED_MASK = 0x0008; + + public static final int LINE_HEIGHT_RELATIVE_MASK = 0x0010; + public static final int FONT_SIZE_RELATIVE_MASK = 0x0020; + public static final int COLOR_RELATIVE_MASK = 0x0040; + public static final int PARENT_RELATIVE_MASK = 0x0080; + public static final int BLOCK_WIDTH_RELATIVE_MASK = 0x0100; + public static final int BLOCK_HEIGHT_RELATIVE_MASK = 0x0200; + public static final int BOX_RELATIVE_MASK = 0x0400; + public static final int ROOT_LINE_HEIGHT_RELATIVE_MASK = 0x0800; + public static final int ROOT_FONT_SIZE_RELATIVE_MASK = 0x1000; + public static final int VIEWPORT_RELATIVE_MASK = 0x2000; + + public static final int ORIGIN_MASK = 0xE0000000; // 3 last bits // // The origin values. // - public static final short USER_AGENT_ORIGIN = 0; - public static final short USER_ORIGIN = 0x2000; // 0010 - public static final short NON_CSS_ORIGIN = 0x4000; // 0100 - public static final short AUTHOR_ORIGIN = 0x6000; // 0110 - public static final short INLINE_AUTHOR_ORIGIN = (short) 0x8000; // 1000 - public static final short OVERRIDE_ORIGIN = (short) 0xA000; // 1010 + public static final int USER_AGENT_ORIGIN = 0; + public static final int USER_ORIGIN = 0x20000000; // 0010 + public static final int NON_CSS_ORIGIN = 0x40000000; // 0100 + public static final int AUTHOR_ORIGIN = 0x60000000; // 0110 + public static final int INLINE_AUTHOR_ORIGIN = 0x80000000; // 1000 + public static final int OVERRIDE_ORIGIN = 0xA0000000; // 1010 /** * The values. @@ -66,7 +65,7 @@ public class StyleMap { /** * To store the value masks. */ - protected short[] masks; + protected int[] masks; /** * Whether the values of this map cannot be re-cascaded. @@ -78,7 +77,7 @@ public class StyleMap { */ public StyleMap(int size) { values = new Value[size]; - masks = new short[size]; + masks = new int[size]; } /** @@ -105,7 +104,7 @@ public Value getValue(int i) { /** * Returns the mask of the given property value. */ - public short getMask(int i) { + public int getMask(int i) { return masks[i]; } @@ -141,8 +140,8 @@ public boolean isInherited(int i) { /** * Returns the origin value. */ - public short getOrigin(int i) { - return (short) (masks[i] & ORIGIN_MASK); + public int getOrigin(int i) { + return (masks[i] & ORIGIN_MASK); } /** @@ -174,6 +173,22 @@ public boolean isFontSizeRelative(int i) { return (masks[i] & FONT_SIZE_RELATIVE_MASK) != 0; } + /** + * Tells whether the given property value is relative to 'line-height' of the + * {@code :root} element. + */ + public boolean isRootLineHeightRelative(int i) { + return (masks[i] & ROOT_LINE_HEIGHT_RELATIVE_MASK) != 0; + } + + /** + * Tells whether the given property value is relative to 'font-size' of the + * {@code :root} element. + */ + public boolean isRootFontSizeRelative(int i) { + return (masks[i] & ROOT_FONT_SIZE_RELATIVE_MASK) != 0; + } + /** * Tells whether the given property value is relative to the width of the * containing block. @@ -190,6 +205,13 @@ public boolean isBlockHeightRelative(int i) { return (masks[i] & BLOCK_HEIGHT_RELATIVE_MASK) != 0; } + /** + * Tells whether the given property value is relative to the viewport. + */ + public boolean isViewportRelative(int i) { + return (masks[i] & VIEWPORT_RELATIVE_MASK) != 0; + } + /** * Puts a property value, given the property index. * @@ -206,7 +228,7 @@ public void putValue(int i, Value v) { * @param i The property index. * @param m The property mask. */ - public void putMask(int i, short m) { + public void putMask(int i, int m) { masks[i] = m; } @@ -223,9 +245,9 @@ public void putImportant(int i, boolean b) { /** * Sets the origin of the given value. */ - public void putOrigin(int i, short val) { + public void putOrigin(int i, int val) { masks[i] &= ~ORIGIN_MASK; - masks[i] |= (short) (val & ORIGIN_MASK); + masks[i] |= (val & ORIGIN_MASK); } /** @@ -299,6 +321,26 @@ public void putFontSizeRelative(int i, boolean b) { masks[i] &= ~FONT_SIZE_RELATIVE_MASK; } + /** + * Sets the root-line-height-relative flag of a property value. + */ + public void putRootLineHeightRelative(int i, boolean b) { + if (b) + masks[i] |= ROOT_LINE_HEIGHT_RELATIVE_MASK; + else + masks[i] &= ~ROOT_LINE_HEIGHT_RELATIVE_MASK; + } + + /** + * Sets the root-font-size-relative flag of a property value. + */ + public void putRootFontSizeRelative(int i, boolean b) { + if (b) + masks[i] |= ROOT_FONT_SIZE_RELATIVE_MASK; + else + masks[i] &= ~ROOT_FONT_SIZE_RELATIVE_MASK; + } + /** * Sets the block-width-relative flag of a property value. */ @@ -319,6 +361,16 @@ public void putBlockHeightRelative(int i, boolean b) { masks[i] &= ~BLOCK_HEIGHT_RELATIVE_MASK; } + /** + * Sets the viewport-relative flag of a property value. + */ + public void putViewportRelative(int i, boolean b) { + if (b) + masks[i] |= VIEWPORT_RELATIVE_MASK; + else + masks[i] &= ~VIEWPORT_RELATIVE_MASK; + } + /** * Returns a printable representation of this style map. */ diff --git a/echosvg-css/src/main/java/io/sf/carte/echosvg/css/engine/value/AbstractValueManager.java b/echosvg-css/src/main/java/io/sf/carte/echosvg/css/engine/value/AbstractValueManager.java index 4b6ada07d..2a6c764f8 100644 --- a/echosvg-css/src/main/java/io/sf/carte/echosvg/css/engine/value/AbstractValueManager.java +++ b/echosvg-css/src/main/java/io/sf/carte/echosvg/css/engine/value/AbstractValueManager.java @@ -18,9 +18,9 @@ */ package io.sf.carte.echosvg.css.engine.value; +import org.w3c.css.om.unit.CSSUnit; import org.w3c.dom.DOMException; -import org.w3c.css.om.unit.CSSUnit; import io.sf.carte.echosvg.css.dom.CSSValue.Type; import io.sf.carte.echosvg.css.engine.CSSEngine; import io.sf.carte.echosvg.css.engine.CSSStylableElement; diff --git a/echosvg-css/src/main/java/io/sf/carte/echosvg/css/engine/value/ColorFunction.java b/echosvg-css/src/main/java/io/sf/carte/echosvg/css/engine/value/ColorFunction.java index 11196f411..d4012a2b2 100644 --- a/echosvg-css/src/main/java/io/sf/carte/echosvg/css/engine/value/ColorFunction.java +++ b/echosvg-css/src/main/java/io/sf/carte/echosvg/css/engine/value/ColorFunction.java @@ -25,9 +25,8 @@ import org.w3c.api.DOMSyntaxException; import org.w3c.css.om.typed.CSSColor; import org.w3c.css.om.typed.CSSStyleValueList; -import org.w3c.dom.DOMException; - import org.w3c.css.om.unit.CSSUnit; +import org.w3c.dom.DOMException; /** * color() function. diff --git a/echosvg-css/src/main/java/io/sf/carte/echosvg/css/engine/value/LCHColorValue.java b/echosvg-css/src/main/java/io/sf/carte/echosvg/css/engine/value/LCHColorValue.java index 52d79fa6b..46d273651 100644 --- a/echosvg-css/src/main/java/io/sf/carte/echosvg/css/engine/value/LCHColorValue.java +++ b/echosvg-css/src/main/java/io/sf/carte/echosvg/css/engine/value/LCHColorValue.java @@ -21,9 +21,9 @@ import org.w3c.api.DOMSyntaxException; import org.w3c.css.om.typed.CSSLCH; import org.w3c.css.om.typed.CSSNumericValue; +import org.w3c.css.om.unit.CSSUnit; import org.w3c.dom.DOMException; -import org.w3c.css.om.unit.CSSUnit; import io.sf.carte.echosvg.css.engine.value.svg.SVGValueConstants; /** diff --git a/echosvg-css/src/main/java/io/sf/carte/echosvg/css/engine/value/LabColorValue.java b/echosvg-css/src/main/java/io/sf/carte/echosvg/css/engine/value/LabColorValue.java index edf8eb465..17cb92ed2 100644 --- a/echosvg-css/src/main/java/io/sf/carte/echosvg/css/engine/value/LabColorValue.java +++ b/echosvg-css/src/main/java/io/sf/carte/echosvg/css/engine/value/LabColorValue.java @@ -21,9 +21,9 @@ import org.w3c.api.DOMSyntaxException; import org.w3c.css.om.typed.CSSLab; import org.w3c.css.om.typed.CSSNumericValue; +import org.w3c.css.om.unit.CSSUnit; import org.w3c.dom.DOMException; -import org.w3c.css.om.unit.CSSUnit; import io.sf.carte.echosvg.css.engine.value.svg.SVGValueConstants; /** diff --git a/echosvg-css/src/main/java/io/sf/carte/echosvg/css/engine/value/LengthManager.java b/echosvg-css/src/main/java/io/sf/carte/echosvg/css/engine/value/LengthManager.java index b2e799e4b..48c5072d8 100644 --- a/echosvg-css/src/main/java/io/sf/carte/echosvg/css/engine/value/LengthManager.java +++ b/echosvg-css/src/main/java/io/sf/carte/echosvg/css/engine/value/LengthManager.java @@ -18,11 +18,12 @@ */ package io.sf.carte.echosvg.css.engine.value; +import org.w3c.css.om.unit.CSSUnit; import org.w3c.dom.DOMException; -import org.w3c.css.om.unit.CSSUnit; import io.sf.carte.doc.style.css.nsac.LexicalUnit; import io.sf.carte.doc.style.css.property.NumberValue; +import io.sf.carte.echosvg.css.Viewport; import io.sf.carte.echosvg.css.dom.CSSValue.Type; import io.sf.carte.echosvg.css.engine.CSSContext; import io.sf.carte.echosvg.css.engine.CSSEngine; @@ -53,11 +54,7 @@ public abstract class LengthManager extends AbstractValueManager { public Value createValue(LexicalUnit lu, CSSEngine engine) throws DOMException { switch (lu.getLexicalUnitType()) { case DIMENSION: - Value value = createLength(lu); - if (value != null) { - return value; - } - break; + return createLength(lu); case INTEGER: return new FloatValue(CSSUnit.CSS_NUMBER, lu.getIntegerValue()); @@ -73,11 +70,11 @@ public Value createValue(LexicalUnit lu, CSSEngine engine) throws DOMException { throw createInvalidLexicalUnitDOMException(lu.getLexicalUnitType()); } - static FloatValue createLength(LexicalUnit lu) { + FloatValue createLength(LexicalUnit lu) throws DOMException { if (CSSUnit.isLengthUnitType(lu.getCssUnit())) { return new FloatValue(lu.getCssUnit(), lu.getFloatValue()); } - return null; + throw createInvalidLexicalUnitDOMException(lu.getLexicalUnitType()); } /** @@ -169,13 +166,89 @@ public Value computeValue(CSSStylableElement elt, String pseudo, CSSEngine engin fs = (float) (value.getFloatValue() * (Math.sqrt(w * w + h * h) / SQRT2) / 100.0); } return new FloatValue(CSSUnit.CSS_NUMBER, fs); + + case CSSUnit.CSS_LH: + sm.putLineHeightRelative(idx, true); + + v = value.getFloatValue(); + int lhidx = engine.getLineHeightIndex(); + cv = engine.getComputedStyle(elt, pseudo, lhidx); + fs = lengthValue(cv); + return new FloatValue(CSSUnit.CSS_NUMBER, v * fs); + + case CSSUnit.CSS_REM: + sm.putRootFontSizeRelative(idx, true); + + v = value.getFloatValue(); + fsidx = engine.getFontSizeIndex(); + CSSStylableElement root = (CSSStylableElement) elt.getOwnerDocument().getDocumentElement(); + cv = engine.getComputedStyle(root, null, fsidx); + fs = lengthValue(cv); + return new FloatValue(CSSUnit.CSS_NUMBER, v * fs); + + case CSSUnit.CSS_REX: + sm.putRootFontSizeRelative(idx, true); + + v = value.getFloatValue(); + fsidx = engine.getFontSizeIndex(); + root = (CSSStylableElement) elt.getOwnerDocument().getDocumentElement(); + cv = engine.getComputedStyle(root, null, fsidx); + fs = lengthValue(cv); + return new FloatValue(CSSUnit.CSS_NUMBER, v * fs * 0.5f); + + case CSSUnit.CSS_RLH: + sm.putRootLineHeightRelative(idx, true); + + v = value.getFloatValue(); + lhidx = engine.getLineHeightIndex(); + root = (CSSStylableElement) elt.getOwnerDocument().getDocumentElement(); + cv = engine.getComputedStyle(root, null, lhidx); + fs = lengthValue(cv); + return new FloatValue(CSSUnit.CSS_NUMBER, v * fs); + + case CSSUnit.CSS_VW: + sm.putViewportRelative(idx, true); + + v = lengthValue(value); + return new FloatValue(CSSUnit.CSS_NUMBER, v * + engine.getCSSContext().getViewport(elt).getWidth() * 0.01f); + + case CSSUnit.CSS_VH: + sm.putViewportRelative(idx, true); + + v = lengthValue(value); + return new FloatValue(CSSUnit.CSS_NUMBER, v * + engine.getCSSContext().getViewport(elt).getHeight() * 0.01f); + + case CSSUnit.CSS_VMIN: + sm.putViewportRelative(idx, true); + + v = lengthValue(value); + Viewport vp = engine.getCSSContext().getViewport(elt); + float w = vp.getWidth(); + float h = vp.getHeight(); + float min = Math.min(w, h); + return new FloatValue(CSSUnit.CSS_NUMBER, v * min * 0.01f); + + case CSSUnit.CSS_VMAX: + sm.putViewportRelative(idx, true); + + v = lengthValue(value); + vp = engine.getCSSContext().getViewport(elt); + w = vp.getWidth(); + h = vp.getHeight(); + float max = Math.max(w, h); + return new FloatValue(CSSUnit.CSS_NUMBER, v * max * 0.01f); + case CSSUnit.CSS_INVALID: + case CSSUnit.CSS_OTHER: break; default: // Maybe it is one of the new absolute length units try { value = new FloatValue(CSSUnit.CSS_NUMBER, - NumberValue.floatValueConversion(value.getFloatValue(), value.getCSSUnit(), CSSUnit.CSS_PX)); + NumberValue.floatValueConversion(value.getFloatValue(), value.getCSSUnit(), CSSUnit.CSS_MM) + / engine.getCSSContext().getPixelUnitToMillimeter()); } catch (DOMException e) { } } diff --git a/echosvg-css/src/main/java/io/sf/carte/echosvg/css/engine/value/RectManager.java b/echosvg-css/src/main/java/io/sf/carte/echosvg/css/engine/value/RectManager.java index e816010c4..8a5d79264 100644 --- a/echosvg-css/src/main/java/io/sf/carte/echosvg/css/engine/value/RectManager.java +++ b/echosvg-css/src/main/java/io/sf/carte/echosvg/css/engine/value/RectManager.java @@ -91,11 +91,7 @@ private Value createRectComponent(LexicalUnit lu) throws DOMException { } break; case DIMENSION: - NumericValue value = createLength(lu); - if (value != null) { - return value; - } - break; + return createLength(lu); case INTEGER: return new FloatValue(CSSUnit.CSS_NUMBER, lu.getIntegerValue()); case REAL: diff --git a/echosvg-css/src/main/java/io/sf/carte/echosvg/css/engine/value/RectValue.java b/echosvg-css/src/main/java/io/sf/carte/echosvg/css/engine/value/RectValue.java index 9505cba4a..f6dd3d454 100644 --- a/echosvg-css/src/main/java/io/sf/carte/echosvg/css/engine/value/RectValue.java +++ b/echosvg-css/src/main/java/io/sf/carte/echosvg/css/engine/value/RectValue.java @@ -20,9 +20,8 @@ import org.w3c.api.DOMSyntaxException; import org.w3c.css.om.typed.CSSRectValue; -import org.w3c.dom.DOMException; - import org.w3c.css.om.unit.CSSUnit; +import org.w3c.dom.DOMException; /** * This class represents CSS rect values. diff --git a/echosvg-css/src/main/java/io/sf/carte/echosvg/css/engine/value/ValueConstants.java b/echosvg-css/src/main/java/io/sf/carte/echosvg/css/engine/value/ValueConstants.java index 01051c058..6a03e46bc 100644 --- a/echosvg-css/src/main/java/io/sf/carte/echosvg/css/engine/value/ValueConstants.java +++ b/echosvg-css/src/main/java/io/sf/carte/echosvg/css/engine/value/ValueConstants.java @@ -19,6 +19,7 @@ package io.sf.carte.echosvg.css.engine.value; import org.w3c.css.om.unit.CSSUnit; + import io.sf.carte.echosvg.util.CSSConstants; /** diff --git a/echosvg-css/src/main/java/io/sf/carte/echosvg/css/engine/value/css2/FontSizeManager.java b/echosvg-css/src/main/java/io/sf/carte/echosvg/css/engine/value/css2/FontSizeManager.java index 245d7dfae..abb6c7c2e 100644 --- a/echosvg-css/src/main/java/io/sf/carte/echosvg/css/engine/value/css2/FontSizeManager.java +++ b/echosvg-css/src/main/java/io/sf/carte/echosvg/css/engine/value/css2/FontSizeManager.java @@ -24,6 +24,7 @@ import org.w3c.dom.DOMException; import io.sf.carte.doc.style.css.nsac.LexicalUnit; +import io.sf.carte.doc.style.css.property.NumberValue; import io.sf.carte.echosvg.css.Viewport; import io.sf.carte.echosvg.css.dom.CSSValue.Type; import io.sf.carte.echosvg.css.engine.CSSContext; @@ -167,77 +168,117 @@ public Value computeValue(CSSStylableElement elt, String pseudo, CSSEngine engin float scale = 1.0f; boolean doParentRelative = false; - switch (value.getCSSUnit()) { - case CSSUnit.CSS_NUMBER: - case CSSUnit.CSS_PX: - return value; + if (value.getPrimitiveType() == Type.NUMERIC) { + switch (value.getCSSUnit()) { + case CSSUnit.CSS_NUMBER: + case CSSUnit.CSS_PX: + return value; - case CSSUnit.CSS_MM: - CSSContext ctx = engine.getCSSContext(); - float v = lengthValue(value); - return new FloatValue(CSSUnit.CSS_NUMBER, v / ctx.getPixelUnitToMillimeter()); - - case CSSUnit.CSS_CM: - ctx = engine.getCSSContext(); - v = lengthValue(value); - return new FloatValue(CSSUnit.CSS_NUMBER, v * 10f / ctx.getPixelUnitToMillimeter()); - - case CSSUnit.CSS_IN: - ctx = engine.getCSSContext(); - v = lengthValue(value); - return new FloatValue(CSSUnit.CSS_NUMBER, v * 25.4f / ctx.getPixelUnitToMillimeter()); - - case CSSUnit.CSS_PT: - ctx = engine.getCSSContext(); - v = lengthValue(value); - return new FloatValue(CSSUnit.CSS_NUMBER, v * 25.4f / (72f * ctx.getPixelUnitToMillimeter())); - - case CSSUnit.CSS_PC: - ctx = engine.getCSSContext(); - v = lengthValue(value); - return new FloatValue(CSSUnit.CSS_NUMBER, (v * 25.4f / (6f * ctx.getPixelUnitToMillimeter()))); - - case CSSUnit.CSS_EM: - doParentRelative = true; - scale = lengthValue(value); - break; - case CSSUnit.CSS_EX: - doParentRelative = true; - scale = lengthValue(value) * 0.5f; // !!! x-height - break; - case CSSUnit.CSS_PERCENTAGE: - doParentRelative = true; - scale = value.getFloatValue() * 0.01f; - break; - case CSSUnit.CSS_REM: - scale = lengthValue(value); - return rootRelative(elt, engine, idx, scale); - case CSSUnit.CSS_REX: - scale = lengthValue(value) * 0.5f; - return rootRelative(elt, engine, idx, scale); - case CSSUnit.CSS_VW: - v = lengthValue(value); - return new FloatValue(CSSUnit.CSS_NUMBER, v * - engine.getCSSContext().getViewport(elt).getWidth() * 0.01f); - case CSSUnit.CSS_VH: - v = lengthValue(value); - return new FloatValue(CSSUnit.CSS_NUMBER, v * - engine.getCSSContext().getViewport(elt).getHeight() * 0.01f); - case CSSUnit.CSS_VMIN: - v = lengthValue(value); - Viewport vp = engine.getCSSContext().getViewport(elt); - float w = vp.getWidth(); - float h = vp.getHeight(); - float min = Math.min(w, h); - return new FloatValue(CSSUnit.CSS_NUMBER, v * min * 0.01f); - case CSSUnit.CSS_VMAX: - v = lengthValue(value); - vp = engine.getCSSContext().getViewport(elt); - w = vp.getWidth(); - h = vp.getHeight(); - float max = Math.max(w, h); - return new FloatValue(CSSUnit.CSS_NUMBER, v * max * 0.01f); - default: + case CSSUnit.CSS_MM: + CSSContext ctx = engine.getCSSContext(); + float v = lengthValue(value); + return new FloatValue(CSSUnit.CSS_NUMBER, v / ctx.getPixelUnitToMillimeter()); + + case CSSUnit.CSS_CM: + ctx = engine.getCSSContext(); + v = lengthValue(value); + return new FloatValue(CSSUnit.CSS_NUMBER, v * 10f / ctx.getPixelUnitToMillimeter()); + + case CSSUnit.CSS_IN: + ctx = engine.getCSSContext(); + v = lengthValue(value); + return new FloatValue(CSSUnit.CSS_NUMBER, v * 25.4f / ctx.getPixelUnitToMillimeter()); + + case CSSUnit.CSS_PT: + ctx = engine.getCSSContext(); + v = lengthValue(value); + return new FloatValue(CSSUnit.CSS_NUMBER, v * 25.4f / (72f * ctx.getPixelUnitToMillimeter())); + + case CSSUnit.CSS_PC: + ctx = engine.getCSSContext(); + v = lengthValue(value); + return new FloatValue(CSSUnit.CSS_NUMBER, (v * 25.4f / (6f * ctx.getPixelUnitToMillimeter()))); + + case CSSUnit.CSS_EM: + doParentRelative = true; + scale = lengthValue(value); + break; + case CSSUnit.CSS_EX: + doParentRelative = true; + scale = lengthValue(value) * 0.5f; // !!! x-height + break; + case CSSUnit.CSS_PERCENTAGE: + doParentRelative = true; + scale = value.getFloatValue() * 0.01f; + break; + case CSSUnit.CSS_LH: + sm.putLineHeightRelative(idx, true); + scale = lengthValue(value); + int lhidx = engine.getLineHeightIndex(); + CSSStylableElement p = CSSEngine.getParentCSSStylableElement(elt); + float lh; + if (p == null) { + lh = 1.2f * engine.getCSSContext().getMediumFontSize(); + } else { + Value cs = engine.getComputedStyle(p, null, lhidx); + lh = lengthValue(cs); + } + return new FloatValue(CSSUnit.CSS_NUMBER, lh * scale); + case CSSUnit.CSS_REM: + sm.putRootFontSizeRelative(idx, true); + scale = lengthValue(value); + return rootRelative(elt, engine, idx, scale); + case CSSUnit.CSS_REX: + sm.putRootFontSizeRelative(idx, true); + scale = lengthValue(value) * 0.5f; + return rootRelative(elt, engine, idx, scale); + case CSSUnit.CSS_RLH: + sm.putLineHeightRelative(idx, true); + scale = lengthValue(value); + lhidx = engine.getLineHeightIndex(); + CSSStylableElement root = (CSSStylableElement) elt.getOwnerDocument().getDocumentElement(); + if (elt == root) { + lh = 1.2f * engine.getCSSContext().getMediumFontSize(); + } else { + Value cs = engine.getComputedStyle(root, null, lhidx); + lh = lengthValue(cs); + } + return new FloatValue(CSSUnit.CSS_NUMBER, lh * scale); + case CSSUnit.CSS_VW: + sm.putViewportRelative(idx, true); + v = lengthValue(value); + return new FloatValue(CSSUnit.CSS_NUMBER, + v * engine.getCSSContext().getViewport(elt).getWidth() * 0.01f); + case CSSUnit.CSS_VH: + sm.putViewportRelative(idx, true); + v = lengthValue(value); + return new FloatValue(CSSUnit.CSS_NUMBER, + v * engine.getCSSContext().getViewport(elt).getHeight() * 0.01f); + case CSSUnit.CSS_VMIN: + sm.putViewportRelative(idx, true); + v = lengthValue(value); + Viewport vp = engine.getCSSContext().getViewport(elt); + float w = vp.getWidth(); + float h = vp.getHeight(); + float min = Math.min(w, h); + return new FloatValue(CSSUnit.CSS_NUMBER, v * min * 0.01f); + case CSSUnit.CSS_VMAX: + sm.putViewportRelative(idx, true); + v = lengthValue(value); + vp = engine.getCSSContext().getViewport(elt); + w = vp.getWidth(); + h = vp.getHeight(); + float max = Math.max(w, h); + return new FloatValue(CSSUnit.CSS_NUMBER, v * max * 0.01f); + default: + // Maybe it is one of the new absolute length units + try { + return new FloatValue(CSSUnit.CSS_NUMBER, + NumberValue.floatValueConversion(value.getFloatValue(), value.getCSSUnit(), + CSSUnit.CSS_MM) / engine.getCSSContext().getPixelUnitToMillimeter()); + } catch (DOMException e) { + } + } } if (value.isIdentifier(CSSConstants.CSS_LARGER_VALUE)) { @@ -251,8 +292,7 @@ public Value computeValue(CSSStylableElement elt, String pseudo, CSSEngine engin if (doParentRelative) { sm.putParentRelative(idx, true); - CSSStylableElement p; - p = CSSEngine.getParentCSSStylableElement(elt); + CSSStylableElement p = CSSEngine.getParentCSSStylableElement(elt); float fs; if (p == null) { CSSContext ctx = engine.getCSSContext(); diff --git a/echosvg-css/src/main/java/io/sf/carte/echosvg/css/engine/value/svg/GlyphOrientationManager.java b/echosvg-css/src/main/java/io/sf/carte/echosvg/css/engine/value/svg/GlyphOrientationManager.java index efaa647a9..817a69488 100644 --- a/echosvg-css/src/main/java/io/sf/carte/echosvg/css/engine/value/svg/GlyphOrientationManager.java +++ b/echosvg-css/src/main/java/io/sf/carte/echosvg/css/engine/value/svg/GlyphOrientationManager.java @@ -22,6 +22,7 @@ import org.w3c.dom.DOMException; import io.sf.carte.doc.style.css.nsac.LexicalUnit; +import io.sf.carte.doc.style.css.property.NumberValue; import io.sf.carte.echosvg.css.engine.CSSEngine; import io.sf.carte.echosvg.css.engine.value.AbstractValueManager; import io.sf.carte.echosvg.css.engine.value.FloatValue; @@ -121,8 +122,10 @@ public Value createFloatValue(short type, float floatValue) throws DOMException case CSSUnit.CSS_GRAD: case CSSUnit.CSS_RAD: return new FloatValue(type, floatValue); + default: + float f = NumberValue.floatValueConversion(floatValue, type, CSSUnit.CSS_DEG); + return new FloatValue(CSSUnit.CSS_DEG, f); } - throw createInvalidFloatValueDOMException(floatValue); } } diff --git a/echosvg-css/src/main/java/io/sf/carte/echosvg/css/engine/value/svg12/LineHeightManager.java b/echosvg-css/src/main/java/io/sf/carte/echosvg/css/engine/value/svg12/LineHeightManager.java index 0b17a6ca8..1e1061361 100644 --- a/echosvg-css/src/main/java/io/sf/carte/echosvg/css/engine/value/svg12/LineHeightManager.java +++ b/echosvg-css/src/main/java/io/sf/carte/echosvg/css/engine/value/svg12/LineHeightManager.java @@ -148,6 +148,29 @@ public Value computeValue(CSSStylableElement elt, String pseudo, CSSEngine engin return new FloatValue(CSSUnit.CSS_NUMBER, v * fs * 0.01f); } + case CSSUnit.CSS_LH: + float lh; + float v = value.getFloatValue(); + CSSStylableElement p = CSSEngine.getParentCSSStylableElement(elt); + if (p != null) { + int lhidx = engine.getLineHeightIndex(); + lh = engine.getComputedStyle(p, null, lhidx).getFloatValue(); + } else { + lh = 1.2f * engine.getCSSContext().getMediumFontSize(); + } + return new FloatValue(CSSUnit.CSS_NUMBER, v * lh); + + case CSSUnit.CSS_RLH: + v = value.getFloatValue(); + CSSStylableElement root = (CSSStylableElement) elt.getOwnerDocument().getDocumentElement(); + if (root != elt) { + int lhidx = engine.getLineHeightIndex(); + lh = engine.getComputedStyle(root, null, lhidx).getFloatValue(); + } else { + lh = 1.2f * engine.getCSSContext().getMediumFontSize(); + } + return new FloatValue(CSSUnit.CSS_NUMBER, v * lh); + default: return super.computeValue(elt, pseudo, engine, idx, sm, value); } diff --git a/echosvg-test/src/test/java/io/sf/carte/echosvg/test/svg/AbstractSamplesRendering.java b/echosvg-test/src/test/java/io/sf/carte/echosvg/test/svg/AbstractSamplesRendering.java index b11df6617..9ce96b131 100644 --- a/echosvg-test/src/test/java/io/sf/carte/echosvg/test/svg/AbstractSamplesRendering.java +++ b/echosvg-test/src/test/java/io/sf/carte/echosvg/test/svg/AbstractSamplesRendering.java @@ -38,6 +38,8 @@ public class AbstractSamplesRendering { static final String BROWSER_MEDIA = "screen"; + static final String PRINT_MEDIA = "print"; + /** * To test the tEXt chunk. */ @@ -326,7 +328,7 @@ void testXHTMLErrIgnore(String file, String media, int expectedErrorCount) * @throws IOException if an I/O error occurs. */ void testHTML(String file) throws TranscoderException, IOException { - testHTML(file, null); + testHTML(file, null, null); } /** @@ -337,13 +339,15 @@ void testHTML(String file) throws TranscoderException, IOException { * reference image. *

* - * @param file the HTML file to test. - * @param the selector that locates the desired SVG element. + * @param file the HTML file to test. + * @param the selector that locates the desired SVG element. + * @param media the media to test, or {@code null} if default media. * @throws TranscoderException * @throws IOException if an I/O error occurs. */ - void testHTML(String file, String selector) throws TranscoderException, IOException { + void testHTML(String file, String selector, String media) throws TranscoderException, IOException { RenderingTest runner = new HTMLRenderingAccuracyTest(selector); + runner.setMedia(media); runner.setFile(file); runner.runTest(getBelowThresholdAllowed(), getOverThresholdAllowed()); } diff --git a/echosvg-test/src/test/java/io/sf/carte/echosvg/test/svg/SamplesSpecRenderingTest.java b/echosvg-test/src/test/java/io/sf/carte/echosvg/test/svg/SamplesSpecRenderingTest.java index 547b52b69..6e481f6fb 100644 --- a/echosvg-test/src/test/java/io/sf/carte/echosvg/test/svg/SamplesSpecRenderingTest.java +++ b/echosvg-test/src/test/java/io/sf/carte/echosvg/test/svg/SamplesSpecRenderingTest.java @@ -763,17 +763,22 @@ public void testUserSheet() throws TranscoderException, IOException { @Test public void testHTMLEmbed() throws TranscoderException, IOException { - testHTML("samples/tests/spec/styling/css2.html"); + testHTML("samples/tests/spec/styling/css3.html"); + } + + @Test + public void testHTMLEmbedPrint() throws TranscoderException, IOException { + testHTML("samples/tests/spec/styling/css3.html", null, PRINT_MEDIA); } @Test public void testHTMLEmbedSelector() throws TranscoderException, IOException { - testHTML("samples/tests/spec/styling/css2.html", "#theSVG"); + testHTML("samples/tests/spec/styling/css3.html", "#theSVG", null); } @Test public void testXHTMLEmbed() throws TranscoderException, IOException { - testXHTML("samples/tests/spec/styling/css2.xhtml"); + testXHTML("samples/tests/spec/styling/css3.xhtml"); } @Test diff --git a/samples/tests/spec/styling/css2.html b/samples/tests/spec/styling/css3.html similarity index 96% rename from samples/tests/spec/styling/css2.html rename to samples/tests/spec/styling/css3.html index f7685cfeb..5a0b8b7ee 100644 --- a/samples/tests/spec/styling/css2.html +++ b/samples/tests/spec/styling/css3.html @@ -38,7 +38,7 @@