Home | History | Annotate | Download | only in fxcrt
      1 // Copyright 2014 PDFium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
      6 
      7 #ifndef CORE_INCLUDE_FXCRT_FX_COORDINATES_H_
      8 #define CORE_INCLUDE_FXCRT_FX_COORDINATES_H_
      9 
     10 #include "fx_basic.h"
     11 
     12 template<class baseType> class CFX_PSVTemplate;
     13 template<class baseType> class CFX_VTemplate;
     14 template<class baseType> class CFX_PRLTemplate;
     15 template<class baseType> class CFX_RTemplate;
     16 template<class baseType> class CFX_ETemplate;
     17 template<class baseType> class CFX_ATemplate;
     18 template<class baseType> class CFX_RRTemplate;
     19 class CFX_Matrix;
     20 template<class baseType>
     21 class CFX_PSVTemplate
     22 {
     23 public:
     24     typedef CFX_PSVTemplate<baseType>	FXT_PSV;
     25     typedef CFX_PSVTemplate<baseType>	FXT_POINT;
     26     typedef CFX_PSVTemplate<baseType>	FXT_SIZE;
     27     void		Set(baseType x, baseType y)
     28     {
     29         FXT_PSV::x = x, FXT_PSV::y = y;
     30     }
     31     void		Set(const FXT_PSV &psv)
     32     {
     33         FXT_PSV::x = psv.x, FXT_PSV::y = psv.y;
     34     }
     35     void		Add(baseType x, baseType y)
     36     {
     37         FXT_PSV::x += x, FXT_PSV::y += y;
     38     }
     39     void		Subtract(baseType x, baseType y)
     40     {
     41         FXT_PSV::x -= x, FXT_PSV::y -= y;
     42     }
     43     void		Reset()
     44     {
     45         FXT_PSV::x = FXT_PSV::y = 0;
     46     }
     47     FXT_PSV&	operator += (const FXT_PSV &obj)
     48     {
     49         x += obj.x;
     50         y += obj.y;
     51         return *this;
     52     }
     53     FXT_PSV&	operator -= (const FXT_PSV &obj)
     54     {
     55         x -= obj.x;
     56         y -= obj.y;
     57         return *this;
     58     }
     59     FXT_PSV&	operator *= (baseType lamda)
     60     {
     61         x *= lamda;
     62         y *= lamda;
     63         return *this;
     64     }
     65     FXT_PSV&	operator /= (baseType lamda)
     66     {
     67         x /= lamda;
     68         y /= lamda;
     69         return *this;
     70     }
     71     friend	FX_BOOL		operator == (const FXT_PSV &obj1, const FXT_PSV &obj2)
     72     {
     73         return obj1.x == obj2.x && obj1.y == obj2.y;
     74     }
     75     friend	FX_BOOL		operator != (const FXT_PSV &obj1, const FXT_PSV &obj2)
     76     {
     77         return obj1.x != obj2.x || obj1.y != obj2.y;
     78     }
     79     friend	FXT_PSV		operator + (const FXT_PSV &obj1, const FXT_PSV &obj2)
     80     {
     81         CFX_PSVTemplate obj;
     82         obj.x = obj1.x + obj2.x;
     83         obj.y = obj1.y + obj2.y;
     84         return obj;
     85     }
     86     friend	FXT_PSV		operator - (const FXT_PSV &obj1, const FXT_PSV &obj2)
     87     {
     88         CFX_PSVTemplate obj;
     89         obj.x = obj1.x - obj2.x;
     90         obj.y = obj1.y - obj2.y;
     91         return obj;
     92     }
     93     friend	FXT_PSV		operator * (const FXT_PSV &obj, baseType lamda)
     94     {
     95         CFX_PSVTemplate t;
     96         t.x = obj.x * lamda;
     97         t.y = obj.y * lamda;
     98         return t;
     99     }
    100     friend	FXT_PSV		operator * (baseType lamda, const FXT_PSV &obj)
    101     {
    102         CFX_PSVTemplate t;
    103         t.x = lamda * obj.x;
    104         t.y = lamda * obj.y;
    105         return t;
    106     }
    107     friend	FXT_PSV		operator / (const FXT_PSV &obj, baseType lamda)
    108     {
    109         CFX_PSVTemplate t;
    110         t.x = obj.x / lamda;
    111         t.y = obj.y / lamda;
    112         return t;
    113     }
    114     baseType x, y;
    115 };
    116 typedef CFX_PSVTemplate<FX_INT32>			CFX_Point;
    117 typedef CFX_PSVTemplate<FX_FLOAT>			CFX_PointF;
    118 typedef CFX_PSVTemplate<FX_INT32>			CFX_Size;
    119 typedef CFX_PSVTemplate<FX_FLOAT>			CFX_SizeF;
    120 typedef CFX_ArrayTemplate<CFX_Point>		CFX_Points;
    121 typedef CFX_ArrayTemplate<CFX_PointF>		CFX_PointsF;
    122 typedef CFX_PSVTemplate<FX_INT32> *			FX_LPPOINT;
    123 typedef CFX_PSVTemplate<FX_FLOAT> *			FX_LPPOINTF;
    124 typedef CFX_PSVTemplate<FX_INT32> const *	FX_LPCPOINT;
    125 typedef CFX_PSVTemplate<FX_FLOAT> const *	FX_LPCPOINTF;
    126 #define CFX_FloatPoint	CFX_PointF
    127 template<class baseType>
    128 class CFX_VTemplate: public CFX_PSVTemplate<baseType>
    129 {
    130 public:
    131     typedef CFX_PSVTemplate<baseType>	FXT_PSV;
    132     typedef CFX_PSVTemplate<baseType>	FXT_POINT;
    133     typedef CFX_PSVTemplate<baseType>	FXT_SIZE;
    134     typedef CFX_VTemplate<baseType>		FXT_VECTOR;
    135     void		Set(baseType newx, baseType newy)
    136     {
    137         FXT_PSV::x = newx;
    138         FXT_PSV::y = newy;
    139     }
    140     void		Set(const FXT_PSV &psv)
    141     {
    142         FXT_PSV::x = psv.x, FXT_PSV::y = psv.y;
    143     }
    144     void		Set(const FXT_POINT &p1, const FXT_POINT &p2)
    145     {
    146         FXT_PSV::x = p2.x - p1.x, FXT_PSV::y = p2.y - p1.y;
    147     }
    148     void		Reset()
    149     {
    150         FXT_PSV::x = FXT_PSV::y = 0;
    151     }
    152     baseType	SquareLength() const
    153     {
    154         return FXT_PSV::x * FXT_PSV::x + FXT_PSV::y * FXT_PSV::y;
    155     }
    156     baseType	Length() const
    157     {
    158         return FXSYS_sqrt(FXT_PSV::x * FXT_PSV::x + FXT_PSV::y * FXT_PSV::y);
    159     }
    160     void		Normalize()
    161     {
    162         FX_FLOAT fLen = FXSYS_sqrt(FXT_PSV::x * FXT_PSV::x + FXT_PSV::y * FXT_PSV::y);
    163         if (fLen < 0.0001f) {
    164             return;
    165         }
    166         FXT_PSV::x = ((baseType)FXT_PSV::x) / fLen;
    167         FXT_PSV::y = ((baseType)FXT_PSV::y) / fLen;
    168     }
    169     baseType	DotProduct(baseType otherx, baseType othery) const
    170     {
    171         return FXT_PSV::x * otherx + FXT_PSV::y * othery;
    172     }
    173     baseType	DotProduct(const FXT_VECTOR &v) const
    174     {
    175         return FXT_PSV::x * v.x + FXT_PSV::y * v.y;
    176     }
    177     FX_BOOL		IsParallel(baseType otherx, baseType othery) const
    178     {
    179         baseType t = FXT_PSV::x * othery - FXT_PSV::y * otherx;
    180         return FXSYS_fabs(t) < 0x0001f;
    181     }
    182     FX_BOOL		IsParallel(const FXT_VECTOR &v) const
    183     {
    184         return IsParallel(v.x, v.y);
    185     }
    186     FX_BOOL		IsPerpendicular(baseType otherx, baseType othery) const
    187     {
    188         baseType t = DotProduct(otherx, othery);
    189         return FXSYS_fabs(t) < 0x0001f;
    190     }
    191     FX_BOOL		IsPerpendicular(const FXT_VECTOR &v) const
    192     {
    193         return IsPerpendicular(v.x, v.y);
    194     }
    195     void		Translate(baseType dx, baseType dy)
    196     {
    197         FXT_PSV::x += dx, FXT_PSV::y += dy;
    198     }
    199     void		Scale(baseType sx, baseType sy)
    200     {
    201         FXT_PSV::x *= sx, FXT_PSV::y *= sy;
    202     }
    203     void		Rotate(FX_FLOAT fRadian)
    204     {
    205         FX_FLOAT xx = (FX_FLOAT)FXT_PSV::x;
    206         FX_FLOAT yy = (FX_FLOAT)FXT_PSV::y;
    207         FX_FLOAT cosValue = FXSYS_cos(fRadian);
    208         FX_FLOAT sinValue = FXSYS_sin(fRadian);
    209         FXT_PSV::x = xx * cosValue - yy * sinValue;
    210         FXT_PSV::y = xx * sinValue + yy * cosValue;
    211     }
    212     friend	FX_FLOAT	Cosine(const FXT_VECTOR &v1, const FXT_VECTOR &v2)
    213     {
    214         FXSYS_assert(v1.SquareLength() != 0 && v2.SquareLength() != 0);
    215         FX_FLOAT dotProduct = v1.DotProduct(v2);
    216         return dotProduct / (FX_FLOAT)FXSYS_sqrt(v1.SquareLength() * v2.SquareLength());
    217     }
    218     friend	FX_FLOAT	ArcCosine(const FXT_VECTOR &v1, const FXT_VECTOR &v2)
    219     {
    220         return (FX_FLOAT)FXSYS_acos(Cosine(v1, v2));
    221     }
    222     friend	FX_FLOAT	SlopeAngle(const FXT_VECTOR &v)
    223     {
    224         CFX_VTemplate vx;
    225         vx.Set(1, 0);
    226         FX_FLOAT fSlope = ArcCosine(v, vx);
    227         return v.y < 0 ? -fSlope : fSlope;
    228     }
    229 };
    230 typedef CFX_VTemplate<FX_INT32> CFX_Vector;
    231 typedef CFX_VTemplate<FX_FLOAT> CFX_VectorF;
    232 template<class baseType>
    233 class CFX_RTemplate
    234 {
    235 public:
    236     typedef CFX_PSVTemplate<baseType>	FXT_POINT;
    237     typedef CFX_PSVTemplate<baseType>	FXT_SIZE;
    238     typedef CFX_VTemplate<baseType>		FXT_VECTOR;
    239     typedef CFX_PRLTemplate<baseType>	FXT_PARAL;
    240     typedef CFX_RTemplate<baseType>		FXT_RECT;
    241     void		Set(baseType left, baseType top, baseType width, baseType height)
    242     {
    243         FXT_RECT::left = left, FXT_RECT::top = top, FXT_RECT::width = width, FXT_RECT::height = height;
    244     }
    245     void		Set(baseType left, baseType top, const FXT_SIZE &size)
    246     {
    247         FXT_RECT::left = left, FXT_RECT::top = top, FXT_RECT::Size(size);
    248     }
    249     void		Set(const FXT_POINT &p, baseType width, baseType height)
    250     {
    251         TopLeft(p), FXT_RECT::width = width, FXT_RECT::height = height;
    252     }
    253     void		Set(const FXT_POINT &p1, const FXT_POINT &p2)
    254     {
    255         TopLeft(p1), FXT_RECT::width = p2.x - p1.x, FXT_RECT::height = p2.y - p1.y, FXT_RECT::Normalize();
    256     }
    257     void		Set(const FXT_POINT &p, const FXT_VECTOR &v)
    258     {
    259         TopLeft(p), FXT_RECT::width = v.x, FXT_RECT::height = v.y, FXT_RECT::Normalize();
    260     }
    261     void		Reset()
    262     {
    263         FXT_RECT::left = FXT_RECT::top = FXT_RECT::width = FXT_RECT::height = 0;
    264     }
    265     FXT_RECT&	operator += (const FXT_POINT &p)
    266     {
    267         left += p.x, top += p.y;
    268         return *this;
    269     }
    270     FXT_RECT&	operator -= (const FXT_POINT &p)
    271     {
    272         left -= p.x, top -= p.y;
    273         return *this;
    274     }
    275     baseType	right() const
    276     {
    277         return left + width;
    278     }
    279     baseType	bottom() const
    280     {
    281         return top + height;
    282     }
    283     void		Normalize()
    284     {
    285         if (width < 0) {
    286             left += width;
    287             width = -width;
    288         }
    289         if (height < 0) {
    290             top += height;
    291             height = -height;
    292         }
    293     }
    294     void		Offset(baseType dx, baseType dy)
    295     {
    296         left += dx;
    297         top += dy;
    298     }
    299     void		Inflate(baseType x, baseType y)
    300     {
    301         left -= x;
    302         width += x * 2;
    303         top -= y;
    304         height += y * 2;
    305     }
    306     void		Inflate(const FXT_POINT &p)
    307     {
    308         Inflate(p.x, p.y);
    309     }
    310     void		Inflate(baseType left, baseType top, baseType right, baseType bottom)
    311     {
    312         FXT_RECT::left -= left;
    313         FXT_RECT::top -= top;
    314         FXT_RECT::width += left + right;
    315         FXT_RECT::height += top + bottom;
    316     }
    317     void		Inflate(const FXT_RECT &rt)
    318     {
    319         Inflate(rt.left, rt.top, rt.left + rt.width, rt.top + rt.height);
    320     }
    321     void		Deflate(baseType x, baseType y)
    322     {
    323         left += x;
    324         width -= x * 2;
    325         top += y;
    326         height -= y * 2;
    327     }
    328     void		Deflate(const FXT_POINT &p)
    329     {
    330         Deflate(p.x, p.y);
    331     }
    332     void		Deflate(baseType left, baseType top, baseType right, baseType bottom)
    333     {
    334         FXT_RECT::left += left;
    335         FXT_RECT::top += top;
    336         FXT_RECT::width -= left + right;
    337         FXT_RECT::height -= top + bottom;
    338     }
    339     void		Deflate(const FXT_RECT &rt)
    340     {
    341         Deflate(rt.left, rt.top, rt.top + rt.width, rt.top + rt.height);
    342     }
    343     FX_BOOL		IsEmpty() const
    344     {
    345         return width <= 0 || height <= 0;
    346     }
    347     FX_BOOL		IsEmpty(FX_FLOAT fEpsilon) const
    348     {
    349         return width <= fEpsilon || height <= fEpsilon;
    350     }
    351     void		Empty()
    352     {
    353         width = height = 0;
    354     }
    355     FX_BOOL		Contains(baseType x, baseType y) const
    356     {
    357         return x >= left && x < left + width && y >= top && y < top + height;
    358     }
    359     FX_BOOL		Contains(const FXT_POINT &p) const
    360     {
    361         return Contains(p.x, p.y);
    362     }
    363     FX_BOOL		Contains(const FXT_RECT &rt) const
    364     {
    365         return rt.left >= left && rt.right() <= right() && rt.top >= top && rt.bottom() <= bottom();
    366     }
    367     baseType	Width() const
    368     {
    369         return width;
    370     }
    371     baseType	Height() const
    372     {
    373         return height;
    374     }
    375     FXT_SIZE	Size() const
    376     {
    377         FXT_SIZE size;
    378         size.Set(width, height);
    379         return size;
    380     }
    381     void		Size(FXT_SIZE s)
    382     {
    383         width = s.x, height = s.y;
    384     }
    385     FXT_POINT	TopLeft() const
    386     {
    387         FXT_POINT p;
    388         p.x = left;
    389         p.y = top;
    390         return p;
    391     }
    392     FXT_POINT	TopRight() const
    393     {
    394         FXT_POINT p;
    395         p.x = left + width;
    396         p.y = top;
    397         return p;
    398     }
    399     FXT_POINT	BottomLeft() const
    400     {
    401         FXT_POINT p;
    402         p.x = left;
    403         p.y = top + height;
    404         return p;
    405     }
    406     FXT_POINT	BottomRight() const
    407     {
    408         FXT_POINT p;
    409         p.x = left + width;
    410         p.y = top + height;
    411         return p;
    412     }
    413     void		TopLeft(FXT_POINT tl)
    414     {
    415         left = tl.x;
    416         top = tl.y;
    417     }
    418     void		TopRight(FXT_POINT tr)
    419     {
    420         width = tr.x - left;
    421         top = tr.y;
    422     }
    423     void		BottomLeft(FXT_POINT bl)
    424     {
    425         left = bl.x;
    426         height = bl.y - top;
    427     }
    428     void		BottomRight(FXT_POINT br)
    429     {
    430         width = br.x - left;
    431         height = br.y - top;
    432     }
    433     FXT_POINT	Center() const
    434     {
    435         FXT_POINT p;
    436         p.x = left + width / 2;
    437         p.y = top + height / 2;
    438         return p;
    439     }
    440     void		GetParallelogram(FXT_PARAL &pg) const
    441     {
    442         pg.x = left, pg.y = top;
    443         pg.x1 = width, pg.y1 = 0;
    444         pg.x2 = 0, pg.y2 = height;
    445     }
    446     void		Union(baseType x, baseType y)
    447     {
    448         baseType r = right(), b = bottom();
    449         if (left > x) {
    450             left = x;
    451         }
    452         if (r < x) {
    453             r = x;
    454         }
    455         if (top > y) {
    456             top = y;
    457         }
    458         if (b < y) {
    459             b = y;
    460         }
    461         width = r - left;
    462         height = b - top;
    463     }
    464     void		Union(const FXT_POINT &p)
    465     {
    466         Union(p.x, p.y);
    467     }
    468     void		Union(const FXT_RECT &rt)
    469     {
    470         baseType r = right(), b = bottom();
    471         if (left > rt.left) {
    472             left = rt.left;
    473         }
    474         if (r < rt.right()) {
    475             r = rt.right();
    476         }
    477         if (top > rt.top) {
    478             top = rt.top;
    479         }
    480         if (b < rt.bottom()) {
    481             b = rt.bottom();
    482         }
    483         width = r - left;
    484         height = b - top;
    485     }
    486     void		Intersect(const FXT_RECT &rt)
    487     {
    488         baseType r = right(), b = bottom();
    489         if (left < rt.left) {
    490             left = rt.left;
    491         }
    492         if (r > rt.right()) {
    493             r = rt.right();
    494         }
    495         if (top < rt.top) {
    496             top = rt.top;
    497         }
    498         if (b > rt.bottom()) {
    499             b = rt.bottom();
    500         }
    501         width = r - left;
    502         height = b - top;
    503     }
    504     FX_BOOL		IntersectWith(const FXT_RECT &rt) const
    505     {
    506         FXT_RECT rect = rt;
    507         rect.Intersect(*this);
    508         return !rect.IsEmpty();
    509     }
    510     FX_BOOL		IntersectWith(const FXT_RECT &rt, FX_FLOAT fEpsilon) const
    511     {
    512         FXT_RECT rect = rt;
    513         rect.Intersect(*this);
    514         return !rect.IsEmpty(fEpsilon);
    515     }
    516     friend	FX_BOOL	operator == (const FXT_RECT &rc1, const FXT_RECT &rc2)
    517     {
    518         return rc1.left == rc2.left && rc1.top == rc2.top && rc1.width == rc2.width && rc1.height == rc2.height;
    519     }
    520     friend	FX_BOOL	operator != (const FXT_RECT &rc1, const FXT_RECT &rc2)
    521     {
    522         return rc1.left != rc2.left || rc1.top != rc2.top || rc1.width != rc2.width || rc1.height != rc2.height;
    523     }
    524     baseType left, top;
    525     baseType width, height;
    526 };
    527 typedef CFX_RTemplate<FX_INT32>			CFX_Rect;
    528 typedef CFX_RTemplate<FX_FLOAT>			CFX_RectF;
    529 typedef CFX_RTemplate<FX_INT32> *		FX_LPRECT;
    530 typedef CFX_RTemplate<FX_FLOAT> *		FX_LPRECTF;
    531 typedef CFX_RTemplate<FX_INT32> const *	FX_LPCRECT;
    532 typedef CFX_RTemplate<FX_FLOAT> const *	FX_LPCRECTF;
    533 typedef CFX_ArrayTemplate<CFX_RectF>	CFX_RectFArray;
    534 struct FX_RECT {
    535 
    536     int			left;
    537 
    538     int			top;
    539 
    540     int			right;
    541 
    542     int			bottom;
    543 
    544     FX_RECT(): left(0), top(0), right(0), bottom(0) { }
    545 
    546     FX_RECT(int left1, int top1, int right1, int bottom1)
    547     {
    548         left = left1;
    549         top = top1;
    550         right = right1;
    551         bottom = bottom1;
    552     }
    553 
    554     int			Width() const
    555     {
    556         return right - left;
    557     }
    558 
    559     int			Height() const
    560     {
    561         return bottom - top;
    562     }
    563 
    564     FX_BOOL		IsEmpty() const
    565     {
    566         return right <= left || bottom <= top;
    567     }
    568 
    569     void		Normalize();
    570 
    571     void		Intersect(const FX_RECT& src);
    572 
    573     void		Intersect(int left1, int top1, int right1, int bottom1)
    574     {
    575         Intersect(FX_RECT(left1, top1, right1, bottom1));
    576     }
    577 
    578     void		Union(const FX_RECT& other_rect);
    579 
    580     FX_BOOL		operator == (const FX_RECT& src) const
    581     {
    582         return left == src.left && right == src.right && top == src.top && bottom == src.bottom;
    583     }
    584 
    585     void		Offset(int dx, int dy)
    586     {
    587         left += dx;
    588         right += dx;
    589         top += dy;
    590         bottom += dy;
    591     }
    592 
    593     FX_BOOL		Contains(const FX_RECT& other_rect) const
    594     {
    595         return other_rect.left >= left && other_rect.right <= right && other_rect.top >= top && other_rect.bottom <= bottom;
    596     }
    597 
    598     FX_BOOL		Contains(int x, int y) const
    599     {
    600         return x >= left && x < right && y >= top && y < bottom;
    601     }
    602 };
    603 struct FX_SMALL_RECT {
    604 
    605     FX_SHORT	Left;
    606 
    607     FX_SHORT	Top;
    608 
    609     FX_SHORT	Right;
    610 
    611     FX_SHORT	Bottom;
    612 };
    613 class CFX_FloatRect
    614 {
    615 public:
    616 
    617     CFX_FloatRect()
    618     {
    619         left = right = bottom = top = 0;
    620     }
    621 
    622     CFX_FloatRect(FX_FLOAT left1, FX_FLOAT bottom1, FX_FLOAT right1, FX_FLOAT top1)
    623     {
    624         left = left1;
    625         bottom = bottom1;
    626         right = right1;
    627         top = top1;
    628     }
    629 
    630     CFX_FloatRect(const FX_FLOAT* pArray)
    631     {
    632         left = pArray[0];
    633         bottom = pArray[1];
    634         right = pArray[2];
    635         top = pArray[3];
    636     }
    637 
    638     CFX_FloatRect(const FX_RECT& rect);
    639 
    640     FX_BOOL				IsEmpty() const
    641     {
    642         return left >= right || bottom >= top;
    643     }
    644 
    645     void				Normalize();
    646 
    647     void				Reset()
    648     {
    649         left = right = bottom = top = 0;
    650     }
    651 
    652     FX_BOOL				Contains(const CFX_FloatRect& other_rect) const;
    653 
    654     FX_BOOL				Contains(FX_FLOAT x, FX_FLOAT y) const;
    655 
    656     void				Transform(const CFX_Matrix* pMatrix);
    657 
    658     void				Intersect(const CFX_FloatRect& other_rect);
    659 
    660     void				Union(const CFX_FloatRect& other_rect);
    661 
    662     FX_RECT				GetInnerRect() const;
    663 
    664     FX_RECT				GetOutterRect() const;
    665 
    666     FX_RECT				GetClosestRect() const;
    667 
    668     int					Substract4(CFX_FloatRect& substract_rect, CFX_FloatRect* pRects);
    669 
    670     void				InitRect(FX_FLOAT x, FX_FLOAT y)
    671     {
    672         left = right = x;
    673         bottom = top = y;
    674     }
    675 
    676     void				UpdateRect(FX_FLOAT x, FX_FLOAT y);
    677 
    678     FX_FLOAT			Width() const
    679     {
    680         return right - left;
    681     }
    682 
    683     FX_FLOAT			Height() const
    684     {
    685         return top - bottom;
    686     }
    687 
    688     void				Inflate(FX_FLOAT x, FX_FLOAT y)
    689     {
    690         Normalize();
    691         left -= x;
    692         right += x;
    693         bottom -= y;
    694         top += y;
    695     }
    696 
    697     void				Inflate(FX_FLOAT left, FX_FLOAT bottom, FX_FLOAT right, FX_FLOAT top)
    698     {
    699         Normalize();
    700         this->left -= left;
    701         this->bottom -= bottom;
    702         this->right += right;
    703         this->top += top;
    704     }
    705 
    706     void				Inflate(const CFX_FloatRect &rt)
    707     {
    708         Inflate(rt.left, rt.bottom, rt.right, rt.top);
    709     }
    710 
    711     void				Deflate(FX_FLOAT x, FX_FLOAT y)
    712     {
    713         Normalize();
    714         left += x;
    715         right -= x;
    716         bottom += y;
    717         top -= y;
    718     }
    719 
    720     void				Deflate(FX_FLOAT left, FX_FLOAT bottom, FX_FLOAT right, FX_FLOAT top)
    721     {
    722         Normalize();
    723         this->left += left;
    724         this->bottom += bottom;
    725         this->right -= right;
    726         this->top -= top;
    727     }
    728 
    729     void				Deflate(const CFX_FloatRect &rt)
    730     {
    731         Deflate(rt.left, rt.bottom, rt.right, rt.top);
    732     }
    733 
    734     void				Translate(FX_FLOAT e, FX_FLOAT f)
    735     {
    736         left += e;
    737         right += e;
    738         top += f;
    739         bottom += f;
    740     }
    741 
    742     static CFX_FloatRect	GetBBox(const CFX_FloatPoint* pPoints, int nPoints);
    743 
    744     FX_FLOAT			left;
    745 
    746     FX_FLOAT			right;
    747 
    748     FX_FLOAT			bottom;
    749 
    750     FX_FLOAT			top;
    751 };
    752 class CFX_Matrix
    753 {
    754 public:
    755 
    756     CFX_Matrix()
    757     {
    758         a = d = 1;
    759         b = c = e = f = 0;
    760     }
    761 
    762     CFX_Matrix(FX_FLOAT a1, FX_FLOAT b1, FX_FLOAT c1, FX_FLOAT d1, FX_FLOAT e1, FX_FLOAT f1)
    763     {
    764         a = a1;
    765         b = b1;
    766         c = c1;
    767         d = d1;
    768         e = e1;
    769         f = f1;
    770     }
    771 
    772     void			Set(FX_FLOAT a, FX_FLOAT b, FX_FLOAT c, FX_FLOAT d, FX_FLOAT e, FX_FLOAT f);
    773     void			Set(const FX_FLOAT n[6]);
    774 
    775     void			SetIdentity()
    776     {
    777         a = d = 1;
    778         b = c = e = f = 0;
    779     }
    780 
    781     void			SetReverse(const CFX_Matrix &m);
    782 
    783     void			Concat(FX_FLOAT a, FX_FLOAT b, FX_FLOAT c, FX_FLOAT d, FX_FLOAT e, FX_FLOAT f, FX_BOOL bPrepended = FALSE);
    784 
    785     void			Concat(const CFX_Matrix &m, FX_BOOL bPrepended = FALSE);
    786 
    787     void			ConcatInverse(const CFX_Matrix& m, FX_BOOL bPrepended = FALSE);
    788     void			Reset()
    789     {
    790         SetIdentity();
    791     }
    792 
    793     void			Copy(const CFX_Matrix& m)
    794     {
    795         *this = m;
    796     }
    797 
    798     FX_BOOL			IsIdentity() const
    799     {
    800         return a == 1 && b == 0 && c == 0 && d == 1 && e == 0 && f == 0;
    801     }
    802     FX_BOOL			IsInvertible() const;
    803 
    804     FX_BOOL			Is90Rotated() const;
    805 
    806     FX_BOOL			IsScaled() const;
    807 
    808     void			Translate(FX_FLOAT x, FX_FLOAT y, FX_BOOL bPrepended = FALSE);
    809 
    810     void			TranslateI(FX_INT32 x, FX_INT32 y, FX_BOOL bPrepended = FALSE)
    811     {
    812         Translate((FX_FLOAT)x, (FX_FLOAT)y, bPrepended);
    813     }
    814 
    815     void			Scale(FX_FLOAT sx, FX_FLOAT sy, FX_BOOL bPrepended = FALSE);
    816 
    817     void			Rotate(FX_FLOAT fRadian, FX_BOOL bPrepended = FALSE);
    818 
    819     void			RotateAt(FX_FLOAT fRadian, FX_FLOAT x, FX_FLOAT y, FX_BOOL bPrepended = FALSE);
    820 
    821     void			Shear(FX_FLOAT fAlphaRadian, FX_FLOAT fBetaRadian, FX_BOOL bPrepended = FALSE);
    822 
    823     void			MatchRect(const CFX_FloatRect &dest, const CFX_FloatRect &src);
    824 
    825     FX_FLOAT		GetXUnit() const;
    826 
    827     FX_FLOAT		GetYUnit() const;
    828     void			GetUnitRect(CFX_RectF &rect) const;
    829 
    830     CFX_FloatRect	GetUnitRect() const;
    831 
    832     FX_FLOAT		GetUnitArea() const;
    833     FX_FLOAT		TransformXDistance(FX_FLOAT dx) const;
    834     FX_INT32		TransformXDistance(FX_INT32 dx) const;
    835     FX_FLOAT		TransformYDistance(FX_FLOAT dy) const;
    836     FX_INT32		TransformYDistance(FX_INT32 dy) const;
    837     FX_FLOAT		TransformDistance(FX_FLOAT dx, FX_FLOAT dy) const;
    838     FX_INT32		TransformDistance(FX_INT32 dx, FX_INT32 dy) const;
    839 
    840     FX_FLOAT		TransformDistance(FX_FLOAT distance) const;
    841     void			TransformPoint(FX_FLOAT &x, FX_FLOAT &y) const;
    842     void			TransformPoint(FX_INT32 &x, FX_INT32 &y) const;
    843     void			TransformPoints(CFX_PointF *points, FX_INT32 iCount) const;
    844     void			TransformPoints(CFX_Point *points, FX_INT32 iCount) const;
    845 
    846     void			Transform(FX_FLOAT& x, FX_FLOAT& y) const
    847     {
    848         TransformPoint(x, y);
    849     }
    850 
    851     void			Transform(FX_FLOAT x, FX_FLOAT y, FX_FLOAT& x1, FX_FLOAT& y1) const
    852     {
    853         x1 = x, y1 = y;
    854         TransformPoint(x1, y1);
    855     }
    856     void			TransformVector(CFX_VectorF &v) const;
    857     void			TransformVector(CFX_Vector &v) const;
    858     void			TransformRect(CFX_RectF &rect) const;
    859     void			TransformRect(CFX_Rect &rect) const;
    860 
    861     void			TransformRect(FX_FLOAT& left, FX_FLOAT& right, FX_FLOAT& top, FX_FLOAT& bottom) const;
    862 
    863     void			TransformRect(CFX_FloatRect& rect) const
    864     {
    865         TransformRect(rect.left, rect.right, rect.top, rect.bottom);
    866     }
    867 
    868     FX_FLOAT		GetA() const
    869     {
    870         return a;
    871     }
    872 
    873     FX_FLOAT		GetB() const
    874     {
    875         return b;
    876     }
    877 
    878     FX_FLOAT		GetC() const
    879     {
    880         return c;
    881     }
    882 
    883     FX_FLOAT		GetD() const
    884     {
    885         return d;
    886     }
    887 
    888     FX_FLOAT		GetE() const
    889     {
    890         return e;
    891     }
    892 
    893     FX_FLOAT		GetF() const
    894     {
    895         return f;
    896     }
    897 public:
    898     FX_FLOAT a;
    899     FX_FLOAT b;
    900     FX_FLOAT c;
    901     FX_FLOAT d;
    902     FX_FLOAT e;
    903     FX_FLOAT f;
    904 };
    905 #define CFX_AffineMatrix	CFX_Matrix
    906 
    907 #endif  // CORE_INCLUDE_FXCRT_FX_COORDINATES_H_
    908