summaryrefslogtreecommitdiffstats
path: root/gfx
diff options
context:
space:
mode:
authorben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-03-14 23:30:59 +0000
committerben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-03-14 23:30:59 +0000
commite0fc2f1f81f13440af3bb4cf5e56a031f91fc163 (patch)
treec84d3625eac633ea78d68688ecd74e2d0a158334 /gfx
parent98af9aca7168f061bfaae5cd4f4eb3f7de4e70e7 (diff)
downloadchromium_src-e0fc2f1f81f13440af3bb4cf5e56a031f91fc163.zip
chromium_src-e0fc2f1f81f13440af3bb4cf5e56a031f91fc163.tar.gz
chromium_src-e0fc2f1f81f13440af3bb4cf5e56a031f91fc163.tar.bz2
Move base/gfx contents to gfx/
TBR=darin BUG=none TEST=none git-svn-id: svn://svn.chromium.org/chrome/trunk/src@41559 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'gfx')
-rw-r--r--gfx/gfx.gyp7
-rw-r--r--gfx/icon_util.cc2
-rw-r--r--gfx/icon_util_unittest.cc2
-rw-r--r--gfx/point.cc56
-rw-r--r--gfx/point.h80
-rw-r--r--gfx/rect.cc238
-rw-r--r--gfx/rect.h165
-rw-r--r--gfx/rect_unittest.cc314
-rw-r--r--gfx/size.cc70
-rw-r--r--gfx/size.h83
10 files changed, 1015 insertions, 2 deletions
diff --git a/gfx/gfx.gyp b/gfx/gfx.gyp
index 6b88ab6..0af6121 100644
--- a/gfx/gfx.gyp
+++ b/gfx/gfx.gyp
@@ -17,6 +17,7 @@
'../testing/gtest.gyp:gtest',
],
'sources': [
+ 'rect_unittest.cc',
'run_all_unittests.cc',
'test_suite.h',
],
@@ -54,6 +55,12 @@
'sources': [
'gfx_paths.cc',
'gfx_paths.h',
+ 'point.cc',
+ 'point.h',
+ 'rect.cc',
+ 'rect.h',
+ 'size.cc',
+ 'size.h',
],
'conditions': [
['OS=="win"', {
diff --git a/gfx/icon_util.cc b/gfx/icon_util.cc
index f26ab95..b3b89a8 100644
--- a/gfx/icon_util.cc
+++ b/gfx/icon_util.cc
@@ -5,10 +5,10 @@
#include "gfx/icon_util.h"
#include "base/file_util.h"
-#include "base/gfx/size.h"
#include "base/logging.h"
#include "base/scoped_handle.h"
#include "base/scoped_ptr.h"
+#include "gfx/size.h"
#include "skia/ext/image_operations.h"
#include "third_party/skia/include/core/SkBitmap.h"
diff --git a/gfx/icon_util_unittest.cc b/gfx/icon_util_unittest.cc
index f7f9786..26ecffd 100644
--- a/gfx/icon_util_unittest.cc
+++ b/gfx/icon_util_unittest.cc
@@ -2,12 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "base/gfx/size.h"
#include "base/scoped_ptr.h"
#include "base/file_util.h"
#include "base/path_service.h"
#include "gfx/gfx_paths.h"
#include "gfx/icon_util.h"
+#include "gfx/size.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/gfx/point.cc b/gfx/point.cc
new file mode 100644
index 0000000..16a8216
--- /dev/null
+++ b/gfx/point.cc
@@ -0,0 +1,56 @@
+// Copyright (c) 2006-2008 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 "gfx/point.h"
+
+#if defined(OS_WIN)
+#include <windows.h>
+#endif
+
+#include <iostream>
+
+namespace gfx {
+
+Point::Point() : x_(0), y_(0) {
+}
+
+Point::Point(int x, int y) : x_(x), y_(y) {
+}
+
+#if defined(OS_WIN)
+Point::Point(DWORD point) {
+ POINTS points = MAKEPOINTS(point);
+ x_ = points.x;
+ y_ = points.y;
+}
+
+Point::Point(const POINT& point) : x_(point.x), y_(point.y) {
+}
+
+Point& Point::operator=(const POINT& point) {
+ x_ = point.x;
+ y_ = point.y;
+ return *this;
+}
+
+POINT Point::ToPOINT() const {
+ POINT p;
+ p.x = x_;
+ p.y = y_;
+ return p;
+}
+#elif defined(OS_MACOSX)
+Point::Point(const CGPoint& point) : x_(point.x), y_(point.y) {
+}
+
+CGPoint Point::ToCGPoint() const {
+ return CGPointMake(x_, y_);
+}
+#endif
+
+} // namespace gfx
+
+std::ostream& operator<<(std::ostream& out, const gfx::Point& p) {
+ return out << p.x() << "," << p.y();
+}
diff --git a/gfx/point.h b/gfx/point.h
new file mode 100644
index 0000000..513d555
--- /dev/null
+++ b/gfx/point.h
@@ -0,0 +1,80 @@
+// Copyright (c) 2006-2008 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 BASE_GFX_POINT_H__
+#define BASE_GFX_POINT_H__
+
+#include "build/build_config.h"
+
+#include <iosfwd>
+
+#if defined(OS_WIN)
+typedef unsigned long DWORD;
+typedef struct tagPOINT POINT;
+#elif defined(OS_MACOSX)
+#include <ApplicationServices/ApplicationServices.h>
+#endif
+
+namespace gfx {
+
+//
+// A point has an x and y coordinate.
+//
+class Point {
+ public:
+ Point();
+ Point(int x, int y);
+#if defined(OS_WIN)
+ // |point| is a DWORD value that contains a coordinate. The x-coordinate is
+ // the low-order short and the y-coordinate is the high-order short. This
+ // value is commonly acquired from GetMessagePos/GetCursorPos.
+ explicit Point(DWORD point);
+ explicit Point(const POINT& point);
+ Point& operator=(const POINT& point);
+#elif defined(OS_MACOSX)
+ explicit Point(const CGPoint& point);
+#endif
+
+ ~Point() {}
+
+ int x() const { return x_; }
+ int y() const { return y_; }
+
+ void SetPoint(int x, int y) {
+ x_ = x;
+ y_ = y;
+ }
+
+ void set_x(int x) { x_ = x; }
+ void set_y(int y) { y_ = y; }
+
+ void Offset(int delta_x, int delta_y) {
+ x_ += delta_x;
+ y_ += delta_y;
+ }
+
+ bool operator==(const Point& rhs) const {
+ return x_ == rhs.x_ && y_ == rhs.y_;
+ }
+
+ bool operator!=(const Point& rhs) const {
+ return !(*this == rhs);
+ }
+
+#if defined(OS_WIN)
+ POINT ToPOINT() const;
+#elif defined(OS_MACOSX)
+ CGPoint ToCGPoint() const;
+#endif
+
+ private:
+ int x_;
+ int y_;
+};
+
+} // namespace gfx
+
+std::ostream& operator<<(std::ostream& out, const gfx::Point& p);
+
+#endif // BASE_GFX_POINT_H__
diff --git a/gfx/rect.cc b/gfx/rect.cc
new file mode 100644
index 0000000..30338f4
--- /dev/null
+++ b/gfx/rect.cc
@@ -0,0 +1,238 @@
+// Copyright (c) 2010 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 "gfx/rect.h"
+
+#if defined(OS_WIN)
+#include <windows.h>
+#elif defined(OS_MACOSX)
+#include <CoreGraphics/CGGeometry.h>
+#elif defined(OS_POSIX)
+#include <gdk/gdk.h>
+#endif
+
+#include <iostream>
+
+#include "base/logging.h"
+
+namespace {
+
+void AdjustAlongAxis(int dst_origin, int dst_size, int* origin, int* size) {
+ if (*origin < dst_origin) {
+ *origin = dst_origin;
+ *size = std::min(dst_size, *size);
+ } else {
+ *size = std::min(dst_size, *size);
+ *origin = std::min(dst_origin + dst_size, *origin + *size) - *size;
+ }
+}
+
+} // namespace
+
+namespace gfx {
+
+Rect::Rect() {
+}
+
+Rect::Rect(int width, int height) {
+ set_width(width);
+ set_height(height);
+}
+
+Rect::Rect(int x, int y, int width, int height)
+ : origin_(x, y) {
+ set_width(width);
+ set_height(height);
+}
+
+Rect::Rect(const gfx::Point& origin, const gfx::Size& size)
+ : origin_(origin), size_(size) {
+}
+
+#if defined(OS_WIN)
+Rect::Rect(const RECT& r)
+ : origin_(r.left, r.top) {
+ set_width(r.right - r.left);
+ set_height(r.bottom - r.top);
+}
+
+Rect& Rect::operator=(const RECT& r) {
+ origin_.SetPoint(r.left, r.top);
+ set_width(r.right - r.left);
+ set_height(r.bottom - r.top);
+ return *this;
+}
+#elif defined(OS_MACOSX)
+Rect::Rect(const CGRect& r)
+ : origin_(r.origin.x, r.origin.y) {
+ set_width(r.size.width);
+ set_height(r.size.height);
+}
+
+Rect& Rect::operator=(const CGRect& r) {
+ origin_.SetPoint(r.origin.x, r.origin.y);
+ set_width(r.size.width);
+ set_height(r.size.height);
+ return *this;
+}
+#elif defined(OS_POSIX)
+Rect::Rect(const GdkRectangle& r)
+ : origin_(r.x, r.y) {
+ set_width(r.width);
+ set_height(r.height);
+}
+
+Rect& Rect::operator=(const GdkRectangle& r) {
+ origin_.SetPoint(r.x, r.y);
+ set_width(r.width);
+ set_height(r.height);
+ return *this;
+}
+#endif
+
+void Rect::set_width(int width) {
+ size_.set_width(width);
+}
+void Rect::set_height(int height) {
+ size_.set_height(height);
+}
+
+void Rect::SetRect(int x, int y, int width, int height) {
+ origin_.SetPoint(x, y);
+ set_width(width);
+ set_height(height);
+}
+
+void Rect::Inset(int left, int top, int right, int bottom) {
+ Offset(left, top);
+ set_width(std::max(width() - left - right, 0));
+ set_height(std::max(height() - top - bottom, 0));
+}
+
+void Rect::Offset(int horizontal, int vertical) {
+ origin_.Offset(horizontal, vertical);
+}
+
+bool Rect::operator==(const Rect& other) const {
+ return origin_ == other.origin_ && size_ == other.size_;
+}
+
+#if defined(OS_WIN)
+RECT Rect::ToRECT() const {
+ RECT r;
+ r.left = x();
+ r.right = right();
+ r.top = y();
+ r.bottom = bottom();
+ return r;
+}
+#elif defined(OS_MACOSX)
+CGRect Rect::ToCGRect() const {
+ return CGRectMake(x(), y(), width(), height());
+}
+#elif defined(OS_POSIX)
+GdkRectangle Rect::ToGdkRectangle() const {
+ GdkRectangle r = {x(), y(), width(), height()};
+ return r;
+}
+#endif
+
+bool Rect::Contains(int point_x, int point_y) const {
+ return (point_x >= x()) && (point_x < right()) &&
+ (point_y >= y()) && (point_y < bottom());
+}
+
+bool Rect::Contains(const Rect& rect) const {
+ return (rect.x() >= x() && rect.right() <= right() &&
+ rect.y() >= y() && rect.bottom() <= bottom());
+}
+
+bool Rect::Intersects(const Rect& rect) const {
+ return !(rect.x() >= right() || rect.right() <= x() ||
+ rect.y() >= bottom() || rect.bottom() <= y());
+}
+
+Rect Rect::Intersect(const Rect& rect) const {
+ int rx = std::max(x(), rect.x());
+ int ry = std::max(y(), rect.y());
+ int rr = std::min(right(), rect.right());
+ int rb = std::min(bottom(), rect.bottom());
+
+ if (rx >= rr || ry >= rb)
+ rx = ry = rr = rb = 0; // non-intersecting
+
+ return Rect(rx, ry, rr - rx, rb - ry);
+}
+
+Rect Rect::Union(const Rect& rect) const {
+ // special case empty rects...
+ if (IsEmpty())
+ return rect;
+ if (rect.IsEmpty())
+ return *this;
+
+ int rx = std::min(x(), rect.x());
+ int ry = std::min(y(), rect.y());
+ int rr = std::max(right(), rect.right());
+ int rb = std::max(bottom(), rect.bottom());
+
+ return Rect(rx, ry, rr - rx, rb - ry);
+}
+
+Rect Rect::Subtract(const Rect& rect) const {
+ // boundary cases:
+ if (!Intersects(rect))
+ return *this;
+ if (rect.Contains(*this))
+ return Rect();
+
+ int rx = x();
+ int ry = y();
+ int rr = right();
+ int rb = bottom();
+
+ if (rect.y() <= y() && rect.bottom() >= bottom()) {
+ // complete intersection in the y-direction
+ if (rect.x() <= x()) {
+ rx = rect.right();
+ } else {
+ rr = rect.x();
+ }
+ } else if (rect.x() <= x() && rect.right() >= right()) {
+ // complete intersection in the x-direction
+ if (rect.y() <= y()) {
+ ry = rect.bottom();
+ } else {
+ rb = rect.y();
+ }
+ }
+ return Rect(rx, ry, rr - rx, rb - ry);
+}
+
+Rect Rect::AdjustToFit(const Rect& rect) const {
+ int new_x = x();
+ int new_y = y();
+ int new_width = width();
+ int new_height = height();
+ AdjustAlongAxis(rect.x(), rect.width(), &new_x, &new_width);
+ AdjustAlongAxis(rect.y(), rect.height(), &new_y, &new_height);
+ return Rect(new_x, new_y, new_width, new_height);
+}
+
+Point Rect::CenterPoint() const {
+ return Point(x() + (width() + 1) / 2, y() + (height() + 1) / 2);
+}
+
+bool Rect::SharesEdgeWith(const gfx::Rect& rect) const {
+ return (y() == rect.y() && height() == rect.height() &&
+ (x() == rect.right() || right() == rect.x())) ||
+ (x() == rect.x() && width() == rect.width() &&
+ (y() == rect.bottom() || bottom() == rect.y()));
+}
+
+} // namespace gfx
+
+std::ostream& operator<<(std::ostream& out, const gfx::Rect& r) {
+ return out << r.origin() << " " << r.size();
+}
diff --git a/gfx/rect.h b/gfx/rect.h
new file mode 100644
index 0000000..c3c01ad
--- /dev/null
+++ b/gfx/rect.h
@@ -0,0 +1,165 @@
+// Copyright (c) 2009 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 rectangle class. The containment semantics
+// are array-like; that is, the coordinate (x, y) is considered to be
+// contained by the rectangle, but the coordinate (x + width, y) is not.
+// The class will happily let you create malformed rectangles (that is,
+// rectangles with negative width and/or height), but there will be assertions
+// in the operations (such as contain()) to complain in this case.
+
+#ifndef BASE_GFX_RECT_H__
+#define BASE_GFX_RECT_H__
+
+#include <iosfwd>
+
+#include "base/gfx/point.h"
+#include "base/gfx/size.h"
+
+#if defined(OS_WIN)
+typedef struct tagRECT RECT;
+#elif defined(USE_X11)
+typedef struct _GdkRectangle GdkRectangle;
+#endif
+
+namespace gfx {
+
+class Rect {
+ public:
+ Rect();
+ Rect(int width, int height);
+ Rect(int x, int y, int width, int height);
+#if defined(OS_WIN)
+ explicit Rect(const RECT& r);
+#elif defined(OS_MACOSX)
+ explicit Rect(const CGRect& r);
+#elif defined(USE_X11)
+ explicit Rect(const GdkRectangle& r);
+#endif
+ Rect(const gfx::Point& origin, const gfx::Size& size);
+
+ ~Rect() {}
+
+#if defined(OS_WIN)
+ Rect& operator=(const RECT& r);
+#elif defined(OS_MACOSX)
+ Rect& operator=(const CGRect& r);
+#elif defined(USE_X11)
+ Rect& operator=(const GdkRectangle& r);
+#endif
+
+ int x() const { return origin_.x(); }
+ void set_x(int x) { origin_.set_x(x); }
+
+ int y() const { return origin_.y(); }
+ void set_y(int y) { origin_.set_y(y); }
+
+ int width() const { return size_.width(); }
+ void set_width(int width);
+
+ int height() const { return size_.height(); }
+ void set_height(int height);
+
+ const gfx::Point& origin() const { return origin_; }
+ void set_origin(const gfx::Point& origin) { origin_ = origin; }
+
+ const gfx::Size& size() const { return size_; }
+ void set_size(const gfx::Size& size) { size_ = size; }
+
+ int right() const { return x() + width(); }
+ int bottom() const { return y() + height(); }
+
+ void SetRect(int x, int y, int width, int height);
+
+ // Shrink the rectangle by a horizontal and vertical distance on all sides.
+ void Inset(int horizontal, int vertical) {
+ Inset(horizontal, vertical, horizontal, vertical);
+ }
+
+ // Shrink the rectangle by the specified amount on each side.
+ void Inset(int left, int top, int right, int bottom);
+
+ // Move the rectangle by a horizontal and vertical distance.
+ void Offset(int horizontal, int vertical);
+ void Offset(const gfx::Point& point) {
+ Offset(point.x(), point.y());
+ }
+
+ // Returns true if the area of the rectangle is zero.
+ bool IsEmpty() const { return size_.IsEmpty(); }
+
+ bool operator==(const Rect& other) const;
+
+ bool operator!=(const Rect& other) const {
+ return !(*this == other);
+ }
+
+#if defined(OS_WIN)
+ // Construct an equivalent Win32 RECT object.
+ RECT ToRECT() const;
+#elif defined(USE_X11)
+ GdkRectangle ToGdkRectangle() const;
+#elif defined(OS_MACOSX)
+ // Construct an equivalent CoreGraphics object.
+ CGRect ToCGRect() const;
+#endif
+
+ // Returns true if the point identified by point_x and point_y falls inside
+ // this rectangle. The point (x, y) is inside the rectangle, but the
+ // point (x + width, y + height) is not.
+ bool Contains(int point_x, int point_y) const;
+
+ // Returns true if the specified point is contained by this rectangle.
+ bool Contains(const gfx::Point& point) const {
+ return Contains(point.x(), point.y());
+ }
+
+ // Returns true if this rectangle contains the specified rectangle.
+ bool Contains(const Rect& rect) const;
+
+ // Returns true if this rectangle intersects the specified rectangle.
+ bool Intersects(const Rect& rect) const;
+
+ // Computes the intersection of this rectangle with the given rectangle.
+ Rect Intersect(const Rect& rect) const;
+
+ // Computes the union of this rectangle with the given rectangle. The union
+ // is the smallest rectangle containing both rectangles.
+ Rect Union(const Rect& rect) const;
+
+ // Computes the rectangle resulting from subtracting |rect| from |this|. If
+ // |rect| does not intersect completely in either the x- or y-direction, then
+ // |*this| is returned. If |rect| contains |this|, then an empty Rect is
+ // returned.
+ Rect Subtract(const Rect& rect) const;
+
+ // Returns true if this rectangle equals that of the supplied rectangle.
+ bool Equals(const Rect& rect) const {
+ return *this == rect;
+ }
+
+ // Fits as much of the receiving rectangle into the supplied rectangle as
+ // possible, returning the result. For example, if the receiver had
+ // a x-location of 2 and a width of 4, and the supplied rectangle had
+ // an x-location of 0 with a width of 5, the returned rectangle would have
+ // an x-location of 1 with a width of 4.
+ Rect AdjustToFit(const Rect& rect) const;
+
+ // Returns the center of this rectangle.
+ Point CenterPoint() const;
+
+ // Returns true if this rectangle shares an entire edge (i.e., same width or
+ // same height) with the given rectangle, and the rectangles do not overlap.
+ bool SharesEdgeWith(const gfx::Rect& rect) const;
+
+ private:
+ gfx::Point origin_;
+ gfx::Size size_;
+};
+
+} // namespace gfx
+
+std::ostream& operator<<(std::ostream& out, const gfx::Rect& r);
+
+#endif // BASE_GFX_RECT_H__
diff --git a/gfx/rect_unittest.cc b/gfx/rect_unittest.cc
new file mode 100644
index 0000000..f5b4d9b
--- /dev/null
+++ b/gfx/rect_unittest.cc
@@ -0,0 +1,314 @@
+// Copyright (c) 2006-2008 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 "gfx/rect.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+typedef testing::Test RectTest;
+
+TEST(RectTest, Contains) {
+ static const struct ContainsCase {
+ int rect_x;
+ int rect_y;
+ int rect_width;
+ int rect_height;
+ int point_x;
+ int point_y;
+ bool contained;
+ } contains_cases[] = {
+ {0, 0, 10, 10, 0, 0, true},
+ {0, 0, 10, 10, 5, 5, true},
+ {0, 0, 10, 10, 9, 9, true},
+ {0, 0, 10, 10, 5, 10, false},
+ {0, 0, 10, 10, 10, 5, false},
+ {0, 0, 10, 10, -1, -1, false},
+ {0, 0, 10, 10, 50, 50, false},
+ #ifdef NDEBUG
+ {0, 0, -10, -10, 0, 0, false},
+ #endif // NDEBUG
+ };
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(contains_cases); ++i) {
+ const ContainsCase& value = contains_cases[i];
+ gfx::Rect rect(value.rect_x, value.rect_y,
+ value.rect_width, value.rect_height);
+ EXPECT_EQ(value.contained, rect.Contains(value.point_x, value.point_y));
+ }
+}
+
+TEST(RectTest, Intersects) {
+ static const struct {
+ int x1; // rect 1
+ int y1;
+ int w1;
+ int h1;
+ int x2; // rect 2
+ int y2;
+ int w2;
+ int h2;
+ bool intersects;
+ } tests[] = {
+ { 0, 0, 0, 0, 0, 0, 0, 0, false },
+ { 0, 0, 10, 10, 0, 0, 10, 10, true },
+ { 0, 0, 10, 10, 10, 10, 10, 10, false },
+ { 10, 10, 10, 10, 0, 0, 10, 10, false },
+ { 10, 10, 10, 10, 5, 5, 10, 10, true },
+ { 10, 10, 10, 10, 15, 15, 10, 10, true },
+ { 10, 10, 10, 10, 20, 15, 10, 10, false },
+ { 10, 10, 10, 10, 21, 15, 10, 10, false }
+ };
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
+ gfx::Rect r1(tests[i].x1, tests[i].y1, tests[i].w1, tests[i].h1);
+ gfx::Rect r2(tests[i].x2, tests[i].y2, tests[i].w2, tests[i].h2);
+ EXPECT_EQ(tests[i].intersects, r1.Intersects(r2));
+ }
+}
+
+TEST(RectTest, Intersect) {
+ static const struct {
+ int x1; // rect 1
+ int y1;
+ int w1;
+ int h1;
+ int x2; // rect 2
+ int y2;
+ int w2;
+ int h2;
+ int x3; // rect 3: the union of rects 1 and 2
+ int y3;
+ int w3;
+ int h3;
+ } tests[] = {
+ { 0, 0, 0, 0, // zeros
+ 0, 0, 0, 0,
+ 0, 0, 0, 0 },
+ { 0, 0, 4, 4, // equal
+ 0, 0, 4, 4,
+ 0, 0, 4, 4 },
+ { 0, 0, 4, 4, // neighboring
+ 4, 4, 4, 4,
+ 0, 0, 0, 0 },
+ { 0, 0, 4, 4, // overlapping corners
+ 2, 2, 4, 4,
+ 2, 2, 2, 2 },
+ { 0, 0, 4, 4, // T junction
+ 3, 1, 4, 2,
+ 3, 1, 1, 2 },
+ { 3, 0, 2, 2, // gap
+ 0, 0, 2, 2,
+ 0, 0, 0, 0 }
+ };
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
+ gfx::Rect r1(tests[i].x1, tests[i].y1, tests[i].w1, tests[i].h1);
+ gfx::Rect r2(tests[i].x2, tests[i].y2, tests[i].w2, tests[i].h2);
+ gfx::Rect r3(tests[i].x3, tests[i].y3, tests[i].w3, tests[i].h3);
+ gfx::Rect ir = r1.Intersect(r2);
+ EXPECT_EQ(r3.x(), ir.x());
+ EXPECT_EQ(r3.y(), ir.y());
+ EXPECT_EQ(r3.width(), ir.width());
+ EXPECT_EQ(r3.height(), ir.height());
+ }
+}
+
+TEST(RectTest, Union) {
+ static const struct Test {
+ int x1; // rect 1
+ int y1;
+ int w1;
+ int h1;
+ int x2; // rect 2
+ int y2;
+ int w2;
+ int h2;
+ int x3; // rect 3: the union of rects 1 and 2
+ int y3;
+ int w3;
+ int h3;
+ } tests[] = {
+ { 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0 },
+ { 0, 0, 4, 4,
+ 0, 0, 4, 4,
+ 0, 0, 4, 4 },
+ { 0, 0, 4, 4,
+ 4, 4, 4, 4,
+ 0, 0, 8, 8 },
+ { 0, 0, 4, 4,
+ 0, 5, 4, 4,
+ 0, 0, 4, 9 },
+ { 0, 0, 2, 2,
+ 3, 3, 2, 2,
+ 0, 0, 5, 5 },
+ { 3, 3, 2, 2, // reverse r1 and r2 from previous test
+ 0, 0, 2, 2,
+ 0, 0, 5, 5 },
+ { 0, 0, 0, 0, // union with empty rect
+ 2, 2, 2, 2,
+ 2, 2, 2, 2 }
+ };
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
+ gfx::Rect r1(tests[i].x1, tests[i].y1, tests[i].w1, tests[i].h1);
+ gfx::Rect r2(tests[i].x2, tests[i].y2, tests[i].w2, tests[i].h2);
+ gfx::Rect r3(tests[i].x3, tests[i].y3, tests[i].w3, tests[i].h3);
+ gfx::Rect u = r1.Union(r2);
+ EXPECT_EQ(r3.x(), u.x());
+ EXPECT_EQ(r3.y(), u.y());
+ EXPECT_EQ(r3.width(), u.width());
+ EXPECT_EQ(r3.height(), u.height());
+ }
+}
+
+TEST(RectTest, Equals) {
+ ASSERT_TRUE(gfx::Rect(0, 0, 0, 0).Equals(gfx::Rect(0, 0, 0, 0)));
+ ASSERT_TRUE(gfx::Rect(1, 2, 3, 4).Equals(gfx::Rect(1, 2, 3, 4)));
+ ASSERT_FALSE(gfx::Rect(0, 0, 0, 0).Equals(gfx::Rect(0, 0, 0, 1)));
+ ASSERT_FALSE(gfx::Rect(0, 0, 0, 0).Equals(gfx::Rect(0, 0, 1, 0)));
+ ASSERT_FALSE(gfx::Rect(0, 0, 0, 0).Equals(gfx::Rect(0, 1, 0, 0)));
+ ASSERT_FALSE(gfx::Rect(0, 0, 0, 0).Equals(gfx::Rect(1, 0, 0, 0)));
+}
+
+TEST(RectTest, AdjustToFit) {
+ static const struct Test {
+ int x1; // source
+ int y1;
+ int w1;
+ int h1;
+ int x2; // target
+ int y2;
+ int w2;
+ int h2;
+ int x3; // rect 3: results of invoking AdjustToFit
+ int y3;
+ int w3;
+ int h3;
+ } tests[] = {
+ { 0, 0, 2, 2,
+ 0, 0, 2, 2,
+ 0, 0, 2, 2 },
+ { 2, 2, 3, 3,
+ 0, 0, 4, 4,
+ 1, 1, 3, 3 },
+ { -1, -1, 5, 5,
+ 0, 0, 4, 4,
+ 0, 0, 4, 4 },
+ { 2, 2, 4, 4,
+ 0, 0, 3, 3,
+ 0, 0, 3, 3 },
+ { 2, 2, 1, 1,
+ 0, 0, 3, 3,
+ 2, 2, 1, 1 }
+ };
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
+ gfx::Rect r1(tests[i].x1, tests[i].y1, tests[i].w1, tests[i].h1);
+ gfx::Rect r2(tests[i].x2, tests[i].y2, tests[i].w2, tests[i].h2);
+ gfx::Rect r3(tests[i].x3, tests[i].y3, tests[i].w3, tests[i].h3);
+ gfx::Rect u(r1.AdjustToFit(r2));
+ EXPECT_EQ(r3.x(), u.x());
+ EXPECT_EQ(r3.y(), u.y());
+ EXPECT_EQ(r3.width(), u.width());
+ EXPECT_EQ(r3.height(), u.height());
+ }
+}
+
+TEST(RectTest, Subtract) {
+ // Matching
+ EXPECT_TRUE(
+ gfx::Rect(10, 10, 20, 20).Subtract(
+ gfx::Rect(10, 10, 20, 20)).Equals(
+ gfx::Rect(0, 0, 0, 0)));
+
+ // Contains
+ EXPECT_TRUE(
+ gfx::Rect(10, 10, 20, 20).Subtract(
+ gfx::Rect(5, 5, 30, 30)).Equals(
+ gfx::Rect(0, 0, 0, 0)));
+
+ // No intersection
+ EXPECT_TRUE(
+ gfx::Rect(10, 10, 20, 20).Subtract(
+ gfx::Rect(30, 30, 20, 20)).Equals(
+ gfx::Rect(10, 10, 20, 20)));
+
+ // Not a complete intersection in either direction
+ EXPECT_TRUE(
+ gfx::Rect(10, 10, 20, 20).Subtract(
+ gfx::Rect(15, 15, 20, 20)).Equals(
+ gfx::Rect(10, 10, 20, 20)));
+
+ // Complete intersection in the x-direction
+ EXPECT_TRUE(
+ gfx::Rect(10, 10, 20, 20).Subtract(
+ gfx::Rect(10, 15, 20, 20)).Equals(
+ gfx::Rect(10, 10, 20, 5)));
+
+ // Complete intersection in the x-direction
+ EXPECT_TRUE(
+ gfx::Rect(10, 10, 20, 20).Subtract(
+ gfx::Rect(5, 15, 30, 20)).Equals(
+ gfx::Rect(10, 10, 20, 5)));
+
+ // Complete intersection in the x-direction
+ EXPECT_TRUE(
+ gfx::Rect(10, 10, 20, 20).Subtract(
+ gfx::Rect(5, 5, 30, 20)).Equals(
+ gfx::Rect(10, 25, 20, 5)));
+
+ // Complete intersection in the y-direction
+ EXPECT_TRUE(
+ gfx::Rect(10, 10, 20, 20).Subtract(
+ gfx::Rect(10, 10, 10, 30)).Equals(
+ gfx::Rect(20, 10, 10, 20)));
+
+ // Complete intersection in the y-direction
+ EXPECT_TRUE(
+ gfx::Rect(10, 10, 20, 20).Subtract(
+ gfx::Rect(5, 5, 20, 30)).Equals(
+ gfx::Rect(25, 10, 5, 20)));
+}
+
+TEST(RectTest, IsEmpty) {
+ EXPECT_TRUE(gfx::Rect(0, 0, 0, 0).IsEmpty());
+ EXPECT_TRUE(gfx::Rect(0, 0, 0, 0).size().IsEmpty());
+ EXPECT_TRUE(gfx::Rect(0, 0, 10, 0).IsEmpty());
+ EXPECT_TRUE(gfx::Rect(0, 0, 10, 0).size().IsEmpty());
+ EXPECT_TRUE(gfx::Rect(0, 0, 0, 10).IsEmpty());
+ EXPECT_TRUE(gfx::Rect(0, 0, 0, 10).size().IsEmpty());
+ EXPECT_FALSE(gfx::Rect(0, 0, 10, 10).IsEmpty());
+ EXPECT_FALSE(gfx::Rect(0, 0, 10, 10).size().IsEmpty());
+}
+
+TEST(RectTest, SharesEdgeWith) {
+ gfx::Rect r(2, 3, 4, 5);
+
+ // Must be non-overlapping
+ EXPECT_FALSE(r.SharesEdgeWith(r));
+
+ gfx::Rect just_above(2, 1, 4, 2);
+ gfx::Rect just_below(2, 8, 4, 2);
+ gfx::Rect just_left(0, 3, 2, 5);
+ gfx::Rect just_right(6, 3, 2, 5);
+
+ EXPECT_TRUE(r.SharesEdgeWith(just_above));
+ EXPECT_TRUE(r.SharesEdgeWith(just_below));
+ EXPECT_TRUE(r.SharesEdgeWith(just_left));
+ EXPECT_TRUE(r.SharesEdgeWith(just_right));
+
+ // Wrong placement
+ gfx::Rect same_height_no_edge(0, 0, 1, 5);
+ gfx::Rect same_width_no_edge(0, 0, 4, 1);
+
+ EXPECT_FALSE(r.SharesEdgeWith(same_height_no_edge));
+ EXPECT_FALSE(r.SharesEdgeWith(same_width_no_edge));
+
+ gfx::Rect just_above_no_edge(2, 1, 5, 2); // too wide
+ gfx::Rect just_below_no_edge(2, 8, 3, 2); // too narrow
+ gfx::Rect just_left_no_edge(0, 3, 2, 6); // too tall
+ gfx::Rect just_right_no_edge(6, 3, 2, 4); // too short
+
+ EXPECT_FALSE(r.SharesEdgeWith(just_above_no_edge));
+ EXPECT_FALSE(r.SharesEdgeWith(just_below_no_edge));
+ EXPECT_FALSE(r.SharesEdgeWith(just_left_no_edge));
+ EXPECT_FALSE(r.SharesEdgeWith(just_right_no_edge));
+}
diff --git a/gfx/size.cc b/gfx/size.cc
new file mode 100644
index 0000000..d450f20
--- /dev/null
+++ b/gfx/size.cc
@@ -0,0 +1,70 @@
+// Copyright (c) 2006-2008 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 "gfx/size.h"
+
+#if defined(OS_WIN)
+#include <windows.h>
+#elif defined(OS_MACOSX)
+#include <CoreGraphics/CGGeometry.h>
+#endif
+
+#include <iostream>
+
+#include "base/logging.h"
+
+namespace gfx {
+
+Size::Size(int width, int height) {
+ set_width(width);
+ set_height(height);
+}
+
+#if defined(OS_MACOSX)
+Size::Size(const CGSize& s) {
+ set_width(s.width);
+ set_height(s.height);
+}
+
+Size& Size::operator=(const CGSize& s) {
+ set_width(s.width);
+ set_height(s.height);
+ return *this;
+}
+#endif
+
+#if defined(OS_WIN)
+SIZE Size::ToSIZE() const {
+ SIZE s;
+ s.cx = width_;
+ s.cy = height_;
+ return s;
+}
+#elif defined(OS_MACOSX)
+CGSize Size::ToCGSize() const {
+ return CGSizeMake(width_, height_);
+}
+#endif
+
+void Size::set_width(int width) {
+ if (width < 0) {
+ NOTREACHED();
+ width = 0;
+ }
+ width_ = width;
+}
+
+void Size::set_height(int height) {
+ if (height < 0) {
+ NOTREACHED();
+ height = 0;
+ }
+ height_ = height;
+}
+
+} // namespace gfx
+
+std::ostream& operator<<(std::ostream& out, const gfx::Size& s) {
+ return out << s.width() << "x" << s.height();
+}
diff --git a/gfx/size.h b/gfx/size.h
new file mode 100644
index 0000000..896908e8
--- /dev/null
+++ b/gfx/size.h
@@ -0,0 +1,83 @@
+// Copyright (c) 2006-2008 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 BASE_GFX_SIZE_H_
+#define BASE_GFX_SIZE_H_
+
+#include "build/build_config.h"
+
+#include <iosfwd>
+
+#if defined(OS_WIN)
+typedef struct tagSIZE SIZE;
+#elif defined(OS_MACOSX)
+#include <ApplicationServices/ApplicationServices.h>
+#endif
+
+namespace gfx {
+
+//
+// A size has width and height values.
+//
+class Size {
+ public:
+ Size() : width_(0), height_(0) {}
+ Size(int width, int height);
+#if defined(OS_MACOSX)
+ explicit Size(const CGSize& s);
+#endif
+
+ ~Size() {}
+
+#if defined(OS_MACOSX)
+ Size& operator=(const CGSize& s);
+#endif
+
+ int width() const { return width_; }
+ int height() const { return height_; }
+
+ int GetArea() const { return width_ * height_; }
+
+ void SetSize(int width, int height) {
+ set_width(width);
+ set_height(height);
+ }
+
+ void Enlarge(int width, int height) {
+ set_width(width_ + width);
+ set_height(height_ + height);
+ }
+
+ void set_width(int width);
+ void set_height(int height);
+
+ bool operator==(const Size& s) const {
+ return width_ == s.width_ && height_ == s.height_;
+ }
+
+ bool operator!=(const Size& s) const {
+ return !(*this == s);
+ }
+
+ bool IsEmpty() const {
+ // Size doesn't allow negative dimensions, so testing for 0 is enough.
+ return (width_ == 0) || (height_ == 0);
+ }
+
+#if defined(OS_WIN)
+ SIZE ToSIZE() const;
+#elif defined(OS_MACOSX)
+ CGSize ToCGSize() const;
+#endif
+
+ private:
+ int width_;
+ int height_;
+};
+
+} // namespace gfx
+
+std::ostream& operator<<(std::ostream& out, const gfx::Size& s);
+
+#endif // BASE_GFX_SIZE_H_