xref: /haiku/src/libs/icon/transformer/StrokeTransformer.cpp (revision 03187b607b2b5eec7ee059f1ead09bdba14991fb)
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 using namespace BPrivate::Icon;
24 using std::nothrow;
25 
26 
27 // constructor
28 StrokeTransformer::StrokeTransformer(VertexSource& source)
29 	: Transformer(source, "Stroke"),
30 	  Stroke(source)
31 {
32 }
33 
34 // constructor
35 StrokeTransformer::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
68 StrokeTransformer::~StrokeTransformer()
69 {
70 }
71 
72 // Clone
73 Transformer*
74 StrokeTransformer::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
90 void
91 StrokeTransformer::rewind(unsigned path_id)
92 {
93 	Stroke::rewind(path_id);
94 }
95 
96 // vertex
97 unsigned
98 StrokeTransformer::vertex(double* x, double* y)
99 {
100 	return Stroke::vertex(x, y);
101 }
102 
103 // SetSource
104 void
105 StrokeTransformer::SetSource(VertexSource& source)
106 {
107 	Transformer::SetSource(source);
108 	Stroke::attach(source);
109 }
110 
111 // WantsOpenPaths
112 bool
113 StrokeTransformer::WantsOpenPaths() const
114 {
115 	return true;
116 }
117 
118 // ApproximationScale
119 double
120 StrokeTransformer::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
134 status_t
135 StrokeTransformer::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
167 PropertyObject*
168 StrokeTransformer::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
209 bool
210 StrokeTransformer::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