dom/smil/nsSMILCompositor.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

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 #include "nsSMILCompositor.h"
     7 #include "nsSMILCSSProperty.h"
     8 #include "nsCSSProps.h"
     9 #include "nsHashKeys.h"
    11 // PLDHashEntryHdr methods
    12 bool
    13 nsSMILCompositor::KeyEquals(KeyTypePointer aKey) const
    14 {
    15   return aKey && aKey->Equals(mKey);
    16 }
    18 /*static*/ PLDHashNumber
    19 nsSMILCompositor::HashKey(KeyTypePointer aKey)
    20 {
    21   // Combine the 3 values into one numeric value, which will be hashed.
    22   // NOTE: We right-shift one of the pointers by 2 to get some randomness in
    23   // its 2 lowest-order bits. (Those shifted-off bits will always be 0 since
    24   // our pointers will be word-aligned.)
    25   return (NS_PTR_TO_UINT32(aKey->mElement.get()) >> 2) +
    26     NS_PTR_TO_UINT32(aKey->mAttributeName.get()) +
    27     (aKey->mIsCSS ? 1 : 0);
    28 }
    30 // Cycle-collection support
    31 void
    32 nsSMILCompositor::Traverse(nsCycleCollectionTraversalCallback* aCallback)
    33 {
    34   if (!mKey.mElement)
    35     return;
    37   NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*aCallback, "Compositor mKey.mElement");
    38   aCallback->NoteXPCOMChild(mKey.mElement);
    39 }
    41 // Other methods
    42 void
    43 nsSMILCompositor::AddAnimationFunction(nsSMILAnimationFunction* aFunc)
    44 {
    45   if (aFunc) {
    46     mAnimationFunctions.AppendElement(aFunc);
    47   }
    48 }
    50 void
    51 nsSMILCompositor::ComposeAttribute()
    52 {
    53   if (!mKey.mElement)
    54     return;
    56   // FIRST: Get the nsISMILAttr (to grab base value from, and to eventually
    57   // give animated value to)
    58   nsAutoPtr<nsISMILAttr> smilAttr(CreateSMILAttr());
    59   if (!smilAttr) {
    60     // Target attribute not found (or, out of memory)
    61     return;
    62   }
    63   if (mAnimationFunctions.IsEmpty()) {
    64     // No active animation functions. (We can still have a nsSMILCompositor in
    65     // that case if an animation function has *just* become inactive)
    66     smilAttr->ClearAnimValue();
    67     return;
    68   }
    70   // SECOND: Sort the animationFunctions, to prepare for compositing.
    71   nsSMILAnimationFunction::Comparator comparator;
    72   mAnimationFunctions.Sort(comparator);
    74   // THIRD: Step backwards through animation functions to find out
    75   // which ones we actually care about.
    76   uint32_t firstFuncToCompose = GetFirstFuncToAffectSandwich();
    78   // FOURTH: Get & cache base value
    79   nsSMILValue sandwichResultValue;
    80   if (!mAnimationFunctions[firstFuncToCompose]->WillReplace()) {
    81     sandwichResultValue = smilAttr->GetBaseValue();
    82   }
    83   UpdateCachedBaseValue(sandwichResultValue);
    85   if (!mForceCompositing) {
    86     return;
    87   }
    89   // FIFTH: Compose animation functions
    90   uint32_t length = mAnimationFunctions.Length();
    91   for (uint32_t i = firstFuncToCompose; i < length; ++i) {
    92     mAnimationFunctions[i]->ComposeResult(*smilAttr, sandwichResultValue);
    93   }
    94   if (sandwichResultValue.IsNull()) {
    95     smilAttr->ClearAnimValue();
    96     return;
    97   }
    99   // SIXTH: Set the animated value to the final composited result.
   100   nsresult rv = smilAttr->SetAnimValue(sandwichResultValue);
   101   if (NS_FAILED(rv)) {
   102     NS_WARNING("nsISMILAttr::SetAnimValue failed");
   103   }
   104 }
   106 void
   107 nsSMILCompositor::ClearAnimationEffects()
   108 {
   109   if (!mKey.mElement || !mKey.mAttributeName)
   110     return;
   112   nsAutoPtr<nsISMILAttr> smilAttr(CreateSMILAttr());
   113   if (!smilAttr) {
   114     // Target attribute not found (or, out of memory)
   115     return;
   116   }
   117   smilAttr->ClearAnimValue();
   118 }
   120 // Protected Helper Functions
   121 // --------------------------
   122 nsISMILAttr*
   123 nsSMILCompositor::CreateSMILAttr()
   124 {
   125   if (mKey.mIsCSS) {
   126     nsCSSProperty propId =
   127       nsCSSProps::LookupProperty(nsDependentAtomString(mKey.mAttributeName),
   128                                  nsCSSProps::eEnabledForAllContent);
   129     if (nsSMILCSSProperty::IsPropertyAnimatable(propId)) {
   130       return new nsSMILCSSProperty(propId, mKey.mElement.get());
   131     }
   132   } else {
   133     return mKey.mElement->GetAnimatedAttr(mKey.mAttributeNamespaceID,
   134                                           mKey.mAttributeName);
   135   }
   136   return nullptr;
   137 }
   139 uint32_t
   140 nsSMILCompositor::GetFirstFuncToAffectSandwich()
   141 {
   142   uint32_t i;
   143   for (i = mAnimationFunctions.Length(); i > 0; --i) {
   144     nsSMILAnimationFunction* curAnimFunc = mAnimationFunctions[i-1];
   145     // In the following, the lack of short-circuit behavior of |= means that we
   146     // will ALWAYS run UpdateCachedTarget (even if mForceCompositing is true)
   147     // but only call HasChanged and WasSkippedInPrevSample if necessary.  This
   148     // is important since we need UpdateCachedTarget to run in order to detect
   149     // changes to the target in subsequent samples.
   150     mForceCompositing |=
   151       curAnimFunc->UpdateCachedTarget(mKey) ||
   152       curAnimFunc->HasChanged() ||
   153       curAnimFunc->WasSkippedInPrevSample();
   155     if (curAnimFunc->WillReplace()) {
   156       --i;
   157       break;
   158     }
   159   }
   160   // Mark remaining animation functions as having been skipped so if we later
   161   // use them we'll know to force compositing.
   162   // Note that we only really need to do this if something has changed
   163   // (otherwise we would have set the flag on a previous sample) and if
   164   // something has changed mForceCompositing will be true.
   165   if (mForceCompositing) {
   166     for (uint32_t j = i; j > 0; --j) {
   167       mAnimationFunctions[j-1]->SetWasSkipped();
   168     }
   169   }
   170   return i;
   171 }
   173 void
   174 nsSMILCompositor::UpdateCachedBaseValue(const nsSMILValue& aBaseValue)
   175 {
   176   if (!mCachedBaseValue) {
   177     // We don't have last sample's base value cached. Assume it's changed.
   178     mCachedBaseValue = new nsSMILValue(aBaseValue);
   179     NS_WARN_IF_FALSE(mCachedBaseValue, "failed to cache base value (OOM?)");
   180     mForceCompositing = true;
   181   } else if (*mCachedBaseValue != aBaseValue) {
   182     // Base value has changed since last sample.
   183     *mCachedBaseValue = aBaseValue;
   184     mForceCompositing = true;
   185   }
   186 }

mercurial