xref: /haiku/src/libs/icon/transformer/ContourTransformer.cpp (revision 3634f142352af2428aed187781fc9d75075e9140)
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
25 using std::nothrow;
26 
27 
28 // constructor
29 ContourTransformer::ContourTransformer(VertexSource& source)
30 	: Transformer("Contour"),
31 	  PathTransformer(source),
32 	  Contour(source)
33 {
34 	auto_detect_orientation(true);
35 }
36 
37 // constructor
38 ContourTransformer::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
68 ContourTransformer::~ContourTransformer()
69 {
70 }
71 
72 // Clone
73 Transformer*
74 ContourTransformer::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
89 void
90 ContourTransformer::rewind(unsigned path_id)
91 {
92 	Contour::rewind(path_id);
93 }
94 
95 // vertex
96 unsigned
97 ContourTransformer::vertex(double* x, double* y)
98 {
99 	return Contour::vertex(x, y);
100 }
101 
102 // SetSource
103 void
104 ContourTransformer::SetSource(VertexSource& source)
105 {
106 	PathTransformer::SetSource(source);
107 	Contour::attach(source);
108 }
109 
110 // ApproximationScale
111 double
112 ContourTransformer::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
126 status_t
127 ContourTransformer::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
153 PropertyObject*
154 ContourTransformer::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
184 bool
185 ContourTransformer::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