summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHidehiko Abe <hidehiko@google.com>2018-04-13 06:33:47 -0700
committerandroid-build-merger <android-build-merger@google.com>2018-04-13 06:33:47 -0700
commit8cadf386df57b1ed249634ab88dce7c6f252de4e (patch)
tree36c89cd375dee720134b6af77c4907a01371f5a7
parent026f42b9b0be91cab925c28b01b5271e17d1e7f5 (diff)
parent34c1558fedad7b65b8595d9e452e3190efa3ed12 (diff)
downloadlibchrome-8cadf386df57b1ed249634ab88dce7c6f252de4e.tar.gz
Migrate libmojo repository into libchrome, part 1.
am: 34c1558fed Change-Id: I55e227b5f259dd320b23645d4d051b8e4aab9024
-rw-r--r--Android.bp22
-rw-r--r--base/base_paths.cc49
-rw-r--r--base/base_paths.h54
-rw-r--r--base/base_paths_posix.cc123
-rw-r--r--base/base_paths_posix.h27
-rw-r--r--base/files/file_util_posix.cc2
-rw-r--r--base/i18n/base_i18n_export.h29
-rw-r--r--base/i18n/rtl.h155
-rw-r--r--base/json/json_reader_unittest.cc9
-rw-r--r--base/json/json_value_serializer_unittest.cc11
-rw-r--r--base/path_service.cc329
-rw-r--r--base/path_service.h97
-rw-r--r--base/unguessable_token.cc41
-rw-r--r--base/unguessable_token.h103
-rw-r--r--device/bluetooth/bluetooth_advertisement.cc37
-rw-r--r--device/bluetooth/bluetooth_advertisement.h152
-rw-r--r--device/bluetooth/bluetooth_common.h49
-rw-r--r--device/bluetooth/bluetooth_export.h28
-rw-r--r--device/bluetooth/bluetooth_uuid.cc98
-rw-r--r--device/bluetooth/bluetooth_uuid.h106
-rw-r--r--device/bluetooth/bluez/bluetooth_service_attribute_value_bluez.cc54
-rw-r--r--device/bluetooth/bluez/bluetooth_service_attribute_value_bluez.h59
-rw-r--r--libchrome_tools/patch/path_service.patch124
-rw-r--r--ui/gfx/geometry/insets.cc22
-rw-r--r--ui/gfx/geometry/insets.h130
-rw-r--r--ui/gfx/geometry/insets_f.cc16
-rw-r--r--ui/gfx/geometry/insets_f.h100
-rw-r--r--ui/gfx/geometry/point.cc105
-rw-r--r--ui/gfx/geometry/point.h148
-rw-r--r--ui/gfx/geometry/point_conversions.cc30
-rw-r--r--ui/gfx/geometry/point_conversions.h24
-rw-r--r--ui/gfx/geometry/point_f.cc32
-rw-r--r--ui/gfx/geometry/point_f.h126
-rw-r--r--ui/gfx/geometry/rect.cc346
-rw-r--r--ui/gfx/geometry/rect.h350
-rw-r--r--ui/gfx/geometry/rect_f.cc259
-rw-r--r--ui/gfx/geometry/rect_f.h242
-rw-r--r--ui/gfx/geometry/safe_integer_conversions.h62
-rw-r--r--ui/gfx/geometry/size.cc115
-rw-r--r--ui/gfx/geometry/size.h103
-rw-r--r--ui/gfx/geometry/size_conversions.cc30
-rw-r--r--ui/gfx/geometry/size_conversions.h24
-rw-r--r--ui/gfx/geometry/size_f.cc39
-rw-r--r--ui/gfx/geometry/size_f.h97
-rw-r--r--ui/gfx/geometry/vector2d.cc40
-rw-r--r--ui/gfx/geometry/vector2d.h100
-rw-r--r--ui/gfx/geometry/vector2d_f.cc60
-rw-r--r--ui/gfx/geometry/vector2d_f.h118
-rw-r--r--ui/gfx/gfx_export.h29
-rw-r--r--ui/gfx/range/BUILD.gn33
-rw-r--r--ui/gfx/range/gfx_range_export.h29
-rw-r--r--ui/gfx/range/range.cc34
-rw-r--r--ui/gfx/range/range.h139
-rw-r--r--ui/gfx/range/range_f.cc58
-rw-r--r--ui/gfx/range/range_f.h101
-rw-r--r--ui/gfx/range/range_unittest.cc266
56 files changed, 5082 insertions, 83 deletions
diff --git a/Android.bp b/Android.bp
index c2a3ec056c..d4842e1e08 100644
--- a/Android.bp
+++ b/Android.bp
@@ -80,6 +80,8 @@ libchromeCommonSrc = [
"base/at_exit.cc",
"base/base64.cc",
"base/base64url.cc",
+ "base/base_paths.cc",
+ "base/base_paths_posix.cc",
"base/base_switches.cc",
"base/bind_helpers.cc",
"base/build_time.cc",
@@ -154,6 +156,7 @@ libchromeCommonSrc = [
"base/metrics/sample_vector.cc",
"base/metrics/sparse_histogram.cc",
"base/metrics/statistics_recorder.cc",
+ "base/path_service.cc",
"base/pending_task.cc",
"base/pickle.cc",
"base/posix/global_descriptors.cc",
@@ -270,9 +273,27 @@ libchromeCommonSrc = [
"base/trace_event/trace_log_constants.cc",
"base/tracked_objects.cc",
"base/tracking_info.cc",
+ "base/unguessable_token.cc",
"base/values.cc",
"base/version.cc",
"base/vlog.cc",
+ "device/bluetooth/bluetooth_advertisement.cc",
+ "device/bluetooth/bluetooth_uuid.cc",
+ "device/bluetooth/bluez/bluetooth_service_attribute_value_bluez.cc",
+ "ui/gfx/geometry/insets.cc",
+ "ui/gfx/geometry/insets_f.cc",
+ "ui/gfx/geometry/point.cc",
+ "ui/gfx/geometry/point_conversions.cc",
+ "ui/gfx/geometry/point_f.cc",
+ "ui/gfx/geometry/rect.cc",
+ "ui/gfx/geometry/rect_f.cc",
+ "ui/gfx/geometry/size.cc",
+ "ui/gfx/geometry/size_conversions.cc",
+ "ui/gfx/geometry/size_f.cc",
+ "ui/gfx/geometry/vector2d.cc",
+ "ui/gfx/geometry/vector2d_f.cc",
+ "ui/gfx/range/range.cc",
+ "ui/gfx/range/range_f.cc",
]
libchromeLinuxSrc = [
@@ -553,6 +574,7 @@ cc_test {
"base/vlog_unittest.cc",
"testing/multiprocess_func_list.cc",
"testrunner.cc",
+ "ui/gfx/range/range_unittest.cc",
],
cflags: ["-DUNIT_TEST"],
diff --git a/base/base_paths.cc b/base/base_paths.cc
new file mode 100644
index 0000000000..31bc55401a
--- /dev/null
+++ b/base/base_paths.cc
@@ -0,0 +1,49 @@
+// 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/base_paths.h"
+
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/path_service.h"
+
+namespace base {
+
+bool PathProvider(int key, FilePath* result) {
+ // NOTE: DIR_CURRENT is a special case in PathService::Get
+
+ switch (key) {
+ case DIR_EXE:
+ PathService::Get(FILE_EXE, result);
+ *result = result->DirName();
+ return true;
+ case DIR_MODULE:
+ PathService::Get(FILE_MODULE, result);
+ *result = result->DirName();
+ return true;
+ case DIR_TEMP:
+ if (!GetTempDir(result))
+ return false;
+ return true;
+ case base::DIR_HOME:
+ *result = GetHomeDir();
+ return true;
+ case DIR_TEST_DATA: {
+ FilePath test_data_path;
+ if (!PathService::Get(DIR_SOURCE_ROOT, &test_data_path))
+ return false;
+ test_data_path = test_data_path.Append(FILE_PATH_LITERAL("base"));
+ test_data_path = test_data_path.Append(FILE_PATH_LITERAL("test"));
+ test_data_path = test_data_path.Append(FILE_PATH_LITERAL("data"));
+ if (!PathExists(test_data_path)) // We don't want to create this.
+ return false;
+ *result = test_data_path;
+ return true;
+ }
+ default:
+ return false;
+ }
+}
+
+} // namespace base
diff --git a/base/base_paths.h b/base/base_paths.h
new file mode 100644
index 0000000000..ef6aa82836
--- /dev/null
+++ b/base/base_paths.h
@@ -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.
+
+#ifndef BASE_BASE_PATHS_H_
+#define BASE_BASE_PATHS_H_
+
+// This file declares path keys for the base module. These can be used with
+// the PathService to access various special directories and files.
+
+#include "build/build_config.h"
+
+#if defined(OS_WIN)
+#include "base/base_paths_win.h"
+#elif defined(OS_MACOSX)
+#include "base/base_paths_mac.h"
+#elif defined(OS_ANDROID)
+#include "base/base_paths_android.h"
+#endif
+
+#if defined(OS_POSIX)
+#include "base/base_paths_posix.h"
+#endif
+
+namespace base {
+
+enum BasePathKey {
+ PATH_START = 0,
+
+ DIR_CURRENT, // Current directory.
+ DIR_EXE, // Directory containing FILE_EXE.
+ DIR_MODULE, // Directory containing FILE_MODULE.
+ DIR_TEMP, // Temporary directory.
+ DIR_HOME, // User's root home directory. On Windows this will look
+ // like "C:\Users\<user>" which isn't necessarily a great
+ // place to put files.
+ FILE_EXE, // Path and filename of the current executable.
+ FILE_MODULE, // Path and filename of the module containing the code for
+ // the PathService (which could differ from FILE_EXE if the
+ // PathService were compiled into a shared object, for
+ // example).
+ DIR_SOURCE_ROOT, // Returns the root of the source tree. This key is useful
+ // for tests that need to locate various resources. It
+ // should not be used outside of test code.
+ DIR_USER_DESKTOP, // The current user's Desktop.
+
+ DIR_TEST_DATA, // Used only for testing.
+
+ PATH_END
+};
+
+} // namespace base
+
+#endif // BASE_BASE_PATHS_H_
diff --git a/base/base_paths_posix.cc b/base/base_paths_posix.cc
new file mode 100644
index 0000000000..37d646cd26
--- /dev/null
+++ b/base/base_paths_posix.cc
@@ -0,0 +1,123 @@
+// 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 base::PathProviderPosix, default path provider on POSIX OSes that
+// don't have their own base_paths_OS.cc implementation (i.e. all but Mac and
+// Android).
+
+#include "base/base_paths.h"
+
+#include <limits.h>
+#include <stddef.h>
+
+#include <memory>
+#include <ostream>
+#include <string>
+
+#include "base/environment.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/logging.h"
+// Unused, and this file is not ported to libchrome.
+// #include "base/nix/xdg_util.h"
+#include "base/path_service.h"
+#include "base/process/process_metrics.h"
+#include "build/build_config.h"
+
+#if defined(OS_FREEBSD)
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#elif defined(OS_SOLARIS)
+#include <stdlib.h>
+#endif
+
+namespace base {
+
+bool PathProviderPosix(int key, FilePath* result) {
+ FilePath path;
+ switch (key) {
+ case FILE_EXE:
+ case FILE_MODULE: { // TODO(evanm): is this correct?
+#if defined(OS_LINUX)
+ FilePath bin_dir;
+ if (!ReadSymbolicLink(FilePath(kProcSelfExe), &bin_dir)) {
+ NOTREACHED() << "Unable to resolve " << kProcSelfExe << ".";
+ return false;
+ }
+ *result = bin_dir;
+ return true;
+#elif defined(OS_FREEBSD)
+ int name[] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 };
+ char bin_dir[PATH_MAX + 1];
+ size_t length = sizeof(bin_dir);
+ // Upon return, |length| is the number of bytes written to |bin_dir|
+ // including the string terminator.
+ int error = sysctl(name, 4, bin_dir, &length, NULL, 0);
+ if (error < 0 || length <= 1) {
+ NOTREACHED() << "Unable to resolve path.";
+ return false;
+ }
+ *result = FilePath(FilePath::StringType(bin_dir, length - 1));
+ return true;
+#elif defined(OS_SOLARIS)
+ char bin_dir[PATH_MAX + 1];
+ if (realpath(getexecname(), bin_dir) == NULL) {
+ NOTREACHED() << "Unable to resolve " << getexecname() << ".";
+ return false;
+ }
+ *result = FilePath(bin_dir);
+ return true;
+#elif defined(OS_OPENBSD)
+ // There is currently no way to get the executable path on OpenBSD
+ char* cpath;
+ if ((cpath = getenv("CHROME_EXE_PATH")) != NULL)
+ *result = FilePath(cpath);
+ else
+ *result = FilePath("/usr/local/chrome/chrome");
+ return true;
+#endif
+ }
+// Following paths are not supported in libchrome/libmojo.
+#if 0
+ case DIR_SOURCE_ROOT: {
+ // Allow passing this in the environment, for more flexibility in build
+ // tree configurations (sub-project builds, gyp --output_dir, etc.)
+ std::unique_ptr<Environment> env(Environment::Create());
+ std::string cr_source_root;
+ if (env->GetVar("CR_SOURCE_ROOT", &cr_source_root)) {
+ path = FilePath(cr_source_root);
+ if (PathExists(path)) {
+ *result = path;
+ return true;
+ }
+ DLOG(WARNING) << "CR_SOURCE_ROOT is set, but it appears to not "
+ << "point to a directory.";
+ }
+ // On POSIX, unit tests execute two levels deep from the source root.
+ // For example: out/{Debug|Release}/net_unittest
+ if (PathService::Get(DIR_EXE, &path)) {
+ *result = path.DirName().DirName();
+ return true;
+ }
+
+ DLOG(ERROR) << "Couldn't find your source root. "
+ << "Try running from your chromium/src directory.";
+ return false;
+ }
+ case DIR_USER_DESKTOP:
+ *result = nix::GetXDGUserDirectory("DESKTOP", "Desktop");
+ return true;
+ case DIR_CACHE: {
+ std::unique_ptr<Environment> env(Environment::Create());
+ FilePath cache_dir(
+ nix::GetXDGDirectory(env.get(), "XDG_CACHE_HOME", ".cache"));
+ *result = cache_dir;
+ return true;
+ }
+#endif
+ }
+ return false;
+}
+
+} // namespace base
diff --git a/base/base_paths_posix.h b/base/base_paths_posix.h
new file mode 100644
index 0000000000..ef002aeb0b
--- /dev/null
+++ b/base/base_paths_posix.h
@@ -0,0 +1,27 @@
+// 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 BASE_BASE_PATHS_POSIX_H_
+#define BASE_BASE_PATHS_POSIX_H_
+
+// This file declares windows-specific path keys for the base module.
+// These can be used with the PathService to access various special
+// directories and files.
+
+namespace base {
+
+enum {
+ PATH_POSIX_START = 400,
+
+ DIR_CACHE, // Directory where to put cache data. Note this is
+ // *not* where the browser cache lives, but the
+ // browser cache can be a subdirectory.
+ // This is $XDG_CACHE_HOME on Linux and
+ // ~/Library/Caches on Mac.
+ PATH_POSIX_END
+};
+
+} // namespace base
+
+#endif // BASE_BASE_PATHS_POSIX_H_
diff --git a/base/files/file_util_posix.cc b/base/files/file_util_posix.cc
index 3501e241e9..91f12030a0 100644
--- a/base/files/file_util_posix.cc
+++ b/base/files/file_util_posix.cc
@@ -29,6 +29,7 @@
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/singleton.h"
+#include "base/path_service.h"
#include "base/posix/eintr_wrapper.h"
#include "base/stl_util.h"
#include "base/strings/string_split.h"
@@ -49,7 +50,6 @@
#if defined(OS_ANDROID)
#include "base/android/content_uri_utils.h"
#include "base/os_compat_android.h"
-#include "base/path_service.h"
#endif
#if !defined(OS_IOS)
diff --git a/base/i18n/base_i18n_export.h b/base/i18n/base_i18n_export.h
new file mode 100644
index 0000000000..e8a2adda17
--- /dev/null
+++ b/base/i18n/base_i18n_export.h
@@ -0,0 +1,29 @@
+// Copyright (c) 2011 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_I18N_BASE_I18N_EXPORT_H_
+#define BASE_I18N_BASE_I18N_EXPORT_H_
+
+#if defined(COMPONENT_BUILD)
+#if defined(WIN32)
+
+#if defined(BASE_I18N_IMPLEMENTATION)
+#define BASE_I18N_EXPORT __declspec(dllexport)
+#else
+#define BASE_I18N_EXPORT __declspec(dllimport)
+#endif // defined(BASE_I18N_IMPLEMENTATION)
+
+#else // defined(WIN32)
+#if defined(BASE_I18N_IMPLEMENTATION)
+#define BASE_I18N_EXPORT __attribute__((visibility("default")))
+#else
+#define BASE_I18N_EXPORT
+#endif
+#endif
+
+#else // defined(COMPONENT_BUILD)
+#define BASE_I18N_EXPORT
+#endif
+
+#endif // BASE_I18N_BASE_I18N_EXPORT_H_
diff --git a/base/i18n/rtl.h b/base/i18n/rtl.h
new file mode 100644
index 0000000000..df15cd0208
--- /dev/null
+++ b/base/i18n/rtl.h
@@ -0,0 +1,155 @@
+// Copyright (c) 2011 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_I18N_RTL_H_
+#define BASE_I18N_RTL_H_
+
+#include <string>
+
+#include "base/compiler_specific.h"
+#include "base/i18n/base_i18n_export.h"
+#include "base/strings/string16.h"
+#include "build/build_config.h"
+
+namespace base {
+
+class FilePath;
+
+namespace i18n {
+
+const char16 kRightToLeftMark = 0x200F;
+const char16 kLeftToRightMark = 0x200E;
+const char16 kLeftToRightEmbeddingMark = 0x202A;
+const char16 kRightToLeftEmbeddingMark = 0x202B;
+const char16 kPopDirectionalFormatting = 0x202C;
+const char16 kLeftToRightOverride = 0x202D;
+const char16 kRightToLeftOverride = 0x202E;
+
+// Locale.java mirrored this enum TextDirection. Please keep in sync.
+enum TextDirection {
+ UNKNOWN_DIRECTION = 0,
+ RIGHT_TO_LEFT = 1,
+ LEFT_TO_RIGHT = 2,
+ TEXT_DIRECTION_MAX = LEFT_TO_RIGHT,
+};
+
+// Get the locale that the currently running process has been configured to use.
+// The return value is of the form language[-country] (e.g., en-US) where the
+// language is the 2 or 3 letter code from ISO-639.
+BASE_I18N_EXPORT std::string GetConfiguredLocale();
+
+// Canonicalize a string (eg. a POSIX locale string) to a Chrome locale name.
+BASE_I18N_EXPORT std::string GetCanonicalLocale(const std::string& locale);
+
+// Sets the default locale of ICU.
+// Once the application locale of Chrome in GetApplicationLocale is determined,
+// the default locale of ICU need to be changed to match the application locale
+// so that ICU functions work correctly in a locale-dependent manner.
+// This is handy in that we don't have to call GetApplicationLocale()
+// everytime we call locale-dependent ICU APIs as long as we make sure
+// that this is called before any locale-dependent API is called.
+BASE_I18N_EXPORT void SetICUDefaultLocale(const std::string& locale_string);
+
+// Returns true if the application text direction is right-to-left.
+BASE_I18N_EXPORT bool IsRTL();
+
+// Returns whether the text direction for the default ICU locale is RTL. This
+// assumes that SetICUDefaultLocale has been called to set the default locale to
+// the UI locale of Chrome.
+// NOTE: Generally, you should call IsRTL() instead of this.
+BASE_I18N_EXPORT bool ICUIsRTL();
+
+// Returns the text direction for |locale_name|.
+// As a startup optimization, this method checks the locale against a list of
+// Chrome-supported RTL locales.
+BASE_I18N_EXPORT TextDirection
+GetTextDirectionForLocaleInStartUp(const char* locale_name);
+
+// Returns the text direction for |locale_name|.
+BASE_I18N_EXPORT TextDirection GetTextDirectionForLocale(
+ const char* locale_name);
+
+// Given the string in |text|, returns the directionality of the first or last
+// character with strong directionality in the string. If no character in the
+// text has strong directionality, LEFT_TO_RIGHT is returned. The Bidi
+// character types L, LRE, LRO, R, AL, RLE, and RLO are considered as strong
+// directionality characters. Please refer to http://unicode.org/reports/tr9/
+// for more information.
+BASE_I18N_EXPORT TextDirection GetFirstStrongCharacterDirection(
+ const string16& text);
+BASE_I18N_EXPORT TextDirection GetLastStrongCharacterDirection(
+ const string16& text);
+
+// Given the string in |text|, returns LEFT_TO_RIGHT or RIGHT_TO_LEFT if all the
+// strong directionality characters in the string are of the same
+// directionality. It returns UNKNOWN_DIRECTION if the string contains a mix of
+// LTR and RTL strong directionality characters. Defaults to LEFT_TO_RIGHT if
+// the string does not contain directionality characters. Please refer to
+// http://unicode.org/reports/tr9/ for more information.
+BASE_I18N_EXPORT TextDirection GetStringDirection(const string16& text);
+
+// Given the string in |text|, this function modifies the string in place with
+// the appropriate Unicode formatting marks that mark the string direction
+// (either left-to-right or right-to-left). The function checks both the current
+// locale and the contents of the string in order to determine the direction of
+// the returned string. The function returns true if the string in |text| was
+// properly adjusted.
+//
+// Certain LTR strings are not rendered correctly when the context is RTL. For
+// example, the string "Foo!" will appear as "!Foo" if it is rendered as is in
+// an RTL context. Calling this function will make sure the returned localized
+// string is always treated as a right-to-left string. This is done by
+// inserting certain Unicode formatting marks into the returned string.
+//
+// ** Notes about the Windows version of this function:
+// TODO(idana) bug 6806: this function adjusts the string in question only
+// if the current locale is right-to-left. The function does not take care of
+// the opposite case (an RTL string displayed in an LTR context) since
+// adjusting the string involves inserting Unicode formatting characters that
+// Windows does not handle well unless right-to-left language support is
+// installed. Since the English version of Windows doesn't have right-to-left
+// language support installed by default, inserting the direction Unicode mark
+// results in Windows displaying squares.
+BASE_I18N_EXPORT bool AdjustStringForLocaleDirection(string16* text);
+
+// Undoes the actions of the above function (AdjustStringForLocaleDirection).
+BASE_I18N_EXPORT bool UnadjustStringForLocaleDirection(string16* text);
+
+// Returns true if the string contains at least one character with strong right
+// to left directionality; that is, a character with either R or AL Unicode
+// BiDi character type.
+BASE_I18N_EXPORT bool StringContainsStrongRTLChars(const string16& text);
+
+// Wraps a string with an LRE-PDF pair which essentialy marks the string as a
+// Left-To-Right string. Doing this is useful in order to make sure LTR
+// strings are rendered properly in an RTL context.
+BASE_I18N_EXPORT void WrapStringWithLTRFormatting(string16* text);
+
+// Wraps a string with an RLE-PDF pair which essentialy marks the string as a
+// Right-To-Left string. Doing this is useful in order to make sure RTL
+// strings are rendered properly in an LTR context.
+BASE_I18N_EXPORT void WrapStringWithRTLFormatting(string16* text);
+
+// Wraps file path to get it to display correctly in RTL UI. All filepaths
+// should be passed through this function before display in UI for RTL locales.
+BASE_I18N_EXPORT void WrapPathWithLTRFormatting(const FilePath& path,
+ string16* rtl_safe_path);
+
+// Return the string in |text| wrapped with LRE (Left-To-Right Embedding) and
+// PDF (Pop Directional Formatting) marks, if needed for UI display purposes.
+BASE_I18N_EXPORT string16 GetDisplayStringInLTRDirectionality(
+ const string16& text) WARN_UNUSED_RESULT;
+
+// Strip the beginning (U+202A..U+202B, U+202D..U+202E) and/or ending (U+202C)
+// explicit bidi control characters from |text|, if there are any. Otherwise,
+// return the text itself. Explicit bidi control characters display and have
+// semantic effect. They can be deleted so they might not always appear in a
+// pair.
+BASE_I18N_EXPORT string16 StripWrappingBidiControlCharacters(
+ const string16& text) WARN_UNUSED_RESULT;
+
+} // namespace i18n
+} // namespace base
+
+#endif // BASE_I18N_RTL_H_
diff --git a/base/json/json_reader_unittest.cc b/base/json/json_reader_unittest.cc
index 1344de6391..f645b427fc 100644
--- a/base/json/json_reader_unittest.cc
+++ b/base/json/json_reader_unittest.cc
@@ -8,14 +8,11 @@
#include <memory>
-#if !defined(__ANDROID__) && !defined(__ANDROID_HOST__)
#include "base/base_paths.h"
-#include "base/path_service.h"
-#endif
-
#include "base/files/file_util.h"
#include "base/logging.h"
#include "base/macros.h"
+#include "base/path_service.h"
#include "base/strings/string_piece.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
@@ -570,8 +567,7 @@ TEST(JSONReaderTest, Reading) {
}
}
-#if !defined(__ANDROID__) && !defined(__ANDROID_HOST__)
-TEST(JSONReaderTest, ReadFromFile) {
+TEST(JSONReaderTest, DISABLED_ReadFromFile) {
FilePath path;
ASSERT_TRUE(PathService::Get(base::DIR_TEST_DATA, &path));
path = path.AppendASCII("json");
@@ -585,7 +581,6 @@ TEST(JSONReaderTest, ReadFromFile) {
ASSERT_TRUE(root) << reader.GetErrorMessage();
EXPECT_TRUE(root->IsType(Value::Type::DICTIONARY));
}
-#endif // !__ANDROID__ && !__ANDROID_HOST__
// Tests that the root of a JSON object can be deleted safely while its
// children outlive it.
diff --git a/base/json/json_value_serializer_unittest.cc b/base/json/json_value_serializer_unittest.cc
index 1d58c61e04..e5cb126861 100644
--- a/base/json/json_value_serializer_unittest.cc
+++ b/base/json/json_value_serializer_unittest.cc
@@ -11,9 +11,7 @@
#include "base/json/json_reader.h"
#include "base/json/json_string_value_serializer.h"
#include "base/json/json_writer.h"
-#if !defined(__ANDROID__) && !defined(__ANDROID_HOST__)
#include "base/path_service.h"
-#endif
#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
@@ -397,8 +395,6 @@ TEST(JSONValueSerializerTest, JSONReaderComments) {
ASSERT_FALSE(JSONReader::Read("/ * * / [1]"));
}
-#if !defined(__ANDROID__) && !defined(__ANDROID_HOST__)
-
class JSONFileValueSerializerTest : public testing::Test {
protected:
void SetUp() override { ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); }
@@ -406,7 +402,7 @@ class JSONFileValueSerializerTest : public testing::Test {
ScopedTempDir temp_dir_;
};
-TEST_F(JSONFileValueSerializerTest, Roundtrip) {
+TEST_F(JSONFileValueSerializerTest, DISABLED_Roundtrip) {
FilePath original_file_path;
ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &original_file_path));
original_file_path = original_file_path.AppendASCII("serializer_test.json");
@@ -449,7 +445,7 @@ TEST_F(JSONFileValueSerializerTest, Roundtrip) {
EXPECT_TRUE(DeleteFile(written_file_path, false));
}
-TEST_F(JSONFileValueSerializerTest, RoundtripNested) {
+TEST_F(JSONFileValueSerializerTest, DISABLED_RoundtripNested) {
FilePath original_file_path;
ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &original_file_path));
original_file_path =
@@ -475,7 +471,7 @@ TEST_F(JSONFileValueSerializerTest, RoundtripNested) {
EXPECT_TRUE(DeleteFile(written_file_path, false));
}
-TEST_F(JSONFileValueSerializerTest, NoWhitespace) {
+TEST_F(JSONFileValueSerializerTest, DISABLED_NoWhitespace) {
FilePath source_file_path;
ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &source_file_path));
source_file_path =
@@ -485,7 +481,6 @@ TEST_F(JSONFileValueSerializerTest, NoWhitespace) {
std::unique_ptr<Value> root = deserializer.Deserialize(nullptr, nullptr);
ASSERT_TRUE(root);
}
-#endif // !__ANDROID__ && !__ANDROID_HOST__
} // namespace
diff --git a/base/path_service.cc b/base/path_service.cc
new file mode 100644
index 0000000000..1b9d394930
--- /dev/null
+++ b/base/path_service.cc
@@ -0,0 +1,329 @@
+// 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/path_service.h"
+
+#if defined(OS_WIN)
+#include <windows.h>
+#include <shellapi.h>
+#include <shlobj.h>
+#endif
+
+#include "base/containers/hash_tables.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/logging.h"
+#include "base/synchronization/lock.h"
+#include "build/build_config.h"
+
+namespace base {
+
+bool PathProvider(int key, FilePath* result);
+
+#if defined(OS_WIN)
+bool PathProviderWin(int key, FilePath* result);
+#elif defined(OS_MACOSX)
+bool PathProviderMac(int key, FilePath* result);
+#elif defined(OS_ANDROID)
+bool PathProviderAndroid(int key, FilePath* result);
+#elif defined(OS_POSIX)
+// PathProviderPosix is the default path provider on POSIX OSes other than
+// Mac and Android.
+bool PathProviderPosix(int key, FilePath* result);
+#endif
+
+namespace {
+
+typedef hash_map<int, FilePath> PathMap;
+
+// We keep a linked list of providers. In a debug build we ensure that no two
+// providers claim overlapping keys.
+struct Provider {
+ PathService::ProviderFunc func;
+ struct Provider* next;
+#ifndef NDEBUG
+ int key_start;
+ int key_end;
+#endif
+ bool is_static;
+};
+
+Provider base_provider = {
+ PathProvider,
+ NULL,
+#ifndef NDEBUG
+ PATH_START,
+ PATH_END,
+#endif
+ true
+};
+
+#if defined(OS_WIN)
+Provider base_provider_win = {
+ PathProviderWin,
+ &base_provider,
+#ifndef NDEBUG
+ PATH_WIN_START,
+ PATH_WIN_END,
+#endif
+ true
+};
+#endif
+
+#if defined(OS_MACOSX)
+Provider base_provider_mac = {
+ PathProviderMac,
+ &base_provider,
+#ifndef NDEBUG
+ PATH_MAC_START,
+ PATH_MAC_END,
+#endif
+ true
+};
+#endif
+
+#if defined(OS_ANDROID)
+Provider base_provider_android = {
+ PathProviderAndroid,
+ &base_provider,
+#ifndef NDEBUG
+ PATH_ANDROID_START,
+ PATH_ANDROID_END,
+#endif
+ true
+};
+#endif
+
+#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
+Provider base_provider_posix = {
+ PathProviderPosix,
+ &base_provider,
+#ifndef NDEBUG
+ PATH_POSIX_START,
+ PATH_POSIX_END,
+#endif
+ true
+};
+#endif
+
+
+struct PathData {
+ Lock lock;
+ PathMap cache; // Cache mappings from path key to path value.
+ PathMap overrides; // Track path overrides.
+ Provider* providers; // Linked list of path service providers.
+ bool cache_disabled; // Don't use cache if true;
+
+ PathData() : cache_disabled(false) {
+#if defined(OS_WIN)
+ providers = &base_provider_win;
+#elif defined(OS_MACOSX)
+ providers = &base_provider_mac;
+#elif defined(OS_ANDROID)
+ providers = &base_provider_android;
+#elif defined(OS_POSIX)
+ providers = &base_provider_posix;
+#endif
+ }
+};
+
+static PathData* GetPathData() {
+ static auto* path_data = new PathData();
+ return path_data;
+}
+
+// Tries to find |key| in the cache. |path_data| should be locked by the caller!
+bool LockedGetFromCache(int key, const PathData* path_data, FilePath* result) {
+ if (path_data->cache_disabled)
+ return false;
+ // check for a cached version
+ PathMap::const_iterator it = path_data->cache.find(key);
+ if (it != path_data->cache.end()) {
+ *result = it->second;
+ return true;
+ }
+ return false;
+}
+
+// Tries to find |key| in the overrides map. |path_data| should be locked by the
+// caller!
+bool LockedGetFromOverrides(int key, PathData* path_data, FilePath* result) {
+ // check for an overridden version.
+ PathMap::const_iterator it = path_data->overrides.find(key);
+ if (it != path_data->overrides.end()) {
+ if (!path_data->cache_disabled)
+ path_data->cache[key] = it->second;
+ *result = it->second;
+ return true;
+ }
+ return false;
+}
+
+} // namespace
+
+// TODO(brettw): this function does not handle long paths (filename > MAX_PATH)
+// characters). This isn't supported very well by Windows right now, so it is
+// moot, but we should keep this in mind for the future.
+// static
+bool PathService::Get(int key, FilePath* result) {
+ PathData* path_data = GetPathData();
+ DCHECK(path_data);
+ DCHECK(result);
+ DCHECK_GE(key, DIR_CURRENT);
+
+ // special case the current directory because it can never be cached
+ if (key == DIR_CURRENT)
+ return GetCurrentDirectory(result);
+
+ Provider* provider = NULL;
+ {
+ AutoLock scoped_lock(path_data->lock);
+ if (LockedGetFromCache(key, path_data, result))
+ return true;
+
+ if (LockedGetFromOverrides(key, path_data, result))
+ return true;
+
+ // Get the beginning of the list while it is still locked.
+ provider = path_data->providers;
+ }
+
+ FilePath path;
+
+ // Iterating does not need the lock because only the list head might be
+ // modified on another thread.
+ while (provider) {
+ if (provider->func(key, &path))
+ break;
+ DCHECK(path.empty()) << "provider should not have modified path";
+ provider = provider->next;
+ }
+
+ if (path.empty())
+ return false;
+
+ if (path.ReferencesParent()) {
+ // Make sure path service never returns a path with ".." in it.
+ path = MakeAbsoluteFilePath(path);
+ if (path.empty())
+ return false;
+ }
+ *result = path;
+
+ AutoLock scoped_lock(path_data->lock);
+ if (!path_data->cache_disabled)
+ path_data->cache[key] = path;
+
+ return true;
+}
+
+// static
+bool PathService::Override(int key, const FilePath& path) {
+ // Just call the full function with true for the value of |create|, and
+ // assume that |path| may not be absolute yet.
+ return OverrideAndCreateIfNeeded(key, path, false, true);
+}
+
+// static
+bool PathService::OverrideAndCreateIfNeeded(int key,
+ const FilePath& path,
+ bool is_absolute,
+ bool create) {
+ PathData* path_data = GetPathData();
+ DCHECK(path_data);
+ DCHECK_GT(key, DIR_CURRENT) << "invalid path key";
+
+ FilePath file_path = path;
+
+ // For some locations this will fail if called from inside the sandbox there-
+ // fore we protect this call with a flag.
+ if (create) {
+ // Make sure the directory exists. We need to do this before we translate
+ // this to the absolute path because on POSIX, MakeAbsoluteFilePath fails
+ // if called on a non-existent path.
+ if (!PathExists(file_path) && !CreateDirectory(file_path))
+ return false;
+ }
+
+ // We need to have an absolute path.
+ if (!is_absolute) {
+ file_path = MakeAbsoluteFilePath(file_path);
+ if (file_path.empty())
+ return false;
+ }
+ DCHECK(file_path.IsAbsolute());
+
+ AutoLock scoped_lock(path_data->lock);
+
+ // Clear the cache now. Some of its entries could have depended
+ // on the value we are overriding, and are now out of sync with reality.
+ path_data->cache.clear();
+
+ path_data->overrides[key] = file_path;
+
+ return true;
+}
+
+// static
+bool PathService::RemoveOverride(int key) {
+ PathData* path_data = GetPathData();
+ DCHECK(path_data);
+
+ AutoLock scoped_lock(path_data->lock);
+
+ if (path_data->overrides.find(key) == path_data->overrides.end())
+ return false;
+
+ // Clear the cache now. Some of its entries could have depended on the value
+ // we are going to remove, and are now out of sync.
+ path_data->cache.clear();
+
+ path_data->overrides.erase(key);
+
+ return true;
+}
+
+// static
+void PathService::RegisterProvider(ProviderFunc func, int key_start,
+ int key_end) {
+ PathData* path_data = GetPathData();
+ DCHECK(path_data);
+ DCHECK_GT(key_end, key_start);
+
+ Provider* p;
+
+ p = new Provider;
+ p->is_static = false;
+ p->func = func;
+#ifndef NDEBUG
+ p->key_start = key_start;
+ p->key_end = key_end;
+#endif
+
+ AutoLock scoped_lock(path_data->lock);
+
+#ifndef NDEBUG
+ Provider *iter = path_data->providers;
+ while (iter) {
+ DCHECK(key_start >= iter->key_end || key_end <= iter->key_start) <<
+ "path provider collision";
+ iter = iter->next;
+ }
+#endif
+
+ p->next = path_data->providers;
+ path_data->providers = p;
+}
+
+// static
+void PathService::DisableCache() {
+ PathData* path_data = GetPathData();
+ DCHECK(path_data);
+
+ AutoLock scoped_lock(path_data->lock);
+ path_data->cache.clear();
+ path_data->cache_disabled = true;
+}
+
+} // namespace base
diff --git a/base/path_service.h b/base/path_service.h
new file mode 100644
index 0000000000..c7f1abe714
--- /dev/null
+++ b/base/path_service.h
@@ -0,0 +1,97 @@
+// 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 BASE_PATH_SERVICE_H_
+#define BASE_PATH_SERVICE_H_
+
+#include <string>
+
+#include "base/base_export.h"
+#include "base/base_paths.h"
+#include "base/gtest_prod_util.h"
+#include "build/build_config.h"
+
+namespace base {
+
+class FilePath;
+class ScopedPathOverride;
+
+// The path service is a global table mapping keys to file system paths. It is
+// OK to use this service from multiple threads.
+//
+class BASE_EXPORT PathService {
+ public:
+ // Retrieves a path to a special directory or file and places it into the
+ // string pointed to by 'path'. If you ask for a directory it is guaranteed
+ // to NOT have a path separator at the end. For example, "c:\windows\temp"
+ // Directories are also guaranteed to exist when this function succeeds.
+ //
+ // Returns true if the directory or file was successfully retrieved. On
+ // failure, 'path' will not be changed.
+ static bool Get(int key, FilePath* path);
+
+ // Overrides the path to a special directory or file. This cannot be used to
+ // change the value of DIR_CURRENT, but that should be obvious. Also, if the
+ // path specifies a directory that does not exist, the directory will be
+ // created by this method. This method returns true if successful.
+ //
+ // If the given path is relative, then it will be resolved against
+ // DIR_CURRENT.
+ //
+ // WARNING: Consumers of PathService::Get may expect paths to be constant
+ // over the lifetime of the app, so this method should be used with caution.
+ //
+ // Unit tests generally should use ScopedPathOverride instead. Overrides from
+ // one test should not carry over to another.
+ static bool Override(int key, const FilePath& path);
+
+ // This function does the same as PathService::Override but it takes extra
+ // parameters:
+ // - |is_absolute| indicates that |path| has already been expanded into an
+ // absolute path, otherwise MakeAbsoluteFilePath() will be used. This is
+ // useful to override paths that may not exist yet, since MakeAbsoluteFilePath
+ // fails for those. Note that MakeAbsoluteFilePath also expands symbolic
+ // links, even if path.IsAbsolute() is already true.
+ // - |create| guides whether the directory to be overriden must
+ // be created in case it doesn't exist already.
+ static bool OverrideAndCreateIfNeeded(int key,
+ const FilePath& path,
+ bool is_absolute,
+ bool create);
+
+ // To extend the set of supported keys, you can register a path provider,
+ // which is just a function mirroring PathService::Get. The ProviderFunc
+ // returns false if it cannot provide a non-empty path for the given key.
+ // Otherwise, true is returned.
+ //
+ // WARNING: This function could be called on any thread from which the
+ // PathService is used, so a the ProviderFunc MUST BE THREADSAFE.
+ //
+ typedef bool (*ProviderFunc)(int, FilePath*);
+
+ // Call to register a path provider. You must specify the range "[key_start,
+ // key_end)" of supported path keys.
+ static void RegisterProvider(ProviderFunc provider,
+ int key_start,
+ int key_end);
+
+ // Disable internal cache.
+ static void DisableCache();
+
+ private:
+ friend class ScopedPathOverride;
+ FRIEND_TEST_ALL_PREFIXES(PathServiceTest, RemoveOverride);
+
+ // Removes an override for a special directory or file. Returns true if there
+ // was an override to remove or false if none was present.
+ // NOTE: This function is intended to be used by tests only!
+ static bool RemoveOverride(int key);
+};
+
+} // namespace base
+
+// TODO(brettw) Convert all callers to using the base namespace and remove this.
+using base::PathService;
+
+#endif // BASE_PATH_SERVICE_H_
diff --git a/base/unguessable_token.cc b/base/unguessable_token.cc
new file mode 100644
index 0000000000..cd9830e686
--- /dev/null
+++ b/base/unguessable_token.cc
@@ -0,0 +1,41 @@
+// Copyright 2016 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/unguessable_token.h"
+
+#include "base/format_macros.h"
+#include "base/rand_util.h"
+#include "base/strings/stringprintf.h"
+
+namespace base {
+
+UnguessableToken::UnguessableToken(uint64_t high, uint64_t low)
+ : high_(high), low_(low) {}
+
+std::string UnguessableToken::ToString() const {
+ return base::StringPrintf("(%08" PRIX64 "%08" PRIX64 ")", high_, low_);
+}
+
+// static
+UnguessableToken UnguessableToken::Create() {
+ UnguessableToken token;
+ // Use base::RandBytes instead of crypto::RandBytes, because crypto calls the
+ // base version directly, and to prevent the dependency from base/ to crypto/.
+ base::RandBytes(&token, sizeof(token));
+ return token;
+}
+
+// static
+UnguessableToken UnguessableToken::Deserialize(uint64_t high, uint64_t low) {
+ // Receiving a zeroed out UnguessableToken from another process means that it
+ // was never initialized via Create(). Treat this case as a security issue.
+ DCHECK(!(high == 0 && low == 0));
+ return UnguessableToken(high, low);
+}
+
+std::ostream& operator<<(std::ostream& out, const UnguessableToken& token) {
+ return out << token.ToString();
+}
+
+} // namespace base
diff --git a/base/unguessable_token.h b/base/unguessable_token.h
new file mode 100644
index 0000000000..9f38783a3c
--- /dev/null
+++ b/base/unguessable_token.h
@@ -0,0 +1,103 @@
+// Copyright 2016 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_UNGUESSABLE_TOKEN_H_
+#define BASE_UNGUESSABLE_TOKEN_H_
+
+#include <stdint.h>
+#include <string.h>
+#include <iosfwd>
+#include <tuple>
+
+#include "base/base_export.h"
+#include "base/hash.h"
+#include "base/logging.h"
+
+namespace base {
+
+struct UnguessableTokenHash;
+
+// A UnguessableToken is an 128-bit token generated from a cryptographically
+// strong random source.
+//
+// UnguessableToken should be used when a sensitive ID needs to be unguessable,
+// and is shared across processes. It can be used as part of a larger aggregate
+// type, or as an ID in and of itself.
+//
+// Use Create() for creating new UnguessableTokens.
+//
+// NOTE: It is illegal to send empty UnguessableTokens across processes, and
+// sending/receiving empty tokens should be treated as a security issue.
+// If there is a valid scenario for sending "no token" across processes,
+// base::Optional should be used instead of an empty token.
+class BASE_EXPORT UnguessableToken {
+ public:
+ // Create a unique UnguessableToken.
+ static UnguessableToken Create();
+
+ // Return a UnguessableToken built from the high/low bytes provided.
+ // It should only be used in deserialization scenarios.
+ //
+ // NOTE: If the deserialized token is empty, it means that it was never
+ // initialized via Create(). This is a security issue, and should be handled.
+ static UnguessableToken Deserialize(uint64_t high, uint64_t low);
+
+ // Creates an empty UnguessableToken.
+ // Assign to it with Create() before using it.
+ constexpr UnguessableToken() = default;
+
+ // NOTE: Serializing an empty UnguessableToken is an illegal operation.
+ uint64_t GetHighForSerialization() const {
+ DCHECK(!is_empty());
+ return high_;
+ };
+
+ // NOTE: Serializing an empty UnguessableToken is an illegal operation.
+ uint64_t GetLowForSerialization() const {
+ DCHECK(!is_empty());
+ return low_;
+ }
+
+ bool is_empty() const { return high_ == 0 && low_ == 0; }
+
+ std::string ToString() const;
+
+ explicit operator bool() const { return !is_empty(); }
+
+ bool operator<(const UnguessableToken& other) const {
+ return std::tie(high_, low_) < std::tie(other.high_, other.low_);
+ }
+
+ bool operator==(const UnguessableToken& other) const {
+ return high_ == other.high_ && low_ == other.low_;
+ }
+
+ bool operator!=(const UnguessableToken& other) const {
+ return !(*this == other);
+ }
+
+ private:
+ friend struct UnguessableTokenHash;
+ UnguessableToken(uint64_t high, uint64_t low);
+
+ // Note: Two uint64_t are used instead of uint8_t[16], in order to have a
+ // simpler ToString() and is_empty().
+ uint64_t high_ = 0;
+ uint64_t low_ = 0;
+};
+
+BASE_EXPORT std::ostream& operator<<(std::ostream& out,
+ const UnguessableToken& token);
+
+// For use in std::unordered_map.
+struct UnguessableTokenHash {
+ size_t operator()(const base::UnguessableToken& token) const {
+ DCHECK(token);
+ return base::HashInts64(token.high_, token.low_);
+ }
+};
+
+} // namespace base
+
+#endif // BASE_UNGUESSABLE_TOKEN_H_
diff --git a/device/bluetooth/bluetooth_advertisement.cc b/device/bluetooth/bluetooth_advertisement.cc
new file mode 100644
index 0000000000..05b0e52d22
--- /dev/null
+++ b/device/bluetooth/bluetooth_advertisement.cc
@@ -0,0 +1,37 @@
+// Copyright 2015 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 "device/bluetooth/bluetooth_advertisement.h"
+
+namespace device {
+
+BluetoothAdvertisement::Data::Data(AdvertisementType type)
+ : type_(type), include_tx_power_(false) {
+}
+
+BluetoothAdvertisement::Data::~Data() {
+}
+
+BluetoothAdvertisement::Data::Data()
+ : type_(ADVERTISEMENT_TYPE_BROADCAST), include_tx_power_(false) {
+}
+
+void BluetoothAdvertisement::AddObserver(
+ BluetoothAdvertisement::Observer* observer) {
+ CHECK(observer);
+ observers_.AddObserver(observer);
+}
+
+void BluetoothAdvertisement::RemoveObserver(
+ BluetoothAdvertisement::Observer* observer) {
+ CHECK(observer);
+ observers_.RemoveObserver(observer);
+}
+
+BluetoothAdvertisement::BluetoothAdvertisement() {
+}
+BluetoothAdvertisement::~BluetoothAdvertisement() {
+}
+
+} // namespace device
diff --git a/device/bluetooth/bluetooth_advertisement.h b/device/bluetooth/bluetooth_advertisement.h
new file mode 100644
index 0000000000..412baa72ee
--- /dev/null
+++ b/device/bluetooth/bluetooth_advertisement.h
@@ -0,0 +1,152 @@
+// Copyright 2015 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 DEVICE_BLUETOOTH_BLUETOOTH_ADVERTISEMENT_H_
+#define DEVICE_BLUETOOTH_BLUETOOTH_ADVERTISEMENT_H_
+
+#include <stdint.h>
+
+#include <map>
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/observer_list.h"
+#include "device/bluetooth/bluetooth_export.h"
+
+namespace device {
+
+// BluetoothAdvertisement represents an advertisement which advertises over the
+// LE channel during its lifetime.
+class DEVICE_BLUETOOTH_EXPORT BluetoothAdvertisement
+ : public base::RefCounted<BluetoothAdvertisement> {
+ public:
+ // Possible types of error raised while registering or unregistering
+ // advertisements.
+ enum ErrorCode {
+ ERROR_UNSUPPORTED_PLATFORM, // Bluetooth advertisement not supported on
+ // current platform.
+ ERROR_ADVERTISEMENT_ALREADY_EXISTS, // An advertisement is already
+ // registered.
+ ERROR_ADVERTISEMENT_DOES_NOT_EXIST, // Unregistering an advertisement which
+ // is not registered.
+ ERROR_ADVERTISEMENT_INVALID_LENGTH, // Advertisement is not of a valid
+ // length.
+#if defined(OS_CHROMEOS) || defined(OS_LINUX)
+ ERROR_INVALID_ADVERTISEMENT_INTERVAL, // Advertisement interval specified
+ // is out of valid range.
+#endif
+ INVALID_ADVERTISEMENT_ERROR_CODE
+ };
+
+ // Type of advertisement.
+ enum AdvertisementType {
+ // This advertises with the type set to ADV_NONCONN_IND, which indicates
+ // to receivers that our device is not connectable.
+ ADVERTISEMENT_TYPE_BROADCAST,
+ // This advertises with the type set to ADV_IND or ADV_SCAN_IND, which
+ // indicates to receivers that our device is connectable.
+ ADVERTISEMENT_TYPE_PERIPHERAL
+ };
+
+ using UUIDList = std::vector<std::string>;
+ using ManufacturerData = std::map<uint16_t, std::vector<uint8_t>>;
+ using ServiceData = std::map<std::string, std::vector<uint8_t>>;
+
+ // Structure that holds the data for an advertisement.
+ class DEVICE_BLUETOOTH_EXPORT Data {
+ public:
+ explicit Data(AdvertisementType type);
+ ~Data();
+
+ AdvertisementType type() { return type_; }
+ std::unique_ptr<UUIDList> service_uuids() {
+ return std::move(service_uuids_);
+ }
+ std::unique_ptr<ManufacturerData> manufacturer_data() {
+ return std::move(manufacturer_data_);
+ }
+ std::unique_ptr<UUIDList> solicit_uuids() {
+ return std::move(solicit_uuids_);
+ }
+ std::unique_ptr<ServiceData> service_data() {
+ return std::move(service_data_);
+ }
+
+ void set_service_uuids(std::unique_ptr<UUIDList> service_uuids) {
+ service_uuids_ = std::move(service_uuids);
+ }
+ void set_manufacturer_data(
+ std::unique_ptr<ManufacturerData> manufacturer_data) {
+ manufacturer_data_ = std::move(manufacturer_data);
+ }
+ void set_solicit_uuids(std::unique_ptr<UUIDList> solicit_uuids) {
+ solicit_uuids_ = std::move(solicit_uuids);
+ }
+ void set_service_data(std::unique_ptr<ServiceData> service_data) {
+ service_data_ = std::move(service_data);
+ }
+
+ void set_include_tx_power(bool include_tx_power) {
+ include_tx_power_ = include_tx_power;
+ }
+
+ private:
+ Data();
+
+ AdvertisementType type_;
+ std::unique_ptr<UUIDList> service_uuids_;
+ std::unique_ptr<ManufacturerData> manufacturer_data_;
+ std::unique_ptr<UUIDList> solicit_uuids_;
+ std::unique_ptr<ServiceData> service_data_;
+ bool include_tx_power_;
+
+ DISALLOW_COPY_AND_ASSIGN(Data);
+ };
+
+ // Interface for observing changes to this advertisement.
+ class Observer {
+ public:
+ virtual ~Observer() {}
+
+ // Called when this advertisement is released and is no longer advertising.
+ virtual void AdvertisementReleased(
+ BluetoothAdvertisement* advertisement) = 0;
+ };
+
+ // Adds and removes observers for events for this advertisement.
+ void AddObserver(BluetoothAdvertisement::Observer* observer);
+ void RemoveObserver(BluetoothAdvertisement::Observer* observer);
+
+ // Unregisters this advertisement. Called on destruction of this object
+ // automatically but can be called directly to explicitly unregister this
+ // object.
+ using SuccessCallback = base::Closure;
+ using ErrorCallback = base::Callback<void(ErrorCode)>;
+ virtual void Unregister(const SuccessCallback& success_callback,
+ const ErrorCallback& error_callback) = 0;
+
+ protected:
+ friend class base::RefCounted<BluetoothAdvertisement>;
+
+ BluetoothAdvertisement();
+
+ // The destructor will unregister this advertisement.
+ virtual ~BluetoothAdvertisement();
+
+ // List of observers interested in event notifications from us. Objects in
+ // |observers_| are expected to outlive a BluetoothAdvertisement object.
+ base::ObserverList<BluetoothAdvertisement::Observer> observers_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(BluetoothAdvertisement);
+};
+
+} // namespace device
+
+#endif // DEVICE_BLUETOOTH_BLUETOOTH_ADVERTISEMENT_H_
diff --git a/device/bluetooth/bluetooth_common.h b/device/bluetooth/bluetooth_common.h
new file mode 100644
index 0000000000..6045980f9b
--- /dev/null
+++ b/device/bluetooth/bluetooth_common.h
@@ -0,0 +1,49 @@
+// Copyright 2016 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 DEVICE_BLUETOOTH_BLUETOOTH_TYPES_H_
+#define DEVICE_BLUETOOTH_BLUETOOTH_TYPES_H_
+
+#include "device/bluetooth/bluetooth_export.h"
+
+// This file is for enums and small types common to several
+// parts of bluetooth.
+
+namespace device {
+
+// Devices and adapters can support a number of transports,
+// and bluetooth hosts can scan for devices based on the
+// transports they support.
+enum BluetoothTransport : uint8_t {
+ BLUETOOTH_TRANSPORT_INVALID = 0x00,
+ // Valid transports are given as a bitset.
+ BLUETOOTH_TRANSPORT_CLASSIC = 0x01,
+ BLUETOOTH_TRANSPORT_LE = 0x02,
+ BLUETOOTH_TRANSPORT_DUAL =
+ (BLUETOOTH_TRANSPORT_CLASSIC | BLUETOOTH_TRANSPORT_LE)
+};
+
+// Possible values that may be returned by BluetoothDevice::GetDeviceType(),
+// representing different types of bluetooth device that we support or are aware
+// of decoded from the bluetooth class information.
+enum class BluetoothDeviceType {
+ UNKNOWN,
+ COMPUTER,
+ PHONE,
+ MODEM,
+ AUDIO,
+ CAR_AUDIO,
+ VIDEO,
+ PERIPHERAL,
+ JOYSTICK,
+ GAMEPAD,
+ KEYBOARD,
+ MOUSE,
+ TABLET,
+ KEYBOARD_MOUSE_COMBO
+};
+
+} // namespace device
+
+#endif // DEVICE_BLUETOOTH_BLUETOOTH_TYPES_H_
diff --git a/device/bluetooth/bluetooth_export.h b/device/bluetooth/bluetooth_export.h
new file mode 100644
index 0000000000..90cc58cdb0
--- /dev/null
+++ b/device/bluetooth/bluetooth_export.h
@@ -0,0 +1,28 @@
+// Copyright 2014 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 DEVICE_BLUETOOTH_DEVICE_BLUETOOTH_EXPORT_H_
+#define DEVICE_BLUETOOTH_DEVICE_BLUETOOTH_EXPORT_H_
+
+#if defined(COMPONENT_BUILD) && defined(WIN32)
+
+#if defined(DEVICE_BLUETOOTH_IMPLEMENTATION)
+#define DEVICE_BLUETOOTH_EXPORT __declspec(dllexport)
+#else
+#define DEVICE_BLUETOOTH_EXPORT __declspec(dllimport)
+#endif
+
+#elif defined(COMPONENT_BUILD) && !defined(WIN32)
+
+#if defined(DEVICE_BLUETOOTH_IMPLEMENTATION)
+#define DEVICE_BLUETOOTH_EXPORT __attribute__((visibility("default")))
+#else
+#define DEVICE_BLUETOOTH_EXPORT
+#endif
+
+#else
+#define DEVICE_BLUETOOTH_EXPORT
+#endif
+
+#endif // DEVICE_BLUETOOTH_DEVICE_BLUETOOTH_EXPORT_H_
diff --git a/device/bluetooth/bluetooth_uuid.cc b/device/bluetooth/bluetooth_uuid.cc
new file mode 100644
index 0000000000..b35094deba
--- /dev/null
+++ b/device/bluetooth/bluetooth_uuid.cc
@@ -0,0 +1,98 @@
+// Copyright 2014 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 "device/bluetooth/bluetooth_uuid.h"
+
+#include <stddef.h>
+
+#include "base/logging.h"
+#include "base/strings/string_util.h"
+
+namespace device {
+
+namespace {
+
+const char kCommonUuidPostfix[] = "-0000-1000-8000-00805f9b34fb";
+const char kCommonUuidPrefix[] = "0000";
+
+// Returns the canonical, 128-bit canonical, and the format of the UUID
+// in |canonical|, |canonical_128|, and |format| based on |uuid|.
+void GetCanonicalUuid(std::string uuid,
+ std::string* canonical,
+ std::string* canonical_128,
+ BluetoothUUID::Format* format) {
+ // Initialize the values for the failure case.
+ canonical->clear();
+ canonical_128->clear();
+ *format = BluetoothUUID::kFormatInvalid;
+
+ if (uuid.empty())
+ return;
+
+ if (uuid.size() < 11 &&
+ base::StartsWith(uuid, "0x", base::CompareCase::SENSITIVE)) {
+ uuid = uuid.substr(2);
+ }
+
+ if (!(uuid.size() == 4 || uuid.size() == 8 || uuid.size() == 36))
+ return;
+
+ for (size_t i = 0; i < uuid.size(); ++i) {
+ if (i == 8 || i == 13 || i == 18 || i == 23) {
+ if (uuid[i] != '-')
+ return;
+ } else {
+ if (!base::IsHexDigit(uuid[i]))
+ return;
+ uuid[i] = base::ToLowerASCII(uuid[i]);
+ }
+ }
+
+ canonical->assign(uuid);
+ if (uuid.size() == 4) {
+ canonical_128->assign(kCommonUuidPrefix + uuid + kCommonUuidPostfix);
+ *format = BluetoothUUID::kFormat16Bit;
+ } else if (uuid.size() == 8) {
+ canonical_128->assign(uuid + kCommonUuidPostfix);
+ *format = BluetoothUUID::kFormat32Bit;
+ } else {
+ canonical_128->assign(uuid);
+ *format = BluetoothUUID::kFormat128Bit;
+ }
+}
+
+} // namespace
+
+
+BluetoothUUID::BluetoothUUID(const std::string& uuid) {
+ GetCanonicalUuid(uuid, &value_, &canonical_value_, &format_);
+}
+
+BluetoothUUID::BluetoothUUID() : format_(kFormatInvalid) {
+}
+
+BluetoothUUID::~BluetoothUUID() {
+}
+
+bool BluetoothUUID::IsValid() const {
+ return format_ != kFormatInvalid;
+}
+
+bool BluetoothUUID::operator<(const BluetoothUUID& uuid) const {
+ return canonical_value_ < uuid.canonical_value_;
+}
+
+bool BluetoothUUID::operator==(const BluetoothUUID& uuid) const {
+ return canonical_value_ == uuid.canonical_value_;
+}
+
+bool BluetoothUUID::operator!=(const BluetoothUUID& uuid) const {
+ return canonical_value_ != uuid.canonical_value_;
+}
+
+void PrintTo(const BluetoothUUID& uuid, std::ostream* out) {
+ *out << uuid.canonical_value();
+}
+
+} // namespace device
diff --git a/device/bluetooth/bluetooth_uuid.h b/device/bluetooth/bluetooth_uuid.h
new file mode 100644
index 0000000000..8487f6a2da
--- /dev/null
+++ b/device/bluetooth/bluetooth_uuid.h
@@ -0,0 +1,106 @@
+// Copyright 2014 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 DEVICE_BLUETOOTH_BLUETOOTH_UUID_H_
+#define DEVICE_BLUETOOTH_BLUETOOTH_UUID_H_
+
+#include <string>
+
+#include "device/bluetooth/bluetooth_export.h"
+
+namespace device {
+
+// Opaque wrapper around a Bluetooth UUID. Instances of UUID represent the
+// 128-bit universally unique identifiers (UUIDs) of profiles and attributes
+// used in Bluetooth based communication, such as a peripheral's services,
+// characteristics, and characteristic descriptors. An instance are
+// constructed using a string representing 16, 32, or 128 bit UUID formats.
+class DEVICE_BLUETOOTH_EXPORT BluetoothUUID {
+ public:
+ // Possible representation formats used during construction.
+ enum Format {
+ kFormatInvalid,
+ kFormat16Bit,
+ kFormat32Bit,
+ kFormat128Bit
+ };
+
+ // Single argument constructor. |uuid| can be a 16, 32, or 128 bit UUID
+ // represented as a 4, 8, or 36 character string with the following
+ // formats:
+ // xxxx
+ // 0xxxxx
+ // xxxxxxxx
+ // 0xxxxxxxxx
+ // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
+ //
+ // 16 and 32 bit UUIDs will be internally converted to a 128 bit UUID using
+ // the base UUID defined in the Bluetooth specification, hence custom UUIDs
+ // should be provided in the 128-bit format. If |uuid| is in an unsupported
+ // format, the result might be invalid. Use IsValid to check for validity
+ // after construction.
+ explicit BluetoothUUID(const std::string& uuid);
+
+ // Default constructor does nothing. Since BluetoothUUID is copyable, this
+ // constructor is useful for initializing member variables and assigning a
+ // value to them later. The default constructor will initialize an invalid
+ // UUID by definition and the string accessors will return an empty string.
+ BluetoothUUID();
+ virtual ~BluetoothUUID();
+
+ // Returns true, if the UUID is in a valid canonical format.
+ bool IsValid() const;
+
+ // Returns the representation format of the UUID. This reflects the format
+ // that was provided during construction.
+ Format format() const { return format_; }
+
+ // Returns the value of the UUID as a string. The representation format is
+ // based on what was passed in during construction. For the supported sizes,
+ // this representation can have the following formats:
+ // - 16 bit: xxxx
+ // - 32 bit: xxxxxxxx
+ // - 128 bit: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
+ // where x is a lowercase hex digit.
+ const std::string& value() const { return value_; }
+
+ // Returns the underlying 128-bit value as a string in the following format:
+ // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
+ // where x is a lowercase hex digit.
+ const std::string& canonical_value() const { return canonical_value_; }
+
+ // Permit sufficient comparison to allow a UUID to be used as a key in a
+ // std::map.
+ bool operator<(const BluetoothUUID& uuid) const;
+
+ // Equality operators.
+ bool operator==(const BluetoothUUID& uuid) const;
+ bool operator!=(const BluetoothUUID& uuid) const;
+
+ private:
+ // String representation of the UUID that was used during construction. For
+ // the supported sizes, this representation can have the following formats:
+ // - 16 bit: xxxx
+ // - 32 bit: xxxxxxxx
+ // - 128 bit: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
+ Format format_;
+ std::string value_;
+
+ // The 128-bit string representation of the UUID.
+ std::string canonical_value_;
+};
+
+// This is required by gtest to print a readable output on test failures.
+void DEVICE_BLUETOOTH_EXPORT
+PrintTo(const BluetoothUUID& uuid, std::ostream* out);
+
+struct BluetoothUUIDHash {
+ size_t operator()(const device::BluetoothUUID& uuid) const {
+ return std::hash<std::string>()(uuid.canonical_value());
+ }
+};
+
+} // namespace device
+
+#endif // DEVICE_BLUETOOTH_BLUETOOTH_UUID_H_
diff --git a/device/bluetooth/bluez/bluetooth_service_attribute_value_bluez.cc b/device/bluetooth/bluez/bluetooth_service_attribute_value_bluez.cc
new file mode 100644
index 0000000000..ee6cbf6112
--- /dev/null
+++ b/device/bluetooth/bluez/bluetooth_service_attribute_value_bluez.cc
@@ -0,0 +1,54 @@
+// Copyright 2016 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 "device/bluetooth/bluez/bluetooth_service_attribute_value_bluez.h"
+
+#include <utility>
+
+#include "base/logging.h"
+#include "base/memory/ptr_util.h"
+
+namespace bluez {
+
+BluetoothServiceAttributeValueBlueZ::BluetoothServiceAttributeValueBlueZ()
+ : type_(NULLTYPE), size_(0), value_(base::Value::CreateNullValue()) {}
+
+BluetoothServiceAttributeValueBlueZ::BluetoothServiceAttributeValueBlueZ(
+ Type type,
+ size_t size,
+ std::unique_ptr<base::Value> value)
+ : type_(type), size_(size), value_(std::move(value)) {
+ CHECK_NE(type, SEQUENCE);
+}
+
+BluetoothServiceAttributeValueBlueZ::BluetoothServiceAttributeValueBlueZ(
+ std::unique_ptr<Sequence> sequence)
+ : type_(SEQUENCE),
+ size_(sequence->size()),
+ sequence_(std::move(sequence)) {}
+
+BluetoothServiceAttributeValueBlueZ::BluetoothServiceAttributeValueBlueZ(
+ const BluetoothServiceAttributeValueBlueZ& attribute) {
+ *this = attribute;
+}
+
+BluetoothServiceAttributeValueBlueZ& BluetoothServiceAttributeValueBlueZ::
+operator=(const BluetoothServiceAttributeValueBlueZ& attribute) {
+ if (this != &attribute) {
+ type_ = attribute.type_;
+ size_ = attribute.size_;
+ if (attribute.type_ == SEQUENCE) {
+ value_ = nullptr;
+ sequence_ = base::MakeUnique<Sequence>(*attribute.sequence_);
+ } else {
+ value_ = attribute.value_->CreateDeepCopy();
+ sequence_ = nullptr;
+ }
+ }
+ return *this;
+}
+
+BluetoothServiceAttributeValueBlueZ::~BluetoothServiceAttributeValueBlueZ() {}
+
+} // namespace bluez
diff --git a/device/bluetooth/bluez/bluetooth_service_attribute_value_bluez.h b/device/bluetooth/bluez/bluetooth_service_attribute_value_bluez.h
new file mode 100644
index 0000000000..fdd291a5f1
--- /dev/null
+++ b/device/bluetooth/bluez/bluetooth_service_attribute_value_bluez.h
@@ -0,0 +1,59 @@
+// Copyright 2016 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 DEVICE_BLUETOOTH_BLUEZ_BLUETOOTH_SERVICE_ATTRIBUTE_VALUE_BLUEZ_H_
+#define DEVICE_BLUETOOTH_BLUEZ_BLUETOOTH_SERVICE_ATTRIBUTE_VALUE_BLUEZ_H_
+
+#include <cstddef>
+#include <memory>
+#include <vector>
+
+#include "base/values.h"
+#include "device/bluetooth/bluetooth_export.h"
+
+namespace bluez {
+
+// This class contains a Bluetooth service attribute. A service attribute is
+// defined by the following fields,
+// type: This is the type of the attribute. Along with being any of the
+// fixed types, an attribute can also be of type sequence, which means
+// that it contains an array of other attributes.
+// size: This is the size of the attribute. This can be variable for each type.
+// For example, a UUID can have the sizes, 2, 4 or 16 bytes.
+// value: This is the raw value of the attribute. For example, for a UUID, it
+// will be the string representation of the UUID. For a sequence, it
+// will be an array of other attributes.
+class DEVICE_BLUETOOTH_EXPORT BluetoothServiceAttributeValueBlueZ {
+ public:
+ enum Type { NULLTYPE = 0, UINT, INT, UUID, STRING, BOOL, SEQUENCE, URL };
+
+ using Sequence = std::vector<BluetoothServiceAttributeValueBlueZ>;
+
+ BluetoothServiceAttributeValueBlueZ();
+ BluetoothServiceAttributeValueBlueZ(Type type,
+ size_t size,
+ std::unique_ptr<base::Value> value);
+ explicit BluetoothServiceAttributeValueBlueZ(
+ std::unique_ptr<Sequence> sequence);
+ BluetoothServiceAttributeValueBlueZ(
+ const BluetoothServiceAttributeValueBlueZ& attribute);
+ BluetoothServiceAttributeValueBlueZ& operator=(
+ const BluetoothServiceAttributeValueBlueZ& attribute);
+ ~BluetoothServiceAttributeValueBlueZ();
+
+ Type type() const { return type_; }
+ size_t size() const { return size_; }
+ const Sequence& sequence() const { return *sequence_.get(); }
+ const base::Value& value() const { return *value_.get(); }
+
+ private:
+ Type type_;
+ size_t size_;
+ std::unique_ptr<base::Value> value_;
+ std::unique_ptr<Sequence> sequence_;
+};
+
+} // namespace bluez
+
+#endif // DEVICE_BLUETOOTH_BLUEZ_BLUETOOTH_SERVICE_ATTRIBUTE_VALUE_BLUEZ_H_
diff --git a/libchrome_tools/patch/path_service.patch b/libchrome_tools/patch/path_service.patch
index f831d984e7..75b30dc044 100644
--- a/libchrome_tools/patch/path_service.patch
+++ b/libchrome_tools/patch/path_service.patch
@@ -1,23 +1,36 @@
-# Currently, PathService is not available on libchrome.
+# Several paths are not supported in PathService by libchrome.
---- a/base/files/file_util_posix.cc
-+++ b/base/files/file_util_posix.cc
-@@ -29,7 +29,6 @@
+--- a/base/base_paths_posix.cc
++++ b/base/base_paths_posix.cc
+@@ -19,7 +19,8 @@
+ #include "base/files/file_path.h"
+ #include "base/files/file_util.h"
#include "base/logging.h"
- #include "base/macros.h"
- #include "base/memory/singleton.h"
--#include "base/path_service.h"
- #include "base/posix/eintr_wrapper.h"
- #include "base/stl_util.h"
- #include "base/strings/string_split.h"
-@@ -50,6 +49,7 @@
- #if defined(OS_ANDROID)
- #include "base/android/content_uri_utils.h"
- #include "base/os_compat_android.h"
-+#include "base/path_service.h"
+-#include "base/nix/xdg_util.h"
++// Unused, and this file is not ported to libchrome.
++// #include "base/nix/xdg_util.h"
+ #include "base/path_service.h"
+ #include "base/process/process_metrics.h"
+ #include "build/build_config.h"
+@@ -77,6 +78,8 @@ bool PathProviderPosix(int key, FilePath
+ return true;
#endif
-
- #if !defined(OS_IOS)
+ }
++// Following paths are not supported in libchrome/libmojo.
++#if 0
+ case DIR_SOURCE_ROOT: {
+ // Allow passing this in the environment, for more flexibility in build
+ // tree configurations (sub-project builds, gyp --output_dir, etc.)
+@@ -112,6 +115,7 @@ bool PathProviderPosix(int key, FilePath
+ *result = cache_dir;
+ return true;
+ }
++#endif
+ }
+ return false;
+ }
+--- a/base/files/file_util_posix.cc
++++ b/base/files/file_util_posix.cc
@@ -533,6 +533,8 @@ bool GetTempDir(FilePath* path) {
} else {
#if defined(OS_ANDROID)
@@ -29,64 +42,41 @@
#endif
--- a/base/json/json_reader_unittest.cc
+++ b/base/json/json_reader_unittest.cc
-@@ -8,11 +8,14 @@
-
- #include <memory>
-
-+#if !defined(__ANDROID__) && !defined(__ANDROID_HOST__)
- #include "base/base_paths.h"
-+#include "base/path_service.h"
-+#endif
-+
- #include "base/files/file_util.h"
- #include "base/logging.h"
- #include "base/macros.h"
--#include "base/path_service.h"
- #include "base/strings/string_piece.h"
- #include "base/strings/utf_string_conversions.h"
- #include "base/values.h"
-@@ -567,6 +570,7 @@ TEST(JSONReaderTest, Reading) {
+@@ -567,7 +567,7 @@ TEST(JSONReaderTest, Reading) {
}
}
-+#if !defined(__ANDROID__) && !defined(__ANDROID_HOST__)
- TEST(JSONReaderTest, ReadFromFile) {
+-TEST(JSONReaderTest, ReadFromFile) {
++TEST(JSONReaderTest, DISABLED_ReadFromFile) {
FilePath path;
ASSERT_TRUE(PathService::Get(base::DIR_TEST_DATA, &path));
-@@ -581,6 +585,7 @@ TEST(JSONReaderTest, ReadFromFile) {
- ASSERT_TRUE(root) << reader.GetErrorMessage();
- EXPECT_TRUE(root->IsType(Value::Type::DICTIONARY));
- }
-+#endif // !__ANDROID__ && !__ANDROID_HOST__
-
- // Tests that the root of a JSON object can be deleted safely while its
- // children outlive it.
+ path = path.AppendASCII("json");
--- a/base/json/json_value_serializer_unittest.cc
+++ b/base/json/json_value_serializer_unittest.cc
-@@ -11,7 +11,9 @@
- #include "base/json/json_reader.h"
- #include "base/json/json_string_value_serializer.h"
- #include "base/json/json_writer.h"
-+#if !defined(__ANDROID__) && !defined(__ANDROID_HOST__)
- #include "base/path_service.h"
-+#endif
- #include "base/strings/string_piece.h"
- #include "base/strings/string_util.h"
- #include "base/strings/utf_string_conversions.h"
-@@ -395,6 +397,8 @@ TEST(JSONValueSerializerTest, JSONReader
- ASSERT_FALSE(JSONReader::Read("/ * * / [1]"));
- }
+@@ -402,7 +402,7 @@ class JSONFileValueSerializerTest : publ
+ ScopedTempDir temp_dir_;
+ };
-+#if !defined(__ANDROID__) && !defined(__ANDROID_HOST__)
-+
- class JSONFileValueSerializerTest : public testing::Test {
- protected:
- void SetUp() override { ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); }
-@@ -481,6 +485,7 @@ TEST_F(JSONFileValueSerializerTest, NoWh
- std::unique_ptr<Value> root = deserializer.Deserialize(nullptr, nullptr);
- ASSERT_TRUE(root);
+-TEST_F(JSONFileValueSerializerTest, Roundtrip) {
++TEST_F(JSONFileValueSerializerTest, DISABLED_Roundtrip) {
+ FilePath original_file_path;
+ ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &original_file_path));
+ original_file_path = original_file_path.AppendASCII("serializer_test.json");
+@@ -445,7 +445,7 @@ TEST_F(JSONFileValueSerializerTest, Roun
+ EXPECT_TRUE(DeleteFile(written_file_path, false));
}
-+#endif // !__ANDROID__ && !__ANDROID_HOST__
- } // namespace
+-TEST_F(JSONFileValueSerializerTest, RoundtripNested) {
++TEST_F(JSONFileValueSerializerTest, DISABLED_RoundtripNested) {
+ FilePath original_file_path;
+ ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &original_file_path));
+ original_file_path =
+@@ -471,7 +471,7 @@ TEST_F(JSONFileValueSerializerTest, Roun
+ EXPECT_TRUE(DeleteFile(written_file_path, false));
+ }
+-TEST_F(JSONFileValueSerializerTest, NoWhitespace) {
++TEST_F(JSONFileValueSerializerTest, DISABLED_NoWhitespace) {
+ FilePath source_file_path;
+ ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &source_file_path));
+ source_file_path =
diff --git a/ui/gfx/geometry/insets.cc b/ui/gfx/geometry/insets.cc
new file mode 100644
index 0000000000..9acc6e0fc1
--- /dev/null
+++ b/ui/gfx/geometry/insets.cc
@@ -0,0 +1,22 @@
+// 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.
+
+#include "ui/gfx/geometry/insets.h"
+
+#include "base/strings/stringprintf.h"
+#include "ui/gfx/geometry/vector2d.h"
+
+namespace gfx {
+
+std::string Insets::ToString() const {
+ // Print members in the same order of the constructor parameters.
+ return base::StringPrintf("%d,%d,%d,%d", top(), left(), bottom(), right());
+}
+
+Insets Insets::Offset(const gfx::Vector2d& vector) const {
+ return gfx::Insets(top() + vector.y(), left() + vector.x(),
+ bottom() - vector.y(), right() - vector.x());
+}
+
+} // namespace gfx
diff --git a/ui/gfx/geometry/insets.h b/ui/gfx/geometry/insets.h
new file mode 100644
index 0000000000..a88bae3e42
--- /dev/null
+++ b/ui/gfx/geometry/insets.h
@@ -0,0 +1,130 @@
+// 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_GEOMETRY_INSETS_H_
+#define UI_GFX_GEOMETRY_INSETS_H_
+
+#include <string>
+
+#include "ui/gfx/geometry/insets_f.h"
+#include "ui/gfx/gfx_export.h"
+
+namespace gfx {
+
+class Vector2d;
+
+// Represents the widths of the four borders or margins of an unspecified
+// rectangle. An Insets stores the thickness of the top, left, bottom and right
+// edges, without storing the actual size and position of the rectangle itself.
+//
+// This can be used to represent a space within a rectangle, by "shrinking" the
+// rectangle by the inset amount on all four sides. Alternatively, it can
+// represent a border that has a different thickness on each side.
+class GFX_EXPORT Insets {
+ public:
+ constexpr Insets() : top_(0), left_(0), bottom_(0), right_(0) {}
+ constexpr explicit Insets(int all)
+ : top_(all), left_(all), bottom_(all), right_(all) {}
+ constexpr Insets(int vertical, int horizontal)
+ : top_(vertical),
+ left_(horizontal),
+ bottom_(vertical),
+ right_(horizontal) {}
+ constexpr Insets(int top, int left, int bottom, int right)
+ : top_(top), left_(left), bottom_(bottom), right_(right) {}
+
+ constexpr int top() const { return top_; }
+ constexpr int left() const { return left_; }
+ constexpr int bottom() const { return bottom_; }
+ constexpr int right() const { return right_; }
+
+ // Returns the total width taken up by the insets, which is the sum of the
+ // left and right insets.
+ constexpr int width() const { return left_ + right_; }
+
+ // Returns the total height taken up by the insets, which is the sum of the
+ // top and bottom insets.
+ constexpr int height() const { return top_ + bottom_; }
+
+ // Returns true if the insets are empty.
+ bool IsEmpty() const { return width() == 0 && height() == 0; }
+
+ void Set(int top, int left, int bottom, int right) {
+ top_ = top;
+ left_ = left;
+ bottom_ = bottom;
+ right_ = right;
+ }
+
+ bool operator==(const Insets& insets) const {
+ return top_ == insets.top_ && left_ == insets.left_ &&
+ bottom_ == insets.bottom_ && right_ == insets.right_;
+ }
+
+ bool operator!=(const Insets& insets) const {
+ return !(*this == insets);
+ }
+
+ void operator+=(const Insets& insets) {
+ top_ += insets.top_;
+ left_ += insets.left_;
+ bottom_ += insets.bottom_;
+ right_ += insets.right_;
+ }
+
+ void operator-=(const Insets& insets) {
+ top_ -= insets.top_;
+ left_ -= insets.left_;
+ bottom_ -= insets.bottom_;
+ right_ -= insets.right_;
+ }
+
+ Insets operator-() const {
+ return Insets(-top_, -left_, -bottom_, -right_);
+ }
+
+ Insets Scale(float scale) const {
+ return Scale(scale, scale);
+ }
+
+ Insets Scale(float x_scale, float y_scale) const {
+ return Insets(static_cast<int>(top() * y_scale),
+ static_cast<int>(left() * x_scale),
+ static_cast<int>(bottom() * y_scale),
+ static_cast<int>(right() * x_scale));
+ }
+
+ // Adjusts the vertical and horizontal dimensions by the values described in
+ // |vector|. Offsetting insets before applying to a rectangle would be
+ // equivalent to offseting the rectangle then applying the insets.
+ Insets Offset(const gfx::Vector2d& vector) const;
+
+ operator InsetsF() const {
+ return InsetsF(static_cast<float>(top()), static_cast<float>(left()),
+ static_cast<float>(bottom()), static_cast<float>(right()));
+ }
+
+ // Returns a string representation of the insets.
+ std::string ToString() const;
+
+ private:
+ int top_;
+ int left_;
+ int bottom_;
+ int right_;
+};
+
+inline Insets operator+(Insets lhs, const Insets& rhs) {
+ lhs += rhs;
+ return lhs;
+}
+
+inline Insets operator-(Insets lhs, const Insets& rhs) {
+ lhs -= rhs;
+ return lhs;
+}
+
+} // namespace gfx
+
+#endif // UI_GFX_GEOMETRY_INSETS_H_
diff --git a/ui/gfx/geometry/insets_f.cc b/ui/gfx/geometry/insets_f.cc
new file mode 100644
index 0000000000..c1bc27ec52
--- /dev/null
+++ b/ui/gfx/geometry/insets_f.cc
@@ -0,0 +1,16 @@
+// 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/geometry/insets_f.h"
+
+#include "base/strings/stringprintf.h"
+
+namespace gfx {
+
+std::string InsetsF::ToString() const {
+ // Print members in the same order of the constructor parameters.
+ return base::StringPrintf("%f,%f,%f,%f", top(), left(), bottom(), right());
+}
+
+} // namespace gfx
diff --git a/ui/gfx/geometry/insets_f.h b/ui/gfx/geometry/insets_f.h
new file mode 100644
index 0000000000..30c2ff2b79
--- /dev/null
+++ b/ui/gfx/geometry/insets_f.h
@@ -0,0 +1,100 @@
+// 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_GEOMETRY_INSETS_F_H_
+#define UI_GFX_GEOMETRY_INSETS_F_H_
+
+#include <string>
+
+#include "ui/gfx/gfx_export.h"
+
+namespace gfx {
+
+// A floating point version of gfx::Insets.
+class GFX_EXPORT InsetsF {
+ public:
+ constexpr InsetsF() : top_(0.f), left_(0.f), bottom_(0.f), right_(0.f) {}
+ constexpr explicit InsetsF(float all)
+ : top_(all), left_(all), bottom_(all), right_(all) {}
+ constexpr InsetsF(float vertical, float horizontal)
+ : top_(vertical),
+ left_(horizontal),
+ bottom_(vertical),
+ right_(horizontal) {}
+ constexpr InsetsF(float top, float left, float bottom, float right)
+ : top_(top), left_(left), bottom_(bottom), right_(right) {}
+
+ constexpr float top() const { return top_; }
+ constexpr float left() const { return left_; }
+ constexpr float bottom() const { return bottom_; }
+ constexpr float right() const { return right_; }
+
+ // Returns the total width taken up by the insets, which is the sum of the
+ // left and right insets.
+ constexpr float width() const { return left_ + right_; }
+
+ // Returns the total height taken up by the insets, which is the sum of the
+ // top and bottom insets.
+ constexpr float height() const { return top_ + bottom_; }
+
+ // Returns true if the insets are empty.
+ bool IsEmpty() const { return width() == 0.f && height() == 0.f; }
+
+ void Set(float top, float left, float bottom, float right) {
+ top_ = top;
+ left_ = left;
+ bottom_ = bottom;
+ right_ = right;
+ }
+
+ bool operator==(const InsetsF& insets) const {
+ return top_ == insets.top_ && left_ == insets.left_ &&
+ bottom_ == insets.bottom_ && right_ == insets.right_;
+ }
+
+ bool operator!=(const InsetsF& insets) const {
+ return !(*this == insets);
+ }
+
+ void operator+=(const InsetsF& insets) {
+ top_ += insets.top_;
+ left_ += insets.left_;
+ bottom_ += insets.bottom_;
+ right_ += insets.right_;
+ }
+
+ void operator-=(const InsetsF& insets) {
+ top_ -= insets.top_;
+ left_ -= insets.left_;
+ bottom_ -= insets.bottom_;
+ right_ -= insets.right_;
+ }
+
+ InsetsF operator-() const {
+ return InsetsF(-top_, -left_, -bottom_, -right_);
+ }
+
+ // Returns a string representation of the insets.
+ std::string ToString() const;
+
+ private:
+ float top_;
+ float left_;
+ float bottom_;
+ float right_;
+};
+
+inline InsetsF operator+(InsetsF lhs, const InsetsF& rhs) {
+ lhs += rhs;
+ return lhs;
+}
+
+inline InsetsF operator-(InsetsF lhs, const InsetsF& rhs) {
+ lhs -= rhs;
+ return lhs;
+}
+
+} // namespace gfx
+
+#endif // UI_GFX_GEOMETRY_INSETS_F_H_
diff --git a/ui/gfx/geometry/point.cc b/ui/gfx/geometry/point.cc
new file mode 100644
index 0000000000..285b208d44
--- /dev/null
+++ b/ui/gfx/geometry/point.cc
@@ -0,0 +1,105 @@
+// 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/geometry/point.h"
+
+#include "base/strings/stringprintf.h"
+#include "build/build_config.h"
+#include "ui/gfx/geometry/point_conversions.h"
+#include "ui/gfx/geometry/point_f.h"
+
+#if defined(OS_WIN)
+#include <windows.h>
+#elif defined(OS_IOS)
+#include <CoreGraphics/CoreGraphics.h>
+#elif defined(OS_MACOSX)
+#include <ApplicationServices/ApplicationServices.h>
+#endif
+
+namespace gfx {
+
+#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;
+}
+#elif defined(OS_MACOSX)
+Point::Point(const CGPoint& point) : x_(point.x), y_(point.y) {
+}
+#endif
+
+#if defined(OS_WIN)
+POINT Point::ToPOINT() const {
+ POINT p;
+ p.x = x();
+ p.y = y();
+ return p;
+}
+#elif defined(OS_MACOSX)
+CGPoint Point::ToCGPoint() const {
+ return CGPointMake(x(), y());
+}
+#endif
+
+void Point::SetToMin(const Point& other) {
+ x_ = x_ <= other.x_ ? x_ : other.x_;
+ y_ = y_ <= other.y_ ? y_ : other.y_;
+}
+
+void Point::SetToMax(const Point& other) {
+ x_ = x_ >= other.x_ ? x_ : other.x_;
+ y_ = y_ >= other.y_ ? y_ : other.y_;
+}
+
+std::string Point::ToString() const {
+ return base::StringPrintf("%d,%d", x(), y());
+}
+
+Point ScaleToCeiledPoint(const Point& point, float x_scale, float y_scale) {
+ if (x_scale == 1.f && y_scale == 1.f)
+ return point;
+ return ToCeiledPoint(ScalePoint(gfx::PointF(point), x_scale, y_scale));
+}
+
+Point ScaleToCeiledPoint(const Point& point, float scale) {
+ if (scale == 1.f)
+ return point;
+ return ToCeiledPoint(ScalePoint(gfx::PointF(point), scale, scale));
+}
+
+Point ScaleToFlooredPoint(const Point& point, float x_scale, float y_scale) {
+ if (x_scale == 1.f && y_scale == 1.f)
+ return point;
+ return ToFlooredPoint(ScalePoint(gfx::PointF(point), x_scale, y_scale));
+}
+
+Point ScaleToFlooredPoint(const Point& point, float scale) {
+ if (scale == 1.f)
+ return point;
+ return ToFlooredPoint(ScalePoint(gfx::PointF(point), scale, scale));
+}
+
+Point ScaleToRoundedPoint(const Point& point, float x_scale, float y_scale) {
+ if (x_scale == 1.f && y_scale == 1.f)
+ return point;
+ return ToRoundedPoint(ScalePoint(gfx::PointF(point), x_scale, y_scale));
+}
+
+Point ScaleToRoundedPoint(const Point& point, float scale) {
+ if (scale == 1.f)
+ return point;
+ return ToRoundedPoint(ScalePoint(gfx::PointF(point), scale, scale));
+}
+
+} // namespace gfx
diff --git a/ui/gfx/geometry/point.h b/ui/gfx/geometry/point.h
new file mode 100644
index 0000000000..bb248d5432
--- /dev/null
+++ b/ui/gfx/geometry/point.h
@@ -0,0 +1,148 @@
+// 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_GEOMETRY_POINT_H_
+#define UI_GFX_GEOMETRY_POINT_H_
+
+#include <iosfwd>
+#include <string>
+#include <tuple>
+
+#include "base/numerics/saturated_arithmetic.h"
+#include "build/build_config.h"
+#include "ui/gfx/geometry/vector2d.h"
+#include "ui/gfx/gfx_export.h"
+
+#if defined(OS_WIN)
+typedef unsigned long DWORD;
+typedef struct tagPOINT POINT;
+#elif defined(OS_MACOSX)
+typedef struct CGPoint CGPoint;
+#endif
+
+namespace gfx {
+
+// A point has an x and y coordinate.
+class GFX_EXPORT Point {
+ public:
+ constexpr Point() : x_(0), y_(0) {}
+ constexpr Point(int x, int y) : x_(x), y_(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
+
+#if defined(OS_WIN)
+ POINT ToPOINT() const;
+#elif defined(OS_MACOSX)
+ CGPoint ToCGPoint() const;
+#endif
+
+ constexpr int x() const { return x_; }
+ constexpr int y() const { return y_; }
+ void set_x(int x) { x_ = x; }
+ void set_y(int y) { y_ = y; }
+
+ void SetPoint(int x, int y) {
+ x_ = x;
+ y_ = y;
+ }
+
+ void Offset(int delta_x, int delta_y) {
+ x_ = base::SaturatedAddition(x_, delta_x);
+ y_ = base::SaturatedAddition(y_, delta_y);
+ }
+
+ void operator+=(const Vector2d& vector) {
+ x_ = base::SaturatedAddition(x_, vector.x());
+ y_ = base::SaturatedAddition(y_, vector.y());
+ }
+
+ void operator-=(const Vector2d& vector) {
+ x_ = base::SaturatedSubtraction(x_, vector.x());
+ y_ = base::SaturatedSubtraction(y_, vector.y());
+ }
+
+ void SetToMin(const Point& other);
+ void SetToMax(const Point& other);
+
+ bool IsOrigin() const { return x_ == 0 && y_ == 0; }
+
+ Vector2d OffsetFromOrigin() const { return Vector2d(x_, 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
+ // other.
+ // This comparison is required to use Point in sets, or sorted
+ // vectors.
+ bool operator<(const Point& rhs) const {
+ return std::tie(y_, x_) < std::tie(rhs.y_, rhs.x_);
+ }
+
+ // Returns a string representation of point.
+ std::string ToString() const;
+
+ private:
+ int x_;
+ int y_;
+};
+
+inline bool operator==(const Point& lhs, const Point& rhs) {
+ return lhs.x() == rhs.x() && lhs.y() == rhs.y();
+}
+
+inline bool operator!=(const Point& lhs, const Point& rhs) {
+ return !(lhs == rhs);
+}
+
+inline Point operator+(const Point& lhs, const Vector2d& rhs) {
+ Point result(lhs);
+ result += rhs;
+ return result;
+}
+
+inline Point operator-(const Point& lhs, const Vector2d& rhs) {
+ Point result(lhs);
+ result -= rhs;
+ return result;
+}
+
+inline Vector2d operator-(const Point& lhs, const Point& rhs) {
+ return Vector2d(base::SaturatedSubtraction(lhs.x(), rhs.x()),
+ base::SaturatedSubtraction(lhs.y(), rhs.y()));
+}
+
+inline Point PointAtOffsetFromOrigin(const Vector2d& offset_from_origin) {
+ return Point(offset_from_origin.x(), offset_from_origin.y());
+}
+
+// This is declared here for use in gtest-based unit tests but is defined in
+// the //ui/gfx:test_support target. Depend on that to use this in your unit
+// test. This should not be used in production code - call ToString() instead.
+void PrintTo(const Point& point, ::std::ostream* os);
+
+// Helper methods to scale a gfx::Point to a new gfx::Point.
+GFX_EXPORT Point ScaleToCeiledPoint(const Point& point,
+ float x_scale,
+ float y_scale);
+GFX_EXPORT Point ScaleToCeiledPoint(const Point& point, float x_scale);
+GFX_EXPORT Point ScaleToFlooredPoint(const Point& point,
+ float x_scale,
+ float y_scale);
+GFX_EXPORT Point ScaleToFlooredPoint(const Point& point, float x_scale);
+GFX_EXPORT Point ScaleToRoundedPoint(const Point& point,
+ float x_scale,
+ float y_scale);
+GFX_EXPORT Point ScaleToRoundedPoint(const Point& point, float x_scale);
+
+} // namespace gfx
+
+#endif // UI_GFX_GEOMETRY_POINT_H_
diff --git a/ui/gfx/geometry/point_conversions.cc b/ui/gfx/geometry/point_conversions.cc
new file mode 100644
index 0000000000..0613e7a9db
--- /dev/null
+++ b/ui/gfx/geometry/point_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/geometry/point_conversions.h"
+
+#include "ui/gfx/geometry/safe_integer_conversions.h"
+
+namespace gfx {
+
+Point ToFlooredPoint(const PointF& point) {
+ int x = ToFlooredInt(point.x());
+ int y = ToFlooredInt(point.y());
+ return Point(x, y);
+}
+
+Point ToCeiledPoint(const PointF& point) {
+ int x = ToCeiledInt(point.x());
+ int y = ToCeiledInt(point.y());
+ return Point(x, y);
+}
+
+Point ToRoundedPoint(const PointF& point) {
+ int x = ToRoundedInt(point.x());
+ int y = ToRoundedInt(point.y());
+ return Point(x, y);
+}
+
+} // namespace gfx
+
diff --git a/ui/gfx/geometry/point_conversions.h b/ui/gfx/geometry/point_conversions.h
new file mode 100644
index 0000000000..bfab9e4e46
--- /dev/null
+++ b/ui/gfx/geometry/point_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_GEOMETRY_POINT_CONVERSIONS_H_
+#define UI_GFX_GEOMETRY_POINT_CONVERSIONS_H_
+
+#include "ui/gfx/geometry/point.h"
+#include "ui/gfx/geometry/point_f.h"
+
+namespace gfx {
+
+// Returns a Point with each component from the input PointF floored.
+GFX_EXPORT Point ToFlooredPoint(const PointF& point);
+
+// Returns a Point with each component from the input PointF ceiled.
+GFX_EXPORT Point ToCeiledPoint(const PointF& point);
+
+// Returns a Point with each component from the input PointF rounded.
+GFX_EXPORT Point ToRoundedPoint(const PointF& point);
+
+} // namespace gfx
+
+#endif // UI_GFX_GEOMETRY_POINT_CONVERSIONS_H_
diff --git a/ui/gfx/geometry/point_f.cc b/ui/gfx/geometry/point_f.cc
new file mode 100644
index 0000000000..0d15394593
--- /dev/null
+++ b/ui/gfx/geometry/point_f.cc
@@ -0,0 +1,32 @@
+// 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/geometry/point_f.h"
+
+#include "base/strings/stringprintf.h"
+
+namespace gfx {
+
+void PointF::SetToMin(const PointF& other) {
+ x_ = x_ <= other.x_ ? x_ : other.x_;
+ y_ = y_ <= other.y_ ? y_ : other.y_;
+}
+
+void PointF::SetToMax(const PointF& other) {
+ x_ = x_ >= other.x_ ? x_ : other.x_;
+ y_ = y_ >= other.y_ ? y_ : other.y_;
+}
+
+std::string PointF::ToString() const {
+ return base::StringPrintf("%f,%f", x(), y());
+}
+
+PointF ScalePoint(const PointF& p, float x_scale, float y_scale) {
+ PointF scaled_p(p);
+ scaled_p.Scale(x_scale, y_scale);
+ return scaled_p;
+}
+
+
+} // namespace gfx
diff --git a/ui/gfx/geometry/point_f.h b/ui/gfx/geometry/point_f.h
new file mode 100644
index 0000000000..5d92b1100c
--- /dev/null
+++ b/ui/gfx/geometry/point_f.h
@@ -0,0 +1,126 @@
+// 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_GEOMETRY_POINT_F_H_
+#define UI_GFX_GEOMETRY_POINT_F_H_
+
+#include <iosfwd>
+#include <string>
+#include <tuple>
+
+#include "ui/gfx/geometry/point.h"
+#include "ui/gfx/geometry/vector2d_f.h"
+#include "ui/gfx/gfx_export.h"
+
+namespace gfx {
+
+// A floating version of gfx::Point.
+class GFX_EXPORT PointF {
+ public:
+ constexpr PointF() : x_(0.f), y_(0.f) {}
+ constexpr PointF(float x, float y) : x_(x), y_(y) {}
+
+ constexpr explicit PointF(const Point& p)
+ : PointF(static_cast<float>(p.x()), static_cast<float>(p.y())) {}
+
+ constexpr float x() const { return x_; }
+ constexpr float y() const { return y_; }
+ void set_x(float x) { x_ = x; }
+ void set_y(float y) { y_ = y; }
+
+ void SetPoint(float x, float y) {
+ x_ = x;
+ y_ = y;
+ }
+
+ void Offset(float delta_x, float delta_y) {
+ x_ += delta_x;
+ y_ += delta_y;
+ }
+
+ void operator+=(const Vector2dF& vector) {
+ x_ += vector.x();
+ y_ += vector.y();
+ }
+
+ void operator-=(const Vector2dF& vector) {
+ x_ -= vector.x();
+ y_ -= vector.y();
+ }
+
+ void SetToMin(const PointF& other);
+ void SetToMax(const PointF& other);
+
+ bool IsOrigin() const { return x_ == 0 && y_ == 0; }
+
+ Vector2dF OffsetFromOrigin() const { return Vector2dF(x_, 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
+ // other.
+ // This comparison is required to use PointF in sets, or sorted
+ // vectors.
+ bool operator<(const PointF& rhs) const {
+ return std::tie(y_, x_) < std::tie(rhs.y_, rhs.x_);
+ }
+
+ void Scale(float scale) {
+ Scale(scale, scale);
+ }
+
+ void Scale(float x_scale, float y_scale) {
+ SetPoint(x() * x_scale, y() * y_scale);
+ }
+
+ // Returns a string representation of point.
+ std::string ToString() const;
+
+ private:
+ float x_;
+ float y_;
+};
+
+inline bool operator==(const PointF& lhs, const PointF& rhs) {
+ return lhs.x() == rhs.x() && lhs.y() == rhs.y();
+}
+
+inline bool operator!=(const PointF& lhs, const PointF& rhs) {
+ return !(lhs == rhs);
+}
+
+inline PointF operator+(const PointF& lhs, const Vector2dF& rhs) {
+ PointF result(lhs);
+ result += rhs;
+ return result;
+}
+
+inline PointF operator-(const PointF& lhs, const Vector2dF& rhs) {
+ PointF result(lhs);
+ result -= rhs;
+ return result;
+}
+
+inline Vector2dF operator-(const PointF& lhs, const PointF& rhs) {
+ return Vector2dF(lhs.x() - rhs.x(), lhs.y() - rhs.y());
+}
+
+inline PointF PointAtOffsetFromOrigin(const Vector2dF& offset_from_origin) {
+ return PointF(offset_from_origin.x(), offset_from_origin.y());
+}
+
+GFX_EXPORT PointF ScalePoint(const PointF& p, float x_scale, float y_scale);
+
+inline PointF ScalePoint(const PointF& p, float scale) {
+ return ScalePoint(p, scale, scale);
+}
+
+// This is declared here for use in gtest-based unit tests but is defined in
+// the //ui/gfx:test_support target. Depend on that to use this in your unit
+// test. This should not be used in production code - call ToString() instead.
+void PrintTo(const PointF& point, ::std::ostream* os);
+
+} // namespace gfx
+
+#endif // UI_GFX_GEOMETRY_POINT_F_H_
diff --git a/ui/gfx/geometry/rect.cc b/ui/gfx/geometry/rect.cc
new file mode 100644
index 0000000000..b5ceda5829
--- /dev/null
+++ b/ui/gfx/geometry/rect.cc
@@ -0,0 +1,346 @@
+// 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/geometry/rect.h"
+
+#include <algorithm>
+
+#if defined(OS_WIN)
+#include <windows.h>
+#elif defined(OS_IOS)
+#include <CoreGraphics/CoreGraphics.h>
+#elif defined(OS_MACOSX)
+#include <ApplicationServices/ApplicationServices.h>
+#endif
+
+#include "base/logging.h"
+#include "base/numerics/saturated_arithmetic.h"
+#include "base/strings/stringprintf.h"
+#include "build/build_config.h"
+#include "ui/gfx/geometry/insets.h"
+
+namespace gfx {
+
+#if defined(OS_WIN)
+Rect::Rect(const RECT& r)
+ : origin_(r.left, r.top),
+ size_(std::abs(r.right - r.left), std::abs(r.bottom - r.top)) {
+}
+#elif defined(OS_MACOSX)
+Rect::Rect(const CGRect& r)
+ : origin_(r.origin.x, r.origin.y), size_(r.size.width, r.size.height) {
+}
+#endif
+
+#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());
+}
+#endif
+
+void AdjustAlongAxis(int dst_origin, int dst_size, int* origin, int* size) {
+ *size = std::min(dst_size, *size);
+ if (*origin < dst_origin)
+ *origin = dst_origin;
+ else
+ *origin = std::min(dst_origin + dst_size, *origin + *size) - *size;
+}
+
+} // namespace
+
+namespace gfx {
+
+// This is the per-axis heuristic for picking the most useful origin and
+// width/height to represent the input range.
+static void SaturatedClampRange(int min, int max, int* origin, int* span) {
+ if (max < min) {
+ *span = 0;
+ *origin = min;
+ return;
+ }
+
+ int effective_span = base::SaturatedSubtraction(max, min);
+ int span_loss = base::SaturatedSubtraction(max, min + effective_span);
+
+ // If the desired width is within the limits of ints, we can just
+ // use the simple computations to represent the range precisely.
+ if (span_loss == 0) {
+ *span = effective_span;
+ *origin = min;
+ return;
+ }
+
+ // Now we have to approximate. If one of min or max is close enough
+ // to zero we choose to represent that one precisely. The other side is
+ // probably practically "infinite", so we move it.
+ if (base::SaturatedAbsolute(max) < std::numeric_limits<int>::max() / 2) {
+ // Maintain origin + span == max.
+ *span = effective_span;
+ *origin = max - effective_span;
+ } else if (base::SaturatedAbsolute(min) <
+ std::numeric_limits<int>::max() / 2) {
+ // Maintain origin == min.
+ *span = effective_span;
+ *origin = min;
+ } else {
+ // Both are big, so keep the center.
+ *span = effective_span;
+ *origin = min + span_loss / 2;
+ }
+}
+
+void Rect::SetByBounds(int left, int top, int right, int bottom) {
+ int x, y;
+ int width, height;
+ SaturatedClampRange(left, right, &x, &width);
+ SaturatedClampRange(top, bottom, &y, &height);
+ origin_.SetPoint(x, y);
+ size_.SetSize(width, height);
+}
+
+void Rect::Inset(const Insets& insets) {
+ Inset(insets.left(), insets.top(), insets.right(), insets.bottom());
+}
+
+void Rect::Inset(int left, int top, int right, int bottom) {
+ origin_ += Vector2d(left, top);
+ // left+right might overflow/underflow, but width() - (left+right) might
+ // overflow as well.
+ set_width(base::SaturatedSubtraction(width(),
+ base::SaturatedAddition(left, right)));
+ set_height(base::SaturatedSubtraction(height(),
+ base::SaturatedAddition(top, bottom)));
+}
+
+void Rect::Offset(int horizontal, int vertical) {
+ origin_ += Vector2d(horizontal, vertical);
+ // Ensure that width and height remain valid.
+ set_width(width());
+ set_height(height());
+}
+
+void Rect::operator+=(const Vector2d& offset) {
+ origin_ += offset;
+ // Ensure that width and height remain valid.
+ set_width(width());
+ set_height(height());
+}
+
+void Rect::operator-=(const Vector2d& offset) {
+ origin_ -= offset;
+}
+
+Insets Rect::InsetsFrom(const Rect& inner) const {
+ return Insets(inner.y() - y(),
+ inner.x() - x(),
+ bottom() - inner.bottom(),
+ right() - inner.right());
+}
+
+bool Rect::operator<(const Rect& other) const {
+ if (origin_ == other.origin_) {
+ if (width() == other.width()) {
+ return height() < other.height();
+ } else {
+ return width() < other.width();
+ }
+ } else {
+ return origin_ < other.origin_;
+ }
+}
+
+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 !(IsEmpty() || rect.IsEmpty() || rect.x() >= right() ||
+ rect.right() <= x() || rect.y() >= bottom() || rect.bottom() <= y());
+}
+
+void Rect::Intersect(const Rect& rect) {
+ if (IsEmpty() || rect.IsEmpty()) {
+ SetRect(0, 0, 0, 0); // Throws away empty position.
+ return;
+ }
+
+ int left = std::max(x(), rect.x());
+ int top = std::max(y(), rect.y());
+ int new_right = std::min(right(), rect.right());
+ int new_bottom = std::min(bottom(), rect.bottom());
+
+ if (left >= new_right || top >= new_bottom) {
+ SetRect(0, 0, 0, 0); // Throws away empty position.
+ return;
+ }
+
+ SetByBounds(left, top, new_right, new_bottom);
+}
+
+void Rect::Union(const Rect& rect) {
+ if (IsEmpty()) {
+ *this = rect;
+ return;
+ }
+ if (rect.IsEmpty())
+ return;
+
+ SetByBounds(std::min(x(), rect.x()), std::min(y(), rect.y()),
+ std::max(right(), rect.right()),
+ std::max(bottom(), rect.bottom()));
+}
+
+void Rect::Subtract(const Rect& rect) {
+ if (!Intersects(rect))
+ return;
+ if (rect.Contains(*this)) {
+ SetRect(0, 0, 0, 0);
+ return;
+ }
+
+ 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 if (rect.right() >= right()) {
+ 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 if (rect.bottom() >= bottom()) {
+ rb = rect.y();
+ }
+ }
+ SetByBounds(rx, ry, rr, rb);
+}
+
+void Rect::AdjustToFit(const Rect& rect) {
+ 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);
+ SetRect(new_x, new_y, new_width, new_height);
+}
+
+Point Rect::CenterPoint() const {
+ return Point(x() + width() / 2, y() + height() / 2);
+}
+
+void Rect::ClampToCenteredSize(const Size& size) {
+ int new_width = std::min(width(), size.width());
+ int new_height = std::min(height(), size.height());
+ int new_x = x() + (width() - new_width) / 2;
+ int new_y = y() + (height() - new_height) / 2;
+ SetRect(new_x, new_y, new_width, new_height);
+}
+
+void Rect::SplitVertically(Rect* left_half, Rect* right_half) const {
+ DCHECK(left_half);
+ DCHECK(right_half);
+
+ left_half->SetRect(x(), y(), width() / 2, height());
+ right_half->SetRect(
+ left_half->right(), y(), width() - left_half->width(), height());
+}
+
+bool Rect::SharesEdgeWith(const 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()));
+}
+
+int Rect::ManhattanDistanceToPoint(const Point& point) const {
+ int x_distance =
+ std::max<int>(0, std::max(x() - point.x(), point.x() - right()));
+ int y_distance =
+ std::max<int>(0, std::max(y() - point.y(), point.y() - bottom()));
+
+ return x_distance + y_distance;
+}
+
+int Rect::ManhattanInternalDistance(const Rect& rect) const {
+ Rect c(*this);
+ c.Union(rect);
+
+ int x = std::max(0, c.width() - width() - rect.width() + 1);
+ int y = std::max(0, c.height() - height() - rect.height() + 1);
+ return x + y;
+}
+
+std::string Rect::ToString() const {
+ return base::StringPrintf("%s %s",
+ origin().ToString().c_str(),
+ size().ToString().c_str());
+}
+
+bool Rect::ApproximatelyEqual(const Rect& rect, int tolerance) const {
+ return std::abs(x() - rect.x()) <= tolerance &&
+ std::abs(y() - rect.y()) <= tolerance &&
+ std::abs(right() - rect.right()) <= tolerance &&
+ std::abs(bottom() - rect.bottom()) <= tolerance;
+}
+
+Rect operator+(const Rect& lhs, const Vector2d& rhs) {
+ Rect result(lhs);
+ result += rhs;
+ return result;
+}
+
+Rect operator-(const Rect& lhs, const Vector2d& rhs) {
+ Rect result(lhs);
+ result -= rhs;
+ return result;
+}
+
+Rect IntersectRects(const Rect& a, const Rect& b) {
+ Rect result = a;
+ result.Intersect(b);
+ return result;
+}
+
+Rect UnionRects(const Rect& a, const Rect& b) {
+ Rect result = a;
+ result.Union(b);
+ return result;
+}
+
+Rect SubtractRects(const Rect& a, const Rect& b) {
+ Rect result = a;
+ result.Subtract(b);
+ return result;
+}
+
+Rect BoundingRect(const Point& p1, const Point& p2) {
+ Rect result;
+ result.SetByBounds(std::min(p1.x(), p2.x()), std::min(p1.y(), p2.y()),
+ std::max(p1.x(), p2.x()), std::max(p1.y(), p2.y()));
+ return result;
+}
+
+} // namespace gfx
diff --git a/ui/gfx/geometry/rect.h b/ui/gfx/geometry/rect.h
new file mode 100644
index 0000000000..1858d44d2c
--- /dev/null
+++ b/ui/gfx/geometry/rect.h
@@ -0,0 +1,350 @@
+// 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 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 Contains()) to complain in this case.
+
+#ifndef UI_GFX_GEOMETRY_RECT_H_
+#define UI_GFX_GEOMETRY_RECT_H_
+
+#include <cmath>
+#include <iosfwd>
+#include <string>
+
+#include "base/logging.h"
+#include "build/build_config.h"
+#include "ui/gfx/geometry/point.h"
+#include "ui/gfx/geometry/safe_integer_conversions.h"
+#include "ui/gfx/geometry/size.h"
+#include "ui/gfx/geometry/vector2d.h"
+
+#if defined(OS_WIN)
+typedef struct tagRECT RECT;
+#elif defined(OS_MACOSX)
+typedef struct CGRect CGRect;
+#endif
+
+namespace gfx {
+
+class Insets;
+
+class GFX_EXPORT Rect {
+ public:
+ constexpr Rect() = default;
+ constexpr Rect(int width, int height) : size_(width, height) {}
+ constexpr Rect(int x, int y, int width, int height)
+ : origin_(x, y),
+ size_(GetClampedValue(x, width), GetClampedValue(y, height)) {}
+ constexpr explicit Rect(const Size& size) : size_(size) {}
+ constexpr Rect(const Point& origin, const Size& size)
+ : origin_(origin),
+ size_(GetClampedValue(origin.x(), size.width()),
+ GetClampedValue(origin.y(), size.height())) {}
+
+#if defined(OS_WIN)
+ explicit Rect(const RECT& r);
+#elif defined(OS_MACOSX)
+ explicit Rect(const CGRect& r);
+#endif
+
+#if defined(OS_WIN)
+ // Construct an equivalent Win32 RECT object.
+ RECT ToRECT() const;
+#elif defined(OS_MACOSX)
+ // Construct an equivalent CoreGraphics object.
+ CGRect ToCGRect() const;
+#endif
+
+ constexpr int x() const { return origin_.x(); }
+ void set_x(int x) {
+ origin_.set_x(x);
+ size_.set_width(GetClampedValue(x, width()));
+ }
+
+ constexpr int y() const { return origin_.y(); }
+ void set_y(int y) {
+ origin_.set_y(y);
+ size_.set_height(GetClampedValue(y, height()));
+ }
+
+ constexpr int width() const { return size_.width(); }
+ void set_width(int width) { size_.set_width(GetClampedValue(x(), width)); }
+
+ constexpr int height() const { return size_.height(); }
+ void set_height(int height) {
+ size_.set_height(GetClampedValue(y(), height));
+ }
+
+ constexpr const Point& origin() const { return origin_; }
+ void set_origin(const Point& origin) {
+ origin_ = origin;
+ // Ensure that width and height remain valid.
+ set_width(width());
+ set_height(height());
+ }
+
+ constexpr const Size& size() const { return size_; }
+ void set_size(const Size& size) {
+ set_width(size.width());
+ set_height(size.height());
+ }
+
+ constexpr int right() const { return x() + width(); }
+ constexpr int bottom() const { return y() + height(); }
+
+ constexpr Point top_right() const { return Point(right(), y()); }
+ constexpr Point bottom_left() const { return Point(x(), bottom()); }
+ constexpr Point bottom_right() const { return Point(right(), bottom()); }
+
+ Vector2d OffsetFromOrigin() const { return Vector2d(x(), y()); }
+
+ void SetRect(int x, int y, int width, int height) {
+ origin_.SetPoint(x, y);
+ // Ensure that width and height remain valid.
+ set_width(width);
+ set_height(height);
+ }
+
+ // Use in place of SetRect() when you know the edges of the rectangle instead
+ // of the dimensions, rather than trying to determine the width/height
+ // yourself. This safely handles cases where the width/height would overflow.
+ void SetByBounds(int left, int top, int right, int bottom);
+
+ // 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 given insets.
+ void Inset(const Insets& insets);
+
+ // 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 Vector2d& distance) { Offset(distance.x(), distance.y()); }
+ void operator+=(const Vector2d& offset);
+ void operator-=(const Vector2d& offset);
+
+ Insets InsetsFrom(const Rect& inner) const;
+
+ // Returns true if the area of the rectangle is zero.
+ bool IsEmpty() const { return size_.IsEmpty(); }
+
+ // A rect is less than another rect if its origin is less than
+ // the other rect's origin. If the origins are equal, then the
+ // shortest rect is less than the other. If the origin and the
+ // height are equal, then the narrowest rect is less than.
+ // This comparison is required to use Rects in sets, or sorted
+ // vectors.
+ bool operator<(const Rect& other) const;
+
+ // 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 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.
+ // An empty rectangle doesn't intersect any rectangle.
+ bool Intersects(const Rect& rect) const;
+
+ // Computes the intersection of this rectangle with the given rectangle.
+ void Intersect(const Rect& rect);
+
+ // Computes the union of this rectangle with the given rectangle. The union
+ // is the smallest rectangle containing both rectangles.
+ void Union(const Rect& rect);
+
+ // Computes the rectangle resulting from subtracting |rect| from |*this|,
+ // i.e. the bounding rect of |Region(*this) - Region(rect)|.
+ void Subtract(const Rect& rect);
+
+ // Fits as much of the receiving rectangle into the supplied rectangle as
+ // possible, becoming 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.
+ void AdjustToFit(const Rect& rect);
+
+ // Returns the center of this rectangle.
+ Point CenterPoint() const;
+
+ // Becomes a rectangle that has the same center point but with a size capped
+ // at given |size|.
+ void ClampToCenteredSize(const Size& size);
+
+ // Splits |this| in two halves, |left_half| and |right_half|.
+ void SplitVertically(Rect* left_half, Rect* right_half) 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 Rect& rect) const;
+
+ // Returns the manhattan distance from the rect to the point. If the point is
+ // inside the rect, returns 0.
+ int ManhattanDistanceToPoint(const Point& point) const;
+
+ // Returns the manhattan distance between the contents of this rect and the
+ // contents of the given rect. That is, if the intersection of the two rects
+ // is non-empty then the function returns 0. If the rects share a side, it
+ // returns the smallest non-zero value appropriate for int.
+ int ManhattanInternalDistance(const Rect& rect) const;
+
+ std::string ToString() const;
+
+ bool ApproximatelyEqual(const Rect& rect, int tolerance) const;
+
+ private:
+ gfx::Point origin_;
+ gfx::Size size_;
+
+ // Returns true iff a+b would overflow max int.
+ static constexpr bool AddWouldOverflow(int a, int b) {
+ // In this function, GCC tries to make optimizations that would only work if
+ // max - a wouldn't overflow but it isn't smart enough to notice that a > 0.
+ // So cast everything to unsigned to avoid this. As it is guaranteed that
+ // max - a and b are both already positive, the cast is a noop.
+ //
+ // This is intended to be: a > 0 && max - a < b
+ return a > 0 && b > 0 &&
+ static_cast<unsigned>(std::numeric_limits<int>::max() - a) <
+ static_cast<unsigned>(b);
+ }
+
+ // Clamp the size to avoid integer overflow in bottom() and right().
+ // This returns the width given an origin and a width.
+ // TODO(enne): this should probably use base::SaturatedAddition, but that
+ // function is not a constexpr.
+ static constexpr int GetClampedValue(int origin, int size) {
+ return AddWouldOverflow(origin, size)
+ ? std::numeric_limits<int>::max() - origin
+ : size;
+ }
+};
+
+inline bool operator==(const Rect& lhs, const Rect& rhs) {
+ return lhs.origin() == rhs.origin() && lhs.size() == rhs.size();
+}
+
+inline bool operator!=(const Rect& lhs, const Rect& rhs) {
+ return !(lhs == rhs);
+}
+
+GFX_EXPORT Rect operator+(const Rect& lhs, const Vector2d& rhs);
+GFX_EXPORT Rect operator-(const Rect& lhs, const Vector2d& rhs);
+
+inline Rect operator+(const Vector2d& lhs, const Rect& rhs) {
+ return rhs + lhs;
+}
+
+GFX_EXPORT Rect IntersectRects(const Rect& a, const Rect& b);
+GFX_EXPORT Rect UnionRects(const Rect& a, const Rect& b);
+GFX_EXPORT Rect SubtractRects(const Rect& a, const Rect& b);
+
+// Constructs a rectangle with |p1| and |p2| as opposite corners.
+//
+// This could also be thought of as "the smallest rect that contains both
+// points", except that we consider points on the right/bottom edges of the
+// rect to be outside the rect. So technically one or both points will not be
+// contained within the rect, because they will appear on one of these edges.
+GFX_EXPORT Rect BoundingRect(const Point& p1, const Point& p2);
+
+// Scales the rect and returns the enclosing rect. Use this only the inputs are
+// known to not overflow. Use ScaleToEnclosingRectSafe if the inputs are
+// unknown and need to use saturated math.
+inline Rect ScaleToEnclosingRect(const Rect& rect,
+ float x_scale,
+ float y_scale) {
+ if (x_scale == 1.f && y_scale == 1.f)
+ return rect;
+ // These next functions cast instead of using e.g. ToFlooredInt() because we
+ // haven't checked to ensure that the clamping behavior of the helper
+ // functions doesn't degrade performance, and callers shouldn't be passing
+ // values that cause overflow anyway.
+ DCHECK(base::IsValueInRangeForNumericType<int>(
+ std::floor(rect.x() * x_scale)));
+ DCHECK(base::IsValueInRangeForNumericType<int>(
+ std::floor(rect.y() * y_scale)));
+ DCHECK(base::IsValueInRangeForNumericType<int>(
+ std::ceil(rect.right() * x_scale)));
+ DCHECK(base::IsValueInRangeForNumericType<int>(
+ std::ceil(rect.bottom() * y_scale)));
+ int x = static_cast<int>(std::floor(rect.x() * x_scale));
+ int y = static_cast<int>(std::floor(rect.y() * y_scale));
+ int r = rect.width() == 0 ?
+ x : static_cast<int>(std::ceil(rect.right() * x_scale));
+ int b = rect.height() == 0 ?
+ y : static_cast<int>(std::ceil(rect.bottom() * y_scale));
+ return Rect(x, y, r - x, b - y);
+}
+
+inline Rect ScaleToEnclosingRect(const Rect& rect, float scale) {
+ return ScaleToEnclosingRect(rect, scale, scale);
+}
+
+// ScaleToEnclosingRect but clamping instead of asserting if the resulting rect
+// would overflow.
+inline Rect ScaleToEnclosingRectSafe(const Rect& rect,
+ float x_scale,
+ float y_scale) {
+ if (x_scale == 1.f && y_scale == 1.f)
+ return rect;
+ int x = base::saturated_cast<int>(std::floor(rect.x() * x_scale));
+ int y = base::saturated_cast<int>(std::floor(rect.y() * y_scale));
+ int w = base::saturated_cast<int>(std::ceil(rect.width() * x_scale));
+ int h = base::saturated_cast<int>(std::ceil(rect.height() * y_scale));
+ return Rect(x, y, w, h);
+}
+
+inline Rect ScaleToEnclosingRectSafe(const Rect& rect, float scale) {
+ return ScaleToEnclosingRectSafe(rect, scale, scale);
+}
+
+inline Rect ScaleToEnclosedRect(const Rect& rect,
+ float x_scale,
+ float y_scale) {
+ if (x_scale == 1.f && y_scale == 1.f)
+ return rect;
+ DCHECK(base::IsValueInRangeForNumericType<int>(
+ std::ceil(rect.x() * x_scale)));
+ DCHECK(base::IsValueInRangeForNumericType<int>(
+ std::ceil(rect.y() * y_scale)));
+ DCHECK(base::IsValueInRangeForNumericType<int>(
+ std::floor(rect.right() * x_scale)));
+ DCHECK(base::IsValueInRangeForNumericType<int>(
+ std::floor(rect.bottom() * y_scale)));
+ int x = static_cast<int>(std::ceil(rect.x() * x_scale));
+ int y = static_cast<int>(std::ceil(rect.y() * y_scale));
+ int r = rect.width() == 0 ?
+ x : static_cast<int>(std::floor(rect.right() * x_scale));
+ int b = rect.height() == 0 ?
+ y : static_cast<int>(std::floor(rect.bottom() * y_scale));
+ return Rect(x, y, r - x, b - y);
+}
+
+inline Rect ScaleToEnclosedRect(const Rect& rect, float scale) {
+ return ScaleToEnclosedRect(rect, scale, scale);
+}
+
+// This is declared here for use in gtest-based unit tests but is defined in
+// the //ui/gfx:test_support target. Depend on that to use this in your unit
+// test. This should not be used in production code - call ToString() instead.
+void PrintTo(const Rect& rect, ::std::ostream* os);
+
+} // namespace gfx
+
+#endif // UI_GFX_GEOMETRY_RECT_H_
diff --git a/ui/gfx/geometry/rect_f.cc b/ui/gfx/geometry/rect_f.cc
new file mode 100644
index 0000000000..a08e384776
--- /dev/null
+++ b/ui/gfx/geometry/rect_f.cc
@@ -0,0 +1,259 @@
+// 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/geometry/rect_f.h"
+
+#include <algorithm>
+
+#if defined(OS_IOS)
+#include <CoreGraphics/CoreGraphics.h>
+#elif defined(OS_MACOSX)
+#include <ApplicationServices/ApplicationServices.h>
+#endif
+
+#include "base/logging.h"
+#include "base/strings/stringprintf.h"
+#include "build/build_config.h"
+#include "ui/gfx/geometry/insets_f.h"
+#include "ui/gfx/geometry/safe_integer_conversions.h"
+
+namespace gfx {
+
+static void AdjustAlongAxis(float dst_origin,
+ float dst_size,
+ float* origin,
+ float* size) {
+ *size = std::min(dst_size, *size);
+ if (*origin < dst_origin)
+ *origin = dst_origin;
+ else
+ *origin = std::min(dst_origin + dst_size, *origin + *size) - *size;
+}
+
+#if defined(OS_MACOSX)
+RectF::RectF(const CGRect& r)
+ : origin_(r.origin.x, r.origin.y), size_(r.size.width, r.size.height) {
+}
+
+CGRect RectF::ToCGRect() const {
+ return CGRectMake(x(), y(), width(), height());
+}
+#endif
+
+void RectF::Inset(const InsetsF& insets) {
+ Inset(insets.left(), insets.top(), insets.right(), insets.bottom());
+}
+
+void RectF::Inset(float left, float top, float right, float bottom) {
+ origin_ += Vector2dF(left, top);
+ set_width(std::max(width() - left - right, static_cast<float>(0)));
+ set_height(std::max(height() - top - bottom, static_cast<float>(0)));
+}
+
+void RectF::Offset(float horizontal, float vertical) {
+ origin_ += Vector2dF(horizontal, vertical);
+}
+
+void RectF::operator+=(const Vector2dF& offset) {
+ origin_ += offset;
+}
+
+void RectF::operator-=(const Vector2dF& offset) {
+ origin_ -= offset;
+}
+
+InsetsF RectF::InsetsFrom(const RectF& inner) const {
+ return InsetsF(inner.y() - y(),
+ inner.x() - x(),
+ bottom() - inner.bottom(),
+ right() - inner.right());
+}
+
+bool RectF::operator<(const RectF& other) const {
+ if (origin_ == other.origin_) {
+ if (width() == other.width()) {
+ return height() < other.height();
+ } else {
+ return width() < other.width();
+ }
+ } else {
+ return origin_ < other.origin_;
+ }
+}
+
+bool RectF::Contains(float point_x, float point_y) const {
+ return (point_x >= x()) && (point_x < right()) && (point_y >= y()) &&
+ (point_y < bottom());
+}
+
+bool RectF::Contains(const RectF& rect) const {
+ return (rect.x() >= x() && rect.right() <= right() && rect.y() >= y() &&
+ rect.bottom() <= bottom());
+}
+
+bool RectF::Intersects(const RectF& rect) const {
+ return !(IsEmpty() || rect.IsEmpty() || rect.x() >= right() ||
+ rect.right() <= x() || rect.y() >= bottom() || rect.bottom() <= y());
+}
+
+void RectF::Intersect(const RectF& rect) {
+ if (IsEmpty() || rect.IsEmpty()) {
+ SetRect(0, 0, 0, 0);
+ return;
+ }
+
+ float rx = std::max(x(), rect.x());
+ float ry = std::max(y(), rect.y());
+ float rr = std::min(right(), rect.right());
+ float rb = std::min(bottom(), rect.bottom());
+
+ if (rx >= rr || ry >= rb)
+ rx = ry = rr = rb = 0; // non-intersecting
+
+ SetRect(rx, ry, rr - rx, rb - ry);
+}
+
+void RectF::Union(const RectF& rect) {
+ if (IsEmpty()) {
+ *this = rect;
+ return;
+ }
+ if (rect.IsEmpty())
+ return;
+
+ float rx = std::min(x(), rect.x());
+ float ry = std::min(y(), rect.y());
+ float rr = std::max(right(), rect.right());
+ float rb = std::max(bottom(), rect.bottom());
+
+ SetRect(rx, ry, rr - rx, rb - ry);
+}
+
+void RectF::Subtract(const RectF& rect) {
+ if (!Intersects(rect))
+ return;
+ if (rect.Contains(*static_cast<const RectF*>(this))) {
+ SetRect(0, 0, 0, 0);
+ return;
+ }
+
+ float rx = x();
+ float ry = y();
+ float rr = right();
+ float rb = bottom();
+
+ if (rect.y() <= y() && rect.bottom() >= bottom()) {
+ // complete intersection in the y-direction
+ if (rect.x() <= x()) {
+ rx = rect.right();
+ } else if (rect.right() >= right()) {
+ 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 if (rect.bottom() >= bottom()) {
+ rb = rect.y();
+ }
+ }
+ SetRect(rx, ry, rr - rx, rb - ry);
+}
+
+void RectF::AdjustToFit(const RectF& rect) {
+ float new_x = x();
+ float new_y = y();
+ float new_width = width();
+ float new_height = height();
+ AdjustAlongAxis(rect.x(), rect.width(), &new_x, &new_width);
+ AdjustAlongAxis(rect.y(), rect.height(), &new_y, &new_height);
+ SetRect(new_x, new_y, new_width, new_height);
+}
+
+PointF RectF::CenterPoint() const {
+ return PointF(x() + width() / 2, y() + height() / 2);
+}
+
+void RectF::ClampToCenteredSize(const SizeF& size) {
+ float new_width = std::min(width(), size.width());
+ float new_height = std::min(height(), size.height());
+ float new_x = x() + (width() - new_width) / 2;
+ float new_y = y() + (height() - new_height) / 2;
+ SetRect(new_x, new_y, new_width, new_height);
+}
+
+void RectF::SplitVertically(RectF* left_half, RectF* right_half) const {
+ DCHECK(left_half);
+ DCHECK(right_half);
+
+ left_half->SetRect(x(), y(), width() / 2, height());
+ right_half->SetRect(
+ left_half->right(), y(), width() - left_half->width(), height());
+}
+
+bool RectF::SharesEdgeWith(const RectF& 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()));
+}
+
+float RectF::ManhattanDistanceToPoint(const PointF& point) const {
+ float x_distance =
+ std::max<float>(0, std::max(x() - point.x(), point.x() - right()));
+ float y_distance =
+ std::max<float>(0, std::max(y() - point.y(), point.y() - bottom()));
+
+ return x_distance + y_distance;
+}
+
+float RectF::ManhattanInternalDistance(const RectF& rect) const {
+ RectF c(*this);
+ c.Union(rect);
+
+ static const float kEpsilon = std::numeric_limits<float>::epsilon();
+ float x = std::max(0.f, c.width() - width() - rect.width() + kEpsilon);
+ float y = std::max(0.f, c.height() - height() - rect.height() + kEpsilon);
+ return x + y;
+}
+
+bool RectF::IsExpressibleAsRect() const {
+ return IsExpressibleAsInt(x()) && IsExpressibleAsInt(y()) &&
+ IsExpressibleAsInt(width()) && IsExpressibleAsInt(height()) &&
+ IsExpressibleAsInt(right()) && IsExpressibleAsInt(bottom());
+}
+
+std::string RectF::ToString() const {
+ return base::StringPrintf("%s %s",
+ origin().ToString().c_str(),
+ size().ToString().c_str());
+}
+
+RectF IntersectRects(const RectF& a, const RectF& b) {
+ RectF result = a;
+ result.Intersect(b);
+ return result;
+}
+
+RectF UnionRects(const RectF& a, const RectF& b) {
+ RectF result = a;
+ result.Union(b);
+ return result;
+}
+
+RectF SubtractRects(const RectF& a, const RectF& b) {
+ RectF result = a;
+ result.Subtract(b);
+ return result;
+}
+
+RectF BoundingRect(const PointF& p1, const PointF& p2) {
+ float rx = std::min(p1.x(), p2.x());
+ float ry = std::min(p1.y(), p2.y());
+ float rr = std::max(p1.x(), p2.x());
+ float rb = std::max(p1.y(), p2.y());
+ return RectF(rx, ry, rr - rx, rb - ry);
+}
+
+} // namespace gfx
diff --git a/ui/gfx/geometry/rect_f.h b/ui/gfx/geometry/rect_f.h
new file mode 100644
index 0000000000..9d99052c4a
--- /dev/null
+++ b/ui/gfx/geometry/rect_f.h
@@ -0,0 +1,242 @@
+// 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_GEOMETRY_RECT_F_H_
+#define UI_GFX_GEOMETRY_RECT_F_H_
+
+#include <iosfwd>
+#include <string>
+
+#include "build/build_config.h"
+#include "ui/gfx/geometry/point_f.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/geometry/size_f.h"
+#include "ui/gfx/geometry/vector2d_f.h"
+
+#if defined(OS_MACOSX)
+typedef struct CGRect CGRect;
+#endif
+
+namespace gfx {
+
+class InsetsF;
+
+// A floating version of gfx::Rect.
+class GFX_EXPORT RectF {
+ public:
+ constexpr RectF() = default;
+ constexpr RectF(float width, float height) : size_(width, height) {}
+ constexpr RectF(float x, float y, float width, float height)
+ : origin_(x, y), size_(width, height) {}
+ constexpr explicit RectF(const SizeF& size) : size_(size) {}
+ constexpr RectF(const PointF& origin, const SizeF& size)
+ : origin_(origin), size_(size) {}
+
+ constexpr explicit RectF(const Rect& r)
+ : RectF(static_cast<float>(r.x()),
+ static_cast<float>(r.y()),
+ static_cast<float>(r.width()),
+ static_cast<float>(r.height())) {}
+
+#if defined(OS_MACOSX)
+ explicit RectF(const CGRect& r);
+ // Construct an equivalent CoreGraphics object.
+ CGRect ToCGRect() const;
+#endif
+
+ constexpr float x() const { return origin_.x(); }
+ void set_x(float x) { origin_.set_x(x); }
+
+ constexpr float y() const { return origin_.y(); }
+ void set_y(float y) { origin_.set_y(y); }
+
+ constexpr float width() const { return size_.width(); }
+ void set_width(float width) { size_.set_width(width); }
+
+ constexpr float height() const { return size_.height(); }
+ void set_height(float height) { size_.set_height(height); }
+
+ constexpr const PointF& origin() const { return origin_; }
+ void set_origin(const PointF& origin) { origin_ = origin; }
+
+ constexpr const SizeF& size() const { return size_; }
+ void set_size(const SizeF& size) { size_ = size; }
+
+ constexpr float right() const { return x() + width(); }
+ constexpr float bottom() const { return y() + height(); }
+
+ constexpr PointF top_right() const { return PointF(right(), y()); }
+ constexpr PointF bottom_left() const { return PointF(x(), bottom()); }
+ constexpr PointF bottom_right() const { return PointF(right(), bottom()); }
+
+ Vector2dF OffsetFromOrigin() const { return Vector2dF(x(), y()); }
+
+ void SetRect(float x, float y, float width, float height) {
+ origin_.SetPoint(x, y);
+ size_.SetSize(width, height);
+ }
+
+ // Shrink the rectangle by a horizontal and vertical distance on all sides.
+ void Inset(float horizontal, float vertical) {
+ Inset(horizontal, vertical, horizontal, vertical);
+ }
+
+ // Shrink the rectangle by the given insets.
+ void Inset(const InsetsF& insets);
+
+ // Shrink the rectangle by the specified amount on each side.
+ void Inset(float left, float top, float right, float bottom);
+
+ // Move the rectangle by a horizontal and vertical distance.
+ void Offset(float horizontal, float vertical);
+ void Offset(const Vector2dF& distance) { Offset(distance.x(), distance.y()); }
+ void operator+=(const Vector2dF& offset);
+ void operator-=(const Vector2dF& offset);
+
+ InsetsF InsetsFrom(const RectF& inner) const;
+
+ // Returns true if the area of the rectangle is zero.
+ bool IsEmpty() const { return size_.IsEmpty(); }
+
+ // A rect is less than another rect if its origin is less than
+ // the other rect's origin. If the origins are equal, then the
+ // shortest rect is less than the other. If the origin and the
+ // height are equal, then the narrowest rect is less than.
+ // This comparison is required to use Rects in sets, or sorted
+ // vectors.
+ bool operator<(const RectF& other) const;
+
+ // 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(float point_x, float point_y) const;
+
+ // Returns true if the specified point is contained by this rectangle.
+ bool Contains(const PointF& point) const {
+ return Contains(point.x(), point.y());
+ }
+
+ // Returns true if this rectangle contains the specified rectangle.
+ bool Contains(const RectF& rect) const;
+
+ // Returns true if this rectangle intersects the specified rectangle.
+ // An empty rectangle doesn't intersect any rectangle.
+ bool Intersects(const RectF& rect) const;
+
+ // Computes the intersection of this rectangle with the given rectangle.
+ void Intersect(const RectF& rect);
+
+ // Computes the union of this rectangle with the given rectangle. The union
+ // is the smallest rectangle containing both rectangles.
+ void Union(const RectF& rect);
+
+ // Computes the rectangle resulting from subtracting |rect| from |*this|,
+ // i.e. the bounding rect of |Region(*this) - Region(rect)|.
+ void Subtract(const RectF& rect);
+
+ // Fits as much of the receiving rectangle into the supplied rectangle as
+ // possible, becoming 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.
+ void AdjustToFit(const RectF& rect);
+
+ // Returns the center of this rectangle.
+ PointF CenterPoint() const;
+
+ // Becomes a rectangle that has the same center point but with a size capped
+ // at given |size|.
+ void ClampToCenteredSize(const SizeF& size);
+
+ // Splits |this| in two halves, |left_half| and |right_half|.
+ void SplitVertically(RectF* left_half, RectF* right_half) 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 RectF& rect) const;
+
+ // Returns the manhattan distance from the rect to the point. If the point is
+ // inside the rect, returns 0.
+ float ManhattanDistanceToPoint(const PointF& point) const;
+
+ // Returns the manhattan distance between the contents of this rect and the
+ // contents of the given rect. That is, if the intersection of the two rects
+ // is non-empty then the function returns 0. If the rects share a side, it
+ // returns the smallest non-zero value appropriate for float.
+ float ManhattanInternalDistance(const RectF& rect) const;
+
+ // Scales the rectangle by |scale|.
+ void Scale(float scale) {
+ Scale(scale, scale);
+ }
+
+ void Scale(float x_scale, float y_scale) {
+ set_origin(ScalePoint(origin(), x_scale, y_scale));
+ set_size(ScaleSize(size(), x_scale, y_scale));
+ }
+
+ // This method reports if the RectF can be safely converted to an integer
+ // Rect. When it is false, some dimension of the RectF is outside the bounds
+ // of what an integer can represent, and converting it to a Rect will require
+ // clamping.
+ bool IsExpressibleAsRect() const;
+
+ std::string ToString() const;
+
+ private:
+ PointF origin_;
+ SizeF size_;
+};
+
+inline bool operator==(const RectF& lhs, const RectF& rhs) {
+ return lhs.origin() == rhs.origin() && lhs.size() == rhs.size();
+}
+
+inline bool operator!=(const RectF& lhs, const RectF& rhs) {
+ return !(lhs == rhs);
+}
+
+inline RectF operator+(const RectF& lhs, const Vector2dF& rhs) {
+ return RectF(lhs.x() + rhs.x(), lhs.y() + rhs.y(),
+ lhs.width(), lhs.height());
+}
+
+inline RectF operator-(const RectF& lhs, const Vector2dF& rhs) {
+ return RectF(lhs.x() - rhs.x(), lhs.y() - rhs.y(),
+ lhs.width(), lhs.height());
+}
+
+inline RectF operator+(const Vector2dF& lhs, const RectF& rhs) {
+ return rhs + lhs;
+}
+
+GFX_EXPORT RectF IntersectRects(const RectF& a, const RectF& b);
+GFX_EXPORT RectF UnionRects(const RectF& a, const RectF& b);
+GFX_EXPORT RectF SubtractRects(const RectF& a, const RectF& b);
+
+inline RectF ScaleRect(const RectF& r, float x_scale, float y_scale) {
+ return RectF(r.x() * x_scale, r.y() * y_scale,
+ r.width() * x_scale, r.height() * y_scale);
+}
+
+inline RectF ScaleRect(const RectF& r, float scale) {
+ return ScaleRect(r, scale, scale);
+}
+
+// Constructs a rectangle with |p1| and |p2| as opposite corners.
+//
+// This could also be thought of as "the smallest rect that contains both
+// points", except that we consider points on the right/bottom edges of the
+// rect to be outside the rect. So technically one or both points will not be
+// contained within the rect, because they will appear on one of these edges.
+GFX_EXPORT RectF BoundingRect(const PointF& p1, const PointF& p2);
+
+// This is declared here for use in gtest-based unit tests but is defined in
+// the //ui/gfx:test_support target. Depend on that to use this in your unit
+// test. This should not be used in production code - call ToString() instead.
+void PrintTo(const RectF& rect, ::std::ostream* os);
+
+} // namespace gfx
+
+#endif // UI_GFX_GEOMETRY_RECT_F_H_
diff --git a/ui/gfx/geometry/safe_integer_conversions.h b/ui/gfx/geometry/safe_integer_conversions.h
new file mode 100644
index 0000000000..5efe134f07
--- /dev/null
+++ b/ui/gfx/geometry/safe_integer_conversions.h
@@ -0,0 +1,62 @@
+// 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_GEOMETRY_SAFE_INTEGER_CONVERSIONS_H_
+#define UI_GFX_GEOMETRY_SAFE_INTEGER_CONVERSIONS_H_
+
+#include <cmath>
+#include <limits>
+
+#include "base/numerics/safe_conversions.h"
+#include "ui/gfx/gfx_export.h"
+
+namespace gfx {
+
+inline int ToFlooredInt(float value) {
+ return base::saturated_cast<int>(std::floor(value));
+}
+
+inline int ToCeiledInt(float value) {
+ return base::saturated_cast<int>(std::ceil(value));
+}
+
+inline int ToFlooredInt(double value) {
+ return base::saturated_cast<int>(std::floor(value));
+}
+
+inline int ToCeiledInt(double value) {
+ return base::saturated_cast<int>(std::ceil(value));
+}
+
+inline int ToRoundedInt(float value) {
+ float rounded;
+ if (value >= 0.0f)
+ rounded = std::floor(value + 0.5f);
+ else
+ rounded = std::ceil(value - 0.5f);
+ return base::saturated_cast<int>(rounded);
+}
+
+inline int ToRoundedInt(double value) {
+ double rounded;
+ if (value >= 0.0)
+ rounded = std::floor(value + 0.5);
+ else
+ rounded = std::ceil(value - 0.5);
+ return base::saturated_cast<int>(rounded);
+}
+
+inline bool IsExpressibleAsInt(float value) {
+ if (value != value)
+ return false; // no int NaN.
+ if (value > std::numeric_limits<int>::max())
+ return false;
+ if (value < std::numeric_limits<int>::min())
+ return false;
+ return true;
+}
+
+} // namespace gfx
+
+#endif // UI_GFX_GEOMETRY_SAFE_INTEGER_CONVERSIONS_H_
diff --git a/ui/gfx/geometry/size.cc b/ui/gfx/geometry/size.cc
new file mode 100644
index 0000000000..69486723a1
--- /dev/null
+++ b/ui/gfx/geometry/size.cc
@@ -0,0 +1,115 @@
+// 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/geometry/size.h"
+
+#if defined(OS_WIN)
+#include <windows.h>
+#elif defined(OS_IOS)
+#include <CoreGraphics/CoreGraphics.h>
+#elif defined(OS_MACOSX)
+#include <ApplicationServices/ApplicationServices.h>
+#endif
+
+#include "base/numerics/safe_math.h"
+#include "base/numerics/saturated_arithmetic.h"
+#include "base/strings/stringprintf.h"
+#include "build/build_config.h"
+#include "ui/gfx/geometry/safe_integer_conversions.h"
+#include "ui/gfx/geometry/size_conversions.h"
+
+namespace gfx {
+
+#if defined(OS_MACOSX)
+Size::Size(const CGSize& s)
+ : width_(s.width < 0 ? 0 : s.width),
+ height_(s.height < 0 ? 0 : 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
+
+int Size::GetArea() const {
+ return GetCheckedArea().ValueOrDie();
+}
+
+base::CheckedNumeric<int> Size::GetCheckedArea() const {
+ base::CheckedNumeric<int> checked_area = width();
+ checked_area *= height();
+ return checked_area;
+}
+
+void Size::Enlarge(int grow_width, int grow_height) {
+ SetSize(base::SaturatedAddition(width(), grow_width),
+ base::SaturatedAddition(height(), grow_height));
+}
+
+void Size::SetToMin(const Size& other) {
+ width_ = width() <= other.width() ? width() : other.width();
+ height_ = height() <= other.height() ? height() : other.height();
+}
+
+void Size::SetToMax(const Size& other) {
+ width_ = width() >= other.width() ? width() : other.width();
+ height_ = height() >= other.height() ? height() : other.height();
+}
+
+std::string Size::ToString() const {
+ return base::StringPrintf("%dx%d", width(), height());
+}
+
+Size ScaleToCeiledSize(const Size& size, float x_scale, float y_scale) {
+ if (x_scale == 1.f && y_scale == 1.f)
+ return size;
+ return ToCeiledSize(ScaleSize(gfx::SizeF(size), x_scale, y_scale));
+}
+
+Size ScaleToCeiledSize(const Size& size, float scale) {
+ if (scale == 1.f)
+ return size;
+ return ToCeiledSize(ScaleSize(gfx::SizeF(size), scale, scale));
+}
+
+Size ScaleToFlooredSize(const Size& size, float x_scale, float y_scale) {
+ if (x_scale == 1.f && y_scale == 1.f)
+ return size;
+ return ToFlooredSize(ScaleSize(gfx::SizeF(size), x_scale, y_scale));
+}
+
+Size ScaleToFlooredSize(const Size& size, float scale) {
+ if (scale == 1.f)
+ return size;
+ return ToFlooredSize(ScaleSize(gfx::SizeF(size), scale, scale));
+}
+
+Size ScaleToRoundedSize(const Size& size, float x_scale, float y_scale) {
+ if (x_scale == 1.f && y_scale == 1.f)
+ return size;
+ return ToRoundedSize(ScaleSize(gfx::SizeF(size), x_scale, y_scale));
+}
+
+Size ScaleToRoundedSize(const Size& size, float scale) {
+ if (scale == 1.f)
+ return size;
+ return ToRoundedSize(ScaleSize(gfx::SizeF(size), scale, scale));
+}
+
+} // namespace gfx
diff --git a/ui/gfx/geometry/size.h b/ui/gfx/geometry/size.h
new file mode 100644
index 0000000000..8ce4178b3c
--- /dev/null
+++ b/ui/gfx/geometry/size.h
@@ -0,0 +1,103 @@
+// 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_GEOMETRY_SIZE_H_
+#define UI_GFX_GEOMETRY_SIZE_H_
+
+#include <iosfwd>
+#include <string>
+
+#include "base/compiler_specific.h"
+#include "base/numerics/safe_math.h"
+#include "build/build_config.h"
+#include "ui/gfx/gfx_export.h"
+
+#if defined(OS_WIN)
+typedef struct tagSIZE SIZE;
+#elif defined(OS_MACOSX)
+typedef struct CGSize CGSize;
+#endif
+
+namespace gfx {
+
+// A size has width and height values.
+class GFX_EXPORT Size {
+ public:
+ constexpr Size() : width_(0), height_(0) {}
+ constexpr Size(int width, int height)
+ : width_(width < 0 ? 0 : width), height_(height < 0 ? 0 : height) {}
+#if defined(OS_MACOSX)
+ explicit Size(const CGSize& s);
+#endif
+
+#if defined(OS_MACOSX)
+ Size& operator=(const CGSize& s);
+#endif
+
+#if defined(OS_WIN)
+ SIZE ToSIZE() const;
+#elif defined(OS_MACOSX)
+ CGSize ToCGSize() const;
+#endif
+
+ constexpr int width() const { return width_; }
+ constexpr int height() const { return height_; }
+
+ void set_width(int width) { width_ = width < 0 ? 0 : width; }
+ void set_height(int height) { height_ = height < 0 ? 0 : height; }
+
+ // This call will CHECK if the area of this size would overflow int.
+ int GetArea() const;
+ // Returns a checked numeric representation of the area.
+ base::CheckedNumeric<int> GetCheckedArea() const;
+
+ void SetSize(int width, int height) {
+ set_width(width);
+ set_height(height);
+ }
+
+ void Enlarge(int grow_width, int grow_height);
+
+ void SetToMin(const Size& other);
+ void SetToMax(const Size& other);
+
+ bool IsEmpty() const { return !width() || !height(); }
+
+ std::string ToString() const;
+
+ private:
+ int width_;
+ int height_;
+};
+
+inline bool operator==(const Size& lhs, const Size& rhs) {
+ return lhs.width() == rhs.width() && lhs.height() == rhs.height();
+}
+
+inline bool operator!=(const Size& lhs, const Size& rhs) {
+ return !(lhs == rhs);
+}
+
+// This is declared here for use in gtest-based unit tests but is defined in
+// the //ui/gfx:test_support target. Depend on that to use this in your unit
+// test. This should not be used in production code - call ToString() instead.
+void PrintTo(const Size& size, ::std::ostream* os);
+
+// Helper methods to scale a gfx::Size to a new gfx::Size.
+GFX_EXPORT Size ScaleToCeiledSize(const Size& size,
+ float x_scale,
+ float y_scale);
+GFX_EXPORT Size ScaleToCeiledSize(const Size& size, float scale);
+GFX_EXPORT Size ScaleToFlooredSize(const Size& size,
+ float x_scale,
+ float y_scale);
+GFX_EXPORT Size ScaleToFlooredSize(const Size& size, float scale);
+GFX_EXPORT Size ScaleToRoundedSize(const Size& size,
+ float x_scale,
+ float y_scale);
+GFX_EXPORT Size ScaleToRoundedSize(const Size& size, float scale);
+
+} // namespace gfx
+
+#endif // UI_GFX_GEOMETRY_SIZE_H_
diff --git a/ui/gfx/geometry/size_conversions.cc b/ui/gfx/geometry/size_conversions.cc
new file mode 100644
index 0000000000..c924e86c9a
--- /dev/null
+++ b/ui/gfx/geometry/size_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/geometry/size_conversions.h"
+
+#include "ui/gfx/geometry/safe_integer_conversions.h"
+
+namespace gfx {
+
+Size ToFlooredSize(const SizeF& size) {
+ int w = ToFlooredInt(size.width());
+ int h = ToFlooredInt(size.height());
+ return Size(w, h);
+}
+
+Size ToCeiledSize(const SizeF& size) {
+ int w = ToCeiledInt(size.width());
+ int h = ToCeiledInt(size.height());
+ return Size(w, h);
+}
+
+Size ToRoundedSize(const SizeF& size) {
+ int w = ToRoundedInt(size.width());
+ int h = ToRoundedInt(size.height());
+ return Size(w, h);
+}
+
+} // namespace gfx
+
diff --git a/ui/gfx/geometry/size_conversions.h b/ui/gfx/geometry/size_conversions.h
new file mode 100644
index 0000000000..96fb79f93c
--- /dev/null
+++ b/ui/gfx/geometry/size_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_GEOMETRY_SIZE_CONVERSIONS_H_
+#define UI_GFX_GEOMETRY_SIZE_CONVERSIONS_H_
+
+#include "ui/gfx/geometry/size.h"
+#include "ui/gfx/geometry/size_f.h"
+
+namespace gfx {
+
+// Returns a Size with each component from the input SizeF floored.
+GFX_EXPORT Size ToFlooredSize(const SizeF& size);
+
+// Returns a Size with each component from the input SizeF ceiled.
+GFX_EXPORT Size ToCeiledSize(const SizeF& size);
+
+// Returns a Size with each component from the input SizeF rounded.
+GFX_EXPORT Size ToRoundedSize(const SizeF& size);
+
+} // namespace gfx
+
+#endif // UI_GFX_GEOMETRY_SIZE_CONVERSIONS_H_
diff --git a/ui/gfx/geometry/size_f.cc b/ui/gfx/geometry/size_f.cc
new file mode 100644
index 0000000000..6d08e18c62
--- /dev/null
+++ b/ui/gfx/geometry/size_f.cc
@@ -0,0 +1,39 @@
+// 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/geometry/size_f.h"
+
+#include "base/strings/stringprintf.h"
+
+namespace gfx {
+
+float SizeF::GetArea() const {
+ return width() * height();
+}
+
+void SizeF::Enlarge(float grow_width, float grow_height) {
+ SetSize(width() + grow_width, height() + grow_height);
+}
+
+void SizeF::SetToMin(const SizeF& other) {
+ width_ = width() <= other.width() ? width() : other.width();
+ height_ = height() <= other.height() ? height() : other.height();
+}
+
+void SizeF::SetToMax(const SizeF& other) {
+ width_ = width() >= other.width() ? width() : other.width();
+ height_ = height() >= other.height() ? height() : other.height();
+}
+
+std::string SizeF::ToString() const {
+ return base::StringPrintf("%fx%f", width(), height());
+}
+
+SizeF ScaleSize(const SizeF& s, float x_scale, float y_scale) {
+ SizeF scaled_s(s);
+ scaled_s.Scale(x_scale, y_scale);
+ return scaled_s;
+}
+
+} // namespace gfx
diff --git a/ui/gfx/geometry/size_f.h b/ui/gfx/geometry/size_f.h
new file mode 100644
index 0000000000..0757ef6481
--- /dev/null
+++ b/ui/gfx/geometry/size_f.h
@@ -0,0 +1,97 @@
+// 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_GEOMETRY_SIZE_F_H_
+#define UI_GFX_GEOMETRY_SIZE_F_H_
+
+#include <iosfwd>
+#include <string>
+
+#include "base/compiler_specific.h"
+#include "base/gtest_prod_util.h"
+#include "ui/gfx/geometry/size.h"
+#include "ui/gfx/gfx_export.h"
+
+namespace gfx {
+
+FORWARD_DECLARE_TEST(SizeTest, TrivialDimensionTests);
+FORWARD_DECLARE_TEST(SizeTest, ClampsToZero);
+FORWARD_DECLARE_TEST(SizeTest, ConsistentClamping);
+
+// A floating version of gfx::Size.
+class GFX_EXPORT SizeF {
+ public:
+ constexpr SizeF() : width_(0.f), height_(0.f) {}
+ constexpr SizeF(float width, float height)
+ : width_(clamp(width)), height_(clamp(height)) {}
+
+ constexpr explicit SizeF(const Size& size)
+ : SizeF(static_cast<float>(size.width()),
+ static_cast<float>(size.height())) {}
+
+ constexpr float width() const { return width_; }
+ constexpr float height() const { return height_; }
+
+ void set_width(float width) { width_ = clamp(width); }
+ void set_height(float height) { height_ = clamp(height); }
+
+ float GetArea() const;
+
+ void SetSize(float width, float height) {
+ set_width(width);
+ set_height(height);
+ }
+
+ void Enlarge(float grow_width, float grow_height);
+
+ void SetToMin(const SizeF& other);
+ void SetToMax(const SizeF& other);
+
+ bool IsEmpty() const { return !width() || !height(); }
+
+ void Scale(float scale) {
+ Scale(scale, scale);
+ }
+
+ void Scale(float x_scale, float y_scale) {
+ SetSize(width() * x_scale, height() * y_scale);
+ }
+
+ std::string ToString() const;
+
+ private:
+ FRIEND_TEST_ALL_PREFIXES(SizeTest, TrivialDimensionTests);
+ FRIEND_TEST_ALL_PREFIXES(SizeTest, ClampsToZero);
+ FRIEND_TEST_ALL_PREFIXES(SizeTest, ConsistentClamping);
+
+ static constexpr float kTrivial = 8.f * std::numeric_limits<float>::epsilon();
+
+ static constexpr float clamp(float f) { return f > kTrivial ? f : 0.f; }
+
+ float width_;
+ float height_;
+};
+
+inline bool operator==(const SizeF& lhs, const SizeF& rhs) {
+ return lhs.width() == rhs.width() && lhs.height() == rhs.height();
+}
+
+inline bool operator!=(const SizeF& lhs, const SizeF& rhs) {
+ return !(lhs == rhs);
+}
+
+GFX_EXPORT SizeF ScaleSize(const SizeF& p, float x_scale, float y_scale);
+
+inline SizeF ScaleSize(const SizeF& p, float scale) {
+ return ScaleSize(p, scale, scale);
+}
+
+// This is declared here for use in gtest-based unit tests but is defined in
+// the //ui/gfx:test_support target. Depend on that to use this in your unit
+// test. This should not be used in production code - call ToString() instead.
+void PrintTo(const SizeF& size, ::std::ostream* os);
+
+} // namespace gfx
+
+#endif // UI_GFX_GEOMETRY_SIZE_F_H_
diff --git a/ui/gfx/geometry/vector2d.cc b/ui/gfx/geometry/vector2d.cc
new file mode 100644
index 0000000000..2b4875c39c
--- /dev/null
+++ b/ui/gfx/geometry/vector2d.cc
@@ -0,0 +1,40 @@
+// 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/geometry/vector2d.h"
+
+#include <cmath>
+
+#include "base/numerics/saturated_arithmetic.h"
+#include "base/strings/stringprintf.h"
+
+namespace gfx {
+
+bool Vector2d::IsZero() const {
+ return x_ == 0 && y_ == 0;
+}
+
+void Vector2d::Add(const Vector2d& other) {
+ x_ = base::SaturatedAddition(other.x_, x_);
+ y_ = base::SaturatedAddition(other.y_, y_);
+}
+
+void Vector2d::Subtract(const Vector2d& other) {
+ x_ = base::SaturatedSubtraction(x_, other.x_);
+ y_ = base::SaturatedSubtraction(y_, other.y_);
+}
+
+int64_t Vector2d::LengthSquared() const {
+ return static_cast<int64_t>(x_) * x_ + static_cast<int64_t>(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/geometry/vector2d.h b/ui/gfx/geometry/vector2d.h
new file mode 100644
index 0000000000..4b45667adf
--- /dev/null
+++ b/ui/gfx/geometry/vector2d.h
@@ -0,0 +1,100 @@
+// 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_GEOMETRY_VECTOR2D_H_
+#define UI_GFX_GEOMETRY_VECTOR2D_H_
+
+#include <stdint.h>
+
+#include <iosfwd>
+#include <string>
+
+#include "ui/gfx/geometry/vector2d_f.h"
+#include "ui/gfx/gfx_export.h"
+
+namespace gfx {
+
+class GFX_EXPORT Vector2d {
+ public:
+ constexpr Vector2d() : x_(0), y_(0) {}
+ constexpr Vector2d(int x, int y) : x_(x), y_(y) {}
+
+ constexpr int x() const { return x_; }
+ void set_x(int x) { x_ = x; }
+
+ constexpr 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); }
+
+ void SetToMin(const Vector2d& other) {
+ x_ = x_ <= other.x_ ? x_ : other.x_;
+ y_ = y_ <= other.y_ ? y_ : other.y_;
+ }
+
+ void SetToMax(const Vector2d& other) {
+ x_ = x_ >= other.x_ ? x_ : other.x_;
+ y_ = y_ >= other.y_ ? y_ : other.y_;
+ }
+
+ // 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_t LengthSquared() const;
+ // Gives the diagonal length of the vector.
+ float Length() const;
+
+ std::string ToString() const;
+
+ operator Vector2dF() const {
+ return Vector2dF(static_cast<float>(x()), static_cast<float>(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;
+}
+
+// This is declared here for use in gtest-based unit tests but is defined in
+// the //ui/gfx:test_support target. Depend on that to use this in your unit
+// test. This should not be used in production code - call ToString() instead.
+void PrintTo(const Vector2d& vector, ::std::ostream* os);
+
+} // namespace gfx
+
+#endif // UI_GFX_GEOMETRY_VECTOR2D_H_
diff --git a/ui/gfx/geometry/vector2d_f.cc b/ui/gfx/geometry/vector2d_f.cc
new file mode 100644
index 0000000000..ccb15ae0c4
--- /dev/null
+++ b/ui/gfx/geometry/vector2d_f.cc
@@ -0,0 +1,60 @@
+// 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/geometry/vector2d_f.h"
+
+#include <cmath>
+
+#include "base/strings/stringprintf.h"
+
+namespace gfx {
+
+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;
+}
+
+double CrossProduct(const Vector2dF& lhs, const Vector2dF& rhs) {
+ return static_cast<double>(lhs.x()) * rhs.y() -
+ static_cast<double>(lhs.y()) * rhs.x();
+}
+
+double DotProduct(const Vector2dF& lhs, const Vector2dF& rhs) {
+ return static_cast<double>(lhs.x()) * rhs.x() +
+ static_cast<double>(lhs.y()) * rhs.y();
+}
+
+Vector2dF ScaleVector2d(const Vector2dF& v, float x_scale, float y_scale) {
+ Vector2dF scaled_v(v);
+ scaled_v.Scale(x_scale, y_scale);
+ return scaled_v;
+}
+
+} // namespace gfx
diff --git a/ui/gfx/geometry/vector2d_f.h b/ui/gfx/geometry/vector2d_f.h
new file mode 100644
index 0000000000..92f7f87753
--- /dev/null
+++ b/ui/gfx/geometry/vector2d_f.h
@@ -0,0 +1,118 @@
+// 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_GEOMETRY_VECTOR2D_F_H_
+#define UI_GFX_GEOMETRY_VECTOR2D_F_H_
+
+#include <iosfwd>
+#include <string>
+
+#include "ui/gfx/gfx_export.h"
+
+namespace gfx {
+
+class GFX_EXPORT Vector2dF {
+ public:
+ constexpr Vector2dF() : x_(0), y_(0) {}
+ constexpr Vector2dF(float x, float y) : x_(x), y_(y) {}
+
+ constexpr float x() const { return x_; }
+ void set_x(float x) { x_ = x; }
+
+ constexpr 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); }
+
+ void SetToMin(const Vector2dF& other) {
+ x_ = x_ <= other.x_ ? x_ : other.x_;
+ y_ = y_ <= other.y_ ? y_ : other.y_;
+ }
+
+ void SetToMax(const Vector2dF& other) {
+ x_ = x_ >= other.x_ ? x_ : other.x_;
+ y_ = y_ >= other.y_ ? y_ : other.y_;
+ }
+
+ // 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 bool operator!=(const Vector2dF& lhs, const Vector2dF& rhs) {
+ return !(lhs == rhs);
+}
+
+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;
+}
+
+// Return the cross product of two vectors.
+GFX_EXPORT double CrossProduct(const Vector2dF& lhs, const Vector2dF& rhs);
+
+// Return the dot product of two vectors.
+GFX_EXPORT double DotProduct(const Vector2dF& lhs, const Vector2dF& rhs);
+
+// Return a vector that is |v| scaled by the given scale factors along each
+// axis.
+GFX_EXPORT Vector2dF ScaleVector2d(const Vector2dF& v,
+ float x_scale,
+ float y_scale);
+
+// Return a vector that is |v| scaled by the given scale factor.
+inline Vector2dF ScaleVector2d(const Vector2dF& v, float scale) {
+ return ScaleVector2d(v, scale, scale);
+}
+
+// This is declared here for use in gtest-based unit tests but is defined in
+// the //ui/gfx:test_support target. Depend on that to use this in your unit
+// test. This should not be used in production code - call ToString() instead.
+void PrintTo(const Vector2dF& vector, ::std::ostream* os);
+
+} // namespace gfx
+
+#endif // UI_GFX_GEOMETRY_VECTOR2D_F_H_
diff --git a/ui/gfx/gfx_export.h b/ui/gfx/gfx_export.h
new file mode 100644
index 0000000000..20c8bb1681
--- /dev/null
+++ b/ui/gfx/gfx_export.h
@@ -0,0 +1,29 @@
+// Copyright (c) 2013 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_GFX_EXPORT_H_
+#define UI_GFX_GFX_EXPORT_H_
+
+#if defined(COMPONENT_BUILD)
+#if defined(WIN32)
+
+#if defined(GFX_IMPLEMENTATION)
+#define GFX_EXPORT __declspec(dllexport)
+#else
+#define GFX_EXPORT __declspec(dllimport)
+#endif // defined(GFX_IMPLEMENTATION)
+
+#else // defined(WIN32)
+#if defined(GFX_IMPLEMENTATION)
+#define GFX_EXPORT __attribute__((visibility("default")))
+#else
+#define GFX_EXPORT
+#endif
+#endif
+
+#else // defined(COMPONENT_BUILD)
+#define GFX_EXPORT
+#endif
+
+#endif // UI_GFX_GFX_EXPORT_H_
diff --git a/ui/gfx/range/BUILD.gn b/ui/gfx/range/BUILD.gn
new file mode 100644
index 0000000000..0a8d8b2338
--- /dev/null
+++ b/ui/gfx/range/BUILD.gn
@@ -0,0 +1,33 @@
+# Copyright 2016 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.
+
+component("range") {
+ sources = [
+ "gfx_range_export.h",
+ "range.cc",
+ "range.h",
+ "range_f.cc",
+ "range_f.h",
+ "range_mac.mm",
+ "range_win.cc",
+ ]
+
+ if (is_ios) {
+ set_sources_assignment_filter([])
+ sources += [ "range_mac.mm" ]
+ set_sources_assignment_filter(sources_assignment_filter)
+ }
+
+ configs += [
+ # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
+ "//build/config/compiler:no_size_t_to_int_warning",
+ ]
+
+ defines = [ "GFX_RANGE_IMPLEMENTATION" ]
+
+ deps = [
+ "//base",
+ "//ui/gfx:gfx_export",
+ ]
+}
diff --git a/ui/gfx/range/gfx_range_export.h b/ui/gfx/range/gfx_range_export.h
new file mode 100644
index 0000000000..5634c49770
--- /dev/null
+++ b/ui/gfx/range/gfx_range_export.h
@@ -0,0 +1,29 @@
+// Copyright 2016 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 GFX_RANGE_EXPORT_H_
+#define GFX_RANGE_EXPORT_H_
+
+#if defined(COMPONENT_BUILD)
+#if defined(WIN32)
+
+#if defined(GFX_RANGE_IMPLEMENTATION)
+#define GFX_RANGE_EXPORT __declspec(dllexport)
+#else
+#define GFX_RANGE_EXPORT __declspec(dllimport)
+#endif // defined(GFX_RANGE_IMPLEMENTATION)
+
+#else // defined(WIN32)
+#if defined(GFX_RANGE_IMPLEMENTATION)
+#define GFX_RANGE_EXPORT __attribute__((visibility("default")))
+#else
+#define GFX_RANGE_EXPORT
+#endif
+#endif
+
+#else // defined(COMPONENT_BUILD)
+#define GFX_RANGE_EXPORT
+#endif
+
+#endif // GFX_RANGE_EXPORT_H_
diff --git a/ui/gfx/range/range.cc b/ui/gfx/range/range.cc
new file mode 100644
index 0000000000..fa837d0070
--- /dev/null
+++ b/ui/gfx/range/range.cc
@@ -0,0 +1,34 @@
+// 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/range/range.h"
+
+#include <inttypes.h>
+
+#include <algorithm>
+
+#include "base/logging.h"
+#include "base/strings/stringprintf.h"
+
+namespace gfx {
+
+Range Range::Intersect(const Range& range) const {
+ uint32_t min = std::max(GetMin(), range.GetMin());
+ uint32_t max = std::min(GetMax(), range.GetMax());
+
+ if (min >= max) // No intersection.
+ return InvalidRange();
+
+ return Range(min, max);
+}
+
+std::string Range::ToString() const {
+ return base::StringPrintf("{%" PRIu32 ",%" PRIu32 "}", start(), end());
+}
+
+std::ostream& operator<<(std::ostream& os, const Range& range) {
+ return os << range.ToString();
+}
+
+} // namespace gfx
diff --git a/ui/gfx/range/range.h b/ui/gfx/range/range.h
new file mode 100644
index 0000000000..e785eb6c70
--- /dev/null
+++ b/ui/gfx/range/range.h
@@ -0,0 +1,139 @@
+// 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_RANGE_RANGE_H_
+#define UI_GFX_RANGE_RANGE_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <limits>
+#include <ostream>
+#include <string>
+
+#include "build/build_config.h"
+#include "ui/gfx/range/gfx_range_export.h"
+
+#if defined(OS_MACOSX)
+#if __OBJC__
+#import <Foundation/Foundation.h>
+#else
+typedef struct _NSRange NSRange;
+#endif
+#endif // defined(OS_MACOSX)
+
+#if defined(OS_WIN)
+#include <windows.h>
+#include <richedit.h>
+#endif
+
+namespace gfx {
+
+// A Range contains two integer values that represent a numeric range, like the
+// range of characters in a text selection. A range is made of a start and end
+// position; when they are the same, the Range is akin to a caret. Note that
+// |start_| can be greater than |end_| to respect the directionality of the
+// range.
+class GFX_RANGE_EXPORT Range {
+ public:
+ // Creates an empty range {0,0}.
+ constexpr Range() : Range(0) {}
+
+ // Initializes the range with a start and end.
+ constexpr Range(uint32_t start, uint32_t end) : start_(start), end_(end) {}
+
+ // Initializes the range with the same start and end positions.
+ constexpr explicit Range(uint32_t position) : Range(position, position) {}
+
+ // Platform constructors.
+#if defined(OS_MACOSX)
+ explicit Range(const NSRange& range);
+#elif defined(OS_WIN)
+ // The |total_length| paramater should be used if the CHARRANGE is set to
+ // {0,-1} to indicate the whole range.
+ Range(const CHARRANGE& range, LONG total_length = -1);
+#endif
+
+ // Returns a range that is invalid, which is {UINT32_MAX,UINT32_MAX}.
+ static constexpr Range InvalidRange() {
+ return Range(std::numeric_limits<uint32_t>::max());
+ }
+
+ // Checks if the range is valid through comparison to InvalidRange().
+ constexpr bool IsValid() const { return *this != InvalidRange(); }
+
+ // Getters and setters.
+ constexpr uint32_t start() const { return start_; }
+ void set_start(uint32_t start) { start_ = start; }
+
+ constexpr uint32_t end() const { return end_; }
+ void set_end(uint32_t end) { end_ = end; }
+
+ // Returns the absolute value of the length.
+ constexpr uint32_t length() const { return GetMax() - GetMin(); }
+
+ constexpr bool is_reversed() const { return start() > end(); }
+ constexpr bool is_empty() const { return start() == end(); }
+
+ // Returns the minimum and maximum values.
+ constexpr uint32_t GetMin() const {
+ return start() < end() ? start() : end();
+ }
+ constexpr uint32_t GetMax() const {
+ return start() > end() ? start() : end();
+ }
+
+ constexpr bool operator==(const Range& other) const {
+ return start() == other.start() && end() == other.end();
+ }
+ constexpr bool operator!=(const Range& other) const {
+ return !(*this == other);
+ }
+ constexpr bool EqualsIgnoringDirection(const Range& other) const {
+ return GetMin() == other.GetMin() && GetMax() == other.GetMax();
+ }
+
+ // Returns true if this range intersects the specified |range|.
+ constexpr bool Intersects(const Range& range) const {
+ return IsValid() && range.IsValid() &&
+ !(range.GetMax() < GetMin() || range.GetMin() >= GetMax());
+ }
+
+ // Returns true if this range contains the specified |range|.
+ constexpr bool Contains(const Range& range) const {
+ return IsValid() && range.IsValid() && GetMin() <= range.GetMin() &&
+ range.GetMax() <= GetMax();
+ }
+
+ // Computes the intersection of this range with the given |range|.
+ // If they don't intersect, it returns an InvalidRange().
+ // The returned range is always empty or forward (never reversed).
+ Range Intersect(const Range& range) const;
+
+#if defined(OS_MACOSX)
+ Range& operator=(const NSRange& range);
+
+ // NSRange does not store the directionality of a range, so if this
+ // is_reversed(), the range will get flipped when converted to an NSRange.
+ NSRange ToNSRange() const;
+#elif defined(OS_WIN)
+ CHARRANGE ToCHARRANGE() const;
+#endif
+ // GTK+ has no concept of a range.
+
+ std::string ToString() const;
+
+ private:
+ // Note: we use uint32_t instead of size_t because this struct is sent over
+ // IPC which could span 32 & 64 bit processes. This is fine since text spans
+ // shouldn't exceed UINT32_MAX even on 64 bit builds.
+ uint32_t start_;
+ uint32_t end_;
+};
+
+GFX_RANGE_EXPORT std::ostream& operator<<(std::ostream& os, const Range& range);
+
+} // namespace gfx
+
+#endif // UI_GFX_RANGE_RANGE_H_
diff --git a/ui/gfx/range/range_f.cc b/ui/gfx/range/range_f.cc
new file mode 100644
index 0000000000..b3bfc69569
--- /dev/null
+++ b/ui/gfx/range/range_f.cc
@@ -0,0 +1,58 @@
+// Copyright 2015 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/range/range_f.h"
+
+#include <stddef.h>
+
+#include <algorithm>
+#include <cmath>
+
+#include "base/format_macros.h"
+#include "base/strings/stringprintf.h"
+
+namespace gfx {
+
+RangeF RangeF::Intersect(const RangeF& range) const {
+ float min = std::max(GetMin(), range.GetMin());
+ float max = std::min(GetMax(), range.GetMax());
+
+ if (min >= max) // No intersection.
+ return InvalidRange();
+
+ return RangeF(min, max);
+}
+
+RangeF RangeF::Intersect(const Range& range) const {
+ RangeF range_f(range.start(), range.end());
+ return Intersect(range_f);
+}
+
+Range RangeF::Floor() const {
+ uint32_t start = start_ > 0 ? static_cast<uint32_t>(std::floor(start_)) : 0;
+ uint32_t end = end_ > 0 ? static_cast<uint32_t>(std::floor(end_)) : 0;
+ return Range(start, end);
+}
+
+Range RangeF::Ceil() const {
+ uint32_t start = start_ > 0 ? static_cast<uint32_t>(std::ceil(start_)) : 0;
+ uint32_t end = end_ > 0 ? static_cast<uint32_t>(std::ceil(end_)) : 0;
+ return Range(start, end);
+}
+
+Range RangeF::Round() const {
+ uint32_t start = start_ > 0 ? static_cast<uint32_t>(std::round(start_)) : 0;
+ uint32_t end = end_ > 0 ? static_cast<uint32_t>(std::round(end_)) : 0;
+ return Range(start, end);
+}
+
+std::string RangeF::ToString() const {
+ return base::StringPrintf("{%f,%f}", start(), end());
+}
+
+std::ostream& operator<<(std::ostream& os, const RangeF& range) {
+ return os << range.ToString();
+}
+
+} // namespace gfx
diff --git a/ui/gfx/range/range_f.h b/ui/gfx/range/range_f.h
new file mode 100644
index 0000000000..1d58ad4c9f
--- /dev/null
+++ b/ui/gfx/range/range_f.h
@@ -0,0 +1,101 @@
+// Copyright 2015 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_RANGE_RANGE_F_H_
+#define UI_GFX_RANGE_RANGE_F_H_
+
+#include <limits>
+#include <ostream>
+#include <string>
+
+#include "ui/gfx/range/gfx_range_export.h"
+#include "ui/gfx/range/range.h"
+
+namespace gfx {
+
+// A float version of Range. RangeF is made of a start and end position; when
+// they are the same, the range is empty. Note that |start_| can be greater
+// than |end_| to respect the directionality of the range.
+class GFX_RANGE_EXPORT RangeF {
+ public:
+ // Creates an empty range {0,0}.
+ constexpr RangeF() : RangeF(0.f) {}
+
+ // Initializes the range with a start and end.
+ constexpr RangeF(float start, float end) : start_(start), end_(end) {}
+
+ // Initializes the range with the same start and end positions.
+ constexpr explicit RangeF(float position) : RangeF(position, position) {}
+
+ // Returns a range that is invalid, which is {float_max,float_max}.
+ static constexpr RangeF InvalidRange() {
+ return RangeF(std::numeric_limits<float>::max());
+ }
+
+ // Checks if the range is valid through comparison to InvalidRange().
+ constexpr bool IsValid() const { return *this != InvalidRange(); }
+
+ // Getters and setters.
+ constexpr float start() const { return start_; }
+ void set_start(float start) { start_ = start; }
+
+ constexpr float end() const { return end_; }
+ void set_end(float end) { end_ = end; }
+
+ // Returns the absolute value of the length.
+ constexpr float length() const { return GetMax() - GetMin(); }
+
+ constexpr bool is_reversed() const { return start() > end(); }
+ constexpr bool is_empty() const { return start() == end(); }
+
+ // Returns the minimum and maximum values.
+ constexpr float GetMin() const { return start() < end() ? start() : end(); }
+ constexpr float GetMax() const { return start() > end() ? start() : end(); }
+
+ constexpr bool operator==(const RangeF& other) const {
+ return start() == other.start() && end() == other.end();
+ }
+ constexpr bool operator!=(const RangeF& other) const {
+ return !(*this == other);
+ }
+ constexpr bool EqualsIgnoringDirection(const RangeF& other) const {
+ return GetMin() == other.GetMin() && GetMax() == other.GetMax();
+ }
+
+ // Returns true if this range intersects the specified |range|.
+ constexpr bool Intersects(const RangeF& range) const {
+ return IsValid() && range.IsValid() &&
+ !(range.GetMax() < GetMin() || range.GetMin() >= GetMax());
+ }
+
+ // Returns true if this range contains the specified |range|.
+ constexpr bool Contains(const RangeF& range) const {
+ return IsValid() && range.IsValid() && GetMin() <= range.GetMin() &&
+ range.GetMax() <= GetMax();
+ }
+
+ // Computes the intersection of this range with the given |range|.
+ // If they don't intersect, it returns an InvalidRange().
+ // The returned range is always empty or forward (never reversed).
+ RangeF Intersect(const RangeF& range) const;
+ RangeF Intersect(const Range& range) const;
+
+ // Floor/Ceil/Round the start and end values of the given RangeF.
+ Range Floor() const;
+ Range Ceil() const;
+ Range Round() const;
+
+ std::string ToString() const;
+
+ private:
+ float start_;
+ float end_;
+};
+
+GFX_RANGE_EXPORT std::ostream& operator<<(std::ostream& os,
+ const RangeF& range);
+
+} // namespace gfx
+
+#endif // UI_GFX_RANGE_RANGE_F_H_
diff --git a/ui/gfx/range/range_unittest.cc b/ui/gfx/range/range_unittest.cc
new file mode 100644
index 0000000000..4ae7a67c4f
--- /dev/null
+++ b/ui/gfx/range/range_unittest.cc
@@ -0,0 +1,266 @@
+// Copyright (c) 2011 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 <sstream>
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/range/range.h"
+#include "ui/gfx/range/range_f.h"
+
+namespace {
+
+template <typename T>
+class RangeTest : public testing::Test {
+};
+
+typedef testing::Types<gfx::Range, gfx::RangeF> RangeTypes;
+TYPED_TEST_CASE(RangeTest, RangeTypes);
+
+template <typename T>
+void TestContainsAndIntersects(const T& r1,
+ const T& r2,
+ const T& r3) {
+ EXPECT_TRUE(r1.Intersects(r1));
+ EXPECT_TRUE(r1.Contains(r1));
+ EXPECT_EQ(T(10, 12), r1.Intersect(r1));
+
+ EXPECT_FALSE(r1.Intersects(r2));
+ EXPECT_FALSE(r1.Contains(r2));
+ EXPECT_TRUE(r1.Intersect(r2).is_empty());
+ EXPECT_FALSE(r2.Intersects(r1));
+ EXPECT_FALSE(r2.Contains(r1));
+ EXPECT_TRUE(r2.Intersect(r1).is_empty());
+
+ EXPECT_TRUE(r1.Intersects(r3));
+ EXPECT_TRUE(r3.Intersects(r1));
+ EXPECT_TRUE(r3.Contains(r1));
+ EXPECT_FALSE(r1.Contains(r3));
+ EXPECT_EQ(T(10, 12), r1.Intersect(r3));
+ EXPECT_EQ(T(10, 12), r3.Intersect(r1));
+
+ EXPECT_TRUE(r2.Intersects(r3));
+ EXPECT_TRUE(r3.Intersects(r2));
+ EXPECT_FALSE(r3.Contains(r2));
+ EXPECT_FALSE(r2.Contains(r3));
+ EXPECT_EQ(T(5, 8), r2.Intersect(r3));
+ EXPECT_EQ(T(5, 8), r3.Intersect(r2));
+}
+
+} // namespace
+
+TYPED_TEST(RangeTest, EmptyInit) {
+ TypeParam r;
+ EXPECT_EQ(0U, r.start());
+ EXPECT_EQ(0U, r.end());
+ EXPECT_EQ(0U, r.length());
+ EXPECT_FALSE(r.is_reversed());
+ EXPECT_TRUE(r.is_empty());
+ EXPECT_TRUE(r.IsValid());
+ EXPECT_EQ(0U, r.GetMin());
+ EXPECT_EQ(0U, r.GetMax());
+}
+
+TYPED_TEST(RangeTest, StartEndInit) {
+ TypeParam r(10, 15);
+ EXPECT_EQ(10U, r.start());
+ EXPECT_EQ(15U, r.end());
+ EXPECT_EQ(5U, r.length());
+ EXPECT_FALSE(r.is_reversed());
+ EXPECT_FALSE(r.is_empty());
+ EXPECT_TRUE(r.IsValid());
+ EXPECT_EQ(10U, r.GetMin());
+ EXPECT_EQ(15U, r.GetMax());
+}
+
+TYPED_TEST(RangeTest, StartEndReversedInit) {
+ TypeParam r(10, 5);
+ EXPECT_EQ(10U, r.start());
+ EXPECT_EQ(5U, r.end());
+ EXPECT_EQ(5U, r.length());
+ EXPECT_TRUE(r.is_reversed());
+ EXPECT_FALSE(r.is_empty());
+ EXPECT_TRUE(r.IsValid());
+ EXPECT_EQ(5U, r.GetMin());
+ EXPECT_EQ(10U, r.GetMax());
+}
+
+TYPED_TEST(RangeTest, PositionInit) {
+ TypeParam r(12);
+ EXPECT_EQ(12U, r.start());
+ EXPECT_EQ(12U, r.end());
+ EXPECT_EQ(0U, r.length());
+ EXPECT_FALSE(r.is_reversed());
+ EXPECT_TRUE(r.is_empty());
+ EXPECT_TRUE(r.IsValid());
+ EXPECT_EQ(12U, r.GetMin());
+ EXPECT_EQ(12U, r.GetMax());
+}
+
+TYPED_TEST(RangeTest, InvalidRange) {
+ TypeParam r(TypeParam::InvalidRange());
+ EXPECT_EQ(0U, r.length());
+ EXPECT_EQ(r.start(), r.end());
+ EXPECT_EQ(r.GetMax(), r.GetMin());
+ EXPECT_FALSE(r.is_reversed());
+ EXPECT_TRUE(r.is_empty());
+ EXPECT_FALSE(r.IsValid());
+ EXPECT_EQ(r, TypeParam::InvalidRange());
+ EXPECT_TRUE(r.EqualsIgnoringDirection(TypeParam::InvalidRange()));
+}
+
+TYPED_TEST(RangeTest, Equality) {
+ TypeParam r1(10, 4);
+ TypeParam r2(10, 4);
+ TypeParam r3(10, 2);
+ EXPECT_EQ(r1, r2);
+ EXPECT_NE(r1, r3);
+ EXPECT_NE(r2, r3);
+
+ TypeParam r4(11, 4);
+ EXPECT_NE(r1, r4);
+ EXPECT_NE(r2, r4);
+ EXPECT_NE(r3, r4);
+
+ TypeParam r5(12, 5);
+ EXPECT_NE(r1, r5);
+ EXPECT_NE(r2, r5);
+ EXPECT_NE(r3, r5);
+}
+
+TYPED_TEST(RangeTest, EqualsIgnoringDirection) {
+ TypeParam r1(10, 5);
+ TypeParam r2(5, 10);
+ EXPECT_TRUE(r1.EqualsIgnoringDirection(r2));
+}
+
+TYPED_TEST(RangeTest, SetStart) {
+ TypeParam r(10, 20);
+ EXPECT_EQ(10U, r.start());
+ EXPECT_EQ(10U, r.length());
+
+ r.set_start(42);
+ EXPECT_EQ(42U, r.start());
+ EXPECT_EQ(20U, r.end());
+ EXPECT_EQ(22U, r.length());
+ EXPECT_TRUE(r.is_reversed());
+}
+
+TYPED_TEST(RangeTest, SetEnd) {
+ TypeParam r(10, 13);
+ EXPECT_EQ(10U, r.start());
+ EXPECT_EQ(3U, r.length());
+
+ r.set_end(20);
+ EXPECT_EQ(10U, r.start());
+ EXPECT_EQ(20U, r.end());
+ EXPECT_EQ(10U, r.length());
+}
+
+TYPED_TEST(RangeTest, SetStartAndEnd) {
+ TypeParam r;
+ r.set_end(5);
+ r.set_start(1);
+ EXPECT_EQ(1U, r.start());
+ EXPECT_EQ(5U, r.end());
+ EXPECT_EQ(4U, r.length());
+ EXPECT_EQ(1U, r.GetMin());
+ EXPECT_EQ(5U, r.GetMax());
+}
+
+TYPED_TEST(RangeTest, ReversedRange) {
+ TypeParam r(10, 5);
+ EXPECT_EQ(10U, r.start());
+ EXPECT_EQ(5U, r.end());
+ EXPECT_EQ(5U, r.length());
+ EXPECT_TRUE(r.is_reversed());
+ EXPECT_TRUE(r.IsValid());
+ EXPECT_EQ(5U, r.GetMin());
+ EXPECT_EQ(10U, r.GetMax());
+}
+
+TYPED_TEST(RangeTest, SetReversedRange) {
+ TypeParam r(10, 20);
+ r.set_start(25);
+ EXPECT_EQ(25U, r.start());
+ EXPECT_EQ(20U, r.end());
+ EXPECT_EQ(5U, r.length());
+ EXPECT_TRUE(r.is_reversed());
+ EXPECT_TRUE(r.IsValid());
+
+ r.set_end(21);
+ EXPECT_EQ(25U, r.start());
+ EXPECT_EQ(21U, r.end());
+ EXPECT_EQ(4U, r.length());
+ EXPECT_TRUE(r.IsValid());
+ EXPECT_EQ(21U, r.GetMin());
+ EXPECT_EQ(25U, r.GetMax());
+}
+
+TYPED_TEST(RangeTest, ContainAndIntersect) {
+ {
+ SCOPED_TRACE("contain and intersect");
+ TypeParam r1(10, 12);
+ TypeParam r2(1, 8);
+ TypeParam r3(5, 12);
+ TestContainsAndIntersects(r1, r2, r3);
+ }
+ {
+ SCOPED_TRACE("contain and intersect: reversed");
+ TypeParam r1(12, 10);
+ TypeParam r2(8, 1);
+ TypeParam r3(12, 5);
+ TestContainsAndIntersects(r1, r2, r3);
+ }
+ // Invalid rect tests
+ TypeParam r1(10, 12);
+ TypeParam r2(8, 1);
+ TypeParam invalid = r1.Intersect(r2);
+ EXPECT_FALSE(invalid.IsValid());
+ EXPECT_FALSE(invalid.Contains(invalid));
+ EXPECT_FALSE(invalid.Contains(r1));
+ EXPECT_FALSE(invalid.Intersects(invalid));
+ EXPECT_FALSE(invalid.Intersects(r1));
+ EXPECT_FALSE(r1.Contains(invalid));
+ EXPECT_FALSE(r1.Intersects(invalid));
+}
+
+TEST(RangeTest, RangeFConverterTest) {
+ gfx::RangeF range_f(1.2f, 3.9f);
+ gfx::Range range = range_f.Floor();
+ EXPECT_EQ(1U, range.start());
+ EXPECT_EQ(3U, range.end());
+
+ range = range_f.Ceil();
+ EXPECT_EQ(2U, range.start());
+ EXPECT_EQ(4U, range.end());
+
+ range = range_f.Round();
+ EXPECT_EQ(1U, range.start());
+ EXPECT_EQ(4U, range.end());
+
+ // Test for negative values.
+ range_f.set_start(-1.2f);
+ range_f.set_end(-3.8f);
+ range = range_f.Floor();
+ EXPECT_EQ(0U, range.start());
+ EXPECT_EQ(0U, range.end());
+
+ range = range_f.Ceil();
+ EXPECT_EQ(0U, range.start());
+ EXPECT_EQ(0U, range.end());
+
+ range = range_f.Round();
+ EXPECT_EQ(0U, range.start());
+ EXPECT_EQ(0U, range.end());
+}
+
+TEST(RangeTest, ToString) {
+ gfx::Range range(4, 7);
+ EXPECT_EQ("{4,7}", range.ToString());
+
+ range = gfx::Range::InvalidRange();
+ std::ostringstream expected;
+ expected << "{" << range.start() << "," << range.end() << "}";
+ EXPECT_EQ(expected.str(), range.ToString());
+}