| OLD | NEW |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 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 "platform/fonts/shaping/ShapeResultBloberizer.h" | 5 #include "platform/fonts/shaping/ShapeResultBloberizer.h" |
| 6 | 6 |
| 7 #include <hb.h> | 7 #include <hb.h> |
| 8 #include "platform/fonts/Font.h" | 8 #include "platform/fonts/Font.h" |
| 9 #include "platform/fonts/shaping/CachingWordShaper.h" | 9 #include "platform/fonts/shaping/CachingWordShaper.h" |
| 10 #include "platform/fonts/shaping/ShapeResult.h" | 10 #include "platform/fonts/shaping/ShapeResult.h" |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 140 float advance = 0; | 140 float advance = 0; |
| 141 unsigned word_offset = run_info.run.Rtl() ? run_info.run.length() : 0; | 141 unsigned word_offset = run_info.run.Rtl() ? run_info.run.length() : 0; |
| 142 auto results = result_buffer.results_; | 142 auto results = result_buffer.results_; |
| 143 | 143 |
| 144 for (unsigned j = 0; j < results.size(); j++) { | 144 for (unsigned j = 0; j < results.size(); j++) { |
| 145 unsigned resolved_index = run_info.run.Rtl() ? results.size() - 1 - j : j; | 145 unsigned resolved_index = run_info.run.Rtl() ? results.size() - 1 - j : j; |
| 146 const RefPtr<const ShapeResult>& word_result = results[resolved_index]; | 146 const RefPtr<const ShapeResult>& word_result = results[resolved_index]; |
| 147 for (unsigned i = 0; i < word_result->runs_.size(); i++) { | 147 for (unsigned i = 0; i < word_result->runs_.size(); i++) { |
| 148 unsigned resolved_offset = | 148 unsigned resolved_offset = |
| 149 word_offset - (run_info.run.Rtl() ? word_result->NumCharacters() : 0); | 149 word_offset - (run_info.run.Rtl() ? word_result->NumCharacters() : 0); |
| 150 advance += | 150 advance += FillTextEmphasisGlyphsForRun( |
| 151 FillTextEmphasisGlyphsForRun(word_result->runs_[i].get(), run_info, | 151 word_result->runs_[i].get(), run_info.run, |
| 152 emphasis_data, advance, resolved_offset); | 152 run_info.run.CharactersLength(), run_info.run.Direction(), |
| 153 run_info.from, run_info.to, emphasis_data, advance, resolved_offset); |
| 153 } | 154 } |
| 154 word_offset += word_result->NumCharacters() * (run_info.run.Rtl() ? -1 : 1); | 155 word_offset += word_result->NumCharacters() * (run_info.run.Rtl() ? -1 : 1); |
| 155 } | 156 } |
| 156 } | 157 } |
| 157 | 158 |
| 159 void ShapeResultBloberizer::FillTextEmphasisGlyphs(const StringView& text, |
| 160 TextDirection direction, |
| 161 unsigned from, |
| 162 unsigned to, |
| 163 const GlyphData& emphasis, |
| 164 const ShapeResult* result) { |
| 165 float advance = 0; |
| 166 unsigned offset = 0; |
| 167 |
| 168 for (unsigned i = 0; i < result->runs_.size(); i++) { |
| 169 advance += FillTextEmphasisGlyphsForRun(result->runs_[i].get(), text, |
| 170 text.length(), direction, from, to, |
| 171 emphasis, advance, offset); |
| 172 } |
| 173 } |
| 174 |
| 158 namespace { | 175 namespace { |
| 159 | 176 |
| 160 template <typename TextContainerType> | 177 template <typename TextContainerType> |
| 161 inline bool IsSkipInkException(const ShapeResultBloberizer& bloberizer, | 178 inline bool IsSkipInkException(const ShapeResultBloberizer& bloberizer, |
| 162 const TextContainerType& text, | 179 const TextContainerType& text, |
| 163 unsigned character_index) { | 180 unsigned character_index) { |
| 164 // We want to skip descenders in general, but it is undesirable renderings for | 181 // We want to skip descenders in general, but it is undesirable renderings for |
| 165 // CJK characters. | 182 // CJK characters. |
| 166 return bloberizer.GetType() == ShapeResultBloberizer::Type::kTextIntercepts && | 183 return bloberizer.GetType() == ShapeResultBloberizer::Type::kTextIntercepts && |
| 167 !text.Is8Bit() && | 184 !text.Is8Bit() && |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 300 DCHECK(!glyph_data.offset.Height()); | 317 DCHECK(!glyph_data.offset.Height()); |
| 301 Add(glyph_data.glyph, run->font_data_.Get(), | 318 Add(glyph_data.glyph, run->font_data_.Get(), |
| 302 total_advance + glyph_data.offset.Width()); | 319 total_advance + glyph_data.offset.Width()); |
| 303 return true; | 320 return true; |
| 304 }); | 321 }); |
| 305 } | 322 } |
| 306 | 323 |
| 307 return advance; | 324 return advance; |
| 308 } | 325 } |
| 309 | 326 |
| 327 template <typename TextContainerType> |
| 310 float ShapeResultBloberizer::FillTextEmphasisGlyphsForRun( | 328 float ShapeResultBloberizer::FillTextEmphasisGlyphsForRun( |
| 311 const ShapeResult::RunInfo* run, | 329 const ShapeResult::RunInfo* run, |
| 312 const TextRunPaintInfo& run_info, | 330 const TextContainerType& text, |
| 331 unsigned text_length, |
| 332 TextDirection direction, |
| 333 unsigned from, |
| 334 unsigned to, |
| 313 const GlyphData& emphasis_data, | 335 const GlyphData& emphasis_data, |
| 314 float initial_advance, | 336 float initial_advance, |
| 315 unsigned run_offset) { | 337 unsigned run_offset) { |
| 316 if (!run) | 338 if (!run) |
| 317 return 0; | 339 return 0; |
| 318 | 340 |
| 319 unsigned graphemes_in_cluster = 1; | 341 unsigned graphemes_in_cluster = 1; |
| 320 float cluster_advance = 0; | 342 float cluster_advance = 0; |
| 321 | 343 |
| 322 FloatPoint glyph_center = | 344 FloatPoint glyph_center = |
| 323 emphasis_data.font_data->BoundsForGlyph(emphasis_data.glyph).Center(); | 345 emphasis_data.font_data->BoundsForGlyph(emphasis_data.glyph).Center(); |
| 324 | 346 |
| 325 const auto& text_run = run_info.run; | |
| 326 const auto from = run_info.from; | |
| 327 const auto to = run_info.to; | |
| 328 | |
| 329 TextDirection direction = text_run.Direction(); | |
| 330 | |
| 331 // A "cluster" in this context means a cluster as it is used by HarfBuzz: | 347 // A "cluster" in this context means a cluster as it is used by HarfBuzz: |
| 332 // The minimal group of characters and corresponding glyphs, that cannot be | 348 // The minimal group of characters and corresponding glyphs, that cannot be |
| 333 // broken down further from a text shaping point of view. A cluster can | 349 // broken down further from a text shaping point of view. A cluster can |
| 334 // contain multiple glyphs and grapheme clusters, with mutually overlapping | 350 // contain multiple glyphs and grapheme clusters, with mutually overlapping |
| 335 // boundaries. Below we count grapheme clusters per HarfBuzz clusters, then | 351 // boundaries. Below we count grapheme clusters per HarfBuzz clusters, then |
| 336 // linearly split the sum of corresponding glyph advances by the number of | 352 // linearly split the sum of corresponding glyph advances by the number of |
| 337 // grapheme clusters in order to find positions for emphasis mark drawing. | 353 // grapheme clusters in order to find positions for emphasis mark drawing. |
| 338 uint16_t cluster_start = static_cast<uint16_t>( | 354 uint16_t cluster_start = static_cast<uint16_t>( |
| 339 direction == TextDirection::kRtl | 355 direction == TextDirection::kRtl |
| 340 ? run->start_index_ + run->num_characters_ + run_offset | 356 ? run->start_index_ + run->num_characters_ + run_offset |
| (...skipping 12 matching lines...) Expand all Loading... |
| 353 | 369 |
| 354 if ((direction == TextDirection::kRtl && current_character_index >= to) || | 370 if ((direction == TextDirection::kRtl && current_character_index >= to) || |
| 355 (direction != TextDirection::kRtl && current_character_index < from)) { | 371 (direction != TextDirection::kRtl && current_character_index < from)) { |
| 356 advance_so_far += glyph_data.advance; | 372 advance_so_far += glyph_data.advance; |
| 357 direction == TextDirection::kRtl ? --cluster_start : ++cluster_start; | 373 direction == TextDirection::kRtl ? --cluster_start : ++cluster_start; |
| 358 continue; | 374 continue; |
| 359 } | 375 } |
| 360 | 376 |
| 361 cluster_advance += glyph_data.advance; | 377 cluster_advance += glyph_data.advance; |
| 362 | 378 |
| 363 if (text_run.Is8Bit()) { | 379 if (text.Is8Bit()) { |
| 364 float glyph_advance_x = glyph_data.advance; | 380 float glyph_advance_x = glyph_data.advance; |
| 365 if (Character::CanReceiveTextEmphasis( | 381 if (Character::CanReceiveTextEmphasis(text[current_character_index])) { |
| 366 text_run[current_character_index])) { | |
| 367 AddEmphasisMark(*this, emphasis_data, glyph_center, | 382 AddEmphasisMark(*this, emphasis_data, glyph_center, |
| 368 advance_so_far + glyph_advance_x / 2); | 383 advance_so_far + glyph_advance_x / 2); |
| 369 } | 384 } |
| 370 advance_so_far += glyph_advance_x; | 385 advance_so_far += glyph_advance_x; |
| 371 } else if (is_cluster_end) { | 386 } else if (is_cluster_end) { |
| 372 uint16_t cluster_end; | 387 uint16_t cluster_end; |
| 373 if (direction == TextDirection::kRtl) { | 388 if (direction == TextDirection::kRtl) { |
| 374 cluster_end = current_character_index; | 389 cluster_end = current_character_index; |
| 375 } else { | 390 } else { |
| 376 cluster_end = static_cast<uint16_t>( | 391 cluster_end = static_cast<uint16_t>( |
| 377 is_run_end ? run->start_index_ + run->num_characters_ + run_offset | 392 is_run_end ? run->start_index_ + run->num_characters_ + run_offset |
| 378 : run->GlyphToCharacterIndex(i + 1) + run_offset); | 393 : run->GlyphToCharacterIndex(i + 1) + run_offset); |
| 379 } | 394 } |
| 380 graphemes_in_cluster = CountGraphemesInCluster( | 395 graphemes_in_cluster = CountGraphemesInCluster( |
| 381 text_run.Characters16(), text_run.CharactersLength(), cluster_start, | 396 text.Characters16(), text_length, cluster_start, cluster_end); |
| 382 cluster_end); | |
| 383 if (!graphemes_in_cluster || !cluster_advance) | 397 if (!graphemes_in_cluster || !cluster_advance) |
| 384 continue; | 398 continue; |
| 385 | 399 |
| 386 float glyph_advance_x = cluster_advance / graphemes_in_cluster; | 400 float glyph_advance_x = cluster_advance / graphemes_in_cluster; |
| 387 for (unsigned j = 0; j < graphemes_in_cluster; ++j) { | 401 for (unsigned j = 0; j < graphemes_in_cluster; ++j) { |
| 388 // Do not put emphasis marks on space, separator, and control | 402 // Do not put emphasis marks on space, separator, and control |
| 389 // characters. | 403 // characters. |
| 390 if (Character::CanReceiveTextEmphasis( | 404 if (Character::CanReceiveTextEmphasis(text[current_character_index])) { |
| 391 text_run[current_character_index])) { | |
| 392 AddEmphasisMark(*this, emphasis_data, glyph_center, | 405 AddEmphasisMark(*this, emphasis_data, glyph_center, |
| 393 advance_so_far + glyph_advance_x / 2); | 406 advance_so_far + glyph_advance_x / 2); |
| 394 } | 407 } |
| 395 advance_so_far += glyph_advance_x; | 408 advance_so_far += glyph_advance_x; |
| 396 } | 409 } |
| 397 cluster_start = cluster_end; | 410 cluster_start = cluster_end; |
| 398 cluster_advance = 0; | 411 cluster_advance = 0; |
| 399 } | 412 } |
| 400 } | 413 } |
| 401 return advance_so_far - initial_advance; | 414 return advance_so_far - initial_advance; |
| 402 } | 415 } |
| 403 | 416 |
| 404 } // namespace blink | 417 } // namespace blink |
| OLD | NEW |