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

sile-typesetter / sile / 11124789710

01 Oct 2024 11:57AM UTC coverage: 29.567% (-31.4%) from 60.926%
11124789710

push

github

web-flow
Merge pull request #2105 from Omikhleia/refactor-collated-sort

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

5252 existing lines in 53 files now uncovered.

5048 of 17073 relevant lines covered (29.57%)

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

17
local function getStrikethroughParameters ()
18
   local ot = require("core.opentype-parser")
×
19
   local fontoptions = SILE.font.loadDefaults({})
×
20
   local face = SILE.font.cache(fontoptions, SILE.shaper.getFace)
×
21
   local font = ot.parseFont(face)
×
22
   local upem = font.head.unitsPerEm
×
23
   local yStrikeoutPosition = font.os2.yStrikeoutPosition / upem * fontoptions.size
×
24
   local yStrikeoutSize = font.os2.yStrikeoutSize / upem * fontoptions.size
×
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)
×
35
   local outputWidth = SU.rationWidth(self.width, self.width, line.ratio):tonumber()
×
36
   local oldx = typesetter.frame.state.cursorX
×
37
   typesetter.frame:advancePageDirection(-self.raise)
×
38
   typesetter.frame:advanceWritingDirection(outputWidth)
×
39
   local newx = typesetter.frame.state.cursorX
×
40
   local newy = typesetter.frame.state.cursorY
×
41
   SILE.outputter:drawRule(oldx, newy, newx - oldx, self.thickness)
×
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
79
      if options.position and options.raise then
×
80
         SU.error("hrulefill cannot have both position and raise parameters")
×
81
      end
82
      if options.thickness then
×
83
         thickness = SU.cast("measurement", options.thickness)
×
84
      end
85
      if options.position == "underline" then
×
86
         local underlinePosition, underlineThickness = getUnderlineParameters()
×
87
         thickness = thickness or underlineThickness
×
88
         raise = underlinePosition
×
89
      elseif options.position == "strikethrough" then
×
90
         local yStrikeoutPosition, yStrikeoutSize = getStrikethroughParameters()
×
91
         thickness = thickness or yStrikeoutSize
×
92
         raise = yStrikeoutPosition + thickness / 2
×
93
      elseif options.position then
×
94
         SU.error("Unknown hrulefill position '" .. options.position .. "'")
×
95
      else
96
         raise = SU.cast("measurement", options.raise or "0")
×
97
      end
98

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, _)
×
106
      local thickness = SU.cast("measurement", options.thickness or "0.2pt")
×
107
      local raise = SU.cast("measurement", options.raise or "0.5em")
×
108

109
      if options.height then
×
110
         SU.deprecated("\\fullrule[…, height=…]", "\\fullrule[…, thickness=…]", "0.13.1", "0.15.0")
×
111
      end
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
115
      if options.width then
×
116
         SU.deprecated("\\fullrule with width", "\\hrule and \\raise", "0.13.1 ", "0.15.0")
×
117
      end
118

119
      SILE.typesetter:leaveHmode()
×
120
      SILE.call("noindent")
×
121
      SILE.call("hrulefill", { raise = raise, thickness = thickness })
×
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)
×
126
      local underlinePosition, underlineThickness = getUnderlineParameters()
×
127

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

132
         -- Build the content.
133
         -- Cursor will be moved by the actual definitive size.
134
         box:outputContent(typesetter, line)
×
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
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)
×
146
      local yStrikeoutPosition, yStrikeoutSize = getStrikethroughParameters()
×
147

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

152
         -- Build the content.
153
         -- Cursor will be moved by the actual definitive size.
154
         box:outputContent(typesetter, line)
×
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
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