diff options
-rw-r--r-- | ui/gfx/platform_font_win.h | 4 | ||||
-rw-r--r-- | ui/gfx/render_text_harfbuzz.cc | 43 | ||||
-rw-r--r-- | ui/gfx/render_text_harfbuzz.h | 1 | ||||
-rw-r--r-- | ui/gfx/render_text_unittest.cc | 21 | ||||
-rw-r--r-- | ui/gfx/render_text_win.cc | 29 |
5 files changed, 75 insertions, 23 deletions
diff --git a/ui/gfx/platform_font_win.h b/ui/gfx/platform_font_win.h index 90160aa..4fe835b 100644 --- a/ui/gfx/platform_font_win.h +++ b/ui/gfx/platform_font_win.h @@ -8,6 +8,7 @@ #include <string> #include "base/compiler_specific.h" +#include "base/gtest_prod_util.h" #include "base/memory/ref_counted.h" #include "ui/gfx/gfx_export.h" #include "ui/gfx/platform_font.h" @@ -67,6 +68,8 @@ class GFX_EXPORT PlatformFontWin : public PlatformFont { virtual NativeFont GetNativeFont() const override; private: + FRIEND_TEST_ALL_PREFIXES(RenderTextTest, HarfBuzz_UniscribeFallback); + virtual ~PlatformFontWin() {} // Chrome text drawing bottoms out in the Windows GDI functions that take an @@ -105,6 +108,7 @@ class GFX_EXPORT PlatformFontWin : public PlatformFont { private: friend class base::RefCounted<HFontRef>; + FRIEND_TEST_ALL_PREFIXES(RenderTextTest, HarfBuzz_UniscribeFallback); ~HFontRef(); diff --git a/ui/gfx/render_text_harfbuzz.cc b/ui/gfx/render_text_harfbuzz.cc index 642c76e..1aba788 100644 --- a/ui/gfx/render_text_harfbuzz.cc +++ b/ui/gfx/render_text_harfbuzz.cc @@ -1091,6 +1091,7 @@ bool RenderTextHarfBuzz::CompareFamily( void RenderTextHarfBuzz::ShapeRun(internal::TextRunHarfBuzz* run) { const Font& primary_font = font_list().GetPrimaryFont(); + const std::string primary_family = primary_font.GetFontName(); run->font_size = primary_font.GetFontSize(); std::string best_family; @@ -1105,26 +1106,46 @@ void RenderTextHarfBuzz::ShapeRun(internal::TextRunHarfBuzz* run) { #if defined(OS_WIN) Font uniscribe_font; + std::string uniscribe_family; const base::char16* run_text = &(GetLayoutText()[run->range.start()]); if (GetUniscribeFallbackFont(primary_font, run_text, run->range.length(), - &uniscribe_font) && - CompareFamily(run, uniscribe_font.GetFontName(), - uniscribe_font.GetFontRenderParams(), - &best_family, &best_render_params, &best_missing_glyphs)) - return; + &uniscribe_font)) { + uniscribe_family = uniscribe_font.GetFontName(); + if (CompareFamily(run, uniscribe_family, + uniscribe_font.GetFontRenderParams(), + &best_family, &best_render_params, &best_missing_glyphs)) + return; + } #endif - // Skip the first fallback font, which is |primary_font|. std::vector<std::string> fallback_families = - GetFallbackFontFamilies(primary_font.GetFontName()); - for (size_t i = 1; i < fallback_families.size(); ++i) { + GetFallbackFontFamilies(primary_family); + +#if defined(OS_WIN) + // Append fonts in the fallback list of the Uniscribe font. + if (!uniscribe_family.empty()) { + std::vector<std::string> uniscribe_fallbacks = + GetFallbackFontFamilies(uniscribe_family); + fallback_families.insert(fallback_families.end(), + uniscribe_fallbacks.begin(), uniscribe_fallbacks.end()); + } +#endif + + // Try shaping with the fallback fonts. + for (auto family : fallback_families) { + if (family == primary_family) + continue; +#if defined(OS_WIN) + if (family == uniscribe_family) + continue; +#endif FontRenderParamsQuery query(false); - query.families.push_back(fallback_families[i]); + query.families.push_back(family); query.pixel_size = run->font_size; query.style = run->font_style; FontRenderParams fallback_render_params = GetFontRenderParams(query, NULL); - if (CompareFamily(run, fallback_families[i], fallback_render_params, - &best_family, &best_render_params, &best_missing_glyphs)) + if (CompareFamily(run, family, fallback_render_params, &best_family, + &best_render_params, &best_missing_glyphs)) return; } diff --git a/ui/gfx/render_text_harfbuzz.h b/ui/gfx/render_text_harfbuzz.h index 68da3e8..e71d50e 100644 --- a/ui/gfx/render_text_harfbuzz.h +++ b/ui/gfx/render_text_harfbuzz.h @@ -111,6 +111,7 @@ class GFX_EXPORT RenderTextHarfBuzz : public RenderText { FRIEND_TEST_ALL_PREFIXES(RenderTextTest, HarfBuzz_SubglyphGraphemeCases); FRIEND_TEST_ALL_PREFIXES(RenderTextTest, HarfBuzz_SubglyphGraphemePartition); FRIEND_TEST_ALL_PREFIXES(RenderTextTest, HarfBuzz_NonExistentFont); + FRIEND_TEST_ALL_PREFIXES(RenderTextTest, HarfBuzz_UniscribeFallback); // Return the run index that contains the argument; or the length of the // |runs_| vector if argument exceeds the text length or width. diff --git a/ui/gfx/render_text_unittest.cc b/ui/gfx/render_text_unittest.cc index e711581..876c8a8 100644 --- a/ui/gfx/render_text_unittest.cc +++ b/ui/gfx/render_text_unittest.cc @@ -20,6 +20,7 @@ #if defined(OS_WIN) #include "base/win/windows_version.h" +#include "ui/gfx/platform_font_win.h" #include "ui/gfx/render_text_win.h" #endif @@ -30,6 +31,7 @@ using base::ASCIIToUTF16; using base::UTF8ToUTF16; using base::WideToUTF16; +using base::WideToUTF8; namespace gfx { @@ -2352,4 +2354,23 @@ TEST_F(RenderTextTest, FontListFallback) { } #endif // !defined(OS_WIN) +// Ensure that the fallback fonts of the Uniscribe font are tried for shaping. +#if defined(OS_WIN) +TEST_F(RenderTextTest, HarfBuzz_UniscribeFallback) { + RenderTextHarfBuzz render_text; + PlatformFontWin* font_win = new PlatformFontWin("Meiryo", 12); + // Japanese name for Meiryo. This name won't be found in the system's linked + // fonts, forcing RTHB to try the Uniscribe font and its fallbacks. + font_win->font_ref_->font_name_ = WideToUTF8(L"\x30e1\x30a4\x30ea\x30aa"); + FontList font_list((Font(font_win))); + + render_text.SetFontList(font_list); + // Korean character "han". + render_text.SetText(WideToUTF16(L"\xd55c")); + render_text.EnsureLayout(); + ASSERT_EQ(1U, render_text.runs_.size()); + EXPECT_EQ(0U, render_text.runs_[0]->CountMissingGlyphs()); +} +#endif // defined(OS_WIN) + } // namespace gfx diff --git a/ui/gfx/render_text_win.cc b/ui/gfx/render_text_win.cc index f68224b..0ca2957 100644 --- a/ui/gfx/render_text_win.cc +++ b/ui/gfx/render_text_win.cc @@ -1033,8 +1033,10 @@ void RenderTextWin::LayoutTextRun(internal::TextRun* run) { // Try finding a fallback font using a meta file. // TODO(msw|asvitkine): Support RenderText's font_list()? Font uniscribe_font; + bool got_uniscribe_font = false; if (GetUniscribeFallbackFont(original_font, run_text, run_length, &uniscribe_font)) { + got_uniscribe_font = true; current_font = uniscribe_font; missing_count = CountCharsWithMissingGlyphs(run, ShapeTextRunWithFont(run, current_font)); @@ -1066,18 +1068,21 @@ void RenderTextWin::LayoutTextRun(internal::TextRun* run) { } // Try fonts in the fallback list of the Uniscribe font. - fonts = GetFallbackFontFamilies(uniscribe_font.GetFontName()); - for (size_t i = 1; i < fonts.size(); ++i) { - current_font = Font(fonts[i], original_font.GetFontSize()); - missing_count = CountCharsWithMissingGlyphs(run, - ShapeTextRunWithFont(run, current_font)); - if (missing_count == 0) { - successful_substitute_fonts_[original_font.GetFontName()] = current_font; - return; - } - if (missing_count < best_partial_font_missing_char_count) { - best_partial_font_missing_char_count = missing_count; - best_partial_font = current_font; + if (got_uniscribe_font) { + fonts = GetFallbackFontFamilies(uniscribe_font.GetFontName()); + for (size_t i = 1; i < fonts.size(); ++i) { + current_font = Font(fonts[i], original_font.GetFontSize()); + missing_count = CountCharsWithMissingGlyphs(run, + ShapeTextRunWithFont(run, current_font)); + if (missing_count == 0) { + successful_substitute_fonts_[original_font.GetFontName()] = + current_font; + return; + } + if (missing_count < best_partial_font_missing_char_count) { + best_partial_font_missing_char_count = missing_count; + best_partial_font = current_font; + } } } |