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