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