#include "AffineTransformer.h"
#ifdef ICON_O_MATIC
# include <Message.h>
# include "CommonPropertyIDs.h"
# include "Property.h"
# include "PropertyObject.h"
#endif
#include <new>
_USING_ICON_NAMESPACE
using std::nothrow;
AffineTransformer::AffineTransformer(VertexSource& source)
: Transformer("Transformation"),
PathTransformer(source),
Affine(source, *this)
{
}
AffineTransformer::AffineTransformer(VertexSource& source,
BMessage* archive)
: Transformer(archive),
PathTransformer(source),
Affine(source, *this)
{
if (!archive)
return;
int32 size = 6;
const void* matrix;
ssize_t dataSize = size * sizeof(double);
if (archive->FindData("matrix", B_DOUBLE_TYPE,
&matrix, &dataSize) == B_OK) {
if (dataSize == (ssize_t)(size * sizeof(double)))
load_from((const double*)matrix);
}
}
AffineTransformer::~AffineTransformer()
{
}
Transformer*
AffineTransformer::Clone() const
{
AffineTransformer* clone = new (nothrow) AffineTransformer(*fSource);
if (clone)
clone->multiply(*this);
return clone;
}
void
AffineTransformer::rewind(unsigned path_id)
{
Affine::rewind(path_id);
}
unsigned
AffineTransformer::vertex(double* x, double* y)
{
return Affine::vertex(x, y);
}
void
AffineTransformer::SetSource(VertexSource& source)
{
PathTransformer::SetSource(source);
Affine::attach(source);
}
double
AffineTransformer::ApproximationScale() const
{
return fabs(fSource->ApproximationScale() * scale());
}
#ifdef ICON_O_MATIC
status_t
AffineTransformer::Archive(BMessage* into, bool deep) const
{
status_t ret = Transformer::Archive(into, deep);
if (ret == B_OK)
into->what = archive_code;
if (ret == B_OK) {
double matrix[6];
store_to(matrix);
ret = into->AddData("matrix", B_DOUBLE_TYPE,
matrix, 6 * sizeof(double));
}
return ret;
}
PropertyObject*
AffineTransformer::MakePropertyObject() const
{
PropertyObject* object = Transformer::MakePropertyObject();
if (!object)
return NULL;
double tx;
double ty;
translation(&tx, &ty);
object->AddProperty(new FloatProperty(PROPERTY_TRANSLATION_X, tx));
object->AddProperty(new FloatProperty(PROPERTY_TRANSLATION_Y, ty));
object->AddProperty(new FloatProperty(PROPERTY_ROTATION,
agg::rad2deg(rotation())));
double scaleX;
double scaleY;
scaling(&scaleX, &scaleY);
object->AddProperty(new FloatProperty(PROPERTY_SCALE_X, scaleX));
object->AddProperty(new FloatProperty(PROPERTY_SCALE_Y, scaleY));
return object;
}
bool
AffineTransformer::SetToPropertyObject(const PropertyObject* object)
{
AutoNotificationSuspender _(this);
Transformer::SetToPropertyObject(object);
double tx;
double ty;
translation(&tx, &ty);
double r = rotation();
double scaleX;
double scaleY;
scaling(&scaleX, &scaleY);
double newTX = object->Value(PROPERTY_TRANSLATION_X, (float)tx);
double newTY = object->Value(PROPERTY_TRANSLATION_Y, (float)ty);
double newR = object->Value(PROPERTY_ROTATION,
(float)agg::rad2deg(r));
newR = agg::deg2rad(newR);
double newScaleX = object->Value(PROPERTY_SCALE_X, (float)scaleX);
double newScaleY = object->Value(PROPERTY_SCALE_Y, (float)scaleY);
if (newTX != tx || newTY != ty
|| newR != r
|| newScaleX != scaleX
|| newScaleY != scaleY) {
reset();
multiply(agg::trans_affine_scaling(newScaleX, newScaleY));
multiply(agg::trans_affine_rotation(newR));
multiply(agg::trans_affine_translation(newTX, newTY));
Notify();
}
return HasPendingNotifications();
}
#endif