diff options
Diffstat (limited to 'chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_inline_headers.h')
-rw-r--r-- | chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_inline_headers.h | 162 |
1 files changed, 120 insertions, 42 deletions
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_inline_headers.h b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_inline_headers.h index 38a9178c6e1..3609c766682 100644 --- a/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_inline_headers.h +++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_inline_headers.h @@ -37,22 +37,30 @@ #include "third_party/blink/renderer/platform/fonts/shaping/shape_result.h" #include "third_party/blink/renderer/platform/wtf/allocator.h" #include "third_party/blink/renderer/platform/wtf/noncopyable.h" +#include "third_party/blink/renderer/platform/wtf/vector.h" namespace blink { class SimpleFontData; +// This struct should be TriviallyCopyable so that std::copy() is equivalent to +// memcpy. struct HarfBuzzRunGlyphData { DISALLOW_NEW_EXCEPT_PLACEMENT_NEW(); + + static constexpr unsigned kMaxCharacterIndex = (1 << 15) - 1; + uint16_t glyph; - uint16_t character_index; + unsigned character_index : 15; + unsigned safe_to_break_before : 1; float advance; FloatSize offset; void SetGlyphAndPositions(uint16_t glyph_id, uint16_t character_index, float advance, - const FloatSize& offset); + const FloatSize& offset, + bool safe_to_break_before); }; struct ShapeResult::RunInfo { @@ -65,12 +73,14 @@ struct ShapeResult::RunInfo { hb_script_t script, unsigned start_index, unsigned num_glyphs, - unsigned num_characters) + unsigned num_characters, + Vector<unsigned> graphemes) : font_data_(const_cast<SimpleFontData*>(font)), direction_(dir), canvas_rotation_(canvas_rotation), script_(script), glyph_data_(num_glyphs), + graphemes_(graphemes), start_index_(start_index), num_characters_(num_characters), width_(0.0f) {} @@ -81,10 +91,12 @@ struct ShapeResult::RunInfo { canvas_rotation_(other.canvas_rotation_), script_(other.script_), glyph_data_(other.glyph_data_), + graphemes_(other.graphemes_), start_index_(other.start_index_), num_characters_(other.num_characters_), width_(other.width_) {} + unsigned NumGlyphs() const { return glyph_data_.size(); } bool Rtl() const { return HB_DIRECTION_IS_BACKWARD(direction_); } bool IsHorizontal() const { return HB_DIRECTION_IS_HORIZONTAL(direction_); } CanvasRotationInVertical CanvasRotation() const { return canvas_rotation_; } @@ -92,66 +104,100 @@ struct ShapeResult::RunInfo { unsigned PreviousSafeToBreakOffset(unsigned) const; float XPositionForVisualOffset(unsigned, AdjustMidCluster) const; float XPositionForOffset(unsigned, AdjustMidCluster) const; - void CharacterIndexForXPosition(float, GlyphIndexResult*) const; + void CharacterIndexForXPosition(float, + BreakGlyphsOption, + GlyphIndexResult*) const; + void SetGlyphAndPositions(unsigned index, + uint16_t glyph_id, + float advance, + float offset_x, + float offset_y); size_t GlyphToCharacterIndex(size_t i) const { return start_index_ + glyph_data_[i].character_index; } + unsigned NumGraphemes(unsigned start, unsigned end) const; + // For memory reporting. size_t ByteSize() const { return sizeof(this) + glyph_data_.size() * sizeof(HarfBuzzRunGlyphData); } + // Represents a range of HarfBuzzRunGlyphData. |begin| and |end| follow the + // iterator pattern; i.e., |begin| is lower or equal to |end| in the address + // space regardless of LTR/RTL. |begin| is inclusive, |end| is exclusive. + struct GlyphDataRange { + HarfBuzzRunGlyphData* begin; + HarfBuzzRunGlyphData* end; + }; + + // Find the range of HarfBuzzRunGlyphData for the specified character index + // range. This function uses binary search twice, hence O(2 log n). + GlyphDataRange FindGlyphDataRange(unsigned start_character_index, + unsigned end_character_index) { + const auto comparer = [](const HarfBuzzRunGlyphData& glyph_data, + unsigned index) { + return glyph_data.character_index < index; + }; + if (!Rtl()) { + HarfBuzzRunGlyphData* start_glyph = + std::lower_bound(glyph_data_.begin(), glyph_data_.end(), + start_character_index, comparer); + if (UNLIKELY(start_glyph == glyph_data_.end())) + return {nullptr, nullptr}; + HarfBuzzRunGlyphData* end_glyph = std::lower_bound( + start_glyph, glyph_data_.end(), end_character_index, comparer); + return {start_glyph, end_glyph}; + } + + // RTL needs to use reverse iterators because there maybe multiple glyphs + // for a character, and we want to find the first one in the logical order. + auto start_glyph = + std::lower_bound(glyph_data_.rbegin(), glyph_data_.rend(), + start_character_index, comparer); + if (UNLIKELY(start_glyph == glyph_data_.rend())) + return {nullptr, nullptr}; + auto end_glyph = std::lower_bound(start_glyph, glyph_data_.rend(), + end_character_index, comparer); + // Convert reverse iterators to pointers. Then increment to make |begin| + // inclusive and |end| exclusive. + return {&*end_glyph + 1, &*start_glyph + 1}; + } + // Creates a new RunInfo instance representing a subset of the current run. std::unique_ptr<RunInfo> CreateSubRun(unsigned start, unsigned end) { DCHECK(end > start); unsigned number_of_characters = std::min(end - start, num_characters_); + auto glyphs = FindGlyphDataRange(start, end); + unsigned number_of_glyphs = std::distance(glyphs.begin, glyphs.end); - // This ends up looping over the glyphs twice if we don't know the glyph - // count up front. Once to count the number of glyphs and allocate the new - // RunInfo object and then a second time to copy the glyphs over. - // TODO: Compared to the cost of allocation and copying the extra loop is - // probably fine but we might want to try to eliminate it if we can. - unsigned number_of_glyphs; - if (start == 0 && end == num_characters_) { - number_of_glyphs = glyph_data_.size(); - } else { - number_of_glyphs = 0; - ForEachGlyphInRange( - 0, start_index_ + start, start_index_ + end, 0, - [&](const HarfBuzzRunGlyphData&, float, uint16_t) -> bool { - number_of_glyphs++; - return true; - }); + Vector<unsigned> sub_graphemes; + if (graphemes_.size()) { + sub_graphemes.resize(number_of_characters); + for (unsigned i = 0; i < number_of_characters; ++i) { + sub_graphemes[i] = graphemes_[start + i]; + } } auto run = std::make_unique<RunInfo>( font_data_.get(), direction_, canvas_rotation_, script_, - start_index_ + start, number_of_glyphs, number_of_characters); + start_index_ + start, number_of_glyphs, number_of_characters, + std::move(sub_graphemes)); + + static_assert(base::is_trivially_copyable<HarfBuzzRunGlyphData>::value, + "HarfBuzzRunGlyphData should be trivially copyable"); + std::copy(glyphs.begin, glyphs.end, run->glyph_data_.begin()); - unsigned sub_glyph_index = 0; float total_advance = 0; - ForEachGlyphInRange( - 0, start_index_ + start, start_index_ + end, 0, - [&](const HarfBuzzRunGlyphData& glyph_data, float, uint16_t) -> bool { - HarfBuzzRunGlyphData& sub_glyph = run->glyph_data_[sub_glyph_index++]; - sub_glyph.glyph = glyph_data.glyph; - sub_glyph.character_index = glyph_data.character_index - start; - sub_glyph.advance = glyph_data.advance; - sub_glyph.offset = glyph_data.offset; - total_advance += glyph_data.advance; - return true; - }); + for (HarfBuzzRunGlyphData& glyph_data : run->glyph_data_) { + glyph_data.character_index -= start; + total_advance += glyph_data.advance; + } run->width_ = total_advance; run->num_characters_ = number_of_characters; - for (unsigned i = 0; i < safe_break_offsets_.size(); i++) { - if (safe_break_offsets_[i] >= start && safe_break_offsets_[i] <= end) - run->safe_break_offsets_.push_back(safe_break_offsets_[i] - start); - } - return run; } @@ -189,7 +235,7 @@ struct ShapeResult::RunInfo { initial_advance, [&](const HarfBuzzRunGlyphData& glyph_data, float total_advance) -> bool { - const uint16_t character_index = + const unsigned character_index = start_index_ + glyph_data.character_index + index_offset; if (character_index < from) { @@ -209,6 +255,36 @@ struct ShapeResult::RunInfo { }); } + void ExpandRangeToIncludePartialGlyphs(int offset, int* from, int* to) const { + int start = !Rtl() ? offset : (offset + num_characters_); + int end = offset + num_characters_; + + for (unsigned i = 0; i < glyph_data_.size(); ++i) { + int index = offset + glyph_data_[i].character_index; + if (start == index) + continue; + + if (!Rtl()) + end = index; + + if (end > *from && start < *to) { + *from = std::min(*from, start); + *to = std::max(*to, end); + } + + if (!Rtl()) + end = num_characters_; + else + end = start; + start = index; + } + + if (end > *from && start < *to) { + *from = std::min(*from, start); + *to = std::max(*to, end); + } + } + scoped_refptr<SimpleFontData> font_data_; hb_direction_t direction_; // For upright-in-vertical we need to tell the ShapeResultBloberizer to rotate @@ -216,9 +292,11 @@ struct ShapeResult::RunInfo { CanvasRotationInVertical canvas_rotation_; hb_script_t script_; Vector<HarfBuzzRunGlyphData> glyph_data_; - // List of character indecies before which it's safe to break without - // reshaping. - Vector<uint16_t> safe_break_offsets_; + + // graphemes_[i] is the number of graphemes up to (and including) the ith + // character in the run. + Vector<unsigned> graphemes_; + unsigned start_index_; unsigned num_characters_; float width_; |