Closed Bug 691330 Opened 13 years ago Closed 7 years ago

"ASSERTION: Can't end drawing path inside ligature" with SVG, soft hyphen

Categories

(Core :: SVG, defect)

x86_64
macOS
defect
Not set
normal

Tracking

()

RESOLVED WORKSFORME

People

(Reporter: jruderman, Unassigned)

References

Details

(Keywords: assertion, testcase)

Attachments

(2 files)

Attached image testcase
###!!! ASSERTION: Can't end drawing path inside ligature: 'ligatureRunEnd == end', file gfx/thebes/gfxFont.cpp, line 3705

###!!! ASSERTION: Can't draw path starting inside ligature: 'ligatureRunStart == start', file gfx/thebes/gfxFont.cpp, line 3703
Attached file stack traces
Jesse do you get the same assert in html if you embed the same characters inside <p style="letter-spacing:1px"></p>
No.
WFM (no assertion-failures) on Ubuntu Linux x86_64, in a debug build from today.
So, I guess this is Mac-specific?
Could be (I can still repro on Mac trunk). I have plenty of Macs if you want to debug on one.
Thanks -- I was able to repro on my Mac Mini, actually.

So when rendering the testcase, we hit this block of code:

>3684 void
>3685 gfxTextRun::DrawToPath(gfxContext *aContext, gfxPoint aPt,
[...]
>3694     GlyphRunIterator iter(this, aStart, aLength);
>3695     while (iter.NextRun()) {
>3696         gfxFont *font = iter.GetGlyphRun()->mFont;
>3697         PRUint32 start = iter.GetStringStart();
>3698         PRUint32 end = iter.GetStringEnd();
>3699         PRUint32 ligatureRunStart = start;
>3700         PRUint32 ligatureRunEnd = end;
>3701         ShrinkToLigatureBoundaries(&ligatureRunStart, &ligatureRunEnd);
[...]
>3704         NS_ASSERTION(ligatureRunEnd == end,
>3705                      "Can't end drawing path inside ligature");
http://mxr.mozilla.org/mozilla-central/source/gfx/thebes/gfxFont.cpp#3685

Initially, 'start' and 'ligatureRunStart' are 0; 'end' and 'ligatureRunEnd' are 1.

However, the 'ShrinkToLigatureBoundaries' call (line 3701) reduces ligatureRunEnd (aliased as '*aEnd') to 0, in the following chunk:
>3406 void
>3407 gfxTextRun::ShrinkToLigatureBoundaries(PRUint32 *aStart, PRUint32 *aEnd)
[...]
>3417     if (*aEnd < mCharacterCount) {
>3418         while (*aEnd > *aStart && !charGlyphs[*aEnd].IsLigatureGroupStart()) {
>3419             --(*aEnd);
>3420         }
http://mxr.mozilla.org/mozilla-central/source/gfx/thebes/gfxFont.cpp#3407

In the above block of code, charGlyphs[1].mValue is "5", which makes IsLigatureGroupStart() return false.  (both of its ||'d conditions are false)  This makes us enter the while loop and decrement *aEnd aka ligatureRunEnd.  At that point, *aEnd == *aStart == 0, so we break out of the while loop and return up to DrawToPath, which asserts because ligatureRunEnd's value has changed.

I don't really grok this text-run code, but hopefully the above will help someone who does get a head-start on this (or suggest a fix)....
(NOTE: On my Linux box, the only thing different is that charGlyphs[1].mValue is 256 (instead of 5), which makes "IsLigatureGroupStart()" return true (instead of false) -- so we don't decrement ligatureRunEnd, and we don't assert.  Presumably this is due to a difference in fonts, or something.)
(In reply to Daniel Holbert [:dholbert] from comment #6)
> Thanks -- I was able to repro on my Mac Mini, actually.
> 
> So when rendering the testcase, we hit this block of code:
> 
> >3684 void
> >3685 gfxTextRun::DrawToPath(gfxContext *aContext, gfxPoint aPt,
> [...]
> >3694     GlyphRunIterator iter(this, aStart, aLength);
> >3695     while (iter.NextRun()) {
> >3696         gfxFont *font = iter.GetGlyphRun()->mFont;
> >3697         PRUint32 start = iter.GetStringStart();
> >3698         PRUint32 end = iter.GetStringEnd();
> >3699         PRUint32 ligatureRunStart = start;
> >3700         PRUint32 ligatureRunEnd = end;
> >3701         ShrinkToLigatureBoundaries(&ligatureRunStart, &ligatureRunEnd);
> [...]
> >3704         NS_ASSERTION(ligatureRunEnd == end,
> >3705                      "Can't end drawing path inside ligature");
> http://mxr.mozilla.org/mozilla-central/source/gfx/thebes/gfxFont.cpp#3685
> 
> Initially, 'start' and 'ligatureRunStart' are 0; 'end' and 'ligatureRunEnd'
> are 1.
> 
> However, the 'ShrinkToLigatureBoundaries' call (line 3701) reduces
> ligatureRunEnd (aliased as '*aEnd') to 0, in the following chunk:
> >3406 void
> >3407 gfxTextRun::ShrinkToLigatureBoundaries(PRUint32 *aStart, PRUint32 *aEnd)
> [...]
> >3417     if (*aEnd < mCharacterCount) {
> >3418         while (*aEnd > *aStart && !charGlyphs[*aEnd].IsLigatureGroupStart()) {
> >3419             --(*aEnd);
> >3420         }
> http://mxr.mozilla.org/mozilla-central/source/gfx/thebes/gfxFont.cpp#3407
> 
> In the above block of code, charGlyphs[1].mValue is "5", which makes
> IsLigatureGroupStart() return false.  (both of its ||'d conditions are
> false)  This makes us enter the while loop and decrement *aEnd aka
> ligatureRunEnd.  At that point, *aEnd == *aStart == 0, so we break out of
> the while loop and return up to DrawToPath, which asserts because
> ligatureRunEnd's value has changed.
> 

What happens in the html case on a Mac i.e. <p style="letter-spacing:1px"></p> with the special characters inside the <p> tag? The letter-spacing style should turn off optional ligatures for html in the same way that rotate does for svg.
Flags: needinfo?(ryanvm)
No longer asserts on trunk.
Status: NEW → RESOLVED
Closed: 7 years ago
Flags: needinfo?(ryanvm) → in-testsuite+
Resolution: --- → WORKSFORME
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: