• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

sile-typesetter / sile / 11574339945

29 Oct 2024 12:58PM UTC coverage: 34.309% (-33.9%) from 68.22%
11574339945

push

github

web-flow
Merge pull request #2142 from Omikhleia/fix-math-fraction-padding

fix(math): Fractions must have padding to avoid visual confusion

0 of 26 new or added lines in 1 file covered. (0.0%)

5779 existing lines in 69 files now uncovered.

6014 of 17529 relevant lines covered (34.31%)

4588.59 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/packages/rules/init.lua
UNCOV
1
local base = require("packages.base")
×
2

UNCOV
3
local package = pl.class(base)
×
UNCOV
4
package._name = "rules"
×
5

6
local function getUnderlineParameters ()
UNCOV
7
   local ot = require("core.opentype-parser")
×
UNCOV
8
   local fontoptions = SILE.font.loadDefaults({})
×
UNCOV
9
   local face = SILE.font.cache(fontoptions, SILE.shaper.getFace)
×
UNCOV
10
   local font = ot.parseFont(face)
×
UNCOV
11
   local upem = font.head.unitsPerEm
×
UNCOV
12
   local underlinePosition = font.post.underlinePosition / upem * fontoptions.size
×
UNCOV
13
   local underlineThickness = font.post.underlineThickness / upem * fontoptions.size
×
UNCOV
14
   return underlinePosition, underlineThickness
×
15
end
16

17
local function getStrikethroughParameters ()
UNCOV
18
   local ot = require("core.opentype-parser")
×
UNCOV
19
   local fontoptions = SILE.font.loadDefaults({})
×
UNCOV
20
   local face = SILE.font.cache(fontoptions, SILE.shaper.getFace)
×
UNCOV
21
   local font = ot.parseFont(face)
×
UNCOV
22
   local upem = font.head.unitsPerEm
×
UNCOV
23
   local yStrikeoutPosition = font.os2.yStrikeoutPosition / upem * fontoptions.size
×
UNCOV
24
   local yStrikeoutSize = font.os2.yStrikeoutSize / upem * fontoptions.size
×
UNCOV
25
   return yStrikeoutPosition, yStrikeoutSize
×
26
end
27

28
-- \hfill (from the "plain" class) and \leaders (from the "leaders" package) use glues,
29
-- so we behave the same for hrulefill.
UNCOV
30
local hrulefillglue = pl.class(SILE.types.node.hfillglue)
×
UNCOV
31
hrulefillglue.raise = SILE.types.measurement()
×
UNCOV
32
hrulefillglue.thickness = SILE.types.measurement("0.2pt")
×
33

UNCOV
34
function hrulefillglue:outputYourself (typesetter, line)
×
UNCOV
35
   local outputWidth = SU.rationWidth(self.width, self.width, line.ratio):tonumber()
×
UNCOV
36
   local oldx = typesetter.frame.state.cursorX
×
UNCOV
37
   typesetter.frame:advancePageDirection(-self.raise)
×
UNCOV
38
   typesetter.frame:advanceWritingDirection(outputWidth)
×
UNCOV
39
   local newx = typesetter.frame.state.cursorX
×
UNCOV
40
   local newy = typesetter.frame.state.cursorY
×
UNCOV
41
   SILE.outputter:drawRule(oldx, newy, newx - oldx, self.thickness)
×
UNCOV
42
   typesetter.frame:advancePageDirection(self.raise)
×
43
end
44

UNCOV
45
function package:_init ()
×
UNCOV
46
   base._init(self)
×
UNCOV
47
   self:loadPackage("raiselower")
×
UNCOV
48
   self:loadPackage("rebox")
×
49
end
50

UNCOV
51
function package:registerCommands ()
×
UNCOV
52
   self:registerCommand("hrule", function (options, _)
×
UNCOV
53
      local width = SU.cast("length", options.width)
×
UNCOV
54
      local height = SU.cast("length", options.height)
×
UNCOV
55
      local depth = SU.cast("length", options.depth)
×
UNCOV
56
      SILE.typesetter:pushHbox({
×
57
         width = width:absolute(),
58
         height = height:absolute(),
59
         depth = depth:absolute(),
60
         value = options.src,
61
         outputYourself = function (node, typesetter, line)
UNCOV
62
            local outputWidth = SU.rationWidth(node.width, node.width, line.ratio)
×
UNCOV
63
            typesetter.frame:advancePageDirection(-node.height)
×
UNCOV
64
            local oldx = typesetter.frame.state.cursorX
×
UNCOV
65
            local oldy = typesetter.frame.state.cursorY
×
UNCOV
66
            typesetter.frame:advanceWritingDirection(outputWidth)
×
UNCOV
67
            typesetter.frame:advancePageDirection(node.height + node.depth)
×
UNCOV
68
            local newx = typesetter.frame.state.cursorX
×
UNCOV
69
            local newy = typesetter.frame.state.cursorY
×
UNCOV
70
            SILE.outputter:drawRule(oldx, oldy, newx - oldx, newy - oldy)
×
UNCOV
71
            typesetter.frame:advancePageDirection(-node.depth)
×
72
         end,
73
      })
UNCOV
74
   end, "Draws a blob of ink of width <width>, height <height> and depth <depth>")
