vfs: check userland buffers before reading them.
[haiku.git] / src / libs / icon / transformable / Transformable.cpp
bloba2c2cfec2380ef9a9cc225678fd6ddb78377f1d5
1 /*
2 * Copyright 2006-2009, Haiku.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Stephan Aßmus <superstippi@gmx.de>
7 */
9 #include "Transformable.h"
11 #include <stdio.h>
12 #include <string.h>
14 // constructor
15 Transformable::Transformable()
16 : agg::trans_affine()
20 // copy constructor
21 Transformable::Transformable(const Transformable& other)
22 : agg::trans_affine(other)
26 // destructor
27 Transformable::~Transformable()
31 // StoreTo
32 void
33 Transformable::StoreTo(double matrix[matrix_size]) const
35 store_to(matrix);
38 // LoadFrom
39 void
40 Transformable::LoadFrom(const double matrix[matrix_size])
42 // before calling the potentially heavy TransformationChanged()
43 // hook function, make sure that the transformation
44 // really changed
45 Transformable t;
46 t.load_from(matrix);
47 if (*this != t) {
48 load_from(matrix);
49 TransformationChanged();
53 // SetTransform
54 void
55 Transformable::SetTransform(const Transformable& other)
57 if (*this != other) {
58 *this = other;
59 TransformationChanged();
63 // operator=
64 Transformable&
65 Transformable::operator=(const Transformable& other)
67 if (other != *this) {
68 reset();
69 multiply(other);
70 TransformationChanged();
72 return *this;
75 // Multiply
76 Transformable&
77 Transformable::Multiply(const Transformable& other)
79 if (!other.IsIdentity()) {
80 multiply(other);
81 TransformationChanged();
83 return *this;
86 // Reset
87 void
88 Transformable::Reset()
90 if (!IsIdentity()) {
91 reset();
92 TransformationChanged();
96 // Invert
97 void
98 Transformable::Invert()
100 if (!IsIdentity()) {
101 invert();
102 TransformationChanged();
106 // IsIdentity
107 bool
108 Transformable::IsIdentity() const
110 double m[matrix_size];
111 store_to(m);
112 if (m[0] == 1.0 &&
113 m[1] == 0.0 &&
114 m[2] == 0.0 &&
115 m[3] == 1.0 &&
116 m[4] == 0.0 &&
117 m[5] == 0.0)
118 return true;
119 return false;
122 // IsTranslationOnly
123 bool
124 Transformable::IsTranslationOnly() const
126 double m[matrix_size];
127 store_to(m);
128 if (m[0] == 1.0 &&
129 m[1] == 0.0 &&
130 m[2] == 0.0 &&
131 m[3] == 1.0)
132 return true;
133 return false;
136 // IsNotDistorted
137 bool
138 Transformable::IsNotDistorted() const
140 double m[matrix_size];
141 store_to(m);
142 return (m[0] == m[3]);
145 // IsValid
146 bool
147 Transformable::IsValid() const
149 double m[matrix_size];
150 store_to(m);
151 return ((m[0] * m[3] - m[1] * m[2]) != 0.0);
154 // operator==
155 bool
156 Transformable::operator==(const Transformable& other) const
158 double m1[matrix_size];
159 other.store_to(m1);
160 double m2[matrix_size];
161 store_to(m2);
162 return memcmp(m1, m2, sizeof(m1)) == 0;
165 // operator!=
166 bool
167 Transformable::operator!=(const Transformable& other) const
169 return !(*this == other);
172 // Transform
173 void
174 Transformable::Transform(double* x, double* y) const
176 transform(x, y);
179 // Transform
180 void
181 Transformable::Transform(BPoint* point) const
183 if (point) {
184 double x = point->x;
185 double y = point->y;
187 transform(&x, &y);
189 point->x = x;
190 point->y = y;
194 // Transform
195 BPoint
196 Transformable::Transform(const BPoint& point) const
198 BPoint p(point);
199 Transform(&p);
200 return p;
203 // InverseTransform
204 void
205 Transformable::InverseTransform(double* x, double* y) const
207 inverse_transform(x, y);
210 // InverseTransform
211 void
212 Transformable::InverseTransform(BPoint* point) const
214 if (point) {
215 double x = point->x;
216 double y = point->y;
218 inverse_transform(&x, &y);
220 point->x = x;
221 point->y = y;
225 // InverseTransform
226 BPoint
227 Transformable::InverseTransform(const BPoint& point) const
229 BPoint p(point);
230 InverseTransform(&p);
231 return p;
234 inline float
235 min4(float a, float b, float c, float d)
237 return min_c(a, min_c(b, min_c(c, d)));
240 inline float
241 max4(float a, float b, float c, float d)
243 return max_c(a, max_c(b, max_c(c, d)));
246 // TransformBounds
247 BRect
248 Transformable::TransformBounds(BRect bounds) const
250 if (bounds.IsValid()) {
251 BPoint lt(bounds.left, bounds.top);
252 BPoint rt(bounds.right, bounds.top);
253 BPoint lb(bounds.left, bounds.bottom);
254 BPoint rb(bounds.right, bounds.bottom);
256 Transform(&lt);
257 Transform(&rt);
258 Transform(&lb);
259 Transform(&rb);
261 return BRect(floorf(min4(lt.x, rt.x, lb.x, rb.x)),
262 floorf(min4(lt.y, rt.y, lb.y, rb.y)),
263 ceilf(max4(lt.x, rt.x, lb.x, rb.x)),
264 ceilf(max4(lt.y, rt.y, lb.y, rb.y)));
266 return bounds;
269 // TranslateBy
270 void
271 Transformable::TranslateBy(BPoint offset)
273 if (offset.x != 0.0 || offset.y != 0.0) {
274 multiply(agg::trans_affine_translation(offset.x, offset.y));
275 TransformationChanged();
279 // RotateBy
280 void
281 Transformable::RotateBy(BPoint origin, double degrees)
283 if (degrees != 0.0) {
284 multiply(agg::trans_affine_translation(-origin.x, -origin.y));
285 multiply(agg::trans_affine_rotation(degrees * (M_PI / 180.0)));
286 multiply(agg::trans_affine_translation(origin.x, origin.y));
287 TransformationChanged();
291 // ScaleBy
292 void
293 Transformable::ScaleBy(BPoint origin, double xScale, double yScale)
295 if (xScale != 1.0 || yScale != 1.0) {
296 multiply(agg::trans_affine_translation(-origin.x, -origin.y));
297 multiply(agg::trans_affine_scaling(xScale, yScale));
298 multiply(agg::trans_affine_translation(origin.x, origin.y));
299 TransformationChanged();
303 // ShearBy
304 void
305 Transformable::ShearBy(BPoint origin, double xShear, double yShear)
307 if (xShear != 0.0 || yShear != 0.0) {
308 multiply(agg::trans_affine_translation(-origin.x, -origin.y));
309 multiply(agg::trans_affine_skewing(xShear, yShear));
310 multiply(agg::trans_affine_translation(origin.x, origin.y));
311 TransformationChanged();
315 // TransformationChanged
316 void
317 Transformable::TransformationChanged()
319 // default implementation doesn't care