1/*
2 * Copyright (C) 2014 Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 *     * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 *     * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 *     * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#include "config.h"
32#include "core/svg/SVGMatrixTearOff.h"
33
34#include "bindings/core/v8/ExceptionState.h"
35#include "core/dom/ExceptionCode.h"
36#include "core/svg/SVGTransformTearOff.h"
37
38namespace blink {
39
40SVGMatrixTearOff::SVGMatrixTearOff(const AffineTransform& staticValue)
41    : m_staticValue(staticValue)
42    , m_contextTransform(0)
43{
44}
45
46SVGMatrixTearOff::SVGMatrixTearOff(SVGTransformTearOff* transform)
47    : m_contextTransform(transform)
48{
49    ASSERT(transform);
50}
51
52SVGMatrixTearOff::~SVGMatrixTearOff()
53{
54}
55
56const AffineTransform& SVGMatrixTearOff::value() const
57{
58    return m_contextTransform ? m_contextTransform->target()->matrix() : m_staticValue;
59}
60
61AffineTransform* SVGMatrixTearOff::mutableValue()
62{
63    return m_contextTransform ? m_contextTransform->target()->mutableMatrix() : &m_staticValue;
64}
65
66void SVGMatrixTearOff::commitChange()
67{
68    if (!m_contextTransform)
69        return;
70
71    m_contextTransform->target()->onMatrixChange();
72    m_contextTransform->commitChange();
73}
74
75#define DEFINE_SETTER(ATTRIBUTE) \
76    void SVGMatrixTearOff::set##ATTRIBUTE(double f, ExceptionState& exceptionState) \
77    { \
78        if (m_contextTransform && m_contextTransform->isImmutable()) { \
79            exceptionState.throwDOMException(NoModificationAllowedError, "The attribute is read-only."); \
80            return; \
81        } \
82        mutableValue()->set##ATTRIBUTE(f); \
83        commitChange(); \
84    }
85
86DEFINE_SETTER(A);
87DEFINE_SETTER(B);
88DEFINE_SETTER(C);
89DEFINE_SETTER(D);
90DEFINE_SETTER(E);
91DEFINE_SETTER(F);
92
93#undef DEFINE_SETTER
94
95PassRefPtr<SVGMatrixTearOff> SVGMatrixTearOff::translate(double tx, double ty)
96{
97    RefPtr<SVGMatrixTearOff> matrix = create(value());
98    matrix->mutableValue()->translate(tx, ty);
99    return matrix.release();
100}
101
102PassRefPtr<SVGMatrixTearOff> SVGMatrixTearOff::scale(double s)
103{
104    RefPtr<SVGMatrixTearOff> matrix = create(value());
105    matrix->mutableValue()->scale(s, s);
106    return matrix.release();
107}
108
109PassRefPtr<SVGMatrixTearOff> SVGMatrixTearOff::scaleNonUniform(double sx, double sy)
110{
111    RefPtr<SVGMatrixTearOff> matrix = create(value());
112    matrix->mutableValue()->scale(sx, sy);
113    return matrix.release();
114}
115
116PassRefPtr<SVGMatrixTearOff> SVGMatrixTearOff::rotate(double d)
117{
118    RefPtr<SVGMatrixTearOff> matrix = create(value());
119    matrix->mutableValue()->rotate(d);
120    return matrix.release();
121}
122
123PassRefPtr<SVGMatrixTearOff> SVGMatrixTearOff::flipX()
124{
125    RefPtr<SVGMatrixTearOff> matrix = create(value());
126    matrix->mutableValue()->flipX();
127    return matrix.release();
128}
129
130PassRefPtr<SVGMatrixTearOff> SVGMatrixTearOff::flipY()
131{
132    RefPtr<SVGMatrixTearOff> matrix = create(value());
133    matrix->mutableValue()->flipY();
134    return matrix.release();
135}
136
137PassRefPtr<SVGMatrixTearOff> SVGMatrixTearOff::skewX(double angle)
138{
139    RefPtr<SVGMatrixTearOff> matrix = create(value());
140    matrix->mutableValue()->skewX(angle);
141    return matrix.release();
142}
143
144PassRefPtr<SVGMatrixTearOff> SVGMatrixTearOff::skewY(double angle)
145{
146    RefPtr<SVGMatrixTearOff> matrix = create(value());
147    matrix->mutableValue()->skewY(angle);
148    return matrix.release();
149}
150
151PassRefPtr<SVGMatrixTearOff> SVGMatrixTearOff::multiply(PassRefPtr<SVGMatrixTearOff> other)
152{
153    RefPtr<SVGMatrixTearOff> matrix = create(value());
154    *matrix->mutableValue() *= other->value();
155    return matrix.release();
156}
157
158PassRefPtr<SVGMatrixTearOff> SVGMatrixTearOff::inverse(ExceptionState& exceptionState)
159{
160    AffineTransform transform = value().inverse();
161    if (!value().isInvertible())
162        exceptionState.throwDOMException(InvalidStateError, "The matrix is not invertible.");
163
164    return create(transform);
165}
166
167PassRefPtr<SVGMatrixTearOff> SVGMatrixTearOff::rotateFromVector(double x, double y, ExceptionState& exceptionState)
168{
169    if (!x || !y)
170        exceptionState.throwDOMException(InvalidAccessError, "Arguments cannot be zero.");
171
172    AffineTransform copy = value();
173    copy.rotateFromVector(x, y);
174    return create(copy);
175}
176
177}
178