×
75

UNCOV
76
   self:registerCommand("hrulefill", function (options, _)
×
77
      local raise
78
      local thickness
UNCOV
79
      if options.position and options.raise then
×
80
         SU.error("hrulefill cannot have both position and raise parameters")
×
81
      end
UNCOV
82
      if options.thickness then
×
UNCOV
83
         thickness = SU.cast("measurement", options.thickness)
×
84
      end
UNCOV
85
      if options.position == "underline" then
×
UNCOV
86
         local underlinePosition, underlineThickness = getUnderlineParameters()
×
UNCOV
87
         thickness = thickness or underlineThickness
×
UNCOV
88
         raise = underlinePosition
×
UNCOV
89
      elseif options.position == "strikethrough" then
×
UNCOV
90
         local yStrikeoutPosition, yStrikeoutSize = getStrikethroughParameters()
×
UNCOV
91
         thickness = thickness or yStrikeoutSize
×
UNCOV
92
         raise = yStrikeoutPosition + thickness / 2
×
UNCOV
93
      elseif options.position then
×
94
         SU.error("Unknown hrulefill position '" .. options.position .. "'")
×
95
      else
UNCOV
96
         raise = SU.cast("measurement", options.raise or "0")
×
97
      end
98

UNCOV
99
      SILE.typesetter:pushExplicitGlue(hrulefillglue({
×
100
         raise = raise,
101
         thickness = thickness or SILE.types.measurement("0.2pt"),
102
      }))
UNCOV
103
   end, "Add a huge horizontal hrule glue")
×
104

UNCOV
105
   self:registerCommand("fullrule", function (options, _)
×
UNCOV
106
      local thickness = SU.cast("measurement", options.thickness or "0.2pt")
×
UNCOV
107
      local raise = SU.cast("measurement", options.raise or "0.5em")
×
108

UNCOV
109
      if options.height then
×
110
         SU.deprecated("\\fullrule[…, height=…]", "\\fullrule[…, thickness=…]", "0.13.1", "0.15.0")
×
111
      end
UNCOV
112
      if not SILE.typesetter:vmode() then
×
113
         SU.deprecated("\\fullrule in horizontal mode", "\\hrule or \\hrulefill", "0.13.1", "0.15.0")
×
114
      end
UNCOV
115
      if options.width then
×
116
         SU.deprecated("\\fullrule with width", "\\hrule and \\raise", "0.13.1 ", "0.15.0")
×
117
      end
118

UNCOV
119
      SILE.typesetter:leaveHmode()
×
UNCOV
120
      SILE.call("noindent")
×
UNCOV
121
      SILE.call("hrulefill", { raise = raise, thickness = thickness })
×
UNCOV
122
      SILE.typesetter:leaveHmode()
×
UNCOV
123
   end, "Draw a full width hrule centered on the current line")
×
124

UNCOV
125
   self:registerCommand("underline", function (_, content)
×
UNCOV
126
      local underlinePosition, underlineThickness = getUnderlineParameters()
×
127

UNCOV
128
      SILE.typesetter:liner("underline", content, function (box, typesetter, line)
×
UNCOV
129
         local oldX = typesetter.frame.state.cursorX
×
UNCOV
130
         local Y = typesetter.frame.state.cursorY
×
131

132
         -- Build the content.
133
         -- Cursor will be moved by the actual definitive size.
UNCOV
134
         box:outputContent(typesetter, line)
×
UNCOV
135
         local newX = typesetter.frame.state.cursorX
×
136

137
         -- Output a line.
138
         -- NOTE: According to the OpenType specs, underlinePosition is "the suggested distance of
139
         -- the top of the underline from the baseline" so it seems implied that the thickness
140
         -- should expand downwards
UNCOV
141
         SILE.outputter:drawRule(oldX, Y - underlinePosition, newX - oldX, underlineThickness)
×
142
      end)
UNCOV
143
   end, "Underlines some content")
×
144

UNCOV
145
   self:registerCommand("strikethrough", function (_, content)
×
UNCOV
146
      local yStrikeoutPosition, yStrikeoutSize = getStrikethroughParameters()
×
147

UNCOV
148
      SILE.typesetter:liner("strikethrough", content, function (box, typesetter, line)
×
UNCOV
149
         local oldX = typesetter.frame.state.cursorX
×
UNCOV
150
         local Y = typesetter.frame.state.cursorY
×
151

152
         -- Build the content.
153
         -- Cursor will be moved by the actual definitive size.
UNCOV
154
         box:outputContent(typesetter, line)
×
UNCOV
155
         local newX = typesetter.frame.state.cursorX
×
156

157
         -- Output a line.
158
         -- NOTE: The OpenType spec is not explicit regarding how the size
159
         -- (thickness) affects the position. We opt to distribute evenly
UNCOV
160
         SILE.outputter:drawRule(oldX, Y - yStrikeoutPosition - yStrikeoutSize / 2, newX - oldX, yStrikeoutSize)
×
161
      end)
UNCOV
162
   end, "Strikes out some content")
×
163

UNCOV
164
   self:registerCommand("boxaround", function (_, content)
×
165
      -- This command was not documented and lacks feature.
166
      -- Plan replacement with a better suited package.
167
      SU.deprecated("\\boxaround (undocumented)", "\\framebox (package)", "0.12.0")
×
168

169
      local hbox, hlist = SILE.typesetter:makeHbox(content)
×
170
      -- Re-wrap the hbox in another hbox responsible for boxing it at output
171
      -- time, when we will know the line contribution and can compute the scaled width
172
      -- of the box, taking into account possible stretching and shrinking.
173
      SILE.typesetter:pushHbox({
×
174
         inner = hbox,
175
         width = hbox.width,
176
         height = hbox.height,
177
         depth = hbox.depth,
178
         outputYourself = function (node, typesetter, line)
179
            local oldX = typesetter.frame.state.cursorX
×
180
            local Y = typesetter.frame.state.cursorY
×
181

182
            -- Build the original hbox.
183
            -- Cursor will be moved by the actual definitive size.
184
            node.inner:outputYourself(SILE.typesetter, line)
×
185
            local newX = typesetter.frame.state.cursorX
×
186

187
            -- Output a border
188
            -- NOTE: Drawn inside the hbox, so borders overlap with inner content.
189
            local w = newX - oldX
×
190
            local h = node.height:tonumber()
×
191
            local d = node.depth:tonumber()
×
192
            local thickness = 0.5
×
193

194
            SILE.outputter:drawRule(oldX, Y + d - thickness, w, thickness)
×
195
            SILE.outputter:drawRule(oldX, Y - h, w, thickness)
×
196
            SILE.outputter:drawRule(oldX, Y - h, thickness, h + d)
×
197
            SILE.outputter:drawRule(oldX + w - thickness, Y - h, thickness, h + d)
×
198
         end,
199
      })
200
      SILE.typesetter:pushHlist(hlist)
×
UNCOV
201
   end, "Draws a box around some content")
×
202
end
203

204
package.documentation = [[
205
\begin{document}
206
The \autodoc:package{rules} package provides several line-drawing commands.
207

208
The \autodoc:command{\hrule} command draws a blob of ink of a given \autodoc:parameter{width} (length), \autodoc:parameter{height} (above the current baseline), and \autodoc:parameter{depth} (below the current baseline).
209
Such rules are horizontal boxes, placed along the baseline of a line of text and treated just like other text to be output.
210
So, they can appear in the middle of a paragraph, like this:
211
\hrule[width=20pt, height=0.5pt]
212
(That one was generated with \autodoc:command{\hrule[width=20pt, height=0.5pt]}.)
213

214
The \autodoc:command{\underline} command \underline{underlines} its content.
215

216
The \autodoc:command{\strikethrough} command \strikethrough{strikes} its content.
217

218
Both commands support paragraph content spanning multiple lines.
219

220
\autodoc:note{The position and thickness of the underlines and strikethroughs are based on the metrics of the current font, honoring the values defined by the type designer.}
221

222
The \autodoc:command{\hrulefill} inserts an infinite horizontal rubber, similar to an \autodoc:command{\hfill}, but—as its name implies—filled with a rule (that is, a solid line).
223
By default, it stands on the baseline and has a thickness of 0.2pt, below the baseline.
224
It supports optional parameters \autodoc:parameter{raise=<dimension>} and \autodoc:parameter{thickness=<dimension>} to adjust the position and thickness of the line, respectively.
225
The former accepts a negative measurement, to lower the line.
226
Alternatively, use the \autodoc:parameter{position} option, which can be set to \code{underline} or \code{strikethrough}.
227
In that case, it honors the current font metrics and the line is drawn at the appropriate position and, by default, with the relevant thickness.
228
You can still set a custom thickness with the \autodoc:parameter{thickness} parameter.
229

230
For instance, \autodoc:command{\hrulefill[position=underline]} gives:
231
\hrulefill[position=underline]
232

233
Finally, \autodoc:command{\fullrule} draws a thin standalone rule across the width of a full text line.
234
Accepted parameters are \autodoc:parameter{raise} and \autodoc:parameter{thickness}, with the same meanings as above.
235
\end{document}
UNCOV
236
]]
×
237

UNCOV
238
return package
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc