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 "AffineTransformer.h" 11 12 #ifdef ICON_O_MATIC 13 # include <Message.h> 14 15 # include "CommonPropertyIDs.h" 16 # include "Property.h" 17 # include "PropertyObject.h" 18 #endif 19 20 #include <new> 21 22 23 using namespace BPrivate::Icon; 24 using std::nothrow; 25 26 27 // constructor 28 AffineTransformer::AffineTransformer(VertexSource& source) 29 : Transformer(source, "Transformation"), 30 Affine(source, *this) 31 { 32 } 33 34 #ifdef ICON_O_MATIC 35 // constructor 36 AffineTransformer::AffineTransformer(VertexSource& source, 37 BMessage* archive) 38 : Transformer(source, archive), 39 Affine(source, *this) 40 { 41 if (!archive) 42 return; 43 44 int32 size = 6; 45 const void* matrix; 46 ssize_t dataSize = size * sizeof(double); 47 if (archive->FindData("matrix", B_DOUBLE_TYPE, 48 &matrix, &dataSize) == B_OK) { 49 if (dataSize == (ssize_t)(size * sizeof(double))) 50 load_from((const double*)matrix); 51 } 52 } 53 #endif // ICON_O_MATIC 54 55 // destructor 56 AffineTransformer::~AffineTransformer() 57 { 58 } 59 60 // Clone 61 Transformer* 62 AffineTransformer::Clone(VertexSource& source) const 63 { 64 AffineTransformer* clone = new (nothrow) AffineTransformer(source); 65 if (clone) 66 clone->multiply(*this); 67 return clone; 68 } 69 70 // rewind 71 void 72 AffineTransformer::rewind(unsigned path_id) 73 { 74 Affine::rewind(path_id); 75 } 76 77 // vertex 78 unsigned 79 AffineTransformer::vertex(double* x, double* y) 80 { 81 return Affine::vertex(x, y); 82 } 83 84 // SetSource 85 void 86 AffineTransformer::SetSource(VertexSource& source) 87 { 88 Transformer::SetSource(source); 89 Affine::attach(source); 90 } 91 92 // ApproximationScale 93 double 94 AffineTransformer::ApproximationScale() const 95 { 96 return fSource.ApproximationScale() * scale(); 97 } 98 99 // #pragma mark - 100 101 #ifdef ICON_O_MATIC 102 103 // Archive 104 status_t 105 AffineTransformer::Archive(BMessage* into, bool deep) const 106 { 107 status_t ret = Transformer::Archive(into, deep); 108 109 if (ret == B_OK) 110 into->what = archive_code; 111 112 if (ret == B_OK) { 113 double matrix[6]; 114 store_to(matrix); 115 ret = into->AddData("matrix", B_DOUBLE_TYPE, 116 matrix, 6 * sizeof(double)); 117 } 118 119 return ret; 120 } 121 122 // MakePropertyObject 123 PropertyObject* 124 AffineTransformer::MakePropertyObject() const 125 { 126 PropertyObject* object = Transformer::MakePropertyObject(); 127 if (!object) 128 return NULL; 129 130 // translation 131 double tx; 132 double ty; 133 translation(&tx, &ty); 134 object->AddProperty(new FloatProperty(PROPERTY_TRANSLATION_X, tx)); 135 object->AddProperty(new FloatProperty(PROPERTY_TRANSLATION_Y, ty)); 136 137 // rotation 138 object->AddProperty(new FloatProperty(PROPERTY_ROTATION, 139 agg::rad2deg(rotation()))); 140 141 // scale 142 double scaleX; 143 double scaleY; 144 scaling(&scaleX, &scaleY); 145 object->AddProperty(new FloatProperty(PROPERTY_SCALE_X, scaleX)); 146 object->AddProperty(new FloatProperty(PROPERTY_SCALE_Y, scaleY)); 147 148 return object; 149 } 150 151 // SetToPropertyObject 152 bool 153 AffineTransformer::SetToPropertyObject(const PropertyObject* object) 154 { 155 AutoNotificationSuspender _(this); 156 Transformer::SetToPropertyObject(object); 157 158 // current affine parameters 159 double tx; 160 double ty; 161 translation(&tx, &ty); 162 double r = rotation(); 163 double scaleX; 164 double scaleY; 165 scaling(&scaleX, &scaleY); 166 167 // properties 168 double newTX = object->Value(PROPERTY_TRANSLATION_X, (float)tx); 169 double newTY = object->Value(PROPERTY_TRANSLATION_Y, (float)ty); 170 171 double newR = object->Value(PROPERTY_ROTATION, 172 (float)agg::rad2deg(r)); 173 newR = agg::deg2rad(newR); 174 175 double newScaleX = object->Value(PROPERTY_SCALE_X, (float)scaleX); 176 double newScaleY = object->Value(PROPERTY_SCALE_Y, (float)scaleY); 177 178 if (newTX != tx || newTY != ty 179 || newR != r 180 || newScaleX != scaleX 181 || newScaleY != scaleY) { 182 183 reset(); 184 185 multiply(agg::trans_affine_scaling(newScaleX, newScaleY)); 186 multiply(agg::trans_affine_rotation(newR)); 187 multiply(agg::trans_affine_translation(newTX, newTY)); 188 189 Notify(); 190 } 191 192 return HasPendingNotifications(); 193 } 194 195 #endif // ICON_O_MATIC 196 197 198