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 |