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