StrokeTransformer.cpp revision 8b8d44bf
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 "StrokeTransformer.h"
11
12#ifdef ICON_O_MATIC
13# include <Message.h>
14
15# include "CommonPropertyIDs.h"
16# include "OptionProperty.h"
17# include "Property.h"
18# include "PropertyObject.h"
19#endif // ICON_O_MATIC
20
21#include <new>
22
23using namespace BPrivate::Icon;
24using std::nothrow;
25
26
27// constructor
28StrokeTransformer::StrokeTransformer(VertexSource& source)
29	: Transformer(source, "Stroke"),
30	  Stroke(source)
31{
32}
33
34// constructor
35StrokeTransformer::StrokeTransformer(VertexSource& source,
36									 BMessage* archive)
37	: Transformer(source, archive),
38	  Stroke(source)
39{
40	if (!archive)
41		return;
42
43	int32 mode;
44	if (archive->FindInt32("line cap", &mode) == B_OK)
45		line_cap((agg::line_cap_e)mode);
46
47	if (archive->FindInt32("line join", &mode) == B_OK)
48		line_join((agg::line_join_e)mode);
49
50	if (archive->FindInt32("inner join", &mode) == B_OK)
51		inner_join((agg::inner_join_e)mode);
52
53	double value;
54	if (archive->FindDouble("width", &value) == B_OK)
55		width(value);
56
57	if (archive->FindDouble("miter limit", &value) == B_OK)
58		miter_limit(value);
59
60	if (archive->FindDouble("inner miter limit", &value) == B_OK)
61		inner_miter_limit(value);
62
63	if (archive->FindDouble("shorten", &value) == B_OK)
64		shorten(value);
65}
66
67// destructor
68StrokeTransformer::~StrokeTransformer()
69{
70}
71
72// Clone
73Transformer*
74StrokeTransformer::Clone(VertexSource& source) const
75{
76	StrokeTransformer* clone = new (nothrow) StrokeTransformer(source);
77	if (clone) {
78		clone->line_cap(line_cap());
79		clone->line_join(line_join());
80		clone->inner_join(inner_join());
81		clone->width(width());
82		clone->miter_limit(miter_limit());
83		clone->inner_miter_limit(inner_miter_limit());
84		clone->shorten(shorten());
85	}
86	return clone;
87}
88
89// rewind
90void
91StrokeTransformer::rewind(unsigned path_id)
92{
93	Stroke::rewind(path_id);
94}
95
96// vertex
97unsigned
98StrokeTransformer::vertex(double* x, double* y)
99{
100	return Stroke::vertex(x, y);
101}
102
103// SetSource
104void
105StrokeTransformer::SetSource(VertexSource& source)
106{
107	Transformer::SetSource(source);
108	Stroke::attach(source);
109}
110
111// WantsOpenPaths
112bool
113StrokeTransformer::WantsOpenPaths() const
114{
115	return true;
116}
117
118// ApproximationScale
119double
120StrokeTransformer::ApproximationScale() const
121{
122	double scale = fSource.ApproximationScale();
123	double factor = fabs(width());
124	if (factor > 1.0)
125		scale *= factor;
126	return scale;
127}
128
129// #pragma mark -
130
131#ifdef ICON_O_MATIC
132
133// Archive
134status_t
135StrokeTransformer::Archive(BMessage* into, bool deep) const
136{
137	status_t ret = Transformer::Archive(into, deep);
138
139	if (ret == B_OK)
140		into->what = archive_code;
141
142	if (ret == B_OK)
143		ret = into->AddInt32("line cap", line_cap());
144
145	if (ret == B_OK)
146		ret = into->AddInt32("line join", line_join());
147
148	if (ret == B_OK)
149		ret = into->AddInt32("inner join", inner_join());
150
151	if (ret == B_OK)
152		ret = into->AddDouble("width", width());
153
154	if (ret == B_OK)
155		ret = into->AddDouble("miter limit", miter_limit());
156
157	if (ret == B_OK)
158		ret = into->AddDouble("inner miter limit", inner_miter_limit());
159
160	if (ret == B_OK)
161		ret = into->AddDouble("shorten",shorten());
162
163	return ret;
164}
165
166// MakePropertyObject
167PropertyObject*
168StrokeTransformer::MakePropertyObject() const
169{
170	PropertyObject* object = Transformer::MakePropertyObject();
171	if (!object)
172		return NULL;
173
174	// width
175	object->AddProperty(new FloatProperty(PROPERTY_WIDTH, width()));
176
177	// cap mode
178	OptionProperty* property = new OptionProperty(PROPERTY_CAP_MODE);
179	property->AddOption(agg::butt_cap, "Butt");
180	property->AddOption(agg::square_cap, "Square");
181	property->AddOption(agg::round_cap, "Round");
182	property->SetCurrentOptionID(line_cap());
183
184	object->AddProperty(property);
185
186	// join mode
187	property = new OptionProperty(PROPERTY_JOIN_MODE);
188	property->AddOption(agg::miter_join, "Miter");
189	property->AddOption(agg::round_join, "Round");
190	property->AddOption(agg::bevel_join, "Bevel");
191	property->SetCurrentOptionID(line_join());
192
193	object->AddProperty(property);
194
195	// miter limit
196	if (line_join() == agg::miter_join) {
197		object->AddProperty(new FloatProperty(PROPERTY_MITER_LIMIT,
198											  miter_limit()));
199	}
200
201//	// shorten
202//	object->AddProperty(new FloatProperty(PROPERTY_STROKE_SHORTEN,
203//										  shorten()));
204
205	return object;
206}
207
208// SetToPropertyObject
209bool
210StrokeTransformer::SetToPropertyObject(const PropertyObject* object)
211{
212	AutoNotificationSuspender _(this);
213	Transformer::SetToPropertyObject(object);
214
215	// width
216	float w = object->Value(PROPERTY_WIDTH, (float)width());
217	if (w != width()) {
218		width(w);
219		Notify();
220	}
221
222	// cap mode
223	OptionProperty* property = dynamic_cast<OptionProperty*>(
224			object->FindProperty(PROPERTY_CAP_MODE));
225	if (property && line_cap() != property->CurrentOptionID()) {
226		line_cap((agg::line_cap_e)property->CurrentOptionID());
227		Notify();
228	}
229	// join mode
230	property = dynamic_cast<OptionProperty*>(
231		object->FindProperty(PROPERTY_JOIN_MODE));
232	if (property && line_join() != property->CurrentOptionID()) {
233		line_join((agg::line_join_e)property->CurrentOptionID());
234		Notify();
235	}
236
237	// miter limit
238	float l = object->Value(PROPERTY_MITER_LIMIT, (float)miter_limit());
239	if (l != miter_limit()) {
240		miter_limit(l);
241		Notify();
242	}
243
244	// shorten
245	float s = object->Value(PROPERTY_STROKE_SHORTEN, (float)shorten());
246	if (s != shorten()) {
247		shorten(s);
248		Notify();
249	}
250
251	return HasPendingNotifications();
252}
253
254#endif // ICON_O_MATIC
255
256
257