Skip to content

Commit

Permalink
Merge a1ea6e8 into 8decf5b
Browse files Browse the repository at this point in the history
  • Loading branch information
Omikhleia committed Nov 18, 2023
2 parents 8decf5b + a1ea6e8 commit 8361bce
Show file tree
Hide file tree
Showing 7 changed files with 865 additions and 42 deletions.
40 changes: 38 additions & 2 deletions documentation/c07-settings.sil
Expand Up @@ -212,7 +212,9 @@ saying that anyone who would letterspace lowercase would steal sheep.\footnote{H
\section{Typesetter settings}

The settings which affect SILE’s spacing controls have the most obvious effect
on a document; the typesetter itself has some knobs that can be twiddled:
on a document; the typesetter itself has some knobs that can be twiddled.

\subsection{Paragraphing}

\autodoc:setting{typesetter.widowpenalty} and \autodoc:setting{typesetter.orphanpenalty}\footnote{TeX
users, please notice the renaming.} affect how strongly SILE is averse to
Expand Down Expand Up @@ -260,7 +262,41 @@ off the filling glue at the end of the paragraph.
\par
\end{autodoc:example}

\medskip
\subsection{Automated italic correction}

When an italicized word is followed or preceded by non-italicized text, the spacing may need to be adjusted, or “corrected”, so that the characters do not overlap.
You might thus want to insert some additional space between italicized words and non-italicized ones.

Here is some gibberish exemplifying the issue.

\begin{autodoc:example}%
\quad{}(\em{fluff}) ¡\em{fancyful proof}! [\em{puff}] \em{fluff}ⁿ
\par
\end{autodoc:example}

Inserting the necessary spaces manually is quite tedious, not to say impractical.
However, the concept of italic correction does not exist in OpenType fonts, and they do not provide the metrics that would allow a typesetting system to implement it easily.\footnote{%
This would apply to Graphite fonts too.
More generally, there is no known font format supporting kerning across font style changes.
(Well, some TeX fonts have such a possibility, but it does not really help here.)}
A heuristic approach is to use the difference between a glyph’s bounding box and its advance width (when switching from italics to roman) or its bearing width (the other way round).
Assuming italics is slanted forward (in left-to-right writing direction) and that italicized glyphs usually reach their maximum extent to the right towards their top (and towards their bottom, on their left side), then it is possible to approximate a fairly decent correction.

Be aware, nevertheless, that this solution cannot be made perfect, even assuming a reasonable choice of fonts.
Pathological cases may still occur, even in latin scripts, for which there is no solution but using manual kerning.

To enable automated italic correction, you can set the \autodoc:setting{typesetter.italicCorrection} setting to \code{true}.
Let’s turn it on and check how our previous gibberish now behaves.

\begin{autodoc:example}%
\set[parameter=typesetter.italicCorrection, value=true]{%
\quad{}(\em{fluff}) ¡\em{fancyful proof}! [\em{puff}] \em{fluff}ⁿ
\par}
\end{autodoc:example}

Note that this setting only works on full paragraphs, or with horizontal boxes constructed with \autodoc:command{\hbox{<content>}}.\footnote{%
That is, when characters are actually \em{shaped}, so that SILE knows their properties and metrics.}
In other terms, turning it on or off around just a few words in a sentence will not have the intended effect.

\section{Linebreaking settings}

Expand Down
8 changes: 8 additions & 0 deletions justenough/justenoughharfbuzz.c
Expand Up @@ -234,6 +234,8 @@ int je_hb_shape (lua_State *L) {
double height = extents.y_bearing * point_size / upem;
double tHeight = extents.height * point_size / upem;
double width = glyph_pos[j].x_advance * point_size / upem;
double x_bearing = extents.x_bearing * point_size / upem;
double glyphWidth = extents.width * point_size / upem;

/* The PDF model expects us to make positioning adjustments
after a glyph is painted. For this we need to know the natural
Expand Down Expand Up @@ -264,6 +266,12 @@ int je_hb_shape (lua_State *L) {
lua_pushstring(L, "depth");
lua_pushnumber(L, -tHeight - height);
lua_settable(L, -3);
lua_pushstring(L, "x_bearing");
lua_pushnumber(L, x_bearing);
lua_settable(L, -3);
lua_pushstring(L, "glyphWidth");
lua_pushnumber(L, glyphWidth);
lua_settable(L, -3);
}
/* Cleanup */
hb_buffer_destroy(buf);
Expand Down
3 changes: 3 additions & 0 deletions languages/fr.lua
Expand Up @@ -67,6 +67,9 @@ local getSpaceGlue = function(options, parameter)
SILE.settings:set("font.filename", options.filename)
sg = sg:absolute()
end)
-- Track a subtype on that kern:
-- See automated italic correction at the typesetter level.
sg.subtype = "punctspace"
return sg
end

Expand Down
9 changes: 5 additions & 4 deletions shapers/harfbuzz.lua
Expand Up @@ -121,11 +121,12 @@ function shaper.preAddNodes (_, items, nnodeValue) -- Check for complex nodes
end

function shaper.addShapedGlyphToNnodeValue (_, nnodevalue, shapedglyph)
if nnodevalue.complex then
-- Note: previously we stored the shaped items only for "complex" nodes
-- (nodevalue.comple). We now always do it, so as to have them at hand for
-- italic correction.
if not nnodevalue.items then nnodevalue.items = {} end
nnodevalue.items[#nnodevalue.items+1] = shapedglyph

if not nnodevalue.items then nnodevalue.items = {} end
nnodevalue.items[#nnodevalue.items+1] = shapedglyph
end
if not nnodevalue.glyphString then nnodevalue.glyphString = {} end
if not nnodevalue.glyphNames then nnodevalue.glyphNames = {} end
table.insert(nnodevalue.glyphString, shapedglyph.gid)
Expand Down

0 comments on commit 8361bce

Please sign in to comment.