Chromium Code Reviews| Index: Source/core/svg/SVGPointList.cpp |
| diff --git a/Source/core/svg/SVGPointList.cpp b/Source/core/svg/SVGPointList.cpp |
| index 3b7d9b91f0e2424f6e3148ce8e537b909c86097b..ddcac6ce4e6527a9def498572d24518dea95f426 100644 |
| --- a/Source/core/svg/SVGPointList.cpp |
| +++ b/Source/core/svg/SVGPointList.cpp |
| @@ -21,26 +21,196 @@ |
| #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> ret = SVGPointList::create(); |
|
haraken
2014/01/17 11:50:18
ret => svgPointList
kouhei (in TOK)
2014/01/20 01:10:26
Done.
|
| + ret->deepCopy(this); |
| + return ret.release(); |
| +} |
| + |
| +PassRefPtr<NewSVGPropertyBase> SVGPointList::cloneForAnimation(const String& value) const |
| +{ |
| + RefPtr<SVGPointList> ret = SVGPointList::create(); |
|
haraken
2014/01/17 11:50:18
Ditto.
kouhei (in TOK)
2014/01/20 01:10:26
Done.
|
| + ret->setValueAsString(value, IGNORE_EXCEPTION); |
| + return ret.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? |
| + Vector<RefPtr<SVGPoint> >::const_iterator it = m_values.begin(); |
| + Vector<RefPtr<SVGPoint> >::const_iterator itEnd = m_values.end(); |
| + if (it != itEnd) { |
| + builder.append((*it++)->valueAsString()); |
| - 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) |
| +{ |
| + m_values.clear(); |
| + |
| + skipOptionalSVGSpaces(ptr, end); |
| + if (ptr >= end) |
| + return true; |
| + |
| + for (;;) { |
|
haraken
2014/01/17 11:50:18
You can change this to:
while(ptr < end) { ...
kouhei (in TOK)
2014/01/20 01:10:26
No.
|
| + float x = 0.0f; |
| + float y = 0.0f; |
| + bool valid = parseNumber(ptr, end, x) && parseNumber(ptr, end, y, false); |
| + if (!valid) { |
| + return false; |
| + } |
| + m_values.append(SVGPoint::create(FloatPoint(x, y))); |
| + |
| + skipOptionalSVGSpaces(ptr, end); |
| + if (ptr < end && *ptr == ',') { |
|
haraken
2014/01/17 11:50:18
The previous code has |delimParsed| but the new co
kouhei (in TOK)
2014/01/20 01:10:26
Yes. The logic we want to have here is to require
|
| + ++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()) { |
| + m_values.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 (m_values.size() != otherList->m_values.size()) |
| + return; |
| + |
| + for (size_t i = 0; i < m_values.size(); ++i) |
| + m_values[i]->setValue(m_values[i]->value() + otherList->m_values[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->m_values.size(); |
| + 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->m_values.size(); |
| + if (fromListSize != toListSize && fromListSize) { |
| + if (percentage < 0.5) { |
| + if (!isToAnimation) |
| + deepCopy(fromList); |
| + } else { |
| + deepCopy(toList); |
| + } |
| + |
| + return false; |
| + } |
| + |
| + ASSERT(!fromListSize || fromListSize == toListSize); |
| + if (resizeAnimatedListIfNeeded && m_values.size() < toListSize) { |
| + size_t paddingCount = toListSize - m_values.size(); |
| + for (size_t i = 0; i < paddingCount; ++i) |
| + m_values.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->m_values.size(); |
| + size_t toPointListSize = toList->m_values.size(); |
| + size_t toAtEndOfDurationListSize = toAtEndOfDurationList->m_values.size(); |
| + |
| + if (!adjustFromToListValues(fromList, toList, percentage, animationElement->animationMode() == ToAnimation, true)) |
| + return; |
| + |
| + for (size_t i = 0; i < toPointListSize; ++i) { |
| + float animatedX = m_values[i]->x(); |
| + float animatedY = m_values[i]->y(); |
| + |
| + FloatPoint effectiveFrom; |
| + if (fromPointListSize) |
| + effectiveFrom = fromList->m_values[i]->value(); |
| + FloatPoint effectiveTo = toList->m_values[i]->value(); |
| + FloatPoint effectiveToAtEnd; |
| + if (i < toAtEndOfDurationListSize) |
| + effectiveToAtEnd = toAtEndOfDurationList->m_values[i]->value(); |
| + |
| + animationElement->animateAdditiveNumber(percentage, repeatCount, effectiveFrom.x(), effectiveTo.x(), effectiveToAtEnd.x(), animatedX); |
| + animationElement->animateAdditiveNumber(percentage, repeatCount, effectiveFrom.y(), effectiveTo.y(), effectiveToAtEnd.y(), animatedY); |
| + m_values[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; |
| +} |
| + |
| } |