Commit aa051ee8 authored by stapelberg's avatar stapelberg Committed by Commit bot

Fix Pango font rendering with HiDPi displays on Linux.

Don’t scale fonts up twice when running with device_scale_factor > 1.0.

Chrome’s UI is scaled up to device_scale_factor (e.g. 2x) by calling
SkCanvas->scale(). See Chrome’s gfx::Canvas class which calls
canvas.scale(image_scale, image_scale):
https://code.google.com/p/chromium/codesearch#chromium/src/ui/gfx/canvas.cc

Here is a skia fiddle which renders text with .setTextSize(21):
https://fiddle.skia.org/c/098cb32edac7e394aba5b9ff4c08b06c

Here is the same fiddle, but calling canvas.Scale(2.0, 2.0) before rendering to simulate what Chrome does:
https://fiddle.skia.org/c/a7b456338776239278e398741e1098d9

As you can see, the text is twice as large.

Therefore, this commit changes Chrome to take into account the DPI that
GTK provides, but set it in perspective to the device scale factor. This
preserves the same behavior when device scale factor == 1 but yields
correct rendering when device scale factor > 1.0 (hi-dpi displays).

Before this change:
http://t.zekjur.net/chrome-hidpi-enabled.png

After this change:
http://t.zekjur.net/chrome-hidpi-enabled-scalefix.png

This change also enables subpixel rendering on HiDPi displays, which is what Chrome OS also does.
Without subpixel rendering:
http://t.zekjur.net/without-subpixel.png

With subpixel rendering:
http://t.zekjur.net/with-subpixel.png

BUG=143619

Review URL: https://codereview.chromium.org/929733002

