diff --git a/layout/base/nsStyleConsts.h b/layout/base/nsStyleConsts.h index eecc305d707..14a45d11747 100644 --- a/layout/base/nsStyleConsts.h +++ b/layout/base/nsStyleConsts.h @@ -873,6 +873,9 @@ static inline mozilla::css::Side operator++(mozilla::css::Side& side, int) { #define NS_STYLE_STROKE_LINEJOIN_ROUND 1 #define NS_STYLE_STROKE_LINEJOIN_BEVEL 2 +// stroke-dasharray, stroke-dashoffset, stroke-width +#define NS_STYLE_STROKE_PROP_OBJECTVALUE 0 + // text-anchor #define NS_STYLE_TEXT_ANCHOR_START 0 #define NS_STYLE_TEXT_ANCHOR_MIDDLE 1 diff --git a/layout/style/nsCSSKeywordList.h b/layout/style/nsCSSKeywordList.h index a7efcb7884e..ea67b9f24f7 100644 --- a/layout/style/nsCSSKeywordList.h +++ b/layout/style/nsCSSKeywordList.h @@ -134,6 +134,7 @@ CSS_KEY(-moz-objectfill, _moz_objectfill) CSS_KEY(-moz-objectfillopacity, _moz_objectfillopacity) CSS_KEY(-moz-objectstroke, _moz_objectstroke) CSS_KEY(-moz-objectstrokeopacity, _moz_objectstrokeopacity) +CSS_KEY(-moz-objectvalue, _moz_objectvalue) CSS_KEY(-moz-oddtreerow, _moz_oddtreerow) CSS_KEY(-moz-oriya, _moz_oriya) CSS_KEY(-moz-persian, _moz_persian) diff --git a/layout/style/nsCSSParser.cpp b/layout/style/nsCSSParser.cpp index e81c2ceab11..11b6a789608 100644 --- a/layout/style/nsCSSParser.cpp +++ b/layout/style/nsCSSParser.cpp @@ -9849,7 +9849,8 @@ bool CSSParserImpl::ParseDasharray() { nsCSSValue value; - if (ParseVariant(value, VARIANT_INHERIT | VARIANT_NONE, nullptr)) { + if (ParseVariant(value, VARIANT_HK | VARIANT_NONE, + nsCSSProps::kStrokeObjectValueKTable)) { // 'inherit', 'initial', and 'none' are only allowed on their own if (!ExpectEndProperty()) { return false; diff --git a/layout/style/nsCSSPropList.h b/layout/style/nsCSSPropList.h index 066fe62d561..9f8dcfa172c 100644 --- a/layout/style/nsCSSPropList.h +++ b/layout/style/nsCSSPropList.h @@ -3262,7 +3262,7 @@ CSS_PROP_SVG( // NOTE: Internal values have range restrictions. "", 0, - nullptr, + kStrokeObjectValueKTable, CSS_PROP_NO_OFFSET, /* property stored in 2 separate members */ eStyleAnimType_Custom) CSS_PROP_SVG( @@ -3271,8 +3271,8 @@ CSS_PROP_SVG( StrokeDashoffset, CSS_PROPERTY_PARSE_VALUE, "", - VARIANT_HLPN, - nullptr, + VARIANT_HLPN | VARIANT_KEYWORD, + kStrokeObjectValueKTable, offsetof(nsStyleSVG, mStrokeDashoffset), eStyleAnimType_Coord) CSS_PROP_SVG( @@ -3323,8 +3323,8 @@ CSS_PROP_SVG( CSS_PROPERTY_PARSE_VALUE | CSS_PROPERTY_VALUE_NONNEGATIVE, "", - VARIANT_HLPN, - nullptr, + VARIANT_HLPN | VARIANT_KEYWORD, + kStrokeObjectValueKTable, offsetof(nsStyleSVG, mStrokeWidth), eStyleAnimType_Coord) CSS_PROP_SVG( diff --git a/layout/style/nsCSSProps.cpp b/layout/style/nsCSSProps.cpp index 81104e55eb9..320cb06f318 100644 --- a/layout/style/nsCSSProps.cpp +++ b/layout/style/nsCSSProps.cpp @@ -1581,6 +1581,13 @@ const int32_t nsCSSProps::kStrokeLinejoinKTable[] = { eCSSKeyword_UNKNOWN, -1 }; +// Lookup table to store the sole objectValue keyword to let SVG glyphs inherit +// certain stroke-* properties from the outer text object +const int32_t nsCSSProps::kStrokeObjectValueKTable[] = { + eCSSKeyword__moz_objectvalue, NS_STYLE_STROKE_PROP_OBJECTVALUE, + eCSSKeyword_UNKNOWN, -1 +}; + const int32_t nsCSSProps::kTextAnchorKTable[] = { eCSSKeyword_start, NS_STYLE_TEXT_ANCHOR_START, eCSSKeyword_middle, NS_STYLE_TEXT_ANCHOR_MIDDLE, diff --git a/layout/style/nsCSSProps.h b/layout/style/nsCSSProps.h index b054e374072..3e669a636a5 100644 --- a/layout/style/nsCSSProps.h +++ b/layout/style/nsCSSProps.h @@ -355,6 +355,7 @@ public: static const int32_t kShapeRenderingKTable[]; static const int32_t kStrokeLinecapKTable[]; static const int32_t kStrokeLinejoinKTable[]; + static const int32_t kStrokeObjectValueKTable[]; static const int32_t kVectorEffectKTable[]; static const int32_t kTextAnchorKTable[]; static const int32_t kTextRenderingKTable[]; diff --git a/layout/style/nsRuleNode.cpp b/layout/style/nsRuleNode.cpp index fa53baa6751..046b095a0a2 100644 --- a/layout/style/nsRuleNode.cpp +++ b/layout/style/nsRuleNode.cpp @@ -7198,6 +7198,18 @@ SetSVGOpacity(const nsCSSValue& aValue, } } +template +static bool +SetTextObjectValue(const nsCSSValue& aValue, FieldT& aField, T aFallbackValue) +{ + if (aValue.GetUnit() != eCSSUnit_Enumerated || + aValue.GetIntValue() != NS_STYLE_STROKE_PROP_OBJECTVALUE) { + return false; + } + aField = aFallbackValue; + return true; +} + const void* nsRuleNode::ComputeSVGData(void* aStartStruct, const nsRuleData* aRuleData, @@ -7297,7 +7309,7 @@ nsRuleNode::ComputeSVGData(void* aStartStruct, parentSVG->mStroke, mPresContext, aContext, svg->mStroke, eStyleSVGPaintType_None, canStoreInRuleTree); - // stroke-dasharray: , none, inherit + // stroke-dasharray: , none, inherit, -moz-objectValue const nsCSSValue* strokeDasharrayValue = aRuleData->ValueForStrokeDasharray(); switch (strokeDasharrayValue->GetUnit()) { case eCSSUnit_Null: @@ -7305,6 +7317,7 @@ nsRuleNode::ComputeSVGData(void* aStartStruct, case eCSSUnit_Inherit: canStoreInRuleTree = false; + svg->mStrokeDasharrayFromObject = parentSVG->mStrokeDasharrayFromObject; // only do the copy if weren't already set up by the copy constructor // FIXME Bug 389408: This is broken when aStartStruct is non-null! if (!svg->mStrokeDasharray) { @@ -7321,8 +7334,19 @@ nsRuleNode::ComputeSVGData(void* aStartStruct, } break; + case eCSSUnit_Enumerated: + NS_ABORT_IF_FALSE(strokeDasharrayValue->GetIntValue() == + NS_STYLE_STROKE_PROP_OBJECTVALUE, + "Unknown keyword for stroke-dasharray"); + svg->mStrokeDasharrayFromObject = true; + delete [] svg->mStrokeDasharray; + svg->mStrokeDasharray = nullptr; + svg->mStrokeDasharrayLength = 0; + break; + case eCSSUnit_Initial: case eCSSUnit_None: + svg->mStrokeDasharrayFromObject = false; delete [] svg->mStrokeDasharray; svg->mStrokeDasharray = nullptr; svg->mStrokeDasharrayLength = 0; @@ -7330,6 +7354,7 @@ nsRuleNode::ComputeSVGData(void* aStartStruct, case eCSSUnit_List: case eCSSUnit_ListDep: { + svg->mStrokeDasharrayFromObject = false; delete [] svg->mStrokeDasharray; svg->mStrokeDasharray = nullptr; svg->mStrokeDasharrayLength = 0; @@ -7362,10 +7387,19 @@ nsRuleNode::ComputeSVGData(void* aStartStruct, } // stroke-dashoffset: , inherit - SetCoord(*aRuleData->ValueForStrokeDashoffset(), - svg->mStrokeDashoffset, parentSVG->mStrokeDashoffset, - SETCOORD_LPH | SETCOORD_FACTOR | SETCOORD_INITIAL_ZERO, - aContext, mPresContext, canStoreInRuleTree); + const nsCSSValue *strokeDashoffsetValue = + aRuleData->ValueForStrokeDashoffset(); + svg->mStrokeDashoffsetFromObject = + strokeDashoffsetValue->GetUnit() == eCSSUnit_Enumerated && + strokeDashoffsetValue->GetIntValue() == NS_STYLE_STROKE_PROP_OBJECTVALUE; + if (svg->mStrokeDashoffsetFromObject) { + svg->mStrokeDashoffset.SetIntValue(0, eStyleUnit_Integer); + } else { + SetCoord(*aRuleData->ValueForStrokeDashoffset(), + svg->mStrokeDashoffset, parentSVG->mStrokeDashoffset, + SETCOORD_LPH | SETCOORD_FACTOR | SETCOORD_INITIAL_ZERO, + aContext, mPresContext, canStoreInRuleTree); + } // stroke-linecap: enum, inherit, initial SetDiscrete(*aRuleData->ValueForStrokeLinecap(), @@ -7394,9 +7428,22 @@ nsRuleNode::ComputeSVGData(void* aStartStruct, // stroke-width: const nsCSSValue* strokeWidthValue = aRuleData->ValueForStrokeWidth(); - if (eCSSUnit_Initial == strokeWidthValue->GetUnit()) { + switch (strokeWidthValue->GetUnit()) { + case eCSSUnit_Enumerated: + NS_ABORT_IF_FALSE(strokeWidthValue->GetIntValue() == + NS_STYLE_STROKE_PROP_OBJECTVALUE, + "Unrecognized keyword for stroke-width"); + svg->mStrokeWidthFromObject = true; svg->mStrokeWidth.SetCoordValue(nsPresContext::CSSPixelsToAppUnits(1)); - } else { + break; + + case eCSSUnit_Initial: + svg->mStrokeWidthFromObject = false; + svg->mStrokeWidth.SetCoordValue(nsPresContext::CSSPixelsToAppUnits(1)); + break; + + default: + svg->mStrokeWidthFromObject = false; SetCoord(*strokeWidthValue, svg->mStrokeWidth, parentSVG->mStrokeWidth, SETCOORD_LPH | SETCOORD_FACTOR, diff --git a/layout/style/nsStyleStruct.cpp b/layout/style/nsStyleStruct.cpp index a3adacd8a4b..14300de452f 100644 --- a/layout/style/nsStyleStruct.cpp +++ b/layout/style/nsStyleStruct.cpp @@ -868,6 +868,9 @@ nsStyleSVG::nsStyleSVG() mTextRendering = NS_STYLE_TEXT_RENDERING_AUTO; mFillOpacitySource = eStyleSVGOpacitySource_Normal; mStrokeOpacitySource = eStyleSVGOpacitySource_Normal; + mStrokeDasharrayFromObject = false; + mStrokeDashoffsetFromObject = false; + mStrokeWidthFromObject = false; } nsStyleSVG::~nsStyleSVG() @@ -918,6 +921,9 @@ nsStyleSVG::nsStyleSVG(const nsStyleSVG& aSource) mTextRendering = aSource.mTextRendering; mFillOpacitySource = aSource.mFillOpacitySource; mStrokeOpacitySource = aSource.mStrokeOpacitySource; + mStrokeDasharrayFromObject = aSource.mStrokeDasharrayFromObject; + mStrokeDashoffsetFromObject = aSource.mStrokeDashoffsetFromObject; + mStrokeWidthFromObject = aSource.mStrokeWidthFromObject; } static bool PaintURIChanged(const nsStyleSVGPaint& aPaint1, @@ -978,7 +984,10 @@ nsChangeHint nsStyleSVG::CalcDifference(const nsStyleSVG& aOther) const mStrokeLinejoin != aOther.mStrokeLinejoin || mTextAnchor != aOther.mTextAnchor || mFillOpacitySource != aOther.mFillOpacitySource || - mStrokeOpacitySource != aOther.mStrokeOpacitySource) { + mStrokeOpacitySource != aOther.mStrokeOpacitySource || + mStrokeDasharrayFromObject != aOther.mStrokeDasharrayFromObject || + mStrokeDashoffsetFromObject != aOther.mStrokeDashoffsetFromObject || + mStrokeWidthFromObject != aOther.mStrokeWidthFromObject) { NS_UpdateHint(hint, nsChangeHint_RepaintFrame); return hint; } diff --git a/layout/style/nsStyleStruct.h b/layout/style/nsStyleStruct.h index e926113e418..0f9e9ac3081 100644 --- a/layout/style/nsStyleStruct.h +++ b/layout/style/nsStyleStruct.h @@ -2243,6 +2243,11 @@ struct nsStyleSVG { // text object nsStyleSVGOpacitySource mFillOpacitySource : 2; nsStyleSVGOpacitySource mStrokeOpacitySource : 2; + + // SVG glyph outer object inheritance for other properties + bool mStrokeDasharrayFromObject : 1; + bool mStrokeDashoffsetFromObject : 1; + bool mStrokeWidthFromObject : 1; }; struct nsStyleSVGReset { diff --git a/layout/style/test/property_database.js b/layout/style/test/property_database.js index 6eff5b2b1a4..695036a8fcc 100644 --- a/layout/style/test/property_database.js +++ b/layout/style/test/property_database.js @@ -3766,7 +3766,7 @@ var gCSSProperties = { domProp: "strokeDasharray", inherited: true, type: CSS_TYPE_LONGHAND, - initial_values: [ "none" ], + initial_values: [ "none", "-moz-objectValue" ], other_values: [ "5px,3px,2px", "5px 3px 2px", " 5px ,3px , 2px ", "1px", "5%", "3em" ], invalid_values: [ "-5px,3px,2px", "5px,3px,-2px" ] }, @@ -3774,7 +3774,7 @@ var gCSSProperties = { domProp: "strokeDashoffset", inherited: true, type: CSS_TYPE_LONGHAND, - initial_values: [ "0", "-0px", "0em" ], + initial_values: [ "0", "-0px", "0em", "-moz-objectValue" ], other_values: [ "3px", "3%", "1em" ], invalid_values: [] }, @@ -3814,7 +3814,7 @@ var gCSSProperties = { domProp: "strokeWidth", inherited: true, type: CSS_TYPE_LONGHAND, - initial_values: [ "1px" ], + initial_values: [ "1px", "-moz-objectValue" ], other_values: [ "0", "0px", "-0em", "17px", "0.2em" ], invalid_values: [ "-0.1px", "-3px" ] }, diff --git a/layout/style/test/test_value_computation.html b/layout/style/test/test_value_computation.html index 318841bfe76..379d274d202 100644 --- a/layout/style/test/test_value_computation.html +++ b/layout/style/test/test_value_computation.html @@ -45,7 +45,7 @@ var gBadComputed = { // This is the only SVG-length property (i.e., length allowing // unitless lengths) whose initial value is zero. - "stroke-dashoffset": [ "0" ], + "stroke-dashoffset": [ "0", "-moz-objectValue" ], }; var gBadComputedNoFrame = {