diff --git a/layout/base/nsStyleConsts.h b/layout/base/nsStyleConsts.h index 0c12242259c..2214a9cdbe3 100644 --- a/layout/base/nsStyleConsts.h +++ b/layout/base/nsStyleConsts.h @@ -647,6 +647,8 @@ static inline mozilla::css::Side operator++(mozilla::css::Side& side, int) { #define NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE_IN 2 #define NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE_OUT 3 #define NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE_IN_OUT 4 +#define NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_START 5 +#define NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_END 6 // See nsStyleText // Note: these values pickup after the text-align values because there diff --git a/layout/style/nsCSSKeywordList.h b/layout/style/nsCSSKeywordList.h index 26883f26d60..4800dd69b2e 100644 --- a/layout/style/nsCSSKeywordList.h +++ b/layout/style/nsCSSKeywordList.h @@ -437,6 +437,8 @@ CSS_KEY(square, square) CSS_KEY(start, start) CSS_KEY(static, static) CSS_KEY(status-bar, status_bar) +CSS_KEY(step-end, step_end) +CSS_KEY(step-start, step_start) CSS_KEY(stretch, stretch) CSS_KEY(stretch-to-fit, stretch_to_fit) CSS_KEY(stroke, stroke) diff --git a/layout/style/nsCSSParser.cpp b/layout/style/nsCSSParser.cpp index 9bbfb91a25d..87f63d0c2e7 100644 --- a/layout/style/nsCSSParser.cpp +++ b/layout/style/nsCSSParser.cpp @@ -113,7 +113,7 @@ namespace css = mozilla::css; #define VARIANT_NORMAL 0x080000 // M #define VARIANT_SYSFONT 0x100000 // eCSSUnit_System_Font #define VARIANT_GRADIENT 0x200000 // eCSSUnit_Gradient -#define VARIANT_CUBIC_BEZIER 0x400000 // CSS transition timing function +#define VARIANT_TIMING_FUNCTION 0x400000 // cubic-bezier() and steps() #define VARIANT_ALL 0x800000 // #define VARIANT_IMAGE_RECT 0x01000000 // eCSSUnit_Function // This is an extra bit that says that a VARIANT_ANGLE allows unitless zero: @@ -154,7 +154,6 @@ namespace css = mozilla::css; #define VARIANT_HON (VARIANT_HN | VARIANT_NONE) #define VARIANT_HOS (VARIANT_INHERIT | VARIANT_NONE | VARIANT_STRING) #define VARIANT_LPN (VARIANT_LP | VARIANT_NUMBER) -#define VARIANT_TIMING_FUNCTION (VARIANT_KEYWORD | VARIANT_CUBIC_BEZIER) #define VARIANT_UK (VARIANT_URL | VARIANT_KEYWORD) #define VARIANT_UO (VARIANT_URL | VARIANT_NONE) #define VARIANT_ANGLE_OR_ZERO (VARIANT_ANGLE | VARIANT_ZERO_ANGLE) @@ -517,6 +516,7 @@ protected: PRBool ParseTransitionTimingFunctionValueComponent(float& aComponent, char aStop, PRBool aCheckRange); + PRBool ParseTransitionStepTimingFunctionValues(nsCSSValue& aValue); #ifdef MOZ_SVG PRBool ParsePaint(nsCSSProperty aPropID); @@ -4215,7 +4215,7 @@ CSSParserImpl::TranslateDimension(nsCSSValue& aValue, VARIANT_NORMAL | \ VARIANT_SYSFONT | \ VARIANT_GRADIENT | \ - VARIANT_CUBIC_BEZIER | \ + VARIANT_TIMING_FUNCTION | \ VARIANT_ALL | \ VARIANT_CALC @@ -4487,15 +4487,22 @@ CSSParserImpl::ParseVariant(nsCSSValue& aValue, } return PR_TRUE; } - if (((aVariantMask & VARIANT_CUBIC_BEZIER) != 0) && + if (((aVariantMask & VARIANT_TIMING_FUNCTION) != 0) && (eCSSToken_Function == tk->mType)) { - if (tk->mIdent.LowerCaseEqualsLiteral("cubic-bezier")) { + if (tk->mIdent.LowerCaseEqualsLiteral("cubic-bezier")) { if (!ParseTransitionTimingFunctionValues(aValue)) { SkipUntil(')'); return PR_FALSE; } return PR_TRUE; } + if (tk->mIdent.LowerCaseEqualsLiteral("steps")) { + if (!ParseTransitionStepTimingFunctionValues(aValue)) { + SkipUntil(')'); + return PR_FALSE; + } + return PR_TRUE; + } } if ((aVariantMask & VARIANT_CALC) && (eCSSToken_Function == tk->mType) && @@ -7956,6 +7963,48 @@ CSSParserImpl::ParseTransitionTimingFunctionValueComponent(float& aComponent, return PR_FALSE; } +PRBool +CSSParserImpl::ParseTransitionStepTimingFunctionValues(nsCSSValue& aValue) +{ + NS_ASSERTION(!mHavePushBack && + mToken.mType == eCSSToken_Function && + mToken.mIdent.LowerCaseEqualsLiteral("steps"), + "unexpected initial state"); + + nsRefPtr val = nsCSSValue::Array::Create(2); + + if (!ParsePositiveNonZeroVariant(val->Item(0), VARIANT_INTEGER, nsnull)) { + return PR_FALSE; + } + + PRInt32 type = NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_END; + if (ExpectSymbol(',', PR_TRUE)) { + if (!GetToken(PR_TRUE)) { + return PR_FALSE; + } + type = -1; + if (mToken.mType == eCSSToken_Ident) { + if (mToken.mIdent.LowerCaseEqualsLiteral("start")) { + type = NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_START; + } else if (mToken.mIdent.LowerCaseEqualsLiteral("end")) { + type = NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_END; + } + } + if (type == -1) { + UngetToken(); + return PR_FALSE; + } + } + val->Item(1).SetIntValue(type, eCSSUnit_Enumerated); + + if (!ExpectSymbol(')', PR_TRUE)) { + return PR_FALSE; + } + + aValue.SetArrayValue(val, eCSSUnit_Steps); + return PR_TRUE; +} + static nsCSSValueList* AppendValueToList(nsCSSValue& aContainer, nsCSSValueList* aTail, diff --git a/layout/style/nsCSSPropList.h b/layout/style/nsCSSPropList.h index ea83a05c5a2..fddeed2afee 100644 --- a/layout/style/nsCSSPropList.h +++ b/layout/style/nsCSSPropList.h @@ -2288,7 +2288,7 @@ CSS_PROP_DISPLAY( CSS_PROP_DOMPROP_PREFIXED(TransitionTimingFunction), CSS_PROPERTY_PARSE_VALUE_LIST | CSS_PROPERTY_VALUE_LIST_USES_COMMAS, - VARIANT_TIMING_FUNCTION, // used by list parsing + VARIANT_KEYWORD | VARIANT_TIMING_FUNCTION, // used by list parsing kTransitionTimingFunctionKTable, CSS_PROP_NO_OFFSET, eStyleAnimType_None) diff --git a/layout/style/nsCSSProps.cpp b/layout/style/nsCSSProps.cpp index 6e3de9da0a2..1ad926bfa57 100644 --- a/layout/style/nsCSSProps.cpp +++ b/layout/style/nsCSSProps.cpp @@ -1262,6 +1262,8 @@ const PRInt32 nsCSSProps::kTransitionTimingFunctionKTable[] = { eCSSKeyword_ease_in, NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE_IN, eCSSKeyword_ease_out, NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE_OUT, eCSSKeyword_ease_in_out, NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE_IN_OUT, + eCSSKeyword_step_start, NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_START, + eCSSKeyword_step_end, NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_END, eCSSKeyword_UNKNOWN,-1 }; diff --git a/layout/style/nsCSSValue.cpp b/layout/style/nsCSSValue.cpp index fc25fb68ceb..f0f6c104a9e 100644 --- a/layout/style/nsCSSValue.cpp +++ b/layout/style/nsCSSValue.cpp @@ -691,11 +691,12 @@ nsCSSValue::AppendToString(nsCSSProperty aProperty, nsAString& aResult) const nsStyleUtil::AppendEscapedCSSIdent(buffer, aResult); } } - else if (eCSSUnit_Array <= unit && unit <= eCSSUnit_Cubic_Bezier) { + else if (eCSSUnit_Array <= unit && unit <= eCSSUnit_Steps) { switch (unit) { case eCSSUnit_Counter: aResult.AppendLiteral("counter("); break; case eCSSUnit_Counters: aResult.AppendLiteral("counters("); break; case eCSSUnit_Cubic_Bezier: aResult.AppendLiteral("cubic-bezier("); break; + case eCSSUnit_Steps: aResult.AppendLiteral("steps("); break; default: break; } @@ -717,6 +718,21 @@ nsCSSValue::AppendToString(nsCSSProperty aProperty, nsAString& aResult) const else aResult.AppendLiteral(", "); } + if (unit == eCSSUnit_Steps && i == 1) { + NS_ABORT_IF_FALSE(array->Item(i).GetUnit() == eCSSUnit_Enumerated && + (array->Item(i).GetIntValue() == + NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_START || + array->Item(i).GetIntValue() == + NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_END), + "unexpected value"); + if (array->Item(i).GetIntValue() == + NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_START) { + aResult.AppendLiteral("start"); + } else { + aResult.AppendLiteral("end"); + } + continue; + } nsCSSProperty prop = ((eCSSUnit_Counter <= unit && unit <= eCSSUnit_Counters) && i == array->Count() - 1) @@ -981,6 +997,7 @@ nsCSSValue::AppendToString(nsCSSProperty aProperty, nsAString& aResult) const case eCSSUnit_Array: break; case eCSSUnit_Attr: case eCSSUnit_Cubic_Bezier: + case eCSSUnit_Steps: case eCSSUnit_Counter: case eCSSUnit_Counters: aResult.Append(PRUnichar(')')); break; case eCSSUnit_Local_Font: break; diff --git a/layout/style/nsCSSValue.h b/layout/style/nsCSSValue.h index e3c0d3adb70..d22a4b489b4 100644 --- a/layout/style/nsCSSValue.h +++ b/layout/style/nsCSSValue.h @@ -115,7 +115,8 @@ enum nsCSSUnit { eCSSUnit_Counter = 21, // (nsCSSValue::Array*) a counter(string,[string]) value eCSSUnit_Counters = 22, // (nsCSSValue::Array*) a counters(string,string[,string]) value eCSSUnit_Cubic_Bezier = 23, // (nsCSSValue::Array*) a list of float values - eCSSUnit_Function = 24, // (nsCSSValue::Array*) a function with + eCSSUnit_Steps = 24, // (nsCSSValue::Array*) a list of (integer, enumerated) + eCSSUnit_Function = 25, // (nsCSSValue::Array*) a function with // parameters. First elem of array is name, // the rest of the values are arguments. @@ -127,14 +128,14 @@ enum nsCSSUnit { // exists so we can distinguish calc(2em) from 2em as specified values // (but we drop this distinction for nsStyleCoord when we store // computed values). - eCSSUnit_Calc = 25, // (nsCSSValue::Array*) calc() value + eCSSUnit_Calc = 30, // (nsCSSValue::Array*) calc() value // Plus, Minus, Times_* and Divided have arrays with exactly 2 // elements. a + b + c + d is grouped as ((a + b) + c) + d - eCSSUnit_Calc_Plus = 26, // (nsCSSValue::Array*) + node within calc() - eCSSUnit_Calc_Minus = 27, // (nsCSSValue::Array*) - within calc - eCSSUnit_Calc_Times_L = 28, // (nsCSSValue::Array*) num * val within calc - eCSSUnit_Calc_Times_R = 29, // (nsCSSValue::Array*) val * num within calc - eCSSUnit_Calc_Divided = 30, // (nsCSSValue::Array*) / within calc + eCSSUnit_Calc_Plus = 31, // (nsCSSValue::Array*) + node within calc() + eCSSUnit_Calc_Minus = 32, // (nsCSSValue::Array*) - within calc + eCSSUnit_Calc_Times_L = 33, // (nsCSSValue::Array*) num * val within calc + eCSSUnit_Calc_Times_R = 34, // (nsCSSValue::Array*) val * num within calc + eCSSUnit_Calc_Divided = 35, // (nsCSSValue::Array*) / within calc eCSSUnit_URL = 40, // (nsCSSValue::URL*) value eCSSUnit_Image = 41, // (nsCSSValue::Image*) value diff --git a/layout/style/nsComputedDOMStyle.cpp b/layout/style/nsComputedDOMStyle.cpp index c83d1468405..702e2ada7c0 100644 --- a/layout/style/nsComputedDOMStyle.cpp +++ b/layout/style/nsComputedDOMStyle.cpp @@ -3882,6 +3882,35 @@ nsComputedDOMStyle::DoGetTransitionProperty() return valueList; } +void +nsComputedDOMStyle::AppendTimingFunction(nsDOMCSSValueList *aValueList, + const nsTimingFunction& aTimingFunction) +{ + nsROCSSPrimitiveValue* timingFunction = GetROCSSPrimitiveValue(); + aValueList->AppendCSSValue(timingFunction); + + if (aTimingFunction.mType == nsTimingFunction::Function) { + // set the value from the cubic-bezier control points + // (We could try to regenerate the keywords if we want.) + timingFunction->SetString( + nsPrintfCString(64, "cubic-bezier(%f, %f, %f, %f)", + aTimingFunction.mFunc.mX1, + aTimingFunction.mFunc.mY1, + aTimingFunction.mFunc.mX2, + aTimingFunction.mFunc.mY2)); + } else { + nsString tmp; + tmp.AppendLiteral("steps("); + tmp.AppendInt(aTimingFunction.mSteps); + if (aTimingFunction.mType == nsTimingFunction::StepStart) { + tmp.AppendLiteral(", start)"); + } else { + tmp.AppendLiteral(", end)"); + } + timingFunction->SetString(tmp); + } +} + nsIDOMCSSValue* nsComputedDOMStyle::DoGetTransitionTimingFunction() { @@ -3893,16 +3922,8 @@ nsComputedDOMStyle::DoGetTransitionTimingFunction() "first item must be explicit"); PRUint32 i = 0; do { - const nsTransition *transition = &display->mTransitions[i]; - nsROCSSPrimitiveValue* timingFunction = GetROCSSPrimitiveValue(); - valueList->AppendCSSValue(timingFunction); - - // set the value from the cubic-bezier control points - // (We could try to regenerate the keywords if we want.) - const nsTimingFunction& tf = transition->GetTimingFunction(); - timingFunction->SetString( - nsPrintfCString(64, "cubic-bezier(%f, %f, %f, %f)", - tf.mX1, tf.mY1, tf.mX2, tf.mY2)); + AppendTimingFunction(valueList, + display->mTransitions[i].GetTimingFunction()); } while (++i < display->mTransitionTimingFunctionCount); return valueList; diff --git a/layout/style/nsComputedDOMStyle.h b/layout/style/nsComputedDOMStyle.h index 6be79e04c18..0375049f751 100644 --- a/layout/style/nsComputedDOMStyle.h +++ b/layout/style/nsComputedDOMStyle.h @@ -168,6 +168,8 @@ private: void GetImageRectString(nsIURI* aURI, const nsStyleSides& aCropRect, nsString& aString); + void AppendTimingFunction(nsDOMCSSValueList *aValueList, + const nsTimingFunction& aTimingFunction); /* Properties queryable as CSSValues. * To avoid a name conflict with nsIDOM*CSS2Properties, these are all diff --git a/layout/style/nsRuleNode.cpp b/layout/style/nsRuleNode.cpp index e3ba8974626..9c888738e92 100644 --- a/layout/style/nsRuleNode.cpp +++ b/layout/style/nsRuleNode.cpp @@ -3838,6 +3838,28 @@ nsRuleNode::ComputeDisplayData(void* aStartStruct, array->Item(3).GetFloatValue())); } break; + case eCSSUnit_Steps: + { + nsCSSValue::Array* array = + timingFunction.list->mValue.GetArrayValue(); + NS_ASSERTION(array && array->Count() == 2, + "Need 2 items"); + NS_ASSERTION(array->Item(0).GetUnit() == eCSSUnit_Integer, + "unexpected first value"); + NS_ASSERTION(array->Item(1).GetUnit() == eCSSUnit_Enumerated && + (array->Item(1).GetIntValue() == + NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_START || + array->Item(1).GetIntValue() == + NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_END), + "unexpected second value"); + transition->SetTimingFunction( + nsTimingFunction(( + array->Item(1).GetIntValue() == + NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_END) + ? nsTimingFunction::StepEnd : nsTimingFunction::StepStart, + array->Item(0).GetIntValue())); + } + break; default: NS_NOTREACHED("Invalid transition property unit"); } diff --git a/layout/style/nsStyleStruct.cpp b/layout/style/nsStyleStruct.cpp index ab09478044c..20b7521dd52 100644 --- a/layout/style/nsStyleStruct.cpp +++ b/layout/style/nsStyleStruct.cpp @@ -1921,6 +1921,20 @@ nsStyleBackground::Layer::operator==(const Layer& aOther) const // void nsTimingFunction::AssignFromKeyword(PRInt32 aTimingFunctionType) { + switch (aTimingFunctionType) { + case NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_START: + mType = StepStart; + mSteps = 1; + return; + case NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_END: + mType = StepEnd; + mSteps = 1; + return; + default: + mType = Function; + break; + } + PR_STATIC_ASSERT(NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE == 0); PR_STATIC_ASSERT(NS_STYLE_TRANSITION_TIMING_FUNCTION_LINEAR == 1); PR_STATIC_ASSERT(NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE_IN == 2); @@ -1937,10 +1951,10 @@ void nsTimingFunction::AssignFromKeyword(PRInt32 aTimingFunctionType) NS_ABORT_IF_FALSE(0 <= aTimingFunctionType && aTimingFunctionType < 5, "keyword out of range"); - mX1 = timingFunctionValues[aTimingFunctionType][0]; - mY1 = timingFunctionValues[aTimingFunctionType][1]; - mX2 = timingFunctionValues[aTimingFunctionType][2]; - mY2 = timingFunctionValues[aTimingFunctionType][3]; + mFunc.mX1 = timingFunctionValues[aTimingFunctionType][0]; + mFunc.mY1 = timingFunctionValues[aTimingFunctionType][1]; + mFunc.mX2 = timingFunctionValues[aTimingFunctionType][2]; + mFunc.mY2 = timingFunctionValues[aTimingFunctionType][3]; } nsTransition::nsTransition(const nsTransition& aCopy) diff --git a/layout/style/nsStyleStruct.h b/layout/style/nsStyleStruct.h index 0625ee3668d..b08d8c92323 100644 --- a/layout/style/nsStyleStruct.h +++ b/layout/style/nsStyleStruct.h @@ -1309,6 +1309,8 @@ struct nsStyleVisibility { }; struct nsTimingFunction { + enum Type { Function, StepStart, StepEnd }; + explicit nsTimingFunction(PRInt32 aTimingFunctionType = NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE) { @@ -1316,26 +1318,60 @@ struct nsTimingFunction { } nsTimingFunction(float x1, float y1, float x2, float y2) - : mX1(x1) - , mY1(y1) - , mX2(x2) - , mY2(y2) - {} - - float mX1; - float mY1; - float mX2; - float mY2; - - PRBool operator==(const nsTimingFunction& aOther) const + : mType(Function) { - return !(*this != aOther); + mFunc.mX1 = x1; + mFunc.mY1 = y1; + mFunc.mX2 = x2; + mFunc.mY2 = y2; } - PRBool operator!=(const nsTimingFunction& aOther) const + nsTimingFunction(Type aType, PRUint32 aSteps) + : mType(aType) { - return mX1 != aOther.mX1 || mY1 != aOther.mY1 || - mX2 != aOther.mX2 || mY2 != aOther.mY2; + NS_ABORT_IF_FALSE(mType == StepStart || mType == StepEnd, "wrong type"); + mSteps = aSteps; + } + + nsTimingFunction(const nsTimingFunction& aOther) + : mType(aOther.mType) + { + if (mType == Function) { + mFunc.mX1 = aOther.mFunc.mX1; + mFunc.mY1 = aOther.mFunc.mY1; + mFunc.mX2 = aOther.mFunc.mX2; + mFunc.mY2 = aOther.mFunc.mY2; + } else { + mSteps = aOther.mSteps; + } + } + + Type mType; + union { + struct { + float mX1; + float mY1; + float mX2; + float mY2; + } mFunc; + PRUint32 mSteps; + }; + + bool operator==(const nsTimingFunction& aOther) const + { + if (mType != aOther.mType) { + return false; + } + if (mType == Function) { + return mFunc.mX1 == aOther.mFunc.mX1 && mFunc.mY1 == aOther.mFunc.mY1 && + mFunc.mX2 == aOther.mFunc.mX2 && mFunc.mY2 == aOther.mFunc.mY2; + } + return mSteps == aOther.mSteps; + } + + bool operator!=(const nsTimingFunction& aOther) const + { + return !(*this == aOther); } private: diff --git a/layout/style/nsTransitionManager.cpp b/layout/style/nsTransitionManager.cpp index 166e467ebd2..a18703428c6 100644 --- a/layout/style/nsTransitionManager.cpp +++ b/layout/style/nsTransitionManager.cpp @@ -65,6 +65,59 @@ namespace dom = mozilla::dom; * Per-Element data * *****************************************************************************/ +class ComputedTimingFunction { +public: + typedef nsTimingFunction::Type Type; + void Init(const nsTimingFunction &aFunction); + double GetValue(double aPortion) const; +private: + Type mType; + nsSMILKeySpline mTimingFunction; + PRUint32 mSteps; +}; + +void +ComputedTimingFunction::Init(const nsTimingFunction &aFunction) +{ + mType = aFunction.mType; + if (mType == nsTimingFunction::Function) { + mTimingFunction.Init(aFunction.mFunc.mX1, aFunction.mFunc.mY1, + aFunction.mFunc.mX2, aFunction.mFunc.mY2); + } else { + mSteps = aFunction.mSteps; + } +} + +static inline double +StepEnd(PRUint32 aSteps, double aPortion) +{ + NS_ABORT_IF_FALSE(0.0 <= aPortion && aPortion <= 1.0, "out of range"); + PRUint32 step = PRUint32(aPortion * aSteps); // floor + return double(step) / double(aSteps); +} + +double +ComputedTimingFunction::GetValue(double aPortion) const +{ + switch (mType) { + case nsTimingFunction::Function: + return mTimingFunction.GetSplineValue(aPortion); + case nsTimingFunction::StepStart: + // There are diagrams in the spec that seem to suggest this check + // and the bounds point should not be symmetric with StepEnd, but + // should actually step up at rather than immediately after the + // fraction points. However, we rely on rounding negative values + // up to zero, so we can't do that. And it's not clear the spec + // really meant it. + return 1.0 - StepEnd(mSteps, 1.0 - aPortion); + default: + NS_ABORT_IF_FALSE(PR_FALSE, "bad type"); + // fall through + case nsTimingFunction::StepEnd: + return StepEnd(mSteps, aPortion); + } +} + struct ElementPropertyTransition { nsCSSProperty mProperty; @@ -73,7 +126,7 @@ struct ElementPropertyTransition // data from the relevant nsTransition TimeDuration mDuration; - nsSMILKeySpline mTimingFunction; + ComputedTimingFunction mTimingFunction; // This is the start value to be used for a check for whether a // transition is being reversed. Normally the same as mStartValue, @@ -134,7 +187,7 @@ ElementPropertyTransition::ValuePortionFor(TimeStamp aRefreshTime) const timePortion = 1.0; // we might be behind on flushing } - return mTimingFunction.GetSplineValue(timePortion); + return mTimingFunction.GetValue(timePortion); } /** @@ -704,7 +757,7 @@ nsTransitionManager::ConsiderStartingTransition(nsCSSProperty aProperty, pt.mProperty = aProperty; pt.mStartTime = mostRecentRefresh + TimeDuration::FromMilliseconds(delay); pt.mDuration = TimeDuration::FromMilliseconds(duration); - pt.mTimingFunction.Init(tf.mX1, tf.mY1, tf.mX2, tf.mY2); + pt.mTimingFunction.Init(tf); if (!aElementTransitions) { aElementTransitions = diff --git a/layout/style/test/Makefile.in b/layout/style/test/Makefile.in index e3616a43f12..d1fafc74edb 100644 --- a/layout/style/test/Makefile.in +++ b/layout/style/test/Makefile.in @@ -179,6 +179,7 @@ _TEST_FILES = test_acid3_test46.html \ test_transitions_events.html \ test_transitions.html \ test_transitions_per_property.html \ + test_transitions_step_functions.html \ test_transitions_dynamic_changes.html \ test_transitions_bug537151.html \ test_unclosed_parentheses.html \ diff --git a/layout/style/test/property_database.js b/layout/style/test/property_database.js index 7e0fa3fafdd..a4a6c4c0abf 100644 --- a/layout/style/test/property_database.js +++ b/layout/style/test/property_database.js @@ -2641,8 +2641,8 @@ var gCSSProperties = { inherited: false, type: CSS_TYPE_LONGHAND, initial_values: [ "ease", "cubic-bezier(0.25, 0.1, 0.25, 1.0)" ], - other_values: [ "linear", "ease-in", "ease-out", "ease-in-out", "linear, ease-in, cubic-bezier(0.1, 0.2, 0.8, 0.9)", "cubic-bezier(0.5, 0.5, 0.5, 0.5)", "cubic-bezier(0.25, 1.5, 0.75, -0.5)" ], - invalid_values: [ "none", "auto", "cubic-bezier(0.25, 0.1, 0.25)", "cubic-bezier(0.25, 0.1, 0.25, 0.25, 1.0)", "cubic-bezier(-0.5, 0.5, 0.5, 0.5)", "cubic-bezier(1.5, 0.5, 0.5, 0.5)", "cubic-bezier(0.5, 0.5, -0.5, 0.5)", "cubic-bezier(0.5, 0.5, 1.5, 0.5)" ] + other_values: [ "linear", "ease-in", "ease-out", "ease-in-out", "linear, ease-in, cubic-bezier(0.1, 0.2, 0.8, 0.9)", "cubic-bezier(0.5, 0.5, 0.5, 0.5)", "cubic-bezier(0.25, 1.5, 0.75, -0.5)", "step-start", "step-end", "steps(1)", "steps(2, start)", "steps(386)", "steps(3, end)" ], + invalid_values: [ "none", "auto", "cubic-bezier(0.25, 0.1, 0.25)", "cubic-bezier(0.25, 0.1, 0.25, 0.25, 1.0)", "cubic-bezier(-0.5, 0.5, 0.5, 0.5)", "cubic-bezier(1.5, 0.5, 0.5, 0.5)", "cubic-bezier(0.5, 0.5, -0.5, 0.5)", "cubic-bezier(0.5, 0.5, 1.5, 0.5)", "steps(2, step-end)", "steps(0)", "steps(-2)", "steps(0, step-end, 1)" ] }, "unicode-bidi": { domProp: "unicodeBidi", diff --git a/layout/style/test/test_transitions_step_functions.html b/layout/style/test/test_transitions_step_functions.html new file mode 100644 index 00000000000..f8e6b0862d6 --- /dev/null +++ b/layout/style/test/test_transitions_step_functions.html @@ -0,0 +1,98 @@ + + + + + Test for Bug 435441 + + + + + + +
+ +
+
+
+
+ +