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 |