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