| 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" |
| 11 #include "base/i18n/break_iterator.h" | 11 #include "base/i18n/break_iterator.h" |
| 12 #include "base/i18n/char_iterator.h" | 12 #include "base/i18n/char_iterator.h" |
| 13 #include "base/macros.h" |
| 13 #include "base/profiler/scoped_tracker.h" | 14 #include "base/profiler/scoped_tracker.h" |
| 14 #include "base/strings/string_util.h" | 15 #include "base/strings/string_util.h" |
| 15 #include "base/strings/utf_string_conversions.h" | 16 #include "base/strings/utf_string_conversions.h" |
| 16 #include "base/trace_event/trace_event.h" | 17 #include "base/trace_event/trace_event.h" |
| 18 #include "build/build_config.h" |
| 17 #include "third_party/harfbuzz-ng/src/hb.h" | 19 #include "third_party/harfbuzz-ng/src/hb.h" |
| 18 #include "third_party/icu/source/common/unicode/ubidi.h" | 20 #include "third_party/icu/source/common/unicode/ubidi.h" |
| 19 #include "third_party/icu/source/common/unicode/utf16.h" | 21 #include "third_party/icu/source/common/unicode/utf16.h" |
| 20 #include "third_party/skia/include/core/SkColor.h" | 22 #include "third_party/skia/include/core/SkColor.h" |
| 21 #include "third_party/skia/include/core/SkTypeface.h" | 23 #include "third_party/skia/include/core/SkTypeface.h" |
| 22 #include "ui/gfx/canvas.h" | 24 #include "ui/gfx/canvas.h" |
| 23 #include "ui/gfx/font.h" | 25 #include "ui/gfx/font.h" |
| 24 #include "ui/gfx/font_fallback.h" | 26 #include "ui/gfx/font_fallback.h" |
| 25 #include "ui/gfx/font_render_params.h" | 27 #include "ui/gfx/font_render_params.h" |
| 26 #include "ui/gfx/geometry/safe_integer_conversions.h" | 28 #include "ui/gfx/geometry/safe_integer_conversions.h" |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 125 return false; | 127 return false; |
| 126 ScriptSetIntersect(current_char, scripts, &scripts_size); | 128 ScriptSetIntersect(current_char, scripts, &scripts_size); |
| 127 return scripts_size != 0; | 129 return scripts_size != 0; |
| 128 } | 130 } |
| 129 | 131 |
| 130 // Returns the boundary between a special and a regular character. Special | 132 // Returns the boundary between a special and a regular character. Special |
| 131 // characters are brackets or characters that satisfy |IsUnusualBlockCode|. | 133 // characters are brackets or characters that satisfy |IsUnusualBlockCode|. |
| 132 size_t FindRunBreakingCharacter(const base::string16& text, | 134 size_t FindRunBreakingCharacter(const base::string16& text, |
| 133 size_t run_start, | 135 size_t run_start, |
| 134 size_t run_break) { | 136 size_t run_break) { |
| 135 const int32 run_length = static_cast<int32>(run_break - run_start); | 137 const int32_t run_length = static_cast<int32_t>(run_break - run_start); |
| 136 base::i18n::UTF16CharIterator iter(text.c_str() + run_start, run_length); | 138 base::i18n::UTF16CharIterator iter(text.c_str() + run_start, run_length); |
| 137 const UChar32 first_char = iter.get(); | 139 const UChar32 first_char = iter.get(); |
| 138 // The newline character should form a single run so that the line breaker | 140 // The newline character should form a single run so that the line breaker |
| 139 // can handle them easily. | 141 // can handle them easily. |
| 140 if (first_char == '\n') | 142 if (first_char == '\n') |
| 141 return run_start + 1; | 143 return run_start + 1; |
| 142 | 144 |
| 143 const UBlockCode first_block = ublock_getCode(first_char); | 145 const UBlockCode first_block = ublock_getCode(first_char); |
| 144 const bool first_block_unusual = IsUnusualBlockCode(first_block); | 146 const bool first_block_unusual = IsUnusualBlockCode(first_block); |
| 145 const bool first_bracket = IsBracket(first_char); | 147 const bool first_bracket = IsBracket(first_char); |
| (...skipping 1113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1259 | 1261 |
| 1260 for (size_t run_break = 0; run_break < text.length();) { | 1262 for (size_t run_break = 0; run_break < text.length();) { |
| 1261 internal::TextRunHarfBuzz* run = new internal::TextRunHarfBuzz; | 1263 internal::TextRunHarfBuzz* run = new internal::TextRunHarfBuzz; |
| 1262 run->range.set_start(run_break); | 1264 run->range.set_start(run_break); |
| 1263 run->font_style = (style.style(BOLD) ? Font::BOLD : 0) | | 1265 run->font_style = (style.style(BOLD) ? Font::BOLD : 0) | |
| 1264 (style.style(ITALIC) ? Font::ITALIC : 0); | 1266 (style.style(ITALIC) ? Font::ITALIC : 0); |
| 1265 run->baseline_type = style.baseline(); | 1267 run->baseline_type = style.baseline(); |
| 1266 run->strike = style.style(STRIKE); | 1268 run->strike = style.style(STRIKE); |
| 1267 run->diagonal_strike = style.style(DIAGONAL_STRIKE); | 1269 run->diagonal_strike = style.style(DIAGONAL_STRIKE); |
| 1268 run->underline = style.style(UNDERLINE); | 1270 run->underline = style.style(UNDERLINE); |
| 1269 int32 script_item_break = 0; | 1271 int32_t script_item_break = 0; |
| 1270 bidi_iterator.GetLogicalRun(run_break, &script_item_break, &run->level); | 1272 bidi_iterator.GetLogicalRun(run_break, &script_item_break, &run->level); |
| 1271 CHECK_GT(static_cast<size_t>(script_item_break), run_break); | 1273 CHECK_GT(static_cast<size_t>(script_item_break), run_break); |
| 1272 // Odd BiDi embedding levels correspond to RTL runs. | 1274 // Odd BiDi embedding levels correspond to RTL runs. |
| 1273 run->is_rtl = (run->level % 2) == 1; | 1275 run->is_rtl = (run->level % 2) == 1; |
| 1274 // Find the length and script of this script run. | 1276 // Find the length and script of this script run. |
| 1275 script_item_break = ScriptInterval(text, run_break, | 1277 script_item_break = ScriptInterval(text, run_break, |
| 1276 script_item_break - run_break, &run->script) + run_break; | 1278 script_item_break - run_break, &run->script) + run_break; |
| 1277 | 1279 |
| 1278 // Find the next break and advance the iterators as needed. | 1280 // Find the next break and advance the iterators as needed. |
| 1279 const size_t new_run_break = std::min( | 1281 const size_t new_run_break = std::min( |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1459 run->render_params = params; | 1461 run->render_params = params; |
| 1460 | 1462 |
| 1461 hb_font_t* harfbuzz_font = CreateHarfBuzzFont( | 1463 hb_font_t* harfbuzz_font = CreateHarfBuzzFont( |
| 1462 run->skia_face.get(), SkIntToScalar(run->font_size), run->render_params, | 1464 run->skia_face.get(), SkIntToScalar(run->font_size), run->render_params, |
| 1463 subpixel_rendering_suppressed()); | 1465 subpixel_rendering_suppressed()); |
| 1464 | 1466 |
| 1465 // Create a HarfBuzz buffer and add the string to be shaped. The HarfBuzz | 1467 // Create a HarfBuzz buffer and add the string to be shaped. The HarfBuzz |
| 1466 // buffer holds our text, run information to be used by the shaping engine, | 1468 // buffer holds our text, run information to be used by the shaping engine, |
| 1467 // and the resulting glyph data. | 1469 // and the resulting glyph data. |
| 1468 hb_buffer_t* buffer = hb_buffer_create(); | 1470 hb_buffer_t* buffer = hb_buffer_create(); |
| 1469 hb_buffer_add_utf16(buffer, reinterpret_cast<const uint16*>(text.c_str()), | 1471 hb_buffer_add_utf16(buffer, reinterpret_cast<const uint16_t*>(text.c_str()), |
| 1470 text.length(), run->range.start(), run->range.length()); | 1472 text.length(), run->range.start(), run->range.length()); |
| 1471 hb_buffer_set_script(buffer, ICUScriptToHBScript(run->script)); | 1473 hb_buffer_set_script(buffer, ICUScriptToHBScript(run->script)); |
| 1472 hb_buffer_set_direction(buffer, | 1474 hb_buffer_set_direction(buffer, |
| 1473 run->is_rtl ? HB_DIRECTION_RTL : HB_DIRECTION_LTR); | 1475 run->is_rtl ? HB_DIRECTION_RTL : HB_DIRECTION_LTR); |
| 1474 // TODO(ckocagil): Should we determine the actual language? | 1476 // TODO(ckocagil): Should we determine the actual language? |
| 1475 hb_buffer_set_language(buffer, hb_language_get_default()); | 1477 hb_buffer_set_language(buffer, hb_language_get_default()); |
| 1476 | 1478 |
| 1477 { | 1479 { |
| 1478 // TODO(ckocagil): Remove ScopedTracker below once crbug.com/441028 is | 1480 // TODO(ckocagil): Remove ScopedTracker below once crbug.com/441028 is |
| 1479 // fixed. | 1481 // fixed. |
| 1480 tracked_objects::ScopedTracker tracking_profile( | 1482 tracked_objects::ScopedTracker tracking_profile( |
| 1481 FROM_HERE_WITH_EXPLICIT_FUNCTION("441028 hb_shape()")); | 1483 FROM_HERE_WITH_EXPLICIT_FUNCTION("441028 hb_shape()")); |
| 1482 | 1484 |
| 1483 // Shape the text. | 1485 // Shape the text. |
| 1484 hb_shape(harfbuzz_font, buffer, NULL, 0); | 1486 hb_shape(harfbuzz_font, buffer, NULL, 0); |
| 1485 } | 1487 } |
| 1486 | 1488 |
| 1487 // Populate the run fields with the resulting glyph data in the buffer. | 1489 // Populate the run fields with the resulting glyph data in the buffer. |
| 1488 unsigned int glyph_count = 0; | 1490 unsigned int glyph_count = 0; |
| 1489 hb_glyph_info_t* infos = hb_buffer_get_glyph_infos(buffer, &glyph_count); | 1491 hb_glyph_info_t* infos = hb_buffer_get_glyph_infos(buffer, &glyph_count); |
| 1490 run->glyph_count = glyph_count; | 1492 run->glyph_count = glyph_count; |
| 1491 hb_glyph_position_t* hb_positions = | 1493 hb_glyph_position_t* hb_positions = |
| 1492 hb_buffer_get_glyph_positions(buffer, NULL); | 1494 hb_buffer_get_glyph_positions(buffer, NULL); |
| 1493 run->glyphs.reset(new uint16[run->glyph_count]); | 1495 run->glyphs.reset(new uint16_t[run->glyph_count]); |
| 1494 run->glyph_to_char.resize(run->glyph_count); | 1496 run->glyph_to_char.resize(run->glyph_count); |
| 1495 run->positions.reset(new SkPoint[run->glyph_count]); | 1497 run->positions.reset(new SkPoint[run->glyph_count]); |
| 1496 run->width = 0.0f; | 1498 run->width = 0.0f; |
| 1497 | 1499 |
| 1498 for (size_t i = 0; i < run->glyph_count; ++i) { | 1500 for (size_t i = 0; i < run->glyph_count; ++i) { |
| 1499 DCHECK_LE(infos[i].codepoint, std::numeric_limits<uint16>::max()); | 1501 DCHECK_LE(infos[i].codepoint, std::numeric_limits<uint16_t>::max()); |
| 1500 run->glyphs[i] = static_cast<uint16>(infos[i].codepoint); | 1502 run->glyphs[i] = static_cast<uint16_t>(infos[i].codepoint); |
| 1501 run->glyph_to_char[i] = infos[i].cluster; | 1503 run->glyph_to_char[i] = infos[i].cluster; |
| 1502 const SkScalar x_offset = SkFixedToScalar(hb_positions[i].x_offset); | 1504 const SkScalar x_offset = SkFixedToScalar(hb_positions[i].x_offset); |
| 1503 const SkScalar y_offset = SkFixedToScalar(hb_positions[i].y_offset); | 1505 const SkScalar y_offset = SkFixedToScalar(hb_positions[i].y_offset); |
| 1504 run->positions[i].set(run->width + x_offset, -y_offset); | 1506 run->positions[i].set(run->width + x_offset, -y_offset); |
| 1505 run->width += (glyph_width_for_test_ > 0) | 1507 run->width += (glyph_width_for_test_ > 0) |
| 1506 ? glyph_width_for_test_ | 1508 ? glyph_width_for_test_ |
| 1507 : SkFixedToFloat(hb_positions[i].x_advance); | 1509 : SkFixedToFloat(hb_positions[i].x_advance); |
| 1508 // Round run widths if subpixel positioning is off to match native behavior. | 1510 // Round run widths if subpixel positioning is off to match native behavior. |
| 1509 if (!run->render_params.subpixel_positioning) | 1511 if (!run->render_params.subpixel_positioning) |
| 1510 run->width = std::floor(run->width + 0.5f); | 1512 run->width = std::floor(run->width + 0.5f); |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1560 DCHECK(!update_layout_run_list_); | 1562 DCHECK(!update_layout_run_list_); |
| 1561 DCHECK(!update_display_run_list_); | 1563 DCHECK(!update_display_run_list_); |
| 1562 return text_elided() ? display_run_list_.get() : &layout_run_list_; | 1564 return text_elided() ? display_run_list_.get() : &layout_run_list_; |
| 1563 } | 1565 } |
| 1564 | 1566 |
| 1565 const internal::TextRunList* RenderTextHarfBuzz::GetRunList() const { | 1567 const internal::TextRunList* RenderTextHarfBuzz::GetRunList() const { |
| 1566 return const_cast<RenderTextHarfBuzz*>(this)->GetRunList(); | 1568 return const_cast<RenderTextHarfBuzz*>(this)->GetRunList(); |
| 1567 } | 1569 } |
| 1568 | 1570 |
| 1569 } // namespace gfx | 1571 } // namespace gfx |
| OLD | NEW |