View Issue Details

IDProjectCategoryView StatusLast Update
0015244ScribusTypographypublic2026-05-14 08:16
Reportermunzirtaha Assigned To 
PrioritynormalSeverityminorReproducibilityalways
Status newResolutionopen 
PlatformLinuxOSArch LinuxOS Versionlatest
Product Version1.5.4.svn 
Summary0015244: [PATCH] Underlining Arabic text shows as small broken lines
DescriptionDepending 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.
TagsNo tags attached.
Attached Files
underline-issue.pdf (16,731 bytes)
underline-issue.sla (15,156 bytes)
PatchYes

Activities

Fahad

2026-05-02 13:11

developer   ~0053643

It seems fixed somewhere, I couldn't reproduce it anymore.
Screenshot_1_7_4.png (152,050 bytes)   
Screenshot_1_7_4.png (152,050 bytes)   

munzirtaha

2026-05-02 22:28

reporter   ~0053646

Because you changed the font to "Arial". Try "Traditional Arabic" and you would see it's not fixed

Fahad

2026-05-05 13:54

developer   ~0053652

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.
fix_#15244_v1.png (48,763 bytes)   
fix_#15244_v1.png (48,763 bytes)   

Fahad

2026-05-05 18:10

developer   ~0053655

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.
strikeline-after.png (13,016 bytes)   
strikeline-after.png (13,016 bytes)   
strikeline-before.png (11,591 bytes)   
strikeline-before.png (11,591 bytes)   
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);
fix_#15244_v2.patch (1,235 bytes)   

munzirtaha

2026-05-08 13:32

reporter   ~0053669

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 � �
underline-issue.png (142,894 bytes)   
underline-issue.png (142,894 bytes)   

munzirtaha

2026-05-08 14:55

reporter   ~0053670

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

Fahad

2026-05-09 17:57

developer   ~0053676

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.
mada_underline.png (78,857 bytes)   
mada_underline.png (78,857 bytes)   
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);
fix_#15244_v4.patch (2,711 bytes)   

munzirtaha

2026-05-10 15:32

reporter   ~0053682

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.
underline_issue_Raqq.png (144,782 bytes)   
underline_issue_Raqq.png (144,782 bytes)   

Fahad

2026-05-10 16:13

developer   ~0053683

Last edited: 2026-05-10 18:22

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 �️

Fahad

2026-05-10 16:14

developer   ~0053684

libreoffice behavior
raqq-libreoffice-underline.png (36,956 bytes)   
raqq-libreoffice-underline.png (36,956 bytes)   

munzirtaha

2026-05-10 16:48

reporter   ~0053685

In my LibreOffice, I can underline it normally, but try changing the zoom to avoid libO artifacts.

munzirtaha

2026-05-10 16:48

reporter   ~0053686

underline_issue_Raqq-libO.png (174,604 bytes)   
underline_issue_Raqq-libO.png (174,604 bytes)   

Fahad

2026-05-10 18:29

developer   ~0053688

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);
fix_#15244_v5.patch (2,699 bytes)   
fix_#15244_v5.png (27,719 bytes)   
fix_#15244_v5.png (27,719 bytes)   

munzirtaha

2026-05-12 19:39

reporter   ~0053689

munzirtaha

2026-05-13 20:48

reporter   ~0053690

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.
strike-through-aldhabi.png (144,273 bytes)   
strike-through-aldhabi.png (144,273 bytes)   

Fahad

2026-05-14 05:09

developer   ~0053691

Here we go final run. I hope I didn't miss any case. Using xoffs and yoffs was wrong in the first place.
underline-rtl.png (115,586 bytes)   
underline-rtl.png (115,586 bytes)   
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);
fix_#15244_v6.patch (1,391 bytes)   

munzirtaha

2026-05-14 08:16

reporter   ~0053692

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)`

Issue History

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