1/*
2 * Copyright (C) 2016-2019 Apple 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
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#pragma once
27
28#include "SVGMatrix.h"
29#include "SVGTransformValue.h"
30#include "SVGValueProperty.h"
31
32namespace WebCore {
33
34class SVGTransform : public SVGValueProperty<SVGTransformValue>, public SVGPropertyOwner {
35public:
36 static Ref<SVGTransform> create(SVGTransformValue::SVGTransformType type)
37 {
38 return adoptRef(*new SVGTransform(type));
39 }
40
41 static Ref<SVGTransform> create(const AffineTransform& transform = { })
42 {
43 return adoptRef(*new SVGTransform(SVGTransformValue::SVG_TRANSFORM_MATRIX, transform));
44 }
45
46 static Ref<SVGTransform> create(const SVGTransformValue& value)
47 {
48 return adoptRef(*new SVGTransform(value.type(), value.matrix()->value(), value.angle(), value.rotationCenter()));
49 }
50
51 template<typename T>
52 static ExceptionOr<Ref<SVGTransform>> create(ExceptionOr<T>&& value)
53 {
54 if (value.hasException())
55 return value.releaseException();
56 return create(value.releaseReturnValue());
57 }
58
59 ~SVGTransform()
60 {
61 m_value.matrix()->detach();
62 }
63
64 Ref<SVGTransform> clone() const
65 {
66 return SVGTransform::create(m_value);
67 }
68
69 unsigned short type() { return m_value.type(); }
70 float angle() { return m_value.angle(); }
71 const Ref<SVGMatrix>& matrix() { return m_value.matrix(); }
72
73 ExceptionOr<void> setMatrix(SVGMatrix& matrix)
74 {
75 if (isReadOnly())
76 return Exception { NoModificationAllowedError };
77
78 m_value.setMatrix(matrix.value());
79 commitChange();
80 return { };
81 }
82
83 ExceptionOr<void> setTranslate(float tx, float ty)
84 {
85 if (isReadOnly())
86 return Exception { NoModificationAllowedError };
87
88 m_value.setTranslate(tx, ty);
89 commitChange();
90 return { };
91 }
92
93 ExceptionOr<void> setScale(float sx, float sy)
94 {
95 if (isReadOnly())
96 return Exception { NoModificationAllowedError };
97
98 m_value.setScale(sx, sy);
99 commitChange();
100 return { };
101 }
102
103 ExceptionOr<void> setRotate(float angle, float cx, float cy)
104 {
105 if (isReadOnly())
106 return Exception { NoModificationAllowedError };
107
108 m_value.setRotate(angle, cx, cy);
109 commitChange();
110 return { };
111 }
112
113 ExceptionOr<void> setSkewX(float angle)
114 {
115 if (isReadOnly())
116 return Exception { NoModificationAllowedError };
117
118 m_value.setSkewX(angle);
119 commitChange();
120 return { };
121 }
122
123 ExceptionOr<void> setSkewY(float angle)
124 {
125 if (isReadOnly())
126 return Exception { NoModificationAllowedError };
127
128 m_value.setSkewY(angle);
129 commitChange();
130 return { };
131 }
132
133private:
134 using Base = SVGValueProperty<SVGTransformValue>;
135
136 SVGTransform(SVGTransformValue::SVGTransformType type, const AffineTransform& transform = { }, float angle = 0, const FloatPoint& rotationCenter = { })
137 : Base(SVGTransformValue(type, SVGMatrix::create(this, SVGPropertyAccess::ReadWrite, transform), angle, rotationCenter))
138 {
139 }
140
141 SVGPropertyOwner* owner() const override { return m_owner; }
142
143 void commitPropertyChange(SVGProperty* property) override
144 {
145 ASSERT_UNUSED(property, property == m_value.matrix().ptr());
146 if (owner())
147 owner()->commitPropertyChange(this);
148 m_value.matrixDidChange();
149 }
150
151 String valueAsString() const override
152 {
153 return m_value.valueAsString();
154 }
155};
156
157} // namespace WebCore
158