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 <map> | 7 #include <map> |
| 8 | 8 |
| 9 #include "base/i18n/break_iterator.h" | 9 #include "base/i18n/break_iterator.h" |
| 10 #include "base/i18n/char_iterator.h" | 10 #include "base/i18n/char_iterator.h" |
| (...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 338 diagonal_strike(false), | 338 diagonal_strike(false), |
| 339 underline(false) {} | 339 underline(false) {} |
| 340 | 340 |
| 341 TextRunHarfBuzz::~TextRunHarfBuzz() {} | 341 TextRunHarfBuzz::~TextRunHarfBuzz() {} |
| 342 | 342 |
| 343 size_t TextRunHarfBuzz::CharToGlyph(size_t pos) const { | 343 size_t TextRunHarfBuzz::CharToGlyph(size_t pos) const { |
| 344 DCHECK(range.start() <= pos && pos < range.end()); | 344 DCHECK(range.start() <= pos && pos < range.end()); |
| 345 | 345 |
| 346 if (direction == UBIDI_LTR) { | 346 if (direction == UBIDI_LTR) { |
| 347 for (size_t i = 0; i < glyph_count - 1; ++i) { | 347 for (size_t i = 0; i < glyph_count - 1; ++i) { |
| 348 if (pos < glyph_to_char[i + 1]) | 348 if (pos < glyph_to_char[i + 1]) |
|
msw
2014/06/02 19:37:58
For logical LTR string "a" that yields two glyphs
msw
2014/06/03 22:32:09
What about this? LMK if I'm wrong or how we should
ckocagil
2014/06/05 06:51:59
This should be fixed now.
| |
| 349 return i; | 349 return i; |
| 350 } | 350 } |
| 351 return glyph_count - 1; | 351 return glyph_count - 1; |
| 352 } | 352 } |
| 353 | 353 |
| 354 for (size_t i = 0; i < glyph_count; ++i) { | 354 for (size_t i = 0; i < glyph_count; ++i) { |
| 355 if (pos >= glyph_to_char[i]) | 355 if (pos >= glyph_to_char[i]) |
| 356 return i; | 356 return i; |
| 357 } | 357 } |
| 358 NOTREACHED(); | 358 NOTREACHED(); |
| 359 return 0; | 359 return 0; |
| 360 } | 360 } |
| 361 | 361 |
| 362 Range TextRunHarfBuzz::CharRangeToGlyphRange(const Range& range) const { | 362 Range TextRunHarfBuzz::CharRangeToGlyphRange(const Range& char_range) const { |
| 363 DCHECK(range.Contains(range)); | 363 DCHECK(range.Contains(char_range)); |
| 364 DCHECK(!range.is_reversed()); | 364 DCHECK(!char_range.is_reversed()); |
| 365 DCHECK(!range.is_empty()); | 365 DCHECK(!char_range.is_empty()); |
| 366 | 366 |
| 367 const size_t first = CharToGlyph(range.start()); | 367 size_t first = 0; |
| 368 const size_t last = CharToGlyph(range.end() - 1); | 368 size_t last = 0; |
| 369 // TODO(ckocagil): What happens when the character has zero or multiple | 369 |
| 370 // glyphs? Is the "+ 1" below correct then? | 370 if (direction == UBIDI_RTL) { |
| 371 return Range(std::min(first, last), std::max(first, last) + 1); | 371 // For RTL runs, we subtract 1 from |char_range| to get the trailing edges. |
|
msw
2014/05/28 01:18:30
nit: the meaning of "to get the trailing edges" is
ckocagil
2014/06/02 02:57:42
I tried to find a better way to explain this, but
msw
2014/06/02 19:37:58
So a char range of [1,2) would yield "[c)ba" witho
ckocagil
2014/06/03 22:25:17
What I mean by trailing is: imagine if CharToGlyph
| |
| 372 first = char_range.start() == range.start() ? | |
| 373 glyph_count : CharToGlyph(char_range.start() - 1); | |
| 374 last = CharToGlyph(char_range.end() - 1); | |
| 375 } else { | |
| 376 first = CharToGlyph(char_range.start()); | |
| 377 last = char_range.end() == range.end() ? | |
| 378 glyph_count : CharToGlyph(char_range.end()); | |
|
msw
2014/05/28 00:52:33
This doesn't seem right. It seems like if the end
ckocagil
2014/05/28 01:02:02
|char_range.end() == range.end()| doesn't mean "la
msw
2014/05/28 01:18:30
Ah, that makes more way more sense.
| |
| 379 } | |
| 380 return Range(std::min(first, last), std::max(first, last)); | |
| 372 } | 381 } |
| 373 | 382 |
| 374 // Returns whether the given shaped run contains any missing glyphs. | 383 // Returns whether the given shaped run contains any missing glyphs. |
| 375 bool TextRunHarfBuzz::HasMissingGlyphs() const { | 384 bool TextRunHarfBuzz::HasMissingGlyphs() const { |
| 376 static const int kMissingGlyphId = 0; | 385 static const int kMissingGlyphId = 0; |
| 377 for (size_t i = 0; i < glyph_count; ++i) { | 386 for (size_t i = 0; i < glyph_count; ++i) { |
| 378 if (glyphs[i] == kMissingGlyphId) | 387 if (glyphs[i] == kMissingGlyphId) |
| 379 return true; | 388 return true; |
| 380 } | 389 } |
| 381 return false; | 390 return false; |
| (...skipping 542 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 924 // Shape the text. | 933 // Shape the text. |
| 925 hb_shape(harfbuzz_font, buffer, NULL, 0); | 934 hb_shape(harfbuzz_font, buffer, NULL, 0); |
| 926 | 935 |
| 927 // Populate the run fields with the resulting glyph data in the buffer. | 936 // Populate the run fields with the resulting glyph data in the buffer. |
| 928 unsigned int glyph_count = 0; | 937 unsigned int glyph_count = 0; |
| 929 hb_glyph_info_t* infos = hb_buffer_get_glyph_infos(buffer, &glyph_count); | 938 hb_glyph_info_t* infos = hb_buffer_get_glyph_infos(buffer, &glyph_count); |
| 930 hb_glyph_position_t* hb_positions = hb_buffer_get_glyph_positions(buffer, | 939 hb_glyph_position_t* hb_positions = hb_buffer_get_glyph_positions(buffer, |
| 931 NULL); | 940 NULL); |
| 932 run->glyph_count = glyph_count; | 941 run->glyph_count = glyph_count; |
| 933 run->glyphs.reset(new uint16[run->glyph_count]); | 942 run->glyphs.reset(new uint16[run->glyph_count]); |
| 934 run->glyph_to_char.reset(new uint32[run->glyph_count]); | 943 run->glyph_to_char.reset(new uint32[run->glyph_count]); |
|
msw
2014/06/06 02:00:42
Would it be helpful and prudent to make a similar
ckocagil
2014/06/07 05:40:33
It would be helpful, but this is a trade off betwe
| |
| 935 run->positions.reset(new SkPoint[run->glyph_count]); | 944 run->positions.reset(new SkPoint[run->glyph_count]); |
| 936 for (size_t i = 0; i < run->glyph_count; ++i) { | 945 for (size_t i = 0; i < run->glyph_count; ++i) { |
| 937 run->glyphs[i] = infos[i].codepoint; | 946 run->glyphs[i] = infos[i].codepoint; |
| 938 run->glyph_to_char[i] = infos[i].cluster; | 947 run->glyph_to_char[i] = infos[i].cluster; |
| 939 const int x_offset = | 948 const int x_offset = |
| 940 SkScalarRoundToInt(SkFixedToScalar(hb_positions[i].x_offset)); | 949 SkScalarRoundToInt(SkFixedToScalar(hb_positions[i].x_offset)); |
| 941 const int y_offset = | 950 const int y_offset = |
| 942 SkScalarRoundToInt(SkFixedToScalar(hb_positions[i].y_offset)); | 951 SkScalarRoundToInt(SkFixedToScalar(hb_positions[i].y_offset)); |
| 943 run->positions[i].set(run->width + x_offset, y_offset); | 952 run->positions[i].set(run->width + x_offset, y_offset); |
| 944 run->width += | 953 run->width += |
| 945 SkScalarRoundToInt(SkFixedToScalar(hb_positions[i].x_advance)); | 954 SkScalarRoundToInt(SkFixedToScalar(hb_positions[i].x_advance)); |
| 946 } | 955 } |
| 947 | 956 |
| 948 hb_buffer_destroy(buffer); | 957 hb_buffer_destroy(buffer); |
| 949 hb_font_destroy(harfbuzz_font); | 958 hb_font_destroy(harfbuzz_font); |
| 950 } | 959 } |
| 951 | 960 |
| 952 } // namespace gfx | 961 } // namespace gfx |
| OLD | NEW |