| Index: Source/core/svg/SVGPointList.cpp
|
| diff --git a/Source/core/svg/SVGPointList.cpp b/Source/core/svg/SVGPointList.cpp
|
| index 3b7d9b91f0e2424f6e3148ce8e537b909c86097b..e0910d612e6b05e9ffb4e2c39849fecd1fb6296b 100644
|
| --- a/Source/core/svg/SVGPointList.cpp
|
| +++ b/Source/core/svg/SVGPointList.cpp
|
| @@ -21,26 +21,197 @@
|
| #include "config.h"
|
| #include "core/svg/SVGPointList.h"
|
|
|
| +#include "core/svg/SVGAnimationElement.h"
|
| +#include "core/svg/SVGParserUtilities.h"
|
| #include "platform/geometry/FloatPoint.h"
|
| #include "wtf/text/StringBuilder.h"
|
| #include "wtf/text/WTFString.h"
|
|
|
| namespace WebCore {
|
|
|
| +inline PassRefPtr<SVGPointList> toSVGPointList(PassRefPtr<NewSVGPropertyBase> passBase)
|
| +{
|
| + RefPtr<NewSVGPropertyBase> base = passBase;
|
| + ASSERT(base->type() == SVGPointList::classType());
|
| + return static_pointer_cast<SVGPointList>(base.release());
|
| +}
|
| +
|
| +SVGPointList::SVGPointList()
|
| +{
|
| +}
|
| +
|
| +SVGPointList::~SVGPointList()
|
| +{
|
| +}
|
| +
|
| +PassRefPtr<SVGPointList> SVGPointList::clone()
|
| +{
|
| + RefPtr<SVGPointList> svgPointList = SVGPointList::create();
|
| + svgPointList->deepCopy(this);
|
| + return svgPointList.release();
|
| +}
|
| +
|
| +PassRefPtr<NewSVGPropertyBase> SVGPointList::cloneForAnimation(const String& value) const
|
| +{
|
| + RefPtr<SVGPointList> svgPointList = SVGPointList::create();
|
| + svgPointList->setValueAsString(value, IGNORE_EXCEPTION);
|
| + return svgPointList.release();
|
| +}
|
| +
|
| String SVGPointList::valueAsString() const
|
| {
|
| StringBuilder builder;
|
|
|
| - unsigned size = this->size();
|
| - for (unsigned i = 0; i < size; ++i) {
|
| - if (i > 0)
|
| - builder.append(' '); // FIXME: Shouldn't we use commas to seperate?
|
| + ConstIterator it = begin();
|
| + ConstIterator itEnd = end();
|
| + if (it != itEnd) {
|
| + builder.append(it->valueAsString());
|
| + ++it;
|
|
|
| - const FloatPoint& point = at(i);
|
| - builder.append(String::number(point.x()) + ' ' + String::number(point.y()));
|
| + for (; it != itEnd; ++it) {
|
| + builder.append(' ');
|
| + builder.append(it->valueAsString());
|
| + }
|
| }
|
|
|
| return builder.toString();
|
| }
|
|
|
| +template <typename CharType>
|
| +bool SVGPointList::parse(const CharType*& ptr, const CharType* end)
|
| +{
|
| + clear();
|
| +
|
| + skipOptionalSVGSpaces(ptr, end);
|
| + if (ptr >= end)
|
| + return true;
|
| +
|
| + for (;;) {
|
| + float x = 0.0f;
|
| + float y = 0.0f;
|
| + bool valid = parseNumber(ptr, end, x) && parseNumber(ptr, end, y, false);
|
| + if (!valid) {
|
| + return false;
|
| + }
|
| + append(SVGPoint::create(FloatPoint(x, y)));
|
| +
|
| + skipOptionalSVGSpaces(ptr, end);
|
| + if (ptr < end && *ptr == ',') {
|
| + ++ptr;
|
| + skipOptionalSVGSpaces(ptr, end);
|
| +
|
| + // ',' requires the list to be continued
|
| + continue;
|
| + }
|
| +
|
| + // check end of list
|
| + skipOptionalSVGSpaces(ptr, end);
|
| + if (ptr >= end)
|
| + return true;
|
| + }
|
| +}
|
| +
|
| +void SVGPointList::setValueAsString(const String& value, ExceptionState& exceptionState)
|
| +{
|
| + if (value.isEmpty()) {
|
| + clear();
|
| + return;
|
| + }
|
| +
|
| + bool valid = false;
|
| + if (value.is8Bit()) {
|
| + const LChar* ptr = value.characters8();
|
| + const LChar* end = ptr + value.length();
|
| + valid = parse(ptr, end);
|
| + } else {
|
| + const UChar* ptr = value.characters16();
|
| + const UChar* end = ptr + value.length();
|
| + valid = parse(ptr, end);
|
| + }
|
| +
|
| + if (!valid)
|
| + exceptionState.throwDOMException(SyntaxError, "Problem parsing points=\""+value+"\"");
|
| +}
|
| +
|
| +void SVGPointList::add(PassRefPtr<NewSVGPropertyBase> other, SVGElement* contextElement)
|
| +{
|
| + RefPtr<SVGPointList> otherList = toSVGPointList(other);
|
| +
|
| + if (numberOfItems() != otherList->numberOfItems())
|
| + return;
|
| +
|
| + for (size_t i = 0; i < numberOfItems(); ++i)
|
| + at(i)->setValue(at(i)->value() + otherList->at(i)->value());
|
| +}
|
| +
|
| +bool SVGPointList::adjustFromToListValues(PassRefPtr<SVGPointList> passFromList, PassRefPtr<SVGPointList> passToList, float percentage, bool isToAnimation, bool resizeAnimatedListIfNeeded)
|
| +{
|
| + RefPtr<SVGPointList> fromList = passFromList;
|
| + RefPtr<SVGPointList> toList = passToList;
|
| +
|
| + // If no 'to' value is given, nothing to animate.
|
| + size_t toListSize = toList->numberOfItems();
|
| + if (!toListSize)
|
| + return false;
|
| +
|
| + // If the 'from' value is given and it's length doesn't match the 'to' value list length, fallback to a discrete animation.
|
| + size_t fromListSize = fromList->numberOfItems();
|
| + if (fromListSize != toListSize && fromListSize) {
|
| + if (percentage < 0.5) {
|
| + if (!isToAnimation)
|
| + deepCopy(fromList);
|
| + } else {
|
| + deepCopy(toList);
|
| + }
|
| +
|
| + return false;
|
| + }
|
| +
|
| + ASSERT(!fromListSize || fromListSize == toListSize);
|
| + if (resizeAnimatedListIfNeeded && numberOfItems() < toListSize) {
|
| + size_t paddingCount = toListSize - numberOfItems();
|
| + for (size_t i = 0; i < paddingCount; ++i)
|
| + append(SVGPoint::create());
|
| + }
|
| +
|
| + return true;
|
| +}
|
| +
|
| +void SVGPointList::calculateAnimatedValue(SVGAnimationElement* animationElement, float percentage, unsigned repeatCount, PassRefPtr<NewSVGPropertyBase> fromValue, PassRefPtr<NewSVGPropertyBase> toValue, PassRefPtr<NewSVGPropertyBase> toAtEndOfDurationValue, SVGElement* contextElement)
|
| +{
|
| + RefPtr<SVGPointList> fromList = toSVGPointList(fromValue);
|
| + RefPtr<SVGPointList> toList = toSVGPointList(toValue);
|
| + RefPtr<SVGPointList> toAtEndOfDurationList = toSVGPointList(toAtEndOfDurationValue);
|
| +
|
| + size_t fromPointListSize = fromList->numberOfItems();
|
| + size_t toPointListSize = toList->numberOfItems();
|
| + size_t toAtEndOfDurationListSize = toAtEndOfDurationList->numberOfItems();
|
| +
|
| + if (!adjustFromToListValues(fromList, toList, percentage, animationElement->animationMode() == ToAnimation, true))
|
| + return;
|
| +
|
| + for (size_t i = 0; i < toPointListSize; ++i) {
|
| + float animatedX = at(i)->x();
|
| + float animatedY = at(i)->y();
|
| +
|
| + FloatPoint effectiveFrom;
|
| + if (fromPointListSize)
|
| + effectiveFrom = fromList->at(i)->value();
|
| + FloatPoint effectiveTo = toList->at(i)->value();
|
| + FloatPoint effectiveToAtEnd;
|
| + if (i < toAtEndOfDurationListSize)
|
| + effectiveToAtEnd = toAtEndOfDurationList->at(i)->value();
|
| +
|
| + animationElement->animateAdditiveNumber(percentage, repeatCount, effectiveFrom.x(), effectiveTo.x(), effectiveToAtEnd.x(), animatedX);
|
| + animationElement->animateAdditiveNumber(percentage, repeatCount, effectiveFrom.y(), effectiveTo.y(), effectiveToAtEnd.y(), animatedY);
|
| + at(i)->setValue(FloatPoint(animatedX, animatedY));
|
| + }
|
| +}
|
| +
|
| +float SVGPointList::calculateDistance(PassRefPtr<NewSVGPropertyBase> to, SVGElement*)
|
| +{
|
| + // FIXME: Distance calculation is not possible for SVGPointList right now. We need the distance for every single value.
|
| + return -1;
|
| +}
|
| +
|
| }
|
|
|