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
12template<class baseType> class CFX_PSVTemplate;
13template<class baseType> class CFX_VTemplate;
14template<class baseType> class CFX_PRLTemplate;
15template<class baseType> class CFX_RTemplate;
16template<class baseType> class CFX_ETemplate;
17template<class baseType> class CFX_ATemplate;
18template<class baseType> class CFX_RRTemplate;
19class CFX_Matrix;
20template<class baseType>
21class CFX_PSVTemplate
22{
23public:
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};
116typedef CFX_PSVTemplate<FX_INT32>			CFX_Point;
117typedef CFX_PSVTemplate<FX_FLOAT>			CFX_PointF;
118typedef CFX_PSVTemplate<FX_INT32>			CFX_Size;
119typedef CFX_PSVTemplate<FX_FLOAT>			CFX_SizeF;
120typedef CFX_ArrayTemplate<CFX_Point>		CFX_Points;
121typedef CFX_ArrayTemplate<CFX_PointF>		CFX_PointsF;
122typedef CFX_PSVTemplate<FX_INT32> *			FX_LPPOINT;
123typedef CFX_PSVTemplate<FX_FLOAT> *			FX_LPPOINTF;
124typedef CFX_PSVTemplate<FX_INT32> const *	FX_LPCPOINT;
125typedef CFX_PSVTemplate<FX_FLOAT> const *	FX_LPCPOINTF;
126#define CFX_FloatPoint	CFX_PointF
127template<class baseType>
128class CFX_VTemplate: public CFX_PSVTemplate<baseType>
129{
130public:
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};
230typedef CFX_VTemplate<FX_INT32> CFX_Vector;
231typedef CFX_VTemplate<FX_FLOAT> CFX_VectorF;
232template<class baseType>
233class CFX_RTemplate
234{
235public:
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};
527typedef CFX_RTemplate<FX_INT32>			CFX_Rect;
528typedef CFX_RTemplate<FX_FLOAT>			CFX_RectF;
529typedef CFX_RTemplate<FX_INT32> *		FX_LPRECT;
530typedef CFX_RTemplate<FX_FLOAT> *		FX_LPRECTF;
531typedef CFX_RTemplate<FX_INT32> const *	FX_LPCRECT;
532typedef CFX_RTemplate<FX_FLOAT> const *	FX_LPCRECTF;
533typedef CFX_ArrayTemplate<CFX_RectF>	CFX_RectFArray;
534struct 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};
603struct FX_SMALL_RECT {
604
605    FX_SHORT	Left;
606
607    FX_SHORT	Top;
608
609    FX_SHORT	Right;
610
611    FX_SHORT	Bottom;
612};
613class CFX_FloatRect
614{
615public:
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};
752class CFX_Matrix
753{
754public:
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    }
897public:
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