diff options
author | Moonchild <moonchild@palemoon.org> | 2021-06-12 01:12:39 +0000 |
---|---|---|
committer | Moonchild <moonchild@palemoon.org> | 2021-06-12 01:12:39 +0000 |
commit | c337c1496b4cdcdab3b3c52a9ad8c627b52e06a1 (patch) | |
tree | 81a4e8b9065685ce81c621eb5c4c75d7339806a1 | |
parent | 7f6f1c664d19e0dedbbd92dc7694561121f26edf (diff) | |
download | uxp-c337c1496b4cdcdab3b3c52a9ad8c627b52e06a1.tar.gz |
Issue #1781 - Part 1: support calc() in stroke-dashoffset CSS
This adds basic calc() support to stroke-dashoffset. It does not provide
CSS animation (yet, todo for part 2)
-rw-r--r-- | dom/svg/SVGContentUtils.cpp | 8 | ||||
-rw-r--r-- | layout/style/nsCSSPropList.h | 2 | ||||
-rw-r--r-- | layout/style/nsRuleNode.cpp | 111 |
3 files changed, 120 insertions, 1 deletions
diff --git a/dom/svg/SVGContentUtils.cpp b/dom/svg/SVGContentUtils.cpp index 7f372c9b42..21b98daba8 100644 --- a/dom/svg/SVGContentUtils.cpp +++ b/dom/svg/SVGContentUtils.cpp @@ -833,6 +833,14 @@ SVGContentUtils::CoordToFloat(nsSVGElement *aContent, SVGSVGElement* ctx = aContent->GetCtx(); return ctx ? aCoord.GetPercentValue() * ctx->GetLength(SVGContentUtils::XY) : 0.0f; } + case eStyleUnit_Calc: { + MOZ_ASSERT(aCoord.GetCalcValue(), "Invalid calc value"); + nsStyleCoord::Calc* calc = aCoord.GetCalcValue(); + SVGSVGElement* ctx = aContent->GetCtx(); + float len = nsPresContext::AppUnitsToFloatCSSPixels(calc->mLength); + return ctx ? len + calc->mPercent * ctx->GetLength(SVGContentUtils::XY) + : len; + } default: return 0.0f; } diff --git a/layout/style/nsCSSPropList.h b/layout/style/nsCSSPropList.h index e78dafcc5c..f0cab6b131 100644 --- a/layout/style/nsCSSPropList.h +++ b/layout/style/nsCSSPropList.h @@ -3816,7 +3816,7 @@ CSS_PROP_SVG( CSS_PROPERTY_PARSE_VALUE | CSS_PROPERTY_NUMBERS_ARE_PIXELS, "", - VARIANT_HLPN | VARIANT_OPENTYPE_SVG_KEYWORD, + VARIANT_HLPN | VARIANT_OPENTYPE_SVG_KEYWORD | VARIANT_CALC, kStrokeContextValueKTable, offsetof(nsStyleSVG, mStrokeDashoffset), eStyleAnimType_Coord) diff --git a/layout/style/nsRuleNode.cpp b/layout/style/nsRuleNode.cpp index 04715aa99a..74ba732885 100644 --- a/layout/style/nsRuleNode.cpp +++ b/layout/style/nsRuleNode.cpp @@ -4492,6 +4492,15 @@ struct LengthNumberCalcObj bool mIsNumber; }; +struct RealNumberComputedCalc +{ + // We use float for mLength, so it can support real numbers. + float mLength = 0.0f; + float mPercent = 0.0f; + bool mIsNumber = false; +}; + + struct LengthNumberCalcOps : public css::NumbersAlreadyNormalizedOps { typedef LengthNumberCalcObj result_type; @@ -4574,6 +4583,96 @@ struct LengthNumberCalcOps : public css::NumbersAlreadyNormalizedOps } }; +// This is like LengthNumberCalcOps, but then for real/float. +struct LengthPercentNumberCalcOps : public css::NumbersAlreadyNormalizedOps +{ + typedef RealNumberComputedCalc result_type; + + nsStyleContext* const mContext; + nsPresContext* const mPresContext; + RuleNodeCacheConditions& mConditions; + bool mHasPercent = false; + + LengthPercentNumberCalcOps(nsStyleContext* aContext, + nsPresContext* aPresContext, + RuleNodeCacheConditions& aConditions) + : mContext(aContext), + mPresContext(aPresContext), + mConditions(aConditions) { } + + result_type + MergeAdditive(nsCSSUnit aCalcFunction, + result_type aValue1, result_type aValue2) + { + MOZ_ASSERT(aValue1.mIsNumber == aValue2.mIsNumber); + MOZ_ASSERT(aCalcFunction == eCSSUnit_Calc_Plus || + aCalcFunction == eCSSUnit_Calc_Minus, + "unexpected unit"); + + result_type result; + result.mIsNumber = aValue1.mIsNumber; + if (aCalcFunction == eCSSUnit_Calc_Plus) { + result.mLength = aValue1.mLength + aValue2.mLength; + result.mPercent = aValue1.mPercent + aValue2.mPercent; + } else { + result.mLength = aValue2.mLength == NS_IEEEPositiveInfinity() ? + 0.0f : + aValue1.mLength - aValue2.mLength; + result.mPercent = aValue1.mPercent - aValue2.mPercent; + } + return result; + } + + result_type + MergeMultiplicativeL(nsCSSUnit aCalcFunction, + float aValue1, result_type aValue2) + { + MOZ_ASSERT(aCalcFunction == eCSSUnit_Calc_Times_L, + "unexpected unit"); + result_type result; + result.mLength = aValue1 * aValue2.mLength; + result.mPercent = aValue1 * aValue2.mPercent; + result.mIsNumber = aValue2.mIsNumber; + return result; + } + + result_type + MergeMultiplicativeR(nsCSSUnit aCalcFunction, + result_type aValue1, float aValue2) + { + MOZ_ASSERT(aCalcFunction == eCSSUnit_Calc_TimesR || + aCalcFunction == eCSSUnit_Divided, + "unexpected unit"); + result_type result; + if (aCalcFunction == eCSSUnit_Calc_Divided) { + aValue2 = 1.0f / aValue2; + } + result.mLength = aValue1.mLength * aValue2; + result.mPercent = aValue1.mPercent * aValue2; + result.mIsNumber = aValue1.mIsNumber; + return result; + } + + result_type + ComputeLeafValue(const nsCSSValue& aValue) + { + result_type result; + if (aValue.IsLengthUnit()) { + result.mLength = CalcLength(aValue, mContext, mPresContext, mConditions); + } else if (aValue.GetUnit() == eCSSUnit_Percent) { + result.mPercent = aValue.GetPercentValue(); + mHasPercent = true; + } else if (aValue.GetUnit() == eCSSUnit_Number) { + result.mLength = aValue.GetFloatValue(); + result.mIsNumber = true; + } else { + MOZ_ASSERT_UNREACHABLE("unexpected unit"); + result.mLength = CalcLength(aValue, mContext, mPresContext, mConditions); + } + return result; + } +}; + struct SetLineHeightCalcOps : public LengthNumberCalcOps { SetLineHeightCalcOps(nsStyleContext* aStyleContext, @@ -9626,6 +9725,18 @@ nsRuleNode::ComputeSVGData(void* aStartStruct, strokeDashoffsetValue->GetIntValue() == NS_STYLE_STROKE_PROP_CONTEXT_VALUE); if (svg->StrokeDashoffsetFromObject()) { svg->mStrokeDashoffset.SetCoordValue(0); + } else if (strokeDashoffsetValue->IsCalcUnit()) { + LengthPercentNumberCalcOps ops(aContext, mPresContext, conditions); + RealNumberComputedCalc obj = css::ComputeCalc(*strokeDashoffsetValue, ops); + if (obj.mIsNumber) { + svg->mStrokeDashoffset.SetFactorValue(obj.mLength); + } else { + nsStyleCoord::Calc* calcObj = new nsStyleCoord::Calc; + calcObj->mLength = NSToCoordRoundWithClamp(obj.mLength); + calcObj->mPercent = obj.mPercent; + calcObj->mHasPercent = ops.mHasPercent; + svg->mStrokeDashoffset.SetCalcValue(calcObj); + } } else { SetCoord(*aRuleData->ValueForStrokeDashoffset(), svg->mStrokeDashoffset, parentSVG->mStrokeDashoffset, |