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