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 |