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