dom/smil/nsSMILCSSProperty.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/dom/smil/nsSMILCSSProperty.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,273 @@
     1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +/* representation of a SMIL-animatable CSS property on an element */
    1.10 +
    1.11 +#include "nsSMILCSSProperty.h"
    1.12 +#include "nsSMILCSSValueType.h"
    1.13 +#include "nsSMILValue.h"
    1.14 +#include "nsComputedDOMStyle.h"
    1.15 +#include "nsCSSProps.h"
    1.16 +#include "nsStyleAnimation.h"
    1.17 +#include "mozilla/dom/Element.h"
    1.18 +#include "nsIDOMElement.h"
    1.19 +#include "nsIDocument.h"
    1.20 +
    1.21 +using namespace mozilla::dom;
    1.22 +
    1.23 +// Helper function
    1.24 +static bool
    1.25 +GetCSSComputedValue(Element* aElem,
    1.26 +                    nsCSSProperty aPropID,
    1.27 +                    nsAString& aResult)
    1.28 +{
    1.29 +  NS_ABORT_IF_FALSE(!nsCSSProps::IsShorthand(aPropID),
    1.30 +                    "Can't look up computed value of shorthand property");
    1.31 +  NS_ABORT_IF_FALSE(nsSMILCSSProperty::IsPropertyAnimatable(aPropID),
    1.32 +                    "Shouldn't get here for non-animatable properties");
    1.33 +
    1.34 +  nsIDocument* doc = aElem->GetCurrentDoc();
    1.35 +  if (!doc) {
    1.36 +    // This can happen if we process certain types of restyles mid-sample
    1.37 +    // and remove anonymous animated content from the document as a result.
    1.38 +    // See bug 534975.
    1.39 +    return false;
    1.40 +  }
    1.41 +
    1.42 +  nsIPresShell* shell = doc->GetShell();
    1.43 +  if (!shell) {
    1.44 +    NS_WARNING("Unable to look up computed style -- no pres shell");
    1.45 +    return false;
    1.46 +  }
    1.47 +
    1.48 +  nsRefPtr<nsComputedDOMStyle> computedStyle =
    1.49 +    NS_NewComputedDOMStyle(aElem, EmptyString(), shell);
    1.50 +
    1.51 +  computedStyle->GetPropertyValue(aPropID, aResult);
    1.52 +  return true;
    1.53 +}
    1.54 +
    1.55 +// Class Methods
    1.56 +nsSMILCSSProperty::nsSMILCSSProperty(nsCSSProperty aPropID,
    1.57 +                                     Element* aElement)
    1.58 +  : mPropID(aPropID), mElement(aElement)
    1.59 +{
    1.60 +  NS_ABORT_IF_FALSE(IsPropertyAnimatable(mPropID),
    1.61 +                    "Creating a nsSMILCSSProperty for a property "
    1.62 +                    "that's not supported for animation");
    1.63 +}
    1.64 +
    1.65 +nsSMILValue
    1.66 +nsSMILCSSProperty::GetBaseValue() const
    1.67 +{
    1.68 +  // To benefit from Return Value Optimization and avoid copy constructor calls
    1.69 +  // due to our use of return-by-value, we must return the exact same object
    1.70 +  // from ALL return points. This function must only return THIS variable:
    1.71 +  nsSMILValue baseValue;
    1.72 +
    1.73 +  // SPECIAL CASE: (a) Shorthands
    1.74 +  //               (b) 'display'
    1.75 +  if (nsCSSProps::IsShorthand(mPropID) || mPropID == eCSSProperty_display) {
    1.76 +    // We can't look up the base (computed-style) value of shorthand
    1.77 +    // properties because they aren't guaranteed to have a consistent computed
    1.78 +    // value.
    1.79 +    //
    1.80 +    // Also, although we can look up the base value of the display property,
    1.81 +    // doing so involves clearing and resetting the property which can cause
    1.82 +    // frames to be recreated which we'd like to avoid.
    1.83 +    //
    1.84 +    // In either case, just return a dummy value (initialized with the right
    1.85 +    // type, so as not to indicate failure).
    1.86 +    nsSMILValue tmpVal(&nsSMILCSSValueType::sSingleton);
    1.87 +    baseValue.Swap(tmpVal);
    1.88 +    return baseValue;
    1.89 +  }
    1.90 +
    1.91 +  // GENERAL CASE: Non-Shorthands
    1.92 +  // (1) Put empty string in override style for property mPropID
    1.93 +  // (saving old override style value, so we can set it again when we're done)
    1.94 +  nsICSSDeclaration* overrideDecl = mElement->GetSMILOverrideStyle();
    1.95 +  nsAutoString cachedOverrideStyleVal;
    1.96 +  if (overrideDecl) {
    1.97 +    overrideDecl->GetPropertyValue(mPropID, cachedOverrideStyleVal);
    1.98 +    // (Don't bother clearing override style if it's already empty)
    1.99 +    if (!cachedOverrideStyleVal.IsEmpty()) {
   1.100 +      overrideDecl->SetPropertyValue(mPropID, EmptyString());
   1.101 +    }
   1.102 +  }
   1.103 +
   1.104 +  // (2) Get Computed Style
   1.105 +  nsAutoString computedStyleVal;
   1.106 +  bool didGetComputedVal = GetCSSComputedValue(mElement, mPropID,
   1.107 +                                                 computedStyleVal);
   1.108 +
   1.109 +  // (3) Put cached override style back (if it's non-empty)
   1.110 +  if (overrideDecl && !cachedOverrideStyleVal.IsEmpty()) {
   1.111 +    overrideDecl->SetPropertyValue(mPropID, cachedOverrideStyleVal);
   1.112 +  }
   1.113 +
   1.114 +  // (4) Populate our nsSMILValue from the computed style
   1.115 +  if (didGetComputedVal) {
   1.116 +    // When we parse animation values we check if they are context-sensitive or
   1.117 +    // not so that we don't cache animation values whose meaning may change.
   1.118 +    // For base values however this is unnecessary since on each sample the
   1.119 +    // compositor will fetch the (computed) base value and compare it against
   1.120 +    // the cached (computed) value and detect changes for us.
   1.121 +    nsSMILCSSValueType::ValueFromString(mPropID, mElement,
   1.122 +                                        computedStyleVal, baseValue,
   1.123 +                                        nullptr);
   1.124 +  }
   1.125 +  return baseValue;
   1.126 +}
   1.127 +
   1.128 +nsresult
   1.129 +nsSMILCSSProperty::ValueFromString(const nsAString& aStr,
   1.130 +                                   const SVGAnimationElement* aSrcElement,
   1.131 +                                   nsSMILValue& aValue,
   1.132 +                                   bool& aPreventCachingOfSandwich) const
   1.133 +{
   1.134 +  NS_ENSURE_TRUE(IsPropertyAnimatable(mPropID), NS_ERROR_FAILURE);
   1.135 +
   1.136 +  nsSMILCSSValueType::ValueFromString(mPropID, mElement, aStr, aValue,
   1.137 +      &aPreventCachingOfSandwich);
   1.138 +
   1.139 +  if (aValue.IsNull()) {
   1.140 +    return NS_ERROR_FAILURE;
   1.141 +  }
   1.142 +
   1.143 +  // XXX Due to bug 536660 (or at least that seems to be the most likely
   1.144 +  // culprit), when we have animation setting display:none on a <use> element,
   1.145 +  // if we DON'T set the property every sample, chaos ensues.
   1.146 +  if (!aPreventCachingOfSandwich && mPropID == eCSSProperty_display) {
   1.147 +    aPreventCachingOfSandwich = true;
   1.148 +  }
   1.149 +  return NS_OK;
   1.150 +}
   1.151 +
   1.152 +nsresult
   1.153 +nsSMILCSSProperty::SetAnimValue(const nsSMILValue& aValue)
   1.154 +{
   1.155 +  NS_ENSURE_TRUE(IsPropertyAnimatable(mPropID), NS_ERROR_FAILURE);
   1.156 +
   1.157 +  // Convert nsSMILValue to string
   1.158 +  nsAutoString valStr;
   1.159 +  if (!nsSMILCSSValueType::ValueToString(aValue, valStr)) {
   1.160 +    NS_WARNING("Failed to convert nsSMILValue for CSS property into a string");
   1.161 +    return NS_ERROR_FAILURE;
   1.162 +  }
   1.163 +
   1.164 +  // Use string value to style the target element
   1.165 +  nsICSSDeclaration* overrideDecl = mElement->GetSMILOverrideStyle();
   1.166 +  if (overrideDecl) {
   1.167 +    nsAutoString oldValStr;
   1.168 +    overrideDecl->GetPropertyValue(mPropID, oldValStr);
   1.169 +    if (valStr.Equals(oldValStr)) {
   1.170 +      return NS_OK;
   1.171 +    }
   1.172 +    overrideDecl->SetPropertyValue(mPropID, valStr);
   1.173 +  }
   1.174 +  return NS_OK;
   1.175 +}
   1.176 +
   1.177 +void
   1.178 +nsSMILCSSProperty::ClearAnimValue()
   1.179 +{
   1.180 +  // Put empty string in override style for our property
   1.181 +  nsICSSDeclaration* overrideDecl = mElement->GetSMILOverrideStyle();
   1.182 +  if (overrideDecl) {
   1.183 +    overrideDecl->SetPropertyValue(mPropID, EmptyString());
   1.184 +  }
   1.185 +}
   1.186 +
   1.187 +// Based on http://www.w3.org/TR/SVG/propidx.html
   1.188 +// static
   1.189 +bool
   1.190 +nsSMILCSSProperty::IsPropertyAnimatable(nsCSSProperty aPropID)
   1.191 +{
   1.192 +  // NOTE: Right now, Gecko doesn't recognize the following properties from
   1.193 +  // the SVG Property Index:
   1.194 +  //   alignment-baseline
   1.195 +  //   baseline-shift
   1.196 +  //   color-profile
   1.197 +  //   color-rendering
   1.198 +  //   glyph-orientation-horizontal
   1.199 +  //   glyph-orientation-vertical
   1.200 +  //   kerning
   1.201 +  //   writing-mode
   1.202 +
   1.203 +  switch (aPropID) {
   1.204 +    case eCSSProperty_clip:
   1.205 +    case eCSSProperty_clip_rule:
   1.206 +    case eCSSProperty_clip_path:
   1.207 +    case eCSSProperty_color:
   1.208 +    case eCSSProperty_color_interpolation:
   1.209 +    case eCSSProperty_color_interpolation_filters:
   1.210 +    case eCSSProperty_cursor:
   1.211 +    case eCSSProperty_display:
   1.212 +    case eCSSProperty_dominant_baseline:
   1.213 +    case eCSSProperty_fill:
   1.214 +    case eCSSProperty_fill_opacity:
   1.215 +    case eCSSProperty_fill_rule:
   1.216 +    case eCSSProperty_filter:
   1.217 +    case eCSSProperty_flood_color:
   1.218 +    case eCSSProperty_flood_opacity:
   1.219 +    case eCSSProperty_font:
   1.220 +    case eCSSProperty_font_family:
   1.221 +    case eCSSProperty_font_size:
   1.222 +    case eCSSProperty_font_size_adjust:
   1.223 +    case eCSSProperty_font_stretch:
   1.224 +    case eCSSProperty_font_style:
   1.225 +    case eCSSProperty_font_variant:
   1.226 +    case eCSSProperty_font_weight:
   1.227 +    case eCSSProperty_height:
   1.228 +    case eCSSProperty_image_rendering:
   1.229 +    case eCSSProperty_letter_spacing:
   1.230 +    case eCSSProperty_lighting_color:
   1.231 +    case eCSSProperty_marker:
   1.232 +    case eCSSProperty_marker_end:
   1.233 +    case eCSSProperty_marker_mid:
   1.234 +    case eCSSProperty_marker_start:
   1.235 +    case eCSSProperty_mask:
   1.236 +    case eCSSProperty_mask_type:
   1.237 +    case eCSSProperty_opacity:
   1.238 +    case eCSSProperty_overflow:
   1.239 +    case eCSSProperty_pointer_events:
   1.240 +    case eCSSProperty_shape_rendering:
   1.241 +    case eCSSProperty_stop_color:
   1.242 +    case eCSSProperty_stop_opacity:
   1.243 +    case eCSSProperty_stroke:
   1.244 +    case eCSSProperty_stroke_dasharray:
   1.245 +    case eCSSProperty_stroke_dashoffset:
   1.246 +    case eCSSProperty_stroke_linecap:
   1.247 +    case eCSSProperty_stroke_linejoin:
   1.248 +    case eCSSProperty_stroke_miterlimit:
   1.249 +    case eCSSProperty_stroke_opacity:
   1.250 +    case eCSSProperty_stroke_width:
   1.251 +    case eCSSProperty_text_anchor:
   1.252 +    case eCSSProperty_text_decoration:
   1.253 +    case eCSSProperty_text_decoration_line:
   1.254 +    case eCSSProperty_text_rendering:
   1.255 +    case eCSSProperty_vector_effect:
   1.256 +    case eCSSProperty_width:
   1.257 +    case eCSSProperty_visibility:
   1.258 +    case eCSSProperty_word_spacing:
   1.259 +      return true;
   1.260 +
   1.261 +    // EXPLICITLY NON-ANIMATABLE PROPERTIES:
   1.262 +    // (Some of these aren't supported at all in Gecko -- I've commented those
   1.263 +    // ones out. If/when we add support for them, uncomment their line here)
   1.264 +    // ----------------------------------------------------------------------
   1.265 +    // case eCSSProperty_enable_background:
   1.266 +    // case eCSSProperty_glyph_orientation_horizontal:
   1.267 +    // case eCSSProperty_glyph_orientation_vertical:
   1.268 +    // case eCSSProperty_writing_mode:
   1.269 +    case eCSSProperty_direction:
   1.270 +    case eCSSProperty_unicode_bidi:
   1.271 +      return false;
   1.272 +
   1.273 +    default:
   1.274 +      return false;
   1.275 +  }
   1.276 +}

mercurial