Commit 45ed2663 authored by Fredrik Söderquist's avatar Fredrik Söderquist Committed by Commit Bot

Distribute widths evenly among code points in SynthesizeGraphemeWidths

Previously we did not consider the possibility of a typographic unit
containing multiple surrogate pairs, and could as an effect "lose" part
of the width.

Distribute the width evenly among code points instead to at least get
some sort of consistency.

Bug: 879361
Change-Id: I51a4e6c574926215a087b0bc824ac90d580ff169
Reviewed-on: https://chromium-review.googlesource.com/1199423Reviewed-by: default avatarPhilip Rogers <pdr@chromium.org>
Commit-Queue: Fredrik Söderquist <fs@opera.com>
Cr-Commit-Position: refs/heads/master@{#588183}
parent a2b6b8e7
<!DOCTYPE html>
<meta charset="utf-8">
<title>SVGTextContentElement.getSubStringLength on Emoji with ligatures</title>
<script src="../../resources/testharness.js"></script>
<script src="../../resources/testharnessreport.js"></script>
<svg>
<g font-family="Comic Sans MS" font-size="50" text-rendering="geometricPrecision">
<text y="50">👦</text>
<text y="100">👨‍👩‍👧‍👦</text>
<text y="50" x="100">👨‍</text>
<text y="100" x="100">👩🏽‍🌾</text>
<text y="50" x="150">👨‍👦</text>
<text y="100" x="150">👱🏽‍♂️</text>
<text y="50" x="200">🎅🏽</text>
</g>
</svg>
<script>
test(function() {
const textElements = document.getElementsByTagName('text');
for (let i = 0; i < textElements.length; i++) {
const element = textElements[i];
const subStringLength = element.getSubStringLength(0, element.getNumberOfChars());
const bboxWidth = element.getBBox().width;
// Expect the value computed by getSubStringLength() to roughly
// match the value computed for the bbox.
assert_approx_equals(subStringLength, bboxWidth, 1);
}
});
</script>
...@@ -225,6 +225,17 @@ inline bool IsValidSurrogatePair(const TextRun& run, unsigned index) { ...@@ -225,6 +225,17 @@ inline bool IsValidSurrogatePair(const TextRun& run, unsigned index) {
return U16_IS_TRAIL(run[index + 1]); return U16_IS_TRAIL(run[index + 1]);
} }
unsigned CountCodePoints(const TextRun& run,
unsigned index,
unsigned end_index) {
unsigned num_codepoints = 0;
while (index < end_index) {
index += IsValidSurrogatePair(run, index) ? 2 : 1;
num_codepoints++;
}
return num_codepoints;
}
TextRun ConstructTextRun(LayoutSVGInlineText& text, TextRun ConstructTextRun(LayoutSVGInlineText& text,
unsigned position, unsigned position,
unsigned length, unsigned length,
...@@ -270,28 +281,29 @@ void SynthesizeGraphemeWidths(const TextRun& run, ...@@ -270,28 +281,29 @@ void SynthesizeGraphemeWidths(const TextRun& run,
CharacterRange& current_range = ranges[range_index]; CharacterRange& current_range = ranges[range_index];
if (current_range.Width() == 0) { if (current_range.Width() == 0) {
distribute_count++; distribute_count++;
} else if (distribute_count != 0) { continue;
// Only count surrogate pairs as a single character.
bool surrogate_pair = IsValidSurrogatePair(run, range_index);
if (!surrogate_pair)
distribute_count++;
float new_width = current_range.Width() / distribute_count;
current_range.end = current_range.start + new_width;
float last_end_position = current_range.end;
for (unsigned distribute = 1; distribute < distribute_count;
distribute++) {
// This surrogate pair check will skip processing of the second
// character forming the surrogate pair.
unsigned distribute_index =
range_index + distribute + (surrogate_pair ? 1 : 0);
ranges[distribute_index].start = last_end_position;
ranges[distribute_index].end = last_end_position + new_width;
last_end_position = ranges[distribute_index].end;
}
distribute_count = 0;
} }
if (distribute_count == 0)
continue;
distribute_count++;
// Distribute the width evenly among the code points.
const unsigned distribute_end = range_index + distribute_count;
unsigned num_codepoints = CountCodePoints(run, range_index, distribute_end);
DCHECK_GT(num_codepoints, 0u);
float new_width = current_range.Width() / num_codepoints;
float last_end_position = current_range.start;
unsigned distribute_index = range_index;
do {
CharacterRange& range = ranges[distribute_index];
range.start = last_end_position;
range.end = last_end_position + new_width;
last_end_position = range.end;
distribute_index += IsValidSurrogatePair(run, distribute_index) ? 2 : 1;
} while (distribute_index < distribute_end);
distribute_count = 0;
} }
} }
......
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