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