Changeset 228702 in webkit
- Timestamp:
- Feb 19, 2018 11:06:25 AM (6 years ago)
- Location:
- trunk
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/imported/w3c/ChangeLog
r228694 r228702 1 2018-02-17 Antoine Quint <graouts@apple.com> 2 3 [Web Animations] Store all parsed keyframe input information in a single structure 4 https://bugs.webkit.org/show_bug.cgi?id=182903 5 6 Reviewed by Dean Jackson. 7 8 Update test expectations with progressions resulting from returning the style values as provided 9 by the keyframe input when calling getKeyframes(). 10 11 * web-platform-tests/web-animations/interfaces/Animatable/animate-expected.txt: 12 * web-platform-tests/web-animations/interfaces/KeyframeEffect/constructor-expected.txt: 13 * web-platform-tests/web-animations/interfaces/KeyframeEffect/setKeyframes-expected.txt: 14 1 15 2018-02-17 Antoine Quint <graouts@apple.com> 2 16 -
trunk/LayoutTests/imported/w3c/web-platform-tests/web-animations/interfaces/Animatable/animate-expected.txt
r228312 r228702 9 9 PASS Element.animate() accepts empty keyframe lists (input: undefined) 10 10 PASS Element.animate() accepts a one property two value property-indexed keyframes specification 11 FAIL Element.animate() accepts a one shorthand property two value property-indexed keyframes specification assert_equals: properties on ComputedKeyframe #0 should match expected "composite,computedOffset,easing,margin,offset" but got "composite,computedOffset,easing,marginBottom,marginLeft,marginRight,marginTop,offset" 12 FAIL Element.animate() accepts a two property (one shorthand and one of its longhand components) two value property-indexed keyframes specification assert_equals: properties on ComputedKeyframe #0 should match expected "composite,computedOffset,easing,margin,marginTop,offset" but got "composite,computedOffset,easing,marginBottom,marginLeft,marginRight,marginTop,offset" 11 PASS Element.animate() accepts a one shorthand property two value property-indexed keyframes specification 12 PASS Element.animate() accepts a two property (one shorthand and one of its longhand components) two value property-indexed keyframes specification 13 13 PASS Element.animate() accepts a two property two value property-indexed keyframes specification 14 14 PASS Element.animate() accepts a two property property-indexed keyframes specification with different numbers of values 15 15 PASS Element.animate() accepts a property-indexed keyframes specification with an invalid value 16 16 PASS Element.animate() accepts a one property two value property-indexed keyframes specification that needs to stringify its values 17 FAIL Element.animate() accepts a property-indexed keyframes specification with a CSS variable reference assert_equals: value for 'left' on ComputedKeyframe #0 expected "var(--dist)" but got "auto" 18 FAIL Element.animate() accepts a property-indexed keyframes specification with a CSS variable reference in a shorthand property assert_equals: properties on ComputedKeyframe #0 should match expected "composite,computedOffset,easing,margin,offset" but got "composite,computedOffset,easing,marginBottom,marginLeft,marginRight,marginTop,offset" 17 PASS Element.animate() accepts a property-indexed keyframes specification with a CSS variable reference 18 PASS Element.animate() accepts a property-indexed keyframes specification with a CSS variable reference in a shorthand property 19 19 PASS Element.animate() accepts a one property one value property-indexed keyframes specification 20 20 PASS Element.animate() accepts a one property one non-array value property-indexed keyframes specification … … 48 48 PASS Element.animate() accepts a one property two keyframe sequence 49 49 PASS Element.animate() accepts a two property two keyframe sequence 50 FAIL Element.animate() accepts a one shorthand property two keyframe sequence assert_equals: properties on ComputedKeyframe #0 should match expected "composite,computedOffset,easing,margin,offset" but got "composite,computedOffset,easing,marginBottom,marginLeft,marginRight,marginTop,offset" 51 FAIL Element.animate() accepts a two property (a shorthand and one of its component longhands) two keyframe sequence assert_equals: properties on ComputedKeyframe #0 should match expected "composite,computedOffset,easing,margin,marginTop,offset" but got "composite,computedOffset,easing,marginBottom,marginLeft,marginRight,marginTop,offset" 50 PASS Element.animate() accepts a one shorthand property two keyframe sequence 51 PASS Element.animate() accepts a two property (a shorthand and one of its component longhands) two keyframe sequence 52 52 PASS Element.animate() accepts a two property keyframe sequence where one property is missing from the first keyframe 53 53 PASS Element.animate() accepts a two property keyframe sequence where one property is missing from the last keyframe 54 54 PASS Element.animate() accepts a one property two keyframe sequence that needs to stringify its values 55 FAIL Element.animate() accepts a keyframe sequence with a CSS variable reference assert_equals: value for 'left' on ComputedKeyframe #0 expected "var(--dist)" but got "auto" 56 FAIL Element.animate() accepts a keyframe sequence with a CSS variable reference in a shorthand property assert_equals: properties on ComputedKeyframe #0 should match expected "composite,computedOffset,easing,margin,offset" but got "composite,computedOffset,easing,marginBottom,marginLeft,marginRight,marginTop,offset" 55 PASS Element.animate() accepts a keyframe sequence with a CSS variable reference 56 PASS Element.animate() accepts a keyframe sequence with a CSS variable reference in a shorthand property 57 57 FAIL Element.animate() accepts a keyframe sequence with duplicate values for a given interior offset Type error 58 58 FAIL Element.animate() accepts a keyframe sequence with duplicate values for offsets 0 and 1 Type error -
trunk/LayoutTests/imported/w3c/web-platform-tests/web-animations/interfaces/KeyframeEffect/constructor-expected.txt
r228694 r228702 8 8 PASS A KeyframeEffectReadOnly can be constructed with a one property two value property-indexed keyframes specification 9 9 PASS A KeyframeEffectReadOnly constructed with a one property two value property-indexed keyframes specification roundtrips 10 FAIL A KeyframeEffectReadOnly can be constructed with a one shorthand property two value property-indexed keyframes specification assert_equals: properties on ComputedKeyframe #0 should match expected "composite,computedOffset,easing,margin,offset" but got "composite,computedOffset,easing,marginBottom,marginLeft,marginRight,marginTop,offset" 10 PASS A KeyframeEffectReadOnly can be constructed with a one shorthand property two value property-indexed keyframes specification 11 11 PASS A KeyframeEffectReadOnly constructed with a one shorthand property two value property-indexed keyframes specification roundtrips 12 FAIL A KeyframeEffectReadOnly can be constructed with a two property (one shorthand and one of its longhand components) two value property-indexed keyframes specification assert_equals: properties on ComputedKeyframe #0 should match expected "composite,computedOffset,easing,margin,marginTop,offset" but got "composite,computedOffset,easing,marginBottom,marginLeft,marginRight,marginTop,offset" 12 PASS A KeyframeEffectReadOnly can be constructed with a two property (one shorthand and one of its longhand components) two value property-indexed keyframes specification 13 13 PASS A KeyframeEffectReadOnly constructed with a two property (one shorthand and one of its longhand components) two value property-indexed keyframes specification roundtrips 14 14 PASS A KeyframeEffectReadOnly can be constructed with a two property two value property-indexed keyframes specification … … 20 20 PASS A KeyframeEffectReadOnly can be constructed with a one property two value property-indexed keyframes specification that needs to stringify its values 21 21 PASS A KeyframeEffectReadOnly constructed with a one property two value property-indexed keyframes specification that needs to stringify its values roundtrips 22 FAIL A KeyframeEffectReadOnly can be constructed with a property-indexed keyframes specification with a CSS variable reference assert_equals: value for 'left' on ComputedKeyframe #0 expected "var(--dist)" but got "auto" 22 PASS A KeyframeEffectReadOnly can be constructed with a property-indexed keyframes specification with a CSS variable reference 23 23 PASS A KeyframeEffectReadOnly constructed with a property-indexed keyframes specification with a CSS variable reference roundtrips 24 FAIL A KeyframeEffectReadOnly can be constructed with a property-indexed keyframes specification with a CSS variable reference in a shorthand property assert_equals: properties on ComputedKeyframe #0 should match expected "composite,computedOffset,easing,margin,offset" but got "composite,computedOffset,easing,marginBottom,marginLeft,marginRight,marginTop,offset" 24 PASS A KeyframeEffectReadOnly can be constructed with a property-indexed keyframes specification with a CSS variable reference in a shorthand property 25 25 PASS A KeyframeEffectReadOnly constructed with a property-indexed keyframes specification with a CSS variable reference in a shorthand property roundtrips 26 26 PASS A KeyframeEffectReadOnly can be constructed with a one property one value property-indexed keyframes specification … … 86 86 PASS A KeyframeEffectReadOnly can be constructed with a two property two keyframe sequence 87 87 PASS A KeyframeEffectReadOnly constructed with a two property two keyframe sequence roundtrips 88 FAIL A KeyframeEffectReadOnly can be constructed with a one shorthand property two keyframe sequence assert_equals: properties on ComputedKeyframe #0 should match expected "composite,computedOffset,easing,margin,offset" but got "composite,computedOffset,easing,marginBottom,marginLeft,marginRight,marginTop,offset" 88 PASS A KeyframeEffectReadOnly can be constructed with a one shorthand property two keyframe sequence 89 89 PASS A KeyframeEffectReadOnly constructed with a one shorthand property two keyframe sequence roundtrips 90 FAIL A KeyframeEffectReadOnly can be constructed with a two property (a shorthand and one of its component longhands) two keyframe sequence assert_equals: properties on ComputedKeyframe #0 should match expected "composite,computedOffset,easing,margin,marginTop,offset" but got "composite,computedOffset,easing,marginBottom,marginLeft,marginRight,marginTop,offset" 90 PASS A KeyframeEffectReadOnly can be constructed with a two property (a shorthand and one of its component longhands) two keyframe sequence 91 91 PASS A KeyframeEffectReadOnly constructed with a two property (a shorthand and one of its component longhands) two keyframe sequence roundtrips 92 92 PASS A KeyframeEffectReadOnly can be constructed with a two property keyframe sequence where one property is missing from the first keyframe … … 96 96 PASS A KeyframeEffectReadOnly can be constructed with a one property two keyframe sequence that needs to stringify its values 97 97 PASS A KeyframeEffectReadOnly constructed with a one property two keyframe sequence that needs to stringify its values roundtrips 98 FAIL A KeyframeEffectReadOnly can be constructed with a keyframe sequence with a CSS variable reference assert_equals: value for 'left' on ComputedKeyframe #0 expected "var(--dist)" but got "auto" 98 PASS A KeyframeEffectReadOnly can be constructed with a keyframe sequence with a CSS variable reference 99 99 PASS A KeyframeEffectReadOnly constructed with a keyframe sequence with a CSS variable reference roundtrips 100 FAIL A KeyframeEffectReadOnly can be constructed with a keyframe sequence with a CSS variable reference in a shorthand property assert_equals: properties on ComputedKeyframe #0 should match expected "composite,computedOffset,easing,margin,offset" but got "composite,computedOffset,easing,marginBottom,marginLeft,marginRight,marginTop,offset" 100 PASS A KeyframeEffectReadOnly can be constructed with a keyframe sequence with a CSS variable reference in a shorthand property 101 101 PASS A KeyframeEffectReadOnly constructed with a keyframe sequence with a CSS variable reference in a shorthand property roundtrips 102 102 FAIL A KeyframeEffectReadOnly can be constructed with a keyframe sequence with duplicate values for a given interior offset Type error -
trunk/LayoutTests/imported/w3c/web-platform-tests/web-animations/interfaces/KeyframeEffect/setKeyframes-expected.txt
r228312 r228702 2 2 PASS Keyframes can be replaced with an empty keyframe 3 3 PASS Keyframes can be replaced with a one property two value property-indexed keyframes specification 4 FAIL Keyframes can be replaced with a one shorthand property two value property-indexed keyframes specification assert_equals: properties on ComputedKeyframe #0 should match expected "composite,computedOffset,easing,margin,offset" but got "composite,computedOffset,easing,marginBottom,marginLeft,marginRight,marginTop,offset" 5 FAIL Keyframes can be replaced with a two property (one shorthand and one of its longhand components) two value property-indexed keyframes specification assert_equals: properties on ComputedKeyframe #0 should match expected "composite,computedOffset,easing,margin,marginTop,offset" but got "composite,computedOffset,easing,marginBottom,marginLeft,marginRight,marginTop,offset" 4 PASS Keyframes can be replaced with a one shorthand property two value property-indexed keyframes specification 5 PASS Keyframes can be replaced with a two property (one shorthand and one of its longhand components) two value property-indexed keyframes specification 6 6 PASS Keyframes can be replaced with a two property two value property-indexed keyframes specification 7 7 PASS Keyframes can be replaced with a two property property-indexed keyframes specification with different numbers of values 8 8 PASS Keyframes can be replaced with a property-indexed keyframes specification with an invalid value 9 9 PASS Keyframes can be replaced with a one property two value property-indexed keyframes specification that needs to stringify its values 10 FAIL Keyframes can be replaced with a property-indexed keyframes specification with a CSS variable reference assert_equals: value for 'left' on ComputedKeyframe #0 expected "var(--dist)" but got "auto" 11 FAIL Keyframes can be replaced with a property-indexed keyframes specification with a CSS variable reference in a shorthand property assert_equals: properties on ComputedKeyframe #0 should match expected "composite,computedOffset,easing,margin,offset" but got "composite,computedOffset,easing,marginBottom,marginLeft,marginRight,marginTop,offset" 10 PASS Keyframes can be replaced with a property-indexed keyframes specification with a CSS variable reference 11 PASS Keyframes can be replaced with a property-indexed keyframes specification with a CSS variable reference in a shorthand property 12 12 PASS Keyframes can be replaced with a one property one value property-indexed keyframes specification 13 13 PASS Keyframes can be replaced with a one property one non-array value property-indexed keyframes specification … … 41 41 PASS Keyframes can be replaced with a one property two keyframe sequence 42 42 PASS Keyframes can be replaced with a two property two keyframe sequence 43 FAIL Keyframes can be replaced with a one shorthand property two keyframe sequence assert_equals: properties on ComputedKeyframe #0 should match expected "composite,computedOffset,easing,margin,offset" but got "composite,computedOffset,easing,marginBottom,marginLeft,marginRight,marginTop,offset" 44 FAIL Keyframes can be replaced with a two property (a shorthand and one of its component longhands) two keyframe sequence assert_equals: properties on ComputedKeyframe #0 should match expected "composite,computedOffset,easing,margin,marginTop,offset" but got "composite,computedOffset,easing,marginBottom,marginLeft,marginRight,marginTop,offset" 43 PASS Keyframes can be replaced with a one shorthand property two keyframe sequence 44 PASS Keyframes can be replaced with a two property (a shorthand and one of its component longhands) two keyframe sequence 45 45 PASS Keyframes can be replaced with a two property keyframe sequence where one property is missing from the first keyframe 46 46 PASS Keyframes can be replaced with a two property keyframe sequence where one property is missing from the last keyframe 47 47 PASS Keyframes can be replaced with a one property two keyframe sequence that needs to stringify its values 48 FAIL Keyframes can be replaced with a keyframe sequence with a CSS variable reference assert_equals: value for 'left' on ComputedKeyframe #0 expected "var(--dist)" but got "auto" 49 FAIL Keyframes can be replaced with a keyframe sequence with a CSS variable reference in a shorthand property assert_equals: properties on ComputedKeyframe #0 should match expected "composite,computedOffset,easing,margin,offset" but got "composite,computedOffset,easing,marginBottom,marginLeft,marginRight,marginTop,offset" 48 PASS Keyframes can be replaced with a keyframe sequence with a CSS variable reference 49 PASS Keyframes can be replaced with a keyframe sequence with a CSS variable reference in a shorthand property 50 50 FAIL Keyframes can be replaced with a keyframe sequence with duplicate values for a given interior offset Type error 51 51 FAIL Keyframes can be replaced with a keyframe sequence with duplicate values for offsets 0 and 1 Type error -
trunk/Source/WebCore/ChangeLog
r228701 r228702 1 2018-02-17 Antoine Quint <graouts@apple.com> 2 3 [Web Animations] Store all parsed keyframe input information in a single structure 4 https://bugs.webkit.org/show_bug.cgi?id=182903 5 6 Reviewed by Dean Jackson. 7 8 When parsing keyframe input provided through the JS API, we used to create several data structures. 9 During parsing we would create a Vector<ProcessedKeyframe> where we would store the validated values 10 for "offset", "easing" and "composite" as well as CSS properties and CSS values as strings. 11 12 Then we would create a KeyframeList, a class that pre-dates the work on Web Animations and is used 13 for hardware animations, with RenderStyle objects that are used for CSS property blending at runtime. 14 Once the KeyframeList was created, the Vector<ProcessedKeyframe> was discarded. 15 16 Since KeyframeList did not know about nullable offsets, timing functions and composite operations, and 17 because we do not with to modify a legacy class that we will eventually remove once all the Web Animations 18 work is complete, we also stored the parsed offsets as m_offsets, the timing functions as m_timingFunctions 19 and the composite operations as m_compositeOperations. 20 21 In this patch we rename the ProcessedKeyframe structure used temporarily during parsing to ParsedKeyframe and 22 store both the input and processed data related to a given keyframe in that single structure which we keep 23 around as m_parsedKeyframes when we finished processing the keyframes input. This update ParsedKeyframe structure 24 allows to keep around the original nullable offsets, the original CSS properties and CSS values as strings as 25 a HashMap<CSSPropertyID, String>, as well as the CSS properties and CSS values as CSSValue objects using a 26 MutableStyleProperties object. 27 28 This has the benefit of reducing the number of members, but also pave the way for supporting read-write targets 29 where we will be able to decouple parsing keyframes and creating a KeyframeList, which requires a valid target 30 to create RenderStyle objects used for blending, since the original parsing-time information is now stored. 31 32 Finally, this allowed getKeyframes() to be more compliant by returning the CSS values as originally provided in 33 the keyframe input with shorthand properties when provided, rather than the long-hands we used to read back 34 through RenderStyle objects. 35 36 The generated KeyframeList is now stored as m_blendingKeyframes and is only used for the purpose of interfacing 37 with hardware animations and CSS property blending. 38 39 While ProcessedKeyframe was copyable due to holding only simple types, ParsedKeyframe is not since it uses a Ref 40 to hold the MutableStyleProperties. This uncovered some cases where we copied ProcessedKeyframe objects, we now 41 ensure that the ParsedKeyframe objects are moved instead, which was the correct thing to do all along. 42 43 * animation/KeyframeEffectReadOnly.cpp: 44 (WebCore::computeMissingKeyframeOffsets): While we used to store std::optional<double> for the computed offset, 45 we now store a simple double, which makes more sense since the computed offset is eventually a fully resolved 46 value after calling computeMissingKeyframeOffsets(). So we now compute the final computed offset without resorting 47 to intermediate nullable computed offsets. 48 (WebCore::processIterableKeyframes): 49 (WebCore::processPropertyIndexedKeyframes): 50 (WebCore::KeyframeEffectReadOnly::KeyframeEffectReadOnly): 51 (WebCore::KeyframeEffectReadOnly::copyPropertiesFromSource): 52 (WebCore::KeyframeEffectReadOnly::getKeyframes): 53 (WebCore::KeyframeEffectReadOnly::processKeyframes): 54 (WebCore::KeyframeEffectReadOnly::computeStackingContextImpact): 55 (WebCore::KeyframeEffectReadOnly::shouldRunAccelerated): 56 (WebCore::KeyframeEffectReadOnly::getAnimatedStyle): 57 (WebCore::KeyframeEffectReadOnly::setAnimatedPropertiesInStyle): 58 (WebCore::KeyframeEffectReadOnly::startOrStopAccelerated): 59 * animation/KeyframeEffectReadOnly.h: 60 (WebCore::KeyframeEffectReadOnly::ParsedKeyframe::ParsedKeyframe): 61 1 62 2018-02-19 Zalan Bujtas <zalan@apple.com> 2 63 -
trunk/Source/WebCore/animation/KeyframeEffectReadOnly.cpp
r228694 r228702 37 37 #include "JSKeyframeEffectReadOnly.h" 38 38 #include "RenderStyle.h" 39 #include "StyleProperties.h"40 39 #include "StyleResolver.h" 41 40 #include "TimingFunction.h" … … 72 71 } 73 72 74 static inline void computeMissingKeyframeOffsets(Vector<KeyframeEffectReadOnly::P rocessedKeyframe>& keyframes)73 static inline void computeMissingKeyframeOffsets(Vector<KeyframeEffectReadOnly::ParsedKeyframe>& keyframes) 75 74 { 76 75 // https://drafts.csswg.org/web-animations-1/#compute-missing-keyframe-offsets … … 80 79 81 80 // 1. For each keyframe, in keyframes, let the computed keyframe offset of the keyframe be equal to its keyframe offset value. 81 // In our implementation, we only set non-null values to avoid making computedOffset std::optional<double>. Instead, we'll know 82 // that a keyframe hasn't had a computed offset by checking if it has a null offset and a 0 computedOffset, since the first 83 // keyframe will already have a 0 computedOffset. 82 84 for (auto& keyframe : keyframes) 83 keyframe.computedOffset = keyframe.offset ;85 keyframe.computedOffset = keyframe.offset.value_or(0); 84 86 85 87 // 2. If keyframes contains more than one keyframe and the computed keyframe offset of the first keyframe in keyframes is null, 86 88 // set the computed keyframe offset of the first keyframe to 0. 87 if (keyframes.size() > 1 && !keyframes[0]. computedOffset)89 if (keyframes.size() > 1 && !keyframes[0].offset) 88 90 keyframes[0].computedOffset = 0; 89 91 90 92 // 3. If the computed keyframe offset of the last keyframe in keyframes is null, set its computed keyframe offset to 1. 91 if (!keyframes.last(). computedOffset)93 if (!keyframes.last().offset) 92 94 keyframes.last().computedOffset = 1; 93 95 … … 109 111 continue; 110 112 111 double lastNonNullOffset = keyframes[indexOfLastKeyframeWithNonNullOffset].computedOffset .value();112 double offsetDelta = keyframe.computedOffset .value()- lastNonNullOffset;113 double lastNonNullOffset = keyframes[indexOfLastKeyframeWithNonNullOffset].computedOffset; 114 double offsetDelta = keyframe.computedOffset - lastNonNullOffset; 113 115 double offsetIncrement = offsetDelta / (i - indexOfLastKeyframeWithNonNullOffset); 114 116 size_t indexOfFirstKeyframeWithNullOffset = indexOfLastKeyframeWithNonNullOffset + 1; … … 120 122 } 121 123 122 static inline ExceptionOr<void> processIterableKeyframes(ExecState& state, Strong<JSObject>&& keyframesInput, JSValue method, Vector<KeyframeEffectReadOnly::P rocessedKeyframe>& processedKeyframes)124 static inline ExceptionOr<void> processIterableKeyframes(ExecState& state, Strong<JSObject>&& keyframesInput, JSValue method, Vector<KeyframeEffectReadOnly::ParsedKeyframe>& parsedKeyframes) 123 125 { 124 126 VM& vm = state.vm(); … … 126 128 127 129 // 1. Let iter be GetIterator(object, method). 128 forEachInIterable(state, keyframesInput.get(), method, [&p rocessedKeyframes](VM& vm, ExecState& state, JSValue nextValue) -> ExceptionOr<void> {130 forEachInIterable(state, keyframesInput.get(), method, [&parsedKeyframes](VM& vm, ExecState& state, JSValue nextValue) -> ExceptionOr<void> { 129 131 if (!nextValue || !nextValue.isObject()) 130 132 return Exception { TypeError }; … … 137 139 size_t numberOfProperties = ownPropertyNames.size(); 138 140 139 KeyframeEffectReadOnly::P rocessedKeyframe keyframeOutput;141 KeyframeEffectReadOnly::ParsedKeyframe keyframeOutput; 140 142 141 143 String easing("linear"); … … 154 156 else { 155 157 auto cssPropertyId = IDLAttributeNameToAnimationPropertyName(ownPropertyName.string()); 156 if (CSSPropertyAnimation::isPropertyAnimatable(cssPropertyId)) 157 keyframeOutput.cssPropertiesAndValues.set(cssPropertyId, convert<IDLDOMString>(state, ownPropertyRawValue)); 158 if (CSSPropertyAnimation::isPropertyAnimatable(cssPropertyId)) { 159 auto stringValue = convert<IDLDOMString>(state, ownPropertyRawValue); 160 if (keyframeOutput.style->setProperty(cssPropertyId, stringValue)) 161 keyframeOutput.unparsedStyle.set(cssPropertyId, stringValue); 162 } 158 163 } 159 164 RETURN_IF_EXCEPTION(scope, Exception { TypeError }); … … 164 169 keyframeOutput.composite = composite; 165 170 166 p rocessedKeyframes.append(WTFMove(keyframeOutput));171 parsedKeyframes.append(WTFMove(keyframeOutput)); 167 172 168 173 return { }; … … 252 257 } 253 258 254 static inline ExceptionOr<void> processPropertyIndexedKeyframes(ExecState& state, Strong<JSObject>&& keyframesInput, Vector<KeyframeEffectReadOnly::P rocessedKeyframe>& processedKeyframes, Vector<String>& unusedEasings)259 static inline ExceptionOr<void> processPropertyIndexedKeyframes(ExecState& state, Strong<JSObject>&& keyframesInput, Vector<KeyframeEffectReadOnly::ParsedKeyframe>& parsedKeyframes, Vector<String>& unusedEasings) 255 260 { 256 261 // 1. Let property-indexed keyframe be the result of running the procedure to process a keyframe-like object passing object as the keyframe input. … … 270 275 auto propertyValues = m.values; 271 276 // 4. Let property keyframes be an empty sequence of keyframes. 272 Vector<KeyframeEffectReadOnly::P rocessedKeyframe> propertyKeyframes;277 Vector<KeyframeEffectReadOnly::ParsedKeyframe> propertyKeyframes; 273 278 // 5. For each value, v, in property values perform the following steps: 274 279 for (auto& v : propertyValues) { 275 280 // 1. Let k be a new keyframe with a null keyframe offset. 276 KeyframeEffectReadOnly::P rocessedKeyframe k;281 KeyframeEffectReadOnly::ParsedKeyframe k; 277 282 // 2. Add the property-value pair, property name → v, to k. 278 k.cssPropertiesAndValues.set(propertyName, v); 283 if (k.style->setProperty(propertyName, v)) 284 k.unparsedStyle.set(propertyName, v); 279 285 // 3. Append k to property keyframes. 280 propertyKeyframes.append( k);286 propertyKeyframes.append(WTFMove(k)); 281 287 } 282 288 // 6. Apply the procedure to compute missing keyframe offsets to property keyframes. … … 285 291 // 7. Add keyframes in property keyframes to processed keyframes. 286 292 for (auto& keyframe : propertyKeyframes) 287 p rocessedKeyframes.append(keyframe);293 parsedKeyframes.append(WTFMove(keyframe)); 288 294 } 289 295 290 296 // 3. Sort processed keyframes by the computed keyframe offset of each keyframe in increasing order. 291 std::sort(p rocessedKeyframes.begin(), processedKeyframes.end(), [](auto& lhs, auto& rhs) {292 return lhs.computedOffset .value() < rhs.computedOffset.value();297 std::sort(parsedKeyframes.begin(), parsedKeyframes.end(), [](auto& lhs, auto& rhs) { 298 return lhs.computedOffset < rhs.computedOffset; 293 299 }); 294 300 295 301 // 4. Merge adjacent keyframes in processed keyframes when they have equal computed keyframe offsets. 296 302 size_t i = 1; 297 while (i < p rocessedKeyframes.size()) {298 auto& keyframe = p rocessedKeyframes[i];299 auto& previousKeyframe = p rocessedKeyframes[i - 1];303 while (i < parsedKeyframes.size()) { 304 auto& keyframe = parsedKeyframes[i]; 305 auto& previousKeyframe = parsedKeyframes[i - 1]; 300 306 // If the offsets of this keyframe and the previous keyframe are different, 301 307 // this means that the two keyframes should not be merged and we can move 302 308 // on to the next keyframe. 303 if (keyframe.computedOffset .value() != previousKeyframe.computedOffset.value()) {309 if (keyframe.computedOffset != previousKeyframe.computedOffset) { 304 310 i++; 305 311 continue; 306 312 } 307 313 // Otherwise, both this keyframe and the previous keyframe should be merged. 308 // Unprocessed keyframes in p rocessedKeyframes at this stage havea single314 // Unprocessed keyframes in parsedKeyframes at this stage have at most a single 309 315 // property in cssPropertiesAndValues, so just set this on the previous keyframe. 310 auto singleValueInKeyframe = keyframe.cssPropertiesAndValues.begin(); 311 previousKeyframe.cssPropertiesAndValues.set(singleValueInKeyframe->key, singleValueInKeyframe->value); 316 // In case an invalid or null value was originally provided, then the property 317 // was not set and the property count is 0, in which case there is nothing to merge. 318 if (keyframe.style->propertyCount()) { 319 auto property = keyframe.style->propertyAt(0); 320 previousKeyframe.style->setProperty(property.id(), property.value()); 321 previousKeyframe.unparsedStyle.set(property.id(), keyframe.unparsedStyle.get(property.id())); 322 } 312 323 // Since we've processed this keyframe, we can remove it and keep i the same 313 324 // so that we process the next keyframe in the next loop iteration. 314 p rocessedKeyframes.remove(i);325 parsedKeyframes.remove(i); 315 326 } 316 327 … … 327 338 328 339 // 6. Assign each value in offsets to the keyframe offset of the keyframe with corresponding position in property keyframes until the end of either sequence is reached. 329 for (size_t i = 0; i < offsets.size() && i < p rocessedKeyframes.size(); ++i)330 p rocessedKeyframes[i].offset = offsets[i];340 for (size_t i = 0; i < offsets.size() && i < parsedKeyframes.size(); ++i) 341 parsedKeyframes[i].offset = offsets[i]; 331 342 332 343 // 7. Let easings be a sequence of DOMString values assigned based on the type of the “easing” member of the property-indexed keyframe as follows: … … 345 356 // 9. If easings has fewer items than property keyframes, repeat the elements in easings successively starting from the beginning of the list until easings has as many 346 357 // items as property keyframes. 347 if (easings.size() < p rocessedKeyframes.size()) {358 if (easings.size() < parsedKeyframes.size()) { 348 359 size_t initialNumberOfEasings = easings.size(); 349 for (i = initialNumberOfEasings + 1; i <= p rocessedKeyframes.size(); ++i)360 for (i = initialNumberOfEasings + 1; i <= parsedKeyframes.size(); ++i) 350 361 easings.append(easings[i % initialNumberOfEasings]); 351 362 } 352 363 353 364 // 10. If easings has more items than property keyframes, store the excess items as unused easings. 354 while (easings.size() > p rocessedKeyframes.size())365 while (easings.size() > parsedKeyframes.size()) 355 366 unusedEasings.append(easings.takeLast()); 356 367 357 368 // 11. Assign each value in easings to a property named “easing” on the keyframe with the corresponding position in property keyframes until the end of property keyframes 358 369 // is reached. 359 for (size_t i = 0; i < p rocessedKeyframes.size(); ++i)360 p rocessedKeyframes[i].easing = easings[i];370 for (size_t i = 0; i < parsedKeyframes.size(); ++i) 371 parsedKeyframes[i].easing = easings[i]; 361 372 362 373 // 12. If the “composite” member of the property-indexed keyframe is not an empty sequence: … … 373 384 // 2. As with easings, if composite modes has fewer items than property keyframes, repeat the elements in composite modes successively starting from the beginning of 374 385 // the list until composite modes has as many items as property keyframes. 375 if (compositeModes.size() < p rocessedKeyframes.size()) {386 if (compositeModes.size() < parsedKeyframes.size()) { 376 387 size_t initialNumberOfCompositeModes = compositeModes.size(); 377 for (i = initialNumberOfCompositeModes + 1; i <= p rocessedKeyframes.size(); ++i)388 for (i = initialNumberOfCompositeModes + 1; i <= parsedKeyframes.size(); ++i) 378 389 compositeModes.append(compositeModes[i % initialNumberOfCompositeModes]); 379 390 } 380 391 // 3. Assign each value in composite modes to the keyframe-specific composite operation on the keyframe with the corresponding position in property keyframes until 381 392 // the end of property keyframes is reached. 382 for (size_t i = 0; i < compositeModes.size() && i < p rocessedKeyframes.size(); ++i)383 p rocessedKeyframes[i].composite = compositeModes[i];393 for (size_t i = 0; i < compositeModes.size() && i < parsedKeyframes.size(); ++i) 394 parsedKeyframes[i].composite = compositeModes[i]; 384 395 } 385 396 … … 412 423 : AnimationEffectReadOnly(classType, WTFMove(timing)) 413 424 , m_target(target) 414 , m_ keyframes(emptyString())425 , m_blendingKeyframes(emptyString()) 415 426 { 416 427 } … … 419 430 { 420 431 m_target = source->m_target; 421 m_offsets = source->m_offsets;422 m_timingFunctions = source->m_timingFunctions;423 432 m_compositeOperation = source->m_compositeOperation; 424 m_compositeOperations = source->m_compositeOperations;425 433 m_iterationCompositeOperation = source->m_iterationCompositeOperation; 426 434 435 Vector<ParsedKeyframe> parsedKeyframes; 436 for (auto& sourceParsedKeyframe : source->m_parsedKeyframes) { 437 ParsedKeyframe parsedKeyframe; 438 parsedKeyframe.easing = sourceParsedKeyframe.easing; 439 parsedKeyframe.offset = sourceParsedKeyframe.offset; 440 parsedKeyframe.composite = sourceParsedKeyframe.composite; 441 parsedKeyframe.unparsedStyle = sourceParsedKeyframe.unparsedStyle; 442 parsedKeyframe.computedOffset = sourceParsedKeyframe.computedOffset; 443 parsedKeyframe.timingFunction = sourceParsedKeyframe.timingFunction; 444 parsedKeyframe.style = sourceParsedKeyframe.style->mutableCopy(); 445 parsedKeyframes.append(WTFMove(parsedKeyframe)); 446 } 447 m_parsedKeyframes = WTFMove(parsedKeyframes); 448 427 449 timing()->copyPropertiesFromSource(source->timing()); 428 450 429 451 KeyframeList keyframeList("keyframe-effect-" + createCanonicalUUIDString()); 430 for (auto& keyframe : source->m_ keyframes.keyframes()) {452 for (auto& keyframe : source->m_blendingKeyframes.keyframes()) { 431 453 KeyframeValue keyframeValue(keyframe.key(), RenderStyle::clonePtr(*keyframe.style())); 432 454 for (auto propertyId : keyframe.properties()) … … 434 456 keyframeList.insert(WTFMove(keyframeValue)); 435 457 } 436 m_ keyframes = WTFMove(keyframeList);458 m_blendingKeyframes = WTFMove(keyframeList); 437 459 } 438 460 … … 452 474 453 475 // 3. For each keyframe in keyframes perform the following steps: 454 for (size_t i = 0; i < m_keyframes.size(); ++i) { 455 auto& keyframe = m_keyframes[i]; 456 476 for (auto& parsedKeyframe : m_parsedKeyframes) { 457 477 // 1. Initialize a dictionary object, output keyframe, using the following definition: 458 478 // … … 467 487 // offset, keyframe-specific timing function and keyframe-specific composite operation of keyframe. 468 488 BaseComputedKeyframe computedKeyframe; 469 computedKeyframe.offset = m_offsets[i];470 computedKeyframe.computedOffset = keyframe.key();471 computedKeyframe.easing = m_timingFunctions[i]->cssText();472 computedKeyframe.composite = m_compositeOperations[i];489 computedKeyframe.offset = parsedKeyframe.offset; 490 computedKeyframe.computedOffset = parsedKeyframe.computedOffset; 491 computedKeyframe.easing = parsedKeyframe.timingFunction->cssText(); 492 computedKeyframe.composite = parsedKeyframe.composite; 473 493 474 494 auto outputKeyframe = convertDictionaryToJS(state, *jsCast<JSDOMGlobalObject*>(state.lexicalGlobalObject()), computedKeyframe); 475 495 476 auto& style = *keyframe.style();477 auto computedStyleExtractor = ComputedStyleExtractor(m_target.get());478 479 496 // 3. For each animation property-value pair specified on keyframe, declaration, perform the following steps: 480 for (auto cssPropertyId : keyframe.properties()) {497 for (auto it = parsedKeyframe.unparsedStyle.begin(), end = parsedKeyframe.unparsedStyle.end(); it != end; ++it) { 481 498 // 1. Let property name be the result of applying the animation property name to IDL attribute name algorithm to the property name of declaration. 482 auto propertyName = CSSPropertyIDToIDLAttributeName( cssPropertyId);499 auto propertyName = CSSPropertyIDToIDLAttributeName(it->key); 483 500 // 2. Let IDL value be the result of serializing the property value of declaration by passing declaration to the algorithm to serialize a CSS value. 484 auto idlValue = computedStyleExtractor.valueForPropertyinStyle(style, cssPropertyId)->cssText();485 501 // 3. Let value be the result of converting IDL value to an ECMAScript String value. 486 auto value = toJS<IDLDOMString>(state, i dlValue);502 auto value = toJS<IDLDOMString>(state, it->value); 487 503 // 4. Call the [[DefineOwnProperty]] internal method on output keyframe with property name property name, 488 504 // Property Descriptor { [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true, [[Value]]: value } and Boolean flag false. … … 508 524 509 525 // 2. Let processed keyframes be an empty sequence of keyframes. 510 Vector<P rocessedKeyframe> processedKeyframes;526 Vector<ParsedKeyframe> parsedKeyframes; 511 527 512 528 // 3. Let method be the result of GetMethod(object, @@iterator). … … 519 535 Vector<String> unusedEasings; 520 536 if (!method.isUndefined()) 521 processIterableKeyframes(state, WTFMove(keyframesInput), WTFMove(method), p rocessedKeyframes);537 processIterableKeyframes(state, WTFMove(keyframesInput), WTFMove(method), parsedKeyframes); 522 538 else 523 processPropertyIndexedKeyframes(state, WTFMove(keyframesInput), p rocessedKeyframes, unusedEasings);539 processPropertyIndexedKeyframes(state, WTFMove(keyframesInput), parsedKeyframes, unusedEasings); 524 540 525 541 // 6. If processed keyframes is not loosely sorted by offset, throw a TypeError and abort these steps. … … 527 543 // zero or greater than one, throw a TypeError and abort these steps. 528 544 double lastNonNullOffset = -1; 529 for (auto& keyframe : p rocessedKeyframes) {545 for (auto& keyframe : parsedKeyframes) { 530 546 if (!keyframe.offset) 531 547 continue; … … 538 554 // We take a slight detour from the spec text and compute the missing keyframe offsets right away 539 555 // since they can be computed up-front. 540 computeMissingKeyframeOffsets(p rocessedKeyframes);556 computeMissingKeyframeOffsets(parsedKeyframes); 541 557 542 558 KeyframeList keyframeList("keyframe-effect-" + createCanonicalUUIDString()); 543 Vector<std::optional<double>> offsets;544 Vector<RefPtr<TimingFunction>> timingFunctions;545 Vector<std::optional<CompositeOperation>> compositeOperations;546 547 559 StyleResolver& styleResolver = m_target->styleResolver(); 548 auto parserContext = CSSParserContext(HTMLStandardMode);549 560 550 561 // 8. For each frame in processed keyframes, perform the following steps: 551 for (auto& keyframe : processedKeyframes) { 552 offsets.append(keyframe.offset); 553 compositeOperations.append(keyframe.composite); 554 562 for (auto& keyframe : parsedKeyframes) { 555 563 // 1. For each property-value pair in frame, parse the property value using the syntax specified for that property. 556 564 // If the property value is invalid according to the syntax for the property, discard the property-value pair. … … 558 566 // highlighting the invalid property value. 559 567 560 StringBuilder cssText; 561 for (auto it = keyframe.cssPropertiesAndValues.begin(), end = keyframe.cssPropertiesAndValues.end(); it != end; ++it) { 562 cssText.append(getPropertyNameString(it->key)); 563 cssText.appendLiteral(": "); 564 cssText.append(it->value); 565 cssText.appendLiteral("; "); 566 } 567 568 KeyframeValue keyframeValue(keyframe.computedOffset.value(), nullptr); 568 KeyframeValue keyframeValue(keyframe.computedOffset, nullptr); 569 569 auto renderStyle = RenderStyle::createPtr(); 570 auto styleProperties = MutableStyleProperties::create(); 571 styleProperties->parseDeclaration(cssText.toString(), parserContext); 572 unsigned numberOfCSSProperties = styleProperties->propertyCount(); 573 574 for (unsigned i = 0; i < numberOfCSSProperties; ++i) { 570 auto& styleProperties = keyframe.style; 571 for (unsigned i = 0; i < styleProperties->propertyCount(); ++i) { 575 572 auto cssPropertyId = styleProperties->propertyAt(i).id(); 576 573 keyframeValue.addProperty(cssPropertyId); … … 589 586 if (timingFunctionResult.hasException()) 590 587 return timingFunctionResult.releaseException(); 591 timingFunctions.append(timingFunctionResult.returnValue());588 keyframe.timingFunction = timingFunctionResult.returnValue(); 592 589 } 593 590 … … 601 598 } 602 599 603 m_offsets = WTFMove(offsets); 604 m_keyframes = WTFMove(keyframeList); 605 m_timingFunctions = WTFMove(timingFunctions); 606 m_compositeOperations = WTFMove(compositeOperations); 600 m_blendingKeyframes = WTFMove(keyframeList); 601 m_parsedKeyframes = WTFMove(parsedKeyframes); 607 602 608 603 computeStackingContextImpact(); … … 614 609 { 615 610 m_triggersStackingContext = false; 616 for (auto cssPropertyId : m_ keyframes.properties()) {611 for (auto cssPropertyId : m_blendingKeyframes.properties()) { 617 612 if (WillChangeData::propertyCreatesStackingContext(cssPropertyId)) { 618 613 m_triggersStackingContext = true; … … 667 662 bool KeyframeEffectReadOnly::shouldRunAccelerated() 668 663 { 669 for (auto cssPropertyId : m_ keyframes.properties()) {664 for (auto cssPropertyId : m_blendingKeyframes.properties()) { 670 665 if (!CSSPropertyAnimation::animationOfPropertyIsAccelerated(cssPropertyId)) 671 666 return false; … … 679 674 return; 680 675 681 if (!m_ keyframes.size())676 if (!m_blendingKeyframes.size()) 682 677 return; 683 678 … … 700 695 // for a given iteration progress, current iteration and underlying value is calculated as follows. 701 696 702 for (auto cssPropertyId : m_ keyframes.properties()) {697 for (auto cssPropertyId : m_blendingKeyframes.properties()) { 703 698 // 1. If iteration progress is unresolved abort this procedure. 704 699 // 2. Let target property be the longhand property for which the effect value is to be calculated. … … 712 707 unsigned numberOfKeyframesWithOneOffset = 0; 713 708 Vector<std::optional<size_t>> propertySpecificKeyframes; 714 for (size_t i = 0; i < m_ keyframes.size(); ++i) {715 auto& keyframe = m_ keyframes[i];709 for (size_t i = 0; i < m_blendingKeyframes.size(); ++i) { 710 auto& keyframe = m_blendingKeyframes[i]; 716 711 if (!keyframe.containsProperty(cssPropertyId)) 717 712 continue; … … 769 764 if (!keyframeIndex) 770 765 return i ? 1 : 0; 771 return m_ keyframes[keyframeIndex.value()].key();766 return m_blendingKeyframes[keyframeIndex.value()].key(); 772 767 }(); 773 768 if (!offset) … … 795 790 if (intervalEndpoints.size() == 1) { 796 791 auto keyframeIndex = intervalEndpoints[0]; 797 auto keyframeStyle = !keyframeIndex ? &targetStyle : m_ keyframes[keyframeIndex.value()].style();792 auto keyframeStyle = !keyframeIndex ? &targetStyle : m_blendingKeyframes[keyframeIndex.value()].style(); 798 793 CSSPropertyAnimation::blendProperties(this, cssPropertyId, &targetStyle, keyframeStyle, keyframeStyle, 0); 799 794 continue; … … 802 797 // 14. Let start offset be the computed keyframe offset of the first keyframe in interval endpoints. 803 798 auto startKeyframeIndex = intervalEndpoints.first(); 804 auto startOffset = !startKeyframeIndex ? 0 : m_ keyframes[startKeyframeIndex.value()].key();799 auto startOffset = !startKeyframeIndex ? 0 : m_blendingKeyframes[startKeyframeIndex.value()].key(); 805 800 806 801 // 15. Let end offset be the computed keyframe offset of last keyframe in interval endpoints. 807 802 auto endKeyframeIndex = intervalEndpoints.last(); 808 auto endOffset = !endKeyframeIndex ? 1 : m_ keyframes[endKeyframeIndex.value()].key();803 auto endOffset = !endKeyframeIndex ? 1 : m_blendingKeyframes[endKeyframeIndex.value()].key(); 809 804 810 805 // 16. Let interval distance be the result of evaluating (iteration progress - start offset) / (end offset - start offset). … … 817 812 if (auto iterationDuration = timing()->iterationDuration()) { 818 813 auto rangeDuration = (endOffset - startOffset) * iterationDuration.seconds(); 819 transformedDistance = m_ timingFunctions[startKeyframeIndex.value()]->transformTime(intervalDistance, rangeDuration);814 transformedDistance = m_parsedKeyframes[startKeyframeIndex.value()].timingFunction->transformTime(intervalDistance, rangeDuration); 820 815 } 821 816 } … … 824 819 // property specified on the two keyframes in interval endpoints taking the first such value as Vstart and the second as Vend and using transformed 825 820 // distance as the interpolation parameter p. 826 auto startStyle = !startKeyframeIndex ? &targetStyle : m_ keyframes[startKeyframeIndex.value()].style();827 auto endStyle = !endKeyframeIndex ? &targetStyle : m_ keyframes[endKeyframeIndex.value()].style();821 auto startStyle = !startKeyframeIndex ? &targetStyle : m_blendingKeyframes[startKeyframeIndex.value()].style(); 822 auto endStyle = !endKeyframeIndex ? &targetStyle : m_blendingKeyframes[endKeyframeIndex.value()].style(); 828 823 CSSPropertyAnimation::blendProperties(this, cssPropertyId, &targetStyle, startStyle, endStyle, transformedDistance); 829 824 } … … 840 835 auto animation = Animation::create(); 841 836 animation->setDuration(timing()->iterationDuration().seconds()); 842 compositedRenderer->startAnimation(0, animation.ptr(), m_ keyframes);837 compositedRenderer->startAnimation(0, animation.ptr(), m_blendingKeyframes); 843 838 } else { 844 compositedRenderer->animationFinished(m_ keyframes.animationName());839 compositedRenderer->animationFinished(m_blendingKeyframes.animationName()); 845 840 if (!m_target->document().renderTreeBeingDestroyed()) 846 841 m_target->invalidateStyleAndLayerComposition(); -
trunk/Source/WebCore/animation/KeyframeEffectReadOnly.h
r228694 r228702 35 35 #include "KeyframeList.h" 36 36 #include "RenderStyle.h" 37 #include "StyleProperties.h" 37 38 #include <wtf/Ref.h> 38 39 … … 64 65 }; 65 66 66 struct ProcessedKeyframe { 67 struct ParsedKeyframe { 68 std::optional<double> offset; 69 double computedOffset; 70 std::optional<CompositeOperation> composite; 67 71 String easing; 68 std::optional<double> offset; 69 std::optional<double> computedOffset; 70 std::optional<CompositeOperation> composite; 71 HashMap<CSSPropertyID, String> cssPropertiesAndValues; 72 RefPtr<TimingFunction> timingFunction; 73 Ref<MutableStyleProperties> style; 74 HashMap<CSSPropertyID, String> unparsedStyle; 75 76 ParsedKeyframe() 77 : style(MutableStyleProperties::create()) 78 { 79 } 72 80 }; 73 81 … … 114 122 bool shouldRunAccelerated(); 115 123 116 Vector<std::optional<double>> m_offsets;117 Vector<RefPtr<TimingFunction>> m_timingFunctions;118 Vector<std::optional<CompositeOperation>> m_compositeOperations;119 124 bool m_triggersStackingContext { false }; 120 125 bool m_started { false }; … … 122 127 123 128 RefPtr<Element> m_target; 124 KeyframeList m_keyframes; 129 KeyframeList m_blendingKeyframes; 130 Vector<ParsedKeyframe> m_parsedKeyframes; 125 131 }; 126 132
Note: See TracChangeset
for help on using the changeset viewer.