# HG changeset patch # User Boris Chiou Bug 1248340 - Part 10: Add a flag for allowing or not to use StepMiddle in nsTimingFunction There are two possible places to add the flag: 1. When parsing 2. When computing the style Google Chromium uses a flag in the parsing phase to check if it should support step-middle, but I think it's not easy to add the flag (or a new function argument/data member) in nsCSSParser because our parser is complicated and I think changing the APIs of nsCSSParser is not a good idea. We have to pass the flag through a lot of function calls if it is not a data member of nsCSSParser, and using this flag as a data member of it is not intuitive. Therefore, I think we could add this flag in the function argument of nsRuleNode::ComputeTimingFunction and the constructors of nsTimingFunction. Use nsTimingFunction::Type::Ease if step-middle shouldn't be supported. diff --git a/layout/style/nsRuleNode.cpp b/layout/style/nsRuleNode.cpp index dde7419..833ea9d 100644 --- a/layout/style/nsRuleNode.cpp +++ b/layout/style/nsRuleNode.cpp @@ -5045,21 +5045,22 @@ CountTransitionProps(const TransitionPropInfo* aInfo, numTransitions = data.num; } return numTransitions; } /* static */ void nsRuleNode::ComputeTimingFunction(const nsCSSValue& aValue, - nsTimingFunction& aResult) + nsTimingFunction& aResult, + bool aAllowStepMiddle) { switch (aValue.GetUnit()) { case eCSSUnit_Enumerated: - aResult = nsTimingFunction(aValue.GetIntValue()); + aResult = nsTimingFunction(aValue.GetIntValue(), aAllowStepMiddle); break; case eCSSUnit_Cubic_Bezier: { nsCSSValue::Array* array = aValue.GetArrayValue(); NS_ASSERTION(array && array->Count() == 4, "Need 4 control points"); aResult = nsTimingFunction(array->Item(0).GetFloatValue(), array->Item(1).GetFloatValue(), @@ -5083,17 +5084,18 @@ nsRuleNode::ComputeTimingFunction(const nsCSSValue& aValue, NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_END || array->Item(1).GetIntValue() == -1), "unexpected second value"); nsTimingFunction::Type type = nsTimingFunction::GetStepFunctionType(array->Item(1).GetIntValue()); aResult = nsTimingFunction(type, array->Item(0).GetIntValue(), array->Item(1).GetIntValue() == -1 ? nsTimingFunction::Keyword::Implicit : - nsTimingFunction::Keyword::Explicit); + nsTimingFunction::Keyword::Explicit, + aAllowStepMiddle); } break; default: NS_NOTREACHED("Invalid transition property unit"); } } static uint8_t diff --git a/layout/style/nsRuleNode.h b/layout/style/nsRuleNode.h index f5298d8..8e54d8b 100644 --- a/layout/style/nsRuleNode.h +++ b/layout/style/nsRuleNode.h @@ -1067,17 +1067,18 @@ public: static bool ComputeColor(const nsCSSValue& aValue, nsPresContext* aPresContext, nsStyleContext* aStyleContext, nscolor& aResult); static bool ParentHasPseudoElementData(nsStyleContext* aContext); static void ComputeTimingFunction(const nsCSSValue& aValue, - nsTimingFunction& aResult); + nsTimingFunction& aResult, + bool aAllowStepMiddle = false); private: #ifdef DEBUG // non-inline helper function to allow assertions without incomplete // type errors bool ContextHasCachedData(nsStyleContext* aContext, nsStyleStructID aSID); #endif diff --git a/layout/style/nsStyleStruct.cpp b/layout/style/nsStyleStruct.cpp index cea414c..e36fc00 100644 --- a/layout/style/nsStyleStruct.cpp +++ b/layout/style/nsStyleStruct.cpp @@ -2672,29 +2672,35 @@ nsTimingFunction::GetStepFunctionType(int aType) return Type::StepMiddle; case NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_END: default: return Type::StepEnd; } } void -nsTimingFunction::AssignFromKeyword(int32_t aTimingFunctionType) +nsTimingFunction::AssignFromKeyword(int32_t aTimingFunctionType, + bool aAllowStepMiddle) { switch (aTimingFunctionType) { case NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_START: mType = Type::StepStart; mStepSyntax = StepSyntax::Keyword; mSteps = 1; return; case NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_MIDDLE: - mType = Type::StepMiddle; - mStepSyntax = StepSyntax::Keyword; - mSteps = 1; - return; + if (aAllowStepMiddle) { + mType = Type::StepMiddle; + mStepSyntax = StepSyntax::Keyword; + mSteps = 1; + return; + } else { + mType = Type::Ease; + break; + } default: MOZ_FALLTHROUGH_ASSERT("aTimingFunctionType must be a keyword value"); case NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_END: mType = Type::StepEnd; mStepSyntax = StepSyntax::Keyword; mSteps = 1; return; case NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE: diff --git a/layout/style/nsStyleStruct.h b/layout/style/nsStyleStruct.h index b03a5ac..0860735 100644 --- a/layout/style/nsStyleStruct.h +++ b/layout/style/nsStyleStruct.h @@ -2117,41 +2117,52 @@ struct nsTimingFunction static bool IsSplineType(Type aType) { return aType != Type::StepStart && aType != Type::StepMiddle && aType != Type::StepEnd; } explicit nsTimingFunction(int32_t aTimingFunctionType - = NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE) + = NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE, + bool aAllowStepMiddle = false) { - AssignFromKeyword(aTimingFunctionType); + AssignFromKeyword(aTimingFunctionType, aAllowStepMiddle); } nsTimingFunction(float x1, float y1, float x2, float y2) : mType(Type::CubicBezier) { mFunc.mX1 = x1; mFunc.mY1 = y1; mFunc.mX2 = x2; mFunc.mY2 = y2; } // Step timing func format: steps([, [ start | middle | end ] ]?). // If the second parameter is omitted, it is given the value end (implicitly). enum class Keyword { Implicit, Explicit }; - nsTimingFunction(Type aType, uint32_t aSteps, Keyword aKeyword) + nsTimingFunction(Type aType, + uint32_t aSteps, + Keyword aKeyword, + bool aAllowStepMiddle = false) : mType(aType) { MOZ_ASSERT(mType == Type::StepStart || mType == Type::StepMiddle || mType == Type::StepEnd, "wrong type"); + + // Special case + if (mType == Type::StepMiddle && !aAllowStepMiddle) { + AssignFromKeyword(NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE, false); + return; + } + mSteps = aSteps; if (mType == Type::StepStart || mType == Type::StepMiddle) { MOZ_ASSERT(aKeyword == Keyword::Explicit, "only StepEnd can have an implicit keyword"); mStepSyntax = mType == Type::StepStart ? StepSyntax::FunctionalWithStartKeyword : StepSyntax::FunctionalWithMiddleKeyword; } else { @@ -2217,17 +2228,17 @@ struct nsTimingFunction bool operator!=(const nsTimingFunction& aOther) const { return !(*this == aOther); } bool HasSpline() const { return IsSplineType(mType); } private: - void AssignFromKeyword(int32_t aTimingFunctionType); + void AssignFromKeyword(int32_t aTimingFunctionType, bool aAllowStepMiddle); }; namespace mozilla { struct StyleTransition { StyleTransition() { /* leaves uninitialized; see also SetInitialValues */ } explicit StyleTransition(const StyleTransition& aCopy);