/* * Copyright 2006, Haiku. * Distributed under the terms of the MIT License. * * Authors: * Stephan Aßmus */ #include "ChannelTransform.h" #include // constructor ChannelTransform::ChannelTransform() : Transformable(), fPivot(0.0, 0.0), fTranslation(0.0, 0.0), fRotation(0.0), fXScale(1.0), fYScale(1.0) { } // copy constructor ChannelTransform::ChannelTransform(const ChannelTransform& other) : Transformable(other), fPivot(other.fPivot), fTranslation(other.fTranslation), fRotation(other.fRotation), fXScale(other.fXScale), fYScale(other.fYScale) { } // destructor ChannelTransform::~ChannelTransform() { } // SetTransformation void ChannelTransform::SetTransformation(BPoint pivot, BPoint translation, double rotation, double xScale, double yScale) { if (fTranslation != translation || fPivot != pivot || fRotation != rotation || fXScale != xScale || fYScale != yScale) { fPivot = pivot; fTranslation = translation; fRotation = rotation; fXScale = xScale; fYScale = yScale; _UpdateMatrix(); } } // SetPivot void ChannelTransform::SetPivot(BPoint pivot) { if (pivot == fPivot) return; fPivot = pivot; _UpdateMatrix(); } // TranslateBy void ChannelTransform::TranslateBy(BPoint offset) { if (offset.x == 0.0 && offset.y == 0.0) return; fTranslation += offset; _UpdateMatrix(); } // RotateBy // // converts a rotation in world coordinates into // a combined local rotation and a translation void ChannelTransform::RotateBy(BPoint origin, double degrees) { if (degrees == 0.0) return; origin -= fPivot; fRotation += degrees; // rotate fTranslation double xOffset = fTranslation.x - origin.x; double yOffset = fTranslation.y - origin.y; agg::trans_affine_rotation m(degrees * PI / 180.0); m.transform(&xOffset, &yOffset); fTranslation.x = origin.x + xOffset; fTranslation.y = origin.y + yOffset; _UpdateMatrix(); } // RotateBy void ChannelTransform::RotateBy(double degrees) { if (degrees == 0.0) return; fRotation += degrees; _UpdateMatrix(); } //// ScaleBy //// //// converts a scalation in world coordinates into //// a combined local scalation and a translation //void //ChannelTransform::ScaleBy(BPoint origin, double xScale, double yScale) //{ // if (xScale == 1.0 && yScale == 1.0) // return; // // fXScale *= xScale; // fYScale *= yScale; // // // scale fTranslation // double xOffset = fTranslation.x - origin.x; // double yOffset = fTranslation.y - origin.y; // // fTranslation.x = origin.x + (xOffset * xScale); // fTranslation.y = origin.y + (yOffset * yScale); // // _UpdateMatrix(); //} // ScaleBy void ChannelTransform::ScaleBy(double xScale, double yScale) { if (xScale == 1.0 && yScale == 1.0) return; fXScale *= xScale; fYScale *= yScale; _UpdateMatrix(); } // SetTranslationAndScale void ChannelTransform::SetTranslationAndScale(BPoint offset, double xScale, double yScale) { if (fTranslation == offset && fXScale == xScale && fYScale == yScale) return; fTranslation = offset; fXScale = xScale; fYScale = yScale; _UpdateMatrix(); } // Reset void ChannelTransform::Reset() { SetTransformation(B_ORIGIN, B_ORIGIN, 0.0, 1.0, 1.0); } // = ChannelTransform& ChannelTransform::operator=(const ChannelTransform& other) { fTranslation = other.fTranslation; fRotation = other.fRotation; fXScale = other.fXScale; fYScale = other.fYScale; Transformable::operator=(other); return *this; } // _UpdateMatrix void ChannelTransform::_UpdateMatrix() { // fix up scales in case any is zero double xScale = fXScale; if (xScale == 0.0) xScale = 0.000001; double yScale = fYScale; if (yScale == 0.0) yScale = 0.000001; // start clean reset(); // the "pivot" is like the offset from world to local // coordinate system and is the center for rotation and scale multiply(agg::trans_affine_translation(-fPivot.x, -fPivot.y)); multiply(agg::trans_affine_scaling(xScale, yScale)); multiply(agg::trans_affine_rotation(fRotation * PI / 180.0)); multiply(agg::trans_affine_translation(fPivot.x + fTranslation.x, fPivot.y + fTranslation.y)); // call hook function Update(); }