Rewrote BAffineTransform to not be based on agg::trans_affine, which was pulling
in the AGG header. Reused the AGG code were applicable and implemented a lot more features. The Multiply and PreMultiply meaning is reversed with respect to AGG, but follows the mathematical meaning. Added type_code B_AFFINE_TRANSFORM_TYPE to TypeConstants.h and let BAffineTransform derive from BFlattenable. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@35958 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -4,126 +4,393 @@
|
|||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
* Stephen Deken, [email protected]
|
* Stephen Deken, [email protected]
|
||||||
|
* Stephan Aßmus <[email protected]>
|
||||||
*/
|
*/
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.4
|
||||||
|
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
#ifndef _AFFINE_TRANSFORM_H
|
#ifndef _AFFINE_TRANSFORM_H
|
||||||
#define _AFFINE_TRANSFORM_H
|
#define _AFFINE_TRANSFORM_H
|
||||||
|
|
||||||
#include <InterfaceDefs.h>
|
|
||||||
|
|
||||||
#include <agg_trans_affine.h>
|
#include <Flattenable.h>
|
||||||
|
#include <Point.h>
|
||||||
|
|
||||||
class BPoint;
|
#include <math.h>
|
||||||
|
|
||||||
namespace BPrivate {
|
|
||||||
|
|
||||||
class BAffineTransform {
|
class BAffineTransform : public BFlattenable {
|
||||||
|
public:
|
||||||
|
|
||||||
|
static const double kDefaultEpsilon = 1e-14;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
BAffineTransform();
|
BAffineTransform();
|
||||||
|
BAffineTransform(double sx, double shy,
|
||||||
|
double shx, double sy, double tx,
|
||||||
|
double ty);
|
||||||
BAffineTransform(
|
BAffineTransform(
|
||||||
const BAffineTransform& copyFrom);
|
const BAffineTransform& copyFrom);
|
||||||
virtual ~BAffineTransform();
|
virtual ~BAffineTransform();
|
||||||
|
|
||||||
virtual BAffineTransform& operator=(
|
// BFlattenable interface
|
||||||
const BAffineTransform& copyFrom);
|
virtual bool IsFixedSize() const;
|
||||||
|
virtual type_code TypeCode() const;
|
||||||
|
virtual ssize_t FlattenedSize() const;
|
||||||
|
virtual status_t Flatten(void* buffer,
|
||||||
|
ssize_t size) const;
|
||||||
|
virtual status_t Unflatten(type_code code,
|
||||||
|
const void* buffer, ssize_t size);
|
||||||
|
|
||||||
virtual bool operator==(
|
// Construction
|
||||||
const BAffineTransform& other) const;
|
static BAffineTransform AffineTranslation(double x, double y);
|
||||||
virtual bool operator!=(
|
static BAffineTransform AffineRotation(double angle);
|
||||||
const BAffineTransform& other) const;
|
static BAffineTransform AffineScaling(double x, double y);
|
||||||
|
static BAffineTransform AffineScaling(double scale);
|
||||||
// Callbacks
|
static BAffineTransform AffineShearing(double x, double y);
|
||||||
virtual void TransformationChanged() const;
|
|
||||||
|
|
||||||
// Application
|
// Application
|
||||||
BPoint Apply(const BPoint& point) const;
|
inline void Apply(double* x, double* y) const;
|
||||||
void Apply(BPoint* point) const;
|
inline void ApplyInverse(double* x, double* y) const;
|
||||||
void Apply(BPoint* points, uint32 count) const;
|
|
||||||
|
|
||||||
// Rotation
|
BPoint Apply(const BPoint& point) const;
|
||||||
void Rotate(float angle);
|
BPoint ApplyInverse(const BPoint& point) const;
|
||||||
void Rotate(const BPoint& center, float angle);
|
|
||||||
BAffineTransform& RotateBySelf(float angle);
|
void Apply(BPoint* point) const;
|
||||||
BAffineTransform& RotateBySelf(const BPoint& center,
|
void ApplyInverse(BPoint* point) const;
|
||||||
float angle);
|
|
||||||
BAffineTransform RotateByCopy(float angle) const;
|
void Apply(BPoint* points, uint32 count) const;
|
||||||
BAffineTransform RotateByCopy(const BPoint& center,
|
void ApplyInverse(BPoint* points,
|
||||||
float angle) const;
|
uint32 count) const;
|
||||||
|
|
||||||
// Translation
|
// Translation
|
||||||
void Translate(float deltaX, float deltaY);
|
inline const BAffineTransform& TranslateBy(double x, double y);
|
||||||
void Translate(const BPoint& delta);
|
const BAffineTransform& TranslateBy(const BPoint& delta);
|
||||||
BAffineTransform& TranslateBySelf(float deltaX,
|
|
||||||
float deltaY);
|
BAffineTransform TranslateByCopy(double x, double y) const;
|
||||||
BAffineTransform& TranslateBySelf(const BPoint& delta);
|
BAffineTransform TranslateByCopy(const BPoint& delta) const;
|
||||||
BAffineTransform TranslateByCopy(float deltaX,
|
|
||||||
float deltaY) const;
|
// Rotation
|
||||||
BAffineTransform TranslateByCopy(const BPoint& delta) const;
|
inline const BAffineTransform& RotateBy(double angle);
|
||||||
|
const BAffineTransform& RotateBy(const BPoint& center,
|
||||||
|
double angle);
|
||||||
|
|
||||||
|
BAffineTransform RotateByCopy(double angle) const;
|
||||||
|
BAffineTransform RotateByCopy(const BPoint& center,
|
||||||
|
double angle) const;
|
||||||
|
|
||||||
// Scaling
|
// Scaling
|
||||||
void Scale(float scale);
|
inline const BAffineTransform& ScaleBy(double scale);
|
||||||
void Scale(const BPoint& center, float scale);
|
const BAffineTransform& ScaleBy(const BPoint& center,
|
||||||
void Scale(float scaleX, float scaleY);
|
double scale);
|
||||||
void Scale(const BPoint& center, float scaleX,
|
inline const BAffineTransform& ScaleBy(double x, double y);
|
||||||
float scaleY);
|
const BAffineTransform& ScaleBy(const BPoint& center, double x,
|
||||||
void Scale(const BPoint& scale);
|
double y);
|
||||||
void Scale(const BPoint& center,
|
const BAffineTransform& ScaleBy(const BPoint& scale);
|
||||||
|
const BAffineTransform& ScaleBy(const BPoint& center,
|
||||||
const BPoint& scale);
|
const BPoint& scale);
|
||||||
BAffineTransform& ScaleBySelf(float scale);
|
|
||||||
BAffineTransform& ScaleBySelf(const BPoint& center,
|
BAffineTransform ScaleByCopy(double scale) const;
|
||||||
float scale);
|
BAffineTransform ScaleByCopy(const BPoint& center,
|
||||||
BAffineTransform& ScaleBySelf(float scaleX, float scaleY);
|
double scale) const;
|
||||||
BAffineTransform& ScaleBySelf(const BPoint& center,
|
BAffineTransform ScaleByCopy(double x, double y) const;
|
||||||
float scaleX, float scaleY);
|
BAffineTransform ScaleByCopy(const BPoint& center,
|
||||||
BAffineTransform& ScaleBySelf(const BPoint& scale);
|
double x, double y) const;
|
||||||
BAffineTransform& ScaleBySelf(const BPoint& center,
|
BAffineTransform ScaleByCopy(const BPoint& scale) const;
|
||||||
const BPoint& scale);
|
BAffineTransform ScaleByCopy(const BPoint& center,
|
||||||
BAffineTransform ScaleByCopy(float scale) const;
|
|
||||||
BAffineTransform ScaleByCopy(const BPoint& center,
|
|
||||||
float scale) const;
|
|
||||||
BAffineTransform ScaleByCopy(float scaleX,
|
|
||||||
float scaleY) const;
|
|
||||||
BAffineTransform ScaleByCopy(const BPoint& center,
|
|
||||||
float scaleX, float scaleY) const;
|
|
||||||
BAffineTransform ScaleByCopy(const BPoint& scale) const;
|
|
||||||
BAffineTransform ScaleByCopy(const BPoint& center,
|
|
||||||
const BPoint& scale) const;
|
const BPoint& scale) const;
|
||||||
|
|
||||||
// Shearing
|
// Shearing
|
||||||
void Shear(float shearX, float shearY);
|
inline const BAffineTransform& ShearBy(double x, double y);
|
||||||
void Shear(const BPoint& center, float shearX,
|
const BAffineTransform& ShearBy(const BPoint& center, double x,
|
||||||
float shearY);
|
double y);
|
||||||
void Shear(const BPoint& shear);
|
const BAffineTransform& ShearBy(const BPoint& shear);
|
||||||
void Shear(const BPoint& center,
|
const BAffineTransform& ShearBy(const BPoint& center,
|
||||||
const BPoint& shear);
|
const BPoint& shear);
|
||||||
|
|
||||||
BAffineTransform& ShearBySelf(float shearX, float shearY);
|
BAffineTransform ShearByCopy(double x, double y) const;
|
||||||
BAffineTransform& ShearBySelf(const BPoint& center,
|
BAffineTransform ShearByCopy(const BPoint& center,
|
||||||
float shearX, float shearY);
|
double x, double y) const;
|
||||||
BAffineTransform& ShearBySelf(const BPoint& shear);
|
BAffineTransform ShearByCopy(const BPoint& shear) const;
|
||||||
BAffineTransform& ShearBySelf(const BPoint& center,
|
BAffineTransform ShearByCopy(const BPoint& center,
|
||||||
const BPoint& shear);
|
|
||||||
BAffineTransform ShearByCopy(float shearX,
|
|
||||||
float shearY) const;
|
|
||||||
BAffineTransform ShearByCopy(const BPoint& center,
|
|
||||||
float shearX, float shearY) const;
|
|
||||||
BAffineTransform ShearByCopy(const BPoint& shear) const;
|
|
||||||
BAffineTransform ShearByCopy(const BPoint& center,
|
|
||||||
const BPoint& shear) const;
|
const BPoint& shear) const;
|
||||||
|
|
||||||
private:
|
// Multiplication
|
||||||
void _Rotate(float angle);
|
inline const BAffineTransform& Multiply(const BAffineTransform& other);
|
||||||
void _Scale(float scaleX, float scaleY);
|
const BAffineTransform& PreMultiply(const BAffineTransform& other);
|
||||||
void _Translate(float deltaX, float deltaY);
|
inline const BAffineTransform& MultiplyInverse(
|
||||||
void _Shear(float shearX, float shearY);
|
const BAffineTransform& other);
|
||||||
|
inline const BAffineTransform& PreMultiplyInverse(
|
||||||
|
const BAffineTransform& other);
|
||||||
|
|
||||||
void _TransformPoint(BPoint& point) const;
|
// Operators
|
||||||
|
inline BAffineTransform& operator=(
|
||||||
|
const BAffineTransform& copyFrom);
|
||||||
|
|
||||||
private:
|
inline bool operator==(
|
||||||
agg::trans_affine fTransformMatrix;
|
const BAffineTransform& other) const;
|
||||||
|
inline bool operator!=(
|
||||||
|
const BAffineTransform& other) const;
|
||||||
|
|
||||||
|
inline const BAffineTransform& operator*=(const BAffineTransform& other);
|
||||||
|
inline const BAffineTransform& operator/=(const BAffineTransform& other);
|
||||||
|
|
||||||
|
inline BAffineTransform operator*(
|
||||||
|
const BAffineTransform& other) const;
|
||||||
|
inline BAffineTransform operator/(
|
||||||
|
const BAffineTransform& other) const;
|
||||||
|
|
||||||
|
inline BAffineTransform operator~() const;
|
||||||
|
|
||||||
|
// Utility
|
||||||
|
bool IsValid(double epsilon
|
||||||
|
= kDefaultEpsilon) const;
|
||||||
|
bool IsIdentity(double epsilon
|
||||||
|
= kDefaultEpsilon) const;
|
||||||
|
bool IsEqual(const BAffineTransform& other,
|
||||||
|
double epsilon
|
||||||
|
= kDefaultEpsilon) const;
|
||||||
|
|
||||||
|
const BAffineTransform& Invert();
|
||||||
|
const BAffineTransform& FlipX();
|
||||||
|
const BAffineTransform& FlipY();
|
||||||
|
const BAffineTransform& Reset();
|
||||||
|
|
||||||
|
inline double Determinant() const;
|
||||||
|
inline double InverseDeterminant() const;
|
||||||
|
void GetTranslation(double* tx,
|
||||||
|
double* ty) const;
|
||||||
|
double Rotation() const;
|
||||||
|
double Scale() const;
|
||||||
|
void GetScale(double* sx, double* sy) const;
|
||||||
|
void GetScaleAbs(double* sx,
|
||||||
|
double* sy) const;
|
||||||
|
bool GetAffineParameters(double* translationX,
|
||||||
|
double* translationY, double* rotation,
|
||||||
|
double* scaleX, double* scaleY,
|
||||||
|
double* shearX, double* shearY) const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
double sx;
|
||||||
|
double shy;
|
||||||
|
double shx;
|
||||||
|
double sy;
|
||||||
|
double tx;
|
||||||
|
double ty;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace BPrivate
|
|
||||||
|
|
||||||
using namespace BPrivate;
|
// #pragma mark - inline methods
|
||||||
|
|
||||||
|
|
||||||
|
inline void
|
||||||
|
BAffineTransform::Apply(double* x, double* y) const
|
||||||
|
{
|
||||||
|
register double tmp = *x;
|
||||||
|
*x = tmp * sx + *y * shx + tx;
|
||||||
|
*y = tmp * shy + *y * sy + ty;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void
|
||||||
|
BAffineTransform::ApplyInverse(double* x, double* y) const
|
||||||
|
{
|
||||||
|
register double d = InverseDeterminant();
|
||||||
|
register double a = (*x - tx) * d;
|
||||||
|
register double b = (*y - ty) * d;
|
||||||
|
*x = a * sy - b * shx;
|
||||||
|
*y = b * sx - a * shy;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
inline const BAffineTransform&
|
||||||
|
BAffineTransform::TranslateBy(double x, double y)
|
||||||
|
{
|
||||||
|
tx += x;
|
||||||
|
ty += y;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const BAffineTransform&
|
||||||
|
BAffineTransform::RotateBy(double angle)
|
||||||
|
{
|
||||||
|
double ca = cos(angle);
|
||||||
|
double sa = sin(angle);
|
||||||
|
double t0 = sx * ca - shy * sa;
|
||||||
|
double t2 = shx * ca - sy * sa;
|
||||||
|
double t4 = tx * ca - ty * sa;
|
||||||
|
shy = sx * sa + shy * ca;
|
||||||
|
sy = shx * sa + sy * ca;
|
||||||
|
ty = tx * sa + ty * ca;
|
||||||
|
sx = t0;
|
||||||
|
shx = t2;
|
||||||
|
tx = t4;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const BAffineTransform&
|
||||||
|
BAffineTransform::ScaleBy(double x, double y)
|
||||||
|
{
|
||||||
|
double mm0 = x;
|
||||||
|
// Possible hint for the optimizer
|
||||||
|
double mm3 = y;
|
||||||
|
sx *= mm0;
|
||||||
|
shx *= mm0;
|
||||||
|
tx *= mm0;
|
||||||
|
shy *= mm3;
|
||||||
|
sy *= mm3;
|
||||||
|
ty *= mm3;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const BAffineTransform&
|
||||||
|
BAffineTransform::ScaleBy(double s)
|
||||||
|
{
|
||||||
|
double m = s;
|
||||||
|
// Possible hint for the optimizer
|
||||||
|
sx *= m;
|
||||||
|
shx *= m;
|
||||||
|
tx *= m;
|
||||||
|
shy *= m;
|
||||||
|
sy *= m;
|
||||||
|
ty *= m;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const BAffineTransform&
|
||||||
|
BAffineTransform::ShearBy(double x, double y)
|
||||||
|
{
|
||||||
|
BAffineTransform shearTransform = AffineShearing(x, y);
|
||||||
|
return PreMultiply(shearTransform);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
inline const BAffineTransform&
|
||||||
|
BAffineTransform::Multiply(const BAffineTransform& other)
|
||||||
|
{
|
||||||
|
BAffineTransform t(other);
|
||||||
|
return *this = t.PreMultiply(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const BAffineTransform&
|
||||||
|
BAffineTransform::MultiplyInverse(const BAffineTransform& other)
|
||||||
|
{
|
||||||
|
BAffineTransform t(other);
|
||||||
|
t.Invert();
|
||||||
|
return Multiply(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const BAffineTransform&
|
||||||
|
BAffineTransform::PreMultiplyInverse(const BAffineTransform& other)
|
||||||
|
{
|
||||||
|
BAffineTransform t(other);
|
||||||
|
t.Invert();
|
||||||
|
return *this = t.Multiply(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
inline BAffineTransform&
|
||||||
|
BAffineTransform::operator=(const BAffineTransform& other)
|
||||||
|
{
|
||||||
|
sx = other.sx;
|
||||||
|
shy = other.shy;
|
||||||
|
shx = other.shx;
|
||||||
|
sy = other.sy;
|
||||||
|
tx = other.tx;
|
||||||
|
ty = other.ty;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool
|
||||||
|
BAffineTransform::operator==(const BAffineTransform& other) const
|
||||||
|
{
|
||||||
|
return IsEqual(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool
|
||||||
|
BAffineTransform::operator!=(const BAffineTransform& other) const
|
||||||
|
{
|
||||||
|
return !IsEqual(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const BAffineTransform&
|
||||||
|
BAffineTransform::operator*=(const BAffineTransform& other)
|
||||||
|
{
|
||||||
|
return Multiply(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const BAffineTransform&
|
||||||
|
BAffineTransform::operator/=(const BAffineTransform& other)
|
||||||
|
{
|
||||||
|
return MultiplyInverse(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline BAffineTransform
|
||||||
|
BAffineTransform::operator*(const BAffineTransform& other) const
|
||||||
|
{
|
||||||
|
return BAffineTransform(*this).Multiply(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline BAffineTransform
|
||||||
|
BAffineTransform::operator/(const BAffineTransform& other) const
|
||||||
|
{
|
||||||
|
return BAffineTransform(*this).MultiplyInverse(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline BAffineTransform
|
||||||
|
BAffineTransform::operator~() const
|
||||||
|
{
|
||||||
|
BAffineTransform result(*this);
|
||||||
|
return result.Invert();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
inline double
|
||||||
|
BAffineTransform::Determinant() const
|
||||||
|
{
|
||||||
|
return sx * sy - shy * shx;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline double
|
||||||
|
BAffineTransform::InverseDeterminant() const
|
||||||
|
{
|
||||||
|
return 1.0 / (sx * sy - shy * shx);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif // _AFFINE_TRANSFORM_H
|
#endif // _AFFINE_TRANSFORM_H
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
B_AFFINE_TRANSFORM_TYPE = 'AMTX',
|
||||||
B_ANY_TYPE = 'ANYT',
|
B_ANY_TYPE = 'ANYT',
|
||||||
B_ATOM_TYPE = 'ATOM',
|
B_ATOM_TYPE = 'ATOM',
|
||||||
B_ATOMREF_TYPE = 'ATMR',
|
B_ATOMREF_TYPE = 'ATMR',
|
||||||
@@ -64,7 +65,7 @@ enum {
|
|||||||
// System-wide MIME types for handling URL's
|
// System-wide MIME types for handling URL's
|
||||||
|
|
||||||
extern const char *B_URL_HTTP; // application/x-vnd.Be.URL.http
|
extern const char *B_URL_HTTP; // application/x-vnd.Be.URL.http
|
||||||
extern const char *B_URL_HTTPS; // application/x-vnd.Be.URL.https
|
extern const char *B_URL_HTTPS; // application/x-vnd.Be.URL.https
|
||||||
extern const char *B_URL_FTP; // application/x-vnd.Be.URL.ftp
|
extern const char *B_URL_FTP; // application/x-vnd.Be.URL.ftp
|
||||||
extern const char *B_URL_GOPHER; // application/x-vnd.Be.URL.gopher
|
extern const char *B_URL_GOPHER; // application/x-vnd.Be.URL.gopher
|
||||||
extern const char *B_URL_MAILTO; // application/x-vnd.Be.URL.mailto
|
extern const char *B_URL_MAILTO; // application/x-vnd.Be.URL.mailto
|
||||||
|
|||||||
@@ -4,22 +4,61 @@
|
|||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
* Stephen Deken, [email protected]
|
* Stephen Deken, [email protected]
|
||||||
|
* Stephan Aßmus <[email protected]>
|
||||||
*/
|
*/
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Anti-Grain Geometry - Version 2.4
|
||||||
|
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
|
||||||
|
//
|
||||||
|
// Permission to copy, use, modify, sell and distribute this software
|
||||||
|
// is granted provided this copyright notice appears in all copies.
|
||||||
|
// This software is provided "as is" without express or implied
|
||||||
|
// warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Contact: [email protected]
|
||||||
|
// [email protected]
|
||||||
|
// http://www.antigrain.com
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
#include <AffineTransform.h>
|
#include <AffineTransform.h>
|
||||||
#include <Point.h>
|
|
||||||
|
#include <TypeConstants.h>
|
||||||
|
|
||||||
|
|
||||||
BAffineTransform::BAffineTransform()
|
BAffineTransform::BAffineTransform()
|
||||||
:
|
:
|
||||||
fTransformMatrix()
|
sx(1.0),
|
||||||
|
shy(0.0),
|
||||||
|
shx(0.0),
|
||||||
|
sy(1.0),
|
||||||
|
tx(0.0),
|
||||||
|
ty(0.0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BAffineTransform::BAffineTransform(const BAffineTransform& copyFrom)
|
BAffineTransform::BAffineTransform(double sx, double shy, double shx,
|
||||||
|
double sy, double tx, double ty)
|
||||||
:
|
:
|
||||||
fTransformMatrix(copyFrom.fTransformMatrix)
|
sx(sx),
|
||||||
|
shy(shy),
|
||||||
|
shx(shx),
|
||||||
|
sy(sy),
|
||||||
|
tx(tx),
|
||||||
|
ty(ty)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BAffineTransform::BAffineTransform(const BAffineTransform& other)
|
||||||
|
:
|
||||||
|
sx(other.sx),
|
||||||
|
shy(other.shy),
|
||||||
|
shx(other.shx),
|
||||||
|
sy(other.sy),
|
||||||
|
tx(other.tx),
|
||||||
|
ty(other.ty)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -29,153 +68,191 @@ BAffineTransform::~BAffineTransform()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BAffineTransform&
|
// #pragma mark -
|
||||||
BAffineTransform::operator=(const BAffineTransform& copyFrom)
|
|
||||||
{
|
|
||||||
if (copyFrom != *this) {
|
|
||||||
fTransformMatrix.reset();
|
|
||||||
fTransformMatrix.multiply(copyFrom.fTransformMatrix);
|
|
||||||
TransformationChanged();
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
BAffineTransform::operator==(const BAffineTransform& other) const
|
BAffineTransform::IsFixedSize() const
|
||||||
{
|
{
|
||||||
return fTransformMatrix == other.fTransformMatrix;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
type_code
|
||||||
BAffineTransform::operator!=(const BAffineTransform& other) const
|
BAffineTransform::TypeCode() const
|
||||||
{
|
{
|
||||||
return fTransformMatrix != other.fTransformMatrix;
|
return B_AFFINE_TRANSFORM_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
ssize_t
|
||||||
BAffineTransform::TransformationChanged() const
|
BAffineTransform::FlattenedSize() const
|
||||||
{
|
{
|
||||||
// default implementation does nothing
|
return 6 * sizeof(double);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BAffineTransform::Flatten(void* _buffer, ssize_t size) const
|
||||||
|
{
|
||||||
|
if (_buffer == NULL || size < FlattenedSize())
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
double* buffer = reinterpret_cast<double*>(_buffer);
|
||||||
|
|
||||||
|
buffer[0] = sx;
|
||||||
|
buffer[1] = shy;
|
||||||
|
buffer[2] = shx;
|
||||||
|
buffer[3] = sy;
|
||||||
|
buffer[4] = tx;
|
||||||
|
buffer[5] = ty;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BAffineTransform::Unflatten(type_code code, const void* _buffer, ssize_t size)
|
||||||
|
{
|
||||||
|
if (_buffer == NULL || size < FlattenedSize() || code != TypeCode())
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
const double* buffer = reinterpret_cast<const double*>(_buffer);
|
||||||
|
|
||||||
|
sx = buffer[0];
|
||||||
|
shy = buffer[1];
|
||||||
|
shx = buffer[2];
|
||||||
|
sy = buffer[3];
|
||||||
|
tx = buffer[4];
|
||||||
|
ty = buffer[5];
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
/*static*/ BAffineTransform
|
||||||
|
BAffineTransform::AffineTranslation(double x, double y)
|
||||||
|
{
|
||||||
|
return BAffineTransform(1.0, 0.0, 0.0, 1.0, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*static*/ BAffineTransform
|
||||||
|
BAffineTransform::AffineRotation(double angle)
|
||||||
|
{
|
||||||
|
return BAffineTransform(cos(angle), sin(angle), -sin(angle), cos(angle),
|
||||||
|
0.0, 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*static*/ BAffineTransform
|
||||||
|
BAffineTransform::AffineScaling(double x, double y)
|
||||||
|
{
|
||||||
|
return BAffineTransform(x, 0.0, 0.0, y, 0.0, 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*static*/ BAffineTransform
|
||||||
|
BAffineTransform::AffineScaling(double scale)
|
||||||
|
{
|
||||||
|
return BAffineTransform(scale, 0.0, 0.0, scale, 0.0, 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*static*/ BAffineTransform
|
||||||
|
BAffineTransform::AffineShearing(double x, double y)
|
||||||
|
{
|
||||||
|
return BAffineTransform(1.0, tan(y), tan(x), 1.0, 0.0, 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
BPoint
|
BPoint
|
||||||
BAffineTransform::Apply(const BPoint& point) const
|
BAffineTransform::Apply(const BPoint& point) const
|
||||||
{
|
{
|
||||||
BPoint result(point);
|
double x = point.x;
|
||||||
_TransformPoint(result);
|
double y = point.y;
|
||||||
return result;
|
Apply(&x, &y);
|
||||||
|
return BPoint(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BPoint
|
||||||
|
BAffineTransform::ApplyInverse(const BPoint& point) const
|
||||||
|
{
|
||||||
|
double x = point.x;
|
||||||
|
double y = point.y;
|
||||||
|
ApplyInverse(&x, &y);
|
||||||
|
return BPoint(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BAffineTransform::Apply(BPoint* point) const
|
BAffineTransform::Apply(BPoint* point) const
|
||||||
{
|
{
|
||||||
if (point)
|
if (point == NULL)
|
||||||
_TransformPoint(*point);
|
return;
|
||||||
|
double x = point->x;
|
||||||
|
double y = point->y;
|
||||||
|
Apply(&x, &y);
|
||||||
|
point->x = x;
|
||||||
|
point->y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BAffineTransform::ApplyInverse(BPoint* point) const
|
||||||
|
{
|
||||||
|
if (point == NULL)
|
||||||
|
return;
|
||||||
|
double x = point->x;
|
||||||
|
double y = point->y;
|
||||||
|
ApplyInverse(&x, &y);
|
||||||
|
point->x = x;
|
||||||
|
point->y = y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BAffineTransform::Apply(BPoint* points, uint32 count) const
|
BAffineTransform::Apply(BPoint* points, uint32 count) const
|
||||||
{
|
{
|
||||||
if (points) {
|
if (points != NULL) {
|
||||||
for (uint32 i = 0; i < count; ++i)
|
for (uint32 i = 0; i < count; ++i)
|
||||||
_TransformPoint(points[i]);
|
Apply(&points[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BAffineTransform::Rotate(float angle)
|
BAffineTransform::ApplyInverse(BPoint* points, uint32 count) const
|
||||||
{
|
{
|
||||||
_Rotate(angle);
|
if (points != NULL) {
|
||||||
TransformationChanged();
|
for (uint32 i = 0; i < count; ++i)
|
||||||
|
ApplyInverse(&points[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
// #pragma mark -
|
||||||
BAffineTransform::Rotate(const BPoint& center, float angle)
|
|
||||||
|
|
||||||
|
const BAffineTransform&
|
||||||
|
BAffineTransform::TranslateBy(const BPoint& delta)
|
||||||
{
|
{
|
||||||
_Translate(-center.x, -center.y);
|
return TranslateBy(delta.x, delta.y);
|
||||||
_Rotate(angle);
|
|
||||||
_Translate(center.x, center.y);
|
|
||||||
TransformationChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BAffineTransform&
|
|
||||||
BAffineTransform::RotateBySelf(float angle)
|
|
||||||
{
|
|
||||||
Rotate(angle);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BAffineTransform&
|
|
||||||
BAffineTransform::RotateBySelf(const BPoint& center, float angle)
|
|
||||||
{
|
|
||||||
Rotate(center, angle);
|
|
||||||
return *this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BAffineTransform
|
BAffineTransform
|
||||||
BAffineTransform::RotateByCopy(float angle) const
|
BAffineTransform::TranslateByCopy(double x, double y) const
|
||||||
{
|
{
|
||||||
BAffineTransform copy(*this);
|
BAffineTransform copy(*this);
|
||||||
copy.Rotate(angle);
|
copy.TranslateBy(x, y);
|
||||||
return copy;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BAffineTransform
|
|
||||||
BAffineTransform::RotateByCopy(const BPoint& center, float angle) const
|
|
||||||
{
|
|
||||||
BAffineTransform copy(*this);
|
|
||||||
copy.Rotate(center, angle);
|
|
||||||
return copy;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
BAffineTransform::Translate(float deltaX, float deltaY)
|
|
||||||
{
|
|
||||||
_Translate(deltaX, deltaY);
|
|
||||||
TransformationChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
BAffineTransform::Translate(const BPoint& delta)
|
|
||||||
{
|
|
||||||
Translate(delta.x, delta.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BAffineTransform&
|
|
||||||
BAffineTransform::TranslateBySelf(float deltaX, float deltaY)
|
|
||||||
{
|
|
||||||
Translate(deltaX, deltaY);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BAffineTransform&
|
|
||||||
BAffineTransform::TranslateBySelf(const BPoint& delta)
|
|
||||||
{
|
|
||||||
return TranslateBySelf(delta.x, delta.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BAffineTransform
|
|
||||||
BAffineTransform::TranslateByCopy(float deltaX, float deltaY) const
|
|
||||||
{
|
|
||||||
BAffineTransform copy(*this);
|
|
||||||
copy.Translate(deltaX, deltaY);
|
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,125 +264,97 @@ BAffineTransform::TranslateByCopy(const BPoint& delta) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
// #pragma mark -
|
||||||
BAffineTransform::Scale(float scale)
|
|
||||||
|
|
||||||
|
const BAffineTransform&
|
||||||
|
BAffineTransform::RotateBy(const BPoint& center, double angle)
|
||||||
{
|
{
|
||||||
Scale(scale, scale);
|
TranslateBy(-center.x, -center.y);
|
||||||
}
|
RotateBy(angle);
|
||||||
|
return TranslateBy(center.x, center.y);
|
||||||
|
|
||||||
void
|
|
||||||
BAffineTransform::Scale(const BPoint& center, float scale)
|
|
||||||
{
|
|
||||||
Scale(center, scale, scale);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
BAffineTransform::Scale(float scaleX, float scaleY)
|
|
||||||
{
|
|
||||||
_Scale(scaleX, scaleY);
|
|
||||||
TransformationChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
BAffineTransform::Scale(const BPoint& center, float scaleX, float scaleY)
|
|
||||||
{
|
|
||||||
_Translate(-center.x, -center.y);
|
|
||||||
_Scale(scaleX, scaleY);
|
|
||||||
_Translate(center.x, center.y);
|
|
||||||
TransformationChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
BAffineTransform::Scale(const BPoint& scale)
|
|
||||||
{
|
|
||||||
Scale(scale.x, scale.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
BAffineTransform::Scale(const BPoint& center, const BPoint& scale)
|
|
||||||
{
|
|
||||||
Scale(center, scale.x, scale.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BAffineTransform&
|
|
||||||
BAffineTransform::ScaleBySelf(float scale)
|
|
||||||
{
|
|
||||||
return ScaleBySelf(scale, scale);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BAffineTransform&
|
|
||||||
BAffineTransform::ScaleBySelf(const BPoint& center, float scale)
|
|
||||||
{
|
|
||||||
return ScaleBySelf(center, scale, scale);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BAffineTransform&
|
|
||||||
BAffineTransform::ScaleBySelf(float scaleX, float scaleY)
|
|
||||||
{
|
|
||||||
Scale(scaleX, scaleY);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BAffineTransform&
|
|
||||||
BAffineTransform::ScaleBySelf(const BPoint& center, float scaleX, float scaleY)
|
|
||||||
{
|
|
||||||
Scale(center, scaleX, scaleY);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BAffineTransform&
|
|
||||||
BAffineTransform::ScaleBySelf(const BPoint& scale)
|
|
||||||
{
|
|
||||||
return ScaleBySelf(scale.x, scale.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BAffineTransform&
|
|
||||||
BAffineTransform::ScaleBySelf(const BPoint& center, const BPoint& scale)
|
|
||||||
{
|
|
||||||
return ScaleBySelf(center, scale.x, scale.y);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BAffineTransform
|
BAffineTransform
|
||||||
BAffineTransform::ScaleByCopy(float scale) const
|
BAffineTransform::RotateByCopy(double angle) const
|
||||||
|
{
|
||||||
|
BAffineTransform copy(*this);
|
||||||
|
copy.RotateBy(angle);
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BAffineTransform
|
||||||
|
BAffineTransform::RotateByCopy(const BPoint& center, double angle) const
|
||||||
|
{
|
||||||
|
BAffineTransform copy(*this);
|
||||||
|
copy.RotateBy(center, angle);
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
const BAffineTransform&
|
||||||
|
BAffineTransform::ScaleBy(const BPoint& center, double scale)
|
||||||
|
{
|
||||||
|
return ScaleBy(center, scale, scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const BAffineTransform&
|
||||||
|
BAffineTransform::ScaleBy(const BPoint& center, double x, double y)
|
||||||
|
{
|
||||||
|
TranslateBy(-center.x, -center.y);
|
||||||
|
ScaleBy(x, y);
|
||||||
|
return TranslateBy(center.x, center.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const BAffineTransform&
|
||||||
|
BAffineTransform::ScaleBy(const BPoint& scale)
|
||||||
|
{
|
||||||
|
return ScaleBy(scale.x, scale.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const BAffineTransform&
|
||||||
|
BAffineTransform::ScaleBy(const BPoint& center, const BPoint& scale)
|
||||||
|
{
|
||||||
|
return ScaleBy(center, scale.x, scale.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BAffineTransform
|
||||||
|
BAffineTransform::ScaleByCopy(double scale) const
|
||||||
{
|
{
|
||||||
return ScaleByCopy(scale, scale);
|
return ScaleByCopy(scale, scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BAffineTransform
|
BAffineTransform
|
||||||
BAffineTransform::ScaleByCopy(const BPoint& center, float scale) const
|
BAffineTransform::ScaleByCopy(const BPoint& center, double scale) const
|
||||||
{
|
{
|
||||||
return ScaleByCopy(center, scale, scale);
|
return ScaleByCopy(center, scale, scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BAffineTransform
|
BAffineTransform
|
||||||
BAffineTransform::ScaleByCopy(float scaleX, float scaleY) const
|
BAffineTransform::ScaleByCopy(double x, double y) const
|
||||||
{
|
{
|
||||||
BAffineTransform copy(*this);
|
BAffineTransform copy(*this);
|
||||||
copy.Scale(scaleX, scaleY);
|
copy.ScaleBy(x, y);
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BAffineTransform
|
BAffineTransform
|
||||||
BAffineTransform::ScaleByCopy(const BPoint& center, float scaleX,
|
BAffineTransform::ScaleByCopy(const BPoint& center, double x, double y) const
|
||||||
float scaleY) const
|
|
||||||
{
|
{
|
||||||
BAffineTransform copy(*this);
|
BAffineTransform copy(*this);
|
||||||
copy.Scale(center, scaleX, scaleY);
|
copy.ScaleBy(center, x, y);
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -324,85 +373,46 @@ BAffineTransform::ScaleByCopy(const BPoint& center, const BPoint& scale) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
// #pragma mark -
|
||||||
BAffineTransform::Shear(float shearX, float shearY)
|
|
||||||
|
|
||||||
|
const BAffineTransform&
|
||||||
|
BAffineTransform::ShearBy(const BPoint& center, double x, double y)
|
||||||
{
|
{
|
||||||
_Shear(shearX, shearY);
|
TranslateBy(-center.x, -center.y);
|
||||||
TransformationChanged();
|
ShearBy(x, y);
|
||||||
|
return TranslateBy(center.x, center.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
const BAffineTransform&
|
||||||
BAffineTransform::Shear(const BPoint& center, float shearX, float shearY)
|
BAffineTransform::ShearBy(const BPoint& shear)
|
||||||
{
|
{
|
||||||
_Translate(-center.x, -center.y);
|
return ShearBy(shear.x, shear.y);
|
||||||
_Shear(shearX, shearY);
|
|
||||||
_Translate(center.x, center.y);
|
|
||||||
TransformationChanged();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
const BAffineTransform&
|
||||||
BAffineTransform::Shear(const BPoint& shear)
|
BAffineTransform::ShearBy(const BPoint& center, const BPoint& shear)
|
||||||
{
|
{
|
||||||
Shear(shear.x, shear.y);
|
return ShearBy(center, shear.x, shear.y);
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
BAffineTransform::Shear(const BPoint& center, const BPoint& shear)
|
|
||||||
{
|
|
||||||
Shear(center, shear.x, shear.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BAffineTransform&
|
|
||||||
BAffineTransform::ShearBySelf(float shearX, float shearY)
|
|
||||||
{
|
|
||||||
Shear(shearX, shearY);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BAffineTransform&
|
|
||||||
BAffineTransform::ShearBySelf(const BPoint& center, float shearX, float shearY)
|
|
||||||
{
|
|
||||||
Shear(center, shearX, shearY);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BAffineTransform&
|
|
||||||
BAffineTransform::ShearBySelf(const BPoint& shear)
|
|
||||||
{
|
|
||||||
Shear(shear);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BAffineTransform&
|
|
||||||
BAffineTransform::ShearBySelf(const BPoint& center, const BPoint& shear)
|
|
||||||
{
|
|
||||||
Shear(center, shear);
|
|
||||||
return *this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BAffineTransform
|
BAffineTransform
|
||||||
BAffineTransform::ShearByCopy(float shearX, float shearY) const
|
BAffineTransform::ShearByCopy(double x, double y) const
|
||||||
{
|
{
|
||||||
BAffineTransform copy(*this);
|
BAffineTransform copy(*this);
|
||||||
copy.Shear(shearX, shearY);
|
copy.ShearBy(x, y);
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BAffineTransform
|
BAffineTransform
|
||||||
BAffineTransform::ShearByCopy(const BPoint& center, float shearX,
|
BAffineTransform::ShearByCopy(const BPoint& center, double x, double y) const
|
||||||
float shearY) const
|
|
||||||
{
|
{
|
||||||
BAffineTransform copy(*this);
|
BAffineTransform copy(*this);
|
||||||
copy.Shear(center, shearX, shearY);
|
copy.ShearBy(center, x, y);
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -411,7 +421,7 @@ BAffineTransform
|
|||||||
BAffineTransform::ShearByCopy(const BPoint& shear) const
|
BAffineTransform::ShearByCopy(const BPoint& shear) const
|
||||||
{
|
{
|
||||||
BAffineTransform copy(*this);
|
BAffineTransform copy(*this);
|
||||||
copy.Shear(shear);
|
copy.ShearBy(shear);
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -420,7 +430,7 @@ BAffineTransform
|
|||||||
BAffineTransform::ShearByCopy(const BPoint& center, const BPoint& shear) const
|
BAffineTransform::ShearByCopy(const BPoint& center, const BPoint& shear) const
|
||||||
{
|
{
|
||||||
BAffineTransform copy(*this);
|
BAffineTransform copy(*this);
|
||||||
copy.Shear(center, shear);
|
copy.ShearBy(center, shear);
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -428,46 +438,234 @@ BAffineTransform::ShearByCopy(const BPoint& center, const BPoint& shear) const
|
|||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
void
|
const BAffineTransform&
|
||||||
BAffineTransform::_Rotate(float angle)
|
BAffineTransform::PreMultiply(const BAffineTransform& other)
|
||||||
{
|
{
|
||||||
if (angle != 0.0)
|
double t0 = sx * other.sx + shy * other.shx;
|
||||||
fTransformMatrix.multiply(agg::trans_affine_rotation(angle));
|
double t2 = shx * other.sx + sy * other.shx;
|
||||||
|
double t4 = tx * other.sx + ty * other.shx + other.tx;
|
||||||
|
shy = sx * other.shy + shy * other.sy;
|
||||||
|
sy = shx * other.shy + sy * other.sy;
|
||||||
|
ty = tx * other.shy + ty * other.sy + other.ty;
|
||||||
|
sx = t0;
|
||||||
|
shx = t2;
|
||||||
|
tx = t4;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
BAffineTransform::IsValid(double epsilon) const
|
||||||
|
{
|
||||||
|
return fabs(sx) > epsilon && fabs(sy) > epsilon;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
IsEqualEpsilon(double v1, double v2, double epsilon)
|
||||||
|
{
|
||||||
|
return fabs(v1 - v2) <= double(epsilon);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
BAffineTransform::IsIdentity(double epsilon) const
|
||||||
|
{
|
||||||
|
return IsEqualEpsilon(sx, 1.0, epsilon)
|
||||||
|
&& IsEqualEpsilon(shy, 0.0, epsilon)
|
||||||
|
&& IsEqualEpsilon(shx, 0.0, epsilon)
|
||||||
|
&& IsEqualEpsilon(sy, 1.0, epsilon)
|
||||||
|
&& IsEqualEpsilon(tx, 0.0, epsilon)
|
||||||
|
&& IsEqualEpsilon(ty, 0.0, epsilon);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
BAffineTransform::IsEqual(const BAffineTransform& other, double epsilon) const
|
||||||
|
{
|
||||||
|
return IsEqualEpsilon(sx, other.sx, epsilon)
|
||||||
|
&& IsEqualEpsilon(shy, other.shy, epsilon)
|
||||||
|
&& IsEqualEpsilon(shx, other.shx, epsilon)
|
||||||
|
&& IsEqualEpsilon(sy, other.sy, epsilon)
|
||||||
|
&& IsEqualEpsilon(tx, other.tx, epsilon)
|
||||||
|
&& IsEqualEpsilon(ty, other.ty, epsilon);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const BAffineTransform&
|
||||||
|
BAffineTransform::Invert()
|
||||||
|
{
|
||||||
|
double d = InverseDeterminant();
|
||||||
|
|
||||||
|
double t0 = sy * d;
|
||||||
|
sy = sx * d;
|
||||||
|
shy = -shy * d;
|
||||||
|
shx = -shx * d;
|
||||||
|
|
||||||
|
double t4 = -tx * t0 - ty * shx;
|
||||||
|
ty = -tx * shy - ty * sy;
|
||||||
|
|
||||||
|
sx = t0;
|
||||||
|
tx = t4;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const BAffineTransform&
|
||||||
|
BAffineTransform::FlipX()
|
||||||
|
{
|
||||||
|
sx = -sx;
|
||||||
|
shy = -shy;
|
||||||
|
tx = -tx;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const BAffineTransform&
|
||||||
|
BAffineTransform::FlipY()
|
||||||
|
{
|
||||||
|
shx = -shx;
|
||||||
|
sy = -sy;
|
||||||
|
ty = -ty;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const BAffineTransform&
|
||||||
|
BAffineTransform::Reset()
|
||||||
|
{
|
||||||
|
sx = sy = 1.0;
|
||||||
|
shy = shx = tx = ty = 0.0;
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BAffineTransform::_Scale(float scaleX, float scaleY)
|
BAffineTransform::GetTranslation(double* _tx, double* _ty) const
|
||||||
{
|
{
|
||||||
if (scaleX != 0.0 || scaleY != 0.0)
|
if (_tx)
|
||||||
fTransformMatrix.multiply(agg::trans_affine_scaling(scaleX, scaleY));
|
*_tx = tx;
|
||||||
|
if (_ty)
|
||||||
|
*_ty = ty;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
double
|
||||||
|
BAffineTransform::Rotation() const
|
||||||
|
{
|
||||||
|
double x1 = 0.0;
|
||||||
|
double y1 = 0.0;
|
||||||
|
double x2 = 1.0;
|
||||||
|
double y2 = 0.0;
|
||||||
|
Apply(&x1, &y1);
|
||||||
|
Apply(&x2, &y2);
|
||||||
|
return atan2(y2 - y1, x2 - x1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
double
|
||||||
|
BAffineTransform::Scale() const
|
||||||
|
{
|
||||||
|
double x = 0.707106781 * sx + 0.707106781 * shx;
|
||||||
|
double y = 0.707106781 * shy + 0.707106781 * sy;
|
||||||
|
return sqrt(x * x + y * y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BAffineTransform::_Translate(float deltaX, float deltaY)
|
BAffineTransform::GetScale(double* _sx, double* _sy) const
|
||||||
{
|
{
|
||||||
if (deltaX != 0.0 || deltaY != 0.0) {
|
double x1 = 0.0;
|
||||||
fTransformMatrix.multiply(
|
double y1 = 0.0;
|
||||||
agg::trans_affine_translation(deltaX, deltaY));
|
double x2 = 1.0;
|
||||||
}
|
double y2 = 1.0;
|
||||||
|
BAffineTransform t(*this);
|
||||||
|
t.PreMultiply(AffineRotation(-Rotation()));
|
||||||
|
t.Apply(&x1, &y1);
|
||||||
|
t.Apply(&x2, &y2);
|
||||||
|
if (_sx)
|
||||||
|
*_sx = x2 - x1;
|
||||||
|
if (_sy)
|
||||||
|
*_sy = y2 - y1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BAffineTransform::_Shear(float shearX, float shearY)
|
BAffineTransform::GetScaleAbs(double* _sx, double* _sy) const
|
||||||
{
|
{
|
||||||
if (shearX != 0.0 || shearY != 0.0)
|
// When there is considerable shear this method gives us much
|
||||||
fTransformMatrix.multiply(agg::trans_affine_skewing(shearX, shearY));
|
// better estimation than just sx, sy.
|
||||||
|
if (_sx)
|
||||||
|
*_sx = sqrt(sx * sx + shx * shx);
|
||||||
|
if (_sy)
|
||||||
|
*_sy = sqrt(shy * shy + sy * sy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
bool
|
||||||
BAffineTransform::_TransformPoint(BPoint& point) const
|
BAffineTransform::GetAffineParameters(double* _translationX,
|
||||||
|
double* _translationY, double* _rotation, double* _scaleX, double* _scaleY,
|
||||||
|
double* _shearX, double* _shearY) const
|
||||||
{
|
{
|
||||||
double x = point.x;
|
GetTranslation(_translationX, _translationY);
|
||||||
double y = point.y;
|
|
||||||
fTransformMatrix.transform(&x, &y);
|
double rotation = Rotation();
|
||||||
point.x = x;
|
if (_rotation != NULL)
|
||||||
point.y = y;
|
*_rotation = rotation;
|
||||||
|
|
||||||
|
// Calculate shear
|
||||||
|
double x1 = 0.0;
|
||||||
|
double y1 = 0.0;
|
||||||
|
double x2 = 1.0;
|
||||||
|
double y2 = 0.0;
|
||||||
|
double x3 = 0.0;
|
||||||
|
double y3 = 1.0;
|
||||||
|
|
||||||
|
// Reverse the effects of any rotation
|
||||||
|
BAffineTransform t(*this);
|
||||||
|
t.PreMultiply(AffineRotation(-rotation));
|
||||||
|
|
||||||
|
t.Apply(&x1, &y1);
|
||||||
|
t.Apply(&x2, &y2);
|
||||||
|
t.Apply(&x3, &y3);
|
||||||
|
|
||||||
|
double shearX = y2 - y1;
|
||||||
|
double shearY = x3 - x1;
|
||||||
|
|
||||||
|
// Calculate scale
|
||||||
|
x1 = 0.0;
|
||||||
|
y1 = 0.0;
|
||||||
|
x2 = 1.0;
|
||||||
|
y2 = 0.0;
|
||||||
|
x3 = 0.0;
|
||||||
|
y3 = 1.0;
|
||||||
|
|
||||||
|
// Reverse the effects of any shear
|
||||||
|
t.PreMultiplyInverse(AffineShearing(shearX, shearY));
|
||||||
|
|
||||||
|
t.Apply(&x1, &y1);
|
||||||
|
t.Apply(&x2, &y2);
|
||||||
|
t.Apply(&x3, &y3);
|
||||||
|
|
||||||
|
double scaleX = x2 - x1;
|
||||||
|
double scaleY = y3 - y1;
|
||||||
|
|
||||||
|
if (_scaleX != NULL)
|
||||||
|
*_scaleX = scaleX;
|
||||||
|
if (_scaleY != NULL)
|
||||||
|
*_scaleY = scaleY;
|
||||||
|
|
||||||
|
// Since scale was calculated last, the shear values are still scaled.
|
||||||
|
// We cannot get the affine parameters from a matrix with 0 scale.
|
||||||
|
if (scaleX == 0.0 && scaleY == 0.0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (_shearX != NULL)
|
||||||
|
*_shearX = shearX / scaleX;
|
||||||
|
if (_shearY != NULL)
|
||||||
|
*_shearY = shearY / scaleY;
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user