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