Bug 512525 - Implement SVG Fragment Identifier parsing and animation hyperlinking - Part 1 infrastructure to support hyperlinking. r=dholbert

This commit is contained in:
Brian Birtles 2012-05-17 10:56:57 +01:00
Родитель 1333ad9b17
Коммит 9fff4c1440
4 изменённых файлов: 84 добавлений и 2 удалений

Просмотреть файл

@ -354,6 +354,23 @@ nsSMILTimedElement::GetStartTime() const
: nsSMILTimeValue();
}
//----------------------------------------------------------------------
// Hyperlinking support
nsSMILTimeValue
nsSMILTimedElement::GetHyperlinkTime() const
{
nsSMILTimeValue hyperlinkTime; // Default ctor creates unresolved time
if (mElementState == STATE_ACTIVE) {
hyperlinkTime = mCurrentInterval->Begin()->Time();
} else if (!mBeginInstances.IsEmpty()) {
hyperlinkTime = mBeginInstances[0]->Time();
}
return hyperlinkTime;
}
//----------------------------------------------------------------------
// nsSMILTimedElement
@ -1492,7 +1509,8 @@ nsSMILTimedElement::FilterIntervals()
// We can filter old intervals that:
//
// a) are not the previous interval; AND
// b) are not in the middle of a dependency chain
// b) are not in the middle of a dependency chain; AND
// c) are not the first interval
//
// Condition (a) is necessary since the previous interval is used for applying
// fill effects and updating the current interval.
@ -1502,6 +1520,15 @@ nsSMILTimedElement::FilterIntervals()
// intervals. Such chains are used to establish priorities within the
// animation sandwich.
//
// Condition (c) is necessary to support hyperlinks that target animations
// since in some cases the defined behavior is to seek the document back to
// the first resolved begin time. Presumably the intention here is not
// actually to use the first resolved begin time, the
// _the_first_resolved_begin_time_that_produced_an_interval. That is,
// if we have begin="-5s; -3s; 1s; 3s" with a duration on 1s, we should seek
// to 1s. The spec doesn't say this but I'm pretty sure that is the intention.
// It seems negative times were simply not considered.
//
// Although the above conditions allow us to safely filter intervals for most
// scenarios they do not cover all cases and there will still be scenarios
// that generate intervals indefinitely. In such a case we simply set
@ -1514,7 +1541,8 @@ nsSMILTimedElement::FilterIntervals()
for (PRUint32 i = 0; i < mOldIntervals.Length(); ++i)
{
nsSMILInterval* interval = mOldIntervals[i].get();
if (i + 1 < mOldIntervals.Length() /*skip previous interval*/ &&
if (i != 0 && /*skip first interval*/
i + 1 < mOldIntervals.Length() && /*skip previous interval*/
(i < threshold || !interval->IsDependencyChainLink())) {
interval->Unlink(true /*filtered, not deleted*/);
} else {
@ -1584,6 +1612,7 @@ nsSMILTimedElement::FilterInstanceTimes(InstanceTimeList& aList)
// There are a few instance times we should keep though, notably:
// - the current interval begin time,
// - the previous interval end time (see note in RemoveInstanceTimes)
// - the first interval begin time (see note in FilterIntervals)
nsTArray<const nsSMILInstanceTime *> timesToKeep;
if (mCurrentInterval) {
timesToKeep.AppendElement(mCurrentInterval->Begin());
@ -1592,6 +1621,9 @@ nsSMILTimedElement::FilterInstanceTimes(InstanceTimeList& aList)
if (prevInterval) {
timesToKeep.AppendElement(prevInterval->End());
}
if (!mOldIntervals.IsEmpty()) {
timesToKeep.AppendElement(mOldIntervals[0]->Begin());
}
RemoveBelowThreshold removeBelowThreshold(threshold, timesToKeep);
RemoveInstanceTimes(aList, removeBelowThreshold);
}

Просмотреть файл

@ -139,10 +139,29 @@ public:
return mSimpleDur;
}
/**
* Methods for supporting hyperlinking
*/
/**
* Internal SMIL methods
*/
/**
* Returns the time to seek the document to when this element is targetted by
* a hyperlink.
*
* The behavior is defined here:
* http://www.w3.org/TR/smil-animation/#HyperlinkSemantics
*
* It is very similar to GetStartTime() with the exception that when the
* element is not active, the begin time of the *first* interval is returned.
*
* @return the time to seek the documen to in milliseconds or an unresolved
* time if there is no resolved interval.
*/
nsSMILTimeValue GetHyperlinkTime() const;
/**
* Adds an instance time object this element's list of instance times.
* These instance times are used when creating intervals.

Просмотреть файл

@ -422,6 +422,34 @@ nsSVGAnimationElement::IsNodeOfType(PRUint32 aFlags) const
return !(aFlags & ~(eCONTENT | eANIMATION));
}
//----------------------------------------------------------------------
// SVG utility methods
void
nsSVGAnimationElement::ActivateByHyperlink()
{
FlushAnimations();
// The behavior for when the target is an animation element is defined in
// SMIL Animation:
// http://www.w3.org/TR/smil-animation/#HyperlinkSemantics
nsSMILTimeValue seekTime = mTimedElement.GetHyperlinkTime();
if (seekTime.IsDefinite()) {
nsSMILTimeContainer* timeContainer = GetTimeContainer();
if (timeContainer) {
timeContainer->SetCurrentTime(seekTime.GetMillis());
AnimationNeedsResample();
// As with nsSVGSVGElement::SetCurrentTime, we need to trigger
// a synchronous sample now.
FlushAnimations();
}
// else, silently fail. We mustn't be part of an SVG document fragment that
// is attached to the document tree so there's nothing we can do here
} else {
BeginElement();
}
}
//----------------------------------------------------------------------
// Implementation helpers

Просмотреть файл

@ -100,6 +100,9 @@ public:
virtual nsSMILTimedElement& TimedElement();
virtual nsSMILTimeContainer* GetTimeContainer();
// Utility methods for within SVG
void ActivateByHyperlink();
protected:
// nsSVGElement overrides
bool IsEventName(nsIAtom* aName);