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