local base = require("packages.base")
local package = pl.class(base)
package._name = "dropcaps"
function package:_init ()
base._init(self)
self:loadPackage("rebox")
self:loadPackage("raiselower")
end
local shapeHbox = function (options, content)
options.lines, options.join, options.raise, options.shift, options.color, options.scale = nil, nil, nil, nil, nil, nil
SILE.call("noindent")
local hbox = SILE.typesetter:makeHbox(function ()
SILE.call("font", options, content)
end)
return hbox
end
function package:registerCommands ()
self:registerCommand("dropcap", function (options, content)
local lines = SU.cast("integer", options.lines or 3)
local join = SU.boolean(options.join, false)
local standoff = SU.cast("measurement", options.standoff or "1spc")
local raise = SU.cast("measurement", options.raise or 0)
local shift = SU.cast("measurement", options.shift or 0)
local size = SU.cast("measurement or nil", options.size or nil)
local scale = SU.cast("number", options.scale or 1.0)
local color = options.color
options.size = nil
if color then self:loadPackage("color") end
local tmpHbox = shapeHbox(options, content)
local extraHeight = SILE.measurement((lines - 1).."bs"):tonumber()
local targetHeight = tmpHbox.height:tonumber() * scale + extraHeight
SU.debug("dropcaps", "Target height", targetHeight)
local curSize = SILE.measurement(SILE.settings:get("font.size")):tonumber()
local curHeight, curWidth = tmpHbox.height:tonumber(), tmpHbox.width:tonumber()
options.size = size and size:tonumber() or (targetHeight / curHeight * curSize)
local targetWidth = curWidth / curSize * options.size
SU.debug("dropcaps", "Target font size", options.size)
SU.debug("dropcaps", "Target width", targetWidth)
local hbox = shapeHbox(options, content)
local joinOffset = join and standoff:tonumber() or 0
SILE.settings:set("current.hangAfter", -lines)
SILE.settings:set("current.hangIndent", targetWidth + joinOffset)
SU.debug("dropcaps", "joinOffset", joinOffset)
SILE.call("rebox", { height = 0, width = -joinOffset }, function ()
SILE.call("glue", { width = shift - targetWidth - joinOffset })
SILE.call("lower", { height = extraHeight - raise }, function ()
SILE.call(color and "color" or "noop", { color = color }, function ()
SILE.typesetter:pushHbox(hbox)
end)
end)
end)
end, "Show an 'initial capital' (also known as a 'drop cap') at the start of the content paragraph.")
end
package.documentation = [[
\begin{document}
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.
It provides the \autodoc:command{\dropcap} command.
The content passed will be the initial character(s).
The primary option is \autodoc:parameter{lines}, an integer specifying the number of lines to span (defaults to \code{3}).
The scale of the characters can be adjusted relative to the first line using the \autodoc:parameter{scale} option (defaults to \code{1.0}).
The \autodoc:parameter{join} parameter is a boolean for whether to join the dropcap to the first line (defaults to \code{false}).
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.
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.
To tweak the position of the dropcap, measurements may be passed to the \autodoc:parameter{raise} and \autodoc:parameter{shift} options.
Other options passed to \autodoc:command{\dropcap} will be passed through to \autodoc:command{\font} when drawing the initial letter(s).
This may be useful for passing OpenType options or other font preferences.
\begin{note}
One caveat is that the size of the initials is calculated using the default linespacing mechanism.
If you are using an alternative method from the \autodoc:package{linespacing} package, you might see strange results.
Set the \autodoc:setting{document.baselineskip} to approximate your effective leading value for best results.
If that doesn't work set the size manually.
Using \code{SILE.setCommandDefaults()} can be helpful for so you don't have to set the size every time.
\end{note}
\end{document}
]]
return package