summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilipp Gesang <phg42.2a@gmail.com>2013-05-01 18:34:44 +0200
committerPhilipp Gesang <phg42.2a@gmail.com>2013-05-01 18:34:44 +0200
commit7cf60286cb69e8b5ffc47c06bdc9a18bb941e306 (patch)
treebc11ccbfd25d8a4482c8f897c9ac1d615681db9a
parent4466687a3a53e7868bd157ed6f8eac637ea182b5 (diff)
downloadluaotfload-7cf60286cb69e8b5ffc47c06bdc9a18bb941e306.tar.gz
add feature related functionality to auxlib
-rw-r--r--luaotfload-auxiliary.lua164
-rwxr-xr-xmkglyphlist6
-rw-r--r--tests/pln-aux-1.tex4
-rw-r--r--tests/pln-aux-2.tex102
4 files changed, 273 insertions, 3 deletions
diff --git a/luaotfload-auxiliary.lua b/luaotfload-auxiliary.lua
index 1f0c79c..2d55db5 100644
--- a/luaotfload-auxiliary.lua
+++ b/luaotfload-auxiliary.lua
@@ -18,9 +18,15 @@ luaotfload.aux = luaotfload.aux or { }
config = config or { }
config.luaotfload = config.luaotfload or { }
-local utf8 = unicode.utf8
+local aux = luaotfload.aux
+local log = luaotfload.log
+local identifiers = fonts.hashes.identifiers
-local aux = luaotfload.aux
+
+local utf8 = unicode.utf8
+local stringlower = string.lower
+local stringformat = string.format
+local stringgsub = string.gsub
-----------------------------------------------------------------------
--- font patches
@@ -81,7 +87,7 @@ luatexbase.add_to_callback(
"luaotfload.aux.patch_cambria_domh")
-----------------------------------------------------------------------
---- fonts
+--- glyphs
-----------------------------------------------------------------------
--- int -> int -> bool
@@ -114,4 +120,156 @@ end
aux.do_if_glyph_else = do_if_glyph_else
+-----------------------------------------------------------------------
+--- features / scripts / languages
+-----------------------------------------------------------------------
+--- lots of arrowcode ahead
+
+--[[doc--
+This function, modeled after “check_script()” from fontspec, returns
+true if in the given font, the script “asked_script” is accounted for in at
+least one feature.
+--doc]]--
+
+--- int -> string -> bool
+local provides_script = function (font_id, asked_script)
+ asked_script = stringlower(asked_script)
+ if font_id and font_id > 0 then
+ local fontdata = identifiers[font_id].shared.rawdata
+ if fontdata then
+ local fontname = fontdata.metadata.fontname
+ local features = fontdata.resources.features
+ for method, featuredata in next, features do
+ --- where method: "gpos" | "gsub"
+ for feature, data in next, featuredata do
+ if data[asked_script] then
+ log(stringformat(
+ "font no %d (%s) defines feature %s for script %s",
+ font_id, fontname, feature, asked_script))
+ return true
+ end
+ end
+ end
+ log(stringformat(
+ "font no %d (%s) defines no feature for script %s",
+ font_id, fontname, asked_script))
+ end
+ end
+ log(stringformat("no font with id %d", font_id))
+ return false
+end
+
+aux.provides_script = provides_script
+
+--[[doc--
+This function, modeled after “check_language()” from fontspec, returns
+true if in the given font, the language with tage “asked_language” is
+accounted for in the script with tag “asked_script” in at least one
+feature.
+--doc]]--
+
+--- int -> string -> string -> bool
+local provides_language = function (font_id, asked_script, asked_language)
+ asked_script = stringlower(asked_script)
+ asked_language = stringlower(asked_language)
+ if font_id and font_id > 0 then
+ local fontdata = identifiers[font_id].shared.rawdata
+ if fontdata then
+ local fontname = fontdata.metadata.fontname
+ local features = fontdata.resources.features
+ for method, featuredata in next, features do
+ --- where method: "gpos" | "gsub"
+ for feature, data in next, featuredata do
+ local scriptdata = data[asked_script]
+ if scriptdata and scriptdata[asked_language] then
+ log(stringformat("font no %d (%s) defines feature %s "
+ .. "for script %s with language %s",
+ font_id, fontname, feature,
+ asked_script, asked_language))
+ return true
+ end
+ end
+ end
+ log(stringformat(
+ "font no %d (%s) defines no feature for script %s with language %s",
+ font_id, fontname, asked_script, asked_language))
+ end
+ end
+ log(stringformat("no font with id %d", font_id))
+ return false
+end
+
+aux.provides_language = provides_language
+
+--[[doc--
+We strip the syntax elements from feature definitions (shouldn’t
+actually be there in the first place, but who cares ...)
+--doc]]--
+
+local lpeg = require"lpeg"
+local C, P, S = lpeg.C, lpeg.P, lpeg.S
+local lpegmatch = lpeg.match
+
+local sign = S"+-"
+local rhs = P"=" * P(1)^0 * P(-1)
+local strip_garbage = sign^-1 * C((1 - rhs)^1)
+
+--s = "+foo" --> foo
+--ss = "-bar" --> bar
+--sss = "baz" --> baz
+--t = "foo=bar" --> foo
+--tt = "+bar=baz" --> bar
+--ttt = "-baz=true" --> baz
+--
+--print(lpeg.match(strip_garbage, s))
+--print(lpeg.match(strip_garbage, ss))
+--print(lpeg.match(strip_garbage, sss))
+--print(lpeg.match(strip_garbage, t))
+--print(lpeg.match(strip_garbage, tt))
+--print(lpeg.match(strip_garbage, ttt))
+
+--[[doc--
+This function, modeled after “check_feature()” from fontspec, returns
+true if in the given font, the language with tag “asked_language” is
+accounted for in the script with tag “asked_script” in feature
+“asked_feature”.
+--doc]]--
+
+--- int -> string -> string -> string -> bool
+local provides_feature = function(font_id, asked_script,
+ asked_language, asked_feature)
+ asked_script = stringlower(asked_script)
+ asked_language = stringlower(asked_language)
+ asked_feature = lpegmatch(strip_garbage, asked_feature)
+
+ if font_id and font_id > 0 then
+ local fontdata = identifiers[font_id].shared.rawdata
+ if fontdata then
+ local features = fontdata.resources.features
+ local fontname = fontdata.metadata.fontname
+ for method, featuredata in next, features do
+ --- where method: "gpos" | "gsub"
+ local feature = featuredata[asked_feature]
+ if feature then
+ local scriptdata = feature[asked_script]
+ if scriptdata and scriptdata[asked_language] then
+ log(stringformat("font no %d (%s) defines feature %s "
+ .. "for script %s with language %s",
+ font_id, fontname, asked_feature,
+ asked_script, asked_language))
+ return true
+ end
+ end
+ end
+ log(stringformat(
+ "font no %d (%s) does not define feature %s for script %s with language %s",
+ font_id, fontname, asked_feature, asked_script, asked_language))
+ end
+ end
+ log(stringformat("no font with id %d", font_id))
+ return false
+end
+
+aux.provides_feature = provides_feature
+
-- vim:tw=71:sw=2:ts=2:expandtab
diff --git a/mkglyphlist b/mkglyphlist
index 9ee1528..d73a608 100755
--- a/mkglyphlist
+++ b/mkglyphlist
@@ -8,6 +8,12 @@
-- VERSION: 1.0
-- CREATED: 04/23/2013 12:42:17 PM CEST
-----------------------------------------------------------------------
+-- interesting thread on the Context list:
+-- http://www.ntg.nl/pipermail/ntg-context/2008/029057.html
+-----------------------------------------------------------------------
+
+
+-----------------------------------------------------------------------
-- config
-----------------------------------------------------------------------
local glyphfile = "./glyphlist.txt"
diff --git a/tests/pln-aux-1.tex b/tests/pln-aux-1.tex
index f33ef21..a504850 100644
--- a/tests/pln-aux-1.tex
+++ b/tests/pln-aux-1.tex
@@ -1,4 +1,8 @@
\input luaotfload.sty
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% usage for glyph tests
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\baselineskip=17.28pt
\font\iwonaregular=name:iwona at 14.4pt
diff --git a/tests/pln-aux-2.tex b/tests/pln-aux-2.tex
new file mode 100644
index 0000000..62192a5
--- /dev/null
+++ b/tests/pln-aux-2.tex
@@ -0,0 +1,102 @@
+\input luaotfload.sty
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% script, features, and language
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\font\minionregular=file:MinionPro_Regular.otf at 9pt
+\font\biolinum=file:LinBiolinum_R.otf at 9pt
+\font\cmuregular=file:cmunrm.otf at 9pt
+
+%% (1) luaotfload.aux.provides_script(font_id, script)
+%% #1 defined font; #2 OT script tag
+\def\providesscript[#1][#2]{%
+ \bgroup#1%
+ let’s see whether \detokenize{#1} has script #2:
+ \directlua{
+ local aux = luaotfload.aux
+ local succ = aux.provides_script(font.current(), [[#2]])
+ if succ then tex.sprint"true" else tex.sprint"false" end
+ }%
+ \egroup
+ \endgraf%
+}
+
+\providesscript [\minionregular][latn]%% Latin
+\providesscript [\biolinum][latn]
+\providesscript [\cmuregular][latn]
+\providesscript [\minionregular][cyrl]%% Cyrillic
+\providesscript [\biolinum][cyrl]
+\providesscript [\cmuregular][cyrl]
+\providesscript [\minionregular][tibt]%% Tibetan
+\providesscript [\biolinum][tibt]
+\providesscript [\cmuregular][tibt]
+
+\hrule % --------------------------------------------------------------
+
+%% (2) luaotfload.aux.provides_language(font_id, script, language)
+%% #1 defined font; #2 OT script tag; #3 OT language tag
+\def\provideslanguage[#1][#2][#3]{%
+ \bgroup#1%
+ let’s see whether \detokenize{#1} supports language #3 for script #2:
+ \directlua{
+ local aux = luaotfload.aux
+ local succ = aux.provides_language(font.current(), [[#2]], [[#3]])
+ if succ then tex.sprint"true" else tex.sprint"false" end
+ }%
+ \egroup
+ \endgraf%
+}
+
+\provideslanguage [\minionregular][latn][nld]%% Latin/Dutch
+\provideslanguage [\biolinum][latn][nld]
+\provideslanguage [\cmuregular][latn][nld]
+\provideslanguage [\minionregular][latn][deu]%% Latin/German
+\provideslanguage [\biolinum][latn][deu]
+\provideslanguage [\cmuregular][latn][deu]
+\provideslanguage [\minionregular][cyrl][rus]%% Cyrillic/Russian
+\provideslanguage [\biolinum][cyrl][rus]
+\provideslanguage [\cmuregular][cyrl][rus]
+\provideslanguage [\minionregular][cyrl][klm]%% Cyrillic/Kalmyk
+\provideslanguage [\biolinum][cyrl][klm]
+\provideslanguage [\cmuregular][cyrl][klm]
+\provideslanguage [\minionregular][cyrl][srb]%% Cyrillic/Serbian
+\provideslanguage [\biolinum][cyrl][srb]
+\provideslanguage [\cmuregular][cyrl][srb]
+\provideslanguage [\minionregular][tibt][tib]%% Tibetan
+\provideslanguage [\biolinum][tibt][tib]
+\provideslanguage [\cmuregular][tibt][tib]
+
+\hrule % --------------------------------------------------------------
+
+%% (3) luaotfload.aux.provides_feature(
+%% font_id, script, language, feature)
+%% #1 defined font; #2 OT script tag;
+%% #3 OT language tag; #4 OT feature
+\def\providesfeature[#1][#2][#3][#4]{%this is getting ridiculous
+ \bgroup#1%
+ let’s see whether \detokenize{#1} supports feature #4 for the
+ combination of script #2 with language #3:
+ \directlua{
+ local aux = luaotfload.aux
+ local succ = aux.provides_feature(
+ font.current(), [[#2]], [[#3]], [[#4]])
+ if succ then tex.sprint"true" else tex.sprint"false" end
+ }%
+ \egroup
+ \endgraf%
+}
+
+\providesfeature [\minionregular][latn][nld][liga]%% Latin/Dutch
+\providesfeature [\biolinum][latn][nld][liga]
+\providesfeature [\cmuregular][latn][nld][liga]
+\providesfeature [\minionregular][latn][deu][liga]%% Latin/German
+\providesfeature [\biolinum][latn][deu][liga]
+\providesfeature [\cmuregular][latn][deu][liga]
+\providesfeature [\minionregular][cyrl][srb][liga]%% Cyrillic/Serbian
+\providesfeature [\biolinum][cyrl][srb][liga]
+\providesfeature [\cmuregular][cyrl][srb][liga]
+\providesfeature [\minionregular][tibt][tib][liga]%% Tibetan
+\providesfeature [\biolinum][tibt][tib][liga]
+\providesfeature [\cmuregular][tibt][tib][liga]
+
+\bye