summaryrefslogtreecommitdiff
path: root/core/fxcrt/fx_coordinates.h
diff options
context:
space:
mode:
Diffstat (limited to 'core/fxcrt/fx_coordinates.h')
-rw-r--r--core/fxcrt/fx_coordinates.h671
1 files changed, 671 insertions, 0 deletions
diff --git a/core/fxcrt/fx_coordinates.h b/core/fxcrt/fx_coordinates.h
new file mode 100644
index 0000000000..d10f7b0c57
--- /dev/null
+++ b/core/fxcrt/fx_coordinates.h
@@ -0,0 +1,671 @@
+// Copyright 2014 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#ifndef CORE_FXCRT_FX_COORDINATES_H_
+#define CORE_FXCRT_FX_COORDINATES_H_
+
+#include "core/fxcrt/fx_basic.h"
+
+class CFX_Matrix;
+
+template <class BaseType>
+class CFX_PSTemplate {
+ public:
+ CFX_PSTemplate() : x(0), y(0) {}
+ CFX_PSTemplate(BaseType new_x, BaseType new_y) : x(new_x), y(new_y) {}
+ CFX_PSTemplate(const CFX_PSTemplate& other) : x(other.x), y(other.y) {}
+ void clear() {
+ x = 0;
+ y = 0;
+ }
+ CFX_PSTemplate operator=(const CFX_PSTemplate& other) {
+ if (this != &other) {
+ x = other.x;
+ y = other.y;
+ }
+ return *this;
+ }
+ bool operator==(const CFX_PSTemplate& other) const {
+ return x == other.x && y == other.y;
+ }
+ bool operator!=(const CFX_PSTemplate& other) const {
+ return !(*this == other);
+ }
+ CFX_PSTemplate& operator+=(const CFX_PSTemplate<BaseType>& obj) {
+ x += obj.x;
+ y += obj.y;
+ return *this;
+ }
+ CFX_PSTemplate& operator-=(const CFX_PSTemplate<BaseType>& obj) {
+ x -= obj.x;
+ y -= obj.y;
+ return *this;
+ }
+ CFX_PSTemplate& operator*=(BaseType factor) {
+ x *= factor;
+ y *= factor;
+ return *this;
+ }
+ CFX_PSTemplate& operator/=(BaseType divisor) {
+ x /= divisor;
+ y /= divisor;
+ return *this;
+ }
+ CFX_PSTemplate operator+(const CFX_PSTemplate& other) {
+ return CFX_PSTemplate(x + other.x, y + other.y);
+ }
+ CFX_PSTemplate operator-(const CFX_PSTemplate& other) {
+ return CFX_PSTemplate(x - other.x, y - other.y);
+ }
+ CFX_PSTemplate operator*(BaseType factor) {
+ return CFX_PSTemplate(x * factor, y * factor);
+ }
+ CFX_PSTemplate operator/(BaseType divisor) {
+ return CFX_PSTemplate(x / divisor, y / divisor);
+ }
+
+ BaseType x;
+ BaseType y;
+};
+typedef CFX_PSTemplate<int32_t> CFX_Point;
+typedef CFX_PSTemplate<FX_FLOAT> CFX_PointF;
+typedef CFX_PSTemplate<int32_t> CFX_Size;
+typedef CFX_PSTemplate<FX_FLOAT> CFX_SizeF;
+typedef CFX_ArrayTemplate<CFX_Point> CFX_Points;
+typedef CFX_ArrayTemplate<CFX_PointF> CFX_PointsF;
+
+template <class BaseType>
+class CFX_VTemplate : public CFX_PSTemplate<BaseType> {
+ public:
+ using CFX_PSTemplate<BaseType>::x;
+ using CFX_PSTemplate<BaseType>::y;
+
+ CFX_VTemplate() : CFX_PSTemplate<BaseType>() {}
+ CFX_VTemplate(BaseType new_x, BaseType new_y)
+ : CFX_PSTemplate<BaseType>(new_x, new_y) {}
+
+ CFX_VTemplate(const CFX_VTemplate& other) : CFX_PSTemplate<BaseType>(other) {}
+
+ CFX_VTemplate(const CFX_PSTemplate<BaseType>& point1,
+ const CFX_PSTemplate<BaseType>& point2)
+ : CFX_PSTemplate<BaseType>(point2.x - point1.x, point2.y - point1.y) {}
+
+ FX_FLOAT Length() const { return FXSYS_sqrt(x * x + y * y); }
+ void Normalize() {
+ FX_FLOAT fLen = Length();
+ if (fLen < 0.0001f)
+ return;
+
+ x /= fLen;
+ y /= fLen;
+ }
+ void Translate(BaseType dx, BaseType dy) {
+ x += dx;
+ y += dy;
+ }
+ void Scale(BaseType sx, BaseType sy) {
+ x *= sx;
+ y *= sy;
+ }
+ void Rotate(FX_FLOAT fRadian) {
+ FX_FLOAT cosValue = FXSYS_cos(fRadian);
+ FX_FLOAT sinValue = FXSYS_sin(fRadian);
+ x = x * cosValue - y * sinValue;
+ y = x * sinValue + y * cosValue;
+ }
+};
+typedef CFX_VTemplate<int32_t> CFX_Vector;
+typedef CFX_VTemplate<FX_FLOAT> CFX_VectorF;
+
+// Rectangles.
+// TODO(tsepez): Consolidate all these different rectangle classes.
+
+// LTRB rectangles (y-axis runs downwards).
+struct FX_RECT {
+ FX_RECT() : left(0), top(0), right(0), bottom(0) {}
+
+ FX_RECT(int l, int t, int r, int b) : left(l), top(t), right(r), bottom(b) {}
+
+ int Width() const { return right - left; }
+ int Height() const { return bottom - top; }
+ bool IsEmpty() const { return right <= left || bottom <= top; }
+
+ bool Valid() const {
+ pdfium::base::CheckedNumeric<int> w = right;
+ pdfium::base::CheckedNumeric<int> h = bottom;
+ w -= left;
+ h -= top;
+ return w.IsValid() && h.IsValid();
+ }
+
+ void Normalize();
+
+ void Intersect(const FX_RECT& src);
+ void Intersect(int l, int t, int r, int b) { Intersect(FX_RECT(l, t, r, b)); }
+
+ void Union(const FX_RECT& other_rect);
+ void Union(int l, int t, int r, int b) { Union(FX_RECT(l, t, r, b)); }
+
+ void Offset(int dx, int dy) {
+ left += dx;
+ right += dx;
+ top += dy;
+ bottom += dy;
+ }
+
+ bool operator==(const FX_RECT& src) const {
+ return left == src.left && right == src.right && top == src.top &&
+ bottom == src.bottom;
+ }
+
+ bool Contains(const FX_RECT& other_rect) const {
+ return other_rect.left >= left && other_rect.right <= right &&
+ other_rect.top >= top && other_rect.bottom <= bottom;
+ }
+
+ bool Contains(int x, int y) const {
+ return x >= left && x < right && y >= top && y < bottom;
+ }
+
+ int32_t left;
+ int32_t top;
+ int32_t right;
+ int32_t bottom;
+};
+
+// LBRT rectangles (y-axis runs upwards).
+class CFX_FloatPoint {
+ public:
+ CFX_FloatPoint() : x(0.0f), y(0.0f) {}
+ CFX_FloatPoint(FX_FLOAT xx, FX_FLOAT yy) : x(xx), y(yy) {}
+
+ bool operator==(const CFX_FloatPoint& that) const {
+ return x == that.x && y == that.y;
+ }
+ bool operator!=(const CFX_FloatPoint& that) const { return !(*this == that); }
+
+ FX_FLOAT x;
+ FX_FLOAT y;
+};
+
+// LTWH rectangles (y-axis runs downwards).
+template <class baseType>
+class CFX_RTemplate {
+ public:
+ typedef CFX_PSTemplate<baseType> FXT_POINT;
+ typedef CFX_PSTemplate<baseType> FXT_SIZE;
+ typedef CFX_VTemplate<baseType> FXT_VECTOR;
+ typedef CFX_RTemplate<baseType> FXT_RECT;
+ void Set(baseType dst_left,
+ baseType dst_top,
+ baseType dst_width,
+ baseType dst_height) {
+ left = dst_left;
+ top = dst_top;
+ width = dst_width;
+ height = dst_height;
+ }
+ void Set(baseType dst_left, baseType dst_top, const FXT_SIZE& dst_size) {
+ left = dst_left;
+ top = dst_top;
+ Size(dst_size);
+ }
+ void Set(const FXT_POINT& p, baseType dst_width, baseType dst_height) {
+ TopLeft(p);
+ width = dst_width;
+ height = dst_height;
+ }
+ void Set(const FXT_POINT& p1, const FXT_POINT& p2) {
+ TopLeft(p1);
+ width = p2.x - p1.x;
+ height = p2.y - p1.y;
+ Normalize();
+ }
+ void Set(const FXT_POINT& p, const FXT_VECTOR& v) {
+ TopLeft(p);
+ width = v.x;
+ height = v.y;
+ Normalize();
+ }
+ void Reset() {
+ left = 0;
+ top = 0;
+ width = 0;
+ height = 0;
+ }
+ FXT_RECT& operator+=(const FXT_POINT& p) {
+ left += p.x;
+ top += p.y;
+ return *this;
+ }
+ FXT_RECT& operator-=(const FXT_POINT& p) {
+ left -= p.x;
+ top -= p.y;
+ return *this;
+ }
+ baseType right() const { return left + width; }
+ baseType bottom() const { return top + height; }
+ void Normalize() {
+ if (width < 0) {
+ left += width;
+ width = -width;
+ }
+ if (height < 0) {
+ top += height;
+ height = -height;
+ }
+ }
+ void Offset(baseType dx, baseType dy) {
+ left += dx;
+ top += dy;
+ }
+ void Inflate(baseType x, baseType y) {
+ left -= x;
+ width += x * 2;
+ top -= y;
+ height += y * 2;
+ }
+ void Inflate(const FXT_POINT& p) { Inflate(p.x, p.y); }
+ void Inflate(baseType off_left,
+ baseType off_top,
+ baseType off_right,
+ baseType off_bottom) {
+ left -= off_left;
+ top -= off_top;
+ width += off_left + off_right;
+ height += off_top + off_bottom;
+ }
+ void Inflate(const FXT_RECT& rt) {
+ Inflate(rt.left, rt.top, rt.left + rt.width, rt.top + rt.height);
+ }
+ void Deflate(baseType x, baseType y) {
+ left += x;
+ width -= x * 2;
+ top += y;
+ height -= y * 2;
+ }
+ void Deflate(const FXT_POINT& p) { Deflate(p.x, p.y); }
+ void Deflate(baseType off_left,
+ baseType off_top,
+ baseType off_right,
+ baseType off_bottom) {
+ left += off_left;
+ top += off_top;
+ width -= off_left + off_right;
+ height -= off_top + off_bottom;
+ }
+ void Deflate(const FXT_RECT& rt) {
+ Deflate(rt.left, rt.top, rt.top + rt.width, rt.top + rt.height);
+ }
+ FX_BOOL IsEmpty() const { return width <= 0 || height <= 0; }
+ FX_BOOL IsEmpty(FX_FLOAT fEpsilon) const {
+ return width <= fEpsilon || height <= fEpsilon;
+ }
+ void Empty() { width = height = 0; }
+ bool Contains(baseType x, baseType y) const {
+ return x >= left && x < left + width && y >= top && y < top + height;
+ }
+ bool Contains(const FXT_POINT& p) const { return Contains(p.x, p.y); }
+ bool Contains(const FXT_RECT& rt) const {
+ return rt.left >= left && rt.right() <= right() && rt.top >= top &&
+ rt.bottom() <= bottom();
+ }
+ baseType Width() const { return width; }
+ baseType Height() const { return height; }
+ FXT_SIZE Size() const {
+ FXT_SIZE size;
+ size.Set(width, height);
+ return size;
+ }
+ void Size(FXT_SIZE s) { width = s.x, height = s.y; }
+ FXT_POINT TopLeft() const {
+ FXT_POINT p;
+ p.x = left;
+ p.y = top;
+ return p;
+ }
+ FXT_POINT TopRight() const {
+ FXT_POINT p;
+ p.x = left + width;
+ p.y = top;
+ return p;
+ }
+ FXT_POINT BottomLeft() const {
+ FXT_POINT p;
+ p.x = left;
+ p.y = top + height;
+ return p;
+ }
+ FXT_POINT BottomRight() const {
+ FXT_POINT p;
+ p.x = left + width;
+ p.y = top + height;
+ return p;
+ }
+ void TopLeft(FXT_POINT tl) {
+ left = tl.x;
+ top = tl.y;
+ }
+ void TopRight(FXT_POINT tr) {
+ width = tr.x - left;
+ top = tr.y;
+ }
+ void BottomLeft(FXT_POINT bl) {
+ left = bl.x;
+ height = bl.y - top;
+ }
+ void BottomRight(FXT_POINT br) {
+ width = br.x - left;
+ height = br.y - top;
+ }
+ FXT_POINT Center() const {
+ FXT_POINT p;
+ p.x = left + width / 2;
+ p.y = top + height / 2;
+ return p;
+ }
+ void Union(baseType x, baseType y) {
+ baseType r = right();
+ baseType b = bottom();
+ if (left > x)
+ left = x;
+ if (r < x)
+ r = x;
+ if (top > y)
+ top = y;
+ if (b < y)
+ b = y;
+ width = r - left;
+ height = b - top;
+ }
+ void Union(const FXT_POINT& p) { Union(p.x, p.y); }
+ void Union(const FXT_RECT& rt) {
+ baseType r = right();
+ baseType b = bottom();
+ if (left > rt.left)
+ left = rt.left;
+ if (r < rt.right())
+ r = rt.right();
+ if (top > rt.top)
+ top = rt.top;
+ if (b < rt.bottom())
+ b = rt.bottom();
+ width = r - left;
+ height = b - top;
+ }
+ void Intersect(const FXT_RECT& rt) {
+ baseType r = right();
+ baseType b = bottom();
+ if (left < rt.left)
+ left = rt.left;
+ if (r > rt.right())
+ r = rt.right();
+ if (top < rt.top)
+ top = rt.top;
+ if (b > rt.bottom())
+ b = rt.bottom();
+ width = r - left;
+ height = b - top;
+ }
+ FX_BOOL IntersectWith(const FXT_RECT& rt) const {
+ FXT_RECT rect = rt;
+ rect.Intersect(*this);
+ return !rect.IsEmpty();
+ }
+ FX_BOOL IntersectWith(const FXT_RECT& rt, FX_FLOAT fEpsilon) const {
+ FXT_RECT rect = rt;
+ rect.Intersect(*this);
+ return !rect.IsEmpty(fEpsilon);
+ }
+ friend bool operator==(const FXT_RECT& rc1, const FXT_RECT& rc2) {
+ return rc1.left == rc2.left && rc1.top == rc2.top &&
+ rc1.width == rc2.width && rc1.height == rc2.height;
+ }
+ friend bool operator!=(const FXT_RECT& rc1, const FXT_RECT& rc2) {
+ return !(rc1 == rc2);
+ }
+ baseType left, top;
+ baseType width, height;
+};
+typedef CFX_RTemplate<int32_t> CFX_Rect;
+typedef CFX_RTemplate<FX_FLOAT> CFX_RectF;
+typedef CFX_ArrayTemplate<CFX_RectF> CFX_RectFArray;
+
+class CFX_FloatRect {
+ public:
+ CFX_FloatRect() : CFX_FloatRect(0.0f, 0.0f, 0.0f, 0.0f) {}
+ CFX_FloatRect(FX_FLOAT l, FX_FLOAT b, FX_FLOAT r, FX_FLOAT t)
+ : left(l), bottom(b), right(r), top(t) {}
+
+ explicit CFX_FloatRect(const FX_FLOAT* pArray)
+ : CFX_FloatRect(pArray[0], pArray[1], pArray[2], pArray[3]) {}
+
+ explicit CFX_FloatRect(const FX_RECT& rect);
+
+ void Normalize();
+
+ void Reset() {
+ left = 0.0f;
+ right = 0.0f;
+ bottom = 0.0f;
+ top = 0.0f;
+ }
+
+ bool IsEmpty() const { return left >= right || bottom >= top; }
+ bool Contains(const CFX_FloatRect& other_rect) const;
+ bool Contains(FX_FLOAT x, FX_FLOAT y) const;
+
+ void Transform(const CFX_Matrix* pMatrix);
+ void Intersect(const CFX_FloatRect& other_rect);
+ void Union(const CFX_FloatRect& other_rect);
+
+ FX_RECT GetInnerRect() const;
+ FX_RECT GetOuterRect() const;
+ FX_RECT GetClosestRect() const;
+
+ int Substract4(CFX_FloatRect& substract_rect, CFX_FloatRect* pRects);
+
+ void InitRect(FX_FLOAT x, FX_FLOAT y) {
+ left = x;
+ right = x;
+ bottom = y;
+ top = y;
+ }
+ void UpdateRect(FX_FLOAT x, FX_FLOAT y);
+
+ FX_FLOAT Width() const { return right - left; }
+ FX_FLOAT Height() const { return top - bottom; }
+
+ void Inflate(FX_FLOAT x, FX_FLOAT y) {
+ Normalize();
+ left -= x;
+ right += x;
+ bottom -= y;
+ top += y;
+ }
+
+ void Inflate(FX_FLOAT other_left,
+ FX_FLOAT other_bottom,
+ FX_FLOAT other_right,
+ FX_FLOAT other_top) {
+ Normalize();
+ left -= other_left;
+ bottom -= other_bottom;
+ right += other_right;
+ top += other_top;
+ }
+
+ void Inflate(const CFX_FloatRect& rt) {
+ Inflate(rt.left, rt.bottom, rt.right, rt.top);
+ }
+
+ void Deflate(FX_FLOAT x, FX_FLOAT y) {
+ Normalize();
+ left += x;
+ right -= x;
+ bottom += y;
+ top -= y;
+ }
+
+ void Deflate(FX_FLOAT other_left,
+ FX_FLOAT other_bottom,
+ FX_FLOAT other_right,
+ FX_FLOAT other_top) {
+ Normalize();
+ left += other_left;
+ bottom += other_bottom;
+ right -= other_right;
+ top -= other_top;
+ }
+
+ void Deflate(const CFX_FloatRect& rt) {
+ Deflate(rt.left, rt.bottom, rt.right, rt.top);
+ }
+
+ void Translate(FX_FLOAT e, FX_FLOAT f) {
+ left += e;
+ right += e;
+ top += f;
+ bottom += f;
+ }
+
+ static CFX_FloatRect GetBBox(const CFX_PointF* pPoints, int nPoints);
+
+ FX_RECT ToFxRect() const {
+ return FX_RECT(static_cast<int32_t>(left), static_cast<int32_t>(top),
+ static_cast<int32_t>(right), static_cast<int32_t>(bottom));
+ }
+
+ static CFX_FloatRect FromCFXRectF(const CFX_RectF& rect) {
+ return CFX_FloatRect(rect.left, rect.top, rect.right(), rect.bottom());
+ }
+
+ FX_FLOAT left;
+ FX_FLOAT bottom;
+ FX_FLOAT right;
+ FX_FLOAT top;
+};
+
+class CFX_Matrix {
+ public:
+ CFX_Matrix() { SetIdentity(); }
+
+ CFX_Matrix(FX_FLOAT a1,
+ FX_FLOAT b1,
+ FX_FLOAT c1,
+ FX_FLOAT d1,
+ FX_FLOAT e1,
+ FX_FLOAT f1) {
+ a = a1;
+ b = b1;
+ c = c1;
+ d = d1;
+ e = e1;
+ f = f1;
+ }
+
+ void Set(FX_FLOAT a,
+ FX_FLOAT b,
+ FX_FLOAT c,
+ FX_FLOAT d,
+ FX_FLOAT e,
+ FX_FLOAT f);
+ void Set(const FX_FLOAT n[6]);
+
+ void SetIdentity() {
+ a = d = 1;
+ b = c = e = f = 0;
+ }
+
+ void SetReverse(const CFX_Matrix& m);
+
+ void Concat(FX_FLOAT a,
+ FX_FLOAT b,
+ FX_FLOAT c,
+ FX_FLOAT d,
+ FX_FLOAT e,
+ FX_FLOAT f,
+ FX_BOOL bPrepended = FALSE);
+ void Concat(const CFX_Matrix& m, FX_BOOL bPrepended = FALSE);
+ void ConcatInverse(const CFX_Matrix& m, FX_BOOL bPrepended = FALSE);
+
+ FX_BOOL IsIdentity() const {
+ return a == 1 && b == 0 && c == 0 && d == 1 && e == 0 && f == 0;
+ }
+
+ FX_BOOL IsInvertible() const;
+ FX_BOOL Is90Rotated() const;
+ FX_BOOL IsScaled() const;
+
+ void Translate(FX_FLOAT x, FX_FLOAT y, FX_BOOL bPrepended = FALSE);
+ void TranslateI(int32_t x, int32_t y, FX_BOOL bPrepended = FALSE) {
+ Translate((FX_FLOAT)x, (FX_FLOAT)y, bPrepended);
+ }
+
+ void Scale(FX_FLOAT sx, FX_FLOAT sy, FX_BOOL bPrepended = FALSE);
+ void Rotate(FX_FLOAT fRadian, FX_BOOL bPrepended = FALSE);
+ void RotateAt(FX_FLOAT fRadian,
+ FX_FLOAT x,
+ FX_FLOAT y,
+ FX_BOOL bPrepended = FALSE);
+
+ void Shear(FX_FLOAT fAlphaRadian,
+ FX_FLOAT fBetaRadian,
+ FX_BOOL bPrepended = FALSE);
+
+ void MatchRect(const CFX_FloatRect& dest, const CFX_FloatRect& src);
+ FX_FLOAT GetXUnit() const;
+ FX_FLOAT GetYUnit() const;
+ void GetUnitRect(CFX_RectF& rect) const;
+ CFX_FloatRect GetUnitRect() const;
+
+ FX_FLOAT GetUnitArea() const;
+ FX_FLOAT TransformXDistance(FX_FLOAT dx) const;
+ int32_t TransformXDistance(int32_t dx) const;
+ FX_FLOAT TransformYDistance(FX_FLOAT dy) const;
+ int32_t TransformYDistance(int32_t dy) const;
+ FX_FLOAT TransformDistance(FX_FLOAT dx, FX_FLOAT dy) const;
+ int32_t TransformDistance(int32_t dx, int32_t dy) const;
+ FX_FLOAT TransformDistance(FX_FLOAT distance) const;
+
+ void TransformPoint(FX_FLOAT& x, FX_FLOAT& y) const;
+ void TransformPoint(int32_t& x, int32_t& y) const;
+
+ void Transform(FX_FLOAT& x, FX_FLOAT& y) const { TransformPoint(x, y); }
+ void Transform(FX_FLOAT x, FX_FLOAT y, FX_FLOAT& x1, FX_FLOAT& y1) const {
+ x1 = x, y1 = y;
+ TransformPoint(x1, y1);
+ }
+
+ void TransformVector(CFX_VectorF& v) const;
+ void TransformVector(CFX_Vector& v) const;
+ void TransformRect(CFX_RectF& rect) const;
+ void TransformRect(CFX_Rect& rect) const;
+ void TransformRect(FX_FLOAT& left,
+ FX_FLOAT& right,
+ FX_FLOAT& top,
+ FX_FLOAT& bottom) const;
+ void TransformRect(CFX_FloatRect& rect) const {
+ TransformRect(rect.left, rect.right, rect.top, rect.bottom);
+ }
+
+ FX_FLOAT GetA() const { return a; }
+ FX_FLOAT GetB() const { return b; }
+ FX_FLOAT GetC() const { return c; }
+ FX_FLOAT GetD() const { return d; }
+ FX_FLOAT GetE() const { return e; }
+ FX_FLOAT GetF() const { return f; }
+
+ public:
+ FX_FLOAT a;
+ FX_FLOAT b;
+ FX_FLOAT c;
+ FX_FLOAT d;
+ FX_FLOAT e;
+ FX_FLOAT f;
+};
+
+#endif // CORE_FXCRT_FX_COORDINATES_H_