summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilipp Gesang <phg@phi-gamma.net>2016-04-20 07:40:31 +0200
committerPhilipp Gesang <phg@phi-gamma.net>2016-04-20 07:40:31 +0200
commit1c93f97f4bce1b399e90f65657e95ef13434128c (patch)
treec0bb9705e1276e548a19ef656749d890d78860f6
parentc35210aaaf992793bd111a0bd90e28630c7d2101 (diff)
parente14f3c50eedcd2652125177db0deacd8079cc048 (diff)
downloadluaotfload-1c93f97f4bce1b399e90f65657e95ef13434128c.tar.gz
Merge pull request #335 from phi-gamma/master
format and feature handling, fixes for 2.7
-rw-r--r--NEWS3
-rw-r--r--doc/luaotfload-main.tex88
-rw-r--r--src/luaotfload-auxiliary.lua10
-rw-r--r--src/luaotfload-features.lua172
-rw-r--r--src/luaotfload-loaders.lua12
-rw-r--r--src/luaotfload-main.lua2
6 files changed, 96 insertions, 191 deletions
diff --git a/NEWS b/NEWS
index 7325433..ef593b4 100644
--- a/NEWS
+++ b/NEWS
@@ -6,7 +6,8 @@ Change History
* Glyph fallbacks.
* Latest fontloader code.
* Adapt packaging to changed upstream file layout.
- * Remove support for builtin Fontforge libraries.
+ * Remove support for builtin Fontforge libraries (this includes the PFA,
+ PFB, and feature file readers).
2015/12/09, luaotfload v2.6
* Add ``sign`` target to makefile for automated package signing.
diff --git a/doc/luaotfload-main.tex b/doc/luaotfload-main.tex
index fdca3c0..c418991 100644
--- a/doc/luaotfload-main.tex
+++ b/doc/luaotfload-main.tex
@@ -584,38 +584,6 @@ obviously, \inlinecode{random}.
defaulting to \inlinecode{dflt}.
\endaltitem
- \beginaltitem {featurefile}
- A comma-separated list of feature files to be applied to the
- font.
- %
- Feature files contain a textual representation of
- \OpenType tables and extend the features of a font
- on fly.
- %
- After they are applied to a font, features defined in a
- feature file can be enabled or disabled just like any
- other font feature.
- %
- The syntax is documented in \identifier{Adobe}’s
- \OpenType Feature File Specification.\footnote{%
- Cf. \hyperlink {http://www.adobe.com/devnet/opentype/afdko/topic_feature_file_syntax.html}.
- Feature file support is part of the engine which at the
- time of this writing (2014) implements the spec only
- partially.
- See the
- \hyperlink [\LUATEX tracker]{http://tracker.luatex.org/view.php?id=231}
- for details.
- }
-
- For a demonstration of how to set a \inlinecode{tkrn} feature consult
- the file \inlinecode{tkrn.fea} that is part of \identifier{luaotfload}.
- It can be read and applied as follows:
-
- \beginlisting
- \font \test = Latin Modern Roman:featurefile=tkrn.fea;+tkrn
- \endlisting
- \endaltitem
-
\beginaltitem {color}
A font color, defined as a triplet of two-digit hexadecimal
\abbrev{rgb} values, with an optional fourth value for
@@ -816,6 +784,8 @@ advance as well as a special \emphasis{request syntax}. Furthermore, this
allows to define \emphasis{fallback fonts} to supplement fonts that may lack
certain required glyphs.
+\beginsubsection {Fallbacks}
+
For example, the \identifier{Latin Modern} family of fonts does, as indicated
in the name, not provide Cyrillic glyphs. If Latin script dominates in the copy
with interspersed Cyrillic, a fallback can be created from a similiar looking
@@ -832,7 +802,59 @@ that it too derives from Knuth’s original \identifier{Computer Modern} series:
\bye
\endlisting
-TODO
+As simple as this may look on the first glance, this approach is entirely
+inappropriate if more than a couple letters are required from a different font.
+Because the combination pulls nothing except the glyph data, all of the
+important other information that constitute a proper font -- kerning, styles,
+features, and suchlike -- will be missing.
+
+\endsubsection %% Fallbacks
+
+\beginsubsection {Combinations}
+
+Generalizing the idea of a \emphasis{fallback font}, it is also possible to
+pick definite sets of glyphs from multiple fonts. On a bad day, for instance,
+it may be the sanest choice to start out with \identifier{EB Garamond} italics,
+typeset all decimal digits in the bold italics of \identifier{GNU Freefont},
+and tone down the punctuation with extra thin glyphs from \identifier{Source
+Sans}:
+
+\beginlisting
+ \def \feats {-tlig;-liga;mode=base;-kern}
+ \def \fileone {EBGaramond12-Italic.otf}
+ \def \filetwo {FreeMonoBoldOblique.otf}
+ \def \filethree {SourceSansPro-ExtraLight.otf}
+
+ \input luaotfload.sty
+
+ \font \one = file:\fileone :\feats
+ \font \two = file:\filetwo :\feats
+ \font \three = file:\filethree:\feats
+
+ \font \onetwothree = "combo: 1 -> \fontid\one;
+ 2 -> \fontid\two, 0x30-0x39;
+ 3 -> \fontid\three, 0x21*0x3f;
+
+ {\onetwothree \TeX—0123456789—?!}
+ \bye
+\endlisting
+
+\noindent Despite the atrocious result, the example demonstrates well the
+syntax that is used to specify ranges and fonts. Fonts are being referred to by
+their internal index which can be obtained by passing the font command into the
+\texmacro{fontid} macro, e. g. \inlinecode{\fontid\one}, after a font has been
+defined. The first component of the combination is the base font which will be
+extended by the others. It is specified by the index alone.
+
+All further fonts require either the literal \inlinecode{fallback} or a list of
+codepoint definitions to be appended after a comma. The elements of this list
+again denote either single codepoints like \inlinecode{0x21} (referring to the
+exclamation point character) or ranges of codepoints (\inlinecode{0x30-0x39}).
+Elements are separated by the \identifier{ASCII} asterisk character
+(\inlinecode{*}). The characters referenced in the list will be imported from
+the respective font, if available.
+
+\endsubsection %% Combinations
\endsection
diff --git a/src/luaotfload-auxiliary.lua b/src/luaotfload-auxiliary.lua
index 35f8f2b..3d300e7 100644
--- a/src/luaotfload-auxiliary.lua
+++ b/src/luaotfload-auxiliary.lua
@@ -42,7 +42,15 @@ local luaotfload_callbacks = { }
--- https://github.com/khaledhosny/luaotfload/issues/54
local rewrite_fontname = function (tfmdata, specification)
- tfmdata.name = [["]] .. specification .. [["]]
+ local format = tfmdata.format or tfmdata.properties.format
+ if format ~= "type1" then
+ if stringfind (specification, " ") then
+ tfmdata.name = stringformat ("%q", specification)
+ else
+ --- other specs should parse just fine
+ tfmdata.name = specification
+ end
+ end
end
local rewriting = false
diff --git a/src/luaotfload-features.lua b/src/luaotfload-features.lua
index 79f1416..5e9bf7b 100644
--- a/src/luaotfload-features.lua
+++ b/src/luaotfload-features.lua
@@ -1322,146 +1322,6 @@ local noflags = { false, false, false, false }
local tohash = table.tohash
-local function ancient_addfeature (data, feature, specifications)
- local descriptions = data.descriptions
- local resources = data.resources
- local lookups = resources.lookups
- local gsubfeatures = resources.features.gsub
- if gsubfeatures and gsubfeatures[feature] then
- -- already present
- else
- local sequences = resources.sequences
- local fontfeatures = resources.features
- local unicodes = resources.unicodes
- local lookuptypes = resources.lookuptypes
- local splitter = lpeg.splitter(" ",unicodes)
- local done = 0
- local skip = 0
- if not specifications[1] then
- -- so we accept a one entry specification
- specifications = { specifications }
- end
- -- subtables are tables themselves but we also accept flattened singular subtables
- for s=1,#specifications do
- local specification = specifications[s]
- local valid = specification.valid
- if not valid or valid(data,specification,feature) then
- local initialize = specification.initialize
- if initialize then
- -- when false is returned we initialize only once
- specification.initialize = initialize(specification) and initialize or nil
- end
- local askedfeatures = specification.features or everywhere
- local subtables = specification.subtables or { specification.data } or { }
- local featuretype = types[specification.type or "substitution"]
- local featureflags = specification.flags or noflags
- local featureorder = specification.order or { feature }
- local added = false
- local featurename = stringformat("ctx_%s_%s",feature,s)
- local st = { }
- for t=1,#subtables do
- local list = subtables[t]
- local full = stringformat("%s_%s",featurename,t)
- st[t] = full
- if featuretype == "gsub_ligature" then
- lookuptypes[full] = "ligature"
- for code, ligature in next, list do
- local unicode = tonumber(code) or unicodes[code]
- local description = descriptions[unicode]
- if description then
- local slookups = description.slookups
- if type(ligature) == "string" then
- ligature = { lpegmatch(splitter,ligature) }
- end
- local present = true
- for i=1,#ligature do
- if not descriptions[ligature[i]] then
- present = false
- break
- end
- end
- if present then
- if slookups then
- slookups[full] = ligature
- else
- description.slookups = { [full] = ligature }
- end
- done, added = done + 1, true
- else
- skip = skip + 1
- end
- end
- end
- elseif featuretype == "gsub_single" then
- lookuptypes[full] = "substitution"
- for code, replacement in next, list do
- local unicode = tonumber(code) or unicodes[code]
- local description = descriptions[unicode]
- if description then
- local slookups = description.slookups
- replacement = tonumber(replacement) or unicodes[replacement]
- if descriptions[replacement] then
- if slookups then
- slookups[full] = replacement
- else
- description.slookups = { [full] = replacement }
- end
- done, added = done + 1, true
- end
- end
- end
- end
- end
- if added then
- -- script = { lang1, lang2, lang3 } or script = { lang1 = true, ... }
- for k, v in next, askedfeatures do
- if v[1] then
- askedfeatures[k] = tabletohash(v)
- end
- end
- local sequence = {
- chain = 0,
- features = { [feature] = askedfeatures },
- flags = featureflags,
- name = featurename,
- order = featureorder,
- subtables = st,
- type = featuretype,
- }
- if specification.prepend then
- insert(sequences,1,sequence)
- else
- insert(sequences,sequence)
- end
- -- register in metadata (merge as there can be a few)
- if not gsubfeatures then
- gsubfeatures = { }
- fontfeatures.gsub = gsubfeatures
- end
- local k = gsubfeatures[feature]
- if not k then
- k = { }
- gsubfeatures[feature] = k
- end
- for script, languages in next, askedfeatures do
- local kk = k[script]
- if not kk then
- kk = { }
- k[script] = kk
- end
- for language, value in next, languages do
- kk[language] = value
- end
- end
- end
- end
- end
- if trace_loading then
- report_otf("registering feature %a, affected glyphs %a, skipped glyphs %a",feature,done,skip)
- end
- end
-end
-
local function current_addfeature(data,feature,specifications)
local descriptions = data.descriptions
local resources = data.resources
@@ -1856,19 +1716,29 @@ end
otf.addfeature = add_otf_feature
local install_extra_features = function (data, filename, raw)
+ local metadata = data and data.metadata
+ if not metadata then
+ logreport ("both", 4, "features",
+ "no metadata received from font “%s”; not \z
+ installing extra features.", filename)
+ return
+ end
+ local format = data.format
+ if not format then
+ logreport ("both", 4, "features",
+ "no format info for font “%s”/“%s”; not \z
+ installing extra features.",
+ fontname, filename)
+ return
+ end
for feature, specification in next, extrafeatures do
- local fontname
- local subfont
- local metadata = data.metadata
- if metadata then
- fontname = tostring (data.metadata.fontname)
- subfont = tonumber (metadata.subfontindex)
- end
if not fontname then fontname = "<unknown>" end
if not subfont then subfont = -1 end
+ local fontname = tostring (data.metadata.fontname) or "<unknown>"
+ local subfont = tonumber (metadata.subfontindex) or -1
logreport ("both", 3, "features",
"register synthetic feature “%s” for %s font “%s”(%d)",
- feature, data.format, fontname, subfont)
+ feature, format, fontname, subfont)
otf.features.register { name = feature, description = specification[2] }
otf.enhancers.addfeature (data, feature, specification[1])
end
@@ -1887,11 +1757,7 @@ return {
end
otf = fonts.handlers.otf
-
- --- hack for backwards compat with TL2014 loader
- otf.enhancers.addfeature = otf.version < 2.8 and ancient_addfeature
- or current_addfeature
-
+ otf.enhancers.addfeature = current_addfeature
otf.enhancers.register ("check extra features",
install_extra_features)
diff --git a/src/luaotfload-loaders.lua b/src/luaotfload-loaders.lua
index fb01821..d3828aa 100644
--- a/src/luaotfload-loaders.lua
+++ b/src/luaotfload-loaders.lua
@@ -41,6 +41,14 @@ local eval_reader = function (specification)
return eval ()
end
+local unsupported_reader = function (format)
+ return function (specification)
+ logreport ("both", 0, "loaders",
+ "font format “%s” unsupported; cannot load %s.",
+ format, tostring (specification.name))
+ end
+end
+
local install_formats = function ()
local fonts = fonts
if not fonts then return false end
@@ -72,8 +80,8 @@ local install_formats = function ()
return aux ("evl", eval_reader)
and aux ("lua", lua_reader)
- and aux ("pfa", function (spec) return readers.opentype (spec, "pfa", "type1") end)
- and aux ("pfb", function (spec) return readers.opentype (spec, "pfb", "type1") end)
+ and aux ("pfa", unsupported_reader "pfa")
+ and aux ("pfb", unsupported_reader "pfb")
and aux ("ofm", readers.tfm)
end
diff --git a/src/luaotfload-main.lua b/src/luaotfload-main.lua
index 3f1f602..92c1ff1 100644
--- a/src/luaotfload-main.lua
+++ b/src/luaotfload-main.lua
@@ -13,7 +13,7 @@ local luaotfload = luaotfload
luaotfload.log = luaotfload.log or { }
luaotfload.version = "2.7"
luaotfload.loaders = { }
-luaotfload.min_luatex_version = 95 --- i. e. 0.80
+luaotfload.min_luatex_version = 95 --- i. e. 0.95
luaotfload.fontloader_package = "reference" --- default: from current Context
local authors = "\z