Skip to content

Commit

Permalink
Merge 4581dce into 5bc372a
Browse files Browse the repository at this point in the history
  • Loading branch information
Omikhleia committed Apr 9, 2023
2 parents 5bc372a + 4581dce commit 40896e3
Show file tree
Hide file tree
Showing 4 changed files with 138 additions and 113 deletions.
4 changes: 2 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -501,8 +501,8 @@ All notable changes to this project will be documented in this file. See [standa
### Bug Fixes

* **frames:** Inherit class direction setting in new frames ([35c8a25](https://github.com/sile-typesetter/sile/commit/35c8a255c2a19d4f25dc5f60e40d76a52d2ac601))
* **packages:** Make boxaround respect shrink/strech (rules package) ([9d8f708](https://github.com/sile-typesetter/sile/commit/9d8f7086e1f469a24b032307b43dc801fe10fd92))
* **packages:** Make underline respect shrink/strech (rules package) ([a5d99f0](https://github.com/sile-typesetter/sile/commit/a5d99f0619bb58309313ece1ba320a5e465681a2))
* **packages:** Make boxaround respect shrink/stretch (rules package) ([9d8f708](https://github.com/sile-typesetter/sile/commit/9d8f7086e1f469a24b032307b43dc801fe10fd92))
* **packages:** Make underline respect shrink/stretch (rules package) ([a5d99f0](https://github.com/sile-typesetter/sile/commit/a5d99f0619bb58309313ece1ba320a5e465681a2))
* **typesetter:** Enable bidi for default typesetter on package load ([6a8d7f4](https://github.com/sile-typesetter/sile/commit/6a8d7f400faca53d825f1fea000d51f5e967addb))

### [0.12.2](https://github.com/sile-typesetter/sile/compare/v0.12.1...v0.12.2) (2022-01-28)
Expand Down
4 changes: 2 additions & 2 deletions documentation/c04-useful.sil
Original file line number Diff line number Diff line change
Expand Up @@ -201,11 +201,11 @@ The following commands are intended to be used between paragraphs and apply to p
\item{\autodoc:command{\pagebreak} and \autodoc:command{\supereject} request a non-negotiable page break, and are more forceful variants of the previous commands, ensuring that a new page is opened even if there are remaining frames on the page.}
\end{itemize}

With \autodoc:command{\framebreak} and \autodoc:command{\pagebreak}, all vertical strechable elements%
With \autodoc:command{\framebreak} and \autodoc:command{\pagebreak}, all vertical stretchable elements%
\footnote{Vertical: Here, in this document in latin script.
The more advanced topic of writing directions and foreign scripts is tackled later in this manual.}
are expanded to fill up the remaining space as much as possible.
The \autodoc:command{\eject} and \autodoc:command{\supereject} variants insert an infinite vertical stretch, so that all vertical strechable elements on the page stay at their natural size.
The \autodoc:command{\eject} and \autodoc:command{\supereject} variants insert an infinite vertical stretch, so that all vertical stretchable elements on the page stay at their natural size.

\section{Including other files and code}

Expand Down
241 changes: 133 additions & 108 deletions documentation/c09-concepts.sil
Original file line number Diff line number Diff line change
Expand Up @@ -2,71 +2,152 @@
\include[src=documentation/macros.sil]
\chapter{The Nitty Gritty}

\noindent{}We are finally at the bottom of our delve into SILE’s commands
and settings. Here are the basic building blocks out of which all of the
other operations in SILE are created.
We are finally at the bottom of our delve into SILE’s commands and settings.
Here are the basic building blocks out of which all of the other operations in SILE are created.

\note{At this point, it is expected that
you are a class designer, and will be able to follow the details of how
SILE implements these commands and features; we will also explain how to
interact with these components at the Lua level.}
\note{At this point, it is expected that you are a class or package designer, and will be able to follow the details of how SILE implements these commands and features;
we will also explain how to interact with these components at the Lua level.}

\section{Measurements and lengths}

Before dabbling into more advanced topics, let’s introduce “measurements” and “lengths” in SILE,
the two available Lua constructs for representing dimensions.

Measurements are specified in terms of \code{SILE.measurement} objects.
It is a basic construct with an amount and a unit. Let us illustrate two common ways for creating such an object in Lua (from a string, with same syntax as in command parameters; or from a Lua table).

\begin[type=autodoc:codeblock]{raw}
local m1 = SILE.measurement("10pt")
local m2 = SILE.measurement({ amount = 10, unit = "pt" })
\end{raw}

SILE also provides a more advanced construct specified in terms of \code{SILE.length} objects;
these are “three-dimensional” dimensions, in that they consist in a base measurement plus stretch and shrink measurements.
They are therefore composed of three \code{SILE.measurement}.

\begin[type=autodoc:codeblock]{raw}
local l1 = SILE.length("10pt plus 2pt minus 1pt")
local l2 = SILE.length({ length = "1Opt", stretch = "2pt", shrink = "1pt" })
\end{raw}

Both of these are used for various purposes.
In many cases, they are nearly interchangeable.
Casting from one to the other is straightforward:
casting a length to a measurement returns just the base measurement and discards the stretch and shrink properties;
casting a measurement to a length sets its stretch and shrink properties to zero.

\begin[type=autodoc:codeblock]{raw}
local l3 = SILE.length(SILE.measurement("10pt")) -- 10pt, without stretch and shrink
local m3 = SILE.measurement(SILE.length("10pt plus 2pt minus 1pt")) -- 10pt
\end{raw}

Proper casting is important, for your code to remain portable across the various versions of the Lua language.

\section{Boxes, glue, and penalties}

SILE’s job, looking at it in very abstract terms, is all about arranging
little boxes on a page. Some of those boxes have letters in them, and
those letters are such-and-such a number of points wide and
such-and-such a number of points high;
SILE’s job, looking at it in very abstract terms, is all about arranging little boxes on a page.
Some of those boxes have letters in them, and those letters are such-and-such a number of points wide and such-and-such a number of points high;
some of the boxes are empty but are there just to take up space.
When a horizontal row of boxes has been decided (i.e., when a line break is determined)
then the whole row of boxes is put into another box and the vertical list
of boxes are then arranged to form a page.
When a horizontal row of boxes has been decided (i.e., when a line break is determined) then the whole row of boxes is put into another box and the vertical list of boxes are then arranged to form a page.

Conceptually, then, SILE knows about a few different basic components:
horizontal boxes (such as a letter); horizontal glue (the stretchable or shrinkable
space between words); vertical boxes (a line of text); vertical glue (the space
between lines and paragraphs); and penalties (information about where and when
not to break lines and pages).\footnote{Additionally there are three more types of box
that SILE cares about: N-nodes, unshaped nodes, and discretionaries.}

\begin{itemize}
\item{Horizontal boxes (such as a letter)}
\item{Horizontal glue (such as the stretchable or shrinkable space between words)}
\item{Vertical boxes (typically, a line of text)}
\item{Vertical glue (such as the space between lines and paragraphs)}
\item{Penalties (information about where and when not to break lines and pages)}
\end{itemize}

Additionally, horizontal boxes are further specialized.\footnote{The math support in SILE also defines additional types of boxes, not discussed here.}

\begin{itemize}
\item{Discretionaries (special construct used when a word is hyphenated)}
\item{N-nodes and unshaped nodes (text content shaped according to a certain font, or not yet shaped and measured)}
\item{Migrating boxes (such as foonote content)}
\end{itemize}

The most immediately useful of these are horizontal and vertical glue.
Horizontal and vertical glue can be explicitly added into SILE‘s processing
stream using the \code{\\glue} and \code{\\skip} commands. These take a
\code{width} and a \code{height} parameter, respectively, both of which are
glue dimensions. For instance, the \code{\\smallskip} command is
the equivalent of \code{\\skip[height=3pt plus 1pt minus 1pt]}; \code{\\thinspace}
is defined as being \code{\\glue[width=0.16667em]}.

Similarly, there is a \code{\\penalty} command for inserting penalty nodes;
\code{\\break} is defined as \code{\\penalty[penalty=-10000]} and \code{\\nobreak}
is \code{\\penalty[penalty=10000]}.

You can also create horizontal and vertical boxes from within SILE. One
reason for doing so would be to explicitly avoid material being broken up by a
page or line break; another reason for doing so would be that once you box some
material up, you then know how wide or tall it is. The \code{\\hbox} and \code{\\vbox}
commands put their contents into a box; when called from Lua, they also \em{return}
the new box.

\subsection{From Lua}

SILE’s Lua interface contains a \code{nodefactory} for creating boxes and glue.
Before we get into that, however, you need to know that glue measurements in SILE
should always be specified in terms of \code{SILE.length} objects; these are
“three-dimensional” lengths, in that they consist of a base length plus stretch and
shrink. To construct a \code{SILE.length}:
Horizontal and vertical glue can be explicitly added into SILE‘s processing stream using the \autodoc:command{\glue} and \autodoc:command{\skip} commands.
These take a \autodoc:parameter{width} and a \autodoc:parameter{height} parameter, respectively, both of which are glue dimensions.
For instance, the \autodoc:command{\smallskip} command is the equivalent of \autodoc:command{\skip[height=3pt plus 1pt minus 1pt]};
\autodoc:command{\thinspace} is defined as being \autodoc:command{\glue[width=0.16667em]}.

\begin[type=autodoc:codeblock]{raw}
local l = SILE.length({ length = x, stretch = y, shrink = z })
\end{raw}
Similarly, there is a \autodoc:command{\penalty} command for inserting penalty nodes;
\autodoc:command{\break} is defined as \autodoc:command{\penalty[penalty=-10000]}
and \autodoc:command{\nobreak} is \autodoc:command{\penalty[penalty=10000]}.

You can also create horizontal and vertical boxes from within SILE.
One reason for doing so would be to explicitly avoid material being broken up by a page or line break;
another reason for doing so would be that once you box some material up, you then know how wide or tall it is.
The \autodoc:command{\hbox} and \autodoc:command{\vbox} commands put their contents into a box.

Now we can construct horizontal and vertical glue:
At a Lua coding level, SILE’s Lua interface contains a \code{nodefactory} for creating boxes and glue.
Here is one way (among others) for you to construct horizontal and vertical glue:

\begin[type=autodoc:codeblock]{raw}
local glue = SILE.nodefactory.glue({ width = l })
local glue = SILE.nodefactory.glue({ width = l })
local vglue = SILE.nodefactory.vglue({ height = l })
\end{raw}

\section{Kerns}

\define[command=SILEkern]{\font[family=Gentium Plus]{% Book Basic has no +smcp, but readers don't need to know, since we're only using Book Basic as a holdover from old SILE which did.
S\lower[height=0.5ex]{I}L\kern[width=-.2em]\raise[height=0.6ex]{\font[features=+smcp]{e}}}}
\define[command=SILEglue]{\font[family=Gentium Plus]{%
S\lower[height=0.5ex]{I}L\glue[width=-.2em]\raise[height=0.6ex]{\font[features=+smcp]{e}}}}
\autodoc:command{\kern}’s are a type of \autodoc:command{\glue}, only different in that
while a \autodoc:command{\glue} can be broken at the end of a line, a \autodoc:command{\kern}
can’t. Hearkening back to our \SILEkern example from the \em{Macros and
Commands} chapter, consider that example, repeated enough times to cause a
linebreak, but with \autodoc:command{\glue}’s everywhere \autodoc:command{\kern}’s are used
instead:

\line
\SILEglue\SILEglue\SILEglue\SILEglue\SILEglue\SILEglue\SILEglue\SILEglue%
\SILEglue\SILEglue\SILEglue\SILEglue\SILEglue\SILEglue\SILEglue\SILEglue%
\SILEglue\SILEglue\SILEglue\SILEglue\SILEglue\SILEglue\SILEglue\SILEglue%
\SILEglue\color[color=#dd0000]{\SILEglue}\SILEglue\SILEglue\SILEglue%
\SILEglue\SILEglue\SILEglue\SILEglue\SILEglue\SILEglue\SILEglue\SILEglue%
\SILEglue\SILEglue\SILEglue\SILEglue\SILEglue\SILEglue\SILEglue\SILEglue%
\SILEglue\SILEglue\SILEglue\SILEglue\SILEglue\SILEglue\SILEglue\SILEglue%
\SILEglue\SILEglue\SILEglue\SILEglue\SILEglue\SILEglue\SILEglue%
\line

Note the \SILEglue in \color[color=#dd0000]{red} is broken
between its ‘L’ and ‘\raise[height=0.6ex]{\font[family=Gentium Plus,features=+smcp]{e}}’.
Instead, if we typeset the same line using \code{\\kern}’s as we had
originally:

\line
\SILEkern\SILEkern\SILEkern\SILEkern\SILEkern\SILEkern\SILEkern\SILEkern%
\SILEkern\SILEkern\SILEkern\SILEkern\SILEkern\SILEkern\SILEkern\SILEkern%
\SILEkern\SILEkern\SILEkern\SILEkern\SILEkern\SILEkern\SILEkern\SILEkern%
\SILEkern\color[color=#dd0000]{\SILEkern}\SILEkern\SILEkern\SILEkern%
\SILEkern\SILEkern\SILEkern\SILEkern\SILEkern\SILEkern\SILEkern\SILEkern%
\SILEkern\SILEkern\SILEkern\SILEkern\SILEkern\SILEkern\SILEkern\SILEkern%
\SILEkern\SILEkern\SILEkern\SILEkern\SILEkern\SILEkern\SILEkern\SILEkern%
\SILEkern\SILEkern\SILEkern\SILEkern\SILEkern\SILEkern\SILEkern%
\line

The line just continues on right off the page. Why this is a useful feature is
more obvious if there are spaces between them:

\line
Glues:

\SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \color[color=#dd0000]{\SILEglue} \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue
\line

\line
Kerns:

\SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \color[color=#dd0000]{\SILEkern} \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern
\line

\section{The typesetter}

SILE’s typesetting is organised by the \code{SILE.typesetter} object. It
maintains two queues of material that it is still working on: the node queue and
the output queue. Material in these queues is content that has been parsed but
Expand All @@ -90,8 +171,8 @@ into lines and added to the vertical output queue by calling the function
\code{SILE.typesetter:leaveHmode()}. This is handy when for writing custom
functions, but it is a fairly low level control. (It is unlikely to be
useful while writing a document.) A related but higher level command,
\code{\\par}, is more frequently used when writing a document and embedded in
the content. The \code{\\par} command first calls
\autodoc:command{\par}, is more frequently used when writing a document and embedded in
the content. The \autodoc:command{\par} command first calls
\code{SILE.typesetter:leaveHmode()}, then inserts a vertical skip according to
the \autodoc:setting{document.parskip} setting, then goes on to reset a number of
settings that are typically paragraph-related such as hanging indents.
Expand All @@ -101,7 +182,7 @@ the output, first ensure that the material in the current paragraph has been all
properly boxed-up and moved onto the output queue by calling
\code{SILE.typesetter:leaveHmode()}, then add your desired glue to the output
queue.
This is exactly what the \code{\\skip} and similar commands do.
This is exactly what the \autodoc:command{\skip} and similar commands do.

Adding boxes and glue to the typesetter’s queues is
such a common operation that the typesetter has some utility methods to construct
Expand Down Expand Up @@ -138,62 +219,6 @@ Adding horizontal and vertical penalties to the typesetter’s queues is similar
done with the \code{SILE.typesetter:pushPenalty(\{penalty = x\})} and
\code{SILE.typesetter:pushVpenalty(\{penalty = y\})} methods.

\subsection{Kerns}

\define[command=SILEkern]{\font[family=Gentium Plus]{% Book Basic has no +smcp, but readers don't need to know, since we're only using Book Basic as a holdover from old SILE which did.
S\lower[height=0.5ex]{I}L\kern[width=-.2em]\raise[height=0.6ex]{\font[features=+smcp]{e}}}}
\define[command=SILEglue]{\font[family=Gentium Plus]{%
S\lower[height=0.5ex]{I}L\glue[width=-.2em]\raise[height=0.6ex]{\font[features=+smcp]{e}}}}
\code{\\kern}’s are a type of \code{\\glue}, only different in that
while a \code{\\glue} can be broken at the end of a line, a \code{\\kern}
can’t. Hearkening back to our \SILEkern example from the \em{Macros and
Commands} chapter, consider that example, repeated enough times to cause a
linebreak, but with \code{\\glue}’s everywhere \code{\\kern}’s are used
instead:

\line
\SILEglue\SILEglue\SILEglue\SILEglue\SILEglue\SILEglue\SILEglue\SILEglue%
\SILEglue\SILEglue\SILEglue\SILEglue\SILEglue\SILEglue\SILEglue\SILEglue%
\SILEglue\SILEglue\SILEglue\SILEglue\SILEglue\SILEglue\SILEglue\SILEglue%
\SILEglue\color[color=#dd0000]{\SILEglue}\SILEglue\SILEglue\SILEglue%
\SILEglue\SILEglue\SILEglue\SILEglue\SILEglue\SILEglue\SILEglue\SILEglue%
\SILEglue\SILEglue\SILEglue\SILEglue\SILEglue\SILEglue\SILEglue\SILEglue%
\SILEglue\SILEglue\SILEglue\SILEglue\SILEglue\SILEglue\SILEglue\SILEglue%
\SILEglue\SILEglue\SILEglue\SILEglue\SILEglue\SILEglue\SILEglue%
\line

Note the \SILEglue in \color[color=#dd0000]{red} is broken
between its ‘L’ and ‘\raise[height=0.6ex]{\font[family=Gentium Plus,features=+smcp]{e}}’.
Instead, if we typeset the same line using \code{\\kern}’s as we had
originally:

\line
\SILEkern\SILEkern\SILEkern\SILEkern\SILEkern\SILEkern\SILEkern\SILEkern%
\SILEkern\SILEkern\SILEkern\SILEkern\SILEkern\SILEkern\SILEkern\SILEkern%
\SILEkern\SILEkern\SILEkern\SILEkern\SILEkern\SILEkern\SILEkern\SILEkern%
\SILEkern\color[color=#dd0000]{\SILEkern}\SILEkern\SILEkern\SILEkern%
\SILEkern\SILEkern\SILEkern\SILEkern\SILEkern\SILEkern\SILEkern\SILEkern%
\SILEkern\SILEkern\SILEkern\SILEkern\SILEkern\SILEkern\SILEkern\SILEkern%
\SILEkern\SILEkern\SILEkern\SILEkern\SILEkern\SILEkern\SILEkern\SILEkern%
\SILEkern\SILEkern\SILEkern\SILEkern\SILEkern\SILEkern\SILEkern%
\line

The line just continues on right off the page. Why this is a useful feature is
more obvious if there are spaces between them:

\line
Glues:

\SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \color[color=#dd0000]{\SILEglue} \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue \SILEglue
\line

\line
Kerns:

\SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \color[color=#dd0000]{\SILEkern} \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern \SILEkern
\line


\section{Frames}

As we have previously mentioned, SILE arranges text into frames on the page.
Expand Down

0 comments on commit 40896e3

Please sign in to comment.