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