| 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 |