View Issue Details
| ID | Project | Category | View Status | Date Submitted | Last Update |
|---|---|---|---|---|---|
| 0015244 | Scribus | Typography | public | 2018-04-03 22:06 | 2026-05-14 08:16 |
| Reporter | munzirtaha | Assigned To | |||
| Priority | normal | Severity | minor | Reproducibility | always |
| Status | new | Resolution | open | ||
| Platform | Linux | OS | Arch Linux | OS Version | latest |
| Product Version | 1.5.4.svn | ||||
| Summary | 0015244: [PATCH] Underlining Arabic text shows as small broken lines | ||||
| Description | Depending on the text and font used, underlining shows as broken lines. In the attached documents, the text is Arabic and the font used is Traditional Arabic. LibreOffice and all other programs I know of shows the correct behavior. | ||||
| Tags | No tags attached. | ||||
| Attached Files | |||||
| Patch | Yes | ||||
|
|
It seems fixed somewhere, I couldn't reproduce it anymore. |
|
|
Because you changed the font to "Arial". Try "Traditional Arabic" and you would see it's not fixed |
|
|
Thanks Munzir, You are right. After long debugging session I figure out the problem. Problem: The underline was being drawn with an incorrect horizontal offset, leading to misalignment in certain text layouts. The issue was caused by redundant coordinate translation: the painter was already translated to the start of the GlyphRun, but the code was additionally adding the glyph's internal x-offset (xoffs) when calculating the underline start point. Solution: Removed the usage of 'xoffs' when calling p->drawLine. By drawing the underline relative to the current coordinate origin (0,0), we ensure proper alignment without double-calculating the offset. This change ensures that underline rendering remains consistent with the glyph's local coordinate system. |
|
|
Here is the new patch which fix outline underline alignment as well as strike line sine it has the same bug and the fix follow same logic. fix_#15244_v2.patch (1,235 bytes)
Subject: [PATCH] Fix #15244 : Correct underline & StrikeLine alignment in GlyphBox::render --- Index: scribus/text/boxes.cpp IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/scribus/text/boxes.cpp b/scribus/text/boxes.cpp --- a/scribus/text/boxes.cpp (revision 27539) +++ b/scribus/text/boxes.cpp (date 1778003272466) @@ -662,9 +662,9 @@ yoffs = gl.yoffset; } if (charStyle.effects() & ScStyle_Subscript) - p->drawLine(QPointF(xoffs, yoffs - st), QPointF(xoffs + m_glyphRun.width(), yoffs - st)); + p->drawLine(QPointF(xoffs, yoffs - st), QPointF(m_glyphRun.width(), yoffs - st)); else - p->drawLine(QPointF(xoffs, -st), QPointF(xoffs + m_glyphRun.width(), -st)); + p->drawLine(QPointF(xoffs, -st), QPointF(m_glyphRun.width(), -st)); p->setStrokeWidth(sw); p->setStrokeColor(sc); @@ -747,7 +747,7 @@ xoffs = gl.xoffset; yoffs = gl.yoffset; } - p->drawLine(QPointF(xoffs, yoffs - st), QPointF(xoffs + m_glyphRun.width(), yoffs - st)); + p->drawLine(QPointF(xoffs, yoffs - st), QPointF(m_glyphRun.width(), yoffs - st)); p->setStrokeWidth(sw); p->setStrokeColor(sc); |
|
|
This is good news — you managed to pinpoint the function causing the problem, and it’s almost fixed. However, I found that the issue still exists with other fonts, such as Aref Ruqaa, Astrolabe, Mada, .... Umm! Khaled Hosny's fonts � � |
|
|
I think I found the problem. The problem happens with the dotted letters, and only in some fonts, so my guess this happens because in some fonts like Khaled's he is using a separate glyph for the dot and another for the body of the letter and the underline function calculates the width of the first glyph only which is the dot and ignored the other and hence the issue |
|
|
Thanks Munzir for the testing. the problem is In Arabic fonts such as Mada, characters like "ظ" are composed of multiple glyphs: a base glyph and a separate dot glyph positioned with x_offset. When drawing underlines, the code used only the first glyph's x_offset as the line's starting point. If the dot glyph comes first, the underline starts at the dot's offset instead of the base glyph's offset, causing a visual gap. my solution: Find the minimum x_offset across all glyphs in the cluster instead of using just the first glyph's offset. This ensures the underline always starts at the visual beginning of the character. I also fix strikethrough in both cases. fix_#15244_v4.patch (2,711 bytes)
Subject: [PATCH] Fix #15244 : Correct underline & StrikeLine alignment in GlyphBox::render
---
Index: scribus/text/boxes.cpp
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/scribus/text/boxes.cpp b/scribus/text/boxes.cpp
--- a/scribus/text/boxes.cpp (revision 27550)
+++ b/scribus/text/boxes.cpp (date 1778349222213)
@@ -655,16 +655,25 @@
p->setStrokeWidth(lw);
double xoffs(0.0), yoffs(0.0);
+ // Find the visual start of the character by taking the minimum x_offset
+ // among all glyphs in the cluster. This handles composed characters like
+ // Arabic "ظ" where a dot glyph may have a larger x_offset than the base glyph.
if (m_glyphRun.glyphs().count() > 0)
{
- const GlyphLayout& gl = m_glyphRun.glyphs().first();
- xoffs = gl.xoffset;
- yoffs = gl.yoffset;
+ xoffs = m_glyphRun.glyphs().first().xoffset;
+ yoffs = m_glyphRun.glyphs().first().yoffset;
+ for (const GlyphLayout& gl : m_glyphRun.glyphs())
+ {
+ if (gl.xoffset < xoffs)
+ xoffs = gl.xoffset;
+ if (gl.yoffset < yoffs)
+ yoffs = gl.yoffset;
+ }
}
if (charStyle.effects() & ScStyle_Subscript)
- p->drawLine(QPointF(xoffs, yoffs - st), QPointF(xoffs + m_glyphRun.width(), yoffs - st));
+ p->drawLine(QPointF(xoffs, yoffs - st), QPointF( m_glyphRun.width(), yoffs - st));
else
- p->drawLine(QPointF(xoffs, -st), QPointF(xoffs + m_glyphRun.width(), -st));
+ p->drawLine(QPointF(xoffs, -st), QPointF( m_glyphRun.width(), -st));
p->setStrokeWidth(sw);
p->setStrokeColor(sc);
@@ -741,13 +750,24 @@
p->setStrokeWidth(lw);
double xoffs(0.0), yoffs(0.0);
+ // Fix strikethrough position for glyphs composed of multiple parts
+ // (e.g., Arabic characters with separate dots like "ظ").
+ // Find the minimum x_offset to start at the visual beginning of the
+ // character, and the maximum y_offset to position the line correctly
+ // through the dot which sits above the base glyph.
if (m_glyphRun.glyphs().count() > 0)
{
- const GlyphLayout& gl = m_glyphRun.glyphs().first();
- xoffs = gl.xoffset;
- yoffs = gl.yoffset;
+ xoffs = m_glyphRun.glyphs().first().xoffset;
+ yoffs = m_glyphRun.glyphs().first().yoffset;
+ for (const GlyphLayout& gl : m_glyphRun.glyphs())
+ {
+ if (gl.xoffset < xoffs)
+ xoffs = gl.xoffset;
+ if (gl.yoffset > yoffs)
+ yoffs = gl.yoffset;
+ }
}
- p->drawLine(QPointF(xoffs, yoffs - st), QPointF(xoffs + m_glyphRun.width(), yoffs - st));
+ p->drawLine(QPointF(xoffs, yoffs - st), QPointF(m_glyphRun.width(), yoffs - st));
p->setStrokeWidth(sw);
p->setStrokeColor(sc);
|
|
|
Thanks Fahad! It’s much, much better now, but I still haven’t run out of fonts yet. Khalid’s Raqq still has the issue, and I have no idea what’s different about it. |
|
|
Raqq font is not meant to be underlined As far as I know. I check libreoffice behavior, it doesn't underlined or striked out. So this font doesn't support underline in the first place. However, you can underline the text by drawing a line if you really need it. Update: I was wrong sorry �️ |
|
|
libreoffice behavior |
|
|
In my LibreOffice, I can underline it normally, but try changing the zoom to avoid libO artifacts. |
|
|
|
|
|
Thanks Munzir for the deep testing really this is my first time dealing with all these advance fonts. Please test v5 of my patch. Explanation of the change: Start the underline at 0 (the beginning of the GlyphBox) instead of xoffs, since xoffset is only relevant for glyph positioning within the cluster, not for the visual extent of the character. Use m_glyphRun.width() for the line length to cover the full visual width. fix_#15244_v5.patch (2,699 bytes)
Subject: [PATCH] Fix #15244 : Correct underline & StrikeLine alignment in GlyphBox::render
---
Index: scribus/text/boxes.cpp
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/scribus/text/boxes.cpp b/scribus/text/boxes.cpp
--- a/scribus/text/boxes.cpp (revision 27550)
+++ b/scribus/text/boxes.cpp (date 1778349222213)
@@ -655,16 +655,25 @@
p->setStrokeWidth(lw);
double xoffs(0.0), yoffs(0.0);
+ // Find the visual start of the character by taking the minimum x_offset
+ // among all glyphs in the cluster. This handles composed characters like
+ // Arabic "ظ" where a dot glyph may have a larger x_offset than the base glyph.
if (m_glyphRun.glyphs().count() > 0)
{
- const GlyphLayout& gl = m_glyphRun.glyphs().first();
- xoffs = gl.xoffset;
- yoffs = gl.yoffset;
+ xoffs = m_glyphRun.glyphs().first().xoffset;
+ yoffs = m_glyphRun.glyphs().first().yoffset;
+ for (const GlyphLayout& gl : m_glyphRun.glyphs())
+ {
+ if (gl.xoffset < xoffs)
+ xoffs = gl.xoffset;
+ if (gl.yoffset < yoffs)
+ yoffs = gl.yoffset;
+ }
}
if (charStyle.effects() & ScStyle_Subscript)
- p->drawLine(QPointF(xoffs, yoffs - st), QPointF(xoffs + m_glyphRun.width(), yoffs - st));
+ p->drawLine(QPointF(0, yoffs - st), QPointF( m_glyphRun.width(), yoffs - st));
else
- p->drawLine(QPointF(xoffs, -st), QPointF(xoffs + m_glyphRun.width(), -st));
+ p->drawLine(QPointF(0, -st), QPointF( m_glyphRun.width(), -st));
p->setStrokeWidth(sw);
p->setStrokeColor(sc);
@@ -741,13 +750,24 @@
p->setStrokeWidth(lw);
double xoffs(0.0), yoffs(0.0);
+ // Fix strikethrough position for glyphs composed of multiple parts
+ // (e.g., Arabic characters with separate dots like "ظ").
+ // Find the minimum x_offset to start at the visual beginning of the
+ // character, and the maximum y_offset to position the line correctly
+ // through the dot which sits above the base glyph.
if (m_glyphRun.glyphs().count() > 0)
{
- const GlyphLayout& gl = m_glyphRun.glyphs().first();
- xoffs = gl.xoffset;
- yoffs = gl.yoffset;
+ xoffs = m_glyphRun.glyphs().first().xoffset;
+ yoffs = m_glyphRun.glyphs().first().yoffset;
+ for (const GlyphLayout& gl : m_glyphRun.glyphs())
+ {
+ if (gl.xoffset < xoffs)
+ xoffs = gl.xoffset;
+ if (gl.yoffset > yoffs)
+ yoffs = gl.yoffset;
+ }
}
- p->drawLine(QPointF(xoffs, yoffs - st), QPointF(xoffs + m_glyphRun.width(), yoffs - st));
+ p->drawLine(QPointF(0, yoffs - st), QPointF(m_glyphRun.width(), yoffs - st));
p->setStrokeWidth(sw);
p->setStrokeColor(sc);
|
|
|
|
|
|
Thanks Fahad, this patch fixed the underline issue perfectly for all my fonts except the few buggy ones. I’ve now tested the strike-through as well, and it looks like it could use another magic touch. |
|
|
Here we go final run. I hope I didn't miss any case. Using xoffs and yoffs was wrong in the first place. fix_#15244_v6.patch (1,391 bytes)
Index: scribus/text/boxes.cpp
===================================================================
--- scribus/text/boxes.cpp (revision 27567)
+++ scribus/text/boxes.cpp (working copy)
@@ -654,17 +654,10 @@
p->setStrokeColor(p->fillColor());
p->setStrokeWidth(lw);
- double xoffs(0.0), yoffs(0.0);
- if (m_glyphRun.glyphs().count() > 0)
- {
- const GlyphLayout& gl = m_glyphRun.glyphs().first();
- xoffs = gl.xoffset;
- yoffs = gl.yoffset;
- }
if (charStyle.effects() & ScStyle_Subscript)
- p->drawLine(QPointF(xoffs, yoffs - st), QPointF(xoffs + m_glyphRun.width(), yoffs - st));
+ p->drawLine(QPointF(0, 0 - st), QPointF( m_glyphRun.width(), 0 - st));
else
- p->drawLine(QPointF(xoffs, -st), QPointF(xoffs + m_glyphRun.width(), -st));
+ p->drawLine(QPointF(0, 0 - st), QPointF( m_glyphRun.width(), 0 - st));
p->setStrokeWidth(sw);
p->setStrokeColor(sc);
@@ -740,14 +733,7 @@
p->setStrokeColor(p->fillColor());
p->setStrokeWidth(lw);
- double xoffs(0.0), yoffs(0.0);
- if (m_glyphRun.glyphs().count() > 0)
- {
- const GlyphLayout& gl = m_glyphRun.glyphs().first();
- xoffs = gl.xoffset;
- yoffs = gl.yoffset;
- }
- p->drawLine(QPointF(xoffs, yoffs - st), QPointF(xoffs + m_glyphRun.width(), yoffs - st));
+ p->drawLine(QPointF(0, 0 - st), QPointF(m_glyphRun.width(), 0 - st));
p->setStrokeWidth(sw);
p->setStrokeColor(sc);
|
|
|
Indeed, this fixes the issue perfectly. I always appreciate patches that remove more code than they add! One trivial suggestion: it would be slightly cleaner to use `QPointF(0, -st)` rather than `QPointF(0, 0 - st)` |
| Date Modified | Username | Field | Change |
|---|---|---|---|
| 2018-04-03 22:06 | munzirtaha | New Issue | |
| 2018-04-03 22:06 | munzirtaha | File Added: underline-issue.pdf | |
| 2018-04-03 22:06 | munzirtaha | File Added: underline-issue.sla | |
| 2026-05-02 13:11 | Fahad | Note Added: 0053643 | |
| 2026-05-02 13:11 | Fahad | File Added: Screenshot_1_7_4.png | |
| 2026-05-02 22:28 | munzirtaha | Note Added: 0053646 | |
| 2026-05-05 13:54 | Fahad | Note Added: 0053652 | |
| 2026-05-05 13:54 | Fahad | File Added: fix_#15244_v1.patch | |
| 2026-05-05 13:54 | Fahad | File Added: fix_#15244_v1.png | |
| 2026-05-05 14:53 | ale | Summary | Underlining Arabic text shows as small broken lines => [PATCH] Underlining Arabic text shows as small broken lines |
| 2026-05-05 14:53 | ale | Patch | No => Yes |
| 2026-05-05 17:23 | Fahad | File Deleted: fix_#15244_v1.patch | |
| 2026-05-05 18:10 | Fahad | Note Added: 0053655 | |
| 2026-05-05 18:10 | Fahad | File Added: strikeline-after.png | |
| 2026-05-05 18:10 | Fahad | File Added: strikeline-before.png | |
| 2026-05-05 18:10 | Fahad | File Added: fix_#15244_v2.patch | |
| 2026-05-08 13:32 | munzirtaha | Note Added: 0053669 | |
| 2026-05-08 13:32 | munzirtaha | File Added: underline-issue.png | |
| 2026-05-08 14:55 | munzirtaha | Note Added: 0053670 | |
| 2026-05-09 17:57 | Fahad | Note Added: 0053676 | |
| 2026-05-09 17:57 | Fahad | File Added: mada_underline.png | |
| 2026-05-09 17:57 | Fahad | File Added: fix_#15244_v4.patch | |
| 2026-05-10 15:32 | munzirtaha | Note Added: 0053682 | |
| 2026-05-10 15:32 | munzirtaha | File Added: underline_issue_Raqq.png | |
| 2026-05-10 16:13 | Fahad | Note Added: 0053683 | |
| 2026-05-10 16:14 | Fahad | Note Edited: 0053683 | |
| 2026-05-10 16:14 | Fahad | Note Added: 0053684 | |
| 2026-05-10 16:14 | Fahad | File Added: raqq-libreoffice-underline.png | |
| 2026-05-10 16:48 | munzirtaha | Note Added: 0053685 | |
| 2026-05-10 16:48 | munzirtaha | Note Added: 0053686 | |
| 2026-05-10 16:48 | munzirtaha | File Added: underline_issue_Raqq-libO.png | |
| 2026-05-10 18:22 | Fahad | Note Edited: 0053683 | |
| 2026-05-10 18:29 | Fahad | Note Added: 0053688 | |
| 2026-05-10 18:29 | Fahad | File Added: fix_#15244_v5.patch | |
| 2026-05-10 18:29 | Fahad | File Added: fix_#15244_v5.png | |
| 2026-05-12 19:39 | munzirtaha | Note Added: 0053689 | |
| 2026-05-12 19:39 | munzirtaha | File Added: underline-issue-5.png | |
| 2026-05-13 20:34 | munzirtaha | File Deleted: underline-issue-5.png | |
| 2026-05-13 20:48 | munzirtaha | Note Added: 0053690 | |
| 2026-05-13 20:48 | munzirtaha | File Added: strike-through-aldhabi.png | |
| 2026-05-14 05:09 | Fahad | Note Added: 0053691 | |
| 2026-05-14 05:09 | Fahad | File Added: underline-rtl.png | |
| 2026-05-14 05:09 | Fahad | File Added: fix_#15244_v6.patch | |
| 2026-05-14 08:16 | munzirtaha | Note Added: 0053692 |