15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2004, 2005, 2008 Nikolas Zimmermann <zimmermann@kde.org>
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2004, 2005, 2006 Rob Buis <buis@kde.org>
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * This library is free software; you can redistribute it and/or
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modify it under the terms of the GNU Library General Public
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * License as published by the Free Software Foundation; either
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * version 2 of the License, or (at your option) any later version.
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * This library is distributed in the hope that it will be useful,
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * but WITHOUT ANY WARRANTY; without even the implied warranty of
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Library General Public License for more details.
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * You should have received a copy of the GNU Library General Public License
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * along with this library; see the file COPYING.LIB.  If not, write to
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Boston, MA 02110-1301, USA.
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h"
2253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/svg/SVGLengthList.h"
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
24197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include "bindings/core/v8/ExceptionStatePlaceholder.h"
2509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#include "core/svg/SVGAnimationElement.h"
2653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/svg/SVGParserUtilities.h"
27f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)#include "wtf/text/StringBuilder.h"
285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
29c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink {
305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdochinline PassRefPtr<SVGLengthList> toSVGLengthList(PassRefPtr<SVGPropertyBase> passBase)
325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    RefPtr<SVGPropertyBase> base = passBase;
3409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    ASSERT(base->type() == SVGLengthList::classType());
3509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    return static_pointer_cast<SVGLengthList>(base.release());
3609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
3709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
3809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)SVGLengthList::SVGLengthList(SVGLengthMode mode)
3909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    : m_mode(mode)
4009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
4109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
4209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
4309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)SVGLengthList::~SVGLengthList()
4409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
4509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
4609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
4709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)PassRefPtr<SVGLengthList> SVGLengthList::clone()
4809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
4909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    RefPtr<SVGLengthList> ret = SVGLengthList::create(m_mode);
5009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    ret->deepCopy(this);
5109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    return ret.release();
5209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
5309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
5407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben MurdochPassRefPtr<SVGPropertyBase> SVGLengthList::cloneForAnimation(const String& value) const
5509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
5609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    RefPtr<SVGLengthList> ret = SVGLengthList::create(m_mode);
5709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    ret->setValueAsString(value, IGNORE_EXCEPTION);
5809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    return ret.release();
5909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)String SVGLengthList::valueAsString() const
6209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
6309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    StringBuilder builder;
6409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
6509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    ConstIterator it = begin();
6609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    ConstIterator itEnd = end();
6709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if (it != itEnd) {
6809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        builder.append(it->valueAsString());
6909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        ++it;
7009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
7109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        for (; it != itEnd; ++it) {
7209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            builder.append(' ');
7309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            builder.append(it->valueAsString());
7409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        }
7509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
7609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
7709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    return builder.toString();
7809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
7909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
8009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)template <typename CharType>
8109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void SVGLengthList::parseInternal(const CharType*& ptr, const CharType* end, ExceptionState& exceptionState)
8209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
8309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    clear();
845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    while (ptr < end) {
85591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        const CharType* start = ptr;
865d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        while (ptr < end && *ptr != ',' && !isHTMLSpace<CharType>(*ptr))
875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ptr++;
885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (ptr == start)
895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        RefPtr<SVGLength> length = SVGLength::create(m_mode);
925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        String valueString(start, ptr - start);
935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (valueString.isEmpty())
945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return;
9509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        length->setValueAsString(valueString, exceptionState);
9651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        if (exceptionState.hadException())
975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return;
985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        append(length);
995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        skipOptionalSVGSpacesOrDelimiter(ptr, end);
1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void SVGLengthList::setValueAsString(const String& value, ExceptionState& exceptionState)
104591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{
10510f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch    if (value.isEmpty()) {
10610f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch        clear();
107591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        return;
10810f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch    }
109591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    if (value.is8Bit()) {
110591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        const LChar* ptr = value.characters8();
111591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        const LChar* end = ptr + value.length();
11209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        parseInternal(ptr, end, exceptionState);
113591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    } else {
114591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        const UChar* ptr = value.characters16();
115591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        const UChar* end = ptr + value.length();
11609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        parseInternal(ptr, end, exceptionState);
117591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    }
118591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch}
119591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
120d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)void SVGLengthList::add(PassRefPtrWillBeRawPtr<SVGPropertyBase> other, SVGElement* contextElement)
1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
12209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    RefPtr<SVGLengthList> otherList = toSVGLengthList(other);
1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
124d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (length() != otherList->length())
12509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return;
12609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
12709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    SVGLengthContext lengthContext(contextElement);
128d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    for (size_t i = 0; i < length(); ++i)
12909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        at(i)->setValue(at(i)->value(lengthContext) + otherList->at(i)->value(lengthContext), lengthContext, ASSERT_NO_EXCEPTION);
13009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
132197021e6b966cfb06891637935ef33fff06433d1Ben MurdochPassRefPtr<SVGLength> SVGLengthList::createPaddingItem() const
13309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
134197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    return SVGLength::create(m_mode);
1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
13707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdochvoid SVGLengthList::calculateAnimatedValue(SVGAnimationElement* animationElement, float percentage, unsigned repeatCount, PassRefPtr<SVGPropertyBase> fromValue, PassRefPtr<SVGPropertyBase> toValue, PassRefPtr<SVGPropertyBase> toAtEndOfDurationValue, SVGElement* contextElement)
13809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
13909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    RefPtr<SVGLengthList> fromList = toSVGLengthList(fromValue);
14009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    RefPtr<SVGLengthList> toList = toSVGLengthList(toValue);
14109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    RefPtr<SVGLengthList> toAtEndOfDurationList = toSVGLengthList(toAtEndOfDurationValue);
14209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
14309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    SVGLengthContext lengthContext(contextElement);
14409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    ASSERT(m_mode == SVGLength::lengthModeForAnimatedLengthAttribute(animationElement->attributeName()));
14509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
146d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    size_t fromLengthListSize = fromList->length();
147d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    size_t toLengthListSize = toList->length();
148d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    size_t toAtEndOfDurationListSize = toAtEndOfDurationList->length();
14909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
150197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    if (!adjustFromToListValues(fromList, toList, percentage, animationElement->animationMode()))
15109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return;
15209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
15309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    for (size_t i = 0; i < toLengthListSize; ++i) {
15409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        float animatedNumber = at(i)->value(lengthContext);
15509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        SVGLengthType unitType = toList->at(i)->unitType();
15609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        float effectiveFrom = 0;
15709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        if (fromLengthListSize) {
15809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            if (percentage < 0.5)
15909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)                unitType = fromList->at(i)->unitType();
16009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            effectiveFrom = fromList->at(i)->value(lengthContext);
16109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        }
16209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        float effectiveTo = toList->at(i)->value(lengthContext);
16309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        float effectiveToAtEnd = i < toAtEndOfDurationListSize ? toAtEndOfDurationList->at(i)->value(lengthContext) : 0;
16409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
16509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        animationElement->animateAdditiveNumber(percentage, repeatCount, effectiveFrom, effectiveTo, effectiveToAtEnd, animatedNumber);
16609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        at(i)->setUnitType(unitType);
16709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        at(i)->setValue(animatedNumber, lengthContext, ASSERT_NO_EXCEPTION);
16809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
16909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
17009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
17107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdochfloat SVGLengthList::calculateDistance(PassRefPtr<SVGPropertyBase> to, SVGElement*)
17209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
17309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // FIXME: Distance calculation is not possible for SVGLengthList right now. We need the distance for every single value.
17409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    return -1;
17509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
1765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
177