summaryrefslogtreecommitdiffstats
path: root/ui
diff options
context:
space:
mode:
authorxji@chromium.org <xji@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-12-19 04:09:01 +0000
committerxji@chromium.org <xji@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-12-19 04:09:01 +0000
commit732ef6737ef6e1346255be7230032dcaf4e9ad03 (patch)
treec9663673eba42c9f33c413a909c16a37d7bd2ebb /ui
parent963c1b96abd9baa3ccddb7bc59da8a93e0c2ae93 (diff)
downloadchromium_src-732ef6737ef6e1346255be7230032dcaf4e9ad03.zip
chromium_src-732ef6737ef6e1346255be7230032dcaf4e9ad03.tar.gz
chromium_src-732ef6737ef6e1346255be7230032dcaf4e9ad03.tar.bz2
specify locale-dependent font list for UI on ChromeOS, so that those fonts have higher priority over the fallback fonts Pango picks up.
BUG=103860 TEST=build aura, start chromium in 'ar' locale. type in Arabic and check the Arabic text's shapes. remove IDS_UI_FONT_FAMILY_CROS from 'ar' resource file, build aura again, start chromium in 'ar', type in Arabic and the Arabic text's shapes should be different. Review URL: http://codereview.chromium.org/8770034 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@114953 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui')
-rw-r--r--ui/base/strings/app_locale_settings.grd2
-rw-r--r--ui/base/strings/app_locale_settings_ar.xtb1
-rw-r--r--ui/base/strings/app_locale_settings_hi.xtb1
-rw-r--r--ui/base/strings/app_locale_settings_ja.xtb2
-rw-r--r--ui/base/strings/app_locale_settings_ko.xtb1
-rw-r--r--ui/base/strings/app_locale_settings_th.xtb1
-rw-r--r--ui/base/strings/app_locale_settings_zh-CN.xtb1
-rw-r--r--ui/base/strings/app_locale_settings_zh-TW.xtb1
-rw-r--r--ui/gfx/font_list.cc115
-rw-r--r--ui/gfx/font_list.h79
-rw-r--r--ui/gfx/font_list_unittest.cc208
-rw-r--r--ui/gfx/pango_util.cc44
-rw-r--r--ui/gfx/pango_util.h12
-rw-r--r--ui/gfx/render_text.cc51
-rw-r--r--ui/gfx/render_text.h22
-rw-r--r--ui/gfx/render_text_linux.cc47
-rw-r--r--ui/gfx/render_text_linux.h9
-rw-r--r--ui/gfx/render_text_unittest.cc2
-rw-r--r--ui/gfx/render_text_win.cc5
-rw-r--r--ui/ui.gyp2
-rw-r--r--ui/ui_unittests.gypi1
-rw-r--r--ui/views/controls/textfield/native_textfield_views.cc20
22 files changed, 508 insertions, 119 deletions
diff --git a/ui/base/strings/app_locale_settings.grd b/ui/base/strings/app_locale_settings.grd
index 91156c4..ca451d4 100644
--- a/ui/base/strings/app_locale_settings.grd
+++ b/ui/base/strings/app_locale_settings.grd
@@ -192,7 +192,7 @@
<if expr="pp_ifdef('chromeos')">
<!-- The font name like: 'Font Name, 10' -->
<message name="IDS_UI_FONT_FAMILY_CROS" use_name_for_id="true">
- default
+ Chrome Droid Sans,Droid Sans Fallback,sans-serif, 9
</message>
</if>
</messages>
diff --git a/ui/base/strings/app_locale_settings_ar.xtb b/ui/base/strings/app_locale_settings_ar.xtb
index e1d3faf..3e447d7 100644
--- a/ui/base/strings/app_locale_settings_ar.xtb
+++ b/ui/base/strings/app_locale_settings_ar.xtb
@@ -2,4 +2,5 @@
<!DOCTYPE translationbundle>
<translationbundle lang="ar">
<translation id="IDS_MINIMUM_UI_FONT_SIZE">10</translation>
+<translation id="IDS_UI_FONT_FAMILY_CROS">Chrome Droid Sans,Droid Arabic Kufi,Droid Sans Fallback,sans-serif, 10</translation>
</translationbundle>
diff --git a/ui/base/strings/app_locale_settings_hi.xtb b/ui/base/strings/app_locale_settings_hi.xtb
index 56983d7..e024983 100644
--- a/ui/base/strings/app_locale_settings_hi.xtb
+++ b/ui/base/strings/app_locale_settings_hi.xtb
@@ -4,4 +4,5 @@
<translation id="IDS_UI_FONT_SIZE_SCALER_XP">140</translation>
<translation id="IDS_UI_FONT_SIZE_SCALER">125</translation>
<translation id="IDS_MINIMUM_UI_FONT_SIZE">10</translation>
+<translation id="IDS_UI_FONT_FAMILY_CROS">Chrome Droid Sans,Mangal,Lohit Hindi,Droid Sans Fallback,sans-serif, 10</translation>
</translationbundle>
diff --git a/ui/base/strings/app_locale_settings_ja.xtb b/ui/base/strings/app_locale_settings_ja.xtb
index 933d47d..9010c05 100644
--- a/ui/base/strings/app_locale_settings_ja.xtb
+++ b/ui/base/strings/app_locale_settings_ja.xtb
@@ -2,5 +2,5 @@
<!DOCTYPE translationbundle>
<translationbundle lang="ja">
<translation id="IDS_MINIMUM_UI_FONT_SIZE">10</translation>
-<translation id="IDS_UI_FONT_FAMILY_CROS">IPAPGothic, 10</translation>
+<translation id="IDS_UI_FONT_FAMILY_CROS">Chrome Droid Sans,IPAPGothic,Droid Sans Fallback,sans-serif, 10</translation>
</translationbundle>
diff --git a/ui/base/strings/app_locale_settings_ko.xtb b/ui/base/strings/app_locale_settings_ko.xtb
index 7c4134c..2110024 100644
--- a/ui/base/strings/app_locale_settings_ko.xtb
+++ b/ui/base/strings/app_locale_settings_ko.xtb
@@ -2,4 +2,5 @@
<!DOCTYPE translationbundle>
<translationbundle lang="ko">
<translation id="IDS_MINIMUM_UI_FONT_SIZE">10</translation>
+<translation id="IDS_UI_FONT_FAMILY_CROS">Chrome Droid Sans,NanumGothic,Droid Sans Fallback,sans-serif, 10</translation>
</translationbundle>
diff --git a/ui/base/strings/app_locale_settings_th.xtb b/ui/base/strings/app_locale_settings_th.xtb
index 070c16e..550b08e 100644
--- a/ui/base/strings/app_locale_settings_th.xtb
+++ b/ui/base/strings/app_locale_settings_th.xtb
@@ -2,4 +2,5 @@
<!DOCTYPE translationbundle>
<translationbundle lang="th">
<translation id="IDS_MINIMUM_UI_FONT_SIZE">10</translation>
+<translation id="IDS_UI_FONT_FAMILY_CROS">Chrome Droid Sans,Droid Sans Thai,Droid Sans Fallback,sans-serif, 10</translation>
</translationbundle>
diff --git a/ui/base/strings/app_locale_settings_zh-CN.xtb b/ui/base/strings/app_locale_settings_zh-CN.xtb
index 1034e66..f1d2a57 100644
--- a/ui/base/strings/app_locale_settings_zh-CN.xtb
+++ b/ui/base/strings/app_locale_settings_zh-CN.xtb
@@ -2,4 +2,5 @@
<!DOCTYPE translationbundle>
<translationbundle lang="zh-CN">
<translation id="IDS_MINIMUM_UI_FONT_SIZE">10</translation>
+<translation id="IDS_UI_FONT_FAMILY_CROS">Chrome Droid Sans,Song ASC,Droid Sans Fallback,sans-serif, 10</translation>
</translationbundle>
diff --git a/ui/base/strings/app_locale_settings_zh-TW.xtb b/ui/base/strings/app_locale_settings_zh-TW.xtb
index 8829d71..c7a01c1 100644
--- a/ui/base/strings/app_locale_settings_zh-TW.xtb
+++ b/ui/base/strings/app_locale_settings_zh-TW.xtb
@@ -2,4 +2,5 @@
<!DOCTYPE translationbundle>
<translationbundle lang="zh-TW">
<translation id="IDS_MINIMUM_UI_FONT_SIZE">10</translation>
+<translation id="IDS_UI_FONT_FAMILY_CROS">Chrome Droid Sans,Song ASC,Droid Sans Fallback,sans-serif, 10</translation>
</translationbundle>
diff --git a/ui/gfx/font_list.cc b/ui/gfx/font_list.cc
new file mode 100644
index 0000000..a6c0867
--- /dev/null
+++ b/ui/gfx/font_list.cc
@@ -0,0 +1,115 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <stdlib.h>
+
+#include "base/logging.h"
+#include "base/string_number_conversions.h"
+#include "base/string_split.h"
+#include "ui/gfx/font_list.h"
+
+namespace gfx {
+
+FontList::FontList() {
+ fonts_.push_back(Font());
+}
+
+FontList::FontList(const std::string& font_description_string)
+ : font_description_string_(font_description_string) {
+ DCHECK(!font_description_string.empty());
+}
+
+FontList::FontList(const std::vector<Font>& fonts)
+ : fonts_(fonts) {
+ DCHECK(!fonts.empty());
+ if (DCHECK_IS_ON()) {
+ int style = fonts[0].GetStyle();
+ int size = fonts[0].GetFontSize();
+ for (size_t i = 1; i < fonts.size(); ++i) {
+ DCHECK_EQ(fonts[i].GetStyle(), style);
+ DCHECK_EQ(fonts[i].GetFontSize(), size);
+ }
+ }
+}
+
+FontList::FontList(const Font& font) {
+ fonts_.push_back(font);
+}
+
+FontList::~FontList() {
+}
+
+const std::string& FontList::GetFontDescriptionString() const {
+ if (font_description_string_.empty()) {
+ DCHECK(!fonts_.empty());
+ for (size_t i = 0; i < fonts_.size(); ++i) {
+ std::string name = fonts_[i].GetFontName();
+ font_description_string_ += name;
+ font_description_string_ += ',';
+ }
+ // All fonts have the same style and size.
+ // TODO(xji): add style for Windows.
+#if defined(OS_LINUX)
+ int style = fonts_[0].GetStyle();
+ if (style & Font::BOLD)
+ font_description_string_ += "PANGO_WEIGHT_BOLD ";
+ if (style & Font::ITALIC)
+ font_description_string_ += "PANGO_STYLE_ITALIC ";
+#endif
+ int size = fonts_[0].GetFontSize();
+ font_description_string_ += base::IntToString(size);
+ }
+ return font_description_string_;
+}
+
+const std::vector<Font>& FontList::GetFonts() const {
+ if (fonts_.empty()) {
+ DCHECK(!font_description_string_.empty());
+
+ std::vector<std::string> name_style_size;
+ base::SplitString(font_description_string_, ',', &name_style_size);
+ int item_count = static_cast<int>(name_style_size.size());
+ DCHECK_GT(item_count, 1);
+
+ // The last item is [STYLE_OPTIONS] SIZE.
+ std::vector<std::string> styles_size;
+ base::SplitString(name_style_size[item_count - 1], ' ', &styles_size);
+ int size;
+ DCHECK(!styles_size.empty());
+ base::StringToInt(styles_size[styles_size.size() - 1], &size);
+ DCHECK_GT(size, 0);
+
+ int style = 0;
+ // TODO(xji): parse style for Windows.
+#if defined(OS_LINUX)
+ // Besides underline (which is supported through StyleRange), Font only
+ // supports BOLD and ITALIC styles, not other Pango styles.
+ for (size_t i = 0; i < styles_size.size() - 1; ++i) {
+ // Styles are separated by white spaces. base::SplitString splits styles
+ // by space, and it inserts empty string for continuous spaces.
+ if (styles_size[i].empty())
+ continue;
+ if (!styles_size[i].compare("PANGO_WEIGHT_BOLD"))
+ style |= Font::BOLD;
+ else if (!styles_size[i].compare("PANGO_STYLE_ITALIC"))
+ style |= Font::ITALIC;
+ else
+ NOTREACHED();
+ }
+#endif
+
+ for (int i = 0; i < item_count - 1; ++i) {
+ DCHECK(!name_style_size[i].empty());
+
+ Font font(name_style_size[i], size);
+ if (style == Font::NORMAL)
+ fonts_.push_back(font);
+ else
+ fonts_.push_back(font.DeriveFont(0, style));
+ }
+ }
+ return fonts_;
+}
+
+} // namespace gfx
diff --git a/ui/gfx/font_list.h b/ui/gfx/font_list.h
new file mode 100644
index 0000000..ef6b357
--- /dev/null
+++ b/ui/gfx/font_list.h
@@ -0,0 +1,79 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_GFX_FONT_LIST_H_
+#define UI_GFX_FONT_LIST_H_
+#pragma once
+
+#include <string>
+#include <vector>
+
+#include "base/gtest_prod_util.h"
+#include "ui/base/ui_export.h"
+#include "ui/gfx/font.h"
+
+namespace gfx {
+
+// FontList represents a list of fonts either in the form of Font vector or in
+// the form of a string representing font names, styles, and size.
+//
+// The string representation is in the form "FAMILY_LIST [STYLE_OPTIONS] SIZE",
+// where FAMILY_LIST is a comma separated list of families terminated by a
+// comma, STYLE_OPTIONS is a whitespace separated list of words where each word
+// describes one of style, variant, weight, stretch, or gravity, and SIZE is
+// a decimal number (size in points). STYLE_OPTIONS may be absent.
+//
+// The string format complies with that of Pango detailed at
+// http://developer.gnome.org/pango/stable/pango-Fonts.html#pango-font-description-from-string
+//
+// FontList could be initialized either way without conversion to the other
+// form. The conversion to the other form is done only when asked to get the
+// other form.
+//
+// FontList allows operator= since FontList is a data member type in RenderText,
+// and operator= is used in RenderText::SetFontList().
+class UI_EXPORT FontList {
+ public:
+ // Creates a font list with a Font with default name and style.
+ FontList();
+
+ // Creates a font list from a string representing font names, styles, and
+ // size.
+ explicit FontList(const std::string& font_description_string);
+
+ // Creates a font list from a Font vector.
+ // All fonts in this vector should have the same style and size.
+ explicit FontList(const std::vector<Font>& fonts);
+
+ // Creates a font list from a Font.
+ explicit FontList(const Font& font);
+
+ ~FontList();
+
+ // Returns a string representing font names, styles, and size. If the FontList
+ // is initialized by a vector of Font, use the first font's style and size
+ // for the description.
+ const std::string& GetFontDescriptionString() const;
+
+ // Returns the Font vector.
+ const std::vector<Font>& GetFonts() const;
+
+ private:
+ // A vector of Font. If FontList is constructed with font description string,
+ // |fonts_| is not initialized during construction. Instead, it is computed
+ // lazily when user asked to get the font vector.
+ mutable std::vector<Font> fonts_;
+
+ // A string representing font names, styles, and sizes.
+ // Please refer to the comments before class declaration for details on string
+ // format.
+ // If FontList is constructed with a vector of font,
+ // |font_description_string_| is not initialized during construction. Instead,
+ // it is computed lazily when user asked to get the font description string.
+ mutable std::string font_description_string_;
+};
+
+} // namespace gfx
+
+#endif // UI_GFX_FONT_LIST_H_
diff --git a/ui/gfx/font_list_unittest.cc b/ui/gfx/font_list_unittest.cc
new file mode 100644
index 0000000..a9b02fb
--- /dev/null
+++ b/ui/gfx/font_list_unittest.cc
@@ -0,0 +1,208 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/gfx/font_list.h"
+
+#include <string>
+#include <vector>
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace gfx {
+
+typedef testing::Test FontListTest;
+
+TEST_F(FontListTest, FontDescString_FromDescString) {
+ // Test init from font name style size string.
+ FontList font_list = FontList("Droid Sans serif, Sans serif, 10");
+ const std::string& font_str = font_list.GetFontDescriptionString();
+ EXPECT_EQ("Droid Sans serif, Sans serif, 10", font_str);
+}
+
+TEST_F(FontListTest, FontDescString_FromFont) {
+ // Test init from Font.
+ Font font("Arial", 8);
+ FontList font_list = FontList(font);
+ const std::string& font_str = font_list.GetFontDescriptionString();
+ EXPECT_EQ("Arial,8", font_str);
+}
+
+TEST_F(FontListTest, FontDescString_FromFontWithNonNormalStyle) {
+ // Test init from Font with non-normal style.
+ Font font("Arial", 8);
+ FontList font_list = FontList(font.DeriveFont(2, Font::BOLD));
+ const std::string& font_str = font_list.GetFontDescriptionString();
+#if defined(OS_LINUX)
+ EXPECT_EQ("Arial,PANGO_WEIGHT_BOLD 10", font_str);
+#else
+ EXPECT_EQ("Arial,10", font_str);
+#endif
+
+ font_list = FontList(font.DeriveFont(-2, Font::ITALIC));
+ const std::string& font_str_1 = font_list.GetFontDescriptionString();
+#if defined(OS_LINUX)
+ EXPECT_EQ("Arial,PANGO_STYLE_ITALIC 6", font_str_1);
+#else
+ EXPECT_EQ("Arial,6", font_str_1);
+#endif
+}
+
+TEST_F(FontListTest, FontDescString_FromFontVector) {
+ // Test init from Font vector.
+ Font font("Arial", 8);
+ Font font_1("Sans serif", 10);
+ std::vector<Font> fonts;
+ fonts.push_back(font.DeriveFont(0, Font::BOLD));
+ fonts.push_back(font_1.DeriveFont(-2, Font::BOLD));
+ FontList font_list = FontList(fonts);
+ const std::string& font_str = font_list.GetFontDescriptionString();
+#if defined(OS_LINUX)
+ EXPECT_EQ("Arial,Sans serif,PANGO_WEIGHT_BOLD 8", font_str);
+#else
+ EXPECT_EQ("Arial,Sans serif,8", font_str);
+#endif
+}
+
+TEST_F(FontListTest, Fonts_FromDescString) {
+ // Test init from font name size string.
+ FontList font_list = FontList("serif,Sans serif, 10");
+ const std::vector<Font>& fonts = font_list.GetFonts();
+ EXPECT_EQ(2U, fonts.size());
+ EXPECT_EQ("serif", fonts[0].GetFontName());
+ EXPECT_EQ(10, fonts[0].GetFontSize());
+ EXPECT_EQ(Font::NORMAL, fonts[0].GetStyle());
+ EXPECT_EQ("Sans serif", fonts[1].GetFontName());
+ EXPECT_EQ(10, fonts[1].GetFontSize());
+ EXPECT_EQ(Font::NORMAL, fonts[1].GetStyle());
+}
+
+TEST_F(FontListTest, Fonts_FromDescStringInFlexibleFormat) {
+ // Test init from font name size string with flexible format.
+ FontList font_list = FontList(" serif , Sans serif , 10 ");
+ const std::vector<Font>& fonts = font_list.GetFonts();
+ EXPECT_EQ(2U, fonts.size());
+ EXPECT_EQ("serif", fonts[0].GetFontName());
+ EXPECT_EQ(10, fonts[0].GetFontSize());
+ EXPECT_EQ(Font::NORMAL, fonts[0].GetStyle());
+ EXPECT_EQ("Sans serif", fonts[1].GetFontName());
+ EXPECT_EQ(10, fonts[1].GetFontSize());
+ EXPECT_EQ(Font::NORMAL, fonts[1].GetStyle());
+}
+
+TEST_F(FontListTest, Fonts_FromDescStringWithStyleInFlexibleFormat) {
+ // Test init from font name style size string with flexible format.
+ FontList font_list = FontList(" serif , Sans serif , PANGO_WEIGHT_BOLD "
+ " PANGO_STYLE_ITALIC 10 ");
+ const std::vector<Font>& fonts = font_list.GetFonts();
+ EXPECT_EQ(2U, fonts.size());
+ EXPECT_EQ("serif", fonts[0].GetFontName());
+ EXPECT_EQ(10, fonts[0].GetFontSize());
+#if defined(OS_LINUX)
+ EXPECT_EQ(Font::BOLD | Font::ITALIC, fonts[0].GetStyle());
+#else
+ EXPECT_EQ(Font::NORMAL, fonts[0].GetStyle());
+#endif
+ EXPECT_EQ("Sans serif", fonts[1].GetFontName());
+ EXPECT_EQ(10, fonts[1].GetFontSize());
+#if defined(OS_LINUX)
+ EXPECT_EQ(Font::BOLD | Font::ITALIC, fonts[1].GetStyle());
+#else
+ EXPECT_EQ(Font::NORMAL, fonts[1].GetStyle());
+#endif
+}
+
+TEST_F(FontListTest, Fonts_FromFont) {
+ // Test init from Font.
+ Font font("Arial", 8);
+ FontList font_list = FontList(font);
+ const std::vector<Font>& fonts = font_list.GetFonts();
+ EXPECT_EQ(1U, fonts.size());
+ EXPECT_EQ("Arial", fonts[0].GetFontName());
+ EXPECT_EQ(8, fonts[0].GetFontSize());
+ EXPECT_EQ(Font::NORMAL, fonts[0].GetStyle());
+}
+
+TEST_F(FontListTest, Fonts_FromFontWithNonNormalStyle) {
+ // Test init from Font with non-normal style.
+ Font font("Arial", 8);
+ FontList font_list = FontList(font.DeriveFont(2, Font::BOLD));
+ const std::vector<Font>& fonts = font_list.GetFonts();
+ EXPECT_EQ(1U, fonts.size());
+ EXPECT_EQ("Arial", fonts[0].GetFontName());
+ EXPECT_EQ(10, fonts[0].GetFontSize());
+ EXPECT_EQ(Font::BOLD, fonts[0].GetStyle());
+
+ font_list = FontList(font.DeriveFont(-2, Font::ITALIC));
+ const std::vector<Font>& fonts_1 = font_list.GetFonts();
+ EXPECT_EQ(1U, fonts_1.size());
+ EXPECT_EQ("Arial", fonts_1[0].GetFontName());
+ EXPECT_EQ(6, fonts_1[0].GetFontSize());
+ EXPECT_EQ(Font::ITALIC, fonts_1[0].GetStyle());
+}
+
+TEST_F(FontListTest, Fonts_FromFontVector) {
+ // Test init from Font vector.
+ Font font("Arial", 8);
+ Font font_1("Sans serif", 10);
+ std::vector<Font> input_fonts;
+ input_fonts.push_back(font.DeriveFont(0, Font::BOLD));
+ input_fonts.push_back(font_1.DeriveFont(-2, Font::BOLD));
+ FontList font_list = FontList(input_fonts);
+ const std::vector<Font>& fonts = font_list.GetFonts();
+ EXPECT_EQ(2U, fonts.size());
+ EXPECT_EQ("Arial", fonts[0].GetFontName());
+ EXPECT_EQ(8, fonts[0].GetFontSize());
+ EXPECT_EQ(Font::BOLD, fonts[0].GetStyle());
+ EXPECT_EQ("Sans serif", fonts[1].GetFontName());
+ EXPECT_EQ(8, fonts[1].GetFontSize());
+ EXPECT_EQ(Font::BOLD, fonts[1].GetStyle());
+}
+
+TEST_F(FontListTest, Fonts_DescStringWithStyleInFlexibleFormat_RoundTrip) {
+ // Test round trip from font description string to font vector to
+ // font description string.
+ FontList font_list = FontList(" serif , Sans serif , PANGO_WEIGHT_BOLD "
+ " PANGO_STYLE_ITALIC 10 ");
+
+ const std::vector<Font>& fonts = font_list.GetFonts();
+ FontList font_list_1 = FontList(fonts);
+ const std::string& desc_str = font_list_1.GetFontDescriptionString();
+
+#if defined(OS_LINUX)
+ EXPECT_EQ("serif,Sans serif,PANGO_WEIGHT_BOLD PANGO_STYLE_ITALIC 10",
+ desc_str);
+#else
+ EXPECT_EQ("serif,Sans serif,10", desc_str);
+#endif
+}
+
+TEST_F(FontListTest, Fonts_FontVector_RoundTrip) {
+ // Test round trip from font vector to font description string to font vector.
+ Font font("Arial", 8);
+ Font font_1("Sans serif", 10);
+ std::vector<Font> input_fonts;
+ input_fonts.push_back(font.DeriveFont(0, Font::BOLD));
+ input_fonts.push_back(font_1.DeriveFont(-2, Font::BOLD));
+ FontList font_list = FontList(input_fonts);
+
+ const std::string& desc_string = font_list.GetFontDescriptionString();
+ FontList font_list_1 = FontList(desc_string);
+ const std::vector<Font>& round_trip_fonts = font_list_1.GetFonts();
+
+ EXPECT_EQ(2U, round_trip_fonts.size());
+ EXPECT_EQ("Arial", round_trip_fonts[0].GetFontName());
+ EXPECT_EQ(8, round_trip_fonts[0].GetFontSize());
+ EXPECT_EQ("Sans serif", round_trip_fonts[1].GetFontName());
+ EXPECT_EQ(8, round_trip_fonts[1].GetFontSize());
+#if defined(OS_LINUX)
+ EXPECT_EQ(Font::BOLD, round_trip_fonts[0].GetStyle());
+ EXPECT_EQ(Font::BOLD, round_trip_fonts[1].GetStyle());
+#else
+ // Style is ignored.
+ EXPECT_EQ(Font::NORMAL, round_trip_fonts[0].GetStyle());
+ EXPECT_EQ(Font::NORMAL, round_trip_fonts[1].GetStyle());
+#endif
+}
+
+} // namespace gfx
diff --git a/ui/gfx/pango_util.cc b/ui/gfx/pango_util.cc
index 55e4374..1c7e9e4 100644
--- a/ui/gfx/pango_util.cc
+++ b/ui/gfx/pango_util.cc
@@ -169,12 +169,12 @@ void DrawTextOntoCairoSurface(cairo_t* cr,
}
// Pass a width greater than 0 to force wrapping and eliding.
-void SetupPangoLayout(PangoLayout* layout,
- const string16& text,
- const Font& font,
- int width,
- base::i18n::TextDirection text_direction,
- int flags) {
+static void SetupPangoLayoutWithoutFont(
+ PangoLayout* layout,
+ const string16& text,
+ int width,
+ base::i18n::TextDirection text_direction,
+ int flags) {
cairo_font_options_t* cairo_font_options = GetCairoFontOptions();
// This needs to be done early on; it has no effect when called just before
// pango_cairo_show_layout().
@@ -221,10 +221,6 @@ void SetupPangoLayout(PangoLayout* layout,
resolution);
}
- PangoFontDescription* desc = font.GetNativeFont();
- pango_layout_set_font_description(layout, desc);
- pango_font_description_free(desc);
-
// Set text and accelerator character if needed.
if (flags & Canvas::SHOW_PREFIX) {
// Escape the text string to be used as markup.
@@ -254,6 +250,34 @@ void SetupPangoLayout(PangoLayout* layout,
}
}
+void SetupPangoLayout(PangoLayout* layout,
+ const string16& text,
+ const Font& font,
+ int width,
+ base::i18n::TextDirection text_direction,
+ int flags) {
+ SetupPangoLayoutWithoutFont(layout, text, width, text_direction, flags);
+
+ PangoFontDescription* desc = font.GetNativeFont();
+ pango_layout_set_font_description(layout, desc);
+ pango_font_description_free(desc);
+}
+
+void SetupPangoLayoutWithFontDescription(
+ PangoLayout* layout,
+ const string16& text,
+ const std::string& font_description,
+ int width,
+ base::i18n::TextDirection text_direction,
+ int flags) {
+ SetupPangoLayoutWithoutFont(layout, text, width, text_direction, flags);
+
+ PangoFontDescription* desc = pango_font_description_from_string(
+ font_description.c_str());
+ pango_layout_set_font_description(layout, desc);
+ pango_font_description_free(desc);
+}
+
void AdjustTextRectBasedOnLayout(PangoLayout* layout,
const gfx::Rect& bounds,
int flags,
diff --git a/ui/gfx/pango_util.h b/ui/gfx/pango_util.h
index 903e6df..93b9bf2 100644
--- a/ui/gfx/pango_util.h
+++ b/ui/gfx/pango_util.h
@@ -8,6 +8,7 @@
#include <cairo/cairo.h>
#include <pango/pango.h>
+#include <string>
#include "base/i18n/rtl.h"
#include "base/string16.h"
@@ -47,6 +48,17 @@ void SetupPangoLayout(PangoLayout* layout,
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|.
+void SetupPangoLayoutWithFontDescription(
+ PangoLayout* layout,
+ const string16& text,
+ const std::string& font_description,
+ int width,
+ base::i18n::TextDirection text_direction,
+ int flags);
+
// Get Pango's calculated size of |layout| and modify |text_rect| within
// |bounds|.
void AdjustTextRectBasedOnLayout(PangoLayout* layout,
diff --git a/ui/gfx/render_text.cc b/ui/gfx/render_text.cc
index 657dd1a..017ae73 100644
--- a/ui/gfx/render_text.cc
+++ b/ui/gfx/render_text.cc
@@ -163,11 +163,9 @@ void SkiaTextRenderer::DrawDecorations(int x, int y, int width,
StyleRange::StyleRange()
- : font(),
- foreground(SK_ColorBLACK),
+ : foreground(SK_ColorBLACK),
strike(false),
- underline(false),
- range() {
+ underline(false) {
}
RenderText::~RenderText() {
@@ -211,6 +209,16 @@ void RenderText::SetText(const string16& text) {
UpdateLayout();
}
+void RenderText::SetFontList(const FontList& font_list) {
+ font_list_ = font_list;
+ cached_bounds_and_offset_valid_ = false;
+ UpdateLayout();
+}
+
+const Font& RenderText::GetFont() const {
+ return font_list_.GetFonts()[0];
+}
+
void RenderText::ToggleInsertMode() {
insert_mode_ = !insert_mode_;
cached_bounds_and_offset_valid_ = false;
@@ -425,10 +433,6 @@ base::i18n::TextDirection RenderText::GetTextDirection() {
return base::i18n::LEFT_TO_RIGHT;
}
-int RenderText::GetStringWidth() {
- return default_style_.font.GetStringWidth(text());
-}
-
void RenderText::Draw(Canvas* canvas) {
TRACE_EVENT0("gfx", "RenderText::Draw");
{
@@ -444,35 +448,6 @@ void RenderText::Draw(Canvas* canvas) {
DrawCursor(canvas);
}
-SelectionModel RenderText::FindCursorPosition(const Point& point) {
- const Font& font = default_style_.font;
- int left = 0;
- int left_pos = 0;
- int right = font.GetStringWidth(text());
- int right_pos = text().length();
-
- int x = point.x() - (display_rect_.x() + GetUpdatedDisplayOffset().x());
- if (x <= left) return SelectionModel(left_pos);
- if (x >= right) return SelectionModel(right_pos);
- // binary searching the cursor position.
- // TODO(oshima): use the center of character instead of edge.
- // Binary search may not work for language like Arabic.
- while (std::abs(right_pos - left_pos) > 1) {
- int pivot_pos = left_pos + (right_pos - left_pos) / 2;
- int pivot = font.GetStringWidth(text().substr(0, pivot_pos));
- if (pivot < x) {
- left = pivot;
- left_pos = pivot_pos;
- } else if (pivot == x) {
- return SelectionModel(pivot_pos);
- } else {
- right = pivot;
- right_pos = pivot_pos;
- }
- }
- return SelectionModel(left_pos);
-}
-
const Rect& RenderText::GetUpdatedCursorBounds() {
UpdateCachedBoundsAndOffset();
return cursor_bounds_;
@@ -645,7 +620,7 @@ Point RenderText::ToViewPoint(const Point& point) {
Point RenderText::GetOriginForSkiaDrawing() {
Point origin(ToViewPoint(Point()));
// TODO(msw): Establish a vertical baseline for strings of mixed font heights.
- const Font& font = default_style().font;
+ const Font& font = GetFont();
size_t height = font.GetHeight();
// Center the text vertically in the display area.
origin.Offset(0, (display_rect().height() - height) / 2);
diff --git a/ui/gfx/render_text.h b/ui/gfx/render_text.h
index 4329a2c..9f13be4 100644
--- a/ui/gfx/render_text.h
+++ b/ui/gfx/render_text.h
@@ -15,7 +15,7 @@
#include "third_party/skia/include/core/SkColor.h"
#include "third_party/skia/include/core/SkPaint.h"
#include "ui/base/range/range.h"
-#include "ui/gfx/font.h"
+#include "ui/gfx/font_list.h"
#include "ui/gfx/point.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/selection_model.h"
@@ -70,7 +70,11 @@ const SkColor kCursorColor = SK_ColorBLACK;
struct UI_EXPORT StyleRange {
StyleRange();
- Font font;
+ // TODO(asvitkine): Add RenderText support for font weight. Add a |bold| style
+ // flag here, to be handled in RenderText's layout phase. For example, in
+ // RenderTextLinux, generate the new font description with font weight style
+ // option, create a Pango attribute from it, and append the attribute to
+ // layout.
SkColor foreground;
bool strike;
bool underline;
@@ -105,6 +109,11 @@ class UI_EXPORT RenderText {
const string16& text() const { return text_; }
void SetText(const string16& text);
+ const FontList& font_list() const { return font_list_; }
+ void SetFontList(const FontList& font_list);
+ // Get the first font in |font_list_|.
+ const Font& GetFont() const;
+
const SelectionModel& selection_model() const { return selection_model_; }
bool cursor_visible() const { return cursor_visible_; }
@@ -188,12 +197,12 @@ class UI_EXPORT RenderText {
virtual base::i18n::TextDirection GetTextDirection();
// Get the width of the entire string.
- virtual int GetStringWidth();
+ virtual int GetStringWidth() = 0;
- virtual void Draw(Canvas* canvas);
+ void Draw(Canvas* canvas);
// Gets the SelectionModel from a visual point in local coordinates.
- virtual SelectionModel FindCursorPosition(const Point& point);
+ 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
@@ -318,6 +327,9 @@ class UI_EXPORT RenderText {
// Logical UTF-16 string data to be drawn.
string16 text_;
+ // A list of fonts used to render |text_|.
+ FontList font_list_;
+
// Logical selection range and visual cursor position.
SelectionModel selection_model_;
diff --git a/ui/gfx/render_text_linux.cc b/ui/gfx/render_text_linux.cc
index 3aab7f8..9a17ab4 100644
--- a/ui/gfx/render_text_linux.cc
+++ b/ui/gfx/render_text_linux.cc
@@ -6,6 +6,7 @@
#include <pango/pangocairo.h>
#include <algorithm>
+#include <string>
#include <vector>
#include "base/debug/trace_event.h"
@@ -242,10 +243,10 @@ void RenderTextLinux::EnsureLayout() {
cairo_t* cr = scoped_platform_paint.GetPlatformSurface();
layout_ = pango_cairo_create_layout(cr);
- SetupPangoLayout(
+ SetupPangoLayoutWithFontDescription(
layout_,
text(),
- default_style().font,
+ font_list().GetFontDescriptionString(),
display_rect().width(),
base::i18n::GetFirstStrongCharacterDirection(text()),
CanvasSkia::DefaultCanvasTextAlignment());
@@ -257,7 +258,6 @@ void RenderTextLinux::EnsureLayout() {
// TODO(xji): If RenderText will be used for displaying purpose, such as
// label, we will need to remove the single-line-mode setting.
pango_layout_set_single_paragraph_mode(layout_, true);
- SetupPangoAttributes(layout_);
current_line_ = pango_layout_get_line_readonly(layout_, 0);
pango_layout_line_ref(current_line_);
@@ -648,47 +648,6 @@ void RenderTextLinux::ResetLayout() {
layout_text_len_ = 0;
}
-void RenderTextLinux::SetupPangoAttributes(PangoLayout* layout) {
- PangoAttrList* attrs = pango_attr_list_new();
-
- PlatformFont* default_platform_font = default_style().font.platform_font();
-
- PangoAttribute* pango_attr;
- for (StyleRanges::const_iterator i = style_ranges().begin();
- i < style_ranges().end(); ++i) {
- size_t start = std::min(i->range.start(), text().length());
- size_t end = std::min(i->range.end(), text().length());
- if (start >= end)
- continue;
-
- const Font& font = i->font;
- // In Pango, different fonts means different runs, and it breaks Arabic
- // shaping acorss run boundaries. So, set font only when it is different
- // from the default font.
- // TODO(xji): we'll eventually need to split up StyleRange into components
- // (ColorRange, FontRange, etc.) so that we can combine adjacent ranges
- // with the same Fonts (to avoid unnecessarily splitting up runs)
- if (font.platform_font() != default_platform_font) {
- PangoFontDescription* desc = font.GetNativeFont();
- pango_attr = pango_attr_font_desc_new(desc);
- AppendPangoAttribute(start, end, pango_attr, attrs);
- pango_font_description_free(desc);
- }
- }
-
- pango_layout_set_attributes(layout, attrs);
- pango_attr_list_unref(attrs);
-}
-
-void RenderTextLinux::AppendPangoAttribute(size_t start,
- size_t end,
- PangoAttribute* pango_attr,
- PangoAttrList* attrs) {
- pango_attr->start_index = Utf16IndexToUtf8Index(start);
- pango_attr->end_index = Utf16IndexToUtf8Index(end);
- pango_attr_list_insert(attrs, pango_attr);
-}
-
// TODO(xji): Keep a vector of runs to avoid using a singly-linked list.
PangoLayoutRun* RenderTextLinux::GetPreviousRun(PangoLayoutRun* run) const {
GSList* current = current_line_->runs;
diff --git a/ui/gfx/render_text_linux.h b/ui/gfx/render_text_linux.h
index 462494d..bbb6052 100644
--- a/ui/gfx/render_text_linux.h
+++ b/ui/gfx/render_text_linux.h
@@ -78,15 +78,6 @@ class RenderTextLinux : public RenderText {
// Unref |layout_| and |pango_line_|. Set them to NULL.
void ResetLayout();
- // Setup pango attribute: foreground, background, font, strike.
- void SetupPangoAttributes(PangoLayout* layout);
-
- // Append one pango attribute |pango_attr| into pango attribute list |attrs|.
- void AppendPangoAttribute(size_t start,
- size_t end,
- PangoAttribute* pango_attr,
- PangoAttrList* attrs);
-
// Returns |run|'s visually previous run.
// The complexity is O(n) since it is a single-linked list.
PangoLayoutRun* GetPreviousRun(PangoLayoutRun* run) const;
diff --git a/ui/gfx/render_text_unittest.cc b/ui/gfx/render_text_unittest.cc
index 0aa6625..2c60d90 100644
--- a/ui/gfx/render_text_unittest.cc
+++ b/ui/gfx/render_text_unittest.cc
@@ -27,8 +27,6 @@ TEST_F(RenderTextTest, DefaultStyle) {
render_text->SetText(ASCIIToUTF16("abc"));
EXPECT_EQ(1U, render_text->style_ranges().size());
StyleRange style;
- EXPECT_EQ(style.font.GetFontName(),
- render_text->style_ranges()[0].font.GetFontName());
EXPECT_EQ(style.foreground, render_text->style_ranges()[0].foreground);
EXPECT_EQ(ui::Range(0, 3), render_text->style_ranges()[0].range);
EXPECT_EQ(style.strike, render_text->style_ranges()[0].strike);
diff --git a/ui/gfx/render_text_win.cc b/ui/gfx/render_text_win.cc
index 1086c65..5a76179 100644
--- a/ui/gfx/render_text_win.cc
+++ b/ui/gfx/render_text_win.cc
@@ -202,7 +202,7 @@ Rect RenderTextWin::GetCursorBounds(const SelectionModel& selection,
DCHECK(SUCCEEDED(hr));
}
// TODO(msw): Use the last visual run's font instead of the default font?
- int height = run ? run->font.GetHeight() : default_style().font.GetHeight();
+ int height = run ? run->font.GetHeight() : GetFont().GetHeight();
Rect rect(std::min(start_x, end_x), 0, std::abs(end_x - start_x), height);
// Offset to the run start or the right/left end for an out of bounds index.
// Also center the rect vertically in the display area.
@@ -508,7 +508,7 @@ void RenderTextWin::ItemizeLogicalText() {
for (int run_break = 0; run_break < text_length;) {
internal::TextRun* run = new internal::TextRun();
run->range.set_start(run_break);
- run->font = style->font;
+ run->font = GetFont();
run->foreground = style->foreground;
run->strike = style->strike;
run->underline = style->underline;
@@ -577,6 +577,7 @@ void RenderTextWin::LayoutVisualText() {
}
// The run's font doesn't contain the required glyphs, use an alternate.
+ // TODO(msw): support RenderText's font_list().
if (ChooseFallbackFont(hdc, run->font, run_text, run_length,
&run->font)) {
ScriptFreeCache(&run->script_cache);
diff --git a/ui/ui.gyp b/ui/ui.gyp
index c72ccfb..b301786 100644
--- a/ui/ui.gyp
+++ b/ui/ui.gyp
@@ -266,6 +266,8 @@
'gfx/favicon_size.h',
'gfx/font.h',
'gfx/font.cc',
+ 'gfx/font_list.h',
+ 'gfx/font_list.cc',
'gfx/gfx_paths.cc',
'gfx/gfx_paths.h',
'gfx/image/image.cc',
diff --git a/ui/ui_unittests.gypi b/ui/ui_unittests.gypi
index 7b1ec9f..359dc89 100644
--- a/ui/ui_unittests.gypi
+++ b/ui/ui_unittests.gypi
@@ -73,6 +73,7 @@
'gfx/color_analysis_unittest.cc',
'gfx/color_utils_unittest.cc',
'gfx/font_unittest.cc',
+ 'gfx/font_list_unittest.cc',
'gfx/image/image_mac_unittest.mm',
'gfx/image/image_unittest.cc',
'gfx/image/image_unittest_util.h',
diff --git a/ui/views/controls/textfield/native_textfield_views.cc b/ui/views/controls/textfield/native_textfield_views.cc
index 677c458..f5089d7 100644
--- a/ui/views/controls/textfield/native_textfield_views.cc
+++ b/ui/views/controls/textfield/native_textfield_views.cc
@@ -12,9 +12,11 @@
#include "base/logging.h"
#include "base/message_loop.h"
#include "base/utf_string_conversions.h"
+#include "grit/app_locale_settings.h"
#include "grit/ui_strings.h"
#include "ui/base/clipboard/clipboard.h"
#include "ui/base/dragdrop/drag_drop_types.h"
+#include "ui/base/l10n/l10n_util.h"
#include "ui/base/range/range.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/insets.h"
@@ -77,9 +79,14 @@ NativeTextfieldViews::NativeTextfieldViews(Textfield* parent)
// Lowercase is not supported.
DCHECK_NE(parent->style(), Textfield::STYLE_LOWERCASE);
+#if defined(OS_CHROMEOS)
+ GetRenderText()->SetFontList(gfx::FontList(l10n_util::GetStringUTF8(
+ IDS_UI_FONT_FAMILY_CROS)));
+#else
+ GetRenderText()->SetFontList(gfx::FontList(textfield_->font()));
+#endif
// Set the default text style.
gfx::StyleRange default_style;
- default_style.font = textfield_->font();
default_style.foreground = textfield_->text_color();
GetRenderText()->set_default_style(default_style);
GetRenderText()->ApplyDefaultStyle();
@@ -390,13 +397,12 @@ void NativeTextfieldViews::UpdateReadOnly() {
}
void NativeTextfieldViews::UpdateFont() {
- // Update the default text style.
- gfx::StyleRange default_style(GetRenderText()->default_style());
- default_style.font = textfield_->font();
- GetRenderText()->set_default_style(default_style);
- GetRenderText()->ApplyDefaultStyle();
-
+#if !defined(OS_CHROMEOS)
+ // For ChromeOS, we support a font list per locale, UpdateFont() should not
+ // take any effect.
+ GetRenderText()->SetFontList(gfx::FontList(textfield_->font()));
OnCaretBoundsChanged();
+#endif
}
void NativeTextfieldViews::UpdateIsPassword() {