SVGAnimateColorElement.cpp [plain text]
#include "config.h"
#if SVG_SUPPORT
#include "SVGAnimateColorElement.h"
#include "KSVGTimeScheduler.h"
#include "PlatformString.h"
#include "Document.h"
#include "SVGDocumentExtensions.h"
#include "SVGSVGElement.h"
namespace WebCore {
SVGAnimateColorElement::SVGAnimateColorElement(const QualifiedName& tagName, Document *doc)
: SVGAnimationElement(tagName, doc)
, m_toColor(new SVGColor())
, m_fromColor(new SVGColor())
, m_currentItem(-1)
, m_redDiff(0)
, m_greenDiff(0)
, m_blueDiff(0)
{
}
SVGAnimateColorElement::~SVGAnimateColorElement()
{
}
void SVGAnimateColorElement::handleTimerEvent(double timePercentage)
{
if (!m_connected) {
RefPtr<SVGColor> temp = new SVGColor();
temp->setRGBColor(targetAttribute());
m_initialColor = temp->color();
switch(detectAnimationMode())
{
case TO_ANIMATION:
case FROM_TO_ANIMATION:
{
String toColorString(m_to);
m_toColor->setRGBColor(toColorString);
String fromColorString;
if (!m_from.isEmpty()) fromColorString = m_from;
else fromColorString = m_initialColor.name();
m_fromColor->setRGBColor(fromColorString);
Color qTo = m_toColor->color();
Color qFrom = m_fromColor->color();
m_redDiff = qTo.red() - qFrom.red();
m_greenDiff = qTo.green() - qFrom.green();
m_blueDiff = qTo.blue() - qFrom.blue();
break;
}
case BY_ANIMATION:
case FROM_BY_ANIMATION:
{
String byColorString(m_by);
m_toColor->setRGBColor(byColorString);
String fromColorString;
if (!m_from.isEmpty()) fromColorString = m_from;
else fromColorString = m_initialColor.name();
m_fromColor->setRGBColor(fromColorString);
Color qBy = m_toColor->color();
Color qFrom = m_fromColor->color();
int r = qFrom.red() + qBy.red();
int g = qFrom.green() + qBy.green();
int b = qFrom.blue() + qBy.blue();
Color qTo = clampColor(r, g, b);
String toColorString(qTo.name());
m_toColor->setRGBColor(toColorString);
m_redDiff = qTo.red() - qFrom.red();
m_greenDiff = qTo.green() - qFrom.green();
m_blueDiff = qTo.blue() - qFrom.blue();
break;
}
case VALUES_ANIMATION:
break;
default:
{
return;
}
}
ownerSVGElement()->timeScheduler()->connectIntervalTimer(this);
m_connected = true;
return;
}
if (timePercentage >= 1.0)
timePercentage = 1.0;
int r = 0, g = 0, b = 0;
if ((m_redDiff != 0 || m_greenDiff != 0 || m_blueDiff != 0) && !m_values)
calculateColor(timePercentage, r, g, b);
else if (m_values) {
int itemByPercentage = calculateCurrentValueItem(timePercentage);
if (itemByPercentage == -1)
return;
if (m_currentItem != itemByPercentage) {
String value1 = String(m_values->getItem(itemByPercentage));
String value2 = String(m_values->getItem(itemByPercentage + 1));
if (!value1.isEmpty() && !value2.isEmpty()) {
bool apply = false;
if (m_redDiff != 0 || m_greenDiff != 0 || m_blueDiff != 0) {
r = m_toColor->color().red();
g = m_toColor->color().green();
b = m_toColor->color().blue();
apply = true;
}
String toColorString(value2);
m_toColor->setRGBColor(toColorString);
String fromColorString(value1);
m_fromColor->setRGBColor(fromColorString);
Color qTo = m_toColor->color();
Color qFrom = m_fromColor->color();
m_redDiff = qTo.red() - qFrom.red();
m_greenDiff = qTo.green() - qFrom.green();
m_blueDiff = qTo.blue() - qFrom.blue();
m_currentItem = itemByPercentage;
if (!apply)
return;
}
}
else if (m_redDiff != 0 || m_greenDiff != 0 || m_blueDiff != 0)
{
double relativeTime = calculateRelativeTimePercentage(timePercentage, m_currentItem);
calculateColor(relativeTime, r, g, b);
}
}
if (!isFrozen() && timePercentage == 1.0)
{
r = m_initialColor.red();
g = m_initialColor.green();
b = m_initialColor.blue();
}
if (isAccumulated() && repeations() != 0.0)
{
r += m_lastColor.red();
g += m_lastColor.green();
b += m_lastColor.blue();
}
m_currentColor = clampColor(r, g, b);
if (timePercentage == 1.0) {
if ((m_repeatCount > 0 && m_repeations < m_repeatCount - 1) || isIndefinite(m_repeatCount)) {
m_lastColor = m_currentColor;
m_repeations++;
return;
}
ownerSVGElement()->timeScheduler()->disconnectIntervalTimer(this);
m_connected = false;
m_currentItem = -1;
m_redDiff = 0;
m_greenDiff = 0;
m_blueDiff = 0;
}
}
Color SVGAnimateColorElement::clampColor(int r, int g, int b) const
{
if (r > 255)
r = 255;
else if (r < 0)
r = 0;
if (g > 255)
g = 255;
else if (g < 0)
g = 0;
if (b > 255)
b = 255;
else if (b < 0)
b = 0;
return Color(r, g, b);
}
void SVGAnimateColorElement::calculateColor(double time, int &r, int &g, int &b) const
{
r = lround(m_redDiff * time) + m_fromColor->color().red();
g = lround(m_greenDiff * time) + m_fromColor->color().green();
b = lround(m_blueDiff * time) + m_fromColor->color().blue();
}
Color SVGAnimateColorElement::color() const
{
return m_currentColor;
}
Color SVGAnimateColorElement::initialColor() const
{
return m_initialColor;
}
}
#endif // SVG_SUPPORT