Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 /* representation of a SMIL-animatable CSS property on an element */
8 #include "nsSMILCSSProperty.h"
9 #include "nsSMILCSSValueType.h"
10 #include "nsSMILValue.h"
11 #include "nsComputedDOMStyle.h"
12 #include "nsCSSProps.h"
13 #include "nsStyleAnimation.h"
14 #include "mozilla/dom/Element.h"
15 #include "nsIDOMElement.h"
16 #include "nsIDocument.h"
18 using namespace mozilla::dom;
20 // Helper function
21 static bool
22 GetCSSComputedValue(Element* aElem,
23 nsCSSProperty aPropID,
24 nsAString& aResult)
25 {
26 NS_ABORT_IF_FALSE(!nsCSSProps::IsShorthand(aPropID),
27 "Can't look up computed value of shorthand property");
28 NS_ABORT_IF_FALSE(nsSMILCSSProperty::IsPropertyAnimatable(aPropID),
29 "Shouldn't get here for non-animatable properties");
31 nsIDocument* doc = aElem->GetCurrentDoc();
32 if (!doc) {
33 // This can happen if we process certain types of restyles mid-sample
34 // and remove anonymous animated content from the document as a result.
35 // See bug 534975.
36 return false;
37 }
39 nsIPresShell* shell = doc->GetShell();
40 if (!shell) {
41 NS_WARNING("Unable to look up computed style -- no pres shell");
42 return false;
43 }
45 nsRefPtr<nsComputedDOMStyle> computedStyle =
46 NS_NewComputedDOMStyle(aElem, EmptyString(), shell);
48 computedStyle->GetPropertyValue(aPropID, aResult);
49 return true;
50 }
52 // Class Methods
53 nsSMILCSSProperty::nsSMILCSSProperty(nsCSSProperty aPropID,
54 Element* aElement)
55 : mPropID(aPropID), mElement(aElement)
56 {
57 NS_ABORT_IF_FALSE(IsPropertyAnimatable(mPropID),
58 "Creating a nsSMILCSSProperty for a property "
59 "that's not supported for animation");
60 }
62 nsSMILValue
63 nsSMILCSSProperty::GetBaseValue() const
64 {
65 // To benefit from Return Value Optimization and avoid copy constructor calls
66 // due to our use of return-by-value, we must return the exact same object
67 // from ALL return points. This function must only return THIS variable:
68 nsSMILValue baseValue;
70 // SPECIAL CASE: (a) Shorthands
71 // (b) 'display'
72 if (nsCSSProps::IsShorthand(mPropID) || mPropID == eCSSProperty_display) {
73 // We can't look up the base (computed-style) value of shorthand
74 // properties because they aren't guaranteed to have a consistent computed
75 // value.
76 //
77 // Also, although we can look up the base value of the display property,
78 // doing so involves clearing and resetting the property which can cause
79 // frames to be recreated which we'd like to avoid.
80 //
81 // In either case, just return a dummy value (initialized with the right
82 // type, so as not to indicate failure).
83 nsSMILValue tmpVal(&nsSMILCSSValueType::sSingleton);
84 baseValue.Swap(tmpVal);
85 return baseValue;
86 }
88 // GENERAL CASE: Non-Shorthands
89 // (1) Put empty string in override style for property mPropID
90 // (saving old override style value, so we can set it again when we're done)
91 nsICSSDeclaration* overrideDecl = mElement->GetSMILOverrideStyle();
92 nsAutoString cachedOverrideStyleVal;
93 if (overrideDecl) {
94 overrideDecl->GetPropertyValue(mPropID, cachedOverrideStyleVal);
95 // (Don't bother clearing override style if it's already empty)
96 if (!cachedOverrideStyleVal.IsEmpty()) {
97 overrideDecl->SetPropertyValue(mPropID, EmptyString());
98 }
99 }
101 // (2) Get Computed Style
102 nsAutoString computedStyleVal;
103 bool didGetComputedVal = GetCSSComputedValue(mElement, mPropID,
104 computedStyleVal);
106 // (3) Put cached override style back (if it's non-empty)
107 if (overrideDecl && !cachedOverrideStyleVal.IsEmpty()) {
108 overrideDecl->SetPropertyValue(mPropID, cachedOverrideStyleVal);
109 }
111 // (4) Populate our nsSMILValue from the computed style
112 if (didGetComputedVal) {
113 // When we parse animation values we check if they are context-sensitive or
114 // not so that we don't cache animation values whose meaning may change.
115 // For base values however this is unnecessary since on each sample the
116 // compositor will fetch the (computed) base value and compare it against
117 // the cached (computed) value and detect changes for us.
118 nsSMILCSSValueType::ValueFromString(mPropID, mElement,
119 computedStyleVal, baseValue,
120 nullptr);
121 }
122 return baseValue;
123 }
125 nsresult
126 nsSMILCSSProperty::ValueFromString(const nsAString& aStr,
127 const SVGAnimationElement* aSrcElement,
128 nsSMILValue& aValue,
129 bool& aPreventCachingOfSandwich) const
130 {
131 NS_ENSURE_TRUE(IsPropertyAnimatable(mPropID), NS_ERROR_FAILURE);
133 nsSMILCSSValueType::ValueFromString(mPropID, mElement, aStr, aValue,
134 &aPreventCachingOfSandwich);
136 if (aValue.IsNull()) {
137 return NS_ERROR_FAILURE;
138 }
140 // XXX Due to bug 536660 (or at least that seems to be the most likely
141 // culprit), when we have animation setting display:none on a <use> element,
142 // if we DON'T set the property every sample, chaos ensues.
143 if (!aPreventCachingOfSandwich && mPropID == eCSSProperty_display) {
144 aPreventCachingOfSandwich = true;
145 }
146 return NS_OK;
147 }
149 nsresult
150 nsSMILCSSProperty::SetAnimValue(const nsSMILValue& aValue)
151 {
152 NS_ENSURE_TRUE(IsPropertyAnimatable(mPropID), NS_ERROR_FAILURE);
154 // Convert nsSMILValue to string
155 nsAutoString valStr;
156 if (!nsSMILCSSValueType::ValueToString(aValue, valStr)) {
157 NS_WARNING("Failed to convert nsSMILValue for CSS property into a string");
158 return NS_ERROR_FAILURE;
159 }
161 // Use string value to style the target element
162 nsICSSDeclaration* overrideDecl = mElement->GetSMILOverrideStyle();
163 if (overrideDecl) {
164 nsAutoString oldValStr;
165 overrideDecl->GetPropertyValue(mPropID, oldValStr);
166 if (valStr.Equals(oldValStr)) {
167 return NS_OK;
168 }
169 overrideDecl->SetPropertyValue(mPropID, valStr);
170 }
171 return NS_OK;
172 }
174 void
175 nsSMILCSSProperty::ClearAnimValue()
176 {
177 // Put empty string in override style for our property
178 nsICSSDeclaration* overrideDecl = mElement->GetSMILOverrideStyle();
179 if (overrideDecl) {
180 overrideDecl->SetPropertyValue(mPropID, EmptyString());
181 }
182 }
184 // Based on http://www.w3.org/TR/SVG/propidx.html
185 // static
186 bool
187 nsSMILCSSProperty::IsPropertyAnimatable(nsCSSProperty aPropID)
188 {
189 // NOTE: Right now, Gecko doesn't recognize the following properties from
190 // the SVG Property Index:
191 // alignment-baseline
192 // baseline-shift
193 // color-profile
194 // color-rendering
195 // glyph-orientation-horizontal
196 // glyph-orientation-vertical
197 // kerning
198 // writing-mode
200 switch (aPropID) {
201 case eCSSProperty_clip:
202 case eCSSProperty_clip_rule:
203 case eCSSProperty_clip_path:
204 case eCSSProperty_color:
205 case eCSSProperty_color_interpolation:
206 case eCSSProperty_color_interpolation_filters:
207 case eCSSProperty_cursor:
208 case eCSSProperty_display:
209 case eCSSProperty_dominant_baseline:
210 case eCSSProperty_fill:
211 case eCSSProperty_fill_opacity:
212 case eCSSProperty_fill_rule:
213 case eCSSProperty_filter:
214 case eCSSProperty_flood_color:
215 case eCSSProperty_flood_opacity:
216 case eCSSProperty_font:
217 case eCSSProperty_font_family:
218 case eCSSProperty_font_size:
219 case eCSSProperty_font_size_adjust:
220 case eCSSProperty_font_stretch:
221 case eCSSProperty_font_style:
222 case eCSSProperty_font_variant:
223 case eCSSProperty_font_weight:
224 case eCSSProperty_height:
225 case eCSSProperty_image_rendering:
226 case eCSSProperty_letter_spacing:
227 case eCSSProperty_lighting_color:
228 case eCSSProperty_marker:
229 case eCSSProperty_marker_end:
230 case eCSSProperty_marker_mid:
231 case eCSSProperty_marker_start:
232 case eCSSProperty_mask:
233 case eCSSProperty_mask_type:
234 case eCSSProperty_opacity:
235 case eCSSProperty_overflow:
236 case eCSSProperty_pointer_events:
237 case eCSSProperty_shape_rendering:
238 case eCSSProperty_stop_color:
239 case eCSSProperty_stop_opacity:
240 case eCSSProperty_stroke:
241 case eCSSProperty_stroke_dasharray:
242 case eCSSProperty_stroke_dashoffset:
243 case eCSSProperty_stroke_linecap:
244 case eCSSProperty_stroke_linejoin:
245 case eCSSProperty_stroke_miterlimit:
246 case eCSSProperty_stroke_opacity:
247 case eCSSProperty_stroke_width:
248 case eCSSProperty_text_anchor:
249 case eCSSProperty_text_decoration:
250 case eCSSProperty_text_decoration_line:
251 case eCSSProperty_text_rendering:
252 case eCSSProperty_vector_effect:
253 case eCSSProperty_width:
254 case eCSSProperty_visibility:
255 case eCSSProperty_word_spacing:
256 return true;
258 // EXPLICITLY NON-ANIMATABLE PROPERTIES:
259 // (Some of these aren't supported at all in Gecko -- I've commented those
260 // ones out. If/when we add support for them, uncomment their line here)
261 // ----------------------------------------------------------------------
262 // case eCSSProperty_enable_background:
263 // case eCSSProperty_glyph_orientation_horizontal:
264 // case eCSSProperty_glyph_orientation_vertical:
265 // case eCSSProperty_writing_mode:
266 case eCSSProperty_direction:
267 case eCSSProperty_unicode_bidi:
268 return false;
270 default:
271 return false;
272 }
273 }