diff options
Diffstat (limited to 'core/fxcrt/fx_coordinates.h')
-rw-r--r-- | core/fxcrt/fx_coordinates.h | 671 |
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_ |