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.
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
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;
17 template<class baseType>
18 class CFX_PSVTemplate : public CFX_Object
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)
26 FXT_PSV::x = x, FXT_PSV::y = y;
28 void Set(const FXT_PSV &psv)
30 FXT_PSV::x = psv.x, FXT_PSV::y = psv.y;
32 void Add(baseType x, baseType y)
34 FXT_PSV::x += x, FXT_PSV::y += y;
36 void Subtract(baseType x, baseType y)
38 FXT_PSV::x -= x, FXT_PSV::y -= y;
42 FXT_PSV::x = FXT_PSV::y = 0;
44 FXT_PSV& operator += (const FXT_PSV &obj)
50 FXT_PSV& operator -= (const FXT_PSV &obj)
56 FXT_PSV& operator *= (baseType lamda)
62 FXT_PSV& operator /= (baseType lamda)
68 friend FX_BOOL operator == (const FXT_PSV &obj1, const FXT_PSV &obj2)
70 return obj1.x == obj2.x && obj1.y == obj2.y;
72 friend FX_BOOL operator != (const FXT_PSV &obj1, const FXT_PSV &obj2)
74 return obj1.x != obj2.x || obj1.y != obj2.y;
76 friend FXT_PSV operator + (const FXT_PSV &obj1, const FXT_PSV &obj2)
79 obj.x = obj1.x + obj2.x;
80 obj.y = obj1.y + obj2.y;
83 friend FXT_PSV operator - (const FXT_PSV &obj1, const FXT_PSV &obj2)
86 obj.x = obj1.x - obj2.x;
87 obj.y = obj1.y - obj2.y;
90 friend FXT_PSV operator * (const FXT_PSV &obj, baseType lamda)
97 friend FXT_PSV operator * (baseType lamda, const FXT_PSV &obj)
104 friend FXT_PSV operator / (const FXT_PSV &obj, baseType lamda)
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>
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)
134 FXT_PSV::x = x, FXT_PSV::y = y;
136 void Set(const FXT_PSV &psv)
138 FXT_PSV::x = psv.x, FXT_PSV::y = psv.y;
140 void Set(const FXT_POINT &p1, const FXT_POINT &p2)
142 FXT_PSV::x = p2.x - p1.x, FXT_PSV::y = p2.y - p1.y;
146 FXT_PSV::x = FXT_PSV::y = 0;
148 baseType SquareLength() const
150 return FXT_PSV::x * FXT_PSV::x + FXT_PSV::y * FXT_PSV::y;
152 baseType Length() const
154 return FXSYS_sqrt(FXT_PSV::x * FXT_PSV::x + FXT_PSV::y * FXT_PSV::y);
158 FX_FLOAT fLen = FXSYS_sqrt(FXT_PSV::x * FXT_PSV::x + FXT_PSV::y * FXT_PSV::y);
159 if (fLen < 0.0001f) {
162 FXT_PSV::x = ((baseType)FXT_PSV::x) / fLen;
163 FXT_PSV::y = ((baseType)FXT_PSV::y) / fLen;
165 baseType DotProduct(baseType x, baseType y) const
167 return FXT_PSV::x * x + FXT_PSV::y * y;
169 baseType DotProduct(const FXT_VECTOR &v) const
171 return FXT_PSV::x * v.x + FXT_PSV::y * v.y;
173 FX_BOOL IsParallel(baseType x, baseType y) const
175 baseType t = FXT_PSV::x * y - FXT_PSV::y * x;
176 return FXSYS_fabs(t) < 0x0001f;
178 FX_BOOL IsParallel(const FXT_VECTOR &v) const
180 return IsParallel(v.x, v.y);
182 FX_BOOL IsPerpendicular(baseType x, baseType y) const
184 baseType t = DotProduct(x, y);
185 return FXSYS_fabs(t) < 0x0001f;
187 FX_BOOL IsPerpendicular(const FXT_VECTOR &v) const
189 return IsPerpendicular(v.x, v.y);
191 void Translate(baseType dx, baseType dy)
193 FXT_PSV::x += dx, FXT_PSV::y += dy;
195 void Scale(baseType sx, baseType sy)
197 FXT_PSV::x *= sx, FXT_PSV::y *= sy;
199 void Rotate(FX_FLOAT fRadian)
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;
208 friend FX_FLOAT Cosine(const FXT_VECTOR &v1, const FXT_VECTOR &v2)
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());
214 friend FX_FLOAT ArcCosine(const FXT_VECTOR &v1, const FXT_VECTOR &v2)
216 return (FX_FLOAT)FXSYS_acos(Cosine(v1, v2));
218 friend FX_FLOAT SlopeAngle(const FXT_VECTOR &v)
222 FX_FLOAT fSlope = ArcCosine(v, vx);
223 return v.y < 0 ? -fSlope : fSlope;
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
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)
239 FXT_RECT::left = left, FXT_RECT::top = top, FXT_RECT::width = width, FXT_RECT::height = height;
241 void Set(baseType left, baseType top, const FXT_SIZE &size)
243 FXT_RECT::left = left, FXT_RECT::top = top, FXT_RECT::Size(size);
245 void Set(const FXT_POINT &p, baseType width, baseType height)
247 TopLeft(p), FXT_RECT::width = width, FXT_RECT::height = height;
249 void Set(const FXT_POINT &p1, const FXT_POINT &p2)
251 TopLeft(p1), FXT_RECT::width = p2.x - p1.x, FXT_RECT::height = p2.y - p1.y, FXT_RECT::Normalize();
253 void Set(const FXT_POINT &p, const FXT_VECTOR &v)
255 TopLeft(p), FXT_RECT::width = v.x, FXT_RECT::height = v.y, FXT_RECT::Normalize();
259 FXT_RECT::left = FXT_RECT::top = FXT_RECT::width = FXT_RECT::height = 0;
261 FXT_RECT& operator += (const FXT_POINT &p)
263 left += p.x, top += p.y;
266 FXT_RECT& operator -= (const FXT_POINT &p)
268 left -= p.x, top -= p.y;
271 baseType right() const
275 baseType bottom() const
290 void Offset(baseType dx, baseType dy)
295 void Inflate(baseType x, baseType y)
302 void Inflate(const FXT_POINT &p)
306 void Inflate(baseType left, baseType top, baseType right, baseType bottom)
308 FXT_RECT::left -= left;
309 FXT_RECT::top -= top;
310 FXT_RECT::width += left + right;
311 FXT_RECT::height += top + bottom;
313 void Inflate(const FXT_RECT &rt)
315 Inflate(rt.left, rt.top, rt.left + rt.width, rt.top + rt.height);
317 void Deflate(baseType x, baseType y)
324 void Deflate(const FXT_POINT &p)
328 void Deflate(baseType left, baseType top, baseType right, baseType bottom)
330 FXT_RECT::left += left;
331 FXT_RECT::top += top;
332 FXT_RECT::width -= left + right;
333 FXT_RECT::height -= top + bottom;
335 void Deflate(const FXT_RECT &rt)
337 Deflate(rt.left, rt.top, rt.top + rt.width, rt.top + rt.height);
339 FX_BOOL IsEmpty() const
341 return width <= 0 || height <= 0;
343 FX_BOOL IsEmpty(FX_FLOAT fEpsilon) const
345 return width <= fEpsilon || height <= fEpsilon;
351 FX_BOOL Contains(baseType x, baseType y) const
353 return x >= left && x < left + width && y >= top && y < top + height;
355 FX_BOOL Contains(const FXT_POINT &p) const
357 return Contains(p.x, p.y);
359 FX_BOOL Contains(const FXT_RECT &rt) const
361 return rt.left >= left && rt.right() <= right() && rt.top >= top && rt.bottom() <= bottom();
363 baseType Width() const
367 baseType Height() const
371 FXT_SIZE Size() const
374 size.Set(width, height);
377 void Size(FXT_SIZE s)
379 width = s.x, height = s.y;
381 FXT_POINT TopLeft() const
388 FXT_POINT TopRight() const
395 FXT_POINT BottomLeft() const
402 FXT_POINT BottomRight() const
409 void TopLeft(FXT_POINT tl)
414 void TopRight(FXT_POINT tr)
419 void BottomLeft(FXT_POINT bl)
424 void BottomRight(FXT_POINT br)
429 FXT_POINT Center() const
432 p.x = left + width / 2;
433 p.y = top + height / 2;
436 void GetParallelogram(FXT_PARAL &pg) const
438 pg.x = left, pg.y = top;
439 pg.x1 = width, pg.y1 = 0;
440 pg.x2 = 0, pg.y2 = height;
442 void Union(baseType x, baseType y)
444 baseType r = right(), b = bottom();
460 void Union(const FXT_POINT &p)
464 void Union(const FXT_RECT &rt)
466 baseType r = right(), b = bottom();
467 if (left > rt.left) {
470 if (r < rt.right()) {
476 if (b < rt.bottom()) {
482 void Intersect(const FXT_RECT &rt)
484 baseType r = right(), b = bottom();
485 if (left < rt.left) {
488 if (r > rt.right()) {
494 if (b > rt.bottom()) {
500 FX_BOOL IntersectWith(const FXT_RECT &rt) const
503 rect.Intersect(*this);
504 return !rect.IsEmpty();
506 FX_BOOL IntersectWith(const FXT_RECT &rt, FX_FLOAT fEpsilon) const
509 rect.Intersect(*this);
510 return !rect.IsEmpty(fEpsilon);
512 friend FX_BOOL operator == (const FXT_RECT &rc1, const FXT_RECT &rc2)
514 return rc1.left == rc2.left && rc1.top == rc2.top && rc1.width == rc2.width && rc1.height == rc2.height;
516 friend FX_BOOL operator != (const FXT_RECT &rc1, const FXT_RECT &rc2)
518 return rc1.left != rc2.left || rc1.top != rc2.top || rc1.width != rc2.width || rc1.height != rc2.height;
521 baseType width, height;
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;
540 FX_RECT(): left(0), top(0), right(0), bottom(0) { }
542 FX_RECT(int left1, int top1, int right1, int bottom1)
560 FX_BOOL IsEmpty() const
562 return right <= left || bottom <= top;
567 void Intersect(const FX_RECT& src);
569 void Intersect(int left1, int top1, int right1, int bottom1)
571 Intersect(FX_RECT(left1, top1, right1, bottom1));
574 void Union(const FX_RECT& other_rect);
576 FX_BOOL operator == (const FX_RECT& src) const
578 return left == src.left && right == src.right && top == src.top && bottom == src.bottom;
581 void Offset(int dx, int dy)
589 FX_BOOL Contains(const FX_RECT& other_rect) const
591 return other_rect.left >= left && other_rect.right <= right && other_rect.top >= top && other_rect.bottom <= bottom;
594 FX_BOOL Contains(int x, int y) const
596 return x >= left && x < right && y >= top && y < bottom;
599 struct FX_SMALL_RECT {
609 class CFX_FloatRect : public CFX_Object
615 left = right = bottom = top = 0;
618 CFX_FloatRect(FX_FLOAT left1, FX_FLOAT bottom1, FX_FLOAT right1, FX_FLOAT top1)
626 CFX_FloatRect(const FX_FLOAT* pArray)
634 CFX_FloatRect(const FX_RECT& rect);
636 FX_BOOL IsEmpty() const
638 return left >= right || bottom >= top;
645 left = right = bottom = top = 0;
648 FX_BOOL Contains(const CFX_FloatRect& other_rect) const;
650 FX_BOOL Contains(FX_FLOAT x, FX_FLOAT y) const;
652 void Transform(const CFX_Matrix* pMatrix);
654 void Intersect(const CFX_FloatRect& other_rect);
656 void Union(const CFX_FloatRect& other_rect);
658 FX_RECT GetInnerRect() const;
660 FX_RECT GetOutterRect() const;
662 FX_RECT GetClosestRect() const;
664 int Substract4(CFX_FloatRect& substract_rect, CFX_FloatRect* pRects);
666 void InitRect(FX_FLOAT x, FX_FLOAT y)
672 void UpdateRect(FX_FLOAT x, FX_FLOAT y);
674 FX_FLOAT Width() const
679 FX_FLOAT Height() const
684 void Inflate(FX_FLOAT x, FX_FLOAT y)
693 void Inflate(FX_FLOAT left, FX_FLOAT bottom, FX_FLOAT right, FX_FLOAT top)
697 this->bottom -= bottom;
698 this->right += right;
702 void Inflate(const CFX_FloatRect &rt)
704 Inflate(rt.left, rt.bottom, rt.right, rt.top);
707 void Deflate(FX_FLOAT x, FX_FLOAT y)
716 void Deflate(FX_FLOAT left, FX_FLOAT bottom, FX_FLOAT right, FX_FLOAT top)
720 this->bottom += bottom;
721 this->right -= right;
725 void Deflate(const CFX_FloatRect &rt)
727 Deflate(rt.left, rt.bottom, rt.right, rt.top);
730 void Translate(FX_FLOAT e, FX_FLOAT f)
738 static CFX_FloatRect GetBBox(const CFX_FloatPoint* pPoints, int nPoints);
748 class CFX_Matrix : public CFX_Object
758 CFX_Matrix(FX_FLOAT a1, FX_FLOAT b1, FX_FLOAT c1, FX_FLOAT d1, FX_FLOAT e1, FX_FLOAT f1)
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]);
777 void SetReverse(const CFX_Matrix &m);
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);
781 void Concat(const CFX_Matrix &m, FX_BOOL bPrepended = FALSE);
783 void ConcatInverse(const CFX_Matrix& m, FX_BOOL bPrepended = FALSE);
789 void Copy(const CFX_Matrix& m)
794 FX_BOOL IsIdentity() const
796 return a == 1 && b == 0 && c == 0 && d == 1 && e == 0 && f == 0;
798 FX_BOOL IsInvertible() const;
800 FX_BOOL Is90Rotated() const;
802 FX_BOOL IsScaled() const;
804 void Translate(FX_FLOAT x, FX_FLOAT y, FX_BOOL bPrepended = FALSE);
806 void TranslateI(FX_INT32 x, FX_INT32 y, FX_BOOL bPrepended = FALSE)
808 Translate((FX_FLOAT)x, (FX_FLOAT)y, bPrepended);
811 void Scale(FX_FLOAT sx, FX_FLOAT sy, FX_BOOL bPrepended = FALSE);
813 void Rotate(FX_FLOAT fRadian, FX_BOOL bPrepended = FALSE);
815 void RotateAt(FX_FLOAT fRadian, FX_FLOAT x, FX_FLOAT y, FX_BOOL bPrepended = FALSE);
817 void Shear(FX_FLOAT fAlphaRadian, FX_FLOAT fBetaRadian, FX_BOOL bPrepended = FALSE);
819 void MatchRect(const CFX_FloatRect &dest, const CFX_FloatRect &src);
821 FX_FLOAT GetXUnit() const;
823 FX_FLOAT GetYUnit() const;
824 void GetUnitRect(CFX_RectF &rect) const;
826 CFX_FloatRect GetUnitRect() const;
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;
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;
842 void Transform(FX_FLOAT& x, FX_FLOAT& y) const
844 TransformPoint(x, y);
847 void Transform(FX_FLOAT x, FX_FLOAT y, FX_FLOAT& x1, FX_FLOAT& y1) const
850 TransformPoint(x1, y1);
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;
857 void TransformRect(FX_FLOAT& left, FX_FLOAT& right, FX_FLOAT& top, FX_FLOAT& bottom) const;
859 void TransformRect(CFX_FloatRect& rect) const
861 TransformRect(rect.left, rect.right, rect.top, rect.bottom);
864 FX_FLOAT GetA() const
869 FX_FLOAT GetB() const
874 FX_FLOAT GetC() const
879 FX_FLOAT GetD() const
884 FX_FLOAT GetE() const
889 FX_FLOAT GetF() const
901 #define CFX_AffineMatrix CFX_Matrix