<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<!DOCTYPE bugzilla SYSTEM "https://bugs.webkit.org/page.cgi?id=bugzilla.dtd">

<bugzilla version="5.0.4.1"
          urlbase="https://bugs.webkit.org/"
          
          maintainer="admin@webkit.org"
>

    <bug>
          <bug_id>311597</bug_id>
          
          <creation_ts>2026-04-06 15:42:07 -0700</creation_ts>
          <short_desc>getStartPositionOfChar WPT is failing</short_desc>
          <delta_ts>2026-04-13 15:43:11 -0700</delta_ts>
          <reporter_accessible>1</reporter_accessible>
          <cclist_accessible>1</cclist_accessible>
          <classification_id>1</classification_id>
          <classification>Unclassified</classification>
          <product>WebKit</product>
          <component>SVG</component>
          <version>WebKit Nightly Build</version>
          <rep_platform>Unspecified</rep_platform>
          <op_sys>Unspecified</op_sys>
          <bug_status>NEW</bug_status>
          <resolution></resolution>
          
          <see_also>https://bugs.webkit.org/show_bug.cgi?id=311553</see_also>
          <bug_file_loc>https://wpt.live/svg/text/scripted/getstartpositionofchar.html</bug_file_loc>
          <status_whiteboard></status_whiteboard>
          <keywords>InRadar, WPTImpact</keywords>
          <priority>P2</priority>
          <bug_severity>Normal</bug_severity>
          <target_milestone>---</target_milestone>
          
          
          <everconfirmed>1</everconfirmed>
          <reporter name="Karl Dubost">karlcow</reporter>
          <assigned_to name="Nobody">webkit-unassigned</assigned_to>
          <cc>fantasai.bugs</cc>
    
    <cc>sabouhallawa</cc>
    
    <cc>vitor.roriz</cc>
    
    <cc>webkit-bug-importer</cc>
    
    <cc>zimmermann</cc>
          

      

      

      

          <comment_sort_order>oldest_to_newest</comment_sort_order>  
          <long_desc isprivate="0" >
    <commentid>2197403</commentid>
    <comment_count>0</comment_count>
    <who name="Karl Dubost">karlcow</who>
    <bug_when>2026-04-06 15:42:07 -0700</bug_when>
    <thetext>https://wpt.live/svg/text/scripted/getstartpositionofchar.html
https://wpt.fyi/results/svg/text/scripted/getstartpositionofchar.html

This needs to be investigated.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>2197405</commentid>
    <comment_count>1</comment_count>
    <who name="Karl Dubost">karlcow</who>
    <bug_when>2026-04-06 15:53:31 -0700</bug_when>
    <thetext>The WPT test svg/text/scripted/getstartpositionofchar.html fails in Safari for all four vertical writing modes (vertical-rl, vertical-lr, sideways-rl, sideways-lr). Chrome and Firefox pass.

The test creates &lt;text&gt; elements at x=100 y=100 with 10px Ahem font in vertical writing modes, then checks that getStartPositionOfChar and getEndPositionOfChar return positions that advance by the font size (10px) for each character along the block direction.

For vertical-rl, vertical-lr, and sideways-rl, getEndPositionOfChar(0).y should equal getStartPositionOfChar(0).y + 10 but returns the same value as getStartPositionOfChar(0).y. The end position is not advancing by the glyph height in vertical modes.

For sideways-lr, getEndPositionOfChar(0).y should equal getStartPositionOfChar(0).y - 10 but also returns the same value.

Found when working on Bug 311553 
This is a pre-existing issue unrelated to dominant-baseline handling. The query API correctly returns positions for horizontal text but fails to account for glyph advance in the vertical direction.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>2197406</commentid>
    <comment_count>2</comment_count>
    <who name="Karl Dubost">karlcow</who>
    <bug_when>2026-04-06 16:10:41 -0700</bug_when>
    <thetext>The query API at SVGTextQuery.cpp:399-403 computes the end position for vertical text by adding metrics.height() to fragment.y. SVGTextMetrics::measureCharacterRange()

https://searchfox.org/wubkat/rev/4b927e49756cc0415a795b42b81fc9ab95c5813d/Source/WebCore/rendering/svg/SVGTextMetrics.cpp#28-40
```cpp
SVGTextMetrics::SVGTextMetrics(const RenderSVGInlineText&amp; textRenderer, const TextRun&amp; run)
{
    float scalingFactor = textRenderer.scalingFactor();
    ASSERT(scalingFactor);

    const FontCascade&amp; scaledFont = textRenderer.scaledFont();

    // Calculate width/height using the scaled font, divide this result by the scalingFactor afterwards.
    m_width = scaledFont.width(run) / scalingFactor;
    m_height = scaledFont.metricsOfPrimaryFont().height() / scalingFactor;

    m_length = static_cast&lt;unsigned&gt;(run.length());
}
```

(SVGTextMetrics.cpp:28-40) computes:

* the horizontal glyph advance with 
   m_width = scaledFont.width(run)
* the font line height (ascent + descent), a fixed value with
   m_height = scaledFont.metricsOfPrimaryFont().height()

The TextRun is always constructed as horizontal text (SVGTextMetrics.cpp:42-56), regardless of writing mode.

https://searchfox.org/wubkat/rev/4b927e49756cc0415a795b42b81fc9ab95c5813d/Source/WebCore/rendering/svg/SVGTextMetrics.cpp#42-56
```cpp
TextRun SVGTextMetrics::constructTextRun(const RenderSVGInlineText&amp; text, unsigned position, unsigned length)
{
    const RenderStyle&amp; style = text.style();

    TextRun run(StringView(text.text()).substring(position, length),
        0, /* xPos, only relevant with allowTabs=true */
        0, /* padding, only relevant for justified text, not relevant for SVG */
        ExpansionBehavior::allowRightOnly(),
        style.writingMode().bidiDirection(),
        isOverride(style.unicodeBidi()) /* directionalOverride */);

    // We handle letter &amp; word spacing ourselves.
    run.disableSpacing();
    return run;
}
```

Two potential issues:

1. For vertical text, the per-character advance along y is the glyph width (horizontal advance rotated), not the font line height. The query should probably use metrics.width() for vertical advance instead of metrics.height().
2. The fragment structure for vertical text may already position each character at its final y — in which case adding metrics on top double-counts the advance.

need to heck the actual fragment structure (how many fragments, what positions) for vertical text, and the actual metric values returned by measureCharacterRange.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>2199928</commentid>
    <comment_count>3</comment_count>
    <who name="Radar WebKit Bug Importer">webkit-bug-importer</who>
    <bug_when>2026-04-13 15:43:11 -0700</bug_when>
    <thetext>&lt;rdar://problem/174692385&gt;</thetext>
  </long_desc>
      
      

    </bug>

</bugzilla>