DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Header

Mercurial (31ec81b5d7bb)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

/* representation of a SMIL-animatable mapped attribute on an element */
#include "nsSMILMappedAttribute.h"
#include "nsContentUtils.h"
#include "nsError.h" // For NS_PROPTABLE_PROP_OVERWRITTEN
#include "nsSMILValue.h"
#include "nsSMILCSSValueType.h"
#include "nsIDocument.h"
#include "nsIPresShell.h"
#include "nsCSSProps.h"
#include "mozilla/dom/Element.h"

// Callback function, for freeing string buffers stored in property table
static void
ReleaseStringBufferPropertyValue(void*    aObject,       /* unused */
                                 nsIAtom* aPropertyName, /* unused */
                                 void*    aPropertyValue,
                                 void*    aData          /* unused */)
{
  nsStringBuffer* buf = static_cast<nsStringBuffer*>(aPropertyValue);
  buf->Release();
}


nsresult
nsSMILMappedAttribute::ValueFromString(const nsAString& aStr,
                                       const mozilla::dom::SVGAnimationElement* aSrcElement,
                                       nsSMILValue& aValue,
                                       bool& aPreventCachingOfSandwich) const
{
  NS_ENSURE_TRUE(IsPropertyAnimatable(mPropID), NS_ERROR_FAILURE);

  nsSMILCSSValueType::ValueFromString(mPropID, mElement, aStr, aValue,
                                      &aPreventCachingOfSandwich);
  return aValue.IsNull() ? NS_ERROR_FAILURE : NS_OK;
}

nsSMILValue
nsSMILMappedAttribute::GetBaseValue() const
{
  nsAutoString baseStringValue;
  nsRefPtr<nsIAtom> attrName = GetAttrNameAtom();
  bool success = mElement->GetAttr(kNameSpaceID_None, attrName,
                                     baseStringValue);
  nsSMILValue baseValue;
  if (success) {
    // For base values, we don't need to worry whether the value returned is
    // context-sensitive or not since the compositor will take care of comparing
    // the returned (computed) base value and its cached value and determining
    // if an update is required or not.
    nsSMILCSSValueType::ValueFromString(mPropID, mElement,
                                        baseStringValue, baseValue, nullptr);
  } else {
    // Attribute is unset -- use computed value.
    // FIRST: Temporarily clear animated value, to make sure it doesn't pollute
    // the computed value. (We want base value, _without_ animations applied.)
    void* buf = mElement->UnsetProperty(SMIL_MAPPED_ATTR_ANIMVAL,
                                        attrName, nullptr);
    FlushChangesToTargetAttr();

    // SECOND: we use nsSMILCSSProperty::GetBaseValue to look up the property's
    // computed value.  NOTE: This call will temporarily clear the SMIL
    // override-style for the corresponding CSS property on our target element.
    // This prevents any animations that target the CSS property from affecting
    // animations that target the mapped attribute.
    baseValue = nsSMILCSSProperty::GetBaseValue();

    // FINALLY: If we originally had an animated value set, then set it again.
    if (buf) {
      mElement->SetProperty(SMIL_MAPPED_ATTR_ANIMVAL, attrName, buf,
                            ReleaseStringBufferPropertyValue);
      FlushChangesToTargetAttr();
    }
  }
  return baseValue;
}

nsresult
nsSMILMappedAttribute::SetAnimValue(const nsSMILValue& aValue)
{
  NS_ENSURE_TRUE(IsPropertyAnimatable(mPropID), NS_ERROR_FAILURE);

  // Convert nsSMILValue to string
  nsAutoString valStr;
  if (!nsSMILCSSValueType::ValueToString(aValue, valStr)) {
    NS_WARNING("Failed to convert nsSMILValue for mapped attr into a string");
    return NS_ERROR_FAILURE;
  }

  nsRefPtr<nsIAtom> attrName = GetAttrNameAtom();
  nsStringBuffer* oldValStrBuf = static_cast<nsStringBuffer*>
    (mElement->GetProperty(SMIL_MAPPED_ATTR_ANIMVAL, attrName));
  if (oldValStrBuf) {
    nsString oldValStr;
    nsContentUtils::PopulateStringFromStringBuffer(oldValStrBuf, oldValStr);
    if (valStr.Equals(oldValStr)) {
      // New animated value is the same as the old; nothing to do.
      return NS_OK;
    }
  }

  // Set the string as this mapped attribute's animated value.
  nsStringBuffer* valStrBuf =
    nsCSSValue::BufferFromString(nsString(valStr)).get();
  nsresult rv = mElement->SetProperty(SMIL_MAPPED_ATTR_ANIMVAL,
                                      attrName, valStrBuf,
                                      ReleaseStringBufferPropertyValue);
  if (rv == NS_PROPTABLE_PROP_OVERWRITTEN) {
    rv = NS_OK;
  }
  FlushChangesToTargetAttr();

  return rv;
}

void
nsSMILMappedAttribute::ClearAnimValue()
{
  nsRefPtr<nsIAtom> attrName = GetAttrNameAtom();
  mElement->DeleteProperty(SMIL_MAPPED_ATTR_ANIMVAL, attrName);
  FlushChangesToTargetAttr();
}

void
nsSMILMappedAttribute::FlushChangesToTargetAttr() const
{
  // Clear animated content-style-rule
  mElement->DeleteProperty(SMIL_MAPPED_ATTR_ANIMVAL,
                           SMIL_MAPPED_ATTR_STYLERULE_ATOM);
  nsIDocument* doc = mElement->GetCurrentDoc();

  // Request animation restyle
  if (doc) {
    nsIPresShell* shell = doc->GetShell();
    if (shell) {
      shell->RestyleForAnimation(mElement, eRestyle_Self);
    }
  }
}

already_AddRefed<nsIAtom>
nsSMILMappedAttribute::GetAttrNameAtom() const
{
  return do_GetAtom(nsCSSProps::GetStringValue(mPropID));
}