Commit dcf55c3a authored by Koji Ishii's avatar Koji Ishii Committed by Commit Bot

Pass the source string to ShapeResult functions

This patch changes OffsetForPosition and PositionForOffset
functions to accept its source string, and let callers to
pass them.

The given strings are not used yet in this patch, other than
DCHECK with the number of characters in the ShapeResult.

Computing grapheme cluster list for all ShapeResult turned
out to be not cheap enough for LayoutNG that this patch is
the preparation to compute them when needed.

Bug: 636993
Cq-Include-Trybots: luci.chromium.try:linux_layout_tests_layout_ng
Change-Id: I6dc22fda781f63219fba74381da87f1f0b33e85f
Reviewed-on: https://chromium-review.googlesource.com/1118062
Commit-Queue: Koji Ishii <kojii@chromium.org>
Commit-Queue: Emil A Eklund <eae@chromium.org>
Reviewed-by: default avatarEmil A Eklund <eae@chromium.org>
Cr-Commit-Position: refs/heads/master@{#578525}
parent 8fa347f1
...@@ -42,7 +42,8 @@ LayoutUnit NGPhysicalTextFragment::InlinePositionForOffset( ...@@ -42,7 +42,8 @@ LayoutUnit NGPhysicalTextFragment::InlinePositionForOffset(
offset -= start_offset_; offset -= start_offset_;
if (shape_result_) { if (shape_result_) {
return round(shape_result_->PositionForOffset(offset, adjust_mid_cluster)); return round(shape_result_->CaretPositionForOffset(offset, Text(),
adjust_mid_cluster));
} }
// This fragment is a flow control because otherwise ShapeResult exists. // This fragment is a flow control because otherwise ShapeResult exists.
...@@ -192,8 +193,8 @@ unsigned NGPhysicalTextFragment::TextOffsetForPoint( ...@@ -192,8 +193,8 @@ unsigned NGPhysicalTextFragment::TextOffsetForPoint(
const LayoutUnit& point_in_line_direction = const LayoutUnit& point_in_line_direction =
style.IsHorizontalWritingMode() ? point.left : point.top; style.IsHorizontalWritingMode() ? point.left : point.top;
if (const ShapeResult* shape_result = TextShapeResult()) { if (const ShapeResult* shape_result = TextShapeResult()) {
return shape_result->OffsetForPosition(point_in_line_direction.ToFloat(), return shape_result->CaretOffsetForHitTest(
IncludePartialGlyphs, BreakGlyphs) + point_in_line_direction.ToFloat(), Text(), BreakGlyphs) +
StartOffset(); StartOffset();
} }
......
...@@ -103,7 +103,8 @@ CharacterRange CachingWordShaper::GetCharacterRange(const TextRun& run, ...@@ -103,7 +103,8 @@ CharacterRange CachingWordShaper::GetCharacterRange(const TextRun& run,
ShapeResultBuffer buffer; ShapeResultBuffer buffer;
float total_width = ShapeResultsForRun(GetShapeCache(), &font_, run, &buffer); float total_width = ShapeResultsForRun(GetShapeCache(), &font_, run, &buffer);
return buffer.GetCharacterRange(total_width, run.Direction(), from, to); return buffer.GetCharacterRange(run.ToStringView(), run.Direction(),
total_width, from, to);
} }
Vector<CharacterRange> CachingWordShaper::IndividualCharacterRanges( Vector<CharacterRange> CachingWordShaper::IndividualCharacterRanges(
......
...@@ -369,10 +369,12 @@ size_t ShapeResult::ByteSize() const { ...@@ -369,10 +369,12 @@ size_t ShapeResult::ByteSize() const {
return self_byte_size; return self_byte_size;
} }
CharacterRange ShapeResult::GetCharacterRange(unsigned from, CharacterRange ShapeResult::GetCharacterRange(const StringView& text,
unsigned from,
unsigned to) const { unsigned to) const {
return ShapeResultBuffer::GetCharacterRange(this, Direction(), Width(), from, DCHECK_EQ(NumCharacters(), text.length());
to); return ShapeResultBuffer::GetCharacterRange(this, text, Direction(), Width(),
from, to);
} }
unsigned ShapeResult::StartIndexForResult() const { unsigned ShapeResult::StartIndexForResult() const {
...@@ -537,9 +539,12 @@ unsigned ShapeResult::OffsetForPosition( ...@@ -537,9 +539,12 @@ unsigned ShapeResult::OffsetForPosition(
return result.right_character_index; return result.right_character_index;
} }
unsigned ShapeResult::OffsetForHitTest( unsigned ShapeResult::CaretOffsetForHitTest(
float x, float x,
const StringView& text,
BreakGlyphsOption break_glyphs_option) const { BreakGlyphsOption break_glyphs_option) const {
DCHECK_EQ(NumCharacters(), text.length());
GlyphIndexResult result; GlyphIndexResult result;
OffsetForPosition(x, break_glyphs_option, &result); OffsetForPosition(x, break_glyphs_option, &result);
...@@ -603,6 +608,14 @@ float ShapeResult::PositionForOffset( ...@@ -603,6 +608,14 @@ float ShapeResult::PositionForOffset(
return offset_x; return offset_x;
} }
float ShapeResult::CaretPositionForOffset(
unsigned offset,
const StringView& text,
AdjustMidCluster adjust_mid_cluster) const {
DCHECK_EQ(NumCharacters(), text.length());
return PositionForOffset(offset, adjust_mid_cluster);
}
void ShapeResult::FallbackFonts( void ShapeResult::FallbackFonts(
HashSet<const SimpleFontData*>* fallback) const { HashSet<const SimpleFontData*>* fallback) const {
DCHECK(fallback); DCHECK(fallback);
......
...@@ -111,7 +111,9 @@ class PLATFORM_EXPORT ShapeResult : public RefCounted<ShapeResult> { ...@@ -111,7 +111,9 @@ class PLATFORM_EXPORT ShapeResult : public RefCounted<ShapeResult> {
// even when the result is in vertical flow. // even when the result is in vertical flow.
const FloatRect& Bounds() const { return glyph_bounding_box_; } const FloatRect& Bounds() const { return glyph_bounding_box_; }
unsigned NumCharacters() const { return num_characters_; } unsigned NumCharacters() const { return num_characters_; }
CharacterRange GetCharacterRange(unsigned from, unsigned to) const; CharacterRange GetCharacterRange(const StringView& text,
unsigned from,
unsigned to) const;
// The character start/end index of a range shape result. // The character start/end index of a range shape result.
unsigned StartIndexForResult() const; unsigned StartIndexForResult() const;
unsigned EndIndexForResult() const; unsigned EndIndexForResult() const;
...@@ -145,21 +147,29 @@ class PLATFORM_EXPORT ShapeResult : public RefCounted<ShapeResult> { ...@@ -145,21 +147,29 @@ class PLATFORM_EXPORT ShapeResult : public RefCounted<ShapeResult> {
// whether |x| is on the left-half or the right-half of the glyph, it // whether |x| is on the left-half or the right-half of the glyph, it
// determines the left-boundary or the right-boundary, then computes the // determines the left-boundary or the right-boundary, then computes the
// offset from the bidi direction. // offset from the bidi direction.
unsigned OffsetForHitTest(float x, BreakGlyphsOption) const; unsigned CaretOffsetForHitTest(float x,
const StringView& text,
BreakGlyphsOption) const;
// Returns the offset that can fit to between |x| and the left or the right // Returns the offset that can fit to between |x| and the left or the right
// edge. The side of the edge is determined by |line_direction|. // edge. The side of the edge is determined by |line_direction|.
unsigned OffsetToFit(float x, TextDirection line_direction) const; unsigned OffsetToFit(float x, TextDirection line_direction) const;
unsigned OffsetForPosition(float x, unsigned OffsetForPosition(float x,
const StringView& text,
IncludePartialGlyphsOption include_partial_glyphs, IncludePartialGlyphsOption include_partial_glyphs,
BreakGlyphsOption break_glyphs_option) const { BreakGlyphsOption break_glyphs_option) const {
return include_partial_glyphs == OnlyFullGlyphs return include_partial_glyphs == OnlyFullGlyphs
? OffsetForPosition(x, break_glyphs_option) ? OffsetForPosition(x, break_glyphs_option)
: OffsetForHitTest(x, break_glyphs_option); : CaretOffsetForHitTest(x, text, break_glyphs_option);
} }
// Returns the position for a given offset, relative to StartIndexForResult. // Returns the position for a given offset, relative to StartIndexForResult.
float PositionForOffset(unsigned offset, float PositionForOffset(unsigned offset,
AdjustMidCluster = AdjustMidCluster::kToEnd) const; AdjustMidCluster = AdjustMidCluster::kToEnd) const;
// Similar to |PositionForOffset| with mid-glyph (mid-ligature) support.
float CaretPositionForOffset(
unsigned offset,
const StringView& text,
AdjustMidCluster = AdjustMidCluster::kToEnd) const;
LayoutUnit SnappedStartPositionForOffset(unsigned offset) const { LayoutUnit SnappedStartPositionForOffset(unsigned offset) const {
return LayoutUnit::FromFloatFloor(PositionForOffset(offset)); return LayoutUnit::FromFloatFloor(PositionForOffset(offset));
} }
......
...@@ -13,34 +13,53 @@ ...@@ -13,34 +13,53 @@
namespace blink { namespace blink {
namespace {
unsigned CharactersInShapeResult(
const Vector<scoped_refptr<const ShapeResult>, 64>& results) {
unsigned num_characters = 0;
for (const scoped_refptr<const ShapeResult>& result : results)
num_characters += result->NumCharacters();
return num_characters;
}
} // namespace
// TODO(eae): This is a bit of a hack to allow reuse of the implementation // TODO(eae): This is a bit of a hack to allow reuse of the implementation
// for both ShapeResultBuffer and single ShapeResult use cases. Ideally the // for both ShapeResultBuffer and single ShapeResult use cases. Ideally the
// logic should move into ShapeResult itself and then the ShapeResultBuffer // logic should move into ShapeResult itself and then the ShapeResultBuffer
// implementation may wrap that. // implementation may wrap that.
CharacterRange ShapeResultBuffer::GetCharacterRange( CharacterRange ShapeResultBuffer::GetCharacterRange(
scoped_refptr<const ShapeResult> result, scoped_refptr<const ShapeResult> result,
const StringView& text,
TextDirection direction, TextDirection direction,
float total_width, float total_width,
unsigned from, unsigned from,
unsigned to) { unsigned to) {
Vector<scoped_refptr<const ShapeResult>, 64> results; Vector<scoped_refptr<const ShapeResult>, 64> results;
results.push_back(result); results.push_back(result);
return GetCharacterRangeInternal(results, direction, total_width, from, to); return GetCharacterRangeInternal(results, text, direction, total_width, from,
to);
} }
CharacterRange ShapeResultBuffer::GetCharacterRange(float total_width, CharacterRange ShapeResultBuffer::GetCharacterRange(const StringView& text,
TextDirection direction, TextDirection direction,
float total_width,
unsigned from, unsigned from,
unsigned to) const { unsigned to) const {
return GetCharacterRangeInternal(results_, direction, total_width, from, to); return GetCharacterRangeInternal(results_, text, direction, total_width, from,
to);
} }
CharacterRange ShapeResultBuffer::GetCharacterRangeInternal( CharacterRange ShapeResultBuffer::GetCharacterRangeInternal(
const Vector<scoped_refptr<const ShapeResult>, 64>& results, const Vector<scoped_refptr<const ShapeResult>, 64>& results,
const StringView& text,
TextDirection direction, TextDirection direction,
float total_width, float total_width,
unsigned absolute_from, unsigned absolute_from,
unsigned absolute_to) { unsigned absolute_to) {
DCHECK_EQ(CharactersInShapeResult(results), text.length());
float current_x = 0; float current_x = 0;
float from_x = 0; float from_x = 0;
float to_x = 0; float to_x = 0;
...@@ -183,6 +202,7 @@ int ShapeResultBuffer::OffsetForPosition( ...@@ -183,6 +202,7 @@ int ShapeResultBuffer::OffsetForPosition(
float target_x, float target_x,
IncludePartialGlyphsOption partial_glyphs, IncludePartialGlyphsOption partial_glyphs,
BreakGlyphsOption break_glyphs) const { BreakGlyphsOption break_glyphs) const {
StringView text = run.ToStringView();
unsigned total_offset; unsigned total_offset;
if (run.Rtl()) { if (run.Rtl()) {
total_offset = run.length(); total_offset = run.length();
...@@ -193,22 +213,26 @@ int ShapeResultBuffer::OffsetForPosition( ...@@ -193,22 +213,26 @@ int ShapeResultBuffer::OffsetForPosition(
total_offset -= word_result->NumCharacters(); total_offset -= word_result->NumCharacters();
if (target_x >= 0 && target_x <= word_result->Width()) { if (target_x >= 0 && target_x <= word_result->Width()) {
int offset_for_word = word_result->OffsetForPosition( int offset_for_word = word_result->OffsetForPosition(
target_x, partial_glyphs, break_glyphs); target_x,
StringView(text, total_offset, word_result->NumCharacters()),
partial_glyphs, break_glyphs);
return total_offset + offset_for_word; return total_offset + offset_for_word;
} }
target_x -= word_result->Width(); target_x -= word_result->Width();
} }
} else { } else {
total_offset = 0; total_offset = 0;
for (const auto& word_result : results_) { for (const scoped_refptr<const ShapeResult>& word_result : results_) {
if (!word_result) if (!word_result)
continue; continue;
int offset_for_word = word_result->OffsetForPosition( int offset_for_word = word_result->OffsetForPosition(
target_x, partial_glyphs, break_glyphs); target_x, StringView(text, 0, word_result->NumCharacters()),
partial_glyphs, break_glyphs);
DCHECK_GE(offset_for_word, 0); DCHECK_GE(offset_for_word, 0);
total_offset += offset_for_word; total_offset += offset_for_word;
if (target_x >= 0 && target_x <= word_result->Width()) if (target_x >= 0 && target_x <= word_result->Width())
return total_offset; return total_offset;
text = StringView(text, word_result->NumCharacters());
target_x -= word_result->Width(); target_x -= word_result->Width();
} }
} }
......
...@@ -37,14 +37,16 @@ class PLATFORM_EXPORT ShapeResultBuffer { ...@@ -37,14 +37,16 @@ class PLATFORM_EXPORT ShapeResultBuffer {
float target_x, float target_x,
IncludePartialGlyphsOption, IncludePartialGlyphsOption,
BreakGlyphsOption) const; BreakGlyphsOption) const;
CharacterRange GetCharacterRange(float total_width, CharacterRange GetCharacterRange(const StringView& text,
TextDirection, TextDirection,
float total_width,
unsigned from, unsigned from,
unsigned to) const; unsigned to) const;
Vector<CharacterRange> IndividualCharacterRanges(TextDirection, Vector<CharacterRange> IndividualCharacterRanges(TextDirection,
float total_width) const; float total_width) const;
static CharacterRange GetCharacterRange(scoped_refptr<const ShapeResult>, static CharacterRange GetCharacterRange(scoped_refptr<const ShapeResult>,
const StringView& text,
TextDirection, TextDirection,
float total_width, float total_width,
unsigned from, unsigned from,
...@@ -60,6 +62,7 @@ class PLATFORM_EXPORT ShapeResultBuffer { ...@@ -60,6 +62,7 @@ class PLATFORM_EXPORT ShapeResultBuffer {
friend class ShapeResultBloberizer; friend class ShapeResultBloberizer;
static CharacterRange GetCharacterRangeInternal( static CharacterRange GetCharacterRangeInternal(
const Vector<scoped_refptr<const ShapeResult>, 64>&, const Vector<scoped_refptr<const ShapeResult>, 64>&,
const StringView& text,
TextDirection, TextDirection,
float total_width, float total_width,
unsigned from, unsigned from,
......
...@@ -174,6 +174,11 @@ class PLATFORM_EXPORT TextRun final { ...@@ -174,6 +174,11 @@ class PLATFORM_EXPORT TextRun final {
return data_.characters16; return data_.characters16;
} }
StringView ToStringView() const {
return Is8Bit() ? StringView(data_.characters8, len_)
: StringView(data_.characters16, len_);
}
UChar32 CodepointAt(unsigned i) const { UChar32 CodepointAt(unsigned i) const {
SECURITY_DCHECK(i < len_); SECURITY_DCHECK(i < len_);
if (Is8Bit()) if (Is8Bit())
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment