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_ICON_NAMESPACE 24using std::nothrow; 25 26 27// constructor 28AffineTransformer::AffineTransformer(VertexSource& source) 29 : Transformer(source, "Transformation"), 30 Affine(source, *this) 31{ 32} 33 34// constructor 35AffineTransformer::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 54AffineTransformer::~AffineTransformer() 55{ 56} 57 58// Clone 59Transformer* 60AffineTransformer::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 69void 70AffineTransformer::rewind(unsigned path_id) 71{ 72 Affine::rewind(path_id); 73} 74 75// vertex 76unsigned 77AffineTransformer::vertex(double* x, double* y) 78{ 79 return Affine::vertex(x, y); 80} 81 82// SetSource 83void 84AffineTransformer::SetSource(VertexSource& source) 85{ 86 Transformer::SetSource(source); 87 Affine::attach(source); 88} 89 90// ApproximationScale 91double 92AffineTransformer::ApproximationScale() const 93{ 94 return fabs(fSource.ApproximationScale() * scale()); 95} 96 97// #pragma mark - 98 99#ifdef ICON_O_MATIC 100 101// Archive 102status_t 103AffineTransformer::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 121PropertyObject* 122AffineTransformer::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 150bool 151AffineTransformer::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