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