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