summaryrefslogtreecommitdiff
path: root/chromium/ui/gfx
diff options
context:
space:
mode:
authorAndras Becsi <andras.becsi@digia.com>2014-03-18 13:16:26 +0100
committerFrederik Gladhorn <frederik.gladhorn@digia.com>2014-03-20 15:55:39 +0100
commit3f0f86b0caed75241fa71c95a5d73bc0164348c5 (patch)
tree92b9fb00f2e9e90b0be2262093876d4f43b6cd13 /chromium/ui/gfx
parente90d7c4b152c56919d963987e2503f9909a666d2 (diff)
downloadqtwebengine-chromium-3f0f86b0caed75241fa71c95a5d73bc0164348c5.tar.gz
Update to new stable branch 1750
This also includes an updated ninja and chromium dependencies needed on Windows. Change-Id: Icd597d80ed3fa4425933c9f1334c3c2e31291c42 Reviewed-by: Zoltan Arvai <zarvai@inf.u-szeged.hu> Reviewed-by: Zeno Albisser <zeno.albisser@digia.com>
Diffstat (limited to 'chromium/ui/gfx')
-rw-r--r--chromium/ui/gfx/DEPS5
-rw-r--r--chromium/ui/gfx/OWNERS4
-rw-r--r--chromium/ui/gfx/android/DEPS3
-rw-r--r--chromium/ui/gfx/android/device_display_info.cc40
-rw-r--r--chromium/ui/gfx/android/device_display_info.h9
-rw-r--r--chromium/ui/gfx/android/java_bitmap.cc6
-rw-r--r--chromium/ui/gfx/android/java_bitmap.h9
-rw-r--r--chromium/ui/gfx/android/shared_device_display_info.cc128
-rw-r--r--chromium/ui/gfx/android/shared_device_display_info.h68
-rw-r--r--chromium/ui/gfx/android/view_configuration.cc56
-rw-r--r--chromium/ui/gfx/android/view_configuration.h32
-rw-r--r--chromium/ui/gfx/animation/animation.cc7
-rw-r--r--chromium/ui/gfx/animation/animation_container.cc7
-rw-r--r--chromium/ui/gfx/animation/animation_container_unittest.cc41
-rw-r--r--chromium/ui/gfx/animation/tween.cc95
-rw-r--r--chromium/ui/gfx/animation/tween.h30
-rw-r--r--chromium/ui/gfx/animation/tween_unittest.cc136
-rw-r--r--chromium/ui/gfx/blit.cc8
-rw-r--r--chromium/ui/gfx/blit.h34
-rw-r--r--chromium/ui/gfx/box_f.cc36
-rw-r--r--chromium/ui/gfx/box_f.h22
-rw-r--r--chromium/ui/gfx/box_unittest.cc33
-rw-r--r--chromium/ui/gfx/canvas.cc88
-rw-r--r--chromium/ui/gfx/canvas.h71
-rw-r--r--chromium/ui/gfx/canvas_android.cc12
-rw-r--r--chromium/ui/gfx/canvas_paint.h2
-rw-r--r--chromium/ui/gfx/canvas_paint_gtk.cc44
-rw-r--r--chromium/ui/gfx/canvas_paint_gtk.h42
-rw-r--r--chromium/ui/gfx/canvas_paint_mac.h2
-rw-r--r--chromium/ui/gfx/canvas_paint_mac.mm5
-rw-r--r--chromium/ui/gfx/canvas_paint_win.cc2
-rw-r--r--chromium/ui/gfx/canvas_paint_win.h2
-rw-r--r--chromium/ui/gfx/canvas_skia.cc91
-rw-r--r--chromium/ui/gfx/canvas_unittest_mac.mm50
-rw-r--r--chromium/ui/gfx/codec/jpeg_codec.h2
-rw-r--r--chromium/ui/gfx/codec/png_codec.cc28
-rw-r--r--chromium/ui/gfx/codec/png_codec.h9
-rw-r--r--chromium/ui/gfx/color_analysis.h18
-rw-r--r--chromium/ui/gfx/color_analysis_unittest.cc8
-rw-r--r--chromium/ui/gfx/color_profile.h4
-rw-r--r--chromium/ui/gfx/color_utils.h30
-rw-r--r--chromium/ui/gfx/display.cc9
-rw-r--r--chromium/ui/gfx/display.h13
-rw-r--r--chromium/ui/gfx/display_observer.h2
-rw-r--r--chromium/ui/gfx/favicon_size.h4
-rw-r--r--chromium/ui/gfx/font.cc8
-rw-r--r--chromium/ui/gfx/font.h19
-rw-r--r--chromium/ui/gfx/font_fallback_win.h6
-rw-r--r--chromium/ui/gfx/font_list.cc29
-rw-r--r--chromium/ui/gfx/font_list.h16
-rw-r--r--chromium/ui/gfx/font_list_unittest.cc3
-rw-r--r--chromium/ui/gfx/font_render_params_linux.h8
-rw-r--r--chromium/ui/gfx/font_unittest.cc72
-rw-r--r--chromium/ui/gfx/frame_time.h40
-rw-r--r--chromium/ui/gfx/gdi_util.h22
-rw-r--r--chromium/ui/gfx/gfx.gyp440
-rw-r--r--chromium/ui/gfx/gfx_export.h10
-rw-r--r--chromium/ui/gfx/gfx_paths.h2
-rw-r--r--chromium/ui/gfx/gpu_memory_buffer.h12
-rw-r--r--chromium/ui/gfx/gtk_native_view_id_manager.h2
-rw-r--r--chromium/ui/gfx/gtk_preserve_window.h16
-rw-r--r--chromium/ui/gfx/gtk_util.h16
-rw-r--r--chromium/ui/gfx/icon_util.h2
-rw-r--r--chromium/ui/gfx/image/cairo_cached_surface.h2
-rw-r--r--chromium/ui/gfx/image/canvas_image_source.cc6
-rw-r--r--chromium/ui/gfx/image/canvas_image_source.h5
-rw-r--r--chromium/ui/gfx/image/image.cc24
-rw-r--r--chromium/ui/gfx/image/image.h2
-rw-r--r--chromium/ui/gfx/image/image_family.cc2
-rw-r--r--chromium/ui/gfx/image/image_family.h6
-rw-r--r--chromium/ui/gfx/image/image_ios.mm19
-rw-r--r--chromium/ui/gfx/image/image_mac.mm4
-rw-r--r--chromium/ui/gfx/image/image_mac_unittest.mm66
-rw-r--r--chromium/ui/gfx/image/image_png_rep.cc7
-rw-r--r--chromium/ui/gfx/image/image_png_rep.h8
-rw-r--r--chromium/ui/gfx/image/image_skia.cc114
-rw-r--r--chromium/ui/gfx/image/image_skia.h36
-rw-r--r--chromium/ui/gfx/image/image_skia_operations.cc96
-rw-r--r--chromium/ui/gfx/image/image_skia_operations.h2
-rw-r--r--chromium/ui/gfx/image/image_skia_rep.cc23
-rw-r--r--chromium/ui/gfx/image/image_skia_rep.h14
-rw-r--r--chromium/ui/gfx/image/image_skia_source.h15
-rw-r--r--chromium/ui/gfx/image/image_skia_unittest.cc68
-rw-r--r--chromium/ui/gfx/image/image_skia_util_ios.h17
-rw-r--r--chromium/ui/gfx/image/image_skia_util_ios.mm18
-rw-r--r--chromium/ui/gfx/image/image_skia_util_mac.h12
-rw-r--r--chromium/ui/gfx/image/image_skia_util_mac.mm19
-rw-r--r--chromium/ui/gfx/image/image_unittest.cc93
-rw-r--r--chromium/ui/gfx/image/image_unittest_util.cc36
-rw-r--r--chromium/ui/gfx/image/image_unittest_util.h5
-rw-r--r--chromium/ui/gfx/image/image_util.cc4
-rw-r--r--chromium/ui/gfx/image/image_util.h10
-rw-r--r--chromium/ui/gfx/insets.h2
-rw-r--r--chromium/ui/gfx/insets_base.h2
-rw-r--r--chromium/ui/gfx/insets_f.h2
-rw-r--r--chromium/ui/gfx/interpolated_transform.cc6
-rw-r--r--chromium/ui/gfx/interpolated_transform.h17
-rw-r--r--chromium/ui/gfx/interpolated_transform_unittest.cc10
-rw-r--r--chromium/ui/gfx/matrix3_f.h2
-rw-r--r--chromium/ui/gfx/native_widget_types.h4
-rw-r--r--chromium/ui/gfx/ozone/dri/dri_skbitmap.cc208
-rw-r--r--chromium/ui/gfx/ozone/dri/dri_skbitmap.h57
-rw-r--r--chromium/ui/gfx/ozone/dri/dri_surface.cc113
-rw-r--r--chromium/ui/gfx/ozone/dri/dri_surface.h168
-rw-r--r--chromium/ui/gfx/ozone/dri/dri_surface_factory.cc317
-rw-r--r--chromium/ui/gfx/ozone/dri/dri_surface_factory.h75
-rw-r--r--chromium/ui/gfx/ozone/dri/dri_surface_factory_unittest.cc292
-rw-r--r--chromium/ui/gfx/ozone/dri/dri_surface_unittest.cc212
-rw-r--r--chromium/ui/gfx/ozone/dri/dri_vsync_provider.cc32
-rw-r--r--chromium/ui/gfx/ozone/dri/dri_vsync_provider.h29
-rw-r--r--chromium/ui/gfx/ozone/dri/dri_wrapper.cc93
-rw-r--r--chromium/ui/gfx/ozone/dri/dri_wrapper.h86
-rw-r--r--chromium/ui/gfx/ozone/dri/hardware_display_controller.cc129
-rw-r--r--chromium/ui/gfx/ozone/dri/hardware_display_controller.h190
-rw-r--r--chromium/ui/gfx/ozone/dri/hardware_display_controller_unittest.cc301
-rw-r--r--chromium/ui/gfx/ozone/impl/file_surface_factory.cc96
-rw-r--r--chromium/ui/gfx/ozone/impl/file_surface_factory.h49
-rw-r--r--chromium/ui/gfx/ozone/surface_factory_ozone.cc21
-rw-r--r--chromium/ui/gfx/ozone/surface_factory_ozone.h61
-rw-r--r--chromium/ui/gfx/pango_util.cc91
-rw-r--r--chromium/ui/gfx/pango_util.h43
-rw-r--r--chromium/ui/gfx/path.h2
-rw-r--r--chromium/ui/gfx/path_win.cc15
-rw-r--r--chromium/ui/gfx/path_win.h7
-rw-r--r--chromium/ui/gfx/path_x11.cc16
-rw-r--r--chromium/ui/gfx/path_x11.h7
-rw-r--r--chromium/ui/gfx/platform_font.h11
-rw-r--r--chromium/ui/gfx/platform_font_ios.h3
-rw-r--r--chromium/ui/gfx/platform_font_ios.mm9
-rw-r--r--chromium/ui/gfx/platform_font_mac.h29
-rw-r--r--chromium/ui/gfx/platform_font_mac.mm128
-rw-r--r--chromium/ui/gfx/platform_font_ozone.cc25
-rw-r--r--chromium/ui/gfx/platform_font_pango.cc20
-rw-r--r--chromium/ui/gfx/platform_font_pango.h8
-rw-r--r--chromium/ui/gfx/platform_font_win.cc28
-rw-r--r--chromium/ui/gfx/platform_font_win.h8
-rw-r--r--chromium/ui/gfx/point.h2
-rw-r--r--chromium/ui/gfx/point3_f.h8
-rw-r--r--chromium/ui/gfx/point_base.h2
-rw-r--r--chromium/ui/gfx/point_conversions.h6
-rw-r--r--chromium/ui/gfx/point_f.h4
-rw-r--r--chromium/ui/gfx/quad_f.h6
-rw-r--r--chromium/ui/gfx/range/range.h4
-rw-r--r--chromium/ui/gfx/rect.h14
-rw-r--r--chromium/ui/gfx/rect_base.h12
-rw-r--r--chromium/ui/gfx/rect_base_impl.h40
-rw-r--r--chromium/ui/gfx/rect_conversions.h10
-rw-r--r--chromium/ui/gfx/rect_f.h10
-rw-r--r--chromium/ui/gfx/rect_unittest.cc68
-rw-r--r--chromium/ui/gfx/render_text.cc72
-rw-r--r--chromium/ui/gfx/render_text.h85
-rw-r--r--chromium/ui/gfx/render_text_mac.cc18
-rw-r--r--chromium/ui/gfx/render_text_mac.h5
-rw-r--r--chromium/ui/gfx/render_text_ozone.cc13
-rw-r--r--chromium/ui/gfx/render_text_pango.cc (renamed from chromium/ui/gfx/render_text_linux.cc)60
-rw-r--r--chromium/ui/gfx/render_text_pango.h (renamed from chromium/ui/gfx/render_text_linux.h)18
-rw-r--r--chromium/ui/gfx/render_text_unittest.cc118
-rw-r--r--chromium/ui/gfx/render_text_win.cc68
-rw-r--r--chromium/ui/gfx/render_text_win.h2
-rw-r--r--chromium/ui/gfx/scoped_canvas.h38
-rw-r--r--chromium/ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h2
-rw-r--r--chromium/ui/gfx/screen.h2
-rw-r--r--chromium/ui/gfx/screen_mac.mm58
-rw-r--r--chromium/ui/gfx/screen_type_delegate.h4
-rw-r--r--chromium/ui/gfx/screen_win.h2
-rw-r--r--chromium/ui/gfx/scrollbar_size.h2
-rw-r--r--chromium/ui/gfx/selection_model.h2
-rw-r--r--chromium/ui/gfx/sequential_id_generator.cc82
-rw-r--r--chromium/ui/gfx/sequential_id_generator.h60
-rw-r--r--chromium/ui/gfx/sequential_id_generator_unittest.cc62
-rw-r--r--chromium/ui/gfx/shadow_value.h2
-rw-r--r--chromium/ui/gfx/size.h2
-rw-r--r--chromium/ui/gfx/size_base.h2
-rw-r--r--chromium/ui/gfx/size_conversions.h6
-rw-r--r--chromium/ui/gfx/size_f.h4
-rw-r--r--chromium/ui/gfx/skbitmap_operations.cc7
-rw-r--r--chromium/ui/gfx/skbitmap_operations.h2
-rw-r--r--chromium/ui/gfx/skbitmap_operations_unittest.cc3
-rw-r--r--chromium/ui/gfx/skia_util.cc20
-rw-r--r--chromium/ui/gfx/skia_util.h36
-rw-r--r--chromium/ui/gfx/skia_utils_gtk.h4
-rw-r--r--chromium/ui/gfx/switches.h8
-rw-r--r--chromium/ui/gfx/sys_color_change_listener.h6
-rw-r--r--chromium/ui/gfx/text_constants.h10
-rw-r--r--chromium/ui/gfx/text_elider.cc383
-rw-r--r--chromium/ui/gfx/text_elider.h97
-rw-r--r--chromium/ui/gfx/text_elider_unittest.cc199
-rw-r--r--chromium/ui/gfx/text_utils.h16
-rw-r--r--chromium/ui/gfx/text_utils_android.cc5
-rw-r--r--chromium/ui/gfx/text_utils_ios.mm6
-rw-r--r--chromium/ui/gfx/text_utils_skia.cc4
-rw-r--r--chromium/ui/gfx/transform.cc72
-rw-r--r--chromium/ui/gfx/transform.h44
-rw-r--r--chromium/ui/gfx/transform_unittest.cc545
-rw-r--r--chromium/ui/gfx/transform_util.cc302
-rw-r--r--chromium/ui/gfx/transform_util.h25
-rw-r--r--chromium/ui/gfx/transform_util_unittest.cc146
-rw-r--r--chromium/ui/gfx/ui_gfx_exports.cc10
-rw-r--r--chromium/ui/gfx/utf16_indexing.cc8
-rw-r--r--chromium/ui/gfx/utf16_indexing.h14
-rw-r--r--chromium/ui/gfx/vector2d.h2
-rw-r--r--chromium/ui/gfx/vector2d_conversions.h6
-rw-r--r--chromium/ui/gfx/vector2d_f.h12
-rw-r--r--chromium/ui/gfx/vector3d_f.h12
-rw-r--r--chromium/ui/gfx/vsync_provider.h33
-rw-r--r--chromium/ui/gfx/win/dpi.cc88
-rw-r--r--chromium/ui/gfx/win/dpi.h45
-rw-r--r--chromium/ui/gfx/win/hwnd_util.cc32
-rw-r--r--chromium/ui/gfx/win/hwnd_util.h24
-rw-r--r--chromium/ui/gfx/win/singleton_hwnd.cc18
-rw-r--r--chromium/ui/gfx/win/singleton_hwnd.h2
-rw-r--r--chromium/ui/gfx/win/window_impl.cc2
-rw-r--r--chromium/ui/gfx/win/window_impl.h2
-rw-r--r--chromium/ui/gfx/x/x11_atom_cache.cc47
-rw-r--r--chromium/ui/gfx/x/x11_atom_cache.h50
-rw-r--r--chromium/ui/gfx/x/x11_types.cc139
-rw-r--r--chromium/ui/gfx/x/x11_types.h27
217 files changed, 7244 insertions, 2071 deletions
diff --git a/chromium/ui/gfx/DEPS b/chromium/ui/gfx/DEPS
index c2b61851728..07a2ea9406f 100644
--- a/chromium/ui/gfx/DEPS
+++ b/chromium/ui/gfx/DEPS
@@ -1,5 +1,8 @@
include_rules = [
"+base",
- "+skia",
+ "+net",
+ "+skia/ext",
"+third_party/angle",
+ "+third_party/skia",
+ "+ui/test/ui_unittests_resource.h", # TODO(beng): remove
]
diff --git a/chromium/ui/gfx/OWNERS b/chromium/ui/gfx/OWNERS
index fa08e88ba74..563c600ea4d 100644
--- a/chromium/ui/gfx/OWNERS
+++ b/chromium/ui/gfx/OWNERS
@@ -15,5 +15,9 @@ per-file display*=oshima@chromium.org
per-file screen*=oshima@chromium.org
# Transform, interpolated transform and transform util.
+per-file transform*=shawnsingh@chromium.org
per-file transform*=vollick@chromium.org
per-file interpolated_transform*=vollick@chromium.org
+
+# If you're doing structural changes get a review from one of the OWNERS.
+per-file *.gyp*=*
diff --git a/chromium/ui/gfx/android/DEPS b/chromium/ui/gfx/android/DEPS
new file mode 100644
index 00000000000..c80012b5621
--- /dev/null
+++ b/chromium/ui/gfx/android/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+ "+jni",
+]
diff --git a/chromium/ui/gfx/android/device_display_info.cc b/chromium/ui/gfx/android/device_display_info.cc
index 16fd2acb1d8..2de8440e1d3 100644
--- a/chromium/ui/gfx/android/device_display_info.cc
+++ b/chromium/ui/gfx/android/device_display_info.cc
@@ -4,63 +4,39 @@
#include "ui/gfx/android/device_display_info.h"
-#include "base/android/jni_android.h"
-#include "base/android/jni_string.h"
#include "base/logging.h"
-#include "jni/DeviceDisplayInfo_jni.h"
-
-using base::android::AttachCurrentThread;
-using base::android::ScopedJavaLocalRef;
+#include "ui/gfx/android/shared_device_display_info.h"
namespace gfx {
DeviceDisplayInfo::DeviceDisplayInfo() {
- JNIEnv* env = AttachCurrentThread();
- j_device_info_.Reset(Java_DeviceDisplayInfo_create(env,
- base::android::GetApplicationContext()));
}
DeviceDisplayInfo::~DeviceDisplayInfo() {
}
int DeviceDisplayInfo::GetDisplayHeight() {
- JNIEnv* env = AttachCurrentThread();
- jint result =
- Java_DeviceDisplayInfo_getDisplayHeight(env, j_device_info_.obj());
- return static_cast<int>(result);
+ return SharedDeviceDisplayInfo::GetInstance()->GetDisplayHeight();
}
int DeviceDisplayInfo::GetDisplayWidth() {
- JNIEnv* env = AttachCurrentThread();
- jint result =
- Java_DeviceDisplayInfo_getDisplayWidth(env, j_device_info_.obj());
- return static_cast<int>(result);
+ return SharedDeviceDisplayInfo::GetInstance()->GetDisplayWidth();
}
int DeviceDisplayInfo::GetBitsPerPixel() {
- JNIEnv* env = AttachCurrentThread();
- jint result =
- Java_DeviceDisplayInfo_getBitsPerPixel(env, j_device_info_.obj());
- return static_cast<int>(result);
+ return SharedDeviceDisplayInfo::GetInstance()->GetBitsPerPixel();
}
int DeviceDisplayInfo::GetBitsPerComponent() {
- JNIEnv* env = AttachCurrentThread();
- jint result =
- Java_DeviceDisplayInfo_getBitsPerComponent(env, j_device_info_.obj());
- return static_cast<int>(result);
+ return SharedDeviceDisplayInfo::GetInstance()->GetBitsPerComponent();
}
double DeviceDisplayInfo::GetDIPScale() {
- JNIEnv* env = AttachCurrentThread();
- jdouble result =
- Java_DeviceDisplayInfo_getDIPScale(env, j_device_info_.obj());
- return static_cast<double>(result);
+ return SharedDeviceDisplayInfo::GetInstance()->GetDIPScale();
}
-// static
-bool DeviceDisplayInfo::RegisterDeviceDisplayInfo(JNIEnv* env) {
- return RegisterNativesImpl(env);
+int DeviceDisplayInfo::GetSmallestDIPWidth() {
+ return SharedDeviceDisplayInfo::GetInstance()->GetSmallestDIPWidth();
}
} // namespace gfx
diff --git a/chromium/ui/gfx/android/device_display_info.h b/chromium/ui/gfx/android/device_display_info.h
index 9f90f897b6a..83968e9b51e 100644
--- a/chromium/ui/gfx/android/device_display_info.h
+++ b/chromium/ui/gfx/android/device_display_info.h
@@ -8,7 +8,6 @@
#include <jni.h>
#include <string>
-#include "base/android/scoped_java_ref.h"
#include "base/basictypes.h"
#include "ui/gfx/gfx_export.h"
@@ -16,7 +15,7 @@ namespace gfx {
// Facilitates access to device information typically only
// available using the Android SDK, including Display properties.
-class UI_EXPORT DeviceDisplayInfo {
+class GFX_EXPORT DeviceDisplayInfo {
public:
DeviceDisplayInfo();
~DeviceDisplayInfo();
@@ -37,12 +36,10 @@ class UI_EXPORT DeviceDisplayInfo {
// (1.0 is 160dpi, 0.75 is 120dpi, 2.0 is 320dpi).
double GetDIPScale();
- // Registers methods with JNI and returns true if succeeded.
- static bool RegisterDeviceDisplayInfo(JNIEnv* env);
+ // Smallest possible screen size in density-independent pixels.
+ int GetSmallestDIPWidth();
private:
- base::android::ScopedJavaGlobalRef<jobject> j_device_info_;
-
DISALLOW_COPY_AND_ASSIGN(DeviceDisplayInfo);
};
diff --git a/chromium/ui/gfx/android/java_bitmap.cc b/chromium/ui/gfx/android/java_bitmap.cc
index 6c2eaa845a2..2a1be65d215 100644
--- a/chromium/ui/gfx/android/java_bitmap.cc
+++ b/chromium/ui/gfx/android/java_bitmap.cc
@@ -39,11 +39,11 @@ JavaBitmap::~JavaBitmap() {
// static
bool JavaBitmap::RegisterJavaBitmap(JNIEnv* env) {
- return ui::RegisterNativesImpl(env);
+ return RegisterNativesImpl(env);
}
static ScopedJavaLocalRef<jobject> CreateJavaBitmap(const gfx::Size& size) {
- return ui::Java_BitmapHelper_createBitmap(AttachCurrentThread(),
+ return Java_BitmapHelper_createBitmap(AttachCurrentThread(),
size.width(), size.height());
}
@@ -87,7 +87,7 @@ SkBitmap CreateSkBitmapFromResource(const char* name, gfx::Size size) {
DCHECK(!size.IsEmpty());
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jstring> jname(env, env->NewStringUTF(name));
- ScopedJavaLocalRef<jobject> jobj(ui::Java_BitmapHelper_decodeDrawableResource(
+ ScopedJavaLocalRef<jobject> jobj(Java_BitmapHelper_decodeDrawableResource(
env, jname.obj(), size.width(), size.height()));
if (jobj.is_null())
return SkBitmap();
diff --git a/chromium/ui/gfx/android/java_bitmap.h b/chromium/ui/gfx/android/java_bitmap.h
index 319ad79eb1e..9d1e4432cb7 100644
--- a/chromium/ui/gfx/android/java_bitmap.h
+++ b/chromium/ui/gfx/android/java_bitmap.h
@@ -17,7 +17,7 @@ namespace gfx {
// This class wraps a JNI AndroidBitmap object to make it easier to use. It
// handles locking and unlocking of the underlying pixels, along with wrapping
// various JNI methods.
-class UI_EXPORT JavaBitmap {
+class GFX_EXPORT JavaBitmap {
public:
explicit JavaBitmap(jobject bitmap);
~JavaBitmap();
@@ -41,14 +41,15 @@ class UI_EXPORT JavaBitmap {
DISALLOW_COPY_AND_ASSIGN(JavaBitmap);
};
-UI_EXPORT base::android::ScopedJavaLocalRef<jobject> ConvertToJavaBitmap(
+GFX_EXPORT base::android::ScopedJavaLocalRef<jobject> ConvertToJavaBitmap(
const SkBitmap* skbitmap);
-UI_EXPORT SkBitmap CreateSkBitmapFromJavaBitmap(JavaBitmap& jbitmap);
+GFX_EXPORT SkBitmap CreateSkBitmapFromJavaBitmap(JavaBitmap& jbitmap);
// If the resource loads successfully, it will be resized to |size|.
// Note: If the source resource is smaller than |size|, quality may suffer.
-UI_EXPORT SkBitmap CreateSkBitmapFromResource(const char* name, gfx::Size size);
+GFX_EXPORT SkBitmap CreateSkBitmapFromResource(const char* name,
+ gfx::Size size);
} // namespace gfx
diff --git a/chromium/ui/gfx/android/shared_device_display_info.cc b/chromium/ui/gfx/android/shared_device_display_info.cc
new file mode 100644
index 00000000000..9ac18d0218d
--- /dev/null
+++ b/chromium/ui/gfx/android/shared_device_display_info.cc
@@ -0,0 +1,128 @@
+// Copyright 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.
+
+#include "ui/gfx/android/shared_device_display_info.h"
+
+#include "base/android/jni_android.h"
+#include "base/android/jni_string.h"
+#include "base/logging.h"
+#include "jni/DeviceDisplayInfo_jni.h"
+
+namespace gfx {
+
+// static JNI call
+static void UpdateSharedDeviceDisplayInfo(JNIEnv* env,
+ jobject obj,
+ jint display_height,
+ jint display_width,
+ jint bits_per_pixel,
+ jint bits_per_component,
+ jdouble dip_scale,
+ jint smallest_dip_width) {
+ SharedDeviceDisplayInfo::GetInstance()->InvokeUpdate(env, obj,
+ display_height, display_width, bits_per_pixel, bits_per_component,
+ dip_scale, smallest_dip_width);
+}
+
+// static
+SharedDeviceDisplayInfo* SharedDeviceDisplayInfo::GetInstance() {
+ return Singleton<SharedDeviceDisplayInfo>::get();
+}
+
+int SharedDeviceDisplayInfo::GetDisplayHeight() {
+ base::AutoLock autolock(lock_);
+ DCHECK_NE(0, display_height_);
+ return display_height_;
+}
+
+int SharedDeviceDisplayInfo::GetDisplayWidth() {
+ base::AutoLock autolock(lock_);
+ DCHECK_NE(0, display_width_);
+ return display_width_;
+}
+
+int SharedDeviceDisplayInfo::GetBitsPerPixel() {
+ base::AutoLock autolock(lock_);
+ DCHECK_NE(0, bits_per_pixel_);
+ return bits_per_pixel_;
+}
+
+int SharedDeviceDisplayInfo::GetBitsPerComponent() {
+ base::AutoLock autolock(lock_);
+ DCHECK_NE(0, bits_per_component_);
+ return bits_per_component_;
+}
+
+double SharedDeviceDisplayInfo::GetDIPScale() {
+ base::AutoLock autolock(lock_);
+ DCHECK_NE(0, dip_scale_);
+ return dip_scale_;
+}
+
+int SharedDeviceDisplayInfo::GetSmallestDIPWidth() {
+ base::AutoLock autolock(lock_);
+ DCHECK_NE(0, smallest_dip_width_);
+ return smallest_dip_width_;
+}
+
+// static
+bool SharedDeviceDisplayInfo::RegisterSharedDeviceDisplayInfo(JNIEnv* env) {
+ return RegisterNativesImpl(env);
+}
+
+void SharedDeviceDisplayInfo::InvokeUpdate(JNIEnv* env,
+ jobject obj,
+ jint display_height,
+ jint display_width,
+ jint bits_per_pixel,
+ jint bits_per_component,
+ jdouble dip_scale,
+ jint smallest_dip_width) {
+ base::AutoLock autolock(lock_);
+
+ UpdateDisplayInfo(env, obj, display_height,
+ display_width, bits_per_pixel, bits_per_component, dip_scale,
+ smallest_dip_width);
+}
+
+SharedDeviceDisplayInfo::SharedDeviceDisplayInfo()
+ : display_height_(0),
+ display_width_(0),
+ bits_per_pixel_(0),
+ bits_per_component_(0),
+ dip_scale_(0),
+ smallest_dip_width_(0) {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ j_device_info_.Reset(
+ Java_DeviceDisplayInfo_createWithListener(env,
+ base::android::GetApplicationContext()));
+ UpdateDisplayInfo(env, j_device_info_.obj(),
+ Java_DeviceDisplayInfo_getDisplayHeight(env, j_device_info_.obj()),
+ Java_DeviceDisplayInfo_getDisplayWidth(env, j_device_info_.obj()),
+ Java_DeviceDisplayInfo_getBitsPerPixel(env, j_device_info_.obj()),
+ Java_DeviceDisplayInfo_getBitsPerComponent(env, j_device_info_.obj()),
+ Java_DeviceDisplayInfo_getDIPScale(env, j_device_info_.obj()),
+ Java_DeviceDisplayInfo_getSmallestDIPWidth(env, j_device_info_.obj()));
+}
+
+SharedDeviceDisplayInfo::~SharedDeviceDisplayInfo() {
+}
+
+void SharedDeviceDisplayInfo::UpdateDisplayInfo(JNIEnv* env,
+ jobject jobj,
+ jint display_height,
+ jint display_width,
+ jint bits_per_pixel,
+ jint bits_per_component,
+ jdouble dip_scale,
+ jint smallest_dip_width) {
+ display_height_ = static_cast<int>(display_height);
+ display_width_ = static_cast<int>(display_width);
+ bits_per_pixel_ = static_cast<int>(bits_per_pixel);
+ bits_per_component_ = static_cast<int>(bits_per_component);
+ dip_scale_ = static_cast<double>(dip_scale);
+ smallest_dip_width_ = static_cast<int>(smallest_dip_width);
+}
+
+} // namespace gfx
diff --git a/chromium/ui/gfx/android/shared_device_display_info.h b/chromium/ui/gfx/android/shared_device_display_info.h
new file mode 100644
index 00000000000..1e1fc0c6662
--- /dev/null
+++ b/chromium/ui/gfx/android/shared_device_display_info.h
@@ -0,0 +1,68 @@
+// Copyright 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_ANDROID_SHARED_DEVICE_DISPLAY_INFO_H_
+#define UI_GFX_ANDROID_SHARED_DEVICE_DISPLAY_INFO_H_
+
+#include "base/android/scoped_java_ref.h"
+#include "base/basictypes.h"
+#include "base/memory/singleton.h"
+#include "base/synchronization/lock.h"
+
+namespace gfx {
+
+// Facilitates access to device information typically only
+// available using the Android SDK, including Display properties.
+class SharedDeviceDisplayInfo {
+ public:
+ static SharedDeviceDisplayInfo* GetInstance();
+
+ int GetDisplayHeight();
+ int GetDisplayWidth();
+ int GetBitsPerPixel();
+ int GetBitsPerComponent();
+ double GetDIPScale();
+ int GetSmallestDIPWidth();
+
+ // Registers methods with JNI and returns true if succeeded.
+ static bool RegisterSharedDeviceDisplayInfo(JNIEnv* env);
+
+ void InvokeUpdate(JNIEnv* env,
+ jobject jobj,
+ jint display_height,
+ jint display_width,
+ jint bits_per_pixel,
+ jint bits_per_component,
+ jdouble dip_scale,
+ jint smallest_dip_width);
+ private:
+ friend struct DefaultSingletonTraits<SharedDeviceDisplayInfo>;
+
+ SharedDeviceDisplayInfo();
+ ~SharedDeviceDisplayInfo();
+ void UpdateDisplayInfo(JNIEnv* env,
+ jobject jobj,
+ jint display_height,
+ jint display_width,
+ jint bits_per_pixel,
+ jint bits_per_component,
+ jdouble dip_scale,
+ jint smallest_dip_width);
+
+ base::Lock lock_;
+ base::android::ScopedJavaGlobalRef<jobject> j_device_info_;
+
+ int display_height_;
+ int display_width_;
+ int bits_per_pixel_;
+ int bits_per_component_;
+ double dip_scale_;
+ int smallest_dip_width_;
+
+ DISALLOW_COPY_AND_ASSIGN(SharedDeviceDisplayInfo);
+};
+
+} // namespace gfx
+
+#endif // UI_GFX_ANDROID_SHARED_DEVICE_DISPLAY_INFO_H_
diff --git a/chromium/ui/gfx/android/view_configuration.cc b/chromium/ui/gfx/android/view_configuration.cc
new file mode 100644
index 00000000000..63657178b15
--- /dev/null
+++ b/chromium/ui/gfx/android/view_configuration.cc
@@ -0,0 +1,56 @@
+// Copyright 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.
+
+#include "ui/gfx/android/view_configuration.h"
+
+#include "base/android/jni_android.h"
+#include "jni/ViewConfiguration_jni.h"
+
+using namespace JNI_ViewConfiguration;
+using base::android::AttachCurrentThread;
+using base::android::GetApplicationContext;
+
+namespace gfx {
+
+int ViewConfiguration::GetDoubleTapTimeoutInMs() {
+ JNIEnv* env = AttachCurrentThread();
+ return Java_ViewConfiguration_getDoubleTapTimeout(env);
+}
+
+int ViewConfiguration::GetLongPressTimeoutInMs() {
+ JNIEnv* env = AttachCurrentThread();
+ return Java_ViewConfiguration_getLongPressTimeout(env);
+}
+
+int ViewConfiguration::GetTapTimeoutInMs() {
+ JNIEnv* env = AttachCurrentThread();
+ return Java_ViewConfiguration_getTapTimeout(env);
+}
+
+int ViewConfiguration::GetMaximumFlingVelocityInPixelsPerSecond() {
+ JNIEnv* env = AttachCurrentThread();
+ ScopedJavaLocalRef<jobject> view =
+ Java_ViewConfiguration_get(env, GetApplicationContext());
+ return Java_ViewConfiguration_getScaledMaximumFlingVelocity(env, view.obj());
+}
+
+int ViewConfiguration::GetMinimumFlingVelocityInPixelsPerSecond() {
+ JNIEnv* env = AttachCurrentThread();
+ ScopedJavaLocalRef<jobject> view =
+ Java_ViewConfiguration_get(env, GetApplicationContext());
+ return Java_ViewConfiguration_getScaledMinimumFlingVelocity(env, view.obj());
+}
+
+int ViewConfiguration::GetTouchSlopInPixels() {
+ JNIEnv* env = AttachCurrentThread();
+ ScopedJavaLocalRef<jobject> view =
+ Java_ViewConfiguration_get(env, GetApplicationContext());
+ return Java_ViewConfiguration_getScaledTouchSlop(env, view.obj());
+}
+
+bool ViewConfiguration::RegisterViewConfiguration(JNIEnv* env) {
+ return RegisterNativesImpl(env);
+}
+
+} // namespace gfx
diff --git a/chromium/ui/gfx/android/view_configuration.h b/chromium/ui/gfx/android/view_configuration.h
new file mode 100644
index 00000000000..f0995cb3e29
--- /dev/null
+++ b/chromium/ui/gfx/android/view_configuration.h
@@ -0,0 +1,32 @@
+// Copyright 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_ANDROID_VIEW_CONFIGURATION_H_
+#define UI_GFX_ANDROID_VIEW_CONFIGURATION_H_
+
+#include <jni.h>
+
+#include "ui/gfx/gfx_export.h"
+
+namespace gfx {
+
+// Provides access to Android's ViewConfiguration for gesture-related constants.
+class GFX_EXPORT ViewConfiguration {
+ public:
+ static int GetDoubleTapTimeoutInMs();
+ static int GetLongPressTimeoutInMs();
+ static int GetTapTimeoutInMs();
+
+ static int GetMaximumFlingVelocityInPixelsPerSecond();
+ static int GetMinimumFlingVelocityInPixelsPerSecond();
+
+ static int GetTouchSlopInPixels();
+
+ // Registers methods with JNI and returns true if succeeded.
+ static bool RegisterViewConfiguration(JNIEnv* env);
+};
+
+} // namespace gfx
+
+#endif // UI_GFX_ANDROID_VIEW_CONFIGURATION_H_
diff --git a/chromium/ui/gfx/animation/animation.cc b/chromium/ui/gfx/animation/animation.cc
index ba0bac822cc..3b525f22f00 100644
--- a/chromium/ui/gfx/animation/animation.cc
+++ b/chromium/ui/gfx/animation/animation.cc
@@ -62,16 +62,17 @@ void Animation::Stop() {
}
double Animation::CurrentValueBetween(double start, double target) const {
- return Tween::ValueBetween(GetCurrentValue(), start, target);
+ return Tween::DoubleValueBetween(GetCurrentValue(), start, target);
}
int Animation::CurrentValueBetween(int start, int target) const {
- return Tween::ValueBetween(GetCurrentValue(), start, target);
+ return Tween::IntValueBetween(GetCurrentValue(), start, target);
}
gfx::Rect Animation::CurrentValueBetween(const gfx::Rect& start_bounds,
const gfx::Rect& target_bounds) const {
- return Tween::ValueBetween(GetCurrentValue(), start_bounds, target_bounds);
+ return Tween::RectValueBetween(
+ GetCurrentValue(), start_bounds, target_bounds);
}
void Animation::SetContainer(AnimationContainer* container) {
diff --git a/chromium/ui/gfx/animation/animation_container.cc b/chromium/ui/gfx/animation/animation_container.cc
index c76f1bb7797..d8290b2eef6 100644
--- a/chromium/ui/gfx/animation/animation_container.cc
+++ b/chromium/ui/gfx/animation/animation_container.cc
@@ -6,6 +6,7 @@
#include "ui/gfx/animation/animation_container_element.h"
#include "ui/gfx/animation/animation_container_observer.h"
+#include "ui/gfx/frame_time.h"
using base::TimeDelta;
using base::TimeTicks;
@@ -13,7 +14,7 @@ using base::TimeTicks;
namespace gfx {
AnimationContainer::AnimationContainer()
- : last_tick_time_(TimeTicks::Now()),
+ : last_tick_time_(gfx::FrameTime::Now()),
observer_(NULL) {
}
@@ -28,7 +29,7 @@ void AnimationContainer::Start(AnimationContainerElement* element) {
// element isn't running.
if (elements_.empty()) {
- last_tick_time_ = TimeTicks::Now();
+ last_tick_time_ = gfx::FrameTime::Now();
SetMinTimerInterval(element->GetTimerInterval());
} else if (element->GetTimerInterval() < min_timer_interval_) {
SetMinTimerInterval(element->GetTimerInterval());
@@ -61,7 +62,7 @@ void AnimationContainer::Run() {
// ourself here to make sure we're still valid after running all the elements.
scoped_refptr<AnimationContainer> this_ref(this);
- TimeTicks current_time = TimeTicks::Now();
+ TimeTicks current_time = gfx::FrameTime::Now();
last_tick_time_ = current_time;
diff --git a/chromium/ui/gfx/animation/animation_container_unittest.cc b/chromium/ui/gfx/animation/animation_container_unittest.cc
index 25977c26161..70d3b0e10f8 100644
--- a/chromium/ui/gfx/animation/animation_container_unittest.cc
+++ b/chromium/ui/gfx/animation/animation_container_unittest.cc
@@ -5,27 +5,40 @@
#include "ui/gfx/animation/animation_container.h"
#include "base/memory/scoped_ptr.h"
-#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/animation/animation_container_observer.h"
#include "ui/gfx/animation/linear_animation.h"
#include "ui/gfx/animation/test_animation_delegate.h"
-using testing::AtLeast;
-
namespace gfx {
namespace {
-class MockObserver : public AnimationContainerObserver {
+class FakeAnimationContainerObserver : public AnimationContainerObserver {
public:
- MockObserver() {}
+ FakeAnimationContainerObserver()
+ : progressed_count_(0),
+ empty_(false) {
+ }
- MOCK_METHOD1(AnimationContainerProgressed, void(AnimationContainer*));
- MOCK_METHOD1(AnimationContainerEmpty, void(AnimationContainer*));
+ int progressed_count() const { return progressed_count_; }
+ bool empty() const { return empty_; }
private:
- DISALLOW_COPY_AND_ASSIGN(MockObserver);
+ virtual void AnimationContainerProgressed(
+ AnimationContainer* container) OVERRIDE {
+ progressed_count_++;
+ }
+
+ // Invoked when no more animations are being managed by this container.
+ virtual void AnimationContainerEmpty(AnimationContainer* container) OVERRIDE {
+ empty_ = true;
+ }
+
+ int progressed_count_;
+ bool empty_;
+
+ DISALLOW_COPY_AND_ASSIGN(FakeAnimationContainerObserver);
};
class TestAnimation : public LinearAnimation {
@@ -94,7 +107,7 @@ TEST_F(AnimationContainerTest, Multi) {
// Makes sure observer is notified appropriately.
TEST_F(AnimationContainerTest, Observer) {
- MockObserver observer;
+ FakeAnimationContainerObserver observer;
TestAnimationDelegate delegate1;
scoped_refptr<AnimationContainer> container(new AnimationContainer());
@@ -102,12 +115,6 @@ TEST_F(AnimationContainerTest, Observer) {
TestAnimation animation1(&delegate1);
animation1.SetContainer(container.get());
- // We expect to get these two calls: the animation progressed, and then when
- // the animation completed the container went empty.
- EXPECT_CALL(observer, AnimationContainerProgressed(container.get())).Times(
- AtLeast(1));
- EXPECT_CALL(observer, AnimationContainerEmpty(container.get())).Times(1);
-
// Start the animation.
animation1.Start();
EXPECT_TRUE(container->is_running());
@@ -115,9 +122,13 @@ TEST_F(AnimationContainerTest, Observer) {
// Run the message loop. The delegate quits the message loop when notified.
base::MessageLoop::current()->Run();
+ EXPECT_EQ(1, observer.progressed_count());
+
// The timer should have finished.
EXPECT_TRUE(delegate1.finished());
+ EXPECT_TRUE(observer.empty());
+
// And the container should no longer be running.
EXPECT_FALSE(container->is_running());
diff --git a/chromium/ui/gfx/animation/tween.cc b/chromium/ui/gfx/animation/tween.cc
index 4d1a6b3b260..174305078c2 100644
--- a/chromium/ui/gfx/animation/tween.cc
+++ b/chromium/ui/gfx/animation/tween.cc
@@ -10,7 +10,11 @@
#include <float.h>
#endif
+#include <algorithm>
+
+#include "base/basictypes.h"
#include "base/logging.h"
+#include "ui/gfx/safe_integer_conversions.h"
namespace gfx {
@@ -55,13 +59,70 @@ double Tween::CalculateValue(Tween::Type type, double state) {
return state;
}
+namespace {
+uint8 FloatToColorByte(float f) {
+ return std::min(std::max(ToRoundedInt(f * 255.f), 0), 255);
+}
+
+uint8 BlendColorComponents(uint8 start,
+ uint8 target,
+ float start_alpha,
+ float target_alpha,
+ float blended_alpha,
+ double progress) {
+ // Since progress can be outside [0, 1], blending can produce a value outside
+ // [0, 255].
+ float blended_premultiplied = Tween::FloatValueBetween(
+ progress, start / 255.f * start_alpha, target / 255.f * target_alpha);
+ return FloatToColorByte(blended_premultiplied / blended_alpha);
+}
+
+} // namespace
+
+// static
+SkColor Tween::ColorValueBetween(double value, SkColor start, SkColor target) {
+ float start_a = SkColorGetA(start) / 255.f;
+ float target_a = SkColorGetA(target) / 255.f;
+ float blended_a = FloatValueBetween(value, start_a, target_a);
+ if (blended_a <= 0.f)
+ return SkColorSetARGB(0, 0, 0, 0);
+ blended_a = std::min(blended_a, 1.f);
+
+ uint8 blended_r = BlendColorComponents(SkColorGetR(start),
+ SkColorGetR(target),
+ start_a,
+ target_a,
+ blended_a,
+ value);
+ uint8 blended_g = BlendColorComponents(SkColorGetG(start),
+ SkColorGetG(target),
+ start_a,
+ target_a,
+ blended_a,
+ value);
+ uint8 blended_b = BlendColorComponents(SkColorGetB(start),
+ SkColorGetB(target),
+ start_a,
+ target_a,
+ blended_a,
+ value);
+
+ return SkColorSetARGB(
+ FloatToColorByte(blended_a), blended_r, blended_g, blended_b);
+}
+
// static
-double Tween::ValueBetween(double value, double start, double target) {
+double Tween::DoubleValueBetween(double value, double start, double target) {
return start + (target - start) * value;
}
// static
-int Tween::ValueBetween(double value, int start, int target) {
+float Tween::FloatValueBetween(double value, float start, float target) {
+ return static_cast<float>(start + (target - start) * value);
+}
+
+// static
+int Tween::IntValueBetween(double value, int start, int target) {
if (start == target)
return start;
double delta = static_cast<double>(target - start);
@@ -76,22 +137,28 @@ int Tween::ValueBetween(double value, int start, int target) {
#endif
}
+//static
+int Tween::LinearIntValueBetween(double value, int start, int target) {
+ return std::floor(0.5 + DoubleValueBetween(value, start, target));
+}
+
// static
-gfx::Rect Tween::ValueBetween(double value,
- const gfx::Rect& start_bounds,
- const gfx::Rect& target_bounds) {
- return gfx::Rect(ValueBetween(value, start_bounds.x(), target_bounds.x()),
- ValueBetween(value, start_bounds.y(), target_bounds.y()),
- ValueBetween(value, start_bounds.width(),
- target_bounds.width()),
- ValueBetween(value, start_bounds.height(),
- target_bounds.height()));
+gfx::Rect Tween::RectValueBetween(double value,
+ const gfx::Rect& start_bounds,
+ const gfx::Rect& target_bounds) {
+ return gfx::Rect(
+ LinearIntValueBetween(value, start_bounds.x(), target_bounds.x()),
+ LinearIntValueBetween(value, start_bounds.y(), target_bounds.y()),
+ LinearIntValueBetween(value, start_bounds.width(), target_bounds.width()),
+ LinearIntValueBetween(
+ value, start_bounds.height(), target_bounds.height()));
}
// static
-gfx::Transform Tween::ValueBetween(double value,
- const gfx::Transform& start_transform,
- const gfx::Transform& end_transform) {
+gfx::Transform Tween::TransformValueBetween(
+ double value,
+ const gfx::Transform& start_transform,
+ const gfx::Transform& end_transform) {
if (value >= 1.0)
return end_transform;
if (value <= 0.0)
diff --git a/chromium/ui/gfx/animation/tween.h b/chromium/ui/gfx/animation/tween.h
index 0c1f7585ecf..04f353db1ae 100644
--- a/chromium/ui/gfx/animation/tween.h
+++ b/chromium/ui/gfx/animation/tween.h
@@ -6,6 +6,7 @@
#define UI_GFX_ANIMATION_TWEEN_H_
#include "base/basictypes.h"
+#include "third_party/skia/include/core/SkColor.h"
#include "ui/gfx/gfx_export.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/transform.h"
@@ -30,14 +31,27 @@ class GFX_EXPORT Tween {
static double CalculateValue(Type type, double state);
// Conveniences for getting a value between a start and end point.
- static double ValueBetween(double value, double start, double target);
- static int ValueBetween(double value, int start, int target);
- static gfx::Rect ValueBetween(double value,
- const gfx::Rect& start_bounds,
- const gfx::Rect& target_bounds);
- static gfx::Transform ValueBetween(double value,
- const gfx::Transform& start_transform,
- const gfx::Transform& target_transform);
+ static SkColor ColorValueBetween(double value, SkColor start, SkColor target);
+ static double DoubleValueBetween(double value, double start, double target);
+ static float FloatValueBetween(double value, float start, float target);
+
+ // Interpolated between start and target, with every integer in this range
+ // given equal weight.
+ static int IntValueBetween(double value, int start, int target);
+
+ // Interpolates between start and target as real numbers, and rounds the
+ // result to the nearest integer, with ties broken by rounding towards
+ // positive infinity. This gives start and target half the weight of the
+ // other integers in the range. This is the integer interpolation approach
+ // specified by www.w3.org/TR/css3-transitions.
+ static int LinearIntValueBetween(double value, int start, int target);
+ static gfx::Rect RectValueBetween(double value,
+ const gfx::Rect& start_bounds,
+ const gfx::Rect& target_bounds);
+ static gfx::Transform TransformValueBetween(
+ double value,
+ const gfx::Transform& start_transform,
+ const gfx::Transform& target_transform);
private:
Tween();
diff --git a/chromium/ui/gfx/animation/tween_unittest.cc b/chromium/ui/gfx/animation/tween_unittest.cc
new file mode 100644
index 00000000000..d92fe1bacc4
--- /dev/null
+++ b/chromium/ui/gfx/animation/tween_unittest.cc
@@ -0,0 +1,136 @@
+// Copyright 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.
+
+#include "ui/gfx/animation/tween.h"
+
+#include <math.h>
+
+#if defined(OS_WIN)
+#include <float.h>
+#endif
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/test/color_util.h"
+
+namespace gfx {
+namespace {
+
+double next_double(double d) {
+#if defined(OS_WIN)
+ return _nextafter(d, d+1);
+#else
+ return nextafter(d, d+1);
+#endif
+}
+
+// Validates that the same interpolations are made as in Blink.
+TEST(TweenTest, ColorValueBetween) {
+ // From blink's AnimatableColorTest.
+ EXPECT_SKCOLOR_EQ(0xFF00FF00,
+ Tween::ColorValueBetween(-10.0, 0xFF00FF00, 0xFF00FF00));
+ EXPECT_SKCOLOR_EQ(0xFF00FF00,
+ Tween::ColorValueBetween(-10.0, 0xFF00FF00, 0xFFFF00FF));
+ EXPECT_SKCOLOR_EQ(0xFF00FF00,
+ Tween::ColorValueBetween(0.0, 0xFF00FF00, 0xFFFF00FF));
+ EXPECT_SKCOLOR_EQ(0xFF01FE01,
+ Tween::ColorValueBetween(1.0 / 255, 0xFF00FF00, 0xFFFF00FF));
+ EXPECT_SKCOLOR_EQ(0xFF808080,
+ Tween::ColorValueBetween(0.5, 0xFF00FF00, 0xFFFF00FF));
+ EXPECT_SKCOLOR_EQ(
+ 0xFFFE01FE,
+ Tween::ColorValueBetween(254.0 / 255.0, 0xFF00FF00, 0xFFFF00FF));
+ EXPECT_SKCOLOR_EQ(0xFFFF00FF,
+ Tween::ColorValueBetween(1.0, 0xFF00FF00, 0xFFFF00FF));
+ EXPECT_SKCOLOR_EQ(0xFFFF00FF,
+ Tween::ColorValueBetween(10.0, 0xFF00FF00, 0xFFFF00FF));
+ EXPECT_SKCOLOR_EQ(0xFF0C253E,
+ Tween::ColorValueBetween(3.0 / 16.0, 0xFF001020, 0xFF4080C0));
+ EXPECT_SKCOLOR_EQ(0x80FF00FF,
+ Tween::ColorValueBetween(0.5, 0x0000FF00, 0xFFFF00FF));
+ EXPECT_SKCOLOR_EQ(0x60AA55AA,
+ Tween::ColorValueBetween(0.5, 0x4000FF00, 0x80FF00FF));
+ EXPECT_SKCOLOR_EQ(0x60FFAAFF,
+ Tween::ColorValueBetween(0.5, 0x40FF00FF, 0x80FFFFFF));
+ EXPECT_SKCOLOR_EQ(0x103060A0,
+ Tween::ColorValueBetween(0.5, 0x10204080, 0x104080C0));
+}
+
+// Ensures that each of the 3 integers in [0, 1, 2] ae selected with equal
+// weight.
+TEST(TweenTest, IntValueBetween) {
+ EXPECT_EQ(0, Tween::IntValueBetween(0.0, 0, 2));
+ EXPECT_EQ(0, Tween::IntValueBetween(0.5 / 3.0, 0, 2));
+ EXPECT_EQ(0, Tween::IntValueBetween(1.0 / 3.0, 0, 2));
+
+ EXPECT_EQ(1, Tween::IntValueBetween(next_double(1.0 / 3.0), 0, 2));
+ EXPECT_EQ(1, Tween::IntValueBetween(1.5 / 3.0, 0, 2));
+ EXPECT_EQ(1, Tween::IntValueBetween(2.0 / 3.0, 0, 2));
+
+ EXPECT_EQ(2, Tween::IntValueBetween(next_double(2.0 / 3.0), 0, 2));
+ EXPECT_EQ(2, Tween::IntValueBetween(2.5 / 3.0, 0, 2));
+ EXPECT_EQ(2, Tween::IntValueBetween(3.0 / 3.0, 0, 2));
+}
+
+TEST(TweenTest, IntValueBetweenNegative) {
+ EXPECT_EQ(-2, Tween::IntValueBetween(0.0, -2, 0));
+ EXPECT_EQ(-2, Tween::IntValueBetween(0.5 / 3.0, -2, 0));
+ EXPECT_EQ(-2, Tween::IntValueBetween(1.0 / 3.0, -2, 0));
+
+ EXPECT_EQ(-1, Tween::IntValueBetween(next_double(1.0 / 3.0), -2, 0));
+ EXPECT_EQ(-1, Tween::IntValueBetween(1.5 / 3.0, -2, 0));
+ EXPECT_EQ(-1, Tween::IntValueBetween(2.0 / 3.0, -2, 0));
+
+ EXPECT_EQ(0, Tween::IntValueBetween(next_double(2.0 / 3.0), -2, 0));
+ EXPECT_EQ(0, Tween::IntValueBetween(2.5 / 3.0, -2, 0));
+ EXPECT_EQ(0, Tween::IntValueBetween(3.0 / 3.0, -2, 0));
+}
+
+TEST(TweenTest, IntValueBetweenReverse) {
+ EXPECT_EQ(2, Tween::IntValueBetween(0.0, 2, 0));
+ EXPECT_EQ(2, Tween::IntValueBetween(0.5 / 3.0, 2, 0));
+ EXPECT_EQ(2, Tween::IntValueBetween(1.0 / 3.0, 2, 0));
+
+ EXPECT_EQ(1, Tween::IntValueBetween(next_double(1.0 / 3.0), 2, 0));
+ EXPECT_EQ(1, Tween::IntValueBetween(1.5 / 3.0, 2, 0));
+ EXPECT_EQ(1, Tween::IntValueBetween(2.0 / 3.0, 2, 0));
+
+ EXPECT_EQ(0, Tween::IntValueBetween(next_double(2.0 / 3.0), 2, 0));
+ EXPECT_EQ(0, Tween::IntValueBetween(2.5 / 3.0, 2, 0));
+ EXPECT_EQ(0, Tween::IntValueBetween(3.0 / 3.0, 2, 0));
+}
+
+TEST(TweenTest, LinearIntValueBetween) {
+ EXPECT_EQ(0, Tween::LinearIntValueBetween(0.0, 0, 2));
+ EXPECT_EQ(0, Tween::LinearIntValueBetween(0.5 / 4.0, 0, 2));
+ EXPECT_EQ(0, Tween::LinearIntValueBetween(0.99 / 4.0, 0, 2));
+
+ EXPECT_EQ(1, Tween::LinearIntValueBetween(1.0 / 4.0, 0, 2));
+ EXPECT_EQ(1, Tween::LinearIntValueBetween(1.5 / 4.0, 0, 2));
+ EXPECT_EQ(1, Tween::LinearIntValueBetween(2.0 / 4.0, 0, 2));
+ EXPECT_EQ(1, Tween::LinearIntValueBetween(2.5 / 4.0, 0, 2));
+ EXPECT_EQ(1, Tween::LinearIntValueBetween(2.99 / 4.0, 0, 2));
+
+ EXPECT_EQ(2, Tween::LinearIntValueBetween(3.0 / 4.0, 0, 2));
+ EXPECT_EQ(2, Tween::LinearIntValueBetween(3.5 / 4.0, 0, 2));
+ EXPECT_EQ(2, Tween::LinearIntValueBetween(4.0 / 4.0, 0, 2));
+}
+
+TEST(TweenTest, LinearIntValueBetweenNegative) {
+ EXPECT_EQ(-2, Tween::LinearIntValueBetween(0.0, -2, 0));
+ EXPECT_EQ(-2, Tween::LinearIntValueBetween(0.5 / 4.0, -2, 0));
+ EXPECT_EQ(-2, Tween::LinearIntValueBetween(0.99 / 4.0, -2, 0));
+
+ EXPECT_EQ(-1, Tween::LinearIntValueBetween(1.0 / 4.0, -2, 0));
+ EXPECT_EQ(-1, Tween::LinearIntValueBetween(1.5 / 4.0, -2, 0));
+ EXPECT_EQ(-1, Tween::LinearIntValueBetween(2.0 / 4.0, -2, 0));
+ EXPECT_EQ(-1, Tween::LinearIntValueBetween(2.5 / 4.0, -2, 0));
+ EXPECT_EQ(-1, Tween::LinearIntValueBetween(2.99 / 4.0, -2, 0));
+
+ EXPECT_EQ(0, Tween::LinearIntValueBetween(3.0 / 4.0, -2, 0));
+ EXPECT_EQ(0, Tween::LinearIntValueBetween(3.5 / 4.0, -2, 0));
+ EXPECT_EQ(0, Tween::LinearIntValueBetween(4.0 / 4.0, -2, 0));
+}
+
+} // namespace
+} // namespace gfx
diff --git a/chromium/ui/gfx/blit.cc b/chromium/ui/gfx/blit.cc
index a0bae8a17ed..4b87bc9aac5 100644
--- a/chromium/ui/gfx/blit.cc
+++ b/chromium/ui/gfx/blit.cc
@@ -11,11 +11,13 @@
#include "ui/gfx/rect.h"
#include "ui/gfx/vector2d.h"
+#if defined(USE_CAIRO)
#if defined(OS_OPENBSD)
#include <cairo.h>
#elif defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
#include <cairo/cairo.h>
#endif
+#endif
#if defined(OS_MACOSX)
#include "base/mac/scoped_cftyperef.h"
@@ -76,9 +78,7 @@ void BlitContextToContext(NativeDrawingContext dst_context,
base::ScopedCFTypeRef<CGImageRef> src_sub_image(
CGImageCreateWithImageInRect(src_image, src_rect.ToCGRect()));
CGContextDrawImage(dst_context, dst_rect.ToCGRect(), src_sub_image);
-#elif defined(OS_ANDROID)
- NOTIMPLEMENTED();
-#else // Linux, BSD, others
+#elif defined(USE_CAIRO)
// Only translations in the source context are supported; more complex
// source context transforms will be ignored.
cairo_save(dst_context);
@@ -92,6 +92,8 @@ void BlitContextToContext(NativeDrawingContext dst_context,
cairo_clip(dst_context);
cairo_paint(dst_context);
cairo_restore(dst_context);
+#else
+ NOTIMPLEMENTED();
#endif
}
diff --git a/chromium/ui/gfx/blit.h b/chromium/ui/gfx/blit.h
index f0668172c05..af56636bce7 100644
--- a/chromium/ui/gfx/blit.h
+++ b/chromium/ui/gfx/blit.h
@@ -17,35 +17,35 @@ class Rect;
class Vector2d;
// Blits a rectangle from the source context into the destination context.
-UI_EXPORT void BlitContextToContext(NativeDrawingContext dst_context,
+GFX_EXPORT void BlitContextToContext(NativeDrawingContext dst_context,
+ const Rect& dst_rect,
+ NativeDrawingContext src_context,
+ const Point& src_origin);
+
+// Blits a rectangle from the source context into the destination canvas.
+GFX_EXPORT void BlitContextToCanvas(SkCanvas *dst_canvas,
const Rect& dst_rect,
NativeDrawingContext src_context,
const Point& src_origin);
-// Blits a rectangle from the source context into the destination canvas.
-UI_EXPORT void BlitContextToCanvas(SkCanvas *dst_canvas,
- const Rect& dst_rect,
- NativeDrawingContext src_context,
- const Point& src_origin);
-
// Blits a rectangle from the source canvas into the destination context.
-UI_EXPORT void BlitCanvasToContext(NativeDrawingContext dst_context,
+GFX_EXPORT void BlitCanvasToContext(NativeDrawingContext dst_context,
+ const Rect& dst_rect,
+ SkCanvas *src_canvas,
+ const Point& src_origin);
+
+// Blits a rectangle from the source canvas into the destination canvas.
+GFX_EXPORT void BlitCanvasToCanvas(SkCanvas *dst_canvas,
const Rect& dst_rect,
SkCanvas *src_canvas,
const Point& src_origin);
-// Blits a rectangle from the source canvas into the destination canvas.
-UI_EXPORT void BlitCanvasToCanvas(SkCanvas *dst_canvas,
- const Rect& dst_rect,
- SkCanvas *src_canvas,
- const Point& src_origin);
-
// Scrolls the given subset of the given canvas by the given offset.
// The canvas should not have a clip or a transform applied, since platforms
// may implement those operations differently.
-UI_EXPORT void ScrollCanvas(SkCanvas* canvas,
- const Rect& clip,
- const Vector2d& offset);
+GFX_EXPORT void ScrollCanvas(SkCanvas* canvas,
+ const Rect& clip,
+ const Vector2d& offset);
} // namespace gfx
diff --git a/chromium/ui/gfx/box_f.cc b/chromium/ui/gfx/box_f.cc
index efb57967145..62e755bdc3e 100644
--- a/chromium/ui/gfx/box_f.cc
+++ b/chromium/ui/gfx/box_f.cc
@@ -6,6 +6,7 @@
#include <algorithm>
+#include "base/logging.h"
#include "base/strings/stringprintf.h"
namespace gfx {
@@ -24,6 +25,24 @@ bool BoxF::IsEmpty() const {
(height_ == 0 && depth_ == 0);
}
+void BoxF::ExpandTo(const Point3F& min, const Point3F& max) {
+ DCHECK_LE(min.x(), max.x());
+ DCHECK_LE(min.y(), max.y());
+ DCHECK_LE(min.z(), max.z());
+
+ float min_x = std::min(x(), min.x());
+ float min_y = std::min(y(), min.y());
+ float min_z = std::min(z(), min.z());
+ float max_x = std::max(right(), max.x());
+ float max_y = std::max(bottom(), max.y());
+ float max_z = std::max(front(), max.z());
+
+ origin_.SetPoint(min_x, min_y, min_z);
+ width_ = max_x - min_x;
+ height_ = max_y - min_y;
+ depth_ = max_z - min_z;
+}
+
void BoxF::Union(const BoxF& box) {
if (IsEmpty()) {
*this = box;
@@ -31,18 +50,15 @@ void BoxF::Union(const BoxF& box) {
}
if (box.IsEmpty())
return;
+ ExpandTo(box);
+}
- float min_x = std::min(x(), box.x());
- float min_y = std::min(y(), box.y());
- float min_z = std::min(z(), box.z());
- float max_x = std::max(right(), box.right());
- float max_y = std::max(bottom(), box.bottom());
- float max_z = std::max(front(), box.front());
+void BoxF::ExpandTo(const Point3F& point) {
+ ExpandTo(point, point);
+}
- origin_.SetPoint(min_x, min_y, min_z);
- width_ = max_x - min_x;
- height_ = max_y - min_y;
- depth_ = max_z - min_z;
+void BoxF::ExpandTo(const BoxF& box) {
+ ExpandTo(box.origin(), gfx::Point3F(box.right(), box.bottom(), box.front()));
}
BoxF UnionBoxes(const BoxF& a, const BoxF& b) {
diff --git a/chromium/ui/gfx/box_f.h b/chromium/ui/gfx/box_f.h
index 01063b19712..73e0972f662 100644
--- a/chromium/ui/gfx/box_f.h
+++ b/chromium/ui/gfx/box_f.h
@@ -12,7 +12,7 @@ namespace gfx {
// A 3d version of gfx::RectF, with the positive z-axis pointed towards
// the camera.
-class UI_EXPORT BoxF {
+class GFX_EXPORT BoxF {
public:
BoxF()
: width_(0.f),
@@ -94,14 +94,32 @@ class UI_EXPORT BoxF {
const Point3F& origin() const { return origin_; }
void set_origin(const Point3F& origin) { origin_ = origin; }
+ // Expands |this| to contain the given point, if necessary. Please note, even
+ // if |this| is empty, after the function |this| will continue to contain its
+ // |origin_|.
+ void ExpandTo(const Point3F& point);
+
+ // Expands |this| to contain the given box, if necessary. Please note, even
+ // if |this| is empty, after the function |this| will continue to contain its
+ // |origin_|.
+ void ExpandTo(const BoxF& box);
+
private:
+ // Expands the box to contain the two given points. It is required that each
+ // component of |min| is less than or equal to the corresponding component in
+ // |max|. Precisely, what this function does is ensure that after the function
+ // completes, |this| contains origin_, min, max, and origin_ + (width_,
+ // height_, depth_), even if the box is empty. Emptiness checks are handled in
+ // the public function Union.
+ void ExpandTo(const Point3F& min, const Point3F& max);
+
Point3F origin_;
float width_;
float height_;
float depth_;
};
-UI_EXPORT BoxF UnionBoxes(const BoxF& a, const BoxF& b);
+GFX_EXPORT BoxF UnionBoxes(const BoxF& a, const BoxF& b);
inline BoxF ScaleBox(const BoxF& b,
float x_scale,
diff --git a/chromium/ui/gfx/box_unittest.cc b/chromium/ui/gfx/box_unittest.cc
index 0e944ec5a12..db894cae1cd 100644
--- a/chromium/ui/gfx/box_unittest.cc
+++ b/chromium/ui/gfx/box_unittest.cc
@@ -78,6 +78,39 @@ TEST(BoxTest, Union) {
UnionBoxes(box3, box2).ToString());
}
+TEST(BoxTest, ExpandTo) {
+ BoxF box1;
+ BoxF box2(0.f, 0.f, 0.f, 1.f, 1.f, 1.f);
+ BoxF box3(1.f, 1.f, 1.f, 0.f, 0.f, 0.f);
+
+ Point3F point1(0.5f, 0.5f, 0.5f);
+ Point3F point2(-0.5f, -0.5f, -0.5f);
+
+ BoxF expected1_1(0.f, 0.f, 0.f, 0.5f, 0.5f, 0.5f);
+ BoxF expected1_2(-0.5f, -0.5f, -0.5f, 1.f, 1.f, 1.f);
+
+ BoxF expected2_1 = box2;
+ BoxF expected2_2(-0.5f, -0.5f, -0.5f, 1.5f, 1.5f, 1.5f);
+
+ BoxF expected3_1(0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f);
+ BoxF expected3_2(-0.5f, -0.5f, -0.5f, 1.5f, 1.5f, 1.5f);
+
+ box1.ExpandTo(point1);
+ EXPECT_EQ(expected1_1.ToString(), box1.ToString());
+ box1.ExpandTo(point2);
+ EXPECT_EQ(expected1_2.ToString(), box1.ToString());
+
+ box2.ExpandTo(point1);
+ EXPECT_EQ(expected2_1.ToString(), box2.ToString());
+ box2.ExpandTo(point2);
+ EXPECT_EQ(expected2_2.ToString(), box2.ToString());
+
+ box3.ExpandTo(point1);
+ EXPECT_EQ(expected3_1.ToString(), box3.ToString());
+ box3.ExpandTo(point2);
+ EXPECT_EQ(expected3_2.ToString(), box3.ToString());
+}
+
TEST(BoxTest, Scale) {
BoxF box1(2.f, 3.f, 4.f, 5.f, 6.f, 7.f);
diff --git a/chromium/ui/gfx/canvas.cc b/chromium/ui/gfx/canvas.cc
index b59d2a0d888..b89efa9e2b7 100644
--- a/chromium/ui/gfx/canvas.cc
+++ b/chromium/ui/gfx/canvas.cc
@@ -4,6 +4,7 @@
#include "ui/gfx/canvas.h"
+#include <cmath>
#include <limits>
#include "base/i18n/rtl.h"
@@ -23,11 +24,10 @@
namespace gfx {
-Canvas::Canvas(const Size& size, ui::ScaleFactor scale_factor, bool is_opaque)
- : scale_factor_(scale_factor),
+Canvas::Canvas(const Size& size, float image_scale, bool is_opaque)
+ : image_scale_(image_scale),
canvas_(NULL) {
- Size pixel_size = ToCeiledSize(
- ScaleSize(size, ui::GetScaleFactorScale(scale_factor)));
+ Size pixel_size = ToCeiledSize(ScaleSize(size, image_scale));
owned_canvas_ = skia::AdoptRef(skia::CreatePlatformCanvas(pixel_size.width(),
pixel_size.height(),
is_opaque));
@@ -39,24 +39,24 @@ Canvas::Canvas(const Size& size, ui::ScaleFactor scale_factor, bool is_opaque)
owned_canvas_->clear(SkColorSetARGB(0, 0, 0, 0));
#endif
- SkScalar scale = SkFloatToScalar(ui::GetScaleFactorScale(scale_factor));
- canvas_->scale(scale, scale);
+ SkScalar scale_scalar = SkFloatToScalar(image_scale);
+ canvas_->scale(scale_scalar, scale_scalar);
}
Canvas::Canvas(const ImageSkiaRep& image_rep, bool is_opaque)
- : scale_factor_(image_rep.scale_factor()),
+ : image_scale_(image_rep.scale()),
owned_canvas_(skia::AdoptRef(
skia::CreatePlatformCanvas(image_rep.pixel_width(),
image_rep.pixel_height(),
is_opaque))),
canvas_(owned_canvas_.get()) {
- SkScalar scale = SkFloatToScalar(ui::GetScaleFactorScale(scale_factor_));
- canvas_->scale(scale, scale);
+ SkScalar scale_scalar = SkFloatToScalar(image_scale_);
+ canvas_->scale(scale_scalar, scale_scalar);
DrawImageInt(ImageSkia(image_rep), 0, 0);
}
Canvas::Canvas()
- : scale_factor_(ui::SCALE_FACTOR_100P),
+ : image_scale_(1.0),
owned_canvas_(skia::AdoptRef(skia::CreatePlatformCanvas(0, 0, false))),
canvas_(owned_canvas_.get()) {
}
@@ -66,22 +66,36 @@ Canvas::~Canvas() {
// static
Canvas* Canvas::CreateCanvasWithoutScaling(SkCanvas* canvas,
- ui::ScaleFactor scale_factor) {
- return new Canvas(canvas, scale_factor);
+ float image_scale) {
+ return new Canvas(canvas, image_scale);
}
void Canvas::RecreateBackingCanvas(const Size& size,
- ui::ScaleFactor scale_factor,
+ float image_scale,
bool is_opaque) {
- scale_factor_ = scale_factor;
- Size pixel_size = ToFlooredSize(
- ScaleSize(size, ui::GetScaleFactorScale(scale_factor)));
+ image_scale_ = image_scale;
+ Size pixel_size = ToFlooredSize(ScaleSize(size, image_scale));
owned_canvas_ = skia::AdoptRef(skia::CreatePlatformCanvas(pixel_size.width(),
pixel_size.height(),
is_opaque));
canvas_ = owned_canvas_.get();
- SkScalar scale = SkFloatToScalar(ui::GetScaleFactorScale(scale_factor_));
- canvas_->scale(scale, scale);
+ SkScalar scale_scalar = SkFloatToScalar(image_scale);
+ canvas_->scale(scale_scalar, scale_scalar);
+}
+
+// static
+void Canvas::SizeStringInt(const base::string16& text,
+ const FontList& font_list,
+ int* width,
+ int* height,
+ int line_height,
+ int flags) {
+ float fractional_width = *width;
+ float factional_height = *height;
+ SizeStringFloat(text, font_list, &fractional_width,
+ &factional_height, line_height, flags);
+ *width = std::ceil(fractional_width);
+ *height = std::ceil(factional_height);
}
// static
@@ -103,6 +117,14 @@ int Canvas::GetStringWidth(const base::string16& text,
}
// static
+float Canvas::GetStringWidthF(const base::string16& text,
+ const FontList& font_list) {
+ float width = 0, height = 0;
+ SizeStringFloat(text, font_list, &width, &height, 0, NO_ELLIPSIS);
+ return width;
+}
+
+// static
int Canvas::GetStringWidth(const base::string16& text, const Font& font) {
int width = 0, height = 0;
SizeStringInt(text, FontList(font), &width, &height, 0, NO_ELLIPSIS);
@@ -136,7 +158,7 @@ ImageSkiaRep Canvas::ExtractImageRep() const {
SkBitmap result;
device_bitmap.copyTo(&result, SkBitmap::kARGB_8888_Config);
- return ImageSkiaRep(result, scale_factor_);
+ return ImageSkiaRep(result, image_scale_);
}
void Canvas::DrawDashedRect(const Rect& rect, SkColor color) {
@@ -310,6 +332,22 @@ void Canvas::DrawFocusRect(const Rect& rect) {
DrawDashedRect(rect, SK_ColorGRAY);
}
+void Canvas::DrawSolidFocusRect(const Rect& rect, SkColor color) {
+ SkPaint paint;
+ paint.setColor(color);
+ paint.setStrokeWidth(SkIntToScalar(1));
+ // Note: We cannot use DrawRect since it would create a path and fill it which
+ // would cause problems near the edge of the canvas.
+ int x1 = std::min(rect.x(), rect.right());
+ int x2 = std::max(rect.x(), rect.right());
+ int y1 = std::min(rect.y(), rect.bottom());
+ int y2 = std::max(rect.y(), rect.bottom());
+ DrawLine(Point(x1, y1), Point(x2, y1), paint);
+ DrawLine(Point(x1, y2), Point(x2, y2), paint);
+ DrawLine(Point(x1, y1), Point(x1, y2), paint);
+ DrawLine(Point(x2, y1), Point(x2, y2 + 1), paint);
+}
+
void Canvas::DrawImageInt(const ImageSkia& image, int x, int y) {
SkPaint paint;
DrawImageInt(image, x, y, paint);
@@ -329,7 +367,7 @@ void Canvas::DrawImageInt(const ImageSkia& image,
if (image_rep.is_null())
return;
const SkBitmap& bitmap = image_rep.sk_bitmap();
- float bitmap_scale = image_rep.GetScale();
+ float bitmap_scale = image_rep.scale();
canvas_->save();
canvas_->scale(SkFloatToScalar(1.0f / bitmap_scale),
@@ -392,7 +430,7 @@ void Canvas::DrawImageInt(const ImageSkia& image,
if (src_w == dest_w && src_h == dest_h &&
user_scale_x == 1.0f && user_scale_y == 1.0f &&
- image_rep.scale_factor() == ui::SCALE_FACTOR_100P) {
+ image_rep.scale() == 1.0f) {
// Workaround for apparent bug in Skia that causes image to occasionally
// shift.
SkIRect src_rect = { src_x, src_y, src_x + src_w, src_y + src_h };
@@ -574,8 +612,8 @@ void Canvas::Transform(const gfx::Transform& transform) {
canvas_->concat(transform.matrix());
}
-Canvas::Canvas(SkCanvas* canvas, ui::ScaleFactor scale_factor)
- : scale_factor_(scale_factor),
+Canvas::Canvas(SkCanvas* canvas, float image_scale)
+ : image_scale_(image_scale),
owned_canvas_(),
canvas_(canvas) {
DCHECK(canvas);
@@ -601,7 +639,7 @@ const ImageSkiaRep& Canvas::GetImageRepToPaint(
const ImageSkia& image,
float user_additional_scale_x,
float user_additional_scale_y) const {
- const ImageSkiaRep& image_rep = image.GetRepresentation(scale_factor_);
+ const ImageSkiaRep& image_rep = image.GetRepresentation(image_scale_);
if (!image_rep.is_null()) {
SkMatrix m = canvas_->getTotalMatrix();
@@ -610,7 +648,7 @@ const ImageSkiaRep& Canvas::GetImageRepToPaint(
float scale_y = SkScalarToFloat(SkScalarAbs(m.getScaleY())) *
user_additional_scale_y;
- float bitmap_scale = image_rep.GetScale();
+ float bitmap_scale = image_rep.scale();
if (scale_x < bitmap_scale || scale_y < bitmap_scale)
const_cast<SkBitmap&>(image_rep.sk_bitmap()).buildMipMap();
}
diff --git a/chromium/ui/gfx/canvas.h b/chromium/ui/gfx/canvas.h
index c8996a234a8..f8193f1134c 100644
--- a/chromium/ui/gfx/canvas.h
+++ b/chromium/ui/gfx/canvas.h
@@ -38,12 +38,11 @@ class Transform;
// source and destination colors are combined. Unless otherwise specified,
// the variant that does not take a SkXfermode::Mode uses a transfer mode
// of kSrcOver_Mode.
-class UI_EXPORT Canvas {
+class GFX_EXPORT Canvas {
public:
enum TruncateFadeMode {
TruncateFadeTail,
TruncateFadeHead,
- TruncateFadeHeadAndTail,
};
// Specifies the alignment for text rendered with the DrawStringInt method.
@@ -90,34 +89,34 @@ class UI_EXPORT Canvas {
NO_SUBPIXEL_RENDERING = 1 << 10,
};
- // Creates an empty canvas with scale factor of 1x.
+ // Creates an empty canvas with image_scale of 1x.
Canvas();
- // Creates canvas with provided DIP |size| and |scale_factor|.
+ // Creates canvas with provided DIP |size| and |image_scale|.
// If this canvas is not opaque, it's explicitly cleared to transparent before
// being returned.
- Canvas(const Size& size, ui::ScaleFactor scale_factor, bool is_opaque);
+ Canvas(const Size& size, float image_scale, bool is_opaque);
- // Constructs a canvas with the size and the scale factor of the
- // provided |image_rep|, and draws the |image_rep| into it.
+ // Constructs a canvas with the size and the image_scale of the provided
+ // |image_rep|, and draws the |image_rep| into it.
Canvas(const ImageSkiaRep& image_rep, bool is_opaque);
virtual ~Canvas();
- // Creates a Canvas backed by an |sk_canvas| with |scale_factor|.
- // |sk_canvas| is assumed to be already scaled based on |scale_factor|
+ // Creates a Canvas backed by an |sk_canvas| with |image_scale_|.
+ // |sk_canvas| is assumed to be already scaled based on |image_scale|
// so no additional scaling is applied.
static Canvas* CreateCanvasWithoutScaling(SkCanvas* sk_canvas,
- ui::ScaleFactor scale_factor);
+ float image_scale);
- // Recreates the backing platform canvas with DIP |size| and |scale_factor|.
+ // Recreates the backing platform canvas with DIP |size| and |image_scale_|.
// If the canvas is not opaque, it is explicitly cleared.
// This method is public so that canvas_skia_paint can recreate the platform
// canvas after having initialized the canvas.
- // TODO(pkotwicz): Push the scale factor into skia::PlatformCanvas such that
+ // TODO(pkotwicz): Push the image_scale into skia::PlatformCanvas such that
// this method can be private.
void RecreateBackingCanvas(const Size& size,
- ui::ScaleFactor scale_factor,
+ float image_scale,
bool is_opaque);
// Compute the size required to draw some text with the provided fonts.
@@ -139,6 +138,15 @@ class UI_EXPORT Canvas {
int line_height,
int flags);
+ // This is same as SizeStringInt except that fractional size is returned.
+ // See comment in GetStringWidthF for its usage.
+ static void SizeStringFloat(const base::string16& text,
+ const FontList& font_list,
+ float* width,
+ float* height,
+ int line_height,
+ int flags);
+
// Returns the number of horizontal pixels needed to display the specified
// |text| with |font_list|.
static int GetStringWidth(const base::string16& text,
@@ -146,6 +154,14 @@ class UI_EXPORT Canvas {
// Obsolete version. Use the above version which takes FontList.
static int GetStringWidth(const base::string16& text, const Font& font);
+ // This is same as GetStringWidth except that fractional width is returned.
+ // Use this method for the scenario that multiple string widths need to be
+ // summed up. This is because GetStringWidth returns the ceiled width and
+ // adding multiple ceiled widths could cause more precision loss for certain
+ // platform like Mac where the fractioal width is used.
+ static float GetStringWidthF(const base::string16& text,
+ const FontList& font_list);
+
// Returns the default text alignment to be used when drawing text on a
// Canvas based on the directionality of the system locale language.
// This function is used by Canvas::DrawStringInt when the text alignment
@@ -393,6 +409,10 @@ class UI_EXPORT Canvas {
// Draws a dotted gray rectangle used for focus purposes.
void DrawFocusRect(const Rect& rect);
+ // Draws a |rect| in the specified region with the specified |color| with a
+ // with of one logical pixel which might be more device pixels.
+ void DrawSolidFocusRect(const Rect& rect, SkColor color);
+
// Tiles the image in the specified region.
// Parameters are specified relative to current canvas scale not in pixels.
// Thus, |x| is 2 pixels if canvas scale = 2 & |x| = 1.
@@ -429,38 +449,33 @@ class UI_EXPORT Canvas {
// Apply transformation on the canvas.
void Transform(const Transform& transform);
- // Draws the given string with the beginning and/or the end using a fade
- // gradient. When truncating the head
- // |desired_characters_to_truncate_from_head| specifies the maximum number of
- // characters that can be truncated.
+ // Draws the given string with the beginning or the end using a fade gradient.
void DrawFadeTruncatingStringRect(
const base::string16& text,
TruncateFadeMode truncate_mode,
- size_t desired_characters_to_truncate_from_head,
const FontList& font_list,
SkColor color,
const Rect& display_rect);
- // Obsolete version. Use the above version which takes FontList.
- void DrawFadeTruncatingString(
+ void DrawFadeTruncatingStringRectWithFlags(
const base::string16& text,
TruncateFadeMode truncate_mode,
- size_t desired_characters_to_truncate_from_head,
- const Font& font,
+ const FontList& font_list,
SkColor color,
- const Rect& display_rect);
+ const Rect& display_rect,
+ int flags);
skia::PlatformCanvas* platform_canvas() const { return owned_canvas_.get(); }
SkCanvas* sk_canvas() const { return canvas_; }
- ui::ScaleFactor scale_factor() const { return scale_factor_; }
+ float image_scale() const { return image_scale_; }
private:
- Canvas(SkCanvas* canvas, ui::ScaleFactor scale_factor);
+ Canvas(SkCanvas* canvas, float image_scale);
// Test whether the provided rectangle intersects the current clip rect.
bool IntersectsClipRectInt(int x, int y, int w, int h);
bool IntersectsClipRect(const Rect& rect);
- // Returns the image rep which best matches the canvas |scale_factor_|.
+ // Returns the image rep which best matches the canvas |image_scale_|.
// Returns a null image rep if |image| contains no image reps.
// Builds mip map for returned image rep if necessary.
//
@@ -473,8 +488,8 @@ class UI_EXPORT Canvas {
// The device scale factor at which drawing on this canvas occurs.
// An additional scale can be applied via Canvas::Scale(). However,
- // Canvas::Scale() does not affect |scale_factor_|.
- ui::ScaleFactor scale_factor_;
+ // Canvas::Scale() does not affect |image_scale_|.
+ float image_scale_;
skia::RefPtr<skia::PlatformCanvas> owned_canvas_;
SkCanvas* canvas_;
diff --git a/chromium/ui/gfx/canvas_android.cc b/chromium/ui/gfx/canvas_android.cc
index 54e45f7653a..61e3a3af14c 100644
--- a/chromium/ui/gfx/canvas_android.cc
+++ b/chromium/ui/gfx/canvas_android.cc
@@ -9,12 +9,12 @@
namespace gfx {
// static
-void Canvas::SizeStringInt(const base::string16& text,
- const FontList& font_list,
- int* width,
- int* height,
- int line_height,
- int flags) {
+void Canvas::SizeStringFloat(const base::string16& text,
+ const FontList& font_list,
+ float* width,
+ float* height,
+ int line_height,
+ int flags) {
NOTIMPLEMENTED();
}
diff --git a/chromium/ui/gfx/canvas_paint.h b/chromium/ui/gfx/canvas_paint.h
index 4ae8b7c0229..4d38df38ac9 100644
--- a/chromium/ui/gfx/canvas_paint.h
+++ b/chromium/ui/gfx/canvas_paint.h
@@ -17,7 +17,7 @@ class CanvasPaint {
public:
// Creates a canvas that paints to |view| when it is destroyed. The canvas is
// sized to the client area of |view|.
- UI_EXPORT static CanvasPaint* CreateCanvasPaint(gfx::NativeView view);
+ GFX_EXPORT static CanvasPaint* CreateCanvasPaint(gfx::NativeView view);
virtual ~CanvasPaint() {}
diff --git a/chromium/ui/gfx/canvas_paint_gtk.cc b/chromium/ui/gfx/canvas_paint_gtk.cc
index 4c185c02e03..aef6fc982e3 100644
--- a/chromium/ui/gfx/canvas_paint_gtk.cc
+++ b/chromium/ui/gfx/canvas_paint_gtk.cc
@@ -10,6 +10,8 @@
namespace gfx {
+// CanvasSkiaPaint
+
CanvasSkiaPaint::CanvasSkiaPaint(GdkEventExpose* event)
: context_(NULL),
window_(event->window),
@@ -52,8 +54,7 @@ CanvasSkiaPaint::~CanvasSkiaPaint() {
void CanvasSkiaPaint::Init(bool opaque) {
GdkRectangle bounds = rectangle();
- RecreateBackingCanvas(gfx::Size(bounds.width, bounds.height),
- ui::SCALE_FACTOR_100P, opaque);
+ RecreateBackingCanvas(Size(bounds.width, bounds.height), 1.0f, opaque);
skia::PlatformCanvas* canvas = platform_canvas();
@@ -64,6 +65,43 @@ void CanvasSkiaPaint::Init(bool opaque) {
context_ = skia::BeginPlatformPaint(canvas);
}
+// CanvasSkiaPaintCairo
+
+CanvasSkiaPaintCairo::CanvasSkiaPaintCairo(cairo_t* cairo,
+ Size size,
+ bool opaque)
+ : context_(NULL),
+ dest_(cairo),
+ size_(size),
+ composite_alpha_(false) {
+ CHECK(dest_);
+ Init(opaque);
+}
+
+CanvasSkiaPaintCairo::~CanvasSkiaPaintCairo() {
+ if (!is_empty()) {
+ platform_canvas()->restoreToCount(1);
+
+ // Blit the dirty rect to the window.
+ if (composite_alpha_)
+ cairo_set_operator(dest_, CAIRO_OPERATOR_SOURCE);
+ cairo_surface_t* source_surface = cairo_get_target(context_);
+ CHECK(source_surface);
+ // Flush cairo's cache of the surface.
+ cairo_surface_mark_dirty(source_surface);
+ cairo_set_source_surface(dest_, source_surface, 0, 0);
+ GdkRectangle bounds = {0, 0, size_.width(), size_.height()};
+ gdk_cairo_rectangle(dest_, &bounds);
+ cairo_fill(dest_);
+ }
+}
+
+void CanvasSkiaPaintCairo::Init(bool opaque) {
+ RecreateBackingCanvas(size_, 1.0f, opaque);
+
+ context_ = skia::BeginPlatformPaint(platform_canvas());
+}
+
} // namespace gfx
-
+
diff --git a/chromium/ui/gfx/canvas_paint_gtk.h b/chromium/ui/gfx/canvas_paint_gtk.h
index 889f30895b4..487db79f47a 100644
--- a/chromium/ui/gfx/canvas_paint_gtk.h
+++ b/chromium/ui/gfx/canvas_paint_gtk.h
@@ -17,7 +17,7 @@ namespace gfx {
// On construction, it will set up a context for painting into, and on
// destruction, it will commit it to the GdkWindow.
// Note: The created context is always inialized to (0, 0, 0, 0).
-class UI_EXPORT CanvasSkiaPaint : public Canvas {
+class GFX_EXPORT CanvasSkiaPaint : public Canvas {
public:
// This constructor assumes the result is opaque.
explicit CanvasSkiaPaint(GdkEventExpose* event);
@@ -57,6 +57,46 @@ class UI_EXPORT CanvasSkiaPaint : public Canvas {
CanvasSkiaPaint& operator=(const CanvasSkiaPaint&);
};
+// A class designed to translate skia painting into a region in a Cairo context.
+// On construction, it will set up a context for painting into, and on
+// destruction, it will commit it to the Cairo context. If there are any
+// transformations applied to the Cairo context, they will affect the drawing.
+class GFX_EXPORT CanvasSkiaPaintCairo : public Canvas {
+ public:
+ CanvasSkiaPaintCairo(cairo_t* cairo, Size size, bool opaque);
+ virtual ~CanvasSkiaPaintCairo();
+
+ // Sets whether the bitmap is composited in such a way that the alpha channel
+ // is honored. This is only useful if you've enabled an RGBA colormap on the
+ // widget. The default is false.
+ void set_composite_alpha(bool composite_alpha) {
+ composite_alpha_ = composite_alpha;
+ }
+
+ // Returns true if size of the drawing region is empty. The caller should call
+ // this function to determine if anything needs painting.
+ bool is_empty() const {
+ return size_.IsEmpty();
+ }
+
+ Size size() const {
+ return size_;
+ }
+
+ private:
+ void Init(bool opaque);
+
+ cairo_t* context_;
+ cairo_t* dest_;
+ Size size_;
+ // See description above setter.
+ bool composite_alpha_;
+
+ // Disallow copy and assign.
+ CanvasSkiaPaintCairo(const CanvasSkiaPaintCairo&);
+ CanvasSkiaPaintCairo& operator=(const CanvasSkiaPaintCairo&);
+};
+
} // namespace gfx
#endif // UI_GFX_CANVAS_PAINT_LINUX_H_
diff --git a/chromium/ui/gfx/canvas_paint_mac.h b/chromium/ui/gfx/canvas_paint_mac.h
index 16d74109f65..f3658c33f1f 100644
--- a/chromium/ui/gfx/canvas_paint_mac.h
+++ b/chromium/ui/gfx/canvas_paint_mac.h
@@ -17,7 +17,7 @@ namespace gfx {
// graphics context. On construction, it will set up a context for painting
// into, and on destruction, it will commit it to the current context.
// Note: The created context is always inialized to (0, 0, 0, 0).
-class UI_EXPORT CanvasSkiaPaint : public Canvas {
+class GFX_EXPORT CanvasSkiaPaint : public Canvas {
public:
// This constructor assumes the result is opaque.
explicit CanvasSkiaPaint(NSRect dirtyRect);
diff --git a/chromium/ui/gfx/canvas_paint_mac.mm b/chromium/ui/gfx/canvas_paint_mac.mm
index c8796afedae..8ba697d1091 100644
--- a/chromium/ui/gfx/canvas_paint_mac.mm
+++ b/chromium/ui/gfx/canvas_paint_mac.mm
@@ -58,9 +58,8 @@ void CanvasSkiaPaint::Init(bool opaque) {
// Assume that the x scale and the y scale are the same.
CGFloat scale = scaled_unit_rect.size.width;
- ui::ScaleFactor scale_factor = ui::GetScaleFactorFromScale(scale);
gfx::Size size(NSWidth(rectangle_), NSHeight(rectangle_));
- RecreateBackingCanvas(size, scale_factor, opaque);
+ RecreateBackingCanvas(size, scale, opaque);
skia::PlatformCanvas* canvas = platform_canvas();
canvas->clear(SkColorSetARGB(0, 0, 0, 0));
@@ -74,4 +73,4 @@ void CanvasSkiaPaint::Init(bool opaque) {
} // namespace skia
-
+
diff --git a/chromium/ui/gfx/canvas_paint_win.cc b/chromium/ui/gfx/canvas_paint_win.cc
index 71c836724a2..7d20fbcd1c8 100644
--- a/chromium/ui/gfx/canvas_paint_win.cc
+++ b/chromium/ui/gfx/canvas_paint_win.cc
@@ -56,7 +56,7 @@ void CanvasSkiaPaint::Init(bool opaque) {
const int height = ps_.rcPaint.bottom - ps_.rcPaint.top;
RecreateBackingCanvas(gfx::Size(width, height),
- ui::GetScaleFactorFromScale(gfx::win::GetDeviceScaleFactor()),
+ gfx::win::GetDeviceScaleFactor(),
opaque);
skia::PlatformCanvas* canvas = platform_canvas();
diff --git a/chromium/ui/gfx/canvas_paint_win.h b/chromium/ui/gfx/canvas_paint_win.h
index c5d3aee3211..9028cbac6f3 100644
--- a/chromium/ui/gfx/canvas_paint_win.h
+++ b/chromium/ui/gfx/canvas_paint_win.h
@@ -33,7 +33,7 @@ namespace gfx {
// return 0;
// }
// Note: The created context is always inialized to (0, 0, 0, 0).
-class UI_EXPORT CanvasSkiaPaint : public Canvas {
+class GFX_EXPORT CanvasSkiaPaint : public Canvas {
public:
// This constructor assumes the canvas is opaque.
CanvasSkiaPaint(HWND hwnd, HDC dc, const PAINTSTRUCT& ps);
diff --git a/chromium/ui/gfx/canvas_skia.cc b/chromium/ui/gfx/canvas_skia.cc
index ef8ee3625a7..1ad60ba2b04 100644
--- a/chromium/ui/gfx/canvas_skia.cc
+++ b/chromium/ui/gfx/canvas_skia.cc
@@ -20,6 +20,7 @@ namespace gfx {
namespace {
+#if defined(OS_WIN)
// If necessary, wraps |text| with RTL/LTR directionality characters based on
// |flags| and |text| content.
// Returns true if the text will be rendered right-to-left.
@@ -52,6 +53,7 @@ bool AdjustStringDirection(int flags, base::string16* text) {
// locales it will be handled by the if statement above).
return false;
}
+#endif // defined(OS_WIN)
// Checks each pixel immediately adjacent to the given pixel in the bitmap. If
// any of them are not the halo color, returns true. This defines the halo of
@@ -152,31 +154,17 @@ void UpdateRenderText(const Rect& rect,
render_text->SetStyle(UNDERLINE, (font_style & Font::UNDERLINE) != 0);
}
-// Returns updated |flags| to match platform-specific expected behavior.
-int AdjustPlatformSpecificFlags(const base::string16& text, int flags) {
-#if defined(OS_LINUX)
- // TODO(asvitkine): ash/tooltips/tooltip_controller.cc adds \n's to the string
- // without passing MULTI_LINE.
- if (text.find('\n') != base::string16::npos)
- flags |= Canvas::MULTI_LINE;
-#endif
-
- return flags;
-}
-
} // namespace
// static
-void Canvas::SizeStringInt(const base::string16& text,
- const FontList& font_list,
- int* width, int* height,
- int line_height,
- int flags) {
+void Canvas::SizeStringFloat(const base::string16& text,
+ const FontList& font_list,
+ float* width, float* height,
+ int line_height,
+ int flags) {
DCHECK_GE(*width, 0);
DCHECK_GE(*height, 0);
- flags = AdjustPlatformSpecificFlags(text, flags);
-
base::string16 adjusted_text = text;
#if defined(OS_WIN)
AdjustStringDirection(flags, &adjusted_text);
@@ -198,12 +186,12 @@ void Canvas::SizeStringInt(const base::string16& text,
UpdateRenderText(rect, base::string16(), font_list, flags, 0,
render_text.get());
- int h = 0;
- int w = 0;
+ float h = 0;
+ float w = 0;
for (size_t i = 0; i < strings.size(); ++i) {
StripAcceleratorChars(flags, &strings[i]);
render_text->SetText(strings[i]);
- const Size& string_size = render_text->GetStringSize();
+ const SizeF& string_size = render_text->GetStringSizeF();
w = std::max(w, string_size.width());
h += (i > 0 && line_height > 0) ? line_height : string_size.height();
}
@@ -222,7 +210,7 @@ void Canvas::SizeStringInt(const base::string16& text,
StripAcceleratorChars(flags, &adjusted_text);
UpdateRenderText(rect, adjusted_text, font_list, flags, 0,
render_text.get());
- const Size& string_size = render_text->GetStringSize();
+ const SizeF& string_size = render_text->GetStringSizeF();
*width = string_size.width();
*height = string_size.height();
}
@@ -239,8 +227,6 @@ void Canvas::DrawStringRectWithShadows(const base::string16& text,
if (!IntersectsClipRect(text_bounds))
return;
- flags = AdjustPlatformSpecificFlags(text, flags);
-
Rect clip_rect(text_bounds);
clip_rect.Inset(ShadowValue::GetMargin(shadows));
@@ -350,7 +336,7 @@ void Canvas::DrawStringRectWithHalo(const base::string16& text,
// Create a temporary buffer filled with the halo color. It must leave room
// for the 1-pixel border around the text.
Size size(display_rect.width() + 2, display_rect.height() + 2);
- Canvas text_canvas(size, scale_factor(), true);
+ Canvas text_canvas(size, image_scale(), false);
SkPaint bkgnd_paint;
bkgnd_paint.setColor(halo_color);
text_canvas.DrawRect(Rect(size), bkgnd_paint);
@@ -381,19 +367,27 @@ void Canvas::DrawStringRectWithHalo(const base::string16& text,
// Draw the halo bitmap with blur.
ImageSkia text_image = ImageSkia(ImageSkiaRep(text_bitmap,
- text_canvas.scale_factor()));
+ text_canvas.image_scale()));
DrawImageInt(text_image, display_rect.x() - 1, display_rect.y() - 1);
}
void Canvas::DrawFadeTruncatingStringRect(
const base::string16& text,
TruncateFadeMode truncate_mode,
- size_t desired_characters_to_truncate_from_head,
const FontList& font_list,
SkColor color,
const Rect& display_rect) {
- int flags = NO_ELLIPSIS;
+ DrawFadeTruncatingStringRectWithFlags(
+ text, truncate_mode, font_list, color, display_rect, NO_ELLIPSIS);
+}
+void Canvas::DrawFadeTruncatingStringRectWithFlags(
+ const base::string16& text,
+ TruncateFadeMode truncate_mode,
+ const FontList& font_list,
+ SkColor color,
+ const Rect& display_rect,
+ int flags) {
// If the whole string fits in the destination then just draw it directly.
if (GetStringWidth(text, font_list) <= display_rect.width()) {
DrawStringRectWithFlags(text, font_list, color, display_rect, flags);
@@ -401,8 +395,8 @@ void Canvas::DrawFadeTruncatingStringRect(
}
scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
- base::string16 clipped_text = text;
- const bool is_rtl = AdjustStringDirection(flags, &clipped_text);
+ const bool is_rtl = base::i18n::GetFirstStrongCharacterDirection(text) ==
+ base::i18n::RIGHT_TO_LEFT;
switch (truncate_mode) {
case TruncateFadeTail:
@@ -415,26 +409,6 @@ void Canvas::DrawFadeTruncatingStringRect(
if (!is_rtl)
flags |= TEXT_ALIGN_RIGHT;
break;
- case TruncateFadeHeadAndTail:
- DCHECK_GT(desired_characters_to_truncate_from_head, 0u);
- // Due to the fade effect the first character is hard to see.
- // We want to make sure that the first character starting at
- // |desired_characters_to_truncate_from_head| is readable so we reduce
- // the offset by a little bit.
- desired_characters_to_truncate_from_head =
- std::max<int>(0, desired_characters_to_truncate_from_head - 2);
-
- if (desired_characters_to_truncate_from_head) {
- // Make sure to clip the text at a UTF16 boundary.
- U16_SET_CP_LIMIT(text.data(), 0,
- desired_characters_to_truncate_from_head,
- text.length());
- clipped_text = text.substr(desired_characters_to_truncate_from_head);
- }
-
- render_text->set_fade_tail(true);
- render_text->set_fade_head(true);
- break;
}
// Default to left alignment unless right alignment was chosen above.
@@ -442,8 +416,7 @@ void Canvas::DrawFadeTruncatingStringRect(
flags |= TEXT_ALIGN_LEFT;
Rect rect = display_rect;
- UpdateRenderText(rect, clipped_text, font_list, flags, color,
- render_text.get());
+ UpdateRenderText(rect, text, font_list, flags, color, render_text.get());
const int line_height = render_text->GetStringSize().height();
// Center the text vertically.
@@ -457,16 +430,4 @@ void Canvas::DrawFadeTruncatingStringRect(
canvas_->restore();
}
-void Canvas::DrawFadeTruncatingString(
- const base::string16& text,
- TruncateFadeMode truncate_mode,
- size_t desired_characters_to_truncate_from_head,
- const Font& font,
- SkColor color,
- const Rect& display_rect) {
- DrawFadeTruncatingStringRect(text, truncate_mode,
- desired_characters_to_truncate_from_head,
- FontList(font), color, display_rect);
-}
-
} // namespace gfx
diff --git a/chromium/ui/gfx/canvas_unittest_mac.mm b/chromium/ui/gfx/canvas_unittest_mac.mm
index d607218c64f..7aff64b07a8 100644
--- a/chromium/ui/gfx/canvas_unittest_mac.mm
+++ b/chromium/ui/gfx/canvas_unittest_mac.mm
@@ -18,25 +18,16 @@ namespace gfx {
namespace {
-// Mac-specific code for string size computations. This is a verbatim copy
-// of the old implementation that used to be in canvas_mac.mm.
-void CanvasMac_SizeStringInt(const base::string16& text,
- const FontList& font_list,
- int* width,
- int* height,
- int line_height,
- int flags) {
- DLOG_IF(WARNING, line_height != 0) << "Line heights not implemented.";
- DLOG_IF(WARNING, flags & Canvas::MULTI_LINE) << "Multi-line not implemented.";
-
+// Returns the pixel width of the string via calling the native method
+// -sizeWithAttributes.
+float GetStringNativeWidth(const base::string16& text,
+ const FontList& font_list) {
NSFont* native_font = font_list.GetPrimaryFont().GetNativeFont();
NSString* ns_string = base::SysUTF16ToNSString(text);
NSDictionary* attributes =
[NSDictionary dictionaryWithObject:native_font
forKey:NSFontAttributeName];
- NSSize string_size = [ns_string sizeWithAttributes:attributes];
- *width = std::ceil(string_size.width);
- *height = font_list.GetHeight();
+ return [ns_string sizeWithAttributes:attributes].width;
}
} // namespace
@@ -49,30 +40,31 @@ class CanvasTestMac : public testing::Test {
// without specified line height, since that is all the platform
// implementation supports.
void CompareSizes(const char* text) {
- const int kReallyLargeNumber = 12345678;
+ const float kReallyLargeNumber = 12345678;
FontList font_list(font_);
base::string16 text16 = base::UTF8ToUTF16(text);
- int mac_width = kReallyLargeNumber;
- int mac_height = kReallyLargeNumber;
- CanvasMac_SizeStringInt(text16, font_list, &mac_width, &mac_height, 0, 0);
+ float mac_width = GetStringNativeWidth(text16, font_list);
+ int mac_height = font_list.GetHeight();
- int canvas_width = kReallyLargeNumber;
- int canvas_height = kReallyLargeNumber;
- Canvas::SizeStringInt(
+ float canvas_width = kReallyLargeNumber;
+ float canvas_height = kReallyLargeNumber;
+ Canvas::SizeStringFloat(
text16, font_list, &canvas_width, &canvas_height, 0, 0);
EXPECT_NE(kReallyLargeNumber, mac_width) << "no width for " << text;
EXPECT_NE(kReallyLargeNumber, mac_height) << "no height for " << text;
EXPECT_EQ(mac_width, canvas_width) << " width for " << text;
- EXPECT_EQ(mac_height, canvas_height) << " height for " << text;
+ // FontList::GetHeight returns a truncated height.
+ EXPECT_EQ(mac_height,
+ static_cast<int>(canvas_height)) << " height for " << text;
}
private:
Font font_;
};
- // Tests that Canvas' SizeStringInt yields result consistent with a native
+ // Tests that Canvas' SizeStringFloat yields result consistent with a native
// implementation.
TEST_F(CanvasTestMac, StringSizeIdenticalForSkia) {
CompareSizes("");
@@ -81,4 +73,16 @@ class CanvasTestMac : public testing::Test {
CompareSizes("This is a complete sentence.");
}
+TEST_F(CanvasTestMac, FractionalWidth) {
+ const float kReallyLargeNumber = 12345678;
+ float width = kReallyLargeNumber;
+ float height = kReallyLargeNumber;
+
+ FontList font_list;
+ Canvas::SizeStringFloat(
+ base::UTF8ToUTF16("Test"), font_list, &width, &height, 0, 0);
+
+ EXPECT_GT(width, static_cast<int>(width));
+}
+
} // namespace gfx
diff --git a/chromium/ui/gfx/codec/jpeg_codec.h b/chromium/ui/gfx/codec/jpeg_codec.h
index b6b7088c361..8219221283e 100644
--- a/chromium/ui/gfx/codec/jpeg_codec.h
+++ b/chromium/ui/gfx/codec/jpeg_codec.h
@@ -18,7 +18,7 @@ namespace gfx {
// which has an inconvenient interface for callers. This is only used for UI
// elements, WebKit has its own more complicated JPEG decoder which handles,
// among other things, partially downloaded data.
-class UI_EXPORT JPEGCodec {
+class GFX_EXPORT JPEGCodec {
public:
enum ColorFormat {
// 3 bytes per pixel (packed), in RGB order regardless of endianness.
diff --git a/chromium/ui/gfx/codec/png_codec.cc b/chromium/ui/gfx/codec/png_codec.cc
index 30e4eb6d653..b3f4345343f 100644
--- a/chromium/ui/gfx/codec/png_codec.cc
+++ b/chromium/ui/gfx/codec/png_codec.cc
@@ -465,36 +465,12 @@ bool PNGCodec::Decode(const unsigned char* input, size_t input_size,
}
// Set the bitmap's opaqueness based on what we saw.
- bitmap->setIsOpaque(state.is_opaque);
+ bitmap->setAlphaType(state.is_opaque ?
+ kOpaque_SkAlphaType : kPremul_SkAlphaType);
return true;
}
-// static
-SkBitmap* PNGCodec::CreateSkBitmapFromBGRAFormat(
- const std::vector<unsigned char>& bgra, int width, int height) {
- SkBitmap* bitmap = new SkBitmap();
- bitmap->setConfig(SkBitmap::kARGB_8888_Config, width, height);
- bitmap->allocPixels();
-
- bool opaque = false;
- unsigned char* bitmap_data =
- reinterpret_cast<unsigned char*>(bitmap->getAddr32(0, 0));
- for (int i = width * height * 4 - 4; i >= 0; i -= 4) {
- unsigned char alpha = bgra[i + 3];
- if (!opaque && alpha != 255) {
- opaque = false;
- }
- bitmap_data[i + 3] = alpha;
- bitmap_data[i] = (bgra[i] * alpha) >> 8;
- bitmap_data[i + 1] = (bgra[i + 1] * alpha) >> 8;
- bitmap_data[i + 2] = (bgra[i + 2] * alpha) >> 8;
- }
-
- bitmap->setIsOpaque(opaque);
- return bitmap;
-}
-
// Encoder --------------------------------------------------------------------
//
// This section of the code is based on nsPNGEncoder.cpp in Mozilla
diff --git a/chromium/ui/gfx/codec/png_codec.h b/chromium/ui/gfx/codec/png_codec.h
index 86f170d359f..abb3eaab32c 100644
--- a/chromium/ui/gfx/codec/png_codec.h
+++ b/chromium/ui/gfx/codec/png_codec.h
@@ -23,7 +23,7 @@ class Size;
// isn't as robust as would be required for a browser (see Decode() for more).
// WebKit has its own more complicated PNG decoder which handles, among other
// things, partially downloaded data.
-class UI_EXPORT PNGCodec {
+class GFX_EXPORT PNGCodec {
public:
enum ColorFormat {
// 3 bytes per pixel (packed), in RGB order regardless of endianness.
@@ -43,7 +43,7 @@ class UI_EXPORT PNGCodec {
};
// Represents a comment in the tEXt ancillary chunk of the png.
- struct UI_EXPORT Comment {
+ struct GFX_EXPORT Comment {
Comment(const std::string& k, const std::string& t);
~Comment();
@@ -114,11 +114,6 @@ class UI_EXPORT PNGCodec {
static bool Decode(const unsigned char* input, size_t input_size,
SkBitmap* bitmap);
- // Create a SkBitmap from a decoded BGRA DIB. The caller owns the returned
- // SkBitmap.
- static SkBitmap* CreateSkBitmapFromBGRAFormat(
- const std::vector<unsigned char>& bgra, int width, int height);
-
private:
DISALLOW_COPY_AND_ASSIGN(PNGCodec);
};
diff --git a/chromium/ui/gfx/color_analysis.h b/chromium/ui/gfx/color_analysis.h
index 797b4f94663..dcbfabc9d77 100644
--- a/chromium/ui/gfx/color_analysis.h
+++ b/chromium/ui/gfx/color_analysis.h
@@ -25,7 +25,7 @@ namespace color_utils {
// Note: Samplers should be deterministic, as the same image may be analyzed
// twice with two sampler instances and the results displayed side-by-side
// to the user.
-class UI_EXPORT KMeanImageSampler {
+class GFX_EXPORT KMeanImageSampler {
public:
virtual int GetSample(int width, int height) = 0;
@@ -35,7 +35,7 @@ class UI_EXPORT KMeanImageSampler {
};
// This sampler will pick pixels from an evenly spaced grid.
-class UI_EXPORT GridSampler : public KMeanImageSampler {
+class GFX_EXPORT GridSampler : public KMeanImageSampler {
public:
GridSampler();
virtual ~GridSampler();
@@ -49,8 +49,8 @@ class UI_EXPORT GridSampler : public KMeanImageSampler {
// Returns the color in an ARGB |image| that is closest in RGB-space to the
// provided |color|. Exported for testing.
-UI_EXPORT SkColor FindClosestColor(const uint8_t* image, int width, int height,
- SkColor color);
+GFX_EXPORT SkColor FindClosestColor(const uint8_t* image, int width, int height,
+ SkColor color);
// Returns an SkColor that represents the calculated dominant color in the png.
// This uses a KMean clustering algorithm to find clusters of pixel colors in
@@ -89,7 +89,7 @@ UI_EXPORT SkColor FindClosestColor(const uint8_t* image, int width, int height,
//
// Note: Switching to HSV space did not improve the results of this algorithm
// for typical favicon images.
-UI_EXPORT SkColor CalculateKMeanColorOfPNG(
+GFX_EXPORT SkColor CalculateKMeanColorOfPNG(
scoped_refptr<base::RefCountedMemory> png,
uint32_t darkness_limit,
uint32_t brightness_limit,
@@ -97,10 +97,10 @@ UI_EXPORT SkColor CalculateKMeanColorOfPNG(
// Computes a dominant color for an SkBitmap using the above algorithm and
// reasonable defaults for |darkness_limit|, |brightness_limit| and |sampler|.
-UI_EXPORT SkColor CalculateKMeanColorOfBitmap(const SkBitmap& bitmap);
+GFX_EXPORT SkColor CalculateKMeanColorOfBitmap(const SkBitmap& bitmap);
// Compute color covariance matrix for the input bitmap.
-UI_EXPORT gfx::Matrix3F ComputeColorCovariance(const SkBitmap& bitmap);
+GFX_EXPORT gfx::Matrix3F ComputeColorCovariance(const SkBitmap& bitmap);
// Apply a color reduction transform defined by |color_transform| vector to
// |source_bitmap|. The result is put into |target_bitmap|, which is expected
@@ -108,7 +108,7 @@ UI_EXPORT gfx::Matrix3F ComputeColorCovariance(const SkBitmap& bitmap);
// If |fit_to_range|, result is transfored linearly to fit 0-0xFF range.
// Otherwise, data is clipped.
// Returns true if the target has been computed.
-UI_EXPORT bool ApplyColorReduction(const SkBitmap& source_bitmap,
+GFX_EXPORT bool ApplyColorReduction(const SkBitmap& source_bitmap,
const gfx::Vector3dF& color_transform,
bool fit_to_range,
SkBitmap* target_bitmap);
@@ -119,7 +119,7 @@ UI_EXPORT bool ApplyColorReduction(const SkBitmap& source_bitmap,
// Returns true if the conversion succeeded. Note that there might be legitimate
// reasons for the process to fail even if all input was correct. This is a
// condition the caller must be able to handle.
-UI_EXPORT bool ComputePrincipalComponentImage(const SkBitmap& source_bitmap,
+GFX_EXPORT bool ComputePrincipalComponentImage(const SkBitmap& source_bitmap,
SkBitmap* target_bitmap);
} // namespace color_utils
diff --git a/chromium/ui/gfx/color_analysis_unittest.cc b/chromium/ui/gfx/color_analysis_unittest.cc
index c76681c2ac9..7757eb959ba 100644
--- a/chromium/ui/gfx/color_analysis_unittest.cc
+++ b/chromium/ui/gfx/color_analysis_unittest.cc
@@ -295,7 +295,7 @@ TEST_F(ColorAnalysisTest, ComputeColorCovarianceTrivial) {
}
TEST_F(ColorAnalysisTest, ComputeColorCovarianceWithCanvas) {
- gfx::Canvas canvas(gfx::Size(250, 200), ui::SCALE_FACTOR_100P, true);
+ gfx::Canvas canvas(gfx::Size(250, 200), 1.0f, true);
// The image consists of vertical stripes, with color bands set to 100
// in overlapping stripes 150 pixels wide.
canvas.FillRect(gfx::Rect(0, 0, 50, 200), SkColorSetRGB(100, 0, 0));
@@ -364,7 +364,7 @@ TEST_F(ColorAnalysisTest, ApplyColorReductionSingleColor) {
TEST_F(ColorAnalysisTest, ApplyColorReductionBlackAndWhite) {
// Check with images with multiple colors. This is really different only when
// the result is scaled.
- gfx::Canvas canvas(gfx::Size(300, 200), ui::SCALE_FACTOR_100P, true);
+ gfx::Canvas canvas(gfx::Size(300, 200), 1.0f, true);
// The image consists of vertical non-overlapping stripes 150 pixels wide.
canvas.FillRect(gfx::Rect(0, 0, 150, 200), SkColorSetRGB(0, 0, 0));
@@ -404,7 +404,7 @@ TEST_F(ColorAnalysisTest, ApplyColorReductionBlackAndWhite) {
TEST_F(ColorAnalysisTest, ApplyColorReductionMultiColor) {
// Check with images with multiple colors. This is really different only when
// the result is scaled.
- gfx::Canvas canvas(gfx::Size(300, 200), ui::SCALE_FACTOR_100P, true);
+ gfx::Canvas canvas(gfx::Size(300, 200), 1.0f, true);
// The image consists of vertical non-overlapping stripes 100 pixels wide.
canvas.FillRect(gfx::Rect(0, 0, 100, 200), SkColorSetRGB(100, 0, 0));
@@ -452,7 +452,7 @@ TEST_F(ColorAnalysisTest, ComputePrincipalComponentImageNotComputable) {
}
TEST_F(ColorAnalysisTest, ComputePrincipalComponentImage) {
- gfx::Canvas canvas(gfx::Size(300, 200), ui::SCALE_FACTOR_100P, true);
+ gfx::Canvas canvas(gfx::Size(300, 200), 1.0f, true);
// The image consists of vertical non-overlapping stripes 100 pixels wide.
canvas.FillRect(gfx::Rect(0, 0, 100, 200), SkColorSetRGB(10, 10, 10));
diff --git a/chromium/ui/gfx/color_profile.h b/chromium/ui/gfx/color_profile.h
index 3a3f5b2ce04..20a02bf169f 100644
--- a/chromium/ui/gfx/color_profile.h
+++ b/chromium/ui/gfx/color_profile.h
@@ -16,7 +16,7 @@ namespace gfx {
static const size_t kMinProfileLength = 128;
static const size_t kMaxProfileLength = 4 * 1024 * 1024;
-class UI_EXPORT ColorProfile {
+class GFX_EXPORT ColorProfile {
public:
// On Windows, this reads a file from disk so it shouldn't be run on the UI
// or IO thread.
@@ -32,7 +32,7 @@ class UI_EXPORT ColorProfile {
};
// Loads the monitor color space if available.
-UI_EXPORT void GetColorProfile(std::vector<char>* profile);
+GFX_EXPORT void GetColorProfile(std::vector<char>* profile);
} // namespace gfx
diff --git a/chromium/ui/gfx/color_utils.h b/chromium/ui/gfx/color_utils.h
index 440e3825c31..6dd6300aa3b 100644
--- a/chromium/ui/gfx/color_utils.h
+++ b/chromium/ui/gfx/color_utils.h
@@ -20,14 +20,14 @@ struct HSL {
double l;
};
-UI_EXPORT unsigned char GetLuminanceForColor(SkColor color);
+GFX_EXPORT unsigned char GetLuminanceForColor(SkColor color);
// Calculated according to http://www.w3.org/TR/WCAG20/#relativeluminancedef
-UI_EXPORT double RelativeLuminance(SkColor color);
+GFX_EXPORT double RelativeLuminance(SkColor color);
// Note: these transformations assume sRGB as the source color space
-UI_EXPORT void SkColorToHSL(SkColor c, HSL* hsl);
-UI_EXPORT SkColor HSLToSkColor(const HSL& hsl, SkAlpha alpha);
+GFX_EXPORT void SkColorToHSL(SkColor c, HSL* hsl);
+GFX_EXPORT SkColor HSLToSkColor(const HSL& hsl, SkAlpha alpha);
// HSL-Shift an SkColor. The shift values are in the range of 0-1, with the
// option to specify -1 for 'no change'. The shift values are defined as:
@@ -43,29 +43,23 @@ UI_EXPORT SkColor HSLToSkColor(const HSL& hsl, SkAlpha alpha);
// 0 = remove all lightness (make all pixels black).
// 0.5 = leave unchanged.
// 1 = full lightness (make all pixels white).
-UI_EXPORT SkColor HSLShift(SkColor color, const HSL& shift);
-
-// Determine if a given alpha value is nearly completely transparent.
-bool IsColorCloseToTransparent(SkAlpha alpha);
-
-// Determine if a color is near grey.
-bool IsColorCloseToGrey(int r, int g, int b);
+GFX_EXPORT SkColor HSLShift(SkColor color, const HSL& shift);
// Builds a histogram based on the Y' of the Y'UV representation of
// this image.
-UI_EXPORT void BuildLumaHistogram(const SkBitmap& bitmap, int histogram[256]);
+GFX_EXPORT void BuildLumaHistogram(const SkBitmap& bitmap, int histogram[256]);
// Returns a blend of the supplied colors, ranging from |background| (for
// |alpha| == 0) to |foreground| (for |alpha| == 255). The alpha channels of
// the supplied colors are also taken into account, so the returned color may
// be partially transparent.
-UI_EXPORT SkColor AlphaBlend(SkColor foreground, SkColor background,
- SkAlpha alpha);
+GFX_EXPORT SkColor AlphaBlend(SkColor foreground, SkColor background,
+ SkAlpha alpha);
// Makes a dark color lighter or a light color darker by blending |color| with
// white or black depending on its current luminance. |alpha| controls the
// amount of white or black that will be alpha-blended into |color|.
-UI_EXPORT SkColor BlendTowardOppositeLuminance(SkColor color, SkAlpha alpha);
+GFX_EXPORT SkColor BlendTowardOppositeLuminance(SkColor color, SkAlpha alpha);
// Given an opaque foreground and background color, try to return a foreground
// color that is "readable" over the background color by luma-inverting the
@@ -76,13 +70,13 @@ UI_EXPORT SkColor BlendTowardOppositeLuminance(SkColor color, SkAlpha alpha);
//
// NOTE: This won't do anything but waste time if the supplied foreground color
// has a luma value close to the midpoint (0.5 in the HSL representation).
-UI_EXPORT SkColor GetReadableColor(SkColor foreground, SkColor background);
+GFX_EXPORT SkColor GetReadableColor(SkColor foreground, SkColor background);
// Invert a color.
-UI_EXPORT SkColor InvertColor(SkColor color);
+GFX_EXPORT SkColor InvertColor(SkColor color);
// Gets a Windows system color as a SkColor
-UI_EXPORT SkColor GetSysSkColor(int which);
+GFX_EXPORT SkColor GetSysSkColor(int which);
} // namespace color_utils
diff --git a/chromium/ui/gfx/display.cc b/chromium/ui/gfx/display.cc
index ee650d8964f..024b1f9aaa6 100644
--- a/chromium/ui/gfx/display.cc
+++ b/chromium/ui/gfx/display.cc
@@ -57,13 +57,15 @@ bool Display::HasForceDeviceScaleFactor() {
Display::Display()
: id_(kInvalidDisplayID),
device_scale_factor_(GetForcedDeviceScaleFactor()),
- rotation_(ROTATE_0) {
+ rotation_(ROTATE_0),
+ touch_support_(TOUCH_SUPPORT_UNKNOWN) {
}
Display::Display(int64 id)
: id_(id),
device_scale_factor_(GetForcedDeviceScaleFactor()),
- rotation_(ROTATE_0) {
+ rotation_(ROTATE_0),
+ touch_support_(TOUCH_SUPPORT_UNKNOWN) {
}
Display::Display(int64 id, const gfx::Rect& bounds)
@@ -71,7 +73,8 @@ Display::Display(int64 id, const gfx::Rect& bounds)
bounds_(bounds),
work_area_(bounds),
device_scale_factor_(GetForcedDeviceScaleFactor()),
- rotation_(ROTATE_0) {
+ rotation_(ROTATE_0),
+ touch_support_(TOUCH_SUPPORT_UNKNOWN) {
#if defined(USE_AURA)
SetScaleAndBounds(device_scale_factor_, bounds);
#endif
diff --git a/chromium/ui/gfx/display.h b/chromium/ui/gfx/display.h
index 17cedfe38fe..eb35a5f5c6f 100644
--- a/chromium/ui/gfx/display.h
+++ b/chromium/ui/gfx/display.h
@@ -20,7 +20,7 @@ namespace gfx {
// system. For platforms that support DIP (density independent pixel),
// |bounds()| and |work_area| will return values in DIP coordinate
// system, not in backing pixels.
-class UI_EXPORT Display {
+class GFX_EXPORT Display {
public:
// Screen Rotation in clock-wise degrees.
enum Rotation {
@@ -30,6 +30,13 @@ class UI_EXPORT Display {
ROTATE_270,
};
+ // Touch support for the display.
+ enum TouchSupport {
+ TOUCH_SUPPORT_UNKNOWN,
+ TOUCH_SUPPORT_AVAILABLE,
+ TOUCH_SUPPORT_UNAVAILABLE,
+ };
+
// Creates a display with kInvalidDisplayID as default.
Display();
explicit Display(int64 id);
@@ -67,6 +74,9 @@ class UI_EXPORT Display {
Rotation rotation() const { return rotation_; }
void set_rotation(Rotation rotation) { rotation_ = rotation; }
+ TouchSupport touch_support() const { return touch_support_; }
+ void set_touch_support(TouchSupport support) { touch_support_ = support; }
+
// Utility functions that just return the size of display and
// work area.
const Size& size() const { return bounds_.size(); }
@@ -113,6 +123,7 @@ class UI_EXPORT Display {
Rect work_area_;
float device_scale_factor_;
Rotation rotation_;
+ TouchSupport touch_support_;
};
} // namespace gfx
diff --git a/chromium/ui/gfx/display_observer.h b/chromium/ui/gfx/display_observer.h
index 1e7cd8cb899..ca97247f9ed 100644
--- a/chromium/ui/gfx/display_observer.h
+++ b/chromium/ui/gfx/display_observer.h
@@ -13,7 +13,7 @@ class Display;
// Observers for display configuration changes.
// TODO(oshima): consolidate |WorkAreaWatcherObserver| and
// |DisplaySettingsProvier|. crbug.com/122863.
-class UI_EXPORT DisplayObserver {
+class GFX_EXPORT DisplayObserver {
public:
// Called when the |display|'s bound has changed.
virtual void OnDisplayBoundsChanged(const Display& display) = 0;
diff --git a/chromium/ui/gfx/favicon_size.h b/chromium/ui/gfx/favicon_size.h
index ecab851dc1a..ad51a9bdb00 100644
--- a/chromium/ui/gfx/favicon_size.h
+++ b/chromium/ui/gfx/favicon_size.h
@@ -10,12 +10,12 @@
namespace gfx {
// Size (along each axis) of the favicon.
-UI_EXPORT extern const int kFaviconSize;
+GFX_EXPORT extern const int kFaviconSize;
// If the width or height is bigger than the favicon size, a new width/height
// is calculated and returned in width/height that maintains the aspect
// ratio of the supplied values.
-UI_EXPORT void CalculateFaviconTargetSize(int* width, int* height);
+GFX_EXPORT void CalculateFaviconTargetSize(int* width, int* height);
} // namespace gfx
diff --git a/chromium/ui/gfx/font.cc b/chromium/ui/gfx/font.cc
index aa4638c7efc..9eea73b608a 100644
--- a/chromium/ui/gfx/font.cc
+++ b/chromium/ui/gfx/font.cc
@@ -54,6 +54,10 @@ int Font::GetBaseline() const {
return platform_font_->GetBaseline();
}
+int Font::GetCapHeight() const {
+ return platform_font_->GetCapHeight();
+}
+
int Font::GetAverageCharacterWidth() const {
return platform_font_->GetAverageCharacterWidth();
}
@@ -74,6 +78,10 @@ std::string Font::GetFontName() const {
return platform_font_->GetFontName();
}
+std::string Font::GetActualFontNameForTesting() const {
+ return platform_font_->GetActualFontNameForTesting();
+}
+
int Font::GetFontSize() const {
return platform_font_->GetFontSize();
}
diff --git a/chromium/ui/gfx/font.h b/chromium/ui/gfx/font.h
index dfbf410f30c..963dde70ffe 100644
--- a/chromium/ui/gfx/font.h
+++ b/chromium/ui/gfx/font.h
@@ -18,7 +18,16 @@ class PlatformFont;
// Font provides a wrapper around an underlying font. Copy and assignment
// operators are explicitly allowed, and cheap.
-class UI_EXPORT Font {
+//
+// Figure of font metrics:
+// +--------+-------------------+------------------+
+// | | | internal leading |
+// | | ascent (baseline) +------------------+
+// | height | | cap height |
+// | |-------------------+------------------+
+// | | descent (height - baseline) |
+// +--------+--------------------------------------+
+class GFX_EXPORT Font {
public:
// The following constants indicate the font style.
enum FontStyle {
@@ -69,6 +78,9 @@ class UI_EXPORT Font {
// Returns the baseline, or ascent, of the font.
int GetBaseline() const;
+ // Returns the cap height of the font.
+ int GetCapHeight() const;
+
// Returns the average character width for the font.
int GetAverageCharacterWidth() const;
@@ -84,9 +96,12 @@ class UI_EXPORT Font {
// Returns the style of the font.
int GetStyle() const;
- // Returns the font name in UTF-8.
+ // Returns the specified font name in UTF-8.
std::string GetFontName() const;
+ // Returns the actually used font name in UTF-8.
+ std::string GetActualFontNameForTesting() const;
+
// Returns the font size in pixels.
int GetFontSize() const;
diff --git a/chromium/ui/gfx/font_fallback_win.h b/chromium/ui/gfx/font_fallback_win.h
index 7e206da4f43..ee675714e7f 100644
--- a/chromium/ui/gfx/font_fallback_win.h
+++ b/chromium/ui/gfx/font_fallback_win.h
@@ -20,20 +20,20 @@ namespace internal {
//
// Sets |filename| and |font_name| respectively. If a field is not present
// or could not be parsed, the corresponding parameter will be cleared.
-void UI_EXPORT ParseFontLinkEntry(const std::string& entry,
+void GFX_EXPORT ParseFontLinkEntry(const std::string& entry,
std::string* filename,
std::string* font_name);
// Parses a font |family| in the format "FamilyFoo & FamilyBar (TrueType)".
// Splits by '&' and strips off the trailing parenthesized expression.
-void UI_EXPORT ParseFontFamilyString(const std::string& family,
+void GFX_EXPORT ParseFontFamilyString(const std::string& family,
std::vector<std::string>* font_names);
} // namespace internal
// Iterator over linked fallback fonts for a given font. The linked font chain
// comes from the Windows registry, but gets cached between uses.
-class UI_EXPORT LinkedFontsIterator {
+class GFX_EXPORT LinkedFontsIterator {
public:
// Instantiates the iterator over the linked font chain for |font|. The first
// item will be |font| itself.
diff --git a/chromium/ui/gfx/font_list.cc b/chromium/ui/gfx/font_list.cc
index e01483a7cc1..3b1ab9bcd1f 100644
--- a/chromium/ui/gfx/font_list.cc
+++ b/chromium/ui/gfx/font_list.cc
@@ -6,6 +6,7 @@
#include <algorithm>
+#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
@@ -13,6 +14,10 @@
namespace {
+// Font description of the default font set.
+base::LazyInstance<std::string>::Leaky g_default_font_description =
+ LAZY_INSTANCE_INITIALIZER;
+
// Parses font description into |font_names|, |font_style| and |font_size|.
void ParseFontDescriptionString(const std::string& font_description_string,
std::vector<std::string>* font_names,
@@ -75,7 +80,14 @@ FontList::FontList()
common_baseline_(-1),
font_style_(-1),
font_size_(-1) {
- fonts_.push_back(Font());
+ // SetDefaultFontDescription() must be called and the default font description
+ // must be set earlier than any call of the default constructor.
+ DCHECK(!(g_default_font_description == NULL)) // != is not overloaded.
+ << "SetDefaultFontDescription has not been called.";
+
+ font_description_string_ = g_default_font_description.Get();
+ if (font_description_string_.empty())
+ fonts_.push_back(Font());
}
FontList::FontList(const std::string& font_description_string)
@@ -130,6 +142,16 @@ FontList::FontList(const Font& font)
FontList::~FontList() {
}
+// static
+void FontList::SetDefaultFontDescription(const std::string& font_description) {
+ // The description string must end with "px" for size in pixel, or must be
+ // the empty string, which specifies to use a single default font.
+ DCHECK(font_description.empty() ||
+ EndsWith(font_description, "px", true));
+
+ g_default_font_description.Get() = font_description;
+}
+
FontList FontList::DeriveFontList(int font_style) const {
return DeriveFontListWithSizeDeltaAndStyle(0, font_style);
}
@@ -177,6 +199,11 @@ int FontList::GetBaseline() const {
return common_baseline_;
}
+int FontList::GetCapHeight() const {
+ // Assume the primary font is used to render Latin characters.
+ return GetPrimaryFont().GetCapHeight();
+}
+
int FontList::GetStringWidth(const base::string16& text) const {
// Rely on the primary font metrics for the time being.
// TODO(yukishiino): Not only the first font, all the fonts in the list should
diff --git a/chromium/ui/gfx/font_list.h b/chromium/ui/gfx/font_list.h
index ae96251cce8..e37fd625a23 100644
--- a/chromium/ui/gfx/font_list.h
+++ b/chromium/ui/gfx/font_list.h
@@ -32,7 +32,7 @@ namespace gfx {
//
// FontList allows operator= since FontList is a data member type in RenderText,
// and operator= is used in RenderText::SetFontList().
-class UI_EXPORT FontList {
+class GFX_EXPORT FontList {
public:
// Creates a font list with a Font with default name and style.
FontList();
@@ -55,6 +55,16 @@ class UI_EXPORT FontList {
~FontList();
+ // Sets the description string for default FontList construction. If it's
+ // empty, FontList will initialize using the default Font constructor.
+ //
+ // The client code must call this function before any call of the default
+ // constructor. This should be done on the UI thread.
+ //
+ // ui::ResourceBundle may call this function more than once when UI language
+ // is changed.
+ static void SetDefaultFontDescription(const std::string& font_description);
+
// Returns a new FontList with the given |font_style| flags.
FontList DeriveFontList(int font_style) const;
@@ -81,6 +91,10 @@ class UI_EXPORT FontList {
// fonts in the font list.
int GetBaseline() const;
+ // Returns the cap height of this font list.
+ // Currently returns the cap height of the primary font.
+ int GetCapHeight() const;
+
// Returns the number of horizontal pixels needed to display |text|.
int GetStringWidth(const base::string16& text) const;
diff --git a/chromium/ui/gfx/font_list_unittest.cc b/chromium/ui/gfx/font_list_unittest.cc
index a62a13db469..6cbb41fbecd 100644
--- a/chromium/ui/gfx/font_list_unittest.cc
+++ b/chromium/ui/gfx/font_list_unittest.cc
@@ -9,6 +9,7 @@
#include <vector>
#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
@@ -292,6 +293,7 @@ TEST(FontListTest, Fonts_DeriveFontListWithSizeDeltaAndStyle) {
TEST(FontListTest, Fonts_GetHeight_GetBaseline) {
// If a font list has only one font, the height and baseline must be the same.
Font font1("Arial", 16);
+ ASSERT_EQ("arial", StringToLowerASCII(font1.GetActualFontNameForTesting()));
FontList font_list1("Arial, 16px");
EXPECT_EQ(font1.GetHeight(), font_list1.GetHeight());
EXPECT_EQ(font1.GetBaseline(), font_list1.GetBaseline());
@@ -299,6 +301,7 @@ TEST(FontListTest, Fonts_GetHeight_GetBaseline) {
// If there are two different fonts, the font list returns the max value
// for ascent and descent.
Font font2("Symbol", 16);
+ ASSERT_EQ("symbol", StringToLowerASCII(font2.GetActualFontNameForTesting()));
EXPECT_NE(font1.GetBaseline(), font2.GetBaseline());
EXPECT_NE(font1.GetHeight() - font1.GetBaseline(),
font2.GetHeight() - font2.GetBaseline());
diff --git a/chromium/ui/gfx/font_render_params_linux.h b/chromium/ui/gfx/font_render_params_linux.h
index 9ba6ca971b2..ac8323ceade 100644
--- a/chromium/ui/gfx/font_render_params_linux.h
+++ b/chromium/ui/gfx/font_render_params_linux.h
@@ -10,7 +10,7 @@
namespace gfx {
// A collection of parameters describing how text should be rendered on Linux.
-struct UI_EXPORT FontRenderParams {
+struct GFX_EXPORT FontRenderParams {
// No constructor to avoid static initialization.
// Level of hinting to be applied.
@@ -54,16 +54,16 @@ struct UI_EXPORT FontRenderParams {
};
// Returns the system's default parameters for font rendering.
-UI_EXPORT const FontRenderParams& GetDefaultFontRenderParams();
+GFX_EXPORT const FontRenderParams& GetDefaultFontRenderParams();
// Returns the system's default parameters for WebKit font rendering.
-UI_EXPORT const FontRenderParams& GetDefaultWebKitFontRenderParams();
+GFX_EXPORT const FontRenderParams& GetDefaultWebKitFontRenderParams();
// Returns the system's default parameters for WebKit subpixel positioning.
// Subpixel positioning is special since neither GTK nor FontConfig currently
// track it as a preference.
// See https://bugs.freedesktop.org/show_bug.cgi?id=50736
-UI_EXPORT bool GetDefaultWebkitSubpixelPositioning();
+GFX_EXPORT bool GetDefaultWebkitSubpixelPositioning();
} // namespace gfx
diff --git a/chromium/ui/gfx/font_unittest.cc b/chromium/ui/gfx/font_unittest.cc
index 6b5cb798657..2fdaab872f4 100644
--- a/chromium/ui/gfx/font_unittest.cc
+++ b/chromium/ui/gfx/font_unittest.cc
@@ -5,10 +5,11 @@
#include "ui/gfx/font.h"
#include "base/strings/string16.h"
+#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "testing/gtest/include/gtest/gtest.h"
-#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
+#if defined(OS_LINUX) && !defined(USE_OZONE)
#include <pango/pango.h>
#elif defined(OS_WIN)
#include "ui/gfx/platform_font_win.h"
@@ -22,7 +23,7 @@ class FontTest : public testing::Test {
// Fulfills the memory management contract as outlined by the comment at
// gfx::Font::GetNativeFont().
void FreeIfNecessary(NativeFont font) {
-#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
+#if defined(OS_LINUX) && !defined(USE_OZONE)
pango_font_description_free(font);
#endif
}
@@ -59,10 +60,11 @@ int ScopedMinimumFontSizeCallback::minimum_size_ = 0;
TEST_F(FontTest, LoadArial) {
Font cf("Arial", 16);
NativeFont native = cf.GetNativeFont();
- ASSERT_TRUE(native);
- ASSERT_EQ(cf.GetStyle(), Font::NORMAL);
- ASSERT_EQ(cf.GetFontSize(), 16);
- ASSERT_EQ(cf.GetFontName(), "Arial");
+ EXPECT_TRUE(native);
+ EXPECT_EQ(cf.GetStyle(), Font::NORMAL);
+ EXPECT_EQ(cf.GetFontSize(), 16);
+ EXPECT_EQ(cf.GetFontName(), "Arial");
+ EXPECT_EQ("arial", StringToLowerASCII(cf.GetActualFontNameForTesting()));
FreeIfNecessary(native);
}
@@ -70,48 +72,76 @@ TEST_F(FontTest, LoadArialBold) {
Font cf("Arial", 16);
Font bold(cf.DeriveFont(0, Font::BOLD));
NativeFont native = bold.GetNativeFont();
- ASSERT_TRUE(native);
- ASSERT_EQ(bold.GetStyle(), Font::BOLD);
+ EXPECT_TRUE(native);
+ EXPECT_EQ(bold.GetStyle(), Font::BOLD);
+ EXPECT_EQ("arial", StringToLowerASCII(cf.GetActualFontNameForTesting()));
FreeIfNecessary(native);
}
TEST_F(FontTest, Ascent) {
Font cf("Arial", 16);
- ASSERT_GT(cf.GetBaseline(), 2);
- ASSERT_LE(cf.GetBaseline(), 22);
+ EXPECT_GT(cf.GetBaseline(), 2);
+ EXPECT_LE(cf.GetBaseline(), 22);
}
TEST_F(FontTest, Height) {
Font cf("Arial", 16);
- ASSERT_GE(cf.GetHeight(), 16);
+ EXPECT_GE(cf.GetHeight(), 16);
// TODO(akalin): Figure out why height is so large on Linux.
- ASSERT_LE(cf.GetHeight(), 26);
+ EXPECT_LE(cf.GetHeight(), 26);
+}
+
+TEST_F(FontTest, CapHeight) {
+ Font cf("Arial", 16);
+ EXPECT_GT(cf.GetCapHeight(), 0);
+ EXPECT_GT(cf.GetCapHeight(), cf.GetHeight() / 2);
+#if defined(OS_CHROMEOS) || defined(OS_LINUX)
+ EXPECT_EQ(cf.GetCapHeight(), cf.GetBaseline());
+#else
+ EXPECT_LT(cf.GetCapHeight(), cf.GetBaseline());
+#endif
}
TEST_F(FontTest, AvgWidths) {
Font cf("Arial", 16);
- ASSERT_EQ(cf.GetExpectedTextWidth(0), 0);
- ASSERT_GT(cf.GetExpectedTextWidth(1), cf.GetExpectedTextWidth(0));
- ASSERT_GT(cf.GetExpectedTextWidth(2), cf.GetExpectedTextWidth(1));
- ASSERT_GT(cf.GetExpectedTextWidth(3), cf.GetExpectedTextWidth(2));
+ EXPECT_EQ(cf.GetExpectedTextWidth(0), 0);
+ EXPECT_GT(cf.GetExpectedTextWidth(1), cf.GetExpectedTextWidth(0));
+ EXPECT_GT(cf.GetExpectedTextWidth(2), cf.GetExpectedTextWidth(1));
+ EXPECT_GT(cf.GetExpectedTextWidth(3), cf.GetExpectedTextWidth(2));
}
TEST_F(FontTest, AvgCharWidth) {
Font cf("Arial", 16);
- ASSERT_GT(cf.GetAverageCharacterWidth(), 0);
+ EXPECT_GT(cf.GetAverageCharacterWidth(), 0);
}
TEST_F(FontTest, Widths) {
Font cf("Arial", 16);
- ASSERT_EQ(cf.GetStringWidth(base::string16()), 0);
- ASSERT_GT(cf.GetStringWidth(ASCIIToUTF16("a")),
+ EXPECT_EQ(cf.GetStringWidth(base::string16()), 0);
+ EXPECT_GT(cf.GetStringWidth(ASCIIToUTF16("a")),
cf.GetStringWidth(base::string16()));
- ASSERT_GT(cf.GetStringWidth(ASCIIToUTF16("ab")),
+ EXPECT_GT(cf.GetStringWidth(ASCIIToUTF16("ab")),
cf.GetStringWidth(ASCIIToUTF16("a")));
- ASSERT_GT(cf.GetStringWidth(ASCIIToUTF16("abc")),
+ EXPECT_GT(cf.GetStringWidth(ASCIIToUTF16("abc")),
cf.GetStringWidth(ASCIIToUTF16("ab")));
}
+#if !defined(OS_WIN)
+// On Windows, Font::GetActualFontNameForTesting() doesn't work well for now.
+// http://crbug.com/327287
+TEST_F(FontTest, GetActualFontNameForTesting) {
+ Font arial("Arial", 16);
+ EXPECT_EQ("arial", StringToLowerASCII(arial.GetActualFontNameForTesting()));
+ Font symbol("Symbol", 16);
+ EXPECT_EQ("symbol", StringToLowerASCII(symbol.GetActualFontNameForTesting()));
+
+ const char* const invalid_font_name = "no_such_font_name";
+ Font fallback_font(invalid_font_name, 16);
+ EXPECT_NE(invalid_font_name,
+ StringToLowerASCII(fallback_font.GetActualFontNameForTesting()));
+}
+#endif
+
#if defined(OS_WIN)
TEST_F(FontTest, DeriveFontResizesIfSizeTooSmall) {
Font cf("Arial", 8);
diff --git a/chromium/ui/gfx/frame_time.h b/chromium/ui/gfx/frame_time.h
new file mode 100644
index 00000000000..5cc65f5f4a8
--- /dev/null
+++ b/chromium/ui/gfx/frame_time.h
@@ -0,0 +1,40 @@
+// Copyright 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_FRAME_TIME_H
+#define UI_GFX_FRAME_TIME_H
+
+#include "base/time/time.h"
+#include "base/logging.h"
+
+namespace gfx {
+
+// FrameTime::Now() should be used to get timestamps with a timebase that
+// is consistent across the graphics stack.
+class FrameTime {
+ public:
+ static base::TimeTicks Now() {
+ if (TimestampsAreHighRes())
+ return base::TimeTicks::HighResNow();
+ return base::TimeTicks::Now();
+ }
+
+#if defined(OS_WIN)
+ static base::TimeTicks FromQPCValue(LONGLONG qpc_value) {
+ DCHECK(TimestampsAreHighRes());
+ return base::TimeTicks::FromQPCValue(qpc_value);
+ }
+#endif
+
+ static bool TimestampsAreHighRes() {
+ // This should really return base::TimeTicks::IsHighResNowFastAndReliable();
+ // Returning false makes sure we are only using low-res timestamps until we
+ // use FrameTime everywhere we need to. See crbug.com/315334
+ return false;
+ }
+};
+
+}
+
+#endif // UI_GFX_FRAME_TIME_H
diff --git a/chromium/ui/gfx/gdi_util.h b/chromium/ui/gfx/gdi_util.h
index 53b6e91a897..d8563b69966 100644
--- a/chromium/ui/gfx/gdi_util.h
+++ b/chromium/ui/gfx/gdi_util.h
@@ -15,7 +15,8 @@
namespace gfx {
// Creates a BITMAPINFOHEADER structure given the bitmap's size.
-UI_EXPORT void CreateBitmapHeader(int width, int height, BITMAPINFOHEADER* hdr);
+GFX_EXPORT void CreateBitmapHeader(int width, int height,
+ BITMAPINFOHEADER* hdr);
// Creates a BITMAPINFOHEADER structure given the bitmap's size and
// color depth in bits per pixel.
@@ -25,28 +26,29 @@ void CreateBitmapHeaderWithColorDepth(int width, int height, int color_depth,
// Creates a BITMAPV4HEADER structure given the bitmap's size. You probably
// only need to use BMP V4 if you need transparency (alpha channel). This
// function sets the AlphaMask to 0xff000000.
-UI_EXPORT void CreateBitmapV4Header(int width, int height, BITMAPV4HEADER* hdr);
+GFX_EXPORT void CreateBitmapV4Header(int width, int height,
+ BITMAPV4HEADER* hdr);
// Creates a monochrome bitmap header.
void CreateMonochromeBitmapHeader(int width, int height, BITMAPINFOHEADER* hdr);
// Modify the given hrgn by subtracting the given rectangles.
-UI_EXPORT void SubtractRectanglesFromRegion(
+GFX_EXPORT void SubtractRectanglesFromRegion(
HRGN hrgn,
const std::vector<gfx::Rect>& cutouts);
-UI_EXPORT HRGN ConvertPathToHRGN(const gfx::Path& path);
+GFX_EXPORT HRGN ConvertPathToHRGN(const gfx::Path& path);
// Calculate scale to fit an entire page on DC.
-UI_EXPORT double CalculatePageScale(HDC dc, int page_width, int page_height);
+GFX_EXPORT double CalculatePageScale(HDC dc, int page_width, int page_height);
// Apply scaling to the DC.
-UI_EXPORT bool ScaleDC(HDC dc, double scale_factor);
+GFX_EXPORT bool ScaleDC(HDC dc, double scale_factor);
-UI_EXPORT void StretchDIBits(HDC hdc,
- int dest_x, int dest_y, int dest_w, int dest_h,
- int src_x, int src_y, int src_w, int src_h,
- void* pixels, const BITMAPINFO* bitmap_info);
+GFX_EXPORT void StretchDIBits(HDC hdc,
+ int dest_x, int dest_y, int dest_w, int dest_h,
+ int src_x, int src_y, int src_w, int src_h,
+ void* pixels, const BITMAPINFO* bitmap_info);
} // namespace gfx
diff --git a/chromium/ui/gfx/gfx.gyp b/chromium/ui/gfx/gfx.gyp
new file mode 100644
index 00000000000..5fb17d52ee6
--- /dev/null
+++ b/chromium/ui/gfx/gfx.gyp
@@ -0,0 +1,440 @@
+# 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.
+
+{
+ 'variables': {
+ 'chromium_code': 1,
+ },
+ 'targets': [
+ {
+ 'target_name': 'gfx',
+ 'type': '<(component)',
+ 'dependencies': [
+ '<(DEPTH)/base/base.gyp:base',
+ '<(DEPTH)/base/base.gyp:base_i18n',
+ '<(DEPTH)/base/base.gyp:base_static',
+ '<(DEPTH)/base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
+ '<(DEPTH)/net/net.gyp:net',
+ '<(DEPTH)/skia/skia.gyp:skia',
+ '<(DEPTH)/third_party/icu/icu.gyp:icui18n',
+ '<(DEPTH)/third_party/icu/icu.gyp:icuuc',
+ '<(DEPTH)/third_party/libpng/libpng.gyp:libpng',
+ '<(DEPTH)/third_party/zlib/zlib.gyp:zlib',
+ '<(DEPTH)/url/url.gyp:url_lib',
+ ],
+ # text_elider.h includes ICU headers.
+ 'export_dependent_settings': [
+ '<(DEPTH)/skia/skia.gyp:skia',
+ '<(DEPTH)/third_party/icu/icu.gyp:icui18n',
+ '<(DEPTH)/third_party/icu/icu.gyp:icuuc',
+ ],
+ 'defines': [
+ 'GFX_IMPLEMENTATION',
+ ],
+ 'sources': [
+ 'android/device_display_info.cc',
+ 'android/device_display_info.h',
+ 'android/gfx_jni_registrar.cc',
+ 'android/gfx_jni_registrar.h',
+ 'android/java_bitmap.cc',
+ 'android/java_bitmap.h',
+ 'android/shared_device_display_info.cc',
+ 'android/shared_device_display_info.h',
+ 'android/view_configuration.cc',
+ 'android/view_configuration.h',
+ 'animation/animation.cc',
+ 'animation/animation.h',
+ 'animation/animation_container.cc',
+ 'animation/animation_container.h',
+ 'animation/animation_container_element.h',
+ 'animation/animation_container_observer.h',
+ 'animation/animation_delegate.h',
+ 'animation/linear_animation.cc',
+ 'animation/linear_animation.h',
+ 'animation/multi_animation.cc',
+ 'animation/multi_animation.h',
+ 'animation/slide_animation.cc',
+ 'animation/slide_animation.h',
+ 'animation/throb_animation.cc',
+ 'animation/throb_animation.h',
+ 'animation/tween.cc',
+ 'animation/tween.h',
+ 'blit.cc',
+ 'blit.h',
+ 'box_f.cc',
+ 'box_f.h',
+ 'break_list.h',
+ 'canvas.cc',
+ 'canvas.h',
+ 'canvas_android.cc',
+ 'canvas_paint_gtk.cc',
+ 'canvas_paint_gtk.h',
+ 'canvas_paint_mac.h',
+ 'canvas_paint_mac.mm',
+ 'canvas_paint_win.cc',
+ 'canvas_paint_win.h',
+ 'canvas_skia.cc',
+ 'canvas_skia_paint.h',
+ 'codec/jpeg_codec.cc',
+ 'codec/jpeg_codec.h',
+ 'codec/png_codec.cc',
+ 'codec/png_codec.h',
+ 'color_analysis.cc',
+ 'color_analysis.h',
+ 'color_profile.cc',
+ 'color_profile.h',
+ 'color_profile_mac.cc',
+ 'color_profile_win.cc',
+ 'color_utils.cc',
+ 'color_utils.h',
+ 'display.cc',
+ 'display.h',
+ 'display_observer.cc',
+ 'display_observer.h',
+ 'favicon_size.cc',
+ 'favicon_size.h',
+ 'frame_time.h',
+ 'font.cc',
+ 'font.h',
+ 'font_fallback_win.cc',
+ 'font_fallback_win.h',
+ 'font_list.cc',
+ 'font_list.h',
+ 'font_render_params_android.cc',
+ 'font_render_params_linux.cc',
+ 'font_render_params_linux.h',
+ 'font_smoothing_win.cc',
+ 'font_smoothing_win.h',
+ 'gfx_export.h',
+ 'gfx_paths.cc',
+ 'gfx_paths.h',
+ 'gpu_memory_buffer.cc',
+ 'gpu_memory_buffer.h',
+ 'image/canvas_image_source.cc',
+ 'image/canvas_image_source.h',
+ 'image/image.cc',
+ 'image/image.h',
+ 'image/image_family.cc',
+ 'image/image_family.h',
+ 'image/image_ios.mm',
+ 'image/image_mac.mm',
+ 'image/image_png_rep.cc',
+ 'image/image_png_rep.h',
+ 'image/image_skia.cc',
+ 'image/image_skia.h',
+ 'image/image_skia_operations.cc',
+ 'image/image_skia_operations.h',
+ 'image/image_skia_rep.cc',
+ 'image/image_skia_rep.h',
+ 'image/image_skia_source.h',
+ 'image/image_skia_util_ios.h',
+ 'image/image_skia_util_ios.mm',
+ 'image/image_skia_util_mac.h',
+ 'image/image_skia_util_mac.mm',
+ 'image/image_util.cc',
+ 'image/image_util.h',
+ 'image/image_util_ios.mm',
+ 'insets.cc',
+ 'insets.h',
+ 'insets_base.h',
+ 'insets_f.cc',
+ 'insets_f.h',
+ 'interpolated_transform.cc',
+ 'interpolated_transform.h',
+ 'mac/scoped_ns_disable_screen_updates.h',
+ 'matrix3_f.cc',
+ 'matrix3_f.h',
+ 'native_widget_types.h',
+ 'ozone/dri/dri_skbitmap.cc',
+ 'ozone/dri/dri_skbitmap.h',
+ 'ozone/dri/dri_surface.cc',
+ 'ozone/dri/dri_surface.h',
+ 'ozone/dri/dri_surface_factory.cc',
+ 'ozone/dri/dri_surface_factory.h',
+ 'ozone/dri/dri_vsync_provider.cc',
+ 'ozone/dri/dri_vsync_provider.h',
+ 'ozone/dri/dri_wrapper.cc',
+ 'ozone/dri/dri_wrapper.h',
+ 'ozone/dri/hardware_display_controller.cc',
+ 'ozone/dri/hardware_display_controller.h',
+ 'ozone/impl/file_surface_factory.cc',
+ 'ozone/impl/file_surface_factory.h',
+ 'ozone/surface_factory_ozone.cc',
+ 'ozone/surface_factory_ozone.h',
+ 'pango_util.cc',
+ 'pango_util.h',
+ 'path.cc',
+ 'path.h',
+ 'path_aura.cc',
+ 'path_gtk.cc',
+ 'path_win.cc',
+ 'path_win.h',
+ 'path_x11.cc',
+ 'path_x11.h',
+ 'platform_font.h',
+ 'platform_font_android.cc',
+ 'platform_font_ios.h',
+ 'platform_font_ios.mm',
+ 'platform_font_mac.h',
+ 'platform_font_mac.mm',
+ 'platform_font_ozone.cc',
+ 'platform_font_pango.cc',
+ 'platform_font_pango.h',
+ 'platform_font_win.cc',
+ 'platform_font_win.h',
+ 'point.cc',
+ 'point.h',
+ 'point3_f.cc',
+ 'point3_f.h',
+ 'point_base.h',
+ 'point_conversions.cc',
+ 'point_conversions.h',
+ 'point_f.cc',
+ 'point_f.h',
+ 'quad_f.cc',
+ 'quad_f.h',
+ 'range/range.cc',
+ 'range/range.h',
+ 'range/range_mac.mm',
+ 'range/range_win.cc',
+ 'rect.cc',
+ 'rect.h',
+ 'rect_base.h',
+ 'rect_base_impl.h',
+ 'rect_conversions.cc',
+ 'rect_conversions.h',
+ 'rect_f.cc',
+ 'rect_f.h',
+ 'render_text.cc',
+ 'render_text.h',
+ 'render_text_mac.cc',
+ 'render_text_mac.h',
+ 'render_text_ozone.cc',
+ 'render_text_pango.cc',
+ 'render_text_pango.h',
+ 'render_text_win.cc',
+ 'render_text_win.h',
+ 'safe_integer_conversions.h',
+ 'scoped_canvas.h',
+ 'scoped_cg_context_save_gstate_mac.h',
+ 'scoped_ns_graphics_context_save_gstate_mac.h',
+ 'scoped_ns_graphics_context_save_gstate_mac.mm',
+ 'scoped_ui_graphics_push_context_ios.h',
+ 'scoped_ui_graphics_push_context_ios.mm',
+ 'screen.cc',
+ 'screen.h',
+ 'screen_android.cc',
+ 'screen_aura.cc',
+ 'screen_gtk.cc',
+ 'screen_ios.mm',
+ 'screen_mac.mm',
+ 'screen_win.cc',
+ 'screen_win.h',
+ 'scrollbar_size.cc',
+ 'scrollbar_size.h',
+ 'selection_model.cc',
+ 'selection_model.h',
+ 'sequential_id_generator.cc',
+ 'sequential_id_generator.h',
+ 'shadow_value.cc',
+ 'shadow_value.h',
+ 'size.cc',
+ 'size.h',
+ 'size_base.h',
+ 'size_conversions.cc',
+ 'size_conversions.h',
+ 'size_f.cc',
+ 'size_f.h',
+ 'skbitmap_operations.cc',
+ 'skbitmap_operations.h',
+ 'skia_util.cc',
+ 'skia_util.h',
+ 'skia_utils_gtk.cc',
+ 'skia_utils_gtk.h',
+ 'switches.cc',
+ 'switches.h',
+ 'sys_color_change_listener.cc',
+ 'sys_color_change_listener.h',
+ 'text_constants.h',
+ 'text_elider.cc',
+ 'text_elider.h',
+ 'text_utils.cc',
+ 'text_utils.h',
+ 'text_utils_android.cc',
+ 'text_utils_ios.mm',
+ 'text_utils_skia.cc',
+ 'transform.cc',
+ 'transform.h',
+ 'transform_util.cc',
+ 'transform_util.h',
+ 'ui_gfx_exports.cc',
+ 'utf16_indexing.cc',
+ 'utf16_indexing.h',
+ 'vector2d.cc',
+ 'vector2d.h',
+ 'vector2d_conversions.cc',
+ 'vector2d_conversions.h',
+ 'vector2d_f.cc',
+ 'vector2d_f.h',
+ 'vector3d_f.cc',
+ 'vector3d_f.h',
+ 'vsync_provider.h',
+ 'win/dpi.cc',
+ 'win/dpi.h',
+ 'win/hwnd_util.cc',
+ 'win/hwnd_util.h',
+ 'win/scoped_set_map_mode.h',
+ 'win/singleton_hwnd.cc',
+ 'win/singleton_hwnd.h',
+ 'win/window_impl.cc',
+ 'win/window_impl.h',
+ 'x/x11_atom_cache.cc',
+ 'x/x11_atom_cache.h',
+ 'x/x11_types.cc',
+ 'x/x11_types.h',
+ ],
+ 'conditions': [
+ ['OS=="ios"', {
+ # iOS only uses a subset of UI.
+ 'sources/': [
+ ['exclude', '^codec/jpeg_codec\\.cc$'],
+ ],
+ }, {
+ 'dependencies': [
+ '<(libjpeg_gyp_path):libjpeg',
+ ],
+ }],
+ # TODO(asvitkine): Switch all platforms to use canvas_skia.cc.
+ # http://crbug.com/105550
+ ['use_canvas_skia==1', {
+ 'sources!': [
+ 'canvas_android.cc',
+ ],
+ }, { # use_canvas_skia!=1
+ 'sources!': [
+ 'canvas_skia.cc',
+ ],
+ }],
+ ['toolkit_uses_gtk == 1', {
+ 'dependencies': [
+ '<(DEPTH)/build/linux/system.gyp:gtk',
+ ],
+ 'sources': [
+ 'gtk_native_view_id_manager.cc',
+ 'gtk_native_view_id_manager.h',
+ 'gtk_preserve_window.cc',
+ 'gtk_preserve_window.h',
+ 'gdk_compat.h',
+ 'gtk_compat.h',
+ 'gtk_util.cc',
+ 'gtk_util.h',
+ 'image/cairo_cached_surface.cc',
+ 'image/cairo_cached_surface.h',
+ 'scoped_gobject.h',
+ ],
+ }],
+ ['OS=="win"', {
+ 'sources': [
+ 'gdi_util.cc',
+ 'gdi_util.h',
+ 'icon_util.cc',
+ 'icon_util.h',
+ ],
+ # TODO(jschuh): C4267: http://crbug.com/167187 size_t -> int
+ # C4324 is structure was padded due to __declspec(align()), which is
+ # uninteresting.
+ 'msvs_disabled_warnings': [ 4267, 4324 ],
+ }],
+ ['OS=="android"', {
+ 'sources!': [
+ 'animation/throb_animation.cc',
+ 'display_observer.cc',
+ 'path.cc',
+ 'selection_model.cc',
+ ],
+ 'dependencies': [
+ 'gfx_jni_headers',
+ ],
+ 'link_settings': {
+ 'libraries': [
+ '-landroid',
+ '-ljnigraphics',
+ ],
+ },
+ }],
+ ['OS=="android" and android_webview_build==0', {
+ 'dependencies': [
+ '<(DEPTH)/base/base.gyp:base_java',
+ ],
+ }],
+ ['OS=="android" or OS=="ios"', {
+ 'sources!': [
+ 'render_text.cc',
+ 'render_text.h',
+ 'text_utils_skia.cc',
+ ],
+ }],
+ ['use_pango==1', {
+ 'dependencies': [
+ '<(DEPTH)/build/linux/system.gyp:pangocairo',
+ ],
+ 'sources!': [
+ 'platform_font_ozone.cc',
+ 'render_text_ozone.cc',
+ ],
+ }],
+ ['ozone_platform_dri==1', {
+ 'dependencies': [
+ '<(DEPTH)/build/linux/system.gyp:dridrm',
+ ],
+ }],
+ ],
+ 'target_conditions': [
+ # Need 'target_conditions' to override default filename_rules to include
+ # the file on iOS.
+ ['OS == "ios"', {
+ 'sources/': [
+ ['include', '^scoped_cg_context_save_gstate_mac\\.h$'],
+ ],
+ }],
+ ],
+ }
+ ],
+ 'conditions': [
+ ['OS=="android"' , {
+ 'targets': [
+ {
+ 'target_name': 'gfx_view_jni_headers',
+ 'type': 'none',
+ 'variables': {
+ 'jni_gen_package': 'ui/gfx',
+ 'input_java_class': 'android/view/ViewConfiguration.class',
+ },
+ 'includes': [ '../../build/jar_file_jni_generator.gypi' ],
+ },
+ {
+ 'target_name': 'gfx_jni_headers',
+ 'type': 'none',
+ 'dependencies': [
+ 'gfx_view_jni_headers'
+ ],
+ 'direct_dependent_settings': {
+ 'include_dirs': [
+ '<(SHARED_INTERMEDIATE_DIR)/ui/gfx',
+ ],
+ },
+ 'sources': [
+ '../android/java/src/org/chromium/ui/gfx/BitmapHelper.java',
+ '../android/java/src/org/chromium/ui/gfx/DeviceDisplayInfo.java',
+ ],
+ 'variables': {
+ 'jni_gen_package': 'ui/gfx',
+ 'jni_generator_ptr_type': 'long'
+ },
+ 'includes': [ '../../build/jni_generator.gypi' ],
+ },
+ ],
+ }],
+ ],
+}
diff --git a/chromium/ui/gfx/gfx_export.h b/chromium/ui/gfx/gfx_export.h
index f610d98d82d..20c8bb1681d 100644
--- a/chromium/ui/gfx/gfx_export.h
+++ b/chromium/ui/gfx/gfx_export.h
@@ -5,21 +5,17 @@
#ifndef UI_GFX_GFX_EXPORT_H_
#define UI_GFX_GFX_EXPORT_H_
-// TODO(beng): remove include once gfx dependencies have been corrected.
-
-#include "ui/base/ui_export.h"
-
#if defined(COMPONENT_BUILD)
#if defined(WIN32)
-#if defined(UI_IMPLEMENTATION)
+#if defined(GFX_IMPLEMENTATION)
#define GFX_EXPORT __declspec(dllexport)
#else
#define GFX_EXPORT __declspec(dllimport)
-#endif // defined(UI_IMPLEMENTATION)
+#endif // defined(GFX_IMPLEMENTATION)
#else // defined(WIN32)
-#if defined(UI_IMPLEMENTATION)
+#if defined(GFX_IMPLEMENTATION)
#define GFX_EXPORT __attribute__((visibility("default")))
#else
#define GFX_EXPORT
diff --git a/chromium/ui/gfx/gfx_paths.h b/chromium/ui/gfx/gfx_paths.h
index d5eec96fd74..7a779edbc92 100644
--- a/chromium/ui/gfx/gfx_paths.h
+++ b/chromium/ui/gfx/gfx_paths.h
@@ -22,7 +22,7 @@ enum {
};
// Call once to register the provider for the path keys defined above.
-UI_EXPORT void RegisterPathProvider();
+GFX_EXPORT void RegisterPathProvider();
} // namespace gfx
diff --git a/chromium/ui/gfx/gpu_memory_buffer.h b/chromium/ui/gfx/gpu_memory_buffer.h
index c600527f022..4a7b142d175 100644
--- a/chromium/ui/gfx/gpu_memory_buffer.h
+++ b/chromium/ui/gfx/gpu_memory_buffer.h
@@ -18,7 +18,8 @@ namespace gfx {
enum GpuMemoryBufferType {
EMPTY_BUFFER,
SHARED_MEMORY_BUFFER,
- EGL_CLIENT_BUFFER
+ EGL_CLIENT_BUFFER,
+ IO_SURFACE_BUFFER
};
struct GpuMemoryBufferHandle {
@@ -28,6 +29,9 @@ struct GpuMemoryBufferHandle {
#if defined(OS_ANDROID)
, native_buffer(NULL)
#endif
+#if defined(OS_MACOSX)
+ , io_surface_id(0)
+#endif
{
}
bool is_null() const { return type == EMPTY_BUFFER; }
@@ -36,6 +40,10 @@ struct GpuMemoryBufferHandle {
#if defined(OS_ANDROID)
EGLClientBuffer native_buffer;
#endif
+#if defined(OS_MACOSX)
+ uint32 io_surface_id;
+#endif
+
};
// Interface for creating and accessing a zero-copy GPU memory buffer.
@@ -47,7 +55,7 @@ struct GpuMemoryBufferHandle {
// This interface is thread-safe. However, multiple threads mapping
// a buffer for Write or ReadOrWrite simultaneously may result in undefined
// behavior and is not allowed.
-class UI_EXPORT GpuMemoryBuffer {
+class GFX_EXPORT GpuMemoryBuffer {
public:
enum AccessMode {
READ_ONLY,
diff --git a/chromium/ui/gfx/gtk_native_view_id_manager.h b/chromium/ui/gfx/gtk_native_view_id_manager.h
index 242cf0939e3..44219209273 100644
--- a/chromium/ui/gfx/gtk_native_view_id_manager.h
+++ b/chromium/ui/gfx/gtk_native_view_id_manager.h
@@ -31,7 +31,7 @@ struct _GtkPreserveWindow;
// pointers and observes the various signals from the widget for when an X
// window is created, destroyed etc. Thus it provides a thread safe mapping
// from NativeViewIds to the current XID for that widget.
-class UI_EXPORT GtkNativeViewManager {
+class GFX_EXPORT GtkNativeViewManager {
public:
// Returns the singleton instance.
static GtkNativeViewManager* GetInstance();
diff --git a/chromium/ui/gfx/gtk_preserve_window.h b/chromium/ui/gfx/gtk_preserve_window.h
index f48be3f2bdb..5b5198bf56f 100644
--- a/chromium/ui/gfx/gtk_preserve_window.h
+++ b/chromium/ui/gfx/gtk_preserve_window.h
@@ -46,25 +46,25 @@ struct _GtkPreserveWindowClass {
GtkFixedClass parent_class;
};
-UI_EXPORT GType gtk_preserve_window_get_type() G_GNUC_CONST;
-UI_EXPORT GtkWidget* gtk_preserve_window_new();
+GFX_EXPORT GType gtk_preserve_window_get_type() G_GNUC_CONST;
+GFX_EXPORT GtkWidget* gtk_preserve_window_new();
// Whether or not we should preserve associated windows as the widget
// is realized or unrealized.
-UI_EXPORT gboolean gtk_preserve_window_get_preserve(GtkPreserveWindow* widget);
-UI_EXPORT void gtk_preserve_window_set_preserve(GtkPreserveWindow* widget,
- gboolean value);
+GFX_EXPORT gboolean gtk_preserve_window_get_preserve(GtkPreserveWindow* widget);
+GFX_EXPORT void gtk_preserve_window_set_preserve(GtkPreserveWindow* widget,
+ gboolean value);
// Whether or not someone else will gdk_window_resize the GdkWindow associated
// with this widget (needed by the GPU process to synchronize resizing
// with swapped between front and back buffer).
-UI_EXPORT void gtk_preserve_window_delegate_resize(GtkPreserveWindow* widget,
- gboolean delegate);
+GFX_EXPORT void gtk_preserve_window_delegate_resize(GtkPreserveWindow* widget,
+ gboolean delegate);
// Provide a function to return an AtkObject* when calls to get_accessible
// are made on this widget. The parameter |userdata| will be passed to the
// factory function.
-UI_EXPORT void gtk_preserve_window_set_accessible_factory(
+GFX_EXPORT void gtk_preserve_window_set_accessible_factory(
GtkPreserveWindow* widget,
AtkObject* (*factory)(void* userdata),
gpointer userdata);
diff --git a/chromium/ui/gfx/gtk_util.h b/chromium/ui/gfx/gtk_util.h
index 5672bbd8f12..91f864bbe4c 100644
--- a/chromium/ui/gfx/gtk_util.h
+++ b/chromium/ui/gfx/gtk_util.h
@@ -24,28 +24,28 @@ class Rect;
// Call gtk_init() / gdk_init() using the argc and argv from command_line.
// These init functions want an argc and argv that they can mutate; we provide
// those, but leave the original CommandLine unaltered.
-UI_EXPORT void GtkInitFromCommandLine(const CommandLine& command_line);
-UI_EXPORT void GdkInitFromCommandLine(const CommandLine& command_line);
+GFX_EXPORT void GtkInitFromCommandLine(const CommandLine& command_line);
+GFX_EXPORT void GdkInitFromCommandLine(const CommandLine& command_line);
// Convert and copy a SkBitmap to a GdkPixbuf. NOTE: this uses BGRAToRGBA, so
// it is an expensive operation. The returned GdkPixbuf will have a refcount of
// 1, and the caller is responsible for unrefing it when done.
-UI_EXPORT GdkPixbuf* GdkPixbufFromSkBitmap(const SkBitmap& bitmap);
+GFX_EXPORT GdkPixbuf* GdkPixbufFromSkBitmap(const SkBitmap& bitmap);
// Modify the given region by subtracting the given rectangles.
-UI_EXPORT void SubtractRectanglesFromRegion(GdkRegion* region,
- const std::vector<Rect>& cutouts);
+GFX_EXPORT void SubtractRectanglesFromRegion(GdkRegion* region,
+ const std::vector<Rect>& cutouts);
// Returns a static instance of a GdkCursor* object, sharable across the
// process. Caller must gdk_cursor_ref() it if they want to assume ownership.
-UI_EXPORT GdkCursor* GetCursor(int type);
+GFX_EXPORT GdkCursor* GetCursor(int type);
// Initialize some GTK settings so that our dialogs are consistent.
-UI_EXPORT void InitRCStyles();
+GFX_EXPORT void InitRCStyles();
// Queries GtkSettings for the cursor blink cycle time. Returns a 0 duration if
// blinking is disabled.
-UI_EXPORT base::TimeDelta GetCursorBlinkCycle();
+GFX_EXPORT base::TimeDelta GetCursorBlinkCycle();
} // namespace gfx
diff --git a/chromium/ui/gfx/icon_util.h b/chromium/ui/gfx/icon_util.h
index d56f5a10df3..0cb35088147 100644
--- a/chromium/ui/gfx/icon_util.h
+++ b/chromium/ui/gfx/icon_util.h
@@ -57,7 +57,7 @@ class SkBitmap;
// ::DestroyIcon(icon);
//
///////////////////////////////////////////////////////////////////////////////
-class UI_EXPORT IconUtil {
+class GFX_EXPORT IconUtil {
public:
// The size of the large icon entries in .ico files on Windows Vista+.
static const int kLargeIconSize = 256;
diff --git a/chromium/ui/gfx/image/cairo_cached_surface.h b/chromium/ui/gfx/image/cairo_cached_surface.h
index 7c0204aa81b..ceece4ba2d2 100644
--- a/chromium/ui/gfx/image/cairo_cached_surface.h
+++ b/chromium/ui/gfx/image/cairo_cached_surface.h
@@ -27,7 +27,7 @@ namespace gfx {
// them with a certain XDisplay. Some users of surfaces (CustomDrawButtonBase,
// for example) own their surfaces instead since they interact with the
// ResourceBundle instead of the GtkThemeService.
-class UI_EXPORT CairoCachedSurface {
+class GFX_EXPORT CairoCachedSurface {
public:
CairoCachedSurface();
~CairoCachedSurface();
diff --git a/chromium/ui/gfx/image/canvas_image_source.cc b/chromium/ui/gfx/image/canvas_image_source.cc
index 747625ac60d..b336b311810 100644
--- a/chromium/ui/gfx/image/canvas_image_source.cc
+++ b/chromium/ui/gfx/image/canvas_image_source.cc
@@ -6,7 +6,6 @@
#include "base/logging.h"
#include "ui/gfx/canvas.h"
-#include "ui/base/layout.h"
namespace gfx {
@@ -18,9 +17,8 @@ CanvasImageSource::CanvasImageSource(const gfx::Size& size, bool is_opaque)
is_opaque_(is_opaque) {
}
-gfx::ImageSkiaRep CanvasImageSource::GetImageForScale(
- ui::ScaleFactor scale_factor) {
- gfx::Canvas canvas(size_, scale_factor, is_opaque_);
+gfx::ImageSkiaRep CanvasImageSource::GetImageForScale(float scale) {
+ gfx::Canvas canvas(size_, scale, is_opaque_);
Draw(&canvas);
return canvas.ExtractImageRep();
}
diff --git a/chromium/ui/gfx/image/canvas_image_source.h b/chromium/ui/gfx/image/canvas_image_source.h
index 8373387326c..0ce170dfd9c 100644
--- a/chromium/ui/gfx/image/canvas_image_source.h
+++ b/chromium/ui/gfx/image/canvas_image_source.h
@@ -19,7 +19,7 @@ class ImageSkiaRep;
// a scale factor using gfx::Canvas. It creates a new Canvas
// with target scale factor and generates ImageSkiaRep when drawing is
// completed.
-class UI_EXPORT CanvasImageSource : public gfx::ImageSkiaSource {
+class GFX_EXPORT CanvasImageSource : public gfx::ImageSkiaSource {
public:
CanvasImageSource(const gfx::Size& size, bool is_opaque);
@@ -30,8 +30,7 @@ class UI_EXPORT CanvasImageSource : public gfx::ImageSkiaSource {
const gfx::Size& size() const { return size_; };
// Overridden from gfx::ImageSkiaSource.
- virtual gfx::ImageSkiaRep GetImageForScale(
- ui::ScaleFactor scale_factor) OVERRIDE;
+ virtual gfx::ImageSkiaRep GetImageForScale(float scale) OVERRIDE;
protected:
virtual ~CanvasImageSource() {}
diff --git a/chromium/ui/gfx/image/image.cc b/chromium/ui/gfx/image/image.cc
index f089c837504..91b9e69b289 100644
--- a/chromium/ui/gfx/image/image.cc
+++ b/chromium/ui/gfx/image/image.cc
@@ -43,7 +43,7 @@ const ImageSkia ImageSkiaFromGdkPixbuf(GdkPixbuf* pixbuf) {
CHECK(pixbuf);
gfx::Canvas canvas(gfx::Size(gdk_pixbuf_get_width(pixbuf),
gdk_pixbuf_get_height(pixbuf)),
- ui::SCALE_FACTOR_100P,
+ 1.0f,
false);
skia::ScopedPlatformPaint scoped_platform_paint(canvas.sk_canvas());
cairo_t* cr = scoped_platform_paint.GetPlatformSurface();
@@ -65,7 +65,7 @@ GdkPixbuf* GdkPixbufFromPNG(
const std::vector<gfx::ImagePNGRep>& image_png_reps) {
scoped_refptr<base::RefCountedMemory> png_bytes(NULL);
for (size_t i = 0; i < image_png_reps.size(); ++i) {
- if (image_png_reps[i].scale_factor == ui::SCALE_FACTOR_100P)
+ if (image_png_reps[i].scale == 1.0f)
png_bytes = image_png_reps[i].raw_data;
}
@@ -142,7 +142,7 @@ ImageSkia* GetErrorImageSkia() {
bitmap.setConfig(SkBitmap::kARGB_8888_Config, 16, 16);
bitmap.allocPixels();
bitmap.eraseRGB(0xff, 0, 0);
- return new gfx::ImageSkia(gfx::ImageSkiaRep(bitmap, ui::SCALE_FACTOR_100P));
+ return new gfx::ImageSkia(gfx::ImageSkiaRep(bitmap, 1.0f));
}
ImageSkia* ImageSkiaFromPNG(
@@ -159,23 +159,22 @@ ImageSkia* ImageSkiaFromPNG(
if (!gfx::PNGCodec::Decode(raw_data->front(), raw_data->size(),
&bitmap)) {
LOG(ERROR) << "Unable to decode PNG for "
- << ui::GetScaleFactorScale(image_png_reps[i].scale_factor)
+ << image_png_reps[i].scale
<< ".";
return GetErrorImageSkia();
}
image_skia->AddRepresentation(gfx::ImageSkiaRep(
- bitmap, image_png_reps[i].scale_factor));
+ bitmap, image_png_reps[i].scale));
}
return image_skia.release();
}
scoped_refptr<base::RefCountedMemory> Get1xPNGBytesFromImageSkia(
const ImageSkia* image_skia) {
- ImageSkiaRep image_skia_rep = image_skia->GetRepresentation(
- ui::SCALE_FACTOR_100P);
+ ImageSkiaRep image_skia_rep = image_skia->GetRepresentation(1.0f);
scoped_refptr<base::RefCountedBytes> png_bytes(new base::RefCountedBytes());
- if (image_skia_rep.scale_factor() != ui::SCALE_FACTOR_100P ||
+ if (image_skia_rep.scale() != 1.0f ||
!gfx::PNGCodec::EncodeBGRASkBitmap(image_skia_rep.sk_bitmap(), false,
&png_bytes->data())) {
return NULL;
@@ -274,7 +273,7 @@ class ImageRepPNG : public ImageRep {
if (!size_cache_) {
for (std::vector<ImagePNGRep>::const_iterator it = image_reps().begin();
it != image_reps().end(); ++it) {
- if (it->scale_factor == ui::SCALE_FACTOR_100P) {
+ if (it->scale == 1.0f) {
size_cache_.reset(new gfx::Size(it->Size()));
return *size_cache_;
}
@@ -604,7 +603,7 @@ Image Image::CreateFrom1xPNGBytes(const unsigned char* input,
scoped_refptr<base::RefCountedBytes> raw_data(new base::RefCountedBytes());
raw_data->data().assign(input, input + input_size);
std::vector<gfx::ImagePNGRep> image_reps;
- image_reps.push_back(ImagePNGRep(raw_data, ui::SCALE_FACTOR_100P));
+ image_reps.push_back(ImagePNGRep(raw_data, 1.0f));
return gfx::Image(image_reps);
}
@@ -772,7 +771,7 @@ scoped_refptr<base::RefCountedMemory> Image::As1xPNGBytes() const {
const std::vector<gfx::ImagePNGRep>& image_png_reps =
rep->AsImageRepPNG()->image_reps();
for (size_t i = 0; i < image_png_reps.size(); ++i) {
- if (image_png_reps[i].scale_factor == ui::SCALE_FACTOR_100P)
+ if (image_png_reps[i].scale == 1.0f)
return image_png_reps[i].raw_data;
}
return new base::RefCountedBytes();
@@ -827,8 +826,7 @@ scoped_refptr<base::RefCountedMemory> Image::As1xPNGBytes() const {
// final type eg (converting from ImageRepSkia to ImageRepPNG to get an
// ImageRepCocoa).
std::vector<ImagePNGRep> image_png_reps;
- image_png_reps.push_back(gfx::ImagePNGRep(png_bytes,
- ui::SCALE_FACTOR_100P));
+ image_png_reps.push_back(gfx::ImagePNGRep(png_bytes, 1.0f));
rep = new internal::ImageRepPNG(image_png_reps);
AddRepresentation(rep);
return png_bytes;
diff --git a/chromium/ui/gfx/image/image.h b/chromium/ui/gfx/image/image.h
index 00b5baa194b..d4093b74063 100644
--- a/chromium/ui/gfx/image/image.h
+++ b/chromium/ui/gfx/image/image.h
@@ -53,7 +53,7 @@ class ImageRep;
class ImageStorage;
}
-class UI_EXPORT Image {
+class GFX_EXPORT Image {
public:
enum RepresentationType {
kImageRepGdk,
diff --git a/chromium/ui/gfx/image/image_family.cc b/chromium/ui/gfx/image/image_family.cc
index 4a43a92e01f..6719bc1ab18 100644
--- a/chromium/ui/gfx/image/image_family.cc
+++ b/chromium/ui/gfx/image/image_family.cc
@@ -21,6 +21,8 @@ ImageFamily::const_iterator::const_iterator(
const std::map<MapKey, gfx::Image>::const_iterator& other)
: map_iterator_(other) {}
+ImageFamily::const_iterator::~const_iterator() {}
+
ImageFamily::ImageFamily() {}
ImageFamily::~ImageFamily() {}
diff --git a/chromium/ui/gfx/image/image_family.h b/chromium/ui/gfx/image/image_family.h
index c7943713676..c092b2a87ca 100644
--- a/chromium/ui/gfx/image/image_family.h
+++ b/chromium/ui/gfx/image/image_family.h
@@ -25,7 +25,7 @@ class Size;
// size, with high-DPI bitmap versions; use an Image or ImageSkia for that. Each
// image in an ImageFamily should have a different logical size (and may also
// include high-DPI representations).
-class UI_EXPORT ImageFamily {
+class GFX_EXPORT ImageFamily {
private:
// An <aspect ratio, DIP width> pair.
// A 0x0 image has aspect ratio 1.0. 0xN and Nx0 images are treated as 0x0.
@@ -41,13 +41,15 @@ class UI_EXPORT ImageFamily {
public:
// Type for iterating over all images in the family, in order.
// Dereferencing this iterator returns a gfx::Image.
- class UI_EXPORT const_iterator :
+ class GFX_EXPORT const_iterator :
std::iterator<std::bidirectional_iterator_tag, const gfx::Image> {
public:
const_iterator();
const_iterator(const const_iterator& other);
+ ~const_iterator();
+
const_iterator& operator++() {
++map_iterator_;
return *this;
diff --git a/chromium/ui/gfx/image/image_ios.mm b/chromium/ui/gfx/image/image_ios.mm
index 01a3c87fbd2..126bfb491aa 100644
--- a/chromium/ui/gfx/image/image_ios.mm
+++ b/chromium/ui/gfx/image/image_ios.mm
@@ -11,7 +11,6 @@
#include "base/logging.h"
#include "base/mac/scoped_cftyperef.h"
#include "base/mac/scoped_nsobject.h"
-#include "ui/base/layout.h"
#include "ui/gfx/image/image_png_rep.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/gfx/image/image_skia_util_ios.h"
@@ -48,7 +47,7 @@ UIImage* CreateErrorUIImage(float scale) {
// Converts from ImagePNGRep to UIImage.
UIImage* CreateUIImageFromImagePNGRep(const gfx::ImagePNGRep& image_png_rep) {
- float scale = ui::GetScaleFactorScale(image_png_rep.scale_factor);
+ float scale = image_png_rep.scale;
scoped_refptr<base::RefCountedMemory> png = image_png_rep.raw_data;
CHECK(png.get());
NSData* data = [NSData dataWithBytes:png->front() length:png->size()];
@@ -74,17 +73,16 @@ scoped_refptr<base::RefCountedMemory> Get1xPNGBytesFromUIImage(
UIImage* CreateUIImageFromPNG(
const std::vector<gfx::ImagePNGRep>& image_png_reps) {
- ui::ScaleFactor ideal_scale_factor = ui::GetMaxScaleFactor();
- float ideal_scale = ui::GetScaleFactorScale(ideal_scale_factor);
+ float ideal_scale = ImageSkia::GetMaxSupportedScale();
if (image_png_reps.empty())
return CreateErrorUIImage(ideal_scale);
- // Find best match for |ideal_scale_factor|.
+ // Find best match for |ideal_scale|.
float smallest_diff = std::numeric_limits<float>::max();
size_t closest_index = 0u;
for (size_t i = 0; i < image_png_reps.size(); ++i) {
- float scale = ui::GetScaleFactorScale(image_png_reps[i].scale_factor);
+ float scale = image_png_reps[i].scale;
float diff = std::abs(ideal_scale - scale);
if (diff < smallest_diff) {
smallest_diff = diff;
@@ -102,9 +100,8 @@ scoped_refptr<base::RefCountedMemory> Get1xPNGBytesFromImageSkia(
// TODO(rohitrao): Rewrite the callers of this function to save the UIImage
// representation in the gfx::Image. If we're generating it, we might as well
// hold on to it.
- const gfx::ImageSkiaRep& image_skia_rep = skia->GetRepresentation(
- ui::SCALE_FACTOR_100P);
- if (image_skia_rep.scale_factor() != ui::SCALE_FACTOR_100P)
+ const gfx::ImageSkiaRep& image_skia_rep = skia->GetRepresentation(1.0f);
+ if (image_skia_rep.scale() != 1.0f)
return NULL;
UIImage* image = UIImageFromImageSkiaRep(image_skia_rep);
@@ -119,8 +116,8 @@ ImageSkia* ImageSkiaFromPNG(
for (size_t i = 0; i < image_png_reps.size(); ++i) {
base::scoped_nsobject<UIImage> uiimage(
CreateUIImageFromImagePNGRep(image_png_reps[i]));
- gfx::ImageSkiaRep image_skia_rep = ImageSkiaRepOfScaleFactorFromUIImage(
- uiimage, image_png_reps[i].scale_factor);
+ gfx::ImageSkiaRep image_skia_rep = ImageSkiaRepOfScaleFromUIImage(
+ uiimage, image_png_reps[i].scale);
if (!image_skia_rep.is_null())
image_skia->AddRepresentation(image_skia_rep);
}
diff --git a/chromium/ui/gfx/image/image_mac.mm b/chromium/ui/gfx/image/image_mac.mm
index d03b48e0f4b..15a56108342 100644
--- a/chromium/ui/gfx/image/image_mac.mm
+++ b/chromium/ui/gfx/image/image_mac.mm
@@ -65,7 +65,7 @@ NSImage* NSImageFromPNG(const std::vector<gfx::ImagePNGRep>& image_png_reps,
[[NSBitmapImageRep alloc] initWithData:ns_data]);
if (!ns_image_rep) {
LOG(ERROR) << "Unable to decode PNG at "
- << ui::GetScaleFactorScale(image_png_reps[i].scale_factor)
+ << image_png_reps[i].scale
<< ".";
return GetErrorNSImage();
}
@@ -88,7 +88,7 @@ NSImage* NSImageFromPNG(const std::vector<gfx::ImagePNGRep>& image_png_reps,
}
if (!image.get()) {
- float scale = ui::GetScaleFactorScale(image_png_reps[i].scale_factor);
+ float scale = image_png_reps[i].scale;
NSSize image_size = NSMakeSize([ns_image_rep pixelsWide] / scale,
[ns_image_rep pixelsHigh] / scale);
image.reset([[NSImage alloc] initWithSize:image_size]);
diff --git a/chromium/ui/gfx/image/image_mac_unittest.mm b/chromium/ui/gfx/image/image_mac_unittest.mm
index 250deeb5249..2cbbd117a97 100644
--- a/chromium/ui/gfx/image/image_mac_unittest.mm
+++ b/chromium/ui/gfx/image/image_mac_unittest.mm
@@ -16,26 +16,26 @@
namespace {
// Returns true if the structure of |ns_image| matches the structure
-// described by |width|, |height|, and |scale_factors|.
+// described by |width|, |height|, and |scales|.
// The structure matches if:
// - |ns_image| is not nil.
-// - |ns_image| has NSImageReps of |scale_factors|.
+// - |ns_image| has NSImageReps of |scales|.
// - Each of the NSImageReps has a pixel size of [|ns_image| size] *
-// scale_factor.
+// scale.
bool NSImageStructureMatches(
NSImage* ns_image,
int width,
int height,
- const std::vector<ui::ScaleFactor>& scale_factors) {
+ const std::vector<float>& scales) {
if (!ns_image ||
[ns_image size].width != width ||
[ns_image size].height != height ||
- [ns_image representations].count != scale_factors.size()) {
+ [ns_image representations].count != scales.size()) {
return false;
}
- for (size_t i = 0; i < scale_factors.size(); ++i) {
- float scale = ui::GetScaleFactorScale(scale_factors[i]);
+ for (size_t i = 0; i < scales.size(); ++i) {
+ float scale = scales[i];
bool found_match = false;
for (size_t j = 0; j < [ns_image representations].count; ++j) {
NSImageRep* ns_image_rep = [[ns_image representations] objectAtIndex:j];
@@ -74,16 +74,14 @@ void BitmapImageRep(int width, int height,
class ImageMacTest : public testing::Test {
public:
- ImageMacTest()
- : supported_scale_factors_(gfx::test::Get1xAnd2xScaleFactors()) {
+ ImageMacTest() {
+ gfx::ImageSkia::SetSupportedScales(gfx::test::Get1xAnd2xScales());
}
virtual ~ImageMacTest() {
}
private:
- ui::test::ScopedSetSupportedScaleFactors supported_scale_factors_;
-
DISALLOW_COPY_AND_ASSIGN(ImageMacTest);
};
@@ -110,11 +108,11 @@ TEST_F(ImageMacTest, MultiResolutionNSImageToImageSkia) {
const gfx::ImageSkia* image_skia = image.ToImageSkia();
- std::vector<ui::ScaleFactor> scale_factors;
- scale_factors.push_back(ui::SCALE_FACTOR_100P);
- scale_factors.push_back(ui::SCALE_FACTOR_200P);
+ std::vector<float> scales;
+ scales.push_back(1.0f);
+ scales.push_back(2.0f);
EXPECT_TRUE(gt::ImageSkiaStructureMatches(*image_skia, kWidth1x, kHeight1x,
- scale_factors));
+ scales));
// ToImageSkia should create a second representation.
EXPECT_EQ(2u, image.RepresentationCount());
@@ -141,11 +139,11 @@ TEST_F(ImageMacTest, UnalignedMultiResolutionNSImageToImageSkia) {
const gfx::ImageSkia* image_skia = image.ToImageSkia();
- std::vector<ui::ScaleFactor> scale_factors;
- scale_factors.push_back(ui::SCALE_FACTOR_100P);
- scale_factors.push_back(ui::SCALE_FACTOR_200P);
+ std::vector<float> scales;
+ scales.push_back(1.0f);
+ scales.push_back(2.0f);
EXPECT_TRUE(gt::ImageSkiaStructureMatches(*image_skia, kWidth1x, kHeight1x,
- scale_factors));
+ scales));
// ToImageSkia should create a second representation.
EXPECT_EQ(2u, image.RepresentationCount());
@@ -159,9 +157,9 @@ TEST_F(ImageMacTest, MultiResolutionImageSkiaToNSImage) {
gfx::ImageSkia image_skia;
image_skia.AddRepresentation(gfx::ImageSkiaRep(
- gt::CreateBitmap(kWidth1x, kHeight1x), ui::SCALE_FACTOR_100P));
+ gt::CreateBitmap(kWidth1x, kHeight1x), 1.0f));
image_skia.AddRepresentation(gfx::ImageSkiaRep(
- gt::CreateBitmap(kWidth2x, kHeight2x), ui::SCALE_FACTOR_200P));
+ gt::CreateBitmap(kWidth2x, kHeight2x), 2.0f));
gfx::Image image(image_skia);
@@ -170,11 +168,10 @@ TEST_F(ImageMacTest, MultiResolutionImageSkiaToNSImage) {
NSImage* ns_image = image.ToNSImage();
- std::vector<ui::ScaleFactor> scale_factors;
- scale_factors.push_back(ui::SCALE_FACTOR_100P);
- scale_factors.push_back(ui::SCALE_FACTOR_200P);
- EXPECT_TRUE(NSImageStructureMatches(ns_image, kWidth1x, kHeight1x,
- scale_factors));
+ std::vector<float> scales;
+ scales.push_back(1.0f);
+ scales.push_back(2.0f);
+ EXPECT_TRUE(NSImageStructureMatches(ns_image, kWidth1x, kHeight1x, scales));
// Request for NSImage* should create a second representation.
EXPECT_EQ(2u, image.RepresentationCount());
@@ -187,17 +184,16 @@ TEST_F(ImageMacTest, MultiResolutionPNGToNSImage) {
scoped_refptr<base::RefCountedMemory> bytes1x = gt::CreatePNGBytes(kSize1x);
scoped_refptr<base::RefCountedMemory> bytes2x = gt::CreatePNGBytes(kSize2x);
std::vector<gfx::ImagePNGRep> image_png_reps;
- image_png_reps.push_back(gfx::ImagePNGRep(bytes1x, ui::SCALE_FACTOR_100P));
- image_png_reps.push_back(gfx::ImagePNGRep(bytes2x, ui::SCALE_FACTOR_200P));
+ image_png_reps.push_back(gfx::ImagePNGRep(bytes1x, 1.0f));
+ image_png_reps.push_back(gfx::ImagePNGRep(bytes2x, 2.0f));
gfx::Image image(image_png_reps);
NSImage* ns_image = image.ToNSImage();
- std::vector<ui::ScaleFactor> scale_factors;
- scale_factors.push_back(ui::SCALE_FACTOR_100P);
- scale_factors.push_back(ui::SCALE_FACTOR_200P);
- EXPECT_TRUE(NSImageStructureMatches(ns_image, kSize1x, kSize1x,
- scale_factors));
+ std::vector<float> scales;
+ scales.push_back(1.0f);
+ scales.push_back(2.0f);
+ EXPECT_TRUE(NSImageStructureMatches(ns_image, kSize1x, kSize1x, scales));
// Converting from PNG to NSImage should not go through ImageSkia.
EXPECT_FALSE(image.HasRepresentation(gfx::Image::kImageRepSkia));
@@ -205,9 +201,9 @@ TEST_F(ImageMacTest, MultiResolutionPNGToNSImage) {
// Convert to ImageSkia to check pixel contents of NSImageReps.
gfx::ImageSkia image_skia = gfx::ImageSkiaFromNSImage(ns_image);
EXPECT_TRUE(gt::IsEqual(bytes1x,
- image_skia.GetRepresentation(ui::SCALE_FACTOR_100P).sk_bitmap()));
+ image_skia.GetRepresentation(1.0f).sk_bitmap()));
EXPECT_TRUE(gt::IsEqual(bytes2x,
- image_skia.GetRepresentation(ui::SCALE_FACTOR_200P).sk_bitmap()));
+ image_skia.GetRepresentation(2.0f).sk_bitmap()));
}
} // namespace
diff --git a/chromium/ui/gfx/image/image_png_rep.cc b/chromium/ui/gfx/image/image_png_rep.cc
index 253a5291afd..3970d2bcc02 100644
--- a/chromium/ui/gfx/image/image_png_rep.cc
+++ b/chromium/ui/gfx/image/image_png_rep.cc
@@ -4,6 +4,7 @@
#include "ui/gfx/image/image_png_rep.h"
+#include "base/logging.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/codec/png_codec.h"
#include "ui/gfx/size.h"
@@ -12,13 +13,13 @@ namespace gfx {
ImagePNGRep::ImagePNGRep()
: raw_data(NULL),
- scale_factor(ui::SCALE_FACTOR_NONE) {
+ scale(1.0) {
}
ImagePNGRep::ImagePNGRep(const scoped_refptr<base::RefCountedMemory>& data,
- ui::ScaleFactor data_scale_factor)
+ float data_scale)
: raw_data(data),
- scale_factor(data_scale_factor) {
+ scale(data_scale) {
}
ImagePNGRep::~ImagePNGRep() {
diff --git a/chromium/ui/gfx/image/image_png_rep.h b/chromium/ui/gfx/image/image_png_rep.h
index 7e5ce5b4e41..5c26134fa73 100644
--- a/chromium/ui/gfx/image/image_png_rep.h
+++ b/chromium/ui/gfx/image/image_png_rep.h
@@ -6,7 +6,6 @@
#define UI_GFX_IMAGE_IMAGE_PNG_REP_H_
#include "base/memory/ref_counted_memory.h"
-#include "ui/base/layout.h"
#include "ui/gfx/gfx_export.h"
namespace gfx {
@@ -14,10 +13,11 @@ class Size;
// An ImagePNGRep represents a bitmap's png encoded data and the scale factor it
// was intended for.
-struct UI_EXPORT ImagePNGRep {
+struct GFX_EXPORT ImagePNGRep {
+ public:
ImagePNGRep();
ImagePNGRep(const scoped_refptr<base::RefCountedMemory>& data,
- ui::ScaleFactor data_scale_factor);
+ float data_scale);
~ImagePNGRep();
// Width and height of the image, in pixels.
@@ -27,7 +27,7 @@ struct UI_EXPORT ImagePNGRep {
gfx::Size Size() const;
scoped_refptr<base::RefCountedMemory> raw_data;
- ui::ScaleFactor scale_factor;
+ float scale;
};
} // namespace gfx
diff --git a/chromium/ui/gfx/image/image_skia.cc b/chromium/ui/gfx/image/image_skia.cc
index 1ae9874ad4d..a283117db24 100644
--- a/chromium/ui/gfx/image/image_skia.cc
+++ b/chromium/ui/gfx/image/image_skia.cc
@@ -26,6 +26,7 @@ gfx::ImageSkiaRep& NullImageRep() {
return null_image_rep;
}
+std::vector<float>* g_supported_scales = NULL;
} // namespace
namespace internal {
@@ -33,15 +34,15 @@ namespace {
class Matcher {
public:
- explicit Matcher(ui::ScaleFactor scale_factor) : scale_factor_(scale_factor) {
+ explicit Matcher(float scale) : scale_(scale) {
}
bool operator()(const ImageSkiaRep& rep) const {
- return rep.scale_factor() == scale_factor_;
+ return rep.scale() == scale_;
}
private:
- ui::ScaleFactor scale_factor_;
+ float scale_;
};
} // namespace
@@ -61,11 +62,10 @@ class ImageSkiaStorage : public base::RefCountedThreadSafe<ImageSkiaStorage>,
read_only_(false) {
}
- ImageSkiaStorage(ImageSkiaSource* source, ui::ScaleFactor scale_factor)
+ ImageSkiaStorage(ImageSkiaSource* source, float scale)
: source_(source),
read_only_(false) {
- ImageSkia::ImageSkiaReps::iterator it =
- FindRepresentation(scale_factor, true);
+ ImageSkia::ImageSkiaReps::iterator it = FindRepresentation(scale, true);
if (it == image_reps_.end() || it->is_null())
source_.reset();
else
@@ -103,16 +103,15 @@ class ImageSkiaStorage : public base::RefCountedThreadSafe<ImageSkiaStorage>,
}
// Returns the iterator of the image rep whose density best matches
- // |scale_factor|. If the image for the |scale_factor| doesn't exist
- // in the storage and |storage| is set, it fetches new image by calling
- // |ImageSkiaSource::GetImageForScale|. If the source returns the
- // image with different scale factor (if the image doesn't exist in
- // resource, for example), it will fallback to closest image rep.
+ // |scale|. If the image for the |scale| doesn't exist in the storage and
+ // |storage| is set, it fetches new image by calling
+ // |ImageSkiaSource::GetImageForScale|. If the source returns the image with
+ // different scale (if the image doesn't exist in resource, for example), it
+ // will fallback to closest image rep.
std::vector<ImageSkiaRep>::iterator FindRepresentation(
- ui::ScaleFactor scale_factor, bool fetch_new_image) const {
+ float scale, bool fetch_new_image) const {
ImageSkiaStorage* non_const = const_cast<ImageSkiaStorage*>(this);
- float scale = ui::GetScaleFactorScale(scale_factor);
ImageSkia::ImageSkiaReps::iterator closest_iter =
non_const->image_reps().end();
ImageSkia::ImageSkiaReps::iterator exact_iter =
@@ -121,7 +120,7 @@ class ImageSkiaStorage : public base::RefCountedThreadSafe<ImageSkiaStorage>,
for (ImageSkia::ImageSkiaReps::iterator it =
non_const->image_reps().begin();
it < image_reps_.end(); ++it) {
- if (it->GetScale() == scale) {
+ if (it->scale() == scale) {
// found exact match
fetch_new_image = false;
if (it->is_null())
@@ -129,7 +128,7 @@ class ImageSkiaStorage : public base::RefCountedThreadSafe<ImageSkiaStorage>,
exact_iter = it;
break;
}
- float diff = std::abs(it->GetScale() - scale);
+ float diff = std::abs(it->scale() - scale);
if (diff < smallest_diff && !it->is_null()) {
closest_iter = it;
smallest_diff = diff;
@@ -140,25 +139,24 @@ class ImageSkiaStorage : public base::RefCountedThreadSafe<ImageSkiaStorage>,
DCHECK(CalledOnValidThread()) <<
"An ImageSkia with the source must be accessed by the same thread.";
- ImageSkiaRep image = source_->GetImageForScale(scale_factor);
+ ImageSkiaRep image = source_->GetImageForScale(scale);
// If the source returned the new image, store it.
if (!image.is_null() &&
std::find_if(image_reps_.begin(), image_reps_.end(),
- Matcher(image.scale_factor())) == image_reps_.end()) {
+ Matcher(image.scale())) == image_reps_.end()) {
non_const->image_reps().push_back(image);
}
- // If the result image's scale factor isn't same as the expected
- // scale factor, create null ImageSkiaRep with the |scale_factor|
- // so that the next lookup will fallback to the closest scale.
- if (image.is_null() || image.scale_factor() != scale_factor) {
- non_const->image_reps().push_back(
- ImageSkiaRep(SkBitmap(), scale_factor));
+ // If the result image's scale isn't same as the expected scale, create
+ // null ImageSkiaRep with the |scale| so that the next lookup will
+ // fallback to the closest scale.
+ if (image.is_null() || image.scale() != scale) {
+ non_const->image_reps().push_back(ImageSkiaRep(SkBitmap(), scale));
}
// image_reps_ must have the exact much now, so find again.
- return FindRepresentation(scale_factor, false);
+ return FindRepresentation(scale, false);
}
return exact_iter != image_reps_.end() ? exact_iter : closest_iter;
}
@@ -170,7 +168,7 @@ class ImageSkiaStorage : public base::RefCountedThreadSafe<ImageSkiaStorage>,
DetachFromThread();
}
- // Vector of bitmaps and their associated scale factor.
+ // Vector of bitmaps and their associated scale.
std::vector<gfx::ImageSkiaRep> image_reps_;
scoped_ptr<ImageSkiaSource> source_;
@@ -195,8 +193,8 @@ ImageSkia::ImageSkia(ImageSkiaSource* source, const gfx::Size& size)
DetachStorageFromThread();
}
-ImageSkia::ImageSkia(ImageSkiaSource* source, ui::ScaleFactor scale_factor)
- : storage_(new internal::ImageSkiaStorage(source, scale_factor)) {
+ImageSkia::ImageSkia(ImageSkiaSource* source, float scale)
+ : storage_(new internal::ImageSkiaStorage(source, scale)) {
DCHECK(source);
if (!storage_->has_source())
storage_ = NULL;
@@ -222,8 +220,27 @@ ImageSkia::~ImageSkia() {
}
// static
+void ImageSkia::SetSupportedScales(const std::vector<float>& supported_scales) {
+ if (g_supported_scales != NULL)
+ delete g_supported_scales;
+ g_supported_scales = new std::vector<float>(supported_scales);
+ std::sort(g_supported_scales->begin(), g_supported_scales->end());
+}
+
+// static
+const std::vector<float>& ImageSkia::GetSupportedScales() {
+ DCHECK(g_supported_scales != NULL);
+ return *g_supported_scales;
+}
+
+// static
+float ImageSkia::GetMaxSupportedScale() {
+ return g_supported_scales->back();
+}
+
+// static
ImageSkia ImageSkia::CreateFrom1xBitmap(const SkBitmap& bitmap) {
- return ImageSkia(ImageSkiaRep(bitmap, ui::SCALE_FACTOR_100P));
+ return ImageSkia(ImageSkiaRep(bitmap, 1.0f));
}
scoped_ptr<ImageSkia> ImageSkia::DeepCopy() const {
@@ -254,10 +271,9 @@ void ImageSkia::AddRepresentation(const ImageSkiaRep& image_rep) {
// TODO(oshima): This method should be called |SetRepresentation|
// and replace the existing rep if there is already one with the
- // same scale factor so that we can guarantee that a ImageSkia
- // instance contians only one image rep per scale factor. This is
- // not possible now as ImageLoader currently stores need
- // this feature, but this needs to be fixed.
+ // same scale so that we can guarantee that a ImageSkia instance contains only
+ // one image rep per scale. This is not possible now as ImageLoader currently
+ // stores need this feature, but this needs to be fixed.
if (isNull()) {
Init(image_rep);
} else {
@@ -266,37 +282,34 @@ void ImageSkia::AddRepresentation(const ImageSkiaRep& image_rep) {
}
}
-void ImageSkia::RemoveRepresentation(ui::ScaleFactor scale_factor) {
+void ImageSkia::RemoveRepresentation(float scale) {
if (isNull())
return;
CHECK(CanModify());
ImageSkiaReps& image_reps = storage_->image_reps();
ImageSkiaReps::iterator it =
- storage_->FindRepresentation(scale_factor, false);
- if (it != image_reps.end() && it->scale_factor() == scale_factor)
+ storage_->FindRepresentation(scale, false);
+ if (it != image_reps.end() && it->scale() == scale)
image_reps.erase(it);
}
-bool ImageSkia::HasRepresentation(ui::ScaleFactor scale_factor) const {
+bool ImageSkia::HasRepresentation(float scale) const {
if (isNull())
return false;
CHECK(CanRead());
- ImageSkiaReps::iterator it =
- storage_->FindRepresentation(scale_factor, false);
- return (it != storage_->image_reps().end() &&
- it->scale_factor() == scale_factor);
+ ImageSkiaReps::iterator it = storage_->FindRepresentation(scale, false);
+ return (it != storage_->image_reps().end() && it->scale() == scale);
}
-const ImageSkiaRep& ImageSkia::GetRepresentation(
- ui::ScaleFactor scale_factor) const {
+const ImageSkiaRep& ImageSkia::GetRepresentation(float scale) const {
if (isNull())
return NullImageRep();
CHECK(CanRead());
- ImageSkiaReps::iterator it = storage_->FindRepresentation(scale_factor, true);
+ ImageSkiaReps::iterator it = storage_->FindRepresentation(scale, true);
if (it == storage_->image_reps().end())
return NullImageRep();
@@ -311,7 +324,7 @@ void ImageSkia::SetReadOnly() {
void ImageSkia::MakeThreadSafe() {
CHECK(storage_.get());
- EnsureRepsForSupportedScaleFactors();
+ EnsureRepsForSupportedScales();
// Delete source as we no longer needs it.
if (storage_.get())
storage_->DeleteSource();
@@ -354,15 +367,15 @@ std::vector<ImageSkiaRep> ImageSkia::image_reps() const {
return image_reps;
}
-void ImageSkia::EnsureRepsForSupportedScaleFactors() const {
+void ImageSkia::EnsureRepsForSupportedScales() const {
+ DCHECK(g_supported_scales != NULL);
// Don't check ReadOnly because the source may generate images
// even for read only ImageSkia. Concurrent access will be protected
// by |DCHECK(CalledOnValidThread())| in FindRepresentation.
if (storage_.get() && storage_->has_source()) {
- std::vector<ui::ScaleFactor> supported_scale_factors =
- ui::GetSupportedScaleFactors();
- for (size_t i = 0; i < supported_scale_factors.size(); ++i)
- storage_->FindRepresentation(supported_scale_factors[i], true);
+ for (std::vector<float>::const_iterator it = g_supported_scales->begin();
+ it != g_supported_scales->end(); ++it)
+ storage_->FindRepresentation(*it, true);
}
}
@@ -390,8 +403,7 @@ SkBitmap& ImageSkia::GetBitmap() const {
CHECK(CanRead());
#endif
- ImageSkiaReps::iterator it =
- storage_->FindRepresentation(ui::SCALE_FACTOR_100P, true);
+ ImageSkiaReps::iterator it = storage_->FindRepresentation(1.0f, true);
if (it != storage_->image_reps().end())
return it->mutable_sk_bitmap();
return NullImageRep().mutable_sk_bitmap();
diff --git a/chromium/ui/gfx/image/image_skia.h b/chromium/ui/gfx/image/image_skia.h
index 4bc21f877cd..fa5d070ad9b 100644
--- a/chromium/ui/gfx/image/image_skia.h
+++ b/chromium/ui/gfx/image/image_skia.h
@@ -34,7 +34,7 @@ class TestOnThread;
// returned from ImageSkia::GetRepresentation, not on ImageSkia.
//
// ImageSkia is cheap to copy and intentionally supports copy semantics.
-class UI_EXPORT ImageSkia {
+class GFX_EXPORT ImageSkia {
public:
typedef std::vector<ImageSkiaRep> ImageSkiaReps;
@@ -47,9 +47,9 @@ class UI_EXPORT ImageSkia {
ImageSkia(ImageSkiaSource* source, const gfx::Size& size);
// Creates an instance that uses the |source|. The constructor loads the image
- // at |scale_factor| and uses its dimensions to calculate the size in DIP.
- // ImageSkia owns |source|.
- ImageSkia(ImageSkiaSource* source, ui::ScaleFactor scale_factor);
+ // at |scale| and uses its dimensions to calculate the size in DIP. ImageSkia
+ // owns |source|.
+ ImageSkia(ImageSkiaSource* source, float scale);
explicit ImageSkia(const gfx::ImageSkiaRep& image_rep);
@@ -61,6 +61,16 @@ class UI_EXPORT ImageSkia {
~ImageSkia();
+ // Changes the value of GetSupportedScales() to |scales|.
+ static void SetSupportedScales(const std::vector<float>& scales);
+
+ // Returns a vector with the scale factors which are supported by this
+ // platform, in ascending order.
+ static const std::vector<float>& GetSupportedScales();
+
+ // Returns the maximum scale supported by this platform.
+ static float GetMaxSupportedScale();
+
// Creates an image from the passed in bitmap.
// DIP width and height are based on scale factor of 1x.
// Adds ref to passed in bitmap.
@@ -74,7 +84,7 @@ class UI_EXPORT ImageSkia {
// Note that this does NOT generate ImageSkiaReps from its source.
// If you want to create a deep copy with ImageSkiaReps for supported
// scale factors, you need to explicitly call
- // |EnsureRepsForSupportedScaleFactors()| first.
+ // |EnsureRepsForSupportedScales()| first.
scoped_ptr<ImageSkia> DeepCopy() const;
// Returns true if this object is backed by the same ImageSkiaStorage as
@@ -84,18 +94,16 @@ class UI_EXPORT ImageSkia {
// Adds |image_rep| to the image reps contained by this object.
void AddRepresentation(const gfx::ImageSkiaRep& image_rep);
- // Removes the image rep of |scale_factor| if present.
- void RemoveRepresentation(ui::ScaleFactor scale_factor);
+ // Removes the image rep of |scale| if present.
+ void RemoveRepresentation(float scale);
// Returns true if the object owns an image rep whose density matches
- // |scale_factor| exactly.
- bool HasRepresentation(ui::ScaleFactor scale_factor) const;
+ // |scale| exactly.
+ bool HasRepresentation(float scale) const;
- // Returns the image rep whose density best matches
- // |scale_factor|.
+ // Returns the image rep whose density best matches |scale|.
// Returns a null image rep if the object contains no image reps.
- const gfx::ImageSkiaRep& GetRepresentation(
- ui::ScaleFactor scale_factor) const;
+ const gfx::ImageSkiaRep& GetRepresentation(float scale) const;
// Make the ImageSkia instance read-only. Note that this only prevent
// modification from client code, and the storage may still be
@@ -136,7 +144,7 @@ class UI_EXPORT ImageSkia {
// When the source is available, generates all ImageReps for
// supported scale factors. This method is defined as const as
// the state change in the storage is agnostic to the caller.
- void EnsureRepsForSupportedScaleFactors() const;
+ void EnsureRepsForSupportedScales() const;
private:
friend class test::TestOnThread;
diff --git a/chromium/ui/gfx/image/image_skia_operations.cc b/chromium/ui/gfx/image/image_skia_operations.cc
index 663156044d4..6953b59301f 100644
--- a/chromium/ui/gfx/image/image_skia_operations.cc
+++ b/chromium/ui/gfx/image/image_skia_operations.cc
@@ -7,7 +7,6 @@
#include "base/command_line.h"
#include "base/logging.h"
#include "skia/ext/image_operations.h"
-#include "ui/base/layout.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/image/canvas_image_source.h"
#include "ui/gfx/image/image_skia.h"
@@ -37,14 +36,13 @@ gfx::Rect DIPToPixelBounds(gfx::Rect dip_bounds, float scale) {
// Returns an image rep for the ImageSkiaSource to return to visually indicate
// an error.
-ImageSkiaRep GetErrorImageRep(ui::ScaleFactor scale_factor,
- const gfx::Size& pixel_size) {
+ImageSkiaRep GetErrorImageRep(float scale, const gfx::Size& pixel_size) {
SkBitmap bitmap;
bitmap.setConfig(
SkBitmap::kARGB_8888_Config, pixel_size.width(), pixel_size.height());
bitmap.allocPixels();
bitmap.eraseColor(SK_ColorRED);
- return gfx::ImageSkiaRep(bitmap, scale_factor);
+ return gfx::ImageSkiaRep(bitmap, scale);
}
// A base image source class that creates an image from two source images.
@@ -62,27 +60,25 @@ class BinaryImageSource : public gfx::ImageSkiaSource {
}
// gfx::ImageSkiaSource overrides:
- virtual ImageSkiaRep GetImageForScale(ui::ScaleFactor scale_factor) OVERRIDE {
- ImageSkiaRep first_rep = first_.GetRepresentation(scale_factor);
- ImageSkiaRep second_rep = second_.GetRepresentation(scale_factor);
+ virtual ImageSkiaRep GetImageForScale(float scale) OVERRIDE {
+ ImageSkiaRep first_rep = first_.GetRepresentation(scale);
+ ImageSkiaRep second_rep = second_.GetRepresentation(scale);
if (first_rep.pixel_size() != second_rep.pixel_size()) {
- DCHECK_NE(first_rep.scale_factor(), second_rep.scale_factor());
- if (first_rep.scale_factor() == second_rep.scale_factor()) {
+ DCHECK_NE(first_rep.scale(), second_rep.scale());
+ if (first_rep.scale() == second_rep.scale()) {
LOG(ERROR) << "ImageSkiaRep size mismatch in " << source_name_;
- return GetErrorImageRep(first_rep.scale_factor(),
- first_rep.pixel_size());
+ return GetErrorImageRep(first_rep.scale(),first_rep.pixel_size());
}
- first_rep = first_.GetRepresentation(ui::SCALE_FACTOR_100P);
- second_rep = second_.GetRepresentation(ui::SCALE_FACTOR_100P);
+ first_rep = first_.GetRepresentation(1.0f);
+ second_rep = second_.GetRepresentation(1.0f);
DCHECK_EQ(first_rep.pixel_width(), second_rep.pixel_width());
DCHECK_EQ(first_rep.pixel_height(), second_rep.pixel_height());
if (first_rep.pixel_size() != second_rep.pixel_size()) {
LOG(ERROR) << "ImageSkiaRep size mismatch in " << source_name_;
- return GetErrorImageRep(first_rep.scale_factor(),
- first_rep.pixel_size());
+ return GetErrorImageRep(first_rep.scale(), first_rep.pixel_size());
}
} else {
- DCHECK_EQ(first_rep.scale_factor(), second_rep.scale_factor());
+ DCHECK_EQ(first_rep.scale(), second_rep.scale());
}
return CreateImageSkiaRep(first_rep, second_rep);
}
@@ -121,7 +117,7 @@ class BlendingImageSource : public BinaryImageSource {
const ImageSkiaRep& second_rep) const OVERRIDE {
SkBitmap blended = SkBitmapOperations::CreateBlendedBitmap(
first_rep.sk_bitmap(), second_rep.sk_bitmap(), alpha_);
- return ImageSkiaRep(blended, first_rep.scale_factor());
+ return ImageSkiaRep(blended, first_rep.scale());
}
private:
@@ -167,8 +163,8 @@ class TransparentImageSource : public gfx::ImageSkiaSource {
private:
// gfx::ImageSkiaSource overrides:
- virtual ImageSkiaRep GetImageForScale(ui::ScaleFactor scale_factor) OVERRIDE {
- ImageSkiaRep image_rep = image_.GetRepresentation(scale_factor);
+ virtual ImageSkiaRep GetImageForScale(float scale) OVERRIDE {
+ ImageSkiaRep image_rep = image_.GetRepresentation(scale);
SkBitmap alpha;
alpha.setConfig(SkBitmap::kARGB_8888_Config,
image_rep.pixel_width(),
@@ -177,7 +173,7 @@ class TransparentImageSource : public gfx::ImageSkiaSource {
alpha.eraseColor(SkColorSetARGB(alpha_ * 255, 0, 0, 0));
return ImageSkiaRep(
SkBitmapOperations::CreateMaskedBitmap(image_rep.sk_bitmap(), alpha),
- image_rep.scale_factor());
+ image_rep.scale());
}
ImageSkia image_;
@@ -201,7 +197,7 @@ class MaskedImageSource : public BinaryImageSource {
const ImageSkiaRep& second_rep) const OVERRIDE {
return ImageSkiaRep(SkBitmapOperations::CreateMaskedBitmap(
first_rep.sk_bitmap(), second_rep.sk_bitmap()),
- first_rep.scale_factor());
+ first_rep.scale());
}
private:
@@ -224,16 +220,15 @@ class TiledImageSource : public gfx::ImageSkiaSource {
}
// gfx::ImageSkiaSource overrides:
- virtual ImageSkiaRep GetImageForScale(ui::ScaleFactor scale_factor) OVERRIDE {
- ImageSkiaRep source_rep = source_.GetRepresentation(scale_factor);
- float scale = ui::GetScaleFactorScale(source_rep.scale_factor());
+ virtual ImageSkiaRep GetImageForScale(float scale) OVERRIDE {
+ ImageSkiaRep source_rep = source_.GetRepresentation(scale);
gfx::Rect bounds = DIPToPixelBounds(gfx::Rect(src_x_, src_y_, dst_w_,
- dst_h_), scale);
+ dst_h_), source_rep.scale());
return ImageSkiaRep(
SkBitmapOperations::CreateTiledBitmap(
source_rep.sk_bitmap(),
bounds.x(), bounds.y(), bounds.width(), bounds.height()),
- source_rep.scale_factor());
+ source_rep.scale());
}
private:
@@ -258,11 +253,11 @@ class HSLImageSource : public gfx::ImageSkiaSource {
}
// gfx::ImageSkiaSource overrides:
- virtual ImageSkiaRep GetImageForScale(ui::ScaleFactor scale_factor) OVERRIDE {
- ImageSkiaRep image_rep = image_.GetRepresentation(scale_factor);
+ virtual ImageSkiaRep GetImageForScale(float scale) OVERRIDE {
+ ImageSkiaRep image_rep = image_.GetRepresentation(scale);
return gfx::ImageSkiaRep(
SkBitmapOperations::CreateHSLShiftedBitmap(image_rep.sk_bitmap(),
- hsl_shift_), image_rep.scale_factor());
+ hsl_shift_), image_rep.scale());
}
private:
@@ -288,17 +283,17 @@ class ButtonImageSource: public gfx::ImageSkiaSource {
}
// gfx::ImageSkiaSource overrides:
- virtual ImageSkiaRep GetImageForScale(ui::ScaleFactor scale_factor) OVERRIDE {
- ImageSkiaRep image_rep = image_.GetRepresentation(scale_factor);
- ImageSkiaRep mask_rep = mask_.GetRepresentation(scale_factor);
- if (image_rep.scale_factor() != mask_rep.scale_factor()) {
- image_rep = image_.GetRepresentation(ui::SCALE_FACTOR_100P);
- mask_rep = mask_.GetRepresentation(ui::SCALE_FACTOR_100P);
+ virtual ImageSkiaRep GetImageForScale(float scale) OVERRIDE {
+ ImageSkiaRep image_rep = image_.GetRepresentation(scale);
+ ImageSkiaRep mask_rep = mask_.GetRepresentation(scale);
+ if (image_rep.scale() != mask_rep.scale()) {
+ image_rep = image_.GetRepresentation(1.0f);
+ mask_rep = mask_.GetRepresentation(1.0f);
}
return gfx::ImageSkiaRep(
SkBitmapOperations::CreateButtonBackground(color_,
image_rep.sk_bitmap(), mask_rep.sk_bitmap()),
- image_rep.scale_factor());
+ image_rep.scale());
}
private:
@@ -323,16 +318,15 @@ class ExtractSubsetImageSource: public gfx::ImageSkiaSource {
}
// gfx::ImageSkiaSource overrides:
- virtual ImageSkiaRep GetImageForScale(ui::ScaleFactor scale_factor) OVERRIDE {
- ImageSkiaRep image_rep = image_.GetRepresentation(scale_factor);
- float scale_to_pixel = ui::GetScaleFactorScale(image_rep.scale_factor());
+ virtual ImageSkiaRep GetImageForScale(float scale) OVERRIDE {
+ ImageSkiaRep image_rep = image_.GetRepresentation(scale);
SkIRect subset_bounds_in_pixel = RectToSkIRect(
- DIPToPixelBounds(subset_bounds_, scale_to_pixel));
+ DIPToPixelBounds(subset_bounds_, image_rep.scale()));
SkBitmap dst;
bool success = image_rep.sk_bitmap().extractSubset(&dst,
subset_bounds_in_pixel);
DCHECK(success);
- return gfx::ImageSkiaRep(dst, image_rep.scale_factor());
+ return gfx::ImageSkiaRep(dst, image_rep.scale());
}
private:
@@ -356,20 +350,19 @@ class ResizeSource : public ImageSkiaSource {
virtual ~ResizeSource() {}
// gfx::ImageSkiaSource overrides:
- virtual ImageSkiaRep GetImageForScale(ui::ScaleFactor scale_factor) OVERRIDE {
- const ImageSkiaRep& image_rep = source_.GetRepresentation(scale_factor);
+ virtual ImageSkiaRep GetImageForScale(float scale) OVERRIDE {
+ const ImageSkiaRep& image_rep = source_.GetRepresentation(scale);
if (image_rep.GetWidth() == target_dip_size_.width() &&
image_rep.GetHeight() == target_dip_size_.height())
return image_rep;
- const float scale = ui::GetScaleFactorScale(scale_factor);
const Size target_pixel_size = DIPToPixelSize(target_dip_size_, scale);
const SkBitmap resized = skia::ImageOperations::Resize(
image_rep.sk_bitmap(),
resize_method_,
target_pixel_size.width(),
target_pixel_size.height());
- return ImageSkiaRep(resized, scale_factor);
+ return ImageSkiaRep(resized, scale);
}
private:
@@ -392,10 +385,9 @@ class DropShadowSource : public ImageSkiaSource {
virtual ~DropShadowSource() {}
// gfx::ImageSkiaSource overrides:
- virtual ImageSkiaRep GetImageForScale(ui::ScaleFactor scale_factor) OVERRIDE {
- const ImageSkiaRep& image_rep = source_.GetRepresentation(scale_factor);
+ virtual ImageSkiaRep GetImageForScale(float scale) OVERRIDE {
+ const ImageSkiaRep& image_rep = source_.GetRepresentation(scale);
- const float scale = image_rep.GetScale();
ShadowValues shadows_in_pixel;
for (size_t i = 0; i < shaodws_in_dip_.size(); ++i)
shadows_in_pixel.push_back(shaodws_in_dip_[i].Scale(scale));
@@ -403,7 +395,7 @@ class DropShadowSource : public ImageSkiaSource {
const SkBitmap shadow_bitmap = SkBitmapOperations::CreateDropShadow(
image_rep.sk_bitmap(),
shadows_in_pixel);
- return ImageSkiaRep(shadow_bitmap, image_rep.scale_factor());
+ return ImageSkiaRep(shadow_bitmap, image_rep.scale());
}
private:
@@ -425,11 +417,11 @@ class RotatedSource : public ImageSkiaSource {
virtual ~RotatedSource() {}
// gfx::ImageSkiaSource overrides:
- virtual ImageSkiaRep GetImageForScale(ui::ScaleFactor scale_factor) OVERRIDE {
- const ImageSkiaRep& image_rep = source_.GetRepresentation(scale_factor);
+ virtual ImageSkiaRep GetImageForScale(float scale) OVERRIDE {
+ const ImageSkiaRep& image_rep = source_.GetRepresentation(scale);
const SkBitmap rotated_bitmap =
SkBitmapOperations::Rotate(image_rep.sk_bitmap(), rotation_);
- return ImageSkiaRep(rotated_bitmap, image_rep.scale_factor());
+ return ImageSkiaRep(rotated_bitmap, image_rep.scale());
}
private:
diff --git a/chromium/ui/gfx/image/image_skia_operations.h b/chromium/ui/gfx/image/image_skia_operations.h
index 92da50ca1a9..5b81df7bbdb 100644
--- a/chromium/ui/gfx/image/image_skia_operations.h
+++ b/chromium/ui/gfx/image/image_skia_operations.h
@@ -17,7 +17,7 @@ class ImageSkia;
class Rect;
class Size;
-class UI_EXPORT ImageSkiaOperations {
+class GFX_EXPORT ImageSkiaOperations {
public:
// Create an image that is a blend of two others. The alpha argument
// specifies the opacity of the second imag. The provided image must
diff --git a/chromium/ui/gfx/image/image_skia_rep.cc b/chromium/ui/gfx/image/image_skia_rep.cc
index 005b9a3f54b..f8f3acb1946 100644
--- a/chromium/ui/gfx/image/image_skia_rep.cc
+++ b/chromium/ui/gfx/image/image_skia_rep.cc
@@ -6,41 +6,30 @@
namespace gfx {
-ImageSkiaRep::ImageSkiaRep()
- : scale_factor_(ui::SCALE_FACTOR_NONE) {
+ImageSkiaRep::ImageSkiaRep() : scale_(1.0f) {
}
ImageSkiaRep::~ImageSkiaRep() {
}
-ImageSkiaRep::ImageSkiaRep(const gfx::Size& size,
- ui::ScaleFactor scale_factor)
- : scale_factor_(scale_factor) {
- float scale = ui::GetScaleFactorScale(scale_factor);
+ImageSkiaRep::ImageSkiaRep(const gfx::Size& size, float scale) : scale_(scale) {
bitmap_.setConfig(SkBitmap::kARGB_8888_Config,
static_cast<int>(size.width() * scale),
static_cast<int>(size.height() * scale));
bitmap_.allocPixels();
}
-ImageSkiaRep::ImageSkiaRep(const SkBitmap& src,
- ui::ScaleFactor scale_factor)
+ImageSkiaRep::ImageSkiaRep(const SkBitmap& src, float scale)
: bitmap_(src),
- scale_factor_(scale_factor) {
+ scale_(scale) {
}
int ImageSkiaRep::GetWidth() const {
- return static_cast<int>(bitmap_.width() /
- ui::GetScaleFactorScale(scale_factor_));
+ return static_cast<int>(bitmap_.width() / scale_);
}
int ImageSkiaRep::GetHeight() const {
- return static_cast<int>(bitmap_.height() /
- ui::GetScaleFactorScale(scale_factor_));
-}
-
-float ImageSkiaRep::GetScale() const {
- return ui::GetScaleFactorScale(scale_factor_);
+ return static_cast<int>(bitmap_.height() / scale_);
}
} // namespace gfx
diff --git a/chromium/ui/gfx/image/image_skia_rep.h b/chromium/ui/gfx/image/image_skia_rep.h
index 6fca4111597..7a1e83709ab 100644
--- a/chromium/ui/gfx/image/image_skia_rep.h
+++ b/chromium/ui/gfx/image/image_skia_rep.h
@@ -6,14 +6,13 @@
#define UI_GFX_IMAGE_IMAGE_SKIA_REP_H_
#include "third_party/skia/include/core/SkBitmap.h"
-#include "ui/base/layout.h"
#include "ui/gfx/gfx_export.h"
#include "ui/gfx/size.h"
namespace gfx {
// An ImageSkiaRep represents a bitmap and the scale factor it is intended for.
-class UI_EXPORT ImageSkiaRep {
+class GFX_EXPORT ImageSkiaRep {
public:
// Create null bitmap.
ImageSkiaRep();
@@ -21,11 +20,11 @@ class UI_EXPORT ImageSkiaRep {
// Creates a bitmap with kARGB_8888_Config config with given |size| in DIP.
// This allocates pixels in the bitmap.
- ImageSkiaRep(const gfx::Size& size, ui::ScaleFactor scale_factor);
+ ImageSkiaRep(const gfx::Size& size, float scale);
- // Creates a bitmap with given scale factor.
+ // Creates a bitmap with given scale.
// Adds ref to |src|.
- ImageSkiaRep(const SkBitmap& src, ui::ScaleFactor scale_factor);
+ ImageSkiaRep(const SkBitmap& src, float scale);
// Returns true if the backing bitmap is null.
bool is_null() const { return bitmap_.isNull(); }
@@ -42,8 +41,7 @@ class UI_EXPORT ImageSkiaRep {
}
// Retrieves the scale that the bitmap will be painted at.
- float GetScale() const;
- ui::ScaleFactor scale_factor() const { return scale_factor_; }
+ float scale() const { return scale_; }
// Returns backing bitmap.
const SkBitmap& sk_bitmap() const { return bitmap_; }
@@ -53,7 +51,7 @@ class UI_EXPORT ImageSkiaRep {
SkBitmap& mutable_sk_bitmap() { return bitmap_; }
SkBitmap bitmap_;
- ui::ScaleFactor scale_factor_;
+ float scale_;
};
} // namespace gfx
diff --git a/chromium/ui/gfx/image/image_skia_source.h b/chromium/ui/gfx/image/image_skia_source.h
index ed38e1c9389..6250032292b 100644
--- a/chromium/ui/gfx/image/image_skia_source.h
+++ b/chromium/ui/gfx/image/image_skia_source.h
@@ -5,22 +5,23 @@
#ifndef UI_GFX_IMAGE_IMAGE_SKIA_SOURCE_H_
#define UI_GFX_IMAGE_IMAGE_SKIA_SOURCE_H_
-#include "ui/base/layout.h"
+#include <vector>
+
#include "ui/gfx/gfx_export.h"
namespace gfx {
class ImageSkiaRep;
-class UI_EXPORT ImageSkiaSource {
+class GFX_EXPORT ImageSkiaSource {
public:
virtual ~ImageSkiaSource() {}
- // Returns the ImageSkiaRep for the given |scale_factor|. ImageSkia
- // caches the returned ImageSkiaRep and calls this method only if it
- // doesn't have ImageSkaiRep for given |scale_factor|. There is
- // no need for the implementation to cache the image.
- virtual gfx::ImageSkiaRep GetImageForScale(ui::ScaleFactor scale_factor) = 0;
+ // Returns the ImageSkiaRep for the given |scale|. ImageSkia caches the
+ // returned ImageSkiaRep and calls this method only if it doesn't have
+ // ImageSkiaRep for given |scale|. There is no need for the implementation to
+ // cache the image.
+ virtual gfx::ImageSkiaRep GetImageForScale(float scale) = 0;
};
} // namespace gfx
diff --git a/chromium/ui/gfx/image/image_skia_unittest.cc b/chromium/ui/gfx/image/image_skia_unittest.cc
index fd17453f8f9..0047822122b 100644
--- a/chromium/ui/gfx/image/image_skia_unittest.cc
+++ b/chromium/ui/gfx/image/image_skia_unittest.cc
@@ -8,7 +8,6 @@
#include "base/threading/simple_thread.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkBitmap.h"
-#include "ui/base/layout.h"
#include "ui/gfx/image/image_skia_rep.h"
#include "ui/gfx/image/image_skia_source.h"
#include "ui/gfx/size.h"
@@ -32,7 +31,7 @@ class FixedSource : public ImageSkiaSource {
virtual ~FixedSource() {
}
- virtual ImageSkiaRep GetImageForScale(ui::ScaleFactor scale_factor) OVERRIDE {
+ virtual ImageSkiaRep GetImageForScale(float scale) OVERRIDE {
return image_;
}
@@ -49,8 +48,8 @@ class DynamicSource : public ImageSkiaSource {
virtual ~DynamicSource() {
}
- virtual ImageSkiaRep GetImageForScale(ui::ScaleFactor scale_factor) OVERRIDE {
- return gfx::ImageSkiaRep(size_, scale_factor);
+ virtual ImageSkiaRep GetImageForScale(float scale) OVERRIDE {
+ return gfx::ImageSkiaRep(size_, scale);
}
private:
@@ -67,7 +66,7 @@ class NullSource: public ImageSkiaSource {
virtual ~NullSource() {
}
- virtual ImageSkiaRep GetImageForScale(ui::ScaleFactor scale_factor) OVERRIDE {
+ virtual ImageSkiaRep GetImageForScale(float scale) OVERRIDE {
return gfx::ImageSkiaRep();
}
@@ -115,58 +114,55 @@ class TestOnThread : public base::SimpleThread {
} // namespace test
TEST(ImageSkiaTest, FixedSource) {
- ImageSkiaRep image(Size(100, 200), ui::SCALE_FACTOR_100P);
+ ImageSkiaRep image(Size(100, 200), 1.0f);
ImageSkia image_skia(new FixedSource(image), Size(100, 200));
EXPECT_EQ(0U, image_skia.image_reps().size());
- const ImageSkiaRep& result_100p =
- image_skia.GetRepresentation(ui::SCALE_FACTOR_100P);
+ const ImageSkiaRep& result_100p = image_skia.GetRepresentation(1.0f);
EXPECT_EQ(100, result_100p.GetWidth());
EXPECT_EQ(200, result_100p.GetHeight());
- EXPECT_EQ(ui::SCALE_FACTOR_100P, result_100p.scale_factor());
+ EXPECT_EQ(1.0f, result_100p.scale());
EXPECT_EQ(1U, image_skia.image_reps().size());
- const ImageSkiaRep& result_200p =
- image_skia.GetRepresentation(ui::SCALE_FACTOR_200P);
+ const ImageSkiaRep& result_200p = image_skia.GetRepresentation(2.0f);
EXPECT_EQ(100, result_200p.GetWidth());
EXPECT_EQ(200, result_200p.GetHeight());
EXPECT_EQ(100, result_200p.pixel_width());
EXPECT_EQ(200, result_200p.pixel_height());
- EXPECT_EQ(ui::SCALE_FACTOR_100P, result_200p.scale_factor());
+ EXPECT_EQ(1.0f, result_200p.scale());
EXPECT_EQ(1U, image_skia.image_reps().size());
// Get the representation again and make sure it doesn't
// generate new image skia rep.
- image_skia.GetRepresentation(ui::SCALE_FACTOR_100P);
- image_skia.GetRepresentation(ui::SCALE_FACTOR_200P);
+ image_skia.GetRepresentation(1.0f);
+ image_skia.GetRepresentation(2.0f);
EXPECT_EQ(1U, image_skia.image_reps().size());
}
TEST(ImageSkiaTest, DynamicSource) {
ImageSkia image_skia(new DynamicSource(Size(100, 200)), Size(100, 200));
EXPECT_EQ(0U, image_skia.image_reps().size());
- const ImageSkiaRep& result_100p =
- image_skia.GetRepresentation(ui::SCALE_FACTOR_100P);
+ const ImageSkiaRep& result_100p = image_skia.GetRepresentation(1.0f);
EXPECT_EQ(100, result_100p.GetWidth());
EXPECT_EQ(200, result_100p.GetHeight());
- EXPECT_EQ(ui::SCALE_FACTOR_100P, result_100p.scale_factor());
+ EXPECT_EQ(1.0f, result_100p.scale());
EXPECT_EQ(1U, image_skia.image_reps().size());
const ImageSkiaRep& result_200p =
- image_skia.GetRepresentation(ui::SCALE_FACTOR_200P);
+ image_skia.GetRepresentation(2.0f);
EXPECT_EQ(100, result_200p.GetWidth());
EXPECT_EQ(200, result_200p.GetHeight());
EXPECT_EQ(200, result_200p.pixel_width());
EXPECT_EQ(400, result_200p.pixel_height());
- EXPECT_EQ(ui::SCALE_FACTOR_200P, result_200p.scale_factor());
+ EXPECT_EQ(2.0f, result_200p.scale());
EXPECT_EQ(2U, image_skia.image_reps().size());
// Get the representation again and make sure it doesn't
// generate new image skia rep.
- image_skia.GetRepresentation(ui::SCALE_FACTOR_100P);
+ image_skia.GetRepresentation(1.0f);
EXPECT_EQ(2U, image_skia.image_reps().size());
- image_skia.GetRepresentation(ui::SCALE_FACTOR_200P);
+ image_skia.GetRepresentation(2.0f);
EXPECT_EQ(2U, image_skia.image_reps().size());
}
@@ -182,16 +178,16 @@ TEST(ImageSkiaTest, ManyRepsPerScaleFactor) {
// Simulate a source which loads images on a delay. Upon
// GetImageForScaleFactor, it immediately returns null and starts loading
// image reps slowly.
- image.GetRepresentation(ui::SCALE_FACTOR_100P);
- image.GetRepresentation(ui::SCALE_FACTOR_200P);
+ image.GetRepresentation(1.0f);
+ image.GetRepresentation(2.0f);
// After a lengthy amount of simulated time, finally loaded image reps.
image.AddRepresentation(ImageSkiaRep(
- gfx::Size(kSmallIcon1x, kSmallIcon1x), ui::SCALE_FACTOR_100P));
+ gfx::Size(kSmallIcon1x, kSmallIcon1x), 1.0f));
image.AddRepresentation(ImageSkiaRep(
- gfx::Size(kSmallIcon2x, kSmallIcon2x), ui::SCALE_FACTOR_200P));
+ gfx::Size(kSmallIcon2x, kSmallIcon2x), 2.0f));
image.AddRepresentation(ImageSkiaRep(
- gfx::Size(kLargeIcon1x, kLargeIcon1x), ui::SCALE_FACTOR_100P));
+ gfx::Size(kLargeIcon1x, kLargeIcon1x), 1.0f));
std::vector<ImageSkiaRep> image_reps = image.image_reps();
EXPECT_EQ(3u, image_reps.size());
@@ -199,9 +195,9 @@ TEST(ImageSkiaTest, ManyRepsPerScaleFactor) {
int num_1x = 0;
int num_2x = 0;
for (size_t i = 0; i < image_reps.size(); ++i) {
- if (image_reps[i].scale_factor() == ui::SCALE_FACTOR_100P)
+ if (image_reps[i].scale() == 1.0f)
num_1x++;
- else if (image_reps[i].scale_factor() == ui::SCALE_FACTOR_200P)
+ else if (image_reps[i].scale() == 2.0f)
num_2x++;
}
EXPECT_EQ(2, num_1x);
@@ -218,9 +214,9 @@ TEST(ImageSkiaTest, GetBitmap) {
TEST(ImageSkiaTest, GetBitmapFromEmpty) {
// Create an image with 1 representation and remove it so the ImageSkiaStorage
// is left with no representations.
- ImageSkia empty_image(ImageSkiaRep(Size(100, 200), ui::SCALE_FACTOR_100P));
+ ImageSkia empty_image(ImageSkiaRep(Size(100, 200), 1.0f));
ImageSkia empty_image_copy(empty_image);
- empty_image.RemoveRepresentation(ui::SCALE_FACTOR_100P);
+ empty_image.RemoveRepresentation(1.0f);
// Check that ImageSkia::bitmap() still returns a valid SkBitmap pointer for
// the image and all its copies.
@@ -237,12 +233,12 @@ TEST(ImageSkiaTest, BackedBySameObjectAs) {
EXPECT_TRUE(image.BackedBySameObjectAs(unrelated));
image.AddRepresentation(gfx::ImageSkiaRep(gfx::Size(10, 10),
- ui::SCALE_FACTOR_100P));
+ 1.0f));
ImageSkia copy = image;
copy.AddRepresentation(gfx::ImageSkiaRep(gfx::Size(10, 10),
- ui::SCALE_FACTOR_200P));
+ 2.0f));
unrelated.AddRepresentation(gfx::ImageSkiaRep(gfx::Size(10, 10),
- ui::SCALE_FACTOR_100P));
+ 1.0f));
EXPECT_TRUE(image.BackedBySameObjectAs(copy));
EXPECT_FALSE(image.BackedBySameObjectAs(unrelated));
EXPECT_FALSE(copy.BackedBySameObjectAs(unrelated));
@@ -259,7 +255,7 @@ TEST(ImageSkiaTest, EmptyOnThreadTest) {
}
TEST(ImageSkiaTest, StaticOnThreadTest) {
- ImageSkia image(ImageSkiaRep(Size(100, 200), ui::SCALE_FACTOR_100P));
+ ImageSkia image(ImageSkiaRep(Size(100, 200), 1.0f));
EXPECT_FALSE(image.IsThreadSafe());
test::TestOnThread image_on_thread(&image);
@@ -365,8 +361,8 @@ TEST(ImageSkiaTest, SourceOnThreadTest) {
image.MakeThreadSafe();
EXPECT_TRUE(image.IsThreadSafe());
// Check if image reps are generated for supported scale factors.
- EXPECT_EQ(ui::GetSupportedScaleFactors().size(),
- image.image_reps().size());
+ EXPECT_EQ(ImageSkia::GetSupportedScales().size(),
+ image.image_reps().size());
test::TestOnThread threadsafe_on_thread(&image);
threadsafe_on_thread.StartAndJoin();
EXPECT_TRUE(threadsafe_on_thread.can_read());
diff --git a/chromium/ui/gfx/image/image_skia_util_ios.h b/chromium/ui/gfx/image/image_skia_util_ios.h
index 57c9698b955..6576ff8da7a 100644
--- a/chromium/ui/gfx/image/image_skia_util_ios.h
+++ b/chromium/ui/gfx/image/image_skia_util_ios.h
@@ -5,7 +5,6 @@
#ifndef UI_GFX_IMAGE_IMAGE_SKIA_UTIL_IOS_H_
#define UI_GFX_IMAGE_IMAGE_SKIA_UTIL_IOS_H_
-#include "ui/base/layout.h"
#include "ui/gfx/gfx_export.h"
#ifdef __OBJC__
@@ -19,24 +18,22 @@ class ImageSkia;
class ImageSkiaRep;
// Converts to ImageSkia from UIImage.
-UI_EXPORT gfx::ImageSkia ImageSkiaFromUIImage(UIImage* image);
+GFX_EXPORT gfx::ImageSkia ImageSkiaFromUIImage(UIImage* image);
// Converts to an ImageSkiaRep of |scale_factor| from UIImage.
-// |scale_factor| is passed explicitly in order to allow this method to be used
-// with a |scale_factor| which is not supported by the platform.
-// (ui::GetScaleFactorFromScale() is restricted to the platform's supported
-// scale factors.)
-UI_EXPORT gfx::ImageSkiaRep ImageSkiaRepOfScaleFactorFromUIImage(
+// |scale| is passed explicitly in order to allow this method to be used
+// with a |scale| which is not supported by the platform.
+GFX_EXPORT gfx::ImageSkiaRep ImageSkiaRepOfScaleFromUIImage(
UIImage* image,
- ui::ScaleFactor scale_factor);
+ float scale);
// Converts to UIImage from ImageSkia. The returned UIImage will be at the scale
// of the ImageSkiaRep in |image_skia| which most closely matches the device's
// scale factor (eg Retina iPad -> 2x). Returns an autoreleased UIImage.
-UI_EXPORT UIImage* UIImageFromImageSkia(const gfx::ImageSkia& image_skia);
+GFX_EXPORT UIImage* UIImageFromImageSkia(const gfx::ImageSkia& image_skia);
// Converts to UIImage from ImageSkiaRep. Returns an autoreleased UIImage.
-UI_EXPORT UIImage* UIImageFromImageSkiaRep(
+GFX_EXPORT UIImage* UIImageFromImageSkiaRep(
const gfx::ImageSkiaRep& image_skia_rep);
} // namespace gfx
diff --git a/chromium/ui/gfx/image/image_skia_util_ios.mm b/chromium/ui/gfx/image/image_skia_util_ios.mm
index 0ff8978f786..77944eee4c2 100644
--- a/chromium/ui/gfx/image/image_skia_util_ios.mm
+++ b/chromium/ui/gfx/image/image_skia_util_ios.mm
@@ -16,39 +16,37 @@ namespace gfx {
gfx::ImageSkia ImageSkiaFromUIImage(UIImage* image) {
gfx::ImageSkia image_skia;
- gfx::ImageSkiaRep image_skia_rep = ImageSkiaRepOfScaleFactorFromUIImage(
- image, ui::GetMaxScaleFactor());
+ float max_scale = ImageSkia::GetSupportedScales().back();
+ gfx::ImageSkiaRep image_skia_rep = ImageSkiaRepOfScaleFromUIImage(
+ image, max_scale);
if (!image_skia_rep.is_null())
image_skia.AddRepresentation(image_skia_rep);
return image_skia;
}
-gfx::ImageSkiaRep ImageSkiaRepOfScaleFactorFromUIImage(
- UIImage* image,
- ui::ScaleFactor scale_factor) {
+gfx::ImageSkiaRep ImageSkiaRepOfScaleFromUIImage(UIImage* image, float scale) {
if (!image)
return gfx::ImageSkiaRep();
- float scale = ui::GetScaleFactorScale(scale_factor);
CGSize size = image.size;
CGSize desired_size_for_scale =
CGSizeMake(size.width * scale, size.height * scale);
SkBitmap bitmap(gfx::CGImageToSkBitmap(image.CGImage,
desired_size_for_scale,
false));
- return gfx::ImageSkiaRep(bitmap, scale_factor);
+ return gfx::ImageSkiaRep(bitmap, scale);
}
UIImage* UIImageFromImageSkia(const gfx::ImageSkia& image_skia) {
- return UIImageFromImageSkiaRep(image_skia.GetRepresentation(
- ui::GetMaxScaleFactor()));
+ return UIImageFromImageSkiaRep(
+ image_skia.GetRepresentation(ImageSkia::GetSupportedScales().back()));
}
UIImage* UIImageFromImageSkiaRep(const gfx::ImageSkiaRep& image_skia_rep) {
if (image_skia_rep.is_null())
return nil;
- float scale = ui::GetScaleFactorScale(image_skia_rep.scale_factor());
+ float scale = image_skia_rep.scale();
base::ScopedCFTypeRef<CGColorSpaceRef> color_space(
CGColorSpaceCreateDeviceRGB());
return gfx::SkBitmapToUIImageWithColorSpace(image_skia_rep.sk_bitmap(), scale,
diff --git a/chromium/ui/gfx/image/image_skia_util_mac.h b/chromium/ui/gfx/image/image_skia_util_mac.h
index 10d05b045d4..553c3f8741d 100644
--- a/chromium/ui/gfx/image/image_skia_util_mac.h
+++ b/chromium/ui/gfx/image/image_skia_util_mac.h
@@ -25,21 +25,21 @@ namespace gfx {
class ImageSkia;
// Converts to ImageSkia from NSImage.
-UI_EXPORT gfx::ImageSkia ImageSkiaFromNSImage(NSImage* image);
+GFX_EXPORT gfx::ImageSkia ImageSkiaFromNSImage(NSImage* image);
// Resizes NSImage to |size| DIP and then converts to ImageSkia.
-UI_EXPORT gfx::ImageSkia ImageSkiaFromResizedNSImage(NSImage* image,
- NSSize size);
+GFX_EXPORT gfx::ImageSkia ImageSkiaFromResizedNSImage(NSImage* image,
+ NSSize size);
// Resizes |[NSImage imageNamed:@NSApplicationIcon]| to have edge width of
// |size| DIP and returns result as ImageSkia.
-UI_EXPORT gfx::ImageSkia ApplicationIconAtSize(int size);
+GFX_EXPORT gfx::ImageSkia ApplicationIconAtSize(int size);
// Converts to NSImage from ImageSkia.
-UI_EXPORT NSImage* NSImageFromImageSkia(const gfx::ImageSkia& image_skia);
+GFX_EXPORT NSImage* NSImageFromImageSkia(const gfx::ImageSkia& image_skia);
// Converts to NSImage from given ImageSkia and a color space.
-UI_EXPORT NSImage* NSImageFromImageSkiaWithColorSpace(
+GFX_EXPORT NSImage* NSImageFromImageSkiaWithColorSpace(
const gfx::ImageSkia& image_skia,
CGColorSpaceRef color_space);
diff --git a/chromium/ui/gfx/image/image_skia_util_mac.mm b/chromium/ui/gfx/image/image_skia_util_mac.mm
index f9d0475af7f..281badc7423 100644
--- a/chromium/ui/gfx/image/image_skia_util_mac.mm
+++ b/chromium/ui/gfx/image/image_skia_util_mac.mm
@@ -57,24 +57,23 @@ gfx::ImageSkia ImageSkiaFromResizedNSImage(NSImage* image,
if (IsNSImageEmpty(image))
return gfx::ImageSkia();
- std::vector<ui::ScaleFactor> supported_scale_factors =
- ui::GetSupportedScaleFactors();
+ std::vector<float> supported_scales = ImageSkia::GetSupportedScales();
gfx::ImageSkia image_skia;
- for (size_t i = 0; i < supported_scale_factors.size(); ++i) {
- float scale = ui::GetScaleFactorScale(supported_scale_factors[i]);
+ for (size_t i = 0; i < supported_scales.size(); ++i) {
+ float scale = supported_scales[i];
NSSize desired_size_for_scale = NSMakeSize(desired_size.width * scale,
desired_size.height * scale);
NSImageRep* ns_image_rep = GetNSImageRepWithPixelSize(image,
desired_size_for_scale);
- SkBitmap bitmap(gfx::NSImageRepToSkBitmap(ns_image_rep,
- desired_size_for_scale, false));
+ // TODO(dcheng): Should this function take a color space argument?
+ SkBitmap bitmap(gfx::NSImageRepToSkBitmapWithColorSpace(ns_image_rep,
+ desired_size_for_scale, false, base::mac::GetGenericRGBColorSpace()));
if (bitmap.isNull())
continue;
- image_skia.AddRepresentation(gfx::ImageSkiaRep(bitmap,
- supported_scale_factors[i]));
+ image_skia.AddRepresentation(gfx::ImageSkiaRep(bitmap, scale));
}
return image_skia;
}
@@ -90,7 +89,7 @@ NSImage* NSImageFromImageSkia(const gfx::ImageSkia& image_skia) {
return nil;
base::scoped_nsobject<NSImage> image([[NSImage alloc] init]);
- image_skia.EnsureRepsForSupportedScaleFactors();
+ image_skia.EnsureRepsForSupportedScales();
std::vector<gfx::ImageSkiaRep> image_reps = image_skia.image_reps();
for (std::vector<gfx::ImageSkiaRep>::const_iterator it = image_reps.begin();
it != image_reps.end(); ++it) {
@@ -108,7 +107,7 @@ NSImage* NSImageFromImageSkiaWithColorSpace(const gfx::ImageSkia& image_skia,
return nil;
base::scoped_nsobject<NSImage> image([[NSImage alloc] init]);
- image_skia.EnsureRepsForSupportedScaleFactors();
+ image_skia.EnsureRepsForSupportedScales();
std::vector<gfx::ImageSkiaRep> image_reps = image_skia.image_reps();
for (std::vector<gfx::ImageSkiaRep>::const_iterator it = image_reps.begin();
it != image_reps.end(); ++it) {
diff --git a/chromium/ui/gfx/image/image_unittest.cc b/chromium/ui/gfx/image/image_unittest.cc
index 6d3c649643d..039cb13f606 100644
--- a/chromium/ui/gfx/image/image_unittest.cc
+++ b/chromium/ui/gfx/image/image_unittest.cc
@@ -5,7 +5,6 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkPaint.h"
-#include "ui/base/layout.h"
#include "ui/gfx/image/image.h"
#include "ui/gfx/image/image_png_rep.h"
#include "ui/gfx/image/image_skia.h"
@@ -24,13 +23,23 @@
namespace {
-#if defined(TOOLKIT_VIEWS) || defined(OS_ANDROID)
+#if defined(TOOLKIT_VIEWS) || defined(OS_ANDROID) || \
+ (defined(OS_LINUX) && !defined(USE_CAIRO))
const bool kUsesSkiaNatively = true;
#else
const bool kUsesSkiaNatively = false;
#endif
class ImageTest : public testing::Test {
+ public:
+ ImageTest() {
+ std::vector<float> scales;
+ scales.push_back(1.0f);
+#if !defined(OS_IOS)
+ scales.push_back(2.0f);
+#endif
+ gfx::ImageSkia::SetSupportedScales(scales);
+ }
};
namespace gt = gfx::test;
@@ -95,14 +104,14 @@ TEST_F(ImageTest, EmptyImageFromEmptyPlatformImage) {
// invalid data.
TEST_F(ImageTest, EmptyImageFromObviouslyInvalidPNGImage) {
std::vector<gfx::ImagePNGRep> image_png_reps1;
- image_png_reps1.push_back(gfx::ImagePNGRep(NULL, ui::SCALE_FACTOR_100P));
+ image_png_reps1.push_back(gfx::ImagePNGRep(NULL, 1.0f));
gfx::Image image1(image_png_reps1);
EXPECT_TRUE(image1.IsEmpty());
EXPECT_EQ(0U, image1.RepresentationCount());
std::vector<gfx::ImagePNGRep> image_png_reps2;
image_png_reps2.push_back(gfx::ImagePNGRep(
- new base::RefCountedBytes(), ui::SCALE_FACTOR_100P));
+ new base::RefCountedBytes(), 1.0f));
gfx::Image image2(image_png_reps2);
EXPECT_TRUE(image2.IsEmpty());
EXPECT_EQ(0U, image2.RepresentationCount());
@@ -166,7 +175,7 @@ TEST_F(ImageTest, ImageNo1xToPNG) {
const int kSize2x = 50;
gfx::ImageSkia image_skia;
image_skia.AddRepresentation(gfx::ImageSkiaRep(gt::CreateBitmap(
- kSize2x, kSize2x), ui::SCALE_FACTOR_200P));
+ kSize2x, kSize2x), 2.0f));
gfx::Image image1(image_skia);
scoped_refptr<base::RefCountedMemory> png_bytes1 = image1.As1xPNGBytes();
EXPECT_TRUE(png_bytes1.get());
@@ -174,7 +183,7 @@ TEST_F(ImageTest, ImageNo1xToPNG) {
std::vector<gfx::ImagePNGRep> image_png_reps;
image_png_reps.push_back(gfx::ImagePNGRep(
- gt::CreatePNGBytes(kSize2x), ui::SCALE_FACTOR_200P));
+ gt::CreatePNGBytes(kSize2x), 2.0f));
gfx::Image image2(image_png_reps);
EXPECT_FALSE(image2.IsEmpty());
EXPECT_EQ(0, image2.Width());
@@ -192,9 +201,9 @@ TEST_F(ImageTest, CreateExtractPNGBytes) {
scoped_refptr<base::RefCountedMemory> bytes1x = gt::CreatePNGBytes(kSize1x);
std::vector<gfx::ImagePNGRep> image_png_reps;
- image_png_reps.push_back(gfx::ImagePNGRep(bytes1x, ui::SCALE_FACTOR_100P));
+ image_png_reps.push_back(gfx::ImagePNGRep(bytes1x, 1.0f));
image_png_reps.push_back(gfx::ImagePNGRep(
- gt::CreatePNGBytes(kSize2x), ui::SCALE_FACTOR_200P));
+ gt::CreatePNGBytes(kSize2x), 2.0f));
gfx::Image image(image_png_reps);
EXPECT_FALSE(image.IsEmpty());
@@ -212,9 +221,9 @@ TEST_F(ImageTest, MultiResolutionImageSkiaToPNG) {
SkBitmap bitmap_1x = gt::CreateBitmap(kSize1x, kSize1x);
gfx::ImageSkia image_skia;
image_skia.AddRepresentation(gfx::ImageSkiaRep(bitmap_1x,
- ui::SCALE_FACTOR_100P));
+ 1.0f));
image_skia.AddRepresentation(gfx::ImageSkiaRep(gt::CreateBitmap(
- kSize2x, kSize2x), ui::SCALE_FACTOR_200P));
+ kSize2x, kSize2x), 2.0f));
gfx::Image image(image_skia);
EXPECT_TRUE(gt::IsEqual(image.As1xPNGBytes(), bitmap_1x));
@@ -229,20 +238,20 @@ TEST_F(ImageTest, MultiResolutionPNGToImageSkia) {
scoped_refptr<base::RefCountedMemory> bytes2x = gt::CreatePNGBytes(kSize2x);
std::vector<gfx::ImagePNGRep> image_png_reps;
- image_png_reps.push_back(gfx::ImagePNGRep(bytes1x, ui::SCALE_FACTOR_100P));
- image_png_reps.push_back(gfx::ImagePNGRep(bytes2x, ui::SCALE_FACTOR_200P));
+ image_png_reps.push_back(gfx::ImagePNGRep(bytes1x, 1.0f));
+ image_png_reps.push_back(gfx::ImagePNGRep(bytes2x, 2.0f));
gfx::Image image(image_png_reps);
- std::vector<ui::ScaleFactor> scale_factors;
- scale_factors.push_back(ui::SCALE_FACTOR_100P);
- scale_factors.push_back(ui::SCALE_FACTOR_200P);
+ std::vector<float> scales;
+ scales.push_back(1.0f);
+ scales.push_back(2.0f);
gfx::ImageSkia image_skia = image.AsImageSkia();
EXPECT_TRUE(gt::ImageSkiaStructureMatches(image_skia, kSize1x, kSize1x,
- scale_factors));
+ scales));
EXPECT_TRUE(gt::IsEqual(bytes1x,
- image_skia.GetRepresentation(ui::SCALE_FACTOR_100P).sk_bitmap()));
+ image_skia.GetRepresentation(1.0f).sk_bitmap()));
EXPECT_TRUE(gt::IsEqual(bytes2x,
- image_skia.GetRepresentation(ui::SCALE_FACTOR_200P).sk_bitmap()));
+ image_skia.GetRepresentation(2.0f).sk_bitmap()));
}
TEST_F(ImageTest, MultiResolutionPNGToPlatform) {
@@ -252,18 +261,18 @@ TEST_F(ImageTest, MultiResolutionPNGToPlatform) {
scoped_refptr<base::RefCountedMemory> bytes1x = gt::CreatePNGBytes(kSize1x);
scoped_refptr<base::RefCountedMemory> bytes2x = gt::CreatePNGBytes(kSize2x);
std::vector<gfx::ImagePNGRep> image_png_reps;
- image_png_reps.push_back(gfx::ImagePNGRep(bytes1x, ui::SCALE_FACTOR_100P));
- image_png_reps.push_back(gfx::ImagePNGRep(bytes2x, ui::SCALE_FACTOR_200P));
+ image_png_reps.push_back(gfx::ImagePNGRep(bytes1x, 1.0f));
+ image_png_reps.push_back(gfx::ImagePNGRep(bytes2x, 2.0f));
gfx::Image from_png(image_png_reps);
gfx::Image from_platform(gt::CopyPlatformType(from_png));
#if defined(OS_IOS)
// On iOS the platform type (UIImage) only supports one resolution.
- std::vector<ui::ScaleFactor> scale_factors = ui::GetSupportedScaleFactors();
- EXPECT_EQ(scale_factors.size(), 1U);
- if (scale_factors[0] == ui::SCALE_FACTOR_100P)
+ std::vector<float> scales = gfx::ImageSkia::GetSupportedScales();
+ EXPECT_EQ(scales.size(), 1U);
+ if (scales[0] == 1.0f)
EXPECT_TRUE(gt::IsEqual(bytes1x, from_platform.AsBitmap()));
- else if (scale_factors[0] == ui::SCALE_FACTOR_200P)
+ else if (scales[0] == 2.0f)
EXPECT_TRUE(gt::IsEqual(bytes2x, from_platform.AsBitmap()));
else
ADD_FAILURE() << "Unexpected platform scale factor.";
@@ -281,7 +290,7 @@ TEST_F(ImageTest, PlatformToPNGEncodeAndDecode) {
EXPECT_TRUE(image.HasRepresentation(gfx::Image::kImageRepPNG));
std::vector<gfx::ImagePNGRep> image_png_reps;
- image_png_reps.push_back(gfx::ImagePNGRep(png_data, ui::SCALE_FACTOR_100P));
+ image_png_reps.push_back(gfx::ImagePNGRep(png_data, 1.0f));
gfx::Image from_png(image_png_reps);
EXPECT_TRUE(from_png.HasRepresentation(gfx::Image::kImageRepPNG));
@@ -292,15 +301,13 @@ TEST_F(ImageTest, PlatformToPNGEncodeAndDecode) {
// sure these work with the Skia Encode/Decode.
TEST_F(ImageTest, PNGEncodeFromSkiaDecodeToPlatform) {
// Force the conversion sequence skia to png to platform_type.
- ui::ScaleFactor ideal_scale_factor = ui::GetScaleFactorFromScale(1.0f);
-
gfx::Image from_bitmap = gfx::Image::CreateFrom1xBitmap(
gt::CreateBitmap(25, 25));
scoped_refptr<base::RefCountedMemory> png_bytes =
from_bitmap.As1xPNGBytes();
std::vector<gfx::ImagePNGRep> image_png_reps;
- image_png_reps.push_back(gfx::ImagePNGRep(png_bytes, ideal_scale_factor));
+ image_png_reps.push_back(gfx::ImagePNGRep(png_bytes, 1.0f));
gfx::Image from_png(image_png_reps);
gfx::Image from_platform(gt::CopyPlatformType(from_png));
@@ -315,7 +322,7 @@ TEST_F(ImageTest, PNGEncodeFromPlatformDecodeToSkia) {
scoped_refptr<base::RefCountedMemory> png_bytes =
from_platform.As1xPNGBytes();
std::vector<gfx::ImagePNGRep> image_png_reps;
- image_png_reps.push_back(gfx::ImagePNGRep(png_bytes, ui::SCALE_FACTOR_100P));
+ image_png_reps.push_back(gfx::ImagePNGRep(png_bytes, 1.0f));
gfx::Image from_png(image_png_reps);
EXPECT_TRUE(gt::IsEqual(from_platform.AsBitmap(), from_png.AsBitmap()));
@@ -327,7 +334,7 @@ TEST_F(ImageTest, PNGDecodeToSkiaFailure) {
invalid_bytes->data().push_back('0');
std::vector<gfx::ImagePNGRep> image_png_reps;
image_png_reps.push_back(gfx::ImagePNGRep(
- invalid_bytes, ui::SCALE_FACTOR_100P));
+ invalid_bytes, 1.0f));
gfx::Image image(image_png_reps);
gt::CheckImageIndicatesPNGDecodeFailure(image);
}
@@ -338,7 +345,7 @@ TEST_F(ImageTest, PNGDecodeToPlatformFailure) {
invalid_bytes->data().push_back('0');
std::vector<gfx::ImagePNGRep> image_png_reps;
image_png_reps.push_back(gfx::ImagePNGRep(
- invalid_bytes, ui::SCALE_FACTOR_100P));
+ invalid_bytes, 1.0f));
gfx::Image from_png(image_png_reps);
gfx::Image from_platform(gt::CopyPlatformType(from_png));
gt::CheckImageIndicatesPNGDecodeFailure(from_platform);
@@ -531,9 +538,9 @@ TEST_F(ImageTest, SkBitmapConversionPreservesTransparency) {
const int width = 50;
const int height = 50;
SkBitmap bitmap;
- bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height);
+ bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height, 0,
+ kPremul_SkAlphaType);
bitmap.allocPixels();
- bitmap.setIsOpaque(false);
bitmap.eraseARGB(0, 0, 255, 0);
// Paint the upper half of the image in red (lower half is transparent).
@@ -636,16 +643,16 @@ TEST_F(ImageTest, MultiResolutionImageSkia) {
gfx::ImageSkia image_skia;
image_skia.AddRepresentation(gfx::ImageSkiaRep(
gt::CreateBitmap(kWidth1x, kHeight1x),
- ui::SCALE_FACTOR_100P));
+ 1.0f));
image_skia.AddRepresentation(gfx::ImageSkiaRep(
gt::CreateBitmap(kWidth2x, kHeight2x),
- ui::SCALE_FACTOR_200P));
+ 2.0f));
- std::vector<ui::ScaleFactor> scale_factors;
- scale_factors.push_back(ui::SCALE_FACTOR_100P);
- scale_factors.push_back(ui::SCALE_FACTOR_200P);
+ std::vector<float> scales;
+ scales.push_back(1.0f);
+ scales.push_back(2.0f);
EXPECT_TRUE(gt::ImageSkiaStructureMatches(image_skia, kWidth1x, kHeight1x,
- scale_factors));
+ scales));
// Check that the image has a single representation.
gfx::Image image(image_skia);
@@ -661,13 +668,13 @@ TEST_F(ImageTest, RemoveFromMultiResolutionImageSkia) {
gfx::ImageSkia image_skia;
image_skia.AddRepresentation(gfx::ImageSkiaRep(
- gt::CreateBitmap(kWidth2x, kHeight2x), ui::SCALE_FACTOR_200P));
+ gt::CreateBitmap(kWidth2x, kHeight2x), 2.0f));
EXPECT_EQ(1u, image_skia.image_reps().size());
- image_skia.RemoveRepresentation(ui::SCALE_FACTOR_100P);
+ image_skia.RemoveRepresentation(1.0f);
EXPECT_EQ(1u, image_skia.image_reps().size());
- image_skia.RemoveRepresentation(ui::SCALE_FACTOR_200P);
+ image_skia.RemoveRepresentation(2.0f);
EXPECT_EQ(0u, image_skia.image_reps().size());
}
@@ -679,7 +686,7 @@ TEST_F(ImageTest, OwnershipTest) {
SkBitmap bitmap(gt::CreateBitmap(10, 10));
EXPECT_TRUE(!bitmap.isNull());
image = gfx::Image(gfx::ImageSkia(
- gfx::ImageSkiaRep(bitmap, ui::SCALE_FACTOR_100P)));
+ gfx::ImageSkiaRep(bitmap, 1.0f)));
}
EXPECT_TRUE(!image.ToSkBitmap()->isNull());
}
diff --git a/chromium/ui/gfx/image/image_unittest_util.cc b/chromium/ui/gfx/image/image_unittest_util.cc
index ef59eb61636..4baf30a4cc6 100644
--- a/chromium/ui/gfx/image/image_unittest_util.cc
+++ b/chromium/ui/gfx/image/image_unittest_util.cc
@@ -48,11 +48,11 @@ bool ColorsClose(SkColor color1, SkColor color2) {
} // namespace
-std::vector<ui::ScaleFactor> Get1xAnd2xScaleFactors() {
- std::vector<ui::ScaleFactor> scale_factors;
- scale_factors.push_back(ui::SCALE_FACTOR_100P);
- scale_factors.push_back(ui::SCALE_FACTOR_200P);
- return scale_factors;
+std::vector<float> Get1xAnd2xScales() {
+ std::vector<float> scales;
+ scales.push_back(1.0f);
+ scales.push_back(2.0f);
+ return scales;
}
const SkBitmap CreateBitmap(int width, int height) {
@@ -89,10 +89,9 @@ bool IsEqual(const gfx::Image& img1, const gfx::Image& img2) {
return false;
for (size_t i = 0; i < img1_reps.size(); ++i) {
- ui::ScaleFactor scale_factor = img1_reps[i].scale_factor();
- const gfx::ImageSkiaRep& image_rep2 = image_skia2.GetRepresentation(
- scale_factor);
- if (image_rep2.scale_factor() != scale_factor ||
+ float scale = img1_reps[i].scale();
+ const gfx::ImageSkiaRep& image_rep2 = image_skia2.GetRepresentation(scale);
+ if (image_rep2.scale() != scale ||
!IsEqual(img1_reps[i].sk_bitmap(), image_rep2.sk_bitmap())) {
return false;
}
@@ -150,24 +149,22 @@ bool ImageSkiaStructureMatches(
const gfx::ImageSkia& image_skia,
int width,
int height,
- const std::vector<ui::ScaleFactor>& scale_factors) {
+ const std::vector<float>& scales) {
if (image_skia.isNull() ||
image_skia.width() != width ||
image_skia.height() != height ||
- image_skia.image_reps().size() != scale_factors.size()) {
+ image_skia.image_reps().size() != scales.size()) {
return false;
}
- for (size_t i = 0; i < scale_factors.size(); ++i) {
+ for (size_t i = 0; i < scales.size(); ++i) {
gfx::ImageSkiaRep image_rep =
- image_skia.GetRepresentation(scale_factors[i]);
- if (image_rep.is_null() ||
- image_rep.scale_factor() != scale_factors[i])
+ image_skia.GetRepresentation(scales[i]);
+ if (image_rep.is_null() || image_rep.scale() != scales[i])
return false;
- float scale = ui::GetScaleFactorScale(scale_factors[i]);
- if (image_rep.pixel_width() != static_cast<int>(width * scale) ||
- image_rep.pixel_height() != static_cast<int>(height * scale)) {
+ if (image_rep.pixel_width() != static_cast<int>(width * scales[i]) ||
+ image_rep.pixel_height() != static_cast<int>(height * scales[i])) {
return false;
}
}
@@ -183,8 +180,7 @@ bool IsEmpty(const gfx::Image& image) {
PlatformImage CreatePlatformImage() {
const SkBitmap bitmap(CreateBitmap(25, 25));
#if defined(OS_IOS)
- ui::ScaleFactor scale_factor = ui::GetMaxScaleFactor();
- float scale = ui::GetScaleFactorScale(scale_factor);
+ float scale = ImageSkia::GetMaxSupportedScale();
base::ScopedCFTypeRef<CGColorSpaceRef> color_space(
CGColorSpaceCreateDeviceRGB());
diff --git a/chromium/ui/gfx/image/image_unittest_util.h b/chromium/ui/gfx/image/image_unittest_util.h
index a2293c8688b..4788e4e1009 100644
--- a/chromium/ui/gfx/image/image_unittest_util.h
+++ b/chromium/ui/gfx/image/image_unittest_util.h
@@ -8,7 +8,6 @@
#ifndef UI_GFX_IMAGE_IMAGE_UNITTEST_UTIL_H_
#define UI_GFX_IMAGE_IMAGE_UNITTEST_UTIL_H_
-#include "ui/base/layout.h"
#include "ui/gfx/image/image.h"
#include "third_party/skia/include/core/SkColor.h"
@@ -25,7 +24,7 @@ typedef GdkPixbuf* PlatformImage;
typedef gfx::ImageSkia PlatformImage;
#endif
-std::vector<ui::ScaleFactor> Get1xAnd2xScaleFactors();
+std::vector<float> Get1xAnd2xScales();
// Create a bitmap of |width|x|height|.
const SkBitmap CreateBitmap(int width, int height);
@@ -65,7 +64,7 @@ bool ImageSkiaStructureMatches(
const gfx::ImageSkia& image_skia,
int width,
int height,
- const std::vector<ui::ScaleFactor>& scale_factors);
+ const std::vector<float>& scale_factors);
bool IsEmpty(const gfx::Image& image);
diff --git a/chromium/ui/gfx/image/image_util.cc b/chromium/ui/gfx/image/image_util.cc
index e230a0b1264..59d631d171d 100644
--- a/chromium/ui/gfx/image/image_util.cc
+++ b/chromium/ui/gfx/image/image_util.cc
@@ -26,8 +26,8 @@ Image ImageFrom1xJPEGEncodedData(const unsigned char* input,
bool JPEG1xEncodedDataFromImage(const Image& image, int quality,
std::vector<unsigned char>* dst) {
const gfx::ImageSkiaRep& image_skia_rep =
- image.AsImageSkia().GetRepresentation(ui::SCALE_FACTOR_100P);
- if (image_skia_rep.scale_factor() != ui::SCALE_FACTOR_100P)
+ image.AsImageSkia().GetRepresentation(1.0f);
+ if (image_skia_rep.scale() != 1.0f)
return false;
const SkBitmap& bitmap = image_skia_rep.sk_bitmap();
diff --git a/chromium/ui/gfx/image/image_util.h b/chromium/ui/gfx/image/image_util.h
index a039557a8f0..f33835ca232 100644
--- a/chromium/ui/gfx/image/image_util.h
+++ b/chromium/ui/gfx/image/image_util.h
@@ -18,8 +18,8 @@ namespace gfx {
// Creates an image from the given JPEG-encoded input. If there was an error
// creating the image, returns an IsEmpty() Image.
-UI_EXPORT Image ImageFrom1xJPEGEncodedData(const unsigned char* input,
- size_t input_size);
+GFX_EXPORT Image ImageFrom1xJPEGEncodedData(const unsigned char* input,
+ size_t input_size);
// Fills the |dst| vector with JPEG-encoded bytes of the 1x representation of
// the given image.
@@ -27,9 +27,9 @@ UI_EXPORT Image ImageFrom1xJPEGEncodedData(const unsigned char* input,
// was encoded successfully.
// |quality| determines the compression level, 0 == lowest, 100 == highest.
// Returns true if the Image was encoded successfully.
-UI_EXPORT bool JPEG1xEncodedDataFromImage(const Image& image,
- int quality,
- std::vector<unsigned char>* dst);
+GFX_EXPORT bool JPEG1xEncodedDataFromImage(const Image& image,
+ int quality,
+ std::vector<unsigned char>* dst);
} // namespace gfx
diff --git a/chromium/ui/gfx/insets.h b/chromium/ui/gfx/insets.h
index 571751d937e..a419059a55d 100644
--- a/chromium/ui/gfx/insets.h
+++ b/chromium/ui/gfx/insets.h
@@ -18,7 +18,7 @@ typedef struct _GtkBorder GtkBorder;
namespace gfx {
// An integer version of gfx::Insets.
-class UI_EXPORT Insets : public InsetsBase<Insets, int> {
+class GFX_EXPORT Insets : public InsetsBase<Insets, int> {
public:
Insets();
Insets(int top, int left, int bottom, int right);
diff --git a/chromium/ui/gfx/insets_base.h b/chromium/ui/gfx/insets_base.h
index ab105bccfb8..da7aca103e5 100644
--- a/chromium/ui/gfx/insets_base.h
+++ b/chromium/ui/gfx/insets_base.h
@@ -12,7 +12,7 @@ namespace gfx {
// An insets represents the borders of a container (the space the container must
// leave at each of its edges).
template<typename Class, typename Type>
-class UI_EXPORT InsetsBase {
+class GFX_EXPORT InsetsBase {
public:
Type top() const { return top_; }
Type left() const { return left_; }
diff --git a/chromium/ui/gfx/insets_f.h b/chromium/ui/gfx/insets_f.h
index 045b8a02e8e..43b801dcb22 100644
--- a/chromium/ui/gfx/insets_f.h
+++ b/chromium/ui/gfx/insets_f.h
@@ -14,7 +14,7 @@
namespace gfx {
// A floating versin of gfx::Insets.
-class UI_EXPORT InsetsF : public InsetsBase<InsetsF, float> {
+class GFX_EXPORT InsetsF : public InsetsBase<InsetsF, float> {
public:
InsetsF();
InsetsF(float top, float left, float bottom, float right);
diff --git a/chromium/ui/gfx/interpolated_transform.cc b/chromium/ui/gfx/interpolated_transform.cc
index b9698b160cd..4c807f1b4ed 100644
--- a/chromium/ui/gfx/interpolated_transform.cc
+++ b/chromium/ui/gfx/interpolated_transform.cc
@@ -22,10 +22,6 @@ bool IsMultipleOfNinetyDegrees(double degrees) {
return remainder < EPSILON || 90.0 - remainder < EPSILON;
}
-bool IsApproximatelyZero(double value) {
- return fabs(value) < EPSILON;
-}
-
// Returns false if |degrees| is not a multiple of ninety degrees or if
// |rotation| is NULL. It does not affect |rotation| in this case. Otherwise
// *rotation is set to be the appropriate sanitized rotation matrix. That is,
@@ -126,7 +122,7 @@ inline float InterpolatedTransform::ValueBetween(float time,
float t = (time - start_time_) / (end_time_ - start_time_);
return static_cast<float>(
- gfx::Tween::ValueBetween(t, start_value, end_value));
+ gfx::Tween::DoubleValueBetween(t, start_value, end_value));
}
///////////////////////////////////////////////////////////////////////////////
diff --git a/chromium/ui/gfx/interpolated_transform.h b/chromium/ui/gfx/interpolated_transform.h
index 474e3a9dc90..dea9ce91fb3 100644
--- a/chromium/ui/gfx/interpolated_transform.h
+++ b/chromium/ui/gfx/interpolated_transform.h
@@ -25,7 +25,7 @@ namespace ui {
// scale from 0.3 to 1 from between times 0.75 and 1.
//
///////////////////////////////////////////////////////////////////////////////
-class UI_EXPORT InterpolatedTransform {
+class GFX_EXPORT InterpolatedTransform {
public:
InterpolatedTransform();
// The interpolated transform varies only when t in (start_time, end_time).
@@ -84,7 +84,7 @@ class UI_EXPORT InterpolatedTransform {
// Represents an animated rotation.
//
///////////////////////////////////////////////////////////////////////////////
-class UI_EXPORT InterpolatedRotation : public InterpolatedTransform {
+class GFX_EXPORT InterpolatedRotation : public InterpolatedTransform {
public:
InterpolatedRotation(float start_degrees, float end_degrees);
InterpolatedRotation(float start_degrees,
@@ -109,7 +109,7 @@ class UI_EXPORT InterpolatedRotation : public InterpolatedTransform {
// Represents an animated rotation.
//
///////////////////////////////////////////////////////////////////////////////
-class UI_EXPORT InterpolatedAxisAngleRotation : public InterpolatedTransform {
+class GFX_EXPORT InterpolatedAxisAngleRotation : public InterpolatedTransform {
public:
InterpolatedAxisAngleRotation(const gfx::Vector3dF& axis,
float start_degrees,
@@ -138,7 +138,7 @@ class UI_EXPORT InterpolatedAxisAngleRotation : public InterpolatedTransform {
// Represents an animated scale.
//
///////////////////////////////////////////////////////////////////////////////
-class UI_EXPORT InterpolatedScale : public InterpolatedTransform {
+class GFX_EXPORT InterpolatedScale : public InterpolatedTransform {
public:
InterpolatedScale(float start_scale, float end_scale);
InterpolatedScale(float start_scale, float end_scale,
@@ -161,7 +161,7 @@ class UI_EXPORT InterpolatedScale : public InterpolatedTransform {
DISALLOW_COPY_AND_ASSIGN(InterpolatedScale);
};
-class UI_EXPORT InterpolatedTranslation : public InterpolatedTransform {
+class GFX_EXPORT InterpolatedTranslation : public InterpolatedTransform {
public:
InterpolatedTranslation(const gfx::Point& start_pos,
const gfx::Point& end_pos);
@@ -190,7 +190,7 @@ class UI_EXPORT InterpolatedTranslation : public InterpolatedTransform {
// See InterpolatedTransformAboutPivot for an example of its usage.
//
///////////////////////////////////////////////////////////////////////////////
-class UI_EXPORT InterpolatedConstantTransform : public InterpolatedTransform {
+class GFX_EXPORT InterpolatedConstantTransform : public InterpolatedTransform {
public:
explicit InterpolatedConstantTransform(const gfx::Transform& transform);
virtual ~InterpolatedConstantTransform();
@@ -212,7 +212,8 @@ class UI_EXPORT InterpolatedConstantTransform : public InterpolatedTransform {
// P * T * P^-1 where P is a constant transform to the new origin.
//
///////////////////////////////////////////////////////////////////////////////
-class UI_EXPORT InterpolatedTransformAboutPivot : public InterpolatedTransform {
+class GFX_EXPORT InterpolatedTransformAboutPivot
+ : public InterpolatedTransform {
public:
// Takes ownership of the passed transform.
InterpolatedTransformAboutPivot(const gfx::Point& pivot,
@@ -236,7 +237,7 @@ class UI_EXPORT InterpolatedTransformAboutPivot : public InterpolatedTransform {
DISALLOW_COPY_AND_ASSIGN(InterpolatedTransformAboutPivot);
};
-class UI_EXPORT InterpolatedMatrixTransform : public InterpolatedTransform {
+class GFX_EXPORT InterpolatedMatrixTransform : public InterpolatedTransform {
public:
InterpolatedMatrixTransform(const gfx::Transform& start_transform,
const gfx::Transform& end_transform);
diff --git a/chromium/ui/gfx/interpolated_transform_unittest.cc b/chromium/ui/gfx/interpolated_transform_unittest.cc
index acea465d59a..5215a8b07fe 100644
--- a/chromium/ui/gfx/interpolated_transform_unittest.cc
+++ b/chromium/ui/gfx/interpolated_transform_unittest.cc
@@ -19,16 +19,6 @@ void CheckApproximatelyEqual(const gfx::Transform& lhs,
}
}
-float NormalizeAngle(float angle) {
- while (angle < 0.0f) {
- angle += 360.0f;
- }
- while (angle > 360.0f) {
- angle -= 360.0f;
- }
- return angle;
-}
-
} // namespace
TEST(InterpolatedTransformTest, InterpolatedRotation) {
diff --git a/chromium/ui/gfx/matrix3_f.h b/chromium/ui/gfx/matrix3_f.h
index 83f9cd96cf8..a8ae5b578a8 100644
--- a/chromium/ui/gfx/matrix3_f.h
+++ b/chromium/ui/gfx/matrix3_f.h
@@ -10,7 +10,7 @@
namespace gfx {
-class UI_EXPORT Matrix3F {
+class GFX_EXPORT Matrix3F {
public:
~Matrix3F();
diff --git a/chromium/ui/gfx/native_widget_types.h b/chromium/ui/gfx/native_widget_types.h
index 3d7b9d1cd3b..bd14ed50f77 100644
--- a/chromium/ui/gfx/native_widget_types.h
+++ b/chromium/ui/gfx/native_widget_types.h
@@ -171,12 +171,12 @@ typedef PangoFontDescription* NativeFont;
typedef GtkWidget* NativeEditView;
typedef cairo_t* NativeDrawingContext;
typedef void* NativeViewAccessible;
-#elif defined(USE_AURA)
+#elif defined(USE_CAIRO)
typedef PangoFontDescription* NativeFont;
typedef void* NativeEditView;
typedef cairo_t* NativeDrawingContext;
typedef void* NativeViewAccessible;
-#elif defined(OS_ANDROID)
+#else
typedef void* NativeFont;
typedef void* NativeEditView;
typedef void* NativeDrawingContext;
diff --git a/chromium/ui/gfx/ozone/dri/dri_skbitmap.cc b/chromium/ui/gfx/ozone/dri/dri_skbitmap.cc
new file mode 100644
index 00000000000..4fbe0f54d89
--- /dev/null
+++ b/chromium/ui/gfx/ozone/dri/dri_skbitmap.cc
@@ -0,0 +1,208 @@
+// Copyright 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.
+
+#include "ui/gfx/ozone/dri/dri_skbitmap.h"
+
+#include <errno.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <xf86drm.h>
+
+#include "base/compiler_specific.h"
+#include "base/logging.h"
+#include "third_party/skia/include/core/SkPixelRef.h"
+
+namespace gfx {
+
+namespace {
+
+void DestroyDumbBuffer(int fd, uint32_t handle) {
+ struct drm_mode_destroy_dumb destroy_request;
+ destroy_request.handle = handle;
+ drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_request);
+}
+
+// Special DRM implementation of a SkPixelRef. The DRM allocator will create a
+// SkPixelRef for the backing pixels. It will then associate the SkPixelRef with
+// the SkBitmap. SkBitmap will access the allocated memory by locking the pixels
+// in the SkPixelRef.
+// At the end of its life the SkPixelRef is responsible for deallocating the
+// pixel memory.
+class DriSkPixelRef : public SkPixelRef {
+ public:
+ DriSkPixelRef(void* pixels,
+ SkColorTable* color_table_,
+ size_t size,
+ int fd,
+ uint32_t handle);
+ virtual ~DriSkPixelRef();
+
+ virtual void* onLockPixels(SkColorTable** ct) OVERRIDE;
+ virtual void onUnlockPixels() OVERRIDE;
+
+ SK_DECLARE_UNFLATTENABLE_OBJECT()
+ private:
+ // Raw pointer to the pixel memory.
+ void* pixels_;
+
+ // Optional color table associated with the pixel memory.
+ SkColorTable* color_table_;
+
+ // Size of the allocated memory.
+ size_t size_;
+
+ // File descriptor to the graphics card used to allocate/deallocate the
+ // memory.
+ int fd_;
+
+ // Handle for the allocated memory.
+ uint32_t handle_;
+
+ DISALLOW_COPY_AND_ASSIGN(DriSkPixelRef);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// DriSkPixelRef implementation
+
+DriSkPixelRef::DriSkPixelRef(
+ void* pixels,
+ SkColorTable* color_table,
+ size_t size,
+ int fd,
+ uint32_t handle)
+ : pixels_(pixels),
+ color_table_(color_table),
+ size_(size),
+ fd_(fd),
+ handle_(handle) {
+}
+
+DriSkPixelRef::~DriSkPixelRef() {
+ munmap(pixels_, size_);
+ DestroyDumbBuffer(fd_, handle_);
+}
+
+void* DriSkPixelRef::onLockPixels(SkColorTable** ct) {
+ *ct = color_table_;
+ return pixels_;
+}
+
+void DriSkPixelRef::onUnlockPixels() {
+}
+
+} // namespace
+
+// Allocates pixel memory for a SkBitmap using DRM dumb buffers.
+class DriAllocator : public SkBitmap::Allocator {
+ public:
+ DriAllocator();
+
+ virtual bool allocPixelRef(SkBitmap* bitmap,
+ SkColorTable* color_table) OVERRIDE;
+
+ private:
+ bool AllocatePixels(DriSkBitmap* bitmap, SkColorTable* color_table);
+
+ DISALLOW_COPY_AND_ASSIGN(DriAllocator);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// DriAllocator implementation
+
+DriAllocator::DriAllocator() {
+}
+
+bool DriAllocator::allocPixelRef(SkBitmap* bitmap,
+ SkColorTable* color_table) {
+ return AllocatePixels(static_cast<DriSkBitmap*>(bitmap), color_table);
+}
+
+bool DriAllocator::AllocatePixels(DriSkBitmap* bitmap,
+ SkColorTable* color_table) {
+ struct drm_mode_create_dumb request;
+ request.width = bitmap->width();
+ request.height = bitmap->height();
+ request.bpp = bitmap->bytesPerPixel() << 3;
+ request.flags = 0;
+
+ if (drmIoctl(bitmap->get_fd(), DRM_IOCTL_MODE_CREATE_DUMB, &request) < 0) {
+ DLOG(ERROR) << "Cannot create dumb buffer (" << errno << ") "
+ << strerror(errno);
+ return false;
+ }
+
+ CHECK(request.size == bitmap->getSize());
+
+ bitmap->set_handle(request.handle);
+
+ struct drm_mode_map_dumb map_request;
+ map_request.handle = bitmap->get_handle();
+ if (drmIoctl(bitmap->get_fd(), DRM_IOCTL_MODE_MAP_DUMB, &map_request)) {
+ DLOG(ERROR) << "Cannot prepare dumb buffer for mapping (" << errno << ") "
+ << strerror(errno);
+ DestroyDumbBuffer(bitmap->get_fd(), bitmap->get_handle());
+ return false;
+ }
+
+ void* pixels = mmap(0,
+ bitmap->getSize(),
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED,
+ bitmap->get_fd(),
+ map_request.offset);
+ if (pixels == MAP_FAILED) {
+ DLOG(ERROR) << "Cannot mmap dumb buffer (" << errno << ") "
+ << strerror(errno);
+ DestroyDumbBuffer(bitmap->get_fd(), bitmap->get_handle());
+ return false;
+ }
+
+ bitmap->setPixelRef(new DriSkPixelRef(
+ pixels,
+ color_table,
+ bitmap->getSize(),
+ bitmap->get_fd(),
+ bitmap->get_handle()))->unref();
+ bitmap->lockPixels();
+
+ return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// DriSkBitmap implementation
+
+DriSkBitmap::DriSkBitmap(int fd)
+ : fd_(fd),
+ handle_(0),
+ framebuffer_(0) {
+}
+
+DriSkBitmap::~DriSkBitmap() {
+}
+
+bool DriSkBitmap::Initialize() {
+ DriAllocator drm_allocator;
+ return allocPixels(&drm_allocator, NULL);
+}
+
+uint8_t DriSkBitmap::GetColorDepth() const {
+ switch (config()) {
+ case SkBitmap::kNo_Config:
+ case SkBitmap::kA8_Config:
+ return 0;
+ case SkBitmap::kIndex8_Config:
+ return 8;
+ case SkBitmap::kRGB_565_Config:
+ return 16;
+ case SkBitmap::kARGB_4444_Config:
+ return 12;
+ case SkBitmap::kARGB_8888_Config:
+ return 24;
+ default:
+ NOTREACHED();
+ return 0;
+ }
+}
+
+} // namespace gfx
diff --git a/chromium/ui/gfx/ozone/dri/dri_skbitmap.h b/chromium/ui/gfx/ozone/dri/dri_skbitmap.h
new file mode 100644
index 00000000000..f5b8f9455fa
--- /dev/null
+++ b/chromium/ui/gfx/ozone/dri/dri_skbitmap.h
@@ -0,0 +1,57 @@
+// Copyright 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_OZONE_DRI_DRI_SKBITMAP_H_
+#define UI_GFX_OZONE_DRI_DRI_SKBITMAP_H_
+
+#include "base/basictypes.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/gfx/gfx_export.h"
+
+namespace gfx {
+
+// Extend the SkBitmap interface to keep track of additional parameters used by
+// the DRM stack when allocating buffers.
+class GFX_EXPORT DriSkBitmap : public SkBitmap {
+ public:
+ DriSkBitmap(int fd);
+ virtual ~DriSkBitmap();
+
+ // Allocates the backing pixels using DRI.
+ // Return true on success, false otherwise.
+ virtual bool Initialize();
+
+ uint32_t get_handle() const { return handle_; };
+
+ uint32_t get_framebuffer() const { return framebuffer_; };
+
+ int get_fd() const { return fd_; };
+
+ // Return the color depth of a pixel in this buffer.
+ uint8_t GetColorDepth() const;
+
+ private:
+ friend class DriAllocator;
+ friend class HardwareDisplayController;
+
+ void set_handle(uint32_t handle) { handle_ = handle; };
+ void set_framebuffer(uint32_t framebuffer) { framebuffer_ = framebuffer; };
+
+ // File descriptor used by the DRI allocator to request buffers from the DRI
+ // stack.
+ int fd_;
+
+ // Buffer handle used by the DRI allocator.
+ uint32_t handle_;
+
+ // Buffer ID used by the DRI modesettings API. This is set when the buffer is
+ // registered with the CRTC.
+ uint32_t framebuffer_;
+
+ DISALLOW_COPY_AND_ASSIGN(DriSkBitmap);
+};
+
+} // namespace gfx
+
+#endif // UI_GFX_OZONE_DRI_DRI_SKBITMAP_H_
diff --git a/chromium/ui/gfx/ozone/dri/dri_surface.cc b/chromium/ui/gfx/ozone/dri/dri_surface.cc
new file mode 100644
index 00000000000..c9b6af4b562
--- /dev/null
+++ b/chromium/ui/gfx/ozone/dri/dri_surface.cc
@@ -0,0 +1,113 @@
+// Copyright 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.
+
+#include "ui/gfx/ozone/dri/dri_surface.h"
+
+#include <errno.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <xf86drm.h>
+
+#include "base/logging.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "third_party/skia/include/core/SkBitmapDevice.h"
+#include "third_party/skia/include/core/SkCanvas.h"
+#include "ui/gfx/ozone/dri/dri_skbitmap.h"
+#include "ui/gfx/ozone/dri/hardware_display_controller.h"
+#include "ui/gfx/skia_util.h"
+
+namespace gfx {
+
+namespace {
+
+// Extends the SkBitmapDevice to allow setting the SkPixelRef. We use the setter
+// to change the SkPixelRef such that the device always points to the
+// backbuffer.
+class CustomSkBitmapDevice : public SkBitmapDevice {
+ public:
+ CustomSkBitmapDevice(const SkBitmap& bitmap) : SkBitmapDevice(bitmap) {}
+ virtual ~CustomSkBitmapDevice() {}
+
+ void SetPixelRef(SkPixelRef* pixel_ref) { setPixelRef(pixel_ref, 0); }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(CustomSkBitmapDevice);
+};
+
+} // namespace
+
+////////////////////////////////////////////////////////////////////////////////
+// DriSurface implementation
+
+DriSurface::DriSurface(
+ HardwareDisplayController* controller)
+ : controller_(controller),
+ bitmaps_(),
+ front_buffer_(0) {
+}
+
+DriSurface::~DriSurface() {
+}
+
+bool DriSurface::Initialize() {
+ for (int i = 0; i < 2; ++i) {
+ bitmaps_[i].reset(CreateBuffer());
+ // TODO(dnicoara) Should select the configuration based on what the
+ // underlying system supports.
+ bitmaps_[i]->setConfig(SkBitmap::kARGB_8888_Config,
+ controller_->get_mode().hdisplay,
+ controller_->get_mode().vdisplay);
+
+ if (!bitmaps_[i]->Initialize()) {
+ return false;
+ }
+ }
+
+ skia_device_ = skia::AdoptRef(
+ new CustomSkBitmapDevice(*bitmaps_[front_buffer_ ^ 1].get()));
+ skia_canvas_ = skia::AdoptRef(new SkCanvas(skia_device_.get()));
+
+ return true;
+}
+
+uint32_t DriSurface::GetFramebufferId() const {
+ CHECK(bitmaps_[0].get() && bitmaps_[1].get());
+ return bitmaps_[front_buffer_ ^ 1]->get_framebuffer();
+}
+
+// This call is made after the hardware just started displaying our back buffer.
+// We need to update our pointer reference and synchronize the two buffers.
+void DriSurface::SwapBuffers() {
+ CHECK(bitmaps_[0].get() && bitmaps_[1].get());
+
+ // Update our front buffer pointer.
+ front_buffer_ ^= 1;
+
+ // Unlocking will unset the pixel pointer, so it won't be pointing to the old
+ // PixelRef.
+ skia_device_->accessBitmap(false).unlockPixels();
+ // Update the backing pixels for the bitmap device.
+ static_cast<CustomSkBitmapDevice*>(skia_device_.get())->SetPixelRef(
+ bitmaps_[front_buffer_ ^ 1]->pixelRef());
+ // Locking the pixels will set the pixel pointer based on the PixelRef value.
+ skia_device_->accessBitmap(false).lockPixels();
+
+ SkIRect device_damage;
+ skia_canvas_->getClipDeviceBounds(&device_damage);
+ SkRect damage = SkRect::Make(device_damage);
+
+ skia_canvas_->drawBitmapRectToRect(*bitmaps_[front_buffer_].get(),
+ &damage,
+ damage);
+}
+
+SkCanvas* DriSurface::GetDrawableForWidget() {
+ return skia_canvas_.get();
+}
+
+DriSkBitmap* DriSurface::CreateBuffer() {
+ return new DriSkBitmap(controller_->get_fd());
+}
+
+} // namespace gfx
diff --git a/chromium/ui/gfx/ozone/dri/dri_surface.h b/chromium/ui/gfx/ozone/dri/dri_surface.h
new file mode 100644
index 00000000000..53258cf8086
--- /dev/null
+++ b/chromium/ui/gfx/ozone/dri/dri_surface.h
@@ -0,0 +1,168 @@
+// Copyright 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_OZONE_DRI_DRI_SURFACE_H_
+#define UI_GFX_OZONE_DRI_DRI_SURFACE_H_
+
+#include "base/compiler_specific.h"
+#include "base/memory/scoped_ptr.h"
+#include "ui/gfx/gfx_export.h"
+#include "ui/gfx/skia_util.h"
+
+class SkBitmapDevice;
+class SkCanvas;
+
+namespace gfx {
+
+class DriSkBitmap;
+class HardwareDisplayController;
+
+// DriSurface is used to represent a surface that can be scanned out
+// to a monitor. It will store the internal state associated with the drawing
+// surface associated with it. DriSurface also performs all the needed
+// operations to initialize and update the drawing surface.
+//
+// The implementation uses dumb buffers, which is used for software rendering.
+// The intent is to have one DriSurface implementation for a
+// HardwareDisplayController.
+//
+// DoubleBufferedSurface is intended to be the software analog to
+// EGLNativeSurface while DriSurface is intended to provide the glue
+// necessary to initialize and display the surface to the screen.
+//
+// The typical usage pattern is:
+// -----------------------------------------------------------------------------
+// HardwareDisplayController controller;
+// // Initialize controller
+//
+// DriSurface* surface = new DriSurface(controller);
+// surface.Initialize();
+// controller.BindSurfaceToController(surface);
+//
+// while (true) {
+// SkCanvas* canvas = surface->GetDrawableForWidget();
+// DrawStuff(canvas);
+// controller.SchedulePageFlip();
+//
+// Wait for page flip event. The DRM page flip handler will call
+// surface.SwapBuffers();
+// }
+//
+// delete surface;
+// -----------------------------------------------------------------------------
+// In the above example the wait consists of reading a DRM pageflip event from
+// the graphics card file descriptor. This is done by calling |drmHandleEvent|,
+// which will read and process the event. |drmHandleEvent| will call a callback
+// registered by |SchedulePageFlip| which will update the internal state.
+//
+// |SchedulePageFlip| can also be used to limit drawing to the screen's vsync
+// since page flips only happen on vsync. In a threaded environment a message
+// loop would listen on the graphics card file descriptor for an event and
+// |drmHandleEvent| would be called from the message loop. The event handler
+// would also be responsible for updating the renderer's state and signal that
+// it is OK to start drawing the next frame.
+//
+// The following example will illustrate the system state transitions in one
+// iteration of the above loop.
+//
+// 1. Both buffers contain the same image with b[0] being the front buffer
+// (star will represent the frontbuffer).
+// ------- -------
+// | | | |
+// | | | |
+// | | | |
+// | | | |
+// ------- -------
+// b[0]* b[1]
+//
+// 2. Call |GetBackbuffer| to get a SkCanvas wrapper for the backbuffer and draw
+// to it.
+// ------- -------
+// | | | |
+// | | | d |
+// | | | |
+// | | | |
+// ------- -------
+// b[0]* b[1]
+//
+// 3. Call |SchedulePageFlip| to display the backbuffer. At this point we can't
+// modify b[0] because it is the frontbuffer and we can't modify b[1] since it
+// has been scheduled for pageflip. If we do draw in b[1] it is possible that
+// the pageflip and draw happen at the same time and we could get tearing.
+//
+// 4. The pageflip callback is called which will call |SwapSurfaces|. Before
+// |SwapSurfaces| is called the state is as following from the hardware's
+// perspective:
+// ------- -------
+// | | | |
+// | | | d |
+// | | | |
+// | | | |
+// ------- -------
+// b[0] b[1]*
+//
+// 5. |SwapSurfaces| will update out internal reference to the front buffer and
+// synchronize the damaged area such that both buffers are identical. The
+// damaged area is used from the SkCanvas clip.
+// ------- -------
+// | | | |
+// | d | | d |
+// | | | |
+// | | | |
+// ------- -------
+// b[0] b[1]*
+//
+// The synchronization consists of copying the damaged area from the frontbuffer
+// to the backbuffer.
+//
+// At this point we're back to step 1 and can start a new draw iteration.
+class GFX_EXPORT DriSurface {
+ public:
+ DriSurface(HardwareDisplayController* controller);
+
+ virtual ~DriSurface();
+
+ // Used to allocate all necessary buffers for this surface. If the
+ // initialization succeeds, the device is ready to be used for drawing
+ // operations.
+ // Returns true if the initialization is successful, false otherwise.
+ bool Initialize();
+
+ // Returns the ID of the current backbuffer.
+ uint32_t GetFramebufferId() const;
+
+ // Synchronizes and swaps the back buffer with the front buffer.
+ void SwapBuffers();
+
+ // Get a Skia canvas for a backbuffer.
+ SkCanvas* GetDrawableForWidget();
+
+ private:
+ friend class HardwareDisplayController;
+
+ // Used to create the backing buffers.
+ virtual DriSkBitmap* CreateBuffer();
+
+ // Stores DRM information for this output device (connector, encoder, last
+ // CRTC state).
+ HardwareDisplayController* controller_;
+
+ // The actual buffers used for painting.
+ scoped_ptr<DriSkBitmap> bitmaps_[2];
+
+ // BitmapDevice for the current backbuffer.
+ skia::RefPtr<SkBitmapDevice> skia_device_;
+
+ // Canvas for the current backbuffer.
+ skia::RefPtr<SkCanvas> skia_canvas_;
+
+ // Keeps track of which bitmap is |buffers_| is the frontbuffer.
+ int front_buffer_;
+
+ DISALLOW_COPY_AND_ASSIGN(DriSurface);
+};
+
+} // namespace gfx
+
+#endif // UI_GFX_OZONE_DRI_DRI_SURFACE_H_
diff --git a/chromium/ui/gfx/ozone/dri/dri_surface_factory.cc b/chromium/ui/gfx/ozone/dri/dri_surface_factory.cc
new file mode 100644
index 00000000000..4c201373942
--- /dev/null
+++ b/chromium/ui/gfx/ozone/dri/dri_surface_factory.cc
@@ -0,0 +1,317 @@
+// Copyright 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.
+
+#include "ui/gfx/ozone/dri/dri_surface_factory.h"
+
+#include <drm.h>
+#include <errno.h>
+#include <xf86drm.h>
+
+#include "base/message_loop/message_loop.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "third_party/skia/include/core/SkDevice.h"
+#include "ui/gfx/native_widget_types.h"
+#include "ui/gfx/ozone/dri/dri_skbitmap.h"
+#include "ui/gfx/ozone/dri/dri_surface.h"
+#include "ui/gfx/ozone/dri/dri_vsync_provider.h"
+#include "ui/gfx/ozone/dri/dri_wrapper.h"
+#include "ui/gfx/ozone/dri/hardware_display_controller.h"
+
+namespace gfx {
+
+namespace {
+
+const char kDefaultGraphicsCardPath[] = "/dev/dri/card0";
+const char kDPMSProperty[] = "DPMS";
+
+const gfx::AcceleratedWidget kDefaultWidgetHandle = 1;
+
+// DRM callback on page flip events. This callback is triggered after the
+// page flip has happened and the backbuffer is now the new frontbuffer
+// The old frontbuffer is no longer used by the hardware and can be used for
+// future draw operations.
+//
+// |device| will contain a reference to the |DriSurface| object which
+// the event belongs to.
+//
+// TODO(dnicoara) When we have a FD handler for the DRM calls in the message
+// loop, we can move this function in the handler.
+void HandlePageFlipEvent(int fd,
+ unsigned int frame,
+ unsigned int seconds,
+ unsigned int useconds,
+ void* controller) {
+ static_cast<HardwareDisplayController*>(controller)
+ ->OnPageFlipEvent(frame, seconds, useconds);
+}
+
+uint32_t GetDriProperty(int fd, drmModeConnector* connector, const char* name) {
+ for (int i = 0; i < connector->count_props; ++i) {
+ drmModePropertyPtr property = drmModeGetProperty(fd, connector->props[i]);
+ if (!property)
+ continue;
+
+ if (strcmp(property->name, name) == 0) {
+ uint32_t id = property->prop_id;
+ drmModeFreeProperty(property);
+ return id;
+ }
+
+ drmModeFreeProperty(property);
+ }
+ return 0;
+}
+
+uint32_t GetCrtc(int fd, drmModeRes* resources, drmModeConnector* connector) {
+ // If the connector already has an encoder try to re-use.
+ if (connector->encoder_id) {
+ drmModeEncoder* encoder = drmModeGetEncoder(fd, connector->encoder_id);
+ if (encoder) {
+ if (encoder->crtc_id) {
+ uint32_t crtc = encoder->crtc_id;
+ drmModeFreeEncoder(encoder);
+ return crtc;
+ }
+ drmModeFreeEncoder(encoder);
+ }
+ }
+
+ // Try to find an encoder for the connector.
+ for (int i = 0; i < connector->count_encoders; ++i) {
+ drmModeEncoder* encoder = drmModeGetEncoder(fd, connector->encoders[i]);
+ if (!encoder)
+ continue;
+
+ for (int j = 0; j < resources->count_crtcs; ++j) {
+ // Check if the encoder is compatible with this CRTC
+ if (!(encoder->possible_crtcs & (1 << j)))
+ continue;
+
+ drmModeFreeEncoder(encoder);
+ return resources->crtcs[j];
+ }
+ }
+
+ return 0;
+}
+
+} // namespace
+
+DriSurfaceFactory::DriSurfaceFactory()
+ : drm_(),
+ state_(UNINITIALIZED),
+ controller_() {
+}
+
+DriSurfaceFactory::~DriSurfaceFactory() {
+ if (state_ == INITIALIZED)
+ ShutdownHardware();
+}
+
+SurfaceFactoryOzone::HardwareState
+DriSurfaceFactory::InitializeHardware() {
+ CHECK(state_ == UNINITIALIZED);
+
+ // TODO(dnicoara): Short-cut right now. What we want is to look at all the
+ // graphics devices available and select the primary one.
+ drm_.reset(CreateWrapper());
+ if (drm_->get_fd() < 0) {
+ LOG(ERROR) << "Cannot open graphics card '"
+ << kDefaultGraphicsCardPath << "': " << strerror(errno);
+ state_ = FAILED;
+ return state_;
+ }
+
+ state_ = INITIALIZED;
+ return state_;
+}
+
+void DriSurfaceFactory::ShutdownHardware() {
+ CHECK(state_ == INITIALIZED);
+
+ controller_.reset();
+ drm_.reset();
+
+ state_ = UNINITIALIZED;
+}
+
+gfx::AcceleratedWidget DriSurfaceFactory::GetAcceleratedWidget() {
+ CHECK(state_ != FAILED);
+
+ // TODO(dnicoara) When there's more information on which display we want,
+ // then we can return the widget associated with the display.
+ // For now just assume we have 1 display device and return it.
+ if (!controller_.get())
+ controller_.reset(new HardwareDisplayController());
+
+ // TODO(dnicoara) We only have 1 display for now, so only 1 AcceleratedWidget.
+ // When we'll support multiple displays this needs to be changed to return a
+ // different handle for every display.
+ return kDefaultWidgetHandle;
+}
+
+gfx::AcceleratedWidget DriSurfaceFactory::RealizeAcceleratedWidget(
+ gfx::AcceleratedWidget w) {
+ CHECK(state_ == INITIALIZED);
+ // TODO(dnicoara) Once we can handle multiple displays this needs to be
+ // changed.
+ CHECK(w == kDefaultWidgetHandle);
+
+ CHECK(controller_->get_state() ==
+ HardwareDisplayController::UNASSOCIATED);
+
+ // Until now the controller is just a stub. Initializing it will link it to a
+ // hardware display.
+ if (!InitializeControllerForPrimaryDisplay(drm_.get(), controller_.get())) {
+ LOG(ERROR) << "Failed to initialize controller";
+ return gfx::kNullAcceleratedWidget;
+ }
+
+ // Create a surface suitable for the current controller.
+ scoped_ptr<DriSurface> surface(CreateSurface(controller_.get()));
+
+ if (!surface->Initialize()) {
+ LOG(ERROR) << "Failed to initialize surface";
+ return gfx::kNullAcceleratedWidget;
+ }
+
+ // Bind the surface to the controller. This will register the backing buffers
+ // with the hardware CRTC such that we can show the buffers. The controller
+ // takes ownership of the surface.
+ if (!controller_->BindSurfaceToController(surface.Pass())) {
+ LOG(ERROR) << "Failed to bind surface to controller";
+ return gfx::kNullAcceleratedWidget;
+ }
+
+ return reinterpret_cast<gfx::AcceleratedWidget>(controller_->get_surface());
+}
+
+bool DriSurfaceFactory::LoadEGLGLES2Bindings(
+ AddGLLibraryCallback add_gl_library,
+ SetGLGetProcAddressProcCallback set_gl_get_proc_address) {
+ return false;
+}
+
+bool DriSurfaceFactory::AttemptToResizeAcceleratedWidget(
+ gfx::AcceleratedWidget w,
+ const gfx::Rect& bounds) {
+ return false;
+}
+
+bool DriSurfaceFactory::SchedulePageFlip(gfx::AcceleratedWidget w) {
+ CHECK(state_ == INITIALIZED);
+ // TODO(dnicoara) Change this CHECK once we're running with the threaded
+ // compositor.
+ CHECK(base::MessageLoop::current()->type() == base::MessageLoop::TYPE_UI);
+
+ // TODO(dnicoara) Once we can handle multiple displays this needs to be
+ // changed.
+ CHECK(w == kDefaultWidgetHandle);
+
+ if (!controller_->SchedulePageFlip())
+ return false;
+
+ // Only wait for the page flip event to finish if it was properly scheduled.
+ //
+ // TODO(dnicoara) The following call will wait for the page flip event to
+ // complete. This means that it will block until the next VSync. Ideally the
+ // wait should happen in the message loop. The message loop would then
+ // schedule the next draw event. Alternatively, the VSyncProvider could be
+ // used to schedule the next draw. Unfortunately, at this point,
+ // DriOutputDevice does not provide any means to use any of the above
+ // solutions. Note that if the DRM callback does not schedule the next draw,
+ // then some sort of synchronization needs to take place since starting a new
+ // draw before the page flip happened is considered an error. However we can
+ // not use any lock constructs unless we're using the threaded compositor.
+ // Note that the following call does not use any locks, so it is safe to be
+ // made on the UI thread (thought not ideal).
+ WaitForPageFlipEvent(drm_->get_fd());
+
+ return true;
+}
+
+SkCanvas* DriSurfaceFactory::GetCanvasForWidget(
+ gfx::AcceleratedWidget w) {
+ CHECK(state_ == INITIALIZED);
+ return reinterpret_cast<DriSurface*>(w)->GetDrawableForWidget();
+}
+
+gfx::VSyncProvider* DriSurfaceFactory::GetVSyncProvider(
+ gfx::AcceleratedWidget w) {
+ CHECK(state_ == INITIALIZED);
+ return new DriVSyncProvider(controller_.get());
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// DriSurfaceFactory private
+
+DriSurface* DriSurfaceFactory::CreateSurface(
+ HardwareDisplayController* controller) {
+ return new DriSurface(controller);
+}
+
+DriWrapper* DriSurfaceFactory::CreateWrapper() {
+ return new DriWrapper(kDefaultGraphicsCardPath);
+}
+
+bool DriSurfaceFactory::InitializeControllerForPrimaryDisplay(
+ DriWrapper* drm,
+ HardwareDisplayController* controller) {
+ CHECK(state_ == SurfaceFactoryOzone::INITIALIZED);
+
+ drmModeRes* resources = drmModeGetResources(drm->get_fd());
+
+ // Search for an active connector.
+ for (int i = 0; i < resources->count_connectors; ++i) {
+ drmModeConnector* connector = drmModeGetConnector(
+ drm->get_fd(),
+ resources->connectors[i]);
+
+ if (!connector)
+ continue;
+
+ if (connector->connection != DRM_MODE_CONNECTED ||
+ connector->count_modes == 0) {
+ drmModeFreeConnector(connector);
+ continue;
+ }
+
+ uint32_t crtc = GetCrtc(drm->get_fd(), resources, connector);
+
+ if (!crtc)
+ continue;
+
+ uint32_t dpms_property_id = GetDriProperty(drm->get_fd(),
+ connector,
+ kDPMSProperty);
+
+ // TODO(dnicoara) Select one mode for now. In the future we may need to
+ // save all the modes and allow the user to choose a specific mode. Or
+ // even some fullscreen applications may need to change the mode.
+ controller->SetControllerInfo(
+ drm,
+ connector->connector_id,
+ crtc,
+ dpms_property_id,
+ connector->modes[0]);
+
+ drmModeFreeConnector(connector);
+
+ return true;
+ }
+
+ return false;
+}
+
+void DriSurfaceFactory::WaitForPageFlipEvent(int fd) {
+ drmEventContext drm_event;
+ drm_event.version = DRM_EVENT_CONTEXT_VERSION;
+ drm_event.page_flip_handler = HandlePageFlipEvent;
+ drm_event.vblank_handler = NULL;
+
+ // Wait for the page-flip to complete.
+ drmHandleEvent(fd, &drm_event);
+}
+
+} // namespace gfx
diff --git a/chromium/ui/gfx/ozone/dri/dri_surface_factory.h b/chromium/ui/gfx/ozone/dri/dri_surface_factory.h
new file mode 100644
index 00000000000..616e989e910
--- /dev/null
+++ b/chromium/ui/gfx/ozone/dri/dri_surface_factory.h
@@ -0,0 +1,75 @@
+// Copyright 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_OZONE_DRI_DRI_SURFACE_FACTORY_H_
+#define UI_GFX_OZONE_DRI_DRI_SURFACE_FACTORY_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "ui/gfx/ozone/surface_factory_ozone.h"
+
+namespace gfx {
+
+class DriSurface;
+class DriWrapper;
+class HardwareDisplayController;
+
+// SurfaceFactoryOzone implementation on top of DRM/KMS using dumb buffers.
+// This implementation is used in conjunction with the software rendering
+// path.
+class GFX_EXPORT DriSurfaceFactory : public SurfaceFactoryOzone {
+ public:
+ DriSurfaceFactory();
+ virtual ~DriSurfaceFactory();
+
+ virtual HardwareState InitializeHardware() OVERRIDE;
+ virtual void ShutdownHardware() OVERRIDE;
+
+ virtual gfx::AcceleratedWidget GetAcceleratedWidget() OVERRIDE;
+ virtual gfx::AcceleratedWidget RealizeAcceleratedWidget(
+ gfx::AcceleratedWidget w) OVERRIDE;
+
+ virtual bool LoadEGLGLES2Bindings(
+ AddGLLibraryCallback add_gl_library,
+ SetGLGetProcAddressProcCallback set_gl_get_proc_address) OVERRIDE;
+
+ virtual bool AttemptToResizeAcceleratedWidget(
+ gfx::AcceleratedWidget w,
+ const gfx::Rect& bounds) OVERRIDE;
+
+ virtual bool SchedulePageFlip(gfx::AcceleratedWidget w) OVERRIDE;
+
+ virtual SkCanvas* GetCanvasForWidget(gfx::AcceleratedWidget w) OVERRIDE;
+
+ virtual gfx::VSyncProvider* GetVSyncProvider(
+ gfx::AcceleratedWidget w) OVERRIDE;
+
+ private:
+ virtual DriSurface* CreateSurface(
+ HardwareDisplayController* controller);
+
+ virtual DriWrapper* CreateWrapper();
+
+ virtual bool InitializeControllerForPrimaryDisplay(
+ DriWrapper* drm,
+ HardwareDisplayController* controller);
+
+ // Blocks until a DRM event is read.
+ // TODO(dnicoara) Remove once we can safely move DRM event processing in the
+ // message loop while correctly signaling when we're done displaying the
+ // pending frame.
+ virtual void WaitForPageFlipEvent(int fd);
+
+ scoped_ptr<DriWrapper> drm_;
+
+ HardwareState state_;
+
+ // Active output.
+ scoped_ptr<HardwareDisplayController> controller_;
+
+ DISALLOW_COPY_AND_ASSIGN(DriSurfaceFactory);
+};
+
+} // namespace gfx
+
+#endif // UI_GFX_OZONE_DRI_DRI_SURFACE_FACTORY_H_
diff --git a/chromium/ui/gfx/ozone/dri/dri_surface_factory_unittest.cc b/chromium/ui/gfx/ozone/dri/dri_surface_factory_unittest.cc
new file mode 100644
index 00000000000..2e70f642f2a
--- /dev/null
+++ b/chromium/ui/gfx/ozone/dri/dri_surface_factory_unittest.cc
@@ -0,0 +1,292 @@
+// Copyright 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.
+
+#include "base/memory/scoped_ptr.h"
+#include "base/message_loop/message_loop.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/ozone/dri/dri_skbitmap.h"
+#include "ui/gfx/ozone/dri/dri_surface.h"
+#include "ui/gfx/ozone/dri/dri_surface_factory.h"
+#include "ui/gfx/ozone/dri/dri_wrapper.h"
+#include "ui/gfx/ozone/dri/hardware_display_controller.h"
+#include "ui/gfx/ozone/surface_factory_ozone.h"
+
+namespace {
+
+const drmModeModeInfo kDefaultMode =
+ {0, 6, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, {'\0'}};
+
+// Mock file descriptor ID.
+const int kFd = 3;
+
+// Mock connector ID.
+const uint32_t kConnectorId = 1;
+
+// Mock CRTC ID.
+const uint32_t kCrtcId = 1;
+
+const uint32_t kDPMSPropertyId = 1;
+
+const gfx::AcceleratedWidget kDefaultWidgetHandle = 1;
+
+// The real DriWrapper makes actual DRM calls which we can't use in unit tests.
+class MockDriWrapper : public gfx::DriWrapper {
+ public:
+ MockDriWrapper(int fd) : DriWrapper(""),
+ add_framebuffer_expectation_(true),
+ page_flip_expectation_(true) {
+ fd_ = fd;
+ }
+
+ virtual ~MockDriWrapper() { fd_ = -1; }
+
+ virtual drmModeCrtc* GetCrtc(uint32_t crtc_id) OVERRIDE {
+ return new drmModeCrtc;
+ }
+
+ virtual void FreeCrtc(drmModeCrtc* crtc) OVERRIDE {
+ delete crtc;
+ }
+
+ virtual bool SetCrtc(uint32_t crtc_id,
+ uint32_t framebuffer,
+ uint32_t* connectors,
+ drmModeModeInfo* mode) OVERRIDE {
+ return true;
+ }
+
+ virtual bool SetCrtc(drmModeCrtc* crtc, uint32_t* connectors) OVERRIDE {
+ return true;
+ }
+
+ virtual bool AddFramebuffer(const drmModeModeInfo& mode,
+ uint8_t depth,
+ uint8_t bpp,
+ uint32_t stride,
+ uint32_t handle,
+ uint32_t* framebuffer) OVERRIDE {
+ return add_framebuffer_expectation_;
+ }
+
+ virtual bool RemoveFramebuffer(uint32_t framebuffer) OVERRIDE { return true; }
+
+ virtual bool PageFlip(uint32_t crtc_id,
+ uint32_t framebuffer,
+ void* data) OVERRIDE {
+ static_cast<gfx::HardwareDisplayController*>(data)->get_surface()
+ ->SwapBuffers();
+ return page_flip_expectation_;
+ }
+
+ virtual bool ConnectorSetProperty(uint32_t connector_id,
+ uint32_t property_id,
+ uint64_t value) OVERRIDE { return true; }
+
+ void set_add_framebuffer_expectation(bool state) {
+ add_framebuffer_expectation_ = state;
+ }
+
+ void set_page_flip_expectation(bool state) {
+ page_flip_expectation_ = state;
+ }
+
+ private:
+ bool add_framebuffer_expectation_;
+ bool page_flip_expectation_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockDriWrapper);
+};
+
+class MockDriSkBitmap : public gfx::DriSkBitmap {
+ public:
+ MockDriSkBitmap() : DriSkBitmap(kFd) {}
+ virtual ~MockDriSkBitmap() {}
+
+ virtual bool Initialize() OVERRIDE {
+ allocPixels();
+ eraseColor(SK_ColorBLACK);
+ return true;
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MockDriSkBitmap);
+};
+
+class MockDriSurface : public gfx::DriSurface {
+ public:
+ MockDriSurface(gfx::HardwareDisplayController* controller)
+ : DriSurface(controller) {}
+ virtual ~MockDriSurface() {}
+
+ private:
+ virtual gfx::DriSkBitmap* CreateBuffer() OVERRIDE {
+ return new MockDriSkBitmap();
+ }
+
+ DISALLOW_COPY_AND_ASSIGN(MockDriSurface);
+};
+
+// SSFO would normally allocate DRM resources. We can't rely on having a DRM
+// backend to allocate and display our buffers. Thus, we replace these
+// resources with stubs. For DRM calls, we simply use stubs that do nothing and
+// for buffers we use the default SkBitmap allocator.
+class MockDriSurfaceFactory
+ : public gfx::DriSurfaceFactory {
+ public:
+ MockDriSurfaceFactory()
+ : DriSurfaceFactory(),
+ mock_drm_(NULL),
+ drm_wrapper_expectation_(true),
+ initialize_controller_expectation_(true) {}
+ virtual ~MockDriSurfaceFactory() {};
+
+ void set_drm_wrapper_expectation(bool state) {
+ drm_wrapper_expectation_ = state;
+ }
+
+ void set_initialize_controller_expectation(bool state) {
+ initialize_controller_expectation_ = state;
+ }
+
+ MockDriWrapper* get_drm() const {
+ return mock_drm_;
+ }
+
+ private:
+ virtual gfx::DriSurface* CreateSurface(
+ gfx::HardwareDisplayController* controller) OVERRIDE {
+ return new MockDriSurface(controller);
+ }
+
+ virtual gfx::DriWrapper* CreateWrapper() OVERRIDE {
+ if (drm_wrapper_expectation_)
+ mock_drm_ = new MockDriWrapper(kFd);
+ else
+ mock_drm_ = new MockDriWrapper(-1);
+
+ return mock_drm_;
+ }
+
+ // Normally we'd use DRM to figure out the controller configuration. But we
+ // can't use DRM in unit tests, so we just create a fake configuration.
+ virtual bool InitializeControllerForPrimaryDisplay(
+ gfx::DriWrapper* drm,
+ gfx::HardwareDisplayController* controller) OVERRIDE {
+ if (initialize_controller_expectation_) {
+ controller->SetControllerInfo(drm,
+ kConnectorId,
+ kCrtcId,
+ kDPMSPropertyId,
+ kDefaultMode);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ virtual void WaitForPageFlipEvent(int fd) OVERRIDE {}
+
+ MockDriWrapper* mock_drm_;
+ bool drm_wrapper_expectation_;
+ bool initialize_controller_expectation_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockDriSurfaceFactory);
+};
+
+} // namespace
+
+class DriSurfaceFactoryTest : public testing::Test {
+ public:
+ DriSurfaceFactoryTest() {}
+
+ virtual void SetUp() OVERRIDE;
+ virtual void TearDown() OVERRIDE;
+ protected:
+ scoped_ptr<base::MessageLoop> message_loop_;
+ scoped_ptr<MockDriSurfaceFactory> factory_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DriSurfaceFactoryTest);
+};
+
+void DriSurfaceFactoryTest::SetUp() {
+ message_loop_.reset(new base::MessageLoop(base::MessageLoop::TYPE_UI));
+ factory_.reset(new MockDriSurfaceFactory());
+}
+
+void DriSurfaceFactoryTest::TearDown() {
+ factory_.reset();
+ message_loop_.reset();
+}
+
+TEST_F(DriSurfaceFactoryTest, FailInitialization) {
+ factory_->set_drm_wrapper_expectation(false);
+
+ EXPECT_EQ(gfx::SurfaceFactoryOzone::FAILED, factory_->InitializeHardware());
+}
+
+TEST_F(DriSurfaceFactoryTest, SuccessfulInitialization) {
+ EXPECT_EQ(gfx::SurfaceFactoryOzone::INITIALIZED,
+ factory_->InitializeHardware());
+}
+
+TEST_F(DriSurfaceFactoryTest, FailSurfaceInitialization) {
+ factory_->set_initialize_controller_expectation(false);
+
+ EXPECT_EQ(gfx::SurfaceFactoryOzone::INITIALIZED,
+ factory_->InitializeHardware());
+
+ gfx::AcceleratedWidget w = factory_->GetAcceleratedWidget();
+ EXPECT_EQ(kDefaultWidgetHandle, w);
+
+ EXPECT_EQ(gfx::kNullAcceleratedWidget, factory_->RealizeAcceleratedWidget(w));
+}
+
+TEST_F(DriSurfaceFactoryTest, FailBindingSurfaceToController) {
+ EXPECT_EQ(gfx::SurfaceFactoryOzone::INITIALIZED,
+ factory_->InitializeHardware());
+
+ factory_->get_drm()->set_add_framebuffer_expectation(false);
+
+ gfx::AcceleratedWidget w = factory_->GetAcceleratedWidget();
+ EXPECT_EQ(kDefaultWidgetHandle, w);
+
+ EXPECT_EQ(gfx::kNullAcceleratedWidget, factory_->RealizeAcceleratedWidget(w));
+}
+
+TEST_F(DriSurfaceFactoryTest, SuccessfulWidgetRealization) {
+ EXPECT_EQ(gfx::SurfaceFactoryOzone::INITIALIZED,
+ factory_->InitializeHardware());
+
+ gfx::AcceleratedWidget w = factory_->GetAcceleratedWidget();
+ EXPECT_EQ(kDefaultWidgetHandle, w);
+
+ EXPECT_NE(gfx::kNullAcceleratedWidget, factory_->RealizeAcceleratedWidget(w));
+}
+
+TEST_F(DriSurfaceFactoryTest, FailSchedulePageFlip) {
+ EXPECT_EQ(gfx::SurfaceFactoryOzone::INITIALIZED,
+ factory_->InitializeHardware());
+
+ factory_->get_drm()->set_page_flip_expectation(false);
+
+ gfx::AcceleratedWidget w = factory_->GetAcceleratedWidget();
+ EXPECT_EQ(kDefaultWidgetHandle, w);
+
+ EXPECT_NE(gfx::kNullAcceleratedWidget, factory_->RealizeAcceleratedWidget(w));
+
+ EXPECT_FALSE(factory_->SchedulePageFlip(w));
+}
+
+TEST_F(DriSurfaceFactoryTest, SuccessfulSchedulePageFlip) {
+ EXPECT_EQ(gfx::SurfaceFactoryOzone::INITIALIZED,
+ factory_->InitializeHardware());
+
+ gfx::AcceleratedWidget w = factory_->GetAcceleratedWidget();
+ EXPECT_EQ(kDefaultWidgetHandle, w);
+
+ EXPECT_NE(gfx::kNullAcceleratedWidget, factory_->RealizeAcceleratedWidget(w));
+
+ EXPECT_TRUE(factory_->SchedulePageFlip(w));
+}
diff --git a/chromium/ui/gfx/ozone/dri/dri_surface_unittest.cc b/chromium/ui/gfx/ozone/dri/dri_surface_unittest.cc
new file mode 100644
index 00000000000..754659163a2
--- /dev/null
+++ b/chromium/ui/gfx/ozone/dri/dri_surface_unittest.cc
@@ -0,0 +1,212 @@
+// Copyright 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.
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/skia/include/core/SkCanvas.h"
+#include "third_party/skia/include/core/SkColor.h"
+#include "third_party/skia/include/core/SkDevice.h"
+#include "ui/gfx/ozone/dri/dri_skbitmap.h"
+#include "ui/gfx/ozone/dri/dri_surface.h"
+#include "ui/gfx/ozone/dri/hardware_display_controller.h"
+
+namespace {
+
+// Create a basic mode for a 6x4 screen.
+const drmModeModeInfo kDefaultMode =
+ {0, 6, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, {'\0'}};
+
+// Mock file descriptor ID.
+const int kFd = 3;
+
+// Mock connector ID.
+const uint32_t kConnectorId = 1;
+
+// Mock CRTC ID.
+const uint32_t kCrtcId = 1;
+
+// Mock DPMS property ID.
+const uint32_t kDPMSPropertyId = 1;
+
+class MockDriWrapper : public gfx::DriWrapper {
+ public:
+ MockDriWrapper() : DriWrapper(""), id_(1) { fd_ = kFd; }
+ virtual ~MockDriWrapper() { fd_ = -1; }
+
+ virtual drmModeCrtc* GetCrtc(uint32_t crtc_id) OVERRIDE { return NULL; }
+ virtual void FreeCrtc(drmModeCrtc* crtc) OVERRIDE {}
+ virtual bool SetCrtc(uint32_t crtc_id,
+ uint32_t framebuffer,
+ uint32_t* connectors,
+ drmModeModeInfo* mode) OVERRIDE { return true; }
+ virtual bool SetCrtc(drmModeCrtc* crtc, uint32_t* connectors) OVERRIDE {
+ return true;
+ }
+ virtual bool AddFramebuffer(const drmModeModeInfo& mode,
+ uint8_t depth,
+ uint8_t bpp,
+ uint32_t stride,
+ uint32_t handle,
+ uint32_t* framebuffer) OVERRIDE {
+ *framebuffer = id_++;
+ return true;
+ }
+ virtual bool RemoveFramebuffer(uint32_t framebuffer) OVERRIDE { return true; }
+ virtual bool PageFlip(uint32_t crtc_id,
+ uint32_t framebuffer,
+ void* data) OVERRIDE {
+ return true;
+ }
+ virtual bool ConnectorSetProperty(uint32_t connector_id,
+ uint32_t property_id,
+ uint64_t value) OVERRIDE { return true; }
+
+ private:
+ int id_;
+ DISALLOW_COPY_AND_ASSIGN(MockDriWrapper);
+};
+
+class MockDriSkBitmap : public gfx::DriSkBitmap {
+ public:
+ MockDriSkBitmap(int fd,
+ bool initialize_expectation)
+ : DriSkBitmap(fd),
+ initialize_expectation_(initialize_expectation) {}
+ virtual ~MockDriSkBitmap() {}
+
+ virtual bool Initialize() OVERRIDE {
+ if (!initialize_expectation_)
+ return false;
+
+ allocPixels();
+ // Clear the bitmap to black.
+ eraseColor(SK_ColorBLACK);
+
+ return true;
+ }
+ private:
+ bool initialize_expectation_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockDriSkBitmap);
+};
+
+class MockDriSurface : public gfx::DriSurface {
+ public:
+ MockDriSurface(gfx::HardwareDisplayController* controller)
+ : DriSurface(controller),
+ initialize_expectation_(true) {}
+ virtual ~MockDriSurface() {}
+
+ void set_initialize_expectation(bool state) {
+ initialize_expectation_ = state;
+ }
+
+ private:
+ virtual gfx::DriSkBitmap* CreateBuffer() OVERRIDE {
+ return new MockDriSkBitmap(kFd, initialize_expectation_);
+ }
+
+ bool initialize_expectation_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockDriSurface);
+};
+
+} // namespace
+
+class DriSurfaceTest : public testing::Test {
+ public:
+ DriSurfaceTest() {}
+
+ virtual void SetUp() OVERRIDE;
+ virtual void TearDown() OVERRIDE;
+
+ protected:
+ scoped_ptr<MockDriWrapper> drm_;
+ scoped_ptr<gfx::HardwareDisplayController> controller_;
+ scoped_ptr<MockDriSurface> surface_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DriSurfaceTest);
+};
+
+void DriSurfaceTest::SetUp() {
+ drm_.reset(new MockDriWrapper());
+ controller_.reset(new gfx::HardwareDisplayController());
+ controller_->SetControllerInfo(
+ drm_.get(), kConnectorId, kCrtcId, kDPMSPropertyId, kDefaultMode);
+
+ surface_.reset(new MockDriSurface(controller_.get()));
+}
+
+void DriSurfaceTest::TearDown() {
+ surface_.reset();
+ controller_.reset();
+ drm_.reset();
+}
+
+TEST_F(DriSurfaceTest, FailInitialization) {
+ surface_->set_initialize_expectation(false);
+ EXPECT_FALSE(surface_->Initialize());
+}
+
+TEST_F(DriSurfaceTest, SuccessfulInitialization) {
+ EXPECT_TRUE(surface_->Initialize());
+}
+
+TEST_F(DriSurfaceTest, CheckFBIDOnSwap) {
+ EXPECT_TRUE(surface_->Initialize());
+ controller_->BindSurfaceToController(
+ surface_.PassAs<gfx::DriSurface>());
+
+ // Check that the framebuffer ID is correct.
+ EXPECT_EQ(2u, controller_->get_surface()->GetFramebufferId());
+
+ controller_->get_surface()->SwapBuffers();
+
+ EXPECT_EQ(1u, controller_->get_surface()->GetFramebufferId());
+}
+
+TEST_F(DriSurfaceTest, CheckPixelPointerOnSwap) {
+ EXPECT_TRUE(surface_->Initialize());
+
+ void* bitmap_pixels1 = surface_->GetDrawableForWidget()->getDevice()
+ ->accessBitmap(false).getPixels();
+
+ surface_->SwapBuffers();
+
+ void* bitmap_pixels2 = surface_->GetDrawableForWidget()->getDevice()
+ ->accessBitmap(false).getPixels();
+
+ // Check that once the buffers have been swapped the drawable's underlying
+ // pixels have been changed.
+ EXPECT_NE(bitmap_pixels1, bitmap_pixels2);
+}
+
+TEST_F(DriSurfaceTest, CheckCorrectBufferSync) {
+ EXPECT_TRUE(surface_->Initialize());
+
+ SkCanvas* canvas = surface_->GetDrawableForWidget();
+ SkRect clip;
+ // Modify part of the canvas.
+ clip.set(0, 0,
+ canvas->getDeviceSize().width() / 2,
+ canvas->getDeviceSize().height() / 2);
+ canvas->clipRect(clip, SkRegion::kReplace_Op);
+
+ canvas->drawColor(SK_ColorWHITE);
+
+ surface_->SwapBuffers();
+
+ // Verify that the modified contents have been copied over on swap (make sure
+ // the 2 buffers have the same content).
+ for (int i = 0; i < canvas->getDeviceSize().height(); ++i) {
+ for (int j = 0; j < canvas->getDeviceSize().width(); ++j) {
+ if (i < clip.height() && j < clip.width())
+ EXPECT_EQ(SK_ColorWHITE,
+ canvas->getDevice()->accessBitmap(false).getColor(j, i));
+ else
+ EXPECT_EQ(SK_ColorBLACK,
+ canvas->getDevice()->accessBitmap(false).getColor(j, i));
+ }
+ }
+}
diff --git a/chromium/ui/gfx/ozone/dri/dri_vsync_provider.cc b/chromium/ui/gfx/ozone/dri/dri_vsync_provider.cc
new file mode 100644
index 00000000000..b5717e686f1
--- /dev/null
+++ b/chromium/ui/gfx/ozone/dri/dri_vsync_provider.cc
@@ -0,0 +1,32 @@
+// Copyright 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.
+
+#include "ui/gfx/ozone/dri/dri_vsync_provider.h"
+
+#include "base/time/time.h"
+#include "ui/gfx/ozone/dri/hardware_display_controller.h"
+
+namespace gfx {
+
+DriVSyncProvider::DriVSyncProvider(HardwareDisplayController* controller)
+ : controller_(controller) {}
+
+DriVSyncProvider::~DriVSyncProvider() {}
+
+void DriVSyncProvider::GetVSyncParameters(const UpdateVSyncCallback& callback) {
+ // The value is invalid, so we can't update the parameters.
+ if (controller_->get_time_of_last_flip() == 0)
+ return;
+
+ // Stores the time of the last refresh.
+ base::TimeTicks timebase =
+ base::TimeTicks::FromInternalValue(controller_->get_time_of_last_flip());
+ // Stores the refresh rate.
+ base::TimeDelta interval =
+ base::TimeDelta::FromSeconds(1) / controller_->get_mode().vrefresh;
+
+ callback.Run(timebase, interval);
+}
+
+} // namespace gfx
diff --git a/chromium/ui/gfx/ozone/dri/dri_vsync_provider.h b/chromium/ui/gfx/ozone/dri/dri_vsync_provider.h
new file mode 100644
index 00000000000..b6cb6047eb8
--- /dev/null
+++ b/chromium/ui/gfx/ozone/dri/dri_vsync_provider.h
@@ -0,0 +1,29 @@
+// Copyright 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_OZONE_IMPL_DRI_VSYNC_PROVIDER_H_
+#define UI_GFX_OZONE_IMPL_DRI_VSYNC_PROVIDER_H_
+
+#include "ui/gfx/vsync_provider.h"
+
+namespace gfx {
+
+class HardwareDisplayController;
+
+class DriVSyncProvider : public VSyncProvider {
+ public:
+ DriVSyncProvider(HardwareDisplayController* controller);
+ virtual ~DriVSyncProvider();
+
+ virtual void GetVSyncParameters(const UpdateVSyncCallback& callback) OVERRIDE;
+
+ private:
+ HardwareDisplayController* controller_;
+
+ DISALLOW_COPY_AND_ASSIGN(DriVSyncProvider);
+};
+
+} // namespace gfx
+
+#endif // UI_GFX_OZONE_IMPL_DRI_VSYNC_PROVIDER_H_
diff --git a/chromium/ui/gfx/ozone/dri/dri_wrapper.cc b/chromium/ui/gfx/ozone/dri/dri_wrapper.cc
new file mode 100644
index 00000000000..2b1104b444d
--- /dev/null
+++ b/chromium/ui/gfx/ozone/dri/dri_wrapper.cc
@@ -0,0 +1,93 @@
+// Copyright 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.
+
+#include "ui/gfx/ozone/dri/dri_wrapper.h"
+
+#include <fcntl.h>
+#include <unistd.h>
+#include <xf86drmMode.h>
+
+#include "base/logging.h"
+
+namespace gfx {
+
+DriWrapper::DriWrapper(const char* device_path) {
+ fd_ = open(device_path, O_RDWR | O_CLOEXEC);
+}
+
+DriWrapper::~DriWrapper() {
+ if (fd_ >= 0)
+ close(fd_);
+}
+
+drmModeCrtc* DriWrapper::GetCrtc(uint32_t crtc_id) {
+ CHECK(fd_ >= 0);
+ return drmModeGetCrtc(fd_, crtc_id);
+}
+
+void DriWrapper::FreeCrtc(drmModeCrtc* crtc) {
+ drmModeFreeCrtc(crtc);
+}
+
+bool DriWrapper::SetCrtc(uint32_t crtc_id,
+ uint32_t framebuffer,
+ uint32_t* connectors,
+ drmModeModeInfo* mode) {
+ CHECK(fd_ >= 0);
+ return !drmModeSetCrtc(fd_, crtc_id, framebuffer, 0, 0, connectors, 1, mode);
+}
+
+bool DriWrapper::SetCrtc(drmModeCrtc* crtc, uint32_t* connectors) {
+ CHECK(fd_ >= 0);
+ return !drmModeSetCrtc(fd_,
+ crtc->crtc_id,
+ crtc->buffer_id,
+ crtc->x,
+ crtc->y,
+ connectors,
+ 1,
+ &crtc->mode);
+}
+
+bool DriWrapper::AddFramebuffer(const drmModeModeInfo& mode,
+ uint8_t depth,
+ uint8_t bpp,
+ uint32_t stride,
+ uint32_t handle,
+ uint32_t* framebuffer) {
+ CHECK(fd_ >= 0);
+ return !drmModeAddFB(fd_,
+ mode.hdisplay,
+ mode.vdisplay,
+ depth,
+ bpp,
+ stride,
+ handle,
+ framebuffer);
+}
+
+bool DriWrapper::RemoveFramebuffer(uint32_t framebuffer) {
+ CHECK(fd_ >= 0);
+ return !drmModeRmFB(fd_, framebuffer);
+}
+
+bool DriWrapper::PageFlip(uint32_t crtc_id,
+ uint32_t framebuffer,
+ void* data) {
+ CHECK(fd_ >= 0);
+ return !drmModePageFlip(fd_,
+ crtc_id,
+ framebuffer,
+ DRM_MODE_PAGE_FLIP_EVENT,
+ data);
+}
+
+bool DriWrapper::ConnectorSetProperty(uint32_t connector_id,
+ uint32_t property_id,
+ uint64_t value) {
+ CHECK(fd_ >= 0);
+ return !drmModeConnectorSetProperty(fd_, connector_id, property_id, value);
+}
+
+} // namespace gfx
diff --git a/chromium/ui/gfx/ozone/dri/dri_wrapper.h b/chromium/ui/gfx/ozone/dri/dri_wrapper.h
new file mode 100644
index 00000000000..0848132c9ad
--- /dev/null
+++ b/chromium/ui/gfx/ozone/dri/dri_wrapper.h
@@ -0,0 +1,86 @@
+// Copyright 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_OZONE_DRI_DRI_WRAPPER_H_
+#define UI_GFX_OZONE_DRI_DRI_WRAPPER_H_
+
+#include <stdint.h>
+
+#include "base/basictypes.h"
+#include "ui/gfx/gfx_export.h"
+
+typedef struct _drmModeCrtc drmModeCrtc;
+typedef struct _drmModeModeInfo drmModeModeInfo;
+
+namespace gfx {
+
+// Wraps DRM calls into a nice interface. Used to provide different
+// implementations of the DRM calls. For the actual implementation the DRM API
+// would be called. In unit tests this interface would be stubbed.
+class GFX_EXPORT DriWrapper {
+ public:
+ DriWrapper(const char* device_path);
+ virtual ~DriWrapper();
+
+ // Get the CRTC state. This is generally used to save state before using the
+ // CRTC. When the user finishes using the CRTC, the user should restore the
+ // CRTC to it's initial state. Use |SetCrtc| to restore the state.
+ virtual drmModeCrtc* GetCrtc(uint32_t crtc_id);
+
+ // Frees the CRTC mode object.
+ virtual void FreeCrtc(drmModeCrtc* crtc);
+
+ // Used to configure CRTC with ID |crtc_id| to use the connector in
+ // |connectors|. The CRTC will be configured with mode |mode| and will display
+ // the framebuffer with ID |framebuffer|. Before being able to display the
+ // framebuffer, it should be registered with the CRTC using |AddFramebuffer|.
+ virtual bool SetCrtc(uint32_t crtc_id,
+ uint32_t framebuffer,
+ uint32_t* connectors,
+ drmModeModeInfo* mode);
+
+ // Used to set a specific configuration to the CRTC. Normally this function
+ // would be called with a CRTC saved state (from |GetCrtc|) to restore it to
+ // its original configuration.
+ virtual bool SetCrtc(drmModeCrtc* crtc, uint32_t* connectors);
+
+ // Register a buffer with the CRTC. On successful registration, the CRTC will
+ // assign a framebuffer ID to |framebuffer|.
+ virtual bool AddFramebuffer(const drmModeModeInfo& mode,
+ uint8_t depth,
+ uint8_t bpp,
+ uint32_t stride,
+ uint32_t handle,
+ uint32_t* framebuffer);
+
+ // Deregister the given |framebuffer|.
+ virtual bool RemoveFramebuffer(uint32_t framebuffer);
+
+ // Schedules a pageflip for CRTC |crtc_id|. This function will return
+ // immediately. Upon completion of the pageflip event, the CRTC will be
+ // displaying the buffer with ID |framebuffer| and will have a DRM event
+ // queued on |fd_|. |data| is a generic pointer to some information the user
+ // will receive when processing the pageflip event.
+ virtual bool PageFlip(uint32_t crtc_id, uint32_t framebuffer, void* data);
+
+ // Sets the value of property with ID |property_id| to |value|. The property
+ // is applied to the connector with ID |connector_id|.
+ virtual bool ConnectorSetProperty(uint32_t connector_id,
+ uint32_t property_id,
+ uint64_t value);
+
+ int get_fd() const { return fd_; }
+
+ protected:
+ // The file descriptor associated with this wrapper. All DRM operations will
+ // be performed using this FD.
+ int fd_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DriWrapper);
+};
+
+} // namespace gfx
+
+#endif // UI_GFX_OZONE_DRI_DRI_WRAPPER_H_
diff --git a/chromium/ui/gfx/ozone/dri/hardware_display_controller.cc b/chromium/ui/gfx/ozone/dri/hardware_display_controller.cc
new file mode 100644
index 00000000000..6accfc00d53
--- /dev/null
+++ b/chromium/ui/gfx/ozone/dri/hardware_display_controller.cc
@@ -0,0 +1,129 @@
+// Copyright 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.
+
+#include "ui/gfx/ozone/dri/hardware_display_controller.h"
+
+#include <errno.h>
+#include <string.h>
+
+#include "base/basictypes.h"
+#include "base/logging.h"
+#include "base/time/time.h"
+#include "ui/gfx/ozone/dri/dri_skbitmap.h"
+#include "ui/gfx/ozone/dri/dri_surface.h"
+#include "ui/gfx/ozone/dri/dri_wrapper.h"
+
+namespace gfx {
+
+HardwareDisplayController::HardwareDisplayController()
+ : drm_(NULL),
+ connector_id_(0),
+ crtc_id_(0),
+ mode_(),
+ saved_crtc_(NULL),
+ state_(UNASSOCIATED),
+ surface_(),
+ time_of_last_flip_(0) {}
+
+void HardwareDisplayController::SetControllerInfo(
+ DriWrapper* drm,
+ uint32_t connector_id,
+ uint32_t crtc_id,
+ uint32_t dpms_property_id,
+ drmModeModeInfo mode) {
+ drm_ = drm;
+ connector_id_ = connector_id;
+ crtc_id_ = crtc_id;
+ dpms_property_id_ = dpms_property_id;
+ mode_ = mode;
+ saved_crtc_ = drm_->GetCrtc(crtc_id_);
+ state_ = UNINITIALIZED;
+}
+
+HardwareDisplayController::~HardwareDisplayController() {
+ if (saved_crtc_) {
+ if (!drm_->SetCrtc(saved_crtc_, &connector_id_))
+ DLOG(ERROR) << "Failed to restore CRTC state: " << strerror(errno);
+ drm_->FreeCrtc(saved_crtc_);
+ }
+
+ if (surface_.get()) {
+ // Unregister the buffers.
+ for (int i = 0; i < 2; ++i) {
+ if (!drm_->RemoveFramebuffer(surface_->bitmaps_[i]->get_framebuffer()))
+ DLOG(ERROR) << "Failed to remove FB: " << strerror(errno);
+ }
+ }
+}
+
+bool
+HardwareDisplayController::BindSurfaceToController(
+ scoped_ptr<DriSurface> surface) {
+ CHECK(state_ == UNINITIALIZED);
+
+ // Register the buffers.
+ for (int i = 0; i < 2; ++i) {
+ uint32_t fb_id;
+ if (!drm_->AddFramebuffer(mode_,
+ surface->bitmaps_[i]->GetColorDepth(),
+ surface->bitmaps_[i]->bytesPerPixel() << 3,
+ surface->bitmaps_[i]->rowBytes(),
+ surface->bitmaps_[i]->get_handle(),
+ &fb_id)) {
+ DLOG(ERROR) << "Failed to register framebuffer: " << strerror(errno);
+ state_ = FAILED;
+ return false;
+ }
+ surface->bitmaps_[i]->set_framebuffer(fb_id);
+ }
+
+ surface_.reset(surface.release());
+ state_ = SURFACE_INITIALIZED;
+ return true;
+}
+
+bool HardwareDisplayController::SchedulePageFlip() {
+ CHECK(state_ == SURFACE_INITIALIZED || state_ == INITIALIZED);
+
+ if (state_ == SURFACE_INITIALIZED) {
+ // Perform the initial modeset.
+ if (!drm_->SetCrtc(crtc_id_,
+ surface_->GetFramebufferId(),
+ &connector_id_,
+ &mode_)) {
+ DLOG(ERROR) << "Cannot set CRTC: " << strerror(errno);
+ state_ = FAILED;
+ return false;
+ } else {
+ state_ = INITIALIZED;
+ }
+
+ if (dpms_property_id_)
+ drm_->ConnectorSetProperty(connector_id_,
+ dpms_property_id_,
+ DRM_MODE_DPMS_ON);
+ }
+
+ if (!drm_->PageFlip(crtc_id_,
+ surface_->GetFramebufferId(),
+ this)) {
+ state_ = FAILED;
+ LOG(ERROR) << "Cannot page flip: " << strerror(errno);
+ return false;
+ }
+
+ return true;
+}
+
+void HardwareDisplayController::OnPageFlipEvent(unsigned int frame,
+ unsigned int seconds,
+ unsigned int useconds) {
+ time_of_last_flip_ =
+ static_cast<uint64_t>(seconds) * base::Time::kMicrosecondsPerSecond +
+ useconds;
+
+ surface_->SwapBuffers();
+}
+
+} // namespace gfx
diff --git a/chromium/ui/gfx/ozone/dri/hardware_display_controller.h b/chromium/ui/gfx/ozone/dri/hardware_display_controller.h
new file mode 100644
index 00000000000..cae8a6ba821
--- /dev/null
+++ b/chromium/ui/gfx/ozone/dri/hardware_display_controller.h
@@ -0,0 +1,190 @@
+// Copyright 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_OZONE_DRI_HARDWARE_DISPLAY_CONTROLLER_H_
+#define UI_GFX_OZONE_DRI_HARDWARE_DISPLAY_CONTROLLER_H_
+
+#include <stddef.h>
+#include <stdint.h>
+#include <xf86drmMode.h>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
+#include "ui/gfx/gfx_export.h"
+#include "ui/gfx/ozone/dri/dri_wrapper.h"
+
+namespace gfx {
+
+class DriSurface;
+
+// The HDCOz will handle modesettings and scannout operations for hardware
+// devices.
+//
+// In the DRM world there are 3 components that need to be paired up to be able
+// to display an image to the monitor: CRTC (cathode ray tube controller),
+// encoder and connector. The CRTC determines which framebuffer to read, when
+// to scanout and where to scanout. Encoders converts the stream from the CRTC
+// to the appropriate format for the connector. The connector is the physical
+// connection that monitors connect to.
+//
+// There is no 1:1:1 pairing for these components. It is possible for an encoder
+// to be compatible to multiple CRTCs and each connector can be used with
+// multiple encoders. In addition, it is possible to use one CRTC with multiple
+// connectors such that we can display the same image on multiple monitors.
+//
+// For example, the following configuration shows 2 different screens being
+// initialized separately.
+// ------------- -------------
+// | Connector | | Connector |
+// | HDMI | | VGA |
+// ------------- -------------
+// ^ ^
+// | |
+// ------------- -------------
+// | Encoder1 | | Encoder2 |
+// ------------- -------------
+// ^ ^
+// | |
+// ------------- -------------
+// | CRTC1 | | CRTC2 |
+// ------------- -------------
+//
+// In the following configuration 2 different screens are associated with the
+// same CRTC, so on scanout the same framebuffer will be displayed on both
+// monitors.
+// ------------- -------------
+// | Connector | | Connector |
+// | HDMI | | VGA |
+// ------------- -------------
+// ^ ^
+// | |
+// ------------- -------------
+// | Encoder1 | | Encoder2 |
+// ------------- -------------
+// ^ ^
+// | |
+// ----------------------
+// | CRTC1 |
+// ----------------------
+//
+// Note that it is possible to have more connectors than CRTCs which means that
+// only a subset of connectors can be active independently, showing different
+// framebuffers. Though, in this case, it would be possible to have all
+// connectors active if some use the same CRTC to mirror the display.
+//
+// TODO(dnicoara) Need to have a way to detect events (such as monitor
+// connected or disconnected).
+class GFX_EXPORT HardwareDisplayController {
+ public:
+ // Controller states. The state transitions will happen from top to bottom.
+ enum State {
+ // When we allocate a HDCO as a stub. At this point there is no connector
+ // and CRTC associated with this device.
+ UNASSOCIATED,
+
+ // When |SetControllerInfo| is called and the HDCO has the information of
+ // the hardware it will control. At this point it knows everything it needs
+ // to control the hardware but doesn't have a surface.
+ UNINITIALIZED,
+
+ // A surface is associated with the HDCO. This means that the controller can
+ // potentially display the backing surface to the display. Though the
+ // surface framebuffer still needs to be registered with the CRTC.
+ SURFACE_INITIALIZED,
+
+ // The CRTC now knows about the surface attributes.
+ INITIALIZED,
+
+ // Error state if any of the initialization steps fail.
+ FAILED,
+ };
+
+ HardwareDisplayController();
+
+ ~HardwareDisplayController();
+
+ // Set the hardware configuration for this HDCO. Once this is set, the HDCO is
+ // responsible for keeping track of the connector and CRTC and cleaning up
+ // when it is destroyed.
+ void SetControllerInfo(DriWrapper* drm,
+ uint32_t connector_id,
+ uint32_t crtc_id,
+ uint32_t dpms_property_id,
+ drmModeModeInfo mode);
+
+ // Associate the HDCO with a surface implementation and initialize it.
+ bool BindSurfaceToController(scoped_ptr<DriSurface> surface);
+
+ // Schedules the |surface_|'s framebuffer to be displayed on the next vsync
+ // event. The event will be posted on the graphics card file descriptor |fd_|
+ // and it can be read and processed by |drmHandleEvent|. That function can
+ // define the callback for the page flip event. A generic data argument will
+ // be presented to the callback. We use that argument to pass in the HDCO
+ // object the event belongs to.
+ //
+ // Between this call and the callback, the framebuffer used in this call
+ // should not be modified in any way as it would cause screen tearing if the
+ // hardware performed the flip. Note that the frontbuffer should also not
+ // be modified as it could still be displayed.
+ //
+ // Note that this function does not block. Also, this function should not be
+ // called again before the page flip occurrs.
+ //
+ // Returns true if the page flip was successfully registered, false otherwise.
+ bool SchedulePageFlip();
+
+ // Called when the page flip event occurred. The event is provided by the
+ // kernel when a VBlank event finished. This allows the controller to
+ // update internal state and propagate the update to the surface.
+ // The tuple (seconds, useconds) represents the event timestamp. |seconds|
+ // represents the number of seconds while |useconds| represents the
+ // microseconds (< 1 second) in the timestamp.
+ void OnPageFlipEvent(unsigned int frame,
+ unsigned int seconds,
+ unsigned int useconds);
+
+ State get_state() const { return state_; };
+
+ int get_fd() const { return drm_->get_fd(); };
+
+ const drmModeModeInfo& get_mode() const { return mode_; };
+
+ DriSurface* get_surface() const { return surface_.get(); };
+
+ uint64_t get_time_of_last_flip() const {
+ return time_of_last_flip_;
+ };
+
+ private:
+ // Object containing the connection to the graphics device and wraps the API
+ // calls to control it.
+ DriWrapper* drm_;
+
+ // TODO(dnicoara) Need to allow a CRTC to have multiple connectors.
+ uint32_t connector_id_;
+
+ uint32_t crtc_id_;
+
+ uint32_t dpms_property_id_;
+
+ // TODO(dnicoara) Need to store all the modes.
+ drmModeModeInfo mode_;
+
+ // Saved CRTC state from before we used it. Need it to restore state once we
+ // are finished using this device.
+ drmModeCrtc* saved_crtc_;
+
+ State state_;
+
+ scoped_ptr<DriSurface> surface_;
+
+ uint64_t time_of_last_flip_;
+
+ DISALLOW_COPY_AND_ASSIGN(HardwareDisplayController);
+};
+
+} // namespace gfx
+
+#endif // UI_GFX_OZONE_DRI_HARDWARE_DISPLAY_CONTROLLER_H_
diff --git a/chromium/ui/gfx/ozone/dri/hardware_display_controller_unittest.cc b/chromium/ui/gfx/ozone/dri/hardware_display_controller_unittest.cc
new file mode 100644
index 00000000000..3806b5a157b
--- /dev/null
+++ b/chromium/ui/gfx/ozone/dri/hardware_display_controller_unittest.cc
@@ -0,0 +1,301 @@
+// Copyright 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.
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/ozone/dri/dri_skbitmap.h"
+#include "ui/gfx/ozone/dri/dri_surface.h"
+#include "ui/gfx/ozone/dri/dri_wrapper.h"
+#include "ui/gfx/ozone/dri/hardware_display_controller.h"
+
+namespace {
+
+// Create a basic mode for a 6x4 screen.
+const drmModeModeInfo kDefaultMode =
+ {0, 6, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, {'\0'}};
+
+// Mock file descriptor ID.
+const int kFd = 3;
+
+// Mock connector ID.
+const uint32_t kConnectorId = 1;
+
+// Mock CRTC ID.
+const uint32_t kCrtcId = 1;
+
+const uint32_t kDPMSPropertyId = 1;
+
+// The real DriWrapper makes actual DRM calls which we can't use in unit tests.
+class MockDriWrapper : public gfx::DriWrapper {
+ public:
+ MockDriWrapper(int fd) : DriWrapper(""),
+ get_crtc_call_count_(0),
+ free_crtc_call_count_(0),
+ restore_crtc_call_count_(0),
+ add_framebuffer_call_count_(0),
+ remove_framebuffer_call_count_(0),
+ set_crtc_expectation_(true),
+ add_framebuffer_expectation_(true),
+ page_flip_expectation_(true) {
+ fd_ = fd;
+ }
+
+ virtual ~MockDriWrapper() { fd_ = -1; }
+
+ virtual drmModeCrtc* GetCrtc(uint32_t crtc_id) OVERRIDE {
+ get_crtc_call_count_++;
+ return new drmModeCrtc;
+ }
+
+ virtual void FreeCrtc(drmModeCrtc* crtc) OVERRIDE {
+ free_crtc_call_count_++;
+ delete crtc;
+ }
+
+ virtual bool SetCrtc(uint32_t crtc_id,
+ uint32_t framebuffer,
+ uint32_t* connectors,
+ drmModeModeInfo* mode) OVERRIDE {
+ return set_crtc_expectation_;
+ }
+
+ virtual bool SetCrtc(drmModeCrtc* crtc, uint32_t* connectors) OVERRIDE {
+ restore_crtc_call_count_++;
+ return true;
+ }
+
+ virtual bool AddFramebuffer(const drmModeModeInfo& mode,
+ uint8_t depth,
+ uint8_t bpp,
+ uint32_t stride,
+ uint32_t handle,
+ uint32_t* framebuffer) OVERRIDE {
+ add_framebuffer_call_count_++;
+ return add_framebuffer_expectation_;
+ }
+
+ virtual bool RemoveFramebuffer(uint32_t framebuffer) OVERRIDE {
+ remove_framebuffer_call_count_++;
+ return true;
+ }
+
+ virtual bool PageFlip(uint32_t crtc_id,
+ uint32_t framebuffer,
+ void* data) OVERRIDE {
+ return page_flip_expectation_;
+ }
+
+ virtual bool ConnectorSetProperty(uint32_t connector_id,
+ uint32_t property_id,
+ uint64_t value) OVERRIDE { return true; }
+
+ int get_get_crtc_call_count() const {
+ return get_crtc_call_count_;
+ }
+
+ int get_free_crtc_call_count() const {
+ return free_crtc_call_count_;
+ }
+
+ int get_restore_crtc_call_count() const {
+ return restore_crtc_call_count_;
+ }
+
+ int get_add_framebuffer_call_count() const {
+ return add_framebuffer_call_count_;
+ }
+
+ int get_remove_framebuffer_call_count() const {
+ return remove_framebuffer_call_count_;
+ }
+
+ void set_set_crtc_expectation(bool state) {
+ set_crtc_expectation_ = state;
+ }
+
+ void set_add_framebuffer_expectation(bool state) {
+ add_framebuffer_expectation_ = state;
+ }
+
+ void set_page_flip_expectation(bool state) {
+ page_flip_expectation_ = state;
+ }
+
+ private:
+ int get_crtc_call_count_;
+ int free_crtc_call_count_;
+ int restore_crtc_call_count_;
+ int add_framebuffer_call_count_;
+ int remove_framebuffer_call_count_;
+
+ bool set_crtc_expectation_;
+ bool add_framebuffer_expectation_;
+ bool page_flip_expectation_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockDriWrapper);
+};
+
+class MockDriSkBitmap : public gfx::DriSkBitmap {
+ public:
+ MockDriSkBitmap(int fd) : DriSkBitmap(fd) {}
+ virtual ~MockDriSkBitmap() {}
+
+ virtual bool Initialize() OVERRIDE {
+ return allocPixels();
+ }
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MockDriSkBitmap);
+};
+
+class MockDriSurface : public gfx::DriSurface {
+ public:
+ MockDriSurface(gfx::HardwareDisplayController* controller)
+ : DriSurface(controller) {}
+ virtual ~MockDriSurface() {}
+
+ private:
+ virtual gfx::DriSkBitmap* CreateBuffer() OVERRIDE {
+ return new MockDriSkBitmap(kFd);
+ }
+ DISALLOW_COPY_AND_ASSIGN(MockDriSurface);
+};
+
+} // namespace
+
+class HardwareDisplayControllerTest : public testing::Test {
+ public:
+ HardwareDisplayControllerTest() {}
+ virtual ~HardwareDisplayControllerTest() {}
+
+ virtual void SetUp() OVERRIDE;
+ virtual void TearDown() OVERRIDE;
+ protected:
+ scoped_ptr<gfx::HardwareDisplayController> controller_;
+ scoped_ptr<MockDriWrapper> drm_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(HardwareDisplayControllerTest);
+};
+
+void HardwareDisplayControllerTest::SetUp() {
+ controller_.reset(new gfx::HardwareDisplayController());
+ drm_.reset(new MockDriWrapper(kFd));
+}
+
+void HardwareDisplayControllerTest::TearDown() {
+ controller_.reset();
+ drm_.reset();
+}
+
+TEST_F(HardwareDisplayControllerTest, CheckInitialState) {
+ EXPECT_EQ(gfx::HardwareDisplayController::UNASSOCIATED,
+ controller_->get_state());
+}
+
+TEST_F(HardwareDisplayControllerTest,
+ CheckStateAfterControllerIsInitialized) {
+ controller_->SetControllerInfo(
+ drm_.get(), kConnectorId, kCrtcId, kDPMSPropertyId, kDefaultMode);
+
+ EXPECT_EQ(1, drm_->get_get_crtc_call_count());
+ EXPECT_EQ(gfx::HardwareDisplayController::UNINITIALIZED,
+ controller_->get_state());
+}
+
+TEST_F(HardwareDisplayControllerTest, CheckStateAfterSurfaceIsBound) {
+ controller_->SetControllerInfo(
+ drm_.get(), kConnectorId, kCrtcId, kDPMSPropertyId, kDefaultMode);
+ scoped_ptr<gfx::DriSurface> surface(
+ new MockDriSurface(controller_.get()));
+
+ EXPECT_TRUE(surface->Initialize());
+ EXPECT_TRUE(controller_->BindSurfaceToController(surface.Pass()));
+
+ EXPECT_EQ(2, drm_->get_add_framebuffer_call_count());
+ EXPECT_EQ(gfx::HardwareDisplayController::SURFACE_INITIALIZED,
+ controller_->get_state());
+}
+
+TEST_F(HardwareDisplayControllerTest, CheckStateIfBindingFails) {
+ drm_->set_add_framebuffer_expectation(false);
+
+ controller_->SetControllerInfo(
+ drm_.get(), kConnectorId, kCrtcId, kDPMSPropertyId, kDefaultMode);
+ scoped_ptr<gfx::DriSurface> surface(
+ new MockDriSurface(controller_.get()));
+
+ EXPECT_TRUE(surface->Initialize());
+ EXPECT_FALSE(controller_->BindSurfaceToController(surface.Pass()));
+
+ EXPECT_EQ(1, drm_->get_add_framebuffer_call_count());
+ EXPECT_EQ(gfx::HardwareDisplayController::FAILED,
+ controller_->get_state());
+}
+
+TEST_F(HardwareDisplayControllerTest, CheckStateAfterPageFlip) {
+ controller_->SetControllerInfo(
+ drm_.get(), kConnectorId, kCrtcId, kDPMSPropertyId, kDefaultMode);
+ scoped_ptr<gfx::DriSurface> surface(
+ new MockDriSurface(controller_.get()));
+
+ EXPECT_TRUE(surface->Initialize());
+ EXPECT_TRUE(controller_->BindSurfaceToController(surface.Pass()));
+
+ controller_->SchedulePageFlip();
+
+ EXPECT_EQ(gfx::HardwareDisplayController::INITIALIZED,
+ controller_->get_state());
+}
+
+TEST_F(HardwareDisplayControllerTest, CheckStateIfModesetFails) {
+ drm_->set_set_crtc_expectation(false);
+
+ controller_->SetControllerInfo(
+ drm_.get(), kConnectorId, kCrtcId, kDPMSPropertyId, kDefaultMode);
+ scoped_ptr<gfx::DriSurface> surface(
+ new MockDriSurface(controller_.get()));
+
+ EXPECT_TRUE(surface->Initialize());
+ EXPECT_TRUE(controller_->BindSurfaceToController(surface.Pass()));
+
+ controller_->SchedulePageFlip();
+
+ EXPECT_EQ(gfx::HardwareDisplayController::FAILED,
+ controller_->get_state());
+}
+
+TEST_F(HardwareDisplayControllerTest, CheckStateIfPageFlipFails) {
+ drm_->set_page_flip_expectation(false);
+
+ controller_->SetControllerInfo(
+ drm_.get(), kConnectorId, kCrtcId, kDPMSPropertyId, kDefaultMode);
+ scoped_ptr<gfx::DriSurface> surface(
+ new MockDriSurface(controller_.get()));
+
+ EXPECT_TRUE(surface->Initialize());
+ EXPECT_TRUE(controller_->BindSurfaceToController(surface.Pass()));
+
+ controller_->SchedulePageFlip();
+
+ EXPECT_EQ(gfx::HardwareDisplayController::FAILED,
+ controller_->get_state());
+}
+
+TEST_F(HardwareDisplayControllerTest, CheckProperDestruction) {
+ controller_->SetControllerInfo(
+ drm_.get(), kConnectorId, kCrtcId, kDPMSPropertyId, kDefaultMode);
+ scoped_ptr<gfx::DriSurface> surface(
+ new MockDriSurface(controller_.get()));
+
+ EXPECT_TRUE(surface->Initialize());
+ EXPECT_TRUE(controller_->BindSurfaceToController(surface.Pass()));
+
+ EXPECT_EQ(gfx::HardwareDisplayController::SURFACE_INITIALIZED,
+ controller_->get_state());
+
+ controller_.reset();
+
+ EXPECT_EQ(2, drm_->get_remove_framebuffer_call_count());
+ EXPECT_EQ(1, drm_->get_restore_crtc_call_count());
+ EXPECT_EQ(1, drm_->get_free_crtc_call_count());
+}
diff --git a/chromium/ui/gfx/ozone/impl/file_surface_factory.cc b/chromium/ui/gfx/ozone/impl/file_surface_factory.cc
new file mode 100644
index 00000000000..9d34f7f95a3
--- /dev/null
+++ b/chromium/ui/gfx/ozone/impl/file_surface_factory.cc
@@ -0,0 +1,96 @@
+// Copyright 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.
+
+#include "ui/gfx/ozone/impl/file_surface_factory.h"
+
+#include "base/bind.h"
+#include "base/file_util.h"
+#include "base/location.h"
+#include "base/stl_util.h"
+#include "base/threading/worker_pool.h"
+#include "third_party/skia/include/core/SkBitmapDevice.h"
+#include "third_party/skia/include/core/SkDevice.h"
+#include "ui/gfx/codec/png_codec.h"
+
+namespace {
+
+void WriteDataToFile(const base::FilePath& location,
+ const SkBitmap& bitmap) {
+ std::vector<unsigned char> png_data;
+ gfx::PNGCodec::FastEncodeBGRASkBitmap(bitmap, true, &png_data);
+ file_util::WriteFile(location,
+ (char*)vector_as_array(&png_data),
+ png_data.size());
+}
+
+}
+
+namespace gfx {
+
+FileSurfaceFactory::FileSurfaceFactory(
+ const base::FilePath& dump_location)
+ : location_(dump_location) {
+ CHECK(!base::DirectoryExists(location_))
+ << "Location cannot be a directory (" << location_.value() << ")";
+ CHECK(!base::PathExists(location_) || base::PathIsWritable(location_));
+}
+
+FileSurfaceFactory::~FileSurfaceFactory() {}
+
+SurfaceFactoryOzone::HardwareState
+FileSurfaceFactory::InitializeHardware() {
+ return INITIALIZED;
+}
+
+void FileSurfaceFactory::ShutdownHardware() {
+}
+
+AcceleratedWidget FileSurfaceFactory::GetAcceleratedWidget() {
+ return 1;
+}
+
+AcceleratedWidget FileSurfaceFactory::RealizeAcceleratedWidget(
+ AcceleratedWidget widget) {
+ return 1;
+}
+
+bool FileSurfaceFactory::LoadEGLGLES2Bindings(
+ AddGLLibraryCallback add_gl_library,
+ SetGLGetProcAddressProcCallback set_gl_get_proc_address) {
+ return false;
+}
+
+bool FileSurfaceFactory::AttemptToResizeAcceleratedWidget(
+ AcceleratedWidget widget,
+ const Rect& bounds) {
+ device_ = skia::AdoptRef(new SkBitmapDevice(SkBitmap::kARGB_8888_Config,
+ bounds.width(),
+ bounds.height()));
+ canvas_ = skia::AdoptRef(new SkCanvas(device_.get()));
+ return true;
+}
+
+bool FileSurfaceFactory::SchedulePageFlip(AcceleratedWidget widget) {
+ SkBitmap bitmap;
+ bitmap.setConfig(SkBitmap::kARGB_8888_Config,
+ device_->width(),
+ device_->height());
+
+ if (canvas_->readPixels(&bitmap, 0, 0)) {
+ base::WorkerPool::PostTask(FROM_HERE,
+ base::Bind(&WriteDataToFile, location_, bitmap),
+ true);
+ }
+ return true;
+}
+
+SkCanvas* FileSurfaceFactory::GetCanvasForWidget(AcceleratedWidget w) {
+ return canvas_.get();
+}
+
+VSyncProvider* FileSurfaceFactory::GetVSyncProvider(AcceleratedWidget w) {
+ return NULL;
+}
+
+} // namespace gfx
diff --git a/chromium/ui/gfx/ozone/impl/file_surface_factory.h b/chromium/ui/gfx/ozone/impl/file_surface_factory.h
new file mode 100644
index 00000000000..19f1c946a33
--- /dev/null
+++ b/chromium/ui/gfx/ozone/impl/file_surface_factory.h
@@ -0,0 +1,49 @@
+// Copyright 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_OZONE_IMPL_FILE_SURFACE_FACTORY_H_
+#define UI_GFX_OZONE_IMPL_FILE_SURFACE_FACTORY_H_
+
+#include "base/files/file_path.h"
+#include "base/memory/scoped_ptr.h"
+#include "ui/gfx/native_widget_types.h"
+#include "ui/gfx/ozone/surface_factory_ozone.h"
+#include "ui/gfx/skia_util.h"
+
+class SkBitmapDevice;
+class SkCanvas;
+
+namespace gfx {
+
+class GFX_EXPORT FileSurfaceFactory : public SurfaceFactoryOzone {
+ public:
+ explicit FileSurfaceFactory(const base::FilePath& dump_location);
+ virtual ~FileSurfaceFactory();
+
+ private:
+ // SurfaceFactoryOzone:
+ virtual HardwareState InitializeHardware() OVERRIDE;
+ virtual void ShutdownHardware() OVERRIDE;
+ virtual AcceleratedWidget GetAcceleratedWidget() OVERRIDE;
+ virtual AcceleratedWidget RealizeAcceleratedWidget(
+ AcceleratedWidget widget) OVERRIDE;
+ virtual bool LoadEGLGLES2Bindings(
+ AddGLLibraryCallback add_gl_library,
+ SetGLGetProcAddressProcCallback set_gl_get_proc_address) OVERRIDE;
+ virtual bool AttemptToResizeAcceleratedWidget(AcceleratedWidget widget,
+ const Rect& bounds) OVERRIDE;
+ virtual bool SchedulePageFlip(AcceleratedWidget widget) OVERRIDE;
+ virtual SkCanvas* GetCanvasForWidget(AcceleratedWidget widget) OVERRIDE;
+ virtual VSyncProvider* GetVSyncProvider(AcceleratedWidget widget) OVERRIDE;
+
+ base::FilePath location_;
+ skia::RefPtr<SkBitmapDevice> device_;
+ skia::RefPtr<SkCanvas> canvas_;
+
+ DISALLOW_COPY_AND_ASSIGN(FileSurfaceFactory);
+};
+
+} // namespace gfx
+
+#endif // UI_GFX_OZONE_IMPL_FILE_SURFACE_FACTORY_H_
diff --git a/chromium/ui/gfx/ozone/surface_factory_ozone.cc b/chromium/ui/gfx/ozone/surface_factory_ozone.cc
index 9be61f42877..ea8e2f1a0b2 100644
--- a/chromium/ui/gfx/ozone/surface_factory_ozone.cc
+++ b/chromium/ui/gfx/ozone/surface_factory_ozone.cc
@@ -6,6 +6,8 @@
#include <stdlib.h>
+#include "base/command_line.h"
+
namespace gfx {
// static
@@ -23,7 +25,11 @@ class SurfaceFactoryOzoneStub : public SurfaceFactoryOzone {
gfx::AcceleratedWidget w) OVERRIDE {
return 0;
}
- virtual bool LoadEGLGLES2Bindings() OVERRIDE { return true; }
+ virtual bool LoadEGLGLES2Bindings(
+ AddGLLibraryCallback add_gl_library,
+ SetGLGetProcAddressProcCallback set_gl_get_proc_address) OVERRIDE {
+ return true;
+ }
virtual bool AttemptToResizeAcceleratedWidget(
gfx::AcceleratedWidget w,
const gfx::Rect& bounds) OVERRIDE {
@@ -42,7 +48,7 @@ SurfaceFactoryOzone::~SurfaceFactoryOzone() {
}
SurfaceFactoryOzone* SurfaceFactoryOzone::GetInstance() {
- CHECK(impl_) << "SurfaceFactoryOzone accessed before constructed";
+ CHECK(impl_) << "No SurfaceFactoryOzone implementation set.";
return impl_;
}
@@ -65,10 +71,19 @@ intptr_t SurfaceFactoryOzone::GetNativeDisplay() {
return 0;
}
-bool SurfaceFactoryOzone::SchedulePageFlip(gfx::AcceleratedWidget) {
+bool SurfaceFactoryOzone::SchedulePageFlip(gfx::AcceleratedWidget w) {
return true;
}
+SkCanvas* SurfaceFactoryOzone::GetCanvasForWidget(gfx::AcceleratedWidget w) {
+ return NULL;
+}
+
+const int32* SurfaceFactoryOzone::GetEGLSurfaceProperties(
+ const int32* desired_attributes) {
+ return desired_attributes;
+}
+
// static
SurfaceFactoryOzone* SurfaceFactoryOzone::CreateTestHelper() {
return new SurfaceFactoryOzoneStub;
diff --git a/chromium/ui/gfx/ozone/surface_factory_ozone.h b/chromium/ui/gfx/ozone/surface_factory_ozone.h
index 9c5eac23b4f..c09a65ff8c7 100644
--- a/chromium/ui/gfx/ozone/surface_factory_ozone.h
+++ b/chromium/ui/gfx/ozone/surface_factory_ozone.h
@@ -5,22 +5,59 @@
#ifndef UI_GFX_OZONE_SURFACE_LNUX_FACTORY_OZONE_H_
#define UI_GFX_OZONE_SURFACE_LNUX_FACTORY_OZONE_H_
+#include "base/callback.h"
+#include "base/native_library.h"
#include "ui/gfx/gfx_export.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/gfx/rect.h"
+class SkCanvas;
+
namespace gfx {
class Screen;
class VSyncProvider;
+// The Ozone interface allows external implementations to hook into Chromium to
+// provide a system specific implementation. The Ozone interface supports two
+// drawing modes: 1) accelerated drawing through EGL and 2) software drawing
+// through Skia.
+//
+// The following functionality is specific to the drawing mode and may not have
+// any meaningful implementation in the other mode. An implementation must
+// provide functionality for at least one mode.
+//
+// 1) Accelerated Drawing (EGL path):
+//
+// The following functions are specific to EGL:
+// - GetNativeDisplay
+// - LoadEGLGLES2Bindings
+// - GetEGLSurfaceProperties (optional if the properties match the default
+// Chromium ones).
+//
+// 2) Software Drawing (Skia):
+//
+// The following function is specific to the software path:
+// - GetCanvasForWidget
+//
+// The accelerated path can optionally provide support for the software drawing
+// path.
+//
+// The remaining functions are not covered since they are needed in both drawing
+// modes (See comments bellow for descriptions).
class GFX_EXPORT SurfaceFactoryOzone {
public:
// Describes the state of the hardware after initialization.
enum HardwareState {
+ UNINITIALIZED,
INITIALIZED,
FAILED,
};
+ typedef void*(*GLGetProcAddressProc)(const char* name);
+ typedef base::Callback<void(base::NativeLibrary)> AddGLLibraryCallback;
+ typedef base::Callback<void(GLGetProcAddressProc)>
+ SetGLGetProcAddressProcCallback;
+
SurfaceFactoryOzone();
virtual ~SurfaceFactoryOzone();
@@ -46,8 +83,8 @@ class GFX_EXPORT SurfaceFactoryOzone {
// This method must be safe to run inside of the sandbox.
virtual void ShutdownHardware() = 0;
- // Returns the native EGL display. This is generally needed in creating
- // EGL windows.
+ // Returns native platform display handle. This is used to obtain the EGL
+ // display connection for the native display.
virtual intptr_t GetNativeDisplay();
// Obtains an AcceleratedWidget backed by a native Linux framebuffer.
@@ -61,8 +98,11 @@ class GFX_EXPORT SurfaceFactoryOzone {
virtual gfx::AcceleratedWidget RealizeAcceleratedWidget(
gfx::AcceleratedWidget w) = 0;
- // Sets up GL bindings for the native surface.
- virtual bool LoadEGLGLES2Bindings() = 0;
+ // Sets up GL bindings for the native surface. Takes two callback parameters
+ // that allow Ozone to register the GL bindings.
+ virtual bool LoadEGLGLES2Bindings(
+ AddGLLibraryCallback add_gl_library,
+ SetGLGetProcAddressProcCallback set_gl_get_proc_address) = 0;
// If possible attempts to resize the given AcceleratedWidget instance and if
// a resize action was performed returns true, otherwise false (native
@@ -75,6 +115,12 @@ class GFX_EXPORT SurfaceFactoryOzone {
// is needed to perform the actual buffer swap.
virtual bool SchedulePageFlip(gfx::AcceleratedWidget w);
+ // Returns a SkCanvas for the backing buffers. Drawing to the canvas will draw
+ // to the native surface. The canvas is intended for use when no EGL
+ // acceleration is possible. Its implementation is optional when an EGL
+ // backend is provided for rendering.
+ virtual SkCanvas* GetCanvasForWidget(gfx::AcceleratedWidget w);
+
// Returns a gfx::VsyncProvider for the provided AcceleratedWidget. Note
// that this may be called after we have entered the sandbox so if there are
// operations (e.g. opening a file descriptor providing vsync events) that
@@ -82,6 +128,13 @@ class GFX_EXPORT SurfaceFactoryOzone {
// in InitializeHardware. Returns NULL on error.
virtual gfx::VSyncProvider* GetVSyncProvider(gfx::AcceleratedWidget w) = 0;
+ // Returns an array of EGL properties, which can be used in any EGL function
+ // used to select a display configuration. Note that all properties should be
+ // immediately followed by the corresponding desired value and array should be
+ // terminated with EGL_NONE. Ownership of the array is not transferred to
+ // caller. desired_list contains list of desired EGL properties and values.
+ virtual const int32* GetEGLSurfaceProperties(const int32* desired_list);
+
// Create a default SufaceFactoryOzone implementation useful for tests.
static SurfaceFactoryOzone* CreateTestHelper();
diff --git a/chromium/ui/gfx/pango_util.cc b/chromium/ui/gfx/pango_util.cc
index 10bd2538742..1f8ac261b59 100644
--- a/chromium/ui/gfx/pango_util.cc
+++ b/chromium/ui/gfx/pango_util.cc
@@ -136,40 +136,6 @@ double GetPangoResolution() {
return resolution;
}
-void DrawTextOntoCairoSurface(cairo_t* cr,
- const base::string16& text,
- const gfx::Font& font,
- const gfx::Rect& bounds,
- const gfx::Rect& clip,
- SkColor text_color,
- int flags) {
- PangoLayout* layout = pango_cairo_create_layout(cr);
- base::i18n::TextDirection text_direction =
- base::i18n::GetFirstStrongCharacterDirection(text);
- DCHECK(!bounds.IsEmpty());
-
- gfx::SetupPangoLayout(
- layout, text, font, bounds.width(), text_direction, flags);
-
- pango_layout_set_height(layout, bounds.height() * PANGO_SCALE);
-
- cairo_save(cr);
- cairo_rectangle(cr, clip.x(), clip.y(), clip.width(), clip.height());
- cairo_clip(cr);
-
- int width = 0, height = 0;
- pango_layout_get_pixel_size(layout, &width, &height);
- Rect text_rect(bounds.x(), bounds.y(), width, height);
- // Vertically center |text_rect| in |bounds|.
- text_rect += gfx::Vector2d(0, (bounds.height() - text_rect.height()) / 2);
-
- DrawPangoLayout(cr, layout, font, bounds, text_rect,
- text_color, text_direction, flags);
-
- cairo_restore(cr);
- g_object_unref(layout);
-}
-
// Pass a width greater than 0 to force wrapping and eliding.
static void SetupPangoLayoutWithoutFont(
PangoLayout* layout,
@@ -260,7 +226,8 @@ static void SetupPangoLayoutWithoutFont(
if (flags & Canvas::HIDE_PREFIX) {
DCHECK_EQ(1, g_unichar_to_utf8(kAcceleratorChar, NULL));
base::string16 accelerator_removed =
- RemoveAcceleratorChar(text, static_cast<char16>(kAcceleratorChar),
+ RemoveAcceleratorChar(text,
+ static_cast<base::char16>(kAcceleratorChar),
NULL, NULL);
utf8 = UTF16ToUTF8(accelerator_removed);
} else {
@@ -297,60 +264,6 @@ void SetupPangoLayoutWithFontDescription(
pango_layout_set_font_description(layout, desc.get());
}
-void DrawPangoLayout(cairo_t* cr,
- PangoLayout* layout,
- const Font& font,
- const gfx::Rect& bounds,
- const gfx::Rect& text_rect,
- SkColor text_color,
- base::i18n::TextDirection text_direction,
- int flags) {
- double r = SkColorGetR(text_color) / 255.0,
- g = SkColorGetG(text_color) / 255.0,
- b = SkColorGetB(text_color) / 255.0,
- a = SkColorGetA(text_color) / 255.0;
-
- cairo_pattern_t* pattern = NULL;
-
- cairo_save(cr);
-
- // Use a fixed color.
- // Note: We do not elide (fade out the text) here, due to a bug in certain
- // Linux environments (http://crbug.com/123104).
- cairo_set_source_rgba(cr, r, g, b, a);
- cairo_move_to(cr, text_rect.x(), text_rect.y());
- pango_cairo_show_layout(cr, layout);
-
- if (font.GetStyle() & gfx::Font::UNDERLINE) {
- gfx::PlatformFontPango* platform_font =
- static_cast<gfx::PlatformFontPango*>(font.platform_font());
- DrawPangoTextUnderline(cr, platform_font, 0.0, text_rect);
- }
-
- if (pattern)
- cairo_pattern_destroy(pattern);
-
- cairo_restore(cr);
-}
-
-void DrawPangoTextUnderline(cairo_t* cr,
- gfx::PlatformFontPango* platform_font,
- double extra_edge_width,
- const Rect& text_rect) {
- const double underline_y =
- static_cast<double>(text_rect.y()) + text_rect.height() +
- platform_font->underline_position();
- cairo_set_line_width(
- cr, platform_font->underline_thickness() + 2 * extra_edge_width);
- cairo_move_to(cr,
- text_rect.x() - extra_edge_width,
- underline_y);
- cairo_line_to(cr,
- text_rect.x() + text_rect.width() + extra_edge_width,
- underline_y);
- cairo_stroke(cr);
-}
-
size_t GetPangoFontSizeInPixels(PangoFontDescription* pango_font) {
size_t size_in_pixels = pango_font_description_get_size(pango_font);
if (pango_font_description_get_size_is_absolute(pango_font)) {
diff --git a/chromium/ui/gfx/pango_util.h b/chromium/ui/gfx/pango_util.h
index 840163825cd..db60c2e6d58 100644
--- a/chromium/ui/gfx/pango_util.h
+++ b/chromium/ui/gfx/pango_util.h
@@ -50,32 +50,14 @@ class ScopedPangoFontDescription {
DISALLOW_COPY_AND_ASSIGN(ScopedPangoFontDescription);
};
-// Uses Pango to draw text onto |cr|. This is the public method for d
-void UI_EXPORT DrawTextOntoCairoSurface(cairo_t* cr,
- const base::string16& text,
- const gfx::Font& font,
- const gfx::Rect& bounds,
- const gfx::Rect& clip,
- SkColor text_color,
- int flags);
-
// ----------------------------------------------------------------------------
// All other methods in this file are only to be used within the ui/ directory.
// They are shared with internal skia interfaces.
// ----------------------------------------------------------------------------
-// Setup pango |layout|; set the |text|, the font description based on |font|,
-// the |width| in PANGO_SCALE for RTL locale, the base |text_direction|,
-// alignment, ellipsis, word wrapping, resolution, etc.
-void SetupPangoLayout(PangoLayout* layout,
- const base::string16& text,
- const gfx::Font& font,
- int width,
- base::i18n::TextDirection text_direction,
- int flags);
-
-// Setup pango layout |layout| the same way as SetupPangoLayout(), except this
-// sets the font description based on |font_description|.
+// Setup pango |layout|; set the |text|, the font description based on
+// |font_description|, the |width| in PANGO_SCALE for RTL locale, the base
+// |text_direction|, alignment, ellipsis, word wrapping, resolution, etc.
void SetupPangoLayoutWithFontDescription(
PangoLayout* layout,
const base::string16& text,
@@ -84,25 +66,6 @@ void SetupPangoLayoutWithFontDescription(
base::i18n::TextDirection text_direction,
int flags);
-// Draws the |layout| (pango tuple of font, actual text, etc) onto |cr| using
-// |text_color| as the cairo pattern.
-void DrawPangoLayout(cairo_t* cr,
- PangoLayout* layout,
- const Font& font,
- const gfx::Rect& bounds,
- const gfx::Rect& text_rect,
- SkColor text_color,
- base::i18n::TextDirection text_direction,
- int flags);
-
-// Draw an underline under the text using |cr|, which must already be
-// initialized with the correct source. |extra_edge_width| is added to the
-// outer edge of the line.
-void DrawPangoTextUnderline(cairo_t* cr,
- gfx::PlatformFontPango* platform_font,
- double extra_edge_width,
- const Rect& text_rect);
-
// Returns the size in pixels for the specified |pango_font|.
size_t GetPangoFontSizeInPixels(PangoFontDescription* pango_font);
diff --git a/chromium/ui/gfx/path.h b/chromium/ui/gfx/path.h
index f1c7718f9a3..257a65c0102 100644
--- a/chromium/ui/gfx/path.h
+++ b/chromium/ui/gfx/path.h
@@ -12,7 +12,7 @@
namespace gfx {
-class UI_EXPORT Path : public SkPath {
+class GFX_EXPORT Path : public SkPath {
public:
// Used by Path(Point,size_t) constructor.
struct Point {
diff --git a/chromium/ui/gfx/path_win.cc b/chromium/ui/gfx/path_win.cc
index be5d9e22ecb..bce62ac849b 100644
--- a/chromium/ui/gfx/path_win.cc
+++ b/chromium/ui/gfx/path_win.cc
@@ -5,10 +5,25 @@
#include "ui/gfx/path_win.h"
#include "base/memory/scoped_ptr.h"
+#include "base/win/scoped_gdi_object.h"
+#include "third_party/skia/include/core/SkRegion.h"
#include "ui/gfx/path.h"
namespace gfx {
+HRGN CreateHRGNFromSkRegion(const SkRegion& region) {
+ base::win::ScopedRegion temp(::CreateRectRgn(0, 0, 0, 0));
+ base::win::ScopedRegion result(::CreateRectRgn(0, 0, 0, 0));
+
+ for (SkRegion::Iterator i(region); !i.done(); i.next()) {
+ const SkIRect& rect = i.rect();
+ ::SetRectRgn(temp, rect.left(), rect.top(), rect.right(), rect.bottom());
+ ::CombineRgn(result, result, temp, RGN_OR);
+ }
+
+ return result.release();
+}
+
HRGN CreateHRGNFromSkPath(const SkPath& path) {
int point_count = path.getPoints(NULL, 0);
scoped_ptr<SkPoint[]> points(new SkPoint[point_count]);
diff --git a/chromium/ui/gfx/path_win.h b/chromium/ui/gfx/path_win.h
index f64bc80a5ef..317a6fb0700 100644
--- a/chromium/ui/gfx/path_win.h
+++ b/chromium/ui/gfx/path_win.h
@@ -10,12 +10,17 @@
#include "ui/gfx/gfx_export.h"
class SkPath;
+class SkRegion;
namespace gfx {
+// Creates a new HRGN given |region|. The caller is responsible for destroying
+// the returned region.
+GFX_EXPORT HRGN CreateHRGNFromSkRegion(const SkRegion& path);
+
// Creates a new HRGN given |path|. The caller is responsible for destroying
// the returned region.
-UI_EXPORT HRGN CreateHRGNFromSkPath(const SkPath& path);
+GFX_EXPORT HRGN CreateHRGNFromSkPath(const SkPath& path);
} // namespace gfx
diff --git a/chromium/ui/gfx/path_x11.cc b/chromium/ui/gfx/path_x11.cc
index 2cfd10abe34..2fe764fbd4c 100644
--- a/chromium/ui/gfx/path_x11.cc
+++ b/chromium/ui/gfx/path_x11.cc
@@ -7,10 +7,26 @@
#include <X11/Xutil.h>
#include "base/memory/scoped_ptr.h"
+#include "third_party/skia/include/core/SkRegion.h"
#include "ui/gfx/path.h"
namespace gfx {
+Region CreateRegionFromSkRegion(const SkRegion& region) {
+ Region result = XCreateRegion();
+
+ for (SkRegion::Iterator i(region); !i.done(); i.next()) {
+ XRectangle rect;
+ rect.x = i.rect().x();
+ rect.y = i.rect().y();
+ rect.width = i.rect().width();
+ rect.height = i.rect().height();
+ XUnionRectWithRegion(&rect, result, result);
+ }
+
+ return result;
+}
+
Region CreateRegionFromSkPath(const SkPath& path) {
int point_count = path.getPoints(NULL, 0);
scoped_ptr<SkPoint[]> points(new SkPoint[point_count]);
diff --git a/chromium/ui/gfx/path_x11.h b/chromium/ui/gfx/path_x11.h
index e5a309209cc..c6e750742ec 100644
--- a/chromium/ui/gfx/path_x11.h
+++ b/chromium/ui/gfx/path_x11.h
@@ -11,12 +11,17 @@
#include "ui/gfx/gfx_export.h"
class SkPath;
+class SkRegion;
namespace gfx {
+// Creates a new REGION given |region|. The caller is responsible for destroying
+// the returned region.
+GFX_EXPORT REGION* CreateRegionFromSkRegion(const SkRegion& region);
+
// Creates a new REGION given |path|. The caller is responsible for destroying
// the returned region.
-UI_EXPORT REGION* CreateRegionFromSkPath(const SkPath& path);
+GFX_EXPORT REGION* CreateRegionFromSkPath(const SkPath& path);
} // namespace gfx
diff --git a/chromium/ui/gfx/platform_font.h b/chromium/ui/gfx/platform_font.h
index 09bf8be0b3d..bf470983e12 100644
--- a/chromium/ui/gfx/platform_font.h
+++ b/chromium/ui/gfx/platform_font.h
@@ -16,7 +16,7 @@ namespace gfx {
class Font;
-class UI_EXPORT PlatformFont : public base::RefCounted<PlatformFont> {
+class GFX_EXPORT PlatformFont : public base::RefCounted<PlatformFont> {
public:
// Creates an appropriate PlatformFont implementation.
static PlatformFont* CreateDefault();
@@ -42,6 +42,9 @@ class UI_EXPORT PlatformFont : public base::RefCounted<PlatformFont> {
// Returns the baseline, or ascent, of the font.
virtual int GetBaseline() const = 0;
+ // Returns the cap height of the font.
+ virtual int GetCapHeight() const = 0;
+
// Returns the average character width for the font.
virtual int GetAverageCharacterWidth() const = 0;
@@ -57,9 +60,12 @@ class UI_EXPORT PlatformFont : public base::RefCounted<PlatformFont> {
// Returns the style of the font.
virtual int GetStyle() const = 0;
- // Returns the font name in UTF-8.
+ // Returns the specified font name in UTF-8.
virtual std::string GetFontName() const = 0;
+ // Returns the actually used font name in UTF-8.
+ virtual std::string GetActualFontNameForTesting() const = 0;
+
// Returns the font size in pixels.
virtual int GetFontSize() const = 0;
@@ -76,4 +82,3 @@ class UI_EXPORT PlatformFont : public base::RefCounted<PlatformFont> {
} // namespace gfx
#endif // UI_GFX_PLATFORM_FONT_H_
-
diff --git a/chromium/ui/gfx/platform_font_ios.h b/chromium/ui/gfx/platform_font_ios.h
index 789b591415d..ed93a6b6e66 100644
--- a/chromium/ui/gfx/platform_font_ios.h
+++ b/chromium/ui/gfx/platform_font_ios.h
@@ -20,11 +20,13 @@ class PlatformFontIOS : public PlatformFont {
virtual Font DeriveFont(int size_delta, int style) const OVERRIDE;
virtual int GetHeight() const OVERRIDE;
virtual int GetBaseline() const OVERRIDE;
+ virtual int GetCapHeight() const OVERRIDE;
virtual int GetAverageCharacterWidth() const OVERRIDE;
virtual int GetStringWidth(const base::string16& text) const OVERRIDE;
virtual int GetExpectedTextWidth(int length) const OVERRIDE;
virtual int GetStyle() const OVERRIDE;
virtual std::string GetFontName() const OVERRIDE;
+ virtual std::string GetActualFontNameForTesting() const OVERRIDE;
virtual int GetFontSize() const OVERRIDE;
virtual NativeFont GetNativeFont() const OVERRIDE;
@@ -47,6 +49,7 @@ class PlatformFontIOS : public PlatformFont {
// Cached metrics, generated at construction.
int height_;
int ascent_;
+ int cap_height_;
int average_width_;
DISALLOW_COPY_AND_ASSIGN(PlatformFontIOS);
diff --git a/chromium/ui/gfx/platform_font_ios.mm b/chromium/ui/gfx/platform_font_ios.mm
index cfc69cf4964..32dcca4e395 100644
--- a/chromium/ui/gfx/platform_font_ios.mm
+++ b/chromium/ui/gfx/platform_font_ios.mm
@@ -51,6 +51,10 @@ int PlatformFontIOS::GetBaseline() const {
return ascent_;
}
+int PlatformFontIOS::GetCapHeight() const {
+ return cap_height_;
+}
+
int PlatformFontIOS::GetAverageCharacterWidth() const {
return average_width_;
}
@@ -72,6 +76,10 @@ std::string PlatformFontIOS::GetFontName() const {
return font_name_;
}
+std::string PlatformFontIOS::GetActualFontNameForTesting() const {
+ return base::SysNSStringToUTF8([GetNativeFont() familyName]);
+}
+
int PlatformFontIOS::GetFontSize() const {
return font_size_;
}
@@ -103,6 +111,7 @@ void PlatformFontIOS::CalculateMetrics() {
UIFont* font = GetNativeFont();
height_ = font.lineHeight;
ascent_ = font.ascender;
+ cap_height_ = font.capHeight;
average_width_ = [@"x" sizeWithFont:font].width;
}
diff --git a/chromium/ui/gfx/platform_font_mac.h b/chromium/ui/gfx/platform_font_mac.h
index 13c8677c228..2f5f8deb3fe 100644
--- a/chromium/ui/gfx/platform_font_mac.h
+++ b/chromium/ui/gfx/platform_font_mac.h
@@ -6,6 +6,7 @@
#define UI_GFX_PLATFORM_FONT_MAC_H_
#include "base/compiler_specific.h"
+#include "base/mac/scoped_nsobject.h"
#include "ui/gfx/platform_font.h"
namespace gfx {
@@ -21,33 +22,39 @@ class PlatformFontMac : public PlatformFont {
virtual Font DeriveFont(int size_delta, int style) const OVERRIDE;
virtual int GetHeight() const OVERRIDE;
virtual int GetBaseline() const OVERRIDE;
+ virtual int GetCapHeight() const OVERRIDE;
virtual int GetAverageCharacterWidth() const OVERRIDE;
virtual int GetStringWidth(const base::string16& text) const OVERRIDE;
virtual int GetExpectedTextWidth(int length) const OVERRIDE;
virtual int GetStyle() const OVERRIDE;
virtual std::string GetFontName() const OVERRIDE;
+ virtual std::string GetActualFontNameForTesting() const OVERRIDE;
virtual int GetFontSize() const OVERRIDE;
virtual NativeFont GetNativeFont() const OVERRIDE;
private:
- PlatformFontMac(const std::string& font_name, int font_size, int style);
- virtual ~PlatformFontMac() {}
+ PlatformFontMac(const std::string& font_name, int font_size, int font_style);
+ virtual ~PlatformFontMac();
- // Initialize the object with the specified parameters.
- void InitWithNameSizeAndStyle(const std::string& font_name,
- int font_size,
- int style);
-
- // Calculate and cache the font metrics.
+ // Calculates and caches the font metrics.
void CalculateMetrics();
- std::string font_name_;
+ // The NSFont instance for this object. If this object was constructed from an
+ // NSFont instance, this holds that NSFont instance. Otherwise this NSFont
+ // instance is constructed from the name, size, and style, and if there is no
+ // active font that matched those criteria, this object may be nil.
+ base::scoped_nsobject<NSFont> native_font_;
+
+ // The name/size/style trio that specify the font. Initialized in the
+ // constructors.
+ std::string font_name_; // Corresponds to -[NSFont fontFamily].
int font_size_;
- int style_;
+ int font_style_;
- // Cached metrics, generated at construction.
+ // Cached metrics, generated in CalculateMetrics().
int height_;
int ascent_;
+ int cap_height_;
int average_width_;
DISALLOW_COPY_AND_ASSIGN(PlatformFontMac);
diff --git a/chromium/ui/gfx/platform_font_mac.mm b/chromium/ui/gfx/platform_font_mac.mm
index bf0c0bd54ac..877507eb47b 100644
--- a/chromium/ui/gfx/platform_font_mac.mm
+++ b/chromium/ui/gfx/platform_font_mac.mm
@@ -15,33 +15,75 @@
namespace gfx {
+namespace {
+
+// Returns an autoreleased NSFont created with the passed-in specifications.
+NSFont* NSFontWithSpec(const std::string& font_name,
+ int font_size,
+ int font_style) {
+ NSFontSymbolicTraits trait_bits = 0;
+ if (font_style & Font::BOLD)
+ trait_bits |= NSFontBoldTrait;
+ if (font_style & Font::ITALIC)
+ trait_bits |= NSFontItalicTrait;
+ // The Mac doesn't support underline as a font trait, so just drop it.
+ // (Underlines must be added as an attribute on an NSAttributedString.)
+ NSDictionary* traits = @{ NSFontSymbolicTrait : @(trait_bits) };
+
+ NSDictionary* attrs = @{
+ NSFontFamilyAttribute : base::SysUTF8ToNSString(font_name),
+ NSFontTraitsAttribute : traits
+ };
+ NSFontDescriptor* descriptor =
+ [NSFontDescriptor fontDescriptorWithFontAttributes:attrs];
+ NSFont* font = [NSFont fontWithDescriptor:descriptor size:font_size];
+ if (font)
+ return font;
+
+ // Make one fallback attempt by looking up via font name rather than font
+ // family name.
+ attrs = @{
+ NSFontNameAttribute : base::SysUTF8ToNSString(font_name),
+ NSFontTraitsAttribute : traits
+ };
+ descriptor = [NSFontDescriptor fontDescriptorWithFontAttributes:attrs];
+ return [NSFont fontWithDescriptor:descriptor size:font_size];
+}
+
+} // namespace
+
////////////////////////////////////////////////////////////////////////////////
// PlatformFontMac, public:
-PlatformFontMac::PlatformFontMac() {
- font_size_ = [NSFont systemFontSize];
- style_ = gfx::Font::NORMAL;
- NSFont* system_font = [NSFont systemFontOfSize:font_size_];
- font_name_ = base::SysNSStringToUTF8([system_font fontName]);
+PlatformFontMac::PlatformFontMac()
+ : native_font_([[NSFont systemFontOfSize:[NSFont systemFontSize]] retain]),
+ font_name_(base::SysNSStringToUTF8([native_font_ familyName])),
+ font_size_([NSFont systemFontSize]),
+ font_style_(Font::NORMAL) {
CalculateMetrics();
}
-PlatformFontMac::PlatformFontMac(NativeFont native_font) {
- int style = 0;
+PlatformFontMac::PlatformFontMac(NativeFont native_font)
+ : native_font_([native_font retain]),
+ font_name_(base::SysNSStringToUTF8([native_font_ familyName])),
+ font_size_([native_font_ pointSize]),
+ font_style_(Font::NORMAL) {
NSFontSymbolicTraits traits = [[native_font fontDescriptor] symbolicTraits];
if (traits & NSFontItalicTrait)
- style |= Font::ITALIC;
+ font_style_ |= Font::ITALIC;
if (traits & NSFontBoldTrait)
- style |= Font::BOLD;
+ font_style_ |= Font::BOLD;
- InitWithNameSizeAndStyle(base::SysNSStringToUTF8([native_font familyName]),
- [native_font pointSize],
- style);
+ CalculateMetrics();
}
PlatformFontMac::PlatformFontMac(const std::string& font_name,
- int font_size) {
- InitWithNameSizeAndStyle(font_name, font_size, gfx::Font::NORMAL);
+ int font_size)
+ : native_font_([NSFontWithSpec(font_name, font_size, Font::NORMAL) retain]),
+ font_name_(font_name),
+ font_size_(font_size),
+ font_style_(Font::NORMAL) {
+ CalculateMetrics();
}
////////////////////////////////////////////////////////////////////////////////
@@ -59,6 +101,10 @@ int PlatformFontMac::GetBaseline() const {
return ascent_;
}
+int PlatformFontMac::GetCapHeight() const {
+ return cap_height_;
+}
+
int PlatformFontMac::GetAverageCharacterWidth() const {
return average_width_;
}
@@ -73,35 +119,23 @@ int PlatformFontMac::GetExpectedTextWidth(int length) const {
}
int PlatformFontMac::GetStyle() const {
- return style_;
+ return font_style_;
}
std::string PlatformFontMac::GetFontName() const {
return font_name_;
}
+std::string PlatformFontMac::GetActualFontNameForTesting() const {
+ return base::SysNSStringToUTF8([native_font_ familyName]);
+}
+
int PlatformFontMac::GetFontSize() const {
return font_size_;
}
NativeFont PlatformFontMac::GetNativeFont() const {
- // We could cache this, but then we'd have to conditionally change the
- // dtor just for MacOS. Not sure if we want to/need to do that.
- NSFont* font = [NSFont fontWithName:base::SysUTF8ToNSString(font_name_)
- size:font_size_];
-
- if (style_ & Font::BOLD) {
- font = [[NSFontManager sharedFontManager] convertFont:font
- toHaveTrait:NSBoldFontMask];
- }
- if (style_ & Font::ITALIC) {
- font = [[NSFontManager sharedFontManager] convertFont:font
- toHaveTrait:NSItalicFontMask];
- }
- // Mac doesn't support underline as a font trait, just drop it. Underlines
- // can instead be added as an attribute on an NSAttributedString.
-
- return font;
+ return [[native_font_.get() retain] autorelease];
}
////////////////////////////////////////////////////////////////////////////////
@@ -109,25 +143,34 @@ NativeFont PlatformFontMac::GetNativeFont() const {
PlatformFontMac::PlatformFontMac(const std::string& font_name,
int font_size,
- int style) {
- InitWithNameSizeAndStyle(font_name, font_size, style);
+ int font_style)
+ : native_font_([NSFontWithSpec(font_name, font_size, font_style) retain]),
+ font_name_(font_name),
+ font_size_(font_size),
+ font_style_(font_style) {
+ CalculateMetrics();
}
-void PlatformFontMac::InitWithNameSizeAndStyle(const std::string& font_name,
- int font_size,
- int style) {
- font_name_ = font_name;
- font_size_ = font_size;
- style_ = style;
- CalculateMetrics();
+PlatformFontMac::~PlatformFontMac() {
}
void PlatformFontMac::CalculateMetrics() {
- NSFont* font = GetNativeFont();
+ NSFont* font = native_font_.get();
+ if (!font) {
+ // This object was constructed from a font name that doesn't correspond to
+ // an actual font. Don't waste time working out metrics.
+ height_ = 0;
+ ascent_ = 0;
+ cap_height_ = 0;
+ average_width_ = 0;
+ return;
+ }
+
base::scoped_nsobject<NSLayoutManager> layout_manager(
[[NSLayoutManager alloc] init]);
height_ = [layout_manager defaultLineHeightForFont:font];
ascent_ = [font ascender];
+ cap_height_ = [font capHeight];
average_width_ =
NSWidth([font boundingRectForGlyph:[font glyphWithName:@"x"]]);
}
@@ -152,4 +195,3 @@ PlatformFont* PlatformFont::CreateFromNameAndSize(const std::string& font_name,
}
} // namespace gfx
-
diff --git a/chromium/ui/gfx/platform_font_ozone.cc b/chromium/ui/gfx/platform_font_ozone.cc
new file mode 100644
index 00000000000..aef042a0c93
--- /dev/null
+++ b/chromium/ui/gfx/platform_font_ozone.cc
@@ -0,0 +1,25 @@
+// 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.
+
+#include "ui/gfx/platform_font.h"
+
+namespace gfx {
+
+// static
+PlatformFont* PlatformFont::CreateDefault() {
+ return NULL;
+}
+
+// static
+PlatformFont* PlatformFont::CreateFromNativeFont(NativeFont native_font) {
+ return NULL;
+}
+
+// static
+PlatformFont* PlatformFont::CreateFromNameAndSize(const std::string& font_name,
+ int font_size) {
+ return NULL;
+}
+
+} // namespace gfx
diff --git a/chromium/ui/gfx/platform_font_pango.cc b/chromium/ui/gfx/platform_font_pango.cc
index 0ddf363c3f7..db1d7dce351 100644
--- a/chromium/ui/gfx/platform_font_pango.cc
+++ b/chromium/ui/gfx/platform_font_pango.cc
@@ -15,6 +15,7 @@
#include "base/strings/string_split.h"
#include "base/strings/utf_string_conversions.h"
#include "third_party/skia/include/core/SkPaint.h"
+#include "third_party/skia/include/core/SkString.h"
#include "third_party/skia/include/core/SkTypeface.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/font.h"
@@ -182,6 +183,16 @@ int PlatformFontPango::GetBaseline() const {
return ascent_pixels_;
}
+int PlatformFontPango::GetCapHeight() const {
+ // Return the ascent as an approximation because Pango doesn't support cap
+ // height.
+ // TODO(yukishiino): Come up with a better approximation of cap height, or
+ // support cap height metrics. Another option is to have a hard-coded table
+ // of cap height for major fonts used in Chromium/Chrome.
+ // See http://crbug.com/249507
+ return ascent_pixels_;
+}
+
int PlatformFontPango::GetAverageCharacterWidth() const {
const_cast<PlatformFontPango*>(this)->InitPangoMetrics();
return SkScalarRound(average_width_pixels_);
@@ -205,6 +216,12 @@ std::string PlatformFontPango::GetFontName() const {
return font_family_;
}
+std::string PlatformFontPango::GetActualFontNameForTesting() const {
+ SkString family_name;
+ typeface_->getFamilyName(&family_name);
+ return family_name.c_str();
+}
+
int PlatformFontPango::GetFontSize() const {
return font_size_pixels_;
}
@@ -283,7 +300,7 @@ void PlatformFontPango::InitWithNameAndSize(const std::string& font_name,
std::string fallback;
skia::RefPtr<SkTypeface> typeface = skia::AdoptRef(
- SkTypeface::CreateFromName(font_name.c_str(), SkTypeface::kNormal));
+ SkTypeface::CreateFromName(font_name.c_str(), SkTypeface::kNormal));
if (!typeface) {
// A non-scalable font such as .pcf is specified. Falls back to a default
// scalable font.
@@ -381,7 +398,6 @@ void PlatformFontPango::InitPangoMetrics() {
}
}
-
double PlatformFontPango::GetAverageWidth() const {
const_cast<PlatformFontPango*>(this)->InitPangoMetrics();
return average_width_pixels_;
diff --git a/chromium/ui/gfx/platform_font_pango.h b/chromium/ui/gfx/platform_font_pango.h
index 1804f37ddd3..739a633aa47 100644
--- a/chromium/ui/gfx/platform_font_pango.h
+++ b/chromium/ui/gfx/platform_font_pango.h
@@ -18,7 +18,7 @@ class SkPaint;
namespace gfx {
-class UI_EXPORT PlatformFontPango : public PlatformFont {
+class GFX_EXPORT PlatformFontPango : public PlatformFont {
public:
PlatformFontPango();
explicit PlatformFontPango(NativeFont native_font);
@@ -49,11 +49,13 @@ class UI_EXPORT PlatformFontPango : public PlatformFont {
virtual Font DeriveFont(int size_delta, int style) const OVERRIDE;
virtual int GetHeight() const OVERRIDE;
virtual int GetBaseline() const OVERRIDE;
+ virtual int GetCapHeight() const OVERRIDE;
virtual int GetAverageCharacterWidth() const OVERRIDE;
virtual int GetStringWidth(const base::string16& text) const OVERRIDE;
virtual int GetExpectedTextWidth(int length) const OVERRIDE;
virtual int GetStyle() const OVERRIDE;
virtual std::string GetFontName() const OVERRIDE;
+ virtual std::string GetActualFontNameForTesting() const OVERRIDE;
virtual int GetFontSize() const OVERRIDE;
virtual NativeFont GetNativeFont() const OVERRIDE;
@@ -74,8 +76,8 @@ class UI_EXPORT PlatformFontPango : public PlatformFont {
void InitWithNameAndSize(const std::string& font_name, int font_size);
void InitWithTypefaceNameSizeAndStyle(
const skia::RefPtr<SkTypeface>& typeface,
- const std::string& name,
- int size,
+ const std::string& font_family,
+ int font_size,
int style);
void InitFromPlatformFont(const PlatformFontPango* other);
diff --git a/chromium/ui/gfx/platform_font_win.cc b/chromium/ui/gfx/platform_font_win.cc
index 2d4c006f268..0209be6673e 100644
--- a/chromium/ui/gfx/platform_font_win.cc
+++ b/chromium/ui/gfx/platform_font_win.cc
@@ -141,6 +141,10 @@ int PlatformFontWin::GetBaseline() const {
return font_ref_->baseline();
}
+int PlatformFontWin::GetCapHeight() const {
+ return font_ref_->cap_height();
+}
+
int PlatformFontWin::GetAverageCharacterWidth() const {
return font_ref_->ave_char_width();
}
@@ -163,6 +167,13 @@ std::string PlatformFontWin::GetFontName() const {
return font_ref_->font_name();
}
+std::string PlatformFontWin::GetActualFontNameForTesting() const {
+ // With the current implementation on Windows, HFontRef::font_name() returns
+ // the font name taken from the HFONT handle, but it's not the name that comes
+ // from the font's metadata. See http://crbug.com/327287
+ return font_ref_->font_name();
+}
+
std::string PlatformFontWin::GetLocalizedFontName() const {
base::win::ScopedCreateDC memory_dc(CreateCompatibleDC(NULL));
if (!memory_dc.Get())
@@ -235,6 +246,8 @@ PlatformFontWin::HFontRef* PlatformFontWin::CreateHFontRef(HFONT font) {
const int height = std::max<int>(1, font_metrics.tmHeight);
const int baseline = std::max<int>(1, font_metrics.tmAscent);
+ const int cap_height =
+ std::max<int>(1, font_metrics.tmAscent - font_metrics.tmInternalLeading);
const int ave_char_width = std::max<int>(1, font_metrics.tmAveCharWidth);
const int font_size =
std::max<int>(1, font_metrics.tmHeight - font_metrics.tmInternalLeading);
@@ -246,7 +259,8 @@ PlatformFontWin::HFontRef* PlatformFontWin::CreateHFontRef(HFONT font) {
if (font_metrics.tmWeight >= kTextMetricWeightBold)
style |= Font::BOLD;
- return new HFontRef(font, font_size, height, baseline, ave_char_width, style);
+ return new HFontRef(font, font_size, height, baseline, cap_height,
+ ave_char_width, style);
}
PlatformFontWin::PlatformFontWin(HFontRef* hfont_ref) : font_ref_(hfont_ref) {
@@ -256,15 +270,17 @@ PlatformFontWin::PlatformFontWin(HFontRef* hfont_ref) : font_ref_(hfont_ref) {
// PlatformFontWin::HFontRef:
PlatformFontWin::HFontRef::HFontRef(HFONT hfont,
- int font_size,
- int height,
- int baseline,
- int ave_char_width,
- int style)
+ int font_size,
+ int height,
+ int baseline,
+ int cap_height,
+ int ave_char_width,
+ int style)
: hfont_(hfont),
font_size_(font_size),
height_(height),
baseline_(baseline),
+ cap_height_(cap_height),
ave_char_width_(ave_char_width),
style_(style),
dlu_base_x_(-1),
diff --git a/chromium/ui/gfx/platform_font_win.h b/chromium/ui/gfx/platform_font_win.h
index ffa82499d45..4826f777ffc 100644
--- a/chromium/ui/gfx/platform_font_win.h
+++ b/chromium/ui/gfx/platform_font_win.h
@@ -14,7 +14,7 @@
namespace gfx {
-class UI_EXPORT PlatformFontWin : public PlatformFont {
+class GFX_EXPORT PlatformFontWin : public PlatformFont {
public:
PlatformFontWin();
explicit PlatformFontWin(NativeFont native_font);
@@ -57,11 +57,13 @@ class UI_EXPORT PlatformFontWin : public PlatformFont {
virtual Font DeriveFont(int size_delta, int style) const OVERRIDE;
virtual int GetHeight() const OVERRIDE;
virtual int GetBaseline() const OVERRIDE;
+ virtual int GetCapHeight() const OVERRIDE;
virtual int GetAverageCharacterWidth() const OVERRIDE;
virtual int GetStringWidth(const base::string16& text) const OVERRIDE;
virtual int GetExpectedTextWidth(int length) const OVERRIDE;
virtual int GetStyle() const OVERRIDE;
virtual std::string GetFontName() const OVERRIDE;
+ virtual std::string GetActualFontNameForTesting() const OVERRIDE;
virtual int GetFontSize() const OVERRIDE;
virtual NativeFont GetNativeFont() const OVERRIDE;
@@ -84,6 +86,7 @@ class UI_EXPORT PlatformFontWin : public PlatformFont {
int font_size,
int height,
int baseline,
+ int cap_height,
int ave_char_width,
int style);
@@ -91,6 +94,7 @@ class UI_EXPORT PlatformFontWin : public PlatformFont {
HFONT hfont() const { return hfont_; }
int height() const { return height_; }
int baseline() const { return baseline_; }
+ int cap_height() const { return cap_height_; }
int ave_char_width() const { return ave_char_width_; }
int style() const { return style_; }
const std::string& font_name() const { return font_name_; }
@@ -109,6 +113,7 @@ class UI_EXPORT PlatformFontWin : public PlatformFont {
const int font_size_;
const int height_;
const int baseline_;
+ const int cap_height_;
const int ave_char_width_;
const int style_;
// Average character width in dialog units. This is queried lazily from the
@@ -155,4 +160,3 @@ class UI_EXPORT PlatformFontWin : public PlatformFont {
} // namespace gfx
#endif // UI_GFX_PLATFORM_FONT_WIN_H_
-
diff --git a/chromium/ui/gfx/point.h b/chromium/ui/gfx/point.h
index cb233da5274..020c4e1251a 100644
--- a/chromium/ui/gfx/point.h
+++ b/chromium/ui/gfx/point.h
@@ -22,7 +22,7 @@ typedef struct tagPOINT POINT;
namespace gfx {
// A point has an x and y coordinate.
-class UI_EXPORT Point : public PointBase<Point, int, Vector2d> {
+class GFX_EXPORT Point : public PointBase<Point, int, Vector2d> {
public:
Point() : PointBase<Point, int, Vector2d>(0, 0) {}
Point(int x, int y) : PointBase<Point, int, Vector2d>(x, y) {}
diff --git a/chromium/ui/gfx/point3_f.h b/chromium/ui/gfx/point3_f.h
index 5ea0c3181f0..485f6558136 100644
--- a/chromium/ui/gfx/point3_f.h
+++ b/chromium/ui/gfx/point3_f.h
@@ -14,7 +14,7 @@
namespace gfx {
// A point has an x, y and z coordinate.
-class UI_EXPORT Point3F {
+class GFX_EXPORT Point3F {
public:
Point3F() : x_(0), y_(0), z_(0) {}
@@ -90,15 +90,15 @@ inline bool operator!=(const Point3F& lhs, const Point3F& rhs) {
}
// Add a vector to a point, producing a new point offset by the vector.
-UI_EXPORT Point3F operator+(const Point3F& lhs, const Vector3dF& rhs);
+GFX_EXPORT Point3F operator+(const Point3F& lhs, const Vector3dF& rhs);
// Subtract a vector from a point, producing a new point offset by the vector's
// inverse.
-UI_EXPORT Point3F operator-(const Point3F& lhs, const Vector3dF& rhs);
+GFX_EXPORT Point3F operator-(const Point3F& lhs, const Vector3dF& rhs);
// Subtract one point from another, producing a vector that represents the
// distances between the two points along each axis.
-UI_EXPORT Vector3dF operator-(const Point3F& lhs, const Point3F& rhs);
+GFX_EXPORT Vector3dF operator-(const Point3F& lhs, const Point3F& rhs);
inline Point3F PointAtOffsetFromOrigin(const Vector3dF& offset) {
return Point3F(offset.x(), offset.y(), offset.z());
diff --git a/chromium/ui/gfx/point_base.h b/chromium/ui/gfx/point_base.h
index 17f1d5183c4..d7a3951913e 100644
--- a/chromium/ui/gfx/point_base.h
+++ b/chromium/ui/gfx/point_base.h
@@ -15,7 +15,7 @@ namespace gfx {
// A point has an x and y coordinate.
template<typename Class, typename Type, typename VectorClass>
-class UI_EXPORT PointBase {
+class GFX_EXPORT PointBase {
public:
Type x() const { return x_; }
Type y() const { return y_; }
diff --git a/chromium/ui/gfx/point_conversions.h b/chromium/ui/gfx/point_conversions.h
index 9467a9231dc..942edd711cc 100644
--- a/chromium/ui/gfx/point_conversions.h
+++ b/chromium/ui/gfx/point_conversions.h
@@ -11,13 +11,13 @@
namespace gfx {
// Returns a Point with each component from the input PointF floored.
-UI_EXPORT Point ToFlooredPoint(const PointF& point);
+GFX_EXPORT Point ToFlooredPoint(const PointF& point);
// Returns a Point with each component from the input PointF ceiled.
-UI_EXPORT Point ToCeiledPoint(const PointF& point);
+GFX_EXPORT Point ToCeiledPoint(const PointF& point);
// Returns a Point with each component from the input PointF rounded.
-UI_EXPORT Point ToRoundedPoint(const PointF& point);
+GFX_EXPORT Point ToRoundedPoint(const PointF& point);
} // namespace gfx
diff --git a/chromium/ui/gfx/point_f.h b/chromium/ui/gfx/point_f.h
index d9fc18cbbcc..664c18d8aa0 100644
--- a/chromium/ui/gfx/point_f.h
+++ b/chromium/ui/gfx/point_f.h
@@ -14,7 +14,7 @@
namespace gfx {
// A floating version of gfx::Point.
-class UI_EXPORT PointF : public PointBase<PointF, float, Vector2dF> {
+class GFX_EXPORT PointF : public PointBase<PointF, float, Vector2dF> {
public:
PointF() : PointBase<PointF, float, Vector2dF>(0, 0) {}
PointF(float x, float y) : PointBase<PointF, float, Vector2dF>(x, y) {}
@@ -60,7 +60,7 @@ inline PointF PointAtOffsetFromOrigin(const Vector2dF& offset_from_origin) {
return PointF(offset_from_origin.x(), offset_from_origin.y());
}
-UI_EXPORT PointF ScalePoint(const PointF& p, float x_scale, float y_scale);
+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);
diff --git a/chromium/ui/gfx/quad_f.h b/chromium/ui/gfx/quad_f.h
index 5bbc3cd40dd..b8a42e9883e 100644
--- a/chromium/ui/gfx/quad_f.h
+++ b/chromium/ui/gfx/quad_f.h
@@ -17,7 +17,7 @@ namespace gfx {
// A Quad is defined by four corners, allowing it to have edges that are not
// axis-aligned, unlike a Rect.
-class UI_EXPORT QuadF {
+class GFX_EXPORT QuadF {
public:
QuadF() {}
QuadF(const PointF& p1, const PointF& p2, const PointF& p3, const PointF& p4)
@@ -99,10 +99,10 @@ inline bool operator!=(const QuadF& lhs, const QuadF& rhs) {
}
// Add a vector to a quad, offseting each point in the quad by the vector.
-UI_EXPORT QuadF operator+(const QuadF& lhs, const Vector2dF& rhs);
+GFX_EXPORT QuadF operator+(const QuadF& lhs, const Vector2dF& rhs);
// Subtract a vector from a quad, offseting each point in the quad by the
// inverse of the vector.
-UI_EXPORT QuadF operator-(const QuadF& lhs, const Vector2dF& rhs);
+GFX_EXPORT QuadF operator-(const QuadF& lhs, const Vector2dF& rhs);
} // namespace gfx
diff --git a/chromium/ui/gfx/range/range.h b/chromium/ui/gfx/range/range.h
index c41c98c8d03..d0d2a3ec954 100644
--- a/chromium/ui/gfx/range/range.h
+++ b/chromium/ui/gfx/range/range.h
@@ -31,7 +31,7 @@ namespace gfx {
// 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 UI_EXPORT Range {
+class GFX_EXPORT Range {
public:
// Creates an empty range {0,0}.
Range();
@@ -110,7 +110,7 @@ class UI_EXPORT Range {
size_t end_;
};
-UI_EXPORT std::ostream& operator<<(std::ostream& os, const Range& range);
+GFX_EXPORT std::ostream& operator<<(std::ostream& os, const Range& range);
} // namespace gfx
diff --git a/chromium/ui/gfx/rect.h b/chromium/ui/gfx/rect.h
index d983770dca8..df7f9aac366 100644
--- a/chromium/ui/gfx/rect.h
+++ b/chromium/ui/gfx/rect.h
@@ -35,7 +35,7 @@ namespace gfx {
class Insets;
-class UI_EXPORT Rect
+class GFX_EXPORT Rect
: public RectBase<Rect, Point, Size, Insets, Vector2d, int> {
public:
Rect() : RectBase<Rect, Point, Size, Insets, Vector2d, int>(Point()) {}
@@ -89,16 +89,16 @@ inline bool operator!=(const Rect& lhs, const Rect& rhs) {
return !(lhs == rhs);
}
-UI_EXPORT Rect operator+(const Rect& lhs, const Vector2d& rhs);
-UI_EXPORT Rect operator-(const Rect& lhs, const Vector2d& 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;
}
-UI_EXPORT Rect IntersectRects(const Rect& a, const Rect& b);
-UI_EXPORT Rect UnionRects(const Rect& a, const Rect& b);
-UI_EXPORT Rect SubtractRects(const Rect& a, const Rect& b);
+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.
//
@@ -106,7 +106,7 @@ UI_EXPORT Rect SubtractRects(const Rect& a, const Rect& b);
// 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.
-UI_EXPORT Rect BoundingRect(const Point& p1, const Point& p2);
+GFX_EXPORT Rect BoundingRect(const Point& p1, const Point& p2);
inline Rect ScaleToEnclosingRect(const Rect& rect,
float x_scale,
diff --git a/chromium/ui/gfx/rect_base.h b/chromium/ui/gfx/rect_base.h
index f1a286323ec..412836ced19 100644
--- a/chromium/ui/gfx/rect_base.h
+++ b/chromium/ui/gfx/rect_base.h
@@ -24,7 +24,7 @@ template<typename Class,
typename InsetsClass,
typename VectorClass,
typename Type>
-class UI_EXPORT RectBase {
+class GFX_EXPORT RectBase {
public:
Type x() const { return origin_.x(); }
void set_x(Type x) { origin_.set_x(x); }
@@ -143,6 +143,16 @@ class UI_EXPORT RectBase {
// same height) with the given rectangle, and the rectangles do not overlap.
bool SharesEdgeWith(const Class& rect) const;
+ // Returns the manhattan distance from the rect to the point. If the point is
+ // inside the rect, returns 0.
+ Type ManhattanDistanceToPoint(const PointClass& 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 Type.
+ Type ManhattanInternalDistance(const Class& rect) const;
+
protected:
RectBase(const PointClass& origin, const SizeClass& size)
: origin_(origin), size_(size) {}
diff --git a/chromium/ui/gfx/rect_base_impl.h b/chromium/ui/gfx/rect_base_impl.h
index e44bc00bace..52201691a1b 100644
--- a/chromium/ui/gfx/rect_base_impl.h
+++ b/chromium/ui/gfx/rect_base_impl.h
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <limits>
+
#include "ui/gfx/rect_base.h"
#include "base/logging.h"
@@ -9,7 +11,7 @@
// This file provides the implementation for RectBaese template and
// used to instantiate the base class for Rect and RectF classes.
-#if !defined(UI_IMPLEMENTATION)
+#if !defined(GFX_IMPLEMENTATION)
#error "This file is intended for UI implementation only"
#endif
@@ -314,4 +316,40 @@ bool RectBase<Class, PointClass, SizeClass, InsetsClass, VectorClass, Type>::
(y() == rect.bottom() || bottom() == rect.y()));
}
+template<typename Class,
+ typename PointClass,
+ typename SizeClass,
+ typename InsetsClass,
+ typename VectorClass,
+ typename Type>
+Type RectBase<Class, PointClass, SizeClass, InsetsClass, VectorClass, Type>::
+ ManhattanDistanceToPoint(const PointClass& point) const {
+ Type x_distance = std::max<Type>(0, std::max(
+ x() - point.x(), point.x() - right()));
+ Type y_distance = std::max<Type>(0, std::max(
+ y() - point.y(), point.y() - bottom()));
+
+ return x_distance + y_distance;
+}
+
+template<typename Class,
+ typename PointClass,
+ typename SizeClass,
+ typename InsetsClass,
+ typename VectorClass,
+ typename Type>
+Type RectBase<Class, PointClass, SizeClass, InsetsClass, VectorClass, Type>::
+ ManhattanInternalDistance(const Class& rect) const {
+ Class c(x(), y(), width(), height());
+ c.Union(rect);
+
+ static const Type kEpsilon = std::numeric_limits<Type>::is_integer
+ ? 1
+ : std::numeric_limits<Type>::epsilon();
+
+ Type x = std::max<Type>(0, c.width() - width() - rect.width() + kEpsilon);
+ Type y = std::max<Type>(0, c.height() - height() - rect.height() + kEpsilon);
+ return x + y;
+}
+
} // namespace gfx
diff --git a/chromium/ui/gfx/rect_conversions.h b/chromium/ui/gfx/rect_conversions.h
index 854fb6ea392..988f6c76418 100644
--- a/chromium/ui/gfx/rect_conversions.h
+++ b/chromium/ui/gfx/rect_conversions.h
@@ -11,25 +11,25 @@
namespace gfx {
// Returns the smallest Rect that encloses the given RectF.
-UI_EXPORT Rect ToEnclosingRect(const RectF& rect);
+GFX_EXPORT Rect ToEnclosingRect(const RectF& rect);
// Returns the largest Rect that is enclosed by the given RectF.
-UI_EXPORT Rect ToEnclosedRect(const RectF& rect);
+GFX_EXPORT Rect ToEnclosedRect(const RectF& rect);
// Returns the Rect after snapping the corners of the RectF to an integer grid.
// This should only be used when the RectF you provide is expected to be an
// integer rect with floating point error. If it is an arbitrary RectF, then
// you should use a different method.
-UI_EXPORT Rect ToNearestRect(const RectF& rect);
+GFX_EXPORT Rect ToNearestRect(const RectF& rect);
// Returns true if the Rect produced after snapping the corners of the RectF
// to an integer grid is withing |distance|.
-UI_EXPORT bool IsNearestRectWithinDistance(
+GFX_EXPORT bool IsNearestRectWithinDistance(
const gfx::RectF& rect, float distance);
// Returns a Rect obtained by flooring the values of the given RectF.
// Please prefer the previous two functions in new code.
-UI_EXPORT Rect ToFlooredRectDeprecated(const RectF& rect);
+GFX_EXPORT Rect ToFlooredRectDeprecated(const RectF& rect);
} // namespace gfx
diff --git a/chromium/ui/gfx/rect_f.h b/chromium/ui/gfx/rect_f.h
index 62bedf2e359..09de529a627 100644
--- a/chromium/ui/gfx/rect_f.h
+++ b/chromium/ui/gfx/rect_f.h
@@ -17,7 +17,7 @@ namespace gfx {
class InsetsF;
// A floating version of gfx::Rect.
-class UI_EXPORT RectF
+class GFX_EXPORT RectF
: public RectBase<RectF, PointF, SizeF, InsetsF, Vector2dF, float> {
public:
RectF()
@@ -83,9 +83,9 @@ inline RectF operator+(const Vector2dF& lhs, const RectF& rhs) {
return rhs + lhs;
}
-UI_EXPORT RectF IntersectRects(const RectF& a, const RectF& b);
-UI_EXPORT RectF UnionRects(const RectF& a, const RectF& b);
-UI_EXPORT RectF SubtractRects(const RectF& a, const RectF& b);
+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,
@@ -102,7 +102,7 @@ inline RectF ScaleRect(const RectF& r, float scale) {
// 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.
-UI_EXPORT RectF BoundingRect(const PointF& p1, const PointF& p2);
+GFX_EXPORT RectF BoundingRect(const PointF& p1, const PointF& p2);
#if !defined(COMPILER_MSVC)
extern template class RectBase<RectF, PointF, SizeF, InsetsF, Vector2dF, float>;
diff --git a/chromium/ui/gfx/rect_unittest.cc b/chromium/ui/gfx/rect_unittest.cc
index 0b5f01eef3f..31a156b7910 100644
--- a/chromium/ui/gfx/rect_unittest.cc
+++ b/chromium/ui/gfx/rect_unittest.cc
@@ -865,4 +865,72 @@ TEST(RectTest, Corners) {
EXPECT_EQ(PointF(4.2f, 6.2f).ToString(), f.bottom_right().ToString());
}
+TEST(RectTest, ManhattanDistanceToPoint) {
+ Rect i(1, 2, 3, 4);
+ EXPECT_EQ(0, i.ManhattanDistanceToPoint(Point(1, 2)));
+ EXPECT_EQ(0, i.ManhattanDistanceToPoint(Point(4, 6)));
+ EXPECT_EQ(0, i.ManhattanDistanceToPoint(Point(2, 4)));
+ EXPECT_EQ(3, i.ManhattanDistanceToPoint(Point(0, 0)));
+ EXPECT_EQ(2, i.ManhattanDistanceToPoint(Point(2, 0)));
+ EXPECT_EQ(3, i.ManhattanDistanceToPoint(Point(5, 0)));
+ EXPECT_EQ(1, i.ManhattanDistanceToPoint(Point(5, 4)));
+ EXPECT_EQ(3, i.ManhattanDistanceToPoint(Point(5, 8)));
+ EXPECT_EQ(2, i.ManhattanDistanceToPoint(Point(3, 8)));
+ EXPECT_EQ(2, i.ManhattanDistanceToPoint(Point(0, 7)));
+ EXPECT_EQ(1, i.ManhattanDistanceToPoint(Point(0, 3)));
+
+ RectF f(1.1f, 2.1f, 3.1f, 4.1f);
+ EXPECT_FLOAT_EQ(0.f, f.ManhattanDistanceToPoint(PointF(1.1f, 2.1f)));
+ EXPECT_FLOAT_EQ(0.f, f.ManhattanDistanceToPoint(PointF(4.2f, 6.f)));
+ EXPECT_FLOAT_EQ(0.f, f.ManhattanDistanceToPoint(PointF(2.f, 4.f)));
+ EXPECT_FLOAT_EQ(3.2f, f.ManhattanDistanceToPoint(PointF(0.f, 0.f)));
+ EXPECT_FLOAT_EQ(2.1f, f.ManhattanDistanceToPoint(PointF(2.f, 0.f)));
+ EXPECT_FLOAT_EQ(2.9f, f.ManhattanDistanceToPoint(PointF(5.f, 0.f)));
+ EXPECT_FLOAT_EQ(.8f, f.ManhattanDistanceToPoint(PointF(5.f, 4.f)));
+ EXPECT_FLOAT_EQ(2.6f, f.ManhattanDistanceToPoint(PointF(5.f, 8.f)));
+ EXPECT_FLOAT_EQ(1.8f, f.ManhattanDistanceToPoint(PointF(3.f, 8.f)));
+ EXPECT_FLOAT_EQ(1.9f, f.ManhattanDistanceToPoint(PointF(0.f, 7.f)));
+ EXPECT_FLOAT_EQ(1.1f, f.ManhattanDistanceToPoint(PointF(0.f, 3.f)));
+}
+
+TEST(RectTest, ManhattanInternalDistance) {
+ Rect i(0, 0, 400, 400);
+ EXPECT_EQ(0, i.ManhattanInternalDistance(gfx::Rect(-1, 0, 2, 1)));
+ EXPECT_EQ(1, i.ManhattanInternalDistance(gfx::Rect(400, 0, 1, 400)));
+ EXPECT_EQ(2, i.ManhattanInternalDistance(gfx::Rect(-100, -100, 100, 100)));
+ EXPECT_EQ(2, i.ManhattanInternalDistance(gfx::Rect(-101, 100, 100, 100)));
+ EXPECT_EQ(4, i.ManhattanInternalDistance(gfx::Rect(-101, -101, 100, 100)));
+ EXPECT_EQ(435, i.ManhattanInternalDistance(gfx::Rect(630, 603, 100, 100)));
+
+ RectF f(0.0f, 0.0f, 400.0f, 400.0f);
+ static const float kEpsilon = std::numeric_limits<float>::epsilon();
+
+ EXPECT_FLOAT_EQ(
+ 0.0f, f.ManhattanInternalDistance(gfx::RectF(-1.0f, 0.0f, 2.0f, 1.0f)));
+ EXPECT_FLOAT_EQ(
+ kEpsilon,
+ f.ManhattanInternalDistance(gfx::RectF(400.0f, 0.0f, 1.0f, 400.0f)));
+ EXPECT_FLOAT_EQ(2.0f * kEpsilon,
+ f.ManhattanInternalDistance(
+ gfx::RectF(-100.0f, -100.0f, 100.0f, 100.0f)));
+ EXPECT_FLOAT_EQ(
+ 1.0f + kEpsilon,
+ f.ManhattanInternalDistance(gfx::RectF(-101.0f, 100.0f, 100.0f, 100.0f)));
+ EXPECT_FLOAT_EQ(2.0f + 2.0f * kEpsilon,
+ f.ManhattanInternalDistance(
+ gfx::RectF(-101.0f, -101.0f, 100.0f, 100.0f)));
+ EXPECT_FLOAT_EQ(
+ 433.0f + 2.0f * kEpsilon,
+ f.ManhattanInternalDistance(gfx::RectF(630.0f, 603.0f, 100.0f, 100.0f)));
+
+ EXPECT_FLOAT_EQ(
+ 0.0f, f.ManhattanInternalDistance(gfx::RectF(-1.0f, 0.0f, 1.1f, 1.0f)));
+ EXPECT_FLOAT_EQ(
+ 0.1f + kEpsilon,
+ f.ManhattanInternalDistance(gfx::RectF(-1.5f, 0.0f, 1.4f, 1.0f)));
+ EXPECT_FLOAT_EQ(
+ kEpsilon,
+ f.ManhattanInternalDistance(gfx::RectF(-1.5f, 0.0f, 1.5f, 1.0f)));
+}
+
} // namespace gfx
diff --git a/chromium/ui/gfx/render_text.cc b/chromium/ui/gfx/render_text.cc
index 47f42e37cb6..e8e3436f11c 100644
--- a/chromium/ui/gfx/render_text.cc
+++ b/chromium/ui/gfx/render_text.cc
@@ -5,6 +5,7 @@
#include "ui/gfx/render_text.h"
#include <algorithm>
+#include <climits>
#include "base/i18n/break_iterator.h"
#include "base/logging.h"
@@ -27,7 +28,7 @@ namespace {
// All chars are replaced by this char when the password style is set.
// TODO(benrg): GTK uses the first of U+25CF, U+2022, U+2731, U+273A, '*'
// that's available in the font (find_invisible_char() in gtkentry.c).
-const char16 kPasswordReplacementChar = '*';
+const base::char16 kPasswordReplacementChar = '*';
// Default color used for the text and cursor.
const SkColor kDefaultColor = SK_ColorBLACK;
@@ -44,6 +45,33 @@ const SkScalar kLineThickness = (SK_Scalar1 / 18);
// Fraction of the text size to use for a top margin of a diagonal strike.
const SkScalar kDiagonalStrikeMarginOffset = (SK_Scalar1 / 4);
+// Invalid value of baseline. Assigning this value to |baseline_| causes
+// re-calculation of baseline.
+const int kInvalidBaseline = INT_MAX;
+
+// Returns the baseline, with which the text best appears vertically centered.
+int DetermineBaselineCenteringText(const Rect& display_rect,
+ const FontList& font_list) {
+ const int display_height = display_rect.height();
+ const int font_height = font_list.GetHeight();
+ // Lower and upper bound of baseline shift as we try to show as much area of
+ // text as possible. In particular case of |display_height| == |font_height|,
+ // we do not want to shift the baseline.
+ const int min_shift = std::min(0, display_height - font_height);
+ const int max_shift = std::abs(display_height - font_height);
+ const int baseline = font_list.GetBaseline();
+ const int cap_height = font_list.GetCapHeight();
+ const int internal_leading = baseline - cap_height;
+ // Some platforms don't support getting the cap height, and simply return
+ // the entire font ascent from GetCapHeight(). Centering the ascent makes
+ // the font look too low, so if GetCapHeight() returns the ascent, center
+ // the entire font height instead.
+ const int space =
+ display_height - ((internal_leading != 0) ? cap_height : font_height);
+ const int baseline_shift = space / 2 - internal_leading;
+ return baseline + std::max(min_shift, std::min(max_shift, baseline_shift));
+}
+
// Converts |gfx::Font::FontStyle| flags to |SkTypeface::Style| flags.
SkTypeface::Style ConvertFontStyleToSkiaTypefaceStyle(int font_style) {
int skia_style = SkTypeface::kNormal;
@@ -348,16 +376,9 @@ void RenderText::SetHorizontalAlignment(HorizontalAlignment alignment) {
}
}
-void RenderText::SetVerticalAlignment(VerticalAlignment alignment) {
- if (vertical_alignment_ != alignment) {
- vertical_alignment_ = alignment;
- display_offset_ = Vector2d();
- cached_bounds_and_offset_valid_ = false;
- }
-}
-
void RenderText::SetFontList(const FontList& font_list) {
font_list_ = font_list;
+ baseline_ = kInvalidBaseline;
cached_bounds_and_offset_valid_ = false;
ResetLayout();
}
@@ -414,6 +435,7 @@ void RenderText::SetMultiline(bool multiline) {
void RenderText::SetDisplayRect(const Rect& r) {
display_rect_ = r;
+ baseline_ = kInvalidBaseline;
cached_bounds_and_offset_valid_ = false;
lines_.clear();
}
@@ -609,6 +631,7 @@ void RenderText::SetDirectionalityMode(DirectionalityMode mode) {
directionality_mode_ = mode;
text_direction_ = base::i18n::UNKNOWN_DIRECTION;
+ cached_bounds_and_offset_valid_ = false;
ResetLayout();
}
@@ -644,10 +667,22 @@ VisualCursorDirection RenderText::GetVisualDirectionOfLogicalEnd() {
CURSOR_RIGHT : CURSOR_LEFT;
}
+SizeF RenderText::GetStringSizeF() {
+ const Size size = GetStringSize();
+ return SizeF(size.width(), size.height());
+}
+
int RenderText::GetContentWidth() {
return GetStringSize().width() + (cursor_enabled_ ? 1 : 0);
}
+int RenderText::GetBaseline() {
+ if (baseline_ == kInvalidBaseline)
+ baseline_ = DetermineBaselineCenteringText(display_rect(), font_list());
+ DCHECK_NE(kInvalidBaseline, baseline_);
+ return baseline_;
+}
+
void RenderText::Draw(Canvas* canvas) {
EnsureLayout();
@@ -779,7 +814,6 @@ void RenderText::SetTextShadows(const ShadowValues& shadows) {
RenderText::RenderText()
: horizontal_alignment_(base::i18n::IsRTL() ? ALIGN_RIGHT : ALIGN_LEFT),
- vertical_alignment_(ALIGN_VCENTER),
directionality_mode_(DIRECTIONALITY_FROM_TEXT),
text_direction_(base::i18n::UNKNOWN_DIRECTION),
cursor_enabled_(true),
@@ -801,6 +835,7 @@ RenderText::RenderText()
fade_tail_(false),
background_is_transparent_(false),
clip_to_display_rect_(true),
+ baseline_(kInvalidBaseline),
cached_bounds_and_offset_valid_(false) {
}
@@ -844,7 +879,7 @@ const BreakList<size_t>& RenderText::GetLineBreaks() {
if (line_breaks_.max() != 0)
return line_breaks_;
- const string16& layout_text = GetLayoutText();
+ const base::string16& layout_text = GetLayoutText();
const size_t text_length = layout_text.length();
line_breaks_.SetValue(0);
line_breaks_.SetMax(text_length);
@@ -871,7 +906,7 @@ void RenderText::ApplyCompositionAndSelectionStyles() {
styles_[UNDERLINE].ApplyValue(true, composition_range_);
// Apply the selected text color to the [un-reversed] selection range.
- if (!selection().is_empty()) {
+ if (!selection().is_empty() && focused()) {
const Range range(selection().GetMin(), selection().GetMax());
colors_.ApplyValue(selection_color_, range);
}
@@ -964,11 +999,16 @@ Vector2d RenderText::GetAlignmentOffset(size_t line_number) {
if (horizontal_alignment_ == ALIGN_CENTER)
offset.set_x(offset.x() / 2);
}
- if (vertical_alignment_ != ALIGN_TOP) {
- offset.set_y(display_rect().height() - GetStringSize().height());
- if (vertical_alignment_ == ALIGN_VCENTER)
- offset.set_y(offset.y() / 2);
+
+ // Vertically center the text.
+ if (multiline_) {
+ const int text_height = lines_.back().preceding_heights +
+ lines_.back().size.height();
+ offset.set_y((display_rect_.height() - text_height) / 2);
+ } else {
+ offset.set_y(GetBaseline() - GetLayoutTextBaseline());
}
+
return offset;
}
diff --git a/chromium/ui/gfx/render_text.h b/chromium/ui/gfx/render_text.h
index 598f4e1d181..8696d690560 100644
--- a/chromium/ui/gfx/render_text.h
+++ b/chromium/ui/gfx/render_text.h
@@ -25,6 +25,7 @@
#include "ui/gfx/rect.h"
#include "ui/gfx/selection_model.h"
#include "ui/gfx/shadow_value.h"
+#include "ui/gfx/size_f.h"
#include "ui/gfx/text_constants.h"
#include "ui/gfx/vector2d.h"
@@ -151,7 +152,7 @@ struct Line {
// visual layout. Support is built in for a cursor, a selection, simple styling,
// complex scripts, and bi-directional text. Implementations provide mechanisms
// for rendering and translation between logical and visual data.
-class UI_EXPORT RenderText {
+class GFX_EXPORT RenderText {
public:
virtual ~RenderText();
@@ -166,11 +167,6 @@ class UI_EXPORT RenderText {
}
void SetHorizontalAlignment(HorizontalAlignment alignment);
- VerticalAlignment vertical_alignment() const {
- return vertical_alignment_;
- }
- void SetVerticalAlignment(VerticalAlignment alignment);
-
const FontList& font_list() const { return font_list_; }
void SetFontList(const FontList& font_list);
void SetFont(const Font& font);
@@ -311,8 +307,11 @@ class UI_EXPORT RenderText {
// RenderText.
bool GetStyle(TextStyle style) const;
- // Set the text directionality mode and get the text direction yielded.
+ // Set or get the text directionality mode and get the text direction yielded.
void SetDirectionalityMode(DirectionalityMode mode);
+ DirectionalityMode directionality_mode() const {
+ return directionality_mode_;
+ }
base::i18n::TextDirection GetTextDirection();
// Returns the visual movement direction corresponding to the logical end
@@ -326,13 +325,22 @@ class UI_EXPORT RenderText {
// shadows.
virtual Size GetStringSize() = 0;
+ // This is same as GetStringSize except that fractional size is returned.
+ // The default implementation is same as GetStringSize. Certain platforms that
+ // compute the text size as floating-point values, like Mac, will override
+ // this method.
+ // See comment in Canvas::GetStringWidthF for its usage.
+ virtual SizeF GetStringSizeF();
+
// Returns the width of the content (which is the wrapped width in multiline
// mode). Reserves room for the cursor if |cursor_enabled_| is true.
int GetContentWidth();
- // Returns the common baseline of the text. The returned value is the vertical
- // offset from the top of |display_rect| to the text baseline, in pixels.
- virtual int GetBaseline() = 0;
+ // Returns the common baseline of the text. The return value is the vertical
+ // offset from the top of |display_rect_| to the text baseline, in pixels.
+ // The baseline is determined from the font list and display rect, and does
+ // not depend on the text.
+ int GetBaseline();
void Draw(Canvas* canvas);
@@ -346,12 +354,19 @@ class UI_EXPORT RenderText {
// Gets the SelectionModel from a visual point in local coordinates.
virtual SelectionModel FindCursorPosition(const Point& point) = 0;
- // Get the visual bounds of a cursor at |selection|. These bounds typically
- // represent a vertical line, but if |insert_mode| is true they contain the
- // bounds of the associated glyph. These bounds are in local coordinates, but
- // may be outside the visible region if the text is longer than the textfield.
- // Subsequent text, cursor, or bounds changes may invalidate returned values.
- Rect GetCursorBounds(const SelectionModel& selection, bool insert_mode);
+ // Return true if cursor can appear in front of the character at |position|,
+ // which means it is a grapheme boundary or the first character in the text.
+ virtual bool IsCursorablePosition(size_t position) = 0;
+
+ // Get the visual bounds of a cursor at |caret|. These bounds typically
+ // represent a vertical line if |insert_mode| is true. Pass false for
+ // |insert_mode| to retrieve the bounds of the associated glyph. These bounds
+ // are in local coordinates, but may be outside the visible region if the text
+ // is longer than the textfield. Subsequent text, cursor, or bounds changes
+ // may invalidate returned values. Note that |caret| must be placed at
+ // grapheme boundary, that is, |IsCursorablePosition(caret.caret_pos())| must
+ // return true.
+ Rect GetCursorBounds(const SelectionModel& caret, bool insert_mode);
// Compute the current cursor bounds, panning the text to show the cursor in
// the display rect if necessary. These bounds are in local coordinates.
@@ -390,6 +405,30 @@ class UI_EXPORT RenderText {
const std::vector<internal::Line>& lines() const { return lines_; }
void set_lines(std::vector<internal::Line>* lines) { lines_.swap(*lines); }
+ // Returns the baseline of the current text. The return value depends on
+ // the text and its layout while the return value of GetBaseline() doesn't.
+ // GetAlignmentOffset() takes into account the difference between them.
+ //
+ // We'd like a RenderText to show the text always on the same baseline
+ // regardless of the text, so the text does not jump up or down depending
+ // on the text. However, underlying layout engines return different baselines
+ // depending on the text. In general, layout engines determine the minimum
+ // bounding box for the text and return the baseline from the top of the
+ // bounding box. So the baseline changes depending on font metrics used to
+ // layout the text.
+ //
+ // For example, suppose there are FontA and FontB and the baseline of FontA
+ // is smaller than the one of FontB. If the text is laid out only with FontA,
+ // then the baseline of FontA may be returned. If the text includes some
+ // characters which are laid out with FontB, then the baseline of FontB may
+ // be returned.
+ //
+ // GetBaseline() returns the fixed baseline regardless of the text.
+ // GetLayoutTextBaseline() returns the baseline determined by the underlying
+ // layout engine, and it changes depending on the text. GetAlignmentOffset()
+ // returns the difference between them.
+ virtual int GetLayoutTextBaseline() = 0;
+
const Vector2d& GetUpdatedDisplayOffset();
void set_cached_bounds_and_offset_valid(bool valid) {
@@ -441,10 +480,6 @@ class UI_EXPORT RenderText {
virtual size_t TextIndexToLayoutIndex(size_t index) const = 0;
virtual size_t LayoutIndexToTextIndex(size_t index) const = 0;
- // Return true if cursor can appear in front of the character at |position|,
- // which means it is a grapheme boundary or the first character in the text.
- virtual bool IsCursorablePosition(size_t position) = 0;
-
// Reset the layout to be invalid.
virtual void ResetLayout() = 0;
@@ -509,6 +544,7 @@ class UI_EXPORT RenderText {
FRIEND_TEST_ALL_PREFIXES(RenderTextTest, Multiline_MinWidth);
FRIEND_TEST_ALL_PREFIXES(RenderTextTest, Multiline_NormalWidth);
FRIEND_TEST_ALL_PREFIXES(RenderTextTest, Multiline_SufficientWidth);
+ FRIEND_TEST_ALL_PREFIXES(RenderTextTest, Multiline_Newline);
// Set the cursor to |position|, with the caret trailing the previous
// grapheme, or if there is no previous grapheme, leading the cursor position.
@@ -534,10 +570,6 @@ class UI_EXPORT RenderText {
// default is to align left if the application UI is LTR and right if RTL.
HorizontalAlignment horizontal_alignment_;
- // Vertical alignment of the text with respect to |display_rect_|. The
- // default is to align vertically centered.
- VerticalAlignment vertical_alignment_;
-
// The text directionality mode, defaults to DIRECTIONALITY_FROM_TEXT.
DirectionalityMode directionality_mode_;
@@ -623,6 +655,11 @@ class UI_EXPORT RenderText {
// Get this point with GetUpdatedDisplayOffset (or risk using a stale value).
Vector2d display_offset_;
+ // The baseline of the text. This is determined from the height of the
+ // display area and the cap height of the font list so the text is vertically
+ // centered.
+ int baseline_;
+
// The cached bounds and offset are invalidated by changes to the cursor,
// selection, font, and other operations that adjust the visible text bounds.
bool cached_bounds_and_offset_valid_;
diff --git a/chromium/ui/gfx/render_text_mac.cc b/chromium/ui/gfx/render_text_mac.cc
index 2fcea01b157..4feb9302c18 100644
--- a/chromium/ui/gfx/render_text_mac.cc
+++ b/chromium/ui/gfx/render_text_mac.cc
@@ -25,12 +25,12 @@ RenderTextMac::~RenderTextMac() {
Size RenderTextMac::GetStringSize() {
EnsureLayout();
- return string_size_;
+ return Size(std::ceil(string_size_.width()), string_size_.height());
}
-int RenderTextMac::GetBaseline() {
+SizeF RenderTextMac::GetStringSizeF() {
EnsureLayout();
- return common_baseline_;
+ return string_size_;
}
SelectionModel RenderTextMac::FindCursorPosition(const Point& point) {
@@ -54,6 +54,11 @@ std::vector<RenderText::FontSpan> RenderTextMac::GetFontSpansForTesting() {
return spans;
}
+int RenderTextMac::GetLayoutTextBaseline() {
+ EnsureLayout();
+ return common_baseline_;
+}
+
SelectionModel RenderTextMac::AdjacentCharSelectionModel(
const SelectionModel& selection,
VisualCursorDirection direction) {
@@ -107,10 +112,7 @@ void RenderTextMac::EnsureLayout() {
runs_valid_ = false;
const Font& font = GetPrimaryFont();
- base::ScopedCFTypeRef<CFStringRef> font_name_cf_string(
- base::SysUTF8ToCFStringRef(font.GetFontName()));
- base::ScopedCFTypeRef<CTFontRef> ct_font(
- CTFontCreateWithName(font_name_cf_string, font.GetFontSize(), NULL));
+ CTFontRef ct_font = base::mac::NSToCFCast(font.GetNativeFont());
const void* keys[] = { kCTFontAttributeName };
const void* values[] = { ct_font };
@@ -149,7 +151,7 @@ void RenderTextMac::EnsureLayout() {
CGFloat font_list_baseline = font_list().GetBaseline();
ascent = std::max(ascent, font_list_baseline);
descent = std::max(descent, font_list_height - font_list_baseline);
- string_size_ = Size(std::ceil(width), ascent + descent + leading);
+ string_size_ = SizeF(width, ascent + descent + leading);
common_baseline_ = ascent;
}
diff --git a/chromium/ui/gfx/render_text_mac.h b/chromium/ui/gfx/render_text_mac.h
index be5f12865c0..3a18a0fad45 100644
--- a/chromium/ui/gfx/render_text_mac.h
+++ b/chromium/ui/gfx/render_text_mac.h
@@ -27,12 +27,13 @@ class RenderTextMac : public RenderText {
// Overridden from RenderText:
virtual Size GetStringSize() OVERRIDE;
- virtual int GetBaseline() OVERRIDE;
+ virtual SizeF GetStringSizeF() OVERRIDE;
virtual SelectionModel FindCursorPosition(const Point& point) OVERRIDE;
virtual std::vector<FontSpan> GetFontSpansForTesting() OVERRIDE;
protected:
// Overridden from RenderText:
+ virtual int GetLayoutTextBaseline() OVERRIDE;
virtual SelectionModel AdjacentCharSelectionModel(
const SelectionModel& selection,
VisualCursorDirection direction) OVERRIDE;
@@ -81,7 +82,7 @@ class RenderTextMac : public RenderText {
base::ScopedCFTypeRef<CFMutableArrayRef> attributes_;
// Visual dimensions of the text. Computed by |EnsureLayout()|.
- Size string_size_;
+ SizeF string_size_;
// Common baseline for this line of text. Computed by |EnsureLayout()|.
SkScalar common_baseline_;
diff --git a/chromium/ui/gfx/render_text_ozone.cc b/chromium/ui/gfx/render_text_ozone.cc
new file mode 100644
index 00000000000..058b5a6389d
--- /dev/null
+++ b/chromium/ui/gfx/render_text_ozone.cc
@@ -0,0 +1,13 @@
+// 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.
+
+#include "ui/gfx/render_text.h"
+
+namespace gfx {
+
+RenderText* RenderText::CreateInstance() {
+ return NULL;
+}
+
+} // namespace gfx
diff --git a/chromium/ui/gfx/render_text_linux.cc b/chromium/ui/gfx/render_text_pango.cc
index 4b7b93474ae..f120a5c10bb 100644
--- a/chromium/ui/gfx/render_text_linux.cc
+++ b/chromium/ui/gfx/render_text_pango.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "ui/gfx/render_text_linux.h"
+#include "ui/gfx/render_text_pango.h"
#include <pango/pangocairo.h>
#include <algorithm>
@@ -67,7 +67,7 @@ void SetPangoUnderlineMetrics(PangoFontDescription *desc,
// Since caret_pos is used internally, we could save utf8 index for caret_pos
// to avoid conversion.
-RenderTextLinux::RenderTextLinux()
+RenderTextPango::RenderTextPango()
: layout_(NULL),
current_line_(NULL),
log_attrs_(NULL),
@@ -75,11 +75,11 @@ RenderTextLinux::RenderTextLinux()
layout_text_(NULL) {
}
-RenderTextLinux::~RenderTextLinux() {
+RenderTextPango::~RenderTextPango() {
ResetLayout();
}
-Size RenderTextLinux::GetStringSize() {
+Size RenderTextPango::GetStringSize() {
EnsureLayout();
int width = 0, height = 0;
pango_layout_get_pixel_size(layout_, &width, &height);
@@ -91,16 +91,7 @@ Size RenderTextLinux::GetStringSize() {
return Size(width, std::max(height, font_list().GetHeight()));
}
-int RenderTextLinux::GetBaseline() {
- EnsureLayout();
- // Keep a consistent baseline between this particular string's PangoLayout and
- // potentially larger text supported by the FontList.
- // See the example in GetStringSize().
- return std::max(PANGO_PIXELS(pango_layout_get_baseline(layout_)),
- font_list().GetBaseline());
-}
-
-SelectionModel RenderTextLinux::FindCursorPosition(const Point& point) {
+SelectionModel RenderTextPango::FindCursorPosition(const Point& point) {
EnsureLayout();
if (text().empty())
@@ -129,7 +120,7 @@ SelectionModel RenderTextLinux::FindCursorPosition(const Point& point) {
(trailing > 0) ? CURSOR_BACKWARD : CURSOR_FORWARD);
}
-std::vector<RenderText::FontSpan> RenderTextLinux::GetFontSpansForTesting() {
+std::vector<RenderText::FontSpan> RenderTextPango::GetFontSpansForTesting() {
EnsureLayout();
std::vector<RenderText::FontSpan> spans;
@@ -146,7 +137,12 @@ std::vector<RenderText::FontSpan> RenderTextLinux::GetFontSpansForTesting() {
return spans;
}
-SelectionModel RenderTextLinux::AdjacentCharSelectionModel(
+int RenderTextPango::GetLayoutTextBaseline() {
+ EnsureLayout();
+ return PANGO_PIXELS(pango_layout_get_baseline(layout_));
+}
+
+SelectionModel RenderTextPango::AdjacentCharSelectionModel(
const SelectionModel& selection,
VisualCursorDirection direction) {
GSList* run = GetRunContainingCaret(selection);
@@ -186,7 +182,7 @@ SelectionModel RenderTextLinux::AdjacentCharSelectionModel(
FirstSelectionModelInsideRun(item) : LastSelectionModelInsideRun(item);
}
-SelectionModel RenderTextLinux::AdjacentWordSelectionModel(
+SelectionModel RenderTextPango::AdjacentWordSelectionModel(
const SelectionModel& selection,
VisualCursorDirection direction) {
if (obscured())
@@ -214,14 +210,14 @@ SelectionModel RenderTextLinux::AdjacentWordSelectionModel(
return cur;
}
-Range RenderTextLinux::GetGlyphBounds(size_t index) {
+Range RenderTextPango::GetGlyphBounds(size_t index) {
PangoRectangle pos;
pango_layout_index_to_pos(layout_, TextIndexToLayoutIndex(index), &pos);
// TODO(derat): Support fractional ranges for subpixel positioning?
return Range(PANGO_PIXELS(pos.x), PANGO_PIXELS(pos.x + pos.width));
}
-std::vector<Rect> RenderTextLinux::GetSubstringBounds(const Range& range) {
+std::vector<Rect> RenderTextPango::GetSubstringBounds(const Range& range) {
DCHECK_LE(range.GetMax(), text().length());
if (range.is_empty())
return std::vector<Rect>();
@@ -250,7 +246,7 @@ std::vector<Rect> RenderTextLinux::GetSubstringBounds(const Range& range) {
return bounds;
}
-size_t RenderTextLinux::TextIndexToLayoutIndex(size_t index) const {
+size_t RenderTextPango::TextIndexToLayoutIndex(size_t index) const {
DCHECK(layout_);
ptrdiff_t offset = gfx::UTF16IndexToOffset(text(), 0, index);
// Clamp layout indices to the length of the text actually used for layout.
@@ -259,14 +255,14 @@ size_t RenderTextLinux::TextIndexToLayoutIndex(size_t index) const {
return (layout_pointer - layout_text_);
}
-size_t RenderTextLinux::LayoutIndexToTextIndex(size_t index) const {
+size_t RenderTextPango::LayoutIndexToTextIndex(size_t index) const {
DCHECK(layout_);
const char* layout_pointer = layout_text_ + index;
const long offset = g_utf8_pointer_to_offset(layout_text_, layout_pointer);
return gfx::UTF16OffsetToIndex(text(), 0, offset);
}
-bool RenderTextLinux::IsCursorablePosition(size_t position) {
+bool RenderTextPango::IsCursorablePosition(size_t position) {
if (position == 0 && text().empty())
return true;
if (position >= text().length())
@@ -283,7 +279,7 @@ bool RenderTextLinux::IsCursorablePosition(size_t position) {
offset < g_utf8_strlen(layout_text_, -1));
}
-void RenderTextLinux::ResetLayout() {
+void RenderTextPango::ResetLayout() {
// set_cached_bounds_and_offset_valid(false) is done in RenderText for every
// operation that triggers ResetLayout().
if (layout_) {
@@ -303,7 +299,7 @@ void RenderTextLinux::ResetLayout() {
layout_text_ = NULL;
}
-void RenderTextLinux::EnsureLayout() {
+void RenderTextPango::EnsureLayout() {
if (layout_ == NULL) {
cairo_surface_t* surface =
cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 0, 0);
@@ -342,7 +338,7 @@ void RenderTextLinux::EnsureLayout() {
}
}
-void RenderTextLinux::SetupPangoAttributes(PangoLayout* layout) {
+void RenderTextPango::SetupPangoAttributes(PangoLayout* layout) {
PangoAttrList* attrs = pango_attr_list_new();
// Splitting text runs to accommodate styling can break Arabic glyph shaping.
@@ -377,11 +373,11 @@ void RenderTextLinux::SetupPangoAttributes(PangoLayout* layout) {
pango_attr_list_unref(attrs);
}
-void RenderTextLinux::DrawVisualText(Canvas* canvas) {
+void RenderTextPango::DrawVisualText(Canvas* canvas) {
DCHECK(layout_);
// Skia will draw glyphs with respect to the baseline.
- Vector2d offset(GetLineOffset(0) + Vector2d(0, GetBaseline()));
+ Vector2d offset(GetLineOffset(0) + Vector2d(0, GetLayoutTextBaseline()));
SkScalar x = SkIntToScalar(offset.x());
SkScalar y = SkIntToScalar(offset.y());
@@ -476,7 +472,7 @@ void RenderTextLinux::DrawVisualText(Canvas* canvas) {
UndoCompositionAndSelectionStyles();
}
-GSList* RenderTextLinux::GetRunContainingCaret(
+GSList* RenderTextPango::GetRunContainingCaret(
const SelectionModel& caret) const {
size_t position = TextIndexToLayoutIndex(caret.caret_pos());
LogicalCursorDirection affinity = caret.caret_affinity();
@@ -491,28 +487,28 @@ GSList* RenderTextLinux::GetRunContainingCaret(
return NULL;
}
-SelectionModel RenderTextLinux::FirstSelectionModelInsideRun(
+SelectionModel RenderTextPango::FirstSelectionModelInsideRun(
const PangoItem* item) {
size_t caret = IndexOfAdjacentGrapheme(
LayoutIndexToTextIndex(item->offset), CURSOR_FORWARD);
return SelectionModel(caret, CURSOR_BACKWARD);
}
-SelectionModel RenderTextLinux::LastSelectionModelInsideRun(
+SelectionModel RenderTextPango::LastSelectionModelInsideRun(
const PangoItem* item) {
size_t caret = IndexOfAdjacentGrapheme(
LayoutIndexToTextIndex(item->offset + item->length), CURSOR_BACKWARD);
return SelectionModel(caret, CURSOR_FORWARD);
}
-size_t RenderTextLinux::GetGlyphTextIndex(PangoLayoutRun* run,
+size_t RenderTextPango::GetGlyphTextIndex(PangoLayoutRun* run,
int glyph_index) const {
return LayoutIndexToTextIndex(run->item->offset +
run->glyphs->log_clusters[glyph_index]);
}
RenderText* RenderText::CreateInstance() {
- return new RenderTextLinux;
+ return new RenderTextPango;
}
} // namespace gfx
diff --git a/chromium/ui/gfx/render_text_linux.h b/chromium/ui/gfx/render_text_pango.h
index 1500fc0adef..ba7361c4d30 100644
--- a/chromium/ui/gfx/render_text_linux.h
+++ b/chromium/ui/gfx/render_text_pango.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_GFX_RENDER_TEXT_LINUX_H_
-#define UI_GFX_RENDER_TEXT_LINUX_H_
+#ifndef UI_GFX_RENDER_TEXT_PANGO_H_
+#define UI_GFX_RENDER_TEXT_PANGO_H_
#include <pango/pango.h>
#include <vector>
@@ -12,20 +12,20 @@
namespace gfx {
-// RenderTextLinux is the Linux implementation of RenderText using Pango.
-class RenderTextLinux : public RenderText {
+// RenderTextPango is the Linux implementation of RenderText using Pango.
+class RenderTextPango : public RenderText {
public:
- RenderTextLinux();
- virtual ~RenderTextLinux();
+ RenderTextPango();
+ virtual ~RenderTextPango();
// Overridden from RenderText:
virtual Size GetStringSize() OVERRIDE;
- virtual int GetBaseline() OVERRIDE;
virtual SelectionModel FindCursorPosition(const Point& point) OVERRIDE;
virtual std::vector<FontSpan> GetFontSpansForTesting() OVERRIDE;
protected:
// Overridden from RenderText:
+ virtual int GetLayoutTextBaseline() OVERRIDE;
virtual SelectionModel AdjacentCharSelectionModel(
const SelectionModel& selection,
VisualCursorDirection direction) OVERRIDE;
@@ -80,9 +80,9 @@ class RenderTextLinux : public RenderText {
// The text in the |layout_|.
const char* layout_text_;
- DISALLOW_COPY_AND_ASSIGN(RenderTextLinux);
+ DISALLOW_COPY_AND_ASSIGN(RenderTextPango);
};
} // namespace gfx
-#endif // UI_GFX_RENDER_TEXT_LINUX_H_
+#endif // UI_GFX_RENDER_TEXT_PANGO_H_
diff --git a/chromium/ui/gfx/render_text_unittest.cc b/chromium/ui/gfx/render_text_unittest.cc
index 52cb8344b37..c8c50d42814 100644
--- a/chromium/ui/gfx/render_text_unittest.cc
+++ b/chromium/ui/gfx/render_text_unittest.cc
@@ -8,6 +8,7 @@
#include "base/format_macros.h"
#include "base/memory/scoped_ptr.h"
+#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -19,8 +20,8 @@
#include "ui/gfx/render_text_win.h"
#endif
-#if defined(OS_LINUX)
-#include "ui/gfx/render_text_linux.h"
+#if defined(OS_LINUX) && !defined(USE_OZONE)
+#include "ui/gfx/render_text_pango.h"
#endif
#if defined(TOOLKIT_GTK)
@@ -34,11 +35,13 @@ namespace {
// Various weak, LTR, RTL, and Bidi string cases with three characters each.
const wchar_t kWeak[] = L" . ";
const wchar_t kLtr[] = L"abc";
+const wchar_t kRtl[] = L"\x5d0\x5d1\x5d2";
+#if !defined(OS_MACOSX)
const wchar_t kLtrRtl[] = L"a" L"\x5d0\x5d1";
const wchar_t kLtrRtlLtr[] = L"a" L"\x5d1" L"b";
-const wchar_t kRtl[] = L"\x5d0\x5d1\x5d2";
const wchar_t kRtlLtr[] = L"\x5d0\x5d1" L"a";
const wchar_t kRtlLtrRtl[] = L"\x5d0" L"a" L"\x5d1";
+#endif
// Checks whether |range| contains |index|. This is not the same as calling
// |range.Contains(gfx::Range(index))| - as that would return true when
@@ -63,6 +66,7 @@ void SetRTL(bool rtl) {
EXPECT_EQ(rtl, base::i18n::IsRTL());
}
+#if !defined(OS_MACOSX)
// Ensure cursor movement in the specified |direction| yields |expected| values.
void RunMoveCursorLeftRightTest(RenderText* render_text,
const std::vector<SelectionModel>& expected,
@@ -79,6 +83,7 @@ void RunMoveCursorLeftRightTest(RenderText* render_text,
render_text->MoveCursor(LINE_BREAK, direction, false);
EXPECT_EQ(expected.back(), render_text->selection_model());
}
+#endif // !defined(OS_MACOSX)
} // namespace
@@ -182,7 +187,7 @@ TEST_F(RenderTextTest, ApplyColorAndStyle) {
EXPECT_TRUE(render_text->styles()[ITALIC].EqualsForTesting(expected_italic));
}
-#if defined(OS_LINUX)
+#if defined(OS_LINUX) && !defined(USE_OZONE)
TEST_F(RenderTextTest, PangoAttributes) {
scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
render_text->SetText(ASCIIToUTF16("012345678"));
@@ -205,7 +210,7 @@ TEST_F(RenderTextTest, PangoAttributes) {
};
int start = 0, end = 0;
- RenderTextLinux* rt_linux = static_cast<RenderTextLinux*>(render_text.get());
+ RenderTextPango* rt_linux = static_cast<RenderTextPango*>(render_text.get());
rt_linux->EnsureLayout();
PangoAttrList* attributes = pango_layout_get_attributes(rt_linux->layout_);
PangoAttrIterator* iter = pango_attr_list_get_iterator(attributes);
@@ -1137,6 +1142,7 @@ TEST_F(RenderTextTest, StringSizeEmptyString) {
const FontList font_list("Arial,Symbol, 16px");
scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
render_text->SetFontList(font_list);
+ render_text->SetDisplayRect(Rect(0, 0, 0, font_list.GetHeight()));
// The empty string respects FontList metrics for non-zero height
// and baseline.
@@ -1154,7 +1160,11 @@ TEST_F(RenderTextTest, StringSizeEmptyString) {
TEST_F(RenderTextTest, StringSizeRespectsFontListMetrics) {
// Check that Arial and Symbol have different font metrics.
Font arial_font("Arial", 16);
+ ASSERT_EQ("arial",
+ StringToLowerASCII(arial_font.GetActualFontNameForTesting()));
Font symbol_font("Symbol", 16);
+ ASSERT_EQ("symbol",
+ StringToLowerASCII(symbol_font.GetActualFontNameForTesting()));
EXPECT_NE(arial_font.GetHeight(), symbol_font.GetHeight());
EXPECT_NE(arial_font.GetBaseline(), symbol_font.GetBaseline());
// "a" should be rendered with Arial, not with Symbol.
@@ -1178,7 +1188,9 @@ TEST_F(RenderTextTest, StringSizeRespectsFontListMetrics) {
// Check |smaller_font_text| is rendered with the smaller font.
scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
render_text->SetText(UTF8ToUTF16(smaller_font_text));
- render_text->SetFont(smaller_font);
+ render_text->SetFontList(FontList(smaller_font));
+ render_text->SetDisplayRect(Rect(0, 0, 0,
+ render_text->font_list().GetHeight()));
EXPECT_EQ(smaller_font.GetHeight(), render_text->GetStringSize().height());
EXPECT_EQ(smaller_font.GetBaseline(), render_text->GetBaseline());
@@ -1190,6 +1202,8 @@ TEST_F(RenderTextTest, StringSizeRespectsFontListMetrics) {
fonts.push_back(larger_font);
const FontList font_list(fonts);
render_text->SetFontList(font_list);
+ render_text->SetDisplayRect(Rect(0, 0, 0,
+ render_text->font_list().GetHeight()));
EXPECT_LT(smaller_font.GetHeight(), render_text->GetStringSize().height());
EXPECT_LT(smaller_font.GetBaseline(), render_text->GetBaseline());
EXPECT_EQ(font_list.GetHeight(), render_text->GetStringSize().height());
@@ -1291,21 +1305,19 @@ TEST_F(RenderTextTest, GetTextOffset) {
// Set display area's size equal to the font size.
const Size font_size(render_text->GetContentWidth(),
- render_text->GetStringSize().height());
+ render_text->font_list().GetHeight());
Rect display_rect(font_size);
render_text->SetDisplayRect(display_rect);
Vector2d offset = render_text->GetLineOffset(0);
EXPECT_TRUE(offset.IsZero());
- // Set display area's size greater than font size.
- const int kEnlargement = 2;
- display_rect.Inset(0, 0, -kEnlargement, -kEnlargement);
+ const int kEnlargementX = 2;
+ display_rect.Inset(0, 0, -kEnlargementX, 0);
render_text->SetDisplayRect(display_rect);
- // Check the default horizontal and vertical alignment.
+ // Check the default horizontal alignment.
offset = render_text->GetLineOffset(0);
- EXPECT_EQ(kEnlargement / 2, offset.y());
EXPECT_EQ(0, offset.x());
// Check explicitly setting the horizontal alignment.
@@ -1314,21 +1326,20 @@ TEST_F(RenderTextTest, GetTextOffset) {
EXPECT_EQ(0, offset.x());
render_text->SetHorizontalAlignment(ALIGN_CENTER);
offset = render_text->GetLineOffset(0);
- EXPECT_EQ(kEnlargement / 2, offset.x());
+ EXPECT_EQ(kEnlargementX / 2, offset.x());
render_text->SetHorizontalAlignment(ALIGN_RIGHT);
offset = render_text->GetLineOffset(0);
- EXPECT_EQ(kEnlargement, offset.x());
+ EXPECT_EQ(kEnlargementX, offset.x());
- // Check explicitly setting the vertical alignment.
- render_text->SetVerticalAlignment(ALIGN_TOP);
- offset = render_text->GetLineOffset(0);
- EXPECT_EQ(0, offset.y());
- render_text->SetVerticalAlignment(ALIGN_VCENTER);
- offset = render_text->GetLineOffset(0);
- EXPECT_EQ(kEnlargement / 2, offset.y());
- render_text->SetVerticalAlignment(ALIGN_BOTTOM);
+ // Check that text is vertically centered within taller display rects.
+ const int kEnlargementY = display_rect.height();
+ display_rect.Inset(0, 0, 0, -kEnlargementY);
+ render_text->SetDisplayRect(display_rect);
+ const Vector2d prev_offset = render_text->GetLineOffset(0);
+ display_rect.Inset(0, 0, 0, -2 * kEnlargementY);
+ render_text->SetDisplayRect(display_rect);
offset = render_text->GetLineOffset(0);
- EXPECT_EQ(kEnlargement, offset.y());
+ EXPECT_EQ(prev_offset.y() + kEnlargementY, offset.y());
SetRTL(was_rtl);
}
@@ -1674,19 +1685,13 @@ TEST_F(RenderTextTest, Multiline_MinWidth) {
// Ensure strings wrap onto multiple lines for a normal available width.
TEST_F(RenderTextTest, Multiline_NormalWidth) {
- // TODO(ckocagil): Enable this test on XP.
-#if defined(OS_WIN)
- if (base::win::GetVersion() < base::win::VERSION_VISTA)
- return;
-#endif
-
const struct {
const wchar_t* const text;
const Range first_line_char_range;
const Range second_line_char_range;
} kTestStrings[] = {
{ L"abc defg hijkl", Range(0, 9), Range(9, 14) },
- { L"qwertyuiop", Range(0, 8), Range(8, 10) },
+ { L"qwertyzxcvbn", Range(0, 8), Range(8, 12) },
{ L"\x062A\x0641\x0627\x062D\x05EA\x05E4\x05D5\x05D6\x05D9\x05DD",
Range(4, 10), Range(0, 4) }
};
@@ -1730,13 +1735,59 @@ TEST_F(RenderTextTest, Multiline_SufficientWidth) {
EXPECT_EQ(1U, render_text->lines_.size());
}
}
-#endif // defined(OS_WIN)
-#if defined(OS_WIN)
+TEST_F(RenderTextTest, Multiline_Newline) {
+ const struct {
+ const wchar_t* const text;
+ // Ranges of the characters on each line preceding the newline.
+ const Range first_line_char_range;
+ const Range second_line_char_range;
+ } kTestStrings[] = {
+ { L"abc\ndef", Range(0, 3), Range(4, 7) },
+ { L"a \n b ", Range(0, 2), Range(3, 6) },
+ { L"\n" , Range::InvalidRange(), Range::InvalidRange() }
+ };
+
+ scoped_ptr<RenderTextWin> render_text(
+ static_cast<RenderTextWin*>(RenderText::CreateInstance()));
+ render_text->SetDisplayRect(Rect(200, 1000));
+ render_text->SetMultiline(true);
+ Canvas canvas;
+
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestStrings); ++i) {
+ SCOPED_TRACE(base::StringPrintf("kTestStrings[%" PRIuS "]", i));
+ render_text->SetText(WideToUTF16(kTestStrings[i].text));
+ render_text->Draw(&canvas);
+
+ ASSERT_EQ(2U, render_text->lines_.size());
+
+ const Range first_expected_range = kTestStrings[i].first_line_char_range;
+ ASSERT_EQ(first_expected_range.IsValid() ? 2U : 1U,
+ render_text->lines_[0].segments.size());
+ if (first_expected_range.IsValid())
+ EXPECT_EQ(first_expected_range,
+ render_text->lines_[0].segments[0].char_range);
+
+ const internal::LineSegment& newline_segment =
+ render_text->lines_[0].segments[first_expected_range.IsValid() ? 1 : 0];
+ ASSERT_EQ(1U, newline_segment.char_range.length());
+ EXPECT_EQ(L'\n', kTestStrings[i].text[newline_segment.char_range.start()]);
+
+ const Range second_expected_range = kTestStrings[i].second_line_char_range;
+ ASSERT_EQ(second_expected_range.IsValid() ? 1U : 0U,
+ render_text->lines_[1].segments.size());
+ if (second_expected_range.IsValid())
+ EXPECT_EQ(second_expected_range,
+ render_text->lines_[1].segments[0].char_range);
+ }
+}
+
+
TEST_F(RenderTextTest, Win_BreakRunsByUnicodeBlocks) {
scoped_ptr<RenderTextWin> render_text(
static_cast<RenderTextWin*>(RenderText::CreateInstance()));
+ // The '\x25B6' "play character" should break runs. http://crbug.com/278913
render_text->SetText(WideToUTF16(L"x\x25B6y"));
render_text->EnsureLayout();
ASSERT_EQ(3U, render_text->runs_.size());
@@ -1750,8 +1801,7 @@ TEST_F(RenderTextTest, Win_BreakRunsByUnicodeBlocks) {
EXPECT_EQ(Range(0, 2), render_text->runs_[0]->range);
EXPECT_EQ(Range(2, 3), render_text->runs_[1]->range);
EXPECT_EQ(Range(3, 5), render_text->runs_[2]->range);
-
}
-#endif // !defined(OS_WIN)
+#endif // defined(OS_WIN)
} // namespace gfx
diff --git a/chromium/ui/gfx/render_text_win.cc b/chromium/ui/gfx/render_text_win.cc
index e283de319ef..4afbc7fa71e 100644
--- a/chromium/ui/gfx/render_text_win.cc
+++ b/chromium/ui/gfx/render_text_win.cc
@@ -159,13 +159,15 @@ Range CharRangeToGlyphRange(const internal::TextRun& run,
// Starting from |start_char|, finds a suitable line break position at or before
// |available_width| using word break info from |breaks|. If |empty_line| is
// true, this function will not roll back to |start_char| and |*next_char| will
-// be greater than |start_char| (to avoid constructing empty lines).
+// be greater than |start_char| (to avoid constructing empty lines). Returns
+// whether to skip the line before |*next_char|.
// TODO(ckocagil): Do not break ligatures and diacritics.
// TextRun::logical_clusters might help.
// TODO(ckocagil): We might have to reshape after breaking at ligatures.
// See whether resolving the TODO above resolves this too.
// TODO(ckocagil): Do not reserve width for whitespace at the end of lines.
-void BreakRunAtWidth(const internal::TextRun& run,
+bool BreakRunAtWidth(const wchar_t* text,
+ const internal::TextRun& run,
const BreakList<size_t>& breaks,
size_t start_char,
int available_width,
@@ -180,6 +182,11 @@ void BreakRunAtWidth(const internal::TextRun& run,
*width = 0;
for (size_t i = start_char; i < run.range.end(); ++i) {
+ if (U16_IS_SINGLE(text[i]) && text[i] == L'\n') {
+ *next_char = i + 1;
+ return true;
+ }
+
// |word| holds the word boundary at or before |i|, and |next_word| holds
// the word boundary right after |i|. Advance both |word| and |next_word|
// when |i| reaches |next_word|.
@@ -198,20 +205,24 @@ void BreakRunAtWidth(const internal::TextRun& run,
if (*width > available_width) {
if (!empty_line || word_width < *width) {
+ // Roll back one word.
*width -= word_width;
*next_char = std::max(word->first, start_char);
} else if (char_width < *width) {
+ // Roll back one character.
*width -= char_width;
*next_char = i;
} else {
+ // Continue from the next character.
*next_char = i + 1;
}
- return;
+ return true;
}
}
*next_char = run.range.end();
+ return false;
}
// For segments in the same run, checks the continuity and order of |x_range|
@@ -246,6 +257,12 @@ void CheckLineIntegrity(const std::vector<internal::Line>& lines,
}
}
+// Returns true if characters of |block_code| may trigger font fallback.
+bool IsUnusualBlockCode(const UBlockCode block_code) {
+ return block_code == UBLOCK_GEOMETRIC_SHAPES ||
+ block_code == UBLOCK_MISCELLANEOUS_SYMBOLS;
+}
+
} // namespace
namespace internal {
@@ -302,12 +319,14 @@ class LineBreaker {
int min_baseline,
int min_height,
bool multiline,
+ const wchar_t* text,
const BreakList<size_t>* words,
const ScopedVector<TextRun>& runs)
: max_width_(max_width),
min_baseline_(min_baseline),
min_height_(min_height),
multiline_(multiline),
+ text_(text),
words_(words),
runs_(runs),
text_x_(0),
@@ -320,7 +339,16 @@ class LineBreaker {
// Breaks the run at given |run_index| into Line structs.
void AddRun(int run_index) {
const TextRun* run = runs_[run_index];
- if (multiline_ && line_x_ + run->width > max_width_)
+ bool run_fits = !multiline_;
+ if (multiline_ && line_x_ + run->width <= max_width_) {
+ DCHECK(!run->range.is_empty());
+ const wchar_t first_char = text_[run->range.start()];
+ // Uniscribe always puts newline characters in their own runs.
+ if (!U16_IS_SINGLE(first_char) || first_char != L'\n')
+ run_fits = true;
+ }
+
+ if (!run_fits)
BreakRun(run_index);
else
AddSegment(run_index, run->range, run->width);
@@ -356,10 +384,10 @@ class LineBreaker {
// Break the run until it fits the current line.
while (next_char < run->range.end()) {
const size_t current_char = next_char;
- BreakRunAtWidth(*run, *words_, current_char, max_width_ - line_x_,
- line_x_ == 0, &width, &next_char);
+ const bool skip_line = BreakRunAtWidth(text_, *run, *words_, current_char,
+ max_width_ - line_x_, line_x_ == 0, &width, &next_char);
AddSegment(run_index, Range(current_char, next_char), width);
- if (next_char < run->range.end())
+ if (skip_line)
AdvanceLine();
}
}
@@ -443,6 +471,7 @@ class LineBreaker {
const int min_baseline_;
const int min_height_;
const bool multiline_;
+ const wchar_t* text_;
const BreakList<size_t>* const words_;
const ScopedVector<TextRun>& runs_;
@@ -493,11 +522,6 @@ Size RenderTextWin::GetStringSize() {
return multiline_string_size_;
}
-int RenderTextWin::GetBaseline() {
- EnsureLayout();
- return lines()[0].baseline;
-}
-
SelectionModel RenderTextWin::FindCursorPosition(const Point& point) {
if (text().empty())
return SelectionModel();
@@ -541,6 +565,11 @@ std::vector<RenderText::FontSpan> RenderTextWin::GetFontSpansForTesting() {
return spans;
}
+int RenderTextWin::GetLayoutTextBaseline() {
+ EnsureLayout();
+ return lines()[0].baseline;
+}
+
SelectionModel RenderTextWin::AdjacentCharSelectionModel(
const SelectionModel& selection,
VisualCursorDirection direction) {
@@ -741,6 +770,7 @@ void RenderTextWin::EnsureLayout() {
internal::LineBreaker line_breaker(display_rect().width() - 1,
font_list().GetBaseline(),
font_list().GetHeight(), multiline(),
+ GetLayoutText().c_str(),
multiline() ? &GetLineBreaks() : NULL,
runs_);
for (size_t i = 0; i < runs_.size(); ++i)
@@ -914,27 +944,31 @@ void RenderTextWin::ItemizeLogicalText() {
// Clamp run lengths to avoid exceeding the maximum supported glyph count.
if ((run_break - run->range.start()) > max_run_length) {
run_break = run->range.start() + max_run_length;
- if (!gfx::IsValidCodePointIndex(layout_text, run_break))
+ if (!IsValidCodePointIndex(layout_text, run_break))
--run_break;
}
- // Break runs between characters in different code blocks. This avoids using
- // fallback fonts for more characters than needed. http://crbug.com/278913
+ // Break runs adjacent to character substrings in certain code blocks.
+ // This avoids using their fallback fonts for more characters than needed,
+ // in cases like "\x25B6 Media Title", etc. http://crbug.com/278913
if (run_break > run->range.start()) {
const size_t run_start = run->range.start();
const int32 run_length = static_cast<int32>(run_break - run_start);
base::i18n::UTF16CharIterator iter(layout_text.c_str() + run_start,
run_length);
const UBlockCode first_block_code = ublock_getCode(iter.get());
+ const bool first_block_unusual = IsUnusualBlockCode(first_block_code);
while (iter.Advance() && iter.array_pos() < run_length) {
- if (ublock_getCode(iter.get()) != first_block_code) {
+ const UBlockCode current_block_code = ublock_getCode(iter.get());
+ if (current_block_code != first_block_code &&
+ (first_block_unusual || IsUnusualBlockCode(current_block_code))) {
run_break = run_start + iter.array_pos();
break;
}
}
}
- DCHECK(gfx::IsValidCodePointIndex(layout_text, run_break));
+ DCHECK(IsValidCodePointIndex(layout_text, run_break));
style.UpdatePosition(LayoutIndexToTextIndex(run_break));
if (script_item_break == run_break)
diff --git a/chromium/ui/gfx/render_text_win.h b/chromium/ui/gfx/render_text_win.h
index 423e31fcad5..1a1ba4805cb 100644
--- a/chromium/ui/gfx/render_text_win.h
+++ b/chromium/ui/gfx/render_text_win.h
@@ -64,12 +64,12 @@ class RenderTextWin : public RenderText {
// Overridden from RenderText:
virtual Size GetStringSize() OVERRIDE;
- virtual int GetBaseline() OVERRIDE;
virtual SelectionModel FindCursorPosition(const Point& point) OVERRIDE;
virtual std::vector<FontSpan> GetFontSpansForTesting() OVERRIDE;
protected:
// Overridden from RenderText:
+ virtual int GetLayoutTextBaseline() OVERRIDE;
virtual SelectionModel AdjacentCharSelectionModel(
const SelectionModel& selection,
VisualCursorDirection direction) OVERRIDE;
diff --git a/chromium/ui/gfx/scoped_canvas.h b/chromium/ui/gfx/scoped_canvas.h
new file mode 100644
index 00000000000..2e59a078760
--- /dev/null
+++ b/chromium/ui/gfx/scoped_canvas.h
@@ -0,0 +1,38 @@
+// Copyright 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_SCOPED_CANVAS_H_
+#define UI_GFX_SCOPED_CANVAS_H_
+
+#include "ui/gfx/canvas.h"
+
+namespace gfx {
+
+// Saves the drawing state, and restores the state when going out of scope.
+class ScopedCanvas {
+ public:
+ explicit ScopedCanvas(gfx::Canvas* canvas) : canvas_(canvas) {
+ if (canvas_)
+ canvas_->Save();
+ }
+ ~ScopedCanvas() {
+ if (canvas_)
+ canvas_->Restore();
+ }
+ void SetCanvas(gfx::Canvas* canvas) {
+ if (canvas_)
+ canvas_->Restore();
+ canvas_ = canvas;
+ canvas_->Save();
+ }
+
+ private:
+ gfx::Canvas* canvas_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScopedCanvas);
+};
+
+} // namespace gfx
+
+#endif // UI_GFX_SCOPED_CANVAS_H_
diff --git a/chromium/ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h b/chromium/ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h
index 9b0b77829b6..d305576701a 100644
--- a/chromium/ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h
+++ b/chromium/ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h
@@ -17,7 +17,7 @@ class NSGraphicsContext;
namespace gfx {
// A class to save/restore the state of the current context.
-class UI_EXPORT ScopedNSGraphicsContextSaveGState {
+class GFX_EXPORT ScopedNSGraphicsContextSaveGState {
public:
ScopedNSGraphicsContextSaveGState();
~ScopedNSGraphicsContextSaveGState();
diff --git a/chromium/ui/gfx/screen.h b/chromium/ui/gfx/screen.h
index a181cc8d256..1d36d1b51cb 100644
--- a/chromium/ui/gfx/screen.h
+++ b/chromium/ui/gfx/screen.h
@@ -25,7 +25,7 @@ class Rect;
// computer -- see the Display class for that. A single Screen object exists on
// most operating systems regardless of the number of connected displays. On
// Windows 8, two Screens exist: one for Metro UI and another for the desktop.
-class UI_EXPORT Screen {
+class GFX_EXPORT Screen {
public:
// Retrieves the Screen that the specified NativeView belongs to. A value of
// NULL is treated as |SCREEN_TYPE_NATIVE|.
diff --git a/chromium/ui/gfx/screen_mac.mm b/chromium/ui/gfx/screen_mac.mm
index 28707ca7ea3..51c0b665b7e 100644
--- a/chromium/ui/gfx/screen_mac.mm
+++ b/chromium/ui/gfx/screen_mac.mm
@@ -7,6 +7,8 @@
#import <ApplicationServices/ApplicationServices.h>
#import <Cocoa/Cocoa.h>
+#include <map>
+
#include "base/logging.h"
#include "base/mac/sdk_forward_declarations.h"
#include "ui/gfx/display.h"
@@ -42,15 +44,16 @@ NSScreen* GetMatchingScreen(const gfx::Rect& match_rect) {
return max_screen;
}
-gfx::Display GetDisplayForScreen(NSScreen* screen, bool is_primary) {
+gfx::Display GetDisplayForScreen(NSScreen* screen) {
NSRect frame = [screen frame];
// TODO(oshima): Implement ID and Observer.
gfx::Display display(0, gfx::Rect(NSRectToCGRect(frame)));
NSRect visible_frame = [screen visibleFrame];
+ NSScreen* primary = [[NSScreen screens] objectAtIndex:0];
// Convert work area's coordinate systems.
- if (is_primary) {
+ if ([screen isEqual:primary]) {
gfx::Rect work_area = gfx::Rect(NSRectToCGRect(visible_frame));
work_area.set_y(frame.size.height - visible_frame.origin.y -
visible_frame.size.height);
@@ -96,10 +99,15 @@ class ScreenMac : public gfx::Screen {
}
virtual int GetNumDisplays() const OVERRIDE {
- // Don't just return the number of online displays. It includes displays
- // that mirror other displays, which are not desired in the count. It's
+ return GetAllDisplays().size();
+
+ }
+
+ virtual std::vector<gfx::Display> GetAllDisplays() const OVERRIDE {
+ // Don't just return all online displays. This would include displays
+ // that mirror other displays, which are not desired in this list. It's
// tempting to use the count returned by CGGetActiveDisplayList, but active
- // displays exclude sleeping displays, and those are desired in the count.
+ // displays exclude sleeping displays, and those are desired.
// It would be ridiculous to have this many displays connected, but
// CGDirectDisplayID is just an integer, so supporting up to this many
@@ -109,29 +117,39 @@ class ScreenMac : public gfx::Screen {
if (CGGetOnlineDisplayList(arraysize(online_displays),
online_displays,
&online_display_count) != kCGErrorSuccess) {
- // 1 is a reasonable assumption.
- return 1;
+ return std::vector<gfx::Display>(1, GetPrimaryDisplay());
}
- int display_count = 0;
+ typedef std::map<int64, NSScreen*> ScreenIdsToScreensMap;
+ ScreenIdsToScreensMap screen_ids_to_screens;
+ for (NSScreen* screen in [NSScreen screens]) {
+ NSDictionary* screen_device_description = [screen deviceDescription];
+ int64 screen_id = [[screen_device_description
+ objectForKey:@"NSScreenNumber"] unsignedIntValue];
+ screen_ids_to_screens[screen_id] = screen;
+ }
+
+ std::vector<gfx::Display> displays;
for (CGDisplayCount online_display_index = 0;
online_display_index < online_display_count;
++online_display_index) {
CGDirectDisplayID online_display = online_displays[online_display_index];
if (CGDisplayMirrorsDisplay(online_display) == kCGNullDirectDisplay) {
- // If this display doesn't mirror any other, include it in the count.
+ // If this display doesn't mirror any other, include it in the list.
// The primary display in a mirrored set will be counted, but those that
// mirror it will not be.
- ++display_count;
+ ScreenIdsToScreensMap::iterator foundScreen =
+ screen_ids_to_screens.find(online_display);
+ if (foundScreen != screen_ids_to_screens.end()) {
+ displays.push_back(GetDisplayForScreen(foundScreen->second));
+ }
}
}
- return display_count;
- }
+ if (!displays.size())
+ return std::vector<gfx::Display>(1, GetPrimaryDisplay());
- virtual std::vector<gfx::Display> GetAllDisplays() const OVERRIDE {
- NOTIMPLEMENTED();
- return std::vector<gfx::Display>(1, GetPrimaryDisplay());
+ return displays;
}
virtual gfx::Display GetDisplayNearestWindow(
@@ -140,7 +158,9 @@ class ScreenMac : public gfx::Screen {
if (!window)
return GetPrimaryDisplay();
NSScreen* match_screen = [window screen];
- return GetDisplayForScreen(match_screen, false /* may not be primary */);
+ if (!match_screen)
+ return GetPrimaryDisplay();
+ return GetDisplayForScreen(match_screen);
}
virtual gfx::Display GetDisplayNearestPoint(
@@ -152,7 +172,7 @@ class ScreenMac : public gfx::Screen {
ns_point.y = NSMaxY([primary frame]) - ns_point.y;
for (NSScreen* screen in screens) {
if (NSMouseInRect(ns_point, [screen frame], NO))
- return GetDisplayForScreen(screen, screen == primary);
+ return GetDisplayForScreen(screen);
}
return GetPrimaryDisplay();
}
@@ -161,7 +181,7 @@ class ScreenMac : public gfx::Screen {
virtual gfx::Display GetDisplayMatching(
const gfx::Rect& match_rect) const OVERRIDE {
NSScreen* match_screen = GetMatchingScreen(match_rect);
- return GetDisplayForScreen(match_screen, false /* may not be primary */);
+ return GetDisplayForScreen(match_screen);
}
// Returns the primary display.
@@ -169,7 +189,7 @@ class ScreenMac : public gfx::Screen {
// Primary display is defined as the display with the menubar,
// which is always at index 0.
NSScreen* primary = [[NSScreen screens] objectAtIndex:0];
- gfx::Display display = GetDisplayForScreen(primary, true /* primary */);
+ gfx::Display display = GetDisplayForScreen(primary);
return display;
}
diff --git a/chromium/ui/gfx/screen_type_delegate.h b/chromium/ui/gfx/screen_type_delegate.h
index 12e8d90939d..4d9f116aedd 100644
--- a/chromium/ui/gfx/screen_type_delegate.h
+++ b/chromium/ui/gfx/screen_type_delegate.h
@@ -9,7 +9,7 @@
namespace gfx {
-enum UI_EXPORT ScreenType {
+enum GFX_EXPORT ScreenType {
SCREEN_TYPE_NATIVE = 0,
#if defined(OS_CHROMEOS)
SCREEN_TYPE_ALTERNATE = SCREEN_TYPE_NATIVE,
@@ -19,7 +19,7 @@ enum UI_EXPORT ScreenType {
SCREEN_TYPE_LAST = SCREEN_TYPE_ALTERNATE,
};
-class UI_EXPORT ScreenTypeDelegate {
+class GFX_EXPORT ScreenTypeDelegate {
public:
virtual ~ScreenTypeDelegate() {}
diff --git a/chromium/ui/gfx/screen_win.h b/chromium/ui/gfx/screen_win.h
index a9fb7f518ff..7b1ea4c7bcc 100644
--- a/chromium/ui/gfx/screen_win.h
+++ b/chromium/ui/gfx/screen_win.h
@@ -11,7 +11,7 @@
namespace gfx {
-class UI_EXPORT ScreenWin : public gfx::Screen {
+class GFX_EXPORT ScreenWin : public gfx::Screen {
public:
ScreenWin();
virtual ~ScreenWin();
diff --git a/chromium/ui/gfx/scrollbar_size.h b/chromium/ui/gfx/scrollbar_size.h
index d11774d17a7..bfea069af74 100644
--- a/chromium/ui/gfx/scrollbar_size.h
+++ b/chromium/ui/gfx/scrollbar_size.h
@@ -12,7 +12,7 @@ namespace gfx {
// This should return the thickness, in pixels, of a scrollbar in web content.
// This needs to match the values in WebCore's
// ScrollbarThemeChromiumXXX.cpp::scrollbarThickness().
-UI_EXPORT int scrollbar_size();
+GFX_EXPORT int scrollbar_size();
} // namespace gfx
diff --git a/chromium/ui/gfx/selection_model.h b/chromium/ui/gfx/selection_model.h
index 0b811d1c5ce..d509e898a99 100644
--- a/chromium/ui/gfx/selection_model.h
+++ b/chromium/ui/gfx/selection_model.h
@@ -56,7 +56,7 @@ enum LogicalCursorDirection {
// is given by a "caret affinity" which is either CURSOR_BACKWARD (indicating
// the trailing half of the 'c' in this case) or CURSOR_FORWARD (indicating
// the leading half of the 'D').
-class UI_EXPORT SelectionModel {
+class GFX_EXPORT SelectionModel {
public:
// Create a default SelectionModel to be overwritten later.
SelectionModel();
diff --git a/chromium/ui/gfx/sequential_id_generator.cc b/chromium/ui/gfx/sequential_id_generator.cc
new file mode 100644
index 00000000000..7d905c7dbc5
--- /dev/null
+++ b/chromium/ui/gfx/sequential_id_generator.cc
@@ -0,0 +1,82 @@
+// 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.
+
+#include "ui/gfx/sequential_id_generator.h"
+
+#include "base/logging.h"
+
+namespace {
+
+// Removes |key| from |first|, and |first[key]| from |second|.
+template<typename T>
+void Remove(uint32 key, T* first, T* second) {
+ typename T::iterator iter = first->find(key);
+ if (iter == first->end())
+ return;
+
+ uint32 second_key = iter->second;
+ first->erase(iter);
+
+ iter = second->find(second_key);
+ DCHECK(iter != second->end());
+ second->erase(iter);
+}
+
+} // namespace
+
+namespace ui {
+
+SequentialIDGenerator::SequentialIDGenerator(uint32 min_id)
+ : min_id_(min_id),
+ min_available_id_(min_id) {
+}
+
+SequentialIDGenerator::~SequentialIDGenerator() {
+}
+
+uint32 SequentialIDGenerator::GetGeneratedID(uint32 number) {
+ IDMap::iterator find = number_to_id_.find(number);
+ if (find != number_to_id_.end())
+ return find->second;
+
+ int id = GetNextAvailableID();
+ number_to_id_.insert(std::make_pair(number, id));
+ id_to_number_.insert(std::make_pair(id, number));
+ return id;
+}
+
+bool SequentialIDGenerator::HasGeneratedIDFor(uint32 number) const {
+ return number_to_id_.find(number) != number_to_id_.end();
+}
+
+void SequentialIDGenerator::ReleaseGeneratedID(uint32 id) {
+ UpdateNextAvailableIDAfterRelease(id);
+ Remove(id, &id_to_number_, &number_to_id_);
+}
+
+void SequentialIDGenerator::ReleaseNumber(uint32 number) {
+ DCHECK_GT(number_to_id_.count(number), 0U);
+ UpdateNextAvailableIDAfterRelease(number_to_id_[number]);
+ Remove(number, &number_to_id_, &id_to_number_);
+}
+
+uint32 SequentialIDGenerator::GetNextAvailableID() {
+ const uint32 kMaxID = 128;
+ while (id_to_number_.count(min_available_id_) > 0 &&
+ min_available_id_ < kMaxID) {
+ ++min_available_id_;
+ }
+ if (min_available_id_ >= kMaxID)
+ min_available_id_ = min_id_;
+ return min_available_id_;
+}
+
+void SequentialIDGenerator::UpdateNextAvailableIDAfterRelease(uint32 id) {
+ if (id < min_available_id_) {
+ min_available_id_ = id;
+ DCHECK_GE(min_available_id_, min_id_);
+ }
+}
+
+} // namespace ui
diff --git a/chromium/ui/gfx/sequential_id_generator.h b/chromium/ui/gfx/sequential_id_generator.h
new file mode 100644
index 00000000000..e277a1562b1
--- /dev/null
+++ b/chromium/ui/gfx/sequential_id_generator.h
@@ -0,0 +1,60 @@
+// 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_SEQUENTIAL_ID_GENERATOR_H_
+#define UI_GFX_SEQUENTIAL_ID_GENERATOR_H_
+
+#include <map>
+
+#include "base/basictypes.h"
+#include "base/containers/hash_tables.h"
+#include "ui/gfx/gfx_export.h"
+
+namespace ui {
+
+// This is used to generate a series of sequential ID numbers in a way that a
+// new ID is always the lowest possible ID in the sequence.
+class GFX_EXPORT SequentialIDGenerator {
+ public:
+ // Creates a new generator with the specified lower bound for the IDs.
+ explicit SequentialIDGenerator(uint32 min_id);
+ ~SequentialIDGenerator();
+
+ // Generates a unique ID to represent |number|. The generated ID is the
+ // smallest available ID greater than or equal to the |min_id| specified
+ // during creation of the generator.
+ uint32 GetGeneratedID(uint32 number);
+
+ // Checks to see if the generator currently has a unique ID generated for
+ // |number|.
+ bool HasGeneratedIDFor(uint32 number) const;
+
+ // Removes the generated ID |id| from the internal mapping. Since the ID is
+ // no longer mapped to any number, subsequent calls to |GetGeneratedID()| can
+ // use this ID.
+ void ReleaseGeneratedID(uint32 id);
+
+ // Removes the ID previously generated for |number| by calling
+ // |GetGeneratedID()|.
+ void ReleaseNumber(uint32 number);
+
+ private:
+ typedef base::hash_map<uint32, uint32> IDMap;
+
+ uint32 GetNextAvailableID();
+
+ void UpdateNextAvailableIDAfterRelease(uint32 id);
+
+ IDMap number_to_id_;
+ IDMap id_to_number_;
+
+ uint32 min_id_;
+ uint32 min_available_id_;
+
+ DISALLOW_COPY_AND_ASSIGN(SequentialIDGenerator);
+};
+
+} // namespace ui
+
+#endif // UI_GFX_SEQUENTIAL_ID_GENERATOR_H_
diff --git a/chromium/ui/gfx/sequential_id_generator_unittest.cc b/chromium/ui/gfx/sequential_id_generator_unittest.cc
new file mode 100644
index 00000000000..7a07f90ff05
--- /dev/null
+++ b/chromium/ui/gfx/sequential_id_generator_unittest.cc
@@ -0,0 +1,62 @@
+// 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.
+
+#include "ui/gfx/sequential_id_generator.h"
+
+#include "base/logging.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace ui {
+
+typedef testing::Test SequentialIDGeneratorTest;
+
+TEST(SequentialIDGeneratorTest, AddRemove) {
+ const uint32 kMinID = 2;
+ SequentialIDGenerator generator(kMinID);
+
+ EXPECT_EQ(2U, generator.GetGeneratedID(45));
+ EXPECT_EQ(3U, generator.GetGeneratedID(23));
+ EXPECT_EQ(2U, generator.GetGeneratedID(45));
+ EXPECT_TRUE(generator.HasGeneratedIDFor(45));
+ EXPECT_TRUE(generator.HasGeneratedIDFor(23));
+
+ generator.ReleaseGeneratedID(2);
+ EXPECT_FALSE(generator.HasGeneratedIDFor(45));
+ EXPECT_TRUE(generator.HasGeneratedIDFor(23));
+ EXPECT_EQ(3U, generator.GetGeneratedID(23));
+
+ EXPECT_FALSE(generator.HasGeneratedIDFor(1));
+ EXPECT_EQ(2U, generator.GetGeneratedID(1));
+ EXPECT_TRUE(generator.HasGeneratedIDFor(1));
+
+ generator.ReleaseGeneratedID(3);
+ EXPECT_EQ(3U, generator.GetGeneratedID(45));
+ EXPECT_TRUE(generator.HasGeneratedIDFor(45));
+
+ generator.ReleaseNumber(45);
+ EXPECT_FALSE(generator.HasGeneratedIDFor(45));
+}
+
+TEST(SequentialIDGeneratorTest, RemoveMultipleNumbers) {
+ const uint32 kMinID = 4;
+ SequentialIDGenerator generator(kMinID);
+
+ EXPECT_EQ(4U, generator.GetGeneratedID(45));
+ EXPECT_EQ(5U, generator.GetGeneratedID(55));
+ EXPECT_EQ(6U, generator.GetGeneratedID(15));
+
+ generator.ReleaseNumber(45);
+ EXPECT_FALSE(generator.HasGeneratedIDFor(45));
+ generator.ReleaseNumber(15);
+ EXPECT_FALSE(generator.HasGeneratedIDFor(15));
+
+ EXPECT_EQ(5U, generator.GetGeneratedID(55));
+ EXPECT_EQ(4U, generator.GetGeneratedID(12));
+
+ generator.ReleaseNumber(12);
+ generator.ReleaseNumber(55);
+ EXPECT_EQ(4U, generator.GetGeneratedID(0));
+}
+
+} // namespace ui
diff --git a/chromium/ui/gfx/shadow_value.h b/chromium/ui/gfx/shadow_value.h
index 46d84b4be3f..60b601e63bd 100644
--- a/chromium/ui/gfx/shadow_value.h
+++ b/chromium/ui/gfx/shadow_value.h
@@ -21,7 +21,7 @@ typedef std::vector<ShadowValue> ShadowValues;
// ShadowValue encapsulates parameters needed to define a shadow, including the
// shadow's offset, blur amount and color.
-class UI_EXPORT ShadowValue {
+class GFX_EXPORT ShadowValue {
public:
ShadowValue();
ShadowValue(const gfx::Point& offset, double blur, SkColor color);
diff --git a/chromium/ui/gfx/size.h b/chromium/ui/gfx/size.h
index c2340ebce63..c96f5897f3b 100644
--- a/chromium/ui/gfx/size.h
+++ b/chromium/ui/gfx/size.h
@@ -23,7 +23,7 @@ typedef struct tagSIZE SIZE;
namespace gfx {
// A size has width and height values.
-class UI_EXPORT Size : public SizeBase<Size, int> {
+class GFX_EXPORT Size : public SizeBase<Size, int> {
public:
Size() : SizeBase<Size, int>(0, 0) {}
Size(int width, int height) : SizeBase<Size, int>(width, height) {}
diff --git a/chromium/ui/gfx/size_base.h b/chromium/ui/gfx/size_base.h
index 72d47d2c37b..c8349dc4b77 100644
--- a/chromium/ui/gfx/size_base.h
+++ b/chromium/ui/gfx/size_base.h
@@ -11,7 +11,7 @@ namespace gfx {
// A size has width and height values.
template<typename Class, typename Type>
-class UI_EXPORT SizeBase {
+class GFX_EXPORT SizeBase {
public:
Type width() const { return width_; }
Type height() const { return height_; }
diff --git a/chromium/ui/gfx/size_conversions.h b/chromium/ui/gfx/size_conversions.h
index f642c4cc7cf..af68195b55b 100644
--- a/chromium/ui/gfx/size_conversions.h
+++ b/chromium/ui/gfx/size_conversions.h
@@ -11,13 +11,13 @@
namespace gfx {
// Returns a Size with each component from the input SizeF floored.
-UI_EXPORT Size ToFlooredSize(const SizeF& size);
+GFX_EXPORT Size ToFlooredSize(const SizeF& size);
// Returns a Size with each component from the input SizeF ceiled.
-UI_EXPORT Size ToCeiledSize(const SizeF& size);
+GFX_EXPORT Size ToCeiledSize(const SizeF& size);
// Returns a Size with each component from the input SizeF rounded.
-UI_EXPORT Size ToRoundedSize(const SizeF& size);
+GFX_EXPORT Size ToRoundedSize(const SizeF& size);
} // namespace gfx
diff --git a/chromium/ui/gfx/size_f.h b/chromium/ui/gfx/size_f.h
index ee90189f7d9..b9065273c8e 100644
--- a/chromium/ui/gfx/size_f.h
+++ b/chromium/ui/gfx/size_f.h
@@ -14,7 +14,7 @@
namespace gfx {
// A floating version of gfx::Size.
-class UI_EXPORT SizeF : public SizeBase<SizeF, float> {
+class GFX_EXPORT SizeF : public SizeBase<SizeF, float> {
public:
SizeF() : SizeBase<SizeF, float>(0, 0) {}
SizeF(float width, float height) : SizeBase<SizeF, float>(width, height) {}
@@ -39,7 +39,7 @@ inline bool operator!=(const SizeF& lhs, const SizeF& rhs) {
return !(lhs == rhs);
}
-UI_EXPORT SizeF ScaleSize(const SizeF& p, float x_scale, float y_scale);
+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);
diff --git a/chromium/ui/gfx/skbitmap_operations.cc b/chromium/ui/gfx/skbitmap_operations.cc
index bcc27238d57..c89153692a4 100644
--- a/chromium/ui/gfx/skbitmap_operations.cc
+++ b/chromium/ui/gfx/skbitmap_operations.cc
@@ -560,10 +560,9 @@ SkBitmap SkBitmapOperations::CreateHSLShiftedBitmap(
SkBitmap shifted;
shifted.setConfig(SkBitmap::kARGB_8888_Config, bitmap.width(),
- bitmap.height(), 0);
+ bitmap.height());
shifted.allocPixels();
shifted.eraseARGB(0, 0, 0, 0);
- shifted.setIsOpaque(false);
SkAutoLockPixels lock_bitmap(bitmap);
SkAutoLockPixels lock_shifted(shifted);
@@ -704,7 +703,8 @@ SkBitmap SkBitmapOperations::UnPreMultiply(const SkBitmap& bitmap) {
return bitmap;
SkBitmap opaque_bitmap;
- opaque_bitmap.setConfig(bitmap.config(), bitmap.width(), bitmap.height());
+ opaque_bitmap.setConfig(bitmap.config(), bitmap.width(), bitmap.height(),
+ 0, kOpaque_SkAlphaType);
opaque_bitmap.allocPixels();
{
@@ -720,7 +720,6 @@ SkBitmap SkBitmapOperations::UnPreMultiply(const SkBitmap& bitmap) {
}
}
- opaque_bitmap.setIsOpaque(true);
return opaque_bitmap;
}
diff --git a/chromium/ui/gfx/skbitmap_operations.h b/chromium/ui/gfx/skbitmap_operations.h
index 3a0d3c97504..fd25d5efc97 100644
--- a/chromium/ui/gfx/skbitmap_operations.h
+++ b/chromium/ui/gfx/skbitmap_operations.h
@@ -17,7 +17,7 @@ class Size;
class SkBitmap;
-class UI_EXPORT SkBitmapOperations {
+class GFX_EXPORT SkBitmapOperations {
public:
// Enum for use in rotating images (must be in 90 degree increments),
// see: Rotate.
diff --git a/chromium/ui/gfx/skbitmap_operations_unittest.cc b/chromium/ui/gfx/skbitmap_operations_unittest.cc
index bfb208cae2a..4e488aa2c45 100644
--- a/chromium/ui/gfx/skbitmap_operations_unittest.cc
+++ b/chromium/ui/gfx/skbitmap_operations_unittest.cc
@@ -63,10 +63,9 @@ SkBitmap ReferenceCreateHSLShiftedBitmap(
color_utils::HSL hsl_shift) {
SkBitmap shifted;
shifted.setConfig(SkBitmap::kARGB_8888_Config, bitmap.width(),
- bitmap.height(), 0);
+ bitmap.height());
shifted.allocPixels();
shifted.eraseARGB(0, 0, 0, 0);
- shifted.setIsOpaque(false);
SkAutoLockPixels lock_bitmap(bitmap);
SkAutoLockPixels lock_shifted(shifted);
diff --git a/chromium/ui/gfx/skia_util.cc b/chromium/ui/gfx/skia_util.cc
index 50092ab13b6..bb7cde7b4ba 100644
--- a/chromium/ui/gfx/skia_util.cc
+++ b/chromium/ui/gfx/skia_util.cc
@@ -50,15 +50,15 @@ RectF SkRectToRectF(const SkRect& rect) {
void TransformToFlattenedSkMatrix(const gfx::Transform& transform,
SkMatrix* flattened) {
// Convert from 4x4 to 3x3 by dropping the third row and column.
- flattened->set(0, SkDoubleToScalar(transform.matrix().getDouble(0, 0)));
- flattened->set(1, SkDoubleToScalar(transform.matrix().getDouble(0, 1)));
- flattened->set(2, SkDoubleToScalar(transform.matrix().getDouble(0, 3)));
- flattened->set(3, SkDoubleToScalar(transform.matrix().getDouble(1, 0)));
- flattened->set(4, SkDoubleToScalar(transform.matrix().getDouble(1, 1)));
- flattened->set(5, SkDoubleToScalar(transform.matrix().getDouble(1, 3)));
- flattened->set(6, SkDoubleToScalar(transform.matrix().getDouble(3, 0)));
- flattened->set(7, SkDoubleToScalar(transform.matrix().getDouble(3, 1)));
- flattened->set(8, SkDoubleToScalar(transform.matrix().getDouble(3, 3)));
+ flattened->set(0, SkMScalarToScalar(transform.matrix().get(0, 0)));
+ flattened->set(1, SkMScalarToScalar(transform.matrix().get(0, 1)));
+ flattened->set(2, SkMScalarToScalar(transform.matrix().get(0, 3)));
+ flattened->set(3, SkMScalarToScalar(transform.matrix().get(1, 0)));
+ flattened->set(4, SkMScalarToScalar(transform.matrix().get(1, 1)));
+ flattened->set(5, SkMScalarToScalar(transform.matrix().get(1, 3)));
+ flattened->set(6, SkMScalarToScalar(transform.matrix().get(3, 0)));
+ flattened->set(7, SkMScalarToScalar(transform.matrix().get(3, 1)));
+ flattened->set(8, SkMScalarToScalar(transform.matrix().get(3, 3)));
}
skia::RefPtr<SkShader> CreateImageRepShader(const gfx::ImageSkiaRep& image_rep,
@@ -68,7 +68,7 @@ skia::RefPtr<SkShader> CreateImageRepShader(const gfx::ImageSkiaRep& image_rep,
image_rep.sk_bitmap(), tile_mode, tile_mode));
SkScalar scale_x = local_matrix.getScaleX();
SkScalar scale_y = local_matrix.getScaleY();
- SkScalar bitmap_scale = SkFloatToScalar(image_rep.GetScale());
+ SkScalar bitmap_scale = SkFloatToScalar(image_rep.scale());
// Unscale matrix by |bitmap_scale| such that the bitmap is drawn at the
// correct density.
diff --git a/chromium/ui/gfx/skia_util.h b/chromium/ui/gfx/skia_util.h
index 592ff5f2f66..92c886a4309 100644
--- a/chromium/ui/gfx/skia_util.h
+++ b/chromium/ui/gfx/skia_util.h
@@ -26,14 +26,14 @@ class ShadowValue;
class Transform;
// Convert between Skia and gfx rect types.
-UI_EXPORT SkRect RectToSkRect(const Rect& rect);
-UI_EXPORT SkIRect RectToSkIRect(const Rect& rect);
-UI_EXPORT Rect SkIRectToRect(const SkIRect& rect);
-UI_EXPORT SkRect RectFToSkRect(const RectF& rect);
-UI_EXPORT RectF SkRectToRectF(const SkRect& rect);
+GFX_EXPORT SkRect RectToSkRect(const Rect& rect);
+GFX_EXPORT SkIRect RectToSkIRect(const Rect& rect);
+GFX_EXPORT Rect SkIRectToRect(const SkIRect& rect);
+GFX_EXPORT SkRect RectFToSkRect(const RectF& rect);
+GFX_EXPORT RectF SkRectToRectF(const SkRect& rect);
-UI_EXPORT void TransformToFlattenedSkMatrix(const gfx::Transform& transform,
- SkMatrix* flattened);
+GFX_EXPORT void TransformToFlattenedSkMatrix(const gfx::Transform& transform,
+ SkMatrix* flattened);
// Creates a bitmap shader for the image rep with the image rep's scale factor.
// Sets the created shader's local matrix such that it displays the image rep at
@@ -42,32 +42,32 @@ UI_EXPORT void TransformToFlattenedSkMatrix(const gfx::Transform& transform,
// TODO(pkotwicz): Allow shader's local matrix to be changed after the shader
// is created.
//
-UI_EXPORT skia::RefPtr<SkShader> CreateImageRepShader(
+GFX_EXPORT skia::RefPtr<SkShader> CreateImageRepShader(
const gfx::ImageSkiaRep& image_rep,
SkShader::TileMode tile_mode,
const SkMatrix& local_matrix);
// Creates a vertical gradient shader. The caller owns the shader.
// Example usage to avoid leaks:
-UI_EXPORT skia::RefPtr<SkShader> CreateGradientShader(int start_point,
- int end_point,
- SkColor start_color,
- SkColor end_color);
+GFX_EXPORT skia::RefPtr<SkShader> CreateGradientShader(int start_point,
+ int end_point,
+ SkColor start_color,
+ SkColor end_color);
// Creates a draw looper to generate |shadows|. The caller owns the draw looper.
// NULL is returned if |shadows| is empty since no draw looper is needed in
// this case.
-UI_EXPORT skia::RefPtr<SkDrawLooper> CreateShadowDrawLooper(
+GFX_EXPORT skia::RefPtr<SkDrawLooper> CreateShadowDrawLooper(
const std::vector<ShadowValue>& shadows);
// Returns true if the two bitmaps contain the same pixels.
-UI_EXPORT bool BitmapsAreEqual(const SkBitmap& bitmap1,
- const SkBitmap& bitmap2);
+GFX_EXPORT bool BitmapsAreEqual(const SkBitmap& bitmap1,
+ const SkBitmap& bitmap2);
// Converts Skia ARGB format pixels in |skia| to RGBA.
-UI_EXPORT void ConvertSkiaToRGBA(const unsigned char* skia,
- int pixel_width,
- unsigned char* rgba);
+GFX_EXPORT void ConvertSkiaToRGBA(const unsigned char* skia,
+ int pixel_width,
+ unsigned char* rgba);
} // namespace gfx
diff --git a/chromium/ui/gfx/skia_utils_gtk.h b/chromium/ui/gfx/skia_utils_gtk.h
index abe397722ac..6b74da246ea 100644
--- a/chromium/ui/gfx/skia_utils_gtk.h
+++ b/chromium/ui/gfx/skia_utils_gtk.h
@@ -13,10 +13,10 @@ typedef struct _GdkColor GdkColor;
namespace gfx {
// Converts GdkColors to the ARGB layout Skia expects.
-UI_EXPORT SkColor GdkColorToSkColor(GdkColor color);
+GFX_EXPORT SkColor GdkColorToSkColor(GdkColor color);
// Converts ARGB to GdkColor.
-UI_EXPORT GdkColor SkColorToGdkColor(SkColor color);
+GFX_EXPORT GdkColor SkColorToGdkColor(SkColor color);
} // namespace gfx
diff --git a/chromium/ui/gfx/switches.h b/chromium/ui/gfx/switches.h
index e3cd9e7db85..c5629f249c4 100644
--- a/chromium/ui/gfx/switches.h
+++ b/chromium/ui/gfx/switches.h
@@ -9,10 +9,10 @@
namespace switches {
-UI_EXPORT extern const char kEnableBrowserTextSubpixelPositioning[];
-UI_EXPORT extern const char kEnableWebkitTextSubpixelPositioning[];
-UI_EXPORT extern const char kForceDeviceScaleFactor[];
-UI_EXPORT extern const char kHighDPISupport[];
+GFX_EXPORT extern const char kEnableBrowserTextSubpixelPositioning[];
+GFX_EXPORT extern const char kEnableWebkitTextSubpixelPositioning[];
+GFX_EXPORT extern const char kForceDeviceScaleFactor[];
+GFX_EXPORT extern const char kHighDPISupport[];
} // namespace switches
diff --git a/chromium/ui/gfx/sys_color_change_listener.h b/chromium/ui/gfx/sys_color_change_listener.h
index db3f9df74cc..31afd0cc49f 100644
--- a/chromium/ui/gfx/sys_color_change_listener.h
+++ b/chromium/ui/gfx/sys_color_change_listener.h
@@ -15,10 +15,10 @@ namespace gfx {
// only true if the system has high-contrast mode enabled and and is using a
// light-on-dark color scheme. To be notified when this status changes, use
// ScopedSysColorChangeListener, below.
-UI_EXPORT bool IsInvertedColorScheme();
+GFX_EXPORT bool IsInvertedColorScheme();
// Interface for classes that want to listen to system color changes.
-class UI_EXPORT SysColorChangeListener {
+class GFX_EXPORT SysColorChangeListener {
public:
virtual void OnSysColorChange() = 0;
@@ -28,7 +28,7 @@ class UI_EXPORT SysColorChangeListener {
// Create an instance of this class in any object that wants to listen
// for system color changes.
-class UI_EXPORT ScopedSysColorChangeListener {
+class GFX_EXPORT ScopedSysColorChangeListener {
public:
explicit ScopedSysColorChangeListener(SysColorChangeListener* listener);
~ScopedSysColorChangeListener();
diff --git a/chromium/ui/gfx/text_constants.h b/chromium/ui/gfx/text_constants.h
index cafeab4669b..4ac788e6109 100644
--- a/chromium/ui/gfx/text_constants.h
+++ b/chromium/ui/gfx/text_constants.h
@@ -28,16 +28,6 @@ enum HorizontalAlignment {
ALIGN_RIGHT,
};
-// Vertical text alignment modes.
-enum VerticalAlignment {
- // Align the text's top edge with that of its display area.
- ALIGN_TOP = 0,
- // Align the text's center with that of its display area.
- ALIGN_VCENTER,
- // Align the text's bottom edge with that of its display area.
- ALIGN_BOTTOM,
-};
-
// The directionality modes used to determine the base text direction.
enum DirectionalityMode {
// Use the first strong character's direction.
diff --git a/chromium/ui/gfx/text_elider.cc b/chromium/ui/gfx/text_elider.cc
index bc4eb3bb858..5b9469614f2 100644
--- a/chromium/ui/gfx/text_elider.cc
+++ b/chromium/ui/gfx/text_elider.cc
@@ -34,16 +34,16 @@ namespace gfx {
// U+2026 in utf8
const char kEllipsis[] = "\xE2\x80\xA6";
-const char16 kEllipsisUTF16[] = { 0x2026, 0 };
-const char16 kForwardSlash = '/';
+const base::char16 kEllipsisUTF16[] = { 0x2026, 0 };
+const base::char16 kForwardSlash = '/';
namespace {
// Helper class to split + elide text, while respecting UTF16 surrogate pairs.
class StringSlicer {
public:
- StringSlicer(const string16& text,
- const string16& ellipsis,
+ StringSlicer(const base::string16& text,
+ const base::string16& ellipsis,
bool elide_in_middle)
: text_(text),
ellipsis_(ellipsis),
@@ -55,8 +55,9 @@ class StringSlicer {
// beginning and end of the string; otherwise, the end of the string is
// removed and only the beginning remains. If |insert_ellipsis| is true,
// then an ellipsis character will be inserted at the cut point.
- string16 CutString(size_t length, bool insert_ellipsis) {
- const string16 ellipsis_text = insert_ellipsis ? ellipsis_ : string16();
+ base::string16 CutString(size_t length, bool insert_ellipsis) {
+ const base::string16 ellipsis_text = insert_ellipsis ? ellipsis_
+ : base::string16();
if (!elide_in_middle_)
return text_.substr(0, FindValidBoundaryBefore(length)) + ellipsis_text;
@@ -90,10 +91,10 @@ class StringSlicer {
}
// The text to be sliced.
- const string16& text_;
+ const base::string16& text_;
// Ellipsis string to use.
- const string16& ellipsis_;
+ const base::string16& ellipsis_;
// If true, the middle of the string will be elided.
bool elide_in_middle_;
@@ -103,12 +104,13 @@ class StringSlicer {
// Build a path from the first |num_components| elements in |path_elements|.
// Prepends |path_prefix|, appends |filename|, inserts ellipsis if appropriate.
-string16 BuildPathFromComponents(const string16& path_prefix,
- const std::vector<string16>& path_elements,
- const string16& filename,
- size_t num_components) {
+base::string16 BuildPathFromComponents(
+ const base::string16& path_prefix,
+ const std::vector<base::string16>& path_elements,
+ const base::string16& filename,
+ size_t num_components) {
// Add the initial elements of the path.
- string16 path = path_prefix;
+ base::string16 path = path_prefix;
// Build path from first |num_components| elements.
for (size_t j = 0; j < num_components; ++j)
@@ -116,7 +118,7 @@ string16 BuildPathFromComponents(const string16& path_prefix,
// Add |filename|, ellipsis if necessary.
if (num_components != (path_elements.size() - 1))
- path += string16(kEllipsisUTF16) + kForwardSlash;
+ path += base::string16(kEllipsisUTF16) + kForwardSlash;
path += filename;
return path;
@@ -125,32 +127,33 @@ string16 BuildPathFromComponents(const string16& path_prefix,
// Takes a prefix (Domain, or Domain+subdomain) and a collection of path
// components and elides if possible. Returns a string containing the longest
// possible elided path, or an empty string if elision is not possible.
-string16 ElideComponentizedPath(const string16& url_path_prefix,
- const std::vector<string16>& url_path_elements,
- const string16& url_filename,
- const string16& url_query,
- const gfx::FontList& font_list,
- int available_pixel_width) {
+base::string16 ElideComponentizedPath(
+ const base::string16& url_path_prefix,
+ const std::vector<base::string16>& url_path_elements,
+ const base::string16& url_filename,
+ const base::string16& url_query,
+ const FontList& font_list,
+ float available_pixel_width) {
const size_t url_path_number_of_elements = url_path_elements.size();
CHECK(url_path_number_of_elements);
for (size_t i = url_path_number_of_elements - 1; i > 0; --i) {
- string16 elided_path = BuildPathFromComponents(url_path_prefix,
+ base::string16 elided_path = BuildPathFromComponents(url_path_prefix,
url_path_elements, url_filename, i);
- if (available_pixel_width >= gfx::GetStringWidth(elided_path, font_list))
+ if (available_pixel_width >= GetStringWidthF(elided_path, font_list))
return ElideText(elided_path + url_query, font_list,
available_pixel_width, ELIDE_AT_END);
}
- return string16();
+ return base::string16();
}
} // namespace
-string16 ElideEmail(const string16& email,
- const gfx::FontList& font_list,
- int available_pixel_width) {
- if (gfx::GetStringWidth(email, font_list) <= available_pixel_width)
+base::string16 ElideEmail(const base::string16& email,
+ const FontList& font_list,
+ float available_pixel_width) {
+ if (GetStringWidthF(email, font_list) <= available_pixel_width)
return email;
// Split the email into its local-part (username) and domain-part. The email
@@ -159,32 +162,32 @@ string16 ElideEmail(const string16& email,
// symbol in the domain part of the email however so splitting at the last @
// symbol is safe.
const size_t split_index = email.find_last_of('@');
- DCHECK_NE(split_index, string16::npos);
- string16 username = email.substr(0, split_index);
- string16 domain = email.substr(split_index + 1);
+ DCHECK_NE(split_index, base::string16::npos);
+ base::string16 username = email.substr(0, split_index);
+ base::string16 domain = email.substr(split_index + 1);
DCHECK(!username.empty());
DCHECK(!domain.empty());
// Subtract the @ symbol from the available width as it is mandatory.
- const string16 kAtSignUTF16 = ASCIIToUTF16("@");
- available_pixel_width -= gfx::GetStringWidth(kAtSignUTF16, font_list);
+ const base::string16 kAtSignUTF16 = ASCIIToUTF16("@");
+ available_pixel_width -= GetStringWidthF(kAtSignUTF16, font_list);
// Check whether eliding the domain is necessary: if eliding the username
// is sufficient, the domain will not be elided.
- const int full_username_width = gfx::GetStringWidth(username, font_list);
- const int available_domain_width =
+ const float full_username_width = GetStringWidthF(username, font_list);
+ const float available_domain_width =
available_pixel_width -
std::min(full_username_width,
- gfx::GetStringWidth(username.substr(0, 1) + kEllipsisUTF16,
- font_list));
- if (gfx::GetStringWidth(domain, font_list) > available_domain_width) {
+ GetStringWidthF(username.substr(0, 1) + kEllipsisUTF16,
+ font_list));
+ if (GetStringWidthF(domain, font_list) > available_domain_width) {
// Elide the domain so that it only takes half of the available width.
// Should the username not need all the width available in its half, the
// domain will occupy the leftover width.
// If |desired_domain_width| is greater than |available_domain_width|: the
// minimal username elision allowed by the specifications will not fit; thus
// |desired_domain_width| must be <= |available_domain_width| at all cost.
- const int desired_domain_width =
+ const float desired_domain_width =
std::min(available_domain_width,
std::max(available_pixel_width - full_username_width,
available_pixel_width / 2));
@@ -193,36 +196,30 @@ string16 ElideEmail(const string16& email,
// Failing to elide the domain such that at least one character remains
// (other than the ellipsis itself) remains: return a single ellipsis.
if (domain.length() <= 1U)
- return string16(kEllipsisUTF16);
+ return base::string16(kEllipsisUTF16);
}
// Fit the username in the remaining width (at this point the elided username
// is guaranteed to fit with at least one character remaining given all the
// precautions taken earlier).
- available_pixel_width -= gfx::GetStringWidth(domain, font_list);
+ available_pixel_width -= GetStringWidthF(domain, font_list);
username = ElideText(username, font_list, available_pixel_width,
ELIDE_AT_END);
return username + kAtSignUTF16 + domain;
}
-string16 ElideEmail(const string16& email,
- const gfx::Font& font,
- int available_pixel_width) {
- return ElideEmail(email, gfx::FontList(font), available_pixel_width);
-}
-
// TODO(pkasting): http://crbug.com/77883 This whole function gets
// kerning/ligatures/etc. issues potentially wrong by assuming that the width of
// a rendered string is always the sum of the widths of its substrings. Also I
// suspect it could be made simpler.
-string16 ElideUrl(const GURL& url,
- const gfx::FontList& font_list,
- int available_pixel_width,
- const std::string& languages) {
+base::string16 ElideUrl(const GURL& url,
+ const FontList& font_list,
+ float available_pixel_width,
+ const std::string& languages) {
// Get a formatted string and corresponding parsing of the url.
url_parse::Parsed parsed;
- const string16 url_string =
+ const base::string16 url_string =
net::FormatUrl(url, languages, net::kFormatUrlOmitAll,
net::UnescapeRule::SPACES, &parsed, NULL, NULL);
if (available_pixel_width <= 0)
@@ -235,28 +232,28 @@ string16 ElideUrl(const GURL& url,
// Now start eliding url_string to fit within available pixel width.
// Fist pass - check to see whether entire url_string fits.
- const int pixel_width_url_string = gfx::GetStringWidth(url_string, font_list);
+ const float pixel_width_url_string = GetStringWidthF(url_string, font_list);
if (available_pixel_width >= pixel_width_url_string)
return url_string;
// Get the path substring, including query and reference.
const size_t path_start_index = parsed.path.begin;
const size_t path_len = parsed.path.len;
- string16 url_path_query_etc = url_string.substr(path_start_index);
- string16 url_path = url_string.substr(path_start_index, path_len);
+ base::string16 url_path_query_etc = url_string.substr(path_start_index);
+ base::string16 url_path = url_string.substr(path_start_index, path_len);
// Return general elided text if url minus the query fits.
- const string16 url_minus_query =
+ const base::string16 url_minus_query =
url_string.substr(0, path_start_index + path_len);
- if (available_pixel_width >= gfx::GetStringWidth(url_minus_query, font_list))
+ if (available_pixel_width >= GetStringWidthF(url_minus_query, font_list))
return ElideText(url_string, font_list, available_pixel_width,
ELIDE_AT_END);
// Get Host.
- string16 url_host = UTF8ToUTF16(url.host());
+ base::string16 url_host = UTF8ToUTF16(url.host());
// Get domain and registry information from the URL.
- string16 url_domain = UTF8ToUTF16(
+ base::string16 url_domain = UTF8ToUTF16(
net::registry_controlled_domains::GetDomainAndRegistry(
url, net::registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES));
if (url_domain.empty())
@@ -269,11 +266,11 @@ string16 ElideUrl(const GURL& url,
}
// Get sub domain.
- string16 url_subdomain;
+ base::string16 url_subdomain;
const size_t domain_start_index = url_host.find(url_domain);
- if (domain_start_index != string16::npos)
+ if (domain_start_index != base::string16::npos)
url_subdomain = url_host.substr(0, domain_start_index);
- const string16 kWwwPrefix = UTF8ToUTF16("www.");
+ const base::string16 kWwwPrefix = UTF8ToUTF16("www.");
if ((url_subdomain == kWwwPrefix || url_subdomain.empty() ||
url.SchemeIsFile())) {
url_subdomain.clear();
@@ -284,59 +281,59 @@ string16 ElideUrl(const GURL& url,
// domain is now C: - this is a nice hack for eliding to work pleasantly.
if (url.SchemeIsFile()) {
// Split the path string using ":"
- std::vector<string16> file_path_split;
+ std::vector<base::string16> file_path_split;
base::SplitString(url_path, ':', &file_path_split);
if (file_path_split.size() > 1) { // File is of type "file:///C:/.."
url_host.clear();
url_domain.clear();
url_subdomain.clear();
- const string16 kColon = UTF8ToUTF16(":");
+ const base::string16 kColon = UTF8ToUTF16(":");
url_host = url_domain = file_path_split.at(0).substr(1) + kColon;
url_path_query_etc = url_path = file_path_split.at(1);
}
}
// Second Pass - remove scheme - the rest fits.
- const int pixel_width_url_host = gfx::GetStringWidth(url_host, font_list);
- const int pixel_width_url_path = gfx::GetStringWidth(url_path_query_etc,
- font_list);
+ const float pixel_width_url_host = GetStringWidthF(url_host, font_list);
+ const float pixel_width_url_path = GetStringWidthF(url_path_query_etc,
+ font_list);
if (available_pixel_width >=
pixel_width_url_host + pixel_width_url_path)
return url_host + url_path_query_etc;
// Third Pass: Subdomain, domain and entire path fits.
- const int pixel_width_url_domain = gfx::GetStringWidth(url_domain, font_list);
- const int pixel_width_url_subdomain = gfx::GetStringWidth(url_subdomain,
- font_list);
+ const float pixel_width_url_domain = GetStringWidthF(url_domain, font_list);
+ const float pixel_width_url_subdomain =
+ GetStringWidthF(url_subdomain, font_list);
if (available_pixel_width >=
pixel_width_url_subdomain + pixel_width_url_domain +
pixel_width_url_path)
return url_subdomain + url_domain + url_path_query_etc;
// Query element.
- string16 url_query;
- const int kPixelWidthDotsTrailer = gfx::GetStringWidth(
- string16(kEllipsisUTF16), font_list);
+ base::string16 url_query;
+ const float kPixelWidthDotsTrailer = GetStringWidthF(
+ base::string16(kEllipsisUTF16), font_list);
if (parsed.query.is_nonempty()) {
url_query = UTF8ToUTF16("?") + url_string.substr(parsed.query.begin);
if (available_pixel_width >=
(pixel_width_url_subdomain + pixel_width_url_domain +
- pixel_width_url_path - gfx::GetStringWidth(url_query, font_list))) {
+ pixel_width_url_path - GetStringWidthF(url_query, font_list))) {
return ElideText(url_subdomain + url_domain + url_path_query_etc,
font_list, available_pixel_width, ELIDE_AT_END);
}
}
// Parse url_path using '/'.
- std::vector<string16> url_path_elements;
+ std::vector<base::string16> url_path_elements;
base::SplitString(url_path, kForwardSlash, &url_path_elements);
// Get filename - note that for a path ending with /
// such as www.google.com/intl/ads/, the file name is ads/.
size_t url_path_number_of_elements = url_path_elements.size();
DCHECK(url_path_number_of_elements != 0);
- string16 url_filename;
+ base::string16 url_filename;
if ((url_path_elements.at(url_path_number_of_elements - 1)).length() > 0) {
url_filename = *(url_path_elements.end() - 1);
} else if (url_path_number_of_elements > 1) { // Path ends with a '/'.
@@ -356,12 +353,13 @@ string16 ElideUrl(const GURL& url,
}
// Start eliding the path and replacing elements by ".../".
- const string16 kEllipsisAndSlash = string16(kEllipsisUTF16) + kForwardSlash;
- const int pixel_width_ellipsis_slash = gfx::GetStringWidth(kEllipsisAndSlash,
- font_list);
+ const base::string16 kEllipsisAndSlash =
+ base::string16(kEllipsisUTF16) + kForwardSlash;
+ const float pixel_width_ellipsis_slash =
+ GetStringWidthF(kEllipsisAndSlash, font_list);
// Check with both subdomain and domain.
- string16 elided_path =
+ base::string16 elided_path =
ElideComponentizedPath(url_subdomain + url_domain, url_path_elements,
url_filename, url_query, font_list,
available_pixel_width);
@@ -373,7 +371,7 @@ string16 ElideUrl(const GURL& url,
// This is added only if the subdomain pixel width is larger than
// the pixel width of kEllipsis. Otherwise, subdomain remains,
// which means that this case has been resolved earlier.
- string16 url_elided_domain = url_subdomain + url_domain;
+ base::string16 url_elided_domain = url_subdomain + url_domain;
if (pixel_width_url_subdomain > kPixelWidthDotsTrailer) {
if (!url_subdomain.empty())
url_elided_domain = kEllipsisAndSlash[0] + url_domain;
@@ -389,15 +387,15 @@ string16 ElideUrl(const GURL& url,
}
// Return elided domain/.../filename anyway.
- string16 final_elided_url_string(url_elided_domain);
- const int url_elided_domain_width = gfx::GetStringWidth(url_elided_domain,
- font_list);
+ base::string16 final_elided_url_string(url_elided_domain);
+ const float url_elided_domain_width = GetStringWidthF(url_elided_domain,
+ font_list);
// A hack to prevent trailing ".../...".
if ((available_pixel_width - url_elided_domain_width) >
pixel_width_ellipsis_slash + kPixelWidthDotsTrailer +
- gfx::GetStringWidth(ASCIIToUTF16("UV"), font_list)) {
- final_elided_url_string += BuildPathFromComponents(string16(),
+ GetStringWidthF(ASCIIToUTF16("UV"), font_list)) {
+ final_elided_url_string += BuildPathFromComponents(base::string16(),
url_path_elements, url_filename, 1);
} else {
final_elided_url_string += url_path;
@@ -407,80 +405,67 @@ string16 ElideUrl(const GURL& url,
ELIDE_AT_END);
}
-string16 ElideUrl(const GURL& url,
- const gfx::Font& font,
- int available_pixel_width,
- const std::string& languages) {
- return ElideUrl(url, gfx::FontList(font), available_pixel_width, languages);
-}
-
-string16 ElideFilename(const base::FilePath& filename,
- const gfx::FontList& font_list,
- int available_pixel_width) {
+base::string16 ElideFilename(const base::FilePath& filename,
+ const FontList& font_list,
+ float available_pixel_width) {
#if defined(OS_WIN)
- string16 filename_utf16 = filename.value();
- string16 extension = filename.Extension();
- string16 rootname = filename.BaseName().RemoveExtension().value();
+ base::string16 filename_utf16 = filename.value();
+ base::string16 extension = filename.Extension();
+ base::string16 rootname = filename.BaseName().RemoveExtension().value();
#elif defined(OS_POSIX)
- string16 filename_utf16 = WideToUTF16(base::SysNativeMBToWide(
+ base::string16 filename_utf16 = WideToUTF16(base::SysNativeMBToWide(
filename.value()));
- string16 extension = WideToUTF16(base::SysNativeMBToWide(
+ base::string16 extension = WideToUTF16(base::SysNativeMBToWide(
filename.Extension()));
- string16 rootname = WideToUTF16(base::SysNativeMBToWide(
+ base::string16 rootname = WideToUTF16(base::SysNativeMBToWide(
filename.BaseName().RemoveExtension().value()));
#endif
- const int full_width = gfx::GetStringWidth(filename_utf16, font_list);
+ const float full_width = GetStringWidthF(filename_utf16, font_list);
if (full_width <= available_pixel_width)
return base::i18n::GetDisplayStringInLTRDirectionality(filename_utf16);
if (rootname.empty() || extension.empty()) {
- const string16 elided_name = ElideText(filename_utf16, font_list,
+ const base::string16 elided_name = ElideText(filename_utf16, font_list,
available_pixel_width, ELIDE_AT_END);
return base::i18n::GetDisplayStringInLTRDirectionality(elided_name);
}
- const int ext_width = gfx::GetStringWidth(extension, font_list);
- const int root_width = gfx::GetStringWidth(rootname, font_list);
+ const float ext_width = GetStringWidthF(extension, font_list);
+ const float root_width = GetStringWidthF(rootname, font_list);
// We may have trimmed the path.
if (root_width + ext_width <= available_pixel_width) {
- const string16 elided_name = rootname + extension;
+ const base::string16 elided_name = rootname + extension;
return base::i18n::GetDisplayStringInLTRDirectionality(elided_name);
}
if (ext_width >= available_pixel_width) {
- const string16 elided_name = ElideText(rootname + extension, font_list,
- available_pixel_width,
- ELIDE_IN_MIDDLE);
+ const base::string16 elided_name = ElideText(
+ rootname + extension, font_list, available_pixel_width,
+ ELIDE_IN_MIDDLE);
return base::i18n::GetDisplayStringInLTRDirectionality(elided_name);
}
- int available_root_width = available_pixel_width - ext_width;
- string16 elided_name =
+ float available_root_width = available_pixel_width - ext_width;
+ base::string16 elided_name =
ElideText(rootname, font_list, available_root_width, ELIDE_AT_END);
elided_name += extension;
return base::i18n::GetDisplayStringInLTRDirectionality(elided_name);
}
-string16 ElideFilename(const base::FilePath& filename,
- const gfx::Font& font,
- int available_pixel_width) {
- return ElideFilename(filename, gfx::FontList(font), available_pixel_width);
-}
-
-string16 ElideText(const string16& text,
- const gfx::FontList& font_list,
- int available_pixel_width,
- ElideBehavior elide_behavior) {
+base::string16 ElideText(const base::string16& text,
+ const FontList& font_list,
+ float available_pixel_width,
+ ElideBehavior elide_behavior) {
if (text.empty())
return text;
- const int current_text_pixel_width = gfx::GetStringWidth(text, font_list);
+ const float current_text_pixel_width = GetStringWidthF(text, font_list);
const bool elide_in_middle = (elide_behavior == ELIDE_IN_MIDDLE);
const bool insert_ellipsis = (elide_behavior != TRUNCATE_AT_END);
- const string16 ellipsis = string16(kEllipsisUTF16);
+ const base::string16 ellipsis = base::string16(kEllipsisUTF16);
StringSlicer slicer(text, ellipsis, elide_in_middle);
// Pango will return 0 width for absurdly long strings. Cut the string in
@@ -492,7 +477,7 @@ string16 ElideText(const string16& text,
// (eliding way too much from a ridiculous string is probably still
// ridiculous), but we should check other widths for bogus values as well.
if (current_text_pixel_width <= 0 && !text.empty()) {
- const string16 cut = slicer.CutString(text.length() / 2, false);
+ const base::string16 cut = slicer.CutString(text.length() / 2, false);
return ElideText(cut, font_list, available_pixel_width, elide_behavior);
}
@@ -500,8 +485,8 @@ string16 ElideText(const string16& text,
return text;
if (insert_ellipsis &&
- gfx::GetStringWidth(ellipsis, font_list) > available_pixel_width)
- return string16();
+ GetStringWidthF(ellipsis, font_list) > available_pixel_width)
+ return base::string16();
// Use binary search to compute the elided text.
size_t lo = 0;
@@ -510,8 +495,8 @@ string16 ElideText(const string16& text,
for (guess = (lo + hi) / 2; lo <= hi; guess = (lo + hi) / 2) {
// We check the length of the whole desired string at once to ensure we
// handle kerning/ligatures/etc. correctly.
- const string16 cut = slicer.CutString(guess, insert_ellipsis);
- const int guess_length = gfx::GetStringWidth(cut, font_list);
+ const base::string16 cut = slicer.CutString(guess, insert_ellipsis);
+ const float guess_length = GetStringWidthF(cut, font_list);
// Check again that we didn't hit a Pango width overflow. If so, cut the
// current string in half and start over.
if (guess_length <= 0) {
@@ -527,18 +512,17 @@ string16 ElideText(const string16& text,
return slicer.CutString(guess, insert_ellipsis);
}
-string16 ElideText(const string16& text,
- const gfx::Font& font,
- int available_pixel_width,
- ElideBehavior elide_behavior) {
- return ElideText(text, gfx::FontList(font), available_pixel_width,
- elide_behavior);
+base::string16 ElideText(const base::string16& text,
+ const Font& font,
+ float available_pixel_width,
+ ElideBehavior elide_behavior) {
+ return ElideText(text, FontList(font), available_pixel_width, elide_behavior);
}
SortedDisplayURL::SortedDisplayURL(const GURL& url,
const std::string& languages) {
net::AppendFormattedHost(url, languages, &sort_host_);
- string16 host_minus_www = net::StripWWW(sort_host_);
+ base::string16 host_minus_www = net::StripWWW(sort_host_);
url_parse::Parsed parsed;
display_url_ =
net::FormatUrl(url, languages, net::kFormatUrlOmitAll,
@@ -570,8 +554,8 @@ int SortedDisplayURL::Compare(const SortedDisplayURL& other,
return host_compare_result;
// Hosts match, compare on the portion of the url after the host.
- string16 path = this->AfterHost();
- string16 o_path = other.AfterHost();
+ base::string16 path = this->AfterHost();
+ base::string16 o_path = other.AfterHost();
compare_status = U_ZERO_ERROR;
UCollationResult path_compare_result = collator->compare(
static_cast<const UChar*>(path.c_str()),
@@ -596,16 +580,17 @@ int SortedDisplayURL::Compare(const SortedDisplayURL& other,
return display_url_compare_result;
}
-string16 SortedDisplayURL::AfterHost() const {
+base::string16 SortedDisplayURL::AfterHost() const {
const size_t slash_index = display_url_.find(sort_host_, prefix_end_);
- if (slash_index == string16::npos) {
+ if (slash_index == base::string16::npos) {
NOTREACHED();
- return string16();
+ return base::string16();
}
return display_url_.substr(slash_index + sort_host_.length());
}
-bool ElideString(const string16& input, int max_len, string16* output) {
+bool ElideString(const base::string16& input, int max_len,
+ base::string16* output) {
DCHECK_GE(max_len, 0);
if (static_cast<int>(input.length()) <= max_len) {
output->assign(input);
@@ -650,7 +635,7 @@ namespace {
class RectangleString {
public:
RectangleString(size_t max_rows, size_t max_cols,
- bool strict, string16 *output)
+ bool strict, base::string16 *output)
: max_rows_(max_rows),
max_cols_(max_cols),
current_row_(0),
@@ -667,7 +652,7 @@ class RectangleString {
// AddString() may be called multiple times to concatenate together
// multiple strings into the region (the current caller doesn't do
// this, however).
- void AddString(const string16& input);
+ void AddString(const base::string16& input);
// Perform any deferred output processing. Must be called after the
// last AddString() call has occurred.
@@ -676,15 +661,15 @@ class RectangleString {
private:
// Add a line to the rectangular region at the current position,
// either by itself or by breaking it into words.
- void AddLine(const string16& line);
+ void AddLine(const base::string16& line);
// Add a word to the rectangular region at the current position,
// either by itself or by breaking it into characters.
- void AddWord(const string16& word);
+ void AddWord(const base::string16& word);
// Add text to the output string if the rectangular boundaries
// have not been exceeded, advancing the current position.
- void Append(const string16& string);
+ void Append(const base::string16& string);
// Set the current position to the beginning of the next line. If
// |output| is true, add a newline to the output string if the rectangular
@@ -716,12 +701,12 @@ class RectangleString {
bool suppressed_;
// String onto which the output is accumulated.
- string16* output_;
+ base::string16* output_;
DISALLOW_COPY_AND_ASSIGN(RectangleString);
};
-void RectangleString::AddString(const string16& input) {
+void RectangleString::AddString(const base::string16& input) {
base::i18n::BreakIterator lines(input,
base::i18n::BreakIterator::BREAK_NEWLINE);
if (lines.Init()) {
@@ -740,7 +725,7 @@ bool RectangleString::Finalize() {
return false;
}
-void RectangleString::AddLine(const string16& line) {
+void RectangleString::AddLine(const base::string16& line) {
if (line.length() < max_cols_) {
Append(line);
} else {
@@ -758,7 +743,7 @@ void RectangleString::AddLine(const string16& line) {
current_col_ = 0;
}
-void RectangleString::AddWord(const string16& word) {
+void RectangleString::AddWord(const base::string16& word) {
if (word.length() < max_cols_) {
// Word can be made to fit, no need to fragment it.
if (current_col_ + word.length() >= max_cols_)
@@ -785,7 +770,7 @@ void RectangleString::AddWord(const string16& word) {
}
}
-void RectangleString::Append(const string16& string) {
+void RectangleString::Append(const base::string16& string) {
if (current_row_ < max_rows_)
output_->append(string);
else
@@ -809,11 +794,11 @@ void RectangleString::NewLine(bool output) {
// can be broken into smaller methods sharing this state.
class RectangleText {
public:
- RectangleText(const gfx::FontList& font_list,
- int available_pixel_width,
+ RectangleText(const FontList& font_list,
+ float available_pixel_width,
int available_pixel_height,
WordWrapBehavior wrap_behavior,
- std::vector<string16>* lines)
+ std::vector<base::string16>* lines)
: font_list_(font_list),
line_height_(font_list.GetHeight()),
available_pixel_width_(available_pixel_width),
@@ -834,7 +819,7 @@ class RectangleText {
// AddString() may be called multiple times to concatenate together
// multiple strings into the region (the current caller doesn't do
// this, however).
- void AddString(const string16& input);
+ void AddString(const base::string16& input);
// Perform any deferred output processing. Must be called after the last
// AddString() call has occured. Returns a combination of
@@ -845,36 +830,36 @@ class RectangleText {
private:
// Add a line to the rectangular region at the current position,
// either by itself or by breaking it into words.
- void AddLine(const string16& line);
+ void AddLine(const base::string16& line);
// Wrap the specified word across multiple lines.
- int WrapWord(const string16& word);
+ int WrapWord(const base::string16& word);
// Add a long word - wrapping, eliding or truncating per the wrap behavior.
- int AddWordOverflow(const string16& word);
+ int AddWordOverflow(const base::string16& word);
// Add a word to the rectangluar region at the current position.
- int AddWord(const string16& word);
+ int AddWord(const base::string16& word);
// Append the specified |text| to the current output line, incrementing the
// running width by the specified amount. This is an optimization over
// |AddToCurrentLine()| when |text_width| is already known.
- void AddToCurrentLineWithWidth(const string16& text, int text_width);
+ void AddToCurrentLineWithWidth(const base::string16& text, float text_width);
// Append the specified |text| to the current output line.
- void AddToCurrentLine(const string16& text);
+ void AddToCurrentLine(const base::string16& text);
// Set the current position to the beginning of the next line.
bool NewLine();
// The font list used for measuring text width.
- const gfx::FontList& font_list_;
+ const FontList& font_list_;
// The height of each line of text.
const int line_height_;
// The number of pixels of available width in the rectangle.
- const int available_pixel_width_;
+ const float available_pixel_width_;
// The number of pixels of available height in the rectangle.
const int available_pixel_height_;
@@ -883,19 +868,19 @@ class RectangleText {
const WordWrapBehavior wrap_behavior_;
// The current running width.
- int current_width_;
+ float current_width_;
// The current running height.
int current_height_;
// The current line of text.
- string16 current_line_;
+ base::string16 current_line_;
// Indicates whether the last line ended with \n.
bool last_line_ended_in_lf_;
// The output vector of lines.
- std::vector<string16>* lines_;
+ std::vector<base::string16>* lines_;
// Indicates whether a word was so long that it had to be truncated or elided
// to fit the available width.
@@ -907,12 +892,12 @@ class RectangleText {
DISALLOW_COPY_AND_ASSIGN(RectangleText);
};
-void RectangleText::AddString(const string16& input) {
+void RectangleText::AddString(const base::string16& input) {
base::i18n::BreakIterator lines(input,
base::i18n::BreakIterator::BREAK_NEWLINE);
if (lines.Init()) {
while (!insufficient_height_ && lines.Advance()) {
- string16 line = lines.GetString();
+ base::string16 line = lines.GetString();
// The BREAK_NEWLINE iterator will keep the trailing newline character,
// except in the case of the last line, which may not have one. Remove
// the newline character, if it exists.
@@ -935,13 +920,13 @@ int RectangleText::Finalize() {
lines_->pop_back();
}
if (last_line_ended_in_lf_)
- lines_->push_back(string16());
+ lines_->push_back(base::string16());
return (insufficient_width_ ? INSUFFICIENT_SPACE_HORIZONTAL : 0) |
(insufficient_height_ ? INSUFFICIENT_SPACE_VERTICAL : 0);
}
-void RectangleText::AddLine(const string16& line) {
- const int line_width = gfx::GetStringWidth(line, font_list_);
+void RectangleText::AddLine(const base::string16& line) {
+ const float line_width = GetStringWidthF(line, font_list_);
if (line_width <= available_pixel_width_) {
AddToCurrentLineWithWidth(line, line_width);
} else {
@@ -952,7 +937,7 @@ void RectangleText::AddLine(const string16& line) {
if (words.Init()) {
while (words.Advance()) {
const bool truncate = !current_line_.empty();
- const string16& word = words.GetString();
+ const base::string16& word = words.GetString();
const int lines_added = AddWord(word);
if (lines_added) {
if (truncate) {
@@ -975,13 +960,13 @@ void RectangleText::AddLine(const string16& line) {
NewLine();
}
-int RectangleText::WrapWord(const string16& word) {
+int RectangleText::WrapWord(const base::string16& word) {
// Word is so wide that it must be fragmented.
- string16 text = word;
+ base::string16 text = word;
int lines_added = 0;
bool first_fragment = true;
while (!insufficient_height_ && !text.empty()) {
- string16 fragment =
+ base::string16 fragment =
ElideText(text, font_list_, available_pixel_width_,
TRUNCATE_AT_END);
// At least one character has to be added at every line, even if the
@@ -997,7 +982,7 @@ int RectangleText::WrapWord(const string16& word) {
return lines_added;
}
-int RectangleText::AddWordOverflow(const string16& word) {
+int RectangleText::AddWordOverflow(const base::string16& word) {
int lines_added = 0;
// Unless this is the very first word, put it on a new line.
@@ -1015,7 +1000,7 @@ int RectangleText::AddWordOverflow(const string16& word) {
} else {
const ElideBehavior elide_behavior =
(wrap_behavior_ == ELIDE_LONG_WORDS ? ELIDE_AT_END : TRUNCATE_AT_END);
- const string16 elided_word =
+ const base::string16 elided_word =
ElideText(word, font_list_, available_pixel_width_, elide_behavior);
AddToCurrentLine(elided_word);
insufficient_width_ = true;
@@ -1024,11 +1009,11 @@ int RectangleText::AddWordOverflow(const string16& word) {
return lines_added;
}
-int RectangleText::AddWord(const string16& word) {
+int RectangleText::AddWord(const base::string16& word) {
int lines_added = 0;
- string16 trimmed;
+ base::string16 trimmed;
TrimWhitespace(word, TRIM_TRAILING, &trimmed);
- const int trimmed_width = gfx::GetStringWidth(trimmed, font_list_);
+ const float trimmed_width = GetStringWidthF(trimmed, font_list_);
if (trimmed_width <= available_pixel_width_) {
// Word can be made to fit, no need to fragment it.
if ((current_width_ + trimmed_width > available_pixel_width_) && NewLine())
@@ -1042,12 +1027,12 @@ int RectangleText::AddWord(const string16& word) {
return lines_added;
}
-void RectangleText::AddToCurrentLine(const string16& text) {
- AddToCurrentLineWithWidth(text, gfx::GetStringWidth(text, font_list_));
+void RectangleText::AddToCurrentLine(const base::string16& text) {
+ AddToCurrentLineWithWidth(text, GetStringWidthF(text, font_list_));
}
-void RectangleText::AddToCurrentLineWithWidth(const string16& text,
- int text_width) {
+void RectangleText::AddToCurrentLineWithWidth(const base::string16& text,
+ float text_width) {
if (current_height_ >= available_pixel_height_) {
insufficient_height_ = true;
return;
@@ -1072,20 +1057,21 @@ bool RectangleText::NewLine() {
} // namespace
-bool ElideRectangleString(const string16& input, size_t max_rows,
- size_t max_cols, bool strict, string16* output) {
+bool ElideRectangleString(const base::string16& input, size_t max_rows,
+ size_t max_cols, bool strict,
+ base::string16* output) {
RectangleString rect(max_rows, max_cols, strict, output);
rect.Init();
rect.AddString(input);
return rect.Finalize();
}
-int ElideRectangleText(const string16& input,
- const gfx::FontList& font_list,
- int available_pixel_width,
+int ElideRectangleText(const base::string16& input,
+ const FontList& font_list,
+ float available_pixel_width,
int available_pixel_height,
WordWrapBehavior wrap_behavior,
- std::vector<string16>* lines) {
+ std::vector<base::string16>* lines) {
RectangleText rect(font_list,
available_pixel_width,
available_pixel_height,
@@ -1096,30 +1082,19 @@ int ElideRectangleText(const string16& input,
return rect.Finalize();
}
-int ElideRectangleText(const string16& input,
- const gfx::Font& font,
- int available_pixel_width,
- int available_pixel_height,
- WordWrapBehavior wrap_behavior,
- std::vector<string16>* lines) {
- return ElideRectangleText(input, gfx::FontList(font),
- available_pixel_width, available_pixel_height,
- wrap_behavior, lines);
-}
-
-string16 TruncateString(const string16& string, size_t length) {
+base::string16 TruncateString(const base::string16& string, size_t length) {
if (string.size() <= length)
// String fits, return it.
return string;
if (length == 0)
// No room for the elide string, return an empty string.
- return string16();
+ return base::string16();
size_t max = length - 1;
// Added to the end of strings that are too big.
- static const char16 kElideString[] = { 0x2026, 0 };
+ static const base::char16 kElideString[] = { 0x2026, 0 };
if (max == 0)
// Just enough room for the elide string.
diff --git a/chromium/ui/gfx/text_elider.h b/chromium/ui/gfx/text_elider.h
index 008a1cd1b5b..4eaca828c7d 100644
--- a/chromium/ui/gfx/text_elider.h
+++ b/chromium/ui/gfx/text_elider.h
@@ -26,8 +26,8 @@ namespace gfx {
class Font;
class FontList;
-UI_EXPORT extern const char kEllipsis[];
-UI_EXPORT extern const char16 kEllipsisUTF16[];
+GFX_EXPORT extern const char kEllipsis[];
+GFX_EXPORT extern const base::char16 kEllipsisUTF16[];
// Elides a well-formed email address (e.g. username@domain.com) to fit into
// |available_pixel_width| using the specified |font_list|.
@@ -39,13 +39,9 @@ UI_EXPORT extern const char16 kEllipsisUTF16[];
// equally with the elided username (should the username be short enough that it
// doesn't need half the available width: the elided domain will occupy that
// extra width).
-UI_EXPORT string16 ElideEmail(const string16& email,
- const gfx::FontList& font_list,
- int available_pixel_width);
-// Obsolete version. Use the above version which takes gfx::FontList.
-UI_EXPORT string16 ElideEmail(const string16& email,
- const gfx::Font& font,
- int available_pixel_width);
+GFX_EXPORT base::string16 ElideEmail(const base::string16& email,
+ const gfx::FontList& font_list,
+ float available_pixel_width);
// This function takes a GURL object and elides it. It returns a string
// which composed of parts from subdomain, domain, path, filename and query.
@@ -61,15 +57,10 @@ UI_EXPORT string16 ElideEmail(const string16& email,
// as an LTR string (using base::i18n::WrapStringWithLTRFormatting()) so that it
// is displayed properly in an RTL context. Please refer to
// http://crbug.com/6487 for more information.
-UI_EXPORT string16 ElideUrl(const GURL& url,
- const gfx::FontList& font_list,
- int available_pixel_width,
- const std::string& languages);
-// Obsolete version. Use the above version which takes gfx::FontList.
-UI_EXPORT string16 ElideUrl(const GURL& url,
- const gfx::Font& font,
- int available_pixel_width,
- const std::string& languages);
+GFX_EXPORT base::string16 ElideUrl(const GURL& url,
+ const gfx::FontList& font_list,
+ float available_pixel_width,
+ const std::string& languages);
enum ElideBehavior {
// Add ellipsis at the end of the string.
@@ -82,15 +73,15 @@ enum ElideBehavior {
// Elides |text| to fit in |available_pixel_width| according to the specified
// |elide_behavior|.
-UI_EXPORT string16 ElideText(const string16& text,
- const gfx::FontList& font_list,
- int available_pixel_width,
- ElideBehavior elide_behavior);
+GFX_EXPORT base::string16 ElideText(const base::string16& text,
+ const gfx::FontList& font_list,
+ float available_pixel_width,
+ ElideBehavior elide_behavior);
// Obsolete version. Use the above version which takes gfx::FontList.
-UI_EXPORT string16 ElideText(const string16& text,
- const gfx::Font& font,
- int available_pixel_width,
- ElideBehavior elide_behavior);
+GFX_EXPORT base::string16 ElideText(const base::string16& text,
+ const gfx::Font& font,
+ float available_pixel_width,
+ ElideBehavior elide_behavior);
// Elide a filename to fit a given pixel width, with an emphasis on not hiding
// the extension unless we have to. If filename contains a path, the path will
@@ -98,20 +89,16 @@ UI_EXPORT string16 ElideText(const string16& text,
// filename is forced to have LTR directionality, which means that in RTL UI
// the elided filename is wrapped with LRE (Left-To-Right Embedding) mark and
// PDF (Pop Directional Formatting) mark.
-UI_EXPORT string16 ElideFilename(const base::FilePath& filename,
- const gfx::FontList& font_list,
- int available_pixel_width);
-// Obsolete version. Use the above version which takes gfx::FontList.
-UI_EXPORT string16 ElideFilename(const base::FilePath& filename,
- const gfx::Font& font,
- int available_pixel_width);
+GFX_EXPORT base::string16 ElideFilename(const base::FilePath& filename,
+ const gfx::FontList& font_list,
+ float available_pixel_width);
// SortedDisplayURL maintains a string from a URL suitable for display to the
// use. SortedDisplayURL also provides a function used for comparing two
// SortedDisplayURLs for use in visually ordering the SortedDisplayURLs.
//
// SortedDisplayURL is relatively cheap and supports value semantics.
-class UI_EXPORT SortedDisplayURL {
+class GFX_EXPORT SortedDisplayURL {
public:
SortedDisplayURL(const GURL& url, const std::string& languages);
SortedDisplayURL();
@@ -123,20 +110,20 @@ class UI_EXPORT SortedDisplayURL {
int Compare(const SortedDisplayURL& other, icu::Collator* collator) const;
// Returns the display string for the URL.
- const string16& display_url() const { return display_url_; }
+ const base::string16& display_url() const { return display_url_; }
private:
// Returns everything after the host. This is used by Compare if the hosts
// match.
- string16 AfterHost() const;
+ base::string16 AfterHost() const;
// Host name minus 'www.'. Used by Compare.
- string16 sort_host_;
+ base::string16 sort_host_;
// End of the prefix (spec and separator) in display_url_.
size_t prefix_end_;
- string16 display_url_;
+ base::string16 display_url_;
DISALLOW_COPY_AND_ASSIGN(SortedDisplayURL);
};
@@ -154,8 +141,8 @@ class UI_EXPORT SortedDisplayURL {
// puts "Hell...Tom" in str and returns true.
// TODO(tsepez): Doesn't handle UTF-16 surrogate pairs properly.
// TODO(tsepez): Doesn't handle bidi properly.
-UI_EXPORT bool ElideString(const string16& input, int max_len,
- string16* output);
+GFX_EXPORT bool ElideString(const base::string16& input, int max_len,
+ base::string16* output);
// Reformat |input| into |output| so that it fits into a |max_rows| by
// |max_cols| rectangle of characters. Input newlines are respected, but
@@ -166,9 +153,11 @@ UI_EXPORT bool ElideString(const string16& input, int max_len,
// intra-word (respecting UTF-16 surrogate pairs) as necssary. Truncation
// (indicated by an added 3 dots) occurs if the result is still too long.
// Returns true if the input had to be truncated (and not just reformatted).
-UI_EXPORT bool ElideRectangleString(const string16& input, size_t max_rows,
- size_t max_cols, bool strict,
- string16* output);
+GFX_EXPORT bool ElideRectangleString(const base::string16& input,
+ size_t max_rows,
+ size_t max_cols,
+ bool strict,
+ base::string16* output);
// Specifies the word wrapping behavior of |ElideRectangleText()| when a word
// would exceed the available width.
@@ -206,26 +195,20 @@ enum ReformattingResultFlags {
// param. Returns a combination of |ReformattingResultFlags| that indicate
// whether the given rectangle had insufficient space to accommodate |texŧ|,
// leading to elision or truncation (and not just reformatting).
-UI_EXPORT int ElideRectangleText(const string16& text,
- const gfx::FontList& font_list,
- int available_pixel_width,
- int available_pixel_height,
- WordWrapBehavior wrap_behavior,
- std::vector<string16>* lines);
-// Obsolete version. Use the above version which takes gfx::FontList.
-UI_EXPORT int ElideRectangleText(const string16& text,
- const gfx::Font& font,
- int available_pixel_width,
- int available_pixel_height,
- WordWrapBehavior wrap_behavior,
- std::vector<string16>* lines);
+GFX_EXPORT int ElideRectangleText(const base::string16& text,
+ const gfx::FontList& font_list,
+ float available_pixel_width,
+ int available_pixel_height,
+ WordWrapBehavior wrap_behavior,
+ std::vector<base::string16>* lines);
// Truncates the string to length characters. This breaks the string at
// the first word break before length, adding the horizontal ellipsis
// character (unicode character 0x2026) to render ...
// The supplied string is returned if the string has length characters or
// less.
-UI_EXPORT string16 TruncateString(const string16& string, size_t length);
+GFX_EXPORT base::string16 TruncateString(const base::string16& string,
+ size_t length);
} // namespace gfx
diff --git a/chromium/ui/gfx/text_elider_unittest.cc b/chromium/ui/gfx/text_elider_unittest.cc
index 2a90e5d73cb..5fa74cbd101 100644
--- a/chromium/ui/gfx/text_elider_unittest.cc
+++ b/chromium/ui/gfx/text_elider_unittest.cc
@@ -13,6 +13,8 @@
#include "base/strings/utf_string_conversions.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/font.h"
+#include "ui/gfx/font_list.h"
+#include "ui/gfx/text_utils.h"
#include "url/gurl.h"
namespace gfx {
@@ -41,36 +43,22 @@ struct TestData {
};
void RunUrlTest(Testcase* testcases, size_t num_testcases) {
- static const gfx::Font font;
+ static const FontList font_list;
for (size_t i = 0; i < num_testcases; ++i) {
const GURL url(testcases[i].input);
// Should we test with non-empty language list?
// That's kinda redundant with net_util_unittests.
+ const float available_width =
+ GetStringWidthF(UTF8ToUTF16(testcases[i].output), font_list);
EXPECT_EQ(UTF8ToUTF16(testcases[i].output),
- ElideUrl(url, font,
- font.GetStringWidth(UTF8ToUTF16(testcases[i].output)),
- std::string()));
+ ElideUrl(url, font_list, available_width, std::string()));
}
}
-gfx::Font GetTestingFont() {
- gfx::Font font;
-#if defined(OS_MACOSX)
- // Use a specific font for certain tests on Mac.
- // 1) Different Mac machines might be configured with different default font.
- // The number of extra pixels needed to make ElideEmail/TestFilenameEliding
- // tests work might vary per the default font.
- // 2) This specific font helps expose the line width exceeding problem as in
- // ElideRectangleTextCheckLineWidth.
- font = gfx::Font("LucidaGrande", 12);
-#endif
- return font;
-}
-
} // namespace
-// TODO(ios): Complex eliding is off by one for some of those tests on iOS.
-// See crbug.com/154019
+// TODO(ios): This test fails on iOS because iOS version of GetStringWidthF
+// that calls [NSString sizeWithFont] returns the rounded string width.
#if defined(OS_IOS)
#define MAYBE_ElideEmail DISABLED_ElideEmail
#else
@@ -121,22 +109,14 @@ TEST(TextEliderTest, MAYBE_ElideEmail) {
{"mmmmm@llllllllll", "m" + kEllipsisStr + "@l" + kEllipsisStr},
};
- const gfx::Font font = GetTestingFont();
+ const FontList font_list;
for (size_t i = 0; i < arraysize(testcases); ++i) {
const string16 expected_output = UTF8ToUTF16(testcases[i].output);
- int available_width = font.GetStringWidth(expected_output);
-#if defined(OS_MACOSX)
- // Give two extra pixels to offset the ceiling width returned by
- // GetStringWidth on Mac. This workaround will no longer be needed once
- // the floating point width is adopted (http://crbug.com/288987).
- // Note that we need one more pixel than TestFilenameEliding because
- // multiple strings are elided and we need to offset more.
- available_width += 2;
-#endif
EXPECT_EQ(expected_output,
- ElideEmail(UTF8ToUTF16(testcases[i].input),
- font,
- available_width));
+ ElideEmail(
+ UTF8ToUTF16(testcases[i].input),
+ font_list,
+ GetStringWidthF(expected_output, font_list)));
}
}
@@ -153,14 +133,14 @@ TEST(TextEliderTest, ElideEmailMoreSpace) {
"supermegalongusername@withasuperlonnnggggdomain.gouv.qc.ca",
};
- const gfx::Font font;
+ const FontList font_list;
for (size_t i = 0; i < arraysize(test_width_factors); ++i) {
- const int test_width = test_width_factors[i] *
- font.GetAverageCharacterWidth();
+ const int test_width =
+ font_list.GetExpectedTextWidth(test_width_factors[i]);
for (size_t j = 0; j < arraysize(test_emails); ++j) {
// Extra space is available: the email should not be elided.
const string16 test_email = UTF8ToUTF16(test_emails[j]);
- EXPECT_EQ(test_email, ElideEmail(test_email, font, test_width));
+ EXPECT_EQ(test_email, ElideEmail(test_email, font_list, test_width));
}
}
}
@@ -199,23 +179,26 @@ TEST(TextEliderTest, TestTrailingEllipsisSlashEllipsisHack) {
const std::string kEllipsisStr(kEllipsis);
// Very little space, would cause double ellipsis.
- gfx::Font font;
+ FontList font_list;
GURL url("http://battersbox.com/directory/foo/peter_paul_and_mary.html");
- int available_width = font.GetStringWidth(
- UTF8ToUTF16("battersbox.com/" + kEllipsisStr + "/" + kEllipsisStr));
+ float available_width = GetStringWidthF(
+ UTF8ToUTF16("battersbox.com/" + kEllipsisStr + "/" + kEllipsisStr),
+ font_list);
// Create the expected string, after elision. Depending on font size, the
// directory might become /dir... or /di... or/d... - it never should be
// shorter than that. (If it is, the font considers d... to be longer
// than .../... - that should never happen).
- ASSERT_GT(font.GetStringWidth(UTF8ToUTF16(kEllipsisStr + "/" + kEllipsisStr)),
- font.GetStringWidth(UTF8ToUTF16("d" + kEllipsisStr)));
+ ASSERT_GT(GetStringWidthF(UTF8ToUTF16(kEllipsisStr + "/" + kEllipsisStr),
+ font_list),
+ GetStringWidthF(UTF8ToUTF16("d" + kEllipsisStr), font_list));
GURL long_url("http://battersbox.com/directorynameisreallylongtoforcetrunc");
- string16 expected = ElideUrl(long_url, font, available_width, std::string());
+ string16 expected =
+ ElideUrl(long_url, font_list, available_width, std::string());
// Ensure that the expected result still contains part of the directory name.
ASSERT_GT(expected.length(), std::string("battersbox.com/d").length());
EXPECT_EQ(expected,
- ElideUrl(url, font, available_width, std::string()));
+ ElideUrl(url, font_list, available_width, std::string()));
// More space available - elide directories, partially elide filename.
Testcase testcases[] = {
@@ -288,8 +271,8 @@ TEST(TextEliderTest, TestFileURLEliding) {
RunUrlTest(testcases, arraysize(testcases));
}
-// TODO(ios): Complex eliding is off by one for some of those tests on iOS.
-// See crbug.com/154019
+// TODO(ios): This test fails on iOS because iOS version of GetStringWidthF
+// that calls [NSString sizeWithFont] returns the rounded string width.
#if defined(OS_IOS)
#define MAYBE_TestFilenameEliding DISABLED_TestFilenameEliding
#else
@@ -334,28 +317,22 @@ TEST(TextEliderTest, MAYBE_TestFilenameEliding) {
"file.name.re" + kEllipsisStr + "emelylongext"}
};
- static const gfx::Font font = GetTestingFont();
+ static const FontList font_list;
for (size_t i = 0; i < arraysize(testcases); ++i) {
base::FilePath filepath(testcases[i].input);
string16 expected = UTF8ToUTF16(testcases[i].output);
expected = base::i18n::GetDisplayStringInLTRDirectionality(expected);
- int available_width = font.GetStringWidth(UTF8ToUTF16(testcases[i].output));
-#if defined(OS_MACOSX)
- // Give one extra pixel to offset the ceiling width returned by
- // GetStringWidth on Mac. This workaround will no longer be needed once
- // the floating point width is adopted (http://crbug.com/288987).
- available_width += 1;
-#endif
- EXPECT_EQ(expected, ElideFilename(filepath, font, available_width));
+ EXPECT_EQ(expected, ElideFilename(filepath, font_list,
+ GetStringWidthF(UTF8ToUTF16(testcases[i].output), font_list)));
}
}
TEST(TextEliderTest, ElideTextTruncate) {
- const gfx::Font font;
- const int kTestWidth = font.GetStringWidth(ASCIIToUTF16("Test"));
+ const FontList font_list;
+ const float kTestWidth = GetStringWidthF(ASCIIToUTF16("Test"), font_list);
struct TestData {
const char* input;
- int width;
+ float width;
const char* output;
} cases[] = {
{ "", 0, "" },
@@ -367,20 +344,21 @@ TEST(TextEliderTest, ElideTextTruncate) {
};
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) {
- string16 result = ElideText(UTF8ToUTF16(cases[i].input), font,
+ string16 result = ElideText(UTF8ToUTF16(cases[i].input), font_list,
cases[i].width, TRUNCATE_AT_END);
EXPECT_EQ(cases[i].output, UTF16ToUTF8(result));
}
}
TEST(TextEliderTest, ElideTextEllipsis) {
- const gfx::Font font;
- const int kTestWidth = font.GetStringWidth(ASCIIToUTF16("Test"));
+ const FontList font_list;
+ const float kTestWidth = GetStringWidthF(ASCIIToUTF16("Test"), font_list);
const char* kEllipsis = "\xE2\x80\xA6";
- const int kEllipsisWidth = font.GetStringWidth(UTF8ToUTF16(kEllipsis));
+ const float kEllipsisWidth =
+ GetStringWidthF(UTF8ToUTF16(kEllipsis), font_list);
struct TestData {
const char* input;
- int width;
+ float width;
const char* output;
} cases[] = {
{ "", 0, "" },
@@ -392,7 +370,7 @@ TEST(TextEliderTest, ElideTextEllipsis) {
};
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) {
- string16 result = ElideText(UTF8ToUTF16(cases[i].input), font,
+ string16 result = ElideText(UTF8ToUTF16(cases[i].input), font_list,
cases[i].width, ELIDE_AT_END);
EXPECT_EQ(cases[i].output, UTF16ToUTF8(result));
}
@@ -418,27 +396,27 @@ static void CheckSurrogatePairs(const string16& text,
}
TEST(TextEliderTest, ElideTextSurrogatePairs) {
- const gfx::Font font;
+ const FontList font_list;
// The below is 'MUSICAL SYMBOL G CLEF', which is represented in UTF-16 as
// two characters forming a surrogate pair 0x0001D11E.
const std::string kSurrogate = "\xF0\x9D\x84\x9E";
const string16 kTestString =
UTF8ToUTF16(kSurrogate + "ab" + kSurrogate + kSurrogate + "cd");
- const int kTestStringWidth = font.GetStringWidth(kTestString);
+ const float kTestStringWidth = GetStringWidthF(kTestString, font_list);
const char16 kSurrogateFirstChar = kTestString[0];
const char16 kSurrogateSecondChar = kTestString[1];
string16 result;
// Elide |kTextString| to all possible widths and check that no instance of
// |kSurrogate| was split in two.
- for (int width = 0; width <= kTestStringWidth; width++) {
- result = ElideText(kTestString, font, width, TRUNCATE_AT_END);
+ for (float width = 0; width <= kTestStringWidth; width++) {
+ result = ElideText(kTestString, font_list, width, TRUNCATE_AT_END);
CheckSurrogatePairs(result, kSurrogateFirstChar, kSurrogateSecondChar);
- result = ElideText(kTestString, font, width, ELIDE_AT_END);
+ result = ElideText(kTestString, font_list, width, ELIDE_AT_END);
CheckSurrogatePairs(result, kSurrogateFirstChar, kSurrogateSecondChar);
- result = ElideText(kTestString, font, width, ELIDE_IN_MIDDLE);
+ result = ElideText(kTestString, font_list, width, ELIDE_IN_MIDDLE);
CheckSurrogatePairs(result, kSurrogateFirstChar, kSurrogateSecondChar);
}
}
@@ -467,17 +445,19 @@ TEST(TextEliderTest, ElideTextLongStrings) {
{data_scheme + million_a, long_string_end},
};
- const gfx::Font font;
- int ellipsis_width = font.GetStringWidth(kEllipsisStr);
+ const FontList font_list;
+ float ellipsis_width = GetStringWidthF(kEllipsisStr, font_list);
for (size_t i = 0; i < arraysize(testcases_end); ++i) {
// Compare sizes rather than actual contents because if the test fails,
// output is rather long.
EXPECT_EQ(testcases_end[i].output.size(),
- ElideText(testcases_end[i].input, font,
- font.GetStringWidth(testcases_end[i].output),
- ELIDE_AT_END).size());
+ ElideText(
+ testcases_end[i].input,
+ font_list,
+ GetStringWidthF(testcases_end[i].output, font_list),
+ ELIDE_AT_END).size());
EXPECT_EQ(kEllipsisStr,
- ElideText(testcases_end[i].input, font, ellipsis_width,
+ ElideText(testcases_end[i].input, font_list, ellipsis_width,
ELIDE_AT_END));
}
@@ -498,11 +478,13 @@ TEST(TextEliderTest, ElideTextLongStrings) {
// Compare sizes rather than actual contents because if the test fails,
// output is rather long.
EXPECT_EQ(testcases_middle[i].output.size(),
- ElideText(testcases_middle[i].input, font,
- font.GetStringWidth(testcases_middle[i].output),
- ELIDE_AT_END).size());
+ ElideText(
+ testcases_middle[i].input,
+ font_list,
+ GetStringWidthF(testcases_middle[i].output, font_list),
+ ELIDE_AT_END).size());
EXPECT_EQ(kEllipsisStr,
- ElideText(testcases_middle[i].input, font, ellipsis_width,
+ ElideText(testcases_middle[i].input, font_list, ellipsis_width,
ELIDE_AT_END));
}
}
@@ -580,13 +562,13 @@ TEST(TextEliderTest, ElideString) {
}
TEST(TextEliderTest, ElideRectangleText) {
- const gfx::Font font;
- const int line_height = font.GetHeight();
- const int test_width = font.GetStringWidth(ASCIIToUTF16("Test"));
+ const FontList font_list;
+ const int line_height = font_list.GetHeight();
+ const float test_width = GetStringWidthF(ASCIIToUTF16("Test"), font_list);
struct TestData {
const char* input;
- int available_pixel_width;
+ float available_pixel_width;
int available_pixel_height;
bool truncated_y;
const char* output;
@@ -622,7 +604,7 @@ TEST(TextEliderTest, ElideRectangleText) {
std::vector<string16> lines;
EXPECT_EQ(cases[i].truncated_y ? INSUFFICIENT_SPACE_VERTICAL : 0,
ElideRectangleText(UTF8ToUTF16(cases[i].input),
- font,
+ font_list,
cases[i].available_pixel_width,
cases[i].available_pixel_height,
TRUNCATE_LONG_WORDS,
@@ -637,14 +619,14 @@ TEST(TextEliderTest, ElideRectangleText) {
}
TEST(TextEliderTest, ElideRectangleTextPunctuation) {
- const gfx::Font font;
- const int line_height = font.GetHeight();
- const int test_width = font.GetStringWidth(ASCIIToUTF16("Test"));
- const int test_t_width = font.GetStringWidth(ASCIIToUTF16("Test T"));
+ const FontList font_list;
+ const int line_height = font_list.GetHeight();
+ const float test_width = GetStringWidthF(ASCIIToUTF16("Test"), font_list);
+ const float test_t_width = GetStringWidthF(ASCIIToUTF16("Test T"), font_list);
struct TestData {
const char* input;
- int available_pixel_width;
+ float available_pixel_width;
int available_pixel_height;
bool wrap_words;
bool truncated_x;
@@ -662,7 +644,7 @@ TEST(TextEliderTest, ElideRectangleTextPunctuation) {
(cases[i].wrap_words ? WRAP_LONG_WORDS : TRUNCATE_LONG_WORDS);
EXPECT_EQ(cases[i].truncated_x ? INSUFFICIENT_SPACE_HORIZONTAL : 0,
ElideRectangleText(UTF8ToUTF16(cases[i].input),
- font,
+ font_list,
cases[i].available_pixel_width,
cases[i].available_pixel_height,
wrap_behavior,
@@ -677,15 +659,15 @@ TEST(TextEliderTest, ElideRectangleTextPunctuation) {
}
TEST(TextEliderTest, ElideRectangleTextLongWords) {
- const gfx::Font font;
+ const FontList font_list;
const int kAvailableHeight = 1000;
const string16 kElidedTesting = UTF8ToUTF16(std::string("Tes") + kEllipsis);
- const int elided_width = font.GetStringWidth(kElidedTesting);
- const int test_width = font.GetStringWidth(ASCIIToUTF16("Test"));
+ const float elided_width = GetStringWidthF(kElidedTesting, font_list);
+ const float test_width = GetStringWidthF(ASCIIToUTF16("Test"), font_list);
struct TestData {
const char* input;
- int available_pixel_width;
+ float available_pixel_width;
WordWrapBehavior wrap_behavior;
bool truncated_x;
const char* output;
@@ -723,7 +705,7 @@ TEST(TextEliderTest, ElideRectangleTextLongWords) {
std::vector<string16> lines;
EXPECT_EQ(cases[i].truncated_x ? INSUFFICIENT_SPACE_HORIZONTAL : 0,
ElideRectangleText(UTF8ToUTF16(cases[i].input),
- font,
+ font_list,
cases[i].available_pixel_width,
kAvailableHeight,
cases[i].wrap_behavior,
@@ -735,35 +717,30 @@ TEST(TextEliderTest, ElideRectangleTextLongWords) {
}
}
-// TODO(ios): Complex eliding is off by one for some of those tests on iOS.
-// See crbug.com/154019
-#if defined(OS_IOS)
-#define MAYBE_ElideRectangleTextCheckLineWidth \
- DISABLED_ElideRectangleTextCheckLineWidth
-#else
-#define MAYBE_ElideRectangleTextCheckLineWidth ElideRectangleTextCheckLineWidth
-#endif
-
// This test is to make sure that the width of each wrapped line does not
// exceed the available width. On some platform like Mac, this test used to
// fail because the truncated integer width is returned for the string
// and the accumulation of the truncated values causes the elide function
// to wrap incorrectly.
-TEST(TextEliderTest, MAYBE_ElideRectangleTextCheckLineWidth) {
- gfx::Font font = GetTestingFont();
- const int kAvailableWidth = 235;
+TEST(TextEliderTest, ElideRectangleTextCheckLineWidth) {
+ FontList font_list;
+#if defined(OS_MACOSX) && !defined(OS_IOS)
+ // Use a specific font to expose the line width exceeding problem.
+ font_list = FontList(Font("LucidaGrande", 12));
+#endif
+ const float kAvailableWidth = 235;
const int kAvailableHeight = 1000;
const char text[] = "that Russian place we used to go to after fencing";
std::vector<string16> lines;
EXPECT_EQ(0, ElideRectangleText(UTF8ToUTF16(text),
- font,
+ font_list,
kAvailableWidth,
kAvailableHeight,
WRAP_LONG_WORDS,
&lines));
ASSERT_EQ(2u, lines.size());
- EXPECT_LE(font.GetStringWidth(lines[0]), kAvailableWidth);
- EXPECT_LE(font.GetStringWidth(lines[1]), kAvailableWidth);
+ EXPECT_LE(GetStringWidthF(lines[0], font_list), kAvailableWidth);
+ EXPECT_LE(GetStringWidthF(lines[1], font_list), kAvailableWidth);
}
TEST(TextEliderTest, ElideRectangleString) {
diff --git a/chromium/ui/gfx/text_utils.h b/chromium/ui/gfx/text_utils.h
index bd94902fba6..088f97cea9e 100644
--- a/chromium/ui/gfx/text_utils.h
+++ b/chromium/ui/gfx/text_utils.h
@@ -17,15 +17,19 @@ class FontList;
// |accelerated_char_pos| and |accelerated_char_span| will be set to the index
// and span of the last accelerated character, respectively, or -1 and 0 if
// there was none.
-UI_EXPORT base::string16 RemoveAcceleratorChar(const base::string16& s,
- base::char16 accelerator_char,
- int* accelerated_char_pos,
- int* accelerated_char_span);
+GFX_EXPORT base::string16 RemoveAcceleratorChar(const base::string16& s,
+ base::char16 accelerator_char,
+ int* accelerated_char_pos,
+ int* accelerated_char_span);
// Returns the number of horizontal pixels needed to display the specified
// |text| with |font_list|.
-UI_EXPORT int GetStringWidth(const base::string16& text,
- const FontList& font_list);
+GFX_EXPORT int GetStringWidth(const base::string16& text,
+ const FontList& font_list);
+
+// This is same as GetStringWidth except that fractional width is returned.
+GFX_EXPORT float GetStringWidthF(const base::string16& text,
+ const FontList& font_list);
} // namespace gfx
diff --git a/chromium/ui/gfx/text_utils_android.cc b/chromium/ui/gfx/text_utils_android.cc
index c564b9b1db0..93938d57ff0 100644
--- a/chromium/ui/gfx/text_utils_android.cc
+++ b/chromium/ui/gfx/text_utils_android.cc
@@ -13,4 +13,9 @@ int GetStringWidth(const base::string16& text, const FontList& font_list) {
return 0;
}
+float GetStringWidthF(const base::string16& text, const FontList& font_list) {
+ NOTIMPLEMENTED();
+ return 0;
+}
+
} // namespace gfx
diff --git a/chromium/ui/gfx/text_utils_ios.mm b/chromium/ui/gfx/text_utils_ios.mm
index 1841864ff85..56c01df7f55 100644
--- a/chromium/ui/gfx/text_utils_ios.mm
+++ b/chromium/ui/gfx/text_utils_ios.mm
@@ -14,9 +14,13 @@
namespace gfx {
int GetStringWidth(const base::string16& text, const FontList& font_list) {
+ return std::ceil(GetStringWidthF(text, font_list));
+}
+
+float GetStringWidthF(const base::string16& text, const FontList& font_list) {
NSString* ns_text = base::SysUTF16ToNSString(text);
NativeFont native_font = font_list.GetPrimaryFont().GetNativeFont();
- return std::ceil([ns_text sizeWithFont:native_font].width);
+ return [ns_text sizeWithFont:native_font].width;
}
} // namespace gfx
diff --git a/chromium/ui/gfx/text_utils_skia.cc b/chromium/ui/gfx/text_utils_skia.cc
index 0de1156a14b..4ef0c234897 100644
--- a/chromium/ui/gfx/text_utils_skia.cc
+++ b/chromium/ui/gfx/text_utils_skia.cc
@@ -12,4 +12,8 @@ int GetStringWidth(const base::string16& text, const FontList& font_list) {
return Canvas::GetStringWidth(text, font_list);
}
+float GetStringWidthF(const base::string16& text, const FontList& font_list) {
+ return Canvas::GetStringWidthF(text, font_list);
+}
+
} // namespace gfx
diff --git a/chromium/ui/gfx/transform.cc b/chromium/ui/gfx/transform.cc
index 5f8a36760d1..7fe5174e750 100644
--- a/chromium/ui/gfx/transform.cc
+++ b/chromium/ui/gfx/transform.cc
@@ -11,6 +11,7 @@
#include "base/logging.h"
#include "base/strings/stringprintf.h"
+#include "ui/gfx/box_f.h"
#include "ui/gfx/point.h"
#include "ui/gfx/point3_f.h"
#include "ui/gfx/rect.h"
@@ -24,11 +25,19 @@ namespace gfx {
namespace {
// Taken from SkMatrix44.
-const SkMScalar kEpsilon = 1e-8;
+const SkMScalar kEpsilon = 1e-8f;
SkMScalar TanDegrees(double degrees) {
- SkMScalar radians = degrees * M_PI / 180;
- return std::tan(radians);
+ double radians = degrees * M_PI / 180;
+ return SkDoubleToMScalar(std::tan(radians));
+}
+
+inline bool ApproximatelyZero(SkMScalar x, SkMScalar tolerance) {
+ return std::abs(x) <= tolerance;
+}
+
+inline bool ApproximatelyOne(SkMScalar x, SkMScalar tolerance) {
+ return std::abs(x - SkDoubleToMScalar(1.0)) <= tolerance;
}
} // namespace
@@ -169,7 +178,7 @@ void Transform::Translate3d(SkMScalar x, SkMScalar y, SkMScalar z) {
matrix_.preTranslate(x, y, z);
}
-void Transform::SkewX(SkMScalar angle_x) {
+void Transform::SkewX(double angle_x) {
if (matrix_.isIdentity())
matrix_.set(0, 1, TanDegrees(angle_x));
else {
@@ -179,7 +188,7 @@ void Transform::SkewX(SkMScalar angle_x) {
}
}
-void Transform::SkewY(SkMScalar angle_y) {
+void Transform::SkewY(double angle_y) {
if (matrix_.isIdentity())
matrix_.set(1, 0, TanDegrees(angle_y));
else {
@@ -209,6 +218,25 @@ void Transform::ConcatTransform(const Transform& transform) {
matrix_.postConcat(transform.matrix_);
}
+bool Transform::IsApproximatelyIdentityOrTranslation(
+ SkMScalar tolerance) const {
+ DCHECK_GE(tolerance, 0);
+ return
+ ApproximatelyOne(matrix_.get(0, 0), tolerance) &&
+ ApproximatelyZero(matrix_.get(1, 0), tolerance) &&
+ ApproximatelyZero(matrix_.get(2, 0), tolerance) &&
+ matrix_.get(3, 0) == 0 &&
+ ApproximatelyZero(matrix_.get(0, 1), tolerance) &&
+ ApproximatelyOne(matrix_.get(1, 1), tolerance) &&
+ ApproximatelyZero(matrix_.get(2, 1), tolerance) &&
+ matrix_.get(3, 1) == 0 &&
+ ApproximatelyZero(matrix_.get(0, 2), tolerance) &&
+ ApproximatelyZero(matrix_.get(1, 2), tolerance) &&
+ ApproximatelyOne(matrix_.get(2, 2), tolerance) &&
+ matrix_.get(3, 2) == 0 &&
+ matrix_.get(3, 3) == 1;
+}
+
bool Transform::IsIdentityOrIntegerTranslation() const {
if (!IsIdentityOrTranslation())
return false;
@@ -424,7 +452,34 @@ bool Transform::TransformRectReverse(RectF* rect) const {
return true;
}
-bool Transform::Blend(const Transform& from, SkMScalar progress) {
+void Transform::TransformBox(BoxF* box) const {
+ BoxF bounds;
+ bool first_point = true;
+ for (int corner = 0; corner < 8; ++corner) {
+ gfx::Point3F point = box->origin();
+ point += gfx::Vector3dF(corner & 1 ? box->width() : 0.f,
+ corner & 2 ? box->height() : 0.f,
+ corner & 4 ? box->depth() : 0.f);
+ TransformPoint(&point);
+ if (first_point) {
+ bounds.set_origin(point);
+ first_point = false;
+ } else {
+ bounds.ExpandTo(point);
+ }
+ }
+ *box = bounds;
+}
+
+bool Transform::TransformBoxReverse(BoxF* box) const {
+ gfx::Transform inverse = *this;
+ if (!GetInverse(&inverse))
+ return false;
+ inverse.TransformBox(box);
+ return true;
+}
+
+bool Transform::Blend(const Transform& from, double progress) {
DecomposedTransform to_decomp;
DecomposedTransform from_decomp;
if (!DecomposeTransform(&to_decomp, *this) ||
@@ -448,8 +503,9 @@ void Transform::TransformPointInternal(const SkMatrix44& xform,
xform.mapMScalars(p);
- if (p[3] != 1 && abs(p[3]) > 0) {
- point->SetPoint(p[0] / p[3], p[1] / p[3], p[2]/ p[3]);
+ if (p[3] != SK_MScalar1 && p[3] != 0.f) {
+ float w_inverse = SK_MScalar1 / p[3];
+ point->SetPoint(p[0] * w_inverse, p[1] * w_inverse, p[2] * w_inverse);
} else {
point->SetPoint(p[0], p[1], p[2]);
}
diff --git a/chromium/ui/gfx/transform.h b/chromium/ui/gfx/transform.h
index 8e51d7941be..5e3b8303340 100644
--- a/chromium/ui/gfx/transform.h
+++ b/chromium/ui/gfx/transform.h
@@ -14,6 +14,7 @@
namespace gfx {
+class BoxF;
class RectF;
class Point;
class Point3F;
@@ -21,7 +22,7 @@ class Vector3dF;
// 4x4 transformation matrix. Transform is cheap and explicitly allows
// copy/assign.
-class UI_EXPORT Transform {
+class GFX_EXPORT Transform {
public:
enum SkipInitialization {
@@ -96,8 +97,8 @@ class UI_EXPORT Transform {
// Applies the current transformation on a skew and assigns the result
// to |this|.
- void SkewX(SkMScalar angle_x);
- void SkewY(SkMScalar angle_y);
+ void SkewX(double angle_x);
+ void SkewY(double angle_y);
// Applies the current transformation on a perspective transform and assigns
// the result to |this|.
@@ -119,6 +120,10 @@ class UI_EXPORT Transform {
return !(matrix_.getType() & ~SkMatrix44::kTranslate_Mask);
}
+ // Returns true if the matrix is either identity or pure translation,
+ // allowing for an amount of inaccuracy as specified by the parameter.
+ bool IsApproximatelyIdentityOrTranslation(SkMScalar tolerance) const;
+
// Returns true if the matrix is either a positive scale and/or a translation.
bool IsPositiveScaleOrTranslation() const {
if (!IsScaleOrTranslation())
@@ -179,12 +184,10 @@ class UI_EXPORT Transform {
// Returns the x and y translation components of the matrix.
Vector2dF To2dTranslation() const;
- // Applies the transformation on the point. Returns true if the point is
- // transformed successfully.
+ // Applies the transformation to the point.
void TransformPoint(Point3F* point) const;
- // Applies the transformation on the point. Returns true if the point is
- // transformed successfully. Rounds the result to the nearest point.
+ // Applies the transformation to the point.
void TransformPoint(Point* point) const;
// Applies the reverse transformation on the point. Returns true if the
@@ -195,17 +198,28 @@ class UI_EXPORT Transform {
// transformation can be inverted. Rounds the result to the nearest point.
bool TransformPointReverse(Point* point) const;
- // Applies transformation on the rectangle. Returns true if the transformed
- // rectangle was axis aligned. If it returns false, rect will be the
- // smallest axis aligned bounding box containing the transformed rect.
+ // Applies transformation on the given rect. After the function completes,
+ // |rect| will be the smallest axis aligned bounding rect containing the
+ // transformed rect.
void TransformRect(RectF* rect) const;
- // Applies the reverse transformation on the rectangle. Returns true if
- // the transformed rectangle was axis aligned. If it returns false,
- // rect will be the smallest axis aligned bounding box containing the
- // transformed rect.
+ // Applies the reverse transformation on the given rect. After the function
+ // completes, |rect| will be the smallest axis aligned bounding rect
+ // containing the transformed rect. Returns false if the matrix cannot be
+ // inverted.
bool TransformRectReverse(RectF* rect) const;
+ // Applies transformation on the given box. After the function completes,
+ // |box| will be the smallest axis aligned bounding box containing the
+ // transformed box.
+ void TransformBox(BoxF* box) const;
+
+ // Applies the reverse transformation on the given box. After the function
+ // completes, |box| will be the smallest axis aligned bounding box
+ // containing the transformed box. Returns false if the matrix cannot be
+ // inverted.
+ bool TransformBoxReverse(BoxF* box) const;
+
// Decomposes |this| and |from|, interpolates the decomposed values, and
// sets |this| to the reconstituted result. Returns false if either matrix
// can't be decomposed. Uses routines described in this spec:
@@ -215,7 +229,7 @@ class UI_EXPORT Transform {
// you're going to be calling this rapidly (e.g., in an animation) you should
// decompose once using gfx::DecomposeTransforms and reuse your
// DecomposedTransform.
- bool Blend(const Transform& from, SkMScalar progress);
+ bool Blend(const Transform& from, double progress);
// Returns |this| * |other|.
Transform operator*(const Transform& other) const {
diff --git a/chromium/ui/gfx/transform_unittest.cc b/chromium/ui/gfx/transform_unittest.cc
index 4394af67896..0bf9dde73fc 100644
--- a/chromium/ui/gfx/transform_unittest.cc
+++ b/chromium/ui/gfx/transform_unittest.cc
@@ -14,6 +14,7 @@
#include "base/basictypes.h"
#include "base/logging.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/box_f.h"
#include "ui/gfx/point.h"
#include "ui/gfx/point3_f.h"
#include "ui/gfx/quad_f.h"
@@ -90,22 +91,22 @@ bool MatricesAreNearlyEqual(const Transform& lhs,
void InitializeTestMatrix(Transform* transform) {
SkMatrix44& matrix = transform->matrix();
- matrix.setDouble(0, 0, 10.0);
- matrix.setDouble(1, 0, 11.0);
- matrix.setDouble(2, 0, 12.0);
- matrix.setDouble(3, 0, 13.0);
- matrix.setDouble(0, 1, 14.0);
- matrix.setDouble(1, 1, 15.0);
- matrix.setDouble(2, 1, 16.0);
- matrix.setDouble(3, 1, 17.0);
- matrix.setDouble(0, 2, 18.0);
- matrix.setDouble(1, 2, 19.0);
- matrix.setDouble(2, 2, 20.0);
- matrix.setDouble(3, 2, 21.0);
- matrix.setDouble(0, 3, 22.0);
- matrix.setDouble(1, 3, 23.0);
- matrix.setDouble(2, 3, 24.0);
- matrix.setDouble(3, 3, 25.0);
+ matrix.set(0, 0, 10.f);
+ matrix.set(1, 0, 11.f);
+ matrix.set(2, 0, 12.f);
+ matrix.set(3, 0, 13.f);
+ matrix.set(0, 1, 14.f);
+ matrix.set(1, 1, 15.f);
+ matrix.set(2, 1, 16.f);
+ matrix.set(3, 1, 17.f);
+ matrix.set(0, 2, 18.f);
+ matrix.set(1, 2, 19.f);
+ matrix.set(2, 2, 20.f);
+ matrix.set(3, 2, 21.f);
+ matrix.set(0, 3, 22.f);
+ matrix.set(1, 3, 23.f);
+ matrix.set(2, 3, 24.f);
+ matrix.set(3, 3, 25.f);
// Sanity check
EXPECT_ROW1_EQ(10.0f, 14.0f, 18.0f, 22.0f, (*transform));
@@ -116,22 +117,22 @@ void InitializeTestMatrix(Transform* transform) {
void InitializeTestMatrix2(Transform* transform) {
SkMatrix44& matrix = transform->matrix();
- matrix.setDouble(0, 0, 30.0);
- matrix.setDouble(1, 0, 31.0);
- matrix.setDouble(2, 0, 32.0);
- matrix.setDouble(3, 0, 33.0);
- matrix.setDouble(0, 1, 34.0);
- matrix.setDouble(1, 1, 35.0);
- matrix.setDouble(2, 1, 36.0);
- matrix.setDouble(3, 1, 37.0);
- matrix.setDouble(0, 2, 38.0);
- matrix.setDouble(1, 2, 39.0);
- matrix.setDouble(2, 2, 40.0);
- matrix.setDouble(3, 2, 41.0);
- matrix.setDouble(0, 3, 42.0);
- matrix.setDouble(1, 3, 43.0);
- matrix.setDouble(2, 3, 44.0);
- matrix.setDouble(3, 3, 45.0);
+ matrix.set(0, 0, 30.f);
+ matrix.set(1, 0, 31.f);
+ matrix.set(2, 0, 32.f);
+ matrix.set(3, 0, 33.f);
+ matrix.set(0, 1, 34.f);
+ matrix.set(1, 1, 35.f);
+ matrix.set(2, 1, 36.f);
+ matrix.set(3, 1, 37.f);
+ matrix.set(0, 2, 38.f);
+ matrix.set(1, 2, 39.f);
+ matrix.set(2, 2, 40.f);
+ matrix.set(3, 2, 41.f);
+ matrix.set(0, 3, 42.f);
+ matrix.set(1, 3, 43.f);
+ matrix.set(2, 3, 44.f);
+ matrix.set(3, 3, 45.f);
// Sanity check
EXPECT_ROW1_EQ(30.0f, 34.0f, 38.0f, 42.0f, (*transform));
@@ -140,6 +141,33 @@ void InitializeTestMatrix2(Transform* transform) {
EXPECT_ROW4_EQ(33.0f, 37.0f, 41.0f, 45.0f, (*transform));
}
+const SkMScalar kApproxZero =
+ SkFloatToMScalar(std::numeric_limits<float>::epsilon());
+const SkMScalar kApproxOne = 1 - kApproxZero;
+
+void InitializeApproxIdentityMatrix(Transform* transform) {
+ SkMatrix44& matrix = transform->matrix();
+ matrix.set(0, 0, kApproxOne);
+ matrix.set(0, 1, kApproxZero);
+ matrix.set(0, 2, kApproxZero);
+ matrix.set(0, 3, kApproxZero);
+
+ matrix.set(1, 0, kApproxZero);
+ matrix.set(1, 1, kApproxOne);
+ matrix.set(1, 2, kApproxZero);
+ matrix.set(1, 3, kApproxZero);
+
+ matrix.set(2, 0, kApproxZero);
+ matrix.set(2, 1, kApproxZero);
+ matrix.set(2, 2, kApproxOne);
+ matrix.set(2, 3, kApproxZero);
+
+ matrix.set(3, 0, kApproxZero);
+ matrix.set(3, 1, kApproxZero);
+ matrix.set(3, 2, kApproxZero);
+ matrix.set(3, 3, kApproxOne);
+}
+
#ifdef SK_MSCALAR_IS_DOUBLE
#define ERROR_THRESHOLD 1e-14
#else
@@ -654,6 +682,23 @@ TEST(XFormTest, SetRotate2D) {
}
}
+TEST(XFormTest, TransformPointWithExtremePerspective) {
+ Point3F point(1.f, 1.f, 1.f);
+ Transform perspective;
+ perspective.ApplyPerspectiveDepth(1.f);
+ Point3F transformed = point;
+ perspective.TransformPoint(&transformed);
+ EXPECT_EQ(point.ToString(), transformed.ToString());
+
+ transformed = point;
+ perspective.MakeIdentity();
+ perspective.ApplyPerspectiveDepth(1.1f);
+ perspective.TransformPoint(&transformed);
+ EXPECT_FLOAT_EQ(11.f, transformed.x());
+ EXPECT_FLOAT_EQ(11.f, transformed.y());
+ EXPECT_FLOAT_EQ(11.f, transformed.z());
+}
+
TEST(XFormTest, BlendTranslate) {
Transform from;
for (int i = -5; i < 15; ++i) {
@@ -738,14 +783,21 @@ TEST(XFormTest, CanBlend180DegreeRotation) {
for (size_t index = 0; index < ARRAYSIZE_UNSAFE(axes); ++index) {
for (int i = -5; i < 15; ++i) {
Transform to;
- to.RotateAbout(axes[index], 180);
+ to.RotateAbout(axes[index], 180.0);
double t = i / 9.0;
EXPECT_TRUE(to.Blend(from, t));
- Transform expected;
- expected.RotateAbout(axes[index], 180 * t);
+ // A 180 degree rotation is exactly opposite on the sphere, therefore
+ // either great circle arc to it is equivalent (and numerical precision
+ // will determine which is closer). Test both directions.
+ Transform expected1;
+ expected1.RotateAbout(axes[index], 180.0 * t);
+ Transform expected2;
+ expected2.RotateAbout(axes[index], -180.0 * t);
- EXPECT_TRUE(MatricesAreNearlyEqual(expected, to));
+ EXPECT_TRUE(MatricesAreNearlyEqual(expected1, to) ||
+ MatricesAreNearlyEqual(expected2, to))
+ << "axis: " << index << ", i: " << i;
}
}
}
@@ -757,9 +809,9 @@ TEST(XFormTest, BlendScale) {
to.Scale3d(5, 4, 3);
double t = i / 9.0;
EXPECT_TRUE(to.Blend(from, t));
- EXPECT_FLOAT_EQ(t * 4 + 1, to.matrix().get(0, 0));
- EXPECT_FLOAT_EQ(t * 3 + 1, to.matrix().get(1, 1));
- EXPECT_FLOAT_EQ(t * 2 + 1, to.matrix().get(2, 2));
+ EXPECT_FLOAT_EQ(t * 4 + 1, to.matrix().get(0, 0)) << "i: " << i;
+ EXPECT_FLOAT_EQ(t * 3 + 1, to.matrix().get(1, 1)) << "i: " << i;
+ EXPECT_FLOAT_EQ(t * 2 + 1, to.matrix().get(2, 2)) << "i: " << i;
}
}
@@ -767,12 +819,12 @@ TEST(XFormTest, BlendSkew) {
Transform from;
for (int i = 0; i < 2; ++i) {
Transform to;
- to.SkewX(20);
- to.SkewY(10);
+ to.SkewX(10);
+ to.SkewY(5);
double t = i;
Transform expected;
- expected.SkewX(t * 20);
- expected.SkewY(t * 10);
+ expected.SkewX(t * 10);
+ expected.SkewY(t * 5);
EXPECT_TRUE(to.Blend(from, t));
EXPECT_TRUE(MatricesAreNearlyEqual(expected, to));
}
@@ -1201,7 +1253,7 @@ TEST(XFormTest, VerifyBlendForCompositeTransform) {
// We short circuit if blend is >= 1, so to check the numerics, we will
// check that we get close to what we expect when we're nearly done
// interpolating.
- to.Blend(from, .99999);
+ to.Blend(from, .99999f);
// Recomposing the matrix results in a normalized matrix, so to verify we
// need to normalize the expectedEndOfAnimation before comparing elements.
@@ -1259,14 +1311,17 @@ TEST(XFormTest, FactorTRS) {
EXPECT_TRUE(success);
EXPECT_FLOAT_EQ(decomp.translate[0], degrees * 2);
EXPECT_FLOAT_EQ(decomp.translate[1], -degrees * 3);
- double rotation = std::acos(decomp.quaternion[3]) * 360.0 / M_PI;
+ double rotation =
+ std::acos(SkMScalarToDouble(decomp.quaternion[3])) * 360.0 / M_PI;
while (rotation < 0.0)
rotation += 360.0;
while (rotation > 360.0)
rotation -= 360.0;
- EXPECT_FLOAT_EQ(rotation, degrees);
- EXPECT_FLOAT_EQ(decomp.scale[0], degrees + 1);
- EXPECT_FLOAT_EQ(decomp.scale[1], 2 * degrees + 1);
+
+ const float epsilon = 0.00015f;
+ EXPECT_NEAR(rotation, degrees, epsilon);
+ EXPECT_NEAR(decomp.scale[0], degrees + 1, epsilon);
+ EXPECT_NEAR(decomp.scale[1], 2 * degrees + 1, epsilon);
}
}
@@ -1282,15 +1337,15 @@ TEST(XFormTest, IntegerTranslation) {
EXPECT_TRUE(transform.IsIdentityOrIntegerTranslation());
transform.MakeIdentity();
- transform.Translate3d(4.5, 0, 0);
+ transform.Translate3d(4.5f, 0, 0);
EXPECT_FALSE(transform.IsIdentityOrIntegerTranslation());
transform.MakeIdentity();
- transform.Translate3d(0, -6.7, 0);
+ transform.Translate3d(0, -6.7f, 0);
EXPECT_FALSE(transform.IsIdentityOrIntegerTranslation());
transform.MakeIdentity();
- transform.Translate3d(0, 0, 8.9);
+ transform.Translate3d(0, 0, 8.9f);
EXPECT_FALSE(transform.IsIdentityOrIntegerTranslation());
}
@@ -1329,10 +1384,10 @@ TEST(XFormTest, verifyMatrixInversion) {
// Try to invert a matrix that is not invertible.
// The inverse() function should reset the output matrix to identity.
gfx::Transform uninvertible;
- uninvertible.matrix().setDouble(0, 0, 0.0);
- uninvertible.matrix().setDouble(1, 1, 0.0);
- uninvertible.matrix().setDouble(2, 2, 0.0);
- uninvertible.matrix().setDouble(3, 3, 0.0);
+ uninvertible.matrix().set(0, 0, 0.f);
+ uninvertible.matrix().set(1, 1, 0.f);
+ uninvertible.matrix().set(2, 2, 0.f);
+ uninvertible.matrix().set(3, 3, 0.f);
EXPECT_FALSE(uninvertible.IsInvertible());
gfx::Transform inverse_of_uninvertible;
@@ -1495,67 +1550,67 @@ TEST(XFormTest, verifyEqualsBooleanOperator) {
// return false.
Transform D;
D = A;
- D.matrix().setDouble(0, 0, 0.0);
+ D.matrix().set(0, 0, 0.f);
EXPECT_FALSE(A == D);
D = A;
- D.matrix().setDouble(1, 0, 0.0);
+ D.matrix().set(1, 0, 0.f);
EXPECT_FALSE(A == D);
D = A;
- D.matrix().setDouble(2, 0, 0.0);
+ D.matrix().set(2, 0, 0.f);
EXPECT_FALSE(A == D);
D = A;
- D.matrix().setDouble(3, 0, 0.0);
+ D.matrix().set(3, 0, 0.f);
EXPECT_FALSE(A == D);
D = A;
- D.matrix().setDouble(0, 1, 0.0);
+ D.matrix().set(0, 1, 0.f);
EXPECT_FALSE(A == D);
D = A;
- D.matrix().setDouble(1, 1, 0.0);
+ D.matrix().set(1, 1, 0.f);
EXPECT_FALSE(A == D);
D = A;
- D.matrix().setDouble(2, 1, 0.0);
+ D.matrix().set(2, 1, 0.f);
EXPECT_FALSE(A == D);
D = A;
- D.matrix().setDouble(3, 1, 0.0);
+ D.matrix().set(3, 1, 0.f);
EXPECT_FALSE(A == D);
D = A;
- D.matrix().setDouble(0, 2, 0.0);
+ D.matrix().set(0, 2, 0.f);
EXPECT_FALSE(A == D);
D = A;
- D.matrix().setDouble(1, 2, 0.0);
+ D.matrix().set(1, 2, 0.f);
EXPECT_FALSE(A == D);
D = A;
- D.matrix().setDouble(2, 2, 0.0);
+ D.matrix().set(2, 2, 0.f);
EXPECT_FALSE(A == D);
D = A;
- D.matrix().setDouble(3, 2, 0.0);
+ D.matrix().set(3, 2, 0.f);
EXPECT_FALSE(A == D);
D = A;
- D.matrix().setDouble(0, 3, 0.0);
+ D.matrix().set(0, 3, 0.f);
EXPECT_FALSE(A == D);
D = A;
- D.matrix().setDouble(1, 3, 0.0);
+ D.matrix().set(1, 3, 0.f);
EXPECT_FALSE(A == D);
D = A;
- D.matrix().setDouble(2, 3, 0.0);
+ D.matrix().set(2, 3, 0.f);
EXPECT_FALSE(A == D);
D = A;
- D.matrix().setDouble(3, 3, 0.0);
+ D.matrix().set(3, 3, 0.f);
EXPECT_FALSE(A == D);
}
@@ -1945,23 +2000,23 @@ TEST(XFormTest, verifyHasPerspective) {
EXPECT_FALSE(A.HasPerspective());
A.MakeIdentity();
- A.matrix().setDouble(3, 0, -1.0);
+ A.matrix().set(3, 0, -1.f);
EXPECT_TRUE(A.HasPerspective());
A.MakeIdentity();
- A.matrix().setDouble(3, 1, -1.0);
+ A.matrix().set(3, 1, -1.f);
EXPECT_TRUE(A.HasPerspective());
A.MakeIdentity();
- A.matrix().setDouble(3, 2, -0.3);
+ A.matrix().set(3, 2, -0.3f);
EXPECT_TRUE(A.HasPerspective());
A.MakeIdentity();
- A.matrix().setDouble(3, 3, 0.5);
+ A.matrix().set(3, 3, 0.5f);
EXPECT_TRUE(A.HasPerspective());
A.MakeIdentity();
- A.matrix().setDouble(3, 3, 0.0);
+ A.matrix().set(3, 3, 0.f);
EXPECT_TRUE(A.HasPerspective());
}
@@ -2002,14 +2057,14 @@ TEST(XFormTest, verifyIsInvertible) {
// to zero (i.e. camera positioned at the origin), is not invertible.
A.MakeIdentity();
A.ApplyPerspectiveDepth(1.0);
- A.matrix().setDouble(3, 3, 0.0);
+ A.matrix().set(3, 3, 0.f);
EXPECT_FALSE(A.IsInvertible());
// Adding more to a non-invertible matrix will not make it invertible in the
// general case.
A.MakeIdentity();
A.ApplyPerspectiveDepth(1.0);
- A.matrix().setDouble(3, 3, 0.0);
+ A.matrix().set(3, 3, 0.f);
A.Scale3d(6.0, 7.0, 8.0);
A.RotateAboutXAxis(10.0);
A.RotateAboutYAxis(20.0);
@@ -2019,10 +2074,10 @@ TEST(XFormTest, verifyIsInvertible) {
// A degenerate matrix of all zeros is not invertible.
A.MakeIdentity();
- A.matrix().setDouble(0, 0, 0.0);
- A.matrix().setDouble(1, 1, 0.0);
- A.matrix().setDouble(2, 2, 0.0);
- A.matrix().setDouble(3, 3, 0.0);
+ A.matrix().set(0, 0, 0.f);
+ A.matrix().set(1, 1, 0.f);
+ A.matrix().set(2, 2, 0.f);
+ A.matrix().set(3, 3, 0.f);
EXPECT_FALSE(A.IsInvertible());
}
@@ -2038,67 +2093,67 @@ TEST(XFormTest, verifyIsIdentity) {
// Modifying any one individual element should cause the matrix to no longer
// be identity.
A.MakeIdentity();
- A.matrix().setDouble(0, 0, 2.0);
+ A.matrix().set(0, 0, 2.f);
EXPECT_FALSE(A.IsIdentity());
A.MakeIdentity();
- A.matrix().setDouble(1, 0, 2.0);
+ A.matrix().set(1, 0, 2.f);
EXPECT_FALSE(A.IsIdentity());
A.MakeIdentity();
- A.matrix().setDouble(2, 0, 2.0);
+ A.matrix().set(2, 0, 2.f);
EXPECT_FALSE(A.IsIdentity());
A.MakeIdentity();
- A.matrix().setDouble(3, 0, 2.0);
+ A.matrix().set(3, 0, 2.f);
EXPECT_FALSE(A.IsIdentity());
A.MakeIdentity();
- A.matrix().setDouble(0, 1, 2.0);
+ A.matrix().set(0, 1, 2.f);
EXPECT_FALSE(A.IsIdentity());
A.MakeIdentity();
- A.matrix().setDouble(1, 1, 2.0);
+ A.matrix().set(1, 1, 2.f);
EXPECT_FALSE(A.IsIdentity());
A.MakeIdentity();
- A.matrix().setDouble(2, 1, 2.0);
+ A.matrix().set(2, 1, 2.f);
EXPECT_FALSE(A.IsIdentity());
A.MakeIdentity();
- A.matrix().setDouble(3, 1, 2.0);
+ A.matrix().set(3, 1, 2.f);
EXPECT_FALSE(A.IsIdentity());
A.MakeIdentity();
- A.matrix().setDouble(0, 2, 2.0);
+ A.matrix().set(0, 2, 2.f);
EXPECT_FALSE(A.IsIdentity());
A.MakeIdentity();
- A.matrix().setDouble(1, 2, 2.0);
+ A.matrix().set(1, 2, 2.f);
EXPECT_FALSE(A.IsIdentity());
A.MakeIdentity();
- A.matrix().setDouble(2, 2, 2.0);
+ A.matrix().set(2, 2, 2.f);
EXPECT_FALSE(A.IsIdentity());
A.MakeIdentity();
- A.matrix().setDouble(3, 2, 2.0);
+ A.matrix().set(3, 2, 2.f);
EXPECT_FALSE(A.IsIdentity());
A.MakeIdentity();
- A.matrix().setDouble(0, 3, 2.0);
+ A.matrix().set(0, 3, 2.f);
EXPECT_FALSE(A.IsIdentity());
A.MakeIdentity();
- A.matrix().setDouble(1, 3, 2.0);
+ A.matrix().set(1, 3, 2.f);
EXPECT_FALSE(A.IsIdentity());
A.MakeIdentity();
- A.matrix().setDouble(2, 3, 2.0);
+ A.matrix().set(2, 3, 2.f);
EXPECT_FALSE(A.IsIdentity());
A.MakeIdentity();
- A.matrix().setDouble(3, 3, 2.0);
+ A.matrix().set(3, 3, 2.f);
EXPECT_FALSE(A.IsIdentity());
}
@@ -2116,73 +2171,123 @@ TEST(XFormTest, verifyIsIdentityOrTranslation) {
// (2, 3) are the translation components, so modifying them should still
// return true.
A.MakeIdentity();
- A.matrix().setDouble(0, 0, 2.0);
+ A.matrix().set(0, 0, 2.f);
EXPECT_FALSE(A.IsIdentityOrTranslation());
A.MakeIdentity();
- A.matrix().setDouble(1, 0, 2.0);
+ A.matrix().set(1, 0, 2.f);
EXPECT_FALSE(A.IsIdentityOrTranslation());
A.MakeIdentity();
- A.matrix().setDouble(2, 0, 2.0);
+ A.matrix().set(2, 0, 2.f);
EXPECT_FALSE(A.IsIdentityOrTranslation());
A.MakeIdentity();
- A.matrix().setDouble(3, 0, 2.0);
+ A.matrix().set(3, 0, 2.f);
EXPECT_FALSE(A.IsIdentityOrTranslation());
A.MakeIdentity();
- A.matrix().setDouble(0, 1, 2.0);
+ A.matrix().set(0, 1, 2.f);
EXPECT_FALSE(A.IsIdentityOrTranslation());
A.MakeIdentity();
- A.matrix().setDouble(1, 1, 2.0);
+ A.matrix().set(1, 1, 2.f);
EXPECT_FALSE(A.IsIdentityOrTranslation());
A.MakeIdentity();
- A.matrix().setDouble(2, 1, 2.0);
+ A.matrix().set(2, 1, 2.f);
EXPECT_FALSE(A.IsIdentityOrTranslation());
A.MakeIdentity();
- A.matrix().setDouble(3, 1, 2.0);
+ A.matrix().set(3, 1, 2.f);
EXPECT_FALSE(A.IsIdentityOrTranslation());
A.MakeIdentity();
- A.matrix().setDouble(0, 2, 2.0);
+ A.matrix().set(0, 2, 2.f);
EXPECT_FALSE(A.IsIdentityOrTranslation());
A.MakeIdentity();
- A.matrix().setDouble(1, 2, 2.0);
+ A.matrix().set(1, 2, 2.f);
EXPECT_FALSE(A.IsIdentityOrTranslation());
A.MakeIdentity();
- A.matrix().setDouble(2, 2, 2.0);
+ A.matrix().set(2, 2, 2.f);
EXPECT_FALSE(A.IsIdentityOrTranslation());
A.MakeIdentity();
- A.matrix().setDouble(3, 2, 2.0);
+ A.matrix().set(3, 2, 2.f);
EXPECT_FALSE(A.IsIdentityOrTranslation());
// Note carefully - expecting true here.
A.MakeIdentity();
- A.matrix().setDouble(0, 3, 2.0);
+ A.matrix().set(0, 3, 2.f);
EXPECT_TRUE(A.IsIdentityOrTranslation());
// Note carefully - expecting true here.
A.MakeIdentity();
- A.matrix().setDouble(1, 3, 2.0);
+ A.matrix().set(1, 3, 2.f);
EXPECT_TRUE(A.IsIdentityOrTranslation());
// Note carefully - expecting true here.
A.MakeIdentity();
- A.matrix().setDouble(2, 3, 2.0);
+ A.matrix().set(2, 3, 2.f);
EXPECT_TRUE(A.IsIdentityOrTranslation());
A.MakeIdentity();
- A.matrix().setDouble(3, 3, 2.0);
+ A.matrix().set(3, 3, 2.f);
EXPECT_FALSE(A.IsIdentityOrTranslation());
}
+TEST(XFormTest, verifyIsApproximatelyIdentityOrTranslation) {
+ Transform A;
+ SkMatrix44& matrix = A.matrix();
+
+ // Exact pure translation.
+ A.MakeIdentity();
+
+ // Set translate values to values other than 0 or 1.
+ matrix.set(0, 3, 3.4f);
+ matrix.set(1, 3, 4.4f);
+ matrix.set(2, 3, 5.6f);
+
+ EXPECT_TRUE(A.IsApproximatelyIdentityOrTranslation(0));
+ EXPECT_TRUE(A.IsApproximatelyIdentityOrTranslation(kApproxZero));
+
+ // Approximately pure translation.
+ InitializeApproxIdentityMatrix(&A);
+
+ // Some values must be exact.
+ matrix.set(3, 0, 0);
+ matrix.set(3, 1, 0);
+ matrix.set(3, 2, 0);
+ matrix.set(3, 3, 1);
+
+ // Set translate values to values other than 0 or 1.
+ matrix.set(0, 3, 3.4f);
+ matrix.set(1, 3, 4.4f);
+ matrix.set(2, 3, 5.6f);
+
+ EXPECT_FALSE(A.IsApproximatelyIdentityOrTranslation(0));
+ EXPECT_TRUE(A.IsApproximatelyIdentityOrTranslation(kApproxZero));
+
+ // Not approximately pure translation.
+ InitializeApproxIdentityMatrix(&A);
+
+ // Some values must be exact.
+ matrix.set(3, 0, 0);
+ matrix.set(3, 1, 0);
+ matrix.set(3, 2, 0);
+ matrix.set(3, 3, 1);
+
+ // Set some values (not translate values) to values other than 0 or 1.
+ matrix.set(0, 1, 3.4f);
+ matrix.set(3, 2, 4.4f);
+ matrix.set(2, 0, 5.6f);
+
+ EXPECT_FALSE(A.IsApproximatelyIdentityOrTranslation(0));
+ EXPECT_FALSE(A.IsApproximatelyIdentityOrTranslation(kApproxZero));
+}
+
TEST(XFormTest, verifyIsScaleOrTranslation) {
Transform A;
@@ -2199,72 +2304,72 @@ TEST(XFormTest, verifyIsScaleOrTranslation) {
// Note carefully - expecting true here.
A.MakeIdentity();
- A.matrix().setDouble(0, 0, 2.0);
+ A.matrix().set(0, 0, 2.f);
EXPECT_TRUE(A.IsScaleOrTranslation());
A.MakeIdentity();
- A.matrix().setDouble(1, 0, 2.0);
+ A.matrix().set(1, 0, 2.f);
EXPECT_FALSE(A.IsScaleOrTranslation());
A.MakeIdentity();
- A.matrix().setDouble(2, 0, 2.0);
+ A.matrix().set(2, 0, 2.f);
EXPECT_FALSE(A.IsScaleOrTranslation());
A.MakeIdentity();
- A.matrix().setDouble(3, 0, 2.0);
+ A.matrix().set(3, 0, 2.f);
EXPECT_FALSE(A.IsScaleOrTranslation());
A.MakeIdentity();
- A.matrix().setDouble(0, 1, 2.0);
+ A.matrix().set(0, 1, 2.f);
EXPECT_FALSE(A.IsScaleOrTranslation());
// Note carefully - expecting true here.
A.MakeIdentity();
- A.matrix().setDouble(1, 1, 2.0);
+ A.matrix().set(1, 1, 2.f);
EXPECT_TRUE(A.IsScaleOrTranslation());
A.MakeIdentity();
- A.matrix().setDouble(2, 1, 2.0);
+ A.matrix().set(2, 1, 2.f);
EXPECT_FALSE(A.IsScaleOrTranslation());
A.MakeIdentity();
- A.matrix().setDouble(3, 1, 2.0);
+ A.matrix().set(3, 1, 2.f);
EXPECT_FALSE(A.IsScaleOrTranslation());
A.MakeIdentity();
- A.matrix().setDouble(0, 2, 2.0);
+ A.matrix().set(0, 2, 2.f);
EXPECT_FALSE(A.IsScaleOrTranslation());
A.MakeIdentity();
- A.matrix().setDouble(1, 2, 2.0);
+ A.matrix().set(1, 2, 2.f);
EXPECT_FALSE(A.IsScaleOrTranslation());
// Note carefully - expecting true here.
A.MakeIdentity();
- A.matrix().setDouble(2, 2, 2.0);
+ A.matrix().set(2, 2, 2.f);
EXPECT_TRUE(A.IsScaleOrTranslation());
A.MakeIdentity();
- A.matrix().setDouble(3, 2, 2.0);
+ A.matrix().set(3, 2, 2.f);
EXPECT_FALSE(A.IsScaleOrTranslation());
// Note carefully - expecting true here.
A.MakeIdentity();
- A.matrix().setDouble(0, 3, 2.0);
+ A.matrix().set(0, 3, 2.f);
EXPECT_TRUE(A.IsScaleOrTranslation());
// Note carefully - expecting true here.
A.MakeIdentity();
- A.matrix().setDouble(1, 3, 2.0);
+ A.matrix().set(1, 3, 2.f);
EXPECT_TRUE(A.IsScaleOrTranslation());
// Note carefully - expecting true here.
A.MakeIdentity();
- A.matrix().setDouble(2, 3, 2.0);
+ A.matrix().set(2, 3, 2.f);
EXPECT_TRUE(A.IsScaleOrTranslation());
A.MakeIdentity();
- A.matrix().setDouble(3, 3, 2.0);
+ A.matrix().set(3, 3, 2.f);
EXPECT_FALSE(A.IsScaleOrTranslation());
}
@@ -2307,52 +2412,52 @@ static bool EmpiricallyPreserves2dAxisAlignment(const Transform& transform) {
TEST(XFormTest, Preserves2dAxisAlignment) {
static const struct TestCase {
- double a; // row 1, column 1
- double b; // row 1, column 2
- double c; // row 2, column 1
- double d; // row 2, column 2
+ SkMScalar a; // row 1, column 1
+ SkMScalar b; // row 1, column 2
+ SkMScalar c; // row 2, column 1
+ SkMScalar d; // row 2, column 2
bool expected;
} test_cases[] = {
- { 3.0, 0.0,
- 0.0, 4.0, true }, // basic case
- { 0.0, 4.0,
- 3.0, 0.0, true }, // rotate by 90
- { 0.0, 0.0,
- 0.0, 4.0, true }, // degenerate x
- { 3.0, 0.0,
- 0.0, 0.0, true }, // degenerate y
- { 0.0, 0.0,
- 3.0, 0.0, true }, // degenerate x + rotate by 90
- { 0.0, 4.0,
- 0.0, 0.0, true }, // degenerate y + rotate by 90
- { 3.0, 4.0,
- 0.0, 0.0, false },
- { 0.0, 0.0,
- 3.0, 4.0, false },
- { 0.0, 3.0,
- 0.0, 4.0, false },
- { 3.0, 0.0,
- 4.0, 0.0, false },
- { 3.0, 4.0,
- 5.0, 0.0, false },
- { 3.0, 4.0,
- 0.0, 5.0, false },
- { 3.0, 0.0,
- 4.0, 5.0, false },
- { 0.0, 3.0,
- 4.0, 5.0, false },
- { 2.0, 3.0,
- 4.0, 5.0, false },
+ { 3.f, 0.f,
+ 0.f, 4.f, true }, // basic case
+ { 0.f, 4.f,
+ 3.f, 0.f, true }, // rotate by 90
+ { 0.f, 0.f,
+ 0.f, 4.f, true }, // degenerate x
+ { 3.f, 0.f,
+ 0.f, 0.f, true }, // degenerate y
+ { 0.f, 0.f,
+ 3.f, 0.f, true }, // degenerate x + rotate by 90
+ { 0.f, 4.f,
+ 0.f, 0.f, true }, // degenerate y + rotate by 90
+ { 3.f, 4.f,
+ 0.f, 0.f, false },
+ { 0.f, 0.f,
+ 3.f, 4.f, false },
+ { 0.f, 3.f,
+ 0.f, 4.f, false },
+ { 3.f, 0.f,
+ 4.f, 0.f, false },
+ { 3.f, 4.f,
+ 5.f, 0.f, false },
+ { 3.f, 4.f,
+ 0.f, 5.f, false },
+ { 3.f, 0.f,
+ 4.f, 5.f, false },
+ { 0.f, 3.f,
+ 4.f, 5.f, false },
+ { 2.f, 3.f,
+ 4.f, 5.f, false },
};
Transform transform;
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
const TestCase& value = test_cases[i];
transform.MakeIdentity();
- transform.matrix().setDouble(0, 0, value.a);
- transform.matrix().setDouble(0, 1, value.b);
- transform.matrix().setDouble(1, 0, value.c);
- transform.matrix().setDouble(1, 1, value.d);
+ transform.matrix().set(0, 0, value.a);
+ transform.matrix().set(0, 1, value.b);
+ transform.matrix().set(1, 0, value.c);
+ transform.matrix().set(1, 1, value.d);
if (value.expected) {
EXPECT_TRUE(EmpiricallyPreserves2dAxisAlignment(transform));
@@ -2368,19 +2473,19 @@ TEST(XFormTest, Preserves2dAxisAlignment) {
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
const TestCase& value = test_cases[i];
transform.MakeIdentity();
- transform.matrix().setDouble(0, 0, value.a);
- transform.matrix().setDouble(0, 1, value.b);
- transform.matrix().setDouble(1, 0, value.c);
- transform.matrix().setDouble(1, 1, value.d);
-
- transform.matrix().setDouble(0, 2, 1.0);
- transform.matrix().setDouble(0, 3, 2.0);
- transform.matrix().setDouble(1, 2, 3.0);
- transform.matrix().setDouble(1, 3, 4.0);
- transform.matrix().setDouble(2, 0, 5.0);
- transform.matrix().setDouble(2, 1, 6.0);
- transform.matrix().setDouble(2, 2, 7.0);
- transform.matrix().setDouble(2, 3, 8.0);
+ transform.matrix().set(0, 0, value.a);
+ transform.matrix().set(0, 1, value.b);
+ transform.matrix().set(1, 0, value.c);
+ transform.matrix().set(1, 1, value.d);
+
+ transform.matrix().set(0, 2, 1.f);
+ transform.matrix().set(0, 3, 2.f);
+ transform.matrix().set(1, 2, 3.f);
+ transform.matrix().set(1, 3, 4.f);
+ transform.matrix().set(2, 0, 5.f);
+ transform.matrix().set(2, 1, 6.f);
+ transform.matrix().set(2, 2, 7.f);
+ transform.matrix().set(2, 3, 8.f);
if (value.expected) {
EXPECT_TRUE(EmpiricallyPreserves2dAxisAlignment(transform));
@@ -2396,23 +2501,23 @@ TEST(XFormTest, Preserves2dAxisAlignment) {
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
const TestCase& value = test_cases[i];
transform.MakeIdentity();
- transform.matrix().setDouble(0, 0, value.a);
- transform.matrix().setDouble(0, 1, value.b);
- transform.matrix().setDouble(1, 0, value.c);
- transform.matrix().setDouble(1, 1, value.d);
-
- transform.matrix().setDouble(0, 2, 1.0);
- transform.matrix().setDouble(0, 3, 2.0);
- transform.matrix().setDouble(1, 2, 3.0);
- transform.matrix().setDouble(1, 3, 4.0);
- transform.matrix().setDouble(2, 0, 5.0);
- transform.matrix().setDouble(2, 1, 6.0);
- transform.matrix().setDouble(2, 2, 7.0);
- transform.matrix().setDouble(2, 3, 8.0);
- transform.matrix().setDouble(3, 0, 9.0);
- transform.matrix().setDouble(3, 1, 10.0);
- transform.matrix().setDouble(3, 2, 11.0);
- transform.matrix().setDouble(3, 3, 12.0);
+ transform.matrix().set(0, 0, value.a);
+ transform.matrix().set(0, 1, value.b);
+ transform.matrix().set(1, 0, value.c);
+ transform.matrix().set(1, 1, value.d);
+
+ transform.matrix().set(0, 2, 1.f);
+ transform.matrix().set(0, 3, 2.f);
+ transform.matrix().set(1, 2, 3.f);
+ transform.matrix().set(1, 3, 4.f);
+ transform.matrix().set(2, 0, 5.f);
+ transform.matrix().set(2, 1, 6.f);
+ transform.matrix().set(2, 2, 7.f);
+ transform.matrix().set(2, 3, 8.f);
+ transform.matrix().set(3, 0, 9.f);
+ transform.matrix().set(3, 1, 10.f);
+ transform.matrix().set(3, 2, 11.f);
+ transform.matrix().set(3, 3, 12.f);
EXPECT_FALSE(EmpiricallyPreserves2dAxisAlignment(transform));
EXPECT_FALSE(transform.Preserves2dAxisAlignment());
@@ -2504,6 +2609,50 @@ TEST(XFormTest, To2dTranslation) {
EXPECT_EQ(translation.ToString(), transform.To2dTranslation().ToString());
}
+TEST(XFormTest, TransformRect) {
+ Transform translation;
+ translation.Translate(3.f, 7.f);
+ RectF rect(1.f, 2.f, 3.f, 4.f);
+ RectF expected(4.f, 9.f, 3.f, 4.f);
+ translation.TransformRect(&rect);
+ EXPECT_EQ(expected.ToString(), rect.ToString());
+}
+
+TEST(XFormTest, TransformRectReverse) {
+ Transform translation;
+ translation.Translate(3.f, 7.f);
+ RectF rect(1.f, 2.f, 3.f, 4.f);
+ RectF expected(-2.f, -5.f, 3.f, 4.f);
+ EXPECT_TRUE(translation.TransformRectReverse(&rect));
+ EXPECT_EQ(expected.ToString(), rect.ToString());
+
+ Transform singular;
+ singular.Scale3d(0.f, 0.f, 0.f);
+ EXPECT_FALSE(singular.TransformRectReverse(&rect));
+}
+
+TEST(XFormTest, TransformBox) {
+ Transform translation;
+ translation.Translate3d(3.f, 7.f, 6.f);
+ BoxF box(1.f, 2.f, 3.f, 4.f, 5.f, 6.f);
+ BoxF expected(4.f, 9.f, 9.f, 4.f, 5.f, 6.f);
+ translation.TransformBox(&box);
+ EXPECT_EQ(expected.ToString(), box.ToString());
+}
+
+TEST(XFormTest, TransformBoxReverse) {
+ Transform translation;
+ translation.Translate3d(3.f, 7.f, 6.f);
+ BoxF box(1.f, 2.f, 3.f, 4.f, 5.f, 6.f);
+ BoxF expected(-2.f, -5.f, -3.f, 4.f, 5.f, 6.f);
+ EXPECT_TRUE(translation.TransformBoxReverse(&box));
+ EXPECT_EQ(expected.ToString(), box.ToString());
+
+ Transform singular;
+ singular.Scale3d(0.f, 0.f, 0.f);
+ EXPECT_FALSE(singular.TransformBoxReverse(&box));
+}
+
} // namespace
} // namespace gfx
diff --git a/chromium/ui/gfx/transform_util.cc b/chromium/ui/gfx/transform_util.cc
index 9bb3bbcbcfb..655ce57f2bb 100644
--- a/chromium/ui/gfx/transform_util.cc
+++ b/chromium/ui/gfx/transform_util.cc
@@ -7,14 +7,21 @@
#include <algorithm>
#include <cmath>
+#include "base/logging.h"
+#include "base/strings/stringprintf.h"
#include "ui/gfx/point.h"
+#include "ui/gfx/point3_f.h"
+#include "ui/gfx/rect.h"
namespace gfx {
namespace {
SkMScalar Length3(SkMScalar v[3]) {
- return std::sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
+ double vd[3] = {SkMScalarToDouble(v[0]), SkMScalarToDouble(v[1]),
+ SkMScalarToDouble(v[2])};
+ return SkDoubleToMScalar(
+ std::sqrt(vd[0] * vd[0] + vd[1] * vd[1] + vd[2] * vd[2]));
}
void Scale3(SkMScalar v[3], SkMScalar scale) {
@@ -24,20 +31,20 @@ void Scale3(SkMScalar v[3], SkMScalar scale) {
template <int n>
SkMScalar Dot(const SkMScalar* a, const SkMScalar* b) {
- SkMScalar toReturn = 0;
+ double total = 0.0;
for (int i = 0; i < n; ++i)
- toReturn += a[i] * b[i];
- return toReturn;
+ total += a[i] * b[i];
+ return SkDoubleToMScalar(total);
}
template <int n>
void Combine(SkMScalar* out,
const SkMScalar* a,
const SkMScalar* b,
- SkMScalar scale_a,
- SkMScalar scale_b) {
+ double scale_a,
+ double scale_b) {
for (int i = 0; i < n; ++i)
- out[i] = a[i] * scale_a + b[i] * scale_b;
+ out[i] = SkDoubleToMScalar(a[i] * scale_a + b[i] * scale_b);
}
void Cross3(SkMScalar out[3], SkMScalar a[3], SkMScalar b[3]) {
@@ -49,15 +56,19 @@ void Cross3(SkMScalar out[3], SkMScalar a[3], SkMScalar b[3]) {
out[2] = z;
}
+SkMScalar Round(SkMScalar n) {
+ return SkDoubleToMScalar(std::floor(SkMScalarToDouble(n) + 0.5));
+}
+
// Taken from http://www.w3.org/TR/css3-transforms/.
bool Slerp(SkMScalar out[4],
const SkMScalar q1[4],
const SkMScalar q2[4],
- SkMScalar progress) {
- SkMScalar product = Dot<4>(q1, q2);
+ double progress) {
+ double product = Dot<4>(q1, q2);
// Clamp product to -1.0 <= product <= 1.0.
- product = std::min(std::max(product, -SK_MScalar1), SK_MScalar1);
+ product = std::min(std::max(product, -1.0), 1.0);
// Interpolate angles along the shortest path. For example, to interpolate
// between a 175 degree angle and a 185 degree angle, interpolate along the
@@ -66,25 +77,25 @@ bool Slerp(SkMScalar out[4],
// the current W3C spec. Fixing the spec to match this approach is discussed
// at:
// http://lists.w3.org/Archives/Public/www-style/2013May/0131.html
- SkMScalar scale1 = SK_MScalar1;
+ double scale1 = 1.0;
if (product < 0) {
product = -product;
- scale1 = -SK_MScalar1;
+ scale1 = -1.0;
}
- const SkMScalar epsilon = 1e-5;
- if (std::abs(product - SK_MScalar1) < epsilon) {
+ const double epsilon = 1e-5;
+ if (std::abs(product - 1.0) < epsilon) {
for (int i = 0; i < 4; ++i)
out[i] = q1[i];
return true;
}
- SkMScalar denom = std::sqrt(1 - product * product);
- SkMScalar theta = std::acos(product);
- SkMScalar w = std::sin(progress * theta) * (1 / denom);
+ double denom = std::sqrt(1.0 - product * product);
+ double theta = std::acos(product);
+ double w = std::sin(progress * theta) * (1.0 / denom);
scale1 *= std::cos(progress * theta) - product * w;
- SkMScalar scale2 = w;
+ double scale2 = w;
Combine<4>(out, q1, q2, scale1, scale2);
return true;
@@ -104,6 +115,163 @@ bool Normalize(SkMatrix44& m) {
return true;
}
+SkMatrix44 BuildPerspectiveMatrix(const DecomposedTransform& decomp) {
+ SkMatrix44 matrix(SkMatrix44::kIdentity_Constructor);
+
+ for (int i = 0; i < 4; i++)
+ matrix.setDouble(3, i, decomp.perspective[i]);
+ return matrix;
+}
+
+SkMatrix44 BuildTranslationMatrix(const DecomposedTransform& decomp) {
+ SkMatrix44 matrix(SkMatrix44::kUninitialized_Constructor);
+ // Implicitly calls matrix.setIdentity()
+ matrix.setTranslate(SkDoubleToMScalar(decomp.translate[0]),
+ SkDoubleToMScalar(decomp.translate[1]),
+ SkDoubleToMScalar(decomp.translate[2]));
+ return matrix;
+}
+
+SkMatrix44 BuildSnappedTranslationMatrix(DecomposedTransform decomp) {
+ decomp.translate[0] = Round(decomp.translate[0]);
+ decomp.translate[1] = Round(decomp.translate[1]);
+ decomp.translate[2] = Round(decomp.translate[2]);
+ return BuildTranslationMatrix(decomp);
+}
+
+SkMatrix44 BuildRotationMatrix(const DecomposedTransform& decomp) {
+ double x = decomp.quaternion[0];
+ double y = decomp.quaternion[1];
+ double z = decomp.quaternion[2];
+ double w = decomp.quaternion[3];
+
+ SkMatrix44 matrix(SkMatrix44::kUninitialized_Constructor);
+
+ // Implicitly calls matrix.setIdentity()
+ matrix.set3x3(1.0 - 2.0 * (y * y + z * z),
+ 2.0 * (x * y + z * w),
+ 2.0 * (x * z - y * w),
+ 2.0 * (x * y - z * w),
+ 1.0 - 2.0 * (x * x + z * z),
+ 2.0 * (y * z + x * w),
+ 2.0 * (x * z + y * w),
+ 2.0 * (y * z - x * w),
+ 1.0 - 2.0 * (x * x + y * y));
+ return matrix;
+}
+
+SkMatrix44 BuildSnappedRotationMatrix(const DecomposedTransform& decomp) {
+ // Create snapped rotation.
+ SkMatrix44 rotation_matrix = BuildRotationMatrix(decomp);
+ for (int i = 0; i < 3; ++i) {
+ for (int j = 0; j < 3; ++j) {
+ SkMScalar value = rotation_matrix.get(i, j);
+ // Snap values to -1, 0 or 1.
+ if (value < -0.5f) {
+ value = -1.0f;
+ } else if (value > 0.5f) {
+ value = 1.0f;
+ } else {
+ value = 0.0f;
+ }
+ rotation_matrix.set(i, j, value);
+ }
+ }
+ return rotation_matrix;
+}
+
+SkMatrix44 BuildSkewMatrix(const DecomposedTransform& decomp) {
+ SkMatrix44 matrix(SkMatrix44::kIdentity_Constructor);
+
+ SkMatrix44 temp(SkMatrix44::kIdentity_Constructor);
+ if (decomp.skew[2]) {
+ temp.setDouble(1, 2, decomp.skew[2]);
+ matrix.preConcat(temp);
+ }
+
+ if (decomp.skew[1]) {
+ temp.setDouble(1, 2, 0);
+ temp.setDouble(0, 2, decomp.skew[1]);
+ matrix.preConcat(temp);
+ }
+
+ if (decomp.skew[0]) {
+ temp.setDouble(0, 2, 0);
+ temp.setDouble(0, 1, decomp.skew[0]);
+ matrix.preConcat(temp);
+ }
+ return matrix;
+}
+
+SkMatrix44 BuildScaleMatrix(const DecomposedTransform& decomp) {
+ SkMatrix44 matrix(SkMatrix44::kUninitialized_Constructor);
+ matrix.setScale(SkDoubleToMScalar(decomp.scale[0]),
+ SkDoubleToMScalar(decomp.scale[1]),
+ SkDoubleToMScalar(decomp.scale[2]));
+ return matrix;
+}
+
+SkMatrix44 BuildSnappedScaleMatrix(DecomposedTransform decomp) {
+ decomp.scale[0] = Round(decomp.scale[0]);
+ decomp.scale[1] = Round(decomp.scale[1]);
+ decomp.scale[2] = Round(decomp.scale[2]);
+ return BuildScaleMatrix(decomp);
+}
+
+Transform ComposeTransform(const SkMatrix44& perspective,
+ const SkMatrix44& translation,
+ const SkMatrix44& rotation,
+ const SkMatrix44& skew,
+ const SkMatrix44& scale) {
+ SkMatrix44 matrix(SkMatrix44::kIdentity_Constructor);
+
+ matrix.preConcat(perspective);
+ matrix.preConcat(translation);
+ matrix.preConcat(rotation);
+ matrix.preConcat(skew);
+ matrix.preConcat(scale);
+
+ Transform to_return;
+ to_return.matrix() = matrix;
+ return to_return;
+}
+
+bool CheckViewportPointMapsWithinOnePixel(const Point& point,
+ const Transform& transform) {
+ Point3F point_original(point);
+ Point3F point_transformed(point);
+
+ // Can't use TransformRect here since it would give us the axis-aligned
+ // bounding rect of the 4 points in the initial rectable which is not what we
+ // want.
+ transform.TransformPoint(&point_transformed);
+
+ if ((point_transformed - point_original).Length() > 1.f) {
+ // The changed distance should not be more than 1 pixel.
+ return false;
+ }
+ return true;
+}
+
+bool CheckTransformsMapsIntViewportWithinOnePixel(const Rect& viewport,
+ const Transform& original,
+ const Transform& snapped) {
+
+ Transform original_inv(Transform::kSkipInitialization);
+ bool invertible = true;
+ invertible &= original.GetInverse(&original_inv);
+ DCHECK(invertible) << "Non-invertible transform, cannot snap.";
+
+ Transform combined = snapped * original_inv;
+
+ return CheckViewportPointMapsWithinOnePixel(viewport.origin(), combined) &&
+ CheckViewportPointMapsWithinOnePixel(viewport.top_right(), combined) &&
+ CheckViewportPointMapsWithinOnePixel(viewport.bottom_left(),
+ combined) &&
+ CheckViewportPointMapsWithinOnePixel(viewport.bottom_right(),
+ combined);
+}
+
} // namespace
Transform GetScaleTransform(const Point& anchor, float scale) {
@@ -126,9 +294,9 @@ DecomposedTransform::DecomposedTransform() {
bool BlendDecomposedTransforms(DecomposedTransform* out,
const DecomposedTransform& to,
const DecomposedTransform& from,
- SkMScalar progress) {
- SkMScalar scalea = progress;
- SkMScalar scaleb = SK_MScalar1 - progress;
+ double progress) {
+ double scalea = progress;
+ double scaleb = 1.0 - progress;
Combine<3>(out->translate, to.translate, from.translate, scalea, scaleb);
Combine<3>(out->scale, to.scale, from.scale, scalea, scaleb);
Combine<3>(out->skew, to.skew, from.skew, scalea, scaleb);
@@ -266,54 +434,68 @@ bool DecomposeTransform(DecomposedTransform* decomp,
// Taken from http://www.w3.org/TR/css3-transforms/.
Transform ComposeTransform(const DecomposedTransform& decomp) {
- SkMatrix44 matrix(SkMatrix44::kIdentity_Constructor);
- for (int i = 0; i < 4; i++)
- matrix.set(3, i, decomp.perspective[i]);
+ SkMatrix44 perspective = BuildPerspectiveMatrix(decomp);
+ SkMatrix44 translation = BuildTranslationMatrix(decomp);
+ SkMatrix44 rotation = BuildRotationMatrix(decomp);
+ SkMatrix44 skew = BuildSkewMatrix(decomp);
+ SkMatrix44 scale = BuildScaleMatrix(decomp);
- matrix.preTranslate(
- decomp.translate[0], decomp.translate[1], decomp.translate[2]);
+ return ComposeTransform(perspective, translation, rotation, skew, scale);
+}
- SkMScalar x = decomp.quaternion[0];
- SkMScalar y = decomp.quaternion[1];
- SkMScalar z = decomp.quaternion[2];
- SkMScalar w = decomp.quaternion[3];
+bool SnapTransform(Transform* out,
+ const Transform& transform,
+ const Rect& viewport) {
+ DecomposedTransform decomp;
+ DecomposeTransform(&decomp, transform);
- SkMatrix44 rotation_matrix(SkMatrix44::kUninitialized_Constructor);
- rotation_matrix.set3x3(1.0 - 2.0 * (y * y + z * z),
- 2.0 * (x * y + z * w),
- 2.0 * (x * z - y * w),
- 2.0 * (x * y - z * w),
- 1.0 - 2.0 * (x * x + z * z),
- 2.0 * (y * z + x * w),
- 2.0 * (x * z + y * w),
- 2.0 * (y * z - x * w),
- 1.0 - 2.0 * (x * x + y * y));
+ SkMatrix44 rotation_matrix = BuildSnappedRotationMatrix(decomp);
+ SkMatrix44 translation = BuildSnappedTranslationMatrix(decomp);
+ SkMatrix44 scale = BuildSnappedScaleMatrix(decomp);
- matrix.preConcat(rotation_matrix);
+ // Rebuild matrices for other unchanged components.
+ SkMatrix44 perspective = BuildPerspectiveMatrix(decomp);
- SkMatrix44 temp(SkMatrix44::kIdentity_Constructor);
- if (decomp.skew[2]) {
- temp.set(1, 2, decomp.skew[2]);
- matrix.preConcat(temp);
- }
+ // Completely ignore the skew.
+ SkMatrix44 skew(SkMatrix44::kIdentity_Constructor);
- if (decomp.skew[1]) {
- temp.set(1, 2, 0);
- temp.set(0, 2, decomp.skew[1]);
- matrix.preConcat(temp);
- }
+ // Get full tranform
+ Transform snapped =
+ ComposeTransform(perspective, translation, rotation_matrix, skew, scale);
- if (decomp.skew[0]) {
- temp.set(0, 2, 0);
- temp.set(0, 1, decomp.skew[0]);
- matrix.preConcat(temp);
+ // Verify that viewport is not moved unnaturally.
+ bool snappable =
+ CheckTransformsMapsIntViewportWithinOnePixel(viewport, transform, snapped);
+ if (snappable) {
+ *out = snapped;
}
+ return snappable;
+}
- matrix.preScale(decomp.scale[0], decomp.scale[1], decomp.scale[2]);
-
- Transform to_return;
- to_return.matrix() = matrix;
- return to_return;
+std::string DecomposedTransform::ToString() const {
+ return base::StringPrintf(
+ "translate: %+0.4f %+0.4f %+0.4f\n"
+ "scale: %+0.4f %+0.4f %+0.4f\n"
+ "skew: %+0.4f %+0.4f %+0.4f\n"
+ "perspective: %+0.4f %+0.4f %+0.4f %+0.4f\n"
+ "quaternion: %+0.4f %+0.4f %+0.4f %+0.4f\n",
+ translate[0],
+ translate[1],
+ translate[2],
+ scale[0],
+ scale[1],
+ scale[2],
+ skew[0],
+ skew[1],
+ skew[2],
+ perspective[0],
+ perspective[1],
+ perspective[2],
+ perspective[3],
+ quaternion[0],
+ quaternion[1],
+ quaternion[2],
+ quaternion[3]);
}
} // namespace ui
diff --git a/chromium/ui/gfx/transform_util.h b/chromium/ui/gfx/transform_util.h
index be5ba4c03ce..a77ded28f73 100644
--- a/chromium/ui/gfx/transform_util.h
+++ b/chromium/ui/gfx/transform_util.h
@@ -11,13 +11,14 @@
namespace gfx {
class Point;
+class Rect;
// Returns a scale transform at |anchor| point.
-UI_EXPORT Transform GetScaleTransform(const Point& anchor, float scale);
+GFX_EXPORT Transform GetScaleTransform(const Point& anchor, float scale);
// Contains the components of a factored transform. These components may be
// blended and recomposed.
-struct UI_EXPORT DecomposedTransform {
+struct GFX_EXPORT DecomposedTransform {
// The default constructor initializes the components in such a way that
// if used with Compose below, will produce the identity transform.
DecomposedTransform();
@@ -28,6 +29,8 @@ struct UI_EXPORT DecomposedTransform {
SkMScalar perspective[4];
SkMScalar quaternion[4];
+ std::string ToString() const;
+
// Copy and assign are allowed.
};
@@ -35,21 +38,25 @@ struct UI_EXPORT DecomposedTransform {
// routines described in http://www.w3.org/TR/css3-3d-transform/.
// |progress| is in the range [0, 1] (0 leaves |out| unchanged, and 1
// assigns |from| to |out|).
-UI_EXPORT bool BlendDecomposedTransforms(DecomposedTransform* out,
- const DecomposedTransform& to,
- const DecomposedTransform& from,
- SkMScalar progress);
+GFX_EXPORT bool BlendDecomposedTransforms(DecomposedTransform* out,
+ const DecomposedTransform& to,
+ const DecomposedTransform& from,
+ double progress);
// Decomposes this transform into its translation, scale, skew, perspective,
// and rotation components following the routines detailed in this spec:
// http://www.w3.org/TR/css3-3d-transforms/.
-UI_EXPORT bool DecomposeTransform(DecomposedTransform* out,
- const Transform& transform);
+GFX_EXPORT bool DecomposeTransform(DecomposedTransform* out,
+ const Transform& transform);
// Composes a transform from the given translation, scale, skew, prespective,
// and rotation components following the routines detailed in this spec:
// http://www.w3.org/TR/css3-3d-transforms/.
-UI_EXPORT Transform ComposeTransform(const DecomposedTransform& decomp);
+GFX_EXPORT Transform ComposeTransform(const DecomposedTransform& decomp);
+
+GFX_EXPORT bool SnapTransform(Transform* out,
+ const Transform& transform,
+ const Rect& viewport);
} // namespace gfx
diff --git a/chromium/ui/gfx/transform_util_unittest.cc b/chromium/ui/gfx/transform_util_unittest.cc
index 94195c29bb9..41bfc40783a 100644
--- a/chromium/ui/gfx/transform_util_unittest.cc
+++ b/chromium/ui/gfx/transform_util_unittest.cc
@@ -6,6 +6,8 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/point.h"
+#include "ui/gfx/point3_f.h"
+#include "ui/gfx/rect.h"
namespace gfx {
namespace {
@@ -30,5 +32,149 @@ TEST(TransformUtilTest, GetScaleTransform) {
}
}
+TEST(TransformUtilTest, SnapRotation) {
+ Transform result(Transform::kSkipInitialization);
+ Transform transform;
+ transform.RotateAboutZAxis(89.99);
+
+ Rect viewport(1920, 1200);
+ bool snapped = SnapTransform(&result, transform, viewport);
+
+ EXPECT_TRUE(snapped) << "Viewport should snap for this rotation.";
+}
+
+TEST(TransformUtilTest, SnapRotationDistantViewport) {
+ const int kOffset = 5000;
+ Transform result(Transform::kSkipInitialization);
+ Transform transform;
+
+ transform.RotateAboutZAxis(89.99);
+
+ Rect viewport(kOffset, kOffset, 1920, 1200);
+ bool snapped = SnapTransform(&result, transform, viewport);
+
+ EXPECT_FALSE(snapped) << "Distant viewport shouldn't snap by more than 1px.";
+}
+
+TEST(TransformUtilTest, NoSnapRotation) {
+ Transform result(Transform::kSkipInitialization);
+ Transform transform;
+ const int kOffset = 5000;
+
+ transform.RotateAboutZAxis(89.9);
+
+ Rect viewport(kOffset, kOffset, 1920, 1200);
+ bool snapped = SnapTransform(&result, transform, viewport);
+
+ EXPECT_FALSE(snapped) << "Viewport should not snap for this rotation.";
+}
+
+// Translations should always be snappable, the most we would move is 0.5
+// pixels towards either direction to the nearest value in each component.
+TEST(TransformUtilTest, SnapTranslation) {
+ Transform result(Transform::kSkipInitialization);
+ Transform transform;
+
+ transform.Translate3d(
+ SkDoubleToMScalar(1.01), SkDoubleToMScalar(1.99), SkDoubleToMScalar(3.0));
+
+ Rect viewport(1920, 1200);
+ bool snapped = SnapTransform(&result, transform, viewport);
+
+ EXPECT_TRUE(snapped) << "Viewport should snap for this translation.";
+}
+
+TEST(TransformUtilTest, SnapTranslationDistantViewport) {
+ Transform result(Transform::kSkipInitialization);
+ Transform transform;
+ const int kOffset = 5000;
+
+ transform.Translate3d(
+ SkDoubleToMScalar(1.01), SkDoubleToMScalar(1.99), SkDoubleToMScalar(3.0));
+
+ Rect viewport(kOffset, kOffset, 1920, 1200);
+ bool snapped = SnapTransform(&result, transform, viewport);
+
+ EXPECT_TRUE(snapped)
+ << "Distant viewport should still snap by less than 1px.";
+}
+
+TEST(TransformUtilTest, SnapScale) {
+ Transform result(Transform::kSkipInitialization);
+ Transform transform;
+
+ transform.Scale3d(SkDoubleToMScalar(5.0),
+ SkDoubleToMScalar(2.00001),
+ SkDoubleToMScalar(1.0));
+ Rect viewport(1920, 1200);
+ bool snapped = SnapTransform(&result, transform, viewport);
+
+ EXPECT_TRUE(snapped) << "Viewport should snap for this scaling.";
+}
+
+TEST(TransformUtilTest, NoSnapScale) {
+ Transform result(Transform::kSkipInitialization);
+ Transform transform;
+
+ transform.Scale3d(
+ SkDoubleToMScalar(5.0), SkDoubleToMScalar(2.1), SkDoubleToMScalar(1.0));
+ Rect viewport(1920, 1200);
+ bool snapped = SnapTransform(&result, transform, viewport);
+
+ EXPECT_FALSE(snapped) << "Viewport shouldn't snap for this scaling.";
+}
+
+TEST(TransformUtilTest, SnapCompositeTransform) {
+ Transform result(Transform::kSkipInitialization);
+ Transform transform;
+
+ transform.Translate3d(SkDoubleToMScalar(30.5), SkDoubleToMScalar(20.0),
+ SkDoubleToMScalar(10.1));
+ transform.RotateAboutZAxis(89.99);
+ transform.Scale3d(SkDoubleToMScalar(1.0),
+ SkDoubleToMScalar(3.00001),
+ SkDoubleToMScalar(2.0));
+
+ Rect viewport(1920, 1200);
+ bool snapped = SnapTransform(&result, transform, viewport);
+ ASSERT_TRUE(snapped) << "Viewport should snap all components.";
+
+ Point3F point;
+
+ point = Point3F(viewport.origin());
+ result.TransformPoint(&point);
+ EXPECT_EQ(Point3F(31.f, 20.f, 10.f), point) << "Transformed origin";
+
+ point = Point3F(viewport.top_right());
+ result.TransformPoint(&point);
+ EXPECT_EQ(Point3F(31.f, 1940.f, 10.f), point) << "Transformed top-right";
+
+ point = Point3F(viewport.bottom_left());
+ result.TransformPoint(&point);
+ EXPECT_EQ(Point3F(-3569.f, 20.f, 10.f), point) << "Transformed bottom-left";
+
+ point = Point3F(viewport.bottom_right());
+ result.TransformPoint(&point);
+ EXPECT_EQ(Point3F(-3569.f, 1940.f, 10.f), point)
+ << "Transformed bottom-right";
+}
+
+TEST(TransformUtilTest, NoSnapSkewedCompositeTransform) {
+ Transform result(Transform::kSkipInitialization);
+ Transform transform;
+
+
+ transform.RotateAboutZAxis(89.99);
+ transform.Scale3d(SkDoubleToMScalar(1.0),
+ SkDoubleToMScalar(3.00001),
+ SkDoubleToMScalar(2.0));
+ transform.Translate3d(SkDoubleToMScalar(30.5), SkDoubleToMScalar(20.0),
+ SkDoubleToMScalar(10.1));
+ transform.SkewX(20.0);
+ Rect viewport(1920, 1200);
+ bool snapped = SnapTransform(&result, transform, viewport);
+ EXPECT_FALSE(snapped) << "Skewed viewport should not snap.";
+}
+
} // namespace
} // namespace gfx
diff --git a/chromium/ui/gfx/ui_gfx_exports.cc b/chromium/ui/gfx/ui_gfx_exports.cc
new file mode 100644
index 00000000000..ca95eb33194
--- /dev/null
+++ b/chromium/ui/gfx/ui_gfx_exports.cc
@@ -0,0 +1,10 @@
+// Copyright 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.
+
+// This file is for including headers that are not included in any other .cc
+// files contained with the ui/gfx module. We need to include these here so
+// that linker will know to include the symbols, defined by these headers, in
+// the resulting dynamic library (gfx.dll).
+
+#include "ui/gfx/vsync_provider.h"
diff --git a/chromium/ui/gfx/utf16_indexing.cc b/chromium/ui/gfx/utf16_indexing.cc
index 6af10c18499..c7f38de0d11 100644
--- a/chromium/ui/gfx/utf16_indexing.cc
+++ b/chromium/ui/gfx/utf16_indexing.cc
@@ -9,12 +9,12 @@
namespace gfx {
-bool IsValidCodePointIndex(const string16& s, size_t index) {
+bool IsValidCodePointIndex(const base::string16& s, size_t index) {
return index == 0 || index == s.length() ||
!(CBU16_IS_TRAIL(s[index]) && CBU16_IS_LEAD(s[index - 1]));
}
-ptrdiff_t UTF16IndexToOffset(const string16& s, size_t base, size_t pos) {
+ptrdiff_t UTF16IndexToOffset(const base::string16& s, size_t base, size_t pos) {
// The indices point between UTF-16 words (range 0 to s.length() inclusive).
// In order to consistently handle indices that point to the middle of a
// surrogate pair, we count the first word in that surrogate pair and not
@@ -30,7 +30,9 @@ ptrdiff_t UTF16IndexToOffset(const string16& s, size_t base, size_t pos) {
return delta;
}
-size_t UTF16OffsetToIndex(const string16& s, size_t base, ptrdiff_t offset) {
+size_t UTF16OffsetToIndex(const base::string16& s,
+ size_t base,
+ ptrdiff_t offset) {
DCHECK_LE(base, s.length());
// As in UTF16IndexToOffset, we count the first half of a surrogate pair, not
// the second. When stepping from pos to pos+1 we check s[pos:pos+1] == s[pos]
diff --git a/chromium/ui/gfx/utf16_indexing.h b/chromium/ui/gfx/utf16_indexing.h
index 7f56384299f..4c2b2c19d56 100644
--- a/chromium/ui/gfx/utf16_indexing.h
+++ b/chromium/ui/gfx/utf16_indexing.h
@@ -12,7 +12,7 @@ namespace gfx {
// Returns false if s[index-1] is a high surrogate and s[index] is a low
// surrogate, true otherwise.
-UI_EXPORT bool IsValidCodePointIndex(const string16& s, size_t index);
+GFX_EXPORT bool IsValidCodePointIndex(const base::string16& s, size_t index);
// |UTF16IndexToOffset| returns the number of code points between |base| and
// |pos| in the given string. |UTF16OffsetToIndex| returns the index that is
@@ -37,12 +37,12 @@ UI_EXPORT bool IsValidCodePointIndex(const string16& s, size_t index);
// Always,
// UTF16IndexToOffset(s, base, UTF16OffsetToIndex(s, base, ofs)) == ofs
// UTF16IndexToOffset(s, i, j) == -UTF16IndexToOffset(s, j, i)
-UI_EXPORT ptrdiff_t UTF16IndexToOffset(const string16& s,
- size_t base,
- size_t pos);
-UI_EXPORT size_t UTF16OffsetToIndex(const string16& s,
- size_t base,
- ptrdiff_t offset);
+GFX_EXPORT ptrdiff_t UTF16IndexToOffset(const base::string16& s,
+ size_t base,
+ size_t pos);
+GFX_EXPORT size_t UTF16OffsetToIndex(const base::string16& s,
+ size_t base,
+ ptrdiff_t offset);
} // namespace gfx
diff --git a/chromium/ui/gfx/vector2d.h b/chromium/ui/gfx/vector2d.h
index 9494120d26d..8dd76324d1a 100644
--- a/chromium/ui/gfx/vector2d.h
+++ b/chromium/ui/gfx/vector2d.h
@@ -18,7 +18,7 @@
namespace gfx {
-class UI_EXPORT Vector2d {
+class GFX_EXPORT Vector2d {
public:
Vector2d() : x_(0), y_(0) {}
Vector2d(int x, int y) : x_(x), y_(y) {}
diff --git a/chromium/ui/gfx/vector2d_conversions.h b/chromium/ui/gfx/vector2d_conversions.h
index 051092e78fe..509a4567d10 100644
--- a/chromium/ui/gfx/vector2d_conversions.h
+++ b/chromium/ui/gfx/vector2d_conversions.h
@@ -11,13 +11,13 @@
namespace gfx {
// Returns a Vector2d with each component from the input Vector2dF floored.
-UI_EXPORT Vector2d ToFlooredVector2d(const Vector2dF& vector2d);
+GFX_EXPORT Vector2d ToFlooredVector2d(const Vector2dF& vector2d);
// Returns a Vector2d with each component from the input Vector2dF ceiled.
-UI_EXPORT Vector2d ToCeiledVector2d(const Vector2dF& vector2d);
+GFX_EXPORT Vector2d ToCeiledVector2d(const Vector2dF& vector2d);
// Returns a Vector2d with each component from the input Vector2dF rounded.
-UI_EXPORT Vector2d ToRoundedVector2d(const Vector2dF& vector2d);
+GFX_EXPORT Vector2d ToRoundedVector2d(const Vector2dF& vector2d);
} // namespace gfx
diff --git a/chromium/ui/gfx/vector2d_f.h b/chromium/ui/gfx/vector2d_f.h
index ebd0b5b4fb5..289b9b7a8d1 100644
--- a/chromium/ui/gfx/vector2d_f.h
+++ b/chromium/ui/gfx/vector2d_f.h
@@ -16,7 +16,7 @@
namespace gfx {
-class UI_EXPORT Vector2dF {
+class GFX_EXPORT Vector2dF {
public:
Vector2dF() : x_(0), y_(0) {}
Vector2dF(float x, float y) : x_(x), y_(y) {}
@@ -91,16 +91,16 @@ inline Vector2dF operator-(const Vector2dF& lhs, const Vector2dF& rhs) {
}
// Return the cross product of two vectors.
-UI_EXPORT double CrossProduct(const Vector2dF& lhs, const Vector2dF& rhs);
+GFX_EXPORT double CrossProduct(const Vector2dF& lhs, const Vector2dF& rhs);
// Return the dot product of two vectors.
-UI_EXPORT double DotProduct(const Vector2dF& lhs, const Vector2dF& rhs);
+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.
-UI_EXPORT Vector2dF ScaleVector2d(const Vector2dF& v,
- float x_scale,
- float y_scale);
+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) {
diff --git a/chromium/ui/gfx/vector3d_f.h b/chromium/ui/gfx/vector3d_f.h
index aaa415b53bd..0e91a362eca 100644
--- a/chromium/ui/gfx/vector3d_f.h
+++ b/chromium/ui/gfx/vector3d_f.h
@@ -17,7 +17,7 @@
namespace gfx {
-class UI_EXPORT Vector3dF {
+class GFX_EXPORT Vector3dF {
public:
Vector3dF();
Vector3dF(float x, float y, float z);
@@ -105,14 +105,14 @@ inline Vector3dF CrossProduct(const Vector3dF& lhs, const Vector3dF& rhs) {
}
// Return the dot product of two vectors.
-UI_EXPORT float DotProduct(const Vector3dF& lhs, const Vector3dF& rhs);
+GFX_EXPORT float DotProduct(const Vector3dF& lhs, const Vector3dF& rhs);
// Return a vector that is |v| scaled by the given scale factors along each
// axis.
-UI_EXPORT Vector3dF ScaleVector3d(const Vector3dF& v,
- float x_scale,
- float y_scale,
- float z_scale);
+GFX_EXPORT Vector3dF ScaleVector3d(const Vector3dF& v,
+ float x_scale,
+ float y_scale,
+ float z_scale);
// Return a vector that is |v| scaled by the given scale factor.
inline Vector3dF ScaleVector3d(const Vector3dF& v, float scale) {
diff --git a/chromium/ui/gfx/vsync_provider.h b/chromium/ui/gfx/vsync_provider.h
new file mode 100644
index 00000000000..90464bcbf68
--- /dev/null
+++ b/chromium/ui/gfx/vsync_provider.h
@@ -0,0 +1,33 @@
+// Copyright 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_VSYNC_PROVIDER_H_
+#define UI_GFX_VSYNC_PROVIDER_H_
+
+#include "base/callback.h"
+#include "base/time/time.h"
+#include "ui/gfx/gfx_export.h"
+
+namespace gfx {
+
+class GFX_EXPORT VSyncProvider {
+ public:
+ virtual ~VSyncProvider() {}
+
+ typedef base::Callback<
+ void(const base::TimeTicks timebase, const base::TimeDelta interval)>
+ UpdateVSyncCallback;
+
+ // Get the time of the most recent screen refresh, along with the time
+ // between consecutive refreshes. The callback is called as soon as
+ // the data is available: it could be immediately from this method,
+ // later via a PostTask to the current MessageLoop, or never (if we have
+ // no data source). We provide the strong guarantee that the callback will
+ // not be called once the instance of this class is destroyed.
+ virtual void GetVSyncParameters(const UpdateVSyncCallback& callback) = 0;
+};
+
+} // namespace gfx
+
+#endif // UI_GFX_VSYNC_PROVIDER_H_
diff --git a/chromium/ui/gfx/win/dpi.cc b/chromium/ui/gfx/win/dpi.cc
index 98d23bd5ef9..6bc25dee646 100644
--- a/chromium/ui/gfx/win/dpi.cc
+++ b/chromium/ui/gfx/win/dpi.cc
@@ -8,7 +8,6 @@
#include "base/command_line.h"
#include "base/win/scoped_hdc.h"
#include "base/win/windows_version.h"
-#include "ui/base/layout.h"
#include "base/win/registry.h"
#include "ui/gfx/display.h"
#include "ui/gfx/switches.h"
@@ -21,31 +20,6 @@ namespace {
int kDefaultDPIX = 96;
int kDefaultDPIY = 96;
-// Tests to see if the command line flag "--high-dpi-support" is set.
-bool IsHighDPIEnabled() {
- // Default is disabled.
- if (CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kHighDPISupport)) {
- return CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
- switches::kHighDPISupport).compare("1") == 0;
- }
- return false;
-}
-
-// Gets the device scale factor. If support is enabled, this will return the
-// best available scale based on the screen's pixel density. This can be
-// affected (overridden) by --force-device-scale-factor=x
-float GetDeviceScaleFactorImpl() {
- if (IsHighDPIEnabled()) {
- float scale = gfx::Display::HasForceDeviceScaleFactor() ?
- gfx::Display::GetForcedDeviceScaleFactor() : gfx::GetDPIScale();
- // Quantize to nearest supported scale factor.
- scale = ui::GetScaleFactorScale(ui::GetScaleFactorFromScale(scale));
- return scale;
- }
- return 1.0f;
-}
-
BOOL IsProcessDPIAwareWrapper() {
typedef BOOL(WINAPI *IsProcessDPIAwarePtr)(VOID);
IsProcessDPIAwarePtr is_process_dpi_aware_func =
@@ -56,10 +30,41 @@ BOOL IsProcessDPIAwareWrapper() {
return FALSE;
}
+float g_device_scale_factor = 0.0f;
+
+float GetUnforcedDeviceScaleFactor() {
+ return static_cast<float>(gfx::GetDPI().width()) /
+ static_cast<float>(kDefaultDPIX);
+}
+
+float GetModernUIScaleWrapper() {
+ float result = 1.0f;
+ typedef float(WINAPI *GetModernUIScalePtr)(VOID);
+ HMODULE lib = LoadLibraryA("metro_driver.dll");
+ if (lib) {
+ GetModernUIScalePtr func =
+ reinterpret_cast<GetModernUIScalePtr>(
+ GetProcAddress(lib, "GetModernUIScale"));
+ if (func)
+ result = func();
+ FreeLibrary(lib);
+ }
+ return result;
+}
+
} // namespace
namespace gfx {
+float GetModernUIScale() {
+ return GetModernUIScaleWrapper();
+}
+
+void InitDeviceScaleFactor(float scale) {
+ DCHECK_NE(0.0f, scale);
+ g_device_scale_factor = scale;
+}
+
Size GetDPI() {
static int dpi_x = 0;
static int dpi_y = 0;
@@ -79,18 +84,30 @@ Size GetDPI() {
float GetDPIScale() {
if (IsHighDPIEnabled()) {
- return static_cast<float>(GetDPI().width()) /
- static_cast<float>(kDefaultDPIX);
+ return gfx::Display::HasForceDeviceScaleFactor() ?
+ gfx::Display::GetForcedDeviceScaleFactor() :
+ GetUnforcedDeviceScaleFactor();
}
return 1.0;
}
+bool IsHighDPIEnabled() {
+ // Default is disabled.
+ if (CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kHighDPISupport)) {
+ return CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+ switches::kHighDPISupport).compare("1") == 0;
+ }
+ return false;
+}
+
bool IsInHighDPIMode() {
return GetDPIScale() > 1.0;
}
void EnableHighDPISupport() {
- if (IsHighDPIEnabled()) {
+ if (IsHighDPIEnabled() &&
+ (base::win::GetVersion() < base::win::VERSION_WIN8_1)) {
typedef BOOL(WINAPI *SetProcessDPIAwarePtr)(VOID);
SetProcessDPIAwarePtr set_process_dpi_aware_func =
reinterpret_cast<SetProcessDPIAwarePtr>(
@@ -104,12 +121,17 @@ void EnableHighDPISupport() {
namespace win {
float GetDeviceScaleFactor() {
- static const float device_scale_factor = GetDeviceScaleFactorImpl();
- return device_scale_factor;
+ DCHECK_NE(0.0f, g_device_scale_factor);
+ return g_device_scale_factor;
}
Point ScreenToDIPPoint(const Point& pixel_point) {
- return ToFlooredPoint(ScalePoint(pixel_point, 1.0f / GetDeviceScaleFactor()));
+ static float scaling_factor =
+ GetDeviceScaleFactor() > GetUnforcedDeviceScaleFactor() ?
+ 1.0f / GetDeviceScaleFactor() :
+ 1.0f;
+ return ToFlooredPoint(ScalePoint(pixel_point,
+ scaling_factor));
}
Point DIPToScreenPoint(const Point& dip_point) {
@@ -162,7 +184,6 @@ double GetUndocumentedDPIScale() {
return scale;
}
-
double GetUndocumentedDPITouchScale() {
static double scale =
(base::win::GetVersion() < base::win::VERSION_WIN8_1) ?
@@ -170,6 +191,5 @@ double GetUndocumentedDPITouchScale() {
return scale;
}
-
} // namespace win
} // namespace gfx
diff --git a/chromium/ui/gfx/win/dpi.h b/chromium/ui/gfx/win/dpi.h
index a056f532661..772944f50f9 100644
--- a/chromium/ui/gfx/win/dpi.h
+++ b/chromium/ui/gfx/win/dpi.h
@@ -12,37 +12,52 @@
namespace gfx {
-UI_EXPORT Size GetDPI();
+// Initialization of the scale factor that should be applied for rendering
+// in this process. Must be called before attempts to call any of the getter
+// methods below in this file, e.g. in the early toolkit/resource bundle setup.
+// This can be called multiple times during various tests, but subsequent calls
+// have no effect.
+GFX_EXPORT void InitDeviceScaleFactor(float scale);
+
+GFX_EXPORT Size GetDPI();
// Gets the scale factor of the display. For example, if the display DPI is
-// 96 then the scale factor is 1.0.
-UI_EXPORT float GetDPIScale();
+// 96 then the scale factor is 1.0. Note that this is the "desktop" scale, which
+// may be differnt than GetModernUIScale().
+GFX_EXPORT float GetDPIScale();
+
+// Gets the scale factor of the modern (metro) UI display. Returns 1.0 for
+// unscaled or "not running on win8+"
+GFX_EXPORT float GetModernUIScale();
+
+// Tests to see if the command line flag "--high-dpi-support" is set.
+GFX_EXPORT bool IsHighDPIEnabled();
-UI_EXPORT bool IsInHighDPIMode();
+GFX_EXPORT bool IsInHighDPIMode();
-UI_EXPORT void EnableHighDPISupport();
+GFX_EXPORT void EnableHighDPISupport();
// TODO(kevers|girard): Move above methods into win namespace.
namespace win {
-UI_EXPORT float GetDeviceScaleFactor();
+GFX_EXPORT float GetDeviceScaleFactor();
-UI_EXPORT Point ScreenToDIPPoint(const Point& pixel_point);
+GFX_EXPORT Point ScreenToDIPPoint(const Point& pixel_point);
-UI_EXPORT Point DIPToScreenPoint(const Point& dip_point);
+GFX_EXPORT Point DIPToScreenPoint(const Point& dip_point);
-UI_EXPORT Rect ScreenToDIPRect(const Rect& pixel_bounds);
+GFX_EXPORT Rect ScreenToDIPRect(const Rect& pixel_bounds);
-UI_EXPORT Rect DIPToScreenRect(const Rect& dip_bounds);
+GFX_EXPORT Rect DIPToScreenRect(const Rect& dip_bounds);
-UI_EXPORT Size ScreenToDIPSize(const Size& size_in_pixels);
+GFX_EXPORT Size ScreenToDIPSize(const Size& size_in_pixels);
-UI_EXPORT Size DIPToScreenSize(const Size& dip_size);
+GFX_EXPORT Size DIPToScreenSize(const Size& dip_size);
// Win32's GetSystemMetrics uses pixel measures. This function calls
// GetSystemMetrics for the given |metric|, then converts the result to DIP.
-UI_EXPORT int GetSystemMetricsInDIP(int metric);
+GFX_EXPORT int GetSystemMetricsInDIP(int metric);
// Sometimes the OS secretly scales apps that are not DPIAware. This is not
// visible through standard OS calls like GetWindowPos(), or through
@@ -50,12 +65,12 @@ UI_EXPORT int GetSystemMetricsInDIP(int metric);
// Returns the scale factor of the display, where 96 DPI is 1.0.
// (Avoid this function... use GetDPIScale() instead.)
// TODO(girard): Remove this once DPIAware is enabled - http://crbug.com/149881
-UI_EXPORT double GetUndocumentedDPIScale();
+GFX_EXPORT double GetUndocumentedDPIScale();
// Win7 and Win8 send touch events scaled according to the current DPI
// scaling. Win8.1 corrects this, and sends touch events in DPI units.
// This function returns the appropriate scaling factor for touch events.
-UI_EXPORT double GetUndocumentedDPITouchScale();
+GFX_EXPORT double GetUndocumentedDPITouchScale();
} // namespace win
} // namespace gfx
diff --git a/chromium/ui/gfx/win/hwnd_util.cc b/chromium/ui/gfx/win/hwnd_util.cc
index 91f0ddd182a..fec39d4fe59 100644
--- a/chromium/ui/gfx/win/hwnd_util.cc
+++ b/chromium/ui/gfx/win/hwnd_util.cc
@@ -50,6 +50,24 @@ void AdjustWindowToFit(HWND hwnd, const RECT& bounds, bool fit_to_monitor) {
SWP_NOACTIVATE | SWP_NOZORDER);
}
+// Turn off optimizations for these functions so they show up in crash reports.
+MSVC_DISABLE_OPTIMIZE();
+
+void CrashOutOfMemory() {
+ LOG_GETLASTERROR(FATAL);
+}
+
+void CrashAccessDenied() {
+ LOG_GETLASTERROR(FATAL);
+}
+
+// Crash isn't one of the ones we commonly see.
+void CrashOther() {
+ LOG_GETLASTERROR(FATAL);
+}
+
+MSVC_ENABLE_OPTIMIZE();
+
} // namespace
string16 GetClassName(HWND window) {
@@ -170,8 +188,20 @@ void CenterAndSizeWindow(HWND parent,
}
void CheckWindowCreated(HWND hwnd) {
- if (!hwnd)
+ if (!hwnd) {
+ switch (GetLastError()) {
+ case ERROR_NOT_ENOUGH_MEMORY:
+ CrashOutOfMemory();
+ break;
+ case ERROR_ACCESS_DENIED:
+ CrashAccessDenied();
+ break;
+ default:
+ CrashOther();
+ break;
+ }
LOG_GETLASTERROR(FATAL);
+ }
}
void ShowSystemMenu(HWND window) {
diff --git a/chromium/ui/gfx/win/hwnd_util.h b/chromium/ui/gfx/win/hwnd_util.h
index 70e5f8f1c2b..472daccd82e 100644
--- a/chromium/ui/gfx/win/hwnd_util.h
+++ b/chromium/ui/gfx/win/hwnd_util.h
@@ -16,38 +16,38 @@ class Size;
// A version of the GetClassNameW API that returns the class name in an
// string16. An empty result indicates a failure to get the class name.
-UI_EXPORT string16 GetClassName(HWND hwnd);
+GFX_EXPORT string16 GetClassName(HWND hwnd);
// Useful for subclassing a HWND. Returns the previous window procedure.
-UI_EXPORT WNDPROC SetWindowProc(HWND hwnd, WNDPROC wndproc);
+GFX_EXPORT WNDPROC SetWindowProc(HWND hwnd, WNDPROC wndproc);
// Pointer-friendly wrappers around Get/SetWindowLong(..., GWLP_USERDATA, ...)
// Returns the previously set value.
-UI_EXPORT void* SetWindowUserData(HWND hwnd, void* user_data);
-UI_EXPORT void* GetWindowUserData(HWND hwnd);
+GFX_EXPORT void* SetWindowUserData(HWND hwnd, void* user_data);
+GFX_EXPORT void* GetWindowUserData(HWND hwnd);
// Returns true if the specified window is the current active top window or one
// of its children.
-UI_EXPORT bool DoesWindowBelongToActiveWindow(HWND window);
+GFX_EXPORT bool DoesWindowBelongToActiveWindow(HWND window);
// Sizes the window to have a window size of |pref|, then centers the window
// over |parent|, ensuring the window fits on screen.
-UI_EXPORT void CenterAndSizeWindow(HWND parent,
- HWND window,
- const gfx::Size& pref);
+GFX_EXPORT void CenterAndSizeWindow(HWND parent,
+ HWND window,
+ const gfx::Size& pref);
// If |hwnd| is NULL logs various thing and CHECKs. Invoke right after calling
// CreateWindow.
-UI_EXPORT void CheckWindowCreated(HWND hwnd);
+GFX_EXPORT void CheckWindowCreated(HWND hwnd);
// Shows |window|'s system menu (at a specified |point| in screen coordinates).
-UI_EXPORT void ShowSystemMenu(HWND window);
-UI_EXPORT void ShowSystemMenuAtPoint(HWND window, const gfx::Point& point);
+GFX_EXPORT void ShowSystemMenu(HWND window);
+GFX_EXPORT void ShowSystemMenuAtPoint(HWND window, const gfx::Point& point);
// Returns the window you can use to parent a top level window.
// Note that in some cases we create child windows not parented to its final
// container so in those cases you should pass true in |get_real_hwnd|.
-UI_EXPORT HWND GetWindowToParentTo(bool get_real_hwnd);
+GFX_EXPORT HWND GetWindowToParentTo(bool get_real_hwnd);
} // namespace gfx
diff --git a/chromium/ui/gfx/win/singleton_hwnd.cc b/chromium/ui/gfx/win/singleton_hwnd.cc
index 37993e8f4f0..2de6a8b8a16 100644
--- a/chromium/ui/gfx/win/singleton_hwnd.cc
+++ b/chromium/ui/gfx/win/singleton_hwnd.cc
@@ -15,16 +15,6 @@ SingletonHwnd* SingletonHwnd::GetInstance() {
}
void SingletonHwnd::AddObserver(Observer* observer) {
- if (!hwnd()) {
- if (!base::MessageLoop::current() ||
- base::MessageLoop::current()->type() != base::MessageLoop::TYPE_UI) {
- // Creating this window in (e.g.) a renderer inhibits shutdown on
- // Windows. See http://crbug.com/230122 and http://crbug.com/236039.
- DLOG(ERROR) << "Cannot create windows on non-UI thread!";
- return;
- }
- WindowImpl::Init(NULL, Rect());
- }
observer_list_.AddObserver(observer);
}
@@ -47,6 +37,14 @@ BOOL SingletonHwnd::ProcessWindowMessage(HWND window,
}
SingletonHwnd::SingletonHwnd() {
+ if (!base::MessageLoop::current() ||
+ base::MessageLoop::current()->type() != base::MessageLoop::TYPE_UI) {
+ // Creating this window in (e.g.) a renderer inhibits shutdown on
+ // Windows. See http://crbug.com/230122 and http://crbug.com/236039.
+ DLOG(ERROR) << "Cannot create windows on non-UI thread!";
+ return;
+ }
+ WindowImpl::Init(NULL, Rect());
}
SingletonHwnd::~SingletonHwnd() {
diff --git a/chromium/ui/gfx/win/singleton_hwnd.h b/chromium/ui/gfx/win/singleton_hwnd.h
index 96af6e79205..50fb9fd9df9 100644
--- a/chromium/ui/gfx/win/singleton_hwnd.h
+++ b/chromium/ui/gfx/win/singleton_hwnd.h
@@ -19,7 +19,7 @@ namespace gfx {
// Singleton message-only HWND that allows interested clients to receive WM_*
// notifications.
-class SingletonHwnd : public WindowImpl {
+class GFX_EXPORT SingletonHwnd : public WindowImpl {
public:
static SingletonHwnd* GetInstance();
diff --git a/chromium/ui/gfx/win/window_impl.cc b/chromium/ui/gfx/win/window_impl.cc
index e2e6af05c61..7f0c232ae61 100644
--- a/chromium/ui/gfx/win/window_impl.cc
+++ b/chromium/ui/gfx/win/window_impl.cc
@@ -108,7 +108,7 @@ ATOM ClassRegistrar::RetrieveClassAtom(const ClassInfo& class_info) {
0,
0,
NULL,
- NULL,
+ reinterpret_cast<HBRUSH>(GetStockObject(BLACK_BRUSH)),
NULL,
class_info.icon,
class_info.icon,
diff --git a/chromium/ui/gfx/win/window_impl.h b/chromium/ui/gfx/win/window_impl.h
index 2b0018e3f46..1825c0b2f00 100644
--- a/chromium/ui/gfx/win/window_impl.h
+++ b/chromium/ui/gfx/win/window_impl.h
@@ -40,7 +40,7 @@ class MessageMapInterface {
// Windows.
//
///////////////////////////////////////////////////////////////////////////////
-class UI_EXPORT WindowImpl : public MessageMapInterface {
+class GFX_EXPORT WindowImpl : public MessageMapInterface {
public:
WindowImpl();
virtual ~WindowImpl();
diff --git a/chromium/ui/gfx/x/x11_atom_cache.cc b/chromium/ui/gfx/x/x11_atom_cache.cc
new file mode 100644
index 00000000000..da75c0be34e
--- /dev/null
+++ b/chromium/ui/gfx/x/x11_atom_cache.cc
@@ -0,0 +1,47 @@
+// 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/x/x11_atom_cache.h"
+
+#include <X11/Xatom.h>
+
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+
+namespace ui {
+
+X11AtomCache::X11AtomCache(Display* xdisplay, const char** to_cache)
+ : xdisplay_(xdisplay),
+ uncached_atoms_allowed_(false) {
+ int cache_count = 0;
+ for (const char** i = to_cache; *i != NULL; i++)
+ cache_count++;
+
+ scoped_ptr< ::Atom[]> cached_atoms(new ::Atom[cache_count]);
+
+ // Grab all the atoms we need now to minimize roundtrips to the X11 server.
+ XInternAtoms(xdisplay_,
+ const_cast<char**>(to_cache), cache_count, False,
+ cached_atoms.get());
+
+ for (int i = 0; i < cache_count; ++i)
+ cached_atoms_.insert(std::make_pair(to_cache[i], cached_atoms[i]));
+}
+
+X11AtomCache::~X11AtomCache() {}
+
+::Atom X11AtomCache::GetAtom(const char* name) const {
+ std::map<std::string, ::Atom>::const_iterator it = cached_atoms_.find(name);
+
+ if (uncached_atoms_allowed_ && it == cached_atoms_.end()) {
+ ::Atom atom = XInternAtom(xdisplay_, name, false);
+ cached_atoms_.insert(std::make_pair(name, atom));
+ return atom;
+ }
+
+ CHECK(it != cached_atoms_.end()) << " Atom " << name << " not found";
+ return it->second;
+}
+
+} // namespace ui
diff --git a/chromium/ui/gfx/x/x11_atom_cache.h b/chromium/ui/gfx/x/x11_atom_cache.h
new file mode 100644
index 00000000000..fefa64205d0
--- /dev/null
+++ b/chromium/ui/gfx/x/x11_atom_cache.h
@@ -0,0 +1,50 @@
+// 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_X_X11_ATOM_CACHE_H_
+#define UI_GFX_X_X11_ATOM_CACHE_H_
+
+#include "base/basictypes.h"
+#include "ui/gfx/gfx_export.h"
+
+#include <map>
+#include <string>
+
+#include <X11/Xlib.h>
+
+// Get rid of a macro from Xlib.h that conflicts with Aura's RootWindow class.
+#undef RootWindow
+
+namespace ui {
+
+// Pre-caches all Atoms on first use to minimize roundtrips to the X11
+// server. By default, GetAtom() will CHECK() that atoms accessed through
+// GetAtom() were passed to the constructor, but this behaviour can be changed
+// with allow_uncached_atoms().
+class GFX_EXPORT X11AtomCache {
+ public:
+ // Preinterns the NULL terminated list of string |to_cache_ on |xdisplay|.
+ X11AtomCache(Display* xdisplay, const char** to_cache);
+ ~X11AtomCache();
+
+ // Returns the pre-interned Atom without having to go to the x server.
+ ::Atom GetAtom(const char*) const;
+
+ // When an Atom isn't in the list of items we've cached, we should look it
+ // up, cache it locally, and then return the result.
+ void allow_uncached_atoms() { uncached_atoms_allowed_ = true; }
+
+ private:
+ Display* xdisplay_;
+
+ bool uncached_atoms_allowed_;
+
+ mutable std::map<std::string, ::Atom> cached_atoms_;
+
+ DISALLOW_COPY_AND_ASSIGN(X11AtomCache);
+};
+
+} // namespace ui
+
+#endif // UI_GFX_X_X11_ATOM_CACHE_H_
diff --git a/chromium/ui/gfx/x/x11_types.cc b/chromium/ui/gfx/x/x11_types.cc
index c47c852527b..48ce6416b69 100644
--- a/chromium/ui/gfx/x/x11_types.cc
+++ b/chromium/ui/gfx/x/x11_types.cc
@@ -4,6 +4,8 @@
#include "ui/gfx/x/x11_types.h"
+#include <X11/Xlib.h>
+
#include "base/message_loop/message_loop.h"
namespace gfx {
@@ -12,5 +14,142 @@ XDisplay* GetXDisplay() {
return base::MessagePumpForUI::GetDefaultXDisplay();
}
+void PutARGBImage(XDisplay* display,
+ void* visual, int depth,
+ XID pixmap, void* pixmap_gc,
+ const uint8* data,
+ int width, int height) {
+ PutARGBImage(display,
+ visual, depth,
+ pixmap, pixmap_gc,
+ data, width, height,
+ 0, 0, // src_x, src_y
+ 0, 0, // dst_x, dst_y
+ width, height);
+}
+
+int BitsPerPixelForPixmapDepth(XDisplay* dpy, int depth) {
+ int count;
+ XPixmapFormatValues* formats = XListPixmapFormats(dpy, &count);
+ if (!formats)
+ return -1;
+
+ int bits_per_pixel = -1;
+ for (int i = 0; i < count; ++i) {
+ if (formats[i].depth == depth) {
+ bits_per_pixel = formats[i].bits_per_pixel;
+ break;
+ }
+ }
+
+ XFree(formats);
+ return bits_per_pixel;
+}
+
+void PutARGBImage(XDisplay* display,
+ void* visual, int depth,
+ XID pixmap, void* pixmap_gc,
+ const uint8* data,
+ int data_width, int data_height,
+ int src_x, int src_y,
+ int dst_x, int dst_y,
+ int copy_width, int copy_height) {
+ // TODO(scherkus): potential performance impact... consider passing in as a
+ // parameter.
+ int pixmap_bpp = BitsPerPixelForPixmapDepth(display, depth);
+
+ XImage image;
+ memset(&image, 0, sizeof(image));
+
+ image.width = data_width;
+ image.height = data_height;
+ image.format = ZPixmap;
+ image.byte_order = LSBFirst;
+ image.bitmap_unit = 8;
+ image.bitmap_bit_order = LSBFirst;
+ image.depth = depth;
+ image.bits_per_pixel = pixmap_bpp;
+ image.bytes_per_line = data_width * pixmap_bpp / 8;
+
+ if (pixmap_bpp == 32) {
+ image.red_mask = 0xff0000;
+ image.green_mask = 0xff00;
+ image.blue_mask = 0xff;
+
+ // If the X server depth is already 32-bits and the color masks match,
+ // then our job is easy.
+ Visual* vis = static_cast<Visual*>(visual);
+ if (image.red_mask == vis->red_mask &&
+ image.green_mask == vis->green_mask &&
+ image.blue_mask == vis->blue_mask) {
+ image.data = const_cast<char*>(reinterpret_cast<const char*>(data));
+ XPutImage(display, pixmap, static_cast<GC>(pixmap_gc), &image,
+ src_x, src_y, dst_x, dst_y,
+ copy_width, copy_height);
+ } else {
+ // Otherwise, we need to shuffle the colors around. Assume red and blue
+ // need to be swapped.
+ //
+ // It's possible to use some fancy SSE tricks here, but since this is the
+ // slow path anyway, we do it slowly.
+
+ uint8_t* bitmap32 =
+ static_cast<uint8_t*>(malloc(4 * data_width * data_height));
+ if (!bitmap32)
+ return;
+ uint8_t* const orig_bitmap32 = bitmap32;
+ const uint32_t* bitmap_in = reinterpret_cast<const uint32_t*>(data);
+ for (int y = 0; y < data_height; ++y) {
+ for (int x = 0; x < data_width; ++x) {
+ const uint32_t pixel = *(bitmap_in++);
+ bitmap32[0] = (pixel >> 16) & 0xff; // Red
+ bitmap32[1] = (pixel >> 8) & 0xff; // Green
+ bitmap32[2] = pixel & 0xff; // Blue
+ bitmap32[3] = (pixel >> 24) & 0xff; // Alpha
+ bitmap32 += 4;
+ }
+ }
+ image.data = reinterpret_cast<char*>(orig_bitmap32);
+ XPutImage(display, pixmap, static_cast<GC>(pixmap_gc), &image,
+ src_x, src_y, dst_x, dst_y,
+ copy_width, copy_height);
+ free(orig_bitmap32);
+ }
+ } else if (pixmap_bpp == 16) {
+ // Some folks have VNC setups which still use 16-bit visuals and VNC
+ // doesn't include Xrender.
+
+ uint16_t* bitmap16 =
+ static_cast<uint16_t*>(malloc(2 * data_width * data_height));
+ if (!bitmap16)
+ return;
+ uint16_t* const orig_bitmap16 = bitmap16;
+ const uint32_t* bitmap_in = reinterpret_cast<const uint32_t*>(data);
+ for (int y = 0; y < data_height; ++y) {
+ for (int x = 0; x < data_width; ++x) {
+ const uint32_t pixel = *(bitmap_in++);
+ uint16_t out_pixel = ((pixel >> 8) & 0xf800) |
+ ((pixel >> 5) & 0x07e0) |
+ ((pixel >> 3) & 0x001f);
+ *(bitmap16++) = out_pixel;
+ }
+ }
+
+ image.data = reinterpret_cast<char*>(orig_bitmap16);
+ image.red_mask = 0xf800;
+ image.green_mask = 0x07e0;
+ image.blue_mask = 0x001f;
+
+ XPutImage(display, pixmap, static_cast<GC>(pixmap_gc), &image,
+ src_x, src_y, dst_x, dst_y,
+ copy_width, copy_height);
+ free(orig_bitmap16);
+ } else {
+ LOG(FATAL) << "Sorry, we don't support your visual depth without "
+ "Xrender support (depth:" << depth
+ << " bpp:" << pixmap_bpp << ")";
+ }
+}
+
} // namespace gfx
diff --git a/chromium/ui/gfx/x/x11_types.h b/chromium/ui/gfx/x/x11_types.h
index eab42f2352b..0f96fdc6a89 100644
--- a/chromium/ui/gfx/x/x11_types.h
+++ b/chromium/ui/gfx/x/x11_types.h
@@ -5,6 +5,7 @@
#ifndef UI_GFX_X_X11_UTIL_H_
#define UI_GFX_X_X11_UTIL_H_
+#include "base/basictypes.h"
#include "ui/gfx/gfx_export.h"
typedef unsigned long XID;
@@ -19,6 +20,32 @@ namespace gfx {
// chrome codebase to get the display from window.
GFX_EXPORT XDisplay* GetXDisplay();
+// Return the number of bits-per-pixel for a pixmap of the given depth
+GFX_EXPORT int BitsPerPixelForPixmapDepth(XDisplay* display, int depth);
+
+// Draws ARGB data on the given pixmap using the given GC, converting to the
+// server side visual depth as needed. Destination is assumed to be the same
+// dimensions as |data| or larger. |data| is also assumed to be in row order
+// with each line being exactly |width| * 4 bytes long.
+GFX_EXPORT void PutARGBImage(XDisplay* display,
+ void* visual, int depth,
+ XID pixmap, void* pixmap_gc,
+ const uint8* data,
+ int width, int height);
+
+// Same as above only more general:
+// - |data_width| and |data_height| refer to the data image
+// - |src_x|, |src_y|, |copy_width| and |copy_height| define source region
+// - |dst_x|, |dst_y|, |copy_width| and |copy_height| define destination region
+GFX_EXPORT void PutARGBImage(XDisplay* display,
+ void* visual, int depth,
+ XID pixmap, void* pixmap_gc,
+ const uint8* data,
+ int data_width, int data_height,
+ int src_x, int src_y,
+ int dst_x, int dst_y,
+ int copy_width, int copy_height);
+
} // namespace gfx
#endif // UI_GFX_X_X11_UTIL_H_