Cr-Commit-Position: refs/heads/master@{#321457}
parent cd34266e
...@@ -126,8 +126,12 @@ void ChromeBrowserMainExtraPartsAura::PreCreateThreads() { ...@@ -126,8 +126,12 @@ void ChromeBrowserMainExtraPartsAura::PreCreateThreads() {
if (!chrome::ShouldOpenAshOnStartup()) if (!chrome::ShouldOpenAshOnStartup())
#endif #endif
{ {
gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE, gfx::Screen* screen = views::CreateDesktopScreen();
views::CreateDesktopScreen()); gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE, screen);
#if defined(USE_X11)
views::LinuxUI::instance()->UpdateDeviceScaleFactor(
screen->GetPrimaryDisplay().device_scale_factor());
#endif
} }
#endif #endif
} }
......
...@@ -382,7 +382,7 @@ gfx::FontRenderParams GetGtkFontRenderParams() { ...@@ -382,7 +382,7 @@ gfx::FontRenderParams GetGtkFontRenderParams() {
// Queries GTK for its font DPI setting and returns the number of pixels in a // Queries GTK for its font DPI setting and returns the number of pixels in a
// point. // point.
double GetPixelsInPoint() { double GetPixelsInPoint(float device_scale_factor) {
GtkSettings* gtk_settings = gtk_settings_get_default(); GtkSettings* gtk_settings = gtk_settings_get_default();
CHECK(gtk_settings); CHECK(gtk_settings);
gint gtk_dpi = -1; gint gtk_dpi = -1;
...@@ -391,6 +391,10 @@ double GetPixelsInPoint() { ...@@ -391,6 +391,10 @@ double GetPixelsInPoint() {
// GTK multiplies the DPI by 1024 before storing it. // GTK multiplies the DPI by 1024 before storing it.
double dpi = (gtk_dpi > 0) ? gtk_dpi / 1024.0 : 96.0; double dpi = (gtk_dpi > 0) ? gtk_dpi / 1024.0 : 96.0;
// Take device_scale_factor into account — if Chrome already scales the
// entire UI up by 2x, we should not also scale up.
dpi /= device_scale_factor;
// There are 72 points in an inch. // There are 72 points in an inch.
return dpi / 72.0; return dpi / 72.0;
} }
...@@ -414,7 +418,8 @@ views::LinuxUI::NonClientMiddleClickAction GetDefaultMiddleClickAction() { ...@@ -414,7 +418,8 @@ views::LinuxUI::NonClientMiddleClickAction GetDefaultMiddleClickAction() {
Gtk2UI::Gtk2UI() Gtk2UI::Gtk2UI()
: default_font_size_pixels_(0), : default_font_size_pixels_(0),
default_font_style_(gfx::Font::NORMAL), default_font_style_(gfx::Font::NORMAL),
middle_click_action_(GetDefaultMiddleClickAction()) { middle_click_action_(GetDefaultMiddleClickAction()),
device_scale_factor_(1.0) {
GtkInitFromCommandLine(*base::CommandLine::ForCurrentProcess()); GtkInitFromCommandLine(*base::CommandLine::ForCurrentProcess());
} }
...@@ -1386,7 +1391,7 @@ void Gtk2UI::UpdateDefaultFont(const PangoFontDescription* desc) { ...@@ -1386,7 +1391,7 @@ void Gtk2UI::UpdateDefaultFont(const PangoFontDescription* desc) {
const double size_points = pango_font_description_get_size(desc) / const double size_points = pango_font_description_get_size(desc) /
static_cast<double>(PANGO_SCALE); static_cast<double>(PANGO_SCALE);
default_font_size_pixels_ = static_cast<int>( default_font_size_pixels_ = static_cast<int>(
GetPixelsInPoint() * size_points + 0.5); GetPixelsInPoint(device_scale_factor_) * size_points + 0.5);
query.point_size = static_cast<int>(size_points); query.point_size = static_cast<int>(size_points);
} }
...@@ -1409,6 +1414,12 @@ void Gtk2UI::OnStyleSet(GtkWidget* widget, GtkStyle* previous_style) { ...@@ -1409,6 +1414,12 @@ void Gtk2UI::OnStyleSet(GtkWidget* widget, GtkStyle* previous_style) {
NativeThemeGtk2::instance()->NotifyObservers(); NativeThemeGtk2::instance()->NotifyObservers();
} }
void Gtk2UI::UpdateDeviceScaleFactor(float device_scale_factor) {
device_scale_factor_ = device_scale_factor;
GtkStyle* label_style = gtk_rc_get_style(fake_label_.get());
UpdateDefaultFont(label_style->font_desc);
}
} // namespace libgtk2ui } // namespace libgtk2ui
views::LinuxUI* BuildGtk2UI() { views::LinuxUI* BuildGtk2UI() {
......
...@@ -119,6 +119,9 @@ class Gtk2UI : public views::LinuxUI { ...@@ -119,6 +119,9 @@ class Gtk2UI : public views::LinuxUI {
bool MatchEvent(const ui::Event& event, bool MatchEvent(const ui::Event& event,
std::vector<ui::TextEditCommandAuraLinux>* commands) override; std::vector<ui::TextEditCommandAuraLinux>* commands) override;
// ui::Views::LinuxUI:
void UpdateDeviceScaleFactor(float device_scale_factor) override;
private: private:
typedef std::map<int, SkColor> ColorMap; typedef std::map<int, SkColor> ColorMap;
typedef std::map<int, color_utils::HSL> TintMap; typedef std::map<int, color_utils::HSL> TintMap;
...@@ -263,6 +266,8 @@ class Gtk2UI : public views::LinuxUI { ...@@ -263,6 +266,8 @@ class Gtk2UI : public views::LinuxUI {
// instance. // instance.
NativeThemeGetter native_theme_overrider_; NativeThemeGetter native_theme_overrider_;
float device_scale_factor_;
DISALLOW_COPY_AND_ASSIGN(Gtk2UI); DISALLOW_COPY_AND_ASSIGN(Gtk2UI);
}; };
......
...@@ -16,8 +16,10 @@ ...@@ -16,8 +16,10 @@
#include "base/strings/string_util.h" #include "base/strings/string_util.h"
#include "base/strings/stringprintf.h" #include "base/strings/stringprintf.h"
#include "base/synchronization/lock.h" #include "base/synchronization/lock.h"
#include "ui/gfx/display.h"
#include "ui/gfx/font.h" #include "ui/gfx/font.h"
#include "ui/gfx/linux_font_delegate.h" #include "ui/gfx/linux_font_delegate.h"
#include "ui/gfx/screen.h"
#include "ui/gfx/switches.h" #include "ui/gfx/switches.h"
namespace gfx { namespace gfx {
...@@ -62,15 +64,6 @@ struct SynchronizedCache { ...@@ -62,15 +64,6 @@ struct SynchronizedCache {
base::LazyInstance<SynchronizedCache>::Leaky g_synchronized_cache = base::LazyInstance<SynchronizedCache>::Leaky g_synchronized_cache =
LAZY_INSTANCE_INITIALIZER; LAZY_INSTANCE_INITIALIZER;
bool IsBrowserTextSubpixelPositioningEnabled(
const FontRenderParamsQuery& query) {
#if defined(OS_CHROMEOS)
return query.device_scale_factor > 1.0f;
#else
return false;
#endif
}
// Converts Fontconfig FC_HINT_STYLE to FontRenderParams::Hinting. // Converts Fontconfig FC_HINT_STYLE to FontRenderParams::Hinting.
FontRenderParams::Hinting ConvertFontconfigHintStyle(int hint_style) { FontRenderParams::Hinting ConvertFontconfigHintStyle(int hint_style) {
switch (hint_style) { switch (hint_style) {
...@@ -208,10 +201,19 @@ uint32 HashFontRenderParamsQuery(const FontRenderParamsQuery& query) { ...@@ -208,10 +201,19 @@ uint32 HashFontRenderParamsQuery(const FontRenderParamsQuery& query) {
FontRenderParams GetFontRenderParams(const FontRenderParamsQuery& query, FontRenderParams GetFontRenderParams(const FontRenderParamsQuery& query,
std::string* family_out) { std::string* family_out) {
FontRenderParamsQuery actual_query(query); FontRenderParamsQuery actual_query(query);
if (actual_query.device_scale_factor == 0) {
#if defined(OS_CHROMEOS) #if defined(OS_CHROMEOS)
if (actual_query.device_scale_factor == 0)
actual_query.device_scale_factor = device_scale_factor_for_internal_display; actual_query.device_scale_factor = device_scale_factor_for_internal_display;
#else
// Linux does not support per-display DPI, so we use a slightly simpler
// code path than on Chrome OS to figure out the device scale factor.
gfx::Screen* screen = gfx::Screen::GetScreenByType(gfx::SCREEN_TYPE_NATIVE);
if (screen) {
gfx::Display display = screen->GetPrimaryDisplay();
actual_query.device_scale_factor = display.device_scale_factor();
}
#endif #endif
}
const uint32 hash = HashFontRenderParamsQuery(actual_query); const uint32 hash = HashFontRenderParamsQuery(actual_query);
SynchronizedCache* synchronized_cache = g_synchronized_cache.Pointer(); SynchronizedCache* synchronized_cache = g_synchronized_cache.Pointer();
...@@ -252,7 +254,7 @@ FontRenderParams GetFontRenderParams(const FontRenderParamsQuery& query, ...@@ -252,7 +254,7 @@ FontRenderParams GetFontRenderParams(const FontRenderParamsQuery& query,
actual_query.for_web_contents actual_query.for_web_contents
? base::CommandLine::ForCurrentProcess()->HasSwitch( ? base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableWebkitTextSubpixelPositioning) switches::kEnableWebkitTextSubpixelPositioning)
: IsBrowserTextSubpixelPositioningEnabled(actual_query); : actual_query.device_scale_factor > 1.0f;
// To enable subpixel positioning, we need to disable hinting. // To enable subpixel positioning, we need to disable hinting.
if (params.subpixel_positioning) if (params.subpixel_positioning)
......
...@@ -150,6 +150,10 @@ class VIEWS_EXPORT LinuxUI : public ui::LinuxInputMethodContextFactory, ...@@ -150,6 +150,10 @@ class VIEWS_EXPORT LinuxUI : public ui::LinuxInputMethodContextFactory,
// automatically. In case Chromium does not open a new window on startup, // automatically. In case Chromium does not open a new window on startup,
// e.g. an existing browser window already exists, this should be called. // e.g. an existing browser window already exists, this should be called.
virtual void NotifyWindowManagerStartupComplete() = 0; virtual void NotifyWindowManagerStartupComplete() = 0;
// Updates the device scale factor so that the default font size can be
// recalculated.
virtual void UpdateDeviceScaleFactor(float device_scale_factor) = 0;
}; };
} // namespace views } // namespace views
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment