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