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

sile-typesetter / sile / 6713098919

31 Oct 2023 10:21PM UTC coverage: 52.831% (-21.8%) from 74.636%
6713098919

push

github

web-flow
Merge d0a2a1ee9 into b185d4972

45 of 45 new or added lines in 3 files covered. (100.0%)

8173 of 15470 relevant lines covered (52.83%)

6562.28 hits per line

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

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

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

6
function package:_init ()
×
7
  base._init(self)
×
8
  self:loadPackage("rebox")
×
9
  self:loadPackage("raiselower")
×
10
end
11

12
local shapeHbox = function (options, content)
13
  -- Clear irrelevant values before passing to font
14
  options.lines, options.join, options.raise, options.shift, options.color, options.scale = nil, nil, nil, nil, nil, nil
×
15
  SILE.call("noindent")
×
16
  local hbox = SILE.typesetter:makeHbox(function ()
×
17
    SILE.call("font", options, content)
×
18
  end)
19
  return hbox
×
20
end
21

22
function package:registerCommands ()
×
23

24
  -- This implementation relies on the hangafter and hangindent features of Knuth's line-breaking algorithm.
25
  -- These features in core line breaking algorithm supply the blank space in the paragraph shape but don't fill it with anything.
26
  self:registerCommand("dropcap", function (options, content)
×
27
    local lines = SU.cast("integer", options.lines or 3)
×
28
    local join = SU.boolean(options.join, false)
×
29
    local standoff = SU.cast("measurement", options.standoff or "1spc")
×
30
    local raise = SU.cast("measurement", options.raise or 0)
×
31
    local shift = SU.cast("measurement", options.shift or 0)
×
32
    local size = SU.cast("measurement or nil", options.size or nil)
×
33
    local scale = SU.cast("number", options.scale or 1.0)
×
34
    local color = options.color
×
35
    options.size = nil -- we need to measure the "would have been" size before using this
×
36

37
    if color then self:loadPackage("color") end
×
38

39
    -- We want the drop cap to span over N lines, that is N - 1 baselineskip + the height of the first line.
40
    -- Note this only works for the default linespace mechanism.
41
    -- We determine the height of the first line by measuring the size the initial content *would have* been.
42
    -- This gives the font some control over its relative size, sometimes desired sometimes undesired.
43
    local tmpHbox = shapeHbox(options, content)
×
44
    local extraHeight = SILE.measurement((lines - 1).."bs"):tonumber()
×
45
    local targetHeight = tmpHbox.height:tonumber() * scale + extraHeight
×
46
    SU.debug("dropcaps", "Target height", targetHeight)
×
47

48
    -- Now we need to figure out how to scale the dropcap font to get an initial of targetHeight.
49
    -- From that we can also figure out the width it will be at that height.
50
    local curSize = SILE.measurement(SILE.settings:get("font.size")):tonumber()
×
51
    local curHeight, curWidth = tmpHbox.height:tonumber(), tmpHbox.width:tonumber()
×
52
    options.size = size and size:tonumber() or (targetHeight / curHeight * curSize)
×
53
    local targetWidth = curWidth / curSize * options.size
×
54
    SU.debug("dropcaps", "Target font size", options.size)
×
55
    SU.debug("dropcaps", "Target width", targetWidth)
×
56

57
    -- Typeset the dropcap with its final shape, but don't output it yet
58
    local hbox = shapeHbox(options, content)
×
59

60
    -- Setup up the necessary indents for the final paragraph content
61
    local joinOffset = join and standoff:tonumber() or 0
×
62
    SILE.settings:set("current.hangAfter", -lines)
×
63
    SILE.settings:set("current.hangIndent", targetWidth + joinOffset)
×
64
    SU.debug("dropcaps", "joinOffset", joinOffset)
×
65

66
    -- The paragraph is indented so as to leave enough space for the drop cap.
67
    -- We "trick" the typesetter with a zero-dimension box wrapping our original box.
68
    SILE.call("rebox", { height = 0, width = -joinOffset }, function ()
×
69
      SILE.call("glue", { width = shift - targetWidth - joinOffset })
×
70
      SILE.call("lower", { height = extraHeight - raise }, function ()
×
71
        SILE.call(color and "color" or "noop", { color = color }, function ()
×
72
          SILE.typesetter:pushHbox(hbox)
×
73
        end)
74
      end)
75
    end)
76
  end, "Show an 'initial capital' (also known as a 'drop cap') at the start of the content paragraph.")
×
77

78
end
79

80
package.documentation = [[
81
\begin{document}
82
The \autodoc:package{dropcaps} package allows you to format paragraphs with an “initial capital” (also commonly referred as a “drop cap”), typically one large capital letter used as a decorative element at the beginning of a paragraph.
83

84
It provides the \autodoc:command{\dropcap} command.
85
The content passed will be the initial character(s).
86
The primary option is \autodoc:parameter{lines}, an integer specifying the number of lines to span (defaults to \code{3}).
87
The scale of the characters can be adjusted relative to the first line using the \autodoc:parameter{scale} option (defaults to \code{1.0}).
88
The \autodoc:parameter{join} parameter is a boolean for whether to join the dropcap to the first line (defaults to \code{false}).
89
If \autodoc:parameter{join} is \code{true}, the value of the \autodoc:parameter{standoff} option (defaults to \code{1spc}) is applied to all but the first line.
90
Optionally \autodoc:parameter{color} can be passed to change the typeface color, which is sometimes useful to offset the apparent weight of a large glyph.
91
To tweak the position of the dropcap, measurements may be passed to the \autodoc:parameter{raise} and \autodoc:parameter{shift} options.
92
Other options passed to \autodoc:command{\dropcap} will be passed through to \autodoc:command{\font} when drawing the initial letter(s).
93
This may be useful for passing OpenType options or other font preferences.
94

95
\begin{autodoc:note}
96
One caveat is that the size of the initials is calculated using the default linespacing mechanism.
97
If you are using an alternative method from the \autodoc:package{linespacing} package, you might see strange results.
98
Set the \autodoc:setting{document.baselineskip} to approximate your effective leading value for best results.
99
If that doesn't work set the size manually.
100
Using \code{SILE.setCommandDefaults()} can be helpful for so you don't have to set the size every time.
101
\end{autodoc:note}
102
\end{document}
103
]]
×
104

105
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

© 2025 Coveralls, Inc