CCPageScaleAnimation.cpp [plain text]
#include "config.h"
#include "cc/CCPageScaleAnimation.h"
#include "FloatRect.h"
#include "FloatSize.h"
#include <math.h>
namespace WebCore {
PassOwnPtr<CCPageScaleAnimation> CCPageScaleAnimation::create(const IntSize& scrollStart, float pageScaleStart, const IntSize& windowSize, const IntSize& contentSize, double startTime)
{
return adoptPtr(new CCPageScaleAnimation(scrollStart, pageScaleStart, windowSize, contentSize, startTime));
}
CCPageScaleAnimation::CCPageScaleAnimation(const IntSize& scrollStart, float pageScaleStart, const IntSize& windowSize, const IntSize& contentSize, double startTime)
: m_scrollStart(scrollStart)
, m_pageScaleStart(pageScaleStart)
, m_windowSize(windowSize)
, m_contentSize(contentSize)
, m_anchorMode(false)
, m_scrollEnd(scrollStart)
, m_pageScaleEnd(pageScaleStart)
, m_startTime(startTime)
, m_duration(0)
{
}
void CCPageScaleAnimation::zoomTo(const IntSize& finalScroll, float finalPageScale, double duration)
{
if (m_pageScaleStart != finalPageScale) {
FloatRect startRect(IntPoint(m_scrollStart), m_windowSize);
FloatRect endRect(IntPoint(finalScroll), m_windowSize);
endRect.scale(m_pageScaleStart / finalPageScale);
float ratioX = (startRect.x() - endRect.x()) / (endRect.width() - startRect.width());
float ratioY = (startRect.y() - endRect.y()) / (endRect.height() - startRect.height());
IntSize anchor(m_windowSize.width() * ratioX, m_windowSize.height() * ratioY);
zoomWithAnchor(anchor, finalPageScale, duration);
} else {
m_scrollEnd = finalScroll;
m_pageScaleEnd = finalPageScale;
m_duration = duration;
m_anchorMode = false;
}
}
void CCPageScaleAnimation::zoomWithAnchor(const IntSize& anchor, float finalPageScale, double duration)
{
m_scrollEnd = m_scrollStart + anchor;
m_scrollEnd.scale(finalPageScale / m_pageScaleStart);
m_scrollEnd -= anchor;
m_scrollEnd.clampNegativeToZero();
FloatSize scaledContentSize(m_contentSize);
scaledContentSize.scale(finalPageScale / m_pageScaleStart);
IntSize maxScrollPosition = roundedIntSize(scaledContentSize - m_windowSize);
m_scrollEnd = m_scrollEnd.shrunkTo(maxScrollPosition);
m_anchor = anchor;
m_pageScaleEnd = finalPageScale;
m_duration = duration;
m_anchorMode = true;
}
IntSize CCPageScaleAnimation::scrollOffsetAtTime(double time) const
{
return scrollOffsetAtRatio(progressRatioForTime(time));
}
float CCPageScaleAnimation::pageScaleAtTime(double time) const
{
return pageScaleAtRatio(progressRatioForTime(time));
}
bool CCPageScaleAnimation::isAnimationCompleteAtTime(double time) const
{
return time >= endTime();
}
float CCPageScaleAnimation::progressRatioForTime(double time) const
{
if (isAnimationCompleteAtTime(time))
return 1;
return (time - m_startTime) / m_duration;
}
IntSize CCPageScaleAnimation::scrollOffsetAtRatio(float ratio) const
{
if (ratio <= 0)
return m_scrollStart;
if (ratio >= 1)
return m_scrollEnd;
float currentPageScale = pageScaleAtRatio(ratio);
IntSize currentScrollOffset;
if (m_anchorMode) {
IntSize documentAnchor = m_scrollStart + m_anchor;
documentAnchor.scale(currentPageScale / m_pageScaleStart);
currentScrollOffset = documentAnchor - m_anchor;
} else {
FloatSize scaledStartScroll(m_scrollStart);
scaledStartScroll.scale(currentPageScale / m_pageScaleStart);
FloatSize scaledEndScroll(m_scrollEnd);
scaledEndScroll.scale(currentPageScale / m_pageScaleEnd);
FloatSize delta = scaledEndScroll - scaledStartScroll;
delta.scale(ratio);
currentScrollOffset = roundedIntSize(scaledStartScroll + delta);
}
return currentScrollOffset;
}
float CCPageScaleAnimation::pageScaleAtRatio(float ratio) const
{
if (ratio <= 0)
return m_pageScaleStart;
if (ratio >= 1)
return m_pageScaleEnd;
float diff = m_pageScaleEnd / m_pageScaleStart;
float logDiff = log(diff);
logDiff *= ratio;
diff = exp(logDiff);
return m_pageScaleStart * diff;
}
}