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