OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ui/gfx/render_text_harfbuzz.h" | 5 #include "ui/gfx/render_text_harfbuzz.h" |
6 | 6 |
7 #include <limits> | 7 #include <limits> |
8 #include <set> | 8 #include <set> |
9 | 9 |
10 #include "base/i18n/bidi_line_iterator.h" | 10 #include "base/i18n/bidi_line_iterator.h" |
(...skipping 551 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
562 return base::CompareCaseInsensitiveASCII(a.GetFontName(), b.GetFontName()) < | 562 return base::CompareCaseInsensitiveASCII(a.GetFontName(), b.GetFontName()) < |
563 0; | 563 0; |
564 } | 564 } |
565 }; | 565 }; |
566 | 566 |
567 } // namespace | 567 } // namespace |
568 | 568 |
569 namespace internal { | 569 namespace internal { |
570 | 570 |
571 #if !defined(OS_MACOSX) | 571 #if !defined(OS_MACOSX) |
572 sk_sp<SkTypeface> CreateSkiaTypeface(const gfx::Font& font, int style) { | 572 sk_sp<SkTypeface> CreateSkiaTypeface(const Font& font, |
573 int skia_style = SkTypeface::kNormal; | 573 bool italic, |
574 skia_style |= (style & Font::BOLD) ? SkTypeface::kBold : 0; | 574 Font::Weight weight) { |
575 skia_style |= (style & Font::ITALIC) ? SkTypeface::kItalic : 0; | 575 SkFontStyle skia_style( |
576 return sk_sp<SkTypeface>(SkTypeface::CreateFromName( | 576 static_cast<int>(weight), SkFontStyle::kNormal_Width, |
577 font.GetFontName().c_str(), static_cast<SkTypeface::Style>(skia_style))); | 577 italic ? SkFontStyle::kItalic_Slant : SkFontStyle::kUpright_Slant); |
| 578 return sk_sp<SkTypeface>(SkTypeface::MakeFromName( |
| 579 font.GetFontName().c_str(), skia_style)); |
578 } | 580 } |
579 #endif | 581 #endif |
580 | 582 |
581 TextRunHarfBuzz::TextRunHarfBuzz(const gfx::Font& template_font) | 583 TextRunHarfBuzz::TextRunHarfBuzz(const Font& template_font) |
582 : width(0.0f), | 584 : width(0.0f), |
583 preceding_run_widths(0.0f), | 585 preceding_run_widths(0.0f), |
584 is_rtl(false), | 586 is_rtl(false), |
585 level(0), | 587 level(0), |
586 script(USCRIPT_INVALID_CODE), | 588 script(USCRIPT_INVALID_CODE), |
587 glyph_count(static_cast<size_t>(-1)), | 589 glyph_count(static_cast<size_t>(-1)), |
588 font(template_font), | 590 font(template_font), |
589 font_size(0), | 591 font_size(0), |
590 baseline_offset(0), | 592 baseline_offset(0), |
591 baseline_type(0), | 593 baseline_type(0), |
592 font_style(0), | 594 italic(false), |
| 595 weight(Font::Weight::NORMAL), |
593 strike(false), | 596 strike(false), |
594 diagonal_strike(false), | 597 diagonal_strike(false), |
595 underline(false) {} | 598 underline(false) {} |
596 | 599 |
597 TextRunHarfBuzz::~TextRunHarfBuzz() {} | 600 TextRunHarfBuzz::~TextRunHarfBuzz() {} |
598 | 601 |
599 Range TextRunHarfBuzz::CharRangeToGlyphRange(const Range& char_range) const { | 602 Range TextRunHarfBuzz::CharRangeToGlyphRange(const Range& char_range) const { |
600 DCHECK(range.Contains(char_range)); | 603 DCHECK(range.Contains(char_range)); |
601 DCHECK(!char_range.is_reversed()); | 604 DCHECK(!char_range.is_reversed()); |
602 DCHECK(!char_range.is_empty()); | 605 DCHECK(!char_range.is_empty()); |
(...skipping 662 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1265 // Temporarily apply composition underlines and selection colors. | 1268 // Temporarily apply composition underlines and selection colors. |
1266 ApplyCompositionAndSelectionStyles(); | 1269 ApplyCompositionAndSelectionStyles(); |
1267 | 1270 |
1268 // Build the run list from the script items and ranged styles and baselines. | 1271 // Build the run list from the script items and ranged styles and baselines. |
1269 // Use an empty color BreakList to avoid breaking runs at color boundaries. | 1272 // Use an empty color BreakList to avoid breaking runs at color boundaries. |
1270 BreakList<SkColor> empty_colors; | 1273 BreakList<SkColor> empty_colors; |
1271 empty_colors.SetMax(text.length()); | 1274 empty_colors.SetMax(text.length()); |
1272 DCHECK_LE(text.size(), baselines().max()); | 1275 DCHECK_LE(text.size(), baselines().max()); |
1273 for (const BreakList<bool>& style : styles()) | 1276 for (const BreakList<bool>& style : styles()) |
1274 DCHECK_LE(text.size(), style.max()); | 1277 DCHECK_LE(text.size(), style.max()); |
1275 internal::StyleIterator style(empty_colors, baselines(), styles()); | 1278 internal::StyleIterator style(empty_colors, baselines(), weights(), styles()); |
1276 | 1279 |
1277 for (size_t run_break = 0; run_break < text.length();) { | 1280 for (size_t run_break = 0; run_break < text.length();) { |
1278 internal::TextRunHarfBuzz* run = | 1281 internal::TextRunHarfBuzz* run = |
1279 new internal::TextRunHarfBuzz(font_list().GetPrimaryFont()); | 1282 new internal::TextRunHarfBuzz(font_list().GetPrimaryFont()); |
1280 run->range.set_start(run_break); | 1283 run->range.set_start(run_break); |
1281 run->font_style = (style.style(BOLD) ? Font::BOLD : 0) | | 1284 run->italic = style.style(ITALIC); |
1282 (style.style(ITALIC) ? Font::ITALIC : 0); | |
1283 run->baseline_type = style.baseline(); | 1285 run->baseline_type = style.baseline(); |
1284 run->strike = style.style(STRIKE); | 1286 run->strike = style.style(STRIKE); |
1285 run->diagonal_strike = style.style(DIAGONAL_STRIKE); | 1287 run->diagonal_strike = style.style(DIAGONAL_STRIKE); |
1286 run->underline = style.style(UNDERLINE); | 1288 run->underline = style.style(UNDERLINE); |
| 1289 run->weight = style.weight(); |
1287 int32_t script_item_break = 0; | 1290 int32_t script_item_break = 0; |
1288 bidi_iterator.GetLogicalRun(run_break, &script_item_break, &run->level); | 1291 bidi_iterator.GetLogicalRun(run_break, &script_item_break, &run->level); |
1289 CHECK_GT(static_cast<size_t>(script_item_break), run_break); | 1292 CHECK_GT(static_cast<size_t>(script_item_break), run_break); |
1290 // Odd BiDi embedding levels correspond to RTL runs. | 1293 // Odd BiDi embedding levels correspond to RTL runs. |
1291 run->is_rtl = (run->level % 2) == 1; | 1294 run->is_rtl = (run->level % 2) == 1; |
1292 // Find the length and script of this script run. | 1295 // Find the length and script of this script run. |
1293 script_item_break = ScriptInterval(text, run_break, | 1296 script_item_break = ScriptInterval(text, run_break, |
1294 script_item_break - run_break, &run->script) + run_break; | 1297 script_item_break - run_break, &run->script) + run_break; |
1295 | 1298 |
1296 // Find the next break and advance the iterators as needed. | 1299 // Find the next break and advance the iterators as needed. |
(...skipping 20 matching lines...) Expand all Loading... |
1317 | 1320 |
1318 // Undo the temporarily applied composition underlines and selection colors. | 1321 // Undo the temporarily applied composition underlines and selection colors. |
1319 UndoCompositionAndSelectionStyles(); | 1322 UndoCompositionAndSelectionStyles(); |
1320 | 1323 |
1321 run_list_out->InitIndexMap(); | 1324 run_list_out->InitIndexMap(); |
1322 } | 1325 } |
1323 | 1326 |
1324 bool RenderTextHarfBuzz::CompareFamily( | 1327 bool RenderTextHarfBuzz::CompareFamily( |
1325 const base::string16& text, | 1328 const base::string16& text, |
1326 const Font& font, | 1329 const Font& font, |
1327 const gfx::FontRenderParams& render_params, | 1330 const FontRenderParams& render_params, |
1328 internal::TextRunHarfBuzz* run, | 1331 internal::TextRunHarfBuzz* run, |
1329 Font* best_font, | 1332 Font* best_font, |
1330 gfx::FontRenderParams* best_render_params, | 1333 FontRenderParams* best_render_params, |
1331 size_t* best_missing_glyphs) { | 1334 size_t* best_missing_glyphs) { |
1332 if (!ShapeRunWithFont(text, font, render_params, run)) | 1335 if (!ShapeRunWithFont(text, font, render_params, run)) |
1333 return false; | 1336 return false; |
1334 | 1337 |
1335 const size_t missing_glyphs = run->CountMissingGlyphs(); | 1338 const size_t missing_glyphs = run->CountMissingGlyphs(); |
1336 if (missing_glyphs < *best_missing_glyphs) { | 1339 if (missing_glyphs < *best_missing_glyphs) { |
1337 *best_font = font; | 1340 *best_font = font; |
1338 *best_render_params = render_params; | 1341 *best_render_params = render_params; |
1339 *best_missing_glyphs = missing_glyphs; | 1342 *best_missing_glyphs = missing_glyphs; |
1340 } | 1343 } |
(...skipping 10 matching lines...) Expand all Loading... |
1351 void RenderTextHarfBuzz::ShapeRun(const base::string16& text, | 1354 void RenderTextHarfBuzz::ShapeRun(const base::string16& text, |
1352 internal::TextRunHarfBuzz* run) { | 1355 internal::TextRunHarfBuzz* run) { |
1353 const Font& primary_font = font_list().GetPrimaryFont(); | 1356 const Font& primary_font = font_list().GetPrimaryFont(); |
1354 const std::string primary_family = primary_font.GetFontName(); | 1357 const std::string primary_family = primary_font.GetFontName(); |
1355 run->font_size = primary_font.GetFontSize(); | 1358 run->font_size = primary_font.GetFontSize(); |
1356 run->baseline_offset = 0; | 1359 run->baseline_offset = 0; |
1357 if (run->baseline_type != NORMAL_BASELINE) { | 1360 if (run->baseline_type != NORMAL_BASELINE) { |
1358 // Calculate a slightly smaller font. The ratio here is somewhat arbitrary. | 1361 // Calculate a slightly smaller font. The ratio here is somewhat arbitrary. |
1359 // Proportions from 5/9 to 5/7 all look pretty good. | 1362 // Proportions from 5/9 to 5/7 all look pretty good. |
1360 const float ratio = 5.0f / 9.0f; | 1363 const float ratio = 5.0f / 9.0f; |
1361 run->font_size = gfx::ToRoundedInt(primary_font.GetFontSize() * ratio); | 1364 run->font_size = ToRoundedInt(primary_font.GetFontSize() * ratio); |
1362 switch (run->baseline_type) { | 1365 switch (run->baseline_type) { |
1363 case SUPERSCRIPT: | 1366 case SUPERSCRIPT: |
1364 run->baseline_offset = | 1367 run->baseline_offset = |
1365 primary_font.GetCapHeight() - primary_font.GetHeight(); | 1368 primary_font.GetCapHeight() - primary_font.GetHeight(); |
1366 break; | 1369 break; |
1367 case SUPERIOR: | 1370 case SUPERIOR: |
1368 run->baseline_offset = | 1371 run->baseline_offset = |
1369 gfx::ToRoundedInt(primary_font.GetCapHeight() * ratio) - | 1372 ToRoundedInt(primary_font.GetCapHeight() * ratio) - |
1370 primary_font.GetCapHeight(); | 1373 primary_font.GetCapHeight(); |
1371 break; | 1374 break; |
1372 case SUBSCRIPT: | 1375 case SUBSCRIPT: |
1373 run->baseline_offset = | 1376 run->baseline_offset = |
1374 primary_font.GetHeight() - primary_font.GetBaseline(); | 1377 primary_font.GetHeight() - primary_font.GetBaseline(); |
1375 break; | 1378 break; |
1376 case INFERIOR: // Fall through. | 1379 case INFERIOR: // Fall through. |
1377 default: | 1380 default: |
1378 break; | 1381 break; |
1379 } | 1382 } |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1441 continue; | 1444 continue; |
1442 #endif | 1445 #endif |
1443 if (fallback_fonts.find(font) != fallback_fonts.end()) | 1446 if (fallback_fonts.find(font) != fallback_fonts.end()) |
1444 continue; | 1447 continue; |
1445 | 1448 |
1446 fallback_fonts.insert(font); | 1449 fallback_fonts.insert(font); |
1447 | 1450 |
1448 FontRenderParamsQuery query; | 1451 FontRenderParamsQuery query; |
1449 query.families.push_back(font_name); | 1452 query.families.push_back(font_name); |
1450 query.pixel_size = run->font_size; | 1453 query.pixel_size = run->font_size; |
1451 query.style = run->font_style; | 1454 query.style = run->italic ? Font::ITALIC : 0; |
1452 FontRenderParams fallback_render_params = GetFontRenderParams(query, NULL); | 1455 FontRenderParams fallback_render_params = GetFontRenderParams(query, NULL); |
1453 if (CompareFamily(text, font, fallback_render_params, run, &best_font, | 1456 if (CompareFamily(text, font, fallback_render_params, run, &best_font, |
1454 &best_render_params, &best_missing_glyphs)) | 1457 &best_render_params, &best_missing_glyphs)) |
1455 return; | 1458 return; |
1456 } | 1459 } |
1457 | 1460 |
1458 if (best_missing_glyphs != std::numeric_limits<size_t>::max() && | 1461 if (best_missing_glyphs != std::numeric_limits<size_t>::max() && |
1459 (best_font.GetFontName() == run->font.GetFontName() || | 1462 (best_font.GetFontName() == run->font.GetFontName() || |
1460 ShapeRunWithFont(text, best_font, best_render_params, run))) | 1463 ShapeRunWithFont(text, best_font, best_render_params, run))) |
1461 return; | 1464 return; |
1462 | 1465 |
1463 run->glyph_count = 0; | 1466 run->glyph_count = 0; |
1464 run->width = 0.0f; | 1467 run->width = 0.0f; |
1465 } | 1468 } |
1466 | 1469 |
1467 bool RenderTextHarfBuzz::ShapeRunWithFont(const base::string16& text, | 1470 bool RenderTextHarfBuzz::ShapeRunWithFont(const base::string16& text, |
1468 const gfx::Font& font, | 1471 const Font& font, |
1469 const FontRenderParams& params, | 1472 const FontRenderParams& params, |
1470 internal::TextRunHarfBuzz* run) { | 1473 internal::TextRunHarfBuzz* run) { |
1471 sk_sp<SkTypeface> skia_face( | 1474 sk_sp<SkTypeface> skia_face( |
1472 internal::CreateSkiaTypeface(font, run->font_style)); | 1475 internal::CreateSkiaTypeface(font, run->italic, run->weight)); |
1473 if (!skia_face) | 1476 if (!skia_face) |
1474 return false; | 1477 return false; |
1475 | 1478 |
1476 run->skia_face = skia_face; | 1479 run->skia_face = skia_face; |
1477 run->font = font; | 1480 run->font = font; |
1478 run->render_params = params; | 1481 run->render_params = params; |
1479 | 1482 |
1480 hb_font_t* harfbuzz_font = CreateHarfBuzzFont( | 1483 hb_font_t* harfbuzz_font = CreateHarfBuzzFont( |
1481 run->skia_face.get(), SkIntToScalar(run->font_size), run->render_params, | 1484 run->skia_face.get(), SkIntToScalar(run->font_size), run->render_params, |
1482 subpixel_rendering_suppressed()); | 1485 subpixel_rendering_suppressed()); |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1581 DCHECK(!update_layout_run_list_); | 1584 DCHECK(!update_layout_run_list_); |
1582 DCHECK(!update_display_run_list_); | 1585 DCHECK(!update_display_run_list_); |
1583 return text_elided() ? display_run_list_.get() : &layout_run_list_; | 1586 return text_elided() ? display_run_list_.get() : &layout_run_list_; |
1584 } | 1587 } |
1585 | 1588 |
1586 const internal::TextRunList* RenderTextHarfBuzz::GetRunList() const { | 1589 const internal::TextRunList* RenderTextHarfBuzz::GetRunList() const { |
1587 return const_cast<RenderTextHarfBuzz*>(this)->GetRunList(); | 1590 return const_cast<RenderTextHarfBuzz*>(this)->GetRunList(); |
1588 } | 1591 } |
1589 | 1592 |
1590 } // namespace gfx | 1593 } // namespace gfx |
OLD | NEW |