Bug 1906978 - Fix the positioning/anchoring of SVG text runs with bidi control characters. a=dmeehan

The added reftests here failed both prior to and after the bidi-engine update,
although the exact nature of the failures changed due to the engine leaving the
bidi control characters in different places in the reordered text. (This is
explicitly unspecified by the Unicode Bidi Algorithm, because the control codes
are nominally removed after processing; leaving them present but invisible is
an implementation detail.)

The key fix here is that DoGlyphPositioning() anchors the first *addressable*
character of the text, not necessarily the absolute first codepoint, as that
may be a "deleted" control code whose position is arbitrary.

Original Revision: https://phabricator.services.mozilla.com/D216400

Differential Revision: https://phabricator.services.mozilla.com/D216527
This commit is contained in:
Jonathan Kew 2024-07-17 15:08:42 +00:00
parent fb2362783b
commit 78f1bf88f1
5 changed files with 179 additions and 11 deletions

View file

@ -4733,8 +4733,8 @@ void SVGTextFrame::DoAnchoring() {
}
bool vertical = GetWritingMode().IsVertical();
uint32_t start = it.TextElementCharIndex();
while (start < mPositions.Length()) {
for (uint32_t start = it.TextElementCharIndex(); start < mPositions.Length();
start = it.TextElementCharIndex()) {
it.AdvanceToCharacter(start);
nsTextFrame* chunkFrame = it.TextFrame();
@ -4770,8 +4770,6 @@ void SVGTextFrame::DoAnchoring() {
ShiftAnchoredChunk(mPositions, start, end, left, right, anchor, vertical);
}
start = it.TextElementCharIndex();
}
}
@ -4834,15 +4832,19 @@ void SVGTextFrame::DoGlyphPositioning() {
TruncateTo(deltas, charPositions);
TruncateTo(mPositions, charPositions);
// Fill in an unspecified character position at index 0.
if (!mPositions[0].IsXSpecified()) {
mPositions[0].mPosition.x = 0.0;
// Fill in an unspecified position for the first addressable character.
uint32_t first = 0;
while (first + 1 < mPositions.Length() && mPositions[first].mUnaddressable) {
++first;
}
if (!mPositions[0].IsYSpecified()) {
mPositions[0].mPosition.y = 0.0;
if (!mPositions[first].IsXSpecified()) {
mPositions[first].mPosition.x = 0.0;
}
if (!mPositions[0].IsAngleSpecified()) {
mPositions[0].mAngle = 0.0;
if (!mPositions[first].IsYSpecified()) {
mPositions[first].mPosition.y = 0.0;
}
if (!mPositions[first].IsAngleSpecified()) {
mPositions[first].mAngle = 0.0;
}
nsPresContext* presContext = PresContext();

View file

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="400" height="400" xmlns="http://www.w3.org/2000/svg" xmlns:html="http://www.w3.org/1999/xhtml">
<title>Text anchors and bidi control characters</title>
<html:link rel="author" title="Jonathan Kew" href="mailto:jkew@mozilla.com"/>
<g font-family="Arial, sans-serif" font-size="12px">
<line x1="200" y1="20" x2="200" y2="320" stroke="black" stroke-width="0.5"/>
<text x="200" y="40" style="fill: red" text-anchor="start">Start Anchor</text>
<text x="200" y="50" style="fill: green" text-anchor="middle">Middle Anchor</text>
<text x="200" y="60" style="fill: blue" text-anchor="end">End Anchor</text>
<text x="200" y="80" style="fill: red" text-anchor="start">Start Anchor</text>
<text x="200" y="90" style="fill: green" text-anchor="middle">Middle Anchor</text>
<text x="200" y="100" style="fill: blue" text-anchor="end">End Anchor</text>
<text x="200" y="120" style="fill: red" text-anchor="start">Start Anchor</text>
<text x="200" y="130" style="fill: green" text-anchor="middle">Middle Anchor</text>
<text x="200" y="140" style="fill: blue" text-anchor="end">End Anchor</text>
<text x="200" y="160" style="fill: red" text-anchor="start">Start Anchor</text>
<text x="200" y="170" style="fill: green" text-anchor="middle">Middle Anchor</text>
<text x="200" y="180" style="fill: blue" text-anchor="end">End Anchor</text>
<text x="200" y="200" style="fill: red" text-anchor="start">rohcnA tratS</text>
<text x="200" y="210" style="fill: green" text-anchor="middle">rohcnA elddiM</text>
<text x="200" y="220" style="fill: blue" text-anchor="end">rohcnA dnE</text>
<text x="200" y="240" style="fill: red" text-anchor="start">tratS Anchor</text>
<text x="200" y="250" style="fill: green" text-anchor="middle">elddiM Anchor</text>
<text x="200" y="260" style="fill: blue" text-anchor="end">dnE Anchor</text>
<text x="200" y="280" style="fill: red" text-anchor="start">Start rohcnA</text>
<text x="200" y="290" style="fill: green" text-anchor="middle">Middle rohcnA</text>
<text x="200" y="300" style="fill: blue" text-anchor="end">End rohcnA</text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

View file

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="400" height="400" xmlns="http://www.w3.org/2000/svg" xmlns:html="http://www.w3.org/1999/xhtml">
<title>Text anchors and bidi control characters</title>
<html:link rel="author" title="Jonathan Kew" href="mailto:jkew@mozilla.com"/>
<html:link rel="help" href="https://svgwg.org/svg2-draft/text.html#TextAnchoringProperties"/>
<html:link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1906978"/>
<html:link rel="match" href="text-bidi-controls-anchors-1-ref.svg"/>
<g transform="translate(200,20)" font-family="Arial, sans-serif" font-size="12px">
<line x1="0" y1="0" x2="0" y2="300" stroke="black" stroke-width="0.5"/>
<g transform="translate(0,20)">
<text style="fill: red" text-anchor="start">Start Anchor</text>
<text y="10" style="fill: green" text-anchor="middle">Middle Anchor</text>
<text y="20" style="fill: blue" text-anchor="end">End Anchor</text>
</g>
<g transform="translate(0,60)">
<text style="fill: red" text-anchor="start">&#x202b;Start Anchor&#x202c;</text>
<text y="10" style="fill: green" text-anchor="middle">&#x202b;Middle Anchor&#x202c;</text>
<text y="20" style="fill: blue" text-anchor="end">&#x202b;End Anchor&#x202c;</text>
</g>
<g transform="translate(0,100)">
<text style="fill: red" text-anchor="start">&#x202b;Start&#x202c; Anchor</text>
<text y="10" style="fill: green" text-anchor="middle">&#x202b;Middle&#x202c; Anchor</text>
<text y="20" style="fill: blue" text-anchor="end">&#x202b;End&#x202c; Anchor</text>
</g>
<g transform="translate(0,140)">
<text style="fill: red" text-anchor="start">Start &#x202b;Anchor&#x202c;</text>
<text y="10" style="fill: green" text-anchor="middle">Middle &#x202b;Anchor&#x202c;</text>
<text y="20" style="fill: blue" text-anchor="end">End &#x202b;Anchor&#x202c;</text>
</g>
<g transform="translate(0,180)">
<text style="fill: red" text-anchor="start">&#x202e;Start Anchor&#x202c;</text>
<text y="10" style="fill: green" text-anchor="middle">&#x202e;Middle Anchor&#x202c;</text>
<text y="20" style="fill: blue" text-anchor="end">&#x202e;End Anchor&#x202c;</text>
</g>
<g transform="translate(0,220)">
<text style="fill: red" text-anchor="start">&#x202e;Start&#x202c; Anchor</text>
<text y="10" style="fill: green" text-anchor="middle">&#x202e;Middle&#x202c; Anchor</text>
<text y="20" style="fill: blue" text-anchor="end">&#x202e;End&#x202c; Anchor</text>
</g>
<g transform="translate(0,260)">
<text style="fill: red" text-anchor="start">Start &#x202e;Anchor&#x202c;</text>
<text y="10" style="fill: green" text-anchor="middle">Middle &#x202e;Anchor&#x202c;</text>
<text y="20" style="fill: blue" text-anchor="end">End &#x202e;Anchor&#x202c;</text>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

View file

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="400" height="400" xmlns="http://www.w3.org/2000/svg" xmlns:html="http://www.w3.org/1999/xhtml">
<title>Text anchors and bidi control characters</title>
<html:link rel="author" title="Jonathan Kew" href="mailto:jkew@mozilla.com"/>
<g font-family="Arial, sans-serif" font-size="12px">
<line x1="200" y1="20" x2="200" y2="320" stroke="black" stroke-width="0.5"/>
<text x="200" y="40" style="fill: red" text-anchor="end">Start Anchor</text>
<text x="200" y="50" style="fill: green" text-anchor="middle">Middle Anchor</text>
<text x="200" y="60" style="fill: blue" text-anchor="start">End Anchor</text>
<text x="200" y="80" style="fill: red" text-anchor="end">Start Anchor</text>
<text x="200" y="90" style="fill: green" text-anchor="middle">Middle Anchor</text>
<text x="200" y="100" style="fill: blue" text-anchor="start">End Anchor</text>
<text x="200" y="120" style="fill: red" text-anchor="end">Anchor Start</text>
<text x="200" y="130" style="fill: green" text-anchor="middle">Anchor Middle</text>
<text x="200" y="140" style="fill: blue" text-anchor="start">Anchor End</text>
<text x="200" y="160" style="fill: red" text-anchor="end">Anchor Start</text>
<text x="200" y="170" style="fill: green" text-anchor="middle">Anchor Middle</text>
<text x="200" y="180" style="fill: blue" text-anchor="start">Anchor End</text>
<text x="200" y="200" style="fill: red" text-anchor="end">rohcnA tratS</text>
<text x="200" y="210" style="fill: green" text-anchor="middle">rohcnA elddiM</text>
<text x="200" y="220" style="fill: blue" text-anchor="start">rohcnA dnE</text>
<text x="200" y="240" style="fill: red" text-anchor="end">Anchor tratS</text>
<text x="200" y="250" style="fill: green" text-anchor="middle">Anchor elddiM</text>
<text x="200" y="260" style="fill: blue" text-anchor="start">Anchor dnE</text>
<text x="200" y="280" style="fill: red" text-anchor="end">rohcnA Start</text>
<text x="200" y="290" style="fill: green" text-anchor="middle">rohcnA Middle</text>
<text x="200" y="300" style="fill: blue" text-anchor="start">rohcnA End</text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

View file

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="400" height="400" xmlns="http://www.w3.org/2000/svg" xmlns:html="http://www.w3.org/1999/xhtml">
<title>Text anchors and bidi control characters</title>
<html:link rel="author" title="Jonathan Kew" href="mailto:jkew@mozilla.com"/>
<html:link rel="help" href="https://svgwg.org/svg2-draft/text.html#TextAnchoringProperties"/>
<html:link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1906978"/>
<html:link rel="match" href="text-bidi-controls-anchors-2-ref.svg"/>
<g direction="rtl" transform="translate(200,20)" font-family="Arial, sans-serif" font-size="12px">
<line x1="0" y1="0" x2="0" y2="300" stroke="black" stroke-width="0.5"/>
<g transform="translate(0,20)">
<text style="fill: red" text-anchor="start">Start Anchor</text>
<text y="10" style="fill: green" text-anchor="middle">Middle Anchor</text>
<text y="20" style="fill: blue" text-anchor="end">End Anchor</text>
</g>
<g transform="translate(0,60)">
<text style="fill: red" text-anchor="start">&#x202b;Start Anchor&#x202c;</text>
<text y="10" style="fill: green" text-anchor="middle">&#x202b;Middle Anchor&#x202c;</text>
<text y="20" style="fill: blue" text-anchor="end">&#x202b;End Anchor&#x202c;</text>
</g>
<g transform="translate(0,100)">
<text style="fill: red" text-anchor="start">&#x202b;Start&#x202c; Anchor</text>
<text y="10" style="fill: green" text-anchor="middle">&#x202b;Middle&#x202c; Anchor</text>
<text y="20" style="fill: blue" text-anchor="end">&#x202b;End&#x202c; Anchor</text>
</g>
<g transform="translate(0,140)">
<text style="fill: red" text-anchor="start">Start &#x202b;Anchor&#x202c;</text>
<text y="10" style="fill: green" text-anchor="middle">Middle &#x202b;Anchor&#x202c;</text>
<text y="20" style="fill: blue" text-anchor="end">End &#x202b;Anchor&#x202c;</text>
</g>
<g transform="translate(0,180)">
<text style="fill: red" text-anchor="start">&#x202e;Start Anchor&#x202c;</text>
<text y="10" style="fill: green" text-anchor="middle">&#x202e;Middle Anchor&#x202c;</text>
<text y="20" style="fill: blue" text-anchor="end">&#x202e;End Anchor&#x202c;</text>
</g>
<g transform="translate(0,220)">
<text style="fill: red" text-anchor="start">&#x202e;Start&#x202c; Anchor</text>
<text y="10" style="fill: green" text-anchor="middle">&#x202e;Middle&#x202c; Anchor</text>
<text y="20" style="fill: blue" text-anchor="end">&#x202e;End&#x202c; Anchor</text>
</g>
<g transform="translate(0,260)">
<text style="fill: red" text-anchor="start">Start &#x202e;Anchor&#x202c;</text>
<text y="10" style="fill: green" text-anchor="middle">Middle &#x202e;Anchor&#x202c;</text>
<text y="20" style="fill: blue" text-anchor="end">End &#x202e;Anchor&#x202c;</text>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.8 KiB