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