Chromium Code Reviews| 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 | 8 |
| 9 #include "base/i18n/bidi_line_iterator.h" | 9 #include "base/i18n/bidi_line_iterator.h" |
| 10 #include "base/i18n/break_iterator.h" | 10 #include "base/i18n/break_iterator.h" |
| (...skipping 457 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 468 } | 468 } |
| 469 | 469 |
| 470 TextRunHarfBuzz::TextRunHarfBuzz() | 470 TextRunHarfBuzz::TextRunHarfBuzz() |
| 471 : width(0.0f), | 471 : width(0.0f), |
| 472 preceding_run_widths(0.0f), | 472 preceding_run_widths(0.0f), |
| 473 is_rtl(false), | 473 is_rtl(false), |
| 474 level(0), | 474 level(0), |
| 475 script(USCRIPT_INVALID_CODE), | 475 script(USCRIPT_INVALID_CODE), |
| 476 glyph_count(static_cast<size_t>(-1)), | 476 glyph_count(static_cast<size_t>(-1)), |
| 477 font_size(0), | 477 font_size(0), |
| 478 baseline_offset(0), | |
| 479 baseline_type(0), | |
| 478 font_style(0), | 480 font_style(0), |
| 479 strike(false), | 481 strike(false), |
| 480 diagonal_strike(false), | 482 diagonal_strike(false), |
| 481 underline(false) {} | 483 underline(false) {} |
| 482 | 484 |
| 483 TextRunHarfBuzz::~TextRunHarfBuzz() {} | 485 TextRunHarfBuzz::~TextRunHarfBuzz() {} |
| 484 | 486 |
| 485 void TextRunHarfBuzz::GetClusterAt(size_t pos, | 487 void TextRunHarfBuzz::GetClusterAt(size_t pos, |
| 486 Range* chars, | 488 Range* chars, |
| 487 Range* glyphs) const { | 489 Range* glyphs) const { |
| (...skipping 524 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1012 background_is_transparent()); | 1014 background_is_transparent()); |
| 1013 Range glyphs_range = run.CharRangeToGlyphRange(segment.char_range); | 1015 Range glyphs_range = run.CharRangeToGlyphRange(segment.char_range); |
| 1014 scoped_ptr<SkPoint[]> positions(new SkPoint[glyphs_range.length()]); | 1016 scoped_ptr<SkPoint[]> positions(new SkPoint[glyphs_range.length()]); |
| 1015 SkScalar offset_x = | 1017 SkScalar offset_x = |
| 1016 preceding_segment_widths - run.positions[glyphs_range.start()].x(); | 1018 preceding_segment_widths - run.positions[glyphs_range.start()].x(); |
| 1017 for (size_t j = 0; j < glyphs_range.length(); ++j) { | 1019 for (size_t j = 0; j < glyphs_range.length(); ++j) { |
| 1018 positions[j] = run.positions[(glyphs_range.is_reversed()) ? | 1020 positions[j] = run.positions[(glyphs_range.is_reversed()) ? |
| 1019 (glyphs_range.start() - j) : | 1021 (glyphs_range.start() - j) : |
| 1020 (glyphs_range.start() + j)]; | 1022 (glyphs_range.start() + j)]; |
| 1021 positions[j].offset(SkIntToScalar(origin.x()) + offset_x, | 1023 positions[j].offset(SkIntToScalar(origin.x()) + offset_x, |
| 1022 SkIntToScalar(origin.y())); | 1024 SkIntToScalar(origin.y() + run.baseline_offset)); |
| 1023 } | 1025 } |
| 1024 for (BreakList<SkColor>::const_iterator it = | 1026 for (BreakList<SkColor>::const_iterator it = |
| 1025 colors().GetBreak(segment.char_range.start()); | 1027 colors().GetBreak(segment.char_range.start()); |
| 1026 it != colors().breaks().end() && | 1028 it != colors().breaks().end() && |
| 1027 it->first < segment.char_range.end(); | 1029 it->first < segment.char_range.end(); |
| 1028 ++it) { | 1030 ++it) { |
| 1029 const Range intersection = | 1031 const Range intersection = |
| 1030 colors().GetRange(it).Intersect(segment.char_range); | 1032 colors().GetRange(it).Intersect(segment.char_range); |
| 1031 const Range colored_glyphs = run.CharRangeToGlyphRange(intersection); | 1033 const Range colored_glyphs = run.CharRangeToGlyphRange(intersection); |
| 1032 // The range may be empty if a portion of a multi-character grapheme is | 1034 // The range may be empty if a portion of a multi-character grapheme is |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1121 internal::TextRunHarfBuzz* run = new internal::TextRunHarfBuzz; | 1123 internal::TextRunHarfBuzz* run = new internal::TextRunHarfBuzz; |
| 1122 run->range = Range(0, text.length()); | 1124 run->range = Range(0, text.length()); |
| 1123 run_list_out->add(run); | 1125 run_list_out->add(run); |
| 1124 run_list_out->InitIndexMap(); | 1126 run_list_out->InitIndexMap(); |
| 1125 return; | 1127 return; |
| 1126 } | 1128 } |
| 1127 | 1129 |
| 1128 // Temporarily apply composition underlines and selection colors. | 1130 // Temporarily apply composition underlines and selection colors. |
| 1129 ApplyCompositionAndSelectionStyles(); | 1131 ApplyCompositionAndSelectionStyles(); |
| 1130 | 1132 |
| 1131 // Build the list of runs from the script items and ranged styles. Use an | 1133 // Build the run list from the script items and ranges styles and baselines. |
|
msw
2015/02/19 02:50:57
nit: d'oh sorry, s/ranges/ranged/... my fault!
dschuyler
2015/02/25 02:23:06
Done.
| |
| 1132 // empty color BreakList to avoid breaking runs at color boundaries. | 1134 // Use an empty color BreakList to avoid breaking runs at color boundaries. |
| 1133 BreakList<SkColor> empty_colors; | 1135 BreakList<SkColor> empty_colors; |
| 1134 empty_colors.SetMax(text.length()); | 1136 empty_colors.SetMax(text.length()); |
| 1135 internal::StyleIterator style(empty_colors, styles()); | 1137 internal::StyleIterator style(empty_colors, baselines(), styles()); |
| 1136 | 1138 |
| 1137 for (size_t run_break = 0; run_break < text.length();) { | 1139 for (size_t run_break = 0; run_break < text.length();) { |
| 1138 internal::TextRunHarfBuzz* run = new internal::TextRunHarfBuzz; | 1140 internal::TextRunHarfBuzz* run = new internal::TextRunHarfBuzz; |
| 1139 run->range.set_start(run_break); | 1141 run->range.set_start(run_break); |
| 1140 run->font_style = (style.style(BOLD) ? Font::BOLD : 0) | | 1142 run->font_style = (style.style(BOLD) ? Font::BOLD : 0) | |
| 1141 (style.style(ITALIC) ? Font::ITALIC : 0); | 1143 (style.style(ITALIC) ? Font::ITALIC : 0); |
| 1144 run->baseline_type = style.baseline(); | |
| 1142 run->strike = style.style(STRIKE); | 1145 run->strike = style.style(STRIKE); |
| 1143 run->diagonal_strike = style.style(DIAGONAL_STRIKE); | 1146 run->diagonal_strike = style.style(DIAGONAL_STRIKE); |
| 1144 run->underline = style.style(UNDERLINE); | 1147 run->underline = style.style(UNDERLINE); |
| 1145 int32 script_item_break = 0; | 1148 int32 script_item_break = 0; |
| 1146 bidi_iterator.GetLogicalRun(run_break, &script_item_break, &run->level); | 1149 bidi_iterator.GetLogicalRun(run_break, &script_item_break, &run->level); |
| 1147 // Odd BiDi embedding levels correspond to RTL runs. | 1150 // Odd BiDi embedding levels correspond to RTL runs. |
| 1148 run->is_rtl = (run->level % 2) == 1; | 1151 run->is_rtl = (run->level % 2) == 1; |
| 1149 // Find the length and script of this script run. | 1152 // Find the length and script of this script run. |
| 1150 script_item_break = ScriptInterval(text, run_break, | 1153 script_item_break = ScriptInterval(text, run_break, |
| 1151 script_item_break - run_break, &run->script) + run_break; | 1154 script_item_break - run_break, &run->script) + run_break; |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1200 for (auto* run : run_list->runs()) | 1203 for (auto* run : run_list->runs()) |
| 1201 ShapeRun(text, run); | 1204 ShapeRun(text, run); |
| 1202 run_list->ComputePrecedingRunWidths(); | 1205 run_list->ComputePrecedingRunWidths(); |
| 1203 } | 1206 } |
| 1204 | 1207 |
| 1205 void RenderTextHarfBuzz::ShapeRun(const base::string16& text, | 1208 void RenderTextHarfBuzz::ShapeRun(const base::string16& text, |
| 1206 internal::TextRunHarfBuzz* run) { | 1209 internal::TextRunHarfBuzz* run) { |
| 1207 const Font& primary_font = font_list().GetPrimaryFont(); | 1210 const Font& primary_font = font_list().GetPrimaryFont(); |
| 1208 const std::string primary_family = primary_font.GetFontName(); | 1211 const std::string primary_family = primary_font.GetFontName(); |
| 1209 run->font_size = primary_font.GetFontSize(); | 1212 run->font_size = primary_font.GetFontSize(); |
| 1213 run->baseline_offset = 0; | |
| 1214 if (run->baseline_type != NORMAL_BASELINE) { | |
| 1215 // Calculate a slightly smaller font. The ratio here is somewhat arbitrary. | |
| 1216 // Proportions from 5/9 to 5/7 all look pretty good. | |
| 1217 const float ratio = 5.0f / 9.0f; | |
| 1218 run->font_size = std::round(primary_font.GetFontSize() * ratio); | |
| 1219 switch (run->baseline_type) { | |
| 1220 case SUPERSCRIPT: | |
| 1221 run->baseline_offset = | |
| 1222 primary_font.GetCapHeight() - primary_font.GetHeight(); | |
| 1223 break; | |
| 1224 case SUPERIOR: | |
| 1225 run->baseline_offset = std::round(primary_font.GetCapHeight() * ratio) - | |
| 1226 primary_font.GetCapHeight(); | |
| 1227 break; | |
| 1228 case SUBSCRIPT: | |
| 1229 run->baseline_offset = | |
| 1230 primary_font.GetHeight() - primary_font.GetBaseline(); | |
| 1231 break; | |
| 1232 case INFERIOR: // Fall through. | |
| 1233 default: | |
| 1234 break; | |
| 1235 } | |
| 1236 } | |
| 1210 | 1237 |
| 1211 std::string best_family; | 1238 std::string best_family; |
| 1212 FontRenderParams best_render_params; | 1239 FontRenderParams best_render_params; |
| 1213 size_t best_missing_glyphs = std::numeric_limits<size_t>::max(); | 1240 size_t best_missing_glyphs = std::numeric_limits<size_t>::max(); |
| 1214 | 1241 |
| 1215 for (const Font& font : font_list().GetFonts()) { | 1242 for (const Font& font : font_list().GetFonts()) { |
| 1216 if (CompareFamily(text, font.GetFontName(), font.GetFontRenderParams(), | 1243 if (CompareFamily(text, font.GetFontName(), font.GetFontRenderParams(), |
| 1217 run, &best_family, &best_render_params, | 1244 run, &best_family, &best_render_params, |
| 1218 &best_missing_glyphs)) | 1245 &best_missing_glyphs)) |
| 1219 return; | 1246 return; |
| (...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1457 DCHECK(!update_layout_run_list_); | 1484 DCHECK(!update_layout_run_list_); |
| 1458 DCHECK(!update_display_run_list_); | 1485 DCHECK(!update_display_run_list_); |
| 1459 return text_elided() ? display_run_list_.get() : &layout_run_list_; | 1486 return text_elided() ? display_run_list_.get() : &layout_run_list_; |
| 1460 } | 1487 } |
| 1461 | 1488 |
| 1462 const internal::TextRunList* RenderTextHarfBuzz::GetRunList() const { | 1489 const internal::TextRunList* RenderTextHarfBuzz::GetRunList() const { |
| 1463 return const_cast<RenderTextHarfBuzz*>(this)->GetRunList(); | 1490 return const_cast<RenderTextHarfBuzz*>(this)->GetRunList(); |
| 1464 } | 1491 } |
| 1465 | 1492 |
| 1466 } // namespace gfx | 1493 } // namespace gfx |
| OLD | NEW |