| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2013 Google Inc. All rights reserved. | 2 * Copyright (C) 2013 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 20 matching lines...) Expand all Loading... |
| 31 #include "core/animation/EffectInput.h" | 31 #include "core/animation/EffectInput.h" |
| 32 | 32 |
| 33 #include "bindings/core/v8/Dictionary.h" | 33 #include "bindings/core/v8/Dictionary.h" |
| 34 #include "bindings/core/v8/EffectModelOrDictionarySequenceOrDictionary.h" | 34 #include "bindings/core/v8/EffectModelOrDictionarySequenceOrDictionary.h" |
| 35 #include "core/animation/AnimationInputHelpers.h" | 35 #include "core/animation/AnimationInputHelpers.h" |
| 36 #include "core/animation/CompositorAnimations.h" | 36 #include "core/animation/CompositorAnimations.h" |
| 37 #include "core/animation/KeyframeEffectModel.h" | 37 #include "core/animation/KeyframeEffectModel.h" |
| 38 #include "core/animation/StringKeyframe.h" | 38 #include "core/animation/StringKeyframe.h" |
| 39 #include "core/css/CSSStyleSheet.h" | 39 #include "core/css/CSSStyleSheet.h" |
| 40 #include "core/dom/Document.h" | 40 #include "core/dom/Document.h" |
| 41 #include "core/dom/Element.h" | |
| 42 #include "core/dom/ExceptionCode.h" | 41 #include "core/dom/ExceptionCode.h" |
| 43 #include "core/dom/NodeComputedStyle.h" | 42 #include "core/dom/NodeComputedStyle.h" |
| 44 #include "wtf/ASCIICType.h" | 43 #include "wtf/ASCIICType.h" |
| 45 #include "wtf/HashSet.h" | 44 #include "wtf/HashSet.h" |
| 46 #include "wtf/NonCopyingSort.h" | 45 #include "wtf/NonCopyingSort.h" |
| 47 | 46 |
| 48 namespace blink { | 47 namespace blink { |
| 49 | 48 |
| 50 namespace { | 49 namespace { |
| 51 | 50 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 71 } | 70 } |
| 72 | 71 |
| 73 if (offset < lastOffset) { | 72 if (offset < lastOffset) { |
| 74 exceptionState.throwTypeError("Keyframes with specified offsets are not
sorted"); | 73 exceptionState.throwTypeError("Keyframes with specified offsets are not
sorted"); |
| 75 return false; | 74 return false; |
| 76 } | 75 } |
| 77 | 76 |
| 78 return true; | 77 return true; |
| 79 } | 78 } |
| 80 | 79 |
| 81 void setKeyframeValue(Element& element, StringKeyframe& keyframe, const String&
property, const String& value) | 80 void setKeyframeValue(Document& document, StringKeyframe& keyframe, const String
& property, const String& value) |
| 82 { | 81 { |
| 83 StyleSheetContents* styleSheetContents = element.document().elementSheet().c
ontents(); | 82 StyleSheetContents* styleSheetContents = document.elementSheet().contents(); |
| 84 CSSPropertyID cssProperty = AnimationInputHelpers::keyframeAttributeToCSSPro
perty(property, element.document()); | 83 CSSPropertyID cssProperty = AnimationInputHelpers::keyframeAttributeToCSSPro
perty(property, document); |
| 85 if (cssProperty != CSSPropertyInvalid) { | 84 if (cssProperty != CSSPropertyInvalid) { |
| 86 keyframe.setCSSPropertyValue(cssProperty, value, &element, styleSheetCon
tents); | 85 keyframe.setCSSPropertyValue(cssProperty, value, styleSheetContents); |
| 87 return; | 86 return; |
| 88 } | 87 } |
| 89 cssProperty = AnimationInputHelpers::keyframeAttributeToPresentationAttribut
e(property, element); | 88 cssProperty = AnimationInputHelpers::keyframeAttributeToPresentationAttribut
e(property); |
| 90 if (cssProperty != CSSPropertyInvalid) { | 89 if (cssProperty != CSSPropertyInvalid) { |
| 91 keyframe.setPresentationAttributeValue(cssProperty, value, &element, sty
leSheetContents); | 90 keyframe.setPresentationAttributeValue(cssProperty, value, styleSheetCon
tents); |
| 92 return; | 91 return; |
| 93 } | 92 } |
| 94 const QualifiedName* svgAttribute = AnimationInputHelpers::keyframeAttribute
ToSVGAttribute(property, element); | 93 const QualifiedName* svgAttribute = AnimationInputHelpers::keyframeAttribute
ToSVGAttribute(property); |
| 95 if (svgAttribute) | 94 if (svgAttribute) |
| 96 keyframe.setSVGAttributeValue(*svgAttribute, value); | 95 keyframe.setSVGAttributeValue(*svgAttribute, value); |
| 97 } | 96 } |
| 98 | 97 |
| 99 EffectModel* createEffectModelFromKeyframes(Element& element, const StringKeyfra
meVector& keyframes, ExceptionState& exceptionState) | 98 EffectModel* createEffectModelFromKeyframes(const StringKeyframeVector& keyframe
s, ExceptionState& exceptionState) |
| 100 { | 99 { |
| 101 StringKeyframeEffectModel* keyframeEffectModel = StringKeyframeEffectModel::
create(keyframes, LinearTimingFunction::shared()); | 100 StringKeyframeEffectModel* keyframeEffectModel = StringKeyframeEffectModel::
create(keyframes, LinearTimingFunction::shared()); |
| 102 if (!RuntimeEnabledFeatures::cssAdditiveAnimationsEnabled()) { | 101 if (!RuntimeEnabledFeatures::cssAdditiveAnimationsEnabled()) { |
| 103 for (const auto& keyframeGroup : keyframeEffectModel->getPropertySpecifi
cKeyframeGroups()) { | 102 for (const auto& keyframeGroup : keyframeEffectModel->getPropertySpecifi
cKeyframeGroups()) { |
| 104 PropertyHandle property = keyframeGroup.key; | 103 PropertyHandle property = keyframeGroup.key; |
| 105 if (!property.isCSSProperty()) | 104 if (!property.isCSSProperty()) |
| 106 continue; | 105 continue; |
| 107 | 106 |
| 108 for (const auto& keyframe : keyframeGroup.value->keyframes()) { | 107 for (const auto& keyframe : keyframeGroup.value->keyframes()) { |
| 109 if (keyframe->isNeutral()) { | 108 if (keyframe->isNeutral()) { |
| (...skipping 21 matching lines...) Expand all Loading... |
| 131 return false; | 130 return false; |
| 132 } | 131 } |
| 133 result.append(dictionary); | 132 result.append(dictionary); |
| 134 } | 133 } |
| 135 return !exceptionState.hadException(); | 134 return !exceptionState.hadException(); |
| 136 } | 135 } |
| 137 | 136 |
| 138 } // namespace | 137 } // namespace |
| 139 | 138 |
| 140 // Spec: http://w3c.github.io/web-animations/#processing-a-frames-argument | 139 // Spec: http://w3c.github.io/web-animations/#processing-a-frames-argument |
| 141 EffectModel* EffectInput::convert(Element* element, const EffectModelOrDictionar
ySequenceOrDictionary& effectInput, ExecutionContext* executionContext, Exceptio
nState& exceptionState) | 140 EffectModel* EffectInput::convert(Document& document, const EffectModelOrDiction
arySequenceOrDictionary& effectInput, ExecutionContext* executionContext, Except
ionState& exceptionState) |
| 142 { | 141 { |
| 143 if (effectInput.isEffectModel()) | 142 if (effectInput.isEffectModel()) |
| 144 return effectInput.getAsEffectModel(); | 143 return effectInput.getAsEffectModel(); |
| 145 | 144 |
| 146 if (effectInput.isNull() || !element) | 145 if (effectInput.isNull()) |
| 147 return nullptr; | 146 return nullptr; |
| 148 | 147 |
| 149 if (effectInput.isDictionarySequence()) | 148 if (effectInput.isDictionarySequence()) |
| 150 return convertArrayForm(*element, effectInput.getAsDictionarySequence(),
exceptionState); | 149 return convertArrayForm(document, effectInput.getAsDictionarySequence(),
exceptionState); |
| 151 | 150 |
| 152 const Dictionary& dictionary = effectInput.getAsDictionary(); | 151 const Dictionary& dictionary = effectInput.getAsDictionary(); |
| 153 DictionaryIterator iterator = dictionary.getIterator(executionContext); | 152 DictionaryIterator iterator = dictionary.getIterator(executionContext); |
| 154 if (!iterator.isNull()) { | 153 if (!iterator.isNull()) { |
| 155 // TODO(alancutter): Convert keyframes during iteration rather than afte
r to match spec. | 154 // TODO(alancutter): Convert keyframes during iteration rather than afte
r to match spec. |
| 156 Vector<Dictionary> keyframeDictionaries; | 155 Vector<Dictionary> keyframeDictionaries; |
| 157 if (exhaustDictionaryIterator(iterator, executionContext, exceptionState
, keyframeDictionaries)) | 156 if (exhaustDictionaryIterator(iterator, executionContext, exceptionState
, keyframeDictionaries)) |
| 158 return convertArrayForm(*element, keyframeDictionaries, exceptionSta
te); | 157 return convertArrayForm(document, keyframeDictionaries, exceptionSta
te); |
| 159 return nullptr; | 158 return nullptr; |
| 160 } | 159 } |
| 161 | 160 |
| 162 return convertObjectForm(*element, dictionary, exceptionState); | 161 return convertObjectForm(document, dictionary, exceptionState); |
| 163 } | 162 } |
| 164 | 163 |
| 165 EffectModel* EffectInput::convertArrayForm(Element& element, const Vector<Dictio
nary>& keyframeDictionaries, ExceptionState& exceptionState) | 164 EffectModel* EffectInput::convertArrayForm(Document& document, const Vector<Dict
ionary>& keyframeDictionaries, ExceptionState& exceptionState) |
| 166 { | 165 { |
| 167 StringKeyframeVector keyframes; | 166 StringKeyframeVector keyframes; |
| 168 double lastOffset = 0; | 167 double lastOffset = 0; |
| 169 | 168 |
| 170 for (const Dictionary& keyframeDictionary : keyframeDictionaries) { | 169 for (const Dictionary& keyframeDictionary : keyframeDictionaries) { |
| 171 RefPtr<StringKeyframe> keyframe = StringKeyframe::create(); | 170 RefPtr<StringKeyframe> keyframe = StringKeyframe::create(); |
| 172 | 171 |
| 173 ScriptValue scriptValue; | 172 ScriptValue scriptValue; |
| 174 bool frameHasOffset = DictionaryHelper::get(keyframeDictionary, "offset"
, scriptValue) && !scriptValue.isNull(); | 173 bool frameHasOffset = DictionaryHelper::get(keyframeDictionary, "offset"
, scriptValue) && !scriptValue.isNull(); |
| 175 | 174 |
| 176 double offset = 0.0; | 175 double offset = 0.0; |
| 177 if (frameHasOffset) { | 176 if (frameHasOffset) { |
| 178 if (!getAndCheckOffset(keyframeDictionary, offset, lastOffset, excep
tionState)) | 177 if (!getAndCheckOffset(keyframeDictionary, offset, lastOffset, excep
tionState)) |
| 179 return nullptr; | 178 return nullptr; |
| 180 lastOffset = offset; | 179 lastOffset = offset; |
| 181 keyframe->setOffset(offset); | 180 keyframe->setOffset(offset); |
| 182 } | 181 } |
| 183 | 182 |
| 184 String compositeString; | 183 String compositeString; |
| 185 DictionaryHelper::get(keyframeDictionary, "composite", compositeString); | 184 DictionaryHelper::get(keyframeDictionary, "composite", compositeString); |
| 186 if (compositeString == "add") | 185 if (compositeString == "add") |
| 187 keyframe->setComposite(EffectModel::CompositeAdd); | 186 keyframe->setComposite(EffectModel::CompositeAdd); |
| 188 // TODO(alancutter): Support "accumulate" keyframe composition. | 187 // TODO(alancutter): Support "accumulate" keyframe composition. |
| 189 | 188 |
| 190 String timingFunctionString; | 189 String timingFunctionString; |
| 191 if (DictionaryHelper::get(keyframeDictionary, "easing", timingFunctionSt
ring)) { | 190 if (DictionaryHelper::get(keyframeDictionary, "easing", timingFunctionSt
ring)) { |
| 192 RefPtr<TimingFunction> timingFunction = AnimationInputHelpers::parse
TimingFunction(timingFunctionString, &element.document(), exceptionState); | 191 RefPtr<TimingFunction> timingFunction = AnimationInputHelpers::parse
TimingFunction(timingFunctionString, document, exceptionState); |
| 193 if (!timingFunction) | 192 if (!timingFunction) |
| 194 return nullptr; | 193 return nullptr; |
| 195 keyframe->setEasing(timingFunction); | 194 keyframe->setEasing(timingFunction); |
| 196 } | 195 } |
| 197 | 196 |
| 198 Vector<String> keyframeProperties; | 197 Vector<String> keyframeProperties; |
| 199 keyframeDictionary.getPropertyNames(keyframeProperties); | 198 keyframeDictionary.getPropertyNames(keyframeProperties); |
| 200 for (const auto& property : keyframeProperties) { | 199 for (const auto& property : keyframeProperties) { |
| 201 if (property == "offset" | 200 if (property == "offset" |
| 202 || property == "composite" | 201 || property == "composite" |
| 203 || property == "easing") { | 202 || property == "easing") { |
| 204 continue; | 203 continue; |
| 205 } | 204 } |
| 206 | 205 |
| 207 Vector<String> values; | 206 Vector<String> values; |
| 208 if (DictionaryHelper::get(keyframeDictionary, property, values)) { | 207 if (DictionaryHelper::get(keyframeDictionary, property, values)) { |
| 209 exceptionState.throwTypeError("Lists of values not permitted in
array-form list of keyframes"); | 208 exceptionState.throwTypeError("Lists of values not permitted in
array-form list of keyframes"); |
| 210 return nullptr; | 209 return nullptr; |
| 211 } | 210 } |
| 212 | 211 |
| 213 String value; | 212 String value; |
| 214 DictionaryHelper::get(keyframeDictionary, property, value); | 213 DictionaryHelper::get(keyframeDictionary, property, value); |
| 215 | 214 |
| 216 setKeyframeValue(element, *keyframe.get(), property, value); | 215 setKeyframeValue(document, *keyframe.get(), property, value); |
| 217 } | 216 } |
| 218 keyframes.append(keyframe); | 217 keyframes.append(keyframe); |
| 219 } | 218 } |
| 220 | 219 |
| 221 ASSERT(!exceptionState.hadException()); | 220 ASSERT(!exceptionState.hadException()); |
| 222 | 221 |
| 223 return createEffectModelFromKeyframes(element, keyframes, exceptionState); | 222 return createEffectModelFromKeyframes(keyframes, exceptionState); |
| 224 } | 223 } |
| 225 | 224 |
| 226 EffectModel* EffectInput::convertObjectForm(Element& element, const Dictionary&
keyframeDictionary, ExceptionState& exceptionState) | 225 EffectModel* EffectInput::convertObjectForm(Document& document, const Dictionary
& keyframeDictionary, ExceptionState& exceptionState) |
| 227 { | 226 { |
| 228 StringKeyframeVector keyframes; | 227 StringKeyframeVector keyframes; |
| 229 | 228 |
| 230 String timingFunctionString; | 229 String timingFunctionString; |
| 231 RefPtr<TimingFunction> timingFunction = nullptr; | 230 RefPtr<TimingFunction> timingFunction = nullptr; |
| 232 if (DictionaryHelper::get(keyframeDictionary, "easing", timingFunctionString
)) { | 231 if (DictionaryHelper::get(keyframeDictionary, "easing", timingFunctionString
)) { |
| 233 timingFunction = AnimationInputHelpers::parseTimingFunction(timingFuncti
onString, &element.document(), exceptionState); | 232 timingFunction = AnimationInputHelpers::parseTimingFunction(timingFuncti
onString, document, exceptionState); |
| 234 if (!timingFunction) | 233 if (!timingFunction) |
| 235 return nullptr; | 234 return nullptr; |
| 236 } | 235 } |
| 237 | 236 |
| 238 ScriptValue scriptValue; | 237 ScriptValue scriptValue; |
| 239 bool frameHasOffset = DictionaryHelper::get(keyframeDictionary, "offset", sc
riptValue) && !scriptValue.isNull(); | 238 bool frameHasOffset = DictionaryHelper::get(keyframeDictionary, "offset", sc
riptValue) && !scriptValue.isNull(); |
| 240 double offset = 0.0; | 239 double offset = 0.0; |
| 241 if (frameHasOffset && !getAndCheckOffset(keyframeDictionary, offset, 0.0, ex
ceptionState)) | 240 if (frameHasOffset && !getAndCheckOffset(keyframeDictionary, offset, 0.0, ex
ceptionState)) |
| 242 return nullptr; | 241 return nullptr; |
| 243 | 242 |
| (...skipping 28 matching lines...) Expand all Loading... |
| 272 else | 271 else |
| 273 keyframe->setOffset(i / (numKeyframes - 1.0)); | 272 keyframe->setOffset(i / (numKeyframes - 1.0)); |
| 274 | 273 |
| 275 if (timingFunction) | 274 if (timingFunction) |
| 276 keyframe->setEasing(timingFunction); | 275 keyframe->setEasing(timingFunction); |
| 277 | 276 |
| 278 if (compositeString == "add") | 277 if (compositeString == "add") |
| 279 keyframe->setComposite(EffectModel::CompositeAdd); | 278 keyframe->setComposite(EffectModel::CompositeAdd); |
| 280 // TODO(alancutter): Support "accumulate" keyframe composition. | 279 // TODO(alancutter): Support "accumulate" keyframe composition. |
| 281 | 280 |
| 282 setKeyframeValue(element, *keyframe.get(), property, values[i]); | 281 setKeyframeValue(document, *keyframe.get(), property, values[i]); |
| 283 keyframes.append(keyframe); | 282 keyframes.append(keyframe); |
| 284 } | 283 } |
| 285 } | 284 } |
| 286 | 285 |
| 287 std::sort(keyframes.begin(), keyframes.end(), compareKeyframes); | 286 std::sort(keyframes.begin(), keyframes.end(), compareKeyframes); |
| 288 | 287 |
| 289 ASSERT(!exceptionState.hadException()); | 288 ASSERT(!exceptionState.hadException()); |
| 290 | 289 |
| 291 return createEffectModelFromKeyframes(element, keyframes, exceptionState); | 290 return createEffectModelFromKeyframes(keyframes, exceptionState); |
| 292 } | 291 } |
| 293 | 292 |
| 294 } // namespace blink | 293 } // namespace blink |
| OLD | NEW |