109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)/*
209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) * Copyright (C) 2004, 2005, 2006 Nikolas Zimmermann <zimmermann@kde.org>
309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) * Copyright (C) 2004, 2005, 2006, 2007 Rob Buis <buis@kde.org>
409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) * Copyright (C) 2007 Apple Inc. All rights reserved.
509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) *
609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) * This library is free software; you can redistribute it and/or
709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) * modify it under the terms of the GNU Library General Public
809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) * License as published by the Free Software Foundation; either
909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) * version 2 of the License, or (at your option) any later version.
1009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) *
1109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) * This library is distributed in the hope that it will be useful,
1209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) * but WITHOUT ANY WARRANTY; without even the implied warranty of
1309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) * Library General Public License for more details.
1509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) *
1609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) * You should have received a copy of the GNU Library General Public License
1709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) * along with this library; see the file COPYING.LIB.  If not, write to
1809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
1909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) * Boston, MA 02110-1301, USA.
2009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) */
2109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
2209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#include "config.h"
2309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
2409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#include "core/svg/SVGRect.h"
2509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
2609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#include "bindings/v8/ExceptionState.h"
2709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#include "core/dom/ExceptionCode.h"
2809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#include "core/svg/SVGAnimationElement.h"
2909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#include "core/svg/SVGParserUtilities.h"
3009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#include "wtf/text/StringBuilder.h"
3109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#include "wtf/text/WTFString.h"
3209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
3309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)namespace WebCore {
3409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
3509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)SVGRect::SVGRect()
3607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    : SVGPropertyBase(classType())
3709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    , m_isValid(true)
3809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
3909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
4009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
4109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)SVGRect::SVGRect(InvalidSVGRectTag)
4207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    : SVGPropertyBase(classType())
4309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
4409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    setInvalid();
4509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
4609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
4709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)SVGRect::SVGRect(const FloatRect& rect)
4807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    : SVGPropertyBase(classType())
4909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    , m_isValid(true)
5009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    , m_value(rect)
5109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
5209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
5309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
5409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)PassRefPtr<SVGRect> SVGRect::clone() const
5509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
5609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    return SVGRect::create(m_value);
5709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
5809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
5907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben MurdochPassRefPtr<SVGPropertyBase> SVGRect::cloneForAnimation(const String& value) const
6009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
6109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    RefPtr<SVGRect> rect = SVGRect::create();
6209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    rect->setValueAsString(value, IGNORE_EXCEPTION);
6309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    return rect.release();
6409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
6509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
6609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)template<typename CharType>
6709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void SVGRect::parse(const CharType*& ptr, const CharType* end, ExceptionState& exceptionState)
6809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
6909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    const CharType* start = ptr;
7009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
7109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    skipOptionalSVGSpaces(ptr, end);
7209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
7309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    float x = 0.0f;
7409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    float y = 0.0f;
7509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    float width = 0.0f;
7609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    float height = 0.0f;
775d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    bool valid = parseNumber(ptr, end, x) && parseNumber(ptr, end, y) && parseNumber(ptr, end, width) && parseNumber(ptr, end, height, DisallowWhitespace);
7809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
7909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if (!valid) {
8009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        exceptionState.throwDOMException(SyntaxError, "Problem parsing rect \"" + String(start, end - start) + "\"");
8109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        setInvalid();
8209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return;
8309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
8409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
8509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    skipOptionalSVGSpaces(ptr, end);
8609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if (ptr < end) { // nothing should come after the last, fourth number
8709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        exceptionState.throwDOMException(SyntaxError, "Problem parsing rect \"" + String(start, end - start) + "\"");
8809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        setInvalid();
8909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return;
9009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
9109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
9209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    m_value = FloatRect(x, y, width, height);
9309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    m_isValid = true;
9409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
9509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
9609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void SVGRect::setValueAsString(const String& string, ExceptionState& exceptionState)
9709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
9809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if (string.isNull()) {
9909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        setInvalid();
10009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return;
10109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
10209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if (string.isEmpty()) {
10309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        m_value = FloatRect(0.0f, 0.0f, 0.0f, 0.0f);
10409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        m_isValid = true;
10509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return;
10609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
10709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
10809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if (string.is8Bit()) {
10909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        const LChar* ptr = string.characters8();
11009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        const LChar* end = ptr + string.length();
11109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        parse(ptr, end, exceptionState);
11209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return;
11309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
11409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
11509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    const UChar* ptr = string.characters16();
11609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    const UChar* end = ptr + string.length();
11709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    parse(ptr, end, exceptionState);
11809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
11909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
12009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)String SVGRect::valueAsString() const
12109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
12209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    StringBuilder builder;
12309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    builder.append(String::number(x()));
12409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    builder.append(' ');
12509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    builder.append(String::number(y()));
12609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    builder.append(' ');
12709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    builder.append(String::number(width()));
12809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    builder.append(' ');
12909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    builder.append(String::number(height()));
13009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    return builder.toString();
13109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
13209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
133d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)void SVGRect::add(PassRefPtrWillBeRawPtr<SVGPropertyBase> other, SVGElement*)
13409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
13509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    m_value += toSVGRect(other)->value();
13609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
13709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
13807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdochvoid SVGRect::calculateAnimatedValue(SVGAnimationElement* animationElement, float percentage, unsigned repeatCount, PassRefPtr<SVGPropertyBase> fromValue, PassRefPtr<SVGPropertyBase> toValue, PassRefPtr<SVGPropertyBase> toAtEndOfDurationValue, SVGElement*)
13909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
14009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    ASSERT(animationElement);
14109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    RefPtr<SVGRect> fromRect = animationElement->animationMode() == ToAnimation ? this : toSVGRect(fromValue);
14209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    RefPtr<SVGRect> toRect = toSVGRect(toValue);
14309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    RefPtr<SVGRect> toAtEndOfDurationRect = toSVGRect(toAtEndOfDurationValue);
14409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
14509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    float animatedX = x();
14609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    float animatedY = y();
14709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    float animatedWidth = width();
14809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    float animatedHeight = height();
14909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    animationElement->animateAdditiveNumber(percentage, repeatCount, fromRect->x(), toRect->x(), toAtEndOfDurationRect->x(), animatedX);
15009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    animationElement->animateAdditiveNumber(percentage, repeatCount, fromRect->y(), toRect->y(), toAtEndOfDurationRect->y(), animatedY);
15109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    animationElement->animateAdditiveNumber(percentage, repeatCount, fromRect->width(), toRect->width(), toAtEndOfDurationRect->width(), animatedWidth);
15209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    animationElement->animateAdditiveNumber(percentage, repeatCount, fromRect->height(), toRect->height(), toAtEndOfDurationRect->height(), animatedHeight);
15309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
15409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    m_value = FloatRect(animatedX, animatedY, animatedWidth, animatedHeight);
15509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
15609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
15707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdochfloat SVGRect::calculateDistance(PassRefPtr<SVGPropertyBase> to, SVGElement* contextElement)
15809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
15909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // FIXME: Distance calculation is not possible for SVGRect right now. We need the distance for every single value.
16009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    return -1;
16109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
16209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
16309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void SVGRect::setInvalid()
16409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
16509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    m_value = FloatRect(0.0f, 0.0f, 0.0f, 0.0f);
16609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    m_isValid = false;
16709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
16809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
16909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
170