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