diff --git a/core/opentype-parser.lua b/core/opentype-parser.lua index b6362fa0c..a16f2f02a 100644 --- a/core/opentype-parser.lua +++ b/core/opentype-parser.lua @@ -433,6 +433,18 @@ local function parseMath(s) } end +local function parsePost(s) + if s:len() <= 0 then return end + local fd = vstruct.cursor(s) + local header = vstruct.read(">majorVersion:u2 minorVersion:u2 italicAngle:i4 underlinePosition:i2 underlineThickness:i2 isFixedPitch:u4", fd) + local italicAngle = header.italicAngle / 65536 -- 1 << 16 + return { + italicAngle = italicAngle, + underlinePosition = header.underlinePosition, + underlineThickness = header.underlineThickness + } +end + local parseFont = function(face) if not face.font then local font = {} @@ -443,6 +455,7 @@ local parseFont = function(face) font.cpal = parseCpal(hb.get_table(face.data, face.index, "CPAL")) font.svg = parseSvg(hb.get_table(face.data, face.index, "SVG")) font.math = parseMath(hb.get_table(face.data, face.index, "MATH")) + font.post = parsePost(hb.get_table(face.data, face.index, "post")) face.font = font end return face.font diff --git a/packages/rules.lua b/packages/rules.lua index 65f7c4b48..db6dfad18 100644 --- a/packages/rules.lua +++ b/packages/rules.lua @@ -34,13 +34,21 @@ SILE.registerCommand("fullrule", function (options, _) end, "Draw a full width hrule centered on the current line") SILE.registerCommand("underline", function (_, content) + local ot = SILE.require("core/opentype-parser") + local fontoptions = SILE.font.loadDefaults({}) + local face = SILE.font.cache(fontoptions, SILE.shaper.getFace) + local font = ot.parseFont(face) + local upem = font.head.unitsPerEm + local underlinePosition = -font.post.underlinePosition / upem * fontoptions.size + local underlineThickness = font.post.underlineThickness / upem * fontoptions.size + local hbox = SILE.call("hbox", {}, content) local gl = SILE.length() - hbox.width - SILE.call("lower", {height = "0.5pt"}, function() - SILE.call("hrule", {width = gl.length, height = "0.5pt"}) + SILE.call("lower", {height = SU.cast("measurement", underlinePosition)}, function() + SILE.call("hrule", {width = gl.length, height = underlineThickness}) end) SILE.typesetter:pushGlue({width = hbox.width}) -end, "Underlines some content (badly)") +end, "Underlines some content") SILE.registerCommand("boxaround", function (_, content) local hbox = SILE.call("hbox", {}, content) diff --git a/tests/bug-1259.expected b/tests/bug-1259.expected new file mode 100644 index 000000000..b3417022e --- /dev/null +++ b/tests/bug-1259.expected @@ -0,0 +1,36 @@ +Set paper size 419.5275636 595.275597 +Begin page +Mx 20.9764 +My 37.3321 +Set font Gentium Plus;10;400;;normal;;LTR +T 43 68 89 72 w=20.6787 (Have) +Mx 44.3212 +T 86 82 80 72 w=21.5430 (some) +Mx 68.5303 +T 88 81 71 72 85 79 76 81 76 81 74 w=48.6377 (underlining) +Draw line 117.1680 38.0646 -48.6377 0.4883 +Mx 119.8342 +T 85 72 79 68 87 76 89 72 w=31.5820 (relative) +Mx 154.0823 +T 87 82 w=8.4717 (to) +Mx 165.2201 +T 73 82 81 87 w=17.0996 (font) +Mx 182.3197 +T 17 w=2.2900 (.) +Mx 20.9764 +My 73.3321 +Set font Libertinus Serif;30;400;;normal;;LTR +T 54 84 70 w=44.9400 (Use) +Mx 72.4164 +T 86 79 69 70 83 77 74 79 74 79 72 w=143.6400 (underlining) +Draw line 216.0564 74.4721 -143.6400 1.2000 +Mx 222.5564 +T 74 79 w=24.3900 (in) +Mx 253.4464 +T 66 79 80 85 73 70 83 w=95.2800 (another) +Mx 355.2264 +T 71 80 79 85 w=50.1600 (font) +Mx 405.3864 +T 15 w=6.6000 (.) +End page +Finish diff --git a/tests/bug-1259.sil b/tests/bug-1259.sil new file mode 100644 index 000000000..dcc6150e8 --- /dev/null +++ b/tests/bug-1259.sil @@ -0,0 +1,11 @@ +\begin[papersize=a5]{document} +\neverindent +\nofolios +\script[src=packages/rules] + +Have some \underline{underlining} relative to font. + +\font[size=30pt,family=Libertinus Serif] + +Use \underline{underlining} in another font. +\end{document}