Home | History | Annotate | Download | only in svg
      1 /*
      2  * Copyright (C) 2004, 2005, 2008 Nikolas Zimmermann <zimmermann (at) kde.org>
      3  * Copyright (C) 2004, 2005, 2006 Rob Buis <buis (at) kde.org>
      4  *
      5  * This library is free software; you can redistribute it and/or
      6  * modify it under the terms of the GNU Library General Public
      7  * License as published by the Free Software Foundation; either
      8  * version 2 of the License, or (at your option) any later version.
      9  *
     10  * This library is distributed in the hope that it will be useful,
     11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13  * Library General Public License for more details.
     14  *
     15  * You should have received a copy of the GNU Library General Public License
     16  * along with this library; see the file COPYING.LIB.  If not, write to
     17  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     18  * Boston, MA 02110-1301, USA.
     19  */
     20 
     21 #include "config.h"
     22 #include "core/svg/SVGNumberList.h"
     23 
     24 #include "core/svg/SVGAnimationElement.h"
     25 #include "core/svg/SVGParserUtilities.h"
     26 #include "wtf/text/StringBuilder.h"
     27 #include "wtf/text/WTFString.h"
     28 
     29 namespace blink {
     30 
     31 inline PassRefPtr<SVGNumberList> toSVGNumberList(PassRefPtr<SVGPropertyBase> passBase)
     32 {
     33     RefPtr<SVGPropertyBase> base = passBase;
     34     ASSERT(base->type() == SVGNumberList::classType());
     35     return static_pointer_cast<SVGNumberList>(base.release());
     36 }
     37 
     38 SVGNumberList::SVGNumberList()
     39 {
     40 }
     41 
     42 SVGNumberList::~SVGNumberList()
     43 {
     44 }
     45 
     46 String SVGNumberList::valueAsString() const
     47 {
     48     StringBuilder builder;
     49 
     50     ConstIterator it = begin();
     51     ConstIterator itEnd = end();
     52     if (it != itEnd) {
     53         builder.append(it->valueAsString());
     54         ++it;
     55 
     56         for (; it != itEnd; ++it) {
     57             builder.append(' ');
     58             builder.append(it->valueAsString());
     59         }
     60     }
     61 
     62     return builder.toString();
     63 }
     64 
     65 template <typename CharType>
     66 bool SVGNumberList::parse(const CharType*& ptr, const CharType* end)
     67 {
     68     clear();
     69 
     70     while (ptr < end) {
     71         float number = 0;
     72         if (!parseNumber(ptr, end, number))
     73             return false;
     74         append(SVGNumber::create(number));
     75     }
     76 
     77     return true;
     78 }
     79 
     80 void SVGNumberList::setValueAsString(const String& value, ExceptionState& exceptionState)
     81 {
     82     if (value.isEmpty()) {
     83         clear();
     84         return;
     85     }
     86 
     87     bool valid = false;
     88     if (value.is8Bit()) {
     89         const LChar* ptr = value.characters8();
     90         const LChar* end = ptr + value.length();
     91         valid = parse(ptr, end);
     92     } else {
     93         const UChar* ptr = value.characters16();
     94         const UChar* end = ptr + value.length();
     95         valid = parse(ptr, end);
     96     }
     97 
     98     if (!valid) {
     99         exceptionState.throwDOMException(SyntaxError, "Problem parsing number list \""+value+"\"");
    100         // No call to |clear()| here. SVG policy is to use valid items before error.
    101         // Spec: http://www.w3.org/TR/SVG/single-page.html#implnote-ErrorProcessing
    102     }
    103 }
    104 
    105 void SVGNumberList::add(PassRefPtrWillBeRawPtr<SVGPropertyBase> other, SVGElement* contextElement)
    106 {
    107     RefPtr<SVGNumberList> otherList = toSVGNumberList(other);
    108 
    109     if (length() != otherList->length())
    110         return;
    111 
    112     for (size_t i = 0; i < length(); ++i)
    113         at(i)->setValue(at(i)->value() + otherList->at(i)->value());
    114 }
    115 
    116 void SVGNumberList::calculateAnimatedValue(SVGAnimationElement* animationElement, float percentage, unsigned repeatCount, PassRefPtr<SVGPropertyBase> fromValue, PassRefPtr<SVGPropertyBase> toValue, PassRefPtr<SVGPropertyBase> toAtEndOfDurationValue, SVGElement* contextElement)
    117 {
    118     RefPtr<SVGNumberList> fromList = toSVGNumberList(fromValue);
    119     RefPtr<SVGNumberList> toList = toSVGNumberList(toValue);
    120     RefPtr<SVGNumberList> toAtEndOfDurationList = toSVGNumberList(toAtEndOfDurationValue);
    121 
    122     size_t fromListSize = fromList->length();
    123     size_t toListSize = toList->length();
    124     size_t toAtEndOfDurationListSize = toAtEndOfDurationList->length();
    125 
    126     if (!adjustFromToListValues(fromList, toList, percentage, animationElement->animationMode()))
    127         return;
    128 
    129     for (size_t i = 0; i < toListSize; ++i) {
    130         float effectiveFrom = fromListSize ? fromList->at(i)->value() : 0;
    131         float effectiveTo = toListSize ? toList->at(i)->value() : 0;
    132         float effectiveToAtEnd = i < toAtEndOfDurationListSize ? toAtEndOfDurationList->at(i)->value() : 0;
    133 
    134         float animated = at(i)->value();
    135         animationElement->animateAdditiveNumber(percentage, repeatCount, effectiveFrom, effectiveTo, effectiveToAtEnd, animated);
    136         at(i)->setValue(animated);
    137     }
    138 }
    139 
    140 float SVGNumberList::calculateDistance(PassRefPtr<SVGPropertyBase> to, SVGElement*)
    141 {
    142     // FIXME: Distance calculation is not possible for SVGNumberList right now. We need the distance for every single value.
    143     return -1;
    144 }
    145 
    146 Vector<float> SVGNumberList::toFloatVector() const
    147 {
    148     Vector<float> vec;
    149     vec.reserveInitialCapacity(length());
    150     for (size_t i = 0; i < length(); ++i)
    151         vec.uncheckedAppend(at(i)->value());
    152     return vec;
    153 }
    154 
    155 }
    156