fx_coordinates.h revision ee451cb395940862dad63c85adfe8f2fd55e864c
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_
9template<class baseType> class CFX_PSVTemplate;
10template<class baseType> class CFX_VTemplate;
11template<class baseType> class CFX_PRLTemplate;
12template<class baseType> class CFX_RTemplate;
13template<class baseType> class CFX_ETemplate;
14template<class baseType> class CFX_ATemplate;
15template<class baseType> class CFX_RRTemplate;
16class CFX_Matrix;
17template<class baseType>
18class CFX_PSVTemplate : public CFX_Object
19{
20public:
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};
113typedef CFX_PSVTemplate<FX_INT32>			CFX_Point;
114typedef CFX_PSVTemplate<FX_FLOAT>			CFX_PointF;
115typedef CFX_PSVTemplate<FX_INT32>			CFX_Size;
116typedef CFX_PSVTemplate<FX_FLOAT>			CFX_SizeF;
117typedef CFX_ArrayTemplate<CFX_Point>		CFX_Points;
118typedef CFX_ArrayTemplate<CFX_PointF>		CFX_PointsF;
119typedef CFX_PSVTemplate<FX_INT32> *			FX_LPPOINT;
120typedef CFX_PSVTemplate<FX_FLOAT> *			FX_LPPOINTF;
121typedef CFX_PSVTemplate<FX_INT32> const *	FX_LPCPOINT;
122typedef CFX_PSVTemplate<FX_FLOAT> const *	FX_LPCPOINTF;
123#define CFX_FloatPoint	CFX_PointF
124template<class baseType>
125class CFX_VTemplate: public CFX_PSVTemplate<baseType>
126{
127public:
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};
224typedef CFX_VTemplate<FX_INT32> CFX_Vector;
225typedef CFX_VTemplate<FX_FLOAT> CFX_VectorF;
226template<class baseType>
227class CFX_RTemplate: public CFX_Object
228{
229public:
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};
521typedef CFX_RTemplate<FX_INT32>			CFX_Rect;
522typedef CFX_RTemplate<FX_FLOAT>			CFX_RectF;
523typedef CFX_RTemplate<FX_INT32> *		FX_LPRECT;
524typedef CFX_RTemplate<FX_FLOAT> *		FX_LPRECTF;
525typedef CFX_RTemplate<FX_INT32> const *	FX_LPCRECT;
526typedef CFX_RTemplate<FX_FLOAT> const *	FX_LPCRECTF;
527typedef CFX_ArrayTemplate<CFX_RectF>	CFX_RectFArray;
528struct 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};
597struct FX_SMALL_RECT {
598
599    FX_SHORT	Left;
600
601    FX_SHORT	Top;
602
603    FX_SHORT	Right;
604
605    FX_SHORT	Bottom;
606};
607class CFX_FloatRect : public CFX_Object
608{
609public:
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};
746class CFX_Matrix : public CFX_Object
747{
748public:
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    }
891public:
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