aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuis Hector Chavez <lhchavez@google.com>2017-12-14 21:17:47 -0800
committerLuis Hector Chavez <lhchavez@google.com>2017-12-18 10:00:00 -0800
commit2256d987b3a5bffb7da4a7212a2e482d45785957 (patch)
tree265a4118e7d55b940cce5f0c62ae662e3eba241e
parent3033949ebb841470a2cb165e8c50c7b413b0417c (diff)
downloadlibmojo-2256d987b3a5bffb7da4a7212a2e482d45785957.tar.gz
libmojo: Add additional files to support more typemaps
This change adds some more files (in device/ and ui/gfx/) to support ARC's typemaps. Bug: 38318511 Test: m Change-Id: I5b9cb98d7f35b302e0d9605c5cd35c9f745fe07c
-rw-r--r--Android.mk19
-rw-r--r--build_mojom.mk6
-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--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/mojo/BUILD.gn52
-rw-r--r--ui/gfx/geometry/mojo/DEPS4
-rw-r--r--ui/gfx/geometry/mojo/geometry.mojom63
-rw-r--r--ui/gfx/geometry/mojo/geometry.typemap32
-rw-r--r--ui/gfx/geometry/mojo/geometry_struct_traits.h146
-rw-r--r--ui/gfx/geometry/mojo/geometry_struct_traits_unittest.cc206
-rw-r--r--ui/gfx/geometry/mojo/geometry_traits_test_service.mojom41
-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/mojo/BUILD.gn49
-rw-r--r--ui/gfx/range/mojo/DEPS4
-rw-r--r--ui/gfx/range/mojo/range.mojom15
-rw-r--r--ui/gfx/range/mojo/range.typemap17
-rw-r--r--ui/gfx/range/mojo/range_struct_traits.h38
-rw-r--r--ui/gfx/range/mojo/range_struct_traits_unittest.cc68
-rw-r--r--ui/gfx/range/mojo/range_traits_test_service.mojom17
-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_mac.mm38
-rw-r--r--ui/gfx/range/range_mac_unittest.mm43
-rw-r--r--ui/gfx/range/range_unittest.cc266
-rw-r--r--ui/gfx/range/range_win.cc45
-rw-r--r--ui/gfx/range/range_win_unittest.cc63
61 files changed, 4954 insertions, 2 deletions
diff --git a/Android.mk b/Android.mk
index 80bf5a9..a61dbe1 100644
--- a/Android.mk
+++ b/Android.mk
@@ -23,6 +23,8 @@ LOCAL_MOJOM_FILES := \
mojo/common/version.mojom \
mojo/public/interfaces/bindings/interface_control_messages.mojom \
mojo/public/interfaces/bindings/pipe_control_messages.mojom \
+ ui/gfx/geometry/mojo/geometry.mojom \
+ ui/gfx/range/mojo/range.mojom \
# This file was copied from out/Release in a Chrome checkout.
# TODO(lhchavez): Generate this file instead of hardcoding it.
@@ -72,6 +74,9 @@ LOCAL_SRC_FILES := \
base/trace_event/java_heap_dump_provider_android.cc \
base/trace_event/trace_event_android.cc \
base/unguessable_token.cc \
+ device/bluetooth/bluetooth_advertisement.cc \
+ device/bluetooth/bluetooth_uuid.cc \
+ device/bluetooth/bluez/bluetooth_service_attribute_value_bluez.cc \
ipc/ipc_message.cc \
ipc/ipc_message_attachment.cc \
ipc/ipc_message_attachment_set.cc \
@@ -158,6 +163,20 @@ LOCAL_SRC_FILES := \
mojo/public/cpp/system/buffer.cc \
mojo/public/cpp/system/platform_handle.cc \
mojo/public/cpp/system/watcher.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 \
LOCAL_CFLAGS := \
-Wall \
diff --git a/build_mojom.mk b/build_mojom.mk
index 2af9e49..478c79c 100644
--- a/build_mojom.mk
+++ b/build_mojom.mk
@@ -28,8 +28,10 @@ mojom_bindings_generator_flags := $$(LOCAL_MOJOM_BINDINGS_GENERATOR_FLAGS)
# TODO(lhchavez): Generate these files instead of expecting them to be there.
mojom_type_mappings :=
ifneq ($$(LOCAL_MOJOM_TYPE_MAPPINGS),)
- mojom_type_mappings := $$(local_path)/$$(LOCAL_MOJOM_TYPE_MAPPINGS)
- mojom_bindings_generator_flags += --typemap $$(abspath $$(mojom_type_mappings))
+ mojom_type_mappings := \
+ $$(foreach mapping,$$(LOCAL_MOJOM_TYPE_MAPPINGS),$$(local_path)/$$(mapping))
+ mojom_bindings_generator_flags += \
+ $$(foreach path,$$(mojom_type_mappings),--typemap $$(abspath $$(path)))
endif
diff --git a/device/bluetooth/bluetooth_advertisement.cc b/device/bluetooth/bluetooth_advertisement.cc
new file mode 100644
index 0000000..05b0e52
--- /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 0000000..412baa7
--- /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 0000000..6045980
--- /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 0000000..90cc58c
--- /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 0000000..b35094d
--- /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 0000000..8487f6a
--- /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 0000000..2c484c1
--- /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::MakeUnique<base::Value>()) {}
+
+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 0000000..fdd291a
--- /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/ui/gfx/geometry/insets.cc b/ui/gfx/geometry/insets.cc
new file mode 100644
index 0000000..9acc6e0
--- /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 0000000..a88bae3
--- /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 0000000..c1bc27e
--- /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 0000000..30c2ff2
--- /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/mojo/BUILD.gn b/ui/gfx/geometry/mojo/BUILD.gn
new file mode 100644
index 0000000..1fcd39f
--- /dev/null
+++ b/ui/gfx/geometry/mojo/BUILD.gn
@@ -0,0 +1,52 @@
+# 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.
+
+import("//mojo/public/tools/bindings/mojom.gni")
+
+# This target does NOT depend on skia. One can depend on this target to avoid
+# picking up a dependency on skia.
+mojom("mojo") {
+ sources = [
+ "geometry.mojom",
+ ]
+
+ # TODO(crbug.com/699569): Convert to use the new JS bindings.
+ use_new_js_bindings = false
+}
+
+mojom("test_interfaces") {
+ sources = [
+ "geometry_traits_test_service.mojom",
+ ]
+
+ public_deps = [
+ ":mojo",
+ ]
+}
+
+source_set("unit_test") {
+ testonly = true
+
+ sources = [
+ "geometry_struct_traits_unittest.cc",
+ ]
+
+ deps = [
+ ":test_interfaces",
+ "//base",
+ "//mojo/public/cpp/bindings",
+ "//testing/gtest",
+ "//ui/gfx/geometry",
+ ]
+}
+
+source_set("struct_traits") {
+ sources = [
+ "geometry_struct_traits.h",
+ ]
+ public_deps = [
+ ":mojo_shared_cpp_sources",
+ "//ui/gfx/geometry",
+ ]
+}
diff --git a/ui/gfx/geometry/mojo/DEPS b/ui/gfx/geometry/mojo/DEPS
new file mode 100644
index 0000000..3ad6543
--- /dev/null
+++ b/ui/gfx/geometry/mojo/DEPS
@@ -0,0 +1,4 @@
+include_rules = [
+ "+mojo/public",
+ "+ui/gfx/geometry",
+]
diff --git a/ui/gfx/geometry/mojo/geometry.mojom b/ui/gfx/geometry/mojo/geometry.mojom
new file mode 100644
index 0000000..9714386
--- /dev/null
+++ b/ui/gfx/geometry/mojo/geometry.mojom
@@ -0,0 +1,63 @@
+// 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.
+
+module gfx.mojom;
+
+struct Point {
+ int32 x;
+ int32 y;
+};
+
+struct PointF {
+ float x;
+ float y;
+};
+
+struct Size {
+ int32 width;
+ int32 height;
+};
+
+struct SizeF {
+ float width;
+ float height;
+};
+
+struct Rect {
+ int32 x;
+ int32 y;
+ int32 width;
+ int32 height;
+};
+
+struct RectF {
+ float x;
+ float y;
+ float width;
+ float height;
+};
+
+struct Insets {
+ int32 top;
+ int32 left;
+ int32 bottom;
+ int32 right;
+};
+
+struct InsetsF {
+ float top;
+ float left;
+ float bottom;
+ float right;
+};
+
+struct Vector2d {
+ int32 x;
+ int32 y;
+};
+
+struct Vector2dF {
+ float x;
+ float y;
+};
diff --git a/ui/gfx/geometry/mojo/geometry.typemap b/ui/gfx/geometry/mojo/geometry.typemap
new file mode 100644
index 0000000..686ea05
--- /dev/null
+++ b/ui/gfx/geometry/mojo/geometry.typemap
@@ -0,0 +1,32 @@
+# 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.
+
+mojom = "//ui/gfx/geometry/mojo/geometry.mojom"
+public_headers = [
+ "//ui/gfx/geometry/point.h",
+ "//ui/gfx/geometry/point_f.h",
+ "//ui/gfx/geometry/size.h",
+ "//ui/gfx/geometry/rect.h",
+ "//ui/gfx/geometry/rect_f.h",
+ "//ui/gfx/geometry/safe_integer_conversions.h",
+ "//ui/gfx/geometry/insets.h",
+ "//ui/gfx/geometry/vector2d.h",
+ "//ui/gfx/geometry/vector2d_f.h",
+]
+traits_headers = [ "//ui/gfx/geometry/mojo/geometry_struct_traits.h" ]
+deps = [
+ "//ui/gfx/geometry/mojo:struct_traits",
+]
+type_mappings = [
+ "gfx.mojom.Point=gfx::Point",
+ "gfx.mojom.PointF=gfx::PointF",
+ "gfx.mojom.Size=gfx::Size",
+ "gfx.mojom.SizeF=gfx::SizeF",
+ "gfx.mojom.Rect=gfx::Rect",
+ "gfx.mojom.RectF=gfx::RectF",
+ "gfx.mojom.Insets=gfx::Insets",
+ "gfx.mojom.InsetsF=gfx::InsetsF",
+ "gfx.mojom.Vector2d=gfx::Vector2d",
+ "gfx.mojom.Vector2dF=gfx::Vector2dF",
+]
diff --git a/ui/gfx/geometry/mojo/geometry_struct_traits.h b/ui/gfx/geometry/mojo/geometry_struct_traits.h
new file mode 100644
index 0000000..a31d738
--- /dev/null
+++ b/ui/gfx/geometry/mojo/geometry_struct_traits.h
@@ -0,0 +1,146 @@
+// 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 UI_GFX_GEOMETRY_MOJO_GEOMETRY_STRUCT_TRAITS_H_
+#define UI_GFX_GEOMETRY_MOJO_GEOMETRY_STRUCT_TRAITS_H_
+
+#include "ui/gfx/geometry/insets.h"
+#include "ui/gfx/geometry/insets_f.h"
+#include "ui/gfx/geometry/mojo/geometry.mojom-shared.h"
+#include "ui/gfx/geometry/point.h"
+#include "ui/gfx/geometry/point_f.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/geometry/rect_f.h"
+#include "ui/gfx/geometry/size.h"
+#include "ui/gfx/geometry/size_f.h"
+#include "ui/gfx/geometry/vector2d.h"
+#include "ui/gfx/geometry/vector2d_f.h"
+
+namespace mojo {
+
+template <>
+struct StructTraits<gfx::mojom::InsetsDataView, gfx::Insets> {
+ static int top(const gfx::Insets& p) { return p.top(); }
+ static int left(const gfx::Insets& p) { return p.left(); }
+ static int bottom(const gfx::Insets& p) { return p.bottom(); }
+ static int right(const gfx::Insets& p) { return p.right(); }
+ static bool Read(gfx::mojom::InsetsDataView data, gfx::Insets* out) {
+ out->Set(data.top(), data.left(), data.bottom(), data.right());
+ return true;
+ }
+};
+
+template <>
+struct StructTraits<gfx::mojom::InsetsFDataView, gfx::InsetsF> {
+ static float top(const gfx::InsetsF& p) { return p.top(); }
+ static float left(const gfx::InsetsF& p) { return p.left(); }
+ static float bottom(const gfx::InsetsF& p) { return p.bottom(); }
+ static float right(const gfx::InsetsF& p) { return p.right(); }
+ static bool Read(gfx::mojom::InsetsFDataView data, gfx::InsetsF* out) {
+ out->Set(data.top(), data.left(), data.bottom(), data.right());
+ return true;
+ }
+};
+
+template <>
+struct StructTraits<gfx::mojom::PointDataView, gfx::Point> {
+ static int x(const gfx::Point& p) { return p.x(); }
+ static int y(const gfx::Point& p) { return p.y(); }
+ static bool Read(gfx::mojom::PointDataView data, gfx::Point* out) {
+ out->SetPoint(data.x(), data.y());
+ return true;
+ }
+};
+
+template <>
+struct StructTraits<gfx::mojom::PointFDataView, gfx::PointF> {
+ static float x(const gfx::PointF& p) { return p.x(); }
+ static float y(const gfx::PointF& p) { return p.y(); }
+ static bool Read(gfx::mojom::PointFDataView data, gfx::PointF* out) {
+ out->SetPoint(data.x(), data.y());
+ return true;
+ }
+};
+
+template <>
+struct StructTraits<gfx::mojom::RectDataView, gfx::Rect> {
+ static int x(const gfx::Rect& p) { return p.x(); }
+ static int y(const gfx::Rect& p) { return p.y(); }
+ static int width(const gfx::Rect& p) { return p.width(); }
+ static int height(const gfx::Rect& p) { return p.height(); }
+ static bool Read(gfx::mojom::RectDataView data, gfx::Rect* out) {
+ if (data.width() < 0 || data.height() < 0)
+ return false;
+
+ out->SetRect(data.x(), data.y(), data.width(), data.height());
+ return true;
+ }
+};
+
+template <>
+struct StructTraits<gfx::mojom::RectFDataView, gfx::RectF> {
+ static float x(const gfx::RectF& p) { return p.x(); }
+ static float y(const gfx::RectF& p) { return p.y(); }
+ static float width(const gfx::RectF& p) { return p.width(); }
+ static float height(const gfx::RectF& p) { return p.height(); }
+ static bool Read(gfx::mojom::RectFDataView data, gfx::RectF* out) {
+ if (data.width() < 0 || data.height() < 0)
+ return false;
+
+ out->SetRect(data.x(), data.y(), data.width(), data.height());
+ return true;
+ }
+};
+
+template <>
+struct StructTraits<gfx::mojom::SizeDataView, gfx::Size> {
+ static int width(const gfx::Size& p) { return p.width(); }
+ static int height(const gfx::Size& p) { return p.height(); }
+ static bool Read(gfx::mojom::SizeDataView data, gfx::Size* out) {
+ if (data.width() < 0 || data.height() < 0)
+ return false;
+
+ out->SetSize(data.width(), data.height());
+ return true;
+ }
+};
+
+template <>
+struct StructTraits<gfx::mojom::SizeFDataView, gfx::SizeF> {
+ static float width(const gfx::SizeF& p) { return p.width(); }
+ static float height(const gfx::SizeF& p) { return p.height(); }
+ static bool Read(gfx::mojom::SizeFDataView data, gfx::SizeF* out) {
+ if (data.width() < 0 || data.height() < 0)
+ return false;
+
+ out->SetSize(data.width(), data.height());
+ return true;
+ }
+};
+
+template <>
+struct StructTraits<gfx::mojom::Vector2dDataView, gfx::Vector2d> {
+ static int x(const gfx::Vector2d& v) { return v.x(); }
+ static int y(const gfx::Vector2d& v) { return v.y(); }
+ static bool Read(gfx::mojom::Vector2dDataView data, gfx::Vector2d* out) {
+ out->set_x(data.x());
+ out->set_y(data.y());
+ return true;
+ }
+};
+
+template <>
+struct StructTraits<gfx::mojom::Vector2dFDataView, gfx::Vector2dF> {
+ static float x(const gfx::Vector2dF& v) { return v.x(); }
+ static float y(const gfx::Vector2dF& v) { return v.y(); }
+ static bool Read(gfx::mojom::Vector2dFDataView data, gfx::Vector2dF* out) {
+ out->set_x(data.x());
+ out->set_y(data.y());
+ return true;
+ }
+};
+
+} // namespace mojo
+
+#endif // UI_GFX_GEOMETRY_MOJO_GEOMETRY_STRUCT_TRAITS_H_
diff --git a/ui/gfx/geometry/mojo/geometry_struct_traits_unittest.cc b/ui/gfx/geometry/mojo/geometry_struct_traits_unittest.cc
new file mode 100644
index 0000000..2be935b
--- /dev/null
+++ b/ui/gfx/geometry/mojo/geometry_struct_traits_unittest.cc
@@ -0,0 +1,206 @@
+// 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 <utility>
+
+#include "base/message_loop/message_loop.h"
+#include "mojo/public/cpp/bindings/binding_set.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/geometry/mojo/geometry_traits_test_service.mojom.h"
+#include "ui/gfx/geometry/point.h"
+
+namespace gfx {
+
+namespace {
+
+class GeometryStructTraitsTest : public testing::Test,
+ public mojom::GeometryTraitsTestService {
+ public:
+ GeometryStructTraitsTest() {}
+
+ protected:
+ mojom::GeometryTraitsTestServicePtr GetTraitsTestProxy() {
+ mojom::GeometryTraitsTestServicePtr proxy;
+ traits_test_bindings_.AddBinding(this, mojo::MakeRequest(&proxy));
+ return proxy;
+ }
+
+ private:
+ // GeometryTraitsTestService:
+ void EchoPoint(const Point& p, EchoPointCallback callback) override {
+ std::move(callback).Run(p);
+ }
+
+ void EchoPointF(const PointF& p, EchoPointFCallback callback) override {
+ std::move(callback).Run(p);
+ }
+
+ void EchoSize(const Size& s, EchoSizeCallback callback) override {
+ std::move(callback).Run(s);
+ }
+
+ void EchoSizeF(const SizeF& s, EchoSizeFCallback callback) override {
+ std::move(callback).Run(s);
+ }
+
+ void EchoRect(const Rect& r, EchoRectCallback callback) override {
+ std::move(callback).Run(r);
+ }
+
+ void EchoRectF(const RectF& r, EchoRectFCallback callback) override {
+ std::move(callback).Run(r);
+ }
+
+ void EchoInsets(const Insets& i, EchoInsetsCallback callback) override {
+ std::move(callback).Run(i);
+ }
+
+ void EchoInsetsF(const InsetsF& i, EchoInsetsFCallback callback) override {
+ std::move(callback).Run(i);
+ }
+
+ void EchoVector2d(const Vector2d& v, EchoVector2dCallback callback) override {
+ std::move(callback).Run(v);
+ }
+
+ void EchoVector2dF(const Vector2dF& v,
+ EchoVector2dFCallback callback) override {
+ std::move(callback).Run(v);
+ }
+
+ base::MessageLoop loop_;
+ mojo::BindingSet<GeometryTraitsTestService> traits_test_bindings_;
+
+ DISALLOW_COPY_AND_ASSIGN(GeometryStructTraitsTest);
+};
+
+} // namespace
+
+TEST_F(GeometryStructTraitsTest, Point) {
+ const int32_t x = 1234;
+ const int32_t y = -5678;
+ gfx::Point input(x, y);
+ mojom::GeometryTraitsTestServicePtr proxy = GetTraitsTestProxy();
+ gfx::Point output;
+ proxy->EchoPoint(input, &output);
+ EXPECT_EQ(x, output.x());
+ EXPECT_EQ(y, output.y());
+}
+
+TEST_F(GeometryStructTraitsTest, PointF) {
+ const float x = 1234.5f;
+ const float y = 6789.6f;
+ gfx::PointF input(x, y);
+ mojom::GeometryTraitsTestServicePtr proxy = GetTraitsTestProxy();
+ gfx::PointF output;
+ proxy->EchoPointF(input, &output);
+ EXPECT_EQ(x, output.x());
+ EXPECT_EQ(y, output.y());
+}
+
+TEST_F(GeometryStructTraitsTest, Size) {
+ const int32_t width = 1234;
+ const int32_t height = 5678;
+ gfx::Size input(width, height);
+ mojom::GeometryTraitsTestServicePtr proxy = GetTraitsTestProxy();
+ gfx::Size output;
+ proxy->EchoSize(input, &output);
+ EXPECT_EQ(width, output.width());
+ EXPECT_EQ(height, output.height());
+}
+
+TEST_F(GeometryStructTraitsTest, SizeF) {
+ const float width = 1234.5f;
+ const float height = 6789.6f;
+ gfx::SizeF input(width, height);
+ mojom::GeometryTraitsTestServicePtr proxy = GetTraitsTestProxy();
+ gfx::SizeF output;
+ proxy->EchoSizeF(input, &output);
+ EXPECT_EQ(width, output.width());
+ EXPECT_EQ(height, output.height());
+}
+
+TEST_F(GeometryStructTraitsTest, Rect) {
+ const int32_t x = 1234;
+ const int32_t y = 5678;
+ const int32_t width = 4321;
+ const int32_t height = 8765;
+ gfx::Rect input(x, y, width, height);
+ mojom::GeometryTraitsTestServicePtr proxy = GetTraitsTestProxy();
+ gfx::Rect output;
+ proxy->EchoRect(input, &output);
+ EXPECT_EQ(x, output.x());
+ EXPECT_EQ(y, output.y());
+ EXPECT_EQ(width, output.width());
+ EXPECT_EQ(height, output.height());
+}
+
+TEST_F(GeometryStructTraitsTest, RectF) {
+ const float x = 1234.1f;
+ const float y = 5678.2f;
+ const float width = 4321.3f;
+ const float height = 8765.4f;
+ gfx::RectF input(x, y, width, height);
+ mojom::GeometryTraitsTestServicePtr proxy = GetTraitsTestProxy();
+ gfx::RectF output;
+ proxy->EchoRectF(input, &output);
+ EXPECT_EQ(x, output.x());
+ EXPECT_EQ(y, output.y());
+ EXPECT_EQ(width, output.width());
+ EXPECT_EQ(height, output.height());
+}
+
+TEST_F(GeometryStructTraitsTest, Insets) {
+ const int32_t top = 1234;
+ const int32_t left = 5678;
+ const int32_t bottom = 4321;
+ const int32_t right = 8765;
+ gfx::Insets input(top, left, bottom, right);
+ mojom::GeometryTraitsTestServicePtr proxy = GetTraitsTestProxy();
+ gfx::Insets output;
+ proxy->EchoInsets(input, &output);
+ EXPECT_EQ(top, output.top());
+ EXPECT_EQ(left, output.left());
+ EXPECT_EQ(bottom, output.bottom());
+ EXPECT_EQ(right, output.right());
+}
+
+TEST_F(GeometryStructTraitsTest, InsetsF) {
+ const float top = 1234.1f;
+ const float left = 5678.2f;
+ const float bottom = 4321.3f;
+ const float right = 8765.4f;
+ gfx::InsetsF input(top, left, bottom, right);
+ mojom::GeometryTraitsTestServicePtr proxy = GetTraitsTestProxy();
+ gfx::InsetsF output;
+ proxy->EchoInsetsF(input, &output);
+ EXPECT_EQ(top, output.top());
+ EXPECT_EQ(left, output.left());
+ EXPECT_EQ(bottom, output.bottom());
+ EXPECT_EQ(right, output.right());
+}
+
+TEST_F(GeometryStructTraitsTest, Vector2d) {
+ const int32_t x = 1234;
+ const int32_t y = -5678;
+ gfx::Vector2d input(x, y);
+ mojom::GeometryTraitsTestServicePtr proxy = GetTraitsTestProxy();
+ gfx::Vector2d output;
+ proxy->EchoVector2d(input, &output);
+ EXPECT_EQ(x, output.x());
+ EXPECT_EQ(y, output.y());
+}
+
+TEST_F(GeometryStructTraitsTest, Vector2dF) {
+ const float x = 1234.5f;
+ const float y = 6789.6f;
+ gfx::Vector2dF input(x, y);
+ mojom::GeometryTraitsTestServicePtr proxy = GetTraitsTestProxy();
+ gfx::Vector2dF output;
+ proxy->EchoVector2dF(input, &output);
+ EXPECT_EQ(x, output.x());
+ EXPECT_EQ(y, output.y());
+}
+
+} // namespace gfx
diff --git a/ui/gfx/geometry/mojo/geometry_traits_test_service.mojom b/ui/gfx/geometry/mojo/geometry_traits_test_service.mojom
new file mode 100644
index 0000000..8d4fb94
--- /dev/null
+++ b/ui/gfx/geometry/mojo/geometry_traits_test_service.mojom
@@ -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.
+
+module gfx.mojom;
+
+import "ui/gfx/geometry/mojo/geometry.mojom";
+
+// All functions on this interface echo their arguments to test StructTraits
+// serialization and deserialization.
+interface GeometryTraitsTestService {
+ [Sync]
+ EchoPoint(Point p) => (Point pass);
+
+ [Sync]
+ EchoPointF(PointF p) => (PointF pass);
+
+ [Sync]
+ EchoSize(Size s) => (Size pass);
+
+ [Sync]
+ EchoSizeF(SizeF s) => (SizeF pass);
+
+ [Sync]
+ EchoRect(Rect r) => (Rect pass);
+
+ [Sync]
+ EchoRectF(RectF r) => (RectF pass);
+
+ [Sync]
+ EchoInsets(Insets i) => (Insets pass);
+
+ [Sync]
+ EchoInsetsF(InsetsF i) => (InsetsF pass);
+
+ [Sync]
+ EchoVector2d(Vector2d v) => (Vector2d pass);
+
+ [Sync]
+ EchoVector2dF(Vector2dF v) => (Vector2dF pass);
+};
diff --git a/ui/gfx/geometry/point.cc b/ui/gfx/geometry/point.cc
new file mode 100644
index 0000000..285b208
--- /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 0000000..bb248d5
--- /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 0000000..0613e7a
--- /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 0000000..bfab9e4
--- /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 0000000..0d15394
--- /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 0000000..5d92b11
--- /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 0000000..b5ceda5
--- /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 0000000..1858d44
--- /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 0000000..a08e384
--- /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 0000000..9d99052
--- /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 0000000..5efe134
--- /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 0000000..6948672
--- /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 0000000..8ce4178
--- /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 0000000..c924e86
--- /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 0000000..96fb79f
--- /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 0000000..6d08e18
--- /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 0000000..0757ef6
--- /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 0000000..2b4875c
--- /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 0000000..4b45667
--- /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 0000000..ccb15ae
--- /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 0000000..92f7f87
--- /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 0000000..20c8bb1
--- /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 0000000..0a8d8b2
--- /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 0000000..5634c49
--- /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/mojo/BUILD.gn b/ui/gfx/range/mojo/BUILD.gn
new file mode 100644
index 0000000..b6d458d
--- /dev/null
+++ b/ui/gfx/range/mojo/BUILD.gn
@@ -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.
+
+import("//mojo/public/tools/bindings/mojom.gni")
+
+# This target does NOT depend on skia. One can depend on this target to avoid
+# picking up a dependency on skia.
+mojom("mojo") {
+ sources = [
+ "range.mojom",
+ ]
+}
+
+mojom("test_interfaces") {
+ sources = [
+ "range_traits_test_service.mojom",
+ ]
+
+ public_deps = [
+ ":mojo",
+ ]
+}
+
+source_set("unit_test") {
+ testonly = true
+
+ sources = [
+ "range_struct_traits_unittest.cc",
+ ]
+
+ deps = [
+ ":test_interfaces",
+ "//base",
+ "//mojo/public/cpp/bindings",
+ "//testing/gtest",
+ "//ui/gfx/range",
+ ]
+}
+
+source_set("struct_traits") {
+ sources = [
+ "range_struct_traits.h",
+ ]
+ public_deps = [
+ ":mojo_shared_cpp_sources",
+ "//ui/gfx/range",
+ ]
+}
diff --git a/ui/gfx/range/mojo/DEPS b/ui/gfx/range/mojo/DEPS
new file mode 100644
index 0000000..418fc69
--- /dev/null
+++ b/ui/gfx/range/mojo/DEPS
@@ -0,0 +1,4 @@
+include_rules = [
+ "+mojo/public",
+ "+ui/gfx/range",
+]
diff --git a/ui/gfx/range/mojo/range.mojom b/ui/gfx/range/mojo/range.mojom
new file mode 100644
index 0000000..079c146
--- /dev/null
+++ b/ui/gfx/range/mojo/range.mojom
@@ -0,0 +1,15 @@
+// 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.
+
+module gfx.mojom;
+
+struct Range {
+ uint32 start;
+ uint32 end;
+};
+
+struct RangeF {
+ float start;
+ float end;
+};
diff --git a/ui/gfx/range/mojo/range.typemap b/ui/gfx/range/mojo/range.typemap
new file mode 100644
index 0000000..ebf07d1
--- /dev/null
+++ b/ui/gfx/range/mojo/range.typemap
@@ -0,0 +1,17 @@
+# 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.
+
+mojom = "//ui/gfx/range/mojo/range.mojom"
+public_headers = [
+ "//ui/gfx/range/range.h",
+ "//ui/gfx/range/range_f.h",
+]
+traits_headers = [ "//ui/gfx/range/mojo/range_struct_traits.h" ]
+deps = [
+ "//ui/gfx/range/mojo:struct_traits",
+]
+type_mappings = [
+ "gfx.mojom.Range=gfx::Range",
+ "gfx.mojom.RangeF=gfx::RangeF",
+]
diff --git a/ui/gfx/range/mojo/range_struct_traits.h b/ui/gfx/range/mojo/range_struct_traits.h
new file mode 100644
index 0000000..e717d41
--- /dev/null
+++ b/ui/gfx/range/mojo/range_struct_traits.h
@@ -0,0 +1,38 @@
+// 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 UI_GFX_RANGE_MOJO_RANGE_STRUCT_TRAITS_H_
+#define UI_GFX_RANGE_MOJO_RANGE_STRUCT_TRAITS_H_
+
+#include "ui/gfx/range/mojo/range.mojom-shared.h"
+#include "ui/gfx/range/range.h"
+#include "ui/gfx/range/range_f.h"
+
+namespace mojo {
+
+template <>
+struct StructTraits<gfx::mojom::RangeDataView, gfx::Range> {
+ static uint32_t start(const gfx::Range& r) { return r.start(); }
+ static uint32_t end(const gfx::Range& r) { return r.end(); }
+ static bool Read(gfx::mojom::RangeDataView data, gfx::Range* out) {
+ out->set_start(data.start());
+ out->set_end(data.end());
+ return true;
+ }
+};
+
+template <>
+struct StructTraits<gfx::mojom::RangeFDataView, gfx::RangeF> {
+ static float start(const gfx::RangeF& r) { return r.start(); }
+ static float end(const gfx::RangeF& r) { return r.end(); }
+ static bool Read(gfx::mojom::RangeFDataView data, gfx::RangeF* out) {
+ out->set_start(data.start());
+ out->set_end(data.end());
+ return true;
+ }
+};
+
+} // namespace mojo
+
+#endif // UI_GFX_RANGE_MOJO_RANGE_STRUCT_TRAITS_H_
diff --git a/ui/gfx/range/mojo/range_struct_traits_unittest.cc b/ui/gfx/range/mojo/range_struct_traits_unittest.cc
new file mode 100644
index 0000000..31705ca
--- /dev/null
+++ b/ui/gfx/range/mojo/range_struct_traits_unittest.cc
@@ -0,0 +1,68 @@
+// 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 <utility>
+
+#include "base/message_loop/message_loop.h"
+#include "mojo/public/cpp/bindings/binding_set.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/range/mojo/range_traits_test_service.mojom.h"
+
+namespace gfx {
+
+namespace {
+
+class RangeStructTraitsTest : public testing::Test,
+ public mojom::RangeTraitsTestService {
+ public:
+ RangeStructTraitsTest() {}
+
+ protected:
+ mojom::RangeTraitsTestServicePtr GetTraitsTestProxy() {
+ mojom::RangeTraitsTestServicePtr proxy;
+ traits_test_bindings_.AddBinding(this, mojo::MakeRequest(&proxy));
+ return proxy;
+ }
+
+ private:
+ // RangeTraitsTestService:
+ void EchoRange(const Range& p, EchoRangeCallback callback) override {
+ std::move(callback).Run(p);
+ }
+
+ void EchoRangeF(const RangeF& p, EchoRangeFCallback callback) override {
+ std::move(callback).Run(p);
+ }
+
+ base::MessageLoop loop_;
+ mojo::BindingSet<RangeTraitsTestService> traits_test_bindings_;
+
+ DISALLOW_COPY_AND_ASSIGN(RangeStructTraitsTest);
+};
+
+} // namespace
+
+TEST_F(RangeStructTraitsTest, Range) {
+ const uint32_t start = 1234;
+ const uint32_t end = 5678;
+ gfx::Range input(start, end);
+ mojom::RangeTraitsTestServicePtr proxy = GetTraitsTestProxy();
+ gfx::Range output;
+ proxy->EchoRange(input, &output);
+ EXPECT_EQ(start, output.start());
+ EXPECT_EQ(end, output.end());
+}
+
+TEST_F(RangeStructTraitsTest, RangeF) {
+ const float start = 1234.5f;
+ const float end = 6789.6f;
+ gfx::RangeF input(start, end);
+ mojom::RangeTraitsTestServicePtr proxy = GetTraitsTestProxy();
+ gfx::RangeF output;
+ proxy->EchoRangeF(input, &output);
+ EXPECT_EQ(start, output.start());
+ EXPECT_EQ(end, output.end());
+}
+
+} // namespace gfx
diff --git a/ui/gfx/range/mojo/range_traits_test_service.mojom b/ui/gfx/range/mojo/range_traits_test_service.mojom
new file mode 100644
index 0000000..3cde75c
--- /dev/null
+++ b/ui/gfx/range/mojo/range_traits_test_service.mojom
@@ -0,0 +1,17 @@
+// 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.
+
+module gfx.mojom;
+
+import "ui/gfx/range/mojo/range.mojom";
+
+// All functions on this interface echo their arguments to test StructTraits
+// serialization and deserialization.
+interface RangeTraitsTestService {
+ [Sync]
+ EchoRange(Range p) => (Range pass);
+
+ [Sync]
+ EchoRangeF(RangeF p) => (RangeF pass);
+};
diff --git a/ui/gfx/range/range.cc b/ui/gfx/range/range.cc
new file mode 100644
index 0000000..fa837d0
--- /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 0000000..e785eb6
--- /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 0000000..b3bfc69
--- /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 0000000..1d58ad4
--- /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_mac.mm b/ui/gfx/range/range_mac.mm
new file mode 100644
index 0000000..ad7ea6a
--- /dev/null
+++ b/ui/gfx/range/range_mac.mm
@@ -0,0 +1,38 @@
+// 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 "ui/gfx/range/range.h"
+
+#include <stddef.h>
+
+#include <limits>
+
+#include "base/logging.h"
+
+namespace gfx {
+
+Range::Range(const NSRange& range) {
+ *this = range;
+}
+
+Range& Range::operator=(const NSRange& range) {
+ if (range.location == NSNotFound) {
+ DCHECK_EQ(0U, range.length);
+ *this = InvalidRange();
+ } else {
+ set_start(range.location);
+ // Don't overflow |end_|.
+ DCHECK_LE(range.length, std::numeric_limits<size_t>::max() - start());
+ set_end(start() + range.length);
+ }
+ return *this;
+}
+
+NSRange Range::ToNSRange() const {
+ if (!IsValid())
+ return NSMakeRange(NSNotFound, 0);
+ return NSMakeRange(GetMin(), length());
+}
+
+} // namespace gfx
diff --git a/ui/gfx/range/range_mac_unittest.mm b/ui/gfx/range/range_mac_unittest.mm
new file mode 100644
index 0000000..85323f2
--- /dev/null
+++ b/ui/gfx/range/range_mac_unittest.mm
@@ -0,0 +1,43 @@
+// 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 "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/range/range.h"
+
+TEST(RangeTest, FromNSRange) {
+ NSRange nsr = NSMakeRange(10, 3);
+ gfx::Range r(nsr);
+ EXPECT_EQ(nsr.location, r.start());
+ EXPECT_EQ(13U, r.end());
+ EXPECT_EQ(nsr.length, r.length());
+ EXPECT_FALSE(r.is_reversed());
+ EXPECT_TRUE(r.IsValid());
+}
+
+TEST(RangeTest, ToNSRange) {
+ gfx::Range r(10, 12);
+ NSRange nsr = r.ToNSRange();
+ EXPECT_EQ(10U, nsr.location);
+ EXPECT_EQ(2U, nsr.length);
+}
+
+TEST(RangeTest, ReversedToNSRange) {
+ gfx::Range r(20, 10);
+ NSRange nsr = r.ToNSRange();
+ EXPECT_EQ(10U, nsr.location);
+ EXPECT_EQ(10U, nsr.length);
+}
+
+TEST(RangeTest, FromNSRangeInvalid) {
+ NSRange nsr = NSMakeRange(NSNotFound, 0);
+ gfx::Range r(nsr);
+ EXPECT_FALSE(r.IsValid());
+}
+
+TEST(RangeTest, ToNSRangeInvalid) {
+ gfx::Range r(gfx::Range::InvalidRange());
+ NSRange nsr = r.ToNSRange();
+ EXPECT_EQ(static_cast<NSUInteger>(NSNotFound), nsr.location);
+ EXPECT_EQ(0U, nsr.length);
+}
diff --git a/ui/gfx/range/range_unittest.cc b/ui/gfx/range/range_unittest.cc
new file mode 100644
index 0000000..4ae7a67
--- /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());
+}
diff --git a/ui/gfx/range/range_win.cc b/ui/gfx/range/range_win.cc
new file mode 100644
index 0000000..1180e1b
--- /dev/null
+++ b/ui/gfx/range/range_win.cc
@@ -0,0 +1,45 @@
+// 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 "ui/gfx/range/range.h"
+
+#include <limits>
+
+#include "base/logging.h"
+
+namespace gfx {
+
+Range::Range(const CHARRANGE& range, LONG total_length) {
+ // Check if this is an invalid range.
+ if (range.cpMin == -1 && range.cpMax == -1) {
+ *this = InvalidRange();
+ } else {
+ DCHECK_GE(range.cpMin, 0);
+ set_start(range.cpMin);
+ // {0,-1} is the "whole range" but that doesn't mean much out of context,
+ // so use the |total_length| parameter.
+ if (range.cpMax == -1) {
+ DCHECK_EQ(0, range.cpMin);
+ DCHECK_NE(-1, total_length);
+ set_end(total_length);
+ } else {
+ set_end(range.cpMax);
+ }
+ }
+}
+
+CHARRANGE Range::ToCHARRANGE() const {
+ CHARRANGE r = { -1, -1 };
+ if (!IsValid())
+ return r;
+
+ const LONG kLONGMax = std::numeric_limits<LONG>::max();
+ CHECK_LE(static_cast<LONG>(start()), kLONGMax);
+ CHECK_LE(static_cast<LONG>(end()), kLONGMax);
+ r.cpMin = static_cast<LONG>(start());
+ r.cpMax = static_cast<LONG>(end());
+ return r;
+}
+
+} // namespace gfx
diff --git a/ui/gfx/range/range_win_unittest.cc b/ui/gfx/range/range_win_unittest.cc
new file mode 100644
index 0000000..d15375b
--- /dev/null
+++ b/ui/gfx/range/range_win_unittest.cc
@@ -0,0 +1,63 @@
+// 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 "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/range/range.h"
+
+TEST(RangeTest, FromCHARRANGE) {
+ CHARRANGE cr = { 10, 32 };
+ gfx::Range r(cr, 50);
+ EXPECT_EQ(10U, r.start());
+ EXPECT_EQ(32U, r.end());
+ EXPECT_EQ(22U, r.length());
+ EXPECT_FALSE(r.is_reversed());
+ EXPECT_TRUE(r.IsValid());
+}
+
+TEST(RangeTest, FromReversedCHARRANGE) {
+ CHARRANGE cr = { 20, 10 };
+ gfx::Range r(cr, 40);
+ EXPECT_EQ(20U, r.start());
+ EXPECT_EQ(10U, r.end());
+ EXPECT_EQ(10U, r.length());
+ EXPECT_TRUE(r.is_reversed());
+ EXPECT_TRUE(r.IsValid());
+}
+
+TEST(RangeTest, FromCHARRANGETotal) {
+ CHARRANGE cr = { 0, -1 };
+ gfx::Range r(cr, 20);
+ EXPECT_EQ(0U, r.start());
+ EXPECT_EQ(20U, r.end());
+ EXPECT_EQ(20U, r.length());
+ EXPECT_FALSE(r.is_reversed());
+ EXPECT_TRUE(r.IsValid());
+}
+
+TEST(RangeTest, ToCHARRANGE) {
+ gfx::Range r(10, 30);
+ CHARRANGE cr = r.ToCHARRANGE();
+ EXPECT_EQ(10, cr.cpMin);
+ EXPECT_EQ(30, cr.cpMax);
+}
+
+TEST(RangeTest, ReversedToCHARRANGE) {
+ gfx::Range r(20, 10);
+ CHARRANGE cr = r.ToCHARRANGE();
+ EXPECT_EQ(20, cr.cpMin);
+ EXPECT_EQ(10, cr.cpMax);
+}
+
+TEST(RangeTest, FromCHARRANGEInvalid) {
+ CHARRANGE cr = { -1, -1 };
+ gfx::Range r(cr, 30);
+ EXPECT_FALSE(r.IsValid());
+}
+
+TEST(RangeTest, ToCHARRANGEInvalid) {
+ gfx::Range r(gfx::Range::InvalidRange());
+ CHARRANGE cr = r.ToCHARRANGE();
+ EXPECT_EQ(-1, cr.cpMin);
+ EXPECT_EQ(-1, cr.cpMax);
+}