From 0282c3001aaf060ddf7ea177ff6564810ec277e6 Mon Sep 17 00:00:00 2001 From: gravitypdf-bot Date: Tue, 13 Oct 2026 10:40:18 +1100 Subject: [PATCH 1/2] Draw an overline as thick as the font's underline (#741) The overline block in Cell() divided the font key by the table's shrink factor and cast it to an integer, so it looked up font 0, never found the font's underline thickness or cap height, and fell back to 0.06 em and 700/1000 em. The size it measured those against was also left unshrunk. Read the key and size as the underline and line-through blocks do. Co-Authored-By: Claude Opus 5.5 --- CHANGELOG-GRAVITYPDF.md | 2 + src/Mpdf.php | 4 +- tests/Mpdf/OverlineThicknessTest.php | 94 ++++++++++++++++++ .../OverlineThicknessSnapshotTest.php | 57 +++++++++++ .../decorations-amendment-legacy.pdf | Bin 82108 -> 82108 bytes .../decorations-amendment-standard.pdf | Bin 82425 -> 82425 bytes .../data/snapshots/decorations-propagate.pdf | Bin 34930 -> 34930 bytes tests/data/snapshots/overline-thickness.pdf | Bin 0 -> 44517 bytes 8 files changed, 155 insertions(+), 2 deletions(-) create mode 100644 tests/Mpdf/OverlineThicknessTest.php create mode 100644 tests/Snapshots/OverlineThicknessSnapshotTest.php create mode 100644 tests/data/snapshots/overline-thickness.pdf diff --git a/CHANGELOG-GRAVITYPDF.md b/CHANGELOG-GRAVITYPDF.md index 39228a591..f5f8c42af 100644 --- a/CHANGELOG-GRAVITYPDF.md +++ b/CHANGELOG-GRAVITYPDF.md @@ -270,6 +270,7 @@ Bugfixes * `text-outline-width` with no `text-outline-color` raised an undefined-key warning (`outline-COLOR`) and drew the outline black. The warning is gone in either `cssMode`. In standard mode the outline is now drawn in the colour of the text, as `text-outline-color` is `currentColor` by default, and `text-outline` with a width alone, such as `text-outline: 0.2mm`, which was ignored, outlines the text in its colour too. A text outline in `currentColor`, written or by default, is passed on as the keyword, so a `` of another colour inside the outlined text is outlined in its own colour. Set `'cssMode' => \Mpdf\CssMode::LEGACY` to keep black outlines and to ignore that shorthand. [#552] [#650] [#681] * A percentage `border-radius` on a block, such as `border-radius: 50%` on a box 40 mm by 12 mm, drew a pill instead of an ellipse. Both radii were taken of the width of the block around it, and then shrunk to fit. A percentage is now of the block's own border box, as in CSS: a horizontal radius of its width and a vertical one of its height, so `50%` draws an ellipse and `10%` a corner a tenth of each side. A block split across pages resolves a vertical percentage against the height of the part on each page. With `autoPadding` on, a percentage radius no longer adds padding, since the box is not known when the padding is set. In both `cssMode`s. [#552] [#586] * `list-style: U+2022`, the shorthand, numbered the list where `list-style-type: U+2022` drew a bullet. The shorthand dropped the `U+` from the marker it set. It now keeps it, so the shorthand draws the character as the longhand does, in either `cssMode`. [#552] [#746] [#755] +* `text-decoration: overline` was drawn heavier than an underline on the same text, 2.4 pt against 1.76 pt at 40pt in DejaVu Serif Condensed. The overline is now as thick as the font's underline, sits at the font's cap height rather than a fixed 700/1000 em, and in a table shrunk to fit is thinned and placed with its text. In either `cssMode`. [#741] ### Images and SVG @@ -970,3 +971,4 @@ These changes do not change output. [#746]: https://github.com/GravityPDF/mpdf/issues/746 [#755]: https://github.com/GravityPDF/mpdf/pull/755 [#743]: https://github.com/GravityPDF/mpdf/issues/743 +[#741]: https://github.com/GravityPDF/mpdf/issues/741 diff --git a/src/Mpdf.php b/src/Mpdf.php index b700f3353..8d179fd25 100644 --- a/src/Mpdf.php +++ b/src/Mpdf.php @@ -6265,8 +6265,8 @@ function Cell($w, $h = 0, $txt = '', $border = 0, $ln = 0, $align = '', $fill = } // mPDF 5.7.3 inline text-decoration parameters - $decorationfontkey = (int) (((float) $this->textparam['o-decoration']['fontkey']) / $shrin_k); - $decorationfontsize = $this->textparam['o-decoration']['fontsize']; + $decorationfontkey = $this->textparam['o-decoration']['fontkey']; + $decorationfontsize = $this->textparam['o-decoration']['fontsize'] / $shrin_k; if (isset($this->fonts[$decorationfontkey]['ut']) && $this->fonts[$decorationfontkey]['ut']) { $ut = $this->fonts[$decorationfontkey]['ut'] / 1000 * $decorationfontsize; diff --git a/tests/Mpdf/OverlineThicknessTest.php b/tests/Mpdf/OverlineThicknessTest.php new file mode 100644 index 000000000..a2fdafcca --- /dev/null +++ b/tests/Mpdf/OverlineThicknessTest.php @@ -0,0 +1,94 @@ + '', 'default_font' => 'dejavuserifcondensed'], 1.76]; + $cases[$mode . ', core Times'] = [$mode, ['mode' => 'c', 'default_font' => 'times'], 2.0]; + } + + return $cases; + } + + /** + * 40pt text with an overline draws it at the font's underline thickness, the same width as its underline, in + * either CSS mode + * + * @dataProvider modesAndFonts + * + * @param string $mode + * @param array $font + * @param float $points The font's underline thickness at 40pt + */ + public function testAnOverlineIsAsThickAsTheFontsUnderline($mode, array $font, $points) + { + $config = $font + ['cssMode' => $mode]; + + $this->assertSame([$points], $this->lineWidths('

Decorated

', $config)); + $this->assertSame([$points], $this->lineWidths('

Decorated

', $config)); + } + + /** + * In a table shrunk to fit its width, the overline is thinned with the text, as the underline beside it is + * + * @dataProvider modes + * + * @param string $mode + */ + public function testAnOverlineIsShrunkWithItsTable($mode) + { + $widths = $this->lineWidths( + '
DecoratedDecoratedDecorated
', + ['mode' => '', 'default_font' => 'dejavuserifcondensed', 'cssMode' => $mode] + ); + + $this->assertCount(2, $widths); + $this->assertLessThan(1.76, $widths[0]); + $this->assertSame($widths[0], $widths[1]); + } + + /** + * Each CSS mode + * + * @return array[] + */ + public function modes() + { + return [CssMode::STANDARD => [CssMode::STANDARD], CssMode::LEGACY => [CssMode::LEGACY]]; + } + + /** + * The line widths, in points, a document sets for its text decorations, in the order they are drawn + * + * @param string $html + * @param array $config + * + * @return float[] + */ + private function lineWidths($html, array $config) + { + preg_match_all('/([\d.]+) w 0 j 0 J/', implode("\n", $this->pages($this->render($html, $config))), $matches); + + return array_map('floatval', $matches[1]); + } + +} diff --git a/tests/Snapshots/OverlineThicknessSnapshotTest.php b/tests/Snapshots/OverlineThicknessSnapshotTest.php new file mode 100644 index 000000000..a330ee197 --- /dev/null +++ b/tests/Snapshots/OverlineThicknessSnapshotTest.php @@ -0,0 +1,57 @@ + + body { font-size: 9pt; } + h1 { font-size: 13pt; margin: 0 0 2mm 0; } + p.caption { margin: 3mm 0 0 0; } + div.sample { font-size: 40pt; margin: 0; } + +

text-decoration: overline thickness

'; + + foreach (['DejaVu Serif Condensed' => 'dejavuserifcondensed', 'DejaVu Sans Condensed' => 'dejavusanscondensed'] as $name => $family) { + $html .= '

' . $name . ', underline: a line under the text.

+
Decorated
+

' . $name . ', overline: a line over the text, as thick as the underline above.

+
Decorated
+

' . $name . ', underline overline: the two lines the same thickness.

+
Decorated
'; + } + + $html .= '

A table shrunk to fit the page: the line over the text as thin as the line under it.

+ + +
DecoratedDecoratedDecoratedDecorated
'; + + $this->mpdf = $this->createMpdf(); + + $this->mpdf->WriteHTML($html); + } + +} diff --git a/tests/data/snapshots/decorations-amendment-legacy.pdf b/tests/data/snapshots/decorations-amendment-legacy.pdf index 80136f2af0a0f5845b102dc72d7328a9d58df8a6..4b0c605bf76c8bba0147c74f0f8749777ab4ef2a 100644 GIT binary patch delta 204 zcmdnf$hxPIb%P*_zNwLgLb-y0LKYBvDJYm2>6scCD3}9jGjnr=Tm?e|OFbhC3z*2{ zKr!{nFL}&2&tv(@jzhDlrG=icfd!Igs0c`N^GlxXFL@YCjhz$CQ&J653@nT-5|dMm hEi5fkQw-9QlZ;GLElmtlQq1fWYzQftzR-bD8UUUuHM{@- delta 204 zcmdnf$hxPIb%P*_zPXWsLb-y0LKYBvDJYm2>6rpW%z?C#rHMkWf}w$>o{@zGOk{GP znEK?GJm#C{v3zC6q1n{ZT+h6scCD3}9jGjnr=Tm?e|OFbhC3z*0x zzPQPYSX>Oyw4td2=`%OgGc`ccr!-lQS99_mCbP}cS*RC`0{~f1Ot1g| delta 322 zcmey_%=)vLb%Q92zPXWsLb-y0LKYBvDJYm2>6rpW%z?C#rHMkWf}w$>o{@zGOk@&Y z+~h?pE(U1Y&{To+nVagF8X)OYnykmGIr$Eg+2-l2Rvb9&HMKO?votbAvKJ~ciEkP% zJCXDlTk07D-3r$Ov(vQMjeolvKVztov!#)7a&oGvQJSHVky%QrWs;$Zk%6Iwxq-R4 UL9%I*iJgKCAtlrAIWkHE037m60ssI2 diff --git a/tests/data/snapshots/decorations-propagate.pdf b/tests/data/snapshots/decorations-propagate.pdf index 3504d908ece4a63fee4099a45e67856a563709a3..b51b44816f3d190be81d666c1f8e3b3f69b93283 100644 GIT binary patch delta 189 zcmew~f$7r(rVZTullO@5PrfU_Az@*lXKrk%kgH&5Xs%~$W}sjK5t;m+U1_qsV8G@z z{7Q^a)!d>cW?-d8mU>1;K&58pdO#77(#`UMU(4c*QWKLbQlvFFD40M*CckG_nk+9Euz3x? z5+g*hgs7n@Sf!Dro)J)wiJ7?`Pz0oMv%KKfvbbcUq+~M#%OoSqG)uD-LyMGDV*@iw tV-o{|WDCQ@#AG`K8-hw=x$Nw?ic1oUN-By{)3}UHj15h=R8?L5-2lTGGQ9u* diff --git a/tests/data/snapshots/overline-thickness.pdf b/tests/data/snapshots/overline-thickness.pdf new file mode 100644 index 0000000000000000000000000000000000000000..cdc4299716794c9acadd226f9b19432ac63c725c GIT binary patch literal 44517 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 E0}zT>zyJUM literal 0 HcmV?d00001 From 1e5eff49e6e6ee22d0573b47c0166a629b5e99a9 Mon Sep 17 00:00:00 2001 From: gravitypdf-bot Date: Tue, 13 Oct 2026 10:47:21 +1100 Subject: [PATCH 2/2] Share the overline thickness test's documents and CSS modes (#741) Draw the overline and the underline in one document, and take the CSS modes from DrawnStyles rather than a copy of its provider. Co-Authored-By: Claude Opus 5.5 --- tests/Mpdf/OverlineThicknessTest.php | 30 ++++++++++------------------ 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/tests/Mpdf/OverlineThicknessTest.php b/tests/Mpdf/OverlineThicknessTest.php index a2fdafcca..122f6f7e5 100644 --- a/tests/Mpdf/OverlineThicknessTest.php +++ b/tests/Mpdf/OverlineThicknessTest.php @@ -5,12 +5,13 @@ use Yoast\PHPUnitPolyfills\TestCases\TestCase; /** - * An overline is drawn as thick as the font's underline, as an underline is, and at the size a table shrunk to fit - * draws its text at + * An overline takes the font's underline thickness, so it matches the underline on the same text, and a table shrunk + * to fit thins it with its text */ class OverlineThicknessTest extends TestCase { + use DrawnStyles; use PageStreams; /** @@ -21,7 +22,7 @@ class OverlineThicknessTest extends TestCase public function modesAndFonts() { $cases = []; - foreach ([CssMode::STANDARD, CssMode::LEGACY] as $mode) { + foreach (array_keys($this->modes()) as $mode) { $cases[$mode . ', DejaVu Serif Condensed'] = [$mode, ['mode' => '', 'default_font' => 'dejavuserifcondensed'], 1.76]; $cases[$mode . ', core Times'] = [$mode, ['mode' => 'c', 'default_font' => 'times'], 2.0]; } @@ -30,8 +31,7 @@ public function modesAndFonts() } /** - * 40pt text with an overline draws it at the font's underline thickness, the same width as its underline, in - * either CSS mode + * At 40pt an overline and an underline are both drawn at the font's underline thickness, in either CSS mode * * @dataProvider modesAndFonts * @@ -41,14 +41,16 @@ public function modesAndFonts() */ public function testAnOverlineIsAsThickAsTheFontsUnderline($mode, array $font, $points) { - $config = $font + ['cssMode' => $mode]; + $widths = $this->lineWidths( + '

Decorated

Decorated

', + $font + ['cssMode' => $mode] + ); - $this->assertSame([$points], $this->lineWidths('

Decorated

', $config)); - $this->assertSame([$points], $this->lineWidths('

Decorated

', $config)); + $this->assertSame([$points, $points], $widths); } /** - * In a table shrunk to fit its width, the overline is thinned with the text, as the underline beside it is + * In a table shrunk to fit, the overline is thinned with the text to the width of the underline beside it * * @dataProvider modes * @@ -66,16 +68,6 @@ public function testAnOverlineIsShrunkWithItsTable($mode) $this->assertSame($widths[0], $widths[1]); } - /** - * Each CSS mode - * - * @return array[] - */ - public function modes() - { - return [CssMode::STANDARD => [CssMode::STANDARD], CssMode::LEGACY => [CssMode::LEGACY]]; - } - /** * The line widths, in points, a document sets for its text decorations, in the order they are drawn *