xref: /haiku/src/libs/icon/transformer/AffineTransformer.cpp (revision b028e77473189065f2baefc6f5e10d451cf591e2)
1 /*
2  * Copyright 2006-2007, Haiku.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Stephan Aßmus <superstippi@gmx.de>
7  */
8 
9 
10 #include "AffineTransformer.h"
11 
12 #ifdef ICON_O_MATIC
13 # include <Message.h>
14 
15 # include "CommonPropertyIDs.h"
16 # include "Property.h"
17 # include "PropertyObject.h"
18 #endif
19 
20 #include <new>
21 
22 
23 using namespace BPrivate::Icon;
24 using std::nothrow;
25 
26 
27 // constructor
28 AffineTransformer::AffineTransformer(VertexSource& source)
29 	: Transformer(source, "Transformation"),
30 	  Affine(source, *this)
31 {
32 }
33 
34 #ifdef ICON_O_MATIC
35 // constructor
36 AffineTransformer::AffineTransformer(VertexSource& source,
37 									 BMessage* archive)
38 	: Transformer(source, archive),
39 	  Affine(source, *this)
40 {
41 	if (!archive)
42 		return;
43 
44 	int32 size = 6;
45 	const void* matrix;
46 	ssize_t dataSize = size * sizeof(double);
47 	if (archive->FindData("matrix", B_DOUBLE_TYPE,
48 						  &matrix, &dataSize) == B_OK) {
49 		if (dataSize == (ssize_t)(size * sizeof(double)))
50 			load_from((const double*)matrix);
51 	}
52 }
53 #endif // ICON_O_MATIC
54 
55 // destructor
56 AffineTransformer::~AffineTransformer()
57 {
58 }
59 
60 // Clone
61 Transformer*
62 AffineTransformer::Clone(VertexSource& source) const
63 {
64 	AffineTransformer* clone = new (nothrow) AffineTransformer(source);
65 	if (clone)
66 		clone->multiply(*this);
67 	return clone;
68 }
69 
70 // rewind
71 void
72 AffineTransformer::rewind(unsigned path_id)
73 {
74 	Affine::rewind(path_id);
75 }
76 
77 // vertex
78 unsigned
79 AffineTransformer::vertex(double* x, double* y)
80 {
81 	return Affine::vertex(x, y);
82 }
83 
84 // SetSource
85 void
86 AffineTransformer::SetSource(VertexSource& source)
87 {
88 	Transformer::SetSource(source);
89 	Affine::attach(source);
90 }
91 
92 // ApproximationScale
93 double
94 AffineTransformer::ApproximationScale() const
95 {
96 	return fSource.ApproximationScale() * scale();
97 }
98 
99 // #pragma mark -
100 
101 #ifdef ICON_O_MATIC
102 
103 // Archive
104 status_t
105 AffineTransformer::Archive(BMessage* into, bool deep) const
106 {
107 	status_t ret = Transformer::Archive(into, deep);
108 
109 	if (ret == B_OK)
110 		into->what = archive_code;
111 
112 	if (ret == B_OK) {
113 		double matrix[6];
114 		store_to(matrix);
115 		ret = into->AddData("matrix", B_DOUBLE_TYPE,
116 							matrix, 6 * sizeof(double));
117 	}
118 
119 	return ret;
120 }
121 
122 // MakePropertyObject
123 PropertyObject*
124 AffineTransformer::MakePropertyObject() const
125 {
126 	PropertyObject* object = Transformer::MakePropertyObject();
127 	if (!object)
128 		return NULL;
129 
130 	// translation
131 	double tx;
132 	double ty;
133 	translation(&tx, &ty);
134 	object->AddProperty(new FloatProperty(PROPERTY_TRANSLATION_X, tx));
135 	object->AddProperty(new FloatProperty(PROPERTY_TRANSLATION_Y, ty));
136 
137 	// rotation
138 	object->AddProperty(new FloatProperty(PROPERTY_ROTATION,
139 										  agg::rad2deg(rotation())));
140 
141 	// scale
142 	double scaleX;
143 	double scaleY;
144 	scaling(&scaleX, &scaleY);
145 	object->AddProperty(new FloatProperty(PROPERTY_SCALE_X, scaleX));
146 	object->AddProperty(new FloatProperty(PROPERTY_SCALE_Y, scaleY));
147 
148 	return object;
149 }
150 
151 // SetToPropertyObject
152 bool
153 AffineTransformer::SetToPropertyObject(const PropertyObject* object)
154 {
155 	AutoNotificationSuspender _(this);
156 	Transformer::SetToPropertyObject(object);
157 
158 	// current affine parameters
159 	double tx;
160 	double ty;
161 	translation(&tx, &ty);
162 	double r = rotation();
163 	double scaleX;
164 	double scaleY;
165 	scaling(&scaleX, &scaleY);
166 
167 	// properties
168 	double newTX = object->Value(PROPERTY_TRANSLATION_X, (float)tx);
169 	double newTY = object->Value(PROPERTY_TRANSLATION_Y, (float)ty);
170 
171 	double newR = object->Value(PROPERTY_ROTATION,
172 								(float)agg::rad2deg(r));
173 	newR = agg::deg2rad(newR);
174 
175 	double newScaleX = object->Value(PROPERTY_SCALE_X, (float)scaleX);
176 	double newScaleY = object->Value(PROPERTY_SCALE_Y, (float)scaleY);
177 
178 	if (newTX != tx || newTY != ty
179 		|| newR != r
180 		|| newScaleX != scaleX
181 		|| newScaleY != scaleY) {
182 
183 		reset();
184 
185 		multiply(agg::trans_affine_scaling(newScaleX, newScaleY));
186 		multiply(agg::trans_affine_rotation(newR));
187 		multiply(agg::trans_affine_translation(newTX, newTY));
188 
189 		Notify();
190 	}
191 
192 	return HasPendingNotifications();
193 }
194 
195 #endif // ICON_O_MATIC
196 
197 
198