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)
This commit is contained in:
Moonchild
2021-06-12 01:12:39 +00:00
committed by roytam1
parent 4bcb79066b
commit 15a322effa
3 changed files with 120 additions and 1 deletions
+8
View File
@@ -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;
}
+1 -1
View File
@@ -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)
+111
View File
@@ -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,