summaryrefslogtreecommitdiffstats
path: root/ui/gfx
diff options
context:
space:
mode:
authordanakj@chromium.org <danakj@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-10-31 18:33:24 +0000
committerdanakj@chromium.org <danakj@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-10-31 18:33:24 +0000
commitceb36f7d5cec71407b265aba887cd64216d24731 (patch)
treeea977c72eb7882c1629a5c78f56b1a9e7e3e6b60 /ui/gfx
parent80211f670f34191d80b875086aaf7b5b06a743d4 (diff)
downloadchromium_src-ceb36f7d5cec71407b265aba887cd64216d24731.zip
chromium_src-ceb36f7d5cec71407b265aba887cd64216d24731.tar.gz
chromium_src-ceb36f7d5cec71407b265aba887cd64216d24731.tar.bz2
Add Vector2d classes that represent offsets, instead of using Point.
Previously Point served two purposes, to be a position in 2d space, and also an offset from the origin. This introduces a Vector2d class to represent an offset, allowing typesafety checks for geometric operations. The following are now the case: Point +/- Vector = Point - A point plus/minus an offset gives you a point at a position offset by the vector. Vector +/- Vector = Vector - Two offsets can be added together to make a new offset. Point - Point = Vector - Subtracting one point from another gives you the offset between the two points. We add some new methods to perform these operations: Rect::OffsetFromOrigin() gives the offset between the position of the rect and the origin. Point::OffsetFromOrigin() gives the offset between the point and the origin. PointAtOffsetFromOrigin(Vector2d) converts a Vector2d to a Point at the given offset away from the origin. Rect::Offset(), Point::Add(), and Point::Subtract() now receive a Vector2d instead of a point. BUG=147395 R=sky Review URL: https://codereview.chromium.org/11269022 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@165198 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui/gfx')
-rw-r--r--ui/gfx/blit.cc3
-rw-r--r--ui/gfx/blit.h3
-rw-r--r--ui/gfx/blit_unittest.cc12
-rw-r--r--ui/gfx/canvas.cc4
-rw-r--r--ui/gfx/canvas.h2
-rw-r--r--ui/gfx/point.cc14
-rw-r--r--ui/gfx/point.h17
-rw-r--r--ui/gfx/point_base.h26
-rw-r--r--ui/gfx/point_f.cc6
-rw-r--r--ui/gfx/point_f.h17
-rw-r--r--ui/gfx/point_unittest.cc33
-rw-r--r--ui/gfx/rect.cc4
-rw-r--r--ui/gfx/rect.h6
-rw-r--r--ui/gfx/rect_base.h9
-rw-r--r--ui/gfx/rect_base_impl.h97
-rw-r--r--ui/gfx/rect_f.cc5
-rw-r--r--ui/gfx/rect_f.h6
-rw-r--r--ui/gfx/render_text.cc58
-rw-r--r--ui/gfx/render_text.h12
-rw-r--r--ui/gfx/render_text_mac.cc11
-rw-r--r--ui/gfx/vector2d.cc45
-rw-r--r--ui/gfx/vector2d.h81
-rw-r--r--ui/gfx/vector2d_conversions.cc30
-rw-r--r--ui/gfx/vector2d_conversions.h24
-rw-r--r--ui/gfx/vector2d_f.cc54
-rw-r--r--ui/gfx/vector2d_f.h81
-rw-r--r--ui/gfx/vector2d_unittest.cc186
27 files changed, 725 insertions, 121 deletions
diff --git a/ui/gfx/blit.cc b/ui/gfx/blit.cc
index 41da3f5..c6c8d672 100644
--- a/ui/gfx/blit.cc
+++ b/ui/gfx/blit.cc
@@ -9,6 +9,7 @@
#include "skia/ext/platform_canvas.h"
#include "ui/gfx/point.h"
#include "ui/gfx/rect.h"
+#include "ui/gfx/vector2d.h"
#if defined(OS_OPENBSD)
#include <cairo.h>
@@ -128,7 +129,7 @@ void BlitCanvasToCanvas(SkCanvas *dst_canvas,
void ScrollCanvas(SkCanvas* canvas,
const gfx::Rect& in_clip,
- const gfx::Point& amount) {
+ const gfx::Vector2d& amount) {
DCHECK(!HasClipOrTransform(*canvas)); // Don't support special stuff.
#if defined(OS_WIN)
// If we have a PlatformCanvas, we should use ScrollDC. Otherwise, fall
diff --git a/ui/gfx/blit.h b/ui/gfx/blit.h
index d2ed2cf..01fa4f3 100644
--- a/ui/gfx/blit.h
+++ b/ui/gfx/blit.h
@@ -14,6 +14,7 @@ namespace gfx {
class Point;
class Rect;
+class Vector2d;
// Blits a rectangle from the source context into the destination context.
UI_EXPORT void BlitContextToContext(NativeDrawingContext dst_context,
@@ -44,7 +45,7 @@ UI_EXPORT void BlitCanvasToCanvas(SkCanvas *dst_canvas,
// may implement those operations differently.
UI_EXPORT void ScrollCanvas(SkCanvas* canvas,
const Rect& clip,
- const Point& amount);
+ const Vector2d& amount);
} // namespace gfx
diff --git a/ui/gfx/blit_unittest.cc b/ui/gfx/blit_unittest.cc
index 72e1c26..a0c4de9 100644
--- a/ui/gfx/blit_unittest.cc
+++ b/ui/gfx/blit_unittest.cc
@@ -76,12 +76,12 @@ TEST(Blit, ScrollCanvas) {
// Scroll none and make sure it's a NOP.
gfx::ScrollCanvas(&canvas,
gfx::Rect(0, 0, kCanvasWidth, kCanvasHeight),
- gfx::Point(0, 0));
+ gfx::Vector2d(0, 0));
VerifyCanvasValues<5, 5>(&canvas, initial_values);
// Scroll the center 3 pixels up one.
gfx::Rect center_three(1, 1, 3, 3);
- gfx::ScrollCanvas(&canvas, center_three, gfx::Point(0, -1));
+ gfx::ScrollCanvas(&canvas, center_three, gfx::Vector2d(0, -1));
uint8 scroll_up_expected[kCanvasHeight][kCanvasWidth] = {
{ 0x00, 0x01, 0x02, 0x03, 0x04 },
{ 0x10, 0x21, 0x22, 0x23, 0x14 },
@@ -92,7 +92,7 @@ TEST(Blit, ScrollCanvas) {
// Reset and scroll the center 3 pixels down one.
SetToCanvas<5, 5>(&canvas, initial_values);
- gfx::ScrollCanvas(&canvas, center_three, gfx::Point(0, 1));
+ gfx::ScrollCanvas(&canvas, center_three, gfx::Vector2d(0, 1));
uint8 scroll_down_expected[kCanvasHeight][kCanvasWidth] = {
{ 0x00, 0x01, 0x02, 0x03, 0x04 },
{ 0x10, 0x11, 0x12, 0x13, 0x14 },
@@ -103,7 +103,7 @@ TEST(Blit, ScrollCanvas) {
// Reset and scroll the center 3 pixels right one.
SetToCanvas<5, 5>(&canvas, initial_values);
- gfx::ScrollCanvas(&canvas, center_three, gfx::Point(1, 0));
+ gfx::ScrollCanvas(&canvas, center_three, gfx::Vector2d(1, 0));
uint8 scroll_right_expected[kCanvasHeight][kCanvasWidth] = {
{ 0x00, 0x01, 0x02, 0x03, 0x04 },
{ 0x10, 0x11, 0x11, 0x12, 0x14 },
@@ -114,7 +114,7 @@ TEST(Blit, ScrollCanvas) {
// Reset and scroll the center 3 pixels left one.
SetToCanvas<5, 5>(&canvas, initial_values);
- gfx::ScrollCanvas(&canvas, center_three, gfx::Point(-1, 0));
+ gfx::ScrollCanvas(&canvas, center_three, gfx::Vector2d(-1, 0));
uint8 scroll_left_expected[kCanvasHeight][kCanvasWidth] = {
{ 0x00, 0x01, 0x02, 0x03, 0x04 },
{ 0x10, 0x12, 0x13, 0x13, 0x14 },
@@ -125,7 +125,7 @@ TEST(Blit, ScrollCanvas) {
// Diagonal scroll.
SetToCanvas<5, 5>(&canvas, initial_values);
- gfx::ScrollCanvas(&canvas, center_three, gfx::Point(2, 2));
+ gfx::ScrollCanvas(&canvas, center_three, gfx::Vector2d(2, 2));
uint8 scroll_diagonal_expected[kCanvasHeight][kCanvasWidth] = {
{ 0x00, 0x01, 0x02, 0x03, 0x04 },
{ 0x10, 0x11, 0x12, 0x13, 0x14 },
diff --git a/ui/gfx/canvas.cc b/ui/gfx/canvas.cc
index 936af4b..bf41bc1 100644
--- a/ui/gfx/canvas.cc
+++ b/ui/gfx/canvas.cc
@@ -190,8 +190,8 @@ bool Canvas::GetClipBounds(gfx::Rect* bounds) {
return has_non_empty_clip;
}
-void Canvas::Translate(const gfx::Point& point) {
- canvas_->translate(SkIntToScalar(point.x()), SkIntToScalar(point.y()));
+void Canvas::Translate(const gfx::Vector2d& offset) {
+ canvas_->translate(SkIntToScalar(offset.x()), SkIntToScalar(offset.y()));
}
void Canvas::Scale(int x_scale, int y_scale) {
diff --git a/ui/gfx/canvas.h b/ui/gfx/canvas.h
index 4660407..0e080fa 100644
--- a/ui/gfx/canvas.h
+++ b/ui/gfx/canvas.h
@@ -196,7 +196,7 @@ class UI_EXPORT Canvas {
// |bounds| parameter, and returns true if it is non empty.
bool GetClipBounds(gfx::Rect* bounds);
- void Translate(const gfx::Point& point);
+ void Translate(const gfx::Vector2d& offset);
void Scale(int x_scale, int y_scale);
diff --git a/ui/gfx/point.cc b/ui/gfx/point.cc
index 322413e..e0b5595 100644
--- a/ui/gfx/point.cc
+++ b/ui/gfx/point.cc
@@ -12,22 +12,23 @@
namespace gfx {
-template class PointBase<Point, int>;
+template class PointBase<Point, int, Vector2d>;
-Point::Point() : PointBase<Point, int>(0, 0) {
+Point::Point() : PointBase<Point, int, Vector2d>(0, 0) {
}
-Point::Point(int x, int y) : PointBase<Point, int>(x, y) {
+Point::Point(int x, int y) : PointBase<Point, int, Vector2d>(x, y) {
}
#if defined(OS_WIN)
-Point::Point(DWORD point) : PointBase<Point, int>(0, 0){
+Point::Point(DWORD point) : PointBase<Point, int, Vector2d>(0, 0){
POINTS points = MAKEPOINTS(point);
set_x(points.x);
set_y(points.y);
}
-Point::Point(const POINT& point) : PointBase<Point, int>(point.x, point.y) {
+Point::Point(const POINT& point)
+ : PointBase<Point, int, Vector2d>(point.x, point.y) {
}
Point& Point::operator=(const POINT& point) {
@@ -43,7 +44,8 @@ POINT Point::ToPOINT() const {
return p;
}
#elif defined(OS_MACOSX)
-Point::Point(const CGPoint& point) : PointBase<Point, int>(point.x, point.y) {
+Point::Point(const CGPoint& point)
+ : PointBase<Point, int, Vector2d>(point.x, point.y) {
}
CGPoint Point::ToCGPoint() const {
diff --git a/ui/gfx/point.h b/ui/gfx/point.h
index 5984d74..2e476d0 100644
--- a/ui/gfx/point.h
+++ b/ui/gfx/point.h
@@ -8,6 +8,7 @@
#include "ui/base/ui_export.h"
#include "ui/gfx/point_base.h"
#include "ui/gfx/point_f.h"
+#include "ui/gfx/vector2d.h"
#if defined(OS_WIN)
typedef unsigned long DWORD;
@@ -21,7 +22,7 @@ typedef struct tagPOINT POINT;
namespace gfx {
// A point has an x and y coordinate.
-class UI_EXPORT Point : public PointBase<Point, int> {
+class UI_EXPORT Point : public PointBase<Point, int, Vector2d> {
public:
Point();
Point(int x, int y);
@@ -68,16 +69,24 @@ inline bool operator!=(const Point& lhs, const Point& rhs) {
return !(lhs == rhs);
}
-inline Point operator+(Point lhs, Point rhs) {
+inline Point operator+(const Point& lhs, const Vector2d& rhs) {
return lhs.Add(rhs);
}
-inline Point operator-(Point lhs, Point rhs) {
+inline Point operator-(const Point& lhs, const Vector2d& rhs) {
return lhs.Subtract(rhs);
}
+inline Vector2d operator-(const Point& lhs, const Point& rhs) {
+ return lhs.OffsetFrom(rhs);
+}
+
+inline Point PointAtOffsetFromOrigin(const Vector2d& offset_from_origin) {
+ return Point(offset_from_origin.x(), offset_from_origin.y());
+}
+
#if !defined(COMPILER_MSVC)
-extern template class PointBase<Point, int>;
+extern template class PointBase<Point, int, Vector2d>;
#endif
} // namespace gfx
diff --git a/ui/gfx/point_base.h b/ui/gfx/point_base.h
index 34e32f5..acaefe1 100644
--- a/ui/gfx/point_base.h
+++ b/ui/gfx/point_base.h
@@ -14,7 +14,7 @@
namespace gfx {
// A point has an x and y coordinate.
-template<typename Class, typename Type>
+template<typename Class, typename Type, typename VectorClass>
class UI_EXPORT PointBase {
public:
Type x() const { return x_; }
@@ -33,17 +33,25 @@ class UI_EXPORT PointBase {
y_ += delta_y;
}
- Class Add(const Class& other) const WARN_UNUSED_RESULT {
+ void operator+=(const VectorClass& other) {
+ Offset(other.x(), other.y());
+ }
+
+ void operator-=(const VectorClass& other) {
+ Offset(-other.x(), -other.y());
+ }
+
+ Class Add(const VectorClass& other) const WARN_UNUSED_RESULT {
const Class* orig = static_cast<const Class*>(this);
Class copy = *orig;
- copy.Offset(other.x_, other.y_);
+ copy.Offset(other.x(), other.y());
return copy;
}
- Class Subtract(const Class& other) const WARN_UNUSED_RESULT {
+ Class Subtract(const VectorClass& other) const WARN_UNUSED_RESULT {
const Class* orig = static_cast<const Class*>(this);
Class copy = *orig;
- copy.Offset(-other.x_, -other.y_);
+ copy.Offset(-other.x(), -other.y());
return copy;
}
@@ -55,6 +63,14 @@ class UI_EXPORT PointBase {
return x_ == 0 && y_ == 0;
}
+ VectorClass OffsetFromOrigin() const {
+ return VectorClass(x_, y_);
+ }
+
+ VectorClass OffsetFrom(const Class& other) const {
+ return VectorClass(x_ - other.x_, y_ - other.y_);
+ }
+
// A point is less than another point if its y-value is closer
// to the origin. If the y-values are the same, then point with
// the x-value closer to the origin is considered less than the
diff --git a/ui/gfx/point_f.cc b/ui/gfx/point_f.cc
index 3d814c5..d22693a0 100644
--- a/ui/gfx/point_f.cc
+++ b/ui/gfx/point_f.cc
@@ -8,12 +8,12 @@
namespace gfx {
-template class PointBase<PointF, float>;
+template class PointBase<PointF, float, Vector2dF>;
-PointF::PointF() : PointBase<PointF, float>(0, 0) {
+PointF::PointF() : PointBase<PointF, float, Vector2dF>(0, 0) {
}
-PointF::PointF(float x, float y) : PointBase<PointF, float>(x, y) {
+PointF::PointF(float x, float y) : PointBase<PointF, float, Vector2dF>(x, y) {
}
PointF::~PointF() {}
diff --git a/ui/gfx/point_f.h b/ui/gfx/point_f.h
index d6cded9..3e69bd7 100644
--- a/ui/gfx/point_f.h
+++ b/ui/gfx/point_f.h
@@ -9,11 +9,12 @@
#include "ui/base/ui_export.h"
#include "ui/gfx/point_base.h"
+#include "ui/gfx/vector2d_f.h"
namespace gfx {
// A floating version of gfx::Point.
-class UI_EXPORT PointF : public PointBase<PointF, float> {
+class UI_EXPORT PointF : public PointBase<PointF, float, Vector2dF> {
public:
PointF();
PointF(float x, float y);
@@ -39,16 +40,24 @@ inline bool operator!=(const PointF& lhs, const PointF& rhs) {
return !(lhs == rhs);
}
-inline PointF operator+(PointF lhs, PointF rhs) {
+inline PointF operator+(const PointF& lhs, const Vector2dF& rhs) {
return lhs.Add(rhs);
}
-inline PointF operator-(PointF lhs, PointF rhs) {
+inline PointF operator-(const PointF& lhs, const Vector2dF& rhs) {
return lhs.Subtract(rhs);
}
+inline Vector2dF operator-(const PointF& lhs, const PointF& rhs) {
+ return lhs.OffsetFrom(rhs);
+}
+
+inline PointF PointAtOffsetFromOrigin(const Vector2dF& offset_from_origin) {
+ return PointF(offset_from_origin.x(), offset_from_origin.y());
+}
+
#if !defined(COMPILER_MSVC)
-extern template class PointBase<PointF, float>;
+extern template class PointBase<PointF, float, Vector2dF>;
#endif
} // namespace gfx
diff --git a/ui/gfx/point_unittest.cc b/ui/gfx/point_unittest.cc
index cae2166..ea42b53 100644
--- a/ui/gfx/point_unittest.cc
+++ b/ui/gfx/point_unittest.cc
@@ -4,6 +4,7 @@
#include "ui/gfx/point_base.h"
+#include "base/basictypes.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/point.h"
#include "ui/gfx/point_f.h"
@@ -47,4 +48,36 @@ TEST(PointTest, IsOrigin) {
EXPECT_TRUE(gfx::PointF(0, 0).IsOrigin());
}
+TEST(PointTest, VectorArithmetic) {
+ gfx::Point a(1, 5);
+ gfx::Vector2d v1(3, -3);
+ gfx::Vector2d v2(-8, 1);
+
+ static const struct {
+ gfx::Point expected;
+ gfx::Point actual;
+ } tests[] = {
+ { gfx::Point(4, 2), a + v1 },
+ { gfx::Point(-2, 8), a - v1 },
+ { a, a - v1 + v1 },
+ { a, a + v1 - v1 },
+ { a, a + gfx::Vector2d() },
+ { gfx::Point(12, 1), a + v1 - v2 },
+ { gfx::Point(-10, 9), a - v1 + v2 }
+ };
+
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i)
+ EXPECT_EQ(tests[i].expected.ToString(),
+ tests[i].actual.ToString());
+}
+
+TEST(PointTest, OffsetFromPoint) {
+ gfx::Point a(1, 5);
+ gfx::Point b(-20, 8);
+ EXPECT_EQ(gfx::Vector2d(-20 - 1, 8 - 5).ToString(),
+ b.OffsetFrom(a).ToString());
+ EXPECT_EQ(gfx::Vector2d(-20 - 1, 8 - 5).ToString(),
+ (b - a).ToString());
+}
+
} // namespace ui
diff --git a/ui/gfx/rect.cc b/ui/gfx/rect.cc
index 551e6f6..b01d60c 100644
--- a/ui/gfx/rect.cc
+++ b/ui/gfx/rect.cc
@@ -17,9 +17,9 @@
namespace gfx {
-template class RectBase<Rect, Point, Size, Insets, int>;
+template class RectBase<Rect, Point, Size, Insets, Vector2d, int>;
-typedef class RectBase<Rect, Point, Size, Insets, int> RectBaseT;
+typedef class RectBase<Rect, Point, Size, Insets, Vector2d, int> RectBaseT;
Rect::Rect() : RectBaseT(gfx::Point()) {
}
diff --git a/ui/gfx/rect.h b/ui/gfx/rect.h
index bf56896..9138f46 100644
--- a/ui/gfx/rect.h
+++ b/ui/gfx/rect.h
@@ -18,6 +18,7 @@
#include "ui/gfx/rect_base.h"
#include "ui/gfx/rect_f.h"
#include "ui/gfx/size.h"
+#include "ui/gfx/vector2d.h"
#if defined(OS_WIN)
typedef struct tagRECT RECT;
@@ -33,7 +34,8 @@ namespace gfx {
class Insets;
-class UI_EXPORT Rect : public RectBase<Rect, Point, Size, Insets, int> {
+class UI_EXPORT Rect
+ : public RectBase<Rect, Point, Size, Insets, Vector2d, int> {
public:
Rect();
Rect(int width, int height);
@@ -80,7 +82,7 @@ UI_EXPORT Rect UnionRects(const Rect& a, const Rect& b);
UI_EXPORT Rect SubtractRects(const Rect& a, const Rect& b);
#if !defined(COMPILER_MSVC)
-extern template class RectBase<Rect, Point, Size, Insets, int>;
+extern template class RectBase<Rect, Point, Size, Insets, Vector2d, int>;
#endif
} // namespace gfx
diff --git a/ui/gfx/rect_base.h b/ui/gfx/rect_base.h
index a9ddda4..0a3298c 100644
--- a/ui/gfx/rect_base.h
+++ b/ui/gfx/rect_base.h
@@ -22,6 +22,7 @@ template<typename Class,
typename PointClass,
typename SizeClass,
typename InsetsClass,
+ typename VectorClass,
typename Type>
class UI_EXPORT RectBase {
public:
@@ -46,6 +47,10 @@ class UI_EXPORT RectBase {
Type right() const { return x() + width(); }
Type bottom() const { return y() + height(); }
+ VectorClass OffsetFromOrigin() const {
+ return VectorClass(x(), y());
+ }
+
void SetRect(Type x, Type y, Type width, Type height);
// Shrink the rectangle by a horizontal and vertical distance on all sides.
@@ -61,8 +66,8 @@ class UI_EXPORT RectBase {
// Move the rectangle by a horizontal and vertical distance.
void Offset(Type horizontal, Type vertical);
- void Offset(const PointClass& point) {
- Offset(point.x(), point.y());
+ void Offset(const VectorClass& distance) {
+ Offset(distance.x(), distance.y());
}
InsetsClass InsetsFrom(const Class& inner) const {
diff --git a/ui/gfx/rect_base_impl.h b/ui/gfx/rect_base_impl.h
index 291929d..5ca9afa 100644
--- a/ui/gfx/rect_base_impl.h
+++ b/ui/gfx/rect_base_impl.h
@@ -32,9 +32,10 @@ template<typename Class,
typename PointClass,
typename SizeClass,
typename InsetsClass,
+ typename VectorClass,
typename Type>
-RectBase<Class, PointClass, SizeClass, InsetsClass, Type>::RectBase(
- const PointClass& origin, const SizeClass& size)
+RectBase<Class, PointClass, SizeClass, InsetsClass, VectorClass, Type>::
+ RectBase(const PointClass& origin, const SizeClass& size)
: origin_(origin), size_(size) {
}
@@ -42,9 +43,10 @@ template<typename Class,
typename PointClass,
typename SizeClass,
typename InsetsClass,
+ typename VectorClass,
typename Type>
-RectBase<Class, PointClass, SizeClass, InsetsClass, Type>::RectBase(
- const SizeClass& size)
+RectBase<Class, PointClass, SizeClass, InsetsClass, VectorClass, Type>::
+ RectBase(const SizeClass& size)
: size_(size) {
}
@@ -52,9 +54,10 @@ template<typename Class,
typename PointClass,
typename SizeClass,
typename InsetsClass,
+ typename VectorClass,
typename Type>
-RectBase<Class, PointClass, SizeClass, InsetsClass, Type>::RectBase(
- const PointClass& origin)
+RectBase<Class, PointClass, SizeClass, InsetsClass, VectorClass, Type>::
+ RectBase(const PointClass& origin)
: origin_(origin) {
}
@@ -62,16 +65,19 @@ template<typename Class,
typename PointClass,
typename SizeClass,
typename InsetsClass,
+ typename VectorClass,
typename Type>
-RectBase<Class, PointClass, SizeClass, InsetsClass, Type>::~RectBase() {}
+RectBase<Class, PointClass, SizeClass, InsetsClass, VectorClass, Type>::
+ ~RectBase() {}
template<typename Class,
typename PointClass,
typename SizeClass,
typename InsetsClass,
+ typename VectorClass,
typename Type>
-void RectBase<Class, PointClass, SizeClass, InsetsClass, Type>::SetRect(
- Type x, Type y, Type width, Type height) {
+void RectBase<Class, PointClass, SizeClass, InsetsClass, VectorClass, Type>::
+ SetRect(Type x, Type y, Type width, Type height) {
origin_.SetPoint(x, y);
set_width(width);
set_height(height);
@@ -81,9 +87,10 @@ template<typename Class,
typename PointClass,
typename SizeClass,
typename InsetsClass,
+ typename VectorClass,
typename Type>
-void RectBase<Class, PointClass, SizeClass, InsetsClass, Type>::Inset(
- const InsetsClass& insets) {
+void RectBase<Class, PointClass, SizeClass, InsetsClass, VectorClass, Type>::
+ Inset(const InsetsClass& insets) {
Inset(insets.left(), insets.top(), insets.right(), insets.bottom());
}
@@ -91,9 +98,10 @@ template<typename Class,
typename PointClass,
typename SizeClass,
typename InsetsClass,
+ typename VectorClass,
typename Type>
-void RectBase<Class, PointClass, SizeClass, InsetsClass, Type>::Inset(
- Type left, Type top, Type right, Type bottom) {
+void RectBase<Class, PointClass, SizeClass, InsetsClass, VectorClass, Type>::
+ Inset(Type left, Type top, Type right, Type bottom) {
Offset(left, top);
set_width(std::max(width() - left - right, static_cast<Type>(0)));
set_height(std::max(height() - top - bottom, static_cast<Type>(0)));
@@ -103,9 +111,10 @@ template<typename Class,
typename PointClass,
typename SizeClass,
typename InsetsClass,
+ typename VectorClass,
typename Type>
-void RectBase<Class, PointClass, SizeClass, InsetsClass, Type>::Offset(
- Type horizontal, Type vertical) {
+void RectBase<Class, PointClass, SizeClass, InsetsClass, VectorClass, Type>::
+ Offset(Type horizontal, Type vertical) {
origin_.Offset(horizontal, vertical);
}
@@ -113,9 +122,10 @@ template<typename Class,
typename PointClass,
typename SizeClass,
typename InsetsClass,
+ typename VectorClass,
typename Type>
-bool RectBase<Class, PointClass, SizeClass, InsetsClass, Type>::operator<(
- const Class& other) const {
+bool RectBase<Class, PointClass, SizeClass, InsetsClass, VectorClass, Type>::
+ operator<(const Class& other) const {
if (origin_ == other.origin_) {
if (width() == other.width()) {
return height() < other.height();
@@ -131,9 +141,10 @@ template<typename Class,
typename PointClass,
typename SizeClass,
typename InsetsClass,
+ typename VectorClass,
typename Type>
-bool RectBase<Class, PointClass, SizeClass, InsetsClass, Type>::Contains(
- Type point_x, Type point_y) const {
+bool RectBase<Class, PointClass, SizeClass, InsetsClass, VectorClass, Type>::
+ Contains(Type point_x, Type point_y) const {
return (point_x >= x()) && (point_x < right()) &&
(point_y >= y()) && (point_y < bottom());
}
@@ -142,9 +153,10 @@ template<typename Class,
typename PointClass,
typename SizeClass,
typename InsetsClass,
+ typename VectorClass,
typename Type>
-bool RectBase<Class, PointClass, SizeClass, InsetsClass, Type>::Contains(
- const Class& rect) const {
+bool RectBase<Class, PointClass, SizeClass, InsetsClass, VectorClass, Type>::
+ Contains(const Class& rect) const {
return (rect.x() >= x() && rect.right() <= right() &&
rect.y() >= y() && rect.bottom() <= bottom());
}
@@ -153,9 +165,10 @@ template<typename Class,
typename PointClass,
typename SizeClass,
typename InsetsClass,
+ typename VectorClass,
typename Type>
-bool RectBase<Class, PointClass, SizeClass, InsetsClass, Type>::Intersects(
- const Class& rect) const {
+bool RectBase<Class, PointClass, SizeClass, InsetsClass, VectorClass, Type>::
+ Intersects(const Class& rect) const {
return !(rect.x() >= right() || rect.right() <= x() ||
rect.y() >= bottom() || rect.bottom() <= y());
}
@@ -164,9 +177,10 @@ template<typename Class,
typename PointClass,
typename SizeClass,
typename InsetsClass,
+ typename VectorClass,
typename Type>
-void RectBase<Class, PointClass, SizeClass, InsetsClass, Type>::Intersect(
- const Class& rect) {
+void RectBase<Class, PointClass, SizeClass, InsetsClass, VectorClass, Type>::
+ Intersect(const Class& rect) {
if (IsEmpty() || rect.IsEmpty()) {
SetRect(0, 0, 0, 0);
return;
@@ -187,9 +201,10 @@ template<typename Class,
typename PointClass,
typename SizeClass,
typename InsetsClass,
+ typename VectorClass,
typename Type>
-void RectBase<Class, PointClass, SizeClass, InsetsClass, Type>::Union(
- const Class& rect) {
+void RectBase<Class, PointClass, SizeClass, InsetsClass, VectorClass, Type>::
+ Union(const Class& rect) {
if (IsEmpty()) {
*this = rect;
return;
@@ -209,9 +224,10 @@ template<typename Class,
typename PointClass,
typename SizeClass,
typename InsetsClass,
+ typename VectorClass,
typename Type>
-void RectBase<Class, PointClass, SizeClass, InsetsClass, Type>::Subtract(
- const Class& rect) {
+void RectBase<Class, PointClass, SizeClass, InsetsClass, VectorClass, Type>::
+ Subtract(const Class& rect) {
if (!Intersects(rect))
return;
if (rect.Contains(*static_cast<const Class*>(this))) {
@@ -246,9 +262,10 @@ template<typename Class,
typename PointClass,
typename SizeClass,
typename InsetsClass,
+ typename VectorClass,
typename Type>
-void RectBase<Class, PointClass, SizeClass, InsetsClass, Type>::AdjustToFit(
- const Class& rect) {
+void RectBase<Class, PointClass, SizeClass, InsetsClass, VectorClass, Type>::
+ AdjustToFit(const Class& rect) {
Type new_x = x();
Type new_y = y();
Type new_width = width();
@@ -262,9 +279,10 @@ template<typename Class,
typename PointClass,
typename SizeClass,
typename InsetsClass,
+ typename VectorClass,
typename Type>
-PointClass RectBase<Class, PointClass, SizeClass, InsetsClass, Type>::
- CenterPoint() const {
+PointClass RectBase<Class, PointClass, SizeClass, InsetsClass, VectorClass,
+ Type>::CenterPoint() const {
return PointClass(x() + width() / 2, y() + height() / 2);
}
@@ -272,8 +290,9 @@ template<typename Class,
typename PointClass,
typename SizeClass,
typename InsetsClass,
+ typename VectorClass,
typename Type>
-void RectBase<Class, PointClass, SizeClass, InsetsClass, Type>::
+void RectBase<Class, PointClass, SizeClass, InsetsClass, VectorClass, Type>::
ClampToCenteredSize(const SizeClass& size) {
Type new_width = std::min(width(), size.width());
Type new_height = std::min(height(), size.height());
@@ -286,9 +305,10 @@ template<typename Class,
typename PointClass,
typename SizeClass,
typename InsetsClass,
+ typename VectorClass,
typename Type>
-void RectBase<Class, PointClass, SizeClass, InsetsClass, Type>::SplitVertically(
- Class* left_half, Class* right_half) const {
+void RectBase<Class, PointClass, SizeClass, InsetsClass, VectorClass, Type>::
+ SplitVertically(Class* left_half, Class* right_half) const {
DCHECK(left_half);
DCHECK(right_half);
@@ -303,9 +323,10 @@ template<typename Class,
typename PointClass,
typename SizeClass,
typename InsetsClass,
+ typename VectorClass,
typename Type>
-bool RectBase<Class, PointClass, SizeClass, InsetsClass, Type>::SharesEdgeWith(
- const Class& rect) const {
+bool RectBase<Class, PointClass, SizeClass, InsetsClass, VectorClass, Type>::
+ SharesEdgeWith(const Class& rect) const {
return (y() == rect.y() && height() == rect.height() &&
(x() == rect.right() || right() == rect.x())) ||
(x() == rect.x() && width() == rect.width() &&
diff --git a/ui/gfx/rect_f.cc b/ui/gfx/rect_f.cc
index 6035391..f011d71 100644
--- a/ui/gfx/rect_f.cc
+++ b/ui/gfx/rect_f.cc
@@ -11,9 +11,10 @@
namespace gfx {
-template class RectBase<RectF, PointF, SizeF, InsetsF, float>;
+template class RectBase<RectF, PointF, SizeF, InsetsF, Vector2dF, float>;
-typedef class RectBase<RectF, PointF, SizeF, InsetsF, float> RectBaseT;
+typedef class RectBase<RectF, PointF, SizeF, InsetsF, Vector2dF,
+ float> RectBaseT;
RectF::RectF() : RectBaseT(gfx::SizeF()) {
}
diff --git a/ui/gfx/rect_f.h b/ui/gfx/rect_f.h
index 8439eb1..db00324 100644
--- a/ui/gfx/rect_f.h
+++ b/ui/gfx/rect_f.h
@@ -10,13 +10,15 @@
#include "ui/gfx/point_f.h"
#include "ui/gfx/rect_base.h"
#include "ui/gfx/size_f.h"
+#include "ui/gfx/vector2d_f.h"
namespace gfx {
class InsetsF;
// A floating version of gfx::Rect.
-class UI_EXPORT RectF : public RectBase<RectF, PointF, SizeF, InsetsF, float> {
+class UI_EXPORT RectF
+ : public RectBase<RectF, PointF, SizeF, InsetsF, Vector2dF, float> {
public:
RectF();
RectF(float width, float height);
@@ -59,7 +61,7 @@ inline RectF ScaleRect(const RectF& r, float scale) {
}
#if !defined(COMPILER_MSVC)
-extern template class RectBase<RectF, PointF, SizeF, InsetsF, float>;
+extern template class RectBase<RectF, PointF, SizeF, InsetsF, Vector2dF, float>;
#endif
} // namespace gfx
diff --git a/ui/gfx/render_text.cc b/ui/gfx/render_text.cc
index a8246c2..dfbc3a4 100644
--- a/ui/gfx/render_text.cc
+++ b/ui/gfx/render_text.cc
@@ -406,7 +406,7 @@ void RenderText::SetText(const string16& text) {
void RenderText::SetHorizontalAlignment(HorizontalAlignment alignment) {
if (horizontal_alignment_ != alignment) {
horizontal_alignment_ = alignment;
- display_offset_ = Point();
+ display_offset_ = Vector2d();
cached_bounds_and_offset_valid_ = false;
}
}
@@ -765,7 +765,7 @@ RenderText::RenderText()
cached_bounds_and_offset_valid_(false) {
}
-const Point& RenderText::GetUpdatedDisplayOffset() {
+const Vector2d& RenderText::GetUpdatedDisplayOffset() {
UpdateCachedBoundsAndOffset();
return display_offset_;
}
@@ -839,41 +839,39 @@ void RenderText::ApplyCompositionAndSelectionStyles(
}
}
-Point RenderText::GetTextOrigin() {
- Point origin = display_rect().origin();
- origin = origin.Add(GetUpdatedDisplayOffset());
- origin = origin.Add(GetAlignmentOffset());
- return origin;
+Vector2d RenderText::GetTextOffset() {
+ Vector2d offset = display_rect().OffsetFromOrigin();
+ offset.Add(GetUpdatedDisplayOffset());
+ offset.Add(GetAlignmentOffset());
+ return offset;
}
Point RenderText::ToTextPoint(const Point& point) {
- return point.Subtract(GetTextOrigin());
+ return point.Subtract(GetTextOffset());
}
Point RenderText::ToViewPoint(const Point& point) {
- return point.Add(GetTextOrigin());
+ return point.Add(GetTextOffset());
}
int RenderText::GetContentWidth() {
return GetStringSize().width() + (cursor_enabled_ ? 1 : 0);
}
-Point RenderText::GetAlignmentOffset() {
- if (horizontal_alignment() != ALIGN_LEFT) {
- int x_offset = display_rect().width() - GetContentWidth();
- if (horizontal_alignment() == ALIGN_CENTER)
- x_offset /= 2;
- return Point(x_offset, 0);
- }
- return Point();
+Vector2d RenderText::GetAlignmentOffset() {
+ if (horizontal_alignment() == ALIGN_LEFT)
+ return Vector2d();
+
+ int x_offset = display_rect().width() - GetContentWidth();
+ if (horizontal_alignment() == ALIGN_CENTER)
+ x_offset /= 2;
+ return Vector2d(x_offset, 0);
}
Point RenderText::GetOriginForDrawing() {
- Point origin(GetTextOrigin());
- const int height = GetStringSize().height();
// Center the text vertically in the display area.
- origin.Offset(0, (display_rect().height() - height) / 2);
- return origin;
+ return gfx::PointAtOffsetFromOrigin(GetTextOffset()) +
+ Vector2d(0, (display_rect().height() - GetStringSize().height()) / 2);
}
void RenderText::ApplyFadeEffects(internal::SkiaTextRenderer* renderer) {
@@ -974,35 +972,37 @@ void RenderText::UpdateCachedBoundsAndOffset() {
const int display_width = display_rect_.width();
const int content_width = GetContentWidth();
- int delta_offset = 0;
+ int delta_x = 0;
if (content_width <= display_width || !cursor_enabled()) {
// Don't pan if the text fits in the display width or when the cursor is
// disabled.
- delta_offset = -display_offset_.x();
+ delta_x = -display_offset_.x();
} else if (cursor_bounds_.right() >= display_rect_.right()) {
// TODO(xji): when the character overflow is a RTL character, currently, if
// we pan cursor at the rightmost position, the entered RTL character is not
// displayed. Should pan cursor to show the last logical characters.
//
// Pan to show the cursor when it overflows to the right,
- delta_offset = display_rect_.right() - cursor_bounds_.right() - 1;
+ delta_x = display_rect_.right() - cursor_bounds_.right() - 1;
} else if (cursor_bounds_.x() < display_rect_.x()) {
// TODO(xji): have similar problem as above when overflow character is a
// LTR character.
//
// Pan to show the cursor when it overflows to the left.
- delta_offset = display_rect_.x() - cursor_bounds_.x();
+ delta_x = display_rect_.x() - cursor_bounds_.x();
} else if (display_offset_.x() != 0) {
// Reduce the pan offset to show additional overflow text when the display
// width increases.
const int negate_rtl = horizontal_alignment_ == ALIGN_RIGHT ? -1 : 1;
const int offset = negate_rtl * display_offset_.x();
- if (display_width > (content_width + offset))
- delta_offset = negate_rtl * (display_width - (content_width + offset));
+ if (display_width > (content_width + offset)) {
+ delta_x = negate_rtl * (display_width - (content_width + offset));
+ }
}
- display_offset_.Offset(delta_offset, 0);
- cursor_bounds_.Offset(delta_offset, 0);
+ gfx::Vector2d delta_offset(delta_x, 0);
+ display_offset_ += delta_offset;
+ cursor_bounds_.Offset(delta_offset);
}
void RenderText::DrawSelection(Canvas* canvas) {
diff --git a/ui/gfx/render_text.h b/ui/gfx/render_text.h
index 3ba9f87..13215d8 100644
--- a/ui/gfx/render_text.h
+++ b/ui/gfx/render_text.h
@@ -24,6 +24,7 @@
#include "ui/gfx/selection_model.h"
#include "ui/gfx/shadow_value.h"
#include "ui/gfx/text_constants.h"
+#include "ui/gfx/vector2d.h"
class SkCanvas;
class SkDrawLooper;
@@ -294,7 +295,7 @@ class UI_EXPORT RenderText {
protected:
RenderText();
- const Point& GetUpdatedDisplayOffset();
+ const Vector2d& GetUpdatedDisplayOffset();
void set_cached_bounds_and_offset_valid(bool valid) {
cached_bounds_and_offset_valid_ = valid;
@@ -367,8 +368,9 @@ class UI_EXPORT RenderText {
// style (foreground) to selection range.
void ApplyCompositionAndSelectionStyles(StyleRanges* style_ranges);
- // Returns the text origin after applying text alignment and display offset.
- Point GetTextOrigin();
+ // Returns the text offset from the origin after applying text alignment and
+ // display offset.
+ Vector2d GetTextOffset();
// Convert points from the text space to the view space and back.
// Handles the display area, display offset, and the application LTR/RTL mode.
@@ -380,7 +382,7 @@ class UI_EXPORT RenderText {
int GetContentWidth();
// Returns display offset based on current text alignment.
- Point GetAlignmentOffset();
+ Vector2d GetAlignmentOffset();
// Returns the origin point for drawing text. Does not account for font
// baseline, as needed by Skia.
@@ -504,7 +506,7 @@ class UI_EXPORT RenderText {
// The offset for the text to be drawn, relative to the display area.
// Get this point with GetUpdatedDisplayOffset (or risk using a stale value).
- Point display_offset_;
+ Vector2d display_offset_;
// The cached bounds and offset are invalidated by changes to the cursor,
// selection, font, and other operations that adjust the visible text bounds.
diff --git a/ui/gfx/render_text_mac.cc b/ui/gfx/render_text_mac.cc
index 9ee069f..75d7f42 100644
--- a/ui/gfx/render_text_mac.cc
+++ b/ui/gfx/render_text_mac.cc
@@ -232,13 +232,12 @@ void RenderTextMac::ComputeRuns() {
CFArrayRef ct_runs = CTLineGetGlyphRuns(line_);
const CFIndex ct_runs_count = CFArrayGetCount(ct_runs);
- Point offset(GetTextOrigin());
- // Skia will draw glyphs with respect to the baseline.
- offset.Offset(0, common_baseline_);
+ gfx::Vector2d text_offset = GetTextOffset();
- const SkScalar x = SkIntToScalar(offset.x());
- const SkScalar y = SkIntToScalar(offset.y());
- SkPoint run_origin = SkPoint::Make(offset.x(), offset.y());
+ // Skia will draw glyphs with respect to the baseline.
+ const SkScalar x = SkIntToScalar(text_offset.x());
+ const SkScalar y = SkIntToScalar(text_offset.y() + common_baseline_);
+ SkPoint run_origin = SkPoint::Make(x, y);
const CFRange empty_cf_range = CFRangeMake(0, 0);
for (CFIndex i = 0; i < ct_runs_count; ++i) {
diff --git a/ui/gfx/vector2d.cc b/ui/gfx/vector2d.cc
new file mode 100644
index 0000000..a1492cb
--- /dev/null
+++ b/ui/gfx/vector2d.cc
@@ -0,0 +1,45 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/gfx/vector2d.h"
+
+#include <cmath>
+
+#include "base/stringprintf.h"
+
+namespace gfx {
+
+Vector2d::Vector2d() : x_(0), y_(0) {
+}
+
+Vector2d::Vector2d(int x, int y) : x_(x), y_(y) {
+}
+
+bool Vector2d::IsZero() const {
+ return x_ == 0 && y_ == 0;
+}
+
+void Vector2d::Add(const Vector2d& other) {
+ x_ += other.x_;
+ y_ += other.y_;
+}
+
+void Vector2d::Subtract(const Vector2d& other) {
+ x_ -= other.x_;
+ y_ -= other.y_;
+}
+
+int64 Vector2d::LengthSquared() const {
+ return static_cast<int64>(x_) * x_ + static_cast<int64>(y_) * y_;
+}
+
+float Vector2d::Length() const {
+ return static_cast<float>(std::sqrt(static_cast<double>(LengthSquared())));
+}
+
+std::string Vector2d::ToString() const {
+ return base::StringPrintf("[%d %d]", x_, y_);
+}
+
+} // namespace gfx
diff --git a/ui/gfx/vector2d.h b/ui/gfx/vector2d.h
new file mode 100644
index 0000000..6ec3708
--- /dev/null
+++ b/ui/gfx/vector2d.h
@@ -0,0 +1,81 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Defines a simple integer vector class. This class is used to indicate a
+// distance in two dimensions between two points. Subtracting two points should
+// produce a vector, and adding a vector to a point produces the point at the
+// vector's distance from the original point.
+
+#ifndef UI_GFX_VECTOR2D_H_
+#define UI_GFX_VECTOR2D_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "ui/base/ui_export.h"
+#include "ui/gfx/vector2d_f.h"
+
+namespace gfx {
+
+class UI_EXPORT Vector2d {
+ public:
+ Vector2d();
+ Vector2d(int x, int y);
+
+ int x() const { return x_; }
+ void set_x(int x) { x_ = x; }
+
+ int y() const { return y_; }
+ void set_y(int y) { y_ = y; }
+
+ // True if both components of the vector are 0.
+ bool IsZero() const;
+
+ // Add the components of the |other| vector to the current vector.
+ void Add(const Vector2d& other);
+ // Subtract the components of the |other| vector from the current vector.
+ void Subtract(const Vector2d& other);
+
+ void operator+=(const Vector2d& other) { Add(other); }
+ void operator-=(const Vector2d& other) { Subtract(other); }
+
+ // Gives the square of the diagonal length of the vector. Since this is
+ // cheaper to compute than Length(), it is useful when you want to compare
+ // relative lengths of different vectors without needing the actual lengths.
+ int64 LengthSquared() const;
+ // Gives the diagonal length of the vector.
+ float Length() const;
+
+ std::string ToString() const;
+
+ operator Vector2dF() const { return Vector2dF(x_, y_); }
+
+ private:
+ int x_;
+ int y_;
+};
+
+inline bool operator==(const Vector2d& lhs, const Vector2d& rhs) {
+ return lhs.x() == rhs.x() && lhs.y() == rhs.y();
+}
+
+inline Vector2d operator-(const Vector2d& v) {
+ return Vector2d(-v.x(), -v.y());
+}
+
+inline Vector2d operator+(const Vector2d& lhs, const Vector2d& rhs) {
+ Vector2d result = lhs;
+ result.Add(rhs);
+ return result;
+}
+
+inline Vector2d operator-(const Vector2d& lhs, const Vector2d& rhs) {
+ Vector2d result = lhs;
+ result.Add(-rhs);
+ return result;
+}
+
+} // namespace gfx
+
+#endif // UI_GFX_VECTOR2D_H_
diff --git a/ui/gfx/vector2d_conversions.cc b/ui/gfx/vector2d_conversions.cc
new file mode 100644
index 0000000..457e9f7
--- /dev/null
+++ b/ui/gfx/vector2d_conversions.cc
@@ -0,0 +1,30 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/gfx/vector2d_conversions.h"
+
+#include "ui/gfx/safe_integer_conversions.h"
+
+namespace gfx {
+
+Vector2d ToFlooredVector2d(const Vector2dF& vector2d) {
+ int x = ToFlooredInt(vector2d.x());
+ int y = ToFlooredInt(vector2d.y());
+ return Vector2d(x, y);
+}
+
+Vector2d ToCeiledVector2d(const Vector2dF& vector2d) {
+ int x = ToCeiledInt(vector2d.x());
+ int y = ToCeiledInt(vector2d.y());
+ return Vector2d(x, y);
+}
+
+Vector2d ToRoundedVector2d(const Vector2dF& vector2d) {
+ int x = ToRoundedInt(vector2d.x());
+ int y = ToRoundedInt(vector2d.y());
+ return Vector2d(x, y);
+}
+
+} // namespace gfx
+
diff --git a/ui/gfx/vector2d_conversions.h b/ui/gfx/vector2d_conversions.h
new file mode 100644
index 0000000..051092e
--- /dev/null
+++ b/ui/gfx/vector2d_conversions.h
@@ -0,0 +1,24 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_GFX_VECTOR2D_CONVERSIONS_H_
+#define UI_GFX_VECTOR2D_CONVERSIONS_H_
+
+#include "ui/gfx/vector2d.h"
+#include "ui/gfx/vector2d_f.h"
+
+namespace gfx {
+
+// Returns a Vector2d with each component from the input Vector2dF floored.
+UI_EXPORT Vector2d ToFlooredVector2d(const Vector2dF& vector2d);
+
+// Returns a Vector2d with each component from the input Vector2dF ceiled.
+UI_EXPORT Vector2d ToCeiledVector2d(const Vector2dF& vector2d);
+
+// Returns a Vector2d with each component from the input Vector2dF rounded.
+UI_EXPORT Vector2d ToRoundedVector2d(const Vector2dF& vector2d);
+
+} // namespace gfx
+
+#endif // UI_GFX_VECTOR2D_CONVERSIONS_H_
diff --git a/ui/gfx/vector2d_f.cc b/ui/gfx/vector2d_f.cc
new file mode 100644
index 0000000..f628421
--- /dev/null
+++ b/ui/gfx/vector2d_f.cc
@@ -0,0 +1,54 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/gfx/vector2d_f.h"
+
+#include <cmath>
+
+#include "base/stringprintf.h"
+
+namespace gfx {
+
+Vector2dF::Vector2dF()
+ : x_(0),
+ y_(0) {
+}
+
+Vector2dF::Vector2dF(float x, float y)
+ : x_(x),
+ y_(y) {
+}
+
+std::string Vector2dF::ToString() const {
+ return base::StringPrintf("[%f %f]", x_, y_);
+}
+
+bool Vector2dF::IsZero() const {
+ return x_ == 0 && y_ == 0;
+}
+
+void Vector2dF::Add(const Vector2dF& other) {
+ x_ += other.x_;
+ y_ += other.y_;
+}
+
+void Vector2dF::Subtract(const Vector2dF& other) {
+ x_ -= other.x_;
+ y_ -= other.y_;
+}
+
+double Vector2dF::LengthSquared() const {
+ return static_cast<double>(x_) * x_ + static_cast<double>(y_) * y_;
+}
+
+float Vector2dF::Length() const {
+ return static_cast<float>(std::sqrt(LengthSquared()));
+}
+
+void Vector2dF::Scale(float x_scale, float y_scale) {
+ x_ *= x_scale;
+ y_ *= y_scale;
+}
+
+} // namespace gfx
diff --git a/ui/gfx/vector2d_f.h b/ui/gfx/vector2d_f.h
new file mode 100644
index 0000000..e2baa0c
--- /dev/null
+++ b/ui/gfx/vector2d_f.h
@@ -0,0 +1,81 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Defines a simple float vector class. This class is used to indicate a
+// distance in two dimensions between two points. Subtracting two points should
+// produce a vector, and adding a vector to a point produces the point at the
+// vector's distance from the original point.
+
+#ifndef UI_GFX_VECTOR2D_F_H_
+#define UI_GFX_VECTOR2D_F_H_
+
+#include <string>
+
+#include "ui/base/ui_export.h"
+
+namespace gfx {
+
+class UI_EXPORT Vector2dF {
+ public:
+ Vector2dF();
+ Vector2dF(float x, float y);
+
+ float x() const { return x_; }
+ void set_x(float x) { x_ = x; }
+
+ float y() const { return y_; }
+ void set_y(float y) { y_ = y; }
+
+ // True if both components of the vector are 0.
+ bool IsZero() const;
+
+ // Add the components of the |other| vector to the current vector.
+ void Add(const Vector2dF& other);
+ // Subtract the components of the |other| vector from the current vector.
+ void Subtract(const Vector2dF& other);
+
+ void operator+=(const Vector2dF& other) { Add(other); }
+ void operator-=(const Vector2dF& other) { Subtract(other); }
+
+ // Gives the square of the diagonal length of the vector.
+ double LengthSquared() const;
+ // Gives the diagonal length of the vector.
+ float Length() const;
+
+ // Scale the x and y components of the vector by |scale|.
+ void Scale(float scale) { Scale(scale, scale); }
+ // Scale the x and y components of the vector by |x_scale| and |y_scale|
+ // respectively.
+ void Scale(float x_scale, float y_scale);
+
+ std::string ToString() const;
+
+ private:
+ float x_;
+ float y_;
+};
+
+inline bool operator==(const Vector2dF& lhs, const Vector2dF& rhs) {
+ return lhs.x() == rhs.x() && lhs.y() == rhs.y();
+}
+
+inline Vector2dF operator-(const Vector2dF& v) {
+ return Vector2dF(-v.x(), -v.y());
+}
+
+inline Vector2dF operator+(const Vector2dF& lhs, const Vector2dF& rhs) {
+ Vector2dF result = lhs;
+ result.Add(rhs);
+ return result;
+}
+
+inline Vector2dF operator-(const Vector2dF& lhs, const Vector2dF& rhs) {
+ Vector2dF result = lhs;
+ result.Add(-rhs);
+ return result;
+}
+
+} // namespace gfx
+
+#endif // UI_GFX_VECTOR2D_F_H_
diff --git a/ui/gfx/vector2d_unittest.cc b/ui/gfx/vector2d_unittest.cc
new file mode 100644
index 0000000..3dfbdf9
--- /dev/null
+++ b/ui/gfx/vector2d_unittest.cc
@@ -0,0 +1,186 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/basictypes.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/vector2d.h"
+#include "ui/gfx/vector2d_f.h"
+
+#include <cmath>
+#include <limits>
+
+namespace gfx {
+
+TEST(Vector2dTest, ConversionToFloat) {
+ gfx::Vector2d i(3, 4);
+ gfx::Vector2dF f = i;
+ EXPECT_EQ(i, f);
+}
+
+TEST(Vector2dTest, IsZero) {
+ gfx::Vector2d int_zero(0, 0);
+ gfx::Vector2d int_nonzero(2, -2);
+ gfx::Vector2dF float_zero(0, 0);
+ gfx::Vector2dF float_nonzero(0.1f, -0.1f);
+
+ EXPECT_TRUE(int_zero.IsZero());
+ EXPECT_FALSE(int_nonzero.IsZero());
+ EXPECT_TRUE(float_zero.IsZero());
+ EXPECT_FALSE(float_nonzero.IsZero());
+}
+
+TEST(Vector2dTest, Add) {
+ gfx::Vector2d i1(3, 5);
+ gfx::Vector2d i2(4, -1);
+
+ const struct {
+ gfx::Vector2d expected;
+ gfx::Vector2d actual;
+ } int_tests[] = {
+ { gfx::Vector2d(3, 5), i1 + gfx::Vector2d() },
+ { gfx::Vector2d(3 + 4, 5 - 1), i1 + i2 },
+ { gfx::Vector2d(3 - 4, 5 + 1), i1 - i2 }
+ };
+
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(int_tests); ++i)
+ EXPECT_EQ(int_tests[i].expected.ToString(),
+ int_tests[i].actual.ToString());
+
+ gfx::Vector2dF f1(3.1f, 5.1f);
+ gfx::Vector2dF f2(4.3f, -1.3f);
+
+ const struct {
+ gfx::Vector2dF expected;
+ gfx::Vector2dF actual;
+ } float_tests[] = {
+ { gfx::Vector2dF(3.1F, 5.1F), f1 + gfx::Vector2d() },
+ { gfx::Vector2dF(3.1F, 5.1F), f1 + gfx::Vector2dF() },
+ { gfx::Vector2dF(3.1f + 4.3f, 5.1f - 1.3f), f1 + f2 },
+ { gfx::Vector2dF(3.1f - 4.3f, 5.1f + 1.3f), f1 - f2 }
+ };
+
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(float_tests); ++i)
+ EXPECT_EQ(float_tests[i].expected.ToString(),
+ float_tests[i].actual.ToString());
+}
+
+TEST(Vector2dTest, Negative) {
+ const struct {
+ gfx::Vector2d expected;
+ gfx::Vector2d actual;
+ } int_tests[] = {
+ { gfx::Vector2d(0, 0), -gfx::Vector2d(0, 0) },
+ { gfx::Vector2d(-3, -3), -gfx::Vector2d(3, 3) },
+ { gfx::Vector2d(3, 3), -gfx::Vector2d(-3, -3) },
+ { gfx::Vector2d(-3, 3), -gfx::Vector2d(3, -3) },
+ { gfx::Vector2d(3, -3), -gfx::Vector2d(-3, 3) }
+ };
+
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(int_tests); ++i)
+ EXPECT_EQ(int_tests[i].expected.ToString(),
+ int_tests[i].actual.ToString());
+
+ const struct {
+ gfx::Vector2dF expected;
+ gfx::Vector2dF actual;
+ } float_tests[] = {
+ { gfx::Vector2dF(0, 0), -gfx::Vector2d(0, 0) },
+ { gfx::Vector2dF(-0.3f, -0.3f), -gfx::Vector2dF(0.3f, 0.3f) },
+ { gfx::Vector2dF(0.3f, 0.3f), -gfx::Vector2dF(-0.3f, -0.3f) },
+ { gfx::Vector2dF(-0.3f, 0.3f), -gfx::Vector2dF(0.3f, -0.3f) },
+ { gfx::Vector2dF(0.3f, -0.3f), -gfx::Vector2dF(-0.3f, 0.3f) }
+ };
+
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(float_tests); ++i)
+ EXPECT_EQ(float_tests[i].expected.ToString(),
+ float_tests[i].actual.ToString());
+}
+
+TEST(Vector2dTest, Scale) {
+ float double_values[][4] = {
+ { 4.5f, 1.2f, 3.3f, 5.6f },
+ { 4.5f, -1.2f, 3.3f, 5.6f },
+ { 4.5f, 1.2f, 3.3f, -5.6f },
+ { 4.5f, 1.2f, -3.3f, -5.6f },
+ { -4.5f, 1.2f, 3.3f, 5.6f },
+ { -4.5f, 1.2f, 0, 5.6f },
+ { -4.5f, 1.2f, 3.3f, 0 },
+ { 4.5f, 0, 3.3f, 5.6f },
+ { 0, 1.2f, 3.3f, 5.6f }
+ };
+
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(double_values); ++i) {
+ gfx::Vector2dF v(double_values[i][0], double_values[i][1]);
+ v.Scale(double_values[i][2], double_values[i][3]);
+ EXPECT_EQ(v.x(), double_values[i][0] * double_values[i][2]);
+ EXPECT_EQ(v.y(), double_values[i][1] * double_values[i][3]);
+ }
+
+ float single_values[][3] = {
+ { 4.5f, 1.2f, 3.3f },
+ { 4.5f, -1.2f, 3.3f },
+ { 4.5f, 1.2f, 3.3f },
+ { 4.5f, 1.2f, -3.3f },
+ { -4.5f, 1.2f, 3.3f },
+ { -4.5f, 1.2f, 0 },
+ { -4.5f, 1.2f, 3.3f },
+ { 4.5f, 0, 3.3f },
+ { 0, 1.2f, 3.3f }
+ };
+
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(single_values); ++i) {
+ gfx::Vector2dF v(single_values[i][0], single_values[i][1]);
+ v.Scale(single_values[i][2]);
+ EXPECT_EQ(v.x(), single_values[i][0] * single_values[i][2]);
+ EXPECT_EQ(v.y(), single_values[i][1] * single_values[i][2]);
+ }
+}
+
+TEST(Vector2dTest, Length) {
+ int int_values[][2] = {
+ { 0, 0 },
+ { 10, 20 },
+ { 20, 10 },
+ { -10, -20 },
+ { -20, 10 },
+ { 10, -20 },
+ };
+
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(int_values); ++i) {
+ int v0 = int_values[i][0];
+ int v1 = int_values[i][1];
+ double length_squared =
+ static_cast<double>(v0) * v0 + static_cast<double>(v1) * v1;
+ double length = std::sqrt(length_squared);
+ gfx::Vector2d vector(v0, v1);
+ EXPECT_EQ(static_cast<float>(length_squared), vector.LengthSquared());
+ EXPECT_EQ(static_cast<float>(length), vector.Length());
+ }
+
+ float float_values[][2] = {
+ { 0, 0 },
+ { 10.5f, 20.5f },
+ { 20.5f, 10.5f },
+ { -10.5f, -20.5f },
+ { -20.5f, 10.5f },
+ { 10.5f, -20.5f },
+ // A large vector that fails if the Length function doesn't use
+ // double precision internally.
+ { 1236278317862780234892374893213178027.12122348904204230f,
+ 335890352589839028212313231225425134332.38123f },
+ };
+
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(float_values); ++i) {
+ double v0 = float_values[i][0];
+ double v1 = float_values[i][1];
+ double length_squared =
+ static_cast<double>(v0) * v0 + static_cast<double>(v1) * v1;
+ double length = std::sqrt(length_squared);
+ gfx::Vector2dF vector(v0, v1);
+ EXPECT_EQ(length_squared, vector.LengthSquared());
+ EXPECT_EQ(static_cast<float>(length), vector.Length());
+ }
+}
+
+} // namespace ui