static v8::Handle<v8::Value> endElementCallback(const v8::Arguments& args)
{
    INC_STATS("DOM.SVGAnimationElement.endElement");
    SVGAnimationElement* imp = V8SVGAnimationElement::toNative(args.Holder());
    imp->endElement();
    return v8::Handle<v8::Value>();
}
static v8::Handle<v8::Value> hasExtensionCallback(const v8::Arguments& args)
{
    INC_STATS("DOM.SVGAnimationElement.hasExtension");
    SVGAnimationElement* imp = V8SVGAnimationElement::toNative(args.Holder());
    STRING_TO_V8PARAMETER_EXCEPTION_BLOCK(V8Parameter<>, extension, args[0]);
    return v8Boolean(imp->hasExtension(extension));
}
Exemplo n.º 3
0
SVGTimer::TargetAnimationMap SVGTimer::animationsByElement(double elapsedSeconds)
{
    // Build a list of all animations which apply to each element
    // FIXME: This list should be sorted by animation priority
    ExceptionCode ec = 0;
    TargetAnimationMap targetMap;
    SVGNotifySet::const_iterator end = m_notifySet.end();
    for (SVGNotifySet::const_iterator it = m_notifySet.begin(); it != end; ++it) {
        SVGAnimationElement* animation = *it;
        
        // If we're dealing with a disabled element with fill="freeze",
        // we have to take it into account for further calculations.
        if (!m_enabledNotifySet.contains(animation)) {
            if (!animation->isFrozen())
                continue;
            if (elapsedSeconds <= (animation->getStartTime() + animation->getSimpleDuration(ec)))
                continue;
        }
        
        SVGElement* target = const_cast<SVGElement*>(animation->targetElement());
        TargetAnimationMap::iterator i = targetMap.find(target);
        if (i != targetMap.end())
            i->second.append(animation);
        else {
            Vector<SVGAnimationElement*> list;
            list.append(animation);
            targetMap.set(target, list);
        }
    }
    return targetMap;
}
void
nsSMILAnimationController::RewindElements()
{
  bool rewindNeeded = false;
  for (auto iter = mChildContainerTable.Iter(); !iter.Done(); iter.Next()) {
    nsSMILTimeContainer* container = iter.Get()->GetKey();
    if (container->NeedsRewind()) {
      rewindNeeded = true;
      break;
    }
  }

  if (!rewindNeeded)
    return;

  for (auto iter = mAnimationElementTable.Iter(); !iter.Done(); iter.Next()) {
    SVGAnimationElement* animElem = iter.Get()->GetKey();
    nsSMILTimeContainer* timeContainer = animElem->GetTimeContainer();
    if (timeContainer && timeContainer->NeedsRewind()) {
      animElem->TimedElement().Rewind();
    }
  }

  for (auto iter = mChildContainerTable.Iter(); !iter.Done(); iter.Next()) {
    iter.Get()->GetKey()->ClearNeedsRewind();
  }
}
static v8::Handle<v8::Value> externalResourcesRequiredAttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info)
{
    INC_STATS("DOM.SVGAnimationElement.externalResourcesRequired._get");
    SVGAnimationElement* imp = V8SVGAnimationElement::toNative(info.Holder());
    SVGElement* context = imp;
    PassRefPtr<SVGAnimatedBoolean> resultAsPassRefPtr = V8Proxy::withSVGContext(imp->externalResourcesRequiredAnimated(), context);
    return toV8(resultAsPassRefPtr);
}
static v8::Handle<v8::Value> systemLanguageAttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info)
{
    INC_STATS("DOM.SVGAnimationElement.systemLanguage._get");
    SVGAnimationElement* imp = V8SVGAnimationElement::toNative(info.Holder());
    SVGElement* context = imp;
    PassRefPtr<SVGStringList> resultAsPassRefPtr = V8Proxy::withSVGContext(imp->systemLanguage(), context);
    return toV8(resultAsPassRefPtr);
}
static v8::Handle<v8::Value> endElementAtCallback(const v8::Arguments& args)
{
    INC_STATS("DOM.SVGAnimationElement.endElementAt");
    SVGAnimationElement* imp = V8SVGAnimationElement::toNative(args.Holder());
    EXCEPTION_BLOCK(float, offset, static_cast<float>(args[0]->NumberValue()));
    imp->endElementAt(offset);
    return v8::Handle<v8::Value>();
}
/*static*/ PLDHashOperator
nsSMILAnimationController::RewindAnimation(AnimationElementPtrKey* aKey,
                                           void* aData)
{
  SVGAnimationElement* animElem = aKey->GetKey();
  nsSMILTimeContainer* timeContainer = animElem->GetTimeContainer();
  if (timeContainer && timeContainer->NeedsRewind()) {
    animElem->TimedElement().Rewind();
  }

  return PL_DHASH_NEXT;
}
static v8::Handle<v8::Value> getSimpleDurationCallback(const v8::Arguments& args)
{
    INC_STATS("DOM.SVGAnimationElement.getSimpleDuration");
    SVGAnimationElement* imp = V8SVGAnimationElement::toNative(args.Holder());
    ExceptionCode ec = 0;
    {
    float result = imp->getSimpleDuration(ec);
    if (UNLIKELY(ec))
        goto fail;
    return v8::Number::New(result);
    }
    fail:
    V8Proxy::setDOMException(ec);
    return v8::Handle<v8::Value>();
}
/*static*/ PLDHashOperator
nsSMILAnimationController::SampleAnimation(AnimationElementPtrKey* aKey,
                                           void* aData)
{
  NS_ENSURE_TRUE(aKey, PL_DHASH_NEXT);
  NS_ENSURE_TRUE(aKey->GetKey(), PL_DHASH_NEXT);
  NS_ENSURE_TRUE(aData, PL_DHASH_NEXT);

  SVGAnimationElement* animElem = aKey->GetKey();
  if (animElem->PassesConditionalProcessingTests()) {
    SampleAnimationParams* params = static_cast<SampleAnimationParams*>(aData);

    SampleTimedElement(animElem, params->mActiveContainers);
    AddAnimationToCompositorTable(animElem, params->mCompositorTable);
  }

  return PL_DHASH_NEXT;
}
Exemplo n.º 11
0
// FIXME: This funtion will eventually become part of the AnimationCompositor
void SVGTimer::applyAnimations(double elapsedSeconds, const SVGTimer::TargetAnimationMap& targetMap)
{    
    TargetAnimationMap::const_iterator targetIterator = targetMap.begin();
    TargetAnimationMap::const_iterator tend = targetMap.end();
    for (; targetIterator != tend; ++targetIterator) {
        // FIXME: This is still not 100% correct.  Correct would be:
        // 1. Walk backwards through the priority list until a replace (!isAdditive()) is found
        // -- This optimization is not possible without careful consideration for dependent values (such as cx and fx in SVGRadialGradient)
        // 2. Set the initial value (or last replace) as the new animVal
        // 3. Call each enabled animation in turn, to have it apply its changes
        // 4. After building a new animVal, set it on the element.
        
        // Currenly we use the actual animVal on the element as "temporary storage"
        // and abstract the getting/setting of the attributes into the SVGAnimate* classes
        
        unsigned count = targetIterator->second.size();
        for (unsigned i = 0; i < count; ++i) {
            SVGAnimationElement* animation = targetIterator->second[i];
            
            if (!animation->isValidAnimation())
                continue;
            
            if (!animation->updateAnimationBaseValueFromElement())
                continue;
            
            if (!animation->updateAnimatedValueForElapsedSeconds(elapsedSeconds))
                continue;
            
            animation->applyAnimatedValueToElement();
        }
    }
    
    // Make a second pass through the map to avoid multiple setChanged calls on the same element.
    for (targetIterator = targetMap.begin(); targetIterator != tend; ++targetIterator) {
        SVGElement* key = targetIterator->first;
        if (key && key->isStyled())
            static_cast<SVGStyledElement*>(key)->setChanged(true);
    }
}
void
nsSMILAnimationController::DoMilestoneSamples()
{
  // We need to sample the timing model but because SMIL operates independently
  // of the frame-rate, we can get one sample at t=0s and the next at t=10min.
  //
  // In between those two sample times a whole string of significant events
  // might be expected to take place: events firing, new interdependencies
  // between animations resolved and dissolved, etc.
  //
  // Furthermore, at any given time, we want to sample all the intervals that
  // end at that time BEFORE any that begin. This behaviour is implied by SMIL's
  // endpoint-exclusive timing model.
  //
  // So we have the animations (specifically the timed elements) register the
  // next significant moment (called a milestone) in their lifetime and then we
  // step through the model at each of these moments and sample those animations
  // registered for those times. This way events can fire in the correct order,
  // dependencies can be resolved etc.

  nsSMILTime sampleTime = INT64_MIN;

  while (true) {
    // We want to find any milestones AT OR BEFORE the current sample time so we
    // initialise the next milestone to the moment after (1ms after, to be
    // precise) the current sample time and see if there are any milestones
    // before that. Any other milestones will be dealt with in a subsequent
    // sample.
    nsSMILMilestone nextMilestone(GetCurrentTime() + 1, true);
    mChildContainerTable.EnumerateEntries(GetNextMilestone, &nextMilestone);

    if (nextMilestone.mTime > GetCurrentTime()) {
      break;
    }

    GetMilestoneElementsParams params;
    params.mMilestone = nextMilestone;
    mChildContainerTable.EnumerateEntries(GetMilestoneElements, &params);
    uint32_t length = params.mElements.Length();

    // During the course of a sampling we don't want to actually go backwards.
    // Due to negative offsets, early ends and the like, a timed element might
    // register a milestone that is actually in the past. That's fine, but it's
    // still only going to get *sampled* with whatever time we're up to and no
    // earlier.
    //
    // Because we're only performing this clamping at the last moment, the
    // animations will still all get sampled in the correct order and
    // dependencies will be appropriately resolved.
    sampleTime = std::max(nextMilestone.mTime, sampleTime);

    for (uint32_t i = 0; i < length; ++i) {
      SVGAnimationElement* elem = params.mElements[i].get();
      NS_ABORT_IF_FALSE(elem, "nullptr animation element in list");
      nsSMILTimeContainer* container = elem->GetTimeContainer();
      if (!container)
        // The container may be nullptr if the element has been detached from its
        // parent since registering a milestone.
        continue;

      nsSMILTimeValue containerTimeValue =
        container->ParentToContainerTime(sampleTime);
      if (!containerTimeValue.IsDefinite())
        continue;

      // Clamp the converted container time to non-negative values.
      nsSMILTime containerTime = std::max<nsSMILTime>(0, containerTimeValue.GetMillis());

      if (nextMilestone.mIsEnd) {
        elem->TimedElement().SampleEndAt(containerTime);
      } else {
        elem->TimedElement().SampleAt(containerTime);
      }
    }
  }
}
static v8::Handle<v8::Value> getCurrentTimeCallback(const v8::Arguments& args)
{
    INC_STATS("DOM.SVGAnimationElement.getCurrentTime");
    SVGAnimationElement* imp = V8SVGAnimationElement::toNative(args.Holder());
    return v8::Number::New(imp->getCurrentTime());
}
static v8::Handle<v8::Value> targetElementAttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info)
{
    INC_STATS("DOM.SVGAnimationElement.targetElement._get");
    SVGAnimationElement* imp = V8SVGAnimationElement::toNative(info.Holder());
    return toV8(imp->targetElement());
}