summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ui/gfx/render_text_linux.cc4
-rw-r--r--ui/gfx/render_text_mac.cc10
-rw-r--r--ui/gfx/render_text_unittest.cc70
-rw-r--r--ui/gfx/render_text_win.cc7
4 files changed, 87 insertions, 4 deletions
diff --git a/ui/gfx/render_text_linux.cc b/ui/gfx/render_text_linux.cc
index 8700d5d..0bf2686 100644
--- a/ui/gfx/render_text_linux.cc
+++ b/ui/gfx/render_text_linux.cc
@@ -85,6 +85,9 @@ Size RenderTextLinux::GetStringSize() {
pango_layout_get_pixel_size(layout_, &width, &height);
// Keep a consistent height between this particular string's PangoLayout and
// potentially larger text supported by the FontList.
+ // For example, if a text field contains a Japanese character, which is
+ // smaller than Latin ones, and then later a Latin one is inserted, this
+ // ensures that the text baseline does not shift.
return Size(width, std::max(height, font_list().GetHeight()));
}
@@ -92,6 +95,7 @@ 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());
}
diff --git a/ui/gfx/render_text_mac.cc b/ui/gfx/render_text_mac.cc
index f6a1b78..cfc7a51 100644
--- a/ui/gfx/render_text_mac.cc
+++ b/ui/gfx/render_text_mac.cc
@@ -6,6 +6,7 @@
#include <ApplicationServices/ApplicationServices.h>
+#include <algorithm>
#include <cmath>
#include <utility>
@@ -140,6 +141,15 @@ void RenderTextMac::EnsureLayout() {
CGFloat leading = 0;
// TODO(asvitkine): Consider using CTLineGetBoundsWithOptions() on 10.8+.
double width = CTLineGetTypographicBounds(line_, &ascent, &descent, &leading);
+ // Ensure ascent and descent are not smaller than ones of the font list.
+ // Keep them tall enough to draw often-used characters.
+ // For example, if a text field contains a Japanese character, which is
+ // smaller than Latin ones, and then later a Latin one is inserted, this
+ // ensures that the text baseline does not shift.
+ CGFloat font_list_height = font_list().GetHeight();
+ 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(width, ascent + descent + leading);
common_baseline_ = ascent;
}
diff --git a/ui/gfx/render_text_unittest.cc b/ui/gfx/render_text_unittest.cc
index 391f189..7b9f9b6 100644
--- a/ui/gfx/render_text_unittest.cc
+++ b/ui/gfx/render_text_unittest.cc
@@ -4,6 +4,8 @@
#include "ui/gfx/render_text.h"
+#include <algorithm>
+
#include "base/memory/scoped_ptr.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
@@ -1130,19 +1132,69 @@ TEST_F(RenderTextTest, StringSizeSanity) {
// sizes instead of pixel sizes like other implementations.
#if !defined(OS_MACOSX)
TEST_F(RenderTextTest, StringSizeEmptyString) {
- const Font font;
+ // Ascent and descent of Arial and Symbol are different on most platforms.
+ const FontList font_list("Arial,Symbol, 16px");
scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
- render_text->SetFont(font);
+ render_text->SetFontList(font_list);
+ // The empty string respects FontList metrics for non-zero height
+ // and baseline.
render_text->SetText(base::string16());
- EXPECT_EQ(font.GetHeight(), render_text->GetStringSize().height());
+ EXPECT_EQ(font_list.GetHeight(), render_text->GetStringSize().height());
EXPECT_EQ(0, render_text->GetStringSize().width());
+ EXPECT_EQ(font_list.GetBaseline(), render_text->GetBaseline());
render_text->SetText(UTF8ToUTF16(" "));
- EXPECT_EQ(font.GetHeight(), render_text->GetStringSize().height());
+ EXPECT_EQ(font_list.GetHeight(), render_text->GetStringSize().height());
+ EXPECT_EQ(font_list.GetBaseline(), render_text->GetBaseline());
}
#endif // !defined(OS_MACOSX)
+TEST_F(RenderTextTest, StringSizeRespectsFontListMetrics) {
+ // Check that Arial and Symbol have different font metrics.
+ Font arial_font("Arial", 16);
+ Font symbol_font("Symbol", 16);
+ 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.
+ const char* arial_font_text = "a";
+ // "®" (registered trademark symbol) should be rendered with Symbol,
+ // not with Arial.
+ const char* symbol_font_text = "\xC2\xAE";
+
+ Font smaller_font = arial_font;
+ Font larger_font = symbol_font;
+ const char* smaller_font_text = arial_font_text;
+ const char* larger_font_text = symbol_font_text;
+ if (symbol_font.GetHeight() < arial_font.GetHeight() &&
+ symbol_font.GetBaseline() < arial_font.GetBaseline()) {
+ std::swap(smaller_font, larger_font);
+ std::swap(smaller_font_text, larger_font_text);
+ }
+ ASSERT_LT(smaller_font.GetHeight(), larger_font.GetHeight());
+ ASSERT_LT(smaller_font.GetBaseline(), larger_font.GetBaseline());
+
+ // 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);
+ EXPECT_EQ(smaller_font.GetHeight(), render_text->GetStringSize().height());
+ EXPECT_EQ(smaller_font.GetBaseline(), render_text->GetBaseline());
+
+ // Layout the same text with mixed fonts. The text should be rendered with
+ // the smaller font, but the height and baseline are determined with the
+ // metrics of the font list, which is equal to the larger font.
+ std::vector<Font> fonts;
+ fonts.push_back(smaller_font); // The primary font is the smaller font.
+ fonts.push_back(larger_font);
+ const FontList font_list(fonts);
+ render_text->SetFontList(font_list);
+ 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());
+ EXPECT_EQ(font_list.GetBaseline(), render_text->GetBaseline());
+}
+
TEST_F(RenderTextTest, SetFont) {
scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
render_text->SetFont(Font("Arial", 12));
@@ -1150,6 +1202,16 @@ TEST_F(RenderTextTest, SetFont) {
EXPECT_EQ(12, render_text->GetFont().GetFontSize());
}
+TEST_F(RenderTextTest, SetFontList) {
+ scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
+ render_text->SetFontList(FontList("Arial,Symbol, 13px"));
+ const std::vector<Font>& fonts = render_text->font_list().GetFonts();
+ ASSERT_EQ(2U, fonts.size());
+ EXPECT_EQ("Arial", fonts[0].GetFontName());
+ EXPECT_EQ("Symbol", fonts[1].GetFontName());
+ EXPECT_EQ(13, render_text->GetFont().GetFontSize());
+}
+
TEST_F(RenderTextTest, StringSizeBoldWidth) {
scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
render_text->SetText(UTF8ToUTF16("Hello World"));
diff --git a/ui/gfx/render_text_win.cc b/ui/gfx/render_text_win.cc
index 2433dc6..e38d263 100644
--- a/ui/gfx/render_text_win.cc
+++ b/ui/gfx/render_text_win.cc
@@ -534,6 +534,8 @@ void RenderTextWin::DrawVisualText(Canvas* canvas) {
void RenderTextWin::ItemizeLogicalText() {
runs_.clear();
+ // Make |string_size_|'s height and |common_baseline_| tall enough to draw
+ // often-used characters which are rendered with fonts in the font list.
string_size_ = Size(0, font_list().GetHeight());
common_baseline_ = font_list().GetBaseline();
@@ -611,6 +613,11 @@ void RenderTextWin::LayoutVisualText() {
cached_hdc_ = CreateCompatibleDC(NULL);
HRESULT hr = E_FAIL;
+ // Ensure ascent and descent are not smaller than ones of the font list.
+ // Keep them tall enough to draw often-used characters.
+ // For example, if a text field contains a Japanese character, which is
+ // smaller than Latin ones, and then later a Latin one is inserted, this
+ // ensures that the text baseline does not shift.
int ascent = font_list().GetBaseline();
int descent = font_list().GetHeight() - font_list().GetBaseline();
for (size_t i = 0; i < runs_.size(); ++i) {