summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMoonchild <moonchild@palemoon.org>2021-06-12 01:12:39 +0000
committerMoonchild <moonchild@palemoon.org>2021-06-12 01:12:39 +0000
commitc337c1496b4cdcdab3b3c52a9ad8c627b52e06a1 (patch)
tree81a4e8b9065685ce81c621eb5c4c75d7339806a1
parent7f6f1c664d19e0dedbbd92dc7694561121f26edf (diff)
downloaduxp-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.cpp8
-rw-r--r--layout/style/nsCSSPropList.h2
-rw-r--r--layout/style/nsRuleNode.cpp111
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,