texlive[48771] trunk: luaotfload (26sep18)
commits+karl at tug.org
commits+karl at tug.org
Wed Sep 26 22:50:34 CEST 2018
Revision: 48771
http://tug.org/svn/texlive?view=revision&revision=48771
Author: karl
Date: 2018-09-26 22:50:34 +0200 (Wed, 26 Sep 2018)
Log Message:
-----------
luaotfload (26sep18)
Modified Paths:
--------------
trunk/Build/source/texk/texlive/linked_scripts/luaotfload/luaotfload-tool.lua
trunk/Master/texmf-dist/doc/luatex/luaotfload/NEWS
trunk/Master/texmf-dist/doc/luatex/luaotfload/filegraph.pdf
trunk/Master/texmf-dist/doc/man/man1/luaotfload-tool.1
trunk/Master/texmf-dist/doc/man/man1/luaotfload-tool.man1.pdf
trunk/Master/texmf-dist/doc/man/man5/luaotfload.conf.5
trunk/Master/texmf-dist/doc/man/man5/luaotfload.conf.man5.pdf
trunk/Master/texmf-dist/scripts/luaotfload/luaotfload-tool.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-basics-gen.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-basics-nod.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-afk.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-cff.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-cid.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-con.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-def.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-dsp.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-ini.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-map.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-ocl.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-one.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-onr.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-osd.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-ota.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-otc.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-oti.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-otj.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-otl.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-oto.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-otr.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-ots.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-oup.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-tfm.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-ttf.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-fonts-enc.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-fonts-ext.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-fonts-syn.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-l-file.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-l-io.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-l-lpeg.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-l-lua.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-l-math.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-l-string.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-l-table.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-reference.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-util-fil.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-util-str.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-auxiliary.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-characters.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-colors.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-configuration.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-database.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-features.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-init.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-letterspace.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-log.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-main.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-parsers.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-status.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/luaotfload.sty
Added Paths:
-----------
trunk/Master/texmf-dist/doc/luatex/luaotfload/README.md
trunk/Master/texmf-dist/doc/luatex/luaotfload/filegraph.tex
trunk/Master/texmf-dist/doc/luatex/luaotfload/luaotfload-conf.pdf
trunk/Master/texmf-dist/doc/luatex/luaotfload/luaotfload-conf.tex
trunk/Master/texmf-dist/doc/luatex/luaotfload/luaotfload-latex.pdf
trunk/Master/texmf-dist/doc/luatex/luaotfload/luaotfload-latex.tex
trunk/Master/texmf-dist/doc/luatex/luaotfload/luaotfload-main.tex
trunk/Master/texmf-dist/doc/luatex/luaotfload/luaotfload-tool.pdf
trunk/Master/texmf-dist/doc/luatex/luaotfload/luaotfload-tool.rst
trunk/Master/texmf-dist/doc/luatex/luaotfload/luaotfload-tool.tex
trunk/Master/texmf-dist/doc/luatex/luaotfload/luaotfload.conf.rst
trunk/Master/texmf-dist/source/luatex/luaotfload/fontloader-reference-load-order.lua
trunk/Master/texmf-dist/source/luatex/luaotfload/fontloader-reference-load-order.tex
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-2018-09-24.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-imp-effects.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-imp-italics.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-imp-ligatures.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-imp-tex.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-ott.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-vfc.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-fonts-def.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-fonts-gbn.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-fonts-lig.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-fonts-mis.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-l-unicode.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/luaotfload-filelist.lua
Removed Paths:
-------------
trunk/Master/texmf-dist/doc/luatex/luaotfload/README
trunk/Master/texmf-dist/doc/luatex/luaotfload/luaotfload.pdf
trunk/Master/texmf-dist/doc/luatex/luaotfload/valgrind-kpse-suppression.sup
trunk/Master/texmf-dist/scripts/luaotfload/mkcharacters
trunk/Master/texmf-dist/scripts/luaotfload/mkglyphlist
trunk/Master/texmf-dist/scripts/luaotfload/mkimport
trunk/Master/texmf-dist/scripts/luaotfload/mkstatus
trunk/Master/texmf-dist/scripts/luaotfload/mktests
trunk/Master/texmf-dist/source/luatex/luaotfload/Makefile
trunk/Master/texmf-dist/source/luatex/luaotfload/filegraph.dot
trunk/Master/texmf-dist/source/luatex/luaotfload/luaotfload-latex.tex
trunk/Master/texmf-dist/source/luatex/luaotfload/luaotfload-main.tex
trunk/Master/texmf-dist/source/luatex/luaotfload/luaotfload-tool.rst
trunk/Master/texmf-dist/source/luatex/luaotfload/luaotfload.conf.rst
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-2017-02-11.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-basics.tex
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-font-gbn.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-fonts-demo-vf-1.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-fonts.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-fonts.tex
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-languages.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-languages.tex
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-math.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-math.tex
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-mplib.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-mplib.tex
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-plain.tex
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-preprocessor-test.tex
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-preprocessor.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-preprocessor.tex
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-swiglib-test.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-swiglib-test.tex
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-swiglib.lua
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-swiglib.tex
trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-test.tex
Modified: trunk/Build/source/texk/texlive/linked_scripts/luaotfload/luaotfload-tool.lua
===================================================================
--- trunk/Build/source/texk/texlive/linked_scripts/luaotfload/luaotfload-tool.lua 2018-09-26 20:49:48 UTC (rev 48770)
+++ trunk/Build/source/texk/texlive/linked_scripts/luaotfload/luaotfload-tool.lua 2018-09-26 20:50:34 UTC (rev 48771)
@@ -2,13 +2,13 @@
-----------------------------------------------------------------------
-- FILE: luaotfload-tool.lua
-- DESCRIPTION: database functionality
--- REQUIREMENTS: luaotfload 2.8
+-- REQUIREMENTS: luaotfload 2.9
-- AUTHOR: Khaled Hosny, Élie Roux, Philipp Gesang
-- LICENSE: GPL v2.0
-----------------------------------------------------------------------
luaotfload = luaotfload or { }
-local version = "2.8"
+local version = "2.9"
luaotfload.version = version
luaotfload.min_luatex_version = { 0, 95, 0 }
luaotfload.self = "luaotfload-tool"
Modified: trunk/Master/texmf-dist/doc/luatex/luaotfload/NEWS
===================================================================
--- trunk/Master/texmf-dist/doc/luatex/luaotfload/NEWS 2018-09-26 20:49:48 UTC (rev 48770)
+++ trunk/Master/texmf-dist/doc/luatex/luaotfload/NEWS 2018-09-26 20:50:34 UTC (rev 48771)
@@ -1,5 +1,17 @@
Change History
--------------
+2018-09-21 luaotfload v2.9
+ * added various testfiles for the l3build system/travis tests to the github repository
+ * solved a bug regarding directions https://github.com/u-fischer/lua-font-pond/issues/12
+ * adapted luaotfload-letterspace to new fontloader
+ * solved the case problem see https://github.com/u-fischer/lua-font-pond/issues/6
+ * Fix parsing of font.conf see https://github.com/lualatex/luaotfload/pull/420
+ * imported new versions of the context files - fontloader is compatible with luatex 1.08 again
+ * adapted the files list
+ * created a luaotfload-filelist.lua which describes the files of the package
+ * removed some not functional files
+ * adapted mkstatus to use the new file list.
+
2017-01-29, luaotfload v2.8:
* Latest fontloader code.
* Support for Luatex 1.0.
Deleted: trunk/Master/texmf-dist/doc/luatex/luaotfload/README
===================================================================
--- trunk/Master/texmf-dist/doc/luatex/luaotfload/README 2018-09-26 20:49:48 UTC (rev 48770)
+++ trunk/Master/texmf-dist/doc/luatex/luaotfload/README 2018-09-26 20:50:34 UTC (rev 48771)
@@ -1,97 +0,0 @@
-*******************************************************************************
- The Luaotfload Package
-*******************************************************************************
-
-Luaotfload is an adaptation of the ConTeXt font loading system for the Plain
-and LaTeX formats. It allows OpenType fonts to be loaded with font features
-accessible using an extended font request syntax while providing compatibility
-with XeTeX. By indexing metadata in a database it facilitates loading fonts by
-their proper names instead of file names.
-
-Luaotfload may be loaded in Plain LuaTeX with "\input luaotfload.sty" and in
-LuaLaTeX with "\usepackage{luaotfload}". LuaLaTeX users may be interested in
-the fontspec package which provides a high-level interface to the functionality
-provided by this package.
-
-Please see the documentation luaotfload.pdf for more information.
-
-This package is developed by the LuaLaTeX dev team on
-<http://github.com/lualatex/luaotfload>. Please report bugs to the issue
-tracker there.
-
-The development for LuaLaTeX is discussed on the lualatex-dev mailing list. See
-<http://www.tug.org/mailman/listinfo/lualatex-dev> for details.
-
-
-Responsible Persons
--------------------------------------------------------------------------------
-The following people have contributed to this package.
-
-Khaled Hosny <khaledhosny at eglug.org>
-Elie Roux <elie.roux at telecom-bretagne.eu>
-Will Robertson <will.robertson at latex-project.org>
-Philipp Gesang <phg at phi-gamma.net>
-Dohyun Kim <nomosnomos at gmail.com>
-Reuben Thomas <https://github.com/rrthomas>
-Joseph Wright <joseph.wright at morningstar2.co.uk>
-Manuel Pégourié-Gonnard <mpg at elzevir.fr>
-Olof-Joachim Frahm <olof at macrolet.net>
-Patrick Gundlach <gundlach at speedata.de>
-Philipp Stephani <st_philipp at yahoo.de>
-David Carlisle <d.p.carlisle at gmail.com>
-Yan Zhou @zhouyan
-
-Installation
--------------------------------------------------------------------------------
-
-Here are the recommended installation methods (preferred first).
-
-1. If you are using TeX Live 2008 or later, use 'tlmgr install luaotfload'.
- Alternatively, try your (TeX or Linux) distribution's package management
- system.
-
-2. a. Download luaotfload.tds.zip from CTAN.
- b. Unzip it at the root of one or your TDS trees.
- c. You may need to update some filename database after, see your TeX
- distribution's manual for details.
-
-3. a. Grab the sources from CTAN or github.
- b. Run 'make install DESTDIR=/path/to/texmf'.
- c. See 2c.
-
-4. Try to figure it out by looking at the Makefile and comments in the sources.
-
-Prerequisites
--------------------------------------------------------------------------------
-
-You need GNU make to use the Makefile. The executable may be called "gmake" on
-your system.
-
-Typesetting the documentation requires LuaTeX and GraphViz. The Docutils are
-needed to generate the manpage.
-
-License
--------------------------------------------------------------------------------
-
-The luaotfload bundle, as a derived work of ConTeXt, is distributed under the
-GNU GPLv2 license:
-
- <http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>
-
-This license requires the license itself to be distributed with the work. For
-its full text see the documentation in luaotfload.pdf.
-
-
- DISCLAIMER
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License
- as published by the Free Software Foundation; version 2.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- See headers of each source file for copyright details.
-
Added: trunk/Master/texmf-dist/doc/luatex/luaotfload/README.md
===================================================================
--- trunk/Master/texmf-dist/doc/luatex/luaotfload/README.md (rev 0)
+++ trunk/Master/texmf-dist/doc/luatex/luaotfload/README.md 2018-09-26 20:50:34 UTC (rev 48771)
@@ -0,0 +1,103 @@
+# The Luaotfload Package
+
+VERSION: 2.9
+
+DATE: 2018-09-24
+
+
+## Description
+
+Luaotfload is an adaptation of the ConTeXt font loading system for the Plain
+and LaTeX formats. It allows OpenType fonts to be loaded with font features
+accessible using an extended font request syntax while providing compatibility
+with XeTeX. By indexing metadata in a database it facilitates loading fonts by
+their proper names instead of file names.
+
+Luaotfload may be loaded in Plain LuaTeX with "\input luaotfload.sty" and in
+LuaLaTeX with "\usepackage{luaotfload}". LuaLaTeX users may be interested in
+the fontspec package which provides a high-level interface to the functionality
+provided by this package.
+
+Please see the documentation luaotfload.pdf for more information.
+
+## Maintenance
+
+This package is currently maintained at
+<https://github.com/u-fischer/luaotfload>.
+
+Issues can be reported at the issue tracker or at the old issue tracker on
+<http://github.com/lualatex/luaotfload>.
+
+The development for LuaLaTeX is discussed on the lualatex-dev mailing list. See
+<http://www.tug.org/mailman/listinfo/lualatex-dev> for details.
+
+
+## Responsible Persons
+
+The following people have contributed to this package.
+
+- Khaled Hosny <khaledhosny at eglug.org>
+- Elie Roux <elie.roux at telecom-bretagne.eu>
+- Will Robertson <will.robertson at latex-project.org>
+- Philipp Gesang <phg at phi-gamma.net>
+- Dohyun Kim <nomosnomos at gmail.com>
+- Reuben Thomas <https://github.com/rrthomas>
+- Joseph Wright <joseph.wright at morningstar2.co.uk>
+- Manuel Pégourié-Gonnard <mpg at elzevir.fr>
+- Olof-Joachim Frahm <olof at macrolet.net>
+- Patrick Gundlach <gundlach at speedata.de>
+- Philipp Stephani <st_philipp at yahoo.de>
+- David Carlisle <d.p.carlisle at gmail.com>
+- Yan Zhou @zhouyan
+- Ulrike Fischer <fischer at troubleshooting-tex.de>
+- Marcel Krüger <https://github.com/zauguin>
+
+## Installation
+
+1. Install the current version with the package management tools of your TeX system.
+ If you want to install manually: there is a tds-zip file which can be unpacked in a texmf tree.
+
+2. If you want to try the development version download the texmf folder in the development branch.
+ at <https://github.com/u-fischer/luaotfload>
+
+3. Manual installation:
+ * luaotfload-tool.lua belongs in scripts/luatex/luaotfload
+ * fontloader-reference-load-order.tex and fontloader-reference-load-order.lua are source files and can got in source or doc
+ * the other lua-files and the sty belong in tex/luatex/luaotfload
+ * luaotfload.conf.5 and luaotfload-tool.1 belong in doc/man
+ * the rest in doc/luatex/luaotfload
+
+## Documentation
+
+* The main documentation is luaotfload-latex.pdf.
+* luaotfload.conf.5 and luaotfload-tool.1 are man-files, their sources are the rst-files.
+* README.md, NEWS and COPYING contain what their name says.
+* The rest are input files.
+
+
+
+
+## License
+
+The luaotfload bundle, as a derived work of ConTeXt, is distributed under the
+GNU GPLv2 license:
+
+ <http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>
+
+This license requires the license itself to be distributed with the work. For
+its full text see the documentation in luaotfload.pdf.
+
+
+## DISCLAIMER
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; version 2.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ See headers of each source file for copyright details.
+
Property changes on: trunk/Master/texmf-dist/doc/luatex/luaotfload/README.md
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Modified: trunk/Master/texmf-dist/doc/luatex/luaotfload/filegraph.pdf
===================================================================
(Binary files differ)
Added: trunk/Master/texmf-dist/doc/luatex/luaotfload/filegraph.tex
===================================================================
--- trunk/Master/texmf-dist/doc/luatex/luaotfload/filegraph.tex (rev 0)
+++ trunk/Master/texmf-dist/doc/luatex/luaotfload/filegraph.tex 2018-09-26 20:50:34 UTC (rev 48771)
@@ -0,0 +1,265 @@
+% !Mode:: "TeX:EN:UTF-8:Main"
+%created with by @marmot 14.09.2018
+%
+\documentclass[border=3.14mm,tikz]{standalone}
+\usetikzlibrary{fit,matrix,positioning,arrows.meta,decorations.text,shapes.callouts}
+\pgfdeclarelayer{background}
+\pgfdeclarelayer{container}
+\pgfdeclarelayer{foreground}
+\pgfsetlayers{container,background,main,foreground}
+\usepackage {fontspec}
+\usepackage {unicode-math}
+\usepackage{tikzmarmots,tikzducks}
+
+\setmainfont[
+% Numbers = OldStyle, %% buggy with font cache
+ Ligatures = TeX,
+ BoldFont = {Linux Libertine O Bold},
+ ItalicFont = {Linux Libertine O Italic},
+ SlantedFont = {Linux Libertine O Italic},
+]{Linux Libertine O}
+\setmonofont[Ligatures=TeX,Scale=MatchLowercase]{InconsolataN-Regular.otf}
+%setsansfont[Ligatures=TeX]{Linux Biolinum O}
+\setsansfont[Ligatures=TeX,Scale=MatchLowercase]{Iwona Medium}
+
+\usepackage{luacode}
+\begin{luacode}
+require("luaotfload-filelist.lua")
+
+function printctxfontlist ()
+ t= luaotfload.filelist.selectctxfontentries (luaotfload.filelist.data)
+ for i,v in ipairs (t) do
+ tex.sprint("\\mbox{"..v.name..v.ext.."} ")
+ end
+end
+
+function printctxlibslist ()
+ t= luaotfload.filelist.selectctxlibsentries (luaotfload.filelist.data)
+ local rowcnt = 0
+ local sep = "&"
+ for i,v in ipairs (t) do
+ rowcnt = rowcnt + 1
+ if rowcnt % 4 == 0 then sep = "\\\\" else sep = "&" end
+ tex.sprint("\\mbox{"..v.name..v.ext.."}".. sep)
+ end
+end
+
+function printctxgenericlist ()
+ t= luaotfload.filelist.selectctxgeneusedentries (luaotfload.filelist.data)
+ local rowcnt = 0
+ local sep = "&"
+ for i,v in ipairs (t) do
+ rowcnt = rowcnt + 1
+ if rowcnt % 2 == 0 then sep = "\\\\" else sep = "&" end
+ tex.sprint("\\mbox{"..v.ctxpref..v.name..v.ext.."}".. sep)
+ end
+end
+
+
+function printlibrarylist ()
+ t = luaotfload.filelist.selectlollibentries (luaotfload.filelist.data)
+ local rowcnt = 0
+ local sep = "&"
+ for i,v in ipairs (t) do
+ rowcnt = rowcnt + 1
+ if rowcnt % 2 == 0 then sep = "\\\\" else sep = "&" end
+ tex.sprint("\\mbox{"..v.gitpref..v.name..v.ext.."}".. sep)
+ end
+end
+
+function printscriptlist ()
+ t = luaotfload.filelist.selectlolscrentries (luaotfload.filelist.data)
+ for i,v in ipairs ( t ) do
+ if v.kind == 8 then
+ tex.sprint( v.name .."\\\\")
+ end
+ end
+end
+
+\end{luacode}
+\begin{document}
+\begin{tikzpicture}[rounded corners,basic/.style={inner
+sep=9pt,font=\ttfamily,align=center}]
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% text nodes
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% m1
+\matrix [matrix of nodes,font=\ttfamily,nodes={anchor=base west},
+label={[name=mL1,font=\itshape]above:Luaotfload Libraries}] (m1)
+{%
+%<<<<<<<<<<<<<<<<
+\directlua{printlibrarylist()}
+%>>>>>>>>>>>>>>>>
+};
+% m2
+\node[right=4.2cm of m1,fill=gray!20,draw=gray!30,dashed,basic] (m2) {luaotfload-blacklist.cnf};
+% m3
+\matrix [below=2cm of m1,matrix of nodes,font=\ttfamily,nodes={anchor=base west},
+label={[name=mL3,font=\itshape,anchor=south]above:Lualibs -- Lua Libraries from Context}] (m3)
+{%
+%<<<<<<<<<<<<<<<<
+\directlua{printctxlibslist ()}
+%>>>>>>>>>>>>>>>>
+};
+% m4
+\node[left=2cm of m3,fill=gray!20,draw=gray!30,thick,basic,inner sep=6mm] (m4) {luaotfload-main.lua};
+% m5
+\node[fill=gray!20,draw=gray!30,dashed,basic,inner sep=6mm,anchor=south west] at (m3.south -|
+m2.west)(m5){%
+%<<<<<<<<<<<<<<<<
+luaotfload-names.lua.gz\\
+luaotfload-names.luc
+%>>>>>>>>>>>>>>>>
+};
+% m6
+\node[below=3cm of m3,fill=gray!20,draw=gray!30,thick,basic,inner sep=6mm] (m6){luaotfload-init.lua};
+% m7
+\node[above right=0.5cm and 2.5cm of m6,fill=gray!20,draw=gray!30,thick,basic,inner sep=6mm] (m7){luaotfload-log.lua};
+% m8
+\matrix [below left=1cm and 2cm of m6,matrix of nodes,font=\ttfamily,
+row sep=5mm,
+nodes={inner sep=3mm,fill=orange!10,rounded corners},
+label={[name=mL8,font=\it]above:Fontloader}] (m8)
+{%
+%<<<<<<<<<<<<<<<<
+fontloader-basics-gen.lua\\
+fontloader-YY-MM-DD.lua\\
+%<<<<<<<<<<<<<<<<
+};
+% m9
+\node [below right=1cm and 2cm of m6,font=\ttfamily,
+inner sep=3mm,text width=7.3cm,align=left,
+label={[name=mL9,font=\itshape]Font and Node Libraries from Context}] (m9)
+{\spaceskip=1.5em \raggedright
+%%<<<<<<<<<<<<<<<<
+\directlua{printctxfontlist()}
+%>>>>>>>>>>>>>>>>
+};
+% m10
+\node [below=1cm of m9,font=\ttfamily,
+inner sep=3mm,text width=7.3cm,align=center,
+label={[name=mL10,font=\itshape]Font Loader (LuaTeX-Fonts)}] (m10)
+{\tabcolsep=0.5em
+ \begin{tabular}{@{}ll@{}}
+%<<<<<<<<<<<<<<<<
+\directlua{printctxgenericlist ()}
+%>>>>>>>>>>>>>>>>
+ \end{tabular}
+};
+% m11
+\node [above=1cm of m9] (m11) {Merged libraries};
+% m12
+\matrix [below=4cm of m6,xshift=-1cm,matrix of nodes,font=\ttfamily,
+row sep=5mm,
+nodes={inner sep=3mm,fill=gray!10,rounded corners,text width=3cm,align=center},
+label={[name=mL12,font=\sffamily]above:Standalone scripts}] (m12)
+{%
+%<<<<<<<<<<<<<<<<
+\directlua{printscriptlist ()}
+%>>>>>>>>>>>>>>>>
+};
+% m13
+\node[below=1.2cm of m10,fill=gray!20,draw=gray!30,thick,basic,inner sep=6mm] (m13)
+{%
+%<<<<<<<<<<<<<<<<
+luaotfload-glyphlist.lua
+%>>>>>>>>>>>>>>>>
+};
+% m14
+\node[below=0.8cm of m13,fill=gray!20,draw=gray!30,thick,basic,inner sep=6mm] (m14)
+{%
+%<<<<<<<<<<<<<<<<
+luaotfload-characters.lua
+%>>>>>>>>>>>>>>>>
+};
+% m15
+\node[below=3cm of m8,fill=gray!20,draw=gray!30,thick,basic,inner sep=6mm]
+(m15) {%
+%<<<<<<<<<<<<<<<<
+luaotfload-tool.lua
+%>>>>>>>>>>>>>>>>
+};
+% m16
+\node[below=1cm of m15,fill=gray!20,draw=gray!30,thick,basic,inner sep=6mm]
+(m16) {%
+%<<<<<<<<<<<<<<<<
+luaotfload-diagnostics.lua
+%>>>>>>>>>>>>>>>>
+};
+% m17
+\node[below=2cm of m16,xshift=3cm,fill=gray!20,draw=gray!30,dashed,basic,inner sep=6pt]
+(m17) {%
+%<<<<<<<<<<<<<<<<
+luaotfload-status.lua
+%>>>>>>>>>>>>>>>>
+};
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% envelopes
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\begin{pgfonlayer}{background}
+%M1
+\node[fill=gray!10,fit=(m1)(mL1),rounded corners=0](mF1){};
+%M3
+\node[fill=blue!10,fit=(m3)(mL3),rounded corners=0](mF3){};
+%M9
+\node[fill=purple!10,fit=(m9)(mL9)](mF9){};
+%M10
+\node[fill=purple!10,fit=(m10)(mL10)](mF10){};
+\end{pgfonlayer}
+\begin{pgfonlayer}{container}
+%M1
+\node[fill=gray!20,fit=(mF1)](M1){};
+%M3
+\node[fill=blue!20,fit=(mF3)](M3){};
+%M8
+\node[fill=orange!20,fit=(m8)(mL8)](mF8){};
+%M11
+\node[fill=purple!20,fit=(m11)(mF9)(mF10)](M11){};
+%M11
+\node[top color=gray!40,bottom color=red!60!black,fit=(mL12)(m12)](M12){};
+\end{pgfonlayer}
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% arrows
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\begin{scope}[font=\sffamily,>={Triangle[open]},annotate/.style={postaction={decorate,decoration={text along path,text
+align=center,raise=2pt,text={|\sffamily| #1}}}}]
+\draw[->,annotate=luaotfload-database.lua] (M1) -- (m2);
+\draw[->,annotate=main()] (m4) -- (M1);
+\draw[->] (m4) -- (M3);
+\draw[->,annotate=luaotfload-database.lua] (M1.-15) to[out=0,in=90] (m5);
+\draw[->,annotate=main()] (m4) to[out=-70,in=120] (m6);
+\draw[->,annotate=init{{\_}}early()] (m6) to[out=45,in=190] (m7);
+\draw[<-,annotate=init{{\_}}early()] (m8-1-1) to[in=-150,out=0] (m6);
+\draw[<-,annotate=init{{\_}}main()] (m8-2-1) to[in=-100,out=4] (m6);
+\draw[->,annotate=unmerged] (m6) to[out=0,in=180] (mF9.150);
+\draw[->,dashed,annotate=merged] (m8-2-1) to[out=0,in=180] (mF9.170);
+\draw[->,dashed,annotate=pulls] (m12-1-1) to[out=0,in=180] (mF9);
+\draw[->,dashed,annotate=pulls] (m12-1-1) to[out=0,in=180] (mF10);
+\draw[<-,dashed,annotate=merges] (m8-2-1) to[out=-45,in=180] (m12-1-1);
+\draw[->] (mF10) to node[midway,left]{luatex-fonts-enc.lua} (m13);
+\draw[->] (mF10.-30) to[out=-60,in=50]node[pos=0.3,right]{ luaotfload-auxiliary.lua} (m14.15);
+\draw[->,dashed,annotate=generates from glyphlist.txt] (m12-2-1) to[out=0,in=180] (m13);
+\draw[->,dashed,annotate=generates from Context's char-def.lua] (m12-3-1) to[out=0,in=180] (m14);
+\draw[->,dashed,annotate={{-}{-}update}] (m15) to[out=130,in=-80] ++ (-3.5,4)
+to[out=100,in=-110] ++ (0,2)
+to[out=70,in=-165] (m5);
+\draw[->,annotate=version information] (m15) to[out=-170,in=90] ++(-3.5,-3)
+to[out=-90,in=180] (m17);
+\draw[->] (m15) -- node[midway,right]{-\,-diagnose} (m16);
+\draw[->,annotate=hash files] (m16) -- (m17);
+\draw[<-,dashed,annotate=generates from distribution files] (m17)
+to[out=0,in=-135] ++(5,1) to[out=45,in=0] (m12-4-1);
+\end{scope}
+
+\begin{scope}[shift={([xshift=2cm,yshift=-3cm]current bounding box.north west)}]
+\marmot;
+\duck[invisible];
+\node[anchor=south,draw,text width=3cm,shape=rectangle callout,font=\sffamily\scriptsize,align=center]
+at ([yshift=1cm,xshift=-0.5cm]bill)
+{It looks complicated\\ because it is complicated!};
+%
+\end{scope}
+
+\end{tikzpicture}
+\end{document}
\ No newline at end of file
Property changes on: trunk/Master/texmf-dist/doc/luatex/luaotfload/filegraph.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/luatex/luaotfload/luaotfload-conf.pdf
===================================================================
(Binary files differ)
Index: trunk/Master/texmf-dist/doc/luatex/luaotfload/luaotfload-conf.pdf
===================================================================
--- trunk/Master/texmf-dist/doc/luatex/luaotfload/luaotfload-conf.pdf 2018-09-26 20:49:48 UTC (rev 48770)
+++ trunk/Master/texmf-dist/doc/luatex/luaotfload/luaotfload-conf.pdf 2018-09-26 20:50:34 UTC (rev 48771)
Property changes on: trunk/Master/texmf-dist/doc/luatex/luaotfload/luaotfload-conf.pdf
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/pdf
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/luatex/luaotfload/luaotfload-conf.tex
===================================================================
--- trunk/Master/texmf-dist/doc/luatex/luaotfload/luaotfload-conf.tex (rev 0)
+++ trunk/Master/texmf-dist/doc/luatex/luaotfload/luaotfload-conf.tex 2018-09-26 20:50:34 UTC (rev 48771)
@@ -0,0 +1,707 @@
+\documentclass[a4paper]{article}
+% generated by Docutils <http://docutils.sourceforge.net/>
+% rubber: set program xelatex
+\usepackage{fontspec}
+% \defaultfontfeatures{Scale=MatchLowercase}
+% straight double quotes (defined T1 but missing in TU):
+\ifdefined \UnicodeEncodingName
+ \DeclareTextCommand{\textquotedbl}{\UnicodeEncodingName}{%
+ {\addfontfeatures{RawFeature=-tlig,Mapping=}\char34}}%
+\fi
+\usepackage{ifthen}
+\usepackage{alltt}
+\setcounter{secnumdepth}{0}
+\usepackage{longtable,ltcaption,array}
+\setlength{\extrarowheight}{2pt}
+\newlength{\DUtablewidth} % internal use in tables
+\usepackage{tabularx}
+
+%%% Custom LaTeX preamble
+% Linux Libertine (free, wide coverage, not only for Linux)
+\setmainfont{Linux Libertine O}
+\setsansfont{Linux Biolinum O}
+\setmonofont[HyphenChar=None,Scale=MatchLowercase]{DejaVu Sans Mono}
+
+%%% User specified packages and stylesheets
+
+%%% Fallback definitions for Docutils-specific commands
+
+% providelength (provide a length variable and set default, if it is new)
+\providecommand*{\DUprovidelength}[2]{
+ \ifthenelse{\isundefined{#1}}{\newlength{#1}\setlength{#1}{#2}}{}
+}
+
+% docinfo (width of docinfo table)
+\DUprovidelength{\DUdocinfowidth}{0.9\linewidth}
+
+% subtitle (in document title)
+\providecommand*{\DUdocumentsubtitle}[1]{{\large #1}}
+% hyperlinks:
+\ifthenelse{\isundefined{\hypersetup}}{
+ \usepackage[colorlinks=true,linkcolor=blue,urlcolor=blue]{hyperref}
+ \usepackage{bookmark}
+ \urlstyle{same} % normal text font (alternatives: tt, rm, sf)
+}{}
+\hypersetup{
+ pdftitle={luaotfload.conf},
+}
+
+\title{luaotfload.conf%
+ \label{luaotfload-conf}%
+ \\ % subtitle%
+ \DUdocumentsubtitle{Luaotfload configuration file}%
+ \label{luaotfload-configuration-file}}
+\author{}
+\date{}
+
+%%% Body
+\begin{document}
+\maketitle
+
+% Docinfo
+\begin{center}
+\begin{tabularx}{\DUdocinfowidth}{lX}
+\textbf{Date}: &
+ 2018-09-21 \\
+\textbf{Copyright}: &
+ GPL v2.0 \\
+\textbf{Version}: &
+ 2.9 \\
+\textbf{Manual section}: &
+5
+\\
+\textbf{Manual group}: &
+text processing
+\\
+\end{tabularx}
+\end{center}
+
+
+\section{SYNOPSIS%
+ \label{synopsis}%
+}
+
+\begin{itemize}
+\item \textbf{./luaotfload\{.conf,rc\}}
+
+\item \textbf{XDG\_CONFIG\_HOME/luaotfload/luaotfload\{.conf,rc\}}
+
+\item \textbf{\textasciitilde{}/.luaotfloadrc}
+\end{itemize}
+
+
+\section{DESCRIPTION%
+ \label{description}%
+}
+
+The file \texttt{luaotfload.conf} contains configuration options for
+\emph{Luaotfload}, a font loading and font management component for LuaTeX.
+
+
+\section{EXAMPLE%
+ \label{example}%
+}
+
+A small Luaotfload configuration file with few customizations could
+look as follows:
+
+\begin{quote}
+\begin{alltt}
+[db]
+ formats = afm,ttf
+ compress = false
+
+[misc]
+ termwidth = 60
+
+[run]
+ log-level = 6
+\end{alltt}
+\end{quote}
+
+This will make Luaotfload ignore all font files except for PostScript
+binary fonts with a matching AFM file, and Truetype fonts. Also, an
+uncompressed index file will be dumped which is going to be much larger
+than the default gzip’ed index. The terminal width
+is truncated to 60 characters which influences the verbose output
+during indexing. Finally, the verbosity is increased greatly: each font
+file being processed will be printed to the stdout on a separate line,
+along with lots of other information.
+
+To observe the difference in behavior, save above snippet to
+\texttt{./luaotfload.conf} and update the font index:
+
+\begin{quote}
+\begin{alltt}
+luaotfload-tool --update --force
+\end{alltt}
+\end{quote}
+
+The current configuration can be written to disk using
+\textbf{luaotfload-tool}:
+
+\begin{quote}
+\begin{alltt}
+luaotfload-tool --dumpconf > luaotfload.conf
+\end{alltt}
+\end{quote}
+
+The result can itself be used as a configuration file.
+
+
+\section{SYNTAX%
+ \label{syntax}%
+}
+
+The configuration file syntax follows the common INI format. For a more
+detailed description please refer to the section “CONFIGURATION FILE”
+of \textbf{git-config}(1). A brief list of rules is given below:
+
+\begin{quote}
+\begin{itemize}
+\item Blank lines and lines starting with a semicolon (\texttt{;}) are ignored.
+
+\item A configuration file is partitioned into sections that are declared
+by specifying the section title in brackets on a separate line:
+
+\begin{quote}
+\begin{alltt}
+[some-section]
+... section content ...
+\end{alltt}
+\end{quote}
+
+\item Sections consist of one or more variable assignments of the form
+\texttt{variable-name = value} E. g.:
+
+\begin{quote}
+\begin{alltt}
+[foo]
+ bar = baz
+ quux = xyzzy
+ ...
+\end{alltt}
+\end{quote}
+
+\item Section and variable names may contain only uppercase and lowercase
+letters as well as dashes (\texttt{-}).
+\end{itemize}
+\end{quote}
+
+
+\section{VARIABLES%
+ \label{variables}%
+}
+
+Variables in belong into a configuration section and their values must
+be of a certain type. Some of them have further constraints. For
+example, the “color callback” must be a string of one of the values
+\texttt{post\_linebreak\_filter}, \texttt{pre\_linebreak\_filter}, or
+\texttt{pre\_output\_filter}, defined in the section \emph{run} of the
+configuration file.
+
+Currently, the configuration is organized into four sections:
+
+\begin{description}
+\item[{db}] \leavevmode
+Options relating to the font index.
+
+\item[{misc}] \leavevmode
+Options without a clearly defined category.
+
+\item[{paths}] \leavevmode
+Path and file name settings.
+
+\item[{run}] \leavevmode
+Options controlling runtime behavior of Luaotfload.
+
+\end{description}
+
+The list of valid variables, the sections they are part of and their
+type is given below. Types represent Lua types that the values must be
+convertible to; they are abbreviated as follows: \texttt{s} for the \emph{string}
+type, \texttt{n} for \emph{number}, \texttt{b} for \emph{boolean}. A value of \texttt{nil} means
+the variable is unset.
+
+
+\subsection{Section \texttt{db}%
+ \label{section-db}%
+}
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{|p{0.249\DUtablewidth}|p{0.110\DUtablewidth}|p{0.331\DUtablewidth}|}
+\hline
+
+variable
+ &
+type
+ &
+default
+ \\
+\hline
+
+compress
+ &
+b
+ &
+\texttt{true}
+ \\
+\hline
+
+designsize-dimen
+ &
+b
+ &
+\texttt{bp}
+ \\
+\hline
+
+formats
+ &
+s
+ &
+\texttt{\textquotedbl{}otf,ttf,ttc\textquotedbl{}}
+ \\
+\hline
+
+max-fonts
+ &
+n
+ &
+\texttt{2\textasciicircum{}51}
+ \\
+\hline
+
+scan-local
+ &
+b
+ &
+\texttt{false}
+ \\
+\hline
+
+skip-read
+ &
+b
+ &
+\texttt{false}
+ \\
+\hline
+
+strip
+ &
+b
+ &
+\texttt{true}
+ \\
+\hline
+
+update-live
+ &
+b
+ &
+\texttt{true}
+ \\
+\hline
+\end{longtable*}
+
+The flag \texttt{compress} determines whether the font index (usually
+\texttt{luaotfload-names.lua{[}.gz{]}} will be stored in compressed forms.
+If unset it is equivalent of passing \texttt{--no-compress} to
+\textbf{luaotfload-tool}. Since the file is only created for convenience
+and has no effect on the runtime behavior of Luaotfload, the flag
+should remain set. Most editors come with zlib support anyways.
+
+The setting \texttt{designsize-dimen} applies when looking up fonts from
+families with design sizes. In Opentype, these are specified as
+“decipoints” where one decipoint equals ten DTP style “big points”.
+When indexing fonts these values are converted to \texttt{sp}. In order to
+treat the values as though they were specified in TeX points or Didot
+points, set \texttt{designsize-dimen} to \texttt{pt} or \texttt{dd}.
+
+The list of \texttt{formats} must be a comma separated sequence of strings
+containing one or more of these elements:
+
+\begin{itemize}
+\item \texttt{otf} (OpenType format),
+
+\item \texttt{ttf} and \texttt{ttc} (TrueType format),
+
+\item \texttt{afm} (Adobe Font Metrics),
+\end{itemize}
+
+It corresponds loosely to the \texttt{--formats} option to
+\textbf{luaotfload-tool}. Invalid or duplicate members are ignored; if the
+list does not contain any useful identifiers, the default list
+\texttt{\textquotedbl{}otf,ttf,ttc\textquotedbl{}} will be used.
+
+The variable \texttt{max-fonts} determines after processing how many font
+files the font scanner will terminate the search. This is useful for
+debugging issues with the font index and has the same effect as the
+option \texttt{--max-fonts} to \textbf{luaotfload-tools}.
+
+The \texttt{scan-local} flag, if set, will incorporate the current working
+directory as a font search location. NB: This will potentially slow
+down document processing because a font index with local fonts will not
+be saved to disk, so these fonts will have to be re-indexed whenever
+the document is built.
+
+The \texttt{skip-read} flag is only useful for debugging: It makes
+Luaotfload skip reading fonts. The font information for rebuilding the
+index is taken from the presently existing one.
+
+Unsetting the \texttt{strip} flag prevents Luaotfload from removing data
+from the index that is only useful when processing font files. NB: this
+can increase the size of the index files significantly and has no
+effect on the runtime behavior.
+
+If \texttt{update-live} is set, Luaotfload will reload the database if it
+cannot find a requested font. Those who prefer to update manually using
+\textbf{luaotfload-tool} should unset this flag. This option does not affect
+rebuilds due to version mismatch.
+
+
+\subsection{Section \texttt{default-features}%
+ \label{section-default-features}%
+}
+
+By default Luaotfload enables \texttt{node} mode and picks the default font
+features that are prescribed in the OpenType standard. This behavior
+may be overridden in the \texttt{default-features} section. Global defaults
+that will be applied for all scripts can be set via the \texttt{global}
+option, others by the script they are to be applied to. For example,
+a setting of
+
+\begin{quote}
+\begin{alltt}
+[default-features]
+ global = mode=base,color=0000FF
+ dflt = smcp,onum
+\end{alltt}
+\end{quote}
+
+would force \emph{base} mode, tint all fonts blue and activate small
+capitals and text figures globally. Features are specified as a comma
+separated list of variables or variable-value pairs. Variables without
+an explicit value are set to \texttt{true}.
+
+
+\subsection{Section \texttt{misc}%
+ \label{section-misc}%
+}
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{|p{0.191\DUtablewidth}|p{0.110\DUtablewidth}|p{0.307\DUtablewidth}|}
+\hline
+
+variable
+ &
+type
+ &
+default
+ \\
+\hline
+
+statistics
+ &
+b
+ &
+\texttt{false}
+ \\
+\hline
+
+termwidth
+ &
+n
+ &
+\texttt{nil}
+ \\
+\hline
+
+version
+ &
+s
+ &
+<Luaotfload version>
+ \\
+\hline
+\end{longtable*}
+
+With \texttt{statistics} enabled, extra statistics will be collected during
+index creation and appended to the index file. It may then be queried
+at the Lua end or inspected by reading the file itself.
+
+The value of \texttt{termwidth}, if set, overrides the value retrieved by
+querying the properties of the terminal in which Luatex runs. This is
+useful if the engine runs with \texttt{shell\_escape} disabled and the actual
+terminal dimensions cannot be retrieved.
+
+The value of \texttt{version} is derived from the version string hard-coded
+in the Luaotfload source. Override at your own risk.
+
+
+\subsection{Section \texttt{paths}%
+ \label{section-paths}%
+}
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{|p{0.226\DUtablewidth}|p{0.110\DUtablewidth}|p{0.435\DUtablewidth}|}
+\hline
+
+variable
+ &
+type
+ &
+default
+ \\
+\hline
+
+cache-dir
+ &
+s
+ &
+\texttt{\textquotedbl{}fonts\textquotedbl{}}
+ \\
+\hline
+
+names-dir
+ &
+s
+ &
+\texttt{\textquotedbl{}names\textquotedbl{}}
+ \\
+\hline
+
+index-file
+ &
+s
+ &
+\texttt{\textquotedbl{}luaotfload-names.lua\textquotedbl{}}
+ \\
+\hline
+
+lookups-file
+ &
+s
+ &
+\texttt{\textquotedbl{}luaotfload-lookup-cache.lua\textquotedbl{}}
+ \\
+\hline
+\end{longtable*}
+
+The paths \texttt{cache-dir} and \texttt{names-dir} determine the subdirectory
+inside the Luaotfload subtree of the \texttt{luatex-cache} directory where
+the font cache and the font index will be stored, respectively.
+
+Inside the index directory, the names of the index file and the font
+lookup cache will be derived from the respective values of
+\texttt{index-file} and \texttt{lookups-file}. This is the filename base for the
+bytecode compiled version as well as -- for the index -- the gzipped
+version.
+
+
+\subsection{Section \texttt{run}%
+ \label{section-run}%
+}
+
+\setlength{\DUtablewidth}{\linewidth}
+\begin{longtable*}[c]{|p{0.226\DUtablewidth}|p{0.110\DUtablewidth}|p{0.365\DUtablewidth}|}
+\hline
+
+variable
+ &
+type
+ &
+default
+ \\
+\hline
+
+anon-sequence
+ &
+s
+ &
+\texttt{\textquotedbl{}tex,path,name\textquotedbl{}}
+ \\
+\hline
+
+color-callback
+ &
+s
+ &
+\texttt{\textquotedbl{}post\_linebreak\_filter\textquotedbl{}}
+ \\
+\hline
+
+definer
+ &
+s
+ &
+\texttt{\textquotedbl{}patch\textquotedbl{}}
+ \\
+\hline
+
+log-level
+ &
+n
+ &
+\texttt{0}
+ \\
+\hline
+
+resolver
+ &
+s
+ &
+\texttt{\textquotedbl{}cached\textquotedbl{}}
+ \\
+\hline
+
+fontloader
+ &
+s
+ &
+\texttt{\textquotedbl{}default\textquotedbl{}}
+ \\
+\hline
+\end{longtable*}
+
+Unqualified font lookups are treated with the flexible “anonymous”
+mechanism. This involves a chain of lookups applied successively until
+the first one yields a match. By default, the lookup will first search
+for TFM fonts using the Kpathsea library. If this wasn’t successful, an
+attempt is made at interpreting the request as an absolute path (like
+the \texttt{{[}/path/to/font/foo.ttf{]}} syntax) or a file name
+(\texttt{file:foo.ttf}). Finally, the request is interpreted as a font name
+and retrieved from the index (\texttt{name:Foo Regular}). This behavior can
+be configured by specifying a list as the value to \texttt{anon-sequence}.
+Available items are \texttt{tex}, \texttt{path}, \texttt{name} -- representing the
+lookups described above, respectively --, and \texttt{file} for searching a
+filename but not an absolute path. Also, \texttt{my} lookups are valid
+values but they should only be used from within TeX documents, because
+there is no means of customizing a \texttt{my} lookups on the command line.
+
+The \texttt{color-callback} option determines the stage at which fonts that
+defined with a \texttt{color=xxyyzz} feature will be colorized. By default
+this happens in a \texttt{post\_linebreak\_filter} but alternatively the
+\texttt{pre\_linebreak\_filter} or \texttt{pre\_output\_filter} may be chosen, which
+is faster but might produce inconsistent output. The
+\texttt{pre\_output\_filter} used to be the default in the 1.x series of
+Luaotfload, whilst later versions up to and including 2.5 hooked into
+the \texttt{pre\_linebreak\_filter} which naturally didn’t affect any glyphs
+inserting during hyphenation. Both are kept around as options to
+restore the previous behavior if necessary.
+
+The \texttt{definer} allows for switching the \texttt{define\_font} callback.
+Apart from the default \texttt{patch} one may also choose the \texttt{generic}
+one that comes with the vanilla fontloader. Beware that this might
+break tools like Fontspec that rely on the \texttt{patch\_font} callback
+provided by Luaotfload to perform important corrections on font data.
+
+The fontloader backend can be selected by setting the value of
+\texttt{fontloader}. The most important choices are \texttt{default}, which will
+load the dedicated Luaotfload fontloader, and \texttt{reference}, the
+upstream package as shipped with Luaotfload. Other than those, a file
+name accessible via kpathsea can be specified.
+
+Alternatively, the individual files that constitute the fontloader can
+be loaded directly. While less efficient, this greatly aids debugging
+since error messages will reference the actual line numbers of the
+source files and explanatory comments are not stripped. Currently,
+three distinct loading strategies are available: \texttt{unpackaged} will
+load the batch that is part of Luaotfload. These contain the identical
+source code that the reference fontloader has been compiled from.
+Another option, \texttt{context} will attempt to load the same files by
+their names in the Context format from the search path. Consequently
+this option allows to use the version of Context that comes with the
+TeX distribution. Distros tend to prefer the stable version (“current”
+in Context jargon) of those files so certain bugs encountered in the
+more bleeding edge Luaotfload can be avoided this way. A third option
+is to use \texttt{context} with a colon to specify a directory prefix where
+the \emph{TEXMF} is located that the files should be loaded from, e. g.
+\texttt{context:\textasciitilde{}/context/tex/texmf-context}. This can be used when
+referencing another distribution like the Context minimals that is
+installed under a different path not indexed by kpathsea.
+
+The value of \texttt{log-level} sets the default verbosity of messages
+printed by Luaotfload. Only messages defined with a verbosity of less
+than or equal to the supplied value will be output on the terminal.
+At a log level of five Luaotfload can be very noisy. Also, printing too
+many messages will slow down the interpreter due to line buffering
+being disabled (see \textbf{setbuf}(3)).
+
+The \texttt{resolver} setting allows choosing the font name resolution
+function: With the default value \texttt{cached} Luaotfload saves the result
+of a successful font name request to a cache file to speed up
+subsequent lookups. The alternative, \texttt{normal} circumvents the cache
+and resolves every request individually. (Since to the restructuring of
+the font name index in Luaotfload 2.4 the performance difference
+between the cached and uncached lookups should be marginal.)
+
+
+\section{FILES%
+ \label{files}%
+}
+
+Luaotfload only processes the first configuration file it encounters at
+one of the search locations. The file name may be either
+\texttt{luaotfload.conf} or \texttt{luaotfloadrc}, except for the dotfile in the
+user’s home directory which is expected at \texttt{\textasciitilde{}/.luaotfloadrc}.
+
+Configuration files are located following a series of steps. The search
+terminates as soon as a suitable file is encountered. The sequence of
+locations that Luaotfload looks at is
+
+\begin{enumerate}
+\renewcommand{\labelenumi}{\roman{enumi}.}
+\item The current working directory of the LuaTeX process.
+
+\item The subdirectory \texttt{luaotfload/} inside the XDG configuration
+tree, e. g. \texttt{/home/oenothea/config/luaotfload/}.
+
+\item The dotfile.
+
+\item The \emph{TEXMF} (using kpathsea).
+\end{enumerate}
+
+
+\section{SEE ALSO%
+ \label{see-also}%
+}
+
+\textbf{luaotfload-tool}(1), \textbf{luatex}(1), \textbf{lua}(1)
+
+\begin{itemize}
+\item \texttt{texdoc luaotfload} to display the PDF manual for the \emph{Luaotfload}
+package
+
+\item Luaotfload development \url{https://github.com/u-fischer/luaotfload}
+
+\item LuaLaTeX mailing list \url{http://tug.org/pipermail/lualatex-dev/}
+
+\item LuaTeX \url{http://luatex.org/}
+
+\item Luaotfload on CTAN \url{http://ctan.org/pkg/luaotfload}
+\end{itemize}
+
+
+\section{REFERENCES%
+ \label{references}%
+}
+
+\begin{itemize}
+\item The XDG base specification
+\url{http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html}.
+\end{itemize}
+
+
+\section{AUTHORS%
+ \label{authors}%
+}
+
+\emph{Luaotfload} was developed by the LuaLaTeX dev team
+(\url{https://github.com/lualatex/}). It is currently maintained by Ulrike Fischer
+and Marcel Krüger at \url{https://github.com/u-fischer/luaotfload}
+
+This manual page was written by Philipp Gesang <\href{mailto:phg at phi-gamma.net}{phg at phi-gamma.net}>.
+
+\end{document}
Property changes on: trunk/Master/texmf-dist/doc/luatex/luaotfload/luaotfload-conf.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/luatex/luaotfload/luaotfload-latex.pdf
===================================================================
(Binary files differ)
Index: trunk/Master/texmf-dist/doc/luatex/luaotfload/luaotfload-latex.pdf
===================================================================
--- trunk/Master/texmf-dist/doc/luatex/luaotfload/luaotfload-latex.pdf 2018-09-26 20:49:48 UTC (rev 48770)
+++ trunk/Master/texmf-dist/doc/luatex/luaotfload/luaotfload-latex.pdf 2018-09-26 20:50:34 UTC (rev 48771)
Property changes on: trunk/Master/texmf-dist/doc/luatex/luaotfload/luaotfload-latex.pdf
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/pdf
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/luatex/luaotfload/luaotfload-latex.tex
===================================================================
--- trunk/Master/texmf-dist/doc/luatex/luaotfload/luaotfload-latex.tex (rev 0)
+++ trunk/Master/texmf-dist/doc/luatex/luaotfload/luaotfload-latex.tex 2018-09-26 20:50:34 UTC (rev 48771)
@@ -0,0 +1,520 @@
+% !Mode:: "TeX:EN:UTF-8:Main"
+\suppresslongerror1%% sigh ...
+%% Copyright (C) 2009-2018
+%%
+%% by Elie Roux <elie.roux at telecom-bretagne.eu>
+%% and Khaled Hosny <khaledhosny at eglug.org>
+%% and Philipp Gesang <phg at phi-gamma.net>
+%%
+%% This file is part of Luaotfload.
+%%
+%% Home: https://github.com/lualatex/luaotfload
+%% Support: <lualatex-dev at tug.org>.
+%%
+%% Luaotfload is under the GPL v2.0 (exactly) license.
+%%
+%% ----------------------------------------------------------------------------
+%%
+%% Luaotfload is free software; you can redistribute it and/or
+%% modify it under the terms of the GNU General Public License
+%% as published by the Free Software Foundation; version 2
+%% of the License.
+%%
+%% Luaotfload is distributed in the hope that it will be useful,
+%% but WITHOUT ANY WARRANTY; without even the implied warranty of
+%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+%% GNU General Public License for more details.
+%%
+%% You should have received a copy of the GNU General Public License
+%% along with Luaotfload; if not, see <http://www.gnu.org/licenses/>.
+%%
+%% ----------------------------------------------------------------------------
+%%
+
+\documentclass{ltxdoc}
+
+\makeatletter
+
+\usepackage {metalogo,multicol,fancyvrb,xspace}
+\usepackage [x11names] {xcolor}
+
+\def \primarycolor {DodgerBlue4} %%-> rgb 16 78 139 | #104e8b
+\def \secondarycolor {Goldenrod4} %%-> rgb 139 105 200 | #8b6914
+
+\usepackage[
+ bookmarks=true,
+ colorlinks=true,
+ linkcolor=\primarycolor,
+ urlcolor=\secondarycolor,
+ citecolor=\primarycolor,
+ pdftitle={The Luaotfload package},
+ pdfsubject={OpenType layout system for Plain TeX and LaTeX},
+ pdfauthor={Elie Roux & Khaled Hosny & Philipp Gesang & Ulrike Fischer},
+ pdfkeywords={luatex, lualatex, unicode, opentype}
+]{hyperref}
+
+\usepackage {fontspec}
+\usepackage {unicode-math}
+
+\setmainfont[
+% Numbers = OldStyle, %% buggy with font cache
+ Ligatures = TeX,
+ BoldFont = {Linux Libertine O Bold},
+ ItalicFont = {Linux Libertine O Italic},
+ SlantedFont = {Linux Libertine O Italic},
+]{Linux Libertine O}
+\setmonofont[Ligatures=TeX,Scale=MatchLowercase]{InconsolataN-Regular.otf}
+%setsansfont[Ligatures=TeX]{Linux Biolinum O}
+\setsansfont[Ligatures=TeX,Scale=MatchLowercase]{Iwona Medium}
+%setmathfont{XITS Math}
+
+\usepackage{hologo}
+
+\newcommand\TEX {\TeX\xspace}
+\newcommand\LUA {Lua\xspace}
+\newcommand\PDFTEX {pdf\TeX\xspace}
+\newcommand\LUATEX {Lua\TeX\xspace}
+\newcommand\XETEX {\XeTeX\xspace}
+\newcommand\LATEX {\LaTeX\xspace}
+\newcommand\LUALATEX {Lua\LaTeX\xspace}
+\newcommand\CONTEXT {Con\TeX t\xspace}
+\newcommand\OpenType {\identifier{Open\kern-.25ex Type}\xspace}
+
+%% \groupedcommand, with some omissions taken from syst-aux.mkiv
+\let \handlegroupnormalbefore \relax
+\let \handlegroupnormalafter \relax
+
+\protected \def \handlegroupnormal #1#2{%
+ \bgroup % 1
+ \def \handlegroupbefore {#1}%
+ \def \handlegroupafter {#2}%
+ \afterassignment \handlegroupnormalbefore
+ \let \next =
+}
+
+\def \handlegroupnormalbefore {%
+ \bgroup % 2
+ \handlegroupbefore
+ \bgroup % 3
+ \aftergroup \handlegroupnormalafter%
+}
+
+\def \handlegroupnormalafter {%
+ \handlegroupafter
+ \egroup % 3
+ \egroup % 2
+}
+
+\let \groupedcommand \handlegroupnormal %% only the two arg version
+
+\def \definehighlight [#1][#2]{%
+ \ifcsname #1\endcsname\else
+ \expandafter\def\csname #1\endcsname{%
+ \leavevmode
+ \groupedcommand {#2}\empty%
+ }
+ \fi%
+}
+
+%% old, simplistic definition: obsolete now that we have
+%% \groupedcommand
+%\def\definehighlight[#1][#2]%
+ %{\ifcsname #1\endcsname\else
+ %\expandafter\def\csname #1\endcsname%
+ %{\bgroup#2\csname #1_indeed\endcsname}
+ %\expandafter\def\csname #1_indeed\endcsname##1%
+ %{##1\egroup}%
+ %\fi}
+
+\def\restoreunderscore{\catcode`\_=12\relax}
+
+\definehighlight [fileent][\ttfamily\restoreunderscore] %% files, dirs
+\definehighlight [texmacro][\sffamily\itshape\textbackslash] %% cs
+\definehighlight [luaident][\sffamily\itshape\restoreunderscore] %% lua identifiers
+\definehighlight [identifier][\sffamily] %% names
+\definehighlight [abbrev][\rmfamily\scshape] %% acronyms
+\definehighlight [emphasis][\rmfamily\slshape] %% level 1 emph
+
+\definehighlight [Largefont][\Large] %% font size
+\definehighlight [smallcaps][\sc] %% font feature
+\definehighlight [nonproportional][\tt] %% font switch
+
+\newcommand*\email[1]{\href{mailto:#1}{#1}}
+
+\renewcommand\partname{Part}%% gets rid of the stupid “file” heading
+
+\usepackage{syntax}%% bnf for font request syntax
+
+\usepackage{titlesec}
+
+\def\movecountertomargin#1{\llap{\rmfamily\upshape#1\hskip2em}}
+\def\zeropoint{0pt}
+\titleformat \part
+ {\normalsize\rmfamily\bfseries}
+ {\movecountertomargin\thepart} \zeropoint {}
+\titleformat \section
+ {\normalsize\rmfamily\scshape}
+ {\movecountertomargin\thesection} \zeropoint {}
+\titleformat \subsection
+ {\small\rmfamily\itshape}
+ {\movecountertomargin\thesubsection} \zeropoint {}
+\titleformat \subsubsection
+ {\normalsize\rmfamily\upshape}
+ {\movecountertomargin\thesubsubsection} \zeropoint {}
+
+\usepackage{tocloft}
+\renewcommand \cftpartfont {\rmfamily\upshape}
+\renewcommand \cftsecfont {\rmfamily\upshape}
+\renewcommand \cftsubsecfont {\rmfamily\upshape}
+\setlength \cftbeforepartskip {1ex}
+\setlength \cftbeforesecskip {1ex}
+
+\VerbatimFootnotes
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% structurals
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\def \definestructural #1{%
+ \expandafter \let \csname end#1\endcsname \relax
+
+ \expandafter \def \csname begin#1\endcsname {%
+ \@ifnextchar[{\csname begin#1indeed\endcsname}
+ {\csname begin#1indeed\endcsname[]}%
+ }
+
+ \expandafter \def \csname begin#1indeed\endcsname [##1]##2{%
+ \edef \first {##1}%
+ \ifx \first \empty
+ \csname #1\endcsname [##2]{##2}%
+ \else
+ \csname #1\endcsname [\first]{##2}%
+ \fi
+ }
+}
+
+\definestructural {section}
+\definestructural {subsection}
+\definestructural {subsubsection}
+
+\def \fakesection #1{\section*{#1}}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% inline verbatim
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%% Context offers both \type{…} and \type<<…>>, but not an unbalanced
+%% one that we could map directly onto Latex’s \verb|…|.
+\usepackage{pdfpages}
+\usepackage {listings}
+\usepackage {luatexbase}
+\lstset {
+ basicstyle=\ttfamily,
+}
+
+%\let \inlinecode \lstinline
+\protected \def \inlinecode {\lstinline}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% codelistings; this sucks hard since we lack access to buffers
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\newcount \othercatcode \othercatcode 12
+\newcount \activecatcode \othercatcode 13
+
+\newcatcodetable \vrbcatcodes
+\setcatcodetable \vrbcatcodes {%
+ \catcodetable \CatcodeTableIniTeX
+ \catcode 9 \othercatcode %% \tabasciicode
+ \catcode 13 \othercatcode %% \endoflineasciicode
+ \catcode 12 \othercatcode %% \formfeedasciicode
+ \catcode 26 \othercatcode %% \endoffileasciicode
+ \catcode 32 \othercatcode %% \spaceasciicode
+}
+
+\directlua {
+ document = document or { }
+ document.vrbcatcodesidx = tonumber (\the \vrbcatcodes)
+}
+
+\newcatcodetable \literalcatcodes
+\setcatcodetable \literalcatcodes {%
+ \catcodetable \CatcodeTableString
+ \catcode 32 \activecatcode %% \spaceasciicode
+}
+
+\def \listingsurroundskip {\vskip \baselineskip}
+
+\def \beginlisting {%
+ \noindent
+ \begingroup
+ \catcodetable \vrbcatcodes
+ \beginlistingindeed%
+}
+
+\directlua {
+ local texsprint = tex.sprint
+ local stringis_empty = string.is_empty
+ local stringsub = string.sub
+ local stringgsub = string.gsub
+ %local backslash = unicode.utf8.char (0x200c)
+ local backslash = unicode.utf8.char (0x5c)
+ local escaped = [[\string\string\string\]]
+ document.printlines = function (buffer)
+ local lines = string.explode (buffer, "\noexpand\n")
+ print ""
+ for i, line in next, lines do
+ local line = stringgsub (line, backslash, escaped)
+ if stringis_empty (line) then
+ print (i, "listing: <empty line />")
+ texsprint [[\string\listingpar]]
+ else
+ local line = [[\string\beginlistingline]]
+ .. line
+ .. [[\string\endlistingline]]
+ .. [[\string\listingpar]]
+ print (i, "listing: «" .. line .. "»")
+ texsprint (document.vrbcatcodesidx, line)
+ end
+ end
+ end
+}
+
+\def \listingpar {\endgraf}
+
+\let \endlistingline \relax
+\let \endlisting \relax
+
+\protected \def \beginlistingline{%
+ \leavevmode
+ \begingroup
+ \beginlistinglineindeed%
+}
+
+\def \beginlistinglineindeed #1\endlistingline{%
+ \endgroup
+ \hbox{%
+ \addfontfeature {RawFeature=-tlig;-liga}%% So one can’t just turn them all off at once using the ``Ligatures`` key?
+ \obeyspaces
+ #1}%
+}
+
+\def \beginlistingindeed#1\endlisting{%
+ \endgroup
+ \begingroup
+ \endgraf
+ \listingsurroundskip
+ \ttfamily
+ \small
+ \parindent = 0em
+ \leftskip = 2em
+ \hangindent = 2em
+ \directlua{document.printlines ([==[\detokenize {#1}]==])}%
+ \listingsurroundskip
+ \endgroup
+}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% enumerations and lists
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\def \definelist [#1]#2{% name, itemcode
+ \expandafter \def \csname begin#1\endcsname {%
+ \begin {itemize}
+ \let \normalitem = \item
+ \def \altitem ####1{%
+ \def \first {####1}%
+ #2
+ }
+ \let \beginnormalitem \item
+ \let \endnormalitem \relax
+ \let \beginaltitem \altitem
+ \let \endaltitem \relax
+ }
+
+ \expandafter \def \csname end#1\endcsname {%
+ \end {itemize}
+ }
+}
+
+\definelist [descriptions]{\normalitem {\textbf \first}\hfill\break}
+\definelist [definitions]{\normalitem {\fileent {\first}}}
+\definelist [filelist]{\normalitem {\fileent {\first}}\space--\hskip 1em}
+\definelist [functionlist]{\normalitem {\luaident {\first}}\hfill\break}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% columns
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\def \begindoublecolumns {\begin {multicols} {2}}
+\def \enddoublecolumns {\end {multicols}}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% alignment
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\def \begincentered {\begin {center}}
+\def \endcentered {\end {center}}
+
+\def \beginnarrower {\begin {quote}}
+\def \endnarrower {\end {quote}}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% special elements
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\let \beginfrontmatter \relax
+\let \endfrontmatter \relax
+
+\def \beginabstractcontent {\begin {abstract}}
+\def \endabstractcontent {\end {abstract}}
+
+\let \setdocumenttitle \title
+\let \setdocumentdate \date
+\let \setdocumentauthor \author
+\let \typesetdocumenttitle \maketitle
+
+\AtBeginDocument {%% seriously?
+ \let \typesetcontent \tableofcontents%
+}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% floats
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%% syntax definition
+\def \beginsyntaxfloat #1#2{%% #1:label #2:caption
+ \begin {figure} [b]
+ \edef \syntaxlabel {#1}%
+ \def \syntaxcaption {#2}%
+ \setlength\grammarparsep{0pt plus 2pt minus 2pt}%
+ \setlength\grammarindent{5cm}%
+ \begingroup
+ \small
+ \begin {grammar}
+}
+
+\def \endsyntaxfloat {%
+ \end {grammar}
+ \endgroup
+ \caption \syntaxcaption
+ \label \syntaxlabel
+ \end {figure}
+}
+
+%% figures, e.g. the file graph
+\def \figurefloat #1#2#3{%% #1:label #2:caption #3:file
+ \begin {figure} [b]
+ \caption {#2}%
+ \includegraphics[width=\textwidth]{#3}%
+ \label {#1}
+ \end {figure}
+}
+
+%% tables
+\def \tablefloat #1#2{%% #1:label #2:caption
+ \begin {table} [t]
+ \hrule
+ \caption {#2}%
+ \label {#1}
+ \hrule
+ \end {table}
+}
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% hyperlinks
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\protected \def \hyperlink{%
+ \@ifnextchar[{\hyperlinkindeed}%
+ {\hyperlinkindeed[]}%
+}
+
+\def \hyperlinkindeed [#1]#2{%
+ \def \first {#1}%
+ \ifx \first \empty
+ \url {#2}%
+ \else
+ \href {#2}{#1}%
+ \fi%
+}
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% tables
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Our tables aren’t anything special so we stick with “tabular” on the
+%% Latex end.
+%%
+%% This is going to be largely incompatible with Context since format
+%% specifications work quite differently (even between different
+%% Context table variants).
+
+\def \begintabulate [#1]#2\endtabulate{%
+ \begingroup
+ \let \beginrow = \relax %% -> \NC in Context
+ \let \newcell = & %% -> \NC
+ \let \endrow = \cr %% -> \NC \NR
+ \begin {tabular}{#1}%
+ #2
+ \end {tabular}
+ \endgroup
+}
+
+\let \endtabulate \relax
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% escaped characters
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\let \charpercent \textpercent
+\let \charbackslash \textbackslash
+\let \chartilde \textasciitilde
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% main
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\makeatother
+
+\newif \ifcontextmkiv \contextmkivfalse
+
+\usepackage{luacode}
+
+% a few lua functions to grab the file lists.
+\begin{luacode}
+require("luaotfload-filelist.lua")
+
+function printctxlibslist ()
+ t= luaotfload.filelist.selectctxlibsentries (luaotfload.filelist.data)
+ for i,v in ipairs (t) do
+ tex.sprint("\\beginaltitem {"..v.name.. v.ext.."}\\endaltitem")
+ end
+end
+
+function printctxallgenericlist ()
+ t= luaotfload.filelist.selectctxgeneentries (luaotfload.filelist.data)
+ for i,v in ipairs (t) do
+ tex.sprint("\\beginaltitem {"..v.ctxpref..v.name..v.ext.."}\\endaltitem")
+ end
+end
+
+function printctxfontlist ()
+ t= luaotfload.filelist.selectctxfontentries (luaotfload.filelist.data)
+ for i,v in ipairs (t) do
+ tex.sprint("\\beginaltitem {"..v.name..v.ext.."}\\endaltitem")
+ end
+end
+\end{luacode}
+
+
+\begin {document}
+ \input {luaotfload-main.tex}
+\clearpage
+\includepdf[fitpaper,pagecommand={\label{file-graph}}]{filegraph}
+\includepdf[pages=-]{luaotfload-conf.pdf}
+\includepdf[pages=-]{luaotfload-tool.pdf}
+\end {document}
+
+
Property changes on: trunk/Master/texmf-dist/doc/luatex/luaotfload/luaotfload-latex.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/luatex/luaotfload/luaotfload-main.tex
===================================================================
--- trunk/Master/texmf-dist/doc/luatex/luaotfload/luaotfload-main.tex (rev 0)
+++ trunk/Master/texmf-dist/doc/luatex/luaotfload/luaotfload-main.tex 2018-09-26 20:50:34 UTC (rev 48771)
@@ -0,0 +1,1899 @@
+%% Copyright (C) 2009-2018
+%%
+%% by Elie Roux <elie.roux at telecom-bretagne.eu>
+%% and Khaled Hosny <khaledhosny at eglug.org>
+%% and Philipp Gesang <phg at phi-gamma.net>
+%%
+%% This file is part of Luaotfload.
+%%
+%% Home: https://github.com/lualatex/luaotfload
+%% Support: <lualatex-dev at tug.org>.
+%%
+%% Luaotfload is under the GPL v2.0 (exactly) license.
+%%
+%% ----------------------------------------------------------------------------
+%%
+%% Luaotfload is free software; you can redistribute it and/or
+%% modify it under the terms of the GNU General Public License
+%% as published by the Free Software Foundation; version 2
+%% of the License.
+%%
+%% Luaotfload is distributed in the hope that it will be useful,
+%% but WITHOUT ANY WARRANTY; without even the implied warranty of
+%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+%% GNU General Public License for more details.
+%%
+%% You should have received a copy of the GNU General Public License
+%% along with Luaotfload; if not, see <http://www.gnu.org/licenses/>.
+%%
+%% ----------------------------------------------------------------------------
+%%
+
+\beginfrontmatter
+
+ \setdocumenttitle {The \identifier{luaotfload} package}
+ \setdocumentdate {2018/09/24 v2.9}
+ \setdocumentauthor {Elie Roux · Khaled Hosny · Philipp Gesang · Ulrike Fischer\\
+ Home: \hyperlink {https://github.com/lualatex/luaotfload}\\
+ New Home: \hyperlink {https://github.com/u-fischer/luaotfload}\\
+ Support: \email {lualatex-dev at tug.org}}
+
+ \typesetdocumenttitle
+
+ \beginabstractcontent
+ This package is an adaptation of the \CONTEXT font loading system.
+ It allows for loading \OpenType fonts with an extended syntax and adds
+ support for a variety of font features.
+
+ After discussion of the font loading API, this manual gives an
+ overview of the core components of \identifier{Luaotfload}: The
+ packaged font loader code, the names database, configuration, and
+ helper functions on the \LUA\ end.
+ \endabstractcontent
+
+\endfrontmatter
+
+\typesetcontent
+
+\beginsection {New in version 2.9 (by Ulrike Fischer)}
+
+On the one side there is not very much new in this version: The native components of \identifier{Luaotfload} are nearly unchanged. A few bugs have been corrected, the various files lists which loads the components of the font loader have been cleaned up.
+
+On the other side there is a lot new:
+
+\begindescriptions
+
+ \beginaltitem {Fontloader} The fontloader files imported from \CONTEXT\ have been updated to the current version.
+ This was necessary to make \identifier{Luaotfload} compatible with the comimg \LUATEX 1.08. Compared to the previous version from february 2017 quite a number of things have changed. Most importantly the handling of arabic fonts has greatly improved. But this also means that changes in the output are possible.
+ \endaltitem
+
+ \beginaltitem {Lualibs} The update of the fontloader files also required an update of the \identifier{Lualibs} package. This \identifier{Luaotfload} versions needs version 2.6 of \identifier{Lualibs}.
+ \endaltitem
+
+ \beginaltitem {Maintenance} As the current maintainer wasn't available and it was urgent to get a \identifier{Luaotfload} compatible with \LUATEX 1.08 maintenance has been transfered to Ulrike Fischer and Marcel Krüger. The package is currently maintained and developed at \hyperlink{https://github.com/u-fischer/luaotfload.git}. Issues should be reported there.
+ \endaltitem
+
+ \beginaltitem {Documentation}
+ The core of documentation is nearly unchanged. I added this introduction. I recreated with the help of @marmot the graphic. I updated the file lists. I imported as appendix pdf versions of the two man files which are part of the \identifier{Luaotfload} documentation.
+ \endaltitem
+
+\enddescriptions
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\beginsection {Introduction}
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+Font management and installation has always been painful with \TEX. A
+lot of files are needed for one font (\abbrev{tfm}, \abbrev{pfb},
+\abbrev{map}, \abbrev{fd}, \abbrev{vf}), and due to the 8-Bit encoding
+each font is limited to 256 characters.
+
+But the font world has evolved since the original \TEX, and new
+typographic systems have appeared, most notably the so called
+\emphasis{smart font} technologies like \OpenType fonts (\abbrev{otf}).
+
+These fonts can contain many more characters than \TEX fonts, as well
+as additional functionality like ligatures, old-style numbers, small
+capitals, etc., and support more complex writing systems like Arabic
+and Indic\footnote{%
+ Unfortunately, \identifier{luaotfload} doesn‘t support many Indic
+ scripts right now.
+ Assistance in implementing the prerequisites is greatly
+ appreciated.
+}
+scripts.
+
+\OpenType fonts are widely deployed and available for all modern
+operating systems.
+
+As of 2013 they have become the de facto standard for advanced text
+layout.
+
+However, until recently the only way to use them directly in the \TEX
+world was with the \XETEX engine.
+
+Unlike \XETEX, \LUATEX has no built-in support for \OpenType or
+technologies other than the original \TEX fonts.
+
+Instead, it provides hooks for executing \LUA code during the \TEX run
+that allow implementing extensions for loading fonts and manipulating
+how input text is processed without modifying the underlying engine.
+
+This is where \identifier{luaotfload} comes into play:
+Based on code from \CONTEXT, it extends \LUATEX with functionality necessary
+for handling \OpenType fonts.
+
+Additionally, it provides means for accessing fonts known to the operating
+system conveniently by indexing the metadata.
+
+\endsection
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\beginsection {Thanks}
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\identifier{Luaotfload} is part of \LUALATEX, the community-driven
+project to provide a foundation for using the \LATEX format with the
+full capabilites of the \LUATEX engine.
+%
+As such, the distinction between end users, contributors, and project
+maintainers is intentionally kept less strict, lest we unduly
+personalize the common effort.
+
+Nevertheless, the current maintainers would like to express their
+gratitude to Khaled Hosny, Akira Kakuto, Hironori Kitagawa and Dohyun
+Kim.
+%
+Their contributions -- be it patches, advice, or systematic
+testing -- made the switch from version 1.x to 2.2 possible.
+%
+Also, Hans Hagen, the author of the font loader, made porting the
+code to \LATEX a breeze due to the extra effort he invested into
+isolating it from the rest of \CONTEXT, not to mention his assistance
+in the task and willingness to respond to our suggestions.
+
+\endsection
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\beginsection {Loading Fonts}
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\identifier{luaotfload} supports an extended font request syntax:
+
+\beginnarrower
+ \nonproportional{\string\font\string\foo\space= \string{}%
+ \meta{prefix}\nonproportional{:}%
+ \meta{font name}\nonproportional{:}%
+ \meta{font features}\nonproportional{\string}}%
+ \meta{\TEX font features}
+\endnarrower
+
+\noindent
+The curly brackets are optional and escape the spaces in the enclosed
+font name.
+%
+Alternatively, double quotes serve the same purpose.
+%
+A selection of individual parts of the syntax are discussed below;
+for a more formal description see figure \ref{font-syntax}.
+
+\beginsyntaxfloat
+ {font-syntax}
+ {Font request syntax.
+ Braces or double quotes around the
+ \emphasis{specification} rule will
+ preserve whitespace in file names.
+ In addition to the font style modifiers
+ (\emphasis{slash-notation}) given above, there
+ are others that are recognized but will be silently
+ ignored: \nonproportional{aat},
+ \nonproportional{icu}, and
+ \nonproportional{gr}.
+ The special terminals are:
+ \smallcaps {feature\textunderscore id} for a valid font
+ feature name and
+ \smallcaps {feature\textunderscore value} for the corresponding
+ value.
+ \smallcaps {tfmname} is the name of a \abbrev{tfm} file.
+ \smallcaps {digit} again refers to bytes 48--57, and
+ \smallcaps {all\textunderscore characters} to all byte values.
+ \smallcaps {csname} and \smallcaps {dimension} are the \TEX concepts.}
+%
+ <definition> ::= `\\font', {\sc csname}, `=', <font request>, [ <size> ] ;
+
+ <size> ::= `at', {\sc dimension} ;
+
+ <font request> ::= `"', <unquoted font request> `"'
+ \alt `{', <unquoted font request> `}'
+ \alt <unquoted font request> ;
+
+ <unquoted font request> ::= <specification>, [`:', <feature list> ]
+ \alt <path lookup>, [ [`:'], <feature list> ] ;
+
+ <specification> ::= <prefixed spec>, [ <subfont no> ], \{ <modifier> \}
+ \alt <anon lookup>, \{ <modifier> \} ;
+
+ <prefixed spec> ::= `combo:', <combo list>
+ \alt `file:', <file lookup>
+ \alt `name:', <name lookup> ;
+
+ <combo list> ::= <combo def 1>, \{ `;', <combo def> \} ;
+
+ <combo def 1> ::= <combo id>, `->', <combo id> ;
+
+ <combo def> ::= <combo id>, `->', <combo id chars> ;
+
+ <combo id> ::= (`(', \{ {\sc digit} \}, `)' | \{ {\sc digit} \} ) ;
+
+ <combo id chars> ::= (`(', \{ {\sc digit} \}, `,', <combo chars>, `)'
+ \alt \{ {\sc digit} \} ) ;
+
+ <combo chars> ::= `fallback'
+ \alt \{ <combo range>, \{ `*', <combo range> \} \} ;
+
+ <combo range> ::= <combo num>, [ `-', <combo num> ] ;
+
+ <combo num> ::= `0x', \{ {\sc hexdigit} \}
+ \alt `U+', \{ {\sc digit} \}
+ \alt \{ {\sc digit} \} ;
+
+ <file lookup> ::= \{ <name character> \} ;
+
+ <name lookup> ::= \{ <name character> \} ;
+
+ <anon lookup> ::= {\sc tfmname} | <name lookup> ;
+
+ <path lookup> ::= `[', \{ <path content> \}, `]', [ <subfont no> ] ;
+
+ <path content> ::= <path balanced>
+ \alt `\\', {\sc all_characters}
+ \alt {\sc all_characters} - `]'
+
+ <path balanced> ::= `[', [ <path content> ], `]'
+
+ <modifier> ::= `/', (`I' | `B' | `BI' | `IB' | `S=', \{ {\sc digit} \} ) ;
+
+ <subfont no> ::= `(', \{ {\sc digit} \}, `)' ;
+
+ <feature list> ::= <feature expr>, \{ `;', <feature expr> \} ;
+
+ <feature expr> ::= {\sc feature_id}, `=', {\sc feature_value}
+ \alt <feature switch>, {\sc feature_id} ;
+
+ <feature switch> ::= `+' | `-' ;
+
+ <name character> ::= {\sc all_characters} - ( `(' | `/' | `:' ) ;
+\endsyntaxfloat
+
+%% Below guarded space gets borked in index; why‽
+\beginsubsection{Prefix -- the \identifier{luaotfload}{ }Way}
+
+In \identifier{luaotfload}, the canonical syntax for font requests
+requires a \emphasis{prefix}:
+%
+\beginnarrower
+ \nonproportional{\string\font\string\fontname\space= }%
+ \meta{prefix}%
+ \nonproportional{:}%
+ \meta{fontname}%
+ \dots
+\endnarrower
+%
+where \meta{prefix} is either \inlinecode{file:} or \inlinecode {name:}.\footnote{%
+ \identifier{Luaotfload} also knows two further prefixes, \inlinecode {kpse:}
+ and \inlinecode {my:}.
+ %
+ A \inlinecode {kpse} lookup is restricted to files that can be found by
+ \identifier{kpathsea} and will not attempt to locate system fonts.
+ %
+ This behavior can be of value when an extra degree of encapsulation is
+ needed, for instance when supplying a customized tex distribution.
+
+ The \inlinecode {my} lookup takes this a step further: it lets you define
+ a custom resolver function and hook it into the \luaident{resolve_font}
+ callback.
+ %
+ This ensures full control over how a file is located.
+ %
+ For a working example see the
+ \hyperlink [test repo]{https://bitbucket.org/phg/lua-la-tex-tests/src/5f6a535d/pln-lookup-callback-1.tex}.
+}
+%
+It determines whether the font loader should interpret the request as
+a \emphasis{file name} or
+ \emphasis{font name}, respectively,
+which again influences how it will attempt to locate the font.
+%
+Examples for font names are
+ “Latin Modern Italic”,
+ “GFS Bodoni Rg”, and
+ “PT Serif Caption”
+-- they are the human readable identifiers
+usually listed in drop-down menus and the like.\footnote{%
+ Font names may appear like a great choice at first because they
+ offer seemingly more intuitive identifiers in comparison to arguably
+ cryptic file names:
+ %
+ “PT Sans Bold” is a lot more descriptive than \fileent{PTS75F.ttf}.
+ On the other hand, font names are quite arbitrary and there is no
+ universal method to determine their meaning.
+ %
+ While \identifier{luaotfload} provides fairly sophisticated heuristic
+ to figure out a matching font style, weight, and optical size, it
+ cannot be relied upon to work satisfactorily for all font files.
+ %
+ For an in-depth analysis of the situation and how broken font names
+ are, please refer to
+ \hyperlink [this post]{http://www.ntg.nl/pipermail/ntg-context/2013/073889.html}
+ by Hans Hagen, the author of the font loader.
+ %
+ If in doubt, use filenames.
+ %
+ \fileent{luaotfload-tool} can perform the matching for you with the
+ option \inlinecode {--find=<name>}, and you can use the file name it returns
+ in your font definition.
+}
+%
+In order for fonts installed both in system locations and in your
+\fileent{texmf} to be accessible by font name, \identifier{luaotfload} must
+first collect the metadata included in the files.
+%
+Please refer to section~\ref{sec:fontdb} below for instructions on how to
+create the database.
+
+File names are whatever your file system allows them to be, except
+that that they may not contain the characters
+ \inlinecode {(},
+ \inlinecode {:}, and
+ \inlinecode {/}.
+%
+As is obvious from the last exception, the \inlinecode {file:} lookup will
+not process paths to the font location -- only those
+files found when generating the database are addressable this way.
+%
+Continue below in the \XETEX section if you need to load your fonts
+by path.
+%
+The file names corresponding to the example font names above are
+ \fileent{lmroman12-italic.otf},
+ \fileent{GFSBodoni.otf}, and
+ \fileent{PTZ56F.ttf}.
+
+\endsubsection
+
+\beginsubsection {Bracketed Lookups}
+\label{sec:bracket}
+Bracketed lookups allow for arbitrary character content to be used in a
+definition.
+%
+A simple bracketed request looks follows the scheme
+
+\beginnarrower
+ \nonproportional{\string\font\string\fontname\space = [}%
+ \meta{/path/to/file}%
+ \nonproportional{]}
+\endnarrower
+
+\noindent
+Inside the square brackets, every character except for a closing bracket is
+permitted, allowing for arbitrary paths to a font file -- including Windows
+style paths with UNC or drive letter prepended -- to be specified.
+%
+The \identifier{Luaotfload} syntax differs from \XETEX in that the subfont
+selector goes \emphasis{after} the closing bracket:
+
+\beginnarrower
+ \nonproportional{\string\font\string\fontname\space = [}%
+ \meta{/path/to/file}%
+ \nonproportional{]}
+ \nonproportional{(}n\nonproportional{)}
+\endnarrower
+
+Naturally, path-less file names are equally valid and processed the
+same way as an ordinary \inlinecode {file:} lookup.
+
+\beginsubsection {Compatibility}
+
+In addition to the regular prefixed requests, \identifier{luaotfload}
+accepts loading fonts the \XETEX way.
+%
+There are again two modes: bracketed and unbracketed.
+For the bracketed variety, see above, \ref{sec:bracket}.
+
+Unbracketed (or, for lack of a better word: \emphasis{anonymous})
+font requests resemble the conventional \TEX syntax.
+
+\beginnarrower
+ \nonproportional{\string\font\string\fontname\space= }%
+ \meta{font name}
+ \dots
+\endnarrower
+\endsubsection
+
+However, they have a broader spectrum of possible interpretations:
+before anything else, \identifier{luaotfload} attempts to load a
+traditional \TEX Font Metric (\abbrev{tfm} or \abbrev{ofm}).
+%
+If this fails, it performs a \inlinecode {path:} lookup, which itself will
+fall back to a \inlinecode {file:} lookup.
+%
+Lastly, if none of the above succeeded, attempt to resolve the request as a
+\inlinecode {name:} lookup by searching the font index for \meta{font name}.
+%
+The behavior of this “anonymous” lookup is configurable, see the configuation
+manpage for details.
+
+Furthermore, \identifier{luaotfload} supports the slashed (shorthand)
+font style notation from \XETEX.
+
+\beginnarrower
+ \nonproportional{\string\font\string\fontname\space= }%
+ \meta{font name}%
+ \nonproportional{/}%
+ \meta{modifier}
+ \dots
+\endnarrower
+
+\noindent
+Currently, four style modifiers are supported:
+ \inlinecode {I} for italic shape,
+ \inlinecode {B} for bold weight,
+ \inlinecode {BI} or \inlinecode {IB} for the combination of both.
+%
+Other “slashed” modifiers are too specific to the \XETEX engine and
+have no meaning in \LUATEX.
+
+\endsubsection
+
+\beginsubsection{Examples}
+
+\beginsubsubsection{Loading by File Name}
+
+For example, conventional \TeX\ font can be loaded with a
+\inlinecode {file:} request like so:
+
+\beginlisting
+ \font \lmromanten = {file:ec-lmr10} at 10pt
+\endlisting
+
+The \OpenType version of Janusz Nowacki’s font \emphasis{Antykwa
+Półtawskiego}\footnote{%
+ \hyperlink {http://jmn.pl/antykwa-poltawskiego/}, also available in
+ in \TEX Live.
+}
+in its condensed variant can be loaded as follows:
+
+\beginlisting
+ \font \apcregular = file:antpoltltcond-regular.otf at 42pt
+\endlisting
+
+The next example shows how to load the \emphasis{Porson} font digitized by
+the Greek Font Society using \XETEX-style syntax and an absolute path from a
+non-standard directory:
+
+\beginlisting
+ \font \gfsporson = "[/tmp/GFSPorson.otf]" at 12pt
+\endlisting
+
+\identifier{TrueType} collection files (the extension is usually
+\inlinecode{.ttc}) contain more than a single font. In order to refer to these
+subfonts, the respective index may be added in parentheses after the file
+name.\footnote{%
+ Incidentally, this syntactical detail also prevents one from loading files
+ that end in balanced parentheses.
+}
+
+\beginlisting
+ \font \cambriamain = "file:cambria.ttc(0)" at 10pt
+ \font \cambriamath = "file:cambria.ttc(1)" at 10pt
+\endlisting
+
+and likewise, requesting subfont inside a TTC container by path:
+
+\beginlisting
+ \font \asanamain = "[/home/typesetter/.fonts/math/asana.ttc](0):mode=node;+tlig" at 10pt
+ \font \asanamath = "[/home/typesetter/.fonts/math/asana.ttc](1):mode=base" at 10pt
+\endlisting
+
+\endsubsubsection
+
+\beginsubsubsection{Loading by Font Name}
+
+The \inlinecode {name:} lookup does not depend on cryptic filenames:
+
+\beginlisting
+ \font \pagellaregular = {name:TeX Gyre Pagella} at 9pt
+\endlisting
+
+A bit more specific but essentially the same lookup would be:
+
+\beginlisting
+ \font \pagellaregular = {name:TeX Gyre Pagella Regular} at 9pt
+\endlisting
+
+\noindent
+Which fits nicely with the whole set:
+
+\beginlisting
+ \font\pagellaregular = {name:TeX Gyre Pagella Regular} at 9pt
+ \font\pagellaitalic = {name:TeX Gyre Pagella Italic} at 9pt
+ \font\pagellabold = {name:TeX Gyre Pagella Bold} at 9pt
+ \font\pagellabolditalic = {name:TeX Gyre Pagella Bolditalic} at 9pt
+
+ {\pagellaregular foo bar baz\endgraf}
+ {\pagellaitalic foo bar baz\endgraf}
+ {\pagellabold foo bar baz\endgraf}
+ {\pagellabolditalic foo bar baz\endgraf}
+
+ ...
+\endlisting
+
+\endsubsubsection
+
+\beginsubsubsection{Modifiers}
+
+If the entire \emphasis{Iwona} family\footnote{%
+ \hyperlink {http://jmn.pl/kurier-i-iwona/},
+ also in \TEX Live.
+}
+is installed in some location accessible by \identifier{luaotfload},
+the regular shape can be loaded as follows:
+
+\beginlisting
+ \font \iwona = Iwona at 20pt
+\endlisting
+
+\noindent
+To load the most common of the other styles, the slash notation can
+be employed as shorthand:
+
+\beginlisting
+ \font \iwonaitalic = Iwona/I at 20pt
+ \font \iwonabold = Iwona/B at 20pt
+ \font \iwonabolditalic = Iwona/BI at 20pt
+\endlisting
+
+\noindent
+which is equivalent to these full names:
+
+\beginlisting
+ \font \iwonaitalic = "Iwona Italic" at 20pt
+ \font \iwonabold = "Iwona Bold" at 20pt
+ \font \iwonabolditalic = "Iwona BoldItalic" at 20pt
+\endlisting
+
+\endsubsubsection
+\endsubsection
+\endsection
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\beginsection {Font features}
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\emphasis{Font features} are the second to last component in the
+general scheme for font requests:
+
+\beginnarrower
+ \nonproportional{\string\font\string\foo\space= "}%
+ \meta{prefix}%
+ \nonproportional{:}%
+ \meta{font name}%
+ \nonproportional{:}%
+ \meta{font features}%
+ \meta{\TEX font features}%
+ \nonproportional{"}
+\endnarrower
+
+\noindent
+If style modifiers are present (\XETEX style), they must precede
+\meta{font features}.
+
+The element \meta{font features} is a semicolon-separated list of feature
+tags\footnote{%
+ Cf. \hyperlink {http://www.microsoft.com/typography/otspec/featurelist.htm}.
+}
+and font options.
+%
+Prepending a font feature with a \inlinecode{+} (plus sign) enables it,
+whereas a \inlinecode{-} (minus) disables it. For instance, the request
+
+\beginlisting
+ \font \test = LatinModernRoman:+clig;-kern
+\endlisting
+
+\noindent activates contextual ligatures (\inlinecode{clig}) and
+disables kerning (\inlinecode{kern}).
+%
+Alternatively the options \inlinecode{true} or \inlinecode{false} can
+be passed to the feature in a key/value expression.
+%
+The following request has the same meaning as the last one:
+
+\beginlisting
+ \font \test = LatinModernRoman:clig=true;kern=false
+\endlisting
+
+\noindent
+Furthermore, this second syntax is required should a font feature
+accept other options besides a true/false switch.
+%
+For example, \emphasis{stylistic alternates} (\inlinecode{salt}) are
+variants of given glyphs.
+%
+They can be selected either explicitly by supplying the variant
+index (starting from one), or randomly by setting the value to,
+obviously, \inlinecode{random}.
+
+%% TODO verify that this actually works with a font that supports
+%% the salt/random feature!\fi
+\beginlisting
+ \font \librmsaltfirst = LatinModernRoman:salt=1
+\endlisting
+
+\beginsubsection {Basic font features}
+
+\begindescriptions
+
+ \beginaltitem {mode}
+ \identifier{luaotfload} has two \OpenType processing
+ \emphasis{modes}:
+ \identifier{base} and \identifier{node}.
+
+ \identifier{base} mode works by mapping \OpenType
+ features to traditional \TEX ligature and kerning mechanisms.
+ %
+ Supporting only non-contextual substitutions and kerning
+ pairs, it is the slightly faster, albeit somewhat limited, variant.
+ %
+ \identifier{node} mode works by processing \TeX’s internal
+ node list directly at the \LUA end and supports
+ a wider range of \OpenType features.
+ %
+ The downside is that the intricate operations required for
+ \identifier{node} mode may slow down typesetting especially
+ with complex fonts and it does not work in math mode.
+
+ By default \identifier{luaotfload} is in \identifier{node}
+ mode, and \identifier{base} mode has to be requested where needed,
+ e.~g. for math fonts.
+ \endaltitem
+
+ \beginaltitem {script} \label{script-tag}
+ An \OpenType script tag;\footnote{%
+ See \hyperlink {http://www.microsoft.com/typography/otspec/scripttags.htm}
+ for a list of valid values.
+ %
+ For scripts derived from the Latin alphabet the value
+ \inlinecode{latn} is good choice.
+ }
+ the default value is \inlinecode{dflt}.
+ %
+ Some fonts, including very popular ones by foundries like Adobe,
+ do not assign features to the \inlinecode{dflt} script, in
+ which case the script needs to be set explicitly.
+ \endaltitem
+
+ \beginaltitem {language}
+ An \OpenType language system identifier,\footnote{%
+ Cf. \hyperlink {http://www.microsoft.com/typography/otspec/languagetags.htm}.
+ }
+ defaulting to \inlinecode{dflt}.
+ \endaltitem
+
+ \beginaltitem {color}
+ A font color, defined as a triplet of two-digit hexadecimal
+ \abbrev{rgb} values, with an optional fourth value for
+ transparency
+ (where \inlinecode{00} is completely transparent and
+ \inlinecode{FF} is opaque).
+
+ For example, in order to set text in semitransparent red:
+
+ \beginlisting
+ \font \test = "Latin Modern Roman:color=FF0000BB"
+ \endlisting
+ \endaltitem
+
+ \beginaltitem {kernfactor \& letterspace}
+ Define a font with letterspacing (tracking) enabled.
+ %
+ In \identifier{luaotfload}, letterspacing is implemented by
+ inserting additional kerning between glyphs.
+
+ This approach is derived from and still quite similar to the
+ \emphasis{character kerning} (\texmacro{setcharacterkerning} /
+ \texmacro{definecharacterkerning} \& al.) functionality of
+ Context, see the file \fileent{typo-krn.lua} there.
+ %
+ The main difference is that \identifier{luaotfload} does not
+ use \LUATEX attributes to assign letterspacing to regions,
+ but defines virtual letterspaced versions of a font.
+
+ The option \identifier{kernfactor} accepts a numeric value that
+ determines the letterspacing factor to be applied to the font
+ size.
+ %
+ E.~g. a kern factor of $0.42$ applied to a $10$ pt font
+ results in $4.2$ pt of additional kerning applied to each
+ pair of glyphs.
+ %
+ Ligatures are split into their component glyphs unless
+ explicitly ignored (see below).
+
+ For compatibility with \XETEX an alternative
+ \identifier{letterspace} option is supplied that interprets the
+ supplied value as a \emphasis{percentage} of the font size but
+ is otherwise identical to \identifier{kernfactor}.
+ %
+ Consequently, both definitions in below snippet yield the same
+ letterspacing width:
+
+ \beginlisting
+ \font \iwonakernedA = "file:Iwona-Regular.otf:kernfactor=0.125"
+ \font \iwonakernedB = "file:Iwona-Regular.otf:letterspace=12.5"
+ \endlisting
+
+ Specific pairs of letters and ligatures may be exempt from
+ letterspacing by defining the \LUA functions
+ \luaident{keeptogether} and \luaident{keepligature},
+ respectively, inside the namespace \inlinecode {luaotfload.letterspace}.
+ %
+ Both functions are called whenever the letterspacing callback
+ encounters an appropriate node or set of nodes.
+ %
+ If they return a true-ish value, no extra kern is inserted at
+ the current position.
+ %
+ \luaident{keeptogether} receives a pair of consecutive
+ glyph nodes in order of their appearance in the node list.
+ %
+ \luaident{keepligature} receives a single node which can be
+ analyzed into components.
+ %
+ (For details refer to the \emphasis{glyph nodes} section in the
+ \LUATEX reference manual.)
+ %
+ The implementation of both functions is left entirely to the
+ user.
+ \endaltitem
+
+\iffalse
+ \startbuffer [printvectors]
+ \directlua{inspect(fonts.protrusions.setups.default)
+ inspect(fonts.expansions.setups.default)}
+ \stopbuffer
+\fi
+
+ \beginaltitem {protrusion \& expansion}
+ These keys control microtypographic features of the font,
+ namely \emphasis{character protrusion} and \emphasis{font
+ expansion}.
+ %
+ Their arguments are names of \LUA tables that contain
+ values for the respective features.\footnote{%
+ For examples of the table layout please refer to the
+ section of the file \fileent{luaotfload-fonts-ext.lua} where the
+ default values are defined.
+ %
+ Alternatively and with loss of information, you can dump
+ those tables into your terminal by issuing
+ \unless \iffalse
+ \beginlisting
+ \directlua{inspect(fonts.protrusions.setups.default)
+ inspect(fonts.expansions.setups.default)}
+ \endlisting
+ \else
+ \typebuffer [printvectors]
+ \fi
+ at some point after loading \fileent{luaotfload.sty}.
+ }
+ %
+ For both, only the set \identifier{default} is predefined.
+
+ For example, to define a font with the default
+ protrusion vector applied\footnote{%
+ You also need to set
+ \inlinecode {pdfprotrudechars=2} and
+ \inlinecode {pdfadjustspacing=2}
+ to activate protrusion and expansion, respectively.
+ See the
+ \hyperlink [\PDFTEX manual]{http://mirrors.ctan.org/systems/pdftex/manual/pdftex-a.pdf}%
+ for details.
+ }:
+
+ \beginlisting
+ \font \test = LatinModernRoman:protrusion=default
+ \endlisting
+ \endaltitem
+\enddescriptions
+
+\endsubsection
+
+\beginsubsection {Non-standard font features}
+\identifier{luaotfload} adds a number of features that are not defined
+in the original \OpenType specification, most of them
+aiming at emulating the behavior familiar from other \TEX engines.
+%
+Currently (2014) there are three of them:
+
+\begindescriptions
+
+ \beginaltitem {anum}
+ Substitutes the glyphs in the \abbrev{ascii} number range
+ with their counterparts from eastern Arabic or Persian,
+ depending on the value of \identifier{language}.
+ \endaltitem
+
+ \beginaltitem {tlig}
+ Applies legacy \TEX ligatures\footnote{%
+ These contain the feature set \inlinecode {trep} of earlier
+ versions of \identifier{luaotfload}.
+
+ Note to \XETEX users: this is the equivalent of the
+ assignment \inlinecode {mapping=text-tex} using \XETEX's input
+ remapping feature.
+ }:
+
+ \unless \iffalse
+ %% Using braced arg syntax with inline code appears to be
+ %% impossible within Latex tables -- just ignore the weird
+ %% exclamation points below.
+ \begintabulate [rlrl]
+ \beginrow `` \newcell {\inlinecode !``! } \newcell '' \newcell {\inlinecode !''!} \endrow
+ \beginrow ` \newcell {\inlinecode !`! } \newcell ' \newcell {\inlinecode !'! } \endrow
+ \beginrow " \newcell {\inlinecode !"! } \newcell -- \newcell {\inlinecode !--!} \endrow
+ \beginrow --- \newcell {\inlinecode !---!} \newcell !` \newcell {\inlinecode ?!`?} \endrow
+ \beginrow ?` \newcell {\inlinecode !?`! } \newcell \newcell \endrow
+ \endtabulate
+ \else
+ %% XXX find a way to wrap these in the tabulate environment
+ \startframed [frame=off,width=broad,align=middle]
+ \startframed [frame=off,width=\dimexpr(\textwidth/2)]
+ \startxtable [align=middle]
+ \startxrow \startxcell `` \stopxcell \startxcell \inlinecode {``} \stopxcell \startxcell '' \stopxcell \startxcell \inlinecode {''} \stopxcell \stopxrow
+ \startxrow \startxcell ` \stopxcell \startxcell \inlinecode {`} \stopxcell \startxcell ' \stopxcell \startxcell \inlinecode {'} \stopxcell \stopxrow
+ \startxrow \startxcell " \stopxcell \startxcell \inlinecode {"} \stopxcell \startxcell -- \stopxcell \startxcell \inlinecode {--} \stopxcell \stopxrow
+ \startxrow \startxcell --- \stopxcell \startxcell \inlinecode {---} \stopxcell \startxcell !` \stopxcell \startxcell \inlinecode {!`} \stopxcell \stopxrow
+ \startxrow \startxcell ?` \stopxcell \startxcell \inlinecode {?`} \stopxcell \startxcell \stopxcell \startxcell \stopxcell \stopxrow
+ \stopxtable
+ \stopframed
+ \stopframed
+ \fi
+ \endaltitem
+
+ \beginaltitem {itlc}
+ Computes italic correction values (active by default).
+ \endaltitem
+
+\enddescriptions
+
+\endsubsection
+\endsection
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\beginsection {Combining fonts}
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+Version 2.7 and later support combining characters from multiple fonts into a
+single virtualized one. This requires that the affected fonts be loaded in
+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.
+
+Combinations are created by defining a font using the \luaident{combo:} prefix.
+
+\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
+font like \identifier{Computer Modern Unicode}, taking advantage of the fact
+that it too derives from Knuth’s original \identifier{Computer Modern} series:
+
+\beginlisting
+ \input luaotfload.sty
+ \font \lm = file:lmroman10-regular.otf:mode=base
+ \font \cmu = file:cmunrm.otf:mode=base
+ \font \lmu = "combo: 1->\fontid\lm; 2->\fontid\cmu,fallback"
+ \lmu Eh bien, mon prince. Gênes et Lueques ne sont plus que des
+ apanages, des поместья, de la famille Buonaparte.
+ \bye
+\endlisting
+
+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
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\beginsection {Font names database}
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\label{sec:fontdb}
+
+As mentioned above, \identifier{luaotfload} keeps track of which
+fonts are available to \LUATEX by means of a \emphasis{database}.
+%
+This allows referring to fonts not only by explicit filenames but
+also by the proper names contained in the metadata which is often
+more accessible to humans.\footnote{%
+ The tool \hyperlink[\fileent{otfinfo}]{http://www.lcdf.org/type/}
+ (comes with \TEX Live), when invoked on a font file with the
+ \inlinecode {-i} option, lists the variety of name fields defined for
+ it.
+}
+
+When \identifier{luaotfload} is asked to load a font by a font name,
+it will check if the database exists and load it, or else generate a
+fresh one.
+%
+Should it then fail to locate the font, an update to the database is
+performed in case the font has been added to the system only
+recently.
+%
+As soon as the database is updated, the resolver will try
+and look up the font again, all without user intervention.
+%
+The goal is for \identifier{luaotfload} to act in the background and
+behave as unobtrusively as possible, while providing a convenient
+interface to the fonts installed on the system.
+
+Generating the database for the first time may take a while since it
+inspects every font file on your computer.
+%
+This is particularly noticeable if it occurs during a typesetting run.
+In any case, subsequent updates to the database will be quite fast.
+
+\beginsubsection[luaotfload-tool]
+ {\fileent{luaotfload-tool}}
+
+It can still be desirable at times to do some of these steps
+manually, and without having to compile a document.
+%
+To this end, \identifier{luaotfload} comes with the utility
+\fileent{luaotfload-tool} that offers an interface to the database
+functionality.
+%
+Being a \LUA script, there are two ways to run it:
+either make it executable (\inlinecode {chmod +x} on unixoid systems) or
+pass it as an argument to \fileent{texlua}.\footnote{%
+ Tests by the maintainer show only marginal performance gain by
+ running with Luigi Scarso’s
+ \hyperlink [\identifier{Luajit\kern-.25ex\TEX}]{https://foundry.supelec.fr/projects/luajittex/},
+ which is probably due to the fact that most of the time is spent
+ on file system operations.
+
+ \emphasis{Note}:
+ On \abbrev{MS} \identifier{Windows} systems, the script can be run
+ either by calling the wrapper application
+ \fileent{luaotfload-tool.exe} or as
+ \inlinecode {texlua.exe luaotfload-tool.lua}.
+}
+%
+Invoked with the argument \inlinecode {--update} it will perform a database
+update, scanning for fonts not indexed.
+
+\beginlisting
+ luaotfload-tool --update
+\endlisting
+
+Adding the \inlinecode {--force} switch will initiate a complete
+rebuild of the database.
+
+\beginlisting
+ luaotfload-tool --update --force
+\endlisting
+
+\endsubsection
+
+\beginsubsection{Search Paths}
+
+\identifier{luaotfload} scans those directories where fonts are
+expected to be located on a given system.
+%
+On a Linux machine it follows the paths listed in the
+\identifier{Fontconfig} configuration files;
+consult \inlinecode {man 5 fonts.conf} for further information.
+%
+On \identifier{Windows} systems, the standard location is
+\inlinecode {Windows\\Fonts},
+%
+while \identifier{Mac OS~X} requires a multitude of paths to
+be examined.
+%
+The complete list is is given in table \ref{table-searchpaths}.
+Other paths can be specified by setting the environment variable
+\inlinecode {OSFONTDIR}.
+%
+If it is non-empty, then search will be extended to the included
+directories.
+
+\tablefloat {table-searchpaths}
+ {List of paths searched for each supported operating system.}
+ {%
+ \unless \iffalse
+ \begincentered
+ \begintabulate [lp{.5\textwidth}]
+ \beginrow
+ Windows \newcell \inlinecode !\% WINDIR\%\\ Fonts!
+ \endrow
+ \beginrow
+ Linux \newcell \fileent{/usr/local/etc/fonts/fonts.conf} and\hfill\break
+ \fileent{/etc/fonts/fonts.conf}
+ \endrow
+ \beginrow
+ Mac \newcell \fileent{\textasciitilde/Library/Fonts},\break
+ \fileent{/Library/Fonts},\break
+ \fileent{/System/Library/Fonts}, and\hfill\break
+ \fileent{/Network/Library/Fonts}
+ \endrow
+ \endtabulate
+ \endcentered
+ \else
+ \setuplocalinterlinespace [14pt]
+ \starttabulate [|l|p(.5\textwidth)|]
+ \NC Windows \NC \inlinecode {\% WINDIR\%\\ Fonts} \NC \NR
+ \NC Linux \NC \fileent{/usr/local/etc/fonts/fonts.conf} and\crlf
+ \fileent{/etc/fonts/fonts.conf} \NC \NR
+ \NC
+ Mac \NC \fileent{\textasciitilde/Library/Fonts},\crlf
+ \fileent{/Library/Fonts},\break
+ \fileent{/System/Library/Fonts}, and\crlf
+ \fileent{/Network/Library/Fonts} \NC \NR
+ \stoptabulate
+ \fi%
+ }
+
+\endsubsection
+
+\beginsubsection{Querying from Outside}
+
+\fileent{luaotfload-tool} also provides rudimentary means of
+accessing the information collected in the font database.
+%
+If the option \inlinecode {--find=}\emphasis{name} is given, the script will
+try and search the fonts indexed by \identifier{luaotfload} for a
+matching name.
+%
+For instance, the invocation
+
+\beginlisting
+ luaotfload-tool --find="Iwona Regular"
+\endlisting
+
+\noindent
+will verify if “Iwona Regular” is found in the database and can be
+readily requested in a document.
+
+If you are unsure about the actual font name, then add the
+\inlinecode {-F} (or \inlinecode {--fuzzy}) switch to the command line to enable
+approximate matching.
+%
+Suppose you cannot precisely remember if the variant of
+\identifier{Iwona} you are looking for was “Bright” or “Light”.
+The query
+
+\beginlisting
+ luaotfload-tool -F --find="Iwona Bright"
+\endlisting
+
+\noindent
+will tell you that indeed the latter name is correct.
+
+Basic information about fonts in the database can be displayed
+using the \inlinecode {-i} option (\inlinecode {--info}).
+%
+\beginlisting
+ luaotfload-tool -i --find="Iwona Light Italic"
+\endlisting
+%
+\noindent
+The meaning of the printed values is described in section 4.4 of the
+\LUATEX reference manual.\footnote{%
+ In \TEX Live: \fileent{texmf-dist/doc/luatex/base/luatexref-t.pdf}.
+}
+
+For a much more detailed report about a given font try the
+\inlinecode {-I} option instead (\inlinecode {--inspect}).
+\beginlisting
+ luaotfload-tool -I --find="Iwona Light Italic"
+\endlisting
+
+\inlinecode {luaotfload-tool --help} will list the available command line
+switches, including some not discussed in detail here.
+%
+For a full documentation of \identifier{luaotfload-tool} and its
+capabilities refer to the manpage
+(\inlinecode {man 1 luaotfload-tool}).\footnote{%
+ Or see \inlinecode {luaotfload-tool.rst} in the source directory.
+}
+
+\endsubsection
+
+\beginsubsection {Blacklisting Fonts}
+\label{font-blacklist}
+
+Some fonts are problematic in general, or just in \LUATEX.
+%
+If you find that compiling your document takes far too long or eats
+away all your system’s memory, you can track down the culprit by
+running \inlinecode {luaotfload-tool -v} to increase verbosity.
+%
+Take a note of the \emphasis{filename} of the font that database
+creation fails with and append it to the file
+\fileent{luaotfload-blacklist.cnf}.
+
+A blacklist file is a list of font filenames, one per line.
+Specifying the full path to where the file is located is optional, the
+plain filename should suffice.
+%
+File extensions (\fileent{.otf}, \fileent{.ttf}, etc.) may be omitted.
+%
+Anything after a percent (\inlinecode {\%}) character until the end of the line
+is ignored, so use this to add comments.
+%
+Place this file to some location where the \identifier{kpse}
+library can find it, e.~g.
+\fileent{texmf-local/tex/luatex/luaotfload} if you are running
+\identifier{\TEX Live},\footnote{%
+ You may have to run \inlinecode {mktexlsr} if you created a new file in
+ your \fileent{texmf} tree.
+}
+or just leave it in the working directory of your document.
+%
+\identifier{luaotfload} reads all files named
+\fileent{luaotfload-blacklist.cnf} it finds, so the fonts in
+\fileent{./luaotfload-blacklist.cnf} extend the global blacklist.
+
+Furthermore, a filename prepended with a dash character (\inlinecode{-}) is
+removed from the blacklist, causing it to be temporarily whitelisted
+without modifying the global file.
+%
+An example with explicit paths:
+
+\beginlisting
+% example otf-blacklist.cnf
+/Library/Fonts/GillSans.ttc % Luaotfload ignores this font.
+-/Library/Fonts/Optima.ttc % This one is usable again, even if
+ % blacklisted somewhere else.
+\endlisting
+
+\endsubsection
+\endsection
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\beginsection {The Fontloader}
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\beginsubsection {Overview}
+
+To a large extent, \identifier{luaotfload} relies on code originally
+written by Hans Hagen for the
+\hyperlink[\identifier{\CONTEXT}]{http://wiki.contextgarden.net}
+format.
+%
+It integrates the font loader, written entirely in \LUA, as distributed
+in the \identifier{\LUATEX-Fonts} package.
+%
+The original \LUA source files have been combined using the \CONTEXT
+packaging library into a single, self-contained blob. In
+this form the font loader depends only on the \identifier{lualibs}
+package and requires only minor adaptions to integrate into
+\identifier{luaotfload}.
+
+The guiding principle is to let \CONTEXT/\LUATEX-Fonts take care of the
+implementation, and update the imported code as frequently as
+necessary.
+%
+As maintainers, we aim at importing files from upstream essentially
+\emphasis{unmodified}, except for renaming them to prevent name
+clashes.
+%
+This job has been greatly alleviated since the advent of
+\LUATEX-Fonts, prior to which the individual dependencies had to be
+manually spotted and extracted from the \CONTEXT source code in a
+complicated and error-prone fashion.
+
+\endsubsection
+
+\beginsubsection {Contents and Dependencies}
+
+Below is a commented list of the files distributed with
+\identifier{luaotfload} in one way or the other.
+%
+See see the figure on page \pageref{file-graph} for a
+graphical representation of the dependencies.
+%
+\label{package}%
+Through the script \fileent{mkimport} a \CONTEXT library
+is invoked to create the \identifier{luaotfload} fontloader as a merged
+(amalgamated) source file.\footnote{%
+ In \CONTEXT, this facility can be accessed by means of a
+ \hyperlink[script]{https://bitbucket.org/phg/context-mirror/src/beta/scripts/context/lua/mtx-package.lua?at=beta}
+ which is integrated into \fileent{mtxrun} as a subcommand.
+ Run \inlinecode {mtxrun --script package --help} to display further
+ information.
+ For the actual merging code see the file
+ \fileent{util-mrg.lua} that is part of \CONTEXT.
+}
+%
+This file constitutes the “default fontloader” and is part of the
+\identifier{luaotfload} package as \fileent{fontloader-YY-MM-DD.lua},
+where the uppercase letters are placeholders for the build date.
+%
+A companion to it, \fileent{luatex-basics-gen.lua} (renamed to \fileent{fontloader-basics-gen.lua} in \identifier{luaotfload})
+must be loaded beforehand to set up parts of the environment required by the \CONTEXT
+libraries.
+%
+During a \TEX\ run, the fontloader initialization and injection happens
+in the module \fileent{luaotfload-init.lua}.
+%
+Additionally, the “reference fontloader” as imported from \LUATEX-Fonts
+is provided as the file \fileent{fontloader-reference.lua}.
+%
+This file is self-contained in that it packages all the auxiliary \LUA
+libraries too, as Luaotfload did up to the 2.5 series; since that job
+has been offloaded to the \identifier{Lualibs} package, loading this
+fontloader introduces a certain code duplication.
+
+A number of \emphasis{\LUA utility libraries} are not part of the
+\identifier{luaotfload} fontloader, contrary to its equivalent in
+\LUATEX-Fonts. These are already provided by the \identifier{lualibs}
+and have thus been omitted from the merge.\footnote{%
+ Faithful listeners will remember the pre-2.6 era when the fontloader
+ used to be integrated as-is which caused all kinds of code
+ duplication with the pervasive \identifier{lualibs} package.
+ This conceptual glitch has since been amended by tightening the
+ coupling with the excellent \CONTEXT\ toolchain.
+}
+
+\begindoublecolumns
+ \begindefinitions
+ \directlua{ printctxlibslist ()}
+ \enddefinitions
+\enddoublecolumns
+
+The reference fontloader is home to several \LUA files that can be
+grouped twofold as below:
+
+\begindefinitions
+ \beginnormalitem
+ The \emphasis{font loader} itself.
+ These files have been written for \LUATEX-Fonts and they are
+ distributed along with \identifier{luaotfload} so as to resemble
+ the state of the code when it was imported. Their purpose is either
+ to give a slightly aged version of a file if upstream considers
+ latest developments for not yet ready for use outside Context; or,
+ to install placeholders or minimalist versions of APIs relied upon
+ but usually provided by parts of Context not included in the
+ fontloader.
+ \begindoublecolumns
+ \begindefinitions
+ \directlua{printctxallgenericlist ()}
+ \enddefinitions
+ \enddoublecolumns
+ \endnormalitem
+
+ \beginnormalitem
+ Code related to \emphasis{font handling and node processing}, taken
+ directly from \CONTEXT.
+ \begindoublecolumns
+ \begindefinitions
+ \directlua{printctxfontlist ()}
+ \enddefinitions
+ \enddoublecolumns
+ \endnormalitem
+\enddefinitions
+
+As an alternative to the merged file, \identifier {Luaotfload} may load
+individual unpackaged \LUA libraries that come with the source, or even
+use the files from Context directly.
+%
+Thus if you prefer running bleeding edge code from the \CONTEXT beta,
+choose the \inlinecode {context} fontloader via the configuration file
+(see sections \ref{sec:conf} and \ref{sec:pkg} below).
+
+Also, the merged file at some point loads the Adobe Glyph List from a
+\LUA table that is contained in \fileent{luaotfload-glyphlist.lua},
+which is automatically generated by the script
+\fileent{mkglyphlist}.\footnote{%
+ See \fileent{luaotfload-font-enc.lua}.
+ The hard-coded file name is why we have to replace the procedure
+ that loads the file in \fileent{luaotfload-init.lua}.
+}
+%
+There is a make target \identifier{glyphs} that will create a fresh
+glyph list so we don’t need to import it from \CONTEXT any longer.
+
+In addition to these, \identifier{luaotfload} requires a number of
+files not contained in the merge. Some of these have no equivalent in
+\LUATEX-Fonts or \CONTEXT, some were taken unmodified from the latter.
+
+
+\beginfilelist
+ \beginaltitem {luaotfload-features.lua}
+ font feature handling; incorporates some of the code from
+ \fileent{font-otc} from \CONTEXT;
+ \endaltitem
+ \beginaltitem {luaotfload-configuration.lua}
+ handling of \fileent{luaotfload.conf(5)}.
+ \endaltitem
+ \beginaltitem {luaotfload-log.lua}
+ overrides the \CONTEXT logging functionality.
+ \endaltitem
+ \beginaltitem {luaotfload-loaders.lua}
+ registers readers in the fontloader for various kinds of
+ font formats
+ \endaltitem
+ \beginaltitem {luaotfload-parsers.lua}
+ various \abbrev{lpeg}-based parsers.
+ \endaltitem
+ \beginaltitem {luaotfload-database.lua}
+ font names database.
+ \endaltitem
+ \beginaltitem {luaotfload-resolvers.lua}
+ file name resolvers.
+ \endaltitem
+ \beginaltitem {luaotfload-colors.lua}
+ color handling.
+ \endaltitem
+ \beginaltitem {luaotfload-auxiliary.lua}
+ access to internal functionality for package authors (proposals
+ for additions welcome).
+ \endaltitem
+ \beginaltitem {luaotfload-letterspace.lua}
+ font-based letterspacing.
+ \endaltitem
+ \beginaltitem {luaotfload-filelist.lua}
+ data about the files in the package.
+ \endaltitem
+\endfilelist
+
+%\figurefloat
+% {file-graph}
+% {Schematic of the files in \identifier{Luaotfload}}
+% {filegraph.pdf}
+
+\endsubsection
+
+\beginsubsection {Packaging}
+
+\label{sec:pkg}%
+The fontloader code is integrated as an isolated component that can be
+switched out on demand.
+%
+To specify the fontloader you wish to use, the configuration file
+(described in section \ref{sec:conf}) provides the option
+\inlinecode{fontloader}.
+%
+Its value can be one of the identifiers \inlinecode{default} or
+\inlinecode{reference} (see above, section \ref{package}) or the name
+of a file somewhere in the search path of \LUATEX.
+%
+This will make \identifier {Luaotfload} locate the \CONTEXT source by
+means of \identifier{kpathsea} lookups and use those instead of the
+merged package.
+%
+The parameter may be extended with a path to the \CONTEXT
+\fileent{texmf}, separated with a colon:
+
+\beginlisting
+[run]
+ fontloader = context:~/context/tex/texmf-context
+\endlisting
+
+\noindent This setting allows accessing an installation -- e. g. the
+standalone distribution or a source repository -- outside the current
+\TEX distribution.
+
+Like the \identifier{Lualibs} package, the fontloader is deployed as a
+\emphasis{merged package} containing a series of \LUA files joined
+together in their expected order and stripped of non-significant parts.
+%
+The \fileent{mkimport} utility assists in pulling the files from a
+\CONTEXT tree and packaging them for use with \identifier{Luaotfload}.%
+%
+The state of the files currently in \identifier{Luaotfload}’s
+repository can be queried:
+\beginlisting
+./scripts/mkimport news
+\endlisting
+%
+The subcommand for importing takes the prefix of the desired \CONTEXT
+\identifier{texmf} as an optional argument:
+\beginlisting
+./scripts/mkimport import ~/context/tex/texmf-context
+\endlisting
+%
+Whereas the command for packaging requires a path to the
+\emphasis{package description file} and the output name to be passed.
+\beginlisting
+./scripts/mkimport package fontloader-custom.lua
+\endlisting
+
+From the toplevel makefile, the targets \inlinecode{import} and
+\inlinecode{package} provide easy access to the commands as invoked during
+the \identifier{Luaotfload} build process.\footnote{%
+ \emphasis{Hint for those interested in the packaging process}: issue
+ \inlinecode{make show} for a list of available build routines.
+}
+These will call \inlinecode{mkimport} script with the correct
+parameters to generate a datestamped package.
+%
+Whether files have been updated in the upstream distribution can be
+queried by \inlinecode{./scripts/mkimport news}.
+%
+This will compare the imported files with their counterparts in the
+\CONTEXT distribution and report changes.
+
+\endsubsection
+
+\endsection
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\beginsection {Configuration Files}
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\beginnarrower
+ \emphasis{Caution}: For the authoritative documentation, consult the
+ manpage for \fileent{luaotfload.conf(5)}.
+\endnarrower
+
+\label{sec:conf}
+The runtime behavior of \identifier{Luaotfload} can be customized by
+means of a configuration file.
+% location
+At startup, it attempts to locate a file called \fileent
+{luaotfload.conf} or \fileent {luaotfloadrc} at a number of candidate
+locations:
+
+\begincentered
+ \begindefinitions
+ \beginnormalitem \fileent{./luaotfload.conf} \endnormalitem
+ \beginnormalitem \fileent{./luaotfloadrc} \endnormalitem
+ \beginnormalitem \fileent{\$XDG_CONFIG_HOME/luaotfload/luaotfload.conf} \endnormalitem
+ \beginnormalitem \fileent{\$XDG_CONFIG_HOME/luaotfload/luaotfload.rc} \endnormalitem
+ \beginnormalitem \fileent{~/.luaotfloadrc} \endnormalitem
+ \enddefinitions
+\endcentered
+
+\beginnarrower
+ \emphasis{Caution}: The configuration potentially modifies the final
+ document. A project-local file belongs under version control along
+ with the rest of the document. This is to ensure that everybody who
+ builds the project also receives the same customizations as the
+ author.
+\endnarrower
+
+% syntax
+The syntax is fairly close to the format used by
+\fileent{git-config(1)} which in turn was derived from the popular
+\identifier{.INI} format: Lines of key-value pairs are grouped under
+different configuration “sections”.\footnote{%
+ The configuration parser in \fileent {luoatfload-parsers.lua} might
+ be employed by other packages for similar purposes.
+}
+% example settings
+An example for customization via \fileent {luaotfload.conf} might look
+as below:
+
+\beginlisting
+; Example luaotfload.conf containing a rudimentary configuration
+[db]
+ update-live = false
+[run]
+ color-callback = pre_linebreak_filter
+ definer = info_patch
+ log-level = 5
+[default-features]
+ global = mode=base
+\endlisting
+
+This specifies that for the given project, \identifier{Luaotfload}
+shall not attempt to automatically scan for fonts if it can’t resolve a
+request. The font-based colorization will happen during \LUATEX’s
+pre-linebreak filter. The fontloader will output verbose information
+about the fonts at definition time along with globally increased
+verbosity. Lastly, the fontloader defaults to the less expensive
+\luaident{base} mode like it does in \CONTEXT.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\beginsection {Auxiliary Functions}
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+With release version 2.2, \identifier{Luaotfload} received
+additional functions for package authors to call from outside
+(see the file \fileent{luaotfload-auxiliary.lua} for details).
+%
+The purpose of this addition twofold.
+%
+Firstly, \identifier{luaotfload} failed to provide a stable interface
+to internals in the past which resulted in an unmanageable situation
+of different packages abusing the raw access to font objects by means
+of the \luaident{patch_font} callback.
+%
+When the structure of the font object changed due to an update, all
+of these imploded and several packages had to be fixed while
+simultaneously providing fallbacks for earlier versions.
+%
+Now the patching is done on the \identifier{luaotfload} side and can
+be adapted with future modifications to font objects without touching
+the packages that depend on it.
+%
+Second, some the capabilities of the font loader and the names
+database are not immediately relevant in \identifier{luaotfload}
+itself but might nevertheless be of great value to package authors or
+end users.
+
+Note that the current interface is not yet set in stone and the
+development team is open to suggestions for improvements or
+additions.
+
+\beginsubsection {Callback Functions}
+
+The \luaident{patch_font} callback is inserted in the wrapper
+\identifier{luaotfload} provides for the font definition callback.
+%
+At this place it allows manipulating the font object immediately after
+the font loader is done creating it.
+%
+For a short demonstration of its usefulness, here is a snippet that
+writes an entire font object to the file \fileent{fontdump.lua}:
+
+\beginlisting
+ \input luaotfload.sty
+ \directlua{
+ local dumpfile = "fontdump.lua"
+ local dump_font = function (tfmdata)
+ local data = table.serialize(tfmdata)
+ io.savedata(dumpfile, data)
+ end
+
+ luatexbase.add_to_callback(
+ "luaotfload.patch_font",
+ dump_font,
+ "my_private_callbacks.dump_font"
+ )
+ }
+ \font \dumpme = name:Iwona
+ \bye
+\endlisting
+
+\emphasis{Beware}: this creates a Lua file of around 150,000 lines of
+code, taking up 3~\abbrev{mb} of disk space.
+%
+By inspecting the output you can get a first impression of how a font
+is structured in \LUATEX’s memory, what elements it is composed of,
+and in what ways it can be rearranged.
+
+\beginsubsubsection {Compatibility with Earlier Versions}
+
+As has been touched on in the preface to this section, the structure
+of the object as returned by the fontloader underwent rather drastic
+changes during different stages of its development, and not all
+packages that made use of font patching have kept up with every one
+of it.
+%
+To ensure compatibility with these as well as older versions of
+some packages, \identifier{luaotfload} sets up copies of or references
+to data in the font table where it used to be located.
+%
+For instance, important parameters like the requested point size, the
+units factor, and the font name have again been made accessible from
+the toplevel of the table even though they were migrated to different
+subtables in the meantime.
+
+\endsubsubsection
+
+\beginsubsubsection{Patches}
+
+These are mostly concerned with establishing compatibility with \XETEX.
+
+\beginfunctionlist
+
+ \beginaltitem {set_sscale_dimens}
+ Calculate \texmacro{fontdimen}s 10 and 11 to emulate \XETEX.
+ \endaltitem
+
+ \beginaltitem {set_capheight}
+ Calculates \texmacro{fontdimen} 8 like \XETEX.
+ \endaltitem
+
+ \beginaltitem {patch_cambria_domh}
+ Correct some values of the font \emphasis{Cambria Math}.
+ \endaltitem
+
+\endfunctionlist
+
+\endsubsection
+
+\beginsubsection {Package Author’s Interface}
+
+As \LUATEX release 1.0 is nearing, the demand for a reliable interface
+for package authors increases.
+
+\endsubsubsection
+
+\beginsubsubsection{Font Properties}
+
+Below functions mostly concern querying the different components of a
+font like for instance the glyphs it contains, or what font features
+are defined for which scripts.
+
+\beginfunctionlist
+
+ \beginaltitem {aux.font_has_glyph (id : int, index : int)}
+ Predicate that returns true if the font \luaident{id}
+ has glyph \luaident{index}.
+ \endaltitem
+
+ \beginaltitem {aux.slot_of_name(name : string)}
+ Translates an Adobe Glyph name to the corresponding glyph
+ slot.
+ \endaltitem
+
+ \beginaltitem {aux.name_of_slot(slot : int)}
+ The inverse of \luaident{slot_of_name}; note that this
+ might be incomplete as multiple glyph names may map to the
+ same codepoint, only one of which is returned by
+ \luaident{name_of_slot}.
+ \endaltitem
+
+ \beginaltitem {aux.provides_script(id : int, script : string)}
+ Test if a font supports \luaident{script}.
+ \endaltitem
+
+ \beginaltitem {aux.provides_language(id : int, script : string, language : string)}
+ Test if a font defines \luaident{language} for a given
+ \luaident{script}.
+ \endaltitem
+
+ \beginaltitem {aux.provides_feature(id : int, script : string,
+ language : string, feature : string)}
+ Test if a font defines \luaident{feature} for
+ \luaident{language} for a given \luaident{script}.
+ \endaltitem
+
+ \beginaltitem {aux.get_math_dimension(id : int, dimension : string)}
+ Get the dimension \luaident{dimension} of font \luaident{id}.
+ \endaltitem
+
+ \beginaltitem {aux.sprint_math_dimension(id : int, dimension : string)}
+ Same as \luaident{get_math_dimension()}, but output the value
+ in scaled points at the \TEX end.
+ \endaltitem
+
+\endfunctionlist
+
+\endsubsubsection
+
+\beginsubsubsection{Database}
+
+%% not implemented, may come back later
+\beginfunctionlist
+% \beginaltitem {aux.scan_external_dir(dir : string)}
+% Include fonts in directory \luaident{dir} in font lookups without
+% adding them to the database.
+%
+ \beginaltitem {aux.read_font_index (void)}
+ Read the index file from the appropriate location (usually
+ the bytecode file \fileent{luaotfload-names.luc} somewhere
+ in the \fileent{texmf-var} tree) and return the result as a
+ table. The file is processed with each call so it is up to
+ the user to store the result for later access.
+ \endaltitem
+
+ \beginaltitem {aux.font_index (void)}
+ Return a reference of the font names table used internally
+ by \identifier{luaotfload}. The index will be read if it
+ has not been loaded up to this point. Also a font scan that
+ overwrites the current index file might be triggered. Since
+ the return value points to the actual index, any
+ modifications to the table might influence runtime behavior
+ of \identifier{luaotfload}.
+ \endaltitem
+
+\endfunctionlist
+
+\endsubsubsection
+
+\endsubsection
+\endsection
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\beginsection {Troubleshooting}
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\beginsubsection {Database Generation}
+
+If you encounter problems with some fonts, please first update to the
+latest version of this package before reporting a bug, as
+\identifier{luaotfload} is under active development and still a moving
+target.
+%
+The development takes place on \identifier{github} at
+\hyperlink {https://github.com/lualatex/luaotfload} where there is an issue
+tracker for submitting bug reports, feature requests and the likes.
+
+Bug reports are more likely to be addressed if they contain the output
+of
+
+\beginlisting
+ luaotfload-tool --diagnose=environment,files,permissions
+\endlisting
+
+\noindent Consult the man page for a description of these options.
+
+Errors during database generation can be traced by increasing the
+verbosity level and redirecting log output to \fileent{stdout}:
+
+\beginlisting
+ luaotfload-tool -fuvvv --log=stdout
+\endlisting
+
+\noindent or to a file in \fileent{/tmp}:
+
+\beginlisting
+ luaotfload-tool -fuvvv --log=file
+\endlisting
+
+\noindent In the latter case, invoke the \inlinecode {tail(1)} utility on the
+file for live monitoring of the progress.
+
+If database generation fails, the font last printed to the terminal or
+log file is likely to be the culprit.
+%
+Please specify it when reporting a bug, and blacklist it for the time
+being (see above, page \pageref{font-blacklist}).
+
+\endsubsection
+
+\beginsubsection {Font Features}
+
+A common problem is the lack of features for some
+\OpenType fonts even when specified.
+%
+This can be related to the fact that some fonts do not provide features
+for the \inlinecode {dflt} script (see above on page \pageref{script-tag}),
+which is the default one in this package.
+%
+If this happens, assigning a noth script when the font is defined should
+fix it.
+%
+For example with \inlinecode {latn}:
+
+\beginlisting
+ \font \test = file:MyFont.otf:script=latn;+liga;
+\endlisting
+
+You can get a list of features that a font defines for scripts and
+languages by querying it in \fileent{luaotfload-tool}:
+
+\beginlisting
+ luaotfload-tool --find="Iwona" --inspect
+\endlisting
+
+\endsubsection
+
+\beginsubsection {\LUATEX Programming}
+
+Another strategy that helps avoiding problems is to not access raw
+\LUATEX internals directly.
+%
+Some of them, even though they are dangerous to access, have not been
+overridden or disabled.
+%
+Thus, whenever possible prefer the functions in the \luaident{aux}
+namespace over direct manipulation of font objects. For example, raw
+access to the \luaident{font.fonts} table like:
+
+\beginlisting
+ local somefont = font.fonts[2]
+\endlisting
+
+\noindent can render already defined fonts unusable.
+%
+Instead, the function \luaident{font.getfont()} should be used
+because it has been replaced by a safe variant.
+
+However, \luaident{font.getfont()} only covers fonts handled by the
+font loader, e.~g. \identifier{OpenType} and \identifier{TrueType}
+fonts, but not \abbrev{tfm} or \abbrev{ofm}.
+%
+Should you absolutely require access to all fonts known to \LUATEX,
+including the virtual and autogenerated ones, then you need to query
+both \luaident{font.getfont()} and \luaident{font.fonts}.
+%
+In this case, best define you own accessor:
+
+\beginlisting
+ local unsafe_getfont = function (id)
+ local tfmdata = font.getfont (id)
+ if not tfmdata then
+ tfmdata = font.fonts[id]
+ end
+ return tfmdata
+ end
+
+ --- use like getfont()
+ local somefont = unsafe_getfont (2)
+\endlisting
+
+\endsubsection
+\endsection
+
+\beginsection {License}
+
+\identifier {luaotfload} is licensed under the terms of the
+\hyperlink [GNU General Public License version 2.0]%
+ {https://www.gnu.org/licenses/old-licenses/gpl-2.0.html}.
+Following the underlying fontloader code \identifier {luaotfload}
+recognizes only that exact version as its license.
+The „any later version” clause of the original license text as
+copyrighted by the \hyperlink [Free Software Foundation]{http://www.fsf.org/}
+\emphasis {does not apply} to either \identifier {luaotfload} or the
+code imported from \CONTEXT.
+
+The complete text of the license is given as a separate file \fileent
+{COPYING} in the toplevel directory of the
+\hyperlink [\fileent {Luaotfload} Git repository]{https://github.com/lualatex/luaotfload/blob/master/COPYING}.
+Distributions probably package it as \fileent
+{doc/luatex/luaotfload/COPYING} in the relevant \fileent {texmf} tree.
+
+\endsection
+
+\endinput
+
+% vim:ft=tex:tw=79:et:sw=2
Property changes on: trunk/Master/texmf-dist/doc/luatex/luaotfload/luaotfload-main.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/luatex/luaotfload/luaotfload-tool.pdf
===================================================================
(Binary files differ)
Index: trunk/Master/texmf-dist/doc/luatex/luaotfload/luaotfload-tool.pdf
===================================================================
--- trunk/Master/texmf-dist/doc/luatex/luaotfload/luaotfload-tool.pdf 2018-09-26 20:49:48 UTC (rev 48770)
+++ trunk/Master/texmf-dist/doc/luatex/luaotfload/luaotfload-tool.pdf 2018-09-26 20:50:34 UTC (rev 48771)
Property changes on: trunk/Master/texmf-dist/doc/luatex/luaotfload/luaotfload-tool.pdf
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/pdf
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/luatex/luaotfload/luaotfload-tool.rst
===================================================================
--- trunk/Master/texmf-dist/doc/luatex/luaotfload/luaotfload-tool.rst (rev 0)
+++ trunk/Master/texmf-dist/doc/luatex/luaotfload/luaotfload-tool.rst 2018-09-26 20:50:34 UTC (rev 48771)
@@ -0,0 +1,328 @@
+=======================================================================
+ luaotfload-tool
+=======================================================================
+
+-----------------------------------------------------------------------
+ generate and query the Luaotfload font names database
+-----------------------------------------------------------------------
+
+:Date: 2018-09-21
+:Copyright: GPL v2.0
+:Version: 2.9
+:Manual section: 1
+:Manual group: text processing
+
+SYNOPSIS
+=======================================================================
+
+**luaotfload-tool** [ -bcDfFiIlLnpqRSuvVhw ]
+
+**luaotfload-tool** --update [ --force ] [ --quiet ] [ --verbose ]
+ [ --prefer-texmf ] [ --dry-run ]
+ [ --formats=[+|-]EXTENSIONS ]
+ [ --no-compress ] [ --no-strip ]
+ [ --local ] [ --max-fonts=N ]
+
+**luaotfload-tool** --find=FONTNAME [ --fuzzy ] [ --info ] [ --inspect ]
+ [ --no-reload ]
+
+**luaotfload-tool** --flush-lookups
+
+**luaotfload-tool** --cache=DIRECTIVE
+
+**luaotfload-tool** --list=CRITERION[:VALUE] [ --fields=F1,F2,...,Fn ]
+
+**luaotfload-tool** --bisect=DIRECTIVE
+
+**luaotfload-tool** --help
+
+**luaotfload-tool** --version
+
+**luaotfload-tool** --show-blacklist
+
+**luaotfload-tool** --diagnose=CHECK
+
+**luaotfload-tool** --conf=FILE --dumpconf
+
+DESCRIPTION
+=======================================================================
+
+luaotfload-tool accesses the font names database that is required by
+the *Luaotfload* package. There are two general modes: **update** and
+**query**.
+
++ **update**: update the database or rebuild it entirely;
++ **query**: resolve a font name or display close matches.
+
+OPTIONS
+=======================================================================
+
+update mode
+-----------------------------------------------------------------------
+--update, -u Update the database; indexes new fonts.
+--force, -f Force rebuilding of the database; re-indexes
+ all fonts.
+--local, -L Include font files in ``$PWD``. This option
+ will cause large parts of the database to be
+ rebuilt. Thus it is quite inefficient.
+ Additionally, if local font files are found,
+ the database is prevented from being saved
+ to disk, so the local fonts need to be parsed
+ with every invocation of ``luaotfload-tool``.
+--no-reload, -n Suppress auto-updates to the database (e.g.
+ when ``--find`` is passed an unknown name).
+--no-compress, -c Do not filter the plain text version of the
+ font index through gzip. Useful for debugging
+ if your editor is built without zlib.
+
+--prefer-texmf, -p Organize the file name database in a way so
+ that it prefer fonts in the *TEXMF* tree over
+ system fonts if they are installed in both.
+--formats=EXTENSIONS Extensions of the font files to index.
+ Where *EXTENSIONS* is a comma-separated list of
+ supported file extensions (otf, ttf, ttc).
+ If the list is prefixed
+ with a ``+`` sign, the given list is added to
+ the currently active one; ``-`` subtracts.
+ Default: *otf,ttf,ttc*.
+ Examples:
+
+ 1) ``--formats=-ttc,ttf`` would skip
+ TrueType fonts and font collections;
+ 2) ``--formats=otf`` would scan only OpenType
+ files;
+ 3) ``--formats=+afm`` includes binary
+ Postscript files accompanied by an AFM file.
+
+query mode
+-----------------------------------------------------------------------
+--find=NAME Resolve a font name; this looks up <name> in
+ the database and prints the file name it is
+ mapped to.
+ ``--find`` also understands request syntax,
+ i.e. ``--find=file:foo.otf`` checks whether
+ ``foo.otf`` is indexed.
+--fuzzy, -F Show approximate matches to the file name if
+ the lookup was unsuccessful (requires
+ ``--find``).
+
+--info, -i Display basic information to a resolved font
+ file (requires ``--find``).
+--inspect, -I Display detailed information by loading the
+ font and analyzing the font table; very slow!
+ For the meaning of the returned fields see
+ the LuaTeX documentation.
+ (requires ``--find``).
+
+--list=CRITERION Show entries, where *CRITERION* is one of the
+ following:
+
+ 1) the character ``*``, selecting all entries;
+ 2) a field of a database entry, for instance
+ *version* or *format**, according to which
+ the output will be sorted.
+ Information in an unstripped database (see
+ the option ``--no-strip`` above) is nested:
+ Subfields of a record can be addressed using
+ the ``->`` separator, e. g.
+ ``file->location``, ``style->units_per_em``,
+ or
+ ``names->sanitized->english->prefmodifiers``.
+ NB: shell syntax requires that arguments
+ containing ``->`` be properly quoted!
+ 3) an expression of the form ``field:value`` to
+ limit the output to entries whose ``field``
+ matches ``value``.
+
+ For example, in order to output file names and
+ corresponding versions, sorted by the font
+ format::
+
+ ./luaotfload-tool.lua --list="format" --fields="file->base,version"
+
+ This prints::
+
+ otf latinmodern-math.otf Version 1.958
+ otf lmromancaps10-oblique.otf 2.004
+ otf lmmono8-regular.otf 2.004
+ otf lmmonoproplt10-bold.otf 2.004
+ otf lmsans10-oblique.otf 2.004
+ otf lmromanslant8-regular.otf 2.004
+ otf lmroman12-italic.otf 2.004
+ otf lmsansdemicond10-oblique.otf 2.004
+ ...
+
+--fields=FIELDS Comma-separated list of fields that should be
+ printed.
+ Information in an unstripped database (see the
+ option ``--no-strip`` above) is nested:
+ Subfields of a record can be addressed using
+ the ``->`` separator, e. g.
+ ``file->location``, ``style->units_per_em``,
+ or ``names->sanitized->english->subfamily``.
+ The default is plainname,version*.
+ (Only meaningful with ``--list``.)
+
+font and lookup caches
+-----------------------------------------------------------------------
+--flush-lookups Clear font name lookup cache (experimental).
+
+--cache=DIRECTIVE Cache control, where *DIRECTIVE* is one of the
+ following:
+
+ 1) ``purge`` -> delete Lua files from cache;
+ 2) ``erase`` -> delete Lua and Luc files from
+ cache;
+ 3) ``show`` -> print stats.
+
+debugging methods
+-----------------------------------------------------------------------
+--show-blacklist, -b Show blacklisted files (not directories).
+--dry-run, -D Don’t load fonts when updating the database;
+ scan directories only.
+ (For debugging file system related issues.)
+--no-strip Do not strip redundant information after
+ building the database. Warning: this will
+ inflate the index to about two to three times
+ the normal size.
+--max-fonts=N Process at most *N* font files, including fonts
+ already indexed in the count.
+--bisect=DIRECTIVE Bisection of the font database.
+ This mode is intended as assistance in
+ debugging the Luatex engine, especially when
+ tracking memleaks or buggy fonts.
+
+ *DIRECTIVE* can be one of the following:
+
+ 1) ``run`` -> Make ``luaotfload-tool`` respect
+ the bisection progress when running.
+ Combined with ``--update`` and possibly
+ ``--force`` this will only process the files
+ from the start up until the pivot and ignore
+ the rest.
+ 2) ``start`` -> Start bisection: create a
+ bisection state file and initialize the low,
+ high, and pivot indices.
+ 3) ``stop`` -> Terminate the current bisection
+ session by deleting the state file.
+ 4) ``good`` | ``bad`` -> Mark the section
+ processed last as “good” or “bad”,
+ respectively. The next bisection step will
+ continue with the bad section.
+ 5) ``status`` -> Print status information about
+ the current bisection session. Hint: Use
+ with higher verbosity settings for more
+ output.
+
+ A bisection session is initiated by issuing the
+ ``start`` directive. This sets the pivot to the
+ middle of the list of available font files.
+ Now run *luaotfload-tool* with the ``--update``
+ flag set as well as ``--bisect=run``: only the
+ fonts up to the pivot will be considered. If
+ that task exhibited the issue you are tracking,
+ then tell Luaotfload using ``--bisect=bad``.
+ The next step of ``--bisect=run`` will continue
+ bisection with the part of the files below the
+ pivot.
+ Likewise, issue ``--bisect=good`` in order to
+ continue with the fonts above the pivot,
+ assuming the tested part of the list did not
+ trigger the bug.
+
+ Once the culprit font is tracked down, ``good``
+ or ``bad`` will have no effect anymore. ``run``
+ will always end up processing the single font
+ file that was left.
+ Use ``--bisect=stop`` to clear the bisection
+ state.
+
+miscellaneous
+-----------------------------------------------------------------------
+--verbose=N, -v Set verbosity level to *n* or the number of
+ repetitions of ``-v``.
+--quiet No verbose output (log level set to zero).
+--log=CHANNEL Redirect log output (for database
+ troubleshooting), where *CHANNEL* can be
+
+ 1) ``stdout`` -> all output will be
+ dumped to the terminal (default); or
+ 2) ``file`` -> write to a file to the temporary
+ directory (the name will be chosen
+ automatically.
+
+--version, -V Show version numbers of components as well as
+ some basic information and exit.
+--help, -h Show help message and exit.
+
+--diagnose=CHECK Run the diagnostic procedure *CHECK*. Available
+ procedures are:
+
+ 1) ``files`` -> check *Luaotfload* files for
+ modifications;
+ 2) ``permissions`` -> check permissions of
+ cache directories and files;
+ 3) ``environment`` -> print relevant
+ environment and kpse variables;
+ 4) ``repository`` -> check the git repository
+ for new releases,
+ 5) ``index`` -> check database, display
+ information about it.
+
+ Procedures can be chained by concatenating with
+ commas, e.g. ``--diagnose=files,permissions``.
+ Specify ``thorough`` to run all checks.
+
+--conf=FILE Read the configuration from *FILE*. See
+ **luaotfload.conf**\(%) for documentation
+ concerning the format and available options.
+--dumpconf Print the currently active configuration; the
+ output can be saved to a file and used for
+ bootstrapping a custom configuration files.
+
+FILES
+=======================================================================
+
+The font name database is usually located in the directory
+``texmf-var/luatex-cache/generic/names/`` (``$TEXMFCACHE`` as set in
+``texmf.cnf``) of your *TeX Live* distribution as a zlib-compressed
+file ``luaotfload-names.lua.gz``.
+The experimental lookup cache will be created as
+``luaotfload-lookup-cache.lua`` in the same directory.
+These Lua tables are not used directly by Luaotfload, though.
+Instead, they are compiled to Lua bytecode which is written to
+corresponding files with the extension ``.luc`` in the same directory.
+When modifying the files by hand keep in mind that only if the bytecode
+files are missing will Luaotfload use the plain version instead.
+Both kinds of files are safe to delete, at the cost of regenerating
+them with the next run of *LuaTeX*.
+
+SEE ALSO
+=======================================================================
+
+**luaotfload.conf**\(5), **luatex**\(1), **lua**\(1)
+
+* ``texdoc luaotfload`` to display the manual for the *Luaotfload*
+ package
+* Luaotfload development `<https://github.com/lualatex/luaotfload>`_
+* LuaLaTeX mailing list `<http://tug.org/pipermail/lualatex-dev/>`_
+* LuaTeX `<http://luatex.org/>`_
+* ConTeXt `<http://wiki.contextgarden.net>`_
+* Luaotfload on CTAN `<http://ctan.org/pkg/luaotfload>`_
+
+BUGS
+=======================================================================
+
+Tons, probably.
+
+AUTHORS
+=======================================================================
+
+*Luaotfload* was developed by the LuaLaTeX dev team
+(`<https://github.com/lualatex/>`__). It is currently maintained by Ulrike Fischer
+and Marcel Krüger at `<https://github.com/u-fischer/luaotfload>`__
+The fontloader code is provided by Hans Hagen of Pragma ADE, Hasselt
+NL (`<http://pragma-ade.com/>`__).
+
+This manual page was written by Philipp Gesang <phg at phi-gamma.net>.
+
Added: trunk/Master/texmf-dist/doc/luatex/luaotfload/luaotfload-tool.tex
===================================================================
--- trunk/Master/texmf-dist/doc/luatex/luaotfload/luaotfload-tool.tex (rev 0)
+++ trunk/Master/texmf-dist/doc/luatex/luaotfload/luaotfload-tool.tex 2018-09-26 20:50:34 UTC (rev 48771)
@@ -0,0 +1,517 @@
+\documentclass[a4paper]{article}
+% generated by Docutils <http://docutils.sourceforge.net/>
+% rubber: set program xelatex
+\usepackage{fontspec}
+% \defaultfontfeatures{Scale=MatchLowercase}
+% straight double quotes (defined T1 but missing in TU):
+\ifdefined \UnicodeEncodingName
+ \DeclareTextCommand{\textquotedbl}{\UnicodeEncodingName}{%
+ {\addfontfeatures{RawFeature=-tlig,Mapping=}\char34}}%
+\fi
+\usepackage{ifthen}
+\usepackage{alltt}
+\setcounter{secnumdepth}{0}
+\usepackage{tabularx}
+
+%%% Custom LaTeX preamble
+% Linux Libertine (free, wide coverage, not only for Linux)
+\setmainfont{Linux Libertine O}
+\setsansfont{Linux Biolinum O}
+\setmonofont[HyphenChar=None,Scale=MatchLowercase]{DejaVu Sans Mono}
+
+%%% User specified packages and stylesheets
+
+%%% Fallback definitions for Docutils-specific commands
+
+% providelength (provide a length variable and set default, if it is new)
+\providecommand*{\DUprovidelength}[2]{
+ \ifthenelse{\isundefined{#1}}{\newlength{#1}\setlength{#1}{#2}}{}
+}
+
+% docinfo (width of docinfo table)
+\DUprovidelength{\DUdocinfowidth}{0.9\linewidth}
+
+% subtitle (in document title)
+\providecommand*{\DUdocumentsubtitle}[1]{{\large #1}}
+
+% optionlist environment
+\providecommand*{\DUoptionlistlabel}[1]{\bf #1 \hfill}
+\DUprovidelength{\DUoptionlistindent}{3cm}
+\ifthenelse{\isundefined{\DUoptionlist}}{
+ \newenvironment{DUoptionlist}{%
+ \list{}{\setlength{\labelwidth}{\DUoptionlistindent}
+ \setlength{\rightmargin}{1cm}
+ \setlength{\leftmargin}{\rightmargin}
+ \addtolength{\leftmargin}{\labelwidth}
+ \addtolength{\leftmargin}{\labelsep}
+ \renewcommand{\makelabel}{\DUoptionlistlabel}}
+ }
+ {\endlist}
+}{}
+% hyperlinks:
+\ifthenelse{\isundefined{\hypersetup}}{
+ \usepackage[colorlinks=true,linkcolor=blue,urlcolor=blue]{hyperref}
+ \usepackage{bookmark}
+ \urlstyle{same} % normal text font (alternatives: tt, rm, sf)
+}{}
+\hypersetup{
+ pdftitle={luaotfload-tool},
+}
+
+\title{luaotfload-tool%
+ \label{luaotfload-tool}%
+ \\ % subtitle%
+ \DUdocumentsubtitle{generate and query the Luaotfload font names database}%
+ \label{generate-and-query-the-luaotfload-font-names-database}}
+\author{}
+\date{}
+
+%%% Body
+\begin{document}
+\maketitle
+
+% Docinfo
+\begin{center}
+\begin{tabularx}{\DUdocinfowidth}{lX}
+\textbf{Date}: &
+ 2018-09-21 \\
+\textbf{Copyright}: &
+ GPL v2.0 \\
+\textbf{Version}: &
+ 2.9 \\
+\textbf{Manual section}: &
+1
+\\
+\textbf{Manual group}: &
+text processing
+\\
+\end{tabularx}
+\end{center}
+
+
+\section{SYNOPSIS%
+ \label{synopsis}%
+}
+
+\textbf{luaotfload-tool} {[} -bcDfFiIlLnpqRSuvVhw {]}
+
+\begin{description}
+\item[{\textbf{luaotfload-tool} --update {[} --force {]} {[} --quiet {]} {[} --verbose {]}}] \leavevmode
+{[} --prefer-texmf {]} {[} --dry-run {]}
+{[} --formats={[}+|-{]}EXTENSIONS {]}
+{[} --no-compress {]} {[} --no-strip {]}
+{[} --local {]} {[} --max-fonts=N {]}
+
+\item[{\textbf{luaotfload-tool} --find=FONTNAME {[} --fuzzy {]} {[} --info {]} {[} --inspect {]}}] \leavevmode
+{[} --no-reload {]}
+
+\end{description}
+
+\textbf{luaotfload-tool} --flush-lookups
+
+\textbf{luaotfload-tool} --cache=DIRECTIVE
+
+\textbf{luaotfload-tool} --list=CRITERION{[}:VALUE{]} {[} --fields=F1,F2,...,Fn {]}
+
+\textbf{luaotfload-tool} --bisect=DIRECTIVE
+
+\textbf{luaotfload-tool} --help
+
+\textbf{luaotfload-tool} --version
+
+\textbf{luaotfload-tool} --show-blacklist
+
+\textbf{luaotfload-tool} --diagnose=CHECK
+
+\textbf{luaotfload-tool} --conf=FILE --dumpconf
+
+
+\section{DESCRIPTION%
+ \label{description}%
+}
+
+luaotfload-tool accesses the font names database that is required by
+the \emph{Luaotfload} package. There are two general modes: \textbf{update} and
+\textbf{query}.
+
+\begin{itemize}
+\item \textbf{update}: update the database or rebuild it entirely;
+
+\item \textbf{query}: resolve a font name or display close matches.
+\end{itemize}
+
+
+\section{OPTIONS%
+ \label{options}%
+}
+
+
+\subsection{update mode%
+ \label{update-mode}%
+}
+
+\begin{DUoptionlist}
+\item[--update, -u] Update the database; indexes new fonts.
+
+\item[--force, -f] Force rebuilding of the database; re-indexes
+all fonts.
+
+\item[--local, -L] Include font files in \texttt{\$PWD}. This option
+will cause large parts of the database to be
+rebuilt. Thus it is quite inefficient.
+Additionally, if local font files are found,
+the database is prevented from being saved
+to disk, so the local fonts need to be parsed
+with every invocation of \texttt{luaotfload-tool}.
+
+\item[--no-reload, -n] Suppress auto-updates to the database (e.g.
+when \texttt{--find} is passed an unknown name).
+
+\item[--no-compress, -c] Do not filter the plain text version of the
+font index through gzip. Useful for debugging
+if your editor is built without zlib.
+
+\item[--prefer-texmf, -p] Organize the file name database in a way so
+that it prefer fonts in the \emph{TEXMF} tree over
+system fonts if they are installed in both.
+
+\item[--formats=EXTENSIONS] Extensions of the font files to index.
+Where \emph{EXTENSIONS} is a comma-separated list of
+supported file extensions (otf, ttf, ttc).
+If the list is prefixed
+with a \texttt{+} sign, the given list is added to
+the currently active one; \texttt{-} subtracts.
+Default: \emph{otf,ttf,ttc}.
+Examples:
+
+\begin{enumerate}
+\renewcommand{\labelenumi}{\arabic{enumi})}
+\item \texttt{--formats=-ttc,ttf} would skip
+TrueType fonts and font collections;
+
+\item \texttt{--formats=otf} would scan only OpenType
+files;
+
+\item \texttt{--formats=+afm} includes binary
+Postscript files accompanied by an AFM file.
+\end{enumerate}
+\end{DUoptionlist}
+
+
+\subsection{query mode%
+ \label{query-mode}%
+}
+
+\begin{DUoptionlist}
+\item[--find=NAME] Resolve a font name; this looks up <name> in
+the database and prints the file name it is
+mapped to.
+\texttt{--find} also understands request syntax,
+i.e. \texttt{--find=file:foo.otf} checks whether
+\texttt{foo.otf} is indexed.
+
+\item[--fuzzy, -F] Show approximate matches to the file name if
+the lookup was unsuccessful (requires
+\texttt{--find}).
+
+\item[--info, -i] Display basic information to a resolved font
+file (requires \texttt{--find}).
+
+\item[--inspect, -I] Display detailed information by loading the
+font and analyzing the font table; very slow!
+For the meaning of the returned fields see
+the LuaTeX documentation.
+(requires \texttt{--find}).
+
+\item[--list=CRITERION] Show entries, where \emph{CRITERION} is one of the
+following:
+
+\begin{enumerate}
+\renewcommand{\labelenumi}{\arabic{enumi})}
+\item the character \texttt{*}, selecting all entries;
+
+\item a field of a database entry, for instance
+\emph{version} or \emph{format*}, according to which
+the output will be sorted.
+Information in an unstripped database (see
+the option \texttt{--no-strip} above) is nested:
+Subfields of a record can be addressed using
+the \texttt{->} separator, e. g.
+\texttt{file->location}, \texttt{style->units\_per\_em},
+or
+\texttt{names->sanitized->english->prefmodifiers}.
+NB: shell syntax requires that arguments
+containing \texttt{->} be properly quoted!
+
+\item an expression of the form \texttt{field:value} to
+limit the output to entries whose \texttt{field}
+matches \texttt{value}.
+\end{enumerate}
+
+For example, in order to output file names and
+corresponding versions, sorted by the font
+format:
+
+\begin{quote}
+\begin{alltt}
+./luaotfload-tool.lua --list="format" --fields="file->base,version"
+\end{alltt}
+\end{quote}
+
+This prints:
+
+\begin{quote}
+\begin{alltt}
+otf latinmodern-math.otf Version 1.958
+otf lmromancaps10-oblique.otf 2.004
+otf lmmono8-regular.otf 2.004
+otf lmmonoproplt10-bold.otf 2.004
+otf lmsans10-oblique.otf 2.004
+otf lmromanslant8-regular.otf 2.004
+otf lmroman12-italic.otf 2.004
+otf lmsansdemicond10-oblique.otf 2.004
+...
+\end{alltt}
+\end{quote}
+
+\item[--fields=FIELDS] Comma-separated list of fields that should be
+printed.
+Information in an unstripped database (see the
+option \texttt{--no-strip} above) is nested:
+Subfields of a record can be addressed using
+the \texttt{->} separator, e. g.
+\texttt{file->location}, \texttt{style->units\_per\_em},
+or \texttt{names->sanitized->english->subfamily}.
+The default is plainname,version*.
+(Only meaningful with \texttt{--list}.)
+\end{DUoptionlist}
+
+
+\subsection{font and lookup caches%
+ \label{font-and-lookup-caches}%
+}
+
+\begin{DUoptionlist}
+\item[--flush-lookups] Clear font name lookup cache (experimental).
+
+\item[--cache=DIRECTIVE] Cache control, where \emph{DIRECTIVE} is one of the
+following:
+
+\begin{enumerate}
+\renewcommand{\labelenumi}{\arabic{enumi})}
+\item \texttt{purge} -> delete Lua files from cache;
+
+\item \texttt{erase} -> delete Lua and Luc files from
+cache;
+
+\item \texttt{show} -> print stats.
+\end{enumerate}
+\end{DUoptionlist}
+
+
+\subsection{debugging methods%
+ \label{debugging-methods}%
+}
+
+\begin{DUoptionlist}
+\item[--show-blacklist, -b] Show blacklisted files (not directories).
+
+\item[--dry-run, -D] Don’t load fonts when updating the database;
+scan directories only.
+(For debugging file system related issues.)
+
+\item[--no-strip] Do not strip redundant information after
+building the database. Warning: this will
+inflate the index to about two to three times
+the normal size.
+
+\item[--max-fonts=N] Process at most \emph{N} font files, including fonts
+already indexed in the count.
+
+\item[--bisect=DIRECTIVE] Bisection of the font database.
+This mode is intended as assistance in
+debugging the Luatex engine, especially when
+tracking memleaks or buggy fonts.
+
+\emph{DIRECTIVE} can be one of the following:
+
+\begin{enumerate}
+\renewcommand{\labelenumi}{\arabic{enumi})}
+\item \texttt{run} -> Make \texttt{luaotfload-tool} respect
+the bisection progress when running.
+Combined with \texttt{--update} and possibly
+\texttt{--force} this will only process the files
+from the start up until the pivot and ignore
+the rest.
+
+\item \texttt{start} -> Start bisection: create a
+bisection state file and initialize the low,
+high, and pivot indices.
+
+\item \texttt{stop} -> Terminate the current bisection
+session by deleting the state file.
+
+\item \texttt{good} | \texttt{bad} -> Mark the section
+processed last as “good” or “bad”,
+respectively. The next bisection step will
+continue with the bad section.
+
+\item \texttt{status} -> Print status information about
+the current bisection session. Hint: Use
+with higher verbosity settings for more
+output.
+\end{enumerate}
+
+A bisection session is initiated by issuing the
+\texttt{start} directive. This sets the pivot to the
+middle of the list of available font files.
+Now run \emph{luaotfload-tool} with the \texttt{--update}
+flag set as well as \texttt{--bisect=run}: only the
+fonts up to the pivot will be considered. If
+that task exhibited the issue you are tracking,
+then tell Luaotfload using \texttt{--bisect=bad}.
+The next step of \texttt{--bisect=run} will continue
+bisection with the part of the files below the
+pivot.
+Likewise, issue \texttt{--bisect=good} in order to
+continue with the fonts above the pivot,
+assuming the tested part of the list did not
+trigger the bug.
+
+Once the culprit font is tracked down, \texttt{good}
+or \texttt{bad} will have no effect anymore. \texttt{run}
+will always end up processing the single font
+file that was left.
+Use \texttt{--bisect=stop} to clear the bisection
+state.
+\end{DUoptionlist}
+
+
+\subsection{miscellaneous%
+ \label{miscellaneous}%
+}
+
+\begin{DUoptionlist}
+\item[--verbose=N, -v] Set verbosity level to \emph{n} or the number of
+repetitions of \texttt{-v}.
+
+\item[--quiet] No verbose output (log level set to zero).
+
+\item[--log=CHANNEL] Redirect log output (for database
+troubleshooting), where \emph{CHANNEL} can be
+
+\begin{enumerate}
+\renewcommand{\labelenumi}{\arabic{enumi})}
+\item \texttt{stdout} -> all output will be
+dumped to the terminal (default); or
+
+\item \texttt{file} -> write to a file to the temporary
+directory (the name will be chosen
+automatically.
+\end{enumerate}
+
+\item[--version, -V] Show version numbers of components as well as
+some basic information and exit.
+
+\item[--help, -h] Show help message and exit.
+
+\item[--diagnose=CHECK] Run the diagnostic procedure \emph{CHECK}. Available
+procedures are:
+
+\begin{enumerate}
+\renewcommand{\labelenumi}{\arabic{enumi})}
+\item \texttt{files} -> check \emph{Luaotfload} files for
+modifications;
+
+\item \texttt{permissions} -> check permissions of
+cache directories and files;
+
+\item
+\begin{description}
+\item[{\texttt{environment} -> print relevant}] \leavevmode
+environment and kpse variables;
+
+\end{description}
+
+\item \texttt{repository} -> check the git repository
+for new releases,
+
+\item \texttt{index} -> check database, display
+information about it.
+\end{enumerate}
+
+Procedures can be chained by concatenating with
+commas, e.g. \texttt{--diagnose=files,permissions}.
+Specify \texttt{thorough} to run all checks.
+
+\item[--conf=FILE] Read the configuration from \emph{FILE}. See
+\textbf{luaotfload.conf}(\%) for documentation
+concerning the format and available options.
+
+\item[--dumpconf] Print the currently active configuration; the
+output can be saved to a file and used for
+bootstrapping a custom configuration files.
+\end{DUoptionlist}
+
+
+\section{FILES%
+ \label{files}%
+}
+
+The font name database is usually located in the directory
+\texttt{texmf-var/luatex-cache/generic/names/} (\texttt{\$TEXMFCACHE} as set in
+\texttt{texmf.cnf}) of your \emph{TeX Live} distribution as a zlib-compressed
+file \texttt{luaotfload-names.lua.gz}.
+The experimental lookup cache will be created as
+\texttt{luaotfload-lookup-cache.lua} in the same directory.
+These Lua tables are not used directly by Luaotfload, though.
+Instead, they are compiled to Lua bytecode which is written to
+corresponding files with the extension \texttt{.luc} in the same directory.
+When modifying the files by hand keep in mind that only if the bytecode
+files are missing will Luaotfload use the plain version instead.
+Both kinds of files are safe to delete, at the cost of regenerating
+them with the next run of \emph{LuaTeX}.
+
+
+\section{SEE ALSO%
+ \label{see-also}%
+}
+
+\textbf{luaotfload.conf}(5), \textbf{luatex}(1), \textbf{lua}(1)
+
+\begin{itemize}
+\item \texttt{texdoc luaotfload} to display the manual for the \emph{Luaotfload}
+package
+
+\item Luaotfload development \url{https://github.com/lualatex/luaotfload}
+
+\item LuaLaTeX mailing list \url{http://tug.org/pipermail/lualatex-dev/}
+
+\item LuaTeX \url{http://luatex.org/}
+
+\item ConTeXt \url{http://wiki.contextgarden.net}
+
+\item Luaotfload on CTAN \url{http://ctan.org/pkg/luaotfload}
+\end{itemize}
+
+
+\section{BUGS%
+ \label{bugs}%
+}
+
+Tons, probably.
+
+
+\section{AUTHORS%
+ \label{authors}%
+}
+
+\emph{Luaotfload} was developed by the LuaLaTeX dev team
+(\url{https://github.com/lualatex/}). It is currently maintained by Ulrike Fischer
+and Marcel Krüger at \url{https://github.com/u-fischer/luaotfload}
+The fontloader code is provided by Hans Hagen of Pragma ADE, Hasselt
+NL (\url{http://pragma-ade.com/}).
+
+This manual page was written by Philipp Gesang <\href{mailto:phg at phi-gamma.net}{phg at phi-gamma.net}>.
+
+\end{document}
Property changes on: trunk/Master/texmf-dist/doc/luatex/luaotfload/luaotfload-tool.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/luatex/luaotfload/luaotfload.conf.rst
===================================================================
--- trunk/Master/texmf-dist/doc/luatex/luaotfload/luaotfload.conf.rst (rev 0)
+++ trunk/Master/texmf-dist/doc/luatex/luaotfload/luaotfload.conf.rst 2018-09-26 20:50:34 UTC (rev 48771)
@@ -0,0 +1,409 @@
+=======================================================================
+ luaotfload.conf
+=======================================================================
+
+-----------------------------------------------------------------------
+ Luaotfload configuration file
+-----------------------------------------------------------------------
+
+:Date: 2018-09-21
+:Copyright: GPL v2.0
+:Version: 2.9
+:Manual section: 5
+:Manual group: text processing
+
+SYNOPSIS
+=======================================================================
+
+- **./luaotfload{.conf,rc}**
+- **XDG_CONFIG_HOME/luaotfload/luaotfload{.conf,rc}**
+- **~/.luaotfloadrc**
+
+DESCRIPTION
+=======================================================================
+
+The file ``luaotfload.conf`` contains configuration options for
+*Luaotfload*, a font loading and font management component for LuaTeX.
+
+
+EXAMPLE
+=======================================================================
+
+A small Luaotfload configuration file with few customizations could
+look as follows: ::
+
+ [db]
+ formats = afm,ttf
+ compress = false
+
+ [misc]
+ termwidth = 60
+
+ [run]
+ log-level = 6
+
+This will make Luaotfload ignore all font files except for PostScript
+binary fonts with a matching AFM file, and Truetype fonts. Also, an
+uncompressed index file will be dumped which is going to be much larger
+than the default gzip’ed index. The terminal width
+is truncated to 60 characters which influences the verbose output
+during indexing. Finally, the verbosity is increased greatly: each font
+file being processed will be printed to the stdout on a separate line,
+along with lots of other information.
+
+To observe the difference in behavior, save above snippet to
+``./luaotfload.conf`` and update the font index: ::
+
+ luaotfload-tool --update --force
+
+The current configuration can be written to disk using
+**luaotfload-tool**: ::
+
+ luaotfload-tool --dumpconf > luaotfload.conf
+
+The result can itself be used as a configuration file.
+
+
+SYNTAX
+=======================================================================
+
+The configuration file syntax follows the common INI format. For a more
+detailed description please refer to the section “CONFIGURATION FILE”
+of **git-config**\(1). A brief list of rules is given below:
+
+ * Blank lines and lines starting with a semicolon (``;``) are ignored.
+
+ * A configuration file is partitioned into sections that are declared
+ by specifying the section title in brackets on a separate line: ::
+
+ [some-section]
+ ... section content ...
+
+ * Sections consist of one or more variable assignments of the form
+ ``variable-name = value`` E. g.::
+
+ [foo]
+ bar = baz
+ quux = xyzzy
+ ...
+
+ * Section and variable names may contain only uppercase and lowercase
+ letters as well as dashes (``-``).
+
+
+VARIABLES
+=======================================================================
+
+Variables in belong into a configuration section and their values must
+be of a certain type. Some of them have further constraints. For
+example, the “color callback” must be a string of one of the values
+``post_linebreak_filter``, ``pre_linebreak_filter``, or
+``pre_output_filter``, defined in the section *run* of the
+configuration file.
+
+Currently, the configuration is organized into four sections:
+
+db
+ Options relating to the font index.
+
+misc
+ Options without a clearly defined category.
+
+paths
+ Path and file name settings.
+
+run
+ Options controlling runtime behavior of Luaotfload.
+
+The list of valid variables, the sections they are part of and their
+type is given below. Types represent Lua types that the values must be
+convertible to; they are abbreviated as follows: ``s`` for the *string*
+type, ``n`` for *number*, ``b`` for *boolean*. A value of ``nil`` means
+the variable is unset.
+
+
+Section ``db``
+-----------------------------------------------------------------------
+
++--------------------+--------+---------------------------+
+| variable | type | default |
++--------------------+--------+---------------------------+
+| compress | b | ``true`` |
++--------------------+--------+---------------------------+
+| designsize-dimen | b | ``bp`` |
++--------------------+--------+---------------------------+
+| formats | s | ``"otf,ttf,ttc"`` |
++--------------------+--------+---------------------------+
+| max-fonts | n | ``2^51`` |
++--------------------+--------+---------------------------+
+| scan-local | b | ``false`` |
++--------------------+--------+---------------------------+
+| skip-read | b | ``false`` |
++--------------------+--------+---------------------------+
+| strip | b | ``true`` |
++--------------------+--------+---------------------------+
+| update-live | b | ``true`` |
++--------------------+--------+---------------------------+
+
+The flag ``compress`` determines whether the font index (usually
+``luaotfload-names.lua[.gz]`` will be stored in compressed forms.
+If unset it is equivalent of passing ``--no-compress`` to
+**luaotfload-tool**. Since the file is only created for convenience
+and has no effect on the runtime behavior of Luaotfload, the flag
+should remain set. Most editors come with zlib support anyways.
+
+The setting ``designsize-dimen`` applies when looking up fonts from
+families with design sizes. In Opentype, these are specified as
+“decipoints” where one decipoint equals ten DTP style “big points”.
+When indexing fonts these values are converted to ``sp``. In order to
+treat the values as though they were specified in TeX points or Didot
+points, set ``designsize-dimen`` to ``pt`` or ``dd``.
+
+The list of ``formats`` must be a comma separated sequence of strings
+containing one or more of these elements:
+
+* ``otf`` (OpenType format),
+* ``ttf`` and ``ttc`` (TrueType format),
+* ``afm`` (Adobe Font Metrics),
+
+It corresponds loosely to the ``--formats`` option to
+**luaotfload-tool**. Invalid or duplicate members are ignored; if the
+list does not contain any useful identifiers, the default list
+``"otf,ttf,ttc"`` will be used.
+
+The variable ``max-fonts`` determines after processing how many font
+files the font scanner will terminate the search. This is useful for
+debugging issues with the font index and has the same effect as the
+option ``--max-fonts`` to **luaotfload-tools**.
+
+The ``scan-local`` flag, if set, will incorporate the current working
+directory as a font search location. NB: This will potentially slow
+down document processing because a font index with local fonts will not
+be saved to disk, so these fonts will have to be re-indexed whenever
+the document is built.
+
+The ``skip-read`` flag is only useful for debugging: It makes
+Luaotfload skip reading fonts. The font information for rebuilding the
+index is taken from the presently existing one.
+
+Unsetting the ``strip`` flag prevents Luaotfload from removing data
+from the index that is only useful when processing font files. NB: this
+can increase the size of the index files significantly and has no
+effect on the runtime behavior.
+
+If ``update-live`` is set, Luaotfload will reload the database if it
+cannot find a requested font. Those who prefer to update manually using
+**luaotfload-tool** should unset this flag. This option does not affect
+rebuilds due to version mismatch.
+
+Section ``default-features``
+-----------------------------------------------------------------------
+
+By default Luaotfload enables ``node`` mode and picks the default font
+features that are prescribed in the OpenType standard. This behavior
+may be overridden in the ``default-features`` section. Global defaults
+that will be applied for all scripts can be set via the ``global``
+option, others by the script they are to be applied to. For example,
+a setting of ::
+
+ [default-features]
+ global = mode=base,color=0000FF
+ dflt = smcp,onum
+
+would force *base* mode, tint all fonts blue and activate small
+capitals and text figures globally. Features are specified as a comma
+separated list of variables or variable-value pairs. Variables without
+an explicit value are set to ``true``.
+
+
+Section ``misc``
+-----------------------------------------------------------------------
+
++---------------+--------+-------------------------+
+| variable | type | default |
++---------------+--------+-------------------------+
+| statistics | b | ``false`` |
++---------------+--------+-------------------------+
+| termwidth | n | ``nil`` |
++---------------+--------+-------------------------+
+| version | s | <Luaotfload version> |
++---------------+--------+-------------------------+
+
+With ``statistics`` enabled, extra statistics will be collected during
+index creation and appended to the index file. It may then be queried
+at the Lua end or inspected by reading the file itself.
+
+The value of ``termwidth``, if set, overrides the value retrieved by
+querying the properties of the terminal in which Luatex runs. This is
+useful if the engine runs with ``shell_escape`` disabled and the actual
+terminal dimensions cannot be retrieved.
+
+The value of ``version`` is derived from the version string hard-coded
+in the Luaotfload source. Override at your own risk.
+
+
+Section ``paths``
+-----------------------------------------------------------------------
+
++------------------+--------+------------------------------------+
+| variable | type | default |
++------------------+--------+------------------------------------+
+| cache-dir | s | ``"fonts"`` |
++------------------+--------+------------------------------------+
+| names-dir | s | ``"names"`` |
++------------------+--------+------------------------------------+
+| index-file | s | ``"luaotfload-names.lua"`` |
++------------------+--------+------------------------------------+
+| lookups-file | s | ``"luaotfload-lookup-cache.lua"`` |
++------------------+--------+------------------------------------+
+
+The paths ``cache-dir`` and ``names-dir`` determine the subdirectory
+inside the Luaotfload subtree of the ``luatex-cache`` directory where
+the font cache and the font index will be stored, respectively.
+
+Inside the index directory, the names of the index file and the font
+lookup cache will be derived from the respective values of
+``index-file`` and ``lookups-file``. This is the filename base for the
+bytecode compiled version as well as -- for the index -- the gzipped
+version.
+
+
+Section ``run``
+-----------------------------------------------------------------------
+
++------------------+--------+------------------------------+
+| variable | type | default |
++------------------+--------+------------------------------+
+| anon-sequence | s | ``"tex,path,name"`` |
++------------------+--------+------------------------------+
+| color-callback | s | ``"post_linebreak_filter"`` |
++------------------+--------+------------------------------+
+| definer | s | ``"patch"`` |
++------------------+--------+------------------------------+
+| log-level | n | ``0`` |
++------------------+--------+------------------------------+
+| resolver | s | ``"cached"`` |
++------------------+--------+------------------------------+
+| fontloader | s | ``"default"`` |
++------------------+--------+------------------------------+
+
+Unqualified font lookups are treated with the flexible “anonymous”
+mechanism. This involves a chain of lookups applied successively until
+the first one yields a match. By default, the lookup will first search
+for TFM fonts using the Kpathsea library. If this wasn’t successful, an
+attempt is made at interpreting the request as an absolute path (like
+the ``[/path/to/font/foo.ttf]`` syntax) or a file name
+(``file:foo.ttf``). Finally, the request is interpreted as a font name
+and retrieved from the index (``name:Foo Regular``). This behavior can
+be configured by specifying a list as the value to ``anon-sequence``.
+Available items are ``tex``, ``path``, ``name`` -- representing the
+lookups described above, respectively --, and ``file`` for searching a
+filename but not an absolute path. Also, ``my`` lookups are valid
+values but they should only be used from within TeX documents, because
+there is no means of customizing a ``my`` lookups on the command line.
+
+The ``color-callback`` option determines the stage at which fonts that
+defined with a ``color=xxyyzz`` feature will be colorized. By default
+this happens in a ``post_linebreak_filter`` but alternatively the
+``pre_linebreak_filter`` or ``pre_output_filter`` may be chosen, which
+is faster but might produce inconsistent output. The
+``pre_output_filter`` used to be the default in the 1.x series of
+Luaotfload, whilst later versions up to and including 2.5 hooked into
+the ``pre_linebreak_filter`` which naturally didn’t affect any glyphs
+inserting during hyphenation. Both are kept around as options to
+restore the previous behavior if necessary.
+
+The ``definer`` allows for switching the ``define_font`` callback.
+Apart from the default ``patch`` one may also choose the ``generic``
+one that comes with the vanilla fontloader. Beware that this might
+break tools like Fontspec that rely on the ``patch_font`` callback
+provided by Luaotfload to perform important corrections on font data.
+
+The fontloader backend can be selected by setting the value of
+``fontloader``. The most important choices are ``default``, which will
+load the dedicated Luaotfload fontloader, and ``reference``, the
+upstream package as shipped with Luaotfload. Other than those, a file
+name accessible via kpathsea can be specified.
+
+Alternatively, the individual files that constitute the fontloader can
+be loaded directly. While less efficient, this greatly aids debugging
+since error messages will reference the actual line numbers of the
+source files and explanatory comments are not stripped. Currently,
+three distinct loading strategies are available: ``unpackaged`` will
+load the batch that is part of Luaotfload. These contain the identical
+source code that the reference fontloader has been compiled from.
+Another option, ``context`` will attempt to load the same files by
+their names in the Context format from the search path. Consequently
+this option allows to use the version of Context that comes with the
+TeX distribution. Distros tend to prefer the stable version (“current”
+in Context jargon) of those files so certain bugs encountered in the
+more bleeding edge Luaotfload can be avoided this way. A third option
+is to use ``context`` with a colon to specify a directory prefix where
+the *TEXMF* is located that the files should be loaded from, e. g.
+``context:~/context/tex/texmf-context``. This can be used when
+referencing another distribution like the Context minimals that is
+installed under a different path not indexed by kpathsea.
+
+The value of ``log-level`` sets the default verbosity of messages
+printed by Luaotfload. Only messages defined with a verbosity of less
+than or equal to the supplied value will be output on the terminal.
+At a log level of five Luaotfload can be very noisy. Also, printing too
+many messages will slow down the interpreter due to line buffering
+being disabled (see **setbuf**\(3)).
+
+The ``resolver`` setting allows choosing the font name resolution
+function: With the default value ``cached`` Luaotfload saves the result
+of a successful font name request to a cache file to speed up
+subsequent lookups. The alternative, ``normal`` circumvents the cache
+and resolves every request individually. (Since to the restructuring of
+the font name index in Luaotfload 2.4 the performance difference
+between the cached and uncached lookups should be marginal.)
+
+
+FILES
+=======================================================================
+
+Luaotfload only processes the first configuration file it encounters at
+one of the search locations. The file name may be either
+``luaotfload.conf`` or ``luaotfloadrc``, except for the dotfile in the
+user’s home directory which is expected at ``~/.luaotfloadrc``.
+
+Configuration files are located following a series of steps. The search
+terminates as soon as a suitable file is encountered. The sequence of
+locations that Luaotfload looks at is
+
+i. The current working directory of the LuaTeX process.
+ii. The subdirectory ``luaotfload/`` inside the XDG configuration
+ tree, e. g. ``/home/oenothea/config/luaotfload/``.
+iii. The dotfile.
+iv. The *TEXMF* (using kpathsea).
+
+
+SEE ALSO
+=======================================================================
+
+**luaotfload-tool**\(1), **luatex**\(1), **lua**\(1)
+
+* ``texdoc luaotfload`` to display the PDF manual for the *Luaotfload*
+ package
+* Luaotfload development `<https://github.com/u-fischer/luaotfload>`_
+* LuaLaTeX mailing list `<http://tug.org/pipermail/lualatex-dev/>`_
+* LuaTeX `<http://luatex.org/>`_
+* Luaotfload on CTAN `<http://ctan.org/pkg/luaotfload>`_
+
+
+REFERENCES
+=======================================================================
+
+* The XDG base specification
+ `<http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html>`_.
+
+AUTHORS
+=======================================================================
+
+*Luaotfload* was developed by the LuaLaTeX dev team
+(`<https://github.com/lualatex/>`_). It is currently maintained by Ulrike Fischer
+and Marcel Krüger at `<https://github.com/u-fischer/luaotfload>`_
+
+This manual page was written by Philipp Gesang <phg at phi-gamma.net>.
+
Deleted: trunk/Master/texmf-dist/doc/luatex/luaotfload/luaotfload.pdf
===================================================================
(Binary files differ)
Deleted: trunk/Master/texmf-dist/doc/luatex/luaotfload/valgrind-kpse-suppression.sup
===================================================================
--- trunk/Master/texmf-dist/doc/luatex/luaotfload/valgrind-kpse-suppression.sup 2018-09-26 20:49:48 UTC (rev 48770)
+++ trunk/Master/texmf-dist/doc/luatex/luaotfload/valgrind-kpse-suppression.sup 2018-09-26 20:50:34 UTC (rev 48771)
@@ -1,140 +0,0 @@
-{
- kpathsea-garbage-1
- Memcheck:Leak
- match-leak-kinds: all
- ...
- fun:kpathsea_cnf_get
-}
-
-{
- kpathsea-garbage-2
- Memcheck:Leak
- match-leak-kinds: all
- ...
- fun:kpse_program_basename
-}
-
-
-{
- kpathsea-garbage-3
- Memcheck:Leak
- match-leak-kinds: all
- ...
- fun:kpse_find_file
-}
-
-
-{
- kpathsea-garbage-4
- Memcheck:Leak
- match-leak-kinds: all
- ...
- fun:find_file
-}
-
-{
- kpathsea-garbage-5
- Memcheck:Leak
- match-leak-kinds: all
- ...
- fun:lua_kpse_lookup
-}
-
-{
- kpathsea-garbage-6
- Memcheck:Leak
- match-leak-kinds: all
- ...
- fun:find_file
-}
-
-
-{
- kpathsea-garbage-7
- Memcheck:Leak
- match-leak-kinds: all
- ...
- fun:expand_path
-}
-
-{
- kpathsea-garbage-8
- Memcheck:Leak
- match-leak-kinds: all
- ...
- fun:do_lua_kpathsea_lookup
-}
-
-
-{
- kpathsea-garbage-9
- Memcheck:Leak
- match-leak-kinds: all
- ...
- fun:kpathsea_find_file
-}
-
-
-{
- kpathsea-garbage-10
- Memcheck:Leak
- match-leak-kinds: all
- ...
- fun:kpathsea_init_db
-}
-
-
-{
- kpathsea-garbage-11
- Memcheck:Leak
- match-leak-kinds: all
- ...
- fun:kpathsea_find_file_generic
-}
-
-
-{
- kpathsea-garbage-12
- Memcheck:Leak
- match-leak-kinds: all
- ...
- fun:expand_var
-}
-
-
-{
- kpathsea-garbage-13
- Memcheck:Leak
- match-leak-kinds: all
- ...
- fun:init_path
-}
-
-
-{
- kpathsea-garbage-14
- Memcheck:Leak
- match-leak-kinds: all
- ...
- fun:kpse_in_name_ok
-}
-
-
-{
- kpathsea-garbage-15
- Memcheck:Leak
- match-leak-kinds: all
- ...
- fun:kpathsea_var_value
-}
-
-
-{
- kpathsea-garbage-16
- Memcheck:Leak
- match-leak-kinds: all
- ...
- fun:kpse_set_program_name
-}
-
-
Modified: trunk/Master/texmf-dist/doc/man/man1/luaotfload-tool.1
===================================================================
--- trunk/Master/texmf-dist/doc/man/man1/luaotfload-tool.1 2018-09-26 20:49:48 UTC (rev 48770)
+++ trunk/Master/texmf-dist/doc/man/man1/luaotfload-tool.1 2018-09-26 20:50:34 UTC (rev 48771)
@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
-.TH LUAOTFLOAD-TOOL 1 "2017-01-28" "2.8" "text processing"
+.TH LUAOTFLOAD-TOOL 1 "2018-09-21" "2.9" "text processing"
.SH NAME
luaotfload-tool \- generate and query the Luaotfload font names database
.
@@ -429,8 +429,9 @@
Tons, probably.
.SH AUTHORS
.sp
-\fILuaotfload\fP is maintained by the LuaLaTeX dev team
-(\fI\%https://github.com/lualatex/\fP).
+\fILuaotfload\fP was developed by the LuaLaTeX dev team
+(\fI\%https://github.com/lualatex/\fP). It is currently maintained by Ulrike Fischer
+and Marcel Krüger at \fI\%https://github.com/u\-fischer/luaotfload\fP
The fontloader code is provided by Hans Hagen of Pragma ADE, Hasselt
NL (\fI\%http://pragma\-ade.com/\fP).
.sp
Modified: trunk/Master/texmf-dist/doc/man/man1/luaotfload-tool.man1.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/doc/man/man5/luaotfload.conf.5
===================================================================
--- trunk/Master/texmf-dist/doc/man/man5/luaotfload.conf.5 2018-09-26 20:49:48 UTC (rev 48770)
+++ trunk/Master/texmf-dist/doc/man/man5/luaotfload.conf.5 2018-09-26 20:50:34 UTC (rev 48771)
@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
-.TH LUAOTFLOAD.CONF 5 "2017-01-29" "2.8" "text processing"
+.TH LUAOTFLOAD.CONF 5 "2018-09-21" "2.9" "text processing"
.SH NAME
luaotfload.conf \- Luaotfload configuration file
.
@@ -265,8 +265,11 @@
should remain set. Most editors come with zlib support anyways.
.sp
The setting \fBdesignsize\-dimen\fP applies when looking up fonts from
-families with design sizes. The default of DTP\-style “big points”
-can be changed for \fBpt\fP or even \fBdd\fP\&.
+families with design sizes. In Opentype, these are specified as
+“decipoints” where one decipoint equals ten DTP style “big points”.
+When indexing fonts these values are converted to \fBsp\fP\&. In order to
+treat the values as though they were specified in TeX points or Didot
+points, set \fBdesignsize\-dimen\fP to \fBpt\fP or \fBdd\fP\&.
.sp
The list of \fBformats\fP must be a comma separated sequence of strings
containing one or more of these elements:
@@ -602,7 +605,7 @@
\fBtexdoc luaotfload\fP to display the PDF manual for the \fILuaotfload\fP
package
.IP \(bu 2
-Luaotfload development \fI\%https://github.com/lualatex/luaotfload\fP
+Luaotfload development \fI\%https://github.com/u\-fischer/luaotfload\fP
.IP \(bu 2
LuaLaTeX mailing list \fI\%http://tug.org/pipermail/lualatex\-dev/\fP
.IP \(bu 2
@@ -618,8 +621,9 @@
.UNINDENT
.SH AUTHORS
.sp
-\fILuaotfload\fP is maintained by the LuaLaTeX dev team
-(\fI\%https://github.com/lualatex/\fP).
+\fILuaotfload\fP was developed by the LuaLaTeX dev team
+(\fI\%https://github.com/lualatex/\fP). It is currently maintained by Ulrike Fischer
+and Marcel Krüger at \fI\%https://github.com/u\-fischer/luaotfload\fP
.sp
This manual page was written by Philipp Gesang <\fI\%phg at phi\-gamma.net\fP>.
.SH COPYRIGHT
Modified: trunk/Master/texmf-dist/doc/man/man5/luaotfload.conf.man5.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/scripts/luaotfload/luaotfload-tool.lua
===================================================================
--- trunk/Master/texmf-dist/scripts/luaotfload/luaotfload-tool.lua 2018-09-26 20:49:48 UTC (rev 48770)
+++ trunk/Master/texmf-dist/scripts/luaotfload/luaotfload-tool.lua 2018-09-26 20:50:34 UTC (rev 48771)
@@ -2,13 +2,13 @@
-----------------------------------------------------------------------
-- FILE: luaotfload-tool.lua
-- DESCRIPTION: database functionality
--- REQUIREMENTS: luaotfload 2.8
+-- REQUIREMENTS: luaotfload 2.9
-- AUTHOR: Khaled Hosny, Élie Roux, Philipp Gesang
-- LICENSE: GPL v2.0
-----------------------------------------------------------------------
luaotfload = luaotfload or { }
-local version = "2.8"
+local version = "2.9"
luaotfload.version = version
luaotfload.min_luatex_version = { 0, 95, 0 }
luaotfload.self = "luaotfload-tool"
Deleted: trunk/Master/texmf-dist/scripts/luaotfload/mkcharacters
===================================================================
--- trunk/Master/texmf-dist/scripts/luaotfload/mkcharacters 2018-09-26 20:49:48 UTC (rev 48770)
+++ trunk/Master/texmf-dist/scripts/luaotfload/mkcharacters 2018-09-26 20:50:34 UTC (rev 48771)
@@ -1,226 +0,0 @@
-#!/usr/bin/env texlua
------------------------------------------------------------------------
--- FILE: mkcharacters.lua
--- USAGE: ./mkcharacters.lua
--- DESCRIPTION: import parts of char-def.lua
--- REQUIREMENTS: lua, ConTeXt, the lualibs package
--- AUTHOR: Philipp Gesang (Phg), <phg at phi-gamma.net>
------------------------------------------------------------------------
--- We create a stripped-down version of char-def.lua, suitable for use
--- with the generic font loader.
------------------------------------------------------------------------
-
------------------------------------------------------------------------
--- config
------------------------------------------------------------------------
-local mkivpath = arg[1]
-local charfile = arg[2] or "./build/luaotfload-characters.lua"
-
---- for every code point char-def.lua provides a set of fields. they
---- are:
----
---- * adobename
---- * category
---- * cjkwd
---- * comment
---- * contextname
---- * description
---- * direction
---- * lccode
---- * linebreak
---- * mathclass
---- * mathextensible
---- * mathfiller
---- * mathname
---- * mathspec
---- * mathstretch
---- * mathsymbol
---- * mirror
---- * shcode
---- * specials
---- * textclass
---- * uccode
---- * unicodeslot
---- * variants
-
-local import = {
- "direction", "mirror", --> πολυγλωσσία/uax9
- "category", --> https://gist.github.com/phi-gamma/5812290
- "textclass", --> https://gist.github.com/phi-gamma/6488187
-}
-
------------------------------------------------------------------------
--- includes
------------------------------------------------------------------------
-
-kpse.set_program_name"luatex"
-
-require "lualibs"
-
-local chardef
-local charini
-
-if not mkivpath then
- mkivpath = assert (kpse.expand_path
- "~/context/tex/texmf-context/tex/context/base/mkiv/",
- "Failed to locate ConTeXt.")
-end
-
-chardef = mkivpath .. "/char-def.lua"
-charini = mkivpath .. "/char-ini.lua"
-
---- we could grab the files from contextgarden but as Context is part
---- of TL it’s not worth bothering
-if not (chardef and lfs.isfile(chardef)) then
- chardef = assert(kpse.find_file("char-def.lua", "lua"),
- "Failed to locate file char-def.lua from ConTeXt.")
-end
-
-if not (charini and lfs.isfile(charini)) then
- charini = assert(kpse.find_file("char-ini.lua", "lua"),
- "Failed to locate file char-ini.lua from ConTeXt.")
-end
-
-io.write(string.format("extracting data from char-def.lua at %s\n",
- chardef))
-io.write(string.format("loading code from char-ini.lua at %s\n",
- charini))
-
------------------------------------------------------------------------
--- functionality
------------------------------------------------------------------------
-
-local get_characters = function ( )
- local data
- local inchan = io.open(chardef, "r")
- if not inchan then
- io.write("Could not open file for reading: "..chardef.."\n.")
- goto fail
- end
- data = inchan:read "*all"
- inchan:close()
- data = loadstring(data)
- if data then
- data() --> characters.data
- data = nil
- collectgarbage "collect"
- if characters.data and next(characters.data) then
- return characters.data
- end
- io.write "Character table empty.\n"
- goto fail
- end
- io.write(chardef .. " is not a valid Lua file.\n")
- ::fail::
- io.write "Emergency exit.\n"
- os.exit(1)
-end
-
-local extract_fields_indeed
-extract_fields_indeed = function (data, acc, lastidx)
- local idx, char = next(data, lastidx)
- if idx then
- local imported = { }
- for i=1, #import do
- local field = import[i]
- imported[field] = char[field]
- end
- acc[idx] = imported
- return extract_fields_indeed(data, acc, idx)
- end
- return acc
-end
-
-local extract_fields = function (data)
- return extract_fields_indeed(data, {}, nil)
-end
-
---[[ extract_classifiers : from luatex-basics-prepare.tex ]]
-
-local extract_classifiers = function (chardata)
- dofile (charini)
- local s_init = 1 local s_rphf = 7
- local s_medi = 2 local s_half = 8
- local s_fina = 3 local s_pref = 9
- local s_isol = 4 local s_blwf = 10
- local s_mark = 5 local s_pstf = 11
- local s_rest = 6
-
- local mappers = {
- l = s_init, -- left
- d = s_medi, -- double
- c = s_medi, -- joiner
- r = s_fina, -- right
- u = s_isol, -- nonjoiner
- }
-
- local first_arabic, last_arabic = characters.blockrange("arabic")
- local first_syriac, last_syriac = characters.blockrange("syriac")
- local first_mandiac, last_mandiac = characters.blockrange("mandiac")
- local first_nko, last_nko = characters.blockrange("nko")
-
- local classifiers = { }
-
- for k, c in next, chardata do
- if k > 0 then
- local c = chardata[k]
- if c then
- local arabic = c.arabic
- if arabic then
- classifiers[k] = mappers[arabic]
- elseif k >= first_arabic and k <= last_arabic or k >= first_syriac and k <= last_syriac or
- k >= first_mandiac and k <= last_mandiac or k >= first_nko and k <= last_nko then
- if c.category == "mn" then
- classifiers[k] = s_mark
- else
- classifiers[k] = s_rest
- end
- end
- end
- end
- end
- return classifiers
- end
-
-local amend_table_fields = function (data, classifiers)
- --- installed by luatex-basics-prepare.tex
- data.characters = { }
- data.classifiers = classifiers
- return data
-end
-
-local writedata = function (data)
- local outchan = io.open(charfile, "w")
- if not outchan then
- io.write("Could not open "..charfile.." for writing.\n")
- return false
- end
- outchan:write(data)
- outchan:close()
- return true
-end
-
-do
- local chardata = get_characters()
- local classifiers = extract_classifiers(chardata)
- local stripped = extract_fields(chardata)
- local amended = amend_table_fields(stripped, classifiers)
- local serialized = table.serialize(amended, true, {
- compact = true,
- noquotes = true,
- hexify = true, --- for consistency with char-def
- })
- if writedata(serialized) then
- goto done
- end
- goto fail
-end
-
-::done::
- os.exit(0)
-
-::fail::
- io.write "Emergency exit.\n"
- os.exit(1)
-
---- vim:ft=lua:ts=2:et:sw=2
Deleted: trunk/Master/texmf-dist/scripts/luaotfload/mkglyphlist
===================================================================
--- trunk/Master/texmf-dist/scripts/luaotfload/mkglyphlist 2018-09-26 20:49:48 UTC (rev 48770)
+++ trunk/Master/texmf-dist/scripts/luaotfload/mkglyphlist 2018-09-26 20:50:34 UTC (rev 48771)
@@ -1,167 +0,0 @@
-#!/usr/bin/env texlua
------------------------------------------------------------------------
--- FILE: mkglyphlist.lua
--- USAGE: ./mkglyphlist.lua
--- DESCRIPTION: part of the luaotfload package
--- REQUIREMENTS: lua, lpeg, luasocket, the lualibs package
--- AUTHOR: Philipp Gesang (Phg), <phg42.2a at gmail.com>
------------------------------------------------------------------------
--- interesting thread on the Context list:
--- http://www.ntg.nl/pipermail/ntg-context/2008/029057.html
---
--- N.B. this script assumes network connectivity!
------------------------------------------------------------------------
-
-
------------------------------------------------------------------------
--- config
------------------------------------------------------------------------
-local glyphfile = "./build/glyphlist.txt"
-local font_age = "./build/luaotfload-glyphlist.lua"
-local glyph_source = "https://raw.githubusercontent.com/adobe-type-tools/agl-aglfn/master/glyphlist.txt"
-
------------------------------------------------------------------------
--- fallbacks
------------------------------------------------------------------------
---- Hans adds a small list of mappings that are not in the original
---- glyph list but seem to be normalizations of some sort. I trust his
---- experience, so I’ll just include them here. Background:
---- http://www.ntg.nl/pipermail/ntg-context/2013/073089.html
-
-local fallbacks = {
- ["SF10000"]=9484, ["SF20000"]=9492, ["SF30000"]=9488,
- ["SF40000"]=9496, ["SF50000"]=9532, ["SF60000"]=9516,
- ["SF70000"]=9524, ["SF80000"]=9500, ["SF90000"]=9508,
- ["afii208"]=8213,
-}
-
------------------------------------------------------------------------
--- includes
------------------------------------------------------------------------
-require"lpeg"
-require"socket"
-
-kpse.set_program_name"luatex"
-for _, lib in next, { "lualibs-lua.lua",
- "lualibs-lpeg.lua",
- "lualibs-table.lua", } do
- local found = assert(kpse.find_file(lib, "lua"),
- "Could not locate " .. lib)
- require(found)
-end
-
-local C, Cf, Cg, Ct, P, R =
- lpeg.C, lpeg.Cf, lpeg.Cg, lpeg.Ct, lpeg.P, lpeg.R
-
-local http = socket.http
-
------------------------------------------------------------------------
--- functionality
------------------------------------------------------------------------
-
-local dec_of_hex = function (hex) return tonumber(hex, 16) end
-
-local separator = P";"
-local gartenzaun = P"#"
-local eol = P"\n\r" + P"\r\n" + P"\r" + P"\n"
-local space = P" "
-local alphanum = R("az", "AZ", "09")
-local hexdigit = R("af", "AF", "09")
-local eof_tag = gartenzaun * P"END"
-local header_line = gartenzaun * (1-eol)^0 * eol
-local codepoint = hexdigit^1
-local glyphname = alphanum^1
-
-local definition = Cg(C(glyphname) * separator * (C(codepoint)/ dec_of_hex))
- --- With combined glyphs we take only the first
- --- value as char-def and font-age do, and skip
- --- the rest.
- * (space * codepoint)^0
- * eol
-local definitions = Cf(Ct"" * definition^1, rawset)
-
-local p_glyphs = header_line^0 * definitions * eof_tag
-
-local get_glyphs = function (data)
- local res = lpeg.match(p_glyphs, data)
- if not res then
- print("error: could not parse glyph list")
- os.exit(-1)
- end
- for name, glyph in next, fallbacks do
- res[name] = res[name] or glyph
- end
- return res
-end
-
-local file_header = [==[
-if not modules then modules = { } end modules ["font-age"] = {
- version = 2.400,
- comment = "part of the luaotfload package",
- author = "luaotfload team / mkglyphlist",
- copyright = "derived from %s",
- original = "Adobe Glyph List, version 2.0, September 20, 2002",
- dataonly = true,
-}
-
-if context then
- logs.report("fatal error","this module is not for context")
- os.exit(-1)
-end
-
---[[doc--
-Everything below has been autogenerated. Run mkglyphlist to rebuild
-luaotfload-glyphlist.lua.
---doc]]--
-
-]==]
-
-local writedata = function (data)
- data = table.serialize(data, true)
- data = string.format(file_header, glyph_source) .. data
- local fh = io.open(font_age, "wb")
- if not fh then
- print(string.format("error: %s not writable", font_age))
- os.exit(-1)
- end
- print(string.format("saving %d bytes to %s", #data, font_age))
- fh:write(data)
- fh:close()
-end
-
-
-local get_raw get_raw = function (retry)
- local fh = io.open(glyphfile, "rb")
- if fh then
- print ("info: reading glyph list from", glyphfile)
- local data = fh:read"*all"
- fh:close()
- if data then return data end
- elseif not retry then --- attempt download
- print"info: retrieving glyph list from"
- print(glyph_source)
- local cmd = string.format("wget '%s' -o '%s'", glyph_source, glyphfile)
- local st = os.execute(string.format("wget '%s' -O '%s'", glyph_source, glyphfile))
- if st ~= 0 then
- print(string.format("error: download failed; status: %d, command: %q", st, cmd))
- os.exit(-1)
- end
- end
- print("error: could not obtain glyph data from "..glyphfile)
- os.exit(-1)
-end
-
-local main = function ()
- if arg[1] then glyphfile = arg[1] end
- if arg[2] then font_age = arg[2] end
-
- local data = get_raw()
- local parsed = get_glyphs(data)
- writedata(parsed)
- return 0
-end
-
-
-return main()
-
---- vim:ft=lua:ts=2:et:sw=2
Deleted: trunk/Master/texmf-dist/scripts/luaotfload/mkimport
===================================================================
--- trunk/Master/texmf-dist/scripts/luaotfload/mkimport 2018-09-26 20:49:48 UTC (rev 48770)
+++ trunk/Master/texmf-dist/scripts/luaotfload/mkimport 2018-09-26 20:50:34 UTC (rev 48771)
@@ -1,1063 +0,0 @@
-#!/usr/bin/env texlua
--------------------------------------------------------------------------------
--- FILE: mkimport.lua
--- USAGE: texlua ./mkimport.lua
--- DESCRIPTION: check luaotfload imports against Context
--- REQUIREMENTS: luatex, the lualibs package, Context MkIV
--- AUTHOR: Philipp Gesang (Phg), <phg at phi-gamma.net>
--------------------------------------------------------------------------------
---
-
--------------------------------------------------------------------------------
---- PURPOSE
----
---- - Facilitate detecting changes in the fontloader source.
---- - Assist in updating source code and (partially) automate importing.
----
---- - Account for files in the plain fontloader distribution, alert in case of
---- additions or deletions.
----
---- - Fontloader packaging.
----
--------------------------------------------------------------------------------
-
-local debug = false
-
-kpse.set_program_name "luatex"
-
-local lfs = require "lfs"
-local md5 = require "md5"
-local os = require "os"
-
-require "lualibs"
-require "util-mrg"
-
-assert (utilities and utilities.merger and utilities.merger.compact
- and type (utilities.merger.compact) == "function",
- "Whoa, util-mrg.lua is not accessible! How do you expect this to work‽")
-
-local filedirname = file.dirname
-local fileiswritable = file.is_writable
-local ioloaddata = io.loaddata
-local iosavedata = io.savedata
-local iopopen = io.popen
-local iowrite = io.write
-local lfschdir = lfs.chdir
-local lfscurrentdir = lfs.currentdir
-local lfsisdir = lfs.isdir
-local lfsisfile = lfs.isfile
-local md5sumhexa = md5.sumhexa
-local osdate = os.date
-local osgettimeofday = os.gettimeofday
-local osrename = os.rename
-local stringformat = string.format
-local tableconcat = table.concat
-
--------------------------------------------------------------------------------
--- config
--------------------------------------------------------------------------------
-
-local parms = { }
-local our_prefix = "fontloader"
-local luatex_fonts_prefix = "luatex"
-local fontloader_subdir = "src/fontloader"
-
-local origin_paths = {
- context = { "tex/context/base/mkiv", "tex/context/base", },
- fontloader = "tex/generic/context/luatex",
-}
-
-local subdirs = {
- "runtime",
- "misc"
-}
-
-local searchdirs = {
- --- order is important!
- fontloader_subdir,
-}
-
-local prefixes = {
- context = nil,
- fontloader = "luatex",
-}
-
---[[doc--
-
- The output name is fixed so we have to deal with it but maybe we
- can get a patch to mtx-package upstreamed in the future. In any
- case, we are content with renaming the result for the time being.
-
- The target name is constructed on the fly from the current date.
- TODO It should be possible to supply a name and possibly
- destination path on the command line.
-
- Paths are relative to the base directory (``$PWD``).
-
---doc]]--
-
-local loader_target_name = "fontloader-%s.lua"
-local loader_orig_dir = "/src/fontloader/"
-local loader_target_dir = "/build/"
-
--------------------------------------------------------------------------------
--- helpers
--------------------------------------------------------------------------------
-
-local die = function (...)
- io.stderr:write "[\x1b[1;30;41mfatal error\x1b[0m] "
- io.stderr:write (stringformat (...))
- io.stderr:write "\naborting.\n"
- os.exit (1)
-end
-
-local uncertain = 0
-
-local hmm = function (...)
- uncertain = uncertain + 1
- --[[ sorta like an error but non-fatal ]]
- io.stderr:write "[\x1b[1;31merror\x1b[0m] "
- io.stderr:write (stringformat (...))
- io.stderr:write "; continuing nontheless.\n"
-end
-
-local emphasis = function (txt)
- return stringformat("\x1b[1m%s\x1b[0m", txt)
-end
-
-local msg = function (...)
- iowrite (stringformat (...))
- iowrite "\n"
-end
-
-local separator_string = string.rep ("-", 79)
-local separator = function ()
- iowrite (separator_string)
- iowrite "\n"
-end
-
-local good_tag = stringformat("[\x1b[1;30;%dmgood\x1b[0m] · ", 42)
-local bad_tag = stringformat("[\x1b[1;30;%dmBAD\x1b[0m] · ", 41)
-local alert_tag = stringformat("[\x1b[1;%dmalert\x1b[0m] · " , 36)
-local status_tag = stringformat("[\x1b[0;%dmstatus\x1b[0m] · " , 36)
-
-local good = function (...)
- local msg = (stringformat (...))
- iowrite (good_tag)
- iowrite (msg)
- iowrite "\n"
-end
-
-local bad = function (...)
- local msg = (stringformat (...))
- iowrite (bad_tag)
- iowrite (msg)
- iowrite "\n"
-end
-
-local attention = function (...)
- local msg = (stringformat (...))
- iowrite (alert_tag)
- iowrite (msg)
- iowrite "\n"
-end
-
-local status = function (...)
- local msg = (stringformat (...))
- iowrite (status_tag)
- iowrite (msg)
- iowrite "\n"
-end
-
--------------------------------------------------------------------------------
--- definitions
--------------------------------------------------------------------------------
-
---- Accounting of upstream files. There are different categories:
----
---- · *essential*: Files required at runtime.
---- · *merged*: Files merged into the fontloader package.
---- · *ignored*: Lua files not merged, but part of the format.
---- · *tex*: TeX code, i.e. format and examples.
---- · *lualibs*: Files merged, but also provided by the Lualibs package.
-
-local kind_essential = 0
-local kind_merged = 1
-local kind_tex = 2
-local kind_ignored = 3
-local kind_lualibs = 4
-
-local kind_name = {
- [0] = "essential",
- [1] = "merged" ,
- [2] = "tex" ,
- [3] = "ignored" ,
- [4] = "lualibs" ,
-}
-
-local imports = {
-
- fontloader = {
- { name = "basics-gen" , ours = nil , kind = kind_essential },
- { name = "basics-nod" , ours = nil , kind = kind_merged },
- { name = "basics" , ours = nil , kind = kind_tex },
- { name = "fonts-demo-vf-1" , ours = nil , kind = kind_ignored },
- { name = "fonts-enc" , ours = nil , kind = kind_merged },
- { name = "fonts-ext" , ours = nil , kind = kind_merged },
- { name = "fonts-merged" , ours = "reference" , kind = kind_essential },
- { name = "fonts" , ours = nil , kind = kind_merged },
- { name = "fonts" , ours = nil , kind = kind_tex },
- { name = "fonts-syn" , ours = nil , kind = kind_ignored },
- { name = "languages" , ours = nil , kind = kind_ignored },
- { name = "languages" , ours = nil , kind = kind_tex },
- { name = "math" , ours = nil , kind = kind_ignored },
- { name = "math" , ours = nil , kind = kind_tex },
- { name = "mplib" , ours = nil , kind = kind_ignored },
- { name = "mplib" , ours = nil , kind = kind_tex },
- { name = "plain" , ours = nil , kind = kind_tex },
- { name = "preprocessor" , ours = nil , kind = kind_ignored },
- { name = "preprocessor" , ours = nil , kind = kind_tex },
- { name = "preprocessor-test" , ours = nil , kind = kind_tex },
- { name = "swiglib" , ours = nil , kind = kind_ignored },
- { name = "swiglib" , ours = nil , kind = kind_tex },
- { name = "swiglib-test" , ours = nil , kind = kind_ignored },
- { name = "swiglib-test" , ours = nil , kind = kind_tex },
- { name = "test" , ours = nil , kind = kind_tex },
- }, --[[ [fontloader] ]]
-
- context = { --=> all merged
- { name = "data-con" , ours = "data-con" , kind = kind_merged },
- { name = "font-afk" , ours = "font-afk" , kind = kind_merged },
- { name = "font-cff" , ours = "font-cff" , kind = kind_merged },
- { name = "font-cid" , ours = "font-cid" , kind = kind_merged },
- { name = "font-con" , ours = "font-con" , kind = kind_merged },
- { name = "font-def" , ours = "font-def" , kind = kind_merged },
- { name = "font-dsp" , ours = "font-dsp" , kind = kind_merged },
- { name = "font-gbn" , ours = "font-gbn" , kind = kind_merged },
- { name = "font-ini" , ours = "font-ini" , kind = kind_merged },
- { name = "font-lua" , ours = "font-lua" , kind = kind_merged },
- { name = "font-map" , ours = "font-map" , kind = kind_merged },
- { name = "font-ocl" , ours = "font-ocl" , kind = kind_merged },
- { name = "font-otc" , ours = "font-otc" , kind = kind_merged },
- { name = "font-onr" , ours = "font-onr" , kind = kind_merged },
- { name = "font-one" , ours = "font-one" , kind = kind_merged },
- { name = "font-osd" , ours = "font-osd" , kind = kind_merged },
- { name = "font-ota" , ours = "font-ota" , kind = kind_merged },
- { name = "font-oti" , ours = "font-oti" , kind = kind_merged },
- { name = "font-otj" , ours = "font-otj" , kind = kind_merged },
- { name = "font-otl" , ours = "font-otl" , kind = kind_merged },
- { name = "font-oto" , ours = "font-oto" , kind = kind_merged },
- { name = "font-otr" , ours = "font-otr" , kind = kind_merged },
- { name = "font-ots" , ours = "font-ots" , kind = kind_merged },
- { name = "font-oup" , ours = "font-oup" , kind = kind_merged },
- { name = "font-tfm" , ours = "font-tfm" , kind = kind_merged },
- { name = "font-ttf" , ours = "font-ttf" , kind = kind_merged },
-
- { name = "l-boolean" , ours = "l-boolean" , kind = kind_lualibs },
- { name = "l-file" , ours = "l-file" , kind = kind_lualibs },
- { name = "l-function" , ours = "l-function" , kind = kind_lualibs },
- { name = "l-io" , ours = "l-io" , kind = kind_lualibs },
- { name = "l-lpeg" , ours = "l-lpeg" , kind = kind_lualibs },
- { name = "l-lua" , ours = "l-lua" , kind = kind_lualibs },
- { name = "l-math" , ours = "l-math" , kind = kind_lualibs },
- { name = "l-string" , ours = "l-string" , kind = kind_lualibs },
- { name = "l-table" , ours = "l-table" , kind = kind_lualibs },
- { name = "util-str" , ours = "util-str" , kind = kind_lualibs },
- { name = "util-fil" , ours = "util-fil" , kind = kind_lualibs },
- }, --[[ [context] ]]
-} --[[ [imports] ]]
-
-local package = {
-
- optional = { --- components not included in the default package
-
---- The original initialization sequence by Hans Hagen, see the file
---- luatex-fonts.lua for details:
----
---- [01] l-lua.lua
---- [02] l-lpeg.lua
---- [03] l-function.lua
---- [04] l-string.lua
---- [05] l-table.lua
---- [06] l-io.lua
---- [07] l-file.lua
---- [08] l-boolean.lua
---- [09] l-math.lua
---- [10] util-str.lua
---- [11] util-fil.lua
---- [12] luatex-basics-gen.lua
---- [13] data-con.lua
---- [14] luatex-basics-nod.lua
---- [15] luatex-basics-chr.lua
---- [16] font-ini.lua
---- [17] font-con.lua
---- [18] luatex-fonts-enc.lua
---- [19] font-cid.lua
---- [20] font-map.lua
---- [21] luatex-fonts-syn.lua
---- [23] font-oti.lua
---- [24] font-otr.lua
---- [25] font-cff.lua
---- [26] font-ttf.lua
---- [27] font-dsp.lua
---- [28] font-oup.lua
---- [29] font-otl.lua
---- [30] font-oto.lua
---- [31] font-otj.lua
---- [32] font-ota.lua
---- [33] font-ots.lua
---- [34] font-osd.lua
---- [35] font-ocl.lua
---- [36] font-otc.lua
---- [37] font-onr.lua
---- [38] font-one.lua
---- [39] font-afk.lua
---- [40] font-tfm.lua
---- [41] font-lua.lua
---- [42] font-def.lua
---- [43] font-xtx.lua
---- [44] luatex-fonts-ext.lua
---- [45] font-gbn.lua
----
---- Of these, nos. 01--11 are provided by the Lualibs. Keeping them
---- around in the Luaotfload fontloader is therefore unnecessary.
---- Packaging needs to account for this difference.
-
- "l-lua",
- "l-lpeg",
- "l-function",
- "l-string",
- "l-table",
- "l-io",
- "l-file",
- "l-boolean",
- "l-math",
- "util-str",
- "util-fil",
-
---- Another file containing auxiliary definitions must be present
---- prior to initialization of the configuration.
-
- "luatex-basics-gen",
-
---- We have a custom script for autogenerating data so we don’t use the
---- definitions from upstream.
-
- "basics-chr",
-
- }, --[[ [package.optional] ]]
-
---- The files below constitute the “fontloader proper”. Some of the
---- functionality like file resolvers is overloaded later by
---- Luaotfload. Consequently, the resulting package is pretty
---- bare-bones and not usable independently.
-
- required = {
-
- "data-con",
- "basics-nod",
- "font-ini",
- "font-con",
- "fonts-enc",
- "font-cid",
- "font-map",
- "font-oti",
- "font-otr",
- "font-cff",
- "font-ttf",
- "font-dsp",
- "font-oup",
- "font-otl",
- "font-oto",
- "font-otj",
- "font-ota",
- "font-ots",
- "font-osd",
- "font-ocl",
- "font-otc",
- "font-onr",
- "font-one",
- "font-afk",
- "font-tfm",
- "font-lua",
- "font-def",
- "fonts-ext",
- "font-gbn",
-
- }, --[[ [package.required] ]]
-
-} --[[ [package] ]]
-
-local hash_file = function (fname)
- if not lfsisfile (fname) then
- hmm ("cannot find %s", fname)
- return nil
- end
- local raw = ioloaddata (fname)
- if not raw then
- die ("cannot read from %s.", fname)
- end
- return md5sumhexa (raw)
-end
-
-local first_existing_subpath = function (pfx, subs)
- if not subs then return nil end
- local t_subs = type (subs)
- if t_subs == "table" then
- for i = 1, #subs do
- local sub = subs[i]
- local pth = file.join (pfx, sub)
- if lfsisdir (pth) then return pth end
- end
- elseif t_subs == "string" then
- local pth = file.join (pfx, subs)
- if lfsisdir (pth) then return pth end
- end
- return nil
-end
-
-local derive_category_path = function (cat)
- local location = first_existing_subpath (parms.context_root,
- origin_paths[cat])
- if not location then
- die ("invalid base path defined for category " .. cat)
- end
- return location
-end
-
-local derive_suffix = function (kind)
- if kind == kind_tex then return ".tex" end
- return ".lua"
-end
-
-local pfxlen = { }
-local strip_prefix = function (fname, prefix)
- prefix = prefix or our_prefix
- if not pfxlen[prefix] then pfxlen[prefix] = #prefix end
- local len = pfxlen[prefix]
- if #fname <= len + 2 then
- --- too short to accomodate prefix + basename
- return
- end
- if string.sub (fname, 1, len) == prefix then
- return string.sub (fname, len + 2)
- end
-end
-
-local derive_fullname = function (cat, name, kind)
- local tmp = prefixes[cat]
- tmp = tmp and tmp .. "-" .. name or name
- return tmp .. derive_suffix (kind)
-end
-
-local derive_ourname = function (name, kind)
- local suffix = derive_suffix (kind)
- local subdir = kind == kind_essential and "runtime" or "misc"
- return subdir, our_prefix .. "-" .. name .. suffix
-end
-
-local format_file_definition = function (def)
- return stringformat ("name = \"%s\", kind = \"%s\"",
- def.name,
- kind_name[def.kind] or def.kind)
- .. (def.ours and (", ours = \"" .. def.ours .. "\"") or "")
-end
-
-local is_readable = function (f)
- local fh = io.open (f, "r")
- if fh then
- fh:close()
- return true
- end
- return false
-end
-
-local summarize_news = function (status)
- local ni = #status.import
- local nc = #status.create
- local ng = #status.good
- local nm = #status.missing
-
- separator ()
- msg ("Summary: Inspected %d files.", ni + nc + ng + nm)
- separator ()
- if ng > 0 then good ("%d are up to date", ng) end
- if ni > 0 then attention ("%d changed" , ni) end
- if nc > 0 then attention ("%d new" , nc) end
- if nm > 0 then bad ("%d missing" , nm) end
- separator ()
-
- if nm == 0 and nc == 0 and ni == 0 then
- return 0
- end
-
- return -1
-end
-
-local news = function ()
- local status = {
- import = { },
- good = { },
- create = { },
- missing = { },
- }
-
- for cat, entries in next, imports do
- local location = derive_category_path (cat)
- local nfiles = #entries
-
- for i = 1, nfiles do
- local def = entries[i]
- local name = def.name
- local ours = def.ours
- local kind = def.kind
- local fullname = derive_fullname (cat, name, kind)
- local fullpath = file.join (location, fullname)
- local subdir, ourname = derive_ourname (ours or name, kind)
- local ourpath = file.join (fontloader_subdir, subdir, ourname) -- relative
- local imported = false
-
- if not is_readable (fullpath) then
- bad ("source for file %s not found at %s",
- emphasis (ourname),
- emphasis (fullpath))
- status.missing[#status.missing + 1] = ourname
- else
- --- Source file exists and is readable.
- if not lfsisdir (fontloader_subdir) then
- die ("path for fontloader tree ("
- .. fontloader_subdir .. ") is not a directory")
- end
- if is_readable (ourpath) then imported = true end
- local src_hash = hash_file (fullpath)
- if src_hash then
- local dst_hash = imported and hash_file (ourpath)
- local same = src_hash == dst_hash -- same!
- if same then
- good ("file %s unchanged", emphasis (ourname))
- status.good[#status.good + 1] = ourname
- elseif not dst_hash then
- attention ("new file %s requires import from %s",
- emphasis (ourname),
- emphasis (fullpath))
- status.create[#status.create + 1] = ourname
- else --- src and dst exist but differ
- attention ("file %s requires import", emphasis (ourname))
- status.import[#status.import + 1] = ourname
- end
- end
- end
-
- end
- end
-
- return summarize_news (status)
-end --[[ [local news = function ()] ]]
-
-local get_file_definition = function (name, ourname, kind)
- kind = kind or "lua"
- for cat, defs in next, imports do
- local fullname = derive_fullname (cat, name, kind)
- local ndefs = #defs
- for i = 1, ndefs do
- local def = defs[i]
- local dname = def.name
- local dours = def.ours or def.name
- local dkind = def.kind
-
- --- test properties
- local subdir, derived = derive_ourname (dours, dkind)
- if derived == ourname then return def, cat end
- if derive_fullname (cat, dname, dkind) == fullname then return def, cat end
- if dours == ourname then return def, cat end
- if dname == fullname then return def, cat end
- end
- end
- --- search unsuccessful
-end --[[ [local get_file_definition = function (name, ourname, kind)] ]]
-
-local import_imported = 0
-local import_skipped = 1
-local import_failed = 2
-local import_created = 3
-
-local import_status = {
- [import_imported] = "imported",
- [import_skipped ] = "skipped",
- [import_failed ] = "failed",
- [import_created ] = "created",
-}
-
-local summarize_status = function (counters)
- local imported = counters[import_imported] or 0
- local skipped = counters[import_skipped ] or 0
- local created = counters[import_created ] or 0
- local failed = counters[import_failed ] or 0
- local sum = imported + skipped + created + failed
- if sum < 1 then die ("garbage total of imported files: %s", sum) end
- separator ()
- status (" RESULT: %d files processed, %d errors", sum, uncertain)
- separator ()
- if created > 0 then status ("created: %d (%d %%)", created , created * 100 / sum) end
- if imported > 0 then status ("imported: %d (%d %%)", imported, imported * 100 / sum) end
- if skipped > 0 then status ("skipped: %d (%d %%)", skipped , skipped * 100 / sum) end
- separator ()
-end
-
-local import_file = function (name, kind, def, cat)
- local expected_ourname = derive_ourname (name)
- if not def or not cat then
- def, cat = get_file_definition (name, expected_ourname, kind)
- end
-
- if not def then die ("unable to find a definition matching " .. name) end
- if not cat then die ("missing category for file " .. name .. " -- WTF‽") end
-
- local dname = def.name
- local dours = def.ours or dname
- local dkind = def.kind
- local srcdir = derive_category_path (cat)
- local fullname = derive_fullname (cat, dname, kind)
- local subdir, ourname = derive_ourname (dours, kind)
- local ourpath = file.join (fontloader_subdir, subdir)
- local src = file.join (srcdir, fullname)
- local dst = file.join (ourpath, ourname)
- local new = not lfsisfile (dst)
- if not new and hash_file (src) == hash_file (dst) then
- status ("file %s is unchanged, skipping", fullname)
- return import_skipped
- end
- if not (lfsisdir (ourpath) or not lfs.mkdirs (ourpath)) then
- die ("failed to create directory %s for file %s",
- ourpath, ourname)
- end
- status ("importing file %s", fullname)
- file.copy (src, dst)
- if hash_file (src) == hash_file (dst) then
- if new then return import_created end
- return import_imported end
- return import_failed
-end --[[ [local import_file = function (name, kind)] ]]
-
-local import = function (arg)
- --- Multiple files
- local statcount = { } -- import status codes -> size_t
- for cat, defs in next, imports do
- local ndefs = #defs
- for i = 1, ndefs do
- local def = defs[i]
- local stat = import_file (def.name, def.kind, def, cat)
- if stat == import_failed then
- hmm (stringformat ("import failed at file %d of %d (%s)",
- i, ndefs, def.name))
- end
- statcount[stat] = statcount[stat] or 0
- statcount[stat] = statcount[stat] + 1
- end
- end
- summarize_status (statcount)
- return uncertain == 0 and 0 or -42
-end --[[ [local import = function (arg)] ]]
-
-local find_in_path = function (root, subdir, target)
- local file = file.join (root, subdir, target)
- if lfsisfile (file) then
- return file
- end
-end
-
-local search_paths = function (target)
- for i = 1, #searchdirs do
- local root = searchdirs[i]
-
- for j = 1, #subdirs do
- local found = find_in_path (root, subdirs[j], target)
- if found then return found end
- end
-
- end
-
- local found = find_in_path (parms.context_root, origin_paths.context, target)
- if found then return found end
-
- local found = find_in_path (parms.context_root, origin_paths.fontloader, target)
- if found then return found end
- return false
-end
-
-local search_defs = function (target)
- local variants = { target, --[[ unstripped ]] }
- local tmp
- tmp = strip_prefix (target)
- if tmp then variants[#variants + 1] = tmp end
- tmp = strip_prefix (target, luatex_fonts_prefix)
- if tmp then variants[#variants + 1] = tmp end
-
- local nvariants = #variants
-
- for cat, defs in next, imports do
- local ndefs = #defs
- for i = 1, ndefs do
- local def = defs[i]
-
- for i = 1, nvariants do
- local variant = variants[i]
-
- local dname = def.name
- if variant == dname then
- local found = search_paths (variant .. derive_suffix (def.kind))
- if found then return found end
- end
-
- local dkind = def.kind
- local dfull = derive_fullname (cat, dname, dkind)
- if derive_fullname (cat, variant, dkind) == dfull then
- local found = search_paths (dfull)
- if found then return found end
- end
-
- local dours = def.ours
- if dours then
-
- local _, ourname = derive_ourname (dours, dkind)
- if variant == dours then
- local found = search_paths (ourname)
- if found then return found end
- end
-
- if variant == ourname then
- local found = search_paths (ourname)
- if found then return found end
- end
- end
-
- end
- end
- end
- return false
-end
-
-local search = function (target)
- local look_for
- --- pick a file
- if lfsisfile (target) then --- absolute path given
- look_for = target
- goto found
- else
-
- --- search as file name in local tree
- look_for = search_paths (target)
- if look_for then goto found end
-
- --- seach the definitions
- look_for = search_defs (target)
- if look_for then goto found end
-
- end
-
-::fail::
- if not look_for then return end
-
-::found::
- return look_for
-end
-
-local find_matching_def = function (location)
- local basename = file.basename (location)
- if not basename then die ("corrupt path %s", location) end
- local barename = file.removesuffix (basename)
- local pfxless = strip_prefix (barename)
- local kind = file.suffix (pfxless) or "lua"
- for cat, defs in next, imports do
- for _, def in next, defs do
- local dname = def.name
- local dours = def.ours
- if dname == pfxless
- or dname == barename
- -- dname == basename -- can’t happen for lack of suffix
- or dours == pfxless
- or dours == barename
- then
- return cat, def
- end
- end
- end
- return false
-end
-
-local describe = function (target, location)
- --- Map files to import definitions
- separator ()
- status ("found file %s at %s", target, location)
- local cat, def = find_matching_def (location)
- if not cat or not def then
- die ("file %s not found in registry", location)
- end
-
- local dname = def.name
- local dkind = def.kind
- local subdir, ourname = derive_ourname (def.ours or dname, dkind)
- separator ()
- status ("category %s", cat)
- status ("kind %s", kind_name[dkind])
- status ("in Context %s", derive_fullname (cat, dname, dkind))
- status ("in Luaotfload %s", ourname)
- separator ()
- return 0
-end
-
-local tell = function (arg)
- local target = parms.target
- if not target then die "no filename given" end
-
- local location = search (target)
- if not location then
- die ("file %s not found in any of the search locations", target)
- end
-
- return describe (target, location)
-end
-
-local build_paths = function (argv)
- if not argv or type (argv) ~= "table" then die "build_paths" end
-
- local orig_dir = lfscurrentdir ()
- local base_dir = orig_dir .. loader_orig_dir
- local loader_name = stringformat (loader_target_name, os.date ("%F"))
- local target_name = orig_dir .. loader_target_dir .. loader_name
-
- if #argv >= 2 then
- local fname = argv[2]
- local dir = filedirname (fname) .. "/"
- if not lfsisdir (dir) then
- die ("second argument must be point into existing directory, not “%s”",
- argv[2])
- end
- base_dir = dir
- target_name = fname
- end
-
- if #argv == 3 then
- --- also set the target name
- local fname = argv[3]
- local dir = filedirname (fname)
- if not string.is_empty (dir) and not lfsisdir (dir) then
- die ("third argument must be point into writable directory, not “%s”",
- argv[3])
- end
- target_name = fname
- end
-
- local ret = {
- orig_dir = orig_dir,
- base_dir = base_dir,
- merge_name = merge_name,
- target_name = target_name,
- loader_name = loader_name,
- }
- return ret
-end
-
-local luaotfload_header = [==[
---[[info-----------------------------------------------------------------------
- Luaotfload fontloader package
- build %s by %s@%s
--------------------------------------------------------------------------------
-
- © %s PRAGMA ADE / ConTeXt Development Team
-
- The code in this file is provided under the GPL v2.0 license. See the
- file COPYING in the Luaotfload repository for details.
-
- Report bugs to github.com/lualatex/luaotfload
-
- This file has been assembled from components taken from Context. See
- the Luaotfload documentation for details:
-
- $ texdoc luaotfload
- $ man 1 luaotfload-tool
- $ man 5 luaotfload.conf
-
- Included files:
-
-%s
-
---info]]-----------------------------------------------------------------------
-
-]==]
-
-local make_header = function (files)
- local filelist = { }
- for i = 1, #files do
- local f = files[i]
- local _void, ourname = derive_ourname (f, kind_merged)
- filelist [#filelist + 1] = stringformat (" · %s", ourname)
- end
- return stringformat (luaotfload_header,
- os.date "%F %T",
- os.getenv "USER" or "anon",
- os.getenv "HOSTNAME" or "void",
- os.date "%Y",
- table.concat (filelist, "\n"))
-end
-
-
-local scope_start = "\ndo --- [luaotfload, %s scope for “%s” %s] ---\n\n"
-local scope_stop = "\nend --- [luaotfload, %s scope for “%s”] ---\n\n"
-local luaotfload_modeline = "\n--- vim:ft=lua:sw=2:ts=8:et:tw=79\n"
-
-local assemble_fontloader = function (tgt, dst)
- status ("packaging fontloader as “%s”.", emphasis (tgt))
- local required = package.required
- local compact = utilities.merger.compact
- local sequence = { [1] = make_header (required) }
- for i = 1, #required do
- local cur = required [i]
- local subdir, ourname = derive_ourname (cur, kind_merged)
- local ourpath = file.join (fontloader_subdir, subdir, ourname)
- local data = ioloaddata (ourpath)
- if not data then
- bad ("file “%s” cannot be loaded from “%s”", ourname, ourpath)
- return false
- end
- sequence[#sequence + 1] = stringformat (scope_start, tgt, cur, md5sumhexa (data))
- sequence[#sequence + 1] = compact (data)
- sequence[#sequence + 1] = stringformat (scope_stop , tgt, cur)
- end
- sequence[#sequence + 1] = luaotfload_modeline
- local raw = table.concat (sequence)
- local _void, chunk, err = pcall (loadstring, raw)
- print(_void, chunk)
- if chunk == nil then
- bad ("packaging result not well-formed")
- bad ("error message: “%s”", err)
- bad ("dumping to fontloader-junk.lua")
- iosavedata ("fontloader-junk.lua", raw)
- return false
- end
- iosavedata (dst, raw)
- status ("amalgamated %d files, written to “%s”.",
- #required, dst)
- return dst
-end
-
-local package = function (argv)
- local t0 = osgettimeofday ()
- local paths = build_paths (argv)
-
- status ("assuming fontloader source in %s", paths.base_dir)
- status ("reading merge instructions from %s", paths.merge_name)
- status ("writing output to %s", paths.target_name)
-
- --- check preconditions
-
- if not lfsisdir (paths.base_dir) then die ("directory %s does not exist", emphasis (paths.base_dir )) end
- if not fileiswritable (paths.target_name) then die ("cannot write to %s", emphasis (paths.target_name)) end
----- not lfschdir (paths.base_dir) then die ("failed to cd into %s", emphasis (paths.base_dir )) end
-
- if lfsisfile (paths.target_name) then
- status ("output file already exists at “%s”, unlinking",
- paths.target_name)
- local ret, err = os.remove (paths.target_name)
- if ret == nil then
- if not lfschdir (paths.orig_dir) then
- status ("warning: failed to cd retour into %s",
- emphasis (paths.orig_dir))
- end
- die ("failed to remove existing merge package")
- end
- end
- --- perform merge
-
- local ret = assemble_fontloader (paths.loader_name, paths.target_name)
-
- if not ret then
- if not lfschdir (paths.orig_dir) then
- status ("warning: failed to cd retour into %s",
- emphasis (paths.orig_dir))
- end
- die ("merge failed; failed to invoke mtxrun")
- end
-
- --- clean up
-
- if not lfschdir (paths.orig_dir) then
- status ("warning: failed to cd retour into %s",
- emphasis (paths.orig_dir))
- end
-
- --- check postconditions
-
- if not lfsisfile (ret) then
- die ("merge failed; package not found at “%s”", paths.output_name)
- end
-
- --- at this point we know that mtxrun was invoked correctly and the
- --- result file has been created
-
- status ("merge complete; operation finished in %.0f ms",
- (osgettimeofday() - t0) * 1000)
- status ("a fresh fontloader at %s is ready to roll", paths.target_name)
-end
-
-local help = function ()
- iowrite "usage: mkimport <command> [<args>]\n"
- iowrite "\n"
- iowrite "Where <command> is one of\n"
- iowrite " help Print this help message\n"
- iowrite " tell Display information about a file’s integration\n"
- iowrite " news Check Context for updated files\n"
- iowrite " import Update with files from Context\n"
- iowrite " package Invoke mtx-package on the current fontloader\n"
- iowrite "\n"
-end
-
-local job_kind = table.mirrored {
- help = help,
- import = import,
- news = news,
- package = package,
- tell = tell,
-}
-
--------------------------------------------------------------------------------
--- functionality
--------------------------------------------------------------------------------
-
---- job_kind -> bool
-local check_job = function (j)
- return job_kind[j] or die ("invalid job type “%s”.", j)
-end
-
-local parse_argv = function (argv)
- local job
- local tgt
- local pth
-
- local argc = #arg
- if argc < 1 or argc > 3 then return "help" end
- job = arg[1] or "help"
- if argc > 1 then
- tgt = arg[2]
- if argc == 3 then pth = arg[3] end
- end
- if not pth then pth = "~/context/tex/texmf-context" end
- parms.context_root = kpse.expand_path (pth)
- parms.target = tgt
- searchdirs [#searchdirs + 1] = pth
- return job
-end
-
--------------------------------------------------------------------------------
--- entry point
--------------------------------------------------------------------------------
-
-local main = function ()
- local job = parse_argv (arg)
- local runner = check_job (job)
- return runner(arg)
-end
-
-os.exit (main ())
-
---- vim:ft=lua:ts=2:et:sw=2
Deleted: trunk/Master/texmf-dist/scripts/luaotfload/mkstatus
===================================================================
--- trunk/Master/texmf-dist/scripts/luaotfload/mkstatus 2018-09-26 20:49:48 UTC (rev 48770)
+++ trunk/Master/texmf-dist/scripts/luaotfload/mkstatus 2018-09-26 20:50:34 UTC (rev 48771)
@@ -1,307 +0,0 @@
-#!/usr/bin/env texlua
------------------------------------------------------------------------
--- FILE: mkstatus.lua
--- USAGE: ./mkstatus.lua
--- DESCRIPTION: writes the repository state
--- REQUIREMENTS: luatex, the lualibs package
--- AUTHOR: Philipp Gesang (Phg), <phg42.2a at gmail.com>
--- CREATED: 2013-07-07 14:01:12+0200
------------------------------------------------------------------------
---
--- This script generates a list of hashes that serves as the input
--- for the file integrity check (option --diagnose). md5 is all we can
--- assume in Luatex, so it’s really only a superficial test.
---
--- Not that this file also incorporates the Git revision information.
--- Of this, only the actual commit hash is authoritative. The latest
--- tag is included for reference only. Besides that, it’s meaningless.
--- Do not rely on it: Two distinct versions of Luaotfload might very
--- well share the same tag.
-
-kpse.set_program_name "luatex"
-
-local md5 = require "md5"
-
-require "lualibs"
-
-local stringformat = string.format
-local md5sumhexa = md5.sumhexa
-local ioloaddata = io.loaddata
-local iosavedata = io.savedata
-local iopopen = io.popen
-local iowrite = io.write
-local lfsisdir = lfs.isdir
-local stringmatch = string.match
-
------------------------------------------------------------------------
--- settings
------------------------------------------------------------------------
-
-local verbose = false
-local filelist = "./build/luaotfload-status.lua" --- result
-
-local srcdir = "src"
-local builddir = "build"
-local scriptdir = "scripts"
-local loaderdir = "src/fontloader"
-local rtdir = "src/fontloader/runtime"
-local miscdir = "src/fontloader/misc"
-
-local names = {
-
- --- Luaotfload runtime files
- { srcdir, "luaotfload-auxiliary.lua", },
- { srcdir, "luaotfload-colors.lua", },
- { srcdir, "luaotfload-configuration.lua", },
- { srcdir, "luaotfload-database.lua", },
- { srcdir, "luaotfload-diagnostics.lua", },
- { srcdir, "luaotfload-features.lua", },
- { srcdir, "luaotfload-init.lua", },
- { srcdir, "luaotfload-letterspace.lua", },
- { srcdir, "luaotfload-loaders.lua", },
- { srcdir, "luaotfload-log.lua", },
- { srcdir, "luaotfload-main.lua", },
- { srcdir, "luaotfload-parsers.lua", },
- { srcdir, "luaotfload-resolvers.lua", },
- { srcdir, "luaotfload-tool.lua", },
-
- --- generated files
- { builddir, "luaotfload-characters.lua", },
- { builddir, "luaotfload-glyphlist.lua", },
-
- --- scripts
- { scriptdir, "mkcharacters", },
- { scriptdir, "mkglyphlist", },
- { scriptdir, "mkimport", },
- { scriptdir, "mkstatus", },
- { scriptdir, "mktests", },
-
- --- fontloader runtimes
- { rtdir, "fontloader-basics-gen.lua", },
- { rtdir, "fontloader-reference.lua", },
-
- --- fontloader constituents
- { miscdir, "fontloader-basics-nod.lua", },
- { miscdir, "fontloader-data-con.lua", },
- { miscdir, "fontloader-font-afk.lua", },
- { miscdir, "fontloader-font-onr.lua", },
- { miscdir, "fontloader-font-one.lua", },
- { miscdir, "fontloader-font-cid.lua", },
- { miscdir, "fontloader-font-con.lua", },
- { miscdir, "fontloader-font-def.lua", },
- { miscdir, "fontloader-font-ini.lua", },
- { miscdir, "fontloader-font-map.lua", },
- { miscdir, "fontloader-font-oti.lua", },
- { miscdir, "fontloader-font-gbn.lua", },
- { miscdir, "fontloader-font-def.lua", },
- { miscdir, "fontloader-fonts-demo-vf-1.lua", },
- { miscdir, "fontloader-fonts-enc.lua", },
- { miscdir, "fontloader-fonts-ext.lua", },
- { miscdir, "fontloader-fonts.lua", },
- { miscdir, "fontloader-font-lua.lua", },
- { miscdir, "fontloader-fonts-syn.lua", },
- { miscdir, "fontloader-font-tfm.lua", },
- { miscdir, "fontloader-font-otr.lua", },
- { miscdir, "fontloader-font-cff.lua", },
- { miscdir, "fontloader-font-ttf.lua", },
- { miscdir, "fontloader-font-dsp.lua", },
- { miscdir, "fontloader-font-oup.lua", },
- { miscdir, "fontloader-font-otl.lua", },
- { miscdir, "fontloader-font-oto.lua", },
- { miscdir, "fontloader-font-otj.lua", },
- { miscdir, "fontloader-font-ota.lua", },
- { miscdir, "fontloader-font-ots.lua", },
- { miscdir, "fontloader-font-osd.lua", },
- { miscdir, "fontloader-font-ocl.lua", },
- { miscdir, "fontloader-font-otc.lua", },
-
- --- lua libraries
- { miscdir, "fontloader-languages.lua", },
- { miscdir, "fontloader-l-boolean.lua", },
- { miscdir, "fontloader-l-file.lua", },
- { miscdir, "fontloader-l-function.lua", },
- { miscdir, "fontloader-l-io.lua", },
- { miscdir, "fontloader-l-lpeg.lua", },
- { miscdir, "fontloader-l-lua.lua", },
- { miscdir, "fontloader-l-math.lua", },
- { miscdir, "fontloader-l-string.lua", },
- { miscdir, "fontloader-l-table.lua", },
- { miscdir, "fontloader-math.lua", },
- { miscdir, "fontloader-mplib.lua", },
- { miscdir, "fontloader-preprocessor.lua", },
- { miscdir, "fontloader-swiglib.lua", },
- { miscdir, "fontloader-swiglib-test.lua", },
- { miscdir, "fontloader-util-str.lua", },
- { miscdir, "fontloader-util-fil.lua", },
-
-} --[[local names]]
-
------------------------------------------------------------------------
--- helpers
------------------------------------------------------------------------
-
-local die = function (...)
- io.stderr:write "[fatal error]: "
- io.stderr:write (stringformat (...))
- io.stderr:write "\naborting.\n"
- os.exit (1)
-end
-
-local logcmd = "git log -1 \z
- --format=\"return {\z
- %n revision = [[%H]],\z
- %n timestamp = [[%cd]],\z
- %n committer = [[%cn <%ce>]],\z
- %n}\" \z
- --date=iso"
-local describecmd = "git describe --all"
-
-local readpipe = function (cmd)
- local chan = iopopen (cmd)
- if not chan then
- die ("this script needs to be run inside \z
- the luaotfload git repository")
- end
- local data = chan:read "*all"
- chan:close ()
- return data
-end
-
-local git_info = function ()
- --io.write (logcmd)
- --io.write "\n"
- local desc = readpipe (describecmd)
- if not desc then die "cannot parse git information" end
- desc = string.fullstrip (desc)
- local desc = string.explode (desc, "/")[2] or desc
- if not desc then die "cannot parse sanitized git information" end
- local data = readpipe (logcmd)
- if data and type (data) == "string" and data ~= "" then
- data = load (data)
- if not data then
- die "cannot parse git information"
- end
- data = data ()
- data.description = desc
- return data
- end
- die "cannot read from pipe"
-end
-
------------------------------------------------------------------------
--- functionality
------------------------------------------------------------------------
-
-local hash_file = function (fname)
- if not lfs.isfile (fname) then
- die ("cannot find %s.", fname)
- end
- local raw = ioloaddata (fname)
- if not raw then
- die ("cannot read from %s.", fname)
- end
- return md5sumhexa (raw)
-end
-
-local hash_all
-hash_all = function (list, acc)
- if acc == nil then
- local base = table.fastcopy (names)
- return hash_all (table.append (base, list), { })
- end
-
- local finfo = list[#list]
- list[#list] = nil
- if finfo then
- local fpath, fname
- if type (finfo) == "table" then
- local d, f = finfo [1], finfo [2]
- if lfs.isdir (d) then
- fpath = file.join (d, f)
- else
- fpath = f
- end
- fname = f
- else
- fpath = finfo
- end
- if verbose then
- iowrite "· md5("
- iowrite (fpath)
- end
- local sum = hash_file (fpath)
- if verbose then
- iowrite ") = \""
- iowrite (sum)
- iowrite "\"\n"
- end
- acc[#acc+1] = { fname, sum }
- return hash_all (list, acc)
- end
- return acc
-end
-
-local handle_argv = function (argv)
- local ret = { files = { }, loader = nil }
- local argc = #argv
- if argc < 1 then return ret end
- local argoff = 1
- if argv [1] == "-v" then
- verbose = true
- if argc == 1 then return ret end
- argoff = 2
- end
- local aux aux = function (acc, i)
- if i > argc then return acc else
- local cur = argv[i]
- if type (cur) == "string" then
- local loader = stringmatch (cur, "--fontloader=(.+)$")
- if loader then
- cur = loader
- acc.loader = file.basename (cur)
- end
- if lfs.isfile (cur) then
- local files = acc.files
- files[#files + 1] = cur
- end
- else
- die ("file not found: %s", tostring (cur))
- end
- return aux (acc, i + 1)
- end
- end
- return aux (ret, argoff)
-end
-
-local add_files
-add_files = function (lst, acc)
- if lst == nil then return end
- if acc == nil then return add_files (lst, { }) end
- local len = #lst
- if len == 0 then return acc end
- local cur = lst[len]
- local fname = file.basename (cur)
- local path = file.dirname (cur)
- acc[#acc + 1] = { path, fname }
- lst[len] = nil
- return add_files (lst, acc)
-end
-
-local main = function ()
- local raw_extra = handle_argv (arg)
- local cuit_extra = add_files (raw_extra.files)
- local hashes = hash_all (cuit_extra)
- local notes = git_info ()
- notes.loader = raw_extra.loader
- local serialized = table.serialize ({ notes = notes,
- hashes = hashes }, true)
- local success = io.savedata (filelist, serialized)
- if success == false then
- die ("could not write to %s.", filelist)
- end
- return 0
-end
-
-return main ()
-
---- vim:ft=lua:ts=2:et:sw=2
Deleted: trunk/Master/texmf-dist/scripts/luaotfload/mktests
===================================================================
--- trunk/Master/texmf-dist/scripts/luaotfload/mktests 2018-09-26 20:49:48 UTC (rev 48770)
+++ trunk/Master/texmf-dist/scripts/luaotfload/mktests 2018-09-26 20:50:34 UTC (rev 48771)
@@ -1,362 +0,0 @@
-#!/usr/bin/env texlua
------------------------------------------------------------------------
--- FILE: mktests
--- USAGE: ./mktests
--- DESCRIPTION: test the behavior of Luaotfload
--- REQUIREMENTS: Luatex > 0.76, Luaotfload
--- AUTHOR: Philipp Gesang (Phg), <phg42.2a at gmail.com>
------------------------------------------------------------------------
---
---===================================================================--
--- NOTE
--- this is a stub, to be completed long-term
--- suggestions welcome
---===================================================================--
-
-
-local tests = { }
-local lpeg = require "lpeg"
-local lpegmatch = lpeg.match
-
-config = { luaotfload = { } }
-luatexbase = { }
-
-kpse.set_program_name "luatex"
-
-require "lualibs"
-require "luaotfload-basics-gen.lua"
-require "luaotfload-log.lua"
-
-fonts = { names = { } } -- for db; normally provided by the fontloaders
-
-local require_init = { }
-
-local loadmodule = function (name)
- local v = require ("luaotfload-" .. name)
- if v then
- local mod = { }
- local tv = type (v)
- if tv == "table" then
- mod.name = name
- mod.init = v.init
- require_init [#require_init + 1] = mod
- elseif tv == "function" then
- mod.name = name
- mod.init = v
- require_init [#require_init + 1] = mod
- end
- end
-end
-
-require "alt_getopt"
-
-loadmodule "log.lua" --- this populates the luaotfload.log.* namespace
-loadmodule "parsers" --- fonts.conf, configuration, and request syntax
-loadmodule "configuration" --- configuration file handling
-loadmodule "database"
-loadmodule "resolvers" --- Font lookup
-
-do --- init_modules
- --- NB we don’t command the logger at this point.
- local todo = #require_init
- local ret = true
- for i = 1, todo do
- local mod = require_init[i]
- local name = mod.name
- local init = mod.init
- if type (init) ~= "function" then
- error ("luaotfload broken; module "
- .. name .. " missing initializers!")
- end
- local v = mod.init ()
- if v == true then
- --- evaluated well
- elseif type (v) == "table" then
- luaotfload[name] = v
- else
- error ("luaotfload broken; initialization of module "
- .. name .. " returned " .. tostring (v) .. ".")
- return false
- end
- end
-end
-
-local names = fonts.names
-
------------------------------------------------------------------------
---- helper functions
------------------------------------------------------------------------
-
-local pprint_resolve = function (input, output, result)
- texio.write_nl (string.format ("[%s] “%s” -> “%s”",
- result == true and "passed" or "failed",
- input,
- output))
-end
-
-local pprint_result = function (name, failed, total)
- if failed == 0 then
- texio.write_nl (string.format ("[%s] all %d passed", name, total))
- else
- texio.write_nl (string.format ("[%s] %d of %d failed",
- name,
- failed,
- total))
- end
-end
-
-local pprint_spec = function (spec)
- return string.format ("%s/%s*%.2fpt",
- spec.specification,
- spec.style or "regular",
- spec.optsize or 0)
-end
-
------------------------------------------------------------------------
---- parser tests
------------------------------------------------------------------------
-
-local test_config_input = [==[
-
-
-[foo]
-bar = baz
-xyzzy = no
-buzz
-
-[lavernica "brutalitops"]
-# It’s a locomotive that runs on us.
- laan-ev = zip zop zooey ; jib-jab
-Crouton = "Fibrosis \"\\ # "
-
-]==]
-
-local test_config_output = {
- { section = { title = "foo" },
- variables = { bar = "baz",
- xyzzy = false,
- buzz = true } },
- { section = { title = "lavernica",
- subtitle = "brutalitops" },
- variables = { ["laan-ev"] = "zip zop zooey",
- crouton = "Fibrosis \"\\ # " } }
-}
-
-local parse_config = function ()
- local parser = luaotfload.parsers.config
- local result = lpegmatch (parser, test_config_input)
- --- compare values recursively
- local aux aux = function (t1, t2)
- --- cheaply non-tail recursive
- local k1 = table.keys (t1)
- local k2 = table.keys (t2)
- if #k1 ~= #k2 then
- return false
- end
- for i = 1, #k1 do
- local k = k1[i]
- local v1 = t1[k]
- local v2 = t2[k]
- if type (v1) == "table" then
- if type (v2) ~= "table" or not aux (v1, v2) then
- return false
- end
- elseif v1 ~= v2 then
- return false
- end
- end
- return true
- end
- return aux (result, test_config_output) and 0 or 1, 1
-end
-
-tests["parse_config"] = parse_config
-
------------------------------------------------------------------------
---- font tests
------------------------------------------------------------------------
-
---- test sets
-
-local infer_regular_style = {
- --- inferring which one is the correct style for “regular”; can be
- --- obscured by synonyms like “book” etc.
- { "Iwona", "Iwona-Regular.otf" }, -- trivial case
- { "DejaVu Serif", "DejaVuSerif.ttf" },
- { "DejaVu Sans", "DejaVuSans.ttf" },
- { "Adobe Garamond Pro", "agaramondpro_regular.otf" },
- { "Garamond Premier Pro", "GaramondPremrPro.otf" },
- { "CMU Serif", "cmunrm.otf" },
- { "CMU Sans Serif", "cmunss.otf" },
- { "Minion Pro", "MinionPro-Regular.otf" },
- --- Below test will succeed only if we match for the
- --- splainname (= sanitized tfmdata.fullname) field
- --- explicitly.
- { "Minion Pro Italic", "MinionPro-It.otf" },
-}
-
-local choose_optical_size = {
- { { name = "Latin Modern Roman", optsize = 1 }, "lmroman5-regular.otf" },
- { { name = "Latin Modern Roman", optsize = 10 }, "lmroman10-regular.otf" },
- { { name = "Latin Modern Roman", optsize = 12 }, "lmroman12-regular.otf" },
- { { name = "Latin Modern Roman", optsize = 42 }, "lmroman17-regular.otf" },
- { { name = "EB Garamond", optsize = 1 }, "EBGaramond08-Regular.otf" },
- { { name = "EB Garamond", optsize = 8 }, "EBGaramond08-Regular.otf" },
- { { name = "EB Garamond", optsize = 12 }, "EBGaramond12-Regular.otf" },
- { { name = "EB Garamond", optsize = 42 }, "EBGaramond12-Regular.otf" },
- { { name = "Garamond Premier Pro", optsize = 1 }, "GaramondPremrPro-Capt.otf" },
- { { name = "Garamond Premier Pro", optsize = 10 }, "GaramondPremrPro.otf" },
- { { name = "Garamond Premier Pro", optsize = 15 }, "GaramondPremrPro-Subh.otf" },
- { { name = "Garamond Premier Pro", optsize = 42 }, "GaramondPremrPro-Disp.otf" },
-}
-
-local choose_style = {
- { { name = "DejaVu Sans", style = "regular" }, "DejaVuSans.ttf" },
- { { name = "DejaVu Sans", style = "italic" }, "DejaVuSans-Oblique.ttf" },
- { { name = "DejaVu Sans", style = "bold" }, "DejaVuSans-Bold.ttf" },
- { { name = "DejaVu Sans", style = "bolditalic" }, "DejaVuSans-BoldOblique.ttf" },
- { { name = "Linux Libertine O", style = "regular" }, "LinLibertine_R.otf" },
- { { name = "Linux Libertine O", style = "italic" }, "LinLibertine_RI.otf" },
- { { name = "Linux Libertine O", style = "bold" }, "LinLibertine_RB.otf" },
- { { name = "Linux Libertine O", style = "bolditalic" }, "LinLibertine_RBI.otf" },
- { { name = "Liberation Serif", style = "regular" }, "LiberationSerif-Regular.ttf" },
- { { name = "Liberation Serif", style = "italic" }, "LiberationSerif-Italic.ttf" },
- { { name = "Liberation Serif", style = "bold" }, "LiberationSerif-Bold.ttf" },
- { { name = "Liberation Serif", style = "bolditalic" }, "LiberationSerif-BoldItalic.ttf" },
- { { name = "CMU Sans Serif", style = "regular" }, "cmunss.otf" }, -- no “regular” but “medium”
- { { name = "CMU Sans Serif", style = "italic" }, "cmunsi.otf" }, -- no “italic” but “oblique”
- { { name = "CMU Sans Serif", style = "bold" }, "cmunsx.otf" },
- { { name = "CMU Sans Serif", style = "bolditalic" }, "cmunso.otf" },
- --[[--
- Minion Pro Italic is exceptionally weird regarding identifiers in
- that the postscript fontname and both info.fontname and
- info.fullname are given as “minionproit”. Now its english fullname
- (field 18) is “minionproital”. Only the value “fullname” in the root of
- the tfmdata structure (not the one returned by fontloader.info()!)
- accurately yields “Minion Pro Italic”.
-
- To complete the picture, the file naming isn’t very consistent either:
- we find the suffixes “Regular” and “Bold”, but “It” and “BoldIt”. What
- the hell were the designers smoking?
-
- Also, the full Minion Pro set comes with different optical sizes which
- for monetary reasons cannot considered here.
- --]]--
- { { name = "Minion Pro", style = "regular" }, "MinionPro-Regular.otf" },
- { { name = "Minion Pro", style = "italic" }, "MinionPro-It.otf" },
- { { name = "Minion Pro", style = "bold" }, "MinionPro-Bold.otf" },
- { { name = "Minion Pro", style = "bolditalic" }, "MinionPro-BoldIt.otf" },
-}
-
---- this needs a database built with --formats=+pfa,pfb,afm
-
-local resolve_t1_font = {
- { { name = "URW Gothic L", style = "regular" }, "a010013l.pfb" }, --> “book”
--- { { name = "URW Gothic L", style = "italic" }, "a010033l.pfb" }, --> “book oblique”
--- { { name = "URW Gothic L", style = "bold" }, "a010015l.pfb" }, --> “demi”
--- { { name = "URW Gothic L", style = "bolditalic" }, "a010035l.pfb" }, --> “demi oblique”
- { { name = "Century Schoolbook L", style = "regular" }, "c059013l.pfb" },
- { { name = "Century Schoolbook L", style = "italic" }, "c059033l.pfb" },
- { { name = "Century Schoolbook L", style = "bold" }, "c059016l.pfb" },
- { { name = "Century Schoolbook L", style = "bolditalic" }, "c059036l.pfb" },
- { { name = "Nimbus Roman No9 L", style = "regular" }, "n021003l.pfb" },
- { { name = "Nimbus Roman No9 L", style = "italic" }, "n021023l.pfb" },
- { { name = "Nimbus Roman No9 L", style = "bold" }, "n021004l.pfb" }, --- medium, actually
- { { name = "Nimbus Roman No9 L", style = "bolditalic" }, "n021024l.pfb" },
-}
-
-local translate_style = {
- regular = "r",
- italic = "i",
- bold = "b",
- bolditalic = "bi",
-}
-
-local font_name_tests = {
- infer_regular_style,
- choose_optical_size,
- choose_style,
- resolve_t1_font,
-}
-
-local default_spec = {
- name = false,
- lookup = "name",
- specification = false,
- optsize = 0,
-}
-
-local resolve_font_name = function ()
- local failed, total = 0, 0
- for nset = 1, #font_name_tests do
- local set = font_name_tests[nset]
-
- for ntest = 1, #set do
- local test = set[ntest]
- local input, output = test[1], test[2]
-
- if type (input) == "string" then
- local input_spec = table.copy (default_spec)
- input_spec.name = input
- input_spec.specification = input_spec.lookup .. ":" .. input
- local result = fonts.names.lookup_font_name (input_spec) == output
- total = total + 1
- if not result then
- failed = failed + 1
- end
- pprint_resolve (input, output, result)
-
- else
- local input_spec, output = test[1], test[2]
- input_spec.specification = (input_spec.lookup
- or default_spec.lookup)
- .. ":" .. input_spec.name
- input_spec.optsize = input_spec.optsize or default_spec.optsize
- input_spec.style = translate_style [input_spec.style]
- local result = fonts.names.lookup_font_name (input_spec) == output
- total = total + 1
- if not result then
- failed = failed + 1
- end
- pprint_resolve (pprint_spec (input_spec), output, result)
- end
-
- end
- end
- return failed, total
-end
-
-tests ["resolve_font_name"] = resolve_font_name
-
-
------------------------------------------------------------------------
---- runner
------------------------------------------------------------------------
-
-local main = function ()
- local failed, total = 0, 0
- config.actions.apply_defaults ()
- for name, test in next, tests do
- texio.write_nl ("[" .. name .. "]")
- local newfailed, newtotal = test ()
- total = total + 1
- pprint_result (name, newfailed, newtotal)
- failed = failed + newfailed
- total = total + newtotal
- end
-
- if failed == 0 then
- texio.write_nl (string.format ("[report] all %d tests passed.", total))
- else
- texio.write_nl (string.format ("[report] %d of %d tests failed (%d %%).",
- failed,
- total,
- failed / total * 100))
- end
- texio.write_nl ""
- os.exit (0)
-end
-
-return main ()
-
---- vim:ft=lua:ts=2:et:sw=2
Deleted: trunk/Master/texmf-dist/source/luatex/luaotfload/Makefile
===================================================================
--- trunk/Master/texmf-dist/source/luatex/luaotfload/Makefile 2018-09-26 20:49:48 UTC (rev 48770)
+++ trunk/Master/texmf-dist/source/luatex/luaotfload/Makefile 2018-09-26 20:50:34 UTC (rev 48771)
@@ -1,263 +0,0 @@
-# Makefile for luaotfload
-
-NAME = luaotfload
-
-DOCSRCDIR = ./doc
-SCRIPTSRCDIR = ./scripts
-SRCSRCDIR = ./src
-FONTLOADERDIR = $(SRCSRCDIR)/fontloader/runtime
-FONTLOADERSRCDIR= $(SRCSRCDIR)/fontloader/misc
-PACKAGEDIR = $(SRCSRCDIR)/fontloader
-BUILDDIR = ./build
-MISCDIR = ./misc
-
-SRC = $(wildcard $(SRCSRCDIR)/luaotfload-*.lua)
-SRC += $(wildcard $(FONTLOADERDIR)/*.lua)
-SRC += $(SRCSRCDIR)/luaotfload.sty
-SRC += $(MISCDIR)/luaotfload-blacklist.cnf
-
-VGND = $(MISCDIR)/valgrind-kpse-suppression.sup
-CONFDEMO = $(MISCDIR)/luaotfload.conf.example
-
-GLYPHSCRIPT = $(SCRIPTSRCDIR)/mkglyphlist
-CHARSCRIPT = $(SCRIPTSRCDIR)/mkcharacters
-STATUSSCRIPT = $(SCRIPTSRCDIR)/mkstatus
-IMPORTSCRIPT = $(SCRIPTSRCDIR)/mkimport
-TESTSCRIPT = $(SCRIPTSRCDIR)/mktests
-
-GLYPHSOURCE = $(BUILDDIR)/glyphlist.txt
-
-RESOURCESCRIPTS = $(GLYPHSCRIPT) $(CHARSCRIPT) $(STATUSSCRIPT)
-RESOURCESCRIPTS+= $(IMPORTSCRIPT) $(TESTSCRIPT)
-
-TOOLNAME = luaotfload-tool
-TOOL = $(SRCSRCDIR)/$(TOOLNAME).lua
-
-CONFNAME = luaotfload.conf
-
-GRAPH = filegraph
-DOCSRC = $(addprefix $(DOCSRCDIR)/$(NAME), -main.tex -latex.tex)
-LOADERSRC = $(wildcard $(FONTLOADERSRCDIR)/*.lua)
-LOADERSRC += $(wildcard $(FONTLOADERSRCDIR)/*.tex)
-GRAPHSRC = $(DOCSRCDIR)/$(GRAPH).dot
-MANSRC = $(DOCSRCDIR)/$(TOOLNAME).rst $(DOCSRCDIR)/$(CONFNAME).rst
-
-DOCPDF = $(DOCSRCDIR)/$(NAME).pdf
-DOTPDF = $(DOCSRCDIR)/$(GRAPH).pdf
-TOOLMAN = $(DOCSRCDIR)/$(TOOLNAME).1
-CONFMAN = $(DOCSRCDIR)/$(CONFNAME).5
-MANPAGES = $(TOOLMAN) $(CONFMAN)
-
-DOCS = $(DOCPDF) $(DOTPDF) $(MANPAGES)
-
-# Files grouped by generation mode
-GLYPHS = $(BUILDDIR)/$(NAME)-glyphlist.lua
-CHARS = $(BUILDDIR)/$(NAME)-characters.lua
-STATUS = $(BUILDDIR)/$(NAME)-status.lua
-LOADER = $(BUILDDIR)/fontloader-$(shell date +%F).lua
-RESOURCES = $(GLYPHS) $(CHARS) $(LOADER) $(STATUS)
-SOURCE = $(DOCSRC) $(LOADERSRC) $(MANSRC)
-SOURCE += $(SRC) README COPYING Makefile NEWS $(RESOURCESCRIPTS)
-
-# Files grouped by installation location
-SCRIPTSTATUS = $(TOOL) $(RESOURCESCRIPTS)
-RUNSTATUS = $(filter-out $(SCRIPTSTATUS),$(SRC))
-DOCSTATUS = $(DOCPDF) $(DOTPDF) README NEWS COPYING
-SRCSTATUS = $(DOCSRC) $(MANSRC) $(GRAPHSRC) Makefile
-
-# The following definitions should be equivalent
-# ALL_STATUS = $(RUNSTATUS) $(DOCSTATUS) $(SRCSTATUS)
-ALL_STATUS = $(RESOURCES) $(SOURCE)
-
-# Installation locations
-FORMAT = luatex
-SCRIPTDIR = $(TEXMFROOT)/scripts/$(NAME)
-RUNDIR = $(TEXMFROOT)/tex/$(FORMAT)/$(NAME)
-DOCDIR = $(TEXMFROOT)/doc/$(FORMAT)/$(NAME)
-MAN1DIR = $(TEXMFROOT)/doc/man/man1/
-MAN5DIR = $(TEXMFROOT)/doc/man/man5/
-SRCDIR = $(TEXMFROOT)/source/$(FORMAT)/$(NAME)
-TEXMFROOT = $(shell kpsewhich --var-value TEXMFHOME)
-
-# CTAN-friendly subdirectory for packaging
-DISTDIR = $(BUILDDIR)/$(NAME)
-
-CTAN_ZIPFILE = $(NAME).zip
-CTAN_ZIPSIG = $(BUILDDIR)/$(CTAN_ZIPFILE).asc
-TDS_ZIPFILE = $(NAME).tds.zip
-CTAN_ZIP = $(BUILDDIR)/$(CTAN_ZIPFILE)
-TDS_ZIP = $(BUILDDIR)/$(TDS_ZIPFILE)
-ZIPS = $(CTAN_ZIP) $(TDS_ZIP)
-
-LUA = texlua
-
-## For now the $(BUILDDIR) is hardcoded in the scripts
-## but we might just as well pass it to them by as environment
-## variables.
-DO_GLYPHS = $(LUA) $(GLYPHSCRIPT) > /dev/null
-DO_CHARS = $(LUA) $(CHARSCRIPT) > /dev/null
-DO_STATUS = $(LUA) $(STATUSSCRIPT) --fontloader=$(LOADER) >/dev/null
-DO_IMPORT = $(LUA) $(IMPORTSCRIPT) import >/dev/null
-DO_PACKAGE = $(LUA) $(IMPORTSCRIPT) package $(LOADER) >/dev/null
-
-define check-lua-files
- at echo validating syntax
- at for f in $$(find . -name '*.lua') ; do \
- echo -n checking $$f ...; \
- if texluac -p $$f &>/dev/null; then \
- echo -e " \e[1;32mgood.\e[m"; \
- else \
- echo -e " \e[1;31mBAD.\e[m"; \
- exit 1; \
- fi; \
-done
-endef
-
-show: showtargets
-check:
- $(check-lua-files)
-
-all: ctan
-builddir: $(BUILDDIR)
-resources: $(RESOURCES)
-chars: $(CHARS)
-status: $(STATUS)
-package: loader
-loader: $(LOADER)
-ctan: $(CTAN_ZIP)
-tds: $(TDS_ZIP)
-import:
- $(DO_IMPORT)
-
-graph: $(DOTPDF)
-doc: $(DOCS)
-pdf: $(DOCPDF)
-manual: $(MANPAGES)
-
-$(DOTPDF):
- @$(MAKE) -C $(DOCSRCDIR) graph
-
-$(DOCPDF):
- @$(MAKE) -C $(DOCSRCDIR) doc
-
-$(MANPAGES):
- @$(MAKE) -C $(DOCSRCDIR) manuals
-
-$(GLYPHS): builddir
- $(DO_GLYPHS)
-
-$(CHARS): builddir
- $(DO_CHARS)
-
-$(STATUS): builddir loader
- $(DO_STATUS)
-
-$(LOADER): builddir
- $(DO_PACKAGE)
-
-$(BUILDDIR): /dev/null
- mkdir -p $(BUILDDIR)
-
-define make-ctandir
-@$(RM) -rf -- $(DISTDIR)
- at mkdir -p $(DISTDIR) && cp $(RESOURCES) $(DOCPDF) $(VGND) $(CONFDEMO) $(SOURCE) $(DISTDIR)
-endef
-
-$(CTAN_ZIP): $(DOCS) $(SOURCE) $(TDS_ZIP)
- @echo "Making $@ for CTAN upload."
- @$(RM) -- $@
- $(make-ctandir)
- @cd $(BUILDDIR) && zip -r -9 $(CTAN_ZIPFILE) $(TDS_ZIPFILE) $(NAME) >/dev/null
-
-$(CTAN_ZIPSIG): $(CTAN_ZIP)
- @echo "Signing package $(CTAN_ZIP)"
- @$(RM) -- $@
- @gpg --batch --armor --detach-sign "$(CTAN_ZIP)"
-
-define run-install-doc
- at mkdir -p $(DOCDIR) && cp -- $(DOCSTATUS) $(VGND) $(CONFDEMO) $(DOCDIR)
- at mkdir -p $(SRCDIR) && cp -- $(SRCSTATUS) $(SRCDIR)
- at mkdir -p $(MAN1DIR) && cp -- $(TOOLMAN) $(MAN1DIR)
- at mkdir -p $(MAN5DIR) && cp -- $(CONFMAN) $(MAN5DIR)
-endef
-
-define run-install
- at mkdir -p $(SCRIPTDIR) && cp -- $(SCRIPTSTATUS) $(SCRIPTDIR)
- at mkdir -p $(RUNDIR) && cp -- $(RESOURCES) $(RUNSTATUS) $(RUNDIR)
- at mkdir -p $(RUNDIR) && cp -- $(LOADERSRC) $(RUNDIR)
-endef
-
-$(TDS_ZIP): TEXMFROOT=./tmp-texmf
-$(TDS_ZIP): $(DOCS) $(ALL_STATUS) check
- @echo "Making TDS-ready archive $@."
- @$(RM) -- $@
- $(run-install-doc)
- $(run-install)
- @cd $(TEXMFROOT) && zip -9 ../$@ -r . >/dev/null
- @$(RM) -r -- $(TEXMFROOT)
-
-sign: $(CTAN_ZIPSIG)
-
-.PHONY: package install manifest clean mrproper show showtargets
-.PHONY: check import news tds ctan sign package loader
-
-ifndef DESTDIR
-install:
- $(error "in order to install you need to provide $$DESTDIR")
-else
-install: $(TDS_ZIP)
- $(info installing to destination “$(DESTDIR)”)
- install -dm755 "$(DESTDIR)"
- unzip "$(TDS_ZIP)" -d "$(DESTDIR)"
-endif
-
-manifest:
- @echo "Source files:"
- @for f in $(SOURCE); do echo $$f; done
- @echo ""
- @echo "Derived files:"
- @for f in $(GENERATED); do echo $$f; done
-
-CLEANEXTS = log aux toc idx ind ilg out
-CLEANME = $(foreach ext,$(CLEANEXTS),$(wildcard *.$(ext)))
-CLEANME += $(foreach ext,$(CLEANEXTS),$(wildcard $(BUILDDIR)/*$(ext)))
-
-clean:
- $(MAKE) -C $(DOCSRCDIR) $@
- @$(RM) -- $(CLEANME)
-
-mrproper: clean
- $(MAKE) -C $(DOCSRCDIR) $@
- @$(RM) -- $(GENERATED) $(ZIPS) $(GLYPHSOURCE)
- @$(RM) -r -- $(BUILDDIR)
-
-###############################################################################
-showtargets:
- @echo "Available targets:"
- @echo
- @echo " check check Lua files for syntax errors"
- @echo
- @echo " doc compile PDF documentation"
- @echo " resources generate resource files (chars, glyphs)"
- @echo
- @echo " pdf build luaotfload.pdf"
- @echo " manual crate manpages for luaotfload-tool(1) and"
- @echo " luaotfload.conf(5) (requires Docutils)"
- @echo " graph generate file graph (requires GraphViz)"
- @echo
- @echo " loader merge fontloader"
- @echo " chars import char-def.lua as luaotfload-characters.lua"
- @echo " status create repository info (luaotfload-status.lua)"
- @echo
- @echo " import grab files from upstream"
- @echo " package package fontloader"
- @echo
- @echo " tds package a zipball according to the TDS"
- @echo " ctan package a zipball for uploading to CTAN"
- @echo " sign sign zipball"
- @echo
- @echo " clean cleanup side-effects"
- @echo " mrproper cleanup side-effects as well as make targets"
- @echo
-
-# vim:noexpandtab:tabstop=8:shiftwidth=2
Deleted: trunk/Master/texmf-dist/source/luatex/luaotfload/filegraph.dot
===================================================================
--- trunk/Master/texmf-dist/source/luatex/luaotfload/filegraph.dot 2018-09-26 20:49:48 UTC (rev 48770)
+++ trunk/Master/texmf-dist/source/luatex/luaotfload/filegraph.dot 2018-09-26 20:50:34 UTC (rev 48771)
@@ -1,396 +0,0 @@
-strict digraph luaotfload_files { //looks weird with circo ...
- compound = true;
-
-// label = "Schematic of the files included in Luaotfload.";
-// labelloc = "b";
-
- fontsize = "14.4";
- labelfontname = "Iwona Medium Regular";
- fontname = "Iwona Light Regular";
- size = "21cm";
-
- rankdir = LR;
- ranksep = 0.618;
- nodesep = 1.618;
-
- edge [
- arrowhead = onormal,
- fontname = "Iwona Cond Regular",
- penwidth = 1.0,
- ];
- node [
- //penwidth = 0.7,
- fontname = "Liberation Mono",
- fontsize = 12,
- ];
-
-/* ····································································
- * file structure
- * ································································· */
- fontdbutil -> font_names [label="--update",
- style=dashed]
-
- luaotfload -> merged_lua_libs [style=solid]
- luaotfload -> luaotfload_init [label="main()", style=solid]
- luaotfload -> luaotfload_libs [label="main()", style=solid]
-
- fontloader -> merged_luatex_fonts [label="merged",
- style=dotted,
- lhead=cluster_merged]
- fontloader -> merged_context_libs [label="merged",
- style=dotted,
- lhead=cluster_merged]
-
- luaotfload_init -> luaotfload_log [label="init_early()", style=solid]
- luaotfload_init -> luaotfload_basics_gen [label="init_early()", style=solid]
- luaotfload_init -> fontloader [label="init_main()", style=solid]
-
- luaotfload_init -> merged_luatex_fonts [label="unmerged", style=solid]
- luaotfload_init -> merged_context_libs [label="unmerged", style=solid]
-
- merged_luatex_fonts -> font_age [label="luatex-fonts-enc.lua",
- ltail=cluster_merged]
-
- fontdbutil -> fontdbutil_diagnostics [label="--diagnose"]
- fontdbutil -> status [label="version information"]
-
- mkimport -> fontloader [label="merges", style=dashed]
-
- merged_luatex_fonts -> characters [label="luaotfload-auxiliary.lua",
- ltail=cluster_merged]
-
- luaotfload_libs -> font_names [label="luaotfload-database.lua"]
- luaotfload_libs -> otfl_blacklist_cnf [label="luaotfload-database.lua"]
-
-
- mkstatus -> status [label="generates from distribution files",
- style=dashed]
-
- mkglyphlist -> font_age [label="generates from glyphlist.txt",
- style=dashed]
-
- mkcharacters -> characters [label="generates from Context’s char-def.lua",
- style=dashed]
-
- fontdbutil_diagnostics -> status [label="hash files"]
-
- mkimport -> merged_luatex_fonts [label="pulls", style=dashed, constraint=no];
- mkimport -> merged_context_libs [label="pulls", style=dashed, constraint=no];
-
- subgraph { rank = same;
- fontdbutil;
- luaotfload }
-
- subgraph cluster_scripts {
- node [style=filled, color=white];
- style = "filled,rounded";
- color = "#44000011:#CCCCCC77";
- //nodesep = "3.0";
- rank = same;
- label = "Standalone scripts";
- gradientangle=90;
- mkcharacters;
- mkglyphlist;
- mkimport;
- mktest;
- mkstatus;
- }
-
-/* ····································································
- * main files
- * ································································· */
-
- fontdbutil [label = "luaotfload-tool.lua",
- shape = rect,
- width = "3.2cm",
- height = "1.2cm",
- color = "#01012222",
- style = "filled,rounded",
- penwidth=2]
-
- fontdbutil_diagnostics [label = "luaotfload-diagnostics.lua",
- shape = rect,
- width = "3.2cm",
- height = "1.2cm",
- color = "#01012222",
- style = "filled,rounded",
- penwidth=2]
-
- mktest [label = "mktest",
- shape = rect,
- width = "3.2cm",
- height = "0.618cm",
- color = "#FFFFFF66",
- style = "filled,rounded",
- penwidth=2]
-
- mkimport [label = "mkimport",
- shape = rect,
- width = "3.2cm",
- height = "0.618cm",
- color = "#FFFFFF66",
- style = "filled,rounded",
- penwidth=2]
-
- mkstatus [label = "mkstatus",
- shape = rect,
- width = "3.2cm",
- height = "0.618cm",
- color = "#FFFFFF66",
- style = "filled,rounded",
- penwidth=2]
-
- mkglyphlist [label = "mkglyphlist",
- shape = rect,
- width = "3.2cm",
- height = "0.618cm",
- color = "#FFFFFF66",
- style = "filled,rounded",
- penwidth=2]
-
- mkcharacters [label = "mkcharacters",
- shape = rect,
- width = "3.2cm",
- height = "0.618cm",
- color = "#FFFFFF66",
- style = "filled,rounded",
- penwidth=2]
-
- luaotfload [label = "luaotfload-main.lua",
- shape = rect,
- width = "3.2cm",
- height = "1.2cm",
- color = "#01012222",
- style = "filled,rounded",
- penwidth=2]
- /*
- *otfl_fonts [label = "luaotfload-fonts.lua",
- * shape = rect,
- * width = "3.2cm",
- * height = "1.2cm",
- * color = "#01012222",
- * style = "filled,rounded",
- * penwidth=2]
- */
- luaotfload_init [label = "luaotfload-init.lua",
- shape = rect,
- width = "3.2cm",
- height = "1.2cm",
- color = "#44440122",
- style = "filled,rounded",
- penwidth=2]
-
- luaotfload_log [label = "luaotfload-log.lua",
- shape = rect,
- width = "3.2cm",
- height = "1.2cm",
- color = "#44440122",
- style = "filled,rounded",
- penwidth=2]
-
- luaotfload_basics_gen [label = "fontloader-basics-gen.lua",
- shape = rect,
- width = "3.2cm",
- height = "1.2cm",
- color = "#FFFFFF66",
- style = "filled,rounded",
- penwidth=2]
-
- fontloader [label = "fontloader-YY-MM-DD.lua",
- shape = rect,
- width = "3.2cm",
- height = "1.2cm",
- color = "#FFFFFF66",
- style = "filled,rounded",
- penwidth=2]
-
-/* ····································································
- * luaotfload files
- * ································································· */
-
- characters [style = "filled,dashed",
- shape = rect,
- width = "3.2cm",
- fillcolor = "#01012222",
- color = grey40,
- style = "filled,dotted,rounded",
- label = "luaotfload-characters.lua"]
-
- font_age [style = "filled,dashed",
- shape = rect,
- width = "3.2cm",
- fillcolor = "#01012222",
- color = grey40,
- style = "filled,dotted,rounded",
- label = "luaotfload-glyphlist.lua"]
-
- font_names [style = "filled,dashed",
- shape = rect,
- width = "3.2cm",
- fillcolor = "#01012222",
- color = grey40,
- style = "filled,dotted,rounded",
- label = "luaotfload-names.lua.gz\nluaotfload-names.luc"]
-
- status [style = "filled,dashed",
- shape = rect,
- width = "3.2cm",
- fillcolor = "#01012222",
- color = grey40,
- style = "filled,dotted,rounded",
- label = "luaotfload-status.lua"]
-
- otfl_blacklist_cnf [style = "filled,dashed",
- shape = rect,
- width = "3.2cm",
- fillcolor = "#01012222",
- color = grey40,
- style = "filled,dotted,rounded",
- label = "luaotfload-blacklist.cnf"]
-
- luaotfload_libs [
- shape = box,
- style = "filled,rounded",
- color = "grey90",
- fontsize = 10,
- label = <
- <table cellborder="0" bgcolor="#FFFFFFAA">
- <th> <td colspan="2"> <font point-size="12" face="Iwona Italic">Luaotfload Libraries</font> </td> </th>
- <tr> <td>luaotfload-auxiliary.lua</td> <td>luaotfload-features.lua</td> </tr>
- <tr> <td>luaotfload-loaders.lua</td> <td>luaotfload-colors.lua</td> </tr>
- <tr> <td>luaotfload-resolvers.lua</td> <td>luaotfload-letterspace.lua</td> </tr>
- <tr> <td>luaotfload-parsers.lua</td> <td>luaotfload-database.lua</td> </tr>
- <tr> <td>luaotfload-configuration.lua</td><td></td> </tr>
- </table>
- >,
- ]
-
-/* ····································································
- * merged files
- * ································································· */
-
- subgraph cluster_merged {
- node [style=filled, color=white];
- style = "filled,rounded";
- color = "#912CEE33";
- //nodesep = "3.0";
- rank = same;
- label = "Merged Libraries";
- gradientangle=0;
- merged_luatex_fonts;
- merged_context_libs;
- }
-
- fontloader -> merged_luatex_fonts
- fontloader -> merged_context_libs
-
- subgraph cluster_fontloader {
- node [style=filled, color=white];
- style = "filled,rounded";
- color = "bisque";
- //nodesep = "3.0";
- rank = same;
- label = "Fontloader";
- gradientangle=0;
- luaotfload_basics_gen;
- fontloader;
- }
-
- merged_lua_libs [
- shape = box,
- style = "filled,rounded",
- color = "#CCCC1166",
- fontsize = 10,
- fontsize = 10,
- label = <
- <table border="0">
- <th> <td colspan="3"> <font point-size="12" face="Iwona Italic">
- Lualibs – Lua Libraries from Context</font> </td> </th>
- <tr> <td>l-lua.lua</td> <td>l-lpeg.lua</td> <td>l-function.lua</td> </tr>
- <tr> <td>l-string.lua</td> <td>l-table.lua</td> <td>l-io.lua</td> </tr>
- <tr> <td>l-file.lua</td> <td>l-boolean.lua</td> <td>l-math.lua</td> </tr>
- <tr> <td>util-str.lua</td> <td>util-fil.lua</td> </tr>
- </table>
- >,
- ]
-
- merged_luatex_fonts [
- shape = box,
- style = "filled,rounded",
- color = "#FFFFFFAA",
- fontsize = 10,
- label = <
- <table border="0">
- <th> <td colspan="2"> <font point-size="12" face="Iwona Italic">Font Loader (LuaTeX-Fonts)</font> </td> </th>
- <tr>
- <td>luatex-basics-nod.lua</td>
- <td>luatex-basics-chr.lua</td>
- </tr>
- <tr>
- <td>luatex-fonts-enc.lua</td>
- <td>luatex-fonts-syn.lua</td>
- </tr>
- <tr>
- <td>luatex-fonts-ext.lua</td>
- </tr>
- </table>
- >,
- ]
-
- merged_context_libs [
- shape = box,
- style = "filled,rounded",
- color = "#FFFFFFAA",
- fontsize = 10,
- label = <
- <table border="0">
- <th> <td colspan="3"> <font point-size="12" face="Iwona Italic"> Font and Node Libraries from Context </font> </td> </th>
- <tr>
- <td>data-con.lua</td>
- <td>font-ini.lua</td>
- <td>font-con.lua</td>
- </tr>
- <tr>
- <td>font-cid.lua</td>
- <td>font-map.lua</td>
- <td>font-tfm.lua</td>
- </tr>
- <tr>
- <td>font-one.lua</td>
- <td>font-afk.lua</td>
- <td>font-oti.lua</td>
- </tr>
- <tr>
- <td>font-otr.lua</td>
- <td>font-cff.lua</td>
- <td>font-ttf.lua</td>
- </tr>
- <tr>
- <td>font-dsp.lua</td>
- <td>font-oup.lua</td>
- <td>font-otl.lua</td>
- </tr>
- <tr>
- <td>font-oto.lua</td>
- <td>font-otj.lua</td>
- <td>font-ota.lua</td>
- </tr>
- <tr>
- <td>font-ots.lua</td>
- <td>font-osd.lua</td>
- <td>font-lua.lua</td>
- </tr>
- <tr>
- <td>font-def.lua</td>
- <td>font-xtx.lua</td>
- <td>font-gbn.lua</td>
- </tr>
- <tr>
- <td>font-ocl.lua</td>
- </tr>
- </table>
- >,
- ]
-}
-
-// vim:ft=dot:sw=4:ts=4:expandtab
Added: trunk/Master/texmf-dist/source/luatex/luaotfload/fontloader-reference-load-order.lua
===================================================================
--- trunk/Master/texmf-dist/source/luatex/luaotfload/fontloader-reference-load-order.lua (rev 0)
+++ trunk/Master/texmf-dist/source/luatex/luaotfload/fontloader-reference-load-order.lua 2018-09-26 20:50:34 UTC (rev 48771)
@@ -0,0 +1,350 @@
+if not modules then modules = { } end modules ['luatex-fonts'] = {
+ version = 1.001,
+ comment = "companion to luatex-fonts.tex",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- A merged file is generated with:
+--
+-- mtxrun --script package --merge --stripcontext luatex-fonts.lua
+--
+-- A needed resource file is made by:
+--
+-- mtxrun --script context luatex-basics-prepare.tex
+--
+-- A font (generic) database is created with:
+--
+-- mtxrun --script font --reload --simple
+
+-- The following code isolates the generic context code from already defined or to be defined
+-- namespaces. This is the reference loader for plain tex. This generic code is also used in
+-- luaotfload which is a low level lualatex opentype font loader but somehow has gotten a bit
+-- too generic name / prefix, originally set up and maintained by Khaled Hosny. Currently that
+-- set of derived files is maintained by a larger team lead by Philipp Gesang so when there are
+-- issues with this code in latex, you can best contact him. It might make sense then to first
+-- check if context has the same issue. We do our best to keep the interface as clean as possible.
+--
+-- The code base is rather stable now, especially if you stay away from the non generic code. All
+-- relevant data is organized in tables within the main table of a font instance. There are a few
+-- places where in context other code is plugged in, but this does not affect the core code. Users
+-- can (given that their macro package provides this option) access the font data (characters,
+-- descriptions, properties, parameters, etc) of this main table. The documentation is part of
+-- context. There is also a manual for the helper libraries (maintained as part of the cld manuals).
+--
+-- Future versions will probably have some more specific context code removed, like tracing and
+-- obscure hooks, so that we have a more efficient version (and less files too). So, don't depend
+-- too much on low level code that is meant for context as it can change without notice. We might
+-- also add more helper code here, but that depends to what extend metatex (sidetrack of context)
+-- evolves into a low level layer (depends on time, as usual).
+
+-- The code here is the same as in context version 2015.09.11 but the rendering in context can be
+-- different from generic. This can be a side effect of additional callbacks, additional features
+-- and interferences between mechanisms between macro packages. We use the rendering in context
+-- and luatex-plain as reference for issues.
+
+utf = utf or unicode.utf8
+
+-- We have some (global) hooks (for latex):
+
+if not non_generic_context then
+ non_generic_context = { }
+end
+
+if not non_generic_context.luatex_fonts then
+ non_generic_context.luatex_fonts = {
+ -- load_before = nil,
+ -- load_after = nil,
+ -- skip_loading = nil,
+ }
+end
+
+if not generic_context then
+ generic_context = { }
+end
+
+if not generic_context.push_namespaces then
+
+ function generic_context.push_namespaces()
+ -- logs.report("system","push namespace")
+ local normalglobal = { }
+ for k, v in next, _G do
+ normalglobal[k] = v
+ end
+ return normalglobal
+ end
+
+ function generic_context.pop_namespaces(normalglobal,isolate)
+ if normalglobal then
+ -- logs.report("system","pop namespace")
+ for k, v in next, _G do
+ if not normalglobal[k] then
+ generic_context[k] = v
+ if isolate then
+ _G[k] = nil
+ end
+ end
+ end
+ for k, v in next, normalglobal do
+ _G[k] = v
+ end
+ -- just to be sure:
+ setmetatable(generic_context,_G)
+ else
+ logs.report("system","fatal error: invalid pop of generic_context")
+ os.exit()
+ end
+ end
+
+end
+
+local whatever = generic_context.push_namespaces()
+
+-- We keep track of load time by storing the current time. That way we cannot be accused
+-- of slowing down loading too much. Anyhow, there is no reason for this library to perform
+-- slower in any other package as it does in context.
+--
+-- Please don't update to this version without proper testing. It might be that this version
+-- lags behind stock context and the only formal release takes place around tex live code
+-- freeze.
+
+local starttime = os.gettimeofday()
+
+-- As we don't use the context file searching, we need to initialize the kpse library. As the
+-- progname can be anything we will temporary switch to the context namespace if needed. Just
+-- adding the context paths to the path specification is somewhat faster.
+--
+-- Now, with lua 5.2 being used we might create a special ENV for this.
+
+-- kpse.set_program_name("luatex")
+
+-- One can define texio.reporter as alternative terminal/log writer. That's as far
+-- as I want to go with this.
+
+local ctxkpse = nil
+local verbose = true
+
+if not logs or not logs.report then
+ if not logs then
+ logs = { }
+ end
+ function logs.report(c,f,...)
+ local r = texio.reporter or texio.write_nl
+ if f then
+ r(c .. " : " .. string.format(f,...))
+ else
+ r("")
+ end
+ end
+end
+
+local function loadmodule(name,continue)
+ local foundname = kpse.find_file(name,"tex") or ""
+ if not foundname then
+ if not ctxkpse then
+ ctxkpse = kpse.new("luatex","context")
+ end
+ foundname = ctxkpse:find_file(name,"tex") or ""
+ end
+ if foundname == "" then
+ if not continue then
+ logs.report("system","unable to locate file '%s'",name)
+ os.exit()
+ end
+ else
+ if verbose then
+ logs.report("system","loading '%s'",foundname) -- no file.basename yet
+ end
+ dofile(foundname)
+ end
+end
+
+if non_generic_context.luatex_fonts.load_before then
+ loadmodule(non_generic_context.luatex_fonts.load_before,true)
+end
+
+if non_generic_context.luatex_fonts.skip_loading ~= true then
+
+ loadmodule('luatex-fonts-merged.lua',true)
+
+ if fonts then
+
+ if not fonts._merge_loaded_message_done_ then
+ texio.write_nl("log", "!")
+ texio.write_nl("log", "! I am using the merged version of 'luatex-fonts.lua' here. If")
+ texio.write_nl("log", "! you run into problems or experience unexpected behaviour, and")
+ texio.write_nl("log", "! if you have ConTeXt installed you can try to delete the file")
+ texio.write_nl("log", "! 'luatex-font-merged.lua' as I might then use the possibly")
+ texio.write_nl("log", "! updated libraries. The merged version is not supported as it")
+ texio.write_nl("log", "! is a frozen instance. Problems can be reported to the ConTeXt")
+ texio.write_nl("log", "! mailing list.")
+ texio.write_nl("log", "!")
+ end
+
+ fonts._merge_loaded_message_done_ = true
+
+ else
+
+ -- The following helpers are a bit overkill but I don't want to mess up
+ -- context code for the sake of general generality. Around version 1.0
+ -- there will be an official api defined.
+ --
+ -- So, I will strip these libraries and see what is really needed so that
+ -- we don't have this overhead in the generic modules. The next section
+ -- is only there for the packager, so stick to using luatex-fonts with
+ -- luatex-fonts-merged.lua and forget about the rest. The following list
+ -- might change without prior notice (for instance because we shuffled
+ -- code around).
+
+ loadmodule("l-lua.lua")
+ loadmodule("l-lpeg.lua")
+ loadmodule("l-function.lua")
+ loadmodule("l-string.lua")
+ loadmodule("l-table.lua")
+ loadmodule("l-io.lua")
+ loadmodule("l-file.lua")
+ loadmodule("l-boolean.lua")
+ loadmodule("l-math.lua")
+ loadmodule("l-unicode.lua")
+
+ -- A few slightly higher level support modules:
+
+ loadmodule("util-str.lua")
+ loadmodule("util-fil.lua")
+
+ -- The following modules contain code that is either not used at all
+ -- outside context or will fail when enabled due to lack of other
+ -- modules.
+
+ -- First we load a few helper modules. This is about the miminum needed
+ -- to let the font modules do their work. Don't depend on their functions
+ -- as we might strip them in future versions of this generic variant.
+
+ loadmodule('luatex-basics-gen.lua')
+ loadmodule('data-con.lua')
+
+ -- We do need some basic node support. The code in there is not for
+ -- general use as it might change.
+
+ loadmodule('luatex-basics-nod.lua')
+
+ -- We ship a resources needed for font handling (more might end up here).
+
+ loadmodule('luatex-basics-chr.lua')
+
+ -- Now come the font modules that deal with traditional tex fonts as well
+ -- as open type fonts.
+ --
+ -- The font database file (if used at all) must be put someplace visible
+ -- for kpse and is not shared with context. The mtx-fonts script can be
+ -- used to generate this file (using the --reload --force --simple option).
+
+ loadmodule('font-ini.lua')
+ loadmodule('luatex-fonts-mis.lua')
+ loadmodule('font-con.lua')
+ loadmodule('luatex-fonts-enc.lua')
+ loadmodule('font-cid.lua')
+ loadmodule('font-map.lua')
+
+ -- We use a bit simpler database because using the context one demands
+ -- loading more helper code and although it is more flexible (more ways
+ -- to resolve and so) it will never be uses in plain/latex anyway, so
+ -- let's stick to a simple approach.
+
+ loadmodule('luatex-fonts-syn.lua')
+
+ -- We need some helpers.
+
+ loadmodule('font-vfc.lua')
+
+ -- This is the bulk of opentype code.
+
+ loadmodule('font-otr.lua')
+ loadmodule('font-oti.lua')
+ loadmodule('font-ott.lua')
+ loadmodule('font-cff.lua')
+ loadmodule('font-ttf.lua')
+ loadmodule('font-dsp.lua')
+ loadmodule('font-oup.lua')
+ loadmodule('font-otl.lua')
+ loadmodule('font-oto.lua')
+ loadmodule('font-otj.lua')
+ loadmodule('font-ota.lua')
+ loadmodule('font-ots.lua')
+ loadmodule('font-osd.lua')
+ loadmodule('font-ocl.lua')
+ loadmodule('font-otc.lua')
+
+ -- The code for type one fonts.
+
+ loadmodule('font-onr.lua')
+ loadmodule('font-one.lua')
+ loadmodule('font-afk.lua')
+
+ -- And for traditional TeX fonts.
+
+ loadmodule('font-tfm.lua')
+
+ -- Some common code.
+
+ loadmodule('font-lua.lua')
+ loadmodule('font-def.lua')
+
+ -- We support xetex compatible specifiers (plain/latex only).
+
+ loadmodule('luatex-fonts-def.lua') -- was font-xtx.lua
+
+ -- Here come some additional features.
+
+ loadmodule('luatex-fonts-ext.lua')
+ loadmodule('font-imp-tex.lua')
+ loadmodule('font-imp-ligatures.lua')
+ loadmodule('font-imp-italics.lua')
+ loadmodule('font-imp-effects.lua')
+ loadmodule('luatex-fonts-lig.lua')
+
+ -- We need to plug into a callback and the following module implements the
+ -- handlers. Actual plugging in happens later.
+
+ loadmodule('luatex-fonts-gbn.lua')
+
+ end
+
+end
+
+if non_generic_context.luatex_fonts.load_after then
+ loadmodule(non_generic_context.luatex_fonts.load_after,true)
+end
+
+resolvers.loadmodule = loadmodule
+
+-- In order to deal with the fonts we need to initialize some callbacks. One can overload them later
+-- on if needed. First a bit of abstraction.
+
+generic_context.callback_ligaturing = false
+generic_context.callback_kerning = false
+generic_context.callback_pre_linebreak_filter = nodes.simple_font_handler
+generic_context.callback_hpack_filter = nodes.simple_font_handler
+generic_context.callback_define_font = fonts.definers.read
+
+-- The next ones can be done at a different moment if needed. You can create a generic_context namespace
+-- and set no_callbacks_yet to true, load this module, and enable the callbacks later. So, there is really
+-- *no* need to create a alternative for luatex-fonts.lua and luatex-fonts-merged.lua: just load this one
+-- and overload if needed.
+
+if not generic_context.no_callbacks_yet then
+
+ callback.register('ligaturing', generic_context.callback_ligaturing)
+ callback.register('kerning', generic_context.callback_kerning)
+ callback.register('pre_linebreak_filter', generic_context.callback_pre_linebreak_filter)
+ callback.register('hpack_filter', generic_context.callback_hpack_filter)
+ callback.register('define_font' , generic_context.callback_define_font)
+
+end
+
+-- We're done.
+
+logs.report("system","luatex-fonts.lua loaded in %0.3f seconds", os.gettimeofday()-starttime)
+
+generic_context.pop_namespaces(whatever)
Property changes on: trunk/Master/texmf-dist/source/luatex/luaotfload/fontloader-reference-load-order.lua
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/source/luatex/luaotfload/fontloader-reference-load-order.tex
===================================================================
--- trunk/Master/texmf-dist/source/luatex/luaotfload/fontloader-reference-load-order.tex (rev 0)
+++ trunk/Master/texmf-dist/source/luatex/luaotfload/fontloader-reference-load-order.tex 2018-09-26 20:50:34 UTC (rev 48771)
@@ -0,0 +1,140 @@
+%D \module
+%D [ file=luatex-fonts,
+%D version=2009.12.01,
+%D title=\LUATEX\ Support Macros,
+%D subtitle=Generic \OPENTYPE\ Font Handler,
+%D author=Hans Hagen,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+
+%D \subject{Welcome}
+%D
+%D This file is one of a set of basic functionality enhancements
+%D for \LUATEX\ derived from the \CONTEXT\ \MKIV\ code base. Please
+%D don't polute the \type {luatex-*} namespace with code not coming
+%D from the \CONTEXT\ development team as we may add more files.
+%D
+%D As this is an experimental setup, it might not always work out as
+%D expected. Around \LUATEX\ version 0.50 we expect the code to be
+%D more or less okay.
+%D
+%D This file implements a basic font system for a bare \LUATEX\
+%D system. By default \LUATEX\ only knows about the classic \TFM\
+%D fonts but it can read other font formats and pass them to \LUA.
+%D With some glue code one can then construct a suitable \TFM\
+%D representation that \LUATEX\ can work with. For more advanced font
+%D support a bit more code is needed that needs to be hooked
+%D into the callback mechanism.
+%D
+%D This file is currently rather simple: it just loads the \LUA\ file
+%D with the same name. An example of a \type {luatex.tex} file that is
+%D just plain \TEX:
+%D
+%D \starttyping
+%D \catcode`\{=1 % left brace is begin-group character
+%D \catcode`\}=2 % right brace is end-group character
+%D
+%D \input plain
+%D
+%D \everyjob\expandafter{\the\everyjob\input luatex-fonts\relax}
+%D
+%D \dump
+%D \stoptyping
+%D
+%D We could load the \LUA\ file in \type {\everyjob} but maybe some
+%D day we need more here.
+%D
+%D When defining a font you can use two prefixes. A \type {file:}
+%D prefix forced a file search, while a \type {name:} prefix will
+%D result in consulting the names database. Such a database can be
+%D generated with:
+%D
+%D \starttyping
+%D mtxrun --usekpse --script fonts --names
+%D \stoptyping
+%D
+%D This will generate a file \type {luatex-fonts-names.lua} that has
+%D to be placed in a location where it can be found by \KPSE. Beware:
+%D the \type {--kpseonly} flag is only used outside \CONTEXT\ and
+%D provides very limited functionality, just enough for this task.
+%D
+%D The code loaded here does not come out of thin air, but is mostly
+%D shared with \CONTEXT, however, in that macropackage we go beyond
+%D what is provided here. When you use the code packaged here you
+%D need to keep a few things in mind:
+%D
+%D \startitemize
+%D
+%D \item This subsystem will be extended, improved etc. in about the
+%D same pace as \CONTEXT\ \MKIV. However, because \CONTEXT\ provides a
+%D rather high level of integration not all features will be supported
+%D in the same quality. Use \CONTEXT\ if you want more goodies.
+%D
+%D \item There is no official \API\ yet, which means that using
+%D functions implemented here is at your own risk, in the sense that
+%D names and namespaces might change. There will be a minimal \API\
+%D defined once \LUATEX\ version 1.0 is out. Instead of patching the
+%D files it's better to overload functions if needed.
+%D
+%D \item The modules are not stripped too much, which makes it
+%D possible to benefit from improvements in the code that take place
+%D in the perspective of \CONTEXT\ development. They might be split a
+%D bit more in due time so the baseline might become smaller.
+%D
+%D \item The code is maintained and tested by the \CONTEXT\
+%D development team. As such it might be better suited for this macro
+%D package and integration in other systems might demand some
+%D additional wrapping. Problems can be reported to the team but as we
+%D use \CONTEXT\ \MKIV\ as baseline, you'd better check if the problem
+%D is a general \CONTEXT\ problem too.
+%D
+%D \item The more high level support for features that is provided in
+%D \CONTEXT\ is not part of the code loaded here as it makes no sense
+%D elsewhere. Some experimental features are not part of this code
+%D either but some might show up later.
+%D
+%D \item Math font support will be added but only in its basic form
+%D once that the Latin Modern and \TEX\ Gyre math fonts are
+%D available.
+%D
+%D \item At this moment the more nifty speed-ups are not enabled
+%D because they work in tandem with the alternative file handling
+%D that \CONTEXT\ uses. Maybe around \LUATEX\ 1.0 we will bring some
+%D speedup into this code too (if it pays off at all).
+%D
+%D \item The code defines a few global tables. If this code is used
+%D in a larger perspective then you can best make sure that no
+%D conflicts occur. The \CONTEXT\ package expects users to work in
+%D their own namespace (\type {userdata}, \type {thirddata}, \type
+%D {moduledata} or \type {document}. The team takes all freedom to
+%D use any table at the global level but will not use tables that are
+%D named after macro packages. Later the \CONTEXT\ might operate in
+%D a more controlled namespace but it has a low priority.
+%D
+%D \item There is some tracing code present but this is not enabled
+%D and not supported outside \CONTEXT\ either as it integrates quite
+%D tightly into \CONTEXT. In case of problems you can use \CONTEXT\
+%D for tracking down problems.
+%D
+%D \item Patching the code in distributions is dangerous as it might
+%D fix your problem but introduce new ones for \CONTEXT. So, best keep
+%D the original code as it is.
+%D
+%D \item Attributes are (automatically) taken from the range 127-255 so
+%D you'd best not use these yourself.
+%D
+%D \stopitemize
+%D
+%D If this all sounds a bit tricky, keep in mind that it makes no sense
+%D for us to maintain multiple code bases and we happen to use \CONTEXT.
+%D
+%D For more details about how the font subsystem works we refer to
+%D publications in \TEX\ related journals, the \CONTEXT\ documentation,
+%D and the \CONTEXT\ wiki.
+
+\directlua {
+ if not fonts then
+ dofile(kpse.find_file("luatex-fonts.lua","tex"))
+ end
+}
+
+\endinput
Property changes on: trunk/Master/texmf-dist/source/luatex/luaotfload/fontloader-reference-load-order.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Deleted: trunk/Master/texmf-dist/source/luatex/luaotfload/luaotfload-latex.tex
===================================================================
--- trunk/Master/texmf-dist/source/luatex/luaotfload/luaotfload-latex.tex 2018-09-26 20:49:48 UTC (rev 48770)
+++ trunk/Master/texmf-dist/source/luatex/luaotfload/luaotfload-latex.tex 2018-09-26 20:50:34 UTC (rev 48771)
@@ -1,486 +0,0 @@
-\suppresslongerror1%% sigh ...
-%% Copyright (C) 2009-2015
-%%
-%% by Elie Roux <elie.roux at telecom-bretagne.eu>
-%% and Khaled Hosny <khaledhosny at eglug.org>
-%% and Philipp Gesang <phg at phi-gamma.net>
-%%
-%% This file is part of Luaotfload.
-%%
-%% Home: https://github.com/lualatex/luaotfload
-%% Support: <lualatex-dev at tug.org>.
-%%
-%% Luaotfload is under the GPL v2.0 (exactly) license.
-%%
-%% ----------------------------------------------------------------------------
-%%
-%% Luaotfload is free software; you can redistribute it and/or
-%% modify it under the terms of the GNU General Public License
-%% as published by the Free Software Foundation; version 2
-%% of the License.
-%%
-%% Luaotfload is distributed in the hope that it will be useful,
-%% but WITHOUT ANY WARRANTY; without even the implied warranty of
-%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-%% GNU General Public License for more details.
-%%
-%% You should have received a copy of the GNU General Public License
-%% along with Luaotfload; if not, see <http://www.gnu.org/licenses/>.
-%%
-%% ----------------------------------------------------------------------------
-%%
-
-\documentclass{ltxdoc}
-
-\makeatletter
-
-\usepackage {metalogo,multicol,fancyvrb,xspace}
-\usepackage [x11names] {xcolor}
-
-\def \primarycolor {DodgerBlue4} %%-> rgb 16 78 139 | #104e8b
-\def \secondarycolor {Goldenrod4} %%-> rgb 139 105 200 | #8b6914
-
-\usepackage[
- bookmarks=true,
- colorlinks=true,
- linkcolor=\primarycolor,
- urlcolor=\secondarycolor,
- citecolor=\primarycolor,
- pdftitle={The Luaotfload package},
- pdfsubject={OpenType layout system for Plain TeX and LaTeX},
- pdfauthor={Elie Roux & Khaled Hosny & Philipp Gesang},
- pdfkeywords={luatex, lualatex, unicode, opentype}
-]{hyperref}
-
-\usepackage {fontspec}
-\usepackage {unicode-math}
-
-\setmainfont[
-% Numbers = OldStyle, %% buggy with font cache
- Ligatures = TeX,
- BoldFont = {Linux Libertine O Bold},
- ItalicFont = {Linux Libertine O Italic},
- SlantedFont = {Linux Libertine O Italic},
-]{Linux Libertine O}
-\setmonofont[Ligatures=TeX,Scale=MatchLowercase]{Liberation Mono}
-%setsansfont[Ligatures=TeX]{Linux Biolinum O}
-\setsansfont[Ligatures=TeX,Scale=MatchLowercase]{Iwona Medium}
-%setmathfont{XITS Math}
-
-\usepackage{hologo}
-
-\newcommand\TEX {\TeX\xspace}
-\newcommand\LUA {Lua\xspace}
-\newcommand\PDFTEX {pdf\TeX\xspace}
-\newcommand\LUATEX {Lua\TeX\xspace}
-\newcommand\XETEX {\XeTeX\xspace}
-\newcommand\LATEX {\LaTeX\xspace}
-\newcommand\LUALATEX {Lua\LaTeX\xspace}
-\newcommand\CONTEXT {Con\TeX t\xspace}
-\newcommand\OpenType {\identifier{Open\kern-.25ex Type}\xspace}
-
-%% \groupedcommand, with some omissions taken from syst-aux.mkiv
-\let \handlegroupnormalbefore \relax
-\let \handlegroupnormalafter \relax
-
-\protected \def \handlegroupnormal #1#2{%
- \bgroup % 1
- \def \handlegroupbefore {#1}%
- \def \handlegroupafter {#2}%
- \afterassignment \handlegroupnormalbefore
- \let \next =
-}
-
-\def \handlegroupnormalbefore {%
- \bgroup % 2
- \handlegroupbefore
- \bgroup % 3
- \aftergroup \handlegroupnormalafter%
-}
-
-\def \handlegroupnormalafter {%
- \handlegroupafter
- \egroup % 3
- \egroup % 2
-}
-
-\let \groupedcommand \handlegroupnormal %% only the two arg version
-
-\def \definehighlight [#1][#2]{%
- \ifcsname #1\endcsname\else
- \expandafter\def\csname #1\endcsname{%
- \leavevmode
- \groupedcommand {#2}\empty%
- }
- \fi%
-}
-
-%% old, simplistic definition: obsolete now that we have
-%% \groupedcommand
-%\def\definehighlight[#1][#2]%
- %{\ifcsname #1\endcsname\else
- %\expandafter\def\csname #1\endcsname%
- %{\bgroup#2\csname #1_indeed\endcsname}
- %\expandafter\def\csname #1_indeed\endcsname##1%
- %{##1\egroup}%
- %\fi}
-
-\def\restoreunderscore{\catcode`\_=12\relax}
-
-\definehighlight [fileent][\ttfamily\restoreunderscore] %% files, dirs
-\definehighlight [texmacro][\sffamily\itshape\textbackslash] %% cs
-\definehighlight [luaident][\sffamily\itshape\restoreunderscore] %% lua identifiers
-\definehighlight [identifier][\sffamily] %% names
-\definehighlight [abbrev][\rmfamily\scshape] %% acronyms
-\definehighlight [emphasis][\rmfamily\slshape] %% level 1 emph
-
-\definehighlight [Largefont][\Large] %% font size
-\definehighlight [smallcaps][\sc] %% font feature
-\definehighlight [nonproportional][\tt] %% font switch
-
-\newcommand*\email[1]{\href{mailto:#1}{#1}}
-
-\renewcommand\partname{Part}%% gets rid of the stupid “file” heading
-
-\usepackage{syntax}%% bnf for font request syntax
-
-\usepackage{titlesec}
-
-\def\movecountertomargin#1{\llap{\rmfamily\upshape#1\hskip2em}}
-\def\zeropoint{0pt}
-\titleformat \part
- {\normalsize\rmfamily\bfseries}
- {\movecountertomargin\thepart} \zeropoint {}
-\titleformat \section
- {\normalsize\rmfamily\scshape}
- {\movecountertomargin\thesection} \zeropoint {}
-\titleformat \subsection
- {\small\rmfamily\itshape}
- {\movecountertomargin\thesubsection} \zeropoint {}
-\titleformat \subsubsection
- {\normalsize\rmfamily\upshape}
- {\movecountertomargin\thesubsubsection} \zeropoint {}
-
-\usepackage{tocloft}
-\renewcommand \cftpartfont {\rmfamily\upshape}
-\renewcommand \cftsecfont {\rmfamily\upshape}
-\renewcommand \cftsubsecfont {\rmfamily\upshape}
-\setlength \cftbeforepartskip {1ex}
-\setlength \cftbeforesecskip {1ex}
-
-\VerbatimFootnotes
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% structurals
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-\def \definestructural #1{%
- \expandafter \let \csname end#1\endcsname \relax
-
- \expandafter \def \csname begin#1\endcsname {%
- \@ifnextchar[{\csname begin#1indeed\endcsname}
- {\csname begin#1indeed\endcsname[]}%
- }
-
- \expandafter \def \csname begin#1indeed\endcsname [##1]##2{%
- \edef \first {##1}%
- \ifx \first \empty
- \csname #1\endcsname [##2]{##2}%
- \else
- \csname #1\endcsname [\first]{##2}%
- \fi
- }
-}
-
-\definestructural {section}
-\definestructural {subsection}
-\definestructural {subsubsection}
-
-\def \fakesection #1{\section*{#1}}
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% inline verbatim
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-%% Context offers both \type{…} and \type<<…>>, but not an unbalanced
-%% one that we could map directly onto Latex’s \verb|…|.
-
-\usepackage {listings}
-\usepackage {luatexbase}
-\lstset {
- basicstyle=\ttfamily,
-}
-
-%\let \inlinecode \lstinline
-\protected \def \inlinecode {\lstinline}
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% codelistings; this sucks hard since we lack access to buffers
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-\newcount \othercatcode \othercatcode 12
-\newcount \activecatcode \othercatcode 13
-
-\newcatcodetable \vrbcatcodes
-\setcatcodetable \vrbcatcodes {%
- \catcodetable \CatcodeTableIniTeX
- \catcode 9 \othercatcode %% \tabasciicode
- \catcode 13 \othercatcode %% \endoflineasciicode
- \catcode 12 \othercatcode %% \formfeedasciicode
- \catcode 26 \othercatcode %% \endoffileasciicode
- \catcode 32 \othercatcode %% \spaceasciicode
-}
-
-\directlua {
- document = document or { }
- document.vrbcatcodesidx = tonumber (\the \vrbcatcodes)
-}
-
-\newcatcodetable \literalcatcodes
-\setcatcodetable \literalcatcodes {%
- \catcodetable \CatcodeTableString
- \catcode 32 \activecatcode %% \spaceasciicode
-}
-
-\def \listingsurroundskip {\vskip \baselineskip}
-
-\def \beginlisting {%
- \noindent
- \begingroup
- \catcodetable \vrbcatcodes
- \beginlistingindeed%
-}
-
-\directlua {
- local texsprint = tex.sprint
- local stringis_empty = string.is_empty
- local stringsub = string.sub
- local stringgsub = string.gsub
- %local backslash = unicode.utf8.char (0x200c)
- local backslash = unicode.utf8.char (0x5c)
- local escaped = [[\string\string\string\]]
- document.printlines = function (buffer)
- local lines = string.explode (buffer, "\noexpand\n")
- print ""
- for i, line in next, lines do
- local line = stringgsub (line, backslash, escaped)
- if stringis_empty (line) then
- print (i, "listing: <empty line />")
- texsprint [[\string\listingpar]]
- else
- local line = [[\string\beginlistingline]]
- .. line
- .. [[\string\endlistingline]]
- .. [[\string\listingpar]]
- print (i, "listing: «" .. line .. "»")
- texsprint (document.vrbcatcodesidx, line)
- end
- end
- end
-}
-
-\def \listingpar {\endgraf}
-
-\let \endlistingline \relax
-\let \endlisting \relax
-
-\protected \def \beginlistingline{%
- \leavevmode
- \begingroup
- \beginlistinglineindeed%
-}
-
-\def \beginlistinglineindeed #1\endlistingline{%
- \endgroup
- \hbox{%
- \addfontfeature {RawFeature=-tlig;-liga}%% So one can’t just turn them all off at once using the ``Ligatures`` key?
- \obeyspaces
- #1}%
-}
-
-\def \beginlistingindeed#1\endlisting{%
- \endgroup
- \begingroup
- \endgraf
- \listingsurroundskip
- \ttfamily
- \small
- \parindent = 0em
- \leftskip = 2em
- \hangindent = 2em
- \directlua{document.printlines ([==[\detokenize {#1}]==])}%
- \listingsurroundskip
- \endgroup
-}
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% enumerations and lists
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-\def \definelist [#1]#2{% name, itemcode
- \expandafter \def \csname begin#1\endcsname {%
- \begin {itemize}
- \let \normalitem = \item
- \def \altitem ####1{%
- \def \first {####1}%
- #2
- }
- \let \beginnormalitem \item
- \let \endnormalitem \relax
- \let \beginaltitem \altitem
- \let \endaltitem \relax
- }
-
- \expandafter \def \csname end#1\endcsname {%
- \end {itemize}
- }
-}
-
-\definelist [descriptions]{\normalitem {\textbf \first}\hfill\break}
-\definelist [definitions]{\normalitem {\fileent {\first}}}
-\definelist [filelist]{\normalitem {\fileent {\first}}\space--\hskip 1em}
-\definelist [functionlist]{\normalitem {\luaident {\first}}\hfill\break}
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% columns
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-\def \begindoublecolumns {\begin {multicols} {2}}
-\def \enddoublecolumns {\end {multicols}}
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% alignment
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-\def \begincentered {\begin {center}}
-\def \endcentered {\end {center}}
-
-\def \beginnarrower {\begin {quote}}
-\def \endnarrower {\end {quote}}
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% special elements
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-\let \beginfrontmatter \relax
-\let \endfrontmatter \relax
-
-\def \beginabstractcontent {\begin {abstract}}
-\def \endabstractcontent {\end {abstract}}
-
-\let \setdocumenttitle \title
-\let \setdocumentdate \date
-\let \setdocumentauthor \author
-\let \typesetdocumenttitle \maketitle
-
-\AtBeginDocument {%% seriously?
- \let \typesetcontent \tableofcontents%
-}
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% floats
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-%% syntax definition
-\def \beginsyntaxfloat #1#2{%% #1:label #2:caption
- \begin {figure} [b]
- \edef \syntaxlabel {#1}%
- \def \syntaxcaption {#2}%
- \setlength\grammarparsep{12pt plus 2pt minus 2pt}%
- \setlength\grammarindent{5cm}%
- \begingroup
- \small
- \begin {grammar}
-}
-
-\def \endsyntaxfloat {%
- \end {grammar}
- \endgroup
- \caption \syntaxcaption
- \label \syntaxlabel
- \end {figure}
-}
-
-%% figures, e.g. the file graph
-\def \figurefloat #1#2#3{%% #1:label #2:caption #3:file
- \begin {figure} [b]
- \caption {#2}%
- \includegraphics[width=\textwidth]{#3}%
- \label {#1}
- \end {figure}
-}
-
-%% tables
-\def \tablefloat #1#2{%% #1:label #2:caption
- \begin {table} [t]
- \hrule
- \caption {#2}%
- \label {#1}
- \hrule
- \end {table}
-}
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% hyperlinks
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-\protected \def \hyperlink{%
- \@ifnextchar[{\hyperlinkindeed}%
- {\hyperlinkindeed[]}%
-}
-
-\def \hyperlinkindeed [#1]#2{%
- \def \first {#1}%
- \ifx \first \empty
- \url {#2}%
- \else
- \href {#2}{#1}%
- \fi%
-}
-
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% tables
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Our tables aren’t anything special so we stick with “tabular” on the
-%% Latex end.
-%%
-%% This is going to be largely incompatible with Context since format
-%% specifications work quite differently (even between different
-%% Context table variants).
-
-\def \begintabulate [#1]#2\endtabulate{%
- \begingroup
- \let \beginrow = \relax %% -> \NC in Context
- \let \newcell = & %% -> \NC
- \let \endrow = \cr %% -> \NC \NR
- \begin {tabular}{#1}%
- #2
- \end {tabular}
- \endgroup
-}
-
-\let \endtabulate \relax
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% escaped characters
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-\let \charpercent \textpercent
-\let \charbackslash \textbackslash
-\let \chartilde \textasciitilde
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% main
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-\makeatother
-
-\newif \ifcontextmkiv \contextmkivfalse
-
-\begin {document}
- \input {luaotfload-main.tex}
-\end {document}
-
-
Deleted: trunk/Master/texmf-dist/source/luatex/luaotfload/luaotfload-main.tex
===================================================================
--- trunk/Master/texmf-dist/source/luatex/luaotfload/luaotfload-main.tex 2018-09-26 20:49:48 UTC (rev 48770)
+++ trunk/Master/texmf-dist/source/luatex/luaotfload/luaotfload-main.tex 2018-09-26 20:50:34 UTC (rev 48771)
@@ -1,1908 +0,0 @@
-%% Copyright (C) 2009-2017
-%%
-%% by Elie Roux <elie.roux at telecom-bretagne.eu>
-%% and Khaled Hosny <khaledhosny at eglug.org>
-%% and Philipp Gesang <phg at phi-gamma.net>
-%%
-%% This file is part of Luaotfload.
-%%
-%% Home: https://github.com/lualatex/luaotfload
-%% Support: <lualatex-dev at tug.org>.
-%%
-%% Luaotfload is under the GPL v2.0 (exactly) license.
-%%
-%% ----------------------------------------------------------------------------
-%%
-%% Luaotfload is free software; you can redistribute it and/or
-%% modify it under the terms of the GNU General Public License
-%% as published by the Free Software Foundation; version 2
-%% of the License.
-%%
-%% Luaotfload is distributed in the hope that it will be useful,
-%% but WITHOUT ANY WARRANTY; without even the implied warranty of
-%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-%% GNU General Public License for more details.
-%%
-%% You should have received a copy of the GNU General Public License
-%% along with Luaotfload; if not, see <http://www.gnu.org/licenses/>.
-%%
-%% ----------------------------------------------------------------------------
-%%
-
-\beginfrontmatter
-
- \setdocumenttitle {The \identifier{luaotfload} package}
- \setdocumentdate {2017/01/29 v2.8}
- \setdocumentauthor {Elie Roux · Khaled Hosny · Philipp Gesang\\
- Home: \hyperlink {https://github.com/lualatex/luaotfload}\\
- Support: \email {lualatex-dev at tug.org}}
-
- \typesetdocumenttitle
-
- \beginabstractcontent
- This package is an adaptation of the \CONTEXT font loading system.
- It allows for loading \OpenType fonts with an extended syntax and adds
- support for a variety of font features.
-
- After discussion of the font loading API, this manual gives an
- overview of the core components of \identifier{Luaotfload}: The
- packaged font loader code, the names database, configuration, and
- helper functions on the \LUA\ end.
- \endabstractcontent
-
-\endfrontmatter
-
-\typesetcontent
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-\beginsection {Introduction}
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-Font management and installation has always been painful with \TEX. A
-lot of files are needed for one font (\abbrev{tfm}, \abbrev{pfb},
-\abbrev{map}, \abbrev{fd}, \abbrev{vf}), and due to the 8-Bit encoding
-each font is limited to 256 characters.
-
-But the font world has evolved since the original \TEX, and new
-typographic systems have appeared, most notably the so called
-\emphasis{smart font} technologies like \OpenType fonts (\abbrev{otf}).
-
-These fonts can contain many more characters than \TEX fonts, as well
-as additional functionality like ligatures, old-style numbers, small
-capitals, etc., and support more complex writing systems like Arabic
-and Indic\footnote{%
- Unfortunately, \identifier{luaotfload} doesn‘t support many Indic
- scripts right now.
- Assistance in implementing the prerequisites is greatly
- appreciated.
-}
-scripts.
-
-\OpenType fonts are widely deployed and available for all modern
-operating systems.
-
-As of 2013 they have become the de facto standard for advanced text
-layout.
-
-However, until recently the only way to use them directly in the \TEX
-world was with the \XETEX engine.
-
-Unlike \XETEX, \LUATEX has no built-in support for \OpenType or
-technologies other than the original \TEX fonts.
-
-Instead, it provides hooks for executing \LUA code during the \TEX run
-that allow implementing extensions for loading fonts and manipulating
-how input text is processed without modifying the underlying engine.
-
-This is where \identifier{luaotfload} comes into play:
-Based on code from \CONTEXT, it extends \LUATEX with functionality necessary
-for handling \OpenType fonts.
-
-Additionally, it provides means for accessing fonts known to the operating
-system conveniently by indexing the metadata.
-
-\endsection
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-\beginsection {Thanks}
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-\identifier{Luaotfload} is part of \LUALATEX, the community-driven
-project to provide a foundation for using the \LATEX format with the
-full capabilites of the \LUATEX engine.
-%
-As such, the distinction between end users, contributors, and project
-maintainers is intentionally kept less strict, lest we unduly
-personalize the common effort.
-
-Nevertheless, the current maintainers would like to express their
-gratitude to Khaled Hosny, Akira Kakuto, Hironori Kitagawa and Dohyun
-Kim.
-%
-Their contributions -- be it patches, advice, or systematic
-testing -- made the switch from version 1.x to 2.2 possible.
-%
-Also, Hans Hagen, the author of the font loader, made porting the
-code to \LATEX a breeze due to the extra effort he invested into
-isolating it from the rest of \CONTEXT, not to mention his assistance
-in the task and willingness to respond to our suggestions.
-
-\endsection
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-\beginsection {Loading Fonts}
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-\identifier{luaotfload} supports an extended font request syntax:
-
-\beginnarrower
- \nonproportional{\string\font\string\foo\space= \string{}%
- \meta{prefix}\nonproportional{:}%
- \meta{font name}\nonproportional{:}%
- \meta{font features}\nonproportional{\string}}%
- \meta{\TEX font features}
-\endnarrower
-
-\noindent
-The curly brackets are optional and escape the spaces in the enclosed
-font name.
-%
-Alternatively, double quotes serve the same purpose.
-%
-A selection of individual parts of the syntax are discussed below;
-for a more formal description see figure \ref{font-syntax}.
-
-\beginsyntaxfloat
- {font-syntax}
- {Font request syntax.
- Braces or double quotes around the
- \emphasis{specification} rule will
- preserve whitespace in file names.
- In addition to the font style modifiers
- (\emphasis{slash-notation}) given above, there
- are others that are recognized but will be silently
- ignored: \nonproportional{aat},
- \nonproportional{icu}, and
- \nonproportional{gr}.
- The special terminals are:
- \smallcaps {feature\textunderscore id} for a valid font
- feature name and
- \smallcaps {feature\textunderscore value} for the corresponding
- value.
- \smallcaps {tfmname} is the name of a \abbrev{tfm} file.
- \smallcaps {digit} again refers to bytes 48--57, and
- \smallcaps {all\textunderscore characters} to all byte values.
- \smallcaps {csname} and \smallcaps {dimension} are the \TEX concepts.}
-%
- <definition> ::= `\\font', {\sc csname}, `=', <font request>, [ <size> ] ;
-
- <size> ::= `at', {\sc dimension} ;
-
- <font request> ::= `"', <unquoted font request> `"'
- \alt `{', <unquoted font request> `}'
- \alt <unquoted font request> ;
-
- <unquoted font request> ::= <specification>, [`:', <feature list> ]
- \alt <path lookup>, [ [`:'], <feature list> ] ;
-
- <specification> ::= <prefixed spec>, [ <subfont no> ], \{ <modifier> \}
- \alt <anon lookup>, \{ <modifier> \} ;
-
- <prefixed spec> ::= `combo:', <combo list>
- \alt `file:', <file lookup>
- \alt `name:', <name lookup> ;
-
- <combo list> ::= <combo def 1>, \{ `;', <combo def> \} ;
-
- <combo def 1> ::= <combo id>, `->', <combo id> ;
-
- <combo def> ::= <combo id>, `->', <combo id chars> ;
-
- <combo id> ::= (`(', \{ {\sc digit} \}, `)' | \{ {\sc digit} \} ) ;
-
- <combo id chars> ::= (`(', \{ {\sc digit} \}, `,', <combo chars>, `)'
- \alt \{ {\sc digit} \} ) ;
-
- <combo chars> ::= `fallback'
- \alt \{ <combo range>, \{ `*', <combo range> \} \} ;
-
- <combo range> ::= <combo num>, [ `-', <combo num> ] ;
-
- <combo num> ::= `0x', \{ {\sc hexdigit} \}
- \alt `U+', \{ {\sc digit} \}
- \alt \{ {\sc digit} \} ;
-
- <file lookup> ::= \{ <name character> \} ;
-
- <name lookup> ::= \{ <name character> \} ;
-
- <anon lookup> ::= {\sc tfmname} | <name lookup> ;
-
- <path lookup> ::= `[', \{ <path content> \}, `]', [ <subfont no> ] ;
-
- <path content> ::= <path balanced>
- \alt `\\', {\sc all_characters}
- \alt {\sc all_characters} - `]'
-
- <path balanced> ::= `[', [ <path content> ], `]'
-
- <modifier> ::= `/', (`I' | `B' | `BI' | `IB' | `S=', \{ {\sc digit} \} ) ;
-
- <subfont no> ::= `(', \{ {\sc digit} \}, `)' ;
-
- <feature list> ::= <feature expr>, \{ `;', <feature expr> \} ;
-
- <feature expr> ::= {\sc feature_id}, `=', {\sc feature_value}
- \alt <feature switch>, {\sc feature_id} ;
-
- <feature switch> ::= `+' | `-' ;
-
- <name character> ::= {\sc all_characters} - ( `(' | `/' | `:' ) ;
-\endsyntaxfloat
-
-%% Below guarded space gets borked in index; why‽
-\beginsubsection{Prefix -- the \identifier{luaotfload}{ }Way}
-
-In \identifier{luaotfload}, the canonical syntax for font requests
-requires a \emphasis{prefix}:
-%
-\beginnarrower
- \nonproportional{\string\font\string\fontname\space= }%
- \meta{prefix}%
- \nonproportional{:}%
- \meta{fontname}%
- \dots
-\endnarrower
-%
-where \meta{prefix} is either \inlinecode{file:} or \inlinecode {name:}.\footnote{%
- \identifier{Luaotfload} also knows two further prefixes, \inlinecode {kpse:}
- and \inlinecode {my:}.
- %
- A \inlinecode {kpse} lookup is restricted to files that can be found by
- \identifier{kpathsea} and will not attempt to locate system fonts.
- %
- This behavior can be of value when an extra degree of encapsulation is
- needed, for instance when supplying a customized tex distribution.
-
- The \inlinecode {my} lookup takes this a step further: it lets you define
- a custom resolver function and hook it into the \luaident{resolve_font}
- callback.
- %
- This ensures full control over how a file is located.
- %
- For a working example see the
- \hyperlink [test repo]{https://bitbucket.org/phg/lua-la-tex-tests/src/5f6a535d/pln-lookup-callback-1.tex}.
-}
-%
-It determines whether the font loader should interpret the request as
-a \emphasis{file name} or
- \emphasis{font name}, respectively,
-which again influences how it will attempt to locate the font.
-%
-Examples for font names are
- “Latin Modern Italic”,
- “GFS Bodoni Rg”, and
- “PT Serif Caption”
--- they are the human readable identifiers
-usually listed in drop-down menus and the like.\footnote{%
- Font names may appear like a great choice at first because they
- offer seemingly more intuitive identifiers in comparison to arguably
- cryptic file names:
- %
- “PT Sans Bold” is a lot more descriptive than \fileent{PTS75F.ttf}.
- On the other hand, font names are quite arbitrary and there is no
- universal method to determine their meaning.
- %
- While \identifier{luaotfload} provides fairly sophisticated heuristic
- to figure out a matching font style, weight, and optical size, it
- cannot be relied upon to work satisfactorily for all font files.
- %
- For an in-depth analysis of the situation and how broken font names
- are, please refer to
- \hyperlink [this post]{http://www.ntg.nl/pipermail/ntg-context/2013/073889.html}
- by Hans Hagen, the author of the font loader.
- %
- If in doubt, use filenames.
- %
- \fileent{luaotfload-tool} can perform the matching for you with the
- option \inlinecode {--find=<name>}, and you can use the file name it returns
- in your font definition.
-}
-%
-In order for fonts installed both in system locations and in your
-\fileent{texmf} to be accessible by font name, \identifier{luaotfload} must
-first collect the metadata included in the files.
-%
-Please refer to section~\ref{sec:fontdb} below for instructions on how to
-create the database.
-
-File names are whatever your file system allows them to be, except
-that that they may not contain the characters
- \inlinecode {(},
- \inlinecode {:}, and
- \inlinecode {/}.
-%
-As is obvious from the last exception, the \inlinecode {file:} lookup will
-not process paths to the font location -- only those
-files found when generating the database are addressable this way.
-%
-Continue below in the \XETEX section if you need to load your fonts
-by path.
-%
-The file names corresponding to the example font names above are
- \fileent{lmroman12-italic.otf},
- \fileent{GFSBodoni.otf}, and
- \fileent{PTZ56F.ttf}.
-
-\endsubsection
-
-\beginsubsection {Bracketed Lookups}
-\label{sec:conf}
-Bracketed lookups allow for arbitrary character content to be used in a
-definition.
-%
-A simple bracketed request looks follows the scheme
-
-\beginnarrower
- \nonproportional{\string\font\string\fontname\space = [}%
- \meta{/path/to/file}%
- \nonproportional{]}
-\endnarrower
-
-\noindent
-Inside the square brackets, every character except for a closing bracket is
-permitted, allowing for arbitrary paths to a font file -- including Windows
-style paths with UNC or drive letter prepended -- to be specified.
-%
-The \identifier{Luaotfload} syntax differs from \XETEX in that the subfont
-selector goes \emphasis{after} the closing bracket:
-
-\beginnarrower
- \nonproportional{\string\font\string\fontname\space = [}%
- \meta{/path/to/file}%
- \nonproportional{]}
- \nonproportional{(}n\nonproportional{)}
-\endnarrower
-
-Naturally, path-less file names are equally valid and processed the
-same way as an ordinary \inlinecode {file:} lookup.
-
-\beginsubsection {Compatibility}
-
-In addition to the regular prefixed requests, \identifier{luaotfload}
-accepts loading fonts the \XETEX way.
-%
-There are again two modes: bracketed and unbracketed.
-For the bracketed variety, see above, \ref{sec:conf}.
-
-Unbracketed (or, for lack of a better word: \emphasis{anonymous})
-font requests resemble the conventional \TEX syntax.
-
-\beginnarrower
- \nonproportional{\string\font\string\fontname\space= }%
- \meta{font name}
- \dots
-\endnarrower
-\endsubsection
-
-However, they have a broader spectrum of possible interpretations:
-before anything else, \identifier{luaotfload} attempts to load a
-traditional \TEX Font Metric (\abbrev{tfm} or \abbrev{ofm}).
-%
-If this fails, it performs a \inlinecode {path:} lookup, which itself will
-fall back to a \inlinecode {file:} lookup.
-%
-Lastly, if none of the above succeeded, attempt to resolve the request as a
-\inlinecode {name:} lookup by searching the font index for \meta{font name}.
-%
-The behavior of this “anonymous” lookup is configurable, see the configuation
-manpage for details.
-
-Furthermore, \identifier{luaotfload} supports the slashed (shorthand)
-font style notation from \XETEX.
-
-\beginnarrower
- \nonproportional{\string\font\string\fontname\space= }%
- \meta{font name}%
- \nonproportional{/}%
- \meta{modifier}
- \dots
-\endnarrower
-
-\noindent
-Currently, four style modifiers are supported:
- \inlinecode {I} for italic shape,
- \inlinecode {B} for bold weight,
- \inlinecode {BI} or \inlinecode {IB} for the combination of both.
-%
-Other “slashed” modifiers are too specific to the \XETEX engine and
-have no meaning in \LUATEX.
-
-\endsubsection
-
-\beginsubsection{Examples}
-
-\beginsubsubsection{Loading by File Name}
-
-For example, conventional \TeX\ font can be loaded with a
-\inlinecode {file:} request like so:
-
-\beginlisting
- \font \lmromanten = {file:ec-lmr10} at 10pt
-\endlisting
-
-The \OpenType version of Janusz Nowacki’s font \emphasis{Antykwa
-Półtawskiego}\footnote{%
- \hyperlink {http://jmn.pl/antykwa-poltawskiego/}, also available in
- in \TEX Live.
-}
-in its condensed variant can be loaded as follows:
-
-\beginlisting
- \font \apcregular = file:antpoltltcond-regular.otf at 42pt
-\endlisting
-
-The next example shows how to load the \emphasis{Porson} font digitized by
-the Greek Font Society using \XETEX-style syntax and an absolute path from a
-non-standard directory:
-
-\beginlisting
- \font \gfsporson = "[/tmp/GFSPorson.otf]" at 12pt
-\endlisting
-
-\identifier{TrueType} collection files (the extension is usually
-\inlinecode{.ttc}) contain more than a single font. In order to refer to these
-subfonts, the respective index may be added in parentheses after the file
-name.\footnote{%
- Incidentally, this syntactical detail also prevents one from loading files
- that end in balanced parentheses.
-}
-
-\beginlisting
- \font \cambriamain = "file:cambria.ttc(0)" at 10pt
- \font \cambriamath = "file:cambria.ttc(1)" at 10pt
-\endlisting
-
-and likewise, requesting subfont inside a TTC container by path:
-
-\beginlisting
- \font \asanamain = "[/home/typesetter/.fonts/math/asana.ttc](0):mode=node;+tlig" at 10pt
- \font \asanamath = "[/home/typesetter/.fonts/math/asana.ttc](1):mode=base" at 10pt
-\endlisting
-
-\endsubsubsection
-
-\beginsubsubsection{Loading by Font Name}
-
-The \inlinecode {name:} lookup does not depend on cryptic filenames:
-
-\beginlisting
- \font \pagellaregular = {name:TeX Gyre Pagella} at 9pt
-\endlisting
-
-A bit more specific but essentially the same lookup would be:
-
-\beginlisting
- \font \pagellaregular = {name:TeX Gyre Pagella Regular} at 9pt
-\endlisting
-
-\noindent
-Which fits nicely with the whole set:
-
-\beginlisting
- \font\pagellaregular = {name:TeX Gyre Pagella Regular} at 9pt
- \font\pagellaitalic = {name:TeX Gyre Pagella Italic} at 9pt
- \font\pagellabold = {name:TeX Gyre Pagella Bold} at 9pt
- \font\pagellabolditalic = {name:TeX Gyre Pagella Bolditalic} at 9pt
-
- {\pagellaregular foo bar baz\endgraf}
- {\pagellaitalic foo bar baz\endgraf}
- {\pagellabold foo bar baz\endgraf}
- {\pagellabolditalic foo bar baz\endgraf}
-
- ...
-\endlisting
-
-\endsubsubsection
-
-\beginsubsubsection{Modifiers}
-
-If the entire \emphasis{Iwona} family\footnote{%
- \hyperlink {http://jmn.pl/kurier-i-iwona/},
- also in \TEX Live.
-}
-is installed in some location accessible by \identifier{luaotfload},
-the regular shape can be loaded as follows:
-
-\beginlisting
- \font \iwona = Iwona at 20pt
-\endlisting
-
-\noindent
-To load the most common of the other styles, the slash notation can
-be employed as shorthand:
-
-\beginlisting
- \font \iwonaitalic = Iwona/I at 20pt
- \font \iwonabold = Iwona/B at 20pt
- \font \iwonabolditalic = Iwona/BI at 20pt
-\endlisting
-
-\noindent
-which is equivalent to these full names:
-
-\beginlisting
- \font \iwonaitalic = "Iwona Italic" at 20pt
- \font \iwonabold = "Iwona Bold" at 20pt
- \font \iwonabolditalic = "Iwona BoldItalic" at 20pt
-\endlisting
-
-\endsubsubsection
-\endsubsection
-\endsection
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-\beginsection {Font features}
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-\emphasis{Font features} are the second to last component in the
-general scheme for font requests:
-
-\beginnarrower
- \nonproportional{\string\font\string\foo\space= "}%
- \meta{prefix}%
- \nonproportional{:}%
- \meta{font name}%
- \nonproportional{:}%
- \meta{font features}%
- \meta{\TEX font features}%
- \nonproportional{"}
-\endnarrower
-
-\noindent
-If style modifiers are present (\XETEX style), they must precede
-\meta{font features}.
-
-The element \meta{font features} is a semicolon-separated list of feature
-tags\footnote{%
- Cf. \hyperlink {http://www.microsoft.com/typography/otspec/featurelist.htm}.
-}
-and font options.
-%
-Prepending a font feature with a \inlinecode{+} (plus sign) enables it,
-whereas a \inlinecode{-} (minus) disables it. For instance, the request
-
-\beginlisting
- \font \test = LatinModernRoman:+clig;-kern
-\endlisting
-
-\noindent activates contextual ligatures (\inlinecode{clig}) and
-disables kerning (\inlinecode{kern}).
-%
-Alternatively the options \inlinecode{true} or \inlinecode{false} can
-be passed to the feature in a key/value expression.
-%
-The following request has the same meaning as the last one:
-
-\beginlisting
- \font \test = LatinModernRoman:clig=true;kern=false
-\endlisting
-
-\noindent
-Furthermore, this second syntax is required should a font feature
-accept other options besides a true/false switch.
-%
-For example, \emphasis{stylistic alternates} (\inlinecode{salt}) are
-variants of given glyphs.
-%
-They can be selected either explicitly by supplying the variant
-index (starting from one), or randomly by setting the value to,
-obviously, \inlinecode{random}.
-
-%% TODO verify that this actually works with a font that supports
-%% the salt/random feature!\fi
-\beginlisting
- \font \librmsaltfirst = LatinModernRoman:salt=1
-\endlisting
-
-\beginsubsection {Basic font features}
-
-\begindescriptions
-
- \beginaltitem {mode}
- \identifier{luaotfload} has two \OpenType processing
- \emphasis{modes}:
- \identifier{base} and \identifier{node}.
-
- \identifier{base} mode works by mapping \OpenType
- features to traditional \TEX ligature and kerning mechanisms.
- %
- Supporting only non-contextual substitutions and kerning
- pairs, it is the slightly faster, albeit somewhat limited, variant.
- %
- \identifier{node} mode works by processing \TeX’s internal
- node list directly at the \LUA end and supports
- a wider range of \OpenType features.
- %
- The downside is that the intricate operations required for
- \identifier{node} mode may slow down typesetting especially
- with complex fonts and it does not work in math mode.
-
- By default \identifier{luaotfload} is in \identifier{node}
- mode, and \identifier{base} mode has to be requested where needed,
- e.~g. for math fonts.
- \endaltitem
-
- \beginaltitem {script} \label{script-tag}
- An \OpenType script tag;\footnote{%
- See \hyperlink {http://www.microsoft.com/typography/otspec/scripttags.htm}
- for a list of valid values.
- %
- For scripts derived from the Latin alphabet the value
- \inlinecode{latn} is good choice.
- }
- the default value is \inlinecode{dflt}.
- %
- Some fonts, including very popular ones by foundries like Adobe,
- do not assign features to the \inlinecode{dflt} script, in
- which case the script needs to be set explicitly.
- \endaltitem
-
- \beginaltitem {language}
- An \OpenType language system identifier,\footnote{%
- Cf. \hyperlink {http://www.microsoft.com/typography/otspec/languagetags.htm}.
- }
- defaulting to \inlinecode{dflt}.
- \endaltitem
-
- \beginaltitem {color}
- A font color, defined as a triplet of two-digit hexadecimal
- \abbrev{rgb} values, with an optional fourth value for
- transparency
- (where \inlinecode{00} is completely transparent and
- \inlinecode{FF} is opaque).
-
- For example, in order to set text in semitransparent red:
-
- \beginlisting
- \font \test = "Latin Modern Roman:color=FF0000BB"
- \endlisting
- \endaltitem
-
- \beginaltitem {kernfactor \& letterspace}
- Define a font with letterspacing (tracking) enabled.
- %
- In \identifier{luaotfload}, letterspacing is implemented by
- inserting additional kerning between glyphs.
-
- This approach is derived from and still quite similar to the
- \emphasis{character kerning} (\texmacro{setcharacterkerning} /
- \texmacro{definecharacterkerning} \& al.) functionality of
- Context, see the file \fileent{typo-krn.lua} there.
- %
- The main difference is that \identifier{luaotfload} does not
- use \LUATEX attributes to assign letterspacing to regions,
- but defines virtual letterspaced versions of a font.
-
- The option \identifier{kernfactor} accepts a numeric value that
- determines the letterspacing factor to be applied to the font
- size.
- %
- E.~g. a kern factor of $0.42$ applied to a $10$ pt font
- results in $4.2$ pt of additional kerning applied to each
- pair of glyphs.
- %
- Ligatures are split into their component glyphs unless
- explicitly ignored (see below).
-
- For compatibility with \XETEX an alternative
- \identifier{letterspace} option is supplied that interprets the
- supplied value as a \emphasis{percentage} of the font size but
- is otherwise identical to \identifier{kernfactor}.
- %
- Consequently, both definitions in below snippet yield the same
- letterspacing width:
-
- \beginlisting
- \font \iwonakernedA = "file:Iwona-Regular.otf:kernfactor=0.125"
- \font \iwonakernedB = "file:Iwona-Regular.otf:letterspace=12.5"
- \endlisting
-
- Specific pairs of letters and ligatures may be exempt from
- letterspacing by defining the \LUA functions
- \luaident{keeptogether} and \luaident{keepligature},
- respectively, inside the namespace \inlinecode {luaotfload.letterspace}.
- %
- Both functions are called whenever the letterspacing callback
- encounters an appropriate node or set of nodes.
- %
- If they return a true-ish value, no extra kern is inserted at
- the current position.
- %
- \luaident{keeptogether} receives a pair of consecutive
- glyph nodes in order of their appearance in the node list.
- %
- \luaident{keepligature} receives a single node which can be
- analyzed into components.
- %
- (For details refer to the \emphasis{glyph nodes} section in the
- \LUATEX reference manual.)
- %
- The implementation of both functions is left entirely to the
- user.
- \endaltitem
-
-\iffalse
- \startbuffer [printvectors]
- \directlua{inspect(fonts.protrusions.setups.default)
- inspect(fonts.expansions.setups.default)}
- \stopbuffer
-\fi
-
- \beginaltitem {protrusion \& expansion}
- These keys control microtypographic features of the font,
- namely \emphasis{character protrusion} and \emphasis{font
- expansion}.
- %
- Their arguments are names of \LUA tables that contain
- values for the respective features.\footnote{%
- For examples of the table layout please refer to the
- section of the file \fileent{luaotfload-fonts-ext.lua} where the
- default values are defined.
- %
- Alternatively and with loss of information, you can dump
- those tables into your terminal by issuing
- \unless \iffalse
- \beginlisting
- \directlua{inspect(fonts.protrusions.setups.default)
- inspect(fonts.expansions.setups.default)}
- \endlisting
- \else
- \typebuffer [printvectors]
- \fi
- at some point after loading \fileent{luaotfload.sty}.
- }
- %
- For both, only the set \identifier{default} is predefined.
-
- For example, to define a font with the default
- protrusion vector applied\footnote{%
- You also need to set
- \inlinecode {pdfprotrudechars=2} and
- \inlinecode {pdfadjustspacing=2}
- to activate protrusion and expansion, respectively.
- See the
- \hyperlink [\PDFTEX manual]{http://mirrors.ctan.org/systems/pdftex/manual/pdftex-a.pdf}%
- for details.
- }:
-
- \beginlisting
- \font \test = LatinModernRoman:protrusion=default
- \endlisting
- \endaltitem
-\enddescriptions
-
-\endsubsection
-
-\beginsubsection {Non-standard font features}
-\identifier{luaotfload} adds a number of features that are not defined
-in the original \OpenType specification, most of them
-aiming at emulating the behavior familiar from other \TEX engines.
-%
-Currently (2014) there are three of them:
-
-\begindescriptions
-
- \beginaltitem {anum}
- Substitutes the glyphs in the \abbrev{ascii} number range
- with their counterparts from eastern Arabic or Persian,
- depending on the value of \identifier{language}.
- \endaltitem
-
- \beginaltitem {tlig}
- Applies legacy \TEX ligatures\footnote{%
- These contain the feature set \inlinecode {trep} of earlier
- versions of \identifier{luaotfload}.
-
- Note to \XETEX users: this is the equivalent of the
- assignment \inlinecode {mapping=text-tex} using \XETEX's input
- remapping feature.
- }:
-
- \unless \iffalse
- %% Using braced arg syntax with inline code appears to be
- %% impossible within Latex tables -- just ignore the weird
- %% exclamation points below.
- \begintabulate [rlrl]
- \beginrow `` \newcell {\inlinecode !``! } \newcell '' \newcell {\inlinecode !''!} \endrow
- \beginrow ` \newcell {\inlinecode !`! } \newcell ' \newcell {\inlinecode !'! } \endrow
- \beginrow " \newcell {\inlinecode !"! } \newcell -- \newcell {\inlinecode !--!} \endrow
- \beginrow --- \newcell {\inlinecode !---!} \newcell !` \newcell {\inlinecode ?!`?} \endrow
- \beginrow ?` \newcell {\inlinecode !?`! } \newcell \newcell \endrow
- \endtabulate
- \else
- %% XXX find a way to wrap these in the tabulate environment
- \startframed [frame=off,width=broad,align=middle]
- \startframed [frame=off,width=\dimexpr(\textwidth/2)]
- \startxtable [align=middle]
- \startxrow \startxcell `` \stopxcell \startxcell \inlinecode {``} \stopxcell \startxcell '' \stopxcell \startxcell \inlinecode {''} \stopxcell \stopxrow
- \startxrow \startxcell ` \stopxcell \startxcell \inlinecode {`} \stopxcell \startxcell ' \stopxcell \startxcell \inlinecode {'} \stopxcell \stopxrow
- \startxrow \startxcell " \stopxcell \startxcell \inlinecode {"} \stopxcell \startxcell -- \stopxcell \startxcell \inlinecode {--} \stopxcell \stopxrow
- \startxrow \startxcell --- \stopxcell \startxcell \inlinecode {---} \stopxcell \startxcell !` \stopxcell \startxcell \inlinecode {!`} \stopxcell \stopxrow
- \startxrow \startxcell ?` \stopxcell \startxcell \inlinecode {?`} \stopxcell \startxcell \stopxcell \startxcell \stopxcell \stopxrow
- \stopxtable
- \stopframed
- \stopframed
- \fi
- \endaltitem
-
- \beginaltitem {itlc}
- Computes italic correction values (active by default).
- \endaltitem
-
-\enddescriptions
-
-\endsubsection
-\endsection
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-\beginsection {Combining fonts}
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-Version 2.7 and later support combining characters from multiple fonts into a
-single virtualized one. This requires that the affected fonts be loaded in
-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.
-
-Combinations are created by defining a font using the \luaident{combo:} prefix.
-
-\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
-font like \identifier{Computer Modern Unicode}, taking advantage of the fact
-that it too derives from Knuth’s original \identifier{Computer Modern} series:
-
-\beginlisting
- \input luaotfload.sty
- \font \lm = file:lmroman10-regular.otf:mode=base
- \font \cmu = file:cmunrm.otf:mode=base
- \font \lmu = "combo: 1->\fontid\lm; 2->\fontid\cmu,fallback"
- \lmu Eh bien, mon prince. Gênes et Lueques ne sont plus que des
- apanages, des поместья, de la famille Buonaparte.
- \bye
-\endlisting
-
-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
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-\beginsection {Font names database}
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-\label{sec:fontdb}
-
-As mentioned above, \identifier{luaotfload} keeps track of which
-fonts are available to \LUATEX by means of a \emphasis{database}.
-%
-This allows referring to fonts not only by explicit filenames but
-also by the proper names contained in the metadata which is often
-more accessible to humans.\footnote{%
- The tool \hyperlink[\fileent{otfinfo}]{http://www.lcdf.org/type/}
- (comes with \TEX Live), when invoked on a font file with the
- \inlinecode {-i} option, lists the variety of name fields defined for
- it.
-}
-
-When \identifier{luaotfload} is asked to load a font by a font name,
-it will check if the database exists and load it, or else generate a
-fresh one.
-%
-Should it then fail to locate the font, an update to the database is
-performed in case the font has been added to the system only
-recently.
-%
-As soon as the database is updated, the resolver will try
-and look up the font again, all without user intervention.
-%
-The goal is for \identifier{luaotfload} to act in the background and
-behave as unobtrusively as possible, while providing a convenient
-interface to the fonts installed on the system.
-
-Generating the database for the first time may take a while since it
-inspects every font file on your computer.
-%
-This is particularly noticeable if it occurs during a typesetting run.
-In any case, subsequent updates to the database will be quite fast.
-
-\beginsubsection[luaotfload-tool]
- {\fileent{luaotfload-tool}}
-
-It can still be desirable at times to do some of these steps
-manually, and without having to compile a document.
-%
-To this end, \identifier{luaotfload} comes with the utility
-\fileent{luaotfload-tool} that offers an interface to the database
-functionality.
-%
-Being a \LUA script, there are two ways to run it:
-either make it executable (\inlinecode {chmod +x} on unixoid systems) or
-pass it as an argument to \fileent{texlua}.\footnote{%
- Tests by the maintainer show only marginal performance gain by
- running with Luigi Scarso’s
- \hyperlink [\identifier{Luajit\kern-.25ex\TEX}]{https://foundry.supelec.fr/projects/luajittex/},
- which is probably due to the fact that most of the time is spent
- on file system operations.
-
- \emphasis{Note}:
- On \abbrev{MS} \identifier{Windows} systems, the script can be run
- either by calling the wrapper application
- \fileent{luaotfload-tool.exe} or as
- \inlinecode {texlua.exe luaotfload-tool.lua}.
-}
-%
-Invoked with the argument \inlinecode {--update} it will perform a database
-update, scanning for fonts not indexed.
-
-\beginlisting
- luaotfload-tool --update
-\endlisting
-
-Adding the \inlinecode {--force} switch will initiate a complete
-rebuild of the database.
-
-\beginlisting
- luaotfload-tool --update --force
-\endlisting
-
-\endsubsection
-
-\beginsubsection{Search Paths}
-
-\identifier{luaotfload} scans those directories where fonts are
-expected to be located on a given system.
-%
-On a Linux machine it follows the paths listed in the
-\identifier{Fontconfig} configuration files;
-consult \inlinecode {man 5 fonts.conf} for further information.
-%
-On \identifier{Windows} systems, the standard location is
-\inlinecode {Windows\\Fonts},
-%
-while \identifier{Mac OS~X} requires a multitude of paths to
-be examined.
-%
-The complete list is is given in table \ref{table-searchpaths}.
-Other paths can be specified by setting the environment variable
-\inlinecode {OSFONTDIR}.
-%
-If it is non-empty, then search will be extended to the included
-directories.
-
-\tablefloat {table-searchpaths}
- {List of paths searched for each supported operating system.}
- {%
- \unless \iffalse
- \begincentered
- \begintabulate [lp{.5\textwidth}]
- \beginrow
- Windows \newcell \inlinecode !\% WINDIR\%\\ Fonts!
- \endrow
- \beginrow
- Linux \newcell \fileent{/usr/local/etc/fonts/fonts.conf} and\hfill\break
- \fileent{/etc/fonts/fonts.conf}
- \endrow
- \beginrow
- Mac \newcell \fileent{\textasciitilde/Library/Fonts},\break
- \fileent{/Library/Fonts},\break
- \fileent{/System/Library/Fonts}, and\hfill\break
- \fileent{/Network/Library/Fonts}
- \endrow
- \endtabulate
- \endcentered
- \else
- \setuplocalinterlinespace [14pt]
- \starttabulate [|l|p(.5\textwidth)|]
- \NC Windows \NC \inlinecode {\% WINDIR\%\\ Fonts} \NC \NR
- \NC Linux \NC \fileent{/usr/local/etc/fonts/fonts.conf} and\crlf
- \fileent{/etc/fonts/fonts.conf} \NC \NR
- \NC
- Mac \NC \fileent{\textasciitilde/Library/Fonts},\crlf
- \fileent{/Library/Fonts},\break
- \fileent{/System/Library/Fonts}, and\crlf
- \fileent{/Network/Library/Fonts} \NC \NR
- \stoptabulate
- \fi%
- }
-
-\endsubsection
-
-\beginsubsection{Querying from Outside}
-
-\fileent{luaotfload-tool} also provides rudimentary means of
-accessing the information collected in the font database.
-%
-If the option \inlinecode {--find=}\emphasis{name} is given, the script will
-try and search the fonts indexed by \identifier{luaotfload} for a
-matching name.
-%
-For instance, the invocation
-
-\beginlisting
- luaotfload-tool --find="Iwona Regular"
-\endlisting
-
-\noindent
-will verify if “Iwona Regular” is found in the database and can be
-readily requested in a document.
-
-If you are unsure about the actual font name, then add the
-\inlinecode {-F} (or \inlinecode {--fuzzy}) switch to the command line to enable
-approximate matching.
-%
-Suppose you cannot precisely remember if the variant of
-\identifier{Iwona} you are looking for was “Bright” or “Light”.
-The query
-
-\beginlisting
- luaotfload-tool -F --find="Iwona Bright"
-\endlisting
-
-\noindent
-will tell you that indeed the latter name is correct.
-
-Basic information about fonts in the database can be displayed
-using the \inlinecode {-i} option (\inlinecode {--info}).
-%
-\beginlisting
- luaotfload-tool -i --find="Iwona Light Italic"
-\endlisting
-%
-\noindent
-The meaning of the printed values is described in section 4.4 of the
-\LUATEX reference manual.\footnote{%
- In \TEX Live: \fileent{texmf-dist/doc/luatex/base/luatexref-t.pdf}.
-}
-
-For a much more detailed report about a given font try the
-\inlinecode {-I} option instead (\inlinecode {--inspect}).
-\beginlisting
- luaotfload-tool -I --find="Iwona Light Italic"
-\endlisting
-
-\inlinecode {luaotfload-tool --help} will list the available command line
-switches, including some not discussed in detail here.
-%
-For a full documentation of \identifier{luaotfload-tool} and its
-capabilities refer to the manpage
-(\inlinecode {man 1 luaotfload-tool}).\footnote{%
- Or see \inlinecode {luaotfload-tool.rst} in the source directory.
-}
-
-\endsubsection
-
-\beginsubsection {Blacklisting Fonts}
-\label{font-blacklist}
-
-Some fonts are problematic in general, or just in \LUATEX.
-%
-If you find that compiling your document takes far too long or eats
-away all your system’s memory, you can track down the culprit by
-running \inlinecode {luaotfload-tool -v} to increase verbosity.
-%
-Take a note of the \emphasis{filename} of the font that database
-creation fails with and append it to the file
-\fileent{luaotfload-blacklist.cnf}.
-
-A blacklist file is a list of font filenames, one per line.
-Specifying the full path to where the file is located is optional, the
-plain filename should suffice.
-%
-File extensions (\fileent{.otf}, \fileent{.ttf}, etc.) may be omitted.
-%
-Anything after a percent (\inlinecode {\%}) character until the end of the line
-is ignored, so use this to add comments.
-%
-Place this file to some location where the \identifier{kpse}
-library can find it, e.~g.
-\fileent{texmf-local/tex/luatex/luaotfload} if you are running
-\identifier{\TEX Live},\footnote{%
- You may have to run \inlinecode {mktexlsr} if you created a new file in
- your \fileent{texmf} tree.
-}
-or just leave it in the working directory of your document.
-%
-\identifier{luaotfload} reads all files named
-\fileent{luaotfload-blacklist.cnf} it finds, so the fonts in
-\fileent{./luaotfload-blacklist.cnf} extend the global blacklist.
-
-Furthermore, a filename prepended with a dash character (\inlinecode{-}) is
-removed from the blacklist, causing it to be temporarily whitelisted
-without modifying the global file.
-%
-An example with explicit paths:
-
-\beginlisting
-% example otf-blacklist.cnf
-/Library/Fonts/GillSans.ttc % Luaotfload ignores this font.
--/Library/Fonts/Optima.ttc % This one is usable again, even if
- % blacklisted somewhere else.
-\endlisting
-
-\endsubsection
-\endsection
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-\beginsection {The Fontloader}
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-\beginsubsection {Overview}
-
-To a large extent, \identifier{luaotfload} relies on code originally
-written by Hans Hagen for the
-\hyperlink[\identifier{\CONTEXT}]{http://wiki.contextgarden.net}
-format.
-%
-It integrates the font loader, written entirely in \LUA, as distributed
-in the \identifier{\LUATEX-Fonts} package.
-%
-The original \LUA source files have been combined using the \CONTEXT
-packaging library into a single, self-contained blob. In
-this form the font loader depends only on the \identifier{lualibs}
-package and requires only minor adaptions to integrate into
-\identifier{luaotfload}.
-
-The guiding principle is to let \CONTEXT/\LUATEX-Fonts take care of the
-implementation, and update the imported code as frequently as
-necessary.
-%
-As maintainers, we aim at importing files from upstream essentially
-\emphasis{unmodified}, except for renaming them to prevent name
-clashes.
-%
-This job has been greatly alleviated since the advent of
-\LUATEX-Fonts, prior to which the individual dependencies had to be
-manually spotted and extracted from the \CONTEXT source code in a
-complicated and error-prone fashion.
-
-\endsubsection
-
-\beginsubsection {Contents and Dependencies}
-
-Below is a commented list of the files distributed with
-\identifier{luaotfload} in one way or the other.
-%
-See figure \ref{file-graph} on page \pageref{file-graph} for a
-graphical representation of the dependencies.
-%
-\label{package}%
-Through the script \fileent{mkimport} a \CONTEXT library
-is invoked to create the \identifier{luaotfload} fontloader as a merged
-(amalgamated) source file.\footnote{%
- In \CONTEXT, this facility can be accessed by means of a
- \hyperlink[script]{https://bitbucket.org/phg/context-mirror/src/beta/scripts/context/lua/mtx-package.lua?at=beta}
- which is integrated into \fileent{mtxrun} as a subcommand.
- Run \inlinecode {mtxrun --script package --help} to display further
- information.
- For the actual merging code see the file
- \fileent{util-mrg.lua} that is part of \CONTEXT.
-}
-%
-This file constitutes the “default fontloader” and is part of the
-\identifier{luaotfload} package as \fileent{fontloader-YY-MM-DD.lua},
-where the uppercase letters are placeholders for the build date.
-%
-A companion to it, \fileent{luatex-basics-gen.lua} must be loaded
-beforehand to set up parts of the environment required by the \CONTEXT
-libraries.
-%
-During a \TEX\ run, the fontloader initialization and injection happens
-in the module \fileent{luaotfload-init.lua}.
-%
-Additionally, the “reference fontloader” as imported from \LUATEX-Fonts
-is provided as the file \fileent{fontloader-reference.lua}.
-%
-This file is self-contained in that it packages all the auxiliary \LUA
-libraries too, as Luaotfload did up to the 2.5 series; since that job
-has been offloaded to the \identifier{Lualibs} package, loading this
-fontloader introduces a certain code duplication.
-
-A number of \emphasis{\LUA utility libraries} are not part of the
-\identifier{luaotfload} fontloader, contrary to its equivalent in
-\LUATEX-Fonts. These are already provided by the \identifier{lualibs}
-and have thus been omitted from the merge.\footnote{%
- Faithful listeners will remember the pre-2.6 era when the fontloader
- used to be integrated as-is which caused all kinds of code
- duplication with the pervasive \identifier{lualibs} package.
- This conceptual glitch has since been amended by tightening the
- coupling with the excellent \CONTEXT\ toolchain.
-}
-
-\begindoublecolumns
- \begindefinitions
- \beginaltitem {l-lua.lua} \endaltitem
- \beginaltitem {l-lpeg.lua} \endaltitem
- \beginaltitem {l-function.lua} \endaltitem
- \beginaltitem {l-string.lua} \endaltitem
- \beginaltitem {l-table.lua} \endaltitem
- \beginaltitem {l-io.lua} \endaltitem
- \beginaltitem {l-file.lua} \endaltitem
- \beginaltitem {l-boolean.lua} \endaltitem
- \beginaltitem {l-math.lua} \endaltitem
- \beginaltitem {util-str.lua} \endaltitem
- \beginaltitem {util-fil.lua} \endaltitem
- \enddefinitions
-\enddoublecolumns
-
-The reference fontloader is home to several \LUA files that can be
-grouped twofold as below:
-
-\begindefinitions
- \beginnormalitem
- The \emphasis{font loader} itself.
- These files have been written for \LUATEX-Fonts and they are
- distributed along with \identifier{luaotfload} so as to resemble
- the state of the code when it was imported. Their purpose is either
- to give a slightly aged version of a file if upstream considers
- latest developments for not yet ready for use outside Context; or,
- to install placeholders or minimalist versions of APIs relied upon
- but usually provided by parts of Context not included in the
- fontloader.
- \begindoublecolumns
- \begindefinitions
- \beginaltitem{luatex-basics-nod.lua} \endaltitem
- \beginaltitem{luatex-basics-chr.lua} \endaltitem
- \beginaltitem{luatex-fonts-enc.lua} \endaltitem
- \beginaltitem{luatex-fonts-syn.lua} \endaltitem
- \beginaltitem{luatex-fonts-ext.lua} \endaltitem
- \enddefinitions
- \enddoublecolumns
- \endnormalitem
-
- \beginnormalitem
- Code related to \emphasis{font handling and node processing}, taken
- directly from \CONTEXT.
- \begindoublecolumns
- \begindefinitions
- \beginaltitem{data-con.lua} \endaltitem
- \beginaltitem{font-ini.lua} \endaltitem
- \beginaltitem{font-con.lua} \endaltitem
- \beginaltitem{font-cid.lua} \endaltitem
- \beginaltitem{font-map.lua} \endaltitem
- \beginaltitem{font-tfm.lua} \endaltitem
- \beginaltitem{font-one.lua} \endaltitem
- \beginaltitem{font-afk.lua} \endaltitem
- \beginaltitem{font-oti.lua} \endaltitem
- \beginaltitem{font-otr.lua} \endaltitem
- \beginaltitem{font-cff.lua} \endaltitem
- \beginaltitem{font-ttf.lua} \endaltitem
- \beginaltitem{font-dsp.lua} \endaltitem
- \beginaltitem{font-oup.lua} \endaltitem
- \beginaltitem{font-otl.lua} \endaltitem
- \beginaltitem{font-oto.lua} \endaltitem
- \beginaltitem{font-otj.lua} \endaltitem
- \beginaltitem{font-ota.lua} \endaltitem
- \beginaltitem{font-ots.lua} \endaltitem
- \beginaltitem{font-osd.lua} \endaltitem
- \beginaltitem{font-ocl.lua} \endaltitem
- \beginaltitem{font-lua.lua} \endaltitem
- \beginaltitem{font-def.lua} \endaltitem
- \beginaltitem{font-xtx.lua} \endaltitem
- \beginaltitem{font-gbn.lua} \endaltitem
- \enddefinitions
- \enddoublecolumns
- \endnormalitem
-\enddefinitions
-
-As an alternative to the merged file, \identifier {Luaotfload} may load
-individual unpackaged \LUA libraries that come with the source, or even
-use the files from Context directly.
-%
-Thus if you prefer running bleeding edge code from the \CONTEXT beta,
-choose the \inlinecode {context} fontloader via the configuration file
-(see sections \ref{sec:conf} and \ref{sec:pkg} below).
-
-Also, the merged file at some point loads the Adobe Glyph List from a
-\LUA table that is contained in \fileent{luaotfload-glyphlist.lua},
-which is automatically generated by the script
-\fileent{mkglyphlist}.\footnote{%
- See \fileent{luaotfload-font-enc.lua}.
- The hard-coded file name is why we have to replace the procedure
- that loads the file in \fileent{luaotfload-init.lua}.
-}
-%
-There is a make target \identifier{glyphs} that will create a fresh
-glyph list so we don’t need to import it from \CONTEXT any longer.
-
-In addition to these, \identifier{luaotfload} requires a number of
-files not contained in the merge. Some of these have no equivalent in
-\LUATEX-Fonts or \CONTEXT, some were taken unmodified from the latter.
-
-
-\beginfilelist
- \beginaltitem {luaotfload-features.lua}
- font feature handling; incorporates some of the code from
- \fileent{font-otc} from \CONTEXT;
- \endaltitem
- \beginaltitem {luaotfload-configuration.lua}
- handling of \fileent{luaotfload.conf(5)}.
- \endaltitem
- \beginaltitem {luaotfload-log.lua}
- overrides the \CONTEXT logging functionality.
- \endaltitem
- \beginaltitem {luaotfload-loaders.lua}
- registers readers in the fontloader for various kinds of
- font formats
- \endaltitem
- \beginaltitem {luaotfload-parsers.lua}
- various \abbrev{lpeg}-based parsers.
- \endaltitem
- \beginaltitem {luaotfload-database.lua}
- font names database.
- \endaltitem
- \beginaltitem {luaotfload-resolvers.lua}
- file name resolvers.
- \endaltitem
- \beginaltitem {luaotfload-colors.lua}
- color handling.
- \endaltitem
- \beginaltitem {luaotfload-auxiliary.lua}
- access to internal functionality for package authors (proposals
- for additions welcome).
- \endaltitem
- \beginaltitem {luaotfload-letterspace.lua}
- font-based letterspacing.
- \endaltitem
-\endfilelist
-
-\figurefloat
- {file-graph}
- {Schematic of the files in \identifier{Luaotfload}}
- {filegraph.pdf}
-
-\endsubsection
-
-\beginsubsection {Packaging}
-
-\label{sec:pkg}%
-The fontloader code is integrated as an isolated component that can be
-switched out on demand.
-%
-To specify the fontloader you wish to use, the configuration file
-(described in section \ref{sec:conf}) provides the option
-\inlinecode{fontloader}.
-%
-Its value can be one of the identifiers \inlinecode{default} or
-\inlinecode{reference} (see above, section \ref{package}) or the name
-of a file somewhere in the search path of \LUATEX.
-%
-This will make \identifier {Luaotfload} locate the \CONTEXT source by
-means of \identifier{kpathsea} lookups and use those instead of the
-merged package.
-%
-The parameter may be extended with a path to the \CONTEXT
-\fileent{texmf}, separated with a colon:
-
-\beginlisting
-[run]
- fontloader = context:~/context/tex/texmf-context
-\endlisting
-
-\noindent This setting allows accessing an installation -- e. g. the
-standalone distribution or a source repository -- outside the current
-\TEX distribution.
-
-Like the \identifier{Lualibs} package, the fontloader is deployed as a
-\emphasis{merged package} containing a series of \LUA files joined
-together in their expected order and stripped of non-significant parts.
-%
-The \fileent{mkimport} utility assists in pulling the files from a
-\CONTEXT tree and packaging them for use with \identifier{Luaotfload}.%
-%
-The state of the files currently in \identifier{Luaotfload}’s
-repository can be queried:
-\beginlisting
-./scripts/mkimport news
-\endlisting
-%
-The subcommand for importing takes the prefix of the desired \CONTEXT
-\identifier{texmf} as an optional argument:
-\beginlisting
-./scripts/mkimport import ~/context/tex/texmf-context
-\endlisting
-%
-Whereas the command for packaging requires a path to the
-\emphasis{package description file} and the output name to be passed.
-\beginlisting
-./scripts/mkimport package fontloader-custom.lua
-\endlisting
-
-From the toplevel makefile, the targets \inlinecode{import} and
-\inlinecode{package} provide easy access to the commands as invoked during
-the \identifier{Luaotfload} build process.\footnote{%
- \emphasis{Hint for those interested in the packaging process}: issue
- \inlinecode{make show} for a list of available build routines.
-}
-These will call \inlinecode{mkimport} script with the correct
-parameters to generate a datestamped package.
-%
-Whether files have been updated in the upstream distribution can be
-queried by \inlinecode{./scripts/mkimport news}.
-%
-This will compare the imported files with their counterparts in the
-\CONTEXT distribution and report changes.
-
-\endsubsection
-
-\endsection
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-\beginsection {Configuration Files}
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-\beginnarrower
- \emphasis{Caution}: For the authoritative documentation, consult the
- manpage for \fileent{luaotfload.conf(5)}.
-\endnarrower
-
-\label{sec:conf}
-The runtime behavior of \identifier{Luaotfload} can be customized by
-means of a configuration file.
-% location
-At startup, it attempts to locate a file called \fileent
-{luaotfload.conf} or \fileent {luaotfloadrc} at a number of candidate
-locations:
-
-\begincentered
- \begindefinitions
- \beginnormalitem \fileent{./luaotfload.conf} \endnormalitem
- \beginnormalitem \fileent{./luaotfloadrc} \endnormalitem
- \beginnormalitem \fileent{\$XDG_CONFIG_HOME/luaotfload/luaotfload.conf} \endnormalitem
- \beginnormalitem \fileent{\$XDG_CONFIG_HOME/luaotfload/luaotfload.rc} \endnormalitem
- \beginnormalitem \fileent{~/.luaotfloadrc} \endnormalitem
- \enddefinitions
-\endcentered
-
-\beginnarrower
- \emphasis{Caution}: The configuration potentially modifies the final
- document. A project-local file belongs under version control along
- with the rest of the document. This is to ensure that everybody who
- builds the project also receives the same customizations as the
- author.
-\endnarrower
-
-% syntax
-The syntax is fairly close to the format used by
-\fileent{git-config(1)} which in turn was derived from the popular
-\identifier{.INI} format: Lines of key-value pairs are grouped under
-different configuration “sections”.\footnote{%
- The configuration parser in \fileent {luoatfload-parsers.lua} might
- be employed by other packages for similar purposes.
-}
-% example settings
-An example for customization via \fileent {luaotfload.conf} might look
-as below:
-
-\beginlisting
-; Example luaotfload.conf containing a rudimentary configuration
-[db]
- update-live = false
-[run]
- color-callback = pre_linebreak_filter
- definer = info_patch
- log-level = 5
-[default-features]
- global = mode=base
-\endlisting
-
-This specifies that for the given project, \identifier{Luaotfload}
-shall not attempt to automatically scan for fonts if it can’t resolve a
-request. The font-based colorization will happen during \LUATEX’s
-pre-linebreak filter. The fontloader will output verbose information
-about the fonts at definition time along with globally increased
-verbosity. Lastly, the fontloader defaults to the less expensive
-\luaident{base} mode like it does in \CONTEXT.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-\beginsection {Auxiliary Functions}
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-With release version 2.2, \identifier{Luaotfload} received
-additional functions for package authors to call from outside
-(see the file \fileent{luaotfload-auxiliary.lua} for details).
-%
-The purpose of this addition twofold.
-%
-Firstly, \identifier{luaotfload} failed to provide a stable interface
-to internals in the past which resulted in an unmanageable situation
-of different packages abusing the raw access to font objects by means
-of the \luaident{patch_font} callback.
-%
-When the structure of the font object changed due to an update, all
-of these imploded and several packages had to be fixed while
-simultaneously providing fallbacks for earlier versions.
-%
-Now the patching is done on the \identifier{luaotfload} side and can
-be adapted with future modifications to font objects without touching
-the packages that depend on it.
-%
-Second, some the capabilities of the font loader and the names
-database are not immediately relevant in \identifier{luaotfload}
-itself but might nevertheless be of great value to package authors or
-end users.
-
-Note that the current interface is not yet set in stone and the
-development team is open to suggestions for improvements or
-additions.
-
-\beginsubsection {Callback Functions}
-
-The \luaident{patch_font} callback is inserted in the wrapper
-\identifier{luaotfload} provides for the font definition callback.
-%
-At this place it allows manipulating the font object immediately after
-the font loader is done creating it.
-%
-For a short demonstration of its usefulness, here is a snippet that
-writes an entire font object to the file \fileent{fontdump.lua}:
-
-\beginlisting
- \input luaotfload.sty
- \directlua{
- local dumpfile = "fontdump.lua"
- local dump_font = function (tfmdata)
- local data = table.serialize(tfmdata)
- io.savedata(dumpfile, data)
- end
-
- luatexbase.add_to_callback(
- "luaotfload.patch_font",
- dump_font,
- "my_private_callbacks.dump_font"
- )
- }
- \font \dumpme = name:Iwona
- \bye
-\endlisting
-
-\emphasis{Beware}: this creates a Lua file of around 150,000 lines of
-code, taking up 3~\abbrev{mb} of disk space.
-%
-By inspecting the output you can get a first impression of how a font
-is structured in \LUATEX’s memory, what elements it is composed of,
-and in what ways it can be rearranged.
-
-\beginsubsubsection {Compatibility with Earlier Versions}
-
-As has been touched on in the preface to this section, the structure
-of the object as returned by the fontloader underwent rather drastic
-changes during different stages of its development, and not all
-packages that made use of font patching have kept up with every one
-of it.
-%
-To ensure compatibility with these as well as older versions of
-some packages, \identifier{luaotfload} sets up copies of or references
-to data in the font table where it used to be located.
-%
-For instance, important parameters like the requested point size, the
-units factor, and the font name have again been made accessible from
-the toplevel of the table even though they were migrated to different
-subtables in the meantime.
-
-\endsubsubsection
-
-\beginsubsubsection{Patches}
-
-These are mostly concerned with establishing compatibility with \XETEX.
-
-\beginfunctionlist
-
- \beginaltitem {set_sscale_dimens}
- Calculate \texmacro{fontdimen}s 10 and 11 to emulate \XETEX.
- \endaltitem
-
- \beginaltitem {set_capheight}
- Calculates \texmacro{fontdimen} 8 like \XETEX.
- \endaltitem
-
- \beginaltitem {patch_cambria_domh}
- Correct some values of the font \emphasis{Cambria Math}.
- \endaltitem
-
-\endfunctionlist
-
-\endsubsection
-
-\beginsubsection {Package Author’s Interface}
-
-As \LUATEX release 1.0 is nearing, the demand for a reliable interface
-for package authors increases.
-
-\endsubsubsection
-
-\beginsubsubsection{Font Properties}
-
-Below functions mostly concern querying the different components of a
-font like for instance the glyphs it contains, or what font features
-are defined for which scripts.
-
-\beginfunctionlist
-
- \beginaltitem {aux.font_has_glyph (id : int, index : int)}
- Predicate that returns true if the font \luaident{id}
- has glyph \luaident{index}.
- \endaltitem
-
- \beginaltitem {aux.slot_of_name(name : string)}
- Translates an Adobe Glyph name to the corresponding glyph
- slot.
- \endaltitem
-
- \beginaltitem {aux.name_of_slot(slot : int)}
- The inverse of \luaident{slot_of_name}; note that this
- might be incomplete as multiple glyph names may map to the
- same codepoint, only one of which is returned by
- \luaident{name_of_slot}.
- \endaltitem
-
- \beginaltitem {aux.provides_script(id : int, script : string)}
- Test if a font supports \luaident{script}.
- \endaltitem
-
- \beginaltitem {aux.provides_language(id : int, script : string, language : string)}
- Test if a font defines \luaident{language} for a given
- \luaident{script}.
- \endaltitem
-
- \beginaltitem {aux.provides_feature(id : int, script : string,
- language : string, feature : string)}
- Test if a font defines \luaident{feature} for
- \luaident{language} for a given \luaident{script}.
- \endaltitem
-
- \beginaltitem {aux.get_math_dimension(id : int, dimension : string)}
- Get the dimension \luaident{dimension} of font \luaident{id}.
- \endaltitem
-
- \beginaltitem {aux.sprint_math_dimension(id : int, dimension : string)}
- Same as \luaident{get_math_dimension()}, but output the value
- in scaled points at the \TEX end.
- \endaltitem
-
-\endfunctionlist
-
-\endsubsubsection
-
-\beginsubsubsection{Database}
-
-%% not implemented, may come back later
-\beginfunctionlist
-% \beginaltitem {aux.scan_external_dir(dir : string)}
-% Include fonts in directory \luaident{dir} in font lookups without
-% adding them to the database.
-%
- \beginaltitem {aux.read_font_index (void)}
- Read the index file from the appropriate location (usually
- the bytecode file \fileent{luaotfload-names.luc} somewhere
- in the \fileent{texmf-var} tree) and return the result as a
- table. The file is processed with each call so it is up to
- the user to store the result for later access.
- \endaltitem
-
- \beginaltitem {aux.font_index (void)}
- Return a reference of the font names table used internally
- by \identifier{luaotfload}. The index will be read if it
- has not been loaded up to this point. Also a font scan that
- overwrites the current index file might be triggered. Since
- the return value points to the actual index, any
- modifications to the table might influence runtime behavior
- of \identifier{luaotfload}.
- \endaltitem
-
-\endfunctionlist
-
-\endsubsubsection
-
-\endsubsection
-\endsection
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-\beginsection {Troubleshooting}
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-\beginsubsection {Database Generation}
-
-If you encounter problems with some fonts, please first update to the
-latest version of this package before reporting a bug, as
-\identifier{luaotfload} is under active development and still a moving
-target.
-%
-The development takes place on \identifier{github} at
-\hyperlink {https://github.com/lualatex/luaotfload} where there is an issue
-tracker for submitting bug reports, feature requests and the likes.
-
-Bug reports are more likely to be addressed if they contain the output
-of
-
-\beginlisting
- luaotfload-tool --diagnose=environment,files,permissions
-\endlisting
-
-\noindent Consult the man page for a description of these options.
-
-Errors during database generation can be traced by increasing the
-verbosity level and redirecting log output to \fileent{stdout}:
-
-\beginlisting
- luaotfload-tool -fuvvv --log=stdout
-\endlisting
-
-\noindent or to a file in \fileent{/tmp}:
-
-\beginlisting
- luaotfload-tool -fuvvv --log=file
-\endlisting
-
-\noindent In the latter case, invoke the \inlinecode {tail(1)} utility on the
-file for live monitoring of the progress.
-
-If database generation fails, the font last printed to the terminal or
-log file is likely to be the culprit.
-%
-Please specify it when reporting a bug, and blacklist it for the time
-being (see above, page \pageref{font-blacklist}).
-
-\endsubsection
-
-\beginsubsection {Font Features}
-
-A common problem is the lack of features for some
-\OpenType fonts even when specified.
-%
-This can be related to the fact that some fonts do not provide features
-for the \inlinecode {dflt} script (see above on page \pageref{script-tag}),
-which is the default one in this package.
-%
-If this happens, assigning a noth script when the font is defined should
-fix it.
-%
-For example with \inlinecode {latn}:
-
-\beginlisting
- \font \test = file:MyFont.otf:script=latn;+liga;
-\endlisting
-
-You can get a list of features that a font defines for scripts and
-languages by querying it in \fileent{luaotfload-tool}:
-
-\beginlisting
- luaotfload-tool --find="Iwona" --inspect
-\endlisting
-
-\endsubsection
-
-\beginsubsection {\LUATEX Programming}
-
-Another strategy that helps avoiding problems is to not access raw
-\LUATEX internals directly.
-%
-Some of them, even though they are dangerous to access, have not been
-overridden or disabled.
-%
-Thus, whenever possible prefer the functions in the \luaident{aux}
-namespace over direct manipulation of font objects. For example, raw
-access to the \luaident{font.fonts} table like:
-
-\beginlisting
- local somefont = font.fonts[2]
-\endlisting
-
-\noindent can render already defined fonts unusable.
-%
-Instead, the function \luaident{font.getfont()} should be used
-because it has been replaced by a safe variant.
-
-However, \luaident{font.getfont()} only covers fonts handled by the
-font loader, e.~g. \identifier{OpenType} and \identifier{TrueType}
-fonts, but not \abbrev{tfm} or \abbrev{ofm}.
-%
-Should you absolutely require access to all fonts known to \LUATEX,
-including the virtual and autogenerated ones, then you need to query
-both \luaident{font.getfont()} and \luaident{font.fonts}.
-%
-In this case, best define you own accessor:
-
-\beginlisting
- local unsafe_getfont = function (id)
- local tfmdata = font.getfont (id)
- if not tfmdata then
- tfmdata = font.fonts[id]
- end
- return tfmdata
- end
-
- --- use like getfont()
- local somefont = unsafe_getfont (2)
-\endlisting
-
-\endsubsection
-\endsection
-
-\beginsection {License}
-
-\identifier {luaotfload} is licensed under the terms of the
-\hyperlink [GNU General Public License version 2.0]%
- {https://www.gnu.org/licenses/old-licenses/gpl-2.0.html}.
-Following the underlying fontloader code \identifier {luaotfload}
-recognizes only that exact version as its license.
-The „any later version” clause of the original license text as
-copyrighted by the \hyperlink [Free Software Foundation]{http://www.fsf.org/}
-\emphasis {does not apply} to either \identifier {luaotfload} or the
-code imported from \CONTEXT.
-
-The complete text of the license is given as a separate file \fileent
-{COPYING} in the toplevel directory of the
-\hyperlink [\fileent {Luaotfload} Git repository]{https://github.com/lualatex/luaotfload/blob/master/COPYING}.
-Distributions probably package it as \fileent
-{doc/luatex/luaotfload/COPYING} in the relevant \fileent {texmf} tree.
-
-\endsection
-
-\endinput
-
-% vim:ft=tex:tw=79:et:sw=2
Deleted: trunk/Master/texmf-dist/source/luatex/luaotfload/luaotfload-tool.rst
===================================================================
(Binary files differ)
Deleted: trunk/Master/texmf-dist/source/luatex/luaotfload/luaotfload.conf.rst
===================================================================
(Binary files differ)
Deleted: trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-2017-02-11.lua
===================================================================
--- trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-2017-02-11.lua 2018-09-26 20:49:48 UTC (rev 48770)
+++ trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-2017-02-11.lua 2018-09-26 20:50:34 UTC (rev 48771)
@@ -1,21726 +0,0 @@
---[[info-----------------------------------------------------------------------
- Luaotfload fontloader package
- build 2017-02-11 18:16:05 by phg at phlegethon
--------------------------------------------------------------------------------
-
- © 2017 PRAGMA ADE / ConTeXt Development Team
-
- The code in this file is provided under the GPL v2.0 license. See the
- file COPYING in the Luaotfload repository for details.
-
- Report bugs to github.com/lualatex/luaotfload
-
- This file has been assembled from components taken from Context. See
- the Luaotfload documentation for details:
-
- $ texdoc luaotfload
- $ man 1 luaotfload-tool
- $ man 5 luaotfload.conf
-
- Included files:
-
- · fontloader-data-con.lua
- · fontloader-basics-nod.lua
- · fontloader-font-ini.lua
- · fontloader-font-con.lua
- · fontloader-fonts-enc.lua
- · fontloader-font-cid.lua
- · fontloader-font-map.lua
- · fontloader-font-oti.lua
- · fontloader-font-otr.lua
- · fontloader-font-cff.lua
- · fontloader-font-ttf.lua
- · fontloader-font-dsp.lua
- · fontloader-font-oup.lua
- · fontloader-font-otl.lua
- · fontloader-font-oto.lua
- · fontloader-font-otj.lua
- · fontloader-font-ota.lua
- · fontloader-font-ots.lua
- · fontloader-font-osd.lua
- · fontloader-font-ocl.lua
- · fontloader-font-otc.lua
- · fontloader-font-onr.lua
- · fontloader-font-one.lua
- · fontloader-font-afk.lua
- · fontloader-font-tfm.lua
- · fontloader-font-lua.lua
- · fontloader-font-def.lua
- · fontloader-fonts-ext.lua
- · fontloader-font-gbn.lua
-
---info]]-----------------------------------------------------------------------
-
-
-do --- [luaotfload, fontloader-2017-02-11.lua scope for “data-con” d8982c834ed9acc6193eee23067b9d5d] ---
-
-if not modules then modules={} end modules ['data-con']={
- version=1.100,
- comment="companion to luat-lib.mkiv",
- author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright="PRAGMA ADE / ConTeXt Development Team",
- license="see context related readme files"
-}
-local format,lower,gsub=string.format,string.lower,string.gsub
-local trace_cache=false trackers.register("resolvers.cache",function(v) trace_cache=v end)
-local trace_containers=false trackers.register("resolvers.containers",function(v) trace_containers=v end)
-local trace_storage=false trackers.register("resolvers.storage",function(v) trace_storage=v end)
-containers=containers or {}
-local containers=containers
-containers.usecache=true
-local report_containers=logs.reporter("resolvers","containers")
-local allocated={}
-local mt={
- __index=function(t,k)
- if k=="writable" then
- local writable=caches.getwritablepath(t.category,t.subcategory) or { "." }
- t.writable=writable
- return writable
- elseif k=="readables" then
- local readables=caches.getreadablepaths(t.category,t.subcategory) or { "." }
- t.readables=readables
- return readables
- end
- end,
- __storage__=true
-}
-function containers.define(category,subcategory,version,enabled)
- if category and subcategory then
- local c=allocated[category]
- if not c then
- c={}
- allocated[category]=c
- end
- local s=c[subcategory]
- if not s then
- s={
- category=category,
- subcategory=subcategory,
- storage={},
- enabled=enabled,
- version=version or math.pi,
- trace=false,
- }
- setmetatable(s,mt)
- c[subcategory]=s
- end
- return s
- end
-end
-function containers.is_usable(container,name)
- return container.enabled and caches and caches.is_writable(container.writable,name)
-end
-function containers.is_valid(container,name)
- if name and name~="" then
- local storage=container.storage[name]
- return storage and storage.cache_version==container.version
- else
- return false
- end
-end
-function containers.read(container,name)
- local storage=container.storage
- local stored=storage[name]
- if not stored and container.enabled and caches and containers.usecache then
- stored=caches.loaddata(container.readables,name,container.writable)
- if stored and stored.cache_version==container.version then
- if trace_cache or trace_containers then
- report_containers("action %a, category %a, name %a","load",container.subcategory,name)
- end
- else
- stored=nil
- end
- storage[name]=stored
- elseif stored then
- if trace_cache or trace_containers then
- report_containers("action %a, category %a, name %a","reuse",container.subcategory,name)
- end
- end
- return stored
-end
-function containers.write(container,name,data)
- if data then
- data.cache_version=container.version
- if container.enabled and caches then
- local unique,shared=data.unique,data.shared
- data.unique,data.shared=nil,nil
- caches.savedata(container.writable,name,data)
- if trace_cache or trace_containers then
- report_containers("action %a, category %a, name %a","save",container.subcategory,name)
- end
- data.unique,data.shared=unique,shared
- end
- if trace_cache or trace_containers then
- report_containers("action %a, category %a, name %a","store",container.subcategory,name)
- end
- container.storage[name]=data
- end
- return data
-end
-function containers.content(container,name)
- return container.storage[name]
-end
-function containers.cleanname(name)
- return (gsub(lower(name),"[^%w\128-\255]+","-"))
-end
-
-end --- [luaotfload, fontloader-2017-02-11.lua scope for “data-con”] ---
-
-
-do --- [luaotfload, fontloader-2017-02-11.lua scope for “basics-nod” 9288471b8395bfb683aba0ff3964d950] ---
-
-if not modules then modules={} end modules ['luatex-fonts-nod']={
- version=1.001,
- comment="companion to luatex-fonts.lua",
- author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright="PRAGMA ADE / ConTeXt Development Team",
- license="see context related readme files"
-}
-if context then
- texio.write_nl("fatal error: this module is not for context")
- os.exit()
-end
-if tex.attribute[0]~=0 then
- texio.write_nl("log","!")
- texio.write_nl("log","! Attribute 0 is reserved for ConTeXt's font feature management and has to be")
- texio.write_nl("log","! set to zero. Also, some attributes in the range 1-255 are used for special")
- texio.write_nl("log","! purposes so setting them at the TeX end might break the font handler.")
- texio.write_nl("log","!")
- tex.attribute[0]=0
-end
-attributes=attributes or {}
-attributes.unsetvalue=-0x7FFFFFFF
-local numbers,last={},127
-attributes.private=attributes.private or function(name)
- local number=numbers[name]
- if not number then
- if last<255 then
- last=last+1
- end
- number=last
- numbers[name]=number
- end
- return number
-end
-nodes={}
-nodes.pool={}
-nodes.handlers={}
-local nodecodes={}
-local glyphcodes=node.subtypes("glyph")
-local disccodes=node.subtypes("disc")
-for k,v in next,node.types() do
- v=string.gsub(v,"_","")
- nodecodes[k]=v
- nodecodes[v]=k
-end
-for i=0,#glyphcodes do
- glyphcodes[glyphcodes[i]]=i
-end
-for i=0,#disccodes do
- disccodes[disccodes[i]]=i
-end
-nodes.nodecodes=nodecodes
-nodes.glyphcodes=glyphcodes
-nodes.disccodes=disccodes
-local flush_node=node.flush_node
-local remove_node=node.remove
-local new_node=node.new
-local traverse_id=node.traverse_id
-nodes.handlers.protectglyphs=node.protect_glyphs
-nodes.handlers.unprotectglyphs=node.unprotect_glyphs
-local math_code=nodecodes.math
-local end_of_math=node.end_of_math
-function node.end_of_math(n)
- if n.id==math_code and n.subtype==1 then
- return n
- else
- return end_of_math(n)
- end
-end
-function nodes.remove(head,current,free_too)
- local t=current
- head,current=remove_node(head,current)
- if t then
- if free_too then
- flush_node(t)
- t=nil
- else
- t.next,t.prev=nil,nil
- end
- end
- return head,current,t
-end
-function nodes.delete(head,current)
- return nodes.remove(head,current,true)
-end
-function nodes.pool.kern(k)
- local n=new_node("kern",1)
- n.kern=k
- return n
-end
-local getfield=node.getfield
-local setfield=node.setfield
-nodes.getfield=getfield
-nodes.setfield=setfield
-nodes.getattr=getfield
-nodes.setattr=setfield
-nodes.tostring=node.tostring or tostring
-nodes.copy=node.copy
-nodes.copy_node=node.copy
-nodes.copy_list=node.copy_list
-nodes.delete=node.delete
-nodes.dimensions=node.dimensions
-nodes.end_of_math=node.end_of_math
-nodes.flush_list=node.flush_list
-nodes.flush_node=node.flush_node
-nodes.flush=node.flush_node
-nodes.free=node.free
-nodes.insert_after=node.insert_after
-nodes.insert_before=node.insert_before
-nodes.hpack=node.hpack
-nodes.new=node.new
-nodes.tail=node.tail
-nodes.traverse=node.traverse
-nodes.traverse_id=node.traverse_id
-nodes.slide=node.slide
-nodes.vpack=node.vpack
-nodes.first_glyph=node.first_glyph
-nodes.has_glyph=node.has_glyph or node.first_glyph
-nodes.current_attr=node.current_attr
-nodes.has_field=node.has_field
-nodes.last_node=node.last_node
-nodes.usedlist=node.usedlist
-nodes.protrusion_skippable=node.protrusion_skippable
-nodes.write=node.write
-nodes.has_attribute=node.has_attribute
-nodes.set_attribute=node.set_attribute
-nodes.unset_attribute=node.unset_attribute
-nodes.protect_glyphs=node.protect_glyphs
-nodes.unprotect_glyphs=node.unprotect_glyphs
-nodes.mlist_to_hlist=node.mlist_to_hlist
-local direct=node.direct
-local nuts={}
-nodes.nuts=nuts
-local tonode=direct.tonode
-local tonut=direct.todirect
-nodes.tonode=tonode
-nodes.tonut=tonut
-nuts.tonode=tonode
-nuts.tonut=tonut
-local getfield=direct.getfield
-local setfield=direct.setfield
-nuts.getfield=getfield
-nuts.setfield=setfield
-nuts.getnext=direct.getnext
-nuts.setnext=direct.setnext
-nuts.getprev=direct.getprev
-nuts.setprev=direct.setprev
-nuts.getboth=direct.getboth
-nuts.setboth=direct.setboth
-nuts.getid=direct.getid
-nuts.getattr=direct.get_attribute or direct.has_attribute or getfield
-nuts.setattr=setfield
-nuts.getfont=direct.getfont
-nuts.setfont=direct.setfont
-nuts.getsubtype=direct.getsubtype
-nuts.setsubtype=direct.setsubtype or function(n,s) setfield(n,"subtype",s) end
-nuts.getchar=direct.getchar
-nuts.setchar=direct.setchar
-nuts.getdisc=direct.getdisc
-nuts.setdisc=direct.setdisc
-nuts.setlink=direct.setlink
-nuts.getlist=direct.getlist
-nuts.setlist=direct.setlist or function(n,l) setfield(n,"list",l) end
-nuts.getleader=direct.getleader
-nuts.setleader=direct.setleader or function(n,l) setfield(n,"leader",l) end
-if not direct.is_glyph then
- local getchar=direct.getchar
- local getid=direct.getid
- local getfont=direct.getfont
- local glyph_code=nodes.nodecodes.glyph
- function direct.is_glyph(n,f)
- local id=getid(n)
- if id==glyph_code then
- if f and getfont(n)==f then
- return getchar(n)
- else
- return false
- end
- else
- return nil,id
- end
- end
- function direct.is_char(n,f)
- local id=getid(n)
- if id==glyph_code then
- if getsubtype(n)>=256 then
- return false
- elseif f and getfont(n)==f then
- return getchar(n)
- else
- return false
- end
- else
- return nil,id
- end
- end
-end
-nuts.ischar=direct.is_char
-nuts.is_char=direct.is_char
-nuts.isglyph=direct.is_glyph
-nuts.is_glyph=direct.is_glyph
-nuts.insert_before=direct.insert_before
-nuts.insert_after=direct.insert_after
-nuts.delete=direct.delete
-nuts.copy=direct.copy
-nuts.copy_node=direct.copy
-nuts.copy_list=direct.copy_list
-nuts.tail=direct.tail
-nuts.flush_list=direct.flush_list
-nuts.flush_node=direct.flush_node
-nuts.flush=direct.flush
-nuts.free=direct.free
-nuts.remove=direct.remove
-nuts.is_node=direct.is_node
-nuts.end_of_math=direct.end_of_math
-nuts.traverse=direct.traverse
-nuts.traverse_id=direct.traverse_id
-nuts.traverse_char=direct.traverse_char
-nuts.ligaturing=direct.ligaturing
-nuts.kerning=direct.kerning
-nuts.getprop=nuts.getattr
-nuts.setprop=nuts.setattr
-local new_nut=direct.new
-nuts.new=new_nut
-nuts.pool={}
-function nuts.pool.kern(k)
- local n=new_nut("kern",1)
- setfield(n,"kern",k)
- return n
-end
-local propertydata=direct.get_properties_table()
-nodes.properties={ data=propertydata }
-direct.set_properties_mode(true,true)
-function direct.set_properties_mode() end
-nuts.getprop=function(n,k)
- local p=propertydata[n]
- if p then
- return p[k]
- end
-end
-nuts.setprop=function(n,k,v)
- if v then
- local p=propertydata[n]
- if p then
- p[k]=v
- else
- propertydata[n]={ [k]=v }
- end
- end
-end
-nodes.setprop=nodes.setproperty
-nodes.getprop=nodes.getproperty
-
-end --- [luaotfload, fontloader-2017-02-11.lua scope for “basics-nod”] ---
-
-
-do --- [luaotfload, fontloader-2017-02-11.lua scope for “font-ini” 10cb9a563a98e06ff79c35a8751e13dc] ---
-
-if not modules then modules={} end modules ['font-ini']={
- version=1.001,
- comment="companion to font-ini.mkiv",
- author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright="PRAGMA ADE / ConTeXt Development Team",
- license="see context related readme files"
-}
-local allocate=utilities.storage.allocate
-fonts=fonts or {}
-local fonts=fonts
-fonts.hashes={ identifiers=allocate() }
-fonts.tables=fonts.tables or {}
-fonts.helpers=fonts.helpers or {}
-fonts.tracers=fonts.tracers or {}
-fonts.specifiers=fonts.specifiers or {}
-fonts.analyzers={}
-fonts.readers={}
-fonts.definers={ methods={} }
-fonts.loggers={ register=function() end }
-fontloader.totable=fontloader.to_table
-
-end --- [luaotfload, fontloader-2017-02-11.lua scope for “font-ini”] ---
-
-
-do --- [luaotfload, fontloader-2017-02-11.lua scope for “font-con” 7575a7b4e6d04816072945e27d7d0b33] ---
-
-if not modules then modules={} end modules ['font-con']={
- version=1.001,
- comment="companion to font-ini.mkiv",
- author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright="PRAGMA ADE / ConTeXt Development Team",
- license="see context related readme files"
-}
-local next,tostring,rawget=next,tostring,rawget
-local format,match,lower,gsub,find=string.format,string.match,string.lower,string.gsub,string.find
-local sort,insert,concat,sortedkeys,serialize,fastcopy=table.sort,table.insert,table.concat,table.sortedkeys,table.serialize,table.fastcopy
-local derivetable=table.derive
-local ioflush=io.flush
-local trace_defining=false trackers.register("fonts.defining",function(v) trace_defining=v end)
-local trace_scaling=false trackers.register("fonts.scaling",function(v) trace_scaling=v end)
-local report_defining=logs.reporter("fonts","defining")
-local fonts=fonts
-local constructors=fonts.constructors or {}
-fonts.constructors=constructors
-local handlers=fonts.handlers or {}
-fonts.handlers=handlers
-local allocate=utilities.storage.allocate
-local setmetatableindex=table.setmetatableindex
-constructors.dontembed=allocate()
-constructors.autocleanup=true
-constructors.namemode="fullpath"
-constructors.version=1.01
-constructors.cache=containers.define("fonts","constructors",constructors.version,false)
-constructors.privateoffset=0xF0000
-constructors.cacheintex=true
-local designsizes=allocate()
-constructors.designsizes=designsizes
-local loadedfonts=allocate()
-constructors.loadedfonts=loadedfonts
-local factors={
- pt=65536.0,
- bp=65781.8,
-}
-function constructors.setfactor(f)
- constructors.factor=factors[f or 'pt'] or factors.pt
-end
-constructors.setfactor()
-function constructors.scaled(scaledpoints,designsize)
- if scaledpoints<0 then
- local factor=constructors.factor
- if designsize then
- if designsize>factor then
- return (- scaledpoints/1000)*designsize
- else
- return (- scaledpoints/1000)*designsize*factor
- end
- else
- return (- scaledpoints/1000)*10*factor
- end
- else
- return scaledpoints
- end
-end
-function constructors.cleanuptable(tfmdata)
- if constructors.autocleanup and tfmdata.properties.virtualized then
- for k,v in next,tfmdata.characters do
- if v.commands then v.commands=nil end
- end
- end
-end
-function constructors.calculatescale(tfmdata,scaledpoints)
- local parameters=tfmdata.parameters
- if scaledpoints<0 then
- scaledpoints=(- scaledpoints/1000)*(tfmdata.designsize or parameters.designsize)
- end
- return scaledpoints,scaledpoints/(parameters.units or 1000)
-end
-local unscaled={
- ScriptPercentScaleDown=true,
- ScriptScriptPercentScaleDown=true,
- RadicalDegreeBottomRaisePercent=true,
- NoLimitSupFactor=true,
- NoLimitSubFactor=true,
-}
-function constructors.assignmathparameters(target,original)
- local mathparameters=original.mathparameters
- if mathparameters and next(mathparameters) then
- local targetparameters=target.parameters
- local targetproperties=target.properties
- local targetmathparameters={}
- local factor=targetproperties.math_is_scaled and 1 or targetparameters.factor
- for name,value in next,mathparameters do
- if unscaled[name] then
- targetmathparameters[name]=value
- else
- targetmathparameters[name]=value*factor
- end
- end
- if not targetmathparameters.FractionDelimiterSize then
- targetmathparameters.FractionDelimiterSize=1.01*targetparameters.size
- end
- if not mathparameters.FractionDelimiterDisplayStyleSize then
- targetmathparameters.FractionDelimiterDisplayStyleSize=2.40*targetparameters.size
- end
- target.mathparameters=targetmathparameters
- end
-end
-function constructors.beforecopyingcharacters(target,original)
-end
-function constructors.aftercopyingcharacters(target,original)
-end
-constructors.sharefonts=false
-constructors.nofsharedfonts=0
-local sharednames={}
-function constructors.trytosharefont(target,tfmdata)
- if constructors.sharefonts then
- local characters=target.characters
- local n=1
- local t={ target.psname }
- local u=sortedkeys(characters)
- for i=1,#u do
- local k=u[i]
- n=n+1;t[n]=k
- n=n+1;t[n]=characters[k].index or k
- end
- local h=md5.HEX(concat(t," "))
- local s=sharednames[h]
- if s then
- if trace_defining then
- report_defining("font %a uses backend resources of font %a",target.fullname,s)
- end
- target.fullname=s
- constructors.nofsharedfonts=constructors.nofsharedfonts+1
- target.properties.sharedwith=s
- else
- sharednames[h]=target.fullname
- end
- end
-end
-function constructors.enhanceparameters(parameters)
- local xheight=parameters.x_height
- local quad=parameters.quad
- local space=parameters.space
- local stretch=parameters.space_stretch
- local shrink=parameters.space_shrink
- local extra=parameters.extra_space
- local slant=parameters.slant
- parameters.xheight=xheight
- parameters.spacestretch=stretch
- parameters.spaceshrink=shrink
- parameters.extraspace=extra
- parameters.em=quad
- parameters.ex=xheight
- parameters.slantperpoint=slant
- parameters.spacing={
- width=space,
- stretch=stretch,
- shrink=shrink,
- extra=extra,
- }
-end
-local function mathkerns(v,vdelta)
- local k={}
- for i=1,#v do
- local entry=v[i]
- local height=entry.height
- local kern=entry.kern
- k[i]={
- height=height and vdelta*height or 0,
- kern=kern and vdelta*kern or 0,
- }
- end
- return k
-end
-local psfake=0
-local function fixedpsname(psname,fallback)
- local usedname=psname
- if psname and psname~="" then
- if find(psname," ") then
- usedname=gsub(psname,"[%s]+","-")
- else
- end
- elseif not fallback or fallback=="" then
- psfake=psfake+1
- psname="fakename-"..psfake
- else
- psname=fallback
- usedname=gsub(psname,"[^a-zA-Z0-9]+","-")
- end
- return usedname,psname~=usedname
-end
-function constructors.scale(tfmdata,specification)
- local target={}
- if tonumber(specification) then
- specification={ size=specification }
- end
- target.specification=specification
- local scaledpoints=specification.size
- local relativeid=specification.relativeid
- local properties=tfmdata.properties or {}
- local goodies=tfmdata.goodies or {}
- local resources=tfmdata.resources or {}
- local descriptions=tfmdata.descriptions or {}
- local characters=tfmdata.characters or {}
- local changed=tfmdata.changed or {}
- local shared=tfmdata.shared or {}
- local parameters=tfmdata.parameters or {}
- local mathparameters=tfmdata.mathparameters or {}
- local targetcharacters={}
- local targetdescriptions=derivetable(descriptions)
- local targetparameters=derivetable(parameters)
- local targetproperties=derivetable(properties)
- local targetgoodies=goodies
- target.characters=targetcharacters
- target.descriptions=targetdescriptions
- target.parameters=targetparameters
- target.properties=targetproperties
- target.goodies=targetgoodies
- target.shared=shared
- target.resources=resources
- target.unscaled=tfmdata
- local mathsize=tonumber(specification.mathsize) or 0
- local textsize=tonumber(specification.textsize) or scaledpoints
- local forcedsize=tonumber(parameters.mathsize ) or 0
- local extrafactor=tonumber(specification.factor ) or 1
- if (mathsize==2 or forcedsize==2) and parameters.scriptpercentage then
- scaledpoints=parameters.scriptpercentage*textsize/100
- elseif (mathsize==3 or forcedsize==3) and parameters.scriptscriptpercentage then
- scaledpoints=parameters.scriptscriptpercentage*textsize/100
- elseif forcedsize>1000 then
- scaledpoints=forcedsize
- end
- targetparameters.mathsize=mathsize
- targetparameters.textsize=textsize
- targetparameters.forcedsize=forcedsize
- targetparameters.extrafactor=extrafactor
- local tounicode=fonts.mappings.tounicode
- local defaultwidth=resources.defaultwidth or 0
- local defaultheight=resources.defaultheight or 0
- local defaultdepth=resources.defaultdepth or 0
- local units=parameters.units or 1000
- if target.fonts then
- target.fonts=fastcopy(target.fonts)
- end
- targetproperties.language=properties.language or "dflt"
- targetproperties.script=properties.script or "dflt"
- targetproperties.mode=properties.mode or "base"
- local askedscaledpoints=scaledpoints
- local scaledpoints,delta=constructors.calculatescale(tfmdata,scaledpoints,nil,specification)
- local hdelta=delta
- local vdelta=delta
- target.designsize=parameters.designsize
- target.units=units
- target.units_per_em=units
- local direction=properties.direction or tfmdata.direction or 0
- target.direction=direction
- properties.direction=direction
- target.size=scaledpoints
- target.encodingbytes=properties.encodingbytes or 1
- target.embedding=properties.embedding or "subset"
- target.tounicode=1
- target.cidinfo=properties.cidinfo
- target.format=properties.format
- target.cache=constructors.cacheintex and "yes" or "renew"
- local fontname=properties.fontname or tfmdata.fontname
- local fullname=properties.fullname or tfmdata.fullname
- local filename=properties.filename or tfmdata.filename
- local psname=properties.psname or tfmdata.psname
- local name=properties.name or tfmdata.name
- local psname,psfixed=fixedpsname(psname,fontname or fullname or file.nameonly(filename))
- target.fontname=fontname
- target.fullname=fullname
- target.filename=filename
- target.psname=psname
- target.name=name
- properties.fontname=fontname
- properties.fullname=fullname
- properties.filename=filename
- properties.psname=psname
- properties.name=name
- local expansion=parameters.expansion
- if expansion then
- target.stretch=expansion.stretch
- target.shrink=expansion.shrink
- target.step=expansion.step
- target.auto_expand=expansion.auto
- end
- local protrusion=parameters.protrusion
- if protrusion then
- target.auto_protrude=protrusion.auto
- end
- local extendfactor=parameters.extendfactor or 0
- if extendfactor~=0 and extendfactor~=1 then
- hdelta=hdelta*extendfactor
- target.extend=extendfactor*1000
- else
- target.extend=1000
- end
- local slantfactor=parameters.slantfactor or 0
- if slantfactor~=0 then
- target.slant=slantfactor*1000
- else
- target.slant=0
- end
- targetparameters.factor=delta
- targetparameters.hfactor=hdelta
- targetparameters.vfactor=vdelta
- targetparameters.size=scaledpoints
- targetparameters.units=units
- targetparameters.scaledpoints=askedscaledpoints
- local isvirtual=properties.virtualized or tfmdata.type=="virtual"
- local hasquality=target.auto_expand or target.auto_protrude
- local hasitalics=properties.hasitalics
- local autoitalicamount=properties.autoitalicamount
- local stackmath=not properties.nostackmath
- local nonames=properties.noglyphnames
- local haskerns=properties.haskerns or properties.mode=="base"
- local hasligatures=properties.hasligatures or properties.mode=="base"
- local realdimensions=properties.realdimensions
- local writingmode=properties.writingmode or "horizontal"
- local identity=properties.identity or "horizontal"
- if changed and not next(changed) then
- changed=false
- end
- target.type=isvirtual and "virtual" or "real"
- target.writingmode=writingmode=="vertical" and "vertical" or "horizontal"
- target.identity=identity=="vertical" and "vertical" or "horizontal"
- target.postprocessors=tfmdata.postprocessors
- local targetslant=(parameters.slant or parameters[1] or 0)*factors.pt
- local targetspace=(parameters.space or parameters[2] or 0)*hdelta
- local targetspace_stretch=(parameters.space_stretch or parameters[3] or 0)*hdelta
- local targetspace_shrink=(parameters.space_shrink or parameters[4] or 0)*hdelta
- local targetx_height=(parameters.x_height or parameters[5] or 0)*vdelta
- local targetquad=(parameters.quad or parameters[6] or 0)*hdelta
- local targetextra_space=(parameters.extra_space or parameters[7] or 0)*hdelta
- targetparameters.slant=targetslant
- targetparameters.space=targetspace
- targetparameters.space_stretch=targetspace_stretch
- targetparameters.space_shrink=targetspace_shrink
- targetparameters.x_height=targetx_height
- targetparameters.quad=targetquad
- targetparameters.extra_space=targetextra_space
- local ascender=parameters.ascender
- if ascender then
- targetparameters.ascender=delta*ascender
- end
- local descender=parameters.descender
- if descender then
- targetparameters.descender=delta*descender
- end
- constructors.enhanceparameters(targetparameters)
- local protrusionfactor=(targetquad~=0 and 1000/targetquad) or 0
- local scaledwidth=defaultwidth*hdelta
- local scaledheight=defaultheight*vdelta
- local scaleddepth=defaultdepth*vdelta
- local hasmath=(properties.hasmath or next(mathparameters)) and true
- if hasmath then
- constructors.assignmathparameters(target,tfmdata)
- properties.hasmath=true
- target.nomath=false
- target.MathConstants=target.mathparameters
- else
- properties.hasmath=false
- target.nomath=true
- target.mathparameters=nil
- end
- if hasmath then
- local mathitalics=properties.mathitalics
- if mathitalics==false then
- if trace_defining then
- report_defining("%s italics %s for font %a, fullname %a, filename %a","math",hasitalics and "ignored" or "disabled",name,fullname,filename)
- end
- hasitalics=false
- autoitalicamount=false
- end
- else
- local textitalics=properties.textitalics
- if textitalics==false then
- if trace_defining then
- report_defining("%s italics %s for font %a, fullname %a, filename %a","text",hasitalics and "ignored" or "disabled",name,fullname,filename)
- end
- hasitalics=false
- autoitalicamount=false
- end
- end
- if trace_defining then
- report_defining("defining tfm, name %a, fullname %a, filename %a, %spsname %a, hscale %a, vscale %a, math %a, italics %a",
- name,fullname,filename,psfixed and "(fixed) " or "",psname,hdelta,vdelta,
- hasmath and "enabled" or "disabled",hasitalics and "enabled" or "disabled")
- end
- constructors.beforecopyingcharacters(target,tfmdata)
- local sharedkerns={}
- for unicode,character in next,characters do
- local chr,description,index
- if changed then
- local c=changed[unicode]
- if c then
- description=descriptions[c] or descriptions[unicode] or character
- character=characters[c] or character
- index=description.index or c
- else
- description=descriptions[unicode] or character
- index=description.index or unicode
- end
- else
- description=descriptions[unicode] or character
- index=description.index or unicode
- end
- local width=description.width
- local height=description.height
- local depth=description.depth
- if realdimensions then
- if not height or height==0 then
- local bb=description.boundingbox
- local ht=bb[4]
- if ht~=0 then
- height=ht
- end
- if not depth or depth==0 then
- local dp=-bb[2]
- if dp~=0 then
- depth=dp
- end
- end
- elseif not depth or depth==0 then
- local dp=-description.boundingbox[2]
- if dp~=0 then
- depth=dp
- end
- end
- end
- if width then width=hdelta*width else width=scaledwidth end
- if height then height=vdelta*height else height=scaledheight end
- if depth and depth~=0 then
- depth=delta*depth
- if nonames then
- chr={
- index=index,
- height=height,
- depth=depth,
- width=width,
- }
- else
- chr={
- name=description.name,
- index=index,
- height=height,
- depth=depth,
- width=width,
- }
- end
- else
- if nonames then
- chr={
- index=index,
- height=height,
- width=width,
- }
- else
- chr={
- name=description.name,
- index=index,
- height=height,
- width=width,
- }
- end
- end
- local isunicode=description.unicode
- if isunicode then
- chr.unicode=isunicode
- chr.tounicode=tounicode(isunicode)
- end
- if hasquality then
- local ve=character.expansion_factor
- if ve then
- chr.expansion_factor=ve*1000
- end
- local vl=character.left_protruding
- if vl then
- chr.left_protruding=protrusionfactor*width*vl
- end
- local vr=character.right_protruding
- if vr then
- chr.right_protruding=protrusionfactor*width*vr
- end
- end
- if hasmath then
- local vn=character.next
- if vn then
- chr.next=vn
- else
- local vv=character.vert_variants
- if vv then
- local t={}
- for i=1,#vv do
- local vvi=vv[i]
- t[i]={
- ["start"]=(vvi["start"] or 0)*vdelta,
- ["end"]=(vvi["end"] or 0)*vdelta,
- ["advance"]=(vvi["advance"] or 0)*vdelta,
- ["extender"]=vvi["extender"],
- ["glyph"]=vvi["glyph"],
- }
- end
- chr.vert_variants=t
- else
- local hv=character.horiz_variants
- if hv then
- local t={}
- for i=1,#hv do
- local hvi=hv[i]
- t[i]={
- ["start"]=(hvi["start"] or 0)*hdelta,
- ["end"]=(hvi["end"] or 0)*hdelta,
- ["advance"]=(hvi["advance"] or 0)*hdelta,
- ["extender"]=hvi["extender"],
- ["glyph"]=hvi["glyph"],
- }
- end
- chr.horiz_variants=t
- end
- end
- end
- local vi=character.vert_italic
- if vi and vi~=0 then
- chr.vert_italic=vi*hdelta
- end
- local va=character.accent
- if va then
- chr.top_accent=vdelta*va
- end
- if stackmath then
- local mk=character.mathkerns
- if mk then
- local tr,tl,br,bl=mk.topright,mk.topleft,mk.bottomright,mk.bottomleft
- chr.mathkern={
- top_right=tr and mathkerns(tr,vdelta) or nil,
- top_left=tl and mathkerns(tl,vdelta) or nil,
- bottom_right=br and mathkerns(br,vdelta) or nil,
- bottom_left=bl and mathkerns(bl,vdelta) or nil,
- }
- end
- end
- if hasitalics then
- local vi=character.italic
- if vi and vi~=0 then
- chr.italic=vi*hdelta
- end
- end
- elseif autoitalicamount then
- local vi=description.italic
- if not vi then
- local bb=description.boundingbox
- if bb then
- local vi=bb[3]-description.width+autoitalicamount
- if vi>0 then
- chr.italic=vi*hdelta
- end
- else
- end
- elseif vi~=0 then
- chr.italic=vi*hdelta
- end
- elseif hasitalics then
- local vi=character.italic
- if vi and vi~=0 then
- chr.italic=vi*hdelta
- end
- end
- if haskerns then
- local vk=character.kerns
- if vk then
- local s=sharedkerns[vk]
- if not s then
- s={}
- for k,v in next,vk do s[k]=v*hdelta end
- sharedkerns[vk]=s
- end
- chr.kerns=s
- end
- end
- if hasligatures then
- local vl=character.ligatures
- if vl then
- if true then
- chr.ligatures=vl
- else
- local tt={}
- for i,l in next,vl do
- tt[i]=l
- end
- chr.ligatures=tt
- end
- end
- end
- if isvirtual then
- local vc=character.commands
- if vc then
- local ok=false
- for i=1,#vc do
- local key=vc[i][1]
- if key=="right" or key=="down" then
- ok=true
- break
- end
- end
- if ok then
- local tt={}
- for i=1,#vc do
- local ivc=vc[i]
- local key=ivc[1]
- if key=="right" then
- tt[i]={ key,ivc[2]*hdelta }
- elseif key=="down" then
- tt[i]={ key,ivc[2]*vdelta }
- elseif key=="rule" then
- tt[i]={ key,ivc[2]*vdelta,ivc[3]*hdelta }
- else
- tt[i]=ivc
- end
- end
- chr.commands=tt
- else
- chr.commands=vc
- end
- chr.index=nil
- end
- end
- targetcharacters[unicode]=chr
- end
- properties.setitalics=hasitalics
- constructors.aftercopyingcharacters(target,tfmdata)
- constructors.trytosharefont(target,tfmdata)
- return target
-end
-function constructors.finalize(tfmdata)
- if tfmdata.properties and tfmdata.properties.finalized then
- return
- end
- if not tfmdata.characters then
- return nil
- end
- if not tfmdata.goodies then
- tfmdata.goodies={}
- end
- local parameters=tfmdata.parameters
- if not parameters then
- return nil
- end
- if not parameters.expansion then
- parameters.expansion={
- stretch=tfmdata.stretch or 0,
- shrink=tfmdata.shrink or 0,
- step=tfmdata.step or 0,
- auto=tfmdata.auto_expand or false,
- }
- end
- if not parameters.protrusion then
- parameters.protrusion={
- auto=auto_protrude
- }
- end
- if not parameters.size then
- parameters.size=tfmdata.size
- end
- if not parameters.extendfactor then
- parameters.extendfactor=tfmdata.extend or 0
- end
- if not parameters.slantfactor then
- parameters.slantfactor=tfmdata.slant or 0
- end
- local designsize=parameters.designsize
- if designsize then
- parameters.minsize=tfmdata.minsize or designsize
- parameters.maxsize=tfmdata.maxsize or designsize
- else
- designsize=factors.pt*10
- parameters.designsize=designsize
- parameters.minsize=designsize
- parameters.maxsize=designsize
- end
- parameters.minsize=tfmdata.minsize or parameters.designsize
- parameters.maxsize=tfmdata.maxsize or parameters.designsize
- if not parameters.units then
- parameters.units=tfmdata.units or tfmdata.units_per_em or 1000
- end
- if not tfmdata.descriptions then
- local descriptions={}
- setmetatableindex(descriptions,function(t,k) local v={} t[k]=v return v end)
- tfmdata.descriptions=descriptions
- end
- local properties=tfmdata.properties
- if not properties then
- properties={}
- tfmdata.properties=properties
- end
- if not properties.virtualized then
- properties.virtualized=tfmdata.type=="virtual"
- end
- if not tfmdata.properties then
- tfmdata.properties={
- fontname=tfmdata.fontname,
- filename=tfmdata.filename,
- fullname=tfmdata.fullname,
- name=tfmdata.name,
- psname=tfmdata.psname,
- encodingbytes=tfmdata.encodingbytes or 1,
- embedding=tfmdata.embedding or "subset",
- tounicode=tfmdata.tounicode or 1,
- cidinfo=tfmdata.cidinfo or nil,
- format=tfmdata.format or "type1",
- direction=tfmdata.direction or 0,
- writingmode=tfmdata.writingmode or "horizontal",
- identity=tfmdata.identity or "horizontal",
- }
- end
- if not tfmdata.resources then
- tfmdata.resources={}
- end
- if not tfmdata.shared then
- tfmdata.shared={}
- end
- if not properties.hasmath then
- properties.hasmath=not tfmdata.nomath
- end
- tfmdata.MathConstants=nil
- tfmdata.postprocessors=nil
- tfmdata.fontname=nil
- tfmdata.filename=nil
- tfmdata.fullname=nil
- tfmdata.name=nil
- tfmdata.psname=nil
- tfmdata.encodingbytes=nil
- tfmdata.embedding=nil
- tfmdata.tounicode=nil
- tfmdata.cidinfo=nil
- tfmdata.format=nil
- tfmdata.direction=nil
- tfmdata.type=nil
- tfmdata.nomath=nil
- tfmdata.designsize=nil
- tfmdata.size=nil
- tfmdata.stretch=nil
- tfmdata.shrink=nil
- tfmdata.step=nil
- tfmdata.auto_expand=nil
- tfmdata.auto_protrude=nil
- tfmdata.extend=nil
- tfmdata.slant=nil
- tfmdata.units=nil
- tfmdata.units_per_em=nil
- tfmdata.cache=nil
- properties.finalized=true
- return tfmdata
-end
-local hashmethods={}
-constructors.hashmethods=hashmethods
-function constructors.hashfeatures(specification)
- local features=specification.features
- if features then
- local t,tn={},0
- for category,list in next,features do
- if next(list) then
- local hasher=hashmethods[category]
- if hasher then
- local hash=hasher(list)
- if hash then
- tn=tn+1
- t[tn]=category..":"..hash
- end
- end
- end
- end
- if tn>0 then
- return concat(t," & ")
- end
- end
- return "unknown"
-end
-hashmethods.normal=function(list)
- local s={}
- local n=0
- for k,v in next,list do
- if not k then
- elseif k=="number" or k=="features" then
- else
- n=n+1
- s[n]=k..'='..tostring(v)
- end
- end
- if n>0 then
- sort(s)
- return concat(s,"+")
- end
-end
-function constructors.hashinstance(specification,force)
- local hash,size,fallbacks=specification.hash,specification.size,specification.fallbacks
- if force or not hash then
- hash=constructors.hashfeatures(specification)
- specification.hash=hash
- end
- if size<1000 and designsizes[hash] then
- size=math.round(constructors.scaled(size,designsizes[hash]))
- specification.size=size
- end
- if fallbacks then
- return hash..' @ '..tostring(size)..' @ '..fallbacks
- else
- return hash..' @ '..tostring(size)
- end
-end
-function constructors.setname(tfmdata,specification)
- if constructors.namemode=="specification" then
- local specname=specification.specification
- if specname then
- tfmdata.properties.name=specname
- if trace_defining then
- report_otf("overloaded fontname %a",specname)
- end
- end
- end
-end
-function constructors.checkedfilename(data)
- local foundfilename=data.foundfilename
- if not foundfilename then
- local askedfilename=data.filename or ""
- if askedfilename~="" then
- askedfilename=resolvers.resolve(askedfilename)
- foundfilename=resolvers.findbinfile(askedfilename,"") or ""
- if foundfilename=="" then
- report_defining("source file %a is not found",askedfilename)
- foundfilename=resolvers.findbinfile(file.basename(askedfilename),"") or ""
- if foundfilename~="" then
- report_defining("using source file %a due to cache mismatch",foundfilename)
- end
- end
- end
- data.foundfilename=foundfilename
- end
- return foundfilename
-end
-local formats=allocate()
-fonts.formats=formats
-setmetatableindex(formats,function(t,k)
- local l=lower(k)
- if rawget(t,k) then
- t[k]=l
- return l
- end
- return rawget(t,file.suffix(l))
-end)
-do
- local function setindeed(mode,source,target,group,name,position)
- local action=source[mode]
- if not action then
- return
- end
- local t=target[mode]
- if not t then
- report_defining("fatal error in setting feature %a, group %a, mode %a",name,group,mode)
- os.exit()
- elseif position then
- insert(t,position,{ name=name,action=action })
- else
- for i=1,#t do
- local ti=t[i]
- if ti.name==name then
- ti.action=action
- return
- end
- end
- insert(t,{ name=name,action=action })
- end
- end
- local function set(group,name,target,source)
- target=target[group]
- if not target then
- report_defining("fatal target error in setting feature %a, group %a",name,group)
- os.exit()
- end
- local source=source[group]
- if not source then
- report_defining("fatal source error in setting feature %a, group %a",name,group)
- os.exit()
- end
- local position=source.position
- setindeed("node",source,target,group,name,position)
- setindeed("base",source,target,group,name,position)
- setindeed("plug",source,target,group,name,position)
- end
- local function register(where,specification)
- local name=specification.name
- if name and name~="" then
- local default=specification.default
- local description=specification.description
- local initializers=specification.initializers
- local processors=specification.processors
- local manipulators=specification.manipulators
- local modechecker=specification.modechecker
- if default then
- where.defaults[name]=default
- end
- if description and description~="" then
- where.descriptions[name]=description
- end
- if initializers then
- set('initializers',name,where,specification)
- end
- if processors then
- set('processors',name,where,specification)
- end
- if manipulators then
- set('manipulators',name,where,specification)
- end
- if modechecker then
- where.modechecker=modechecker
- end
- end
- end
- constructors.registerfeature=register
- function constructors.getfeatureaction(what,where,mode,name)
- what=handlers[what].features
- if what then
- where=what[where]
- if where then
- mode=where[mode]
- if mode then
- for i=1,#mode do
- local m=mode[i]
- if m.name==name then
- return m.action
- end
- end
- end
- end
- end
- end
- local newfeatures={}
- constructors.newfeatures=newfeatures
- constructors.features=newfeatures
- local function setnewfeatures(what)
- local handler=handlers[what]
- local features=handler.features
- if not features then
- local tables=handler.tables
- local statistics=handler.statistics
- features=allocate {
- defaults={},
- descriptions=tables and tables.features or {},
- used=statistics and statistics.usedfeatures or {},
- initializers={ base={},node={},plug={} },
- processors={ base={},node={},plug={} },
- manipulators={ base={},node={},plug={} },
- }
- features.register=function(specification) return register(features,specification) end
- handler.features=features
- end
- return features
- end
- setmetatable(newfeatures,{
- __call=function(t,k) local v=t[k] return v end,
- __index=function(t,k) local v=setnewfeatures(k) t[k]=v return v end,
- })
-end
-do
- local newhandler={}
- constructors.handlers=newhandler
- constructors.newhandler=newhandler
- local function setnewhandler(what)
- local handler=handlers[what]
- if not handler then
- handler={}
- handlers[what]=handler
- end
- return handler
- end
- setmetatable(newhandler,{
- __call=function(t,k) local v=t[k] return v end,
- __index=function(t,k) local v=setnewhandler(k) t[k]=v return v end,
- })
-end
-do
- local newenhancer={}
- constructors.enhancers=newenhancer
- constructors.newenhancer=newenhancer
- local function setnewenhancer(format)
- local handler=handlers[format]
- local enhancers=handler.enhancers
- if not enhancers then
- local actions=allocate()
- local before=allocate()
- local after=allocate()
- local order=allocate()
- local patches={ before=before,after=after }
- local trace=false
- local report=logs.reporter("fonts",format.." enhancing")
- trackers.register(format..".loading",function(v) trace=v end)
- local function enhance(name,data,filename,raw)
- local enhancer=actions[name]
- if enhancer then
- if trace then
- report("apply enhancement %a to file %a",name,filename)
- ioflush()
- end
- enhancer(data,filename,raw)
- else
- end
- end
- local function apply(data,filename,raw)
- local basename=file.basename(lower(filename))
- if trace then
- report("%s enhancing file %a","start",filename)
- end
- ioflush()
- for e=1,#order do
- local enhancer=order[e]
- local b=before[enhancer]
- if b then
- for pattern,action in next,b do
- if find(basename,pattern) then
- action(data,filename,raw)
- end
- end
- end
- enhance(enhancer,data,filename,raw)
- local a=after[enhancer]
- if a then
- for pattern,action in next,a do
- if find(basename,pattern) then
- action(data,filename,raw)
- end
- end
- end
- ioflush()
- end
- if trace then
- report("%s enhancing file %a","stop",filename)
- end
- ioflush()
- end
- local function register(what,action)
- if action then
- if actions[what] then
- else
- order[#order+1]=what
- end
- actions[what]=action
- else
- report("bad enhancer %a",what)
- end
- end
- local function patch(what,where,pattern,action)
- local pw=patches[what]
- if pw then
- local ww=pw[where]
- if ww then
- ww[pattern]=action
- else
- pw[where]={ [pattern]=action}
- end
- end
- end
- enhancers={
- register=register,
- apply=apply,
- patch=patch,
- patches={ register=patch },
- }
- handler.enhancers=enhancers
- end
- return enhancers
- end
- setmetatable(newenhancer,{
- __call=function(t,k) local v=t[k] return v end,
- __index=function(t,k) local v=setnewenhancer(k) t[k]=v return v end,
- })
-end
-function constructors.checkedfeatures(what,features)
- local defaults=handlers[what].features.defaults
- if features and next(features) then
- features=fastcopy(features)
- for key,value in next,defaults do
- if features[key]==nil then
- features[key]=value
- end
- end
- return features
- else
- return fastcopy(defaults)
- end
-end
-function constructors.initializefeatures(what,tfmdata,features,trace,report)
- if features and next(features) then
- local properties=tfmdata.properties or {}
- local whathandler=handlers[what]
- local whatfeatures=whathandler.features
- local whatmodechecker=whatfeatures.modechecker
- local mode=properties.mode or (whatmodechecker and whatmodechecker(tfmdata,features,features.mode)) or features.mode or "base"
- properties.mode=mode
- features.mode=mode
- local done={}
- while true do
- local redo=false
- local initializers=whatfeatures.initializers[mode]
- if initializers then
- for i=1,#initializers do
- local step=initializers[i]
- local feature=step.name
- local value=features[feature]
- if not value then
- elseif done[feature] then
- else
- local action=step.action
- if trace then
- report("initializing feature %a to %a for mode %a for font %a",feature,
- value,mode,tfmdata.properties.fullname)
- end
- action(tfmdata,value,features)
- if mode~=properties.mode or mode~=features.mode then
- if whatmodechecker then
- properties.mode=whatmodechecker(tfmdata,features,properties.mode)
- features.mode=properties.mode
- end
- if mode~=properties.mode then
- mode=properties.mode
- redo=true
- end
- end
- done[feature]=true
- end
- if redo then
- break
- end
- end
- if not redo then
- break
- end
- else
- break
- end
- end
- properties.mode=mode
- return true
- else
- return false
- end
-end
-function constructors.collectprocessors(what,tfmdata,features,trace,report)
- local processes,nofprocesses={},0
- if features and next(features) then
- local properties=tfmdata.properties
- local whathandler=handlers[what]
- local whatfeatures=whathandler.features
- local whatprocessors=whatfeatures.processors
- local mode=properties.mode
- local processors=whatprocessors[mode]
- if processors then
- for i=1,#processors do
- local step=processors[i]
- local feature=step.name
- if features[feature] then
- local action=step.action
- if trace then
- report("installing feature processor %a for mode %a for font %a",feature,mode,tfmdata.properties.fullname)
- end
- if action then
- nofprocesses=nofprocesses+1
- processes[nofprocesses]=action
- end
- end
- end
- elseif trace then
- report("no feature processors for mode %a for font %a",mode,properties.fullname)
- end
- end
- return processes
-end
-function constructors.applymanipulators(what,tfmdata,features,trace,report)
- if features and next(features) then
- local properties=tfmdata.properties
- local whathandler=handlers[what]
- local whatfeatures=whathandler.features
- local whatmanipulators=whatfeatures.manipulators
- local mode=properties.mode
- local manipulators=whatmanipulators[mode]
- if manipulators then
- for i=1,#manipulators do
- local step=manipulators[i]
- local feature=step.name
- local value=features[feature]
- if value then
- local action=step.action
- if trace then
- report("applying feature manipulator %a for mode %a for font %a",feature,mode,properties.fullname)
- end
- if action then
- action(tfmdata,feature,value)
- end
- end
- end
- end
- end
-end
-function constructors.addcoreunicodes(unicodes)
- if not unicodes then
- unicodes={}
- end
- unicodes.space=0x0020
- unicodes.hyphen=0x002D
- unicodes.zwj=0x200D
- unicodes.zwnj=0x200C
- return unicodes
-end
-
-end --- [luaotfload, fontloader-2017-02-11.lua scope for “font-con”] ---
-
-
-do --- [luaotfload, fontloader-2017-02-11.lua scope for “fonts-enc” a7ace7c1969cd64a5ca9888838f3edb6] ---
-
-if not modules then modules={} end modules ['luatex-font-enc']={
- version=1.001,
- comment="companion to luatex-*.tex",
- author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright="PRAGMA ADE / ConTeXt Development Team",
- license="see context related readme files"
-}
-if context then
- texio.write_nl("fatal error: this module is not for context")
- os.exit()
-end
-local fonts=fonts
-local encodings={}
-fonts.encodings=encodings
-encodings.agl={}
-encodings.known={}
-setmetatable(encodings.agl,{ __index=function(t,k)
- if k=="unicodes" then
- texio.write(" <loading (extended) adobe glyph list>")
- local unicodes=dofile(resolvers.findfile("font-age.lua"))
- encodings.agl={ unicodes=unicodes }
- return unicodes
- else
- return nil
- end
-end })
-encodings.cache=containers.define("fonts","enc",encodings.version,true)
-function encodings.load(filename)
- local name=file.removesuffix(filename)
- local data=containers.read(encodings.cache,name)
- if data then
- return data
- end
- local vector,tag,hash,unicodes={},"",{},{}
- local foundname=resolvers.findfile(filename,'enc')
- if foundname and foundname~="" then
- local ok,encoding,size=resolvers.loadbinfile(foundname)
- if ok and encoding then
- encoding=string.gsub(encoding,"%%(.-)\n","")
- local unicoding=encodings.agl.unicodes
- local tag,vec=string.match(encoding,"/(%w+)%s*%[(.*)%]%s*def")
- local i=0
- for ch in string.gmatch(vec,"/([%a%d%.]+)") do
- if ch~=".notdef" then
- vector[i]=ch
- if not hash[ch] then
- hash[ch]=i
- else
- end
- local u=unicoding[ch]
- if u then
- unicodes[u]=i
- end
- end
- i=i+1
- end
- end
- end
- local data={
- name=name,
- tag=tag,
- vector=vector,
- hash=hash,
- unicodes=unicodes
- }
- return containers.write(encodings.cache,name,data)
-end
-
-end --- [luaotfload, fontloader-2017-02-11.lua scope for “fonts-enc”] ---
-
-
-do --- [luaotfload, fontloader-2017-02-11.lua scope for “font-cid” 52421d1fdaa07ec4b1d936c6ff5079be] ---
-
-if not modules then modules={} end modules ['font-cid']={
- version=1.001,
- comment="companion to font-otf.lua (cidmaps)",
- author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright="PRAGMA ADE / ConTeXt Development Team",
- license="see context related readme files"
-}
-local format,match,lower=string.format,string.match,string.lower
-local tonumber=tonumber
-local P,S,R,C,V,lpegmatch=lpeg.P,lpeg.S,lpeg.R,lpeg.C,lpeg.V,lpeg.match
-local fonts,logs,trackers=fonts,logs,trackers
-local trace_loading=false trackers.register("otf.loading",function(v) trace_loading=v end)
-local report_otf=logs.reporter("fonts","otf loading")
-local cid={}
-fonts.cid=cid
-local cidmap={}
-local cidmax=10
-local number=C(R("09","af","AF")^1)
-local space=S(" \n\r\t")
-local spaces=space^0
-local period=P(".")
-local periods=period*period
-local name=P("/")*C((1-space)^1)
-local unicodes,names={},{}
-local function do_one(a,b)
- unicodes[tonumber(a)]=tonumber(b,16)
-end
-local function do_range(a,b,c)
- c=tonumber(c,16)
- for i=tonumber(a),tonumber(b) do
- unicodes[i]=c
- c=c+1
- end
-end
-local function do_name(a,b)
- names[tonumber(a)]=b
-end
-local grammar=P { "start",
- start=number*spaces*number*V("series"),
- series=(spaces*(V("one")+V("range")+V("named")))^1,
- one=(number*spaces*number)/do_one,
- range=(number*periods*number*spaces*number)/do_range,
- named=(number*spaces*name)/do_name
-}
-local function loadcidfile(filename)
- local data=io.loaddata(filename)
- if data then
- unicodes,names={},{}
- lpegmatch(grammar,data)
- local supplement,registry,ordering=match(filename,"^(.-)%-(.-)%-()%.(.-)$")
- return {
- supplement=supplement,
- registry=registry,
- ordering=ordering,
- filename=filename,
- unicodes=unicodes,
- names=names,
- }
- end
-end
-cid.loadfile=loadcidfile
-local template="%s-%s-%s.cidmap"
-local function locate(registry,ordering,supplement)
- local filename=format(template,registry,ordering,supplement)
- local hashname=lower(filename)
- local found=cidmap[hashname]
- if not found then
- if trace_loading then
- report_otf("checking cidmap, registry %a, ordering %a, supplement %a, filename %a",registry,ordering,supplement,filename)
- end
- local fullname=resolvers.findfile(filename,'cid') or ""
- if fullname~="" then
- found=loadcidfile(fullname)
- if found then
- if trace_loading then
- report_otf("using cidmap file %a",filename)
- end
- cidmap[hashname]=found
- found.usedname=file.basename(filename)
- end
- end
- end
- return found
-end
-function cid.getmap(specification)
- if not specification then
- report_otf("invalid cidinfo specification, table expected")
- return
- end
- local registry=specification.registry
- local ordering=specification.ordering
- local supplement=specification.supplement
- local filename=format(registry,ordering,supplement)
- local lowername=lower(filename)
- local found=cidmap[lowername]
- if found then
- return found
- end
- if ordering=="Identity" then
- local found={
- supplement=supplement,
- registry=registry,
- ordering=ordering,
- filename=filename,
- unicodes={},
- names={},
- }
- cidmap[lowername]=found
- return found
- end
- if trace_loading then
- report_otf("cidmap needed, registry %a, ordering %a, supplement %a",registry,ordering,supplement)
- end
- found=locate(registry,ordering,supplement)
- if not found then
- local supnum=tonumber(supplement)
- local cidnum=nil
- if supnum<cidmax then
- for s=supnum+1,cidmax do
- local c=locate(registry,ordering,s)
- if c then
- found,cidnum=c,s
- break
- end
- end
- end
- if not found and supnum>0 then
- for s=supnum-1,0,-1 do
- local c=locate(registry,ordering,s)
- if c then
- found,cidnum=c,s
- break
- end
- end
- end
- registry=lower(registry)
- ordering=lower(ordering)
- if found and cidnum>0 then
- for s=0,cidnum-1 do
- local filename=format(template,registry,ordering,s)
- if not cidmap[filename] then
- cidmap[filename]=found
- end
- end
- end
- end
- return found
-end
-
-end --- [luaotfload, fontloader-2017-02-11.lua scope for “font-cid”] ---
-
-
-do --- [luaotfload, fontloader-2017-02-11.lua scope for “font-map” 8708bde7467785c4d3b7afdaf2f9333a] ---
-
-if not modules then modules={} end modules ['font-map']={
- version=1.001,
- comment="companion to font-ini.mkiv",
- author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright="PRAGMA ADE / ConTeXt Development Team",
- license="see context related readme files"
-}
-local tonumber,next,type=tonumber,next,type
-local match,format,find,concat,gsub,lower=string.match,string.format,string.find,table.concat,string.gsub,string.lower
-local P,R,S,C,Ct,Cc,lpegmatch=lpeg.P,lpeg.R,lpeg.S,lpeg.C,lpeg.Ct,lpeg.Cc,lpeg.match
-local floor=math.floor
-local formatters=string.formatters
-local sortedhash,sortedkeys=table.sortedhash,table.sortedkeys
-local trace_loading=false trackers.register("fonts.loading",function(v) trace_loading=v end)
-local trace_mapping=false trackers.register("fonts.mapping",function(v) trace_mapping=v end)
-local report_fonts=logs.reporter("fonts","loading")
-local force_ligatures=false directives.register("fonts.mapping.forceligatures",function(v) force_ligatures=v end)
-local fonts=fonts or {}
-local mappings=fonts.mappings or {}
-fonts.mappings=mappings
-local allocate=utilities.storage.allocate
-local hex=R("AF","af","09")
-local hexfour=(hex*hex*hex^-2)/function(s) return tonumber(s,16) end
-local hexsix=(hex*hex*hex^-4)/function(s) return tonumber(s,16) end
-local dec=(R("09")^1)/tonumber
-local period=P(".")
-local unicode=(P("uni")+P("UNI"))*(hexfour*(period+P(-1))*Cc(false)+Ct(hexfour^1)*Cc(true))
-local ucode=(P("u")+P("U") )*(hexsix*(period+P(-1))*Cc(false)+Ct(hexsix^1)*Cc(true))
-local index=P("index")*dec*Cc(false)
-local parser=unicode+ucode+index
-local parsers={}
-local function makenameparser(str)
- if not str or str=="" then
- return parser
- else
- local p=parsers[str]
- if not p then
- p=P(str)*period*dec*Cc(false)
- parsers[str]=p
- end
- return p
- end
-end
-local f_single=formatters["%04X"]
-local f_double=formatters["%04X%04X"]
-local function tounicode16(unicode)
- if unicode<0xD7FF or (unicode>0xDFFF and unicode<=0xFFFF) then
- return f_single(unicode)
- else
- unicode=unicode-0x10000
- return f_double(floor(unicode/1024)+0xD800,unicode%1024+0xDC00)
- end
-end
-local function tounicode16sequence(unicodes)
- local t={}
- for l=1,#unicodes do
- local u=unicodes[l]
- if u<0xD7FF or (u>0xDFFF and u<=0xFFFF) then
- t[l]=f_single(u)
- else
- u=u-0x10000
- t[l]=f_double(floor(u/1024)+0xD800,u%1024+0xDC00)
- end
- end
- return concat(t)
-end
-local function tounicode(unicode,name)
- if type(unicode)=="table" then
- local t={}
- for l=1,#unicode do
- local u=unicode[l]
- if u<0xD7FF or (u>0xDFFF and u<=0xFFFF) then
- t[l]=f_single(u)
- else
- u=u-0x10000
- t[l]=f_double(floor(u/1024)+0xD800,u%1024+0xDC00)
- end
- end
- return concat(t)
- else
- if unicode<0xD7FF or (unicode>0xDFFF and unicode<=0xFFFF) then
- return f_single(unicode)
- else
- unicode=unicode-0x10000
- return f_double(floor(unicode/1024)+0xD800,unicode%1024+0xDC00)
- end
- end
-end
-local function fromunicode16(str)
- if #str==4 then
- return tonumber(str,16)
- else
- local l,r=match(str,"(....)(....)")
- return 0x10000+(tonumber(l,16)-0xD800)*0x400+tonumber(r,16)-0xDC00
- end
-end
-mappings.makenameparser=makenameparser
-mappings.tounicode=tounicode
-mappings.tounicode16=tounicode16
-mappings.tounicode16sequence=tounicode16sequence
-mappings.fromunicode16=fromunicode16
-local ligseparator=P("_")
-local varseparator=P(".")
-local namesplitter=Ct(C((1-ligseparator-varseparator)^1)*(ligseparator*C((1-ligseparator-varseparator)^1))^0)
-do
- local overloads=allocate {
- IJ={ name="I_J",unicode={ 0x49,0x4A },mess=0x0132 },
- ij={ name="i_j",unicode={ 0x69,0x6A },mess=0x0133 },
- ff={ name="f_f",unicode={ 0x66,0x66 },mess=0xFB00 },
- fi={ name="f_i",unicode={ 0x66,0x69 },mess=0xFB01 },
- fl={ name="f_l",unicode={ 0x66,0x6C },mess=0xFB02 },
- ffi={ name="f_f_i",unicode={ 0x66,0x66,0x69 },mess=0xFB03 },
- ffl={ name="f_f_l",unicode={ 0x66,0x66,0x6C },mess=0xFB04 },
- fj={ name="f_j",unicode={ 0x66,0x6A } },
- fk={ name="f_k",unicode={ 0x66,0x6B } },
- }
- local o={}
- for k,v in next,overloads do
- local name=v.name
- local mess=v.mess
- if name then
- o[name]=v
- end
- if mess then
- o[mess]=v
- end
- o[k]=v
- end
- mappings.overloads=o
-end
-function mappings.addtounicode(data,filename,checklookups)
- local resources=data.resources
- local unicodes=resources.unicodes
- if not unicodes then
- if trace_mapping then
- report_fonts("no unicode list, quitting tounicode for %a",filename)
- end
- return
- end
- local properties=data.properties
- local descriptions=data.descriptions
- local overloads=mappings.overloads
- unicodes['space']=unicodes['space'] or 32
- unicodes['hyphen']=unicodes['hyphen'] or 45
- unicodes['zwj']=unicodes['zwj'] or 0x200D
- unicodes['zwnj']=unicodes['zwnj'] or 0x200C
- local private=fonts.constructors and fonts.constructors.privateoffset or 0xF0000
- local unicodevector=fonts.encodings.agl.unicodes or {}
- local contextvector=fonts.encodings.agl.ctxcodes or {}
- local missing={}
- local nofmissing=0
- local oparser=nil
- local cidnames=nil
- local cidcodes=nil
- local cidinfo=properties.cidinfo
- local usedmap=cidinfo and fonts.cid.getmap(cidinfo)
- local uparser=makenameparser()
- if usedmap then
- oparser=usedmap and makenameparser(cidinfo.ordering)
- cidnames=usedmap.names
- cidcodes=usedmap.unicodes
- end
- local ns=0
- local nl=0
- local dlist=sortedkeys(descriptions)
- for i=1,#dlist do
- local du=dlist[i]
- local glyph=descriptions[du]
- local name=glyph.name
- if name then
- local overload=overloads[name] or overloads[du]
- if overload then
- glyph.unicode=overload.unicode
- else
- local gu=glyph.unicode
- if not gu or gu==-1 or du>=private or (du>=0xE000 and du<=0xF8FF) or du==0xFFFE or du==0xFFFF then
- local unicode=unicodevector[name] or contextvector[name]
- if unicode then
- glyph.unicode=unicode
- ns=ns+1
- end
- if (not unicode) and usedmap then
- local foundindex=lpegmatch(oparser,name)
- if foundindex then
- unicode=cidcodes[foundindex]
- if unicode then
- glyph.unicode=unicode
- ns=ns+1
- else
- local reference=cidnames[foundindex]
- if reference then
- local foundindex=lpegmatch(oparser,reference)
- if foundindex then
- unicode=cidcodes[foundindex]
- if unicode then
- glyph.unicode=unicode
- ns=ns+1
- end
- end
- if not unicode or unicode=="" then
- local foundcodes,multiple=lpegmatch(uparser,reference)
- if foundcodes then
- glyph.unicode=foundcodes
- if multiple then
- nl=nl+1
- unicode=true
- else
- ns=ns+1
- unicode=foundcodes
- end
- end
- end
- end
- end
- end
- end
- if not unicode or unicode=="" then
- local split=lpegmatch(namesplitter,name)
- local nsplit=split and #split or 0
- if nsplit==0 then
- elseif nsplit==1 then
- local base=split[1]
- local u=unicodes[base] or unicodevector[base] or contextvector[name]
- if not u then
- elseif type(u)=="table" then
- if u[1]<private then
- unicode=u
- glyph.unicode=unicode
- end
- elseif u<private then
- unicode=u
- glyph.unicode=unicode
- end
- else
- local t,n={},0
- for l=1,nsplit do
- local base=split[l]
- local u=unicodes[base] or unicodevector[base] or contextvector[name]
- if not u then
- break
- elseif type(u)=="table" then
- if u[1]>=private then
- break
- end
- n=n+1
- t[n]=u[1]
- else
- if u>=private then
- break
- end
- n=n+1
- t[n]=u
- end
- end
- if n>0 then
- if n==1 then
- unicode=t[1]
- else
- unicode=t
- end
- glyph.unicode=unicode
- end
- end
- nl=nl+1
- end
- if not unicode or unicode=="" then
- local foundcodes,multiple=lpegmatch(uparser,name)
- if foundcodes then
- glyph.unicode=foundcodes
- if multiple then
- nl=nl+1
- unicode=true
- else
- ns=ns+1
- unicode=foundcodes
- end
- end
- end
- local r=overloads[unicode]
- if r then
- unicode=r.unicode
- glyph.unicode=unicode
- end
- if not unicode then
- missing[du]=true
- nofmissing=nofmissing+1
- end
- end
- end
- else
- local overload=overloads[du]
- if overload then
- glyph.unicode=overload.unicode
- end
- end
- end
- if type(checklookups)=="function" then
- checklookups(data,missing,nofmissing)
- end
- local collected=false
- local unicoded=0
- for i=1,#dlist do
- local du=dlist[i]
- local glyph=descriptions[du]
- if glyph.class=="ligature" and (force_ligatures or not glyph.unicode) then
- if not collected then
- collected=fonts.handlers.otf.readers.getcomponents(data)
- if not collected then
- break
- end
- end
- local u=collected[du]
- if u then
- local n=#u
- for i=1,n do
- if u[i]>private then
- n=0
- break
- end
- end
- if n>0 then
- if n>1 then
- glyph.unicode=u
- else
- glyph.unicode=u[1]
- end
- unicoded=unicoded+1
- end
- end
- end
- end
- if trace_mapping and unicoded>0 then
- report_fonts("%n ligature tounicode mappings deduced from gsub ligature features",unicoded)
- end
- if trace_mapping then
- for i=1,#dlist do
- local du=dlist[i]
- local glyph=descriptions[du]
- local name=glyph.name or "-"
- local index=glyph.index or 0
- local unicode=glyph.unicode
- if unicode then
- if type(unicode)=="table" then
- local unicodes={}
- for i=1,#unicode do
- unicodes[i]=formatters("%U",unicode[i])
- end
- report_fonts("internal slot %U, name %a, unicode %U, tounicode % t",index,name,du,unicodes)
- else
- report_fonts("internal slot %U, name %a, unicode %U, tounicode %U",index,name,du,unicode)
- end
- else
- report_fonts("internal slot %U, name %a, unicode %U",index,name,du)
- end
- end
- end
- if trace_loading and (ns>0 or nl>0) then
- report_fonts("%s tounicode entries added, ligatures %s",nl+ns,ns)
- end
-end
-
-end --- [luaotfload, fontloader-2017-02-11.lua scope for “font-map”] ---
-
-
-do --- [luaotfload, fontloader-2017-02-11.lua scope for “font-oti” 8f48c06a1d632febd7231ad5dfadfc53] ---
-
-if not modules then modules={} end modules ['font-oti']={
- version=1.001,
- comment="companion to font-ini.mkiv",
- author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright="PRAGMA ADE / ConTeXt Development Team",
- license="see context related readme files"
-}
-local lower=string.lower
-local fonts=fonts
-local constructors=fonts.constructors
-local otf=constructors.handlers.otf
-local otffeatures=constructors.features.otf
-local registerotffeature=otffeatures.register
-local otftables=otf.tables or {}
-otf.tables=otftables
-local allocate=utilities.storage.allocate
-registerotffeature {
- name="features",
- description="initialization of feature handler",
- default=true,
-}
-local function setmode(tfmdata,value)
- if value then
- tfmdata.properties.mode=lower(value)
- end
-end
-otf.modeinitializer=setmode
-local function setlanguage(tfmdata,value)
- if value then
- local cleanvalue=lower(value)
- local languages=otftables and otftables.languages
- local properties=tfmdata.properties
- if not languages then
- properties.language=cleanvalue
- elseif languages[value] then
- properties.language=cleanvalue
- else
- properties.language="dflt"
- end
- end
-end
-local function setscript(tfmdata,value)
- if value then
- local cleanvalue=lower(value)
- local scripts=otftables and otftables.scripts
- local properties=tfmdata.properties
- if not scripts then
- properties.script=cleanvalue
- elseif scripts[value] then
- properties.script=cleanvalue
- else
- properties.script="dflt"
- end
- end
-end
-registerotffeature {
- name="mode",
- description="mode",
- initializers={
- base=setmode,
- node=setmode,
- plug=setmode,
- }
-}
-registerotffeature {
- name="language",
- description="language",
- initializers={
- base=setlanguage,
- node=setlanguage,
- plug=setlanguage,
- }
-}
-registerotffeature {
- name="script",
- description="script",
- initializers={
- base=setscript,
- node=setscript,
- plug=setscript,
- }
-}
-otftables.featuretypes=allocate {
- gpos_single="position",
- gpos_pair="position",
- gpos_cursive="position",
- gpos_mark2base="position",
- gpos_mark2ligature="position",
- gpos_mark2mark="position",
- gpos_context="position",
- gpos_contextchain="position",
- gsub_single="substitution",
- gsub_multiple="substitution",
- gsub_alternate="substitution",
- gsub_ligature="substitution",
- gsub_context="substitution",
- gsub_contextchain="substitution",
- gsub_reversecontextchain="substitution",
- gsub_reversesub="substitution",
-}
-function otffeatures.checkeddefaultscript(featuretype,autoscript,scripts)
- if featuretype=="position" then
- local default=scripts.dflt
- if default then
- if autoscript=="position" or autoscript==true then
- return default
- else
- report_otf("script feature %s not applied, enable default positioning")
- end
- else
- end
- elseif featuretype=="substitution" then
- local default=scripts.dflt
- if default then
- if autoscript=="substitution" or autoscript==true then
- return default
- end
- end
- end
-end
-function otffeatures.checkeddefaultlanguage(featuretype,autolanguage,languages)
- if featuretype=="position" then
- local default=languages.dflt
- if default then
- if autolanguage=="position" or autolanguage==true then
- return default
- else
- report_otf("language feature %s not applied, enable default positioning")
- end
- else
- end
- elseif featuretype=="substitution" then
- local default=languages.dflt
- if default then
- if autolanguage=="substitution" or autolanguage==true then
- return default
- end
- end
- end
-end
-
-end --- [luaotfload, fontloader-2017-02-11.lua scope for “font-oti”] ---
-
-
-do --- [luaotfload, fontloader-2017-02-11.lua scope for “font-otr” 2bd0085b78027f261218d63034f43474] ---
-
-if not modules then modules={} end modules ['font-otr']={
- version=1.001,
- comment="companion to font-ini.mkiv",
- author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright="PRAGMA ADE / ConTeXt Development Team",
- license="see context related readme files"
-}
-local next,type,unpack=next,type,unpack
-local byte,lower,char,strip,gsub=string.byte,string.lower,string.char,string.strip,string.gsub
-local bittest=bit32.btest
-local concat,remove,unpack,fastcopy=table.concat,table.remov,table.unpack,table.fastcopy
-local floor,abs,sqrt,round=math.floor,math.abs,math.sqrt,math.round
-local P,R,S,C,Cs,Cc,Ct,Carg,Cmt=lpeg.P,lpeg.R,lpeg.S,lpeg.C,lpeg.Cs,lpeg.Cc,lpeg.Ct,lpeg.Carg,lpeg.Cmt
-local lpegmatch=lpeg.match
-local setmetatableindex=table.setmetatableindex
-local formatters=string.formatters
-local sortedkeys=table.sortedkeys
-local sortedhash=table.sortedhash
-local stripstring=string.strip
-local utf16_to_utf8_be=utf.utf16_to_utf8_be
-local report=logs.reporter("otf reader")
-local trace_cmap=false
-fonts=fonts or {}
-local handlers=fonts.handlers or {}
-fonts.handlers=handlers
-local otf=handlers.otf or {}
-handlers.otf=otf
-local readers=otf.readers or {}
-otf.readers=readers
-local streamreader=utilities.files
-local streamwriter=utilities.files
-readers.streamreader=streamreader
-readers.streamwriter=streamwriter
-local openfile=streamreader.open
-local closefile=streamreader.close
-local setposition=streamreader.setposition
-local skipshort=streamreader.skipshort
-local readbytes=streamreader.readbytes
-local readstring=streamreader.readstring
-local readbyte=streamreader.readcardinal1
-local readushort=streamreader.readcardinal2
-local readuint=streamreader.readcardinal3
-local readulong=streamreader.readcardinal4
-local readshort=streamreader.readinteger2
-local readlong=streamreader.readinteger4
-local readfixed=streamreader.readfixed4
-local readfword=readshort
-local readufword=readushort
-local readoffset=readushort
-local read2dot14=streamreader.read2dot14
-function streamreader.readtag(f)
- return lower(strip(readstring(f,4)))
-end
-local function readlongdatetime(f)
- local a,b,c,d,e,f,g,h=readbytes(f,8)
- return 0x100000000*d+0x1000000*e+0x10000*f+0x100*g+h
-end
-local tableversion=0.004
-readers.tableversion=tableversion
-local privateoffset=fonts.constructors and fonts.constructors.privateoffset or 0xF0000
-local reportedskipped={}
-local function reportskippedtable(tag)
- if not reportedskipped[tag] then
- report("loading of table %a skipped (reported once only)",tag)
- reportedskipped[tag]=true
- end
-end
-local reservednames={ [0]="copyright",
- "family",
- "subfamily",
- "uniqueid",
- "fullname",
- "version",
- "postscriptname",
- "trademark",
- "manufacturer",
- "designer",
- "description",
- "vendorurl",
- "designerurl",
- "license",
- "licenseurl",
- "reserved",
- "typographicfamily",
- "typographicsubfamily",
- "compatiblefullname",
- "sampletext",
- "cidfindfontname",
- "wwsfamily",
- "wwssubfamily",
- "lightbackgroundpalette",
- "darkbackgroundpalette",
-}
-local platforms={ [0]="unicode",
- "macintosh",
- "iso",
- "windows",
- "custom",
-}
-local encodings={
- unicode={ [0]="unicode 1.0 semantics",
- "unicode 1.1 semantics",
- "iso/iec 10646",
- "unicode 2.0 bmp",
- "unicode 2.0 full",
- "unicode variation sequences",
- "unicode full repertoire",
- },
- macintosh={ [0]="roman","japanese","chinese (traditional)","korean","arabic","hebrew","greek","russian",
- "rsymbol","devanagari","gurmukhi","gujarati","oriya","bengali","tamil","telugu","kannada",
- "malayalam","sinhalese","burmese","khmer","thai","laotian","georgian","armenian",
- "chinese (simplified)","tibetan","mongolian","geez","slavic","vietnamese","sindhi",
- "uninterpreted",
- },
- iso={ [0]="7-bit ascii",
- "iso 10646",
- "iso 8859-1",
- },
- windows={ [0]="symbol",
- "unicode bmp",
- "shiftjis",
- "prc",
- "big5",
- "wansung",
- "johab",
- "reserved 7",
- "reserved 8",
- "reserved 9",
- "unicode ucs-4",
- },
- custom={
- }
-}
-local decoders={
- unicode={},
- macintosh={},
- iso={},
- windows={
- ["unicode semantics"]=utf16_to_utf8_be,
- ["unicode bmp"]=utf16_to_utf8_be,
- ["unicode full"]=utf16_to_utf8_be,
- ["unicode 1.0 semantics"]=utf16_to_utf8_be,
- ["unicode 1.1 semantics"]=utf16_to_utf8_be,
- ["unicode 2.0 bmp"]=utf16_to_utf8_be,
- ["unicode 2.0 full"]=utf16_to_utf8_be,
- ["unicode variation sequences"]=utf16_to_utf8_be,
- ["unicode full repertoire"]=utf16_to_utf8_be,
- },
- custom={},
-}
-local languages={
- unicode={
- [ 0]="english",
- },
- macintosh={
- [ 0]="english",
- },
- iso={},
- windows={
- [0x0409]="english - united states",
- },
- custom={},
-}
-local standardromanencoding={ [0]=
- "notdef",".null","nonmarkingreturn","space","exclam","quotedbl",
- "numbersign","dollar","percent","ampersand","quotesingle","parenleft",
- "parenright","asterisk","plus","comma","hyphen","period","slash",
- "zero","one","two","three","four","five","six","seven","eight",
- "nine","colon","semicolon","less","equal","greater","question","at",
- "A","B","C","D","E","F","G","H","I","J","K","L","M","N","O",
- "P","Q","R","S","T","U","V","W","X","Y","Z","bracketleft",
- "backslash","bracketright","asciicircum","underscore","grave","a","b",
- "c","d","e","f","g","h","i","j","k","l","m","n","o","p","q",
- "r","s","t","u","v","w","x","y","z","braceleft","bar",
- "braceright","asciitilde","Adieresis","Aring","Ccedilla","Eacute",
- "Ntilde","Odieresis","Udieresis","aacute","agrave","acircumflex",
- "adieresis","atilde","aring","ccedilla","eacute","egrave",
- "ecircumflex","edieresis","iacute","igrave","icircumflex","idieresis",
- "ntilde","oacute","ograve","ocircumflex","odieresis","otilde","uacute",
- "ugrave","ucircumflex","udieresis","dagger","degree","cent","sterling",
- "section","bullet","paragraph","germandbls","registered","copyright",
- "trademark","acute","dieresis","notequal","AE","Oslash","infinity",
- "plusminus","lessequal","greaterequal","yen","mu","partialdiff",
- "summation","product","pi","integral","ordfeminine","ordmasculine",
- "Omega","ae","oslash","questiondown","exclamdown","logicalnot",
- "radical","florin","approxequal","Delta","guillemotleft",
- "guillemotright","ellipsis","nonbreakingspace","Agrave","Atilde",
- "Otilde","OE","oe","endash","emdash","quotedblleft","quotedblright",
- "quoteleft","quoteright","divide","lozenge","ydieresis","Ydieresis",
- "fraction","currency","guilsinglleft","guilsinglright","fi","fl",
- "daggerdbl","periodcentered","quotesinglbase","quotedblbase",
- "perthousand","Acircumflex","Ecircumflex","Aacute","Edieresis","Egrave",
- "Iacute","Icircumflex","Idieresis","Igrave","Oacute","Ocircumflex",
- "apple","Ograve","Uacute","Ucircumflex","Ugrave","dotlessi",
- "circumflex","tilde","macron","breve","dotaccent","ring","cedilla",
- "hungarumlaut","ogonek","caron","Lslash","lslash","Scaron","scaron",
- "Zcaron","zcaron","brokenbar","Eth","eth","Yacute","yacute","Thorn",
- "thorn","minus","multiply","onesuperior","twosuperior","threesuperior",
- "onehalf","onequarter","threequarters","franc","Gbreve","gbreve",
- "Idotaccent","Scedilla","scedilla","Cacute","cacute","Ccaron","ccaron",
- "dcroat",
-}
-local weights={
- [100]="thin",
- [200]="extralight",
- [300]="light",
- [400]="normal",
- [500]="medium",
- [600]="semibold",
- [700]="bold",
- [800]="extrabold",
- [900]="black",
-}
-local widths={
- [1]="ultracondensed",
- [2]="extracondensed",
- [3]="condensed",
- [4]="semicondensed",
- [5]="normal",
- [6]="semiexpanded",
- [7]="expanded",
- [8]="extraexpanded",
- [9]="ultraexpanded",
-}
-setmetatableindex(weights,function(t,k)
- local r=floor((k+50)/100)*100
- local v=(r>900 and "black") or rawget(t,r) or "normal"
- return v
-end)
-setmetatableindex(widths,function(t,k)
- return "normal"
-end)
-local panoseweights={
- [ 0]="normal",
- [ 1]="normal",
- [ 2]="verylight",
- [ 3]="light",
- [ 4]="thin",
- [ 5]="book",
- [ 6]="medium",
- [ 7]="demi",
- [ 8]="bold",
- [ 9]="heavy",
- [10]="black",
-}
-local panosewidths={
- [ 0]="normal",
- [ 1]="normal",
- [ 2]="normal",
- [ 3]="normal",
- [ 4]="normal",
- [ 5]="expanded",
- [ 6]="condensed",
- [ 7]="veryexpanded",
- [ 8]="verycondensed",
- [ 9]="monospaced",
-}
-local platformnames={
- postscriptname=true,
- fullname=true,
- family=true,
- subfamily=true,
- typographicfamily=true,
- typographicsubfamily=true,
- compatiblefullname=true,
-}
-function readers.name(f,fontdata,specification)
- local datatable=fontdata.tables.name
- if datatable then
- setposition(f,datatable.offset)
- local format=readushort(f)
- local nofnames=readushort(f)
- local offset=readushort(f)
- local start=datatable.offset+offset
- local namelists={
- unicode={},
- windows={},
- macintosh={},
- }
- for i=1,nofnames do
- local platform=platforms[readushort(f)]
- if platform then
- local namelist=namelists[platform]
- if namelist then
- local encoding=readushort(f)
- local language=readushort(f)
- local encodings=encodings[platform]
- local languages=languages[platform]
- if encodings and languages then
- local encoding=encodings[encoding]
- local language=languages[language]
- if encoding and language then
- local name=reservednames[readushort(f)]
- if name then
- namelist[#namelist+1]={
- platform=platform,
- encoding=encoding,
- language=language,
- name=name,
- length=readushort(f),
- offset=start+readushort(f),
- }
- else
- skipshort(f,2)
- end
- else
- skipshort(f,3)
- end
- else
- skipshort(f,3)
- end
- else
- skipshort(f,5)
- end
- else
- skipshort(f,5)
- end
- end
- local names={}
- local done={}
- local function filter(platform,e,l)
- local namelist=namelists[platform]
- for i=1,#namelist do
- local name=namelist[i]
- local nametag=name.name
- if not done[nametag] then
- local encoding=name.encoding
- local language=name.language
- if (not e or encoding==e) and (not l or language==l) then
- setposition(f,name.offset)
- local content=readstring(f,name.length)
- local decoder=decoders[platform]
- if decoder then
- decoder=decoder[encoding]
- end
- if decoder then
- content=decoder(content)
- end
- names[nametag]={
- content=content,
- platform=platform,
- encoding=encoding,
- language=language,
- }
- done[nametag]=true
- end
- end
- end
- end
- filter("windows","unicode bmp","english - united states")
- filter("macintosh","roman","english")
- filter("windows")
- filter("macintosh")
- filter("unicode")
- fontdata.names=names
- if specification.platformnames then
- local collected={}
- for platform,namelist in next,namelists do
- local filtered=false
- for i=1,#namelist do
- local entry=namelist[i]
- local name=entry.name
- if platformnames[name] then
- setposition(f,entry.offset)
- local content=readstring(f,entry.length)
- local encoding=entry.encoding
- local decoder=decoders[platform]
- if decoder then
- decoder=decoder[encoding]
- end
- if decoder then
- content=decoder(content)
- end
- if filtered then
- filtered[name]=content
- else
- filtered={ [name]=content }
- end
- end
- end
- if filtered then
- collected[platform]=filtered
- end
- end
- fontdata.platformnames=collected
- end
- else
- fontdata.names={}
- end
-end
-local validutf=lpeg.patterns.validutf8
-local function getname(fontdata,key)
- local names=fontdata.names
- if names then
- local value=names[key]
- if value then
- local content=value.content
- return lpegmatch(validutf,content) and content or nil
- end
- end
-end
-readers["os/2"]=function(f,fontdata)
- local datatable=fontdata.tables["os/2"]
- if datatable then
- setposition(f,datatable.offset)
- local version=readushort(f)
- local windowsmetrics={
- version=version,
- averagewidth=readshort(f),
- weightclass=readushort(f),
- widthclass=readushort(f),
- fstype=readushort(f),
- subscriptxsize=readshort(f),
- subscriptysize=readshort(f),
- subscriptxoffset=readshort(f),
- subscriptyoffset=readshort(f),
- superscriptxsize=readshort(f),
- superscriptysize=readshort(f),
- superscriptxoffset=readshort(f),
- superscriptyoffset=readshort(f),
- strikeoutsize=readshort(f),
- strikeoutpos=readshort(f),
- familyclass=readshort(f),
- panose={ readbytes(f,10) },
- unicoderanges={ readulong(f),readulong(f),readulong(f),readulong(f) },
- vendor=readstring(f,4),
- fsselection=readushort(f),
- firstcharindex=readushort(f),
- lastcharindex=readushort(f),
- typoascender=readshort(f),
- typodescender=readshort(f),
- typolinegap=readshort(f),
- winascent=readushort(f),
- windescent=readushort(f),
- }
- if version>=1 then
- windowsmetrics.codepageranges={ readulong(f),readulong(f) }
- end
- if version>=3 then
- windowsmetrics.xheight=readshort(f)
- windowsmetrics.capheight=readshort(f)
- windowsmetrics.defaultchar=readushort(f)
- windowsmetrics.breakchar=readushort(f)
- end
- windowsmetrics.weight=windowsmetrics.weightclass and weights[windowsmetrics.weightclass]
- windowsmetrics.width=windowsmetrics.widthclass and widths [windowsmetrics.widthclass]
- windowsmetrics.panoseweight=panoseweights[windowsmetrics.panose[3]]
- windowsmetrics.panosewidth=panosewidths [windowsmetrics.panose[4]]
- fontdata.windowsmetrics=windowsmetrics
- else
- fontdata.windowsmetrics={}
- end
-end
-readers.head=function(f,fontdata)
- local datatable=fontdata.tables.head
- if datatable then
- setposition(f,datatable.offset)
- local fontheader={
- version=readfixed(f),
- revision=readfixed(f),
- checksum=readulong(f),
- magic=readulong(f),
- flags=readushort(f),
- units=readushort(f),
- created=readlongdatetime(f),
- modified=readlongdatetime(f),
- xmin=readshort(f),
- ymin=readshort(f),
- xmax=readshort(f),
- ymax=readshort(f),
- macstyle=readushort(f),
- smallpixels=readushort(f),
- directionhint=readshort(f),
- indextolocformat=readshort(f),
- glyphformat=readshort(f),
- }
- fontdata.fontheader=fontheader
- else
- fontdata.fontheader={}
- end
- fontdata.nofglyphs=0
-end
-readers.hhea=function(f,fontdata,specification)
- if specification.details then
- local datatable=fontdata.tables.hhea
- if datatable then
- setposition(f,datatable.offset)
- fontdata.horizontalheader={
- version=readfixed(f),
- ascender=readfword(f),
- descender=readfword(f),
- linegap=readfword(f),
- maxadvancewidth=readufword(f),
- minleftsidebearing=readfword(f),
- minrightsidebearing=readfword(f),
- maxextent=readfword(f),
- caretsloperise=readshort(f),
- caretsloperun=readshort(f),
- caretoffset=readshort(f),
- reserved_1=readshort(f),
- reserved_2=readshort(f),
- reserved_3=readshort(f),
- reserved_4=readshort(f),
- metricdataformat=readshort(f),
- nofmetrics=readushort(f),
- }
- else
- fontdata.horizontalheader={
- nofmetrics=0,
- }
- end
- end
-end
-readers.vhea=function(f,fontdata,specification)
- if specification.details then
- local datatable=fontdata.tables.vhea
- if datatable then
- setposition(f,datatable.offset)
- local version=readfixed(f)
- fontdata.verticalheader={
- version=version,
- ascender=readfword(f),
- descender=readfword(f),
- linegap=readfword(f),
- maxadvanceheight=readufword(f),
- mintopsidebearing=readfword(f),
- minbottomsidebearing=readfword(f),
- maxextent=readfword(f),
- caretsloperise=readshort(f),
- caretsloperun=readshort(f),
- caretoffset=readshort(f),
- reserved_1=readshort(f),
- reserved_2=readshort(f),
- reserved_3=readshort(f),
- reserved_4=readshort(f),
- metricdataformat=readshort(f),
- nofmetrics=readushort(f),
- }
- else
- fontdata.verticalheader={
- nofmetrics=0,
- }
- end
- end
-end
-readers.maxp=function(f,fontdata,specification)
- if specification.details then
- local datatable=fontdata.tables.maxp
- if datatable then
- setposition(f,datatable.offset)
- local version=readfixed(f)
- local nofglyphs=readushort(f)
- fontdata.nofglyphs=nofglyphs
- if version==0.5 then
- fontdata.maximumprofile={
- version=version,
- nofglyphs=nofglyphs,
- }
- return
- elseif version==1.0 then
- fontdata.maximumprofile={
- version=version,
- nofglyphs=nofglyphs,
- points=readushort(f),
- contours=readushort(f),
- compositepoints=readushort(f),
- compositecontours=readushort(f),
- zones=readushort(f),
- twilightpoints=readushort(f),
- storage=readushort(f),
- functiondefs=readushort(f),
- instructiondefs=readushort(f),
- stackelements=readushort(f),
- sizeofinstructions=readushort(f),
- componentelements=readushort(f),
- componentdepth=readushort(f),
- }
- return
- end
- end
- fontdata.maximumprofile={
- version=version,
- nofglyphs=0,
- }
- end
-end
-readers.hmtx=function(f,fontdata,specification)
- if specification.glyphs then
- local datatable=fontdata.tables.hmtx
- if datatable then
- setposition(f,datatable.offset)
- local horizontalheader=fontdata.horizontalheader
- local nofmetrics=horizontalheader.nofmetrics
- local glyphs=fontdata.glyphs
- local nofglyphs=fontdata.nofglyphs
- local width=0
- local leftsidebearing=0
- for i=0,nofmetrics-1 do
- local glyph=glyphs[i]
- width=readshort(f)
- leftsidebearing=readshort(f)
- if width~=0 then
- glyph.width=width
- end
- end
- for i=nofmetrics,nofglyphs-1 do
- local glyph=glyphs[i]
- if width~=0 then
- glyph.width=width
- end
- end
- end
- end
-end
-readers.vmtx=function(f,fontdata,specification)
- if specification.glyphs then
- local datatable=fontdata.tables.vmtx
- if datatable then
- setposition(f,datatable.offset)
- local verticalheader=fontdata.verticalheader
- local nofmetrics=verticalheader.nofmetrics
- local glyphs=fontdata.glyphs
- local nofglyphs=fontdata.nofglyphs
- local vheight=0
- local vdefault=verticalheader.ascender+verticalheader.descender
- local topsidebearing=0
- for i=0,nofmetrics-1 do
- local glyph=glyphs[i]
- vheight=readshort(f)
- topsidebearing=readshort(f)
- if vheight~=0 and vheight~=vdefault then
- glyph.vheight=vheight
- end
- end
- for i=nofmetrics,nofglyphs-1 do
- local glyph=glyphs[i]
- if vheight~=0 and vheight~=vdefault then
- glyph.vheight=vheight
- end
- end
- end
- end
-end
-readers.vorg=function(f,fontdata,specification)
- if specification.glyphs then
- local datatable=fontdata.tables.vorg
- if datatable then
- report("todo: %s","vorg")
- end
- end
-end
-readers.post=function(f,fontdata,specification)
- local datatable=fontdata.tables.post
- if datatable then
- setposition(f,datatable.offset)
- local version=readfixed(f)
- fontdata.postscript={
- version=version,
- italicangle=round(1000*readfixed(f))/1000,
- underlineposition=readfword(f),
- underlinethickness=readfword(f),
- monospaced=readulong(f),
- minmemtype42=readulong(f),
- maxmemtype42=readulong(f),
- minmemtype1=readulong(f),
- maxmemtype1=readulong(f),
- }
- if not specification.glyphs then
- elseif version==1.0 then
- for index=0,#standardromanencoding do
- glyphs[index].name=standardromanencoding[index]
- end
- elseif version==2.0 then
- local glyphs=fontdata.glyphs
- local nofglyphs=readushort(f)
- local indices={}
- local names={}
- local maxnames=0
- for i=0,nofglyphs-1 do
- local nameindex=readushort(f)
- if nameindex>=258 then
- maxnames=maxnames+1
- nameindex=nameindex-257
- indices[nameindex]=i
- else
- glyphs[i].name=standardromanencoding[nameindex]
- end
- end
- for i=1,maxnames do
- local mapping=indices[i]
- if not mapping then
- report("quit post name fetching at %a of %a: %s",i,maxnames,"no index")
- break
- else
- local length=readbyte(f)
- if length>0 then
- glyphs[mapping].name=readstring(f,length)
- else
- report("quit post name fetching at %a of %a: %s",i,maxnames,"overflow")
- break
- end
- end
- end
- elseif version==2.5 then
- elseif version==3.0 then
- end
- else
- fontdata.postscript={}
- end
-end
-readers.cff=function(f,fontdata,specification)
- if specification.glyphs then
- reportskippedtable("cff")
- end
-end
-local formatreaders={}
-local duplicatestoo=true
-local sequence={
- { 3,1,4 },
- { 3,10,12 },
- { 0,3,4 },
- { 0,1,4 },
- { 0,0,6 },
- { 3,0,6 },
- { 0,5,14 },
- { 3,10,13 },
-}
-local supported={}
-for i=1,#sequence do
- local sp,se,sf=unpack(sequence[i])
- local p=supported[sp]
- if not p then
- p={}
- supported[sp]=p
- end
- local e=p[se]
- if not e then
- e={}
- p[se]=e
- end
- e[sf]=true
-end
-formatreaders[4]=function(f,fontdata,offset)
- setposition(f,offset+2)
- local length=readushort(f)
- local language=readushort(f)
- local nofsegments=readushort(f)/2
- skipshort(f,3)
- local endchars={}
- local startchars={}
- local deltas={}
- local offsets={}
- local indices={}
- local mapping=fontdata.mapping
- local glyphs=fontdata.glyphs
- local duplicates=fontdata.duplicates
- local nofdone=0
- for i=1,nofsegments do
- endchars[i]=readushort(f)
- end
- local reserved=readushort(f)
- for i=1,nofsegments do
- startchars[i]=readushort(f)
- end
- for i=1,nofsegments do
- deltas[i]=readshort(f)
- end
- for i=1,nofsegments do
- offsets[i]=readushort(f)
- end
- local size=(length-2*2-5*2-4*nofsegments*2)/2
- for i=1,size-1 do
- indices[i]=readushort(f)
- end
- for segment=1,nofsegments do
- local startchar=startchars[segment]
- local endchar=endchars[segment]
- local offset=offsets[segment]
- local delta=deltas[segment]
- if startchar==0xFFFF and endchar==0xFFFF then
- elseif startchar==0xFFFF and offset==0 then
- elseif offset==0xFFFF then
- elseif offset==0 then
- if trace_cmap then
- report("format 4.%i segment %2i from %C upto %C at index %H",1,segment,startchar,endchar,(startchar+delta)%65536)
- end
- for unicode=startchar,endchar do
- local index=(unicode+delta)%65536
- if index and index>0 then
- local glyph=glyphs[index]
- if glyph then
- local gu=glyph.unicode
- if not gu then
- glyph.unicode=unicode
- nofdone=nofdone+1
- elseif gu~=unicode then
- if duplicatestoo then
- local d=duplicates[gu]
- if d then
- d[unicode]=true
- else
- duplicates[gu]={ [unicode]=true }
- end
- else
- report("duplicate case 1: %C %04i %s",unicode,index,glyphs[index].name)
- end
- end
- if not mapping[index] then
- mapping[index]=unicode
- end
- end
- end
- end
- else
- local shift=(segment-nofsegments+offset/2)-startchar
- if trace_cmap then
- report("format 4.%i segment %2i from %C upto %C at index %H",0,segment,startchar,endchar,(startchar+delta)%65536)
- end
- for unicode=startchar,endchar do
- local slot=shift+unicode
- local index=indices[slot]
- if index and index>0 then
- index=(index+delta)%65536
- local glyph=glyphs[index]
- if glyph then
- local gu=glyph.unicode
- if not gu then
- glyph.unicode=unicode
- nofdone=nofdone+1
- elseif gu~=unicode then
- if duplicatestoo then
- local d=duplicates[gu]
- if d then
- d[unicode]=true
- else
- duplicates[gu]={ [unicode]=true }
- end
- else
- report("duplicate case 2: %C %04i %s",unicode,index,glyphs[index].name)
- end
- end
- if not mapping[index] then
- mapping[index]=unicode
- end
- end
- end
- end
- end
- end
- return nofdone
-end
-formatreaders[6]=function(f,fontdata,offset)
- setposition(f,offset)
- local format=readushort(f)
- local length=readushort(f)
- local language=readushort(f)
- local mapping=fontdata.mapping
- local glyphs=fontdata.glyphs
- local duplicates=fontdata.duplicates
- local start=readushort(f)
- local count=readushort(f)
- local stop=start+count-1
- local nofdone=0
- if trace_cmap then
- report("format 6 from %C to %C",2,start,stop)
- end
- for unicode=start,stop do
- local index=readushort(f)
- if index>0 then
- local glyph=glyphs[index]
- if glyph then
- local gu=glyph.unicode
- if not gu then
- glyph.unicode=unicode
- nofdone=nofdone+1
- elseif gu~=unicode then
- end
- if not mapping[index] then
- mapping[index]=unicode
- end
- end
- end
- end
- return nofdone
-end
-formatreaders[12]=function(f,fontdata,offset)
- setposition(f,offset+2+2+4+4)
- local mapping=fontdata.mapping
- local glyphs=fontdata.glyphs
- local duplicates=fontdata.duplicates
- local nofgroups=readulong(f)
- local nofdone=0
- for i=1,nofgroups do
- local first=readulong(f)
- local last=readulong(f)
- local index=readulong(f)
- if trace_cmap then
- report("format 12 from %C to %C starts at index %i",first,last,index)
- end
- for unicode=first,last do
- local glyph=glyphs[index]
- if glyph then
- local gu=glyph.unicode
- if not gu then
- glyph.unicode=unicode
- nofdone=nofdone+1
- elseif gu~=unicode then
- local d=duplicates[gu]
- if d then
- d[unicode]=true
- else
- duplicates[gu]={ [unicode]=true }
- end
- end
- if not mapping[index] then
- mapping[index]=unicode
- end
- end
- index=index+1
- end
- end
- return nofdone
-end
-formatreaders[13]=function(f,fontdata,offset)
- setposition(f,offset+2+2+4+4)
- local mapping=fontdata.mapping
- local glyphs=fontdata.glyphs
- local duplicates=fontdata.duplicates
- local nofgroups=readulong(f)
- local nofdone=0
- for i=1,nofgroups do
- local first=readulong(f)
- local last=readulong(f)
- local index=readulong(f)
- if first<privateoffset then
- if trace_cmap then
- report("format 13 from %C to %C get index %i",first,last,index)
- end
- local glyph=glyphs[index]
- local unicode=glyph.unicode
- if not unicode then
- unicode=first
- glyph.unicode=unicode
- first=first+1
- end
- local list=duplicates[unicode]
- mapping[index]=unicode
- if not list then
- list={}
- duplicates[unicode]=list
- end
- if last>=privateoffset then
- local limit=privateoffset-1
- report("format 13 from %C to %C pruned to %C",first,last,limit)
- last=limit
- end
- for unicode=first,last do
- list[unicode]=true
- end
- nofdone=nofdone+last-first+1
- else
- report("format 13 from %C to %C ignored",first,last)
- end
- end
- return nofdone
-end
-formatreaders[14]=function(f,fontdata,offset)
- if offset and offset~=0 then
- setposition(f,offset)
- local format=readushort(f)
- local length=readulong(f)
- local nofrecords=readulong(f)
- local records={}
- local variants={}
- local nofdone=0
- fontdata.variants=variants
- for i=1,nofrecords do
- records[i]={
- selector=readuint(f),
- default=readulong(f),
- other=readulong(f),
- }
- end
- for i=1,nofrecords do
- local record=records[i]
- local selector=record.selector
- local default=record.default
- local other=record.other
- local other=record.other
- if other~=0 then
- setposition(f,offset+other)
- local mapping={}
- local count=readulong(f)
- for i=1,count do
- mapping[readuint(f)]=readushort(f)
- end
- nofdone=nofdone+count
- variants[selector]=mapping
- end
- end
- return nofdone
- else
- return 0
- end
-end
-local function checkcmap(f,fontdata,records,platform,encoding,format)
- local data=records[platform]
- if not data then
- return 0
- end
- data=data[encoding]
- if not data then
- return 0
- end
- data=data[format]
- if not data then
- return 0
- end
- local reader=formatreaders[format]
- if not reader then
- return 0
- end
- local p=platforms[platform]
- local e=encodings[p]
- local n=reader(f,fontdata,data) or 0
- report("cmap checked: platform %i (%s), encoding %i (%s), format %i, new unicodes %i",platform,p,encoding,e and e[encoding] or "?",format,n)
- return n
-end
-function readers.cmap(f,fontdata,specification)
- if specification.glyphs then
- local datatable=fontdata.tables.cmap
- if datatable then
- local tableoffset=datatable.offset
- setposition(f,tableoffset)
- local version=readushort(f)
- local noftables=readushort(f)
- local records={}
- local unicodecid=false
- local variantcid=false
- local variants={}
- local duplicates=fontdata.duplicates or {}
- fontdata.duplicates=duplicates
- for i=1,noftables do
- local platform=readushort(f)
- local encoding=readushort(f)
- local offset=readulong(f)
- local record=records[platform]
- if not record then
- records[platform]={
- [encoding]={
- offsets={ offset },
- formats={},
- }
- }
- else
- local subtables=record[encoding]
- if not subtables then
- record[encoding]={
- offsets={ offset },
- formats={},
- }
- else
- local offsets=subtables.offsets
- offsets[#offsets+1]=offset
- end
- end
- end
- report("found cmaps:")
- for platform,record in sortedhash(records) do
- local p=platforms[platform]
- local e=encodings[p]
- local sp=supported[platform]
- local ps=p or "?"
- if sp then
- report(" platform %i: %s",platform,ps)
- else
- report(" platform %i: %s (unsupported)",platform,ps)
- end
- for encoding,subtables in sortedhash(record) do
- local se=sp and sp[encoding]
- local es=e and e[encoding] or "?"
- if se then
- report(" encoding %i: %s",encoding,es)
- else
- report(" encoding %i: %s (unsupported)",encoding,es)
- end
- local offsets=subtables.offsets
- local formats=subtables.formats
- for i=1,#offsets do
- local offset=tableoffset+offsets[i]
- setposition(f,offset)
- formats[readushort(f)]=offset
- end
- record[encoding]=formats
- local list=sortedkeys(formats)
- for i=1,#list do
- if not (se and se[list[i]]) then
- list[i]=list[i].." (unsupported)"
- end
- end
- report(" formats: % t",list)
- end
- end
- local ok=false
- for i=1,#sequence do
- local sp,se,sf=unpack(sequence[i])
- if checkcmap(f,fontdata,records,sp,se,sf)>0 then
- ok=true
- end
- end
- if not ok then
- report("no useable unicode cmap found")
- end
- fontdata.cidmaps={
- version=version,
- noftables=noftables,
- records=records,
- }
- else
- fontdata.cidmaps={}
- end
- end
-end
-function readers.loca(f,fontdata,specification)
- if specification.glyphs then
- reportskippedtable("loca")
- end
-end
-function readers.glyf(f,fontdata,specification)
- if specification.glyphs then
- reportskippedtable("glyf")
- end
-end
-function readers.colr(f,fontdata,specification)
- if specification.glyphs then
- reportskippedtable("colr")
- end
-end
-function readers.cpal(f,fontdata,specification)
- if specification.glyphs then
- reportskippedtable("cpal")
- end
-end
-function readers.svg(f,fontdata,specification)
- if specification.glyphs then
- reportskippedtable("svg")
- end
-end
-function readers.kern(f,fontdata,specification)
- if specification.kerns then
- local datatable=fontdata.tables.kern
- if datatable then
- setposition(f,datatable.offset)
- local version=readushort(f)
- local noftables=readushort(f)
- for i=1,noftables do
- local version=readushort(f)
- local length=readushort(f)
- local coverage=readushort(f)
- local format=bit32.rshift(coverage,8)
- if format==0 then
- local nofpairs=readushort(f)
- local searchrange=readushort(f)
- local entryselector=readushort(f)
- local rangeshift=readushort(f)
- local kerns={}
- local glyphs=fontdata.glyphs
- for i=1,nofpairs do
- local left=readushort(f)
- local right=readushort(f)
- local kern=readfword(f)
- local glyph=glyphs[left]
- local kerns=glyph.kerns
- if kerns then
- kerns[right]=kern
- else
- glyph.kerns={ [right]=kern }
- end
- end
- elseif format==2 then
- report("todo: kern classes")
- else
- report("todo: kerns")
- end
- end
- end
- end
-end
-function readers.gdef(f,fontdata,specification)
- if specification.details then
- reportskippedtable("gdef")
- end
-end
-function readers.gsub(f,fontdata,specification)
- if specification.details then
- reportskippedtable("gsub")
- end
-end
-function readers.gpos(f,fontdata,specification)
- if specification.details then
- reportskippedtable("gpos")
- end
-end
-function readers.math(f,fontdata,specification)
- if specification.glyphs then
- reportskippedtable("math")
- end
-end
-local function getinfo(maindata,sub,platformnames,rawfamilynames,metricstoo)
- local fontdata=sub and maindata.subfonts and maindata.subfonts[sub] or maindata
- local names=fontdata.names
- local info=nil
- if names then
- local metrics=fontdata.windowsmetrics or {}
- local postscript=fontdata.postscript or {}
- local fontheader=fontdata.fontheader or {}
- local cffinfo=fontdata.cffinfo or {}
- local filename=fontdata.filename
- local weight=getname(fontdata,"weight") or (cffinfo and cffinfo.weight) or (metrics and metrics.weight)
- local width=getname(fontdata,"width") or (cffinfo and cffinfo.width ) or (metrics and metrics.width )
- local fontname=getname(fontdata,"postscriptname")
- local fullname=getname(fontdata,"fullname")
- local family=getname(fontdata,"family")
- local subfamily=getname(fontdata,"subfamily")
- local familyname=getname(fontdata,"typographicfamily")
- local subfamilyname=getname(fontdata,"typographicsubfamily")
- local compatiblename=getname(fontdata,"compatiblefullname")
- if rawfamilynames then
- else
- if not familyname then familyname=family end
- if not subfamilyname then subfamilyname=subfamily end
- end
- info={
- subfontindex=fontdata.subfontindex or sub or 0,
- version=getname(fontdata,"version"),
- fontname=fontname,
- fullname=fullname,
- family=family,
- subfamily=subfamily,
- familyname=familyname,
- subfamilyname=subfamilyname,
- compatiblename=compatiblename,
- weight=weight and lower(weight),
- width=width and lower(width),
- pfmweight=metrics.weightclass or 400,
- pfmwidth=metrics.widthclass or 5,
- panosewidth=metrics.panosewidth,
- panoseweight=metrics.panoseweight,
- italicangle=postscript.italicangle or 0,
- units=fontheader.units or 0,
- designsize=fontdata.designsize,
- minsize=fontdata.minsize,
- maxsize=fontdata.maxsize,
- monospaced=(tonumber(postscript.monospaced or 0)>0) or metrics.panosewidth=="monospaced",
- averagewidth=metrics.averagewidth,
- xheight=metrics.xheight,
- capheight=metrics.capheight,
- ascender=metrics.typoascender,
- descender=metrics.typodescender,
- platformnames=platformnames and fontdata.platformnames or nil,
- }
- if metricstoo then
- local keys={
- "version",
- "ascender","descender","linegap",
- "maxadvancewidth","maxadvanceheight","maxextent",
- "minbottomsidebearing","mintopsidebearing",
- }
- local h=fontdata.horizontalheader or {}
- local v=fontdata.verticalheader or {}
- if h then
- local th={}
- local tv={}
- for i=1,#keys do
- local key=keys[i]
- th[key]=h[key] or 0
- tv[key]=v[key] or 0
- end
- info.horizontalmetrics=th
- info.verticalmetrics=tv
- end
- end
- elseif n then
- info={
- filename=fontdata.filename,
- comment="there is no info for subfont "..n,
- }
- else
- info={
- filename=fontdata.filename,
- comment="there is no info",
- }
- end
- return info
-end
-local function loadtables(f,specification,offset)
- if offset then
- setposition(f,offset)
- end
- local tables={}
- local basename=file.basename(specification.filename)
- local filesize=specification.filesize
- local filetime=specification.filetime
- local fontdata={
- filename=basename,
- filesize=filesize,
- filetime=filetime,
- version=readstring(f,4),
- noftables=readushort(f),
- searchrange=readushort(f),
- entryselector=readushort(f),
- rangeshift=readushort(f),
- tables=tables,
- }
- for i=1,fontdata.noftables do
- local tag=lower(stripstring(readstring(f,4)))
- local checksum=readulong(f)
- local offset=readulong(f)
- local length=readulong(f)
- if offset+length>filesize then
- report("bad %a table in file %a",tag,basename)
- end
- tables[tag]={
- checksum=checksum,
- offset=offset,
- length=length,
- }
- end
- if tables.cff then
- fontdata.format="opentype"
- else
- fontdata.format="truetype"
- end
- return fontdata
-end
-local function prepareglyps(fontdata)
- local glyphs=setmetatableindex(function(t,k)
- local v={
- index=k,
- }
- t[k]=v
- return v
- end)
- fontdata.glyphs=glyphs
- fontdata.mapping={}
-end
-local function readdata(f,offset,specification)
- local fontdata=loadtables(f,specification,offset)
- if specification.glyphs then
- prepareglyps(fontdata)
- end
- readers["name"](f,fontdata,specification)
- local askedname=specification.askedname
- if askedname then
- local fullname=getname(fontdata,"fullname") or ""
- local cleanname=gsub(askedname,"[^a-zA-Z0-9]","")
- local foundname=gsub(fullname,"[^a-zA-Z0-9]","")
- if lower(cleanname)~=lower(foundname) then
- return
- end
- end
- readers["os/2"](f,fontdata,specification)
- readers["head"](f,fontdata,specification)
- readers["maxp"](f,fontdata,specification)
- readers["hhea"](f,fontdata,specification)
- readers["vhea"](f,fontdata,specification)
- readers["hmtx"](f,fontdata,specification)
- readers["vmtx"](f,fontdata,specification)
- readers["vorg"](f,fontdata,specification)
- readers["post"](f,fontdata,specification)
- readers["cff" ](f,fontdata,specification)
- readers["cmap"](f,fontdata,specification)
- readers["loca"](f,fontdata,specification)
- readers["glyf"](f,fontdata,specification)
- readers["colr"](f,fontdata,specification)
- readers["cpal"](f,fontdata,specification)
- readers["svg" ](f,fontdata,specification)
- readers["kern"](f,fontdata,specification)
- readers["gdef"](f,fontdata,specification)
- readers["gsub"](f,fontdata,specification)
- readers["gpos"](f,fontdata,specification)
- readers["math"](f,fontdata,specification)
- fontdata.locations=nil
- fontdata.tables=nil
- fontdata.cidmaps=nil
- fontdata.dictionaries=nil
- return fontdata
-end
-local function loadfontdata(specification)
- local filename=specification.filename
- local fileattr=lfs.attributes(filename)
- local filesize=fileattr and fileattr.size or 0
- local filetime=fileattr and fileattr.modification or 0
- local f=openfile(filename,true)
- if not f then
- report("unable to open %a",filename)
- elseif filesize==0 then
- report("empty file %a",filename)
- closefile(f)
- else
- specification.filesize=filesize
- specification.filetime=filetime
- local version=readstring(f,4)
- local fontdata=nil
- if version=="OTTO" or version=="true" or version=="\0\1\0\0" then
- fontdata=readdata(f,0,specification)
- elseif version=="ttcf" then
- local subfont=tonumber(specification.subfont)
- local offsets={}
- local ttcversion=readulong(f)
- local nofsubfonts=readulong(f)
- for i=1,nofsubfonts do
- offsets[i]=readulong(f)
- end
- if subfont then
- if subfont>=1 and subfont<=nofsubfonts then
- fontdata=readdata(f,offsets[subfont],specification)
- else
- report("no subfont %a in file %a",subfont,filename)
- end
- else
- subfont=specification.subfont
- if type(subfont)=="string" and subfont~="" then
- specification.askedname=subfont
- for i=1,nofsubfonts do
- fontdata=readdata(f,offsets[i],specification)
- if fontdata then
- fontdata.subfontindex=i
- report("subfont named %a has index %a",subfont,i)
- break
- end
- end
- if not fontdata then
- report("no subfont named %a",subfont)
- end
- else
- local subfonts={}
- fontdata={
- filename=filename,
- filesize=filesize,
- filetime=filetime,
- version=version,
- subfonts=subfonts,
- ttcversion=ttcversion,
- nofsubfonts=nofsubfonts,
- }
- for i=1,nofsubfonts do
- subfonts[i]=readdata(f,offsets[i],specification)
- end
- end
- end
- else
- report("unknown version %a in file %a",version,filename)
- end
- closefile(f)
- return fontdata or {}
- end
-end
-local function loadfont(specification,n)
- if type(specification)=="string" then
- specification={
- filename=specification,
- info=true,
- details=true,
- glyphs=true,
- shapes=true,
- kerns=true,
- globalkerns=true,
- lookups=true,
- subfont=n or true,
- tounicode=false,
- }
- end
- if specification.shapes or specification.lookups or specification.kerns then
- specification.glyphs=true
- end
- if specification.glyphs then
- specification.details=true
- end
- if specification.details then
- specification.info=true
- end
- if specification.platformnames then
- specification.platformnames=true
- end
- local function message(str)
- report("fatal error in file %a: %s\n%s",specification.filename,str,debug.traceback())
- end
- local ok,result=xpcall(loadfontdata,message,specification)
- if ok then
- return result
- end
-end
-function readers.loadshapes(filename,n)
- local fontdata=loadfont {
- filename=filename,
- shapes=true,
- subfont=n,
- }
- if fontdata then
- for k,v in next,fontdata.glyphs do
- v.class=nil
- v.index=nil
- v.math=nil
- end
- end
- return fontdata and {
- filename=filename,
- format=fontdata.format,
- glyphs=fontdata.glyphs,
- units=fontdata.fontheader.units,
- } or {
- filename=filename,
- format="unknown",
- glyphs={},
- units=0,
- }
-end
-function readers.loadfont(filename,n)
- local fontdata=loadfont {
- filename=filename,
- glyphs=true,
- shapes=false,
- lookups=true,
- subfont=n,
- }
- if fontdata then
- return {
- tableversion=tableversion,
- creator="context mkiv",
- size=fontdata.filesize,
- time=fontdata.filetime,
- glyphs=fontdata.glyphs,
- descriptions=fontdata.descriptions,
- format=fontdata.format,
- goodies={},
- metadata=getinfo(fontdata,n,false,false,true),
- properties={
- hasitalics=fontdata.hasitalics or false,
- maxcolorclass=fontdata.maxcolorclass,
- hascolor=fontdata.hascolor or false,
- },
- resources={
- filename=filename,
- private=privateoffset,
- duplicates=fontdata.duplicates or {},
- features=fontdata.features or {},
- sublookups=fontdata.sublookups or {},
- marks=fontdata.marks or {},
- markclasses=fontdata.markclasses or {},
- marksets=fontdata.marksets or {},
- sequences=fontdata.sequences or {},
- variants=fontdata.variants,
- version=getname(fontdata,"version"),
- cidinfo=fontdata.cidinfo,
- mathconstants=fontdata.mathconstants,
- colorpalettes=fontdata.colorpalettes,
- svgshapes=fontdata.svgshapes,
- },
- }
- end
-end
-function readers.getinfo(filename,specification)
- local subfont=nil
- local platformnames=false
- local rawfamilynames=false
- if type(specification)=="table" then
- subfont=tonumber(specification.subfont)
- platformnames=specification.platformnames
- rawfamilynames=specification.rawfamilynames
- else
- subfont=tonumber(specification)
- end
- local fontdata=loadfont {
- filename=filename,
- details=true,
- platformnames=platformnames,
- }
- if fontdata then
- local subfonts=fontdata.subfonts
- if not subfonts then
- return getinfo(fontdata,nil,platformnames,rawfamilynames)
- elseif not subfont then
- local info={}
- for i=1,#subfonts do
- info[i]=getinfo(fontdata,i,platformnames,rawfamilynames)
- end
- return info
- elseif subfont>=1 and subfont<=#subfonts then
- return getinfo(fontdata,subfont,platformnames,rawfamilynames)
- else
- return {
- filename=filename,
- comment="there is no subfont "..subfont.." in this file"
- }
- end
- else
- return {
- filename=filename,
- comment="the file cannot be opened for reading",
- }
- end
-end
-function readers.rehash(fontdata,hashmethod)
- report("the %a helper is not yet implemented","rehash")
-end
-function readers.checkhash(fontdata)
- report("the %a helper is not yet implemented","checkhash")
-end
-function readers.pack(fontdata,hashmethod)
- report("the %a helper is not yet implemented","pack")
-end
-function readers.unpack(fontdata)
- report("the %a helper is not yet implemented","unpack")
-end
-function readers.expand(fontdata)
- report("the %a helper is not yet implemented","unpack")
-end
-function readers.compact(fontdata)
- report("the %a helper is not yet implemented","compact")
-end
-local extenders={}
-function readers.registerextender(extender)
- extenders[#extenders+1]=extender
-end
-function readers.extend(fontdata)
- for i=1,#extenders do
- local extender=extenders[i]
- local name=extender.name or "unknown"
- local action=extender.action
- if action then
- action(fontdata)
- end
- end
-end
-
-end --- [luaotfload, fontloader-2017-02-11.lua scope for “font-otr”] ---
-
-
-do --- [luaotfload, fontloader-2017-02-11.lua scope for “font-cff” f3fc74e8629f7a2825c34a34550c790d] ---
-
-if not modules then modules={} end modules ['font-cff']={
- version=1.001,
- comment="companion to font-ini.mkiv",
- author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright="PRAGMA ADE / ConTeXt Development Team",
- license="see context related readme files"
-}
-local next,type,tonumber=next,type,tonumber
-local byte=string.byte
-local concat,remove=table.concat,table.remove
-local floor,abs,round,ceil=math.floor,math.abs,math.round,math.ceil
-local P,C,R,S,C,Cs,Ct=lpeg.P,lpeg.C,lpeg.R,lpeg.S,lpeg.C,lpeg.Cs,lpeg.Ct
-local lpegmatch=lpeg.match
-local formatters=string.formatters
-local readers=fonts.handlers.otf.readers
-local streamreader=readers.streamreader
-local readbytes=streamreader.readbytes
-local readstring=streamreader.readstring
-local readbyte=streamreader.readcardinal1
-local readushort=streamreader.readcardinal2
-local readuint=streamreader.readcardinal3
-local readulong=streamreader.readcardinal4
-local setposition=streamreader.setposition
-local getposition=streamreader.getposition
-local setmetatableindex=table.setmetatableindex
-local trace_charstrings=false trackers.register("fonts.cff.charstrings",function(v) trace_charstrings=v end)
-local report=logs.reporter("otf reader","cff")
-local parsedictionaries
-local parsecharstring
-local parsecharstrings
-local resetcharstrings
-local parseprivates
-local defaultstrings={ [0]=
- ".notdef","space","exclam","quotedbl","numbersign","dollar","percent",
- "ampersand","quoteright","parenleft","parenright","asterisk","plus",
- "comma","hyphen","period","slash","zero","one","two","three","four",
- "five","six","seven","eight","nine","colon","semicolon","less",
- "equal","greater","question","at","A","B","C","D","E","F","G","H",
- "I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W",
- "X","Y","Z","bracketleft","backslash","bracketright","asciicircum",
- "underscore","quoteleft","a","b","c","d","e","f","g","h","i","j",
- "k","l","m","n","o","p","q","r","s","t","u","v","w","x","y",
- "z","braceleft","bar","braceright","asciitilde","exclamdown","cent",
- "sterling","fraction","yen","florin","section","currency",
- "quotesingle","quotedblleft","guillemotleft","guilsinglleft",
- "guilsinglright","fi","fl","endash","dagger","daggerdbl",
- "periodcentered","paragraph","bullet","quotesinglbase","quotedblbase",
- "quotedblright","guillemotright","ellipsis","perthousand","questiondown",
- "grave","acute","circumflex","tilde","macron","breve","dotaccent",
- "dieresis","ring","cedilla","hungarumlaut","ogonek","caron","emdash",
- "AE","ordfeminine","Lslash","Oslash","OE","ordmasculine","ae",
- "dotlessi","lslash","oslash","oe","germandbls","onesuperior",
- "logicalnot","mu","trademark","Eth","onehalf","plusminus","Thorn",
- "onequarter","divide","brokenbar","degree","thorn","threequarters",
- "twosuperior","registered","minus","eth","multiply","threesuperior",
- "copyright","Aacute","Acircumflex","Adieresis","Agrave","Aring",
- "Atilde","Ccedilla","Eacute","Ecircumflex","Edieresis","Egrave",
- "Iacute","Icircumflex","Idieresis","Igrave","Ntilde","Oacute",
- "Ocircumflex","Odieresis","Ograve","Otilde","Scaron","Uacute",
- "Ucircumflex","Udieresis","Ugrave","Yacute","Ydieresis","Zcaron",
- "aacute","acircumflex","adieresis","agrave","aring","atilde",
- "ccedilla","eacute","ecircumflex","edieresis","egrave","iacute",
- "icircumflex","idieresis","igrave","ntilde","oacute","ocircumflex",
- "odieresis","ograve","otilde","scaron","uacute","ucircumflex",
- "udieresis","ugrave","yacute","ydieresis","zcaron","exclamsmall",
- "Hungarumlautsmall","dollaroldstyle","dollarsuperior","ampersandsmall",
- "Acutesmall","parenleftsuperior","parenrightsuperior","twodotenleader",
- "onedotenleader","zerooldstyle","oneoldstyle","twooldstyle",
- "threeoldstyle","fouroldstyle","fiveoldstyle","sixoldstyle",
- "sevenoldstyle","eightoldstyle","nineoldstyle","commasuperior",
- "threequartersemdash","periodsuperior","questionsmall","asuperior",
- "bsuperior","centsuperior","dsuperior","esuperior","isuperior",
- "lsuperior","msuperior","nsuperior","osuperior","rsuperior","ssuperior",
- "tsuperior","ff","ffi","ffl","parenleftinferior","parenrightinferior",
- "Circumflexsmall","hyphensuperior","Gravesmall","Asmall","Bsmall",
- "Csmall","Dsmall","Esmall","Fsmall","Gsmall","Hsmall","Ismall",
- "Jsmall","Ksmall","Lsmall","Msmall","Nsmall","Osmall","Psmall",
- "Qsmall","Rsmall","Ssmall","Tsmall","Usmall","Vsmall","Wsmall",
- "Xsmall","Ysmall","Zsmall","colonmonetary","onefitted","rupiah",
- "Tildesmall","exclamdownsmall","centoldstyle","Lslashsmall",
- "Scaronsmall","Zcaronsmall","Dieresissmall","Brevesmall","Caronsmall",
- "Dotaccentsmall","Macronsmall","figuredash","hypheninferior",
- "Ogoneksmall","Ringsmall","Cedillasmall","questiondownsmall","oneeighth",
- "threeeighths","fiveeighths","seveneighths","onethird","twothirds",
- "zerosuperior","foursuperior","fivesuperior","sixsuperior",
- "sevensuperior","eightsuperior","ninesuperior","zeroinferior",
- "oneinferior","twoinferior","threeinferior","fourinferior",
- "fiveinferior","sixinferior","seveninferior","eightinferior",
- "nineinferior","centinferior","dollarinferior","periodinferior",
- "commainferior","Agravesmall","Aacutesmall","Acircumflexsmall",
- "Atildesmall","Adieresissmall","Aringsmall","AEsmall","Ccedillasmall",
- "Egravesmall","Eacutesmall","Ecircumflexsmall","Edieresissmall",
- "Igravesmall","Iacutesmall","Icircumflexsmall","Idieresissmall",
- "Ethsmall","Ntildesmall","Ogravesmall","Oacutesmall","Ocircumflexsmall",
- "Otildesmall","Odieresissmall","OEsmall","Oslashsmall","Ugravesmall",
- "Uacutesmall","Ucircumflexsmall","Udieresissmall","Yacutesmall",
- "Thornsmall","Ydieresissmall","001.000","001.001","001.002","001.003",
- "Black","Bold","Book","Light","Medium","Regular","Roman","Semibold",
-}
-local cffreaders={
- readbyte,
- readushort,
- readuint,
- readulong,
-}
-local function readheader(f)
- local offset=getposition(f)
- local header={
- offset=offset,
- major=readbyte(f),
- minor=readbyte(f),
- size=readbyte(f),
- osize=readbyte(f),
- }
- setposition(f,offset+header.size)
- return header
-end
-local function readlengths(f)
- local count=readushort(f)
- if count==0 then
- return {}
- end
- local osize=readbyte(f)
- local read=cffreaders[osize]
- if not read then
- report("bad offset size: %i",osize)
- return {}
- end
- local lengths={}
- local previous=read(f)
- for i=1,count do
- local offset=read(f)
- lengths[i]=offset-previous
- previous=offset
- end
- return lengths
-end
-local function readfontnames(f)
- local names=readlengths(f)
- for i=1,#names do
- names[i]=readstring(f,names[i])
- end
- return names
-end
-local function readtopdictionaries(f)
- local dictionaries=readlengths(f)
- for i=1,#dictionaries do
- dictionaries[i]=readstring(f,dictionaries[i])
- end
- return dictionaries
-end
-local function readstrings(f)
- local lengths=readlengths(f)
- local strings=setmetatableindex({},defaultstrings)
- local index=#defaultstrings
- for i=1,#lengths do
- index=index+1
- strings[index]=readstring(f,lengths[i])
- end
- return strings
-end
-do
- local stack={}
- local top=0
- local result={}
- local strings={}
- local p_single=P("\00")/function()
- result.version=strings[stack[top]] or "unset"
- top=0
- end+P("\01")/function()
- result.notice=strings[stack[top]] or "unset"
- top=0
- end+P("\02")/function()
- result.fullname=strings[stack[top]] or "unset"
- top=0
- end+P("\03")/function()
- result.familyname=strings[stack[top]] or "unset"
- top=0
- end+P("\04")/function()
- result.weight=strings[stack[top]] or "unset"
- top=0
- end+P("\05")/function()
- result.fontbbox={ unpack(stack,1,4) }
- top=0
- end
-+P("\13")/function()
- result.uniqueid=stack[top]
- top=0
- end+P("\14")/function()
- result.xuid=concat(stack,"",1,top)
- top=0
- end+P("\15")/function()
- result.charset=stack[top]
- top=0
- end+P("\16")/function()
- result.encoding=stack[top]
- top=0
- end+P("\17")/function()
- result.charstrings=stack[top]
- top=0
- end+P("\18")/function()
- result.private={
- size=stack[top-1],
- offset=stack[top],
- }
- top=0
- end+P("\19")/function()
- result.subroutines=stack[top]
- end+P("\20")/function()
- result.defaultwidthx=stack[top]
- end+P("\21")/function()
- result.nominalwidthx=stack[top]
- end
- local p_double=P("\12")*(
- P("\00")/function()
- result.copyright=stack[top]
- top=0
- end+P("\01")/function()
- result.monospaced=stack[top]==1 and true or false
- top=0
- end+P("\02")/function()
- result.italicangle=stack[top]
- top=0
- end+P("\03")/function()
- result.underlineposition=stack[top]
- top=0
- end+P("\04")/function()
- result.underlinethickness=stack[top]
- top=0
- end+P("\05")/function()
- result.painttype=stack[top]
- top=0
- end+P("\06")/function()
- result.charstringtype=stack[top]
- top=0
- end+P("\07")/function()
- result.fontmatrix={ unpack(stack,1,6) }
- top=0
- end+P("\08")/function()
- result.strokewidth=stack[top]
- top=0
- end+P("\20")/function()
- result.syntheticbase=stack[top]
- top=0
- end+P("\21")/function()
- result.postscript=strings[stack[top]] or "unset"
- top=0
- end+P("\22")/function()
- result.basefontname=strings[stack[top]] or "unset"
- top=0
- end+P("\21")/function()
- result.basefontblend=stack[top]
- top=0
- end+P("\30")/function()
- result.cid.registry=strings[stack[top-2]] or "unset"
- result.cid.ordering=strings[stack[top-1]] or "unset"
- result.cid.supplement=stack[top]
- top=0
- end+P("\31")/function()
- result.cid.fontversion=stack[top]
- top=0
- end+P("\32")/function()
- result.cid.fontrevision=stack[top]
- top=0
- end+P("\33")/function()
- result.cid.fonttype=stack[top]
- top=0
- end+P("\34")/function()
- result.cid.count=stack[top]
- top=0
- end+P("\35")/function()
- result.cid.uidbase=stack[top]
- top=0
- end+P("\36")/function()
- result.cid.fdarray=stack[top]
- top=0
- end+P("\37")/function()
- result.cid.fdselect=stack[top]
- top=0
- end+P("\38")/function()
- result.cid.fontname=strings[stack[top]] or "unset"
- top=0
- end
- )
- local p_last=P("\x0F")/"0"+P("\x1F")/"1"+P("\x2F")/"2"+P("\x3F")/"3"+P("\x4F")/"4"+P("\x5F")/"5"+P("\x6F")/"6"+P("\x7F")/"7"+P("\x8F")/"8"+P("\x9F")/"9"+P("\xAF")/""+P("\xBF")/""+P("\xCF")/""+P("\xDF")/""+P("\xEF")/""+R("\xF0\xFF")/""
- local remap={
- ["\x00"]="00",["\x01"]="01",["\x02"]="02",["\x03"]="03",["\x04"]="04",["\x05"]="05",["\x06"]="06",["\x07"]="07",["\x08"]="08",["\x09"]="09",["\x0A"]="0.",["\x0B"]="0E",["\x0C"]="0E-",["\x0D"]="0",["\x0E"]="0-",["\x0F"]="0",
- ["\x10"]="10",["\x11"]="11",["\x12"]="12",["\x13"]="13",["\x14"]="14",["\x15"]="15",["\x16"]="16",["\x17"]="17",["\x18"]="18",["\x19"]="19",["\x1A"]="0.",["\x1B"]="0E",["\x1C"]="0E-",["\x1D"]="0",["\x1E"]="0-",["\x1F"]="0",
- ["\x20"]="20",["\x21"]="21",["\x22"]="22",["\x23"]="23",["\x24"]="24",["\x25"]="25",["\x26"]="26",["\x27"]="27",["\x28"]="28",["\x29"]="29",["\x2A"]="0.",["\x2B"]="0E",["\x2C"]="0E-",["\x2D"]="0",["\x2E"]="0-",["\x2F"]="0",
- ["\x30"]="30",["\x31"]="31",["\x32"]="32",["\x33"]="33",["\x34"]="34",["\x35"]="35",["\x36"]="36",["\x37"]="37",["\x38"]="38",["\x39"]="39",["\x3A"]="0.",["\x3B"]="0E",["\x3C"]="0E-",["\x3D"]="0",["\x3E"]="0-",["\x3F"]="0",
- ["\x40"]="40",["\x41"]="41",["\x42"]="42",["\x43"]="43",["\x44"]="44",["\x45"]="45",["\x46"]="46",["\x47"]="47",["\x48"]="48",["\x49"]="49",["\x4A"]="0.",["\x4B"]="0E",["\x4C"]="0E-",["\x4D"]="0",["\x4E"]="0-",["\x4F"]="0",
- ["\x50"]="50",["\x51"]="51",["\x52"]="52",["\x53"]="53",["\x54"]="54",["\x55"]="55",["\x56"]="56",["\x57"]="57",["\x58"]="58",["\x59"]="59",["\x5A"]="0.",["\x5B"]="0E",["\x5C"]="0E-",["\x5D"]="0",["\x5E"]="0-",["\x5F"]="0",
- ["\x60"]="60",["\x61"]="61",["\x62"]="62",["\x63"]="63",["\x64"]="64",["\x65"]="65",["\x66"]="66",["\x67"]="67",["\x68"]="68",["\x69"]="69",["\x6A"]="0.",["\x6B"]="0E",["\x6C"]="0E-",["\x6D"]="0",["\x6E"]="0-",["\x6F"]="0",
- ["\x70"]="70",["\x71"]="71",["\x72"]="72",["\x73"]="73",["\x74"]="74",["\x75"]="75",["\x76"]="76",["\x77"]="77",["\x78"]="78",["\x79"]="79",["\x7A"]="0.",["\x7B"]="0E",["\x7C"]="0E-",["\x7D"]="0",["\x7E"]="0-",["\x7F"]="0",
- ["\x80"]="80",["\x81"]="81",["\x82"]="82",["\x83"]="83",["\x84"]="84",["\x85"]="85",["\x86"]="86",["\x87"]="87",["\x88"]="88",["\x89"]="89",["\x8A"]="0.",["\x8B"]="0E",["\x8C"]="0E-",["\x8D"]="0",["\x8E"]="0-",["\x8F"]="0",
- ["\x90"]="90",["\x91"]="91",["\x92"]="92",["\x93"]="93",["\x94"]="94",["\x95"]="95",["\x96"]="96",["\x97"]="97",["\x98"]="98",["\x99"]="99",["\x9A"]="0.",["\x9B"]="0E",["\x9C"]="0E-",["\x9D"]="0",["\x9E"]="0-",["\x9F"]="0",
- ["\xA0"]=".0",["\xA1"]=".1",["\xA2"]=".2",["\xA3"]=".3",["\xA4"]=".4",["\xA5"]=".5",["\xA6"]=".6",["\xA7"]=".7",["\xA8"]=".8",["\xA9"]=".9",["\xAA"]="..",["\xAB"]=".E",["\xAC"]=".E-",["\xAD"]=".",["\xAE"]=".-",["\xAF"]=".",
- ["\xB0"]="E0",["\xB1"]="E1",["\xB2"]="E2",["\xB3"]="E3",["\xB4"]="E4",["\xB5"]="E5",["\xB6"]="E6",["\xB7"]="E7",["\xB8"]="E8",["\xB9"]="E9",["\xBA"]="E.",["\xBB"]="EE",["\xBC"]="EE-",["\xBD"]="E",["\xBE"]="E-",["\xBF"]="E",
- ["\xC0"]="E-0",["\xC1"]="E-1",["\xC2"]="E-2",["\xC3"]="E-3",["\xC4"]="E-4",["\xC5"]="E-5",["\xC6"]="E-6",["\xC7"]="E-7",["\xC8"]="E-8",["\xC9"]="E-9",["\xCA"]="E-.",["\xCB"]="E-E",["\xCC"]="E-E-",["\xCD"]="E-",["\xCE"]="E--",["\xCF"]="E-",
- ["\xD0"]="-0",["\xD1"]="-1",["\xD2"]="-2",["\xD3"]="-3",["\xD4"]="-4",["\xD5"]="-5",["\xD6"]="-6",["\xD7"]="-7",["\xD8"]="-8",["\xD9"]="-9",["\xDA"]="-.",["\xDB"]="-E",["\xDC"]="-E-",["\xDD"]="-",["\xDE"]="--",["\xDF"]="-",
- }
- local p_nibbles=P("\30")*Cs(((1-p_last)/remap)^0+p_last)/function(n)
- top=top+1
- stack[top]=tonumber(n) or 0
- end
- local p_byte=C(R("\32\246"))/function(b0)
- top=top+1
- stack[top]=byte(b0)-139
- end
- local p_positive=C(R("\247\250"))*C(1)/function(b0,b1)
- top=top+1
- stack[top]=(byte(b0)-247)*256+byte(b1)+108
- end
- local p_negative=C(R("\251\254"))*C(1)/function(b0,b1)
- top=top+1
- stack[top]=-(byte(b0)-251)*256-byte(b1)-108
- end
- local p_short=P("\28")*C(1)*C(1)/function(b1,b2)
- top=top+1
- local n=0x100*byte(b1)+byte(b2)
- if n>=0x8000 then
- stack[top]=n-0xFFFF-1
- else
- stack[top]=n
- end
- end
- local p_long=P("\29")*C(1)*C(1)*C(1)*C(1)/function(b1,b2,b3,b4)
- top=top+1
- local n=0x1000000*byte(b1)+0x10000*byte(b2)+0x100*byte(b3)+byte(b4)
- if n>=0x8000000 then
- stack[top]=n-0xFFFFFFFF-1
- else
- stack[top]=n
- end
- end
- local p_unsupported=P(1)/function(detail)
- top=0
- end
- local p_dictionary=(
- p_byte+p_positive+p_negative+p_short+p_long+p_nibbles+p_single+p_double+p_unsupported
- )^1
- parsedictionaries=function(data,dictionaries)
- stack={}
- strings=data.strings
- for i=1,#dictionaries do
- top=0
- result={
- monospaced=false,
- italicangle=0,
- underlineposition=-100,
- underlinethickness=50,
- painttype=0,
- charstringtype=2,
- fontmatrix={ 0.001,0,0,0.001,0,0 },
- fontbbox={ 0,0,0,0 },
- strokewidth=0,
- charset=0,
- encoding=0,
- cid={
- fontversion=0,
- fontrevision=0,
- fonttype=0,
- count=8720,
- }
- }
- lpegmatch(p_dictionary,dictionaries[i])
- dictionaries[i]=result
- end
- result={}
- top=0
- stack={}
- end
- parseprivates=function(data,dictionaries)
- stack={}
- strings=data.strings
- for i=1,#dictionaries do
- local private=dictionaries[i].private
- if private and private.data then
- top=0
- result={
- forcebold=false,
- languagegroup=0,
- expansionfactor=0.06,
- initialrandomseed=0,
- subroutines=0,
- defaultwidthx=0,
- nominalwidthx=0,
- cid={
- },
- }
- lpegmatch(p_dictionary,private.data)
- private.data=result
- end
- end
- result={}
- top=0
- stack={}
- end
- local x=0
- local y=0
- local width=false
- local r=0
- local stems=0
- local globalbias=0
- local localbias=0
- local globals=false
- local locals=false
- local depth=1
- local xmin=0
- local xmax=0
- local ymin=0
- local ymax=0
- local checked=false
- local keepcurve=false
- local version=2
- local function showstate(where)
- report("%w%-10s : [%s] n=%i",depth*2,where,concat(stack," ",1,top),top)
- end
- local function showvalue(where,value,showstack)
- if showstack then
- report("%w%-10s : %s : [%s] n=%i",depth*2,where,tostring(value),concat(stack," ",1,top),top)
- else
- report("%w%-10s : %s",depth*2,where,tostring(value))
- end
- end
- local function moveto(x,y)
- if keepcurve then
- r=r+1
- result[r]={ x,y,"m" }
- end
- if checked then
- if x<xmin then xmin=x elseif x>xmax then xmax=x end
- if y<ymin then ymin=y elseif y>ymax then ymax=y end
- else
- xmin=x
- ymin=y
- xmax=x
- ymax=y
- checked=true
- end
- end
- local function lineto(x,y)
- if keepcurve then
- r=r+1
- result[r]={ x,y,"l" }
- end
- if checked then
- if x<xmin then xmin=x elseif x>xmax then xmax=x end
- if y<ymin then ymin=y elseif y>ymax then ymax=y end
- else
- xmin=x
- ymin=y
- xmax=x
- ymax=y
- checked=true
- end
- end
- local function curveto(x1,y1,x2,y2,x3,y3)
- if keepcurve then
- r=r+1
- result[r]={ x1,y1,x2,y2,x3,y3,"c" }
- end
- if checked then
- if x1<xmin then xmin=x1 elseif x1>xmax then xmax=x1 end
- if y1<ymin then ymin=y1 elseif y1>ymax then ymax=y1 end
- else
- xmin=x1
- ymin=y1
- xmax=x1
- ymax=y1
- checked=true
- end
- if x2<xmin then xmin=x2 elseif x2>xmax then xmax=x2 end
- if y2<ymin then ymin=y2 elseif y2>ymax then ymax=y2 end
- if x3<xmin then xmin=x3 elseif x3>xmax then xmax=x3 end
- if y3<ymin then ymin=y3 elseif y3>ymax then ymax=y3 end
- end
- local function rmoveto()
- if top>2 then
- if not width then
- width=stack[1]
- if trace_charstrings then
- showvalue("width",width)
- end
- end
- elseif not width then
- width=true
- end
- if trace_charstrings then
- showstate("rmoveto")
- end
- x=x+stack[top-1]
- y=y+stack[top]
- top=0
- moveto(x,y)
- end
- local function hmoveto()
- if top>1 then
- if not width then
- width=stack[1]
- if trace_charstrings then
- showvalue("width",width)
- end
- end
- elseif not width then
- width=true
- end
- if trace_charstrings then
- showstate("hmoveto")
- end
- x=x+stack[top]
- top=0
- moveto(x,y)
- end
- local function vmoveto()
- if top>1 then
- if not width then
- width=stack[1]
- if trace_charstrings then
- showvalue("width",width)
- end
- end
- elseif not width then
- width=true
- end
- if trace_charstrings then
- showstate("vmoveto")
- end
- y=y+stack[top]
- top=0
- moveto(x,y)
- end
- local function rlineto()
- if trace_charstrings then
- showstate("rlineto")
- end
- for i=1,top,2 do
- x=x+stack[i]
- y=y+stack[i+1]
- lineto(x,y)
- end
- top=0
- end
- local function xlineto(swap)
- for i=1,top do
- if swap then
- x=x+stack[i]
- swap=false
- else
- y=y+stack[i]
- swap=true
- end
- lineto(x,y)
- end
- top=0
- end
- local function hlineto()
- if trace_charstrings then
- showstate("hlineto")
- end
- xlineto(true)
- end
- local function vlineto()
- if trace_charstrings then
- showstate("vlineto")
- end
- xlineto(false)
- end
- local function rrcurveto()
- if trace_charstrings then
- showstate("rrcurveto")
- end
- for i=1,top,6 do
- local ax=x+stack[i]
- local ay=y+stack[i+1]
- local bx=ax+stack[i+2]
- local by=ay+stack[i+3]
- x=bx+stack[i+4]
- y=by+stack[i+5]
- curveto(ax,ay,bx,by,x,y)
- end
- top=0
- end
- local function hhcurveto()
- if trace_charstrings then
- showstate("hhcurveto")
- end
- local s=1
- if top%2~=0 then
- y=y+stack[1]
- s=2
- end
- for i=s,top,4 do
- local ax=x+stack[i]
- local ay=y
- local bx=ax+stack[i+1]
- local by=ay+stack[i+2]
- x=bx+stack[i+3]
- y=by
- curveto(ax,ay,bx,by,x,y)
- end
- top=0
- end
- local function vvcurveto()
- if trace_charstrings then
- showstate("vvcurveto")
- end
- local s=1
- local d=0
- if top%2~=0 then
- d=stack[1]
- s=2
- end
- for i=s,top,4 do
- local ax=x+d
- local ay=y+stack[i]
- local bx=ax+stack[i+1]
- local by=ay+stack[i+2]
- x=bx
- y=by+stack[i+3]
- curveto(ax,ay,bx,by,x,y)
- d=0
- end
- top=0
- end
- local function xxcurveto(swap)
- local last=top%4~=0 and stack[top]
- if last then
- top=top-1
- end
- local sw=swap
- for i=1,top,4 do
- local ax,ay,bx,by
- if swap then
- ax=x+stack[i]
- ay=y
- bx=ax+stack[i+1]
- by=ay+stack[i+2]
- y=by+stack[i+3]
- if last and i+3==top then
- x=bx+last
- else
- x=bx
- end
- swap=false
- else
- ax=x
- ay=y+stack[i]
- bx=ax+stack[i+1]
- by=ay+stack[i+2]
- x=bx+stack[i+3]
- if last and i+3==top then
- y=by+last
- else
- y=by
- end
- swap=true
- end
- curveto(ax,ay,bx,by,x,y)
- end
- top=0
- end
- local function hvcurveto()
- if trace_charstrings then
- showstate("hvcurveto")
- end
- xxcurveto(true)
- end
- local function vhcurveto()
- if trace_charstrings then
- showstate("vhcurveto")
- end
- xxcurveto(false)
- end
- local function rcurveline()
- if trace_charstrings then
- showstate("rcurveline")
- end
- for i=1,top-2,6 do
- local ax=x+stack[i]
- local ay=y+stack[i+1]
- local bx=ax+stack[i+2]
- local by=ay+stack[i+3]
- x=bx+stack[i+4]
- y=by+stack[i+5]
- curveto(ax,ay,bx,by,x,y)
- end
- x=x+stack[top-1]
- y=y+stack[top]
- lineto(x,y)
- top=0
- end
- local function rlinecurve()
- if trace_charstrings then
- showstate("rlinecurve")
- end
- if top>6 then
- for i=1,top-6,2 do
- x=x+stack[i]
- y=y+stack[i+1]
- lineto(x,y)
- end
- end
- local ax=x+stack[top-5]
- local ay=y+stack[top-4]
- local bx=ax+stack[top-3]
- local by=ay+stack[top-2]
- x=bx+stack[top-1]
- y=by+stack[top]
- curveto(ax,ay,bx,by,x,y)
- top=0
- end
- local function flex()
- if trace_charstrings then
- showstate("flex")
- end
- local ax=x+stack[1]
- local ay=y+stack[2]
- local bx=ax+stack[3]
- local by=ay+stack[4]
- local cx=bx+stack[5]
- local cy=by+stack[6]
- curveto(ax,ay,bx,by,cx,cy)
- local dx=cx+stack[7]
- local dy=cy+stack[8]
- local ex=dx+stack[9]
- local ey=dy+stack[10]
- x=ex+stack[11]
- y=ey+stack[12]
- curveto(dx,dy,ex,ey,x,y)
- top=0
- end
- local function hflex()
- if trace_charstrings then
- showstate("hflex")
- end
- local ax=x+stack[1]
- local ay=y
- local bx=ax+stack[2]
- local by=ay+stack[3]
- local cx=bx+stack[4]
- local cy=by
- curveto(ax,ay,bx,by,cx,cy)
- local dx=cx+stack[5]
- local dy=by
- local ex=dx+stack[6]
- local ey=y
- x=ex+stack[7]
- curveto(dx,dy,ex,ey,x,y)
- top=0
- end
- local function hflex1()
- if trace_charstrings then
- showstate("hflex1")
- end
- local ax=x+stack[1]
- local ay=y+stack[2]
- local bx=ax+stack[3]
- local by=ay+stack[4]
- local cx=bx+stack[5]
- local cy=by
- curveto(ax,ay,bx,by,cx,cy)
- local dx=cx+stack[6]
- local dy=by
- local ex=dx+stack[7]
- local ey=dy+stack[8]
- x=ex+stack[9]
- curveto(dx,dy,ex,ey,x,y)
- top=0
- end
- local function flex1()
- if trace_charstrings then
- showstate("flex1")
- end
- local ax=x+stack[1]
- local ay=y+stack[2]
- local bx=ax+stack[3]
- local by=ay+stack[4]
- local cx=bx+stack[5]
- local cy=by+stack[6]
- curveto(ax,ay,bx,by,cx,cy)
- local dx=cx+stack[7]
- local dy=cy+stack[8]
- local ex=dx+stack[9]
- local ey=dy+stack[10]
- if abs(ex-x)>abs(ey-y) then
- x=ex+stack[11]
- else
- y=ey+stack[11]
- end
- curveto(dx,dy,ex,ey,x,y)
- top=0
- end
- local function getstem()
- if top==0 then
- elseif top%2~=0 then
- if width then
- remove(stack,1)
- else
- width=remove(stack,1)
- if trace_charstrings then
- showvalue("width",width)
- end
- end
- top=top-1
- end
- if trace_charstrings then
- showstate("stem")
- end
- stems=stems+top/2
- top=0
- end
- local function getmask()
- if top==0 then
- elseif top%2~=0 then
- if width then
- remove(stack,1)
- else
- width=remove(stack,1)
- if trace_charstrings then
- showvalue("width",width)
- end
- end
- top=top-1
- end
- if trace_charstrings then
- showstate(operator==19 and "hintmark" or "cntrmask")
- end
- stems=stems+top/2
- top=0
- if stems==0 then
- elseif stems<=8 then
- return 1
- else
- return floor((stems+7)/8)
- end
- end
- local function unsupported(t)
- if trace_charstrings then
- showstate("unsupported "..t)
- end
- top=0
- end
- local function unsupportedsub(t)
- if trace_charstrings then
- showstate("unsupported sub "..t)
- end
- top=0
- end
- local function getstem3()
- if trace_charstrings then
- showstate("stem3")
- end
- top=0
- end
- local function divide()
- if version==1 then
- local d=stack[top]
- top=top-1
- stack[top]=stack[top]/d
- end
- end
- local function closepath()
- if version==1 then
- if trace_charstrings then
- showstate("closepath")
- end
- end
- top=0
- end
- local function hsbw()
- if version==1 then
- if trace_charstrings then
- showstate("dotsection")
- end
- width=stack[top]
- end
- top=0
- end
- local function seac()
- if version==1 then
- if trace_charstrings then
- showstate("seac")
- end
- end
- top=0
- end
- local function sbw()
- if version==1 then
- if trace_charstrings then
- showstate("sbw")
- end
- width=stack[top-1]
- end
- top=0
- end
- local function callothersubr()
- if version==1 then
- if trace_charstrings then
- showstate("callothersubr (unsupported)")
- end
- end
- top=0
- end
- local function pop()
- if version==1 then
- if trace_charstrings then
- showstate("pop (unsupported)")
- end
- top=top+1
- stack[top]=0
- else
- top=0
- end
- end
- local function setcurrentpoint()
- if version==1 then
- if trace_charstrings then
- showstate("pop (unsupported)")
- end
- x=x+stack[top-1]
- y=y+stack[top]
- end
- top=0
- end
- local actions={ [0]=unsupported,
- getstem,
- unsupported,
- getstem,
- vmoveto,
- rlineto,
- hlineto,
- vlineto,
- rrcurveto,
- unsupported,
- unsupported,
- unsupported,
- unsupported,
- hsbw,
- unsupported,
- unsupported,
- unsupported,
- unsupported,
- getstem,
- getmask,
- getmask,
- rmoveto,
- hmoveto,
- getstem,
- rcurveline,
- rlinecurve,
- vvcurveto,
- hhcurveto,
- unsupported,
- unsupported,
- vhcurveto,
- hvcurveto,
- }
- local subactions={
- [000]=dotsection,
- [001]=getstem3,
- [002]=getstem3,
- [006]=seac,
- [007]=sbw,
- [012]=divide,
- [016]=callothersubr,
- [017]=pop,
- [033]=setcurrentpoint,
- [034]=hflex,
- [035]=flex,
- [036]=hflex1,
- [037]=flex1,
- }
- local p_bytes=Ct((P(1)/byte)^0)
- local function call(scope,list,bias,process)
- depth=depth+1
- if top==0 then
- showstate(formatters["unknown %s call"](scope))
- top=0
- else
- local index=stack[top]+bias
- top=top-1
- if trace_charstrings then
- showvalue(scope,index,true)
- end
- local tab=list[index]
- if tab then
- if type(tab)=="string" then
- tab=lpegmatch(p_bytes,tab)
- list[index]=tab
- end
- process(tab)
- else
- showstate(formatters["unknown %s call %i"](scope,index))
- top=0
- end
- end
- depth=depth-1
- end
- local function process(tab)
- local i=1
- local n=#tab
- while i<=n do
- local t=tab[i]
- if t>=32 and t<=246 then
- top=top+1
- stack[top]=t-139
- i=i+1
- elseif t>=247 and t<=250 then
- top=top+1
- stack[top]=(t-247)*256+tab[i+1]+108
- i=i+2
- elseif t>=251 and t<=254 then
- top=top+1
- stack[top]=-(t-251)*256-tab[i+1]-108
- i=i+2
- elseif t==28 then
- top=top+1
- local n=0x100*tab[i+1]+tab[i+2]
- if n>=0x8000 then
- stack[top]=n-0xFFFF-1
- else
- stack[top]=n
- end
- i=i+3
- elseif t==255 then
- local n=0x100*tab[i+1]+tab[i+2]
- top=top+1
- if n>=0x8000 then
- stack[top]=n-0xFFFF-1+(0x100*tab[i+3]+tab[i+4])/0xFFFF
- else
- stack[top]=n+(0x100*tab[i+3]+tab[i+4])/0xFFFF
- end
- i=i+5
- elseif t==11 then
- if trace_charstrings then
- showstate("return")
- end
- return
- elseif t==10 then
- call("local",locals,localbias,process)
- i=i+1
- elseif t==14 then
- if width then
- elseif top>0 then
- width=stack[1]
- if trace_charstrings then
- showvalue("width",width)
- end
- else
- width=true
- end
- if trace_charstrings then
- showstate("endchar")
- end
- return
- elseif t==29 then
- call("global",globals,globalbias,process)
- i=i+1
- elseif t==12 then
- i=i+1
- local t=tab[i]
- local a=subactions[t]
- if a then
- a(t)
- else
- if trace_charstrings then
- showvalue("<subaction>",t)
- end
- top=0
- end
- i=i+1
- else
- local a=actions[t]
- if a then
- local s=a(t)
- if s then
- i=i+s
- end
- else
- if trace_charstrings then
- showvalue("<action>",t)
- end
- top=0
- end
- i=i+1
- end
- end
- end
- local function setbias(globals,locals)
- if version==1 then
- return
- false,
- false
- else
- local g,l=#globals,#locals
- return
- ((g<1240 and 107) or (g<33900 and 1131) or 32768)+1,
- ((l<1240 and 107) or (l<33900 and 1131) or 32768)+1
- end
- end
- parsecharstrings=function(data,glyphs,doshapes,tversion)
- local dictionary=data.dictionaries[1]
- local charstrings=dictionary.charstrings
- local charset=dictionary.charset
- local private=dictionary.private or { data={} }
- keepcurve=doshapes
- version=tversion
- stack={}
- glyphs=glyphs or {}
- strings=data.strings
- globals=data.routines or {}
- locals=dictionary.subroutines or {}
- globalbias,localbias=setbias(globals,locals)
- local nominalwidth=private.data.nominalwidthx or 0
- local defaultwidth=private.data.defaultwidthx or 0
- for i=1,#charstrings do
- local tab=charstrings[i]
- if type(tab)=="string" then
- tab=lpegmatch(p_bytes,tab)
- end
- local index=i-1
- x=0
- y=0
- width=false
- r=0
- top=0
- stems=0
- result={}
- xmin=0
- xmax=0
- ymin=0
- ymax=0
- checked=false
- if trace_charstrings then
- report("glyph: %i",index)
- report("data: % t",tab)
- end
- process(tab)
- local boundingbox={ round(xmin),round(ymin),round(xmax),round(ymax) }
- if width==true or width==false then
- width=defaultwidth
- else
- width=nominalwidth+width
- end
- local glyph=glyphs[index]
- if not glyph then
- glyphs[index]={
- segments=doshapes~=false and result or nil,
- boundingbox=boundingbox,
- width=width,
- name=charset[index],
- }
- else
- glyph.segments=doshapes~=false and result or nil
- glyph.boundingbox=boundingbox
- if not glyph.width then
- glyph.width=width
- end
- if charset and not glyph.name then
- glyph.name=charset[index]
- end
- end
- if trace_charstrings then
- report("width: %s",tostring(width))
- report("boundingbox: % t",boundingbox)
- end
- charstrings[i]=nil
- end
- return glyphs
- end
- parsecharstring=function(data,dictionary,tab,glyphs,index,doshapes,tversion)
- local private=dictionary.private
- keepcurve=doshapes
- version=tversion
- strings=data.strings
- locals=dictionary.subroutines or {}
- globals=data.routines or {}
- globalbias,localbias=setbias(globals,locals)
- local nominalwidth=private and private.data.nominalwidthx or 0
- local defaultwidth=private and private.data.defaultwidthx or 0
- if type(tab)=="string" then
- tab=lpegmatch(p_bytes,tab)
- end
- x=0
- y=0
- width=false
- r=0
- top=0
- stems=0
- result={}
- xmin=0
- xmax=0
- ymin=0
- ymax=0
- checked=false
- if trace_charstrings then
- report("glyph: %i",index)
- report("data: % t",tab)
- end
- process(tab)
- local boundingbox={ xmin,ymin,xmax,ymax }
- if width==true or width==false then
- width=defaultwidth
- else
- width=nominalwidth+width
- end
- index=index-1
- local glyph=glyphs[index]
- if not glyph then
- glyphs[index]={
- segments=doshapes~=false and result or nil,
- boundingbox=boundingbox,
- width=width,
- name=charset[index],
- }
- else
- glyph.segments=doshapes~=false and result or nil
- glyph.boundingbox=boundingbox
- if not glyph.width then
- glyph.width=width
- end
- if charset and not glyph.name then
- glyph.name=charset[index]
- end
- end
- if trace_charstrings then
- report("width: %s",tostring(width))
- report("boundingbox: % t",boundingbox)
- end
- end
- resetcharstrings=function()
- result={}
- top=0
- stack={}
- end
-end
-local function readglobals(f,data)
- local routines=readlengths(f)
- for i=1,#routines do
- routines[i]=readstring(f,routines[i])
- end
- data.routines=routines
-end
-local function readencodings(f,data)
- data.encodings={}
-end
-local function readcharsets(f,data,dictionary)
- local header=data.header
- local strings=data.strings
- local nofglyphs=data.nofglyphs
- local charsetoffset=dictionary.charset
- if charsetoffset~=0 then
- setposition(f,header.offset+charsetoffset)
- local format=readbyte(f)
- local charset={ [0]=".notdef" }
- dictionary.charset=charset
- if format==0 then
- for i=1,nofglyphs do
- charset[i]=strings[readushort(f)]
- end
- elseif format==1 or format==2 then
- local readcount=format==1 and readbyte or readushort
- local i=1
- while i<=nofglyphs do
- local sid=readushort(f)
- local n=readcount(f)
- for s=sid,sid+n do
- charset[i]=strings[s]
- i=i+1
- if i>nofglyphs then
- break
- end
- end
- end
- else
- report("cff parser: unsupported charset format %a",format)
- end
- end
-end
-local function readprivates(f,data)
- local header=data.header
- local dictionaries=data.dictionaries
- local private=dictionaries[1].private
- if private then
- setposition(f,header.offset+private.offset)
- private.data=readstring(f,private.size)
- end
-end
-local function readlocals(f,data,dictionary)
- local header=data.header
- local private=dictionary.private
- if private then
- local subroutineoffset=private.data.subroutines
- if subroutineoffset~=0 then
- setposition(f,header.offset+private.offset+subroutineoffset)
- local subroutines=readlengths(f)
- for i=1,#subroutines do
- subroutines[i]=readstring(f,subroutines[i])
- end
- dictionary.subroutines=subroutines
- private.data.subroutines=nil
- else
- dictionary.subroutines={}
- end
- else
- dictionary.subroutines={}
- end
-end
-local function readcharstrings(f,data)
- local header=data.header
- local dictionaries=data.dictionaries
- local dictionary=dictionaries[1]
- local type=dictionary.charstringtype
- local offset=dictionary.charstrings
- if type==2 then
- setposition(f,header.offset+offset)
- local charstrings=readlengths(f)
- local nofglyphs=#charstrings
- for i=1,nofglyphs do
- charstrings[i]=readstring(f,charstrings[i])
- end
- data.nofglyphs=nofglyphs
- dictionary.charstrings=charstrings
- else
- report("unsupported charstr type %i",type)
- data.nofglyphs=0
- dictionary.charstrings={}
- end
-end
-local function readcidprivates(f,data)
- local header=data.header
- local dictionaries=data.dictionaries[1].cid.dictionaries
- for i=1,#dictionaries do
- local dictionary=dictionaries[i]
- local private=dictionary.private
- if private then
- setposition(f,header.offset+private.offset)
- private.data=readstring(f,private.size)
- end
- end
- parseprivates(data,dictionaries)
-end
-local function readnoselect(f,data,glyphs,doshapes,version)
- local dictionaries=data.dictionaries
- local dictionary=dictionaries[1]
- readglobals(f,data)
- readcharstrings(f,data)
- readencodings(f,data)
- readcharsets(f,data,dictionary)
- readprivates(f,data)
- parseprivates(data,data.dictionaries)
- readlocals(f,data,dictionary)
- parsecharstrings(data,glyphs,doshapes,version)
- resetcharstrings()
-end
-readers.parsecharstrings=parsecharstrings
-local function readfdselect(f,data,glyphs,doshapes,version)
- local header=data.header
- local dictionaries=data.dictionaries
- local dictionary=dictionaries[1]
- local cid=dictionary.cid
- local cidselect=cid and cid.fdselect
- readglobals(f,data)
- readcharstrings(f,data)
- readencodings(f,data)
- local charstrings=dictionary.charstrings
- local fdindex={}
- local nofglyphs=data.nofglyphs
- local maxindex=-1
- setposition(f,header.offset+cidselect)
- local format=readbyte(f)
- if format==1 then
- for i=0,nofglyphs do
- local index=readbyte(i)
- fdindex[i]=index
- if index>maxindex then
- maxindex=index
- end
- end
- elseif format==3 then
- local nofranges=readushort(f)
- local first=readushort(f)
- local index=readbyte(f)
- while true do
- local last=readushort(f)
- if index>maxindex then
- maxindex=index
- end
- for i=first,last do
- fdindex[i]=index
- end
- if last>=nofglyphs then
- break
- else
- first=last+1
- index=readbyte(f)
- end
- end
- else
- end
- if maxindex>=0 then
- local cidarray=cid.fdarray
- setposition(f,header.offset+cidarray)
- local dictionaries=readlengths(f)
- for i=1,#dictionaries do
- dictionaries[i]=readstring(f,dictionaries[i])
- end
- parsedictionaries(data,dictionaries)
- cid.dictionaries=dictionaries
- readcidprivates(f,data)
- for i=1,#dictionaries do
- readlocals(f,data,dictionaries[i])
- end
- for i=1,#charstrings do
- parsecharstring(data,dictionaries[fdindex[i]+1],charstrings[i],glyphs,i,doshapes,version)
- end
- resetcharstrings()
- end
-end
-function readers.cff(f,fontdata,specification)
- if specification.details then
- local datatable=fontdata.tables.cff
- if datatable then
- local offset=datatable.offset
- local glyphs=fontdata.glyphs
- if not f then
- report("invalid filehandle")
- return
- end
- if offset then
- setposition(f,offset)
- end
- local header=readheader(f)
- if header.major>1 then
- report("version mismatch")
- return
- end
- local names=readfontnames(f)
- local dictionaries=readtopdictionaries(f)
- local strings=readstrings(f)
- local data={
- header=header,
- names=names,
- dictionaries=dictionaries,
- strings=strings,
- nofglyphs=fontdata.nofglyphs,
- }
- parsedictionaries(data,data.dictionaries)
- local d=dictionaries[1]
- local c=d.cid
- fontdata.cffinfo={
- familynamename=d.familyname,
- fullname=d.fullname,
- boundingbox=d.boundingbox,
- weight=d.weight,
- italicangle=d.italicangle,
- underlineposition=d.underlineposition,
- underlinethickness=d.underlinethickness,
- monospaced=d.monospaced,
- }
- fontdata.cidinfo=c and {
- registry=c.registry,
- ordering=c.ordering,
- supplement=c.supplement,
- }
- if not specification.glyphs then
- else
- local cid=d.cid
- if cid and cid.fdselect then
- readfdselect(f,data,glyphs,specification.shapes or false)
- else
- readnoselect(f,data,glyphs,specification.shapes or false)
- end
- end
- end
- end
-end
-
-end --- [luaotfload, fontloader-2017-02-11.lua scope for “font-cff”] ---
-
-
-do --- [luaotfload, fontloader-2017-02-11.lua scope for “font-ttf” e0893de6d0f3f421ee4386fa90429db8] ---
-
-if not modules then modules={} end modules ['font-ttf']={
- version=1.001,
- comment="companion to font-ini.mkiv",
- author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright="PRAGMA ADE / ConTeXt Development Team",
- license="see context related readme files"
-}
-local next,type,unpack=next,type,unpack
-local bittest=bit32.btest
-local sqrt=math.sqrt
-local report=logs.reporter("otf reader","ttf")
-local readers=fonts.handlers.otf.readers
-local streamreader=readers.streamreader
-local setposition=streamreader.setposition
-local getposition=streamreader.getposition
-local skipbytes=streamreader.skip
-local readbyte=streamreader.readcardinal1
-local readushort=streamreader.readcardinal2
-local readulong=streamreader.readcardinal4
-local readchar=streamreader.readinteger1
-local readshort=streamreader.readinteger2
-local read2dot14=streamreader.read2dot14
-local function mergecomposites(glyphs,shapes)
- local function merge(index,shape,components)
- local contours={}
- local nofcontours=0
- for i=1,#components do
- local component=components[i]
- local subindex=component.index
- local subshape=shapes[subindex]
- local subcontours=subshape.contours
- if not subcontours then
- local subcomponents=subshape.components
- if subcomponents then
- subcontours=merge(subindex,subshape,subcomponents)
- end
- end
- if subcontours then
- local matrix=component.matrix
- local xscale=matrix[1]
- local xrotate=matrix[2]
- local yrotate=matrix[3]
- local yscale=matrix[4]
- local xoffset=matrix[5]
- local yoffset=matrix[6]
- for i=1,#subcontours do
- local points=subcontours[i]
- local result={}
- for i=1,#points do
- local p=points[i]
- local x=p[1]
- local y=p[2]
- result[i]={
- xscale*x+xrotate*y+xoffset,
- yscale*y+yrotate*x+yoffset,
- p[3]
- }
- end
- nofcontours=nofcontours+1
- contours[nofcontours]=result
- end
- else
- report("missing contours composite %s, component %s of %s, glyph %s",index,i,#components,subindex)
- end
- end
- shape.contours=contours
- shape.components=nil
- return contours
- end
- for index=1,#glyphs do
- local shape=shapes[index]
- local components=shape.components
- if components then
- merge(index,shape,components)
- end
- end
-end
-local function readnothing(f,nofcontours)
- return {
- type="nothing",
- }
-end
-local function curveto(m_x,m_y,l_x,l_y,r_x,r_y)
- return {
- l_x+2/3*(m_x-l_x),l_y+2/3*(m_y-l_y),
- r_x+2/3*(m_x-r_x),r_y+2/3*(m_y-r_y),
- r_x,r_y,"c"
- }
-end
-local function contours2outlines(glyphs,shapes)
- local quadratic=true
- for index=1,#glyphs do
- local glyph=glyphs[index]
- local shape=shapes[index]
- local contours=shape.contours
- if contours then
- local nofcontours=#contours
- local segments={}
- local nofsegments=0
- glyph.segments=segments
- if nofcontours>0 then
- for i=1,nofcontours do
- local contour=contours[i]
- local nofcontour=#contour
- if nofcontour>0 then
- local first_pt=contour[1]
- local first_on=first_pt[3]
- if nofcontour==1 then
- first_pt[3]="m"
- nofsegments=nofsegments+1
- segments[nofsegments]=first_pt
- else
- local first_on=first_pt[3]
- local last_pt=contour[nofcontour]
- local last_on=last_pt[3]
- local start=1
- local control_pt=false
- if first_on then
- start=2
- else
- if last_on then
- first_pt=last_pt
- else
- first_pt={ (first_pt[1]+last_pt[1])/2,(first_pt[2]+last_pt[2])/2,false }
- end
- control_pt=first_pt
- end
- nofsegments=nofsegments+1
- segments[nofsegments]={ first_pt[1],first_pt[2],"m" }
- local previous_pt=first_pt
- for i=start,nofcontour do
- local current_pt=contour[i]
- local current_on=current_pt[3]
- local previous_on=previous_pt[3]
- if previous_on then
- if current_on then
- nofsegments=nofsegments+1
- segments[nofsegments]={ current_pt[1],current_pt[2],"l" }
- else
- control_pt=current_pt
- end
- elseif current_on then
- local ps=segments[nofsegments]
- nofsegments=nofsegments+1
- if quadratic then
- segments[nofsegments]={ control_pt[1],control_pt[2],current_pt[1],current_pt[2],"q" }
- else
- local p=segments[nofsegments-1] local n=#p
- segments[nofsegments]=curveto(control_pt[1],control_pt[2],p[n-2],p[n-1],current_pt[1],current_pt[2])
- end
- control_pt=false
- else
- nofsegments=nofsegments+1
- local halfway_x=(previous_pt[1]+current_pt[1])/2
- local halfway_y=(previous_pt[2]+current_pt[2])/2
- if quadratic then
- segments[nofsegments]={ control_pt[1],control_pt[2],halfway_x,halfway_y,"q" }
- else
- local p=segments[nofsegments-1] local n=#p
- segments[nofsegments]=curveto(control_pt[1],control_pt[2],p[n-2],p[n-1],halfway_x,halfway_y)
- end
- control_pt=current_pt
- end
- previous_pt=current_pt
- end
- if first_pt==last_pt then
- else
- nofsegments=nofsegments+1
- if not control_pt then
- segments[nofsegments]={ first_pt[1],first_pt[2],"l" }
- elseif quadratic then
- segments[nofsegments]={ control_pt[1],control_pt[2],first_pt[1],first_pt[2],"q" }
- else
- local p=last_pt local n=#p
- segments[nofsegments]=curveto(control_pt[1],control_pt[2],p[n-2],p[n-1],first_pt[1],first_pt[2])
- end
- end
- end
- end
- end
- end
- end
- end
-end
-local function readglyph(f,nofcontours)
- local points={}
- local endpoints={}
- local instructions={}
- local flags={}
- for i=1,nofcontours do
- endpoints[i]=readshort(f)+1
- end
- local nofpoints=endpoints[nofcontours]
- local nofinstructions=readushort(f)
- skipbytes(f,nofinstructions)
- local i=1
- while i<=nofpoints do
- local flag=readbyte(f)
- flags[i]=flag
- if bittest(flag,0x0008) then
- for j=1,readbyte(f) do
- i=i+1
- flags[i]=flag
- end
- end
- i=i+1
- end
- local x=0
- for i=1,nofpoints do
- local flag=flags[i]
- local short=bittest(flag,0x0002)
- local same=bittest(flag,0x0010)
- if short then
- if same then
- x=x+readbyte(f)
- else
- x=x-readbyte(f)
- end
- elseif same then
- else
- x=x+readshort(f)
- end
- points[i]={ x,y,bittest(flag,0x0001) }
- end
- local y=0
- for i=1,nofpoints do
- local flag=flags[i]
- local short=bittest(flag,0x0004)
- local same=bittest(flag,0x0020)
- if short then
- if same then
- y=y+readbyte(f)
- else
- y=y-readbyte(f)
- end
- elseif same then
- else
- y=y+readshort(f)
- end
- points[i][2]=y
- end
- local first=1
- for i=1,#endpoints do
- local last=endpoints[i]
- endpoints[i]={ unpack(points,first,last) }
- first=last+1
- end
- return {
- type="glyph",
- contours=endpoints,
- }
-end
-local function readcomposite(f)
- local components={}
- local nofcomponents=0
- local instructions=false
- while true do
- local flags=readushort(f)
- local index=readushort(f)
- local f_xyarg=bittest(flags,0x0002)
- local f_offset=bittest(flags,0x0800)
- local xscale=1
- local xrotate=0
- local yrotate=0
- local yscale=1
- local xoffset=0
- local yoffset=0
- local base=false
- local reference=false
- if f_xyarg then
- if bittest(flags,0x0001) then
- xoffset=readshort(f)
- yoffset=readshort(f)
- else
- xoffset=readchar(f)
- yoffset=readchar(f)
- end
- else
- if bittest(flags,0x0001) then
- base=readshort(f)
- reference=readshort(f)
- else
- base=readchar(f)
- reference=readchar(f)
- end
- end
- if bittest(flags,0x0008) then
- xscale=read2dot14(f)
- yscale=xscale
- if f_xyarg and f_offset then
- xoffset=xoffset*xscale
- yoffset=yoffset*yscale
- end
- elseif bittest(flags,0x0040) then
- xscale=read2dot14(f)
- yscale=read2dot14(f)
- if f_xyarg and f_offset then
- xoffset=xoffset*xscale
- yoffset=yoffset*yscale
- end
- elseif bittest(flags,0x0080) then
- xscale=read2dot14(f)
- xrotate=read2dot14(f)
- yrotate=read2dot14(f)
- yscale=read2dot14(f)
- if f_xyarg and f_offset then
- xoffset=xoffset*sqrt(xscale^2+xrotate^2)
- yoffset=yoffset*sqrt(yrotate^2+yscale^2)
- end
- end
- nofcomponents=nofcomponents+1
- components[nofcomponents]={
- index=index,
- usemine=bittest(flags,0x0200),
- round=bittest(flags,0x0006),
- base=base,
- reference=reference,
- matrix={ xscale,xrotate,yrotate,yscale,xoffset,yoffset },
- }
- if bittest(flags,0x0100) then
- instructions=true
- end
- if not bittest(flags,0x0020) then
- break
- end
- end
- return {
- type="composite",
- components=components,
- }
-end
-function readers.loca(f,fontdata,specification)
- if specification.glyphs then
- local datatable=fontdata.tables.loca
- if datatable then
- local offset=fontdata.tables.glyf.offset
- local format=fontdata.fontheader.indextolocformat
- local locations={}
- setposition(f,datatable.offset)
- if format==1 then
- local nofglyphs=datatable.length/4-1
- -1
- for i=0,nofglyphs do
- locations[i]=offset+readulong(f)
- end
- fontdata.nofglyphs=nofglyphs
- else
- local nofglyphs=datatable.length/2-1
- -1
- for i=0,nofglyphs do
- locations[i]=offset+readushort(f)*2
- end
- fontdata.nofglyphs=nofglyphs
- end
- fontdata.locations=locations
- end
- end
-end
-function readers.glyf(f,fontdata,specification)
- if specification.glyphs then
- local datatable=fontdata.tables.glyf
- if datatable then
- local locations=fontdata.locations
- if locations then
- local glyphs=fontdata.glyphs
- local nofglyphs=fontdata.nofglyphs
- local filesize=fontdata.filesize
- local nothing={ 0,0,0,0 }
- local shapes={}
- local loadshapes=specification.shapes
- for index=0,nofglyphs do
- local location=locations[index]
- if location>=filesize then
- report("discarding %s glyphs due to glyph location bug",nofglyphs-index+1)
- fontdata.nofglyphs=index-1
- fontdata.badfont=true
- break
- elseif location>0 then
- setposition(f,location)
- local nofcontours=readshort(f)
- glyphs[index].boundingbox={
- readshort(f),
- readshort(f),
- readshort(f),
- readshort(f),
- }
- if not loadshapes then
- elseif nofcontours==0 then
- shapes[index]=readnothing(f,nofcontours)
- elseif nofcontours>0 then
- shapes[index]=readglyph(f,nofcontours)
- else
- shapes[index]=readcomposite(f,nofcontours)
- end
- else
- if loadshapes then
- shapes[index]={}
- end
- glyphs[index].boundingbox=nothing
- end
- end
- if loadshapes then
- mergecomposites(glyphs,shapes)
- contours2outlines(glyphs,shapes)
- end
- end
- end
- end
-end
-
-end --- [luaotfload, fontloader-2017-02-11.lua scope for “font-ttf”] ---
-
-
-do --- [luaotfload, fontloader-2017-02-11.lua scope for “font-dsp” 4a5266ada979d5c2d48867dc3ffaefea] ---
-
-if not modules then modules={} end modules ['font-dsp']={
- version=1.001,
- comment="companion to font-ini.mkiv",
- author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright="PRAGMA ADE / ConTeXt Development Team",
- license="see context related readme files"
-}
-local next,type=next,type
-local bittest=bit32.btest
-local rshift=bit32.rshift
-local concat=table.concat
-local lower=string.lower
-local copy=table.copy
-local sub=string.sub
-local strip=string.strip
-local tohash=table.tohash
-local reversed=table.reversed
-local setmetatableindex=table.setmetatableindex
-local formatters=string.formatters
-local sortedkeys=table.sortedkeys
-local sortedhash=table.sortedhash
-local report=logs.reporter("otf reader")
-local readers=fonts.handlers.otf.readers
-local streamreader=readers.streamreader
-local setposition=streamreader.setposition
-local getposition=streamreader.getposition
-local skipshort=streamreader.skipshort
-local readushort=streamreader.readcardinal2
-local readulong=streamreader.readcardinal4
-local readshort=streamreader.readinteger2
-local readfword=readshort
-local readstring=streamreader.readstring
-local readtag=streamreader.readtag
-local readbytes=streamreader.readbytes
-local gsubhandlers={}
-local gposhandlers={}
-local lookupidoffset=-1
-local classes={
- "base",
- "ligature",
- "mark",
- "component",
-}
-local gsubtypes={
- "single",
- "multiple",
- "alternate",
- "ligature",
- "context",
- "chainedcontext",
- "extension",
- "reversechainedcontextsingle",
-}
-local gpostypes={
- "single",
- "pair",
- "cursive",
- "marktobase",
- "marktoligature",
- "marktomark",
- "context",
- "chainedcontext",
- "extension",
-}
-local chaindirections={
- context=0,
- chainedcontext=1,
- reversechainedcontextsingle=-1,
-}
-local lookupnames={
- gsub={
- single="gsub_single",
- multiple="gsub_multiple",
- alternate="gsub_alternate",
- ligature="gsub_ligature",
- context="gsub_context",
- chainedcontext="gsub_contextchain",
- reversechainedcontextsingle="gsub_reversecontextchain",
- },
- gpos={
- single="gpos_single",
- pair="gpos_pair",
- cursive="gpos_cursive",
- marktobase="gpos_mark2base",
- marktoligature="gpos_mark2ligature",
- marktomark="gpos_mark2mark",
- context="gpos_context",
- chainedcontext="gpos_contextchain",
- }
-}
-local lookupflags=setmetatableindex(function(t,k)
- local v={
- bittest(k,0x0008) and true or false,
- bittest(k,0x0004) and true or false,
- bittest(k,0x0002) and true or false,
- bittest(k,0x0001) and true or false,
- }
- t[k]=v
- return v
-end)
-local function readcoverage(f,offset,simple)
- setposition(f,offset)
- local coverageformat=readushort(f)
- local coverage={}
- if coverageformat==1 then
- local nofcoverage=readushort(f)
- if simple then
- for i=1,nofcoverage do
- coverage[i]=readushort(f)
- end
- else
- for i=0,nofcoverage-1 do
- coverage[readushort(f)]=i
- end
- end
- elseif coverageformat==2 then
- local nofranges=readushort(f)
- local n=simple and 1 or 0
- for i=1,nofranges do
- local firstindex=readushort(f)
- local lastindex=readushort(f)
- local coverindex=readushort(f)
- if simple then
- for i=firstindex,lastindex do
- coverage[n]=i
- n=n+1
- end
- else
- for i=firstindex,lastindex do
- coverage[i]=n
- n=n+1
- end
- end
- end
- else
- report("unknown coverage format %a ",coverageformat)
- end
- return coverage
-end
-local function readclassdef(f,offset,preset)
- setposition(f,offset)
- local classdefformat=readushort(f)
- local classdef={}
- if type(preset)=="number" then
- for k=0,preset-1 do
- classdef[k]=1
- end
- end
- if classdefformat==1 then
- local index=readushort(f)
- local nofclassdef=readushort(f)
- for i=1,nofclassdef do
- classdef[index]=readushort(f)+1
- index=index+1
- end
- elseif classdefformat==2 then
- local nofranges=readushort(f)
- local n=0
- for i=1,nofranges do
- local firstindex=readushort(f)
- local lastindex=readushort(f)
- local class=readushort(f)+1
- for i=firstindex,lastindex do
- classdef[i]=class
- end
- end
- else
- report("unknown classdef format %a ",classdefformat)
- end
- if type(preset)=="table" then
- for k in next,preset do
- if not classdef[k] then
- classdef[k]=1
- end
- end
- end
- return classdef
-end
-local function classtocoverage(defs)
- if defs then
- local list={}
- for index,class in next,defs do
- local c=list[class]
- if c then
- c[#c+1]=index
- else
- list[class]={ index }
- end
- end
- return list
- end
-end
-local function readposition(f,format)
- if format==0 then
- return nil
- end
- local x=bittest(format,0x0001) and readshort(f) or 0
- local y=bittest(format,0x0002) and readshort(f) or 0
- local h=bittest(format,0x0004) and readshort(f) or 0
- local v=bittest(format,0x0008) and readshort(f) or 0
- if x==0 and y==0 and h==0 and v==0 then
- return nil
- else
- return { x,y,h,v }
- end
-end
-local function readanchor(f,offset)
- if not offset or offset==0 then
- return nil
- end
- setposition(f,offset)
- local format=readshort(f)
- if format==0 then
- report("invalid anchor format %i @ position %i",format,offset)
- return false
- elseif format>3 then
- report("unsupported anchor format %i @ position %i",format,offset)
- return false
- end
- return { readshort(f),readshort(f) }
-end
-local function readfirst(f,offset)
- if offset then
- setposition(f,offset)
- end
- return { readushort(f) }
-end
-local function readarray(f,offset,first)
- if offset then
- setposition(f,offset)
- end
- local n=readushort(f)
- if first then
- local t={ first }
- for i=2,n do
- t[i]=readushort(f)
- end
- return t,n
- elseif n>0 then
- local t={}
- for i=1,n do
- t[i]=readushort(f)
- end
- return t,n
- end
-end
-local function readcoveragearray(f,offset,t,simple)
- if not t then
- return nil
- end
- local n=#t
- if n==0 then
- return nil
- end
- for i=1,n do
- t[i]=readcoverage(f,offset+t[i],simple)
- end
- return t
-end
-local function covered(subset,all)
- local used,u
- for i=1,#subset do
- local s=subset[i]
- if all[s] then
- if used then
- u=u+1
- used[u]=s
- else
- u=1
- used={ s }
- end
- end
- end
- return used
-end
-local function readlookuparray(f,noflookups,nofcurrent)
- local lookups={}
- if noflookups>0 then
- local length=0
- for i=1,noflookups do
- local index=readushort(f)+1
- if index>length then
- length=index
- end
- lookups[index]=readushort(f)+1
- end
- for index=1,length do
- if not lookups[index] then
- lookups[index]=false
- end
- end
- end
- return lookups
-end
-local function unchainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,what)
- local tableoffset=lookupoffset+offset
- setposition(f,tableoffset)
- local subtype=readushort(f)
- if subtype==1 then
- local coverage=readushort(f)
- local subclasssets=readarray(f)
- local rules={}
- if subclasssets then
- coverage=readcoverage(f,tableoffset+coverage,true)
- for i=1,#subclasssets do
- local offset=subclasssets[i]
- if offset>0 then
- local firstcoverage=coverage[i]
- local rulesoffset=tableoffset+offset
- local subclassrules=readarray(f,rulesoffset)
- for rule=1,#subclassrules do
- setposition(f,rulesoffset+subclassrules[rule])
- local nofcurrent=readushort(f)
- local noflookups=readushort(f)
- local current={ { firstcoverage } }
- for i=2,nofcurrent do
- current[i]={ readushort(f) }
- end
- local lookups=readlookuparray(f,noflookups,nofcurrent)
- rules[#rules+1]={
- current=current,
- lookups=lookups
- }
- end
- end
- end
- else
- report("empty subclassset in %a subtype %i","unchainedcontext",subtype)
- end
- return {
- format="glyphs",
- rules=rules,
- }
- elseif subtype==2 then
- local coverage=readushort(f)
- local currentclassdef=readushort(f)
- local subclasssets=readarray(f)
- local rules={}
- if subclasssets then
- coverage=readcoverage(f,tableoffset+coverage)
- currentclassdef=readclassdef(f,tableoffset+currentclassdef,coverage)
- local currentclasses=classtocoverage(currentclassdef,fontdata.glyphs)
- for class=1,#subclasssets do
- local offset=subclasssets[class]
- if offset>0 then
- local firstcoverage=currentclasses[class]
- if firstcoverage then
- firstcoverage=covered(firstcoverage,coverage)
- if firstcoverage then
- local rulesoffset=tableoffset+offset
- local subclassrules=readarray(f,rulesoffset)
- for rule=1,#subclassrules do
- setposition(f,rulesoffset+subclassrules[rule])
- local nofcurrent=readushort(f)
- local noflookups=readushort(f)
- local current={ firstcoverage }
- for i=2,nofcurrent do
- current[i]=currentclasses[readushort(f)+1]
- end
- local lookups=readlookuparray(f,noflookups,nofcurrent)
- rules[#rules+1]={
- current=current,
- lookups=lookups
- }
- end
- else
- report("no coverage")
- end
- else
- report("no coverage class")
- end
- end
- end
- else
- report("empty subclassset in %a subtype %i","unchainedcontext",subtype)
- end
- return {
- format="class",
- rules=rules,
- }
- elseif subtype==3 then
- local current=readarray(f)
- local noflookups=readushort(f)
- local lookups=readlookuparray(f,noflookups,#current)
- current=readcoveragearray(f,tableoffset,current,true)
- return {
- format="coverage",
- rules={
- {
- current=current,
- lookups=lookups,
- }
- }
- }
- else
- report("unsupported subtype %a in %a %s",subtype,"unchainedcontext",what)
- end
-end
-local function chainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,what)
- local tableoffset=lookupoffset+offset
- setposition(f,tableoffset)
- local subtype=readushort(f)
- if subtype==1 then
- local coverage=readushort(f)
- local subclasssets=readarray(f)
- local rules={}
- if subclasssets then
- coverage=readcoverage(f,tableoffset+coverage,true)
- for i=1,#subclasssets do
- local offset=subclasssets[i]
- if offset>0 then
- local firstcoverage=coverage[i]
- local rulesoffset=tableoffset+offset
- local subclassrules=readarray(f,rulesoffset)
- for rule=1,#subclassrules do
- setposition(f,rulesoffset+subclassrules[rule])
- local nofbefore=readushort(f)
- local before
- if nofbefore>0 then
- before={}
- for i=1,nofbefore do
- before[i]={ readushort(f) }
- end
- end
- local nofcurrent=readushort(f)
- local current={ { firstcoverage } }
- for i=2,nofcurrent do
- current[i]={ readushort(f) }
- end
- local nofafter=readushort(f)
- local after
- if nofafter>0 then
- after={}
- for i=1,nofafter do
- after[i]={ readushort(f) }
- end
- end
- local noflookups=readushort(f)
- local lookups=readlookuparray(f,noflookups,nofcurrent)
- rules[#rules+1]={
- before=before,
- current=current,
- after=after,
- lookups=lookups,
- }
- end
- end
- end
- else
- report("empty subclassset in %a subtype %i","chainedcontext",subtype)
- end
- return {
- format="glyphs",
- rules=rules,
- }
- elseif subtype==2 then
- local coverage=readushort(f)
- local beforeclassdef=readushort(f)
- local currentclassdef=readushort(f)
- local afterclassdef=readushort(f)
- local subclasssets=readarray(f)
- local rules={}
- if subclasssets then
- local coverage=readcoverage(f,tableoffset+coverage)
- local beforeclassdef=readclassdef(f,tableoffset+beforeclassdef,nofglyphs)
- local currentclassdef=readclassdef(f,tableoffset+currentclassdef,coverage)
- local afterclassdef=readclassdef(f,tableoffset+afterclassdef,nofglyphs)
- local beforeclasses=classtocoverage(beforeclassdef,fontdata.glyphs)
- local currentclasses=classtocoverage(currentclassdef,fontdata.glyphs)
- local afterclasses=classtocoverage(afterclassdef,fontdata.glyphs)
- for class=1,#subclasssets do
- local offset=subclasssets[class]
- if offset>0 then
- local firstcoverage=currentclasses[class]
- if firstcoverage then
- firstcoverage=covered(firstcoverage,coverage)
- if firstcoverage then
- local rulesoffset=tableoffset+offset
- local subclassrules=readarray(f,rulesoffset)
- for rule=1,#subclassrules do
- setposition(f,rulesoffset+subclassrules[rule])
- local nofbefore=readushort(f)
- local before
- if nofbefore>0 then
- before={}
- for i=1,nofbefore do
- before[i]=beforeclasses[readushort(f)+1]
- end
- end
- local nofcurrent=readushort(f)
- local current={ firstcoverage }
- for i=2,nofcurrent do
- current[i]=currentclasses[readushort(f)+1]
- end
- local nofafter=readushort(f)
- local after
- if nofafter>0 then
- after={}
- for i=1,nofafter do
- after[i]=afterclasses[readushort(f)+1]
- end
- end
- local noflookups=readushort(f)
- local lookups=readlookuparray(f,noflookups,nofcurrent)
- rules[#rules+1]={
- before=before,
- current=current,
- after=after,
- lookups=lookups,
- }
- end
- else
- report("no coverage")
- end
- else
- report("class is not covered")
- end
- end
- end
- else
- report("empty subclassset in %a subtype %i","chainedcontext",subtype)
- end
- return {
- format="class",
- rules=rules,
- }
- elseif subtype==3 then
- local before=readarray(f)
- local current=readarray(f)
- local after=readarray(f)
- local noflookups=readushort(f)
- local lookups=readlookuparray(f,noflookups,#current)
- before=readcoveragearray(f,tableoffset,before,true)
- current=readcoveragearray(f,tableoffset,current,true)
- after=readcoveragearray(f,tableoffset,after,true)
- return {
- format="coverage",
- rules={
- {
- before=before,
- current=current,
- after=after,
- lookups=lookups,
- }
- }
- }
- else
- report("unsupported subtype %a in %a %s",subtype,"chainedcontext",what)
- end
-end
-local function extension(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,types,handlers,what)
- local tableoffset=lookupoffset+offset
- setposition(f,tableoffset)
- local subtype=readushort(f)
- if subtype==1 then
- local lookuptype=types[readushort(f)]
- local faroffset=readulong(f)
- local handler=handlers[lookuptype]
- if handler then
- return handler(f,fontdata,lookupid,tableoffset+faroffset,0,glyphs,nofglyphs),lookuptype
- else
- report("no handler for lookuptype %a subtype %a in %s %s",lookuptype,subtype,what,"extension")
- end
- else
- report("unsupported subtype %a in %s %s",subtype,what,"extension")
- end
-end
-function gsubhandlers.single(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs)
- local tableoffset=lookupoffset+offset
- setposition(f,tableoffset)
- local subtype=readushort(f)
- if subtype==1 then
- local coverage=readushort(f)
- local delta=readshort(f)
- local coverage=readcoverage(f,tableoffset+coverage)
- for index in next,coverage do
- local newindex=index+delta
- if index>nofglyphs or newindex>nofglyphs then
- report("invalid index in %s format %i: %i -> %i (max %i)","single",subtype,index,newindex,nofglyphs)
- coverage[index]=nil
- else
- coverage[index]=newindex
- end
- end
- return {
- coverage=coverage
- }
- elseif subtype==2 then
- local coverage=readushort(f)
- local nofreplacements=readushort(f)
- local replacements={}
- for i=1,nofreplacements do
- replacements[i]=readushort(f)
- end
- local coverage=readcoverage(f,tableoffset+coverage)
- for index,newindex in next,coverage do
- newindex=newindex+1
- if index>nofglyphs or newindex>nofglyphs then
- report("invalid index in %s format %i: %i -> %i (max %i)","single",subtype,index,newindex,nofglyphs)
- coverage[index]=nil
- else
- coverage[index]=replacements[newindex]
- end
- end
- return {
- coverage=coverage
- }
- else
- report("unsupported subtype %a in %a substitution",subtype,"single")
- end
-end
-local function sethandler(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,what)
- local tableoffset=lookupoffset+offset
- setposition(f,tableoffset)
- local subtype=readushort(f)
- if subtype==1 then
- local coverage=readushort(f)
- local nofsequence=readushort(f)
- local sequences={}
- for i=1,nofsequence do
- sequences[i]=readushort(f)
- end
- for i=1,nofsequence do
- setposition(f,tableoffset+sequences[i])
- local n=readushort(f)
- local s={}
- for i=1,n do
- s[i]=readushort(f)
- end
- sequences[i]=s
- end
- local coverage=readcoverage(f,tableoffset+coverage)
- for index,newindex in next,coverage do
- newindex=newindex+1
- if index>nofglyphs or newindex>nofglyphs then
- report("invalid index in %s format %i: %i -> %i (max %i)",what,subtype,index,newindex,nofglyphs)
- coverage[index]=nil
- else
- coverage[index]=sequences[newindex]
- end
- end
- return {
- coverage=coverage
- }
- else
- report("unsupported subtype %a in %a substitution",subtype,what)
- end
-end
-function gsubhandlers.multiple(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs)
- return sethandler(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,"multiple")
-end
-function gsubhandlers.alternate(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs)
- return sethandler(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,"alternate")
-end
-function gsubhandlers.ligature(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs)
- local tableoffset=lookupoffset+offset
- setposition(f,tableoffset)
- local subtype=readushort(f)
- if subtype==1 then
- local coverage=readushort(f)
- local nofsets=readushort(f)
- local ligatures={}
- for i=1,nofsets do
- ligatures[i]=readushort(f)
- end
- for i=1,nofsets do
- local offset=lookupoffset+offset+ligatures[i]
- setposition(f,offset)
- local n=readushort(f)
- local l={}
- for i=1,n do
- l[i]=offset+readushort(f)
- end
- ligatures[i]=l
- end
- local coverage=readcoverage(f,tableoffset+coverage)
- for index,newindex in next,coverage do
- local hash={}
- local ligatures=ligatures[newindex+1]
- for i=1,#ligatures do
- local offset=ligatures[i]
- setposition(f,offset)
- local lig=readushort(f)
- local cnt=readushort(f)
- local hsh=hash
- for i=2,cnt do
- local c=readushort(f)
- local h=hsh[c]
- if not h then
- h={}
- hsh[c]=h
- end
- hsh=h
- end
- hsh.ligature=lig
- end
- coverage[index]=hash
- end
- return {
- coverage=coverage
- }
- else
- report("unsupported subtype %a in %a substitution",subtype,"ligature")
- end
-end
-function gsubhandlers.context(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs)
- return unchainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,"substitution"),"context"
-end
-function gsubhandlers.chainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs)
- return chainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,"substitution"),"chainedcontext"
-end
-function gsubhandlers.extension(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs)
- return extension(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,gsubtypes,gsubhandlers,"substitution")
-end
-function gsubhandlers.reversechainedcontextsingle(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs)
- local tableoffset=lookupoffset+offset
- setposition(f,tableoffset)
- local subtype=readushort(f)
- if subtype==1 then
- local current=readfirst(f)
- local before=readarray(f)
- local after=readarray(f)
- local replacements=readarray(f)
- current=readcoveragearray(f,tableoffset,current,true)
- before=readcoveragearray(f,tableoffset,before,true)
- after=readcoveragearray(f,tableoffset,after,true)
- return {
- coverage={
- format="reversecoverage",
- before=before,
- current=current,
- after=after,
- replacements=replacements,
- }
- },"reversechainedcontextsingle"
- else
- report("unsupported subtype %a in %a substitution",subtype,"reversechainedcontextsingle")
- end
-end
-local function readpairsets(f,tableoffset,sets,format1,format2)
- local done={}
- for i=1,#sets do
- local offset=sets[i]
- local reused=done[offset]
- if not reused then
- setposition(f,tableoffset+offset)
- local n=readushort(f)
- reused={}
- for i=1,n do
- reused[i]={
- readushort(f),
- readposition(f,format1),
- readposition(f,format2)
- }
- end
- done[offset]=reused
- end
- sets[i]=reused
- end
- return sets
-end
-local function readpairclasssets(f,nofclasses1,nofclasses2,format1,format2)
- local classlist1={}
- for i=1,nofclasses1 do
- local classlist2={}
- classlist1[i]=classlist2
- for j=1,nofclasses2 do
- local one=readposition(f,format1)
- local two=readposition(f,format2)
- if one or two then
- classlist2[j]={ one,two }
- else
- classlist2[j]=false
- end
- end
- end
- return classlist1
-end
-function gposhandlers.single(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs)
- local tableoffset=lookupoffset+offset
- setposition(f,tableoffset)
- local subtype=readushort(f)
- if subtype==1 then
- local coverage=readushort(f)
- local format=readushort(f)
- local value=readposition(f,format)
- local coverage=readcoverage(f,tableoffset+coverage)
- for index,newindex in next,coverage do
- coverage[index]=value
- end
- return {
- format="pair",
- coverage=coverage
- }
- elseif subtype==2 then
- local coverage=readushort(f)
- local format=readushort(f)
- local values={}
- local nofvalues=readushort(f)
- for i=1,nofvalues do
- values[i]=readposition(f,format)
- end
- local coverage=readcoverage(f,tableoffset+coverage)
- for index,newindex in next,coverage do
- coverage[index]=values[newindex+1]
- end
- return {
- format="pair",
- coverage=coverage
- }
- else
- report("unsupported subtype %a in %a positioning",subtype,"single")
- end
-end
-function gposhandlers.pair(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs)
- local tableoffset=lookupoffset+offset
- setposition(f,tableoffset)
- local subtype=readushort(f)
- if subtype==1 then
- local coverage=readushort(f)
- local format1=readushort(f)
- local format2=readushort(f)
- local sets=readarray(f)
- sets=readpairsets(f,tableoffset,sets,format1,format2)
- coverage=readcoverage(f,tableoffset+coverage)
- for index,newindex in next,coverage do
- local set=sets[newindex+1]
- local hash={}
- for i=1,#set do
- local value=set[i]
- if value then
- local other=value[1]
- local first=value[2]
- local second=value[3]
- if first or second then
- hash[other]={ first,second }
- else
- hash[other]=nil
- end
- end
- end
- coverage[index]=hash
- end
- return {
- format="pair",
- coverage=coverage
- }
- elseif subtype==2 then
- local coverage=readushort(f)
- local format1=readushort(f)
- local format2=readushort(f)
- local classdef1=readushort(f)
- local classdef2=readushort(f)
- local nofclasses1=readushort(f)
- local nofclasses2=readushort(f)
- local classlist=readpairclasssets(f,nofclasses1,nofclasses2,format1,format2)
- coverage=readcoverage(f,tableoffset+coverage)
- classdef1=readclassdef(f,tableoffset+classdef1,coverage)
- classdef2=readclassdef(f,tableoffset+classdef2,nofglyphs)
- local usedcoverage={}
- for g1,c1 in next,classdef1 do
- if coverage[g1] then
- local l1=classlist[c1]
- if l1 then
- local hash={}
- for paired,class in next,classdef2 do
- local offsets=l1[class]
- if offsets then
- local first=offsets[1]
- local second=offsets[2]
- if first or second then
- hash[paired]={ first,second }
- else
- end
- end
- end
- usedcoverage[g1]=hash
- end
- end
- end
- return {
- format="pair",
- coverage=usedcoverage
- }
- elseif subtype==3 then
- report("yet unsupported subtype %a in %a positioning",subtype,"pair")
- else
- report("unsupported subtype %a in %a positioning",subtype,"pair")
- end
-end
-function gposhandlers.cursive(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs)
- local tableoffset=lookupoffset+offset
- setposition(f,tableoffset)
- local subtype=readushort(f)
- if subtype==1 then
- local coverage=tableoffset+readushort(f)
- local nofrecords=readushort(f)
- local records={}
- for i=1,nofrecords do
- local entry=readushort(f)
- local exit=readushort(f)
- records[i]={
- entry=entry~=0 and (tableoffset+entry) or false,
- exit=exit~=0 and (tableoffset+exit ) or false,
- }
- end
- coverage=readcoverage(f,coverage)
- for i=1,nofrecords do
- local r=records[i]
- records[i]={
- 1,
- readanchor(f,r.entry) or nil,
- readanchor(f,r.exit ) or nil,
- }
- end
- for index,newindex in next,coverage do
- coverage[index]=records[newindex+1]
- end
- return {
- coverage=coverage
- }
- else
- report("unsupported subtype %a in %a positioning",subtype,"cursive")
- end
-end
-local function handlemark(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,ligature)
- local tableoffset=lookupoffset+offset
- setposition(f,tableoffset)
- local subtype=readushort(f)
- if subtype==1 then
- local markcoverage=tableoffset+readushort(f)
- local basecoverage=tableoffset+readushort(f)
- local nofclasses=readushort(f)
- local markoffset=tableoffset+readushort(f)
- local baseoffset=tableoffset+readushort(f)
- local markcoverage=readcoverage(f,markcoverage)
- local basecoverage=readcoverage(f,basecoverage,true)
- setposition(f,markoffset)
- local markclasses={}
- local nofmarkclasses=readushort(f)
- local lastanchor=fontdata.lastanchor or 0
- local usedanchors={}
- for i=1,nofmarkclasses do
- local class=readushort(f)+1
- local offset=readushort(f)
- if offset==0 then
- markclasses[i]=false
- else
- markclasses[i]={ class,markoffset+offset }
- end
- usedanchors[class]=true
- end
- for i=1,nofmarkclasses do
- local mc=markclasses[i]
- if mc then
- mc[2]=readanchor(f,mc[2])
- end
- end
- setposition(f,baseoffset)
- local nofbaserecords=readushort(f)
- local baserecords={}
- if ligature then
- for i=1,nofbaserecords do
- local offset=readushort(f)
- if offset==0 then
- baserecords[i]=false
- else
- baserecords[i]=baseoffset+offset
- end
- end
- for i=1,nofbaserecords do
- local recordoffset=baserecords[i]
- if recordoffset then
- setposition(f,recordoffset)
- local nofcomponents=readushort(f)
- local components={}
- for i=1,nofcomponents do
- local classes={}
- for i=1,nofclasses do
- local offset=readushort(f)
- if offset~=0 then
- classes[i]=recordoffset+offset
- else
- classes[i]=false
- end
- end
- components[i]=classes
- end
- baserecords[i]=components
- end
- end
- local baseclasses={}
- for i=1,nofclasses do
- baseclasses[i]={}
- end
- for i=1,nofbaserecords do
- local components=baserecords[i]
- if components then
- local b=basecoverage[i]
- for c=1,#components do
- local classes=components[c]
- if classes then
- for i=1,nofclasses do
- local anchor=readanchor(f,classes[i])
- local bclass=baseclasses[i]
- local bentry=bclass[b]
- if bentry then
- bentry[c]=anchor
- else
- bclass[b]={ [c]=anchor }
- end
- end
- end
- end
- end
- end
- for index,newindex in next,markcoverage do
- markcoverage[index]=markclasses[newindex+1] or nil
- end
- return {
- format="ligature",
- baseclasses=baseclasses,
- coverage=markcoverage,
- }
- else
- for i=1,nofbaserecords do
- local r={}
- for j=1,nofclasses do
- local offset=readushort(f)
- if offset==0 then
- r[j]=false
- else
- r[j]=baseoffset+offset
- end
- end
- baserecords[i]=r
- end
- local baseclasses={}
- for i=1,nofclasses do
- baseclasses[i]={}
- end
- for i=1,nofbaserecords do
- local r=baserecords[i]
- local b=basecoverage[i]
- for j=1,nofclasses do
- baseclasses[j][b]=readanchor(f,r[j])
- end
- end
- for index,newindex in next,markcoverage do
- markcoverage[index]=markclasses[newindex+1] or nil
- end
- return {
- format="base",
- baseclasses=baseclasses,
- coverage=markcoverage,
- }
- end
- else
- report("unsupported subtype %a in",subtype)
- end
-end
-function gposhandlers.marktobase(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs)
- return handlemark(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs)
-end
-function gposhandlers.marktoligature(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs)
- return handlemark(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,true)
-end
-function gposhandlers.marktomark(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs)
- return handlemark(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs)
-end
-function gposhandlers.context(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs)
- return unchainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,"positioning"),"context"
-end
-function gposhandlers.chainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs)
- return chainedcontext(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,"positioning"),"chainedcontext"
-end
-function gposhandlers.extension(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs)
- return extension(f,fontdata,lookupid,lookupoffset,offset,glyphs,nofglyphs,gpostypes,gposhandlers,"positioning")
-end
-do
- local plugins={}
- function plugins.size(f,fontdata,tableoffset,feature)
- if fontdata.designsize then
- else
- local function check(offset)
- setposition(f,offset)
- local designsize=readushort(f)
- if designsize>0 then
- local fontstyle=readushort(f)
- local guimenuid=readushort(f)
- local minsize=readushort(f)
- local maxsize=readushort(f)
- if minsize==0 and maxsize==0 and fontstyleid==0 and guimenuid==0 then
- minsize=designsize
- maxsize=designsize
- end
- if designsize>=minsize and designsize<=maxsize then
- return minsize,maxsize,designsize
- end
- end
- end
- local minsize,maxsize,designsize=check(tableoffset+feature.offset+feature.parameters)
- if not designsize then
- minsize,maxsize,designsize=check(tableoffset+feature.parameters)
- if designsize then
- report("bad size feature in %a, falling back to wrong offset",fontdata.filename or "?")
- else
- report("bad size feature in %a,",fontdata.filename or "?")
- end
- end
- if designsize then
- fontdata.minsize=minsize
- fontdata.maxsize=maxsize
- fontdata.designsize=designsize
- end
- end
- end
- local function reorderfeatures(fontdata,scripts,features)
- local scriptlangs={}
- local featurehash={}
- local featureorder={}
- for script,languages in next,scripts do
- for language,record in next,languages do
- local hash={}
- local list=record.featureindices
- for k=1,#list do
- local index=list[k]
- local feature=features[index]
- local lookups=feature.lookups
- local tag=feature.tag
- if tag then
- hash[tag]=true
- end
- if lookups then
- for i=1,#lookups do
- local lookup=lookups[i]
- local o=featureorder[lookup]
- if o then
- local okay=true
- for i=1,#o do
- if o[i]==tag then
- okay=false
- break
- end
- end
- if okay then
- o[#o+1]=tag
- end
- else
- featureorder[lookup]={ tag }
- end
- local f=featurehash[lookup]
- if f then
- local h=f[tag]
- if h then
- local s=h[script]
- if s then
- s[language]=true
- else
- h[script]={ [language]=true }
- end
- else
- f[tag]={ [script]={ [language]=true } }
- end
- else
- featurehash[lookup]={ [tag]={ [script]={ [language]=true } } }
- end
- local h=scriptlangs[tag]
- if h then
- local s=h[script]
- if s then
- s[language]=true
- else
- h[script]={ [language]=true }
- end
- else
- scriptlangs[tag]={ [script]={ [language]=true } }
- end
- end
- end
- end
- end
- end
- return scriptlangs,featurehash,featureorder
- end
- local function readscriplan(f,fontdata,scriptoffset)
- setposition(f,scriptoffset)
- local nofscripts=readushort(f)
- local scripts={}
- for i=1,nofscripts do
- scripts[readtag(f)]=scriptoffset+readushort(f)
- end
- local languagesystems=setmetatableindex("table")
- for script,offset in next,scripts do
- setposition(f,offset)
- local defaultoffset=readushort(f)
- local noflanguages=readushort(f)
- local languages={}
- if defaultoffset>0 then
- languages.dflt=languagesystems[offset+defaultoffset]
- end
- for i=1,noflanguages do
- local language=readtag(f)
- local offset=offset+readushort(f)
- languages[language]=languagesystems[offset]
- end
- scripts[script]=languages
- end
- for offset,usedfeatures in next,languagesystems do
- if offset>0 then
- setposition(f,offset)
- local featureindices={}
- usedfeatures.featureindices=featureindices
- usedfeatures.lookuporder=readushort(f)
- usedfeatures.requiredindex=readushort(f)
- local noffeatures=readushort(f)
- for i=1,noffeatures do
- featureindices[i]=readushort(f)+1
- end
- end
- end
- return scripts
- end
- local function readfeatures(f,fontdata,featureoffset)
- setposition(f,featureoffset)
- local features={}
- local noffeatures=readushort(f)
- for i=1,noffeatures do
- features[i]={
- tag=readtag(f),
- offset=readushort(f)
- }
- end
- for i=1,noffeatures do
- local feature=features[i]
- local offset=featureoffset+feature.offset
- setposition(f,offset)
- local parameters=readushort(f)
- local noflookups=readushort(f)
- if noflookups>0 then
- local lookups={}
- feature.lookups=lookups
- for j=1,noflookups do
- lookups[j]=readushort(f)+1
- end
- end
- if parameters>0 then
- feature.parameters=parameters
- local plugin=plugins[feature.tag]
- if plugin then
- plugin(f,fontdata,featureoffset,feature)
- end
- end
- end
- return features
- end
- local function readlookups(f,lookupoffset,lookuptypes,featurehash,featureorder)
- setposition(f,lookupoffset)
- local lookups={}
- local noflookups=readushort(f)
- for i=1,noflookups do
- lookups[i]=readushort(f)
- end
- for lookupid=1,noflookups do
- local index=lookups[lookupid]
- setposition(f,lookupoffset+index)
- local subtables={}
- local typebits=readushort(f)
- local flagbits=readushort(f)
- local lookuptype=lookuptypes[typebits]
- local lookupflags=lookupflags[flagbits]
- local nofsubtables=readushort(f)
- for j=1,nofsubtables do
- local offset=readushort(f)
- subtables[j]=offset+index
- end
- local markclass=bittest(flagbits,0x0010)
- if markclass then
- markclass=readushort(f)
- end
- local markset=rshift(flagbits,8)
- if markset>0 then
- markclass=markset
- end
- lookups[lookupid]={
- type=lookuptype,
- flags=lookupflags,
- name=lookupid,
- subtables=subtables,
- markclass=markclass,
- features=featurehash[lookupid],
- order=featureorder[lookupid],
- }
- end
- return lookups
- end
- local function readscriptoffsets(f,fontdata,tableoffset)
- if not tableoffset then
- return
- end
- setposition(f,tableoffset)
- local version=readulong(f)
- if version~=0x00010000 then
- report("table version %a of %a is not supported (yet), maybe font %s is bad",version,what,fontdata.filename)
- return
- end
- return tableoffset+readushort(f),tableoffset+readushort(f),tableoffset+readushort(f)
- end
- local f_lookupname=formatters["%s_%s_%s"]
- local function resolvelookups(f,lookupoffset,fontdata,lookups,lookuptypes,lookuphandlers,what)
- local sequences=fontdata.sequences or {}
- local sublookuplist=fontdata.sublookups or {}
- fontdata.sequences=sequences
- fontdata.sublookups=sublookuplist
- local nofsublookups=#sublookuplist
- local nofsequences=#sequences
- local lastsublookup=nofsublookups
- local lastsequence=nofsequences
- local lookupnames=lookupnames[what]
- local sublookuphash={}
- local sublookupcheck={}
- local glyphs=fontdata.glyphs
- local nofglyphs=fontdata.nofglyphs or #glyphs
- local noflookups=#lookups
- local lookupprefix=sub(what,2,2)
- for lookupid=1,noflookups do
- local lookup=lookups[lookupid]
- local lookuptype=lookup.type
- local subtables=lookup.subtables
- local features=lookup.features
- local handler=lookuphandlers[lookuptype]
- if handler then
- local nofsubtables=#subtables
- local order=lookup.order
- local flags=lookup.flags
- if flags[1] then flags[1]="mark" end
- if flags[2] then flags[2]="ligature" end
- if flags[3] then flags[3]="base" end
- local markclass=lookup.markclass
- if nofsubtables>0 then
- local steps={}
- local nofsteps=0
- local oldtype=nil
- for s=1,nofsubtables do
- local step,lt=handler(f,fontdata,lookupid,lookupoffset,subtables[s],glyphs,nofglyphs)
- if lt then
- lookuptype=lt
- if oldtype and lt~=oldtype then
- report("messy %s lookup type %a and %a",what,lookuptype,oldtype)
- end
- oldtype=lookuptype
- end
- if not step then
- report("unsupported %s lookup type %a",what,lookuptype)
- else
- nofsteps=nofsteps+1
- steps[nofsteps]=step
- local rules=step.rules
- if rules then
- for i=1,#rules do
- local rule=rules[i]
- local before=rule.before
- local current=rule.current
- local after=rule.after
- if before then
- for i=1,#before do
- before[i]=tohash(before[i])
- end
- rule.before=reversed(before)
- end
- if current then
- for i=1,#current do
- current[i]=tohash(current[i])
- end
- end
- if after then
- for i=1,#after do
- after[i]=tohash(after[i])
- end
- end
- end
- end
- end
- end
- if nofsteps~=nofsubtables then
- report("bogus subtables removed in %s lookup type %a",what,lookuptype)
- end
- lookuptype=lookupnames[lookuptype] or lookuptype
- if features then
- nofsequences=nofsequences+1
- local l={
- index=nofsequences,
- name=f_lookupname(lookupprefix,"s",lookupid+lookupidoffset),
- steps=steps,
- nofsteps=nofsteps,
- type=lookuptype,
- markclass=markclass or nil,
- flags=flags,
- order=order,
- features=features,
- }
- sequences[nofsequences]=l
- lookup.done=l
- else
- nofsublookups=nofsublookups+1
- local l={
- index=nofsublookups,
- name=f_lookupname(lookupprefix,"l",lookupid+lookupidoffset),
- steps=steps,
- nofsteps=nofsteps,
- type=lookuptype,
- markclass=markclass or nil,
- flags=flags,
- }
- sublookuplist[nofsublookups]=l
- sublookuphash[lookupid]=nofsublookups
- sublookupcheck[lookupid]=0
- lookup.done=l
- end
- else
- report("no subtables for lookup %a",lookupid)
- end
- else
- report("no handler for lookup %a with type %a",lookupid,lookuptype)
- end
- end
- local reported={}
- local function report_issue(i,what,sequence,kind)
- local name=sequence.name
- if not reported[name] then
- report("rule %i in %s lookup %a has %s lookups",i,what,name,kind)
- reported[name]=true
- end
- end
- for i=lastsequence+1,nofsequences do
- local sequence=sequences[i]
- local steps=sequence.steps
- for i=1,#steps do
- local step=steps[i]
- local rules=step.rules
- if rules then
- for i=1,#rules do
- local rule=rules[i]
- local rlookups=rule.lookups
- if not rlookups then
- report_issue(i,what,sequence,"no")
- elseif not next(rlookups) then
- report_issue(i,what,sequence,"empty")
- rule.lookups=nil
- else
- local length=#rlookups
- for index=1,length do
- local lookupid=rlookups[index]
- if lookupid then
- local h=sublookuphash[lookupid]
- if not h then
- local lookup=lookups[lookupid]
- if lookup then
- local d=lookup.done
- if d then
- nofsublookups=nofsublookups+1
- h={
- index=nofsublookups,
- name=f_lookupname(lookupprefix,"d",lookupid+lookupidoffset),
- derived=true,
- steps=d.steps,
- nofsteps=d.nofsteps,
- type=d.lookuptype,
- markclass=d.markclass or nil,
- flags=d.flags,
- }
- sublookuplist[nofsublookups]=copy(h)
- sublookuphash[lookupid]=nofsublookups
- sublookupcheck[lookupid]=1
- h=nofsublookups
- else
- report_issue(i,what,sequence,"missing")
- rule.lookups=nil
- break
- end
- else
- report_issue(i,what,sequence,"bad")
- rule.lookups=nil
- break
- end
- else
- sublookupcheck[lookupid]=sublookupcheck[lookupid]+1
- end
- rlookups[index]=h or false
- else
- rlookups[index]=false
- end
- end
- end
- end
- end
- end
- end
- for i,n in sortedhash(sublookupcheck) do
- local l=lookups[i]
- local t=l.type
- if n==0 and t~="extension" then
- local d=l.done
- report("%s lookup %s of type %a is not used",what,d and d.name or l.name,t)
- end
- end
- end
- local function readscripts(f,fontdata,what,lookuptypes,lookuphandlers,lookupstoo)
- local datatable=fontdata.tables[what]
- if not datatable then
- return
- end
- local tableoffset=datatable.offset
- if not tableoffset then
- return
- end
- local scriptoffset,featureoffset,lookupoffset=readscriptoffsets(f,fontdata,tableoffset)
- if not scriptoffset then
- return
- end
- local scripts=readscriplan(f,fontdata,scriptoffset)
- local features=readfeatures(f,fontdata,featureoffset)
- local scriptlangs,featurehash,featureorder=reorderfeatures(fontdata,scripts,features)
- if fontdata.features then
- fontdata.features[what]=scriptlangs
- else
- fontdata.features={ [what]=scriptlangs }
- end
- if not lookupstoo then
- return
- end
- local lookups=readlookups(f,lookupoffset,lookuptypes,featurehash,featureorder)
- if lookups then
- resolvelookups(f,lookupoffset,fontdata,lookups,lookuptypes,lookuphandlers,what)
- end
- end
- local function checkkerns(f,fontdata,specification)
- local datatable=fontdata.tables.kern
- if not datatable then
- return
- end
- local features=fontdata.features
- local gposfeatures=features and features.gpos
- local name
- if not gposfeatures or not gposfeatures.kern then
- name="kern"
- elseif specification.globalkerns then
- name="globalkern"
- else
- report("ignoring global kern table using gpos kern feature")
- return
- end
- report("adding global kern table as gpos feature %a",name)
- setposition(f,datatable.offset)
- local version=readushort(f)
- local noftables=readushort(f)
- local kerns=setmetatableindex("table")
- for i=1,noftables do
- local version=readushort(f)
- local length=readushort(f)
- local coverage=readushort(f)
- local format=bit32.rshift(coverage,8)
- if format==0 then
- local nofpairs=readushort(f)
- local searchrange=readushort(f)
- local entryselector=readushort(f)
- local rangeshift=readushort(f)
- for i=1,nofpairs do
- kerns[readushort(f)][readushort(f)]=readfword(f)
- end
- elseif format==2 then
- else
- end
- end
- local feature={ dflt={ dflt=true } }
- if not features then
- fontdata.features={ gpos={ [name]=feature } }
- elseif not gposfeatures then
- fontdata.features.gpos={ [name]=feature }
- else
- gposfeatures[name]=feature
- end
- local sequences=fontdata.sequences
- if not sequences then
- sequences={}
- fontdata.sequences=sequences
- end
- local nofsequences=#sequences+1
- sequences[nofsequences]={
- index=nofsequences,
- name=name,
- steps={
- {
- coverage=kerns,
- format="kern",
- },
- },
- nofsteps=1,
- type="gpos_pair",
- flags={ false,false,false,false },
- order={ name },
- features={ [name]=feature },
- }
- end
- function readers.gsub(f,fontdata,specification)
- if specification.details then
- readscripts(f,fontdata,"gsub",gsubtypes,gsubhandlers,specification.lookups)
- end
- end
- function readers.gpos(f,fontdata,specification)
- if specification.details then
- readscripts(f,fontdata,"gpos",gpostypes,gposhandlers,specification.lookups)
- if specification.lookups then
- checkkerns(f,fontdata,specification)
- end
- end
- end
-end
-function readers.gdef(f,fontdata,specification)
- if specification.glyphs then
- local datatable=fontdata.tables.gdef
- if datatable then
- local tableoffset=datatable.offset
- setposition(f,tableoffset)
- local version=readulong(f)
- local classoffset=tableoffset+readushort(f)
- local attachmentoffset=tableoffset+readushort(f)
- local ligaturecarets=tableoffset+readushort(f)
- local markclassoffset=tableoffset+readushort(f)
- local marksetsoffset=version==0x00010002 and (tableoffset+readushort(f))
- local glyphs=fontdata.glyphs
- local marks={}
- local markclasses=setmetatableindex("table")
- local marksets=setmetatableindex("table")
- fontdata.marks=marks
- fontdata.markclasses=markclasses
- fontdata.marksets=marksets
- setposition(f,classoffset)
- local classformat=readushort(f)
- if classformat==1 then
- local firstindex=readushort(f)
- local lastindex=firstindex+readushort(f)-1
- for index=firstindex,lastindex do
- local class=classes[readushort(f)]
- if class=="mark" then
- marks[index]=true
- end
- glyphs[index].class=class
- end
- elseif classformat==2 then
- local nofranges=readushort(f)
- for i=1,nofranges do
- local firstindex=readushort(f)
- local lastindex=readushort(f)
- local class=classes[readushort(f)]
- if class then
- for index=firstindex,lastindex do
- glyphs[index].class=class
- if class=="mark" then
- marks[index]=true
- end
- end
- end
- end
- end
- setposition(f,markclassoffset)
- local classformat=readushort(f)
- if classformat==1 then
- local firstindex=readushort(f)
- local lastindex=firstindex+readushort(f)-1
- for index=firstindex,lastindex do
- markclasses[readushort(f)][index]=true
- end
- elseif classformat==2 then
- local nofranges=readushort(f)
- for i=1,nofranges do
- local firstindex=readushort(f)
- local lastindex=readushort(f)
- local class=markclasses[readushort(f)]
- for index=firstindex,lastindex do
- class[index]=true
- end
- end
- end
- if marksetsoffset and marksetsoffset>tableoffset then
- setposition(f,marksetsoffset)
- local format=readushort(f)
- if format==1 then
- local nofsets=readushort(f)
- local sets={}
- for i=1,nofsets do
- sets[i]=readulong(f)
- end
- for i=1,nofsets do
- local offset=sets[i]
- if offset~=0 then
- marksets[i]=readcoverage(f,marksetsoffset+offset)
- end
- end
- end
- end
- end
- end
-end
-local function readmathvalue(f)
- local v=readshort(f)
- skipshort(f,1)
- return v
-end
-local function readmathconstants(f,fontdata,offset)
- setposition(f,offset)
- fontdata.mathconstants={
- ScriptPercentScaleDown=readshort(f),
- ScriptScriptPercentScaleDown=readshort(f),
- DelimitedSubFormulaMinHeight=readushort(f),
- DisplayOperatorMinHeight=readushort(f),
- MathLeading=readmathvalue(f),
- AxisHeight=readmathvalue(f),
- AccentBaseHeight=readmathvalue(f),
- FlattenedAccentBaseHeight=readmathvalue(f),
- SubscriptShiftDown=readmathvalue(f),
- SubscriptTopMax=readmathvalue(f),
- SubscriptBaselineDropMin=readmathvalue(f),
- SuperscriptShiftUp=readmathvalue(f),
- SuperscriptShiftUpCramped=readmathvalue(f),
- SuperscriptBottomMin=readmathvalue(f),
- SuperscriptBaselineDropMax=readmathvalue(f),
- SubSuperscriptGapMin=readmathvalue(f),
- SuperscriptBottomMaxWithSubscript=readmathvalue(f),
- SpaceAfterScript=readmathvalue(f),
- UpperLimitGapMin=readmathvalue(f),
- UpperLimitBaselineRiseMin=readmathvalue(f),
- LowerLimitGapMin=readmathvalue(f),
- LowerLimitBaselineDropMin=readmathvalue(f),
- StackTopShiftUp=readmathvalue(f),
- StackTopDisplayStyleShiftUp=readmathvalue(f),
- StackBottomShiftDown=readmathvalue(f),
- StackBottomDisplayStyleShiftDown=readmathvalue(f),
- StackGapMin=readmathvalue(f),
- StackDisplayStyleGapMin=readmathvalue(f),
- StretchStackTopShiftUp=readmathvalue(f),
- StretchStackBottomShiftDown=readmathvalue(f),
- StretchStackGapAboveMin=readmathvalue(f),
- StretchStackGapBelowMin=readmathvalue(f),
- FractionNumeratorShiftUp=readmathvalue(f),
- FractionNumeratorDisplayStyleShiftUp=readmathvalue(f),
- FractionDenominatorShiftDown=readmathvalue(f),
- FractionDenominatorDisplayStyleShiftDown=readmathvalue(f),
- FractionNumeratorGapMin=readmathvalue(f),
- FractionNumeratorDisplayStyleGapMin=readmathvalue(f),
- FractionRuleThickness=readmathvalue(f),
- FractionDenominatorGapMin=readmathvalue(f),
- FractionDenominatorDisplayStyleGapMin=readmathvalue(f),
- SkewedFractionHorizontalGap=readmathvalue(f),
- SkewedFractionVerticalGap=readmathvalue(f),
- OverbarVerticalGap=readmathvalue(f),
- OverbarRuleThickness=readmathvalue(f),
- OverbarExtraAscender=readmathvalue(f),
- UnderbarVerticalGap=readmathvalue(f),
- UnderbarRuleThickness=readmathvalue(f),
- UnderbarExtraDescender=readmathvalue(f),
- RadicalVerticalGap=readmathvalue(f),
- RadicalDisplayStyleVerticalGap=readmathvalue(f),
- RadicalRuleThickness=readmathvalue(f),
- RadicalExtraAscender=readmathvalue(f),
- RadicalKernBeforeDegree=readmathvalue(f),
- RadicalKernAfterDegree=readmathvalue(f),
- RadicalDegreeBottomRaisePercent=readshort(f),
- }
-end
-local function readmathglyphinfo(f,fontdata,offset)
- setposition(f,offset)
- local italics=readushort(f)
- local accents=readushort(f)
- local extensions=readushort(f)
- local kerns=readushort(f)
- local glyphs=fontdata.glyphs
- if italics~=0 then
- setposition(f,offset+italics)
- local coverage=readushort(f)
- local nofglyphs=readushort(f)
- coverage=readcoverage(f,offset+italics+coverage,true)
- setposition(f,offset+italics+4)
- for i=1,nofglyphs do
- local italic=readmathvalue(f)
- if italic~=0 then
- local glyph=glyphs[coverage[i]]
- local math=glyph.math
- if not math then
- glyph.math={ italic=italic }
- else
- math.italic=italic
- end
- end
- end
- fontdata.hasitalics=true
- end
- if accents~=0 then
- setposition(f,offset+accents)
- local coverage=readushort(f)
- local nofglyphs=readushort(f)
- coverage=readcoverage(f,offset+accents+coverage,true)
- setposition(f,offset+accents+4)
- for i=1,nofglyphs do
- local accent=readmathvalue(f)
- if accent~=0 then
- local glyph=glyphs[coverage[i]]
- local math=glyph.math
- if not math then
- glyph.math={ accent=accent }
- else
- math.accent=accent
- end
- end
- end
- end
- if extensions~=0 then
- setposition(f,offset+extensions)
- end
- if kerns~=0 then
- local kernoffset=offset+kerns
- setposition(f,kernoffset)
- local coverage=readushort(f)
- local nofglyphs=readushort(f)
- if nofglyphs>0 then
- local function get(offset)
- setposition(f,kernoffset+offset)
- local n=readushort(f)
- if n==0 then
- local k=readmathvalue(f)
- if k==0 then
- else
- return { { kern=k } }
- end
- else
- local l={}
- for i=1,n do
- l[i]={ height=readmathvalue(f) }
- end
- for i=1,n do
- l[i].kern=readmathvalue(f)
- end
- l[n+1]={ kern=readmathvalue(f) }
- return l
- end
- end
- local kernsets={}
- for i=1,nofglyphs do
- local topright=readushort(f)
- local topleft=readushort(f)
- local bottomright=readushort(f)
- local bottomleft=readushort(f)
- kernsets[i]={
- topright=topright~=0 and topright or nil,
- topleft=topleft~=0 and topleft or nil,
- bottomright=bottomright~=0 and bottomright or nil,
- bottomleft=bottomleft~=0 and bottomleft or nil,
- }
- end
- coverage=readcoverage(f,kernoffset+coverage,true)
- for i=1,nofglyphs do
- local kernset=kernsets[i]
- if next(kernset) then
- local k=kernset.topright if k then kernset.topright=get(k) end
- local k=kernset.topleft if k then kernset.topleft=get(k) end
- local k=kernset.bottomright if k then kernset.bottomright=get(k) end
- local k=kernset.bottomleft if k then kernset.bottomleft=get(k) end
- if next(kernset) then
- local glyph=glyphs[coverage[i]]
- local math=glyph.math
- if math then
- math.kerns=kernset
- else
- glyph.math={ kerns=kernset }
- end
- end
- end
- end
- end
- end
-end
-local function readmathvariants(f,fontdata,offset)
- setposition(f,offset)
- local glyphs=fontdata.glyphs
- local minoverlap=readushort(f)
- local vcoverage=readushort(f)
- local hcoverage=readushort(f)
- local vnofglyphs=readushort(f)
- local hnofglyphs=readushort(f)
- local vconstruction={}
- local hconstruction={}
- for i=1,vnofglyphs do
- vconstruction[i]=readushort(f)
- end
- for i=1,hnofglyphs do
- hconstruction[i]=readushort(f)
- end
- fontdata.mathconstants.MinConnectorOverlap=minoverlap
- local function get(offset,coverage,nofglyphs,construction,kvariants,kparts,kitalic)
- if coverage~=0 and nofglyphs>0 then
- local coverage=readcoverage(f,offset+coverage,true)
- for i=1,nofglyphs do
- local c=construction[i]
- if c~=0 then
- local index=coverage[i]
- local glyph=glyphs[index]
- local math=glyph.math
- setposition(f,offset+c)
- local assembly=readushort(f)
- local nofvariants=readushort(f)
- if nofvariants>0 then
- local variants,v=nil,0
- for i=1,nofvariants do
- local variant=readushort(f)
- if variant==index then
- elseif variants then
- v=v+1
- variants[v]=variant
- else
- v=1
- variants={ variant }
- end
- skipshort(f)
- end
- if not variants then
- elseif not math then
- math={ [kvariants]=variants }
- glyph.math=math
- else
- math[kvariants]=variants
- end
- end
- if assembly~=0 then
- setposition(f,offset+c+assembly)
- local italic=readmathvalue(f)
- local nofparts=readushort(f)
- local parts={}
- for i=1,nofparts do
- local p={
- glyph=readushort(f),
- start=readushort(f),
- ["end"]=readushort(f),
- advance=readushort(f),
- }
- local flags=readushort(f)
- if bittest(flags,0x0001) then
- p.extender=1
- end
- parts[i]=p
- end
- if not math then
- math={
- [kparts]=parts
- }
- glyph.math=math
- else
- math[kparts]=parts
- end
- if italic and italic~=0 then
- math[kitalic]=italic
- end
- end
- end
- end
- end
- end
- get(offset,vcoverage,vnofglyphs,vconstruction,"vvariants","vparts","vitalic")
- get(offset,hcoverage,hnofglyphs,hconstruction,"hvariants","hparts","hitalic")
-end
-function readers.math(f,fontdata,specification)
- if specification.glyphs then
- local datatable=fontdata.tables.math
- if datatable then
- local tableoffset=datatable.offset
- setposition(f,tableoffset)
- local version=readulong(f)
- if version~=0x00010000 then
- report("table version %a of %a is not supported (yet), maybe font %s is bad",version,"math",fontdata.filename)
- return
- end
- local constants=readushort(f)
- local glyphinfo=readushort(f)
- local variants=readushort(f)
- if constants==0 then
- report("the math table of %a has no constants",fontdata.filename)
- else
- readmathconstants(f,fontdata,tableoffset+constants)
- end
- if glyphinfo~=0 then
- readmathglyphinfo(f,fontdata,tableoffset+glyphinfo)
- end
- if variants~=0 then
- readmathvariants(f,fontdata,tableoffset+variants)
- end
- end
- end
-end
-function readers.colr(f,fontdata,specification)
- local datatable=fontdata.tables.colr
- if datatable then
- if specification.glyphs then
- local tableoffset=datatable.offset
- setposition(f,tableoffset)
- local version=readushort(f)
- if version~=0 then
- report("table version %a of %a is not supported (yet), maybe font %s is bad",version,"colr",fontdata.filename)
- return
- end
- if not fontdata.tables.cpal then
- report("color table %a in font %a has no mandate %a table","colr",fontdata.filename,"cpal")
- fontdata.colorpalettes={}
- end
- local glyphs=fontdata.glyphs
- local nofglyphs=readushort(f)
- local baseoffset=readulong(f)
- local layeroffset=readulong(f)
- local noflayers=readushort(f)
- local layerrecords={}
- local maxclass=0
- setposition(f,tableoffset+layeroffset)
- for i=1,noflayers do
- local slot=readushort(f)
- local class=readushort(f)
- if class<0xFFFF then
- class=class+1
- if class>maxclass then
- maxclass=class
- end
- end
- layerrecords[i]={
- slot=slot,
- class=class,
- }
- end
- fontdata.maxcolorclass=maxclass
- setposition(f,tableoffset+baseoffset)
- for i=0,nofglyphs-1 do
- local glyphindex=readushort(f)
- local firstlayer=readushort(f)
- local noflayers=readushort(f)
- local t={}
- for i=1,noflayers do
- t[i]=layerrecords[firstlayer+i]
- end
- glyphs[glyphindex].colors=t
- end
- end
- fontdata.hascolor=true
- end
-end
-function readers.cpal(f,fontdata,specification)
- if specification.glyphs then
- local datatable=fontdata.tables.cpal
- if datatable then
- local tableoffset=datatable.offset
- setposition(f,tableoffset)
- local version=readushort(f)
- if version>1 then
- report("table version %a of %a is not supported (yet), maybe font %s is bad",version,"cpal",fontdata.filename)
- return
- end
- local nofpaletteentries=readushort(f)
- local nofpalettes=readushort(f)
- local nofcolorrecords=readushort(f)
- local firstcoloroffset=readulong(f)
- local colorrecords={}
- local palettes={}
- for i=1,nofpalettes do
- palettes[i]=readushort(f)
- end
- if version==1 then
- local palettettypesoffset=readulong(f)
- local palettelabelsoffset=readulong(f)
- local paletteentryoffset=readulong(f)
- end
- setposition(f,tableoffset+firstcoloroffset)
- for i=1,nofcolorrecords do
- local b,g,r,a=readbytes(f,4)
- colorrecords[i]={
- r,g,b,a~=255 and a or nil,
- }
- end
- for i=1,nofpalettes do
- local p={}
- local o=palettes[i]
- for j=1,nofpaletteentries do
- p[j]=colorrecords[o+j]
- end
- palettes[i]=p
- end
- fontdata.colorpalettes=palettes
- end
- end
-end
-function readers.svg(f,fontdata,specification)
- local datatable=fontdata.tables.svg
- if datatable then
- if specification.glyphs then
- local tableoffset=datatable.offset
- setposition(f,tableoffset)
- local version=readushort(f)
- if version~=0 then
- report("table version %a of %a is not supported (yet), maybe font %s is bad",version,"svg",fontdata.filename)
- return
- end
- local glyphs=fontdata.glyphs
- local indexoffset=tableoffset+readulong(f)
- local reserved=readulong(f)
- setposition(f,indexoffset)
- local nofentries=readushort(f)
- local entries={}
- for i=1,nofentries do
- entries[i]={
- first=readushort(f),
- last=readushort(f),
- offset=indexoffset+readulong(f),
- length=readulong(f),
- }
- end
- for i=1,nofentries do
- local entry=entries[i]
- setposition(f,entry.offset)
- entries[i]={
- first=entry.first,
- last=entry.last,
- data=readstring(f,entry.length)
- }
- end
- fontdata.svgshapes=entries
- end
- fontdata.hascolor=true
- end
-end
-
-end --- [luaotfload, fontloader-2017-02-11.lua scope for “font-dsp”] ---
-
-
-do --- [luaotfload, fontloader-2017-02-11.lua scope for “font-oup” f7237130b648a4c2b477dabedc7f90e8] ---
-
-if not modules then modules={} end modules ['font-oup']={
- version=1.001,
- comment="companion to font-ini.mkiv",
- author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright="PRAGMA ADE / ConTeXt Development Team",
- license="see context related readme files"
-}
-local next,type=next,type
-local P,R,S=lpeg.P,lpeg.R,lpeg.S
-local lpegmatch=lpeg.match
-local insert,remove,copy,unpack=table.insert,table.remove,table.copy,table.unpack
-local formatters=string.formatters
-local sortedkeys=table.sortedkeys
-local sortedhash=table.sortedhash
-local tohash=table.tohash
-local report=logs.reporter("otf reader")
-local trace_markwidth=false trackers.register("otf.markwidth",function(v) trace_markwidth=v end)
-local readers=fonts.handlers.otf.readers
-local privateoffset=fonts.constructors and fonts.constructors.privateoffset or 0xF0000
-local f_private=formatters["P%05X"]
-local f_unicode=formatters["U%05X"]
-local f_index=formatters["I%05X"]
-local f_character_y=formatters["%C"]
-local f_character_n=formatters["[ %C ]"]
-local check_duplicates=true
-local check_soft_hyphen=false
-directives.register("otf.checksofthyphen",function(v)
- check_soft_hyphen=v
-end)
-local function replaced(list,index,replacement)
- if type(list)=="number" then
- return replacement
- elseif type(replacement)=="table" then
- local t={}
- local n=index-1
- for i=1,n do
- t[i]=list[i]
- end
- for i=1,#replacement do
- n=n+1
- t[n]=replacement[i]
- end
- for i=index+1,#list do
- n=n+1
- t[n]=list[i]
- end
- else
- list[index]=replacement
- return list
- end
-end
-local function unifyresources(fontdata,indices)
- local descriptions=fontdata.descriptions
- local resources=fontdata.resources
- if not descriptions or not resources then
- return
- end
- local variants=fontdata.resources.variants
- if variants then
- for selector,unicodes in next,variants do
- for unicode,index in next,unicodes do
- unicodes[unicode]=indices[index]
- end
- end
- end
- local function remark(marks)
- if marks then
- local newmarks={}
- for k,v in next,marks do
- local u=indices[k]
- if u then
- newmarks[u]=v
- else
- report("discarding mark %i",k)
- end
- end
- return newmarks
- end
- end
- local marks=resources.marks
- if marks then
- resources.marks=remark(marks)
- end
- local markclasses=resources.markclasses
- if markclasses then
- for class,marks in next,markclasses do
- markclasses[class]=remark(marks)
- end
- end
- local marksets=resources.marksets
- if marksets then
- for class,marks in next,marksets do
- marksets[class]=remark(marks)
- end
- end
- local done={}
- local duplicates=check_duplicates and resources.duplicates
- if duplicates and not next(duplicates) then
- duplicates=false
- end
- local function recover(cover)
- for i=1,#cover do
- local c=cover[i]
- if not done[c] then
- local t={}
- for k,v in next,c do
- t[indices[k]]=v
- end
- cover[i]=t
- done[c]=d
- end
- end
- end
- local function recursed(c)
- local t={}
- for g,d in next,c do
- if type(d)=="table" then
- t[indices[g]]=recursed(d)
- else
- t[g]=indices[d]
- end
- end
- return t
- end
- local function unifythem(sequences)
- if not sequences then
- return
- end
- for i=1,#sequences do
- local sequence=sequences[i]
- local kind=sequence.type
- local steps=sequence.steps
- local features=sequence.features
- if steps then
- for i=1,#steps do
- local step=steps[i]
- if kind=="gsub_single" then
- local c=step.coverage
- if c then
- local t1=done[c]
- if not t1 then
- t1={}
- if duplicates then
- for g1,d1 in next,c do
- local ug1=indices[g1]
- local ud1=indices[d1]
- t1[ug1]=ud1
- local dg1=duplicates[ug1]
- if dg1 then
- for u in next,dg1 do
- t1[u]=ud1
- end
- end
- end
- else
- for g1,d1 in next,c do
- t1[indices[g1]]=indices[d1]
- end
- end
- done[c]=t1
- end
- step.coverage=t1
- end
- elseif kind=="gpos_pair" then
- local c=step.coverage
- if c then
- local t1=done[c]
- if not t1 then
- t1={}
- for g1,d1 in next,c do
- local t2=done[d1]
- if not t2 then
- t2={}
- for g2,d2 in next,d1 do
- t2[indices[g2]]=d2
- end
- done[d1]=t2
- end
- t1[indices[g1]]=t2
- end
- done[c]=t1
- end
- step.coverage=t1
- end
- elseif kind=="gsub_ligature" then
- local c=step.coverage
- if c then
- step.coverage=recursed(c)
- end
- elseif kind=="gsub_alternate" or kind=="gsub_multiple" then
- local c=step.coverage
- if c then
- local t1=done[c]
- if not t1 then
- t1={}
- if duplicates then
- for g1,d1 in next,c do
- for i=1,#d1 do
- d1[i]=indices[d1[i]]
- end
- local ug1=indices[g1]
- t1[ug1]=d1
- local dg1=duplicates[ug1]
- if dg1 then
- for u in next,dg1 do
- t1[u]=copy(d1)
- end
- end
- end
- else
- for g1,d1 in next,c do
- for i=1,#d1 do
- d1[i]=indices[d1[i]]
- end
- t1[indices[g1]]=d1
- end
- end
- done[c]=t1
- end
- step.coverage=t1
- end
- elseif kind=="gpos_mark2base" or kind=="gpos_mark2mark" or kind=="gpos_mark2ligature" then
- local c=step.coverage
- if c then
- local t1=done[c]
- if not t1 then
- t1={}
- for g1,d1 in next,c do
- t1[indices[g1]]=d1
- end
- done[c]=t1
- end
- step.coverage=t1
- end
- local c=step.baseclasses
- if c then
- local t1=done[c]
- if not t1 then
- for g1,d1 in next,c do
- local t2=done[d1]
- if not t2 then
- t2={}
- for g2,d2 in next,d1 do
- t2[indices[g2]]=d2
- end
- done[d1]=t2
- end
- c[g1]=t2
- end
- done[c]=c
- end
- end
- elseif kind=="gpos_single" then
- local c=step.coverage
- if c then
- local t1=done[c]
- if not t1 then
- t1={}
- if duplicates then
- for g1,d1 in next,c do
- local ug1=indices[g1]
- t1[ug1]=d1
- local dg1=duplicates[ug1]
- if dg1 then
- for u in next,dg1 do
- t1[u]=d1
- end
- end
- end
- else
- for g1,d1 in next,c do
- t1[indices[g1]]=d1
- end
- end
- done[c]=t1
- end
- step.coverage=t1
- end
- elseif kind=="gpos_cursive" then
- local c=step.coverage
- if c then
- local t1=done[c]
- if not t1 then
- t1={}
- if duplicates then
- for g1,d1 in next,c do
- local ug1=indices[g1]
- t1[ug1]=d1
- local dg1=duplicates[ug1]
- if dg1 then
- for u in next,dg1 do
- t1[u]=copy(d1)
- end
- end
- end
- else
- for g1,d1 in next,c do
- t1[indices[g1]]=d1
- end
- end
- done[c]=t1
- end
- step.coverage=t1
- end
- end
- local rules=step.rules
- if rules then
- for i=1,#rules do
- local rule=rules[i]
- local before=rule.before if before then recover(before) end
- local after=rule.after if after then recover(after) end
- local current=rule.current if current then recover(current) end
- local replacements=rule.replacements
- if replacements then
- if not done[replacements] then
- local r={}
- for k,v in next,replacements do
- r[indices[k]]=indices[v]
- end
- rule.replacements=r
- done[replacements]=r
- end
- end
- end
- end
- end
- end
- end
- end
- unifythem(resources.sequences)
- unifythem(resources.sublookups)
-end
-local function copyduplicates(fontdata)
- if check_duplicates then
- local descriptions=fontdata.descriptions
- local resources=fontdata.resources
- local duplicates=resources.duplicates
- if check_soft_hyphen then
- local ds=descriptions[0xAD]
- if not ds or ds.width==0 then
- if ds then
- descriptions[0xAD]=nil
- report("patching soft hyphen")
- else
- report("adding soft hyphen")
- end
- if not duplicates then
- duplicates={}
- resources.duplicates=duplicates
- end
- local dh=duplicates[0x2D]
- if dh then
- dh[#dh+1]={ [0xAD]=true }
- else
- duplicates[0x2D]={ [0xAD]=true }
- end
- end
- end
- if duplicates then
- for u,d in next,duplicates do
- local du=descriptions[u]
- if du then
- local t={ f_character_y(u),"@",f_index(du.index),"->" }
- local n=0
- local m=25
- for u in next,d do
- if descriptions[u] then
- if n<m then
- t[n+4]=f_character_n(u)
- end
- else
- local c=copy(du)
- c.unicode=u
- descriptions[u]=c
- if n<m then
- t[n+4]=f_character_y(u)
- end
- end
- n=n+1
- end
- if n<=m then
- report("duplicates: %i : % t",n,t)
- else
- report("duplicates: %i : % t ...",n,t)
- end
- else
- end
- end
- end
- end
-end
-local ignore={
- ["notdef"]=true,
- [".notdef"]=true,
- ["null"]=true,
- [".null"]=true,
- ["nonmarkingreturn"]=true,
-}
-local function checklookups(fontdata,missing,nofmissing)
- local descriptions=fontdata.descriptions
- local resources=fontdata.resources
- if missing and nofmissing and nofmissing<=0 then
- return
- end
- local singles={}
- local alternates={}
- local ligatures={}
- if not missing then
- missing={}
- nofmissing=0
- for u,d in next,descriptions do
- if not d.unicode then
- nofmissing=nofmissing+1
- missing[u]=true
- end
- end
- end
- local function collectthem(sequences)
- if not sequences then
- return
- end
- for i=1,#sequences do
- local sequence=sequences[i]
- local kind=sequence.type
- local steps=sequence.steps
- if steps then
- for i=1,#steps do
- local step=steps[i]
- if kind=="gsub_single" then
- local c=step.coverage
- if c then
- singles[#singles+1]=c
- end
- elseif kind=="gsub_alternate" then
- local c=step.coverage
- if c then
- alternates[#alternates+1]=c
- end
- elseif kind=="gsub_ligature" then
- local c=step.coverage
- if c then
- ligatures[#ligatures+1]=c
- end
- end
- end
- end
- end
- end
- collectthem(resources.sequences)
- collectthem(resources.sublookups)
- local loops=0
- while true do
- loops=loops+1
- local old=nofmissing
- for i=1,#singles do
- local c=singles[i]
- for g1,g2 in next,c do
- if missing[g1] then
- local u2=descriptions[g2].unicode
- if u2 then
- missing[g1]=false
- descriptions[g1].unicode=u2
- nofmissing=nofmissing-1
- end
- end
- if missing[g2] then
- local u1=descriptions[g1].unicode
- if u1 then
- missing[g2]=false
- descriptions[g2].unicode=u1
- nofmissing=nofmissing-1
- end
- end
- end
- end
- for i=1,#alternates do
- local c=alternates[i]
- for g1,d1 in next,c do
- if missing[g1] then
- for i=1,#d1 do
- local g2=d1[i]
- local u2=descriptions[g2].unicode
- if u2 then
- missing[g1]=false
- descriptions[g1].unicode=u2
- nofmissing=nofmissing-1
- end
- end
- end
- if not missing[g1] then
- for i=1,#d1 do
- local g2=d1[i]
- if missing[g2] then
- local u1=descriptions[g1].unicode
- if u1 then
- missing[g2]=false
- descriptions[g2].unicode=u1
- nofmissing=nofmissing-1
- end
- end
- end
- end
- end
- end
- if nofmissing<=0 then
- report("all done in %s loops",loops)
- return
- elseif old==nofmissing then
- break
- end
- end
- local t,n
- local function recursed(c)
- for g,d in next,c do
- if g~="ligature" then
- local u=descriptions[g].unicode
- if u then
- n=n+1
- t[n]=u
- recursed(d)
- n=n-1
- end
- elseif missing[d] then
- local l={}
- local m=0
- for i=1,n do
- local u=t[i]
- if type(u)=="table" then
- for i=1,#u do
- m=m+1
- l[m]=u[i]
- end
- else
- m=m+1
- l[m]=u
- end
- end
- missing[d]=false
- descriptions[d].unicode=l
- nofmissing=nofmissing-1
- end
- end
- end
- if nofmissing>0 then
- t={}
- n=0
- local loops=0
- while true do
- loops=loops+1
- local old=nofmissing
- for i=1,#ligatures do
- recursed(ligatures[i])
- end
- if nofmissing<=0 then
- report("all done in %s loops",loops)
- return
- elseif old==nofmissing then
- break
- end
- end
- t=nil
- n=0
- end
- if nofmissing>0 then
- local done={}
- for i,r in next,missing do
- if r then
- local data=descriptions[i]
- local name=data and data.name or f_index(i)
- if not ignore[name] then
- done[name]=true
- end
- end
- end
- if next(done) then
- report("not unicoded: % t",table.sortedkeys(done))
- end
- end
-end
-local function unifymissing(fontdata)
- if not fonts.mappings then
- require("font-map")
- require("font-agl")
- end
- local unicodes={}
- local private=fontdata.private
- local resources=fontdata.resources
- resources.unicodes=unicodes
- for unicode,d in next,fontdata.descriptions do
- if unicode<privateoffset then
- local name=d.name
- if name then
- unicodes[name]=unicode
- end
- end
- end
- fonts.mappings.addtounicode(fontdata,fontdata.filename,checklookups)
- resources.unicodes=nil
-end
-local function unifyglyphs(fontdata,usenames)
- local private=fontdata.private or privateoffset
- local glyphs=fontdata.glyphs
- local indices={}
- local descriptions={}
- local names=usenames and {}
- local resources=fontdata.resources
- local zero=glyphs[0]
- local zerocode=zero.unicode
- if not zerocode then
- zerocode=private
- zero.unicode=zerocode
- private=private+1
- end
- descriptions[zerocode]=zero
- if names then
- local name=glyphs[0].name or f_private(zerocode)
- indices[0]=name
- names[name]=zerocode
- else
- indices[0]=zerocode
- end
- for index=1,#glyphs do
- local glyph=glyphs[index]
- local unicode=glyph.unicode
- if not unicode then
- unicode=private
- if names then
- local name=glyph.name or f_private(unicode)
- indices[index]=name
- names[name]=unicode
- else
- indices[index]=unicode
- end
- private=private+1
- elseif descriptions[unicode] then
- report("assigning private unicode %U to glyph indexed %05X (%C)",private,index,unicode)
- unicode=private
- if names then
- local name=glyph.name or f_private(unicode)
- indices[index]=name
- names[name]=unicode
- else
- indices[index]=unicode
- end
- private=private+1
- else
- if names then
- local name=glyph.name or f_unicode(unicode)
- indices[index]=name
- names[name]=unicode
- else
- indices[index]=unicode
- end
- end
- descriptions[unicode]=glyph
- end
- for index=1,#glyphs do
- local math=glyphs[index].math
- if math then
- local list=math.vparts
- if list then
- for i=1,#list do local l=list[i] l.glyph=indices[l.glyph] end
- end
- local list=math.hparts
- if list then
- for i=1,#list do local l=list[i] l.glyph=indices[l.glyph] end
- end
- local list=math.vvariants
- if list then
- for i=1,#list do list[i]=indices[list[i]] end
- end
- local list=math.hvariants
- if list then
- for i=1,#list do list[i]=indices[list[i]] end
- end
- end
- end
- local colorpalettes=resources.colorpalettes
- if colorpalettes then
- for index=1,#glyphs do
- local colors=glyphs[index].colors
- if colors then
- for i=1,#colors do
- local c=colors[i]
- c.slot=indices[c.slot]
- end
- end
- end
- end
- fontdata.private=private
- fontdata.glyphs=nil
- fontdata.names=names
- fontdata.descriptions=descriptions
- fontdata.hashmethod=hashmethod
- return indices,names
-end
-local p_bogusname=(
- (P("uni")+P("UNI")+P("Uni")+P("U")+P("u"))*S("Xx")^0*R("09","AF")^1+(P("identity")+P("Identity")+P("IDENTITY"))*R("09","AF")^1+(P("index")+P("Index")+P("INDEX"))*R("09")^1
-)*P(-1)
-local function stripredundant(fontdata)
- local descriptions=fontdata.descriptions
- if descriptions then
- local n=0
- local c=0
- for unicode,d in next,descriptions do
- local name=d.name
- if name and lpegmatch(p_bogusname,name) then
- d.name=nil
- n=n+1
- end
- if d.class=="base" then
- d.class=nil
- c=c+1
- end
- end
- if n>0 then
- report("%s bogus names removed (verbose unicode)",n)
- end
- if c>0 then
- report("%s base class tags removed (default is base)",c)
- end
- end
-end
-function readers.getcomponents(fontdata)
- local resources=fontdata.resources
- if resources then
- local sequences=resources.sequences
- if sequences then
- local collected={}
- for i=1,#sequences do
- local sequence=sequences[i]
- if sequence.type=="gsub_ligature" then
- local steps=sequence.steps
- if steps then
- local l={}
- local function traverse(p,k,v)
- if k=="ligature" then
- collected[v]={ unpack(l) }
- else
- insert(l,k)
- for k,vv in next,v do
- traverse(p,k,vv)
- end
- remove(l)
- end
- end
- for i=1,#steps do
- local coverage=steps[i].coverage
- if coverage then
- for k,v in next,coverage do
- traverse(k,k,v)
- end
- end
- end
- end
- end
- end
- if next(collected) then
- while true do
- local done=false
- for k,v in next,collected do
- for i=1,#v do
- local vi=v[i]
- if vi==k then
- collected[k]=nil
- break
- else
- local c=collected[vi]
- if c then
- done=true
- local t={}
- local n=i-1
- for j=1,n do
- t[j]=v[j]
- end
- for j=1,#c do
- n=n+1
- t[n]=c[j]
- end
- for j=i+1,#v do
- n=n+1
- t[n]=v[j]
- end
- collected[k]=t
- break
- end
- end
- end
- end
- if not done then
- break
- end
- end
- return collected
- end
- end
- end
-end
-readers.unifymissing=unifymissing
-function readers.rehash(fontdata,hashmethod)
- if not (fontdata and fontdata.glyphs) then
- return
- end
- if hashmethod=="indices" then
- fontdata.hashmethod="indices"
- elseif hashmethod=="names" then
- fontdata.hashmethod="names"
- local indices=unifyglyphs(fontdata,true)
- unifyresources(fontdata,indices)
- copyduplicates(fontdata)
- unifymissing(fontdata)
- else
- fontdata.hashmethod="unicode"
- local indices=unifyglyphs(fontdata)
- unifyresources(fontdata,indices)
- copyduplicates(fontdata)
- unifymissing(fontdata)
- stripredundant(fontdata)
- end
-end
-function readers.checkhash(fontdata)
- local hashmethod=fontdata.hashmethod
- if hashmethod=="unicodes" then
- fontdata.names=nil
- elseif hashmethod=="names" and fontdata.names then
- unifyresources(fontdata,fontdata.names)
- copyduplicates(fontdata)
- fontdata.hashmethod="unicode"
- fontdata.names=nil
- else
- readers.rehash(fontdata,"unicode")
- end
-end
-function readers.addunicodetable(fontdata)
- local resources=fontdata.resources
- local unicodes=resources.unicodes
- if not unicodes then
- local descriptions=fontdata.descriptions
- if descriptions then
- unicodes={}
- resources.unicodes=unicodes
- for u,d in next,descriptions do
- local n=d.name
- if n then
- unicodes[n]=u
- end
- end
- end
- end
-end
-local concat,sort=table.concat,table.sort
-local next,type,tostring=next,type,tostring
-local criterium=1
-local threshold=0
-local trace_packing=false trackers.register("otf.packing",function(v) trace_packing=v end)
-local trace_loading=false trackers.register("otf.loading",function(v) trace_loading=v end)
-local report_otf=logs.reporter("fonts","otf loading")
-local function tabstr_normal(t)
- local s={}
- local n=0
- for k,v in next,t do
- n=n+1
- if type(v)=="table" then
- s[n]=k..">"..tabstr_normal(v)
- elseif v==true then
- s[n]=k.."+"
- elseif v then
- s[n]=k.."="..v
- else
- s[n]=k.."-"
- end
- end
- if n==0 then
- return ""
- elseif n==1 then
- return s[1]
- else
- sort(s)
- return concat(s,",")
- end
-end
-local function tabstr_flat(t)
- local s={}
- local n=0
- for k,v in next,t do
- n=n+1
- s[n]=k.."="..v
- end
- if n==0 then
- return ""
- elseif n==1 then
- return s[1]
- else
- sort(s)
- return concat(s,",")
- end
-end
-local function tabstr_mixed(t)
- local s={}
- local n=#t
- if n==0 then
- return ""
- elseif n==1 then
- local k=t[1]
- if k==true then
- return "++"
- elseif k==false then
- return "--"
- else
- return tostring(k)
- end
- else
- for i=1,n do
- local k=t[i]
- if k==true then
- s[i]="++"
- elseif k==false then
- s[i]="--"
- else
- s[i]=k
- end
- end
- return concat(s,",")
- end
-end
-local function tabstr_boolean(t)
- local s={}
- local n=0
- for k,v in next,t do
- n=n+1
- if v then
- s[n]=k.."+"
- else
- s[n]=k.."-"
- end
- end
- if n==0 then
- return ""
- elseif n==1 then
- return s[1]
- else
- sort(s)
- return concat(s,",")
- end
-end
-function readers.pack(data)
- if data then
- local h,t,c={},{},{}
- local hh,tt,cc={},{},{}
- local nt,ntt=0,0
- local function pack_normal(v)
- local tag=tabstr_normal(v)
- local ht=h[tag]
- if ht then
- c[ht]=c[ht]+1
- return ht
- else
- nt=nt+1
- t[nt]=v
- h[tag]=nt
- c[nt]=1
- return nt
- end
- end
- local function pack_flat(v)
- local tag=tabstr_flat(v)
- local ht=h[tag]
- if ht then
- c[ht]=c[ht]+1
- return ht
- else
- nt=nt+1
- t[nt]=v
- h[tag]=nt
- c[nt]=1
- return nt
- end
- end
- local function pack_boolean(v)
- local tag=tabstr_boolean(v)
- local ht=h[tag]
- if ht then
- c[ht]=c[ht]+1
- return ht
- else
- nt=nt+1
- t[nt]=v
- h[tag]=nt
- c[nt]=1
- return nt
- end
- end
- local function pack_indexed(v)
- local tag=concat(v," ")
- local ht=h[tag]
- if ht then
- c[ht]=c[ht]+1
- return ht
- else
- nt=nt+1
- t[nt]=v
- h[tag]=nt
- c[nt]=1
- return nt
- end
- end
- local function pack_mixed(v)
- local tag=tabstr_mixed(v)
- local ht=h[tag]
- if ht then
- c[ht]=c[ht]+1
- return ht
- else
- nt=nt+1
- t[nt]=v
- h[tag]=nt
- c[nt]=1
- return nt
- end
- end
- local function pack_final(v)
- if c[v]<=criterium then
- return t[v]
- else
- local hv=hh[v]
- if hv then
- return hv
- else
- ntt=ntt+1
- tt[ntt]=t[v]
- hh[v]=ntt
- cc[ntt]=c[v]
- return ntt
- end
- end
- end
- local function success(stage,pass)
- if nt==0 then
- if trace_loading or trace_packing then
- report_otf("pack quality: nothing to pack")
- end
- return false
- elseif nt>=threshold then
- local one,two,rest=0,0,0
- if pass==1 then
- for k,v in next,c do
- if v==1 then
- one=one+1
- elseif v==2 then
- two=two+1
- else
- rest=rest+1
- end
- end
- else
- for k,v in next,cc do
- if v>20 then
- rest=rest+1
- elseif v>10 then
- two=two+1
- else
- one=one+1
- end
- end
- data.tables=tt
- end
- if trace_loading or trace_packing then
- report_otf("pack quality: stage %s, pass %s, %s packed, 1-10:%s, 11-20:%s, rest:%s (criterium: %s)",
- stage,pass,one+two+rest,one,two,rest,criterium)
- end
- return true
- else
- if trace_loading or trace_packing then
- report_otf("pack quality: stage %s, pass %s, %s packed, aborting pack (threshold: %s)",
- stage,pass,nt,threshold)
- end
- return false
- end
- end
- local function packers(pass)
- if pass==1 then
- return pack_normal,pack_indexed,pack_flat,pack_boolean,pack_mixed
- else
- return pack_final,pack_final,pack_final,pack_final,pack_final
- end
- end
- local resources=data.resources
- local sequences=resources.sequences
- local sublookups=resources.sublookups
- local features=resources.features
- local palettes=resources.colorpalettes
- local chardata=characters and characters.data
- local descriptions=data.descriptions or data.glyphs
- if not descriptions then
- return
- end
- for pass=1,2 do
- if trace_packing then
- report_otf("start packing: stage 1, pass %s",pass)
- end
- local pack_normal,pack_indexed,pack_flat,pack_boolean,pack_mixed=packers(pass)
- for unicode,description in next,descriptions do
- local boundingbox=description.boundingbox
- if boundingbox then
- description.boundingbox=pack_indexed(boundingbox)
- end
- local math=description.math
- if math then
- local kerns=math.kerns
- if kerns then
- for tag,kern in next,kerns do
- kerns[tag]=pack_normal(kern)
- end
- end
- end
- end
- local function packthem(sequences)
- for i=1,#sequences do
- local sequence=sequences[i]
- local kind=sequence.type
- local steps=sequence.steps
- local order=sequence.order
- local features=sequence.features
- local flags=sequence.flags
- if steps then
- for i=1,#steps do
- local step=steps[i]
- if kind=="gpos_pair" then
- local c=step.coverage
- if c then
- if step.format=="kern" then
- for g1,d1 in next,c do
- c[g1]=pack_normal(d1)
- end
- else
- for g1,d1 in next,c do
- for g2,d2 in next,d1 do
- local f=d2[1] if f then d2[1]=pack_indexed(f) end
- local s=d2[2] if s then d2[2]=pack_indexed(s) end
- end
- end
- end
- end
- elseif kind=="gpos_single" then
- local c=step.coverage
- if c then
- if step.format=="kern" then
- step.coverage=pack_normal(c)
- else
- for g1,d1 in next,c do
- c[g1]=pack_indexed(d1)
- end
- end
- end
- elseif kind=="gpos_cursive" then
- local c=step.coverage
- if c then
- for g1,d1 in next,c do
- local f=d1[2] if f then d1[2]=pack_indexed(f) end
- local s=d1[3] if s then d1[3]=pack_indexed(s) end
- end
- end
- elseif kind=="gpos_mark2base" or kind=="gpos_mark2mark" then
- local c=step.baseclasses
- if c then
- for g1,d1 in next,c do
- for g2,d2 in next,d1 do
- d1[g2]=pack_indexed(d2)
- end
- end
- end
- local c=step.coverage
- if c then
- for g1,d1 in next,c do
- d1[2]=pack_indexed(d1[2])
- end
- end
- elseif kind=="gpos_mark2ligature" then
- local c=step.baseclasses
- if c then
- for g1,d1 in next,c do
- for g2,d2 in next,d1 do
- for g3,d3 in next,d2 do
- d2[g3]=pack_indexed(d3)
- end
- end
- end
- end
- local c=step.coverage
- if c then
- for g1,d1 in next,c do
- d1[2]=pack_indexed(d1[2])
- end
- end
- end
- local rules=step.rules
- if rules then
- for i=1,#rules do
- local rule=rules[i]
- local r=rule.before if r then for i=1,#r do r[i]=pack_boolean(r[i]) end end
- local r=rule.after if r then for i=1,#r do r[i]=pack_boolean(r[i]) end end
- local r=rule.current if r then for i=1,#r do r[i]=pack_boolean(r[i]) end end
- local r=rule.lookups if r then rule.lookups=pack_mixed (r) end
- local r=rule.replacements if r then rule.replacements=pack_flat (r) end
- end
- end
- end
- end
- if order then
- sequence.order=pack_indexed(order)
- end
- if features then
- for script,feature in next,features do
- features[script]=pack_normal(feature)
- end
- end
- if flags then
- sequence.flags=pack_normal(flags)
- end
- end
- end
- if sequences then
- packthem(sequences)
- end
- if sublookups then
- packthem(sublookups)
- end
- if features then
- for k,list in next,features do
- for feature,spec in next,list do
- list[feature]=pack_normal(spec)
- end
- end
- end
- if palettes then
- for i=1,#palettes do
- local p=palettes[i]
- for j=1,#p do
- p[j]=pack_indexed(p[j])
- end
- end
- end
- if not success(1,pass) then
- return
- end
- end
- if nt>0 then
- for pass=1,2 do
- if trace_packing then
- report_otf("start packing: stage 2, pass %s",pass)
- end
- local pack_normal,pack_indexed,pack_flat,pack_boolean,pack_mixed=packers(pass)
- for unicode,description in next,descriptions do
- local math=description.math
- if math then
- local kerns=math.kerns
- if kerns then
- math.kerns=pack_normal(kerns)
- end
- end
- end
- local function packthem(sequences)
- for i=1,#sequences do
- local sequence=sequences[i]
- local kind=sequence.type
- local steps=sequence.steps
- local features=sequence.features
- if steps then
- for i=1,#steps do
- local step=steps[i]
- if kind=="gpos_pair" then
- local c=step.coverage
- if c then
- if step.format=="kern" then
- else
- for g1,d1 in next,c do
- for g2,d2 in next,d1 do
- d1[g2]=pack_normal(d2)
- end
- end
- end
- end
- end
- local rules=step.rules
- if rules then
- for i=1,#rules do
- local rule=rules[i]
- local r=rule.before if r then rule.before=pack_normal(r) end
- local r=rule.after if r then rule.after=pack_normal(r) end
- local r=rule.current if r then rule.current=pack_normal(r) end
- end
- end
- end
- end
- if features then
- sequence.features=pack_normal(features)
- end
- end
- end
- if sequences then
- packthem(sequences)
- end
- if sublookups then
- packthem(sublookups)
- end
- if not success(2,pass) then
- end
- end
- for pass=1,2 do
- if trace_packing then
- report_otf("start packing: stage 3, pass %s",pass)
- end
- local pack_normal,pack_indexed,pack_flat,pack_boolean,pack_mixed=packers(pass)
- local function packthem(sequences)
- for i=1,#sequences do
- local sequence=sequences[i]
- local kind=sequence.type
- local steps=sequence.steps
- local features=sequence.features
- if steps then
- for i=1,#steps do
- local step=steps[i]
- if kind=="gpos_pair" then
- local c=step.coverage
- if c then
- if step.format=="kern" then
- else
- for g1,d1 in next,c do
- c[g1]=pack_normal(d1)
- end
- end
- end
- end
- end
- end
- end
- end
- if sequences then
- packthem(sequences)
- end
- if sublookups then
- packthem(sublookups)
- end
- end
- end
- end
-end
-local unpacked_mt={
- __index=function(t,k)
- t[k]=false
- return k
- end
-}
-function readers.unpack(data)
- if data then
- local tables=data.tables
- if tables then
- local resources=data.resources
- local descriptions=data.descriptions or data.glyphs
- local sequences=resources.sequences
- local sublookups=resources.sublookups
- local features=resources.features
- local palettes=resources.colorpalettes
- local unpacked={}
- setmetatable(unpacked,unpacked_mt)
- for unicode,description in next,descriptions do
- local tv=tables[description.boundingbox]
- if tv then
- description.boundingbox=tv
- end
- local math=description.math
- if math then
- local kerns=math.kerns
- if kerns then
- local tm=tables[kerns]
- if tm then
- math.kerns=tm
- kerns=unpacked[tm]
- end
- if kerns then
- for k,kern in next,kerns do
- local tv=tables[kern]
- if tv then
- kerns[k]=tv
- end
- end
- end
- end
- end
- end
- local function unpackthem(sequences)
- for i=1,#sequences do
- local sequence=sequences[i]
- local kind=sequence.type
- local steps=sequence.steps
- local order=sequence.order
- local features=sequence.features
- local flags=sequence.flags
- local markclass=sequence.markclass
- if steps then
- for i=1,#steps do
- local step=steps[i]
- if kind=="gpos_pair" then
- local c=step.coverage
- if c then
- if step.format=="kern" then
- for g1,d1 in next,c do
- local tv=tables[d1]
- if tv then
- c[g1]=tv
- end
- end
- else
- for g1,d1 in next,c do
- local tv=tables[d1]
- if tv then
- c[g1]=tv
- d1=tv
- end
- for g2,d2 in next,d1 do
- local tv=tables[d2]
- if tv then
- d1[g2]=tv
- d2=tv
- end
- local f=tables[d2[1]] if f then d2[1]=f end
- local s=tables[d2[2]] if s then d2[2]=s end
- end
- end
- end
- end
- elseif kind=="gpos_single" then
- local c=step.coverage
- if c then
- if step.format=="kern" then
- local tv=tables[c]
- if tv then
- step.coverage=tv
- end
- else
- for g1,d1 in next,c do
- local tv=tables[d1]
- if tv then
- c[g1]=tv
- end
- end
- end
- end
- elseif kind=="gpos_cursive" then
- local c=step.coverage
- if c then
- for g1,d1 in next,c do
- local f=tables[d1[2]] if f then d1[2]=f end
- local s=tables[d1[3]] if s then d1[3]=s end
- end
- end
- elseif kind=="gpos_mark2base" or kind=="gpos_mark2mark" then
- local c=step.baseclasses
- if c then
- for g1,d1 in next,c do
- for g2,d2 in next,d1 do
- local tv=tables[d2]
- if tv then
- d1[g2]=tv
- end
- end
- end
- end
- local c=step.coverage
- if c then
- for g1,d1 in next,c do
- local tv=tables[d1[2]]
- if tv then
- d1[2]=tv
- end
- end
- end
- elseif kind=="gpos_mark2ligature" then
- local c=step.baseclasses
- if c then
- for g1,d1 in next,c do
- for g2,d2 in next,d1 do
- for g3,d3 in next,d2 do
- local tv=tables[d2[g3]]
- if tv then
- d2[g3]=tv
- end
- end
- end
- end
- end
- local c=step.coverage
- if c then
- for g1,d1 in next,c do
- local tv=tables[d1[2]]
- if tv then
- d1[2]=tv
- end
- end
- end
- end
- local rules=step.rules
- if rules then
- for i=1,#rules do
- local rule=rules[i]
- local before=rule.before
- if before then
- local tv=tables[before]
- if tv then
- rule.before=tv
- before=tv
- end
- for i=1,#before do
- local tv=tables[before[i]]
- if tv then
- before[i]=tv
- end
- end
- end
- local after=rule.after
- if after then
- local tv=tables[after]
- if tv then
- rule.after=tv
- after=tv
- end
- for i=1,#after do
- local tv=tables[after[i]]
- if tv then
- after[i]=tv
- end
- end
- end
- local current=rule.current
- if current then
- local tv=tables[current]
- if tv then
- rule.current=tv
- current=tv
- end
- for i=1,#current do
- local tv=tables[current[i]]
- if tv then
- current[i]=tv
- end
- end
- end
- local lookups=rule.lookups
- if lookups then
- local tv=tables[lookups]
- if tv then
- rule.lookups=tv
- end
- end
- local replacements=rule.replacements
- if replacements then
- local tv=tables[replacements]
- if tv then
- rule.replacements=tv
- end
- end
- end
- end
- end
- end
- if features then
- local tv=tables[features]
- if tv then
- sequence.features=tv
- features=tv
- end
- for script,feature in next,features do
- local tv=tables[feature]
- if tv then
- features[script]=tv
- end
- end
- end
- if order then
- local tv=tables[order]
- if tv then
- sequence.order=tv
- end
- end
- if flags then
- local tv=tables[flags]
- if tv then
- sequence.flags=tv
- end
- end
- end
- end
- if sequences then
- unpackthem(sequences)
- end
- if sublookups then
- unpackthem(sublookups)
- end
- if features then
- for k,list in next,features do
- for feature,spec in next,list do
- local tv=tables[spec]
- if tv then
- list[feature]=tv
- end
- end
- end
- end
- if palettes then
- for i=1,#palettes do
- local p=palettes[i]
- for j=1,#p do
- local tv=tables[p[j]]
- if tv then
- p[j]=tv
- end
- end
- end
- end
- data.tables=nil
- end
- end
-end
-local mt={
- __index=function(t,k)
- if k=="height" then
- local ht=t.boundingbox[4]
- return ht<0 and 0 or ht
- elseif k=="depth" then
- local dp=-t.boundingbox[2]
- return dp<0 and 0 or dp
- elseif k=="width" then
- return 0
- elseif k=="name" then
- return forcenotdef and ".notdef"
- end
- end
-}
-local function sameformat(sequence,steps,first,nofsteps,kind)
- return true
-end
-local function mergesteps_1(lookup,strict)
- local steps=lookup.steps
- local nofsteps=lookup.nofsteps
- local first=steps[1]
- if strict then
- local f=first.format
- for i=2,nofsteps do
- if steps[i].format~=f then
- report("not merging %a steps of %a lookup %a, different formats",nofsteps,lookup.type,lookup.name)
- return 0
- end
- end
- end
- report("merging %a steps of %a lookup %a",nofsteps,lookup.type,lookup.name)
- local target=first.coverage
- for i=2,nofsteps do
- for k,v in next,steps[i].coverage do
- if not target[k] then
- target[k]=v
- end
- end
- end
- lookup.nofsteps=1
- lookup.merged=true
- lookup.steps={ first }
- return nofsteps-1
-end
-local function mergesteps_2(lookup,strict)
- local steps=lookup.steps
- local nofsteps=lookup.nofsteps
- local first=steps[1]
- if strict then
- local f=first.format
- for i=2,nofsteps do
- if steps[i].format~=f then
- report("not merging %a steps of %a lookup %a, different formats",nofsteps,lookup.type,lookup.name)
- return 0
- end
- end
- end
- report("merging %a steps of %a lookup %a",nofsteps,lookup.type,lookup.name)
- local target=first.coverage
- for i=2,nofsteps do
- for k,v in next,steps[i].coverage do
- local tk=target[k]
- if tk then
- for k,v in next,v do
- if not tk[k] then
- tk[k]=v
- end
- end
- else
- target[k]=v
- end
- end
- end
- lookup.nofsteps=1
- lookup.steps={ first }
- return nofsteps-1
-end
-local function mergesteps_3(lookup,strict)
- local steps=lookup.steps
- local nofsteps=lookup.nofsteps
- local first=steps[1]
- report("merging %a steps of %a lookup %a",nofsteps,lookup.type,lookup.name)
- local baseclasses={}
- local coverage={}
- local used={}
- for i=1,nofsteps do
- local offset=i*10
- local step=steps[i]
- for k,v in sortedhash(step.baseclasses) do
- baseclasses[offset+k]=v
- end
- for k,v in next,step.coverage do
- local tk=coverage[k]
- if tk then
- for k,v in next,v do
- if not tk[k] then
- tk[k]=v
- local c=offset+v[1]
- v[1]=c
- if not used[c] then
- used[c]=true
- end
- end
- end
- else
- coverage[k]=v
- local c=offset+v[1]
- v[1]=c
- if not used[c] then
- used[c]=true
- end
- end
- end
- end
- for k,v in next,baseclasses do
- if not used[k] then
- baseclasses[k]=nil
- report("discarding not used baseclass %i",k)
- end
- end
- first.baseclasses=baseclasses
- first.coverage=coverage
- lookup.nofsteps=1
- lookup.steps={ first }
- return nofsteps-1
-end
-local function nested(old,new)
- for k,v in next,old do
- if k=="ligature" then
- if not new.ligature then
- new.ligature=v
- end
- else
- local n=new[k]
- if n then
- nested(v,n)
- else
- new[k]=v
- end
- end
- end
-end
-local function mergesteps_4(lookup)
- local steps=lookup.steps
- local nofsteps=lookup.nofsteps
- local first=steps[1]
- report("merging %a steps of %a lookup %a",nofsteps,lookup.type,lookup.name)
- local target=first.coverage
- for i=2,nofsteps do
- for k,v in next,steps[i].coverage do
- local tk=target[k]
- if tk then
- nested(v,tk)
- else
- target[k]=v
- end
- end
- end
- lookup.nofsteps=1
- lookup.steps={ first }
- return nofsteps-1
-end
-local function checkkerns(lookup)
- local steps=lookup.steps
- local nofsteps=lookup.nofsteps
- for i=1,nofsteps do
- local step=steps[i]
- if step.format=="pair" then
- local coverage=step.coverage
- local kerns=true
- for g1,d1 in next,coverage do
- if d1[1]~=0 or d1[2]~=0 or d1[4]~=0 then
- kerns=false
- break
- end
- end
- if kerns then
- report("turning pairs of step %a of %a lookup %a into kerns",i,lookup.type,lookup.name)
- for g1,d1 in next,coverage do
- coverage[g1]=d1[3]
- end
- step.format="kern"
- end
- end
- end
-end
-local function checkpairs(lookup)
- local steps=lookup.steps
- local nofsteps=lookup.nofsteps
- local kerned=0
- for i=1,nofsteps do
- local step=steps[i]
- if step.format=="pair" then
- local coverage=step.coverage
- local kerns=true
- for g1,d1 in next,coverage do
- for g2,d2 in next,d1 do
- if d2[2] then
- kerns=false
- break
- else
- local v=d2[1]
- if v[1]~=0 or v[2]~=0 or v[4]~=0 then
- kerns=false
- break
- end
- end
- end
- end
- if kerns then
- report("turning pairs of step %a of %a lookup %a into kerns",i,lookup.type,lookup.name)
- for g1,d1 in next,coverage do
- for g2,d2 in next,d1 do
- d1[g2]=d2[1][3]
- end
- end
- step.format="kern"
- kerned=kerned+1
- end
- end
- end
- return kerned
-end
-function readers.compact(data)
- if not data or data.compacted then
- return
- else
- data.compacted=true
- end
- local resources=data.resources
- local merged=0
- local kerned=0
- local allsteps=0
- local function compact(what)
- local lookups=resources[what]
- if lookups then
- for i=1,#lookups do
- local lookup=lookups[i]
- local nofsteps=lookup.nofsteps
- allsteps=allsteps+nofsteps
- if nofsteps>1 then
- local kind=lookup.type
- if kind=="gsub_single" or kind=="gsub_alternate" or kind=="gsub_multiple" then
- merged=merged+mergesteps_1(lookup)
- elseif kind=="gsub_ligature" then
- merged=merged+mergesteps_4(lookup)
- elseif kind=="gpos_single" then
- merged=merged+mergesteps_1(lookup,true)
- checkkerns(lookup)
- elseif kind=="gpos_pair" then
- merged=merged+mergesteps_2(lookup,true)
- kerned=kerned+checkpairs(lookup)
- elseif kind=="gpos_cursive" then
- merged=merged+mergesteps_2(lookup)
- elseif kind=="gpos_mark2mark" or kind=="gpos_mark2base" or kind=="gpos_mark2ligature" then
- merged=merged+mergesteps_3(lookup)
- end
- end
- end
- else
- report("no lookups in %a",what)
- end
- end
- compact("sequences")
- compact("sublookups")
- if merged>0 then
- report("%i steps of %i removed due to merging",merged,allsteps)
- end
- if kerned>0 then
- report("%i steps of %i steps turned from pairs into kerns",kerned,allsteps)
- end
-end
-function readers.expand(data)
- if not data or data.expanded then
- return
- else
- data.expanded=true
- end
- local resources=data.resources
- local sublookups=resources.sublookups
- local sequences=resources.sequences
- local markclasses=resources.markclasses
- local descriptions=data.descriptions
- if descriptions then
- local defaultwidth=resources.defaultwidth or 0
- local defaultheight=resources.defaultheight or 0
- local defaultdepth=resources.defaultdepth or 0
- local basename=trace_markwidth and file.basename(resources.filename)
- for u,d in next,descriptions do
- local bb=d.boundingbox
- local wd=d.width
- if not wd then
- d.width=defaultwidth
- elseif trace_markwidth and wd~=0 and d.class=="mark" then
- report("mark %a with width %b found in %a",d.name or "<noname>",wd,basename)
- end
- if bb then
- local ht=bb[4]
- local dp=-bb[2]
- if ht==0 or ht<0 then
- else
- d.height=ht
- end
- if dp==0 or dp<0 then
- else
- d.depth=dp
- end
- end
- end
- end
- local function expandlookups(sequences)
- if sequences then
- for i=1,#sequences do
- local sequence=sequences[i]
- local steps=sequence.steps
- if steps then
- local kind=sequence.type
- local markclass=sequence.markclass
- if markclass then
- if not markclasses then
- report_warning("missing markclasses")
- sequence.markclass=false
- else
- sequence.markclass=markclasses[markclass]
- end
- end
- for i=1,sequence.nofsteps do
- local step=steps[i]
- local baseclasses=step.baseclasses
- if baseclasses then
- local coverage=step.coverage
- for k,v in next,coverage do
- v[1]=baseclasses[v[1]]
- end
- elseif kind=="gpos_cursive" then
- local coverage=step.coverage
- for k,v in next,coverage do
- v[1]=coverage
- end
- end
- local rules=step.rules
- if rules then
- local rulehash={}
- local rulesize=0
- local coverage={}
- local lookuptype=sequence.type
- step.coverage=coverage
- for nofrules=1,#rules do
- local rule=rules[nofrules]
- local current=rule.current
- local before=rule.before
- local after=rule.after
- local replacements=rule.replacements or false
- local sequence={}
- local nofsequences=0
- if before then
- for n=1,#before do
- nofsequences=nofsequences+1
- sequence[nofsequences]=before[n]
- end
- end
- local start=nofsequences+1
- for n=1,#current do
- nofsequences=nofsequences+1
- sequence[nofsequences]=current[n]
- end
- local stop=nofsequences
- if after then
- for n=1,#after do
- nofsequences=nofsequences+1
- sequence[nofsequences]=after[n]
- end
- end
- local lookups=rule.lookups or false
- local subtype=nil
- if lookups then
- for k,v in next,lookups do
- local lookup=sublookups[v]
- if lookup then
- lookups[k]=lookup
- if not subtype then
- subtype=lookup.type
- end
- else
- end
- end
- end
- if sequence[1] then
- rulesize=rulesize+1
- rulehash[rulesize]={
- nofrules,
- lookuptype,
- sequence,
- start,
- stop,
- lookups,
- replacements,
- subtype,
- }
- for unic in next,sequence[start] do
- local cu=coverage[unic]
- if not cu then
- coverage[unic]=rulehash
- end
- end
- end
- end
- end
- end
- end
- end
- end
- end
- expandlookups(sequences)
- expandlookups(sublookups)
-end
-
-end --- [luaotfload, fontloader-2017-02-11.lua scope for “font-oup”] ---
-
-
-do --- [luaotfload, fontloader-2017-02-11.lua scope for “font-otl” 2e7c8d9a331c46826211bd507f8e488a] ---
-
-if not modules then modules={} end modules ['font-otl']={
- version=1.001,
- comment="companion to font-ini.mkiv",
- author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright="PRAGMA ADE / ConTeXt Development Team",
- license="see context related readme files",
-}
-local gmatch,find,match,lower,strip=string.gmatch,string.find,string.match,string.lower,string.strip
-local type,next,tonumber,tostring,unpack=type,next,tonumber,tostring,unpack
-local abs=math.abs
-local derivetable=table.derive
-local formatters=string.formatters
-local setmetatableindex=table.setmetatableindex
-local allocate=utilities.storage.allocate
-local registertracker=trackers.register
-local registerdirective=directives.register
-local starttiming=statistics.starttiming
-local stoptiming=statistics.stoptiming
-local elapsedtime=statistics.elapsedtime
-local findbinfile=resolvers.findbinfile
-local trace_loading=false registertracker("otf.loading",function(v) trace_loading=v end)
-local trace_features=false registertracker("otf.features",function(v) trace_features=v end)
-local trace_defining=false registertracker("fonts.defining",function(v) trace_defining=v end)
-local report_otf=logs.reporter("fonts","otf loading")
-local fonts=fonts
-local otf=fonts.handlers.otf
-otf.version=3.027
-otf.cache=containers.define("fonts","otl",otf.version,true)
-otf.svgcache=containers.define("fonts","svg",otf.version,true)
-otf.pdfcache=containers.define("fonts","pdf",otf.version,true)
-otf.svgenabled=false
-local otfreaders=otf.readers
-local hashes=fonts.hashes
-local definers=fonts.definers
-local readers=fonts.readers
-local constructors=fonts.constructors
-local otffeatures=constructors.features.otf
-local registerotffeature=otffeatures.register
-local otfenhancers=constructors.enhancers.otf
-local registerotfenhancer=otfenhancers.register
-local forceload=false
-local cleanup=0
-local syncspace=true
-local forcenotdef=false
-local applyruntimefixes=fonts.treatments and fonts.treatments.applyfixes
-local wildcard="*"
-local default="dflt"
-local formats=fonts.formats
-formats.otf="opentype"
-formats.ttf="truetype"
-formats.ttc="truetype"
-registerdirective("fonts.otf.loader.cleanup",function(v) cleanup=tonumber(v) or (v and 1) or 0 end)
-registerdirective("fonts.otf.loader.force",function(v) forceload=v end)
-registerdirective("fonts.otf.loader.syncspace",function(v) syncspace=v end)
-registerdirective("fonts.otf.loader.forcenotdef",function(v) forcenotdef=v end)
-registerotfenhancer("check extra features",function() end)
-function otf.load(filename,sub,featurefile)
- local featurefile=nil
- local base=file.basename(file.removesuffix(filename))
- local name=file.removesuffix(base)
- local attr=lfs.attributes(filename)
- local size=attr and attr.size or 0
- local time=attr and attr.modification or 0
- if featurefile then
- name=name.."@"..file.removesuffix(file.basename(featurefile))
- end
- if sub=="" then
- sub=false
- end
- local hash=name
- if sub then
- hash=hash.."-"..sub
- end
- hash=containers.cleanname(hash)
- local featurefiles
- if featurefile then
- featurefiles={}
- for s in gmatch(featurefile,"[^,]+") do
- local name=resolvers.findfile(file.addsuffix(s,'fea'),'fea') or ""
- if name=="" then
- report_otf("loading error, no featurefile %a",s)
- else
- local attr=lfs.attributes(name)
- featurefiles[#featurefiles+1]={
- name=name,
- size=attr and attr.size or 0,
- time=attr and attr.modification or 0,
- }
- end
- end
- if #featurefiles==0 then
- featurefiles=nil
- end
- end
- local data=containers.read(otf.cache,hash)
- local reload=not data or data.size~=size or data.time~=time or data.tableversion~=otfreaders.tableversion
- if forceload then
- report_otf("forced reload of %a due to hard coded flag",filename)
- reload=true
- end
- if reload then
- report_otf("loading %a, hash %a",filename,hash)
- starttiming(otfreaders)
- data=otfreaders.loadfont(filename,sub or 1)
- if data then
- local resources=data.resources
- local svgshapes=resources.svgshapes
- if svgshapes then
- resources.svgshapes=nil
- if otf.svgenabled then
- local timestamp=os.date()
- containers.write(otf.svgcache,hash,{
- svgshapes=svgshapes,
- timestamp=timestamp,
- })
- data.properties.svg={
- hash=hash,
- timestamp=timestamp,
- }
- end
- end
- otfreaders.compact(data)
- otfreaders.rehash(data,"unicodes")
- otfreaders.addunicodetable(data)
- otfreaders.extend(data)
- otfreaders.pack(data)
- report_otf("loading done")
- report_otf("saving %a in cache",filename)
- data=containers.write(otf.cache,hash,data)
- if cleanup>1 then
- collectgarbage("collect")
- end
- stoptiming(otfreaders)
- if elapsedtime then
- report_otf("loading, optimizing, packing and caching time %s",elapsedtime(otfreaders))
- end
- if cleanup>3 then
- collectgarbage("collect")
- end
- data=containers.read(otf.cache,hash)
- if cleanup>2 then
- collectgarbage("collect")
- end
- else
- data=nil
- report_otf("loading failed due to read error")
- end
- end
- if data then
- if trace_defining then
- report_otf("loading from cache using hash %a",hash)
- end
- otfreaders.unpack(data)
- otfreaders.expand(data)
- otfreaders.addunicodetable(data)
- otfenhancers.apply(data,filename,data)
- if applyruntimefixes then
- applyruntimefixes(filename,data)
- end
- data.metadata.math=data.resources.mathconstants
- end
- return data
-end
-function otf.setfeatures(tfmdata,features)
- local okay=constructors.initializefeatures("otf",tfmdata,features,trace_features,report_otf)
- if okay then
- return constructors.collectprocessors("otf",tfmdata,features,trace_features,report_otf)
- else
- return {}
- end
-end
-local function copytotfm(data,cache_id)
- if data then
- local metadata=data.metadata
- local properties=derivetable(data.properties)
- local descriptions=derivetable(data.descriptions)
- local goodies=derivetable(data.goodies)
- local characters={}
- local parameters={}
- local mathparameters={}
- local resources=data.resources
- local unicodes=resources.unicodes
- local spaceunits=500
- local spacer="space"
- local designsize=metadata.designsize or 100
- local minsize=metadata.minsize or designsize
- local maxsize=metadata.maxsize or designsize
- local mathspecs=metadata.math
- if designsize==0 then
- designsize=100
- minsize=100
- maxsize=100
- end
- if mathspecs then
- for name,value in next,mathspecs do
- mathparameters[name]=value
- end
- end
- for unicode in next,data.descriptions do
- characters[unicode]={}
- end
- if mathspecs then
- for unicode,character in next,characters do
- local d=descriptions[unicode]
- local m=d.math
- if m then
- local italic=m.italic
- local vitalic=m.vitalic
- local variants=m.hvariants
- local parts=m.hparts
- if variants then
- local c=character
- for i=1,#variants do
- local un=variants[i]
- c.next=un
- c=characters[un]
- end
- c.horiz_variants=parts
- elseif parts then
- character.horiz_variants=parts
- italic=m.hitalic
- end
- local variants=m.vvariants
- local parts=m.vparts
- if variants then
- local c=character
- for i=1,#variants do
- local un=variants[i]
- c.next=un
- c=characters[un]
- end
- c.vert_variants=parts
- elseif parts then
- character.vert_variants=parts
- end
- if italic and italic~=0 then
- character.italic=italic
- end
- if vitalic and vitalic~=0 then
- character.vert_italic=vitalic
- end
- local accent=m.accent
- if accent then
- character.accent=accent
- end
- local kerns=m.kerns
- if kerns then
- character.mathkerns=kerns
- end
- end
- end
- end
- local filename=constructors.checkedfilename(resources)
- local fontname=metadata.fontname
- local fullname=metadata.fullname or fontname
- local psname=fontname or fullname
- local units=metadata.units or 1000
- if units==0 then
- units=1000
- metadata.units=1000
- report_otf("changing %a units to %a",0,units)
- end
- local monospaced=metadata.monospaced
- local charwidth=metadata.averagewidth
- local charxheight=metadata.xheight
- local italicangle=metadata.italicangle
- local hasitalics=metadata.hasitalics
- properties.monospaced=monospaced
- properties.hasitalics=hasitalics
- parameters.italicangle=italicangle
- parameters.charwidth=charwidth
- parameters.charxheight=charxheight
- local space=0x0020
- local emdash=0x2014
- if monospaced then
- if descriptions[space] then
- spaceunits,spacer=descriptions[space].width,"space"
- end
- if not spaceunits and descriptions[emdash] then
- spaceunits,spacer=descriptions[emdash].width,"emdash"
- end
- if not spaceunits and charwidth then
- spaceunits,spacer=charwidth,"charwidth"
- end
- else
- if descriptions[space] then
- spaceunits,spacer=descriptions[space].width,"space"
- end
- if not spaceunits and descriptions[emdash] then
- spaceunits,spacer=descriptions[emdash].width/2,"emdash/2"
- end
- if not spaceunits and charwidth then
- spaceunits,spacer=charwidth,"charwidth"
- end
- end
- spaceunits=tonumber(spaceunits) or units/2
- parameters.slant=0
- parameters.space=spaceunits
- parameters.space_stretch=1*units/2
- parameters.space_shrink=1*units/3
- parameters.x_height=2*units/5
- parameters.quad=units
- if spaceunits<2*units/5 then
- end
- if italicangle and italicangle~=0 then
- parameters.italicangle=italicangle
- parameters.italicfactor=math.cos(math.rad(90+italicangle))
- parameters.slant=- math.tan(italicangle*math.pi/180)
- end
- if monospaced then
- parameters.space_stretch=0
- parameters.space_shrink=0
- elseif syncspace then
- parameters.space_stretch=spaceunits/2
- parameters.space_shrink=spaceunits/3
- end
- parameters.extra_space=parameters.space_shrink
- if charxheight then
- parameters.x_height=charxheight
- else
- local x=0x0078
- if x then
- local x=descriptions[x]
- if x then
- parameters.x_height=x.height
- end
- end
- end
- parameters.designsize=(designsize/10)*65536
- parameters.minsize=(minsize/10)*65536
- parameters.maxsize=(maxsize/10)*65536
- parameters.ascender=abs(metadata.ascender or 0)
- parameters.descender=abs(metadata.descender or 0)
- parameters.units=units
- properties.space=spacer
- properties.encodingbytes=2
- properties.format=data.format or formats.otf
- properties.noglyphnames=true
- properties.filename=filename
- properties.fontname=fontname
- properties.fullname=fullname
- properties.psname=psname
- properties.name=filename or fullname
- return {
- characters=characters,
- descriptions=descriptions,
- parameters=parameters,
- mathparameters=mathparameters,
- resources=resources,
- properties=properties,
- goodies=goodies,
- }
- end
-end
-local converters={
- woff={
- cachename="webfonts",
- action=otf.readers.woff2otf,
- }
-}
-local function checkconversion(specification)
- local filename=specification.filename
- local converter=converters[lower(file.suffix(filename))]
- if converter then
- local base=file.basename(filename)
- local name=file.removesuffix(base)
- local attr=lfs.attributes(filename)
- local size=attr and attr.size or 0
- local time=attr and attr.modification or 0
- if size>0 then
- local cleanname=containers.cleanname(name)
- local cachename=caches.setfirstwritablefile(cleanname,converter.cachename)
- if not io.exists(cachename) or (time~=lfs.attributes(cachename).modification) then
- report_otf("caching font %a in %a",filename,cachename)
- converter.action(filename,cachename)
- lfs.touch(cachename,time,time)
- end
- specification.filename=cachename
- end
- end
-end
-local function otftotfm(specification)
- local cache_id=specification.hash
- local tfmdata=containers.read(constructors.cache,cache_id)
- if not tfmdata then
- checkconversion(specification)
- local name=specification.name
- local sub=specification.sub
- local subindex=specification.subindex
- local filename=specification.filename
- local features=specification.features.normal
- local rawdata=otf.load(filename,sub,features and features.featurefile)
- if rawdata and next(rawdata) then
- local descriptions=rawdata.descriptions
- rawdata.lookuphash={}
- tfmdata=copytotfm(rawdata,cache_id)
- if tfmdata and next(tfmdata) then
- local features=constructors.checkedfeatures("otf",features)
- local shared=tfmdata.shared
- if not shared then
- shared={}
- tfmdata.shared=shared
- end
- shared.rawdata=rawdata
- shared.dynamics={}
- tfmdata.changed={}
- shared.features=features
- shared.processes=otf.setfeatures(tfmdata,features)
- end
- end
- containers.write(constructors.cache,cache_id,tfmdata)
- end
- return tfmdata
-end
-local function read_from_otf(specification)
- local tfmdata=otftotfm(specification)
- if tfmdata then
- tfmdata.properties.name=specification.name
- tfmdata.properties.sub=specification.sub
- tfmdata=constructors.scale(tfmdata,specification)
- local allfeatures=tfmdata.shared.features or specification.features.normal
- constructors.applymanipulators("otf",tfmdata,allfeatures,trace_features,report_otf)
- constructors.setname(tfmdata,specification)
- fonts.loggers.register(tfmdata,file.suffix(specification.filename),specification)
- end
- return tfmdata
-end
-local function checkmathsize(tfmdata,mathsize)
- local mathdata=tfmdata.shared.rawdata.metadata.math
- local mathsize=tonumber(mathsize)
- if mathdata then
- local parameters=tfmdata.parameters
- parameters.scriptpercentage=mathdata.ScriptPercentScaleDown
- parameters.scriptscriptpercentage=mathdata.ScriptScriptPercentScaleDown
- parameters.mathsize=mathsize
- end
-end
-registerotffeature {
- name="mathsize",
- description="apply mathsize specified in the font",
- initializers={
- base=checkmathsize,
- node=checkmathsize,
- }
-}
-function otf.collectlookups(rawdata,kind,script,language)
- if not kind then
- return
- end
- if not script then
- script=default
- end
- if not language then
- language=default
- end
- local lookupcache=rawdata.lookupcache
- if not lookupcache then
- lookupcache={}
- rawdata.lookupcache=lookupcache
- end
- local kindlookup=lookupcache[kind]
- if not kindlookup then
- kindlookup={}
- lookupcache[kind]=kindlookup
- end
- local scriptlookup=kindlookup[script]
- if not scriptlookup then
- scriptlookup={}
- kindlookup[script]=scriptlookup
- end
- local languagelookup=scriptlookup[language]
- if not languagelookup then
- local sequences=rawdata.resources.sequences
- local featuremap={}
- local featurelist={}
- if sequences then
- for s=1,#sequences do
- local sequence=sequences[s]
- local features=sequence.features
- if features then
- features=features[kind]
- if features then
- features=features[script] or features[wildcard]
- if features then
- features=features[language] or features[wildcard]
- if features then
- if not featuremap[sequence] then
- featuremap[sequence]=true
- featurelist[#featurelist+1]=sequence
- end
- end
- end
- end
- end
- end
- if #featurelist==0 then
- featuremap,featurelist=false,false
- end
- else
- featuremap,featurelist=false,false
- end
- languagelookup={ featuremap,featurelist }
- scriptlookup[language]=languagelookup
- end
- return unpack(languagelookup)
-end
-local function getgsub(tfmdata,k,kind,value)
- local shared=tfmdata.shared
- local rawdata=shared and shared.rawdata
- if rawdata then
- local sequences=rawdata.resources.sequences
- if sequences then
- local properties=tfmdata.properties
- local validlookups,lookuplist=otf.collectlookups(rawdata,kind,properties.script,properties.language)
- if validlookups then
- for i=1,#lookuplist do
- local lookup=lookuplist[i]
- local steps=lookup.steps
- local nofsteps=lookup.nofsteps
- for i=1,nofsteps do
- local coverage=steps[i].coverage
- if coverage then
- local found=coverage[k]
- if found then
- return found,lookup.type
- end
- end
- end
- end
- end
- end
- end
-end
-otf.getgsub=getgsub
-function otf.getsubstitution(tfmdata,k,kind,value)
- local found,kind=getgsub(tfmdata,k,kind,value)
- if not found then
- elseif kind=="gsub_single" then
- return found
- elseif kind=="gsub_alternate" then
- local choice=tonumber(value) or 1
- return found[choice] or found[1] or k
- end
- return k
-end
-otf.getalternate=otf.getsubstitution
-function otf.getmultiple(tfmdata,k,kind)
- local found,kind=getgsub(tfmdata,k,kind)
- if found and kind=="gsub_multiple" then
- return found
- end
- return { k }
-end
-function otf.getkern(tfmdata,left,right,kind)
- local kerns=getgsub(tfmdata,left,kind or "kern",true)
- if kerns then
- local found=kerns[right]
- local kind=type(found)
- if kind=="table" then
- found=found[1][3]
- elseif kind~="number" then
- found=false
- end
- if found then
- return found*tfmdata.parameters.factor
- end
- end
- return 0
-end
-local function check_otf(forced,specification,suffix)
- local name=specification.name
- if forced then
- name=specification.forcedname
- end
- local fullname=findbinfile(name,suffix) or ""
- if fullname=="" then
- fullname=fonts.names.getfilename(name,suffix) or ""
- end
- if fullname~="" and not fonts.names.ignoredfile(fullname) then
- specification.filename=fullname
- return read_from_otf(specification)
- end
-end
-local function opentypereader(specification,suffix)
- local forced=specification.forced or ""
- if formats[forced] then
- return check_otf(true,specification,forced)
- else
- return check_otf(false,specification,suffix)
- end
-end
-readers.opentype=opentypereader
-function readers.otf(specification) return opentypereader(specification,"otf") end
-function readers.ttf(specification) return opentypereader(specification,"ttf") end
-function readers.ttc(specification) return opentypereader(specification,"ttf") end
-function readers.woff(specification)
- checkconversion(specification)
- opentypereader(specification,"")
-end
-function otf.scriptandlanguage(tfmdata,attr)
- local properties=tfmdata.properties
- return properties.script or "dflt",properties.language or "dflt"
-end
-local function justset(coverage,unicode,replacement)
- coverage[unicode]=replacement
-end
-otf.coverup={
- stepkey="steps",
- actions={
- chainsubstitution=justset,
- chainposition=justset,
- substitution=justset,
- alternate=justset,
- multiple=justset,
- kern=justset,
- pair=justset,
- ligature=function(coverage,unicode,ligature)
- local first=ligature[1]
- local tree=coverage[first]
- if not tree then
- tree={}
- coverage[first]=tree
- end
- for i=2,#ligature do
- local l=ligature[i]
- local t=tree[l]
- if not t then
- t={}
- tree[l]=t
- end
- tree=t
- end
- tree.ligature=unicode
- end,
- },
- register=function(coverage,featuretype,format)
- return {
- format=format,
- coverage=coverage,
- }
- end
-}
-
-end --- [luaotfload, fontloader-2017-02-11.lua scope for “font-otl”] ---
-
-
-do --- [luaotfload, fontloader-2017-02-11.lua scope for “font-oto” 5fbdd899624d4eef639f81b580afe9aa] ---
-
-if not modules then modules={} end modules ['font-oto']={
- version=1.001,
- comment="companion to font-ini.mkiv",
- author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright="PRAGMA ADE / ConTeXt Development Team",
- license="see context related readme files"
-}
-local concat,unpack=table.concat,table.unpack
-local insert,remove=table.insert,table.remove
-local format,gmatch,gsub,find,match,lower,strip=string.format,string.gmatch,string.gsub,string.find,string.match,string.lower,string.strip
-local type,next,tonumber,tostring,rawget=type,next,tonumber,tostring,rawget
-local trace_baseinit=false trackers.register("otf.baseinit",function(v) trace_baseinit=v end)
-local trace_singles=false trackers.register("otf.singles",function(v) trace_singles=v end)
-local trace_multiples=false trackers.register("otf.multiples",function(v) trace_multiples=v end)
-local trace_alternatives=false trackers.register("otf.alternatives",function(v) trace_alternatives=v end)
-local trace_ligatures=false trackers.register("otf.ligatures",function(v) trace_ligatures=v end)
-local trace_kerns=false trackers.register("otf.kerns",function(v) trace_kerns=v end)
-local trace_preparing=false trackers.register("otf.preparing",function(v) trace_preparing=v end)
-local report_prepare=logs.reporter("fonts","otf prepare")
-local fonts=fonts
-local otf=fonts.handlers.otf
-local otffeatures=otf.features
-local registerotffeature=otffeatures.register
-otf.defaultbasealternate="none"
-local wildcard="*"
-local default="dflt"
-local formatters=string.formatters
-local f_unicode=formatters["%U"]
-local f_uniname=formatters["%U (%s)"]
-local f_unilist=formatters["% t (% t)"]
-local function gref(descriptions,n)
- if type(n)=="number" then
- local name=descriptions[n].name
- if name then
- return f_uniname(n,name)
- else
- return f_unicode(n)
- end
- elseif n then
- local num,nam,j={},{},0
- for i=1,#n do
- local ni=n[i]
- if tonumber(ni) then
- j=j+1
- local di=descriptions[ni]
- num[j]=f_unicode(ni)
- nam[j]=di and di.name or "-"
- end
- end
- return f_unilist(num,nam)
- else
- return "<error in base mode tracing>"
- end
-end
-local function cref(feature,sequence)
- return formatters["feature %a, type %a, chain lookup %a"](feature,sequence.type,sequence.name)
-end
-local function report_alternate(feature,sequence,descriptions,unicode,replacement,value,comment)
- report_prepare("%s: base alternate %s => %s (%S => %S)",
- cref(feature,sequence),
- gref(descriptions,unicode),
- replacement and gref(descriptions,replacement),
- value,
- comment)
-end
-local function report_substitution(feature,sequence,descriptions,unicode,substitution)
- report_prepare("%s: base substitution %s => %S",
- cref(feature,sequence),
- gref(descriptions,unicode),
- gref(descriptions,substitution))
-end
-local function report_ligature(feature,sequence,descriptions,unicode,ligature)
- report_prepare("%s: base ligature %s => %S",
- cref(feature,sequence),
- gref(descriptions,ligature),
- gref(descriptions,unicode))
-end
-local function report_kern(feature,sequence,descriptions,unicode,otherunicode,value)
- report_prepare("%s: base kern %s + %s => %S",
- cref(feature,sequence),
- gref(descriptions,unicode),
- gref(descriptions,otherunicode),
- value)
-end
-local basehash,basehashes,applied={},1,{}
-local function registerbasehash(tfmdata)
- local properties=tfmdata.properties
- local hash=concat(applied," ")
- local base=basehash[hash]
- if not base then
- basehashes=basehashes+1
- base=basehashes
- basehash[hash]=base
- end
- properties.basehash=base
- properties.fullname=(properties.fullname or properties.name).."-"..base
- applied={}
-end
-local function registerbasefeature(feature,value)
- applied[#applied+1]=feature.."="..tostring(value)
-end
-local function makefake(tfmdata,name,present)
- local resources=tfmdata.resources
- local private=resources.private
- local character={ intermediate=true,ligatures={} }
- resources.unicodes[name]=private
- tfmdata.characters[private]=character
- tfmdata.descriptions[private]={ name=name }
- resources.private=private+1
- present[name]=private
- return character
-end
-local function make_1(present,tree,name)
- for k,v in next,tree do
- if k=="ligature" then
- present[name]=v
- else
- make_1(present,v,name.."_"..k)
- end
- end
-end
-local function make_2(present,tfmdata,characters,tree,name,preceding,unicode,done)
- for k,v in next,tree do
- if k=="ligature" then
- local character=characters[preceding]
- if not character then
- if trace_baseinit then
- report_prepare("weird ligature in lookup %a, current %C, preceding %C",sequence.name,v,preceding)
- end
- character=makefake(tfmdata,name,present)
- end
- local ligatures=character.ligatures
- if ligatures then
- ligatures[unicode]={ char=v }
- else
- character.ligatures={ [unicode]={ char=v } }
- end
- if done then
- local d=done[name]
- if not d then
- done[name]={ "dummy",v }
- else
- d[#d+1]=v
- end
- end
- else
- local code=present[name] or unicode
- local name=name.."_"..k
- make_2(present,tfmdata,characters,v,name,code,k,done)
- end
- end
-end
-local function preparesubstitutions(tfmdata,feature,value,validlookups,lookuplist)
- local characters=tfmdata.characters
- local descriptions=tfmdata.descriptions
- local resources=tfmdata.resources
- local changed=tfmdata.changed
- local ligatures={}
- local alternate=tonumber(value) or true and 1
- local defaultalt=otf.defaultbasealternate
- local trace_singles=trace_baseinit and trace_singles
- local trace_alternatives=trace_baseinit and trace_alternatives
- local trace_ligatures=trace_baseinit and trace_ligatures
- if not changed then
- changed={}
- tfmdata.changed=changed
- end
- for i=1,#lookuplist do
- local sequence=lookuplist[i]
- local steps=sequence.steps
- local kind=sequence.type
- if kind=="gsub_single" then
- for i=1,#steps do
- for unicode,data in next,steps[i].coverage do
- if trace_singles then
- report_substitution(feature,sequence,descriptions,unicode,data)
- end
- changed[unicode]=data
- end
- end
- elseif kind=="gsub_alternate" then
- for i=1,#steps do
- for unicode,data in next,steps[i].coverage do
- if not changed[unicode] then
- local replacement=data[alternate]
- if replacement then
- changed[unicode]=replacement
- if trace_alternatives then
- report_alternate(feature,sequence,descriptions,unicode,replacement,value,"normal")
- end
- elseif defaultalt=="first" then
- replacement=data[1]
- changed[unicode]=replacement
- if trace_alternatives then
- report_alternate(feature,sequence,descriptions,unicode,replacement,value,defaultalt)
- end
- elseif defaultalt=="last" then
- replacement=data[#data]
- if trace_alternatives then
- report_alternate(feature,sequence,descriptions,unicode,replacement,value,defaultalt)
- end
- else
- if trace_alternatives then
- report_alternate(feature,sequence,descriptions,unicode,replacement,value,"unknown")
- end
- end
- end
- end
- end
- elseif kind=="gsub_ligature" then
- for i=1,#steps do
- for unicode,data in next,steps[i].coverage do
- ligatures[#ligatures+1]={ unicode,data,"" }
- if trace_ligatures then
- report_ligature(feature,sequence,descriptions,unicode,data)
- end
- end
- end
- end
- end
- local nofligatures=#ligatures
- if nofligatures>0 then
- local characters=tfmdata.characters
- local present={}
- local done=trace_baseinit and trace_ligatures and {}
- for i=1,nofligatures do
- local ligature=ligatures[i]
- local unicode,tree=ligature[1],ligature[2]
- make_1(present,tree,"ctx_"..unicode)
- end
- for i=1,nofligatures do
- local ligature=ligatures[i]
- local unicode,tree,lookupname=ligature[1],ligature[2],ligature[3]
- make_2(present,tfmdata,characters,tree,"ctx_"..unicode,unicode,unicode,done,sequence)
- end
- end
-end
-local function preparepositionings(tfmdata,feature,value,validlookups,lookuplist)
- local characters=tfmdata.characters
- local descriptions=tfmdata.descriptions
- local resources=tfmdata.resources
- local properties=tfmdata.properties
- local traceindeed=trace_baseinit and trace_kerns
- for i=1,#lookuplist do
- local sequence=lookuplist[i]
- local steps=sequence.steps
- local kind=sequence.type
- local format=sequence.format
- if kind=="gpos_pair" then
- for i=1,#steps do
- local step=steps[i]
- if step.format=="kern" then
- for unicode,data in next,steps[i].coverage do
- local character=characters[unicode]
- local kerns=character.kerns
- if not kerns then
- kerns={}
- character.kerns=kerns
- end
- if traceindeed then
- for otherunicode,kern in next,data do
- if not kerns[otherunicode] and kern~=0 then
- kerns[otherunicode]=kern
- report_kern(feature,sequence,descriptions,unicode,otherunicode,kern)
- end
- end
- else
- for otherunicode,kern in next,data do
- if not kerns[otherunicode] and kern~=0 then
- kerns[otherunicode]=kern
- end
- end
- end
- end
- else
- for unicode,data in next,steps[i].coverage do
- local character=characters[unicode]
- local kerns=character.kerns
- for otherunicode,kern in next,data do
- if not kern[2] and not (kerns and kerns[otherunicode]) then
- local kern=kern[1]
- if kern[1]~=0 or kern[2]~=0 or kern[4]~=0 then
- else
- kern=kern[3]
- if kern~=0 then
- if kerns then
- kerns[otherunicode]=kern
- else
- kerns={ [otherunicode]=kern }
- character.kerns=kerns
- end
- if traceindeed then
- report_kern(feature,sequence,descriptions,unicode,otherunicode,kern)
- end
- end
- end
- end
- end
- end
- end
- end
- end
- end
-end
-local function initializehashes(tfmdata)
-end
-local function featuresinitializer(tfmdata,value)
- if true then
- local starttime=trace_preparing and os.clock()
- local features=tfmdata.shared.features
- local fullname=tfmdata.properties.fullname or "?"
- if features then
- initializehashes(tfmdata)
- local collectlookups=otf.collectlookups
- local rawdata=tfmdata.shared.rawdata
- local properties=tfmdata.properties
- local script=properties.script
- local language=properties.language
- local rawresources=rawdata.resources
- local rawfeatures=rawresources and rawresources.features
- local basesubstitutions=rawfeatures and rawfeatures.gsub
- local basepositionings=rawfeatures and rawfeatures.gpos
- if basesubstitutions or basepositionings then
- local sequences=tfmdata.resources.sequences
- for s=1,#sequences do
- local sequence=sequences[s]
- local sfeatures=sequence.features
- if sfeatures then
- local order=sequence.order
- if order then
- for i=1,#order do
- local feature=order[i]
- local value=features[feature]
- if value then
- local validlookups,lookuplist=collectlookups(rawdata,feature,script,language)
- if not validlookups then
- elseif basesubstitutions and basesubstitutions[feature] then
- if trace_preparing then
- report_prepare("filtering base %s feature %a for %a with value %a","sub",feature,fullname,value)
- end
- preparesubstitutions(tfmdata,feature,value,validlookups,lookuplist)
- registerbasefeature(feature,value)
- elseif basepositionings and basepositionings[feature] then
- if trace_preparing then
- report_prepare("filtering base %a feature %a for %a with value %a","pos",feature,fullname,value)
- end
- preparepositionings(tfmdata,feature,value,validlookups,lookuplist)
- registerbasefeature(feature,value)
- end
- end
- end
- end
- end
- end
- end
- registerbasehash(tfmdata)
- end
- if trace_preparing then
- report_prepare("preparation time is %0.3f seconds for %a",os.clock()-starttime,fullname)
- end
- end
-end
-registerotffeature {
- name="features",
- description="features",
- default=true,
- initializers={
- base=featuresinitializer,
- }
-}
-otf.basemodeinitializer=featuresinitializer
-
-end --- [luaotfload, fontloader-2017-02-11.lua scope for “font-oto”] ---
-
-
-do --- [luaotfload, fontloader-2017-02-11.lua scope for “font-otj” 5ea70db9f1990dc1459425853c79f663] ---
-
-if not modules then modules={} end modules ['font-otj']={
- version=1.001,
- comment="companion to font-lib.mkiv",
- author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright="PRAGMA ADE / ConTeXt Development Team",
- license="see context related readme files",
-}
-if not nodes.properties then return end
-local next,rawget=next,rawget
-local fastcopy=table.fastcopy
-local registertracker=trackers.register
-local trace_injections=false registertracker("fonts.injections",function(v) trace_injections=v end)
-local trace_marks=false registertracker("fonts.injections.marks",function(v) trace_marks=v end)
-local trace_cursive=false registertracker("fonts.injections.cursive",function(v) trace_cursive=v end)
-local trace_spaces=false registertracker("fonts.injections.spaces",function(v) trace_spaces=v end)
-local use_advance=false directives.register("fonts.injections.advance",function(v) use_advance=v end)
-local report_injections=logs.reporter("fonts","injections")
-local report_spaces=logs.reporter("fonts","spaces")
-local attributes,nodes,node=attributes,nodes,node
-fonts=fonts
-local hashes=fonts.hashes
-local fontdata=hashes.identifiers
-nodes.injections=nodes.injections or {}
-local injections=nodes.injections
-local tracers=nodes.tracers
-local setcolor=tracers and tracers.colors.set
-local resetcolor=tracers and tracers.colors.reset
-local nodecodes=nodes.nodecodes
-local glyph_code=nodecodes.glyph
-local disc_code=nodecodes.disc
-local kern_code=nodecodes.kern
-local glue_code=nodecodes.glue
-local nuts=nodes.nuts
-local nodepool=nuts.pool
-local newkern=nodepool.kern
-local tonode=nuts.tonode
-local tonut=nuts.tonut
-local getfield=nuts.getfield
-local setfield=nuts.setfield
-local getnext=nuts.getnext
-local getprev=nuts.getprev
-local getid=nuts.getid
-local getfont=nuts.getfont
-local getsubtype=nuts.getsubtype
-local getchar=nuts.getchar
-local getboth=nuts.getboth
-local ischar=nuts.is_char
-local getdisc=nuts.getdisc
-local setdisc=nuts.setdisc
-local traverse_id=nuts.traverse_id
-local traverse_char=nuts.traverse_char
-local insert_node_before=nuts.insert_before
-local insert_node_after=nuts.insert_after
-local properties=nodes.properties.data
-function injections.installnewkern(nk)
- newkern=nk or newkern
-end
-local nofregisteredkerns=0
-local nofregisteredpairs=0
-local nofregisteredmarks=0
-local nofregisteredcursives=0
-local keepregisteredcounts=false
-function injections.keepcounts()
- keepregisteredcounts=true
-end
-function injections.resetcounts()
- nofregisteredkerns=0
- nofregisteredpairs=0
- nofregisteredmarks=0
- nofregisteredcursives=0
- keepregisteredcounts=false
-end
-function injections.reset(n)
- local p=rawget(properties,n)
- if p then
- p.injections=false
- else
- properties[n]=false
- end
-end
-function injections.copy(target,source)
- local sp=rawget(properties,source)
- if sp then
- local tp=rawget(properties,target)
- local si=sp.injections
- if si then
- si=fastcopy(si)
- if tp then
- tp.injections=si
- else
- propertydata[target]={
- injections=si,
- }
- end
- elseif tp then
- tp.injections=false
- else
- properties[target]={ injections={} }
- end
- else
- local tp=rawget(properties,target)
- if tp then
- tp.injections=false
- else
- properties[target]=false
- end
- end
-end
-function injections.setligaindex(n,index)
- local p=rawget(properties,n)
- if p then
- local i=p.injections
- if i then
- i.ligaindex=index
- else
- p.injections={
- ligaindex=index
- }
- end
- else
- properties[n]={
- injections={
- ligaindex=index
- }
- }
- end
-end
-function injections.getligaindex(n,default)
- local p=rawget(properties,n)
- if p then
- local i=p.injections
- if i then
- return i.ligaindex or default
- end
- end
- return default
-end
-function injections.setcursive(start,nxt,factor,rlmode,exit,entry,tfmstart,tfmnext)
- local dx=factor*(exit[1]-entry[1])
- local dy=-factor*(exit[2]-entry[2])
- local ws=tfmstart.width
- local wn=tfmnext.width
- nofregisteredcursives=nofregisteredcursives+1
- if rlmode<0 then
- dx=-(dx+wn)
- else
- dx=dx-ws
- end
- if dx==0 then
- dx=0
- end
- local p=rawget(properties,start)
- if p then
- local i=p.injections
- if i then
- i.cursiveanchor=true
- else
- p.injections={
- cursiveanchor=true,
- }
- end
- else
- properties[start]={
- injections={
- cursiveanchor=true,
- },
- }
- end
- local p=rawget(properties,nxt)
- if p then
- local i=p.injections
- if i then
- i.cursivex=dx
- i.cursivey=dy
- else
- p.injections={
- cursivex=dx,
- cursivey=dy,
- }
- end
- else
- properties[nxt]={
- injections={
- cursivex=dx,
- cursivey=dy,
- },
- }
- end
- return dx,dy,nofregisteredcursives
-end
-function injections.setpair(current,factor,rlmode,r2lflag,spec,injection)
- local x=factor*spec[1]
- local y=factor*spec[2]
- local w=factor*spec[3]
- local h=factor*spec[4]
- if x~=0 or w~=0 or y~=0 or h~=0 then
- local yoffset=y-h
- local leftkern=x
- local rightkern=w-x
- if leftkern~=0 or rightkern~=0 or yoffset~=0 then
- nofregisteredpairs=nofregisteredpairs+1
- if rlmode and rlmode<0 then
- leftkern,rightkern=rightkern,leftkern
- end
- if not injection then
- injection="injections"
- end
- local p=rawget(properties,current)
- if p then
- local i=rawget(p,injection)
- if i then
- if leftkern~=0 then
- i.leftkern=(i.leftkern or 0)+leftkern
- end
- if rightkern~=0 then
- i.rightkern=(i.rightkern or 0)+rightkern
- end
- if yoffset~=0 then
- i.yoffset=(i.yoffset or 0)+yoffset
- end
- elseif leftkern~=0 or rightkern~=0 then
- p[injection]={
- leftkern=leftkern,
- rightkern=rightkern,
- yoffset=yoffset,
- }
- else
- p[injection]={
- yoffset=yoffset,
- }
- end
- elseif leftkern~=0 or rightkern~=0 then
- properties[current]={
- [injection]={
- leftkern=leftkern,
- rightkern=rightkern,
- yoffset=yoffset,
- },
- }
- else
- properties[current]={
- [injection]={
- yoffset=yoffset,
- },
- }
- end
- return x,y,w,h,nofregisteredpairs
- end
- end
- return x,y,w,h
-end
-function injections.setkern(current,factor,rlmode,x,injection)
- local dx=factor*x
- if dx~=0 then
- nofregisteredkerns=nofregisteredkerns+1
- local p=rawget(properties,current)
- if not injection then
- injection="injections"
- end
- if p then
- local i=rawget(p,injection)
- if i then
- i.leftkern=dx+(i.leftkern or 0)
- else
- p[injection]={
- leftkern=dx,
- }
- end
- else
- properties[current]={
- [injection]={
- leftkern=dx,
- },
- }
- end
- return dx,nofregisteredkerns
- else
- return 0,0
- end
-end
-function injections.setmark(start,base,factor,rlmode,ba,ma,tfmbase,mkmk,checkmark)
- local dx,dy=factor*(ba[1]-ma[1]),factor*(ba[2]-ma[2])
- nofregisteredmarks=nofregisteredmarks+1
- if rlmode>=0 then
- dx=tfmbase.width-dx
- end
- local p=rawget(properties,start)
- if p then
- local i=p.injections
- if i then
- if i.markmark then
- else
- i.markx=dx
- i.marky=dy
- i.markdir=rlmode or 0
- i.markbase=nofregisteredmarks
- i.markbasenode=base
- i.markmark=mkmk
- i.checkmark=checkmark
- end
- else
- p.injections={
- markx=dx,
- marky=dy,
- markdir=rlmode or 0,
- markbase=nofregisteredmarks,
- markbasenode=base,
- markmark=mkmk,
- checkmark=checkmark,
- }
- end
- else
- properties[start]={
- injections={
- markx=dx,
- marky=dy,
- markdir=rlmode or 0,
- markbase=nofregisteredmarks,
- markbasenode=base,
- markmark=mkmk,
- checkmark=checkmark,
- },
- }
- end
- return dx,dy,nofregisteredmarks
-end
-local function dir(n)
- return (n and n<0 and "r-to-l") or (n and n>0 and "l-to-r") or "unset"
-end
-local function showchar(n,nested)
- local char=getchar(n)
- report_injections("%wfont %s, char %U, glyph %c",nested and 2 or 0,getfont(n),char,char)
-end
-local function show(n,what,nested,symbol)
- if n then
- local p=rawget(properties,n)
- if p then
- local i=rawget(p,what)
- if i then
- local leftkern=i.leftkern or 0
- local rightkern=i.rightkern or 0
- local yoffset=i.yoffset or 0
- local markx=i.markx or 0
- local marky=i.marky or 0
- local markdir=i.markdir or 0
- local markbase=i.markbase or 0
- local cursivex=i.cursivex or 0
- local cursivey=i.cursivey or 0
- local ligaindex=i.ligaindex or 0
- local cursbase=i.cursiveanchor
- local margin=nested and 4 or 2
- if rightkern~=0 or yoffset~=0 then
- report_injections("%w%s pair: lx %p, rx %p, dy %p",margin,symbol,leftkern,rightkern,yoffset)
- elseif leftkern~=0 then
- report_injections("%w%s kern: dx %p",margin,symbol,leftkern)
- end
- if markx~=0 or marky~=0 or markbase~=0 then
- report_injections("%w%s mark: dx %p, dy %p, dir %s, base %s",margin,symbol,markx,marky,markdir,markbase~=0 and "yes" or "no")
- end
- if cursivex~=0 or cursivey~=0 then
- if cursbase then
- report_injections("%w%s curs: base dx %p, dy %p",margin,symbol,cursivex,cursivey)
- else
- report_injections("%w%s curs: dx %p, dy %p",margin,symbol,cursivex,cursivey)
- end
- elseif cursbase then
- report_injections("%w%s curs: base",margin,symbol)
- end
- if ligaindex~=0 then
- report_injections("%w%s liga: index %i",margin,symbol,ligaindex)
- end
- end
- end
- end
-end
-local function showsub(n,what,where)
- report_injections("begin subrun: %s",where)
- for n in traverse_id(glyph_code,n) do
- showchar(n,where)
- show(n,what,where," ")
- end
- report_injections("end subrun")
-end
-local function trace(head,where)
- report_injections("begin run %s: %s kerns, %s pairs, %s marks and %s cursives registered",
- where or "",nofregisteredkerns,nofregisteredpairs,nofregisteredmarks,nofregisteredcursives)
- local n=head
- while n do
- local id=getid(n)
- if id==glyph_code then
- showchar(n)
- show(n,"injections",false," ")
- show(n,"preinjections",false,"<")
- show(n,"postinjections",false,">")
- show(n,"replaceinjections",false,"=")
- show(n,"emptyinjections",false,"*")
- elseif id==disc_code then
- local pre,post,replace=getdisc(n)
- if pre then
- showsub(pre,"preinjections","pre")
- end
- if post then
- showsub(post,"postinjections","post")
- end
- if replace then
- showsub(replace,"replaceinjections","replace")
- end
- show(n,"emptyinjections",false,"*")
- end
- n=getnext(n)
- end
- report_injections("end run")
-end
-local function show_result(head)
- local current=head
- local skipping=false
- while current do
- local id=getid(current)
- if id==glyph_code then
- report_injections("char: %C, width %p, xoffset %p, yoffset %p",
- getchar(current),getfield(current,"width"),getfield(current,"xoffset"),getfield(current,"yoffset"))
- skipping=false
- elseif id==kern_code then
- report_injections("kern: %p",getfield(current,"kern"))
- skipping=false
- elseif not skipping then
- report_injections()
- skipping=true
- end
- current=getnext(current)
- end
-end
-local function inject_kerns_only(head,where)
- head=tonut(head)
- if trace_injections then
- trace(head,"kerns")
- end
- local current=head
- local prev=nil
- local next=nil
- local prevdisc=nil
- local prevglyph=nil
- local pre=nil
- local post=nil
- local replace=nil
- local pretail=nil
- local posttail=nil
- local replacetail=nil
- while current do
- local id=getid(current)
- local next=getnext(current)
- if id==glyph_code then
- if getsubtype(current)<256 then
- local p=rawget(properties,current)
- if p then
- local i=p.injections
- if i then
- local leftkern=i.leftkern
- if leftkern and leftkern~=0 then
- if use_advance then
- setfield(current,"xoffset",leftkern)
- setfield(current,"xadvance",leftkern)
- else
- insert_node_before(head,current,newkern(leftkern))
- end
- end
- end
- if prevdisc then
- local done=false
- if post then
- local i=p.postinjections
- if i then
- local leftkern=i.leftkern
- if leftkern and leftkern~=0 then
- if use_advance then
- setfield(post,"xadvance",leftkern)
- else
- insert_node_after(post,posttail,newkern(leftkern))
- done=true
- end
- end
- end
- end
- if replace then
- local i=p.replaceinjections
- if i then
- local leftkern=i.leftkern
- if leftkern and leftkern~=0 then
- if use_advance then
- setfield(replace,"xadvance",leftkern)
- else
- insert_node_after(replace,replacetail,newkern(leftkern))
- done=true
- end
- end
- end
- else
- local i=p.emptyinjections
- if i then
- local leftkern=i.leftkern
- if leftkern and leftkern~=0 then
- setfield(prev,"replace",newkern(leftkern))
- end
- end
- end
- if done then
- setdisc(prevdisc,pre,post,replace)
- end
- end
- end
- end
- prevdisc=nil
- prevglyph=current
- elseif id==disc_code then
- pre,post,replace,pretail,posttail,replacetail=getdisc(current,true)
- local done=false
- if pre then
- for n in traverse_char(pre) do
- local p=rawget(properties,n)
- if p then
- local i=p.injections or p.preinjections
- if i then
- local leftkern=i.leftkern
- if leftkern and leftkern~=0 then
- if use_advance then
- setfield(pre,"xoffset",leftkern)
- setfield(pre,"xadvance",leftkern)
- else
- pre=insert_node_before(pre,n,newkern(leftkern))
- done=true
- end
- end
- end
- end
- end
- end
- if post then
- for n in traverse_char(post) do
- local p=rawget(properties,n)
- if p then
- local i=p.injections or p.postinjections
- if i then
- local leftkern=i.leftkern
- if leftkern and leftkern~=0 then
- if use_advance then
- setfield(post,"xoffset",leftkern)
- setfield(post,"xadvance",leftkern)
- else
- post=insert_node_before(post,n,newkern(leftkern))
- done=true
- end
- end
- end
- end
- end
- end
- if replace then
- for n in traverse_char(replace) do
- local p=rawget(properties,n)
- if p then
- local i=p.injections or p.replaceinjections
- if i then
- local leftkern=i.leftkern
- if leftkern and leftkern~=0 then
- if use_advance then
- setfield(replace,"xoffset",leftkern)
- setfield(replace,"xadvance",leftkern)
- else
- replace=insert_node_before(replace,n,newkern(leftkern))
- done=true
- end
- end
- end
- end
- end
- end
- if done then
- setdisc(current,pre,post,replace)
- end
- prevglyph=nil
- prevdisc=current
- else
- prevglyph=nil
- prevdisc=nil
- end
- prev=current
- current=next
- end
- if keepregisteredcounts then
- keepregisteredcounts=false
- else
- nofregisteredkerns=0
- end
- return tonode(head),true
-end
-local function inject_pairs_only(head,where)
- head=tonut(head)
- if trace_injections then
- trace(head,"pairs")
- end
- local current=head
- local prev=nil
- local next=nil
- local prevdisc=nil
- local prevglyph=nil
- local pre=nil
- local post=nil
- local replace=nil
- local pretail=nil
- local posttail=nil
- local replacetail=nil
- while current do
- local id=getid(current)
- local next=getnext(current)
- if id==glyph_code then
- if getsubtype(current)<256 then
- local p=rawget(properties,current)
- if p then
- local i=p.injections
- if i then
- local yoffset=i.yoffset
- if yoffset and yoffset~=0 then
- setfield(current,"yoffset",yoffset)
- end
- local leftkern=i.leftkern
- if leftkern and leftkern~=0 then
- head=insert_node_before(head,current,newkern(leftkern))
- end
- local rightkern=i.rightkern
- if rightkern and rightkern~=0 then
- insert_node_after(head,current,newkern(rightkern))
- end
- else
- local i=p.emptyinjections
- if i then
- local rightkern=i.rightkern
- if rightkern and rightkern~=0 then
- if next and getid(next)==disc_code then
- if replace then
- else
- setfield(next,"replace",newkern(rightkern))
- end
- end
- end
- end
- end
- if prevdisc then
- local done=false
- if post then
- local i=p.postinjections
- if i then
- local leftkern=i.leftkern
- if leftkern and leftkern~=0 then
- insert_node_after(post,posttail,newkern(leftkern))
- done=true
- end
- end
- end
- if replace then
- local i=p.replaceinjections
- if i then
- local leftkern=i.leftkern
- if leftkern and leftkern~=0 then
- insert_node_after(replace,replacetail,newkern(leftkern))
- done=true
- end
- end
- else
- local i=p.emptyinjections
- if i then
- local leftkern=i.leftkern
- if leftkern and leftkern~=0 then
- setfield(prev,"replace",newkern(leftkern))
- end
- end
- end
- if done then
- setdisc(prevdisc,pre,post,replace)
- end
- end
- end
- end
- prevdisc=nil
- prevglyph=current
- elseif id==disc_code then
- pre,post,replace,pretail,posttail,replacetail=getdisc(current,true)
- local done=false
- if pre then
- for n in traverse_char(pre) do
- local p=rawget(properties,n)
- if p then
- local i=p.injections or p.preinjections
- if i then
- local yoffset=i.yoffset
- if yoffset and yoffset~=0 then
- setfield(n,"yoffset",yoffset)
- end
- local leftkern=i.leftkern
- if leftkern and leftkern~=0 then
- pre=insert_node_before(pre,n,newkern(leftkern))
- done=true
- end
- local rightkern=i.rightkern
- if rightkern and rightkern~=0 then
- insert_node_after(pre,n,newkern(rightkern))
- done=true
- end
- end
- end
- end
- end
- if post then
- for n in traverse_char(post) do
- local p=rawget(properties,n)
- if p then
- local i=p.injections or p.postinjections
- if i then
- local yoffset=i.yoffset
- if yoffset and yoffset~=0 then
- setfield(n,"yoffset",yoffset)
- end
- local leftkern=i.leftkern
- if leftkern and leftkern~=0 then
- post=insert_node_before(post,n,newkern(leftkern))
- done=true
- end
- local rightkern=i.rightkern
- if rightkern and rightkern~=0 then
- insert_node_after(post,n,newkern(rightkern))
- done=true
- end
- end
- end
- end
- end
- if replace then
- for n in traverse_char(replace) do
- local p=rawget(properties,n)
- if p then
- local i=p.injections or p.replaceinjections
- if i then
- local yoffset=i.yoffset
- if yoffset and yoffset~=0 then
- setfield(n,"yoffset",yoffset)
- end
- local leftkern=i.leftkern
- if leftkern and leftkern~=0 then
- replace=insert_node_before(replace,n,newkern(leftkern))
- done=true
- end
- local rightkern=i.rightkern
- if rightkern and rightkern~=0 then
- insert_node_after(replace,n,newkern(rightkern))
- done=true
- end
- end
- end
- end
- end
- if prevglyph then
- if pre then
- local p=rawget(properties,prevglyph)
- if p then
- local i=p.preinjections
- if i then
- local rightkern=i.rightkern
- if rightkern and rightkern~=0 then
- pre=insert_node_before(pre,pre,newkern(rightkern))
- done=true
- end
- end
- end
- end
- if replace then
- local p=rawget(properties,prevglyph)
- if p then
- local i=p.replaceinjections
- if i then
- local rightkern=i.rightkern
- if rightkern and rightkern~=0 then
- replace=insert_node_before(replace,replace,newkern(rightkern))
- done=true
- end
- end
- end
- end
- end
- if done then
- setdisc(current,pre,post,replace)
- end
- prevglyph=nil
- prevdisc=current
- else
- prevglyph=nil
- prevdisc=nil
- end
- prev=current
- current=next
- end
- if keepregisteredcounts then
- keepregisteredcounts=false
- else
- nofregisteredkerns=0
- end
- return tonode(head),true
-end
-local function showoffset(n,flag)
- local o=getfield(n,"xoffset")
- if o==0 then
- o=getfield(n,"yoffset")
- end
- if o~=0 then
- setcolor(n,flag and "darkred" or "darkgreen")
- else
- resetcolor(n)
- end
-end
-local function inject_everything(head,where)
- head=tonut(head)
- if trace_injections then
- trace(head,"everything")
- end
- local hascursives=nofregisteredcursives>0
- local hasmarks=nofregisteredmarks>0
- local current=head
- local last=nil
- local font=font
- local markdata=nil
- local prev=nil
- local next=nil
- local prevdisc=nil
- local prevglyph=nil
- local pre=nil
- local post=nil
- local replace=nil
- local pretail=nil
- local posttail=nil
- local replacetail=nil
- local cursiveanchor=nil
- local minc=0
- local maxc=0
- local glyphs={}
- local marks={}
- local nofmarks=0
- local function processmark(p,n,pn)
- local px=getfield(p,"xoffset")
- local ox=0
- local rightkern=nil
- local pp=rawget(properties,p)
- if pp then
- pp=pp.injections
- if pp then
- rightkern=pp.rightkern
- end
- end
- if rightkern then
- if pn.markdir<0 then
- ox=px-pn.markx-rightkern
- else
- if false then
- local leftkern=pp.leftkern
- if leftkern then
- ox=px-pn.markx-leftkern
- else
- ox=px-pn.markx
- end
- else
- ox=px-pn.markx
- end
- end
- else
- ox=px-pn.markx
- if pn.checkmark then
- local wn=getfield(n,"width")
- if wn~=0 then
- wn=wn/2
- if trace_injections then
- report_injections("correcting non zero width mark %C",getchar(n))
- end
- insert_node_before(n,n,newkern(-wn))
- insert_node_after(n,n,newkern(-wn))
- end
- end
- end
- local oy=getfield(n,"yoffset")+getfield(p,"yoffset")+pn.marky
- setfield(n,"xoffset",ox)
- setfield(n,"yoffset",oy)
- if trace_marks then
- showoffset(n,true)
- end
- end
- while current do
- local id=getid(current)
- local next=getnext(current)
- if id==glyph_code then
- if getsubtype(current)<256 then
- local p=rawget(properties,current)
- if p then
- local i=p.injections
- if i then
- local pm=i.markbasenode
- if pm then
- nofmarks=nofmarks+1
- marks[nofmarks]=current
- else
- local yoffset=i.yoffset
- if yoffset and yoffset~=0 then
- setfield(current,"yoffset",yoffset)
- end
- if hascursives then
- local cursivex=i.cursivex
- if cursivex then
- if cursiveanchor then
- if cursivex~=0 then
- i.leftkern=(i.leftkern or 0)+cursivex
- end
- if maxc==0 then
- minc=1
- maxc=1
- glyphs[1]=cursiveanchor
- else
- maxc=maxc+1
- glyphs[maxc]=cursiveanchor
- end
- properties[cursiveanchor].cursivedy=i.cursivey
- last=current
- else
- maxc=0
- end
- elseif maxc>0 then
- local ny=getfield(current,"yoffset")
- for i=maxc,minc,-1 do
- local ti=glyphs[i]
- ny=ny+properties[ti].cursivedy
- setfield(ti,"yoffset",ny)
- if trace_cursive then
- showoffset(ti)
- end
- end
- maxc=0
- cursiveanchor=nil
- end
- if i.cursiveanchor then
- cursiveanchor=current
- else
- if maxc>0 then
- local ny=getfield(current,"yoffset")
- for i=maxc,minc,-1 do
- local ti=glyphs[i]
- ny=ny+properties[ti].cursivedy
- setfield(ti,"yoffset",ny)
- if trace_cursive then
- showoffset(ti)
- end
- end
- maxc=0
- end
- cursiveanchor=nil
- end
- end
- local leftkern=i.leftkern
- if leftkern and leftkern~=0 then
- insert_node_before(head,current,newkern(leftkern))
- end
- local rightkern=i.rightkern
- if rightkern and rightkern~=0 then
- insert_node_after(head,current,newkern(rightkern))
- end
- end
- else
- local i=p.emptyinjections
- if i then
- local rightkern=i.rightkern
- if rightkern and rightkern~=0 then
- if next and getid(next)==disc_code then
- if replace then
- else
- setfield(next,"replace",newkern(rightkern))
- end
- end
- end
- end
- end
- if prevdisc then
- if p then
- local done=false
- if post then
- local i=p.postinjections
- if i then
- local leftkern=i.leftkern
- if leftkern and leftkern~=0 then
- insert_node_after(post,posttail,newkern(leftkern))
- done=true
- end
- end
- end
- if replace then
- local i=p.replaceinjections
- if i then
- local leftkern=i.leftkern
- if leftkern and leftkern~=0 then
- insert_node_after(replace,replacetail,newkern(leftkern))
- done=true
- end
- end
- else
- local i=p.emptyinjections
- if i then
- local leftkern=i.leftkern
- if leftkern and leftkern~=0 then
- setfield(prev,"replace",newkern(leftkern))
- end
- end
- end
- if done then
- setdisc(prevdisc,pre,post,replace)
- end
- end
- end
- else
- if hascursives and maxc>0 then
- local ny=getfield(current,"yoffset")
- for i=maxc,minc,-1 do
- local ti=glyphs[i]
- ny=ny+properties[ti].cursivedy
- setfield(ti,"yoffset",getfield(ti,"yoffset")+ny)
- end
- maxc=0
- cursiveanchor=nil
- end
- end
- end
- prevdisc=nil
- prevglyph=current
- elseif id==disc_code then
- pre,post,replace,pretail,posttail,replacetail=getdisc(current,true)
- local done=false
- if pre then
- for n in traverse_char(pre) do
- local p=rawget(properties,n)
- if p then
- local i=p.injections or p.preinjections
- if i then
- local yoffset=i.yoffset
- if yoffset and yoffset~=0 then
- setfield(n,"yoffset",yoffset)
- end
- local leftkern=i.leftkern
- if leftkern and leftkern~=0 then
- pre=insert_node_before(pre,n,newkern(leftkern))
- done=true
- end
- local rightkern=i.rightkern
- if rightkern and rightkern~=0 then
- insert_node_after(pre,n,newkern(rightkern))
- done=true
- end
- if hasmarks then
- local pm=i.markbasenode
- if pm then
- processmark(pm,current,i)
- end
- end
- end
- end
- end
- end
- if post then
- for n in traverse_char(post) do
- local p=rawget(properties,n)
- if p then
- local i=p.injections or p.postinjections
- if i then
- local yoffset=i.yoffset
- if yoffset and yoffset~=0 then
- setfield(n,"yoffset",yoffset)
- end
- local leftkern=i.leftkern
- if leftkern and leftkern~=0 then
- post=insert_node_before(post,n,newkern(leftkern))
- done=true
- end
- local rightkern=i.rightkern
- if rightkern and rightkern~=0 then
- insert_node_after(post,n,newkern(rightkern))
- done=true
- end
- if hasmarks then
- local pm=i.markbasenode
- if pm then
- processmark(pm,current,i)
- end
- end
- end
- end
- end
- end
- if replace then
- for n in traverse_char(replace) do
- local p=rawget(properties,n)
- if p then
- local i=p.injections or p.replaceinjections
- if i then
- local yoffset=i.yoffset
- if yoffset and yoffset~=0 then
- setfield(n,"yoffset",yoffset)
- end
- local leftkern=i.leftkern
- if leftkern and leftkern~=0 then
- replace=insert_node_before(replace,n,newkern(leftkern))
- done=true
- end
- local rightkern=i.rightkern
- if rightkern and rightkern~=0 then
- insert_node_after(replace,n,newkern(rightkern))
- done=true
- end
- if hasmarks then
- local pm=i.markbasenode
- if pm then
- processmark(pm,current,i)
- end
- end
- end
- end
- end
- end
- if prevglyph then
- if pre then
- local p=rawget(properties,prevglyph)
- if p then
- local i=p.preinjections
- if i then
- local rightkern=i.rightkern
- if rightkern and rightkern~=0 then
- pre=insert_node_before(pre,pre,newkern(rightkern))
- done=true
- end
- end
- end
- end
- if replace then
- local p=rawget(properties,prevglyph)
- if p then
- local i=p.replaceinjections
- if i then
- local rightkern=i.rightkern
- if rightkern and rightkern~=0 then
- replace=insert_node_before(replace,replace,newkern(rightkern))
- done=true
- end
- end
- end
- end
- end
- if done then
- setdisc(current,pre,post,replace)
- end
- prevglyph=nil
- prevdisc=current
- else
- prevglyph=nil
- prevdisc=nil
- end
- prev=current
- current=next
- end
- if hascursives and maxc>0 then
- local ny=getfield(last,"yoffset")
- for i=maxc,minc,-1 do
- local ti=glyphs[i]
- ny=ny+properties[ti].cursivedy
- setfield(ti,"yoffset",ny)
- if trace_cursive then
- showoffset(ti)
- end
- end
- end
- if nofmarks>0 then
- for i=1,nofmarks do
- local m=marks[i]
- local p=rawget(properties,m)
- local i=p.injections
- local b=i.markbasenode
- processmark(b,m,i)
- end
- elseif hasmarks then
- end
- if keepregisteredcounts then
- keepregisteredcounts=false
- else
- nofregisteredkerns=0
- nofregisteredpairs=0
- nofregisteredmarks=0
- nofregisteredcursives=0
- end
- return tonode(head),true
-end
-local triggers=false
-function nodes.injections.setspacekerns(font,sequence)
- if triggers then
- triggers[font]=sequence
- else
- triggers={ [font]=sequence }
- end
-end
-local getthreshold
-if context then
- local threshold=1
- local parameters=fonts.hashes.parameters
- directives.register("otf.threshold",function(v) threshold=tonumber(v) or 1 end)
- getthreshold=function(font)
- local p=parameters[font]
- local f=p.factor
- local s=p.spacing
- local t=threshold*(s and s.width or p.space or 0)-2
- return t>0 and t or 0,f
- end
-else
- injections.threshold=0
- getthreshold=function(font)
- local p=fontdata[font].parameters
- local f=p.factor
- local s=p.spacing
- local t=injections.threshold*(s and s.width or p.space or 0)-2
- return t>0 and t or 0,f
- end
-end
-injections.getthreshold=getthreshold
-function injections.isspace(n,threshold)
- if getid(n)==glue_code then
- local w=getfield(n,"width")
- if threshold and w>threshold then
- return 32
- end
- end
-end
-local function injectspaces(head)
- if not triggers then
- return head,false
- end
- local lastfont=nil
- local spacekerns=nil
- local leftkerns=nil
- local rightkerns=nil
- local factor=0
- local threshold=0
- local leftkern=false
- local rightkern=false
- local function updatefont(font,trig)
- leftkerns=trig.left
- rightkerns=trig.right
- lastfont=font
- threshold,
- factor=getthreshold(font)
- end
- for n in traverse_id(glue_code,tonut(head)) do
- local prev,next=getboth(n)
- local prevchar=ischar(prev)
- local nextchar=ischar(next)
- if nextchar then
- local font=getfont(next)
- local trig=triggers[font]
- if trig then
- if lastfont~=font then
- updatefont(font,trig)
- end
- if rightkerns then
- rightkern=rightkerns[nextchar]
- end
- end
- end
- if prevchar then
- local font=getfont(prev)
- local trig=triggers[font]
- if trig then
- if lastfont~=font then
- updatefont(font,trig)
- end
- if leftkerns then
- leftkern=leftkerns[prevchar]
- end
- end
- end
- if leftkern then
- local old=getfield(n,"width")
- if old>threshold then
- if rightkern then
- local new=old+(leftkern+rightkern)*factor
- if trace_spaces then
- report_spaces("%C [%p -> %p] %C",prevchar,old,new,nextchar)
- end
- setfield(n,"width",new)
- leftkern=false
- else
- local new=old+leftkern*factor
- if trace_spaces then
- report_spaces("%C [%p -> %p]",prevchar,old,new)
- end
- setfield(n,"width",new)
- end
- end
- leftkern=false
- elseif rightkern then
- local old=getfield(n,"width")
- if old>threshold then
- local new=old+rightkern*factor
- if trace_spaces then
- report_spaces("[%p -> %p] %C",nextchar,old,new)
- end
- setfield(n,"width",new)
- end
- rightkern=false
- end
- end
- triggers=false
- return head,true
-end
-function injections.handler(head,where)
- if triggers then
- head=injectspaces(head)
- end
- if nofregisteredmarks>0 or nofregisteredcursives>0 then
- if trace_injections then
- report_injections("injection variant %a","everything")
- end
- return inject_everything(head,where)
- elseif nofregisteredpairs>0 then
- if trace_injections then
- report_injections("injection variant %a","pairs")
- end
- return inject_pairs_only(head,where)
- elseif nofregisteredkerns>0 then
- if trace_injections then
- report_injections("injection variant %a","kerns")
- end
- return inject_kerns_only(head,where)
- else
- return head,false
- end
-end
-
-end --- [luaotfload, fontloader-2017-02-11.lua scope for “font-otj”] ---
-
-
-do --- [luaotfload, fontloader-2017-02-11.lua scope for “font-ota” c281d18dfc89a8ca18af64f55e9fa92b] ---
-
-if not modules then modules={} end modules ['font-ota']={
- version=1.001,
- comment="companion to font-otf.lua (analysing)",
- author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright="PRAGMA ADE / ConTeXt Development Team",
- license="see context related readme files"
-}
-local type=type
-if not trackers then trackers={ register=function() end } end
-local fonts,nodes,node=fonts,nodes,node
-local allocate=utilities.storage.allocate
-local otf=fonts.handlers.otf
-local analyzers=fonts.analyzers
-local initializers=allocate()
-local methods=allocate()
-analyzers.initializers=initializers
-analyzers.methods=methods
-local a_state=attributes.private('state')
-local nuts=nodes.nuts
-local tonut=nuts.tonut
-local getfield=nuts.getfield
-local getnext=nuts.getnext
-local getprev=nuts.getprev
-local getprev=nuts.getprev
-local getprop=nuts.getprop
-local setprop=nuts.setprop
-local getfont=nuts.getfont
-local getsubtype=nuts.getsubtype
-local getchar=nuts.getchar
-local ischar=nuts.is_char
-local traverse_id=nuts.traverse_id
-local end_of_math=nuts.end_of_math
-local nodecodes=nodes.nodecodes
-local disc_code=nodecodes.disc
-local math_code=nodecodes.math
-local fontdata=fonts.hashes.identifiers
-local categories=characters and characters.categories or {}
-local chardata=characters and characters.data
-local otffeatures=fonts.constructors.features.otf
-local registerotffeature=otffeatures.register
-local s_init=1 local s_rphf=7
-local s_medi=2 local s_half=8
-local s_fina=3 local s_pref=9
-local s_isol=4 local s_blwf=10
-local s_mark=5 local s_pstf=11
-local s_rest=6
-local states={
- init=s_init,
- medi=s_medi,
- med2=s_medi,
- fina=s_fina,
- fin2=s_fina,
- fin3=s_fina,
- isol=s_isol,
- mark=s_mark,
- rest=s_rest,
- rphf=s_rphf,
- half=s_half,
- pref=s_pref,
- blwf=s_blwf,
- pstf=s_pstf,
-}
-local features={
- init=s_init,
- medi=s_medi,
- med2=s_medi,
- fina=s_fina,
- fin2=s_fina,
- fin3=s_fina,
- isol=s_isol,
- rphf=s_rphf,
- half=s_half,
- pref=s_pref,
- blwf=s_blwf,
- pstf=s_pstf,
-}
-analyzers.states=states
-analyzers.features=features
-analyzers.useunicodemarks=false
-function analyzers.setstate(head,font)
- local useunicodemarks=analyzers.useunicodemarks
- local tfmdata=fontdata[font]
- local descriptions=tfmdata.descriptions
- local first,last,current,n,done=nil,nil,head,0,false
- current=tonut(current)
- while current do
- local char,id=ischar(current,font)
- if char and not getprop(current,a_state) then
- done=true
- local d=descriptions[char]
- if d then
- if d.class=="mark" then
- done=true
- setprop(current,a_state,s_mark)
- elseif useunicodemarks and categories[char]=="mn" then
- done=true
- setprop(current,a_state,s_mark)
- elseif n==0 then
- first,last,n=current,current,1
- setprop(current,a_state,s_init)
- else
- last,n=current,n+1
- setprop(current,a_state,s_medi)
- end
- else
- if first and first==last then
- setprop(last,a_state,s_isol)
- elseif last then
- setprop(last,a_state,s_fina)
- end
- first,last,n=nil,nil,0
- end
- elseif char==false then
- if first and first==last then
- setprop(last,a_state,s_isol)
- elseif last then
- setprop(last,a_state,s_fina)
- end
- first,last,n=nil,nil,0
- if id==math_code then
- current=end_of_math(current)
- end
- elseif id==disc_code then
- setprop(current,a_state,s_medi)
- last=current
- else
- if first and first==last then
- setprop(last,a_state,s_isol)
- elseif last then
- setprop(last,a_state,s_fina)
- end
- first,last,n=nil,nil,0
- if id==math_code then
- current=end_of_math(current)
- end
- end
- current=getnext(current)
- end
- if first and first==last then
- setprop(last,a_state,s_isol)
- elseif last then
- setprop(last,a_state,s_fina)
- end
- return head,done
-end
-local function analyzeinitializer(tfmdata,value)
- local script,language=otf.scriptandlanguage(tfmdata)
- local action=initializers[script]
- if not action then
- elseif type(action)=="function" then
- return action(tfmdata,value)
- else
- local action=action[language]
- if action then
- return action(tfmdata,value)
- end
- end
-end
-local function analyzeprocessor(head,font,attr)
- local tfmdata=fontdata[font]
- local script,language=otf.scriptandlanguage(tfmdata,attr)
- local action=methods[script]
- if not action then
- elseif type(action)=="function" then
- return action(head,font,attr)
- else
- action=action[language]
- if action then
- return action(head,font,attr)
- end
- end
- return head,false
-end
-registerotffeature {
- name="analyze",
- description="analysis of character classes",
- default=true,
- initializers={
- node=analyzeinitializer,
- },
- processors={
- position=1,
- node=analyzeprocessor,
- }
-}
-methods.latn=analyzers.setstate
-local arab_warned={}
-local function warning(current,what)
- local char=getchar(current)
- if not arab_warned[char] then
- log.report("analyze","arab: character %C has no %a class",char,what)
- arab_warned[char]=true
- end
-end
-local mappers={
- l=s_init,
- d=s_medi,
- c=s_medi,
- r=s_fina,
- u=s_isol,
-}
-local classifiers=characters.classifiers
-if not classifiers then
- local f_arabic,l_arabic=characters.blockrange("arabic")
- local f_syriac,l_syriac=characters.blockrange("syriac")
- local f_mandiac,l_mandiac=characters.blockrange("mandiac")
- local f_nko,l_nko=characters.blockrange("nko")
- local f_ext_a,l_ext_a=characters.blockrange("arabicextendeda")
- classifiers=table.setmetatableindex(function(t,k)
- if type(k)=="number" then
- local c=chardata[k]
- local v=false
- if c then
- local arabic=c.arabic
- if arabic then
- v=mappers[arabic]
- if not v then
- log.report("analyze","error in mapping arabic %C",k)
- v=false
- end
- elseif (k>=f_arabic and k<=l_arabic) or
- (k>=f_syriac and k<=l_syriac) or
- (k>=f_mandiac and k<=l_mandiac) or
- (k>=f_nko and k<=l_nko) or
- (k>=f_ext_a and k<=l_ext_a) then
- if categories[k]=="mn" then
- v=s_mark
- else
- v=s_rest
- end
- end
- end
- t[k]=v
- return v
- end
- end)
- characters.classifiers=classifiers
-end
-function methods.arab(head,font,attr)
- local first,last=nil,nil
- local c_first,c_last=nil,nil
- local current,done=head,false
- current=tonut(current)
- while current do
- local char,id=ischar(current,font)
- if char and not getprop(current,a_state) then
- done=true
- local classifier=classifiers[char]
- if not classifier then
- if last then
- if c_last==s_medi or c_last==s_fina then
- setprop(last,a_state,s_fina)
- else
- warning(last,"fina")
- setprop(last,a_state,s_error)
- end
- first,last=nil,nil
- elseif first then
- if c_first==s_medi or c_first==s_fina then
- setprop(first,a_state,s_isol)
- else
- warning(first,"isol")
- setprop(first,a_state,s_error)
- end
- first=nil
- end
- elseif classifier==s_mark then
- setprop(current,a_state,s_mark)
- elseif classifier==s_isol then
- if last then
- if c_last==s_medi or c_last==s_fina then
- setprop(last,a_state,s_fina)
- else
- warning(last,"fina")
- setprop(last,a_state,s_error)
- end
- first,last=nil,nil
- elseif first then
- if c_first==s_medi or c_first==s_fina then
- setprop(first,a_state,s_isol)
- else
- warning(first,"isol")
- setprop(first,a_state,s_error)
- end
- first=nil
- end
- setprop(current,a_state,s_isol)
- elseif classifier==s_medi then
- if first then
- last=current
- c_last=classifier
- setprop(current,a_state,s_medi)
- else
- setprop(current,a_state,s_init)
- first=current
- c_first=classifier
- end
- elseif classifier==s_fina then
- if last then
- if getprop(last,a_state)~=s_init then
- setprop(last,a_state,s_medi)
- end
- setprop(current,a_state,s_fina)
- first,last=nil,nil
- elseif first then
- setprop(current,a_state,s_fina)
- first=nil
- else
- setprop(current,a_state,s_isol)
- end
- else
- setprop(current,a_state,s_rest)
- if last then
- if c_last==s_medi or c_last==s_fina then
- setprop(last,a_state,s_fina)
- else
- warning(last,"fina")
- setprop(last,a_state,s_error)
- end
- first,last=nil,nil
- elseif first then
- if c_first==s_medi or c_first==s_fina then
- setprop(first,a_state,s_isol)
- else
- warning(first,"isol")
- setprop(first,a_state,s_error)
- end
- first=nil
- end
- end
- else
- if last then
- if c_last==s_medi or c_last==s_fina then
- setprop(last,a_state,s_fina)
- else
- warning(last,"fina")
- setprop(last,a_state,s_error)
- end
- first,last=nil,nil
- elseif first then
- if c_first==s_medi or c_first==s_fina then
- setprop(first,a_state,s_isol)
- else
- warning(first,"isol")
- setprop(first,a_state,s_error)
- end
- first=nil
- end
- if id==math_code then
- current=end_of_math(current)
- end
- end
- current=getnext(current)
- end
- if last then
- if c_last==s_medi or c_last==s_fina then
- setprop(last,a_state,s_fina)
- else
- warning(last,"fina")
- setprop(last,a_state,s_error)
- end
- elseif first then
- if c_first==s_medi or c_first==s_fina then
- setprop(first,a_state,s_isol)
- else
- warning(first,"isol")
- setprop(first,a_state,s_error)
- end
- end
- return head,done
-end
-methods.syrc=methods.arab
-methods.mand=methods.arab
-methods.nko=methods.arab
-directives.register("otf.analyze.useunicodemarks",function(v)
- analyzers.useunicodemarks=v
-end)
-
-end --- [luaotfload, fontloader-2017-02-11.lua scope for “font-ota”] ---
-
-
-do --- [luaotfload, fontloader-2017-02-11.lua scope for “font-ots” 7e1e55f9f728474372665e4a64a43f5a] ---
-
-if not modules then modules={} end modules ['font-ots']={
- version=1.001,
- comment="companion to font-ini.mkiv",
- author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright="PRAGMA ADE / ConTeXt Development Team",
- license="see context related readme files",
-}
-local type,next,tonumber=type,next,tonumber
-local random=math.random
-local formatters=string.formatters
-local insert=table.insert
-local logs,trackers,nodes,attributes=logs,trackers,nodes,attributes
-local registertracker=trackers.register
-local registerdirective=directives.register
-local fonts=fonts
-local otf=fonts.handlers.otf
-local trace_lookups=false registertracker("otf.lookups",function(v) trace_lookups=v end)
-local trace_singles=false registertracker("otf.singles",function(v) trace_singles=v end)
-local trace_multiples=false registertracker("otf.multiples",function(v) trace_multiples=v end)
-local trace_alternatives=false registertracker("otf.alternatives",function(v) trace_alternatives=v end)
-local trace_ligatures=false registertracker("otf.ligatures",function(v) trace_ligatures=v end)
-local trace_contexts=false registertracker("otf.contexts",function(v) trace_contexts=v end)
-local trace_marks=false registertracker("otf.marks",function(v) trace_marks=v end)
-local trace_kerns=false registertracker("otf.kerns",function(v) trace_kerns=v end)
-local trace_cursive=false registertracker("otf.cursive",function(v) trace_cursive=v end)
-local trace_preparing=false registertracker("otf.preparing",function(v) trace_preparing=v end)
-local trace_bugs=false registertracker("otf.bugs",function(v) trace_bugs=v end)
-local trace_details=false registertracker("otf.details",function(v) trace_details=v end)
-local trace_steps=false registertracker("otf.steps",function(v) trace_steps=v end)
-local trace_skips=false registertracker("otf.skips",function(v) trace_skips=v end)
-local trace_directions=false registertracker("otf.directions",function(v) trace_directions=v end)
-local trace_plugins=false registertracker("otf.plugins",function(v) trace_plugins=v end)
-local trace_kernruns=false registertracker("otf.kernruns",function(v) trace_kernruns=v end)
-local trace_discruns=false registertracker("otf.discruns",function(v) trace_discruns=v end)
-local trace_compruns=false registertracker("otf.compruns",function(v) trace_compruns=v end)
-local trace_testruns=false registertracker("otf.testruns",function(v) trace_testruns=v end)
-local optimizekerns=true
-local alwaysdisc=true registerdirective("otf.alwaysdisc",function(v) alwaysdisc=v end)
-local report_direct=logs.reporter("fonts","otf direct")
-local report_subchain=logs.reporter("fonts","otf subchain")
-local report_chain=logs.reporter("fonts","otf chain")
-local report_process=logs.reporter("fonts","otf process")
-local report_warning=logs.reporter("fonts","otf warning")
-local report_run=logs.reporter("fonts","otf run")
-registertracker("otf.replacements","otf.singles,otf.multiples,otf.alternatives,otf.ligatures")
-registertracker("otf.positions","otf.marks,otf.kerns,otf.cursive")
-registertracker("otf.actions","otf.replacements,otf.positions")
-registertracker("otf.injections","nodes.injections")
-registertracker("*otf.sample","otf.steps,otf.actions,otf.analyzing")
-local nuts=nodes.nuts
-local tonode=nuts.tonode
-local tonut=nuts.tonut
-local getfield=nuts.getfield
-local setfield=nuts.setfield
-local getnext=nuts.getnext
-local setnext=nuts.setnext
-local getprev=nuts.getprev
-local setprev=nuts.setprev
-local getboth=nuts.getboth
-local setboth=nuts.setboth
-local getid=nuts.getid
-local getattr=nuts.getattr
-local setattr=nuts.setattr
-local getprop=nuts.getprop
-local setprop=nuts.setprop
-local getfont=nuts.getfont
-local getsubtype=nuts.getsubtype
-local setsubtype=nuts.setsubtype
-local getchar=nuts.getchar
-local setchar=nuts.setchar
-local getdisc=nuts.getdisc
-local setdisc=nuts.setdisc
-local setlink=nuts.setlink
-local ischar=nuts.is_char
-local insert_node_after=nuts.insert_after
-local copy_node=nuts.copy
-local copy_node_list=nuts.copy_list
-local find_node_tail=nuts.tail
-local flush_node_list=nuts.flush_list
-local flush_node=nuts.flush_node
-local end_of_math=nuts.end_of_math
-local traverse_nodes=nuts.traverse
-local traverse_id=nuts.traverse_id
-local remove_node=nuts.remove
-local setmetatableindex=table.setmetatableindex
-local zwnj=0x200C
-local zwj=0x200D
-local wildcard="*"
-local default="dflt"
-local nodecodes=nodes.nodecodes
-local glyphcodes=nodes.glyphcodes
-local disccodes=nodes.disccodes
-local glyph_code=nodecodes.glyph
-local glue_code=nodecodes.glue
-local disc_code=nodecodes.disc
-local math_code=nodecodes.math
-local dir_code=nodecodes.dir
-local localpar_code=nodecodes.localpar
-local discretionary_code=disccodes.discretionary
-local ligature_code=glyphcodes.ligature
-local privateattribute=attributes.private
-local a_state=privateattribute('state')
-local injections=nodes.injections
-local setmark=injections.setmark
-local setcursive=injections.setcursive
-local setkern=injections.setkern
-local setpair=injections.setpair
-local resetinjection=injections.reset
-local copyinjection=injections.copy
-local setligaindex=injections.setligaindex
-local getligaindex=injections.getligaindex
-local cursonce=true
-local fonthashes=fonts.hashes
-local fontdata=fonthashes.identifiers
-local fontfeatures=fonthashes.features
-local otffeatures=fonts.constructors.features.otf
-local registerotffeature=otffeatures.register
-local onetimemessage=fonts.loggers.onetimemessage or function() end
-local getrandom=utilities and utilities.randomizer and utilities.randomizer.get
-otf.defaultnodealternate="none"
-local tfmdata=false
-local characters=false
-local descriptions=false
-local marks=false
-local currentfont=false
-local factor=0
-local threshold=0
-local checkmarks=false
-local sweepnode=nil
-local sweepprev=nil
-local sweepnext=nil
-local sweephead={}
-local notmatchpre={}
-local notmatchpost={}
-local notmatchreplace={}
-local handlers={}
-local isspace=injections.isspace
-local getthreshold=injections.getthreshold
-local checkstep=(nodes and nodes.tracers and nodes.tracers.steppers.check) or function() end
-local registerstep=(nodes and nodes.tracers and nodes.tracers.steppers.register) or function() end
-local registermessage=(nodes and nodes.tracers and nodes.tracers.steppers.message) or function() end
-local function checkdisccontent(d)
- local pre,post,replace=getdisc(d)
- if pre then for n in traverse_id(glue_code,pre) do print("pre",nodes.idstostring(pre)) break end end
- if post then for n in traverse_id(glue_code,post) do print("pos",nodes.idstostring(post)) break end end
- if replace then for n in traverse_id(glue_code,replace) do print("rep",nodes.idstostring(replace)) break end end
-end
-local function logprocess(...)
- if trace_steps then
- registermessage(...)
- end
- report_direct(...)
-end
-local function logwarning(...)
- report_direct(...)
-end
-local f_unicode=formatters["%U"]
-local f_uniname=formatters["%U (%s)"]
-local f_unilist=formatters["% t (% t)"]
-local function gref(n)
- if type(n)=="number" then
- local description=descriptions[n]
- local name=description and description.name
- if name then
- return f_uniname(n,name)
- else
- return f_unicode(n)
- end
- elseif n then
- local num,nam={},{}
- for i=1,#n do
- local ni=n[i]
- if tonumber(ni) then
- local di=descriptions[ni]
- num[i]=f_unicode(ni)
- nam[i]=di and di.name or "-"
- end
- end
- return f_unilist(num,nam)
- else
- return "<error in node mode tracing>"
- end
-end
-local function cref(dataset,sequence,index)
- if not dataset then
- return "no valid dataset"
- elseif index then
- return formatters["feature %a, type %a, chain lookup %a, index %a"](dataset[4],sequence.type,sequence.name,index)
- else
- return formatters["feature %a, type %a, chain lookup %a"](dataset[4],sequence.type,sequence.name)
- end
-end
-local function pref(dataset,sequence)
- return formatters["feature %a, type %a, lookup %a"](dataset[4],sequence.type,sequence.name)
-end
-local function mref(rlmode)
- if not rlmode or rlmode==0 then
- return "---"
- elseif rlmode==-1 or rlmode=="+TRT" then
- return "r2l"
- else
- return "l2r"
- end
-end
-local function copy_glyph(g)
- local components=getfield(g,"components")
- if components then
- setfield(g,"components")
- local n=copy_node(g)
- copyinjection(n,g)
- setfield(g,"components",components)
- return n
- else
- local n=copy_node(g)
- copyinjection(n,g)
- return n
- end
-end
-local function flattendisk(head,disc)
- local pre,post,replace,pretail,posttail,replacetail=getdisc(disc,true)
- local prev,next=getboth(disc)
- local ishead=head==disc
- setdisc(disc)
- flush_node(disc)
- if pre then
- flush_node_list(pre)
- end
- if post then
- flush_node_list(post)
- end
- if ishead then
- if replace then
- if next then
- setlink(replacetail,next)
- end
- return replace,replace
- elseif next then
- return next,next
- else
- return
- end
- else
- if replace then
- if next then
- setlink(replacetail,next)
- end
- setlink(prev,replace)
- return head,replace
- else
- setlink(prev,next)
- return head,next
- end
- end
-end
-local function appenddisc(disc,list)
- local pre,post,replace,pretail,posttail,replacetail=getdisc(disc,true)
- local posthead=list
- local replacehead=copy_node_list(list)
- if post then
- setlink(posttail,posthead)
- else
- post=phead
- end
- if replace then
- setlink(replacetail,replacehead)
- else
- replace=rhead
- end
- setdisc(disc,pre,post,replace)
-end
-local function markstoligature(head,start,stop,char)
- if start==stop and getchar(start)==char then
- return head,start
- else
- local prev=getprev(start)
- local next=getnext(stop)
- setprev(start)
- setnext(stop)
- local base=copy_glyph(start)
- if head==start then
- head=base
- end
- resetinjection(base)
- setchar(base,char)
- setsubtype(base,ligature_code)
- setfield(base,"components",start)
- setlink(prev,base)
- setlink(base,next)
- return head,base
- end
-end
-local function getcomponentindex(start)
- if getid(start)~=glyph_code then
- return 0
- elseif getsubtype(start)==ligature_code then
- local i=0
- local components=getfield(start,"components")
- while components do
- i=i+getcomponentindex(components)
- components=getnext(components)
- end
- return i
- elseif not marks[getchar(start)] then
- return 1
- else
- return 0
- end
-end
-local a_noligature=attributes.private("noligature")
-local function toligature(head,start,stop,char,dataset,sequence,markflag,discfound)
- if getattr(start,a_noligature)==1 then
- return head,start
- end
- if start==stop and getchar(start)==char then
- resetinjection(start)
- setchar(start,char)
- return head,start
- end
- local components=getfield(start,"components")
- if components then
- end
- local prev=getprev(start)
- local next=getnext(stop)
- local comp=start
- setprev(start)
- setnext(stop)
- local base=copy_glyph(start)
- if start==head then
- head=base
- end
- resetinjection(base)
- setchar(base,char)
- setsubtype(base,ligature_code)
- setfield(base,"components",comp)
- if prev then
- setnext(prev,base)
- end
- if next then
- setprev(next,base)
- end
- setboth(base,prev,next)
- if not discfound then
- local deletemarks=markflag~="mark"
- local components=start
- local baseindex=0
- local componentindex=0
- local head=base
- local current=base
- while start do
- local char=getchar(start)
- if not marks[char] then
- baseindex=baseindex+componentindex
- componentindex=getcomponentindex(start)
- elseif not deletemarks then
- setligaindex(start,baseindex+getligaindex(start,componentindex))
- if trace_marks then
- logwarning("%s: keep mark %s, gets index %s",pref(dataset,sequence),gref(char),getligaindex(start))
- end
- local n=copy_node(start)
- copyinjection(n,start)
- head,current=insert_node_after(head,current,n)
- elseif trace_marks then
- logwarning("%s: delete mark %s",pref(dataset,sequence),gref(char))
- end
- start=getnext(start)
- end
- local start=getnext(current)
- while start do
- local char=ischar(start)
- if char then
- if marks[char] then
- setligaindex(start,baseindex+getligaindex(start,componentindex))
- if trace_marks then
- logwarning("%s: set mark %s, gets index %s",pref(dataset,sequence),gref(char),getligaindex(start))
- end
- start=getnext(start)
- else
- break
- end
- else
- break
- end
- end
- else
- local discprev,discnext=getboth(discfound)
- if discprev and discnext then
- local pre,post,replace,pretail,posttail,replacetail=getdisc(discfound,true)
- if not replace then
- local prev=getprev(base)
- local current=comp
- local previous=nil
- local copied=nil
- while current do
- if getid(current)==glyph_code then
- local n=copy_node(current)
- if copied then
- setlink(previous,n)
- else
- copied=n
- end
- previous=n
- end
- current=getnext(current)
- end
- setprev(discnext)
- setnext(discprev)
- if pre then
- setlink(discprev,pre)
- end
- pre=comp
- if post then
- setlink(posttail,discnext)
- setprev(post)
- else
- post=discnext
- end
- setlink(prev,discfound)
- setlink(discfound,next)
- setboth(base)
- setfield(base,"components",copied)
- setdisc(discfound,pre,post,base)
- base=prev
- end
- end
- end
- return head,base
-end
-local function multiple_glyphs(head,start,multiple,ignoremarks,what)
- local nofmultiples=#multiple
- if nofmultiples>0 then
- resetinjection(start)
- setchar(start,multiple[1])
- if nofmultiples>1 then
- local sn=getnext(start)
- for k=2,nofmultiples do
- local n=copy_node(start)
- resetinjection(n)
- setchar(n,multiple[k])
- insert_node_after(head,start,n)
- start=n
- end
- if what==true then
- elseif what>1 then
- local m=multiple[nofmultiples]
- for i=2,what do
- local n=copy_node(start)
- resetinjection(n)
- setchar(n,m)
- insert_node_after(head,start,n)
- start=n
- end
- end
- end
- return head,start,true
- else
- if trace_multiples then
- logprocess("no multiple for %s",gref(getchar(start)))
- end
- return head,start,false
- end
-end
-local function get_alternative_glyph(start,alternatives,value)
- local n=#alternatives
- if value=="random" then
- local r=getrandom and getrandom("glyph",1,n) or random(1,n)
- return alternatives[r],trace_alternatives and formatters["value %a, taking %a"](value,r)
- elseif value=="first" then
- return alternatives[1],trace_alternatives and formatters["value %a, taking %a"](value,1)
- elseif value=="last" then
- return alternatives[n],trace_alternatives and formatters["value %a, taking %a"](value,n)
- end
- value=value==true and 1 or tonumber(value)
- if type(value)~="number" then
- return alternatives[1],trace_alternatives and formatters["invalid value %s, taking %a"](value,1)
- end
- if value>n then
- local defaultalt=otf.defaultnodealternate
- if defaultalt=="first" then
- return alternatives[n],trace_alternatives and formatters["invalid value %s, taking %a"](value,1)
- elseif defaultalt=="last" then
- return alternatives[1],trace_alternatives and formatters["invalid value %s, taking %a"](value,n)
- else
- return false,trace_alternatives and formatters["invalid value %a, %s"](value,"out of range")
- end
- elseif value==0 then
- return getchar(start),trace_alternatives and formatters["invalid value %a, %s"](value,"no change")
- elseif value<1 then
- return alternatives[1],trace_alternatives and formatters["invalid value %a, taking %a"](value,1)
- else
- return alternatives[value],trace_alternatives and formatters["value %a, taking %a"](value,value)
- end
-end
-function handlers.gsub_single(head,start,dataset,sequence,replacement)
- if trace_singles then
- logprocess("%s: replacing %s by single %s",pref(dataset,sequence),gref(getchar(start)),gref(replacement))
- end
- resetinjection(start)
- setchar(start,replacement)
- return head,start,true
-end
-function handlers.gsub_alternate(head,start,dataset,sequence,alternative)
- local kind=dataset[4]
- local what=dataset[1]
- local value=what==true and tfmdata.shared.features[kind] or what
- local choice,comment=get_alternative_glyph(start,alternative,value)
- if choice then
- if trace_alternatives then
- logprocess("%s: replacing %s by alternative %a to %s, %s",pref(dataset,sequence),gref(getchar(start)),gref(choice),comment)
- end
- resetinjection(start)
- setchar(start,choice)
- else
- if trace_alternatives then
- logwarning("%s: no variant %a for %s, %s",pref(dataset,sequence),value,gref(getchar(start)),comment)
- end
- end
- return head,start,true
-end
-function handlers.gsub_multiple(head,start,dataset,sequence,multiple)
- if trace_multiples then
- logprocess("%s: replacing %s by multiple %s",pref(dataset,sequence),gref(getchar(start)),gref(multiple))
- end
- return multiple_glyphs(head,start,multiple,sequence.flags[1],dataset[1])
-end
-function handlers.gsub_ligature(head,start,dataset,sequence,ligature)
- local current=getnext(start)
- if not current then
- return head,start,false,nil
- end
- local stop=nil
- local startchar=getchar(start)
- if marks[startchar] then
- while current do
- local char=ischar(current,currentfont)
- if char then
- local lg=ligature[char]
- if lg then
- stop=current
- ligature=lg
- current=getnext(current)
- else
- break
- end
- else
- break
- end
- end
- if stop then
- local lig=ligature.ligature
- if lig then
- if trace_ligatures then
- local stopchar=getchar(stop)
- head,start=markstoligature(head,start,stop,lig)
- logprocess("%s: replacing %s upto %s by ligature %s case 1",pref(dataset,sequence),gref(startchar),gref(stopchar),gref(getchar(start)))
- else
- head,start=markstoligature(head,start,stop,lig)
- end
- return head,start,true,false
- else
- end
- end
- else
- local skipmark=sequence.flags[1]
- local discfound=false
- local lastdisc=nil
- while current do
- local char,id=ischar(current,currentfont)
- if char then
- if skipmark and marks[char] then
- current=getnext(current)
- else
- local lg=ligature[char]
- if lg then
- if not discfound and lastdisc then
- discfound=lastdisc
- lastdisc=nil
- end
- stop=current
- ligature=lg
- current=getnext(current)
- else
- break
- end
- end
- elseif char==false then
- break
- elseif id==disc_code then
- local replace=getfield(current,"replace")
- if replace then
- while replace do
- local char,id=ischar(replace,currentfont)
- if char then
- local lg=ligature[char]
- if lg then
- ligature=lg
- replace=getnext(replace)
- else
- return head,start,false,false
- end
- else
- return head,start,false,false
- end
- end
- stop=current
- end
- lastdisc=current
- current=getnext(current)
- else
- break
- end
- end
- local lig=ligature.ligature
- if lig then
- if stop then
- if trace_ligatures then
- local stopchar=getchar(stop)
- head,start=toligature(head,start,stop,lig,dataset,sequence,skipmark,discfound)
- logprocess("%s: replacing %s upto %s by ligature %s case 2",pref(dataset,sequence),gref(startchar),gref(stopchar),gref(lig))
- else
- head,start=toligature(head,start,stop,lig,dataset,sequence,skipmark,discfound)
- end
- else
- resetinjection(start)
- setchar(start,lig)
- if trace_ligatures then
- logprocess("%s: replacing %s by (no real) ligature %s case 3",pref(dataset,sequence),gref(startchar),gref(lig))
- end
- end
- return head,start,true,discfound
- else
- end
- end
- return head,start,false,discfound
-end
-function handlers.gpos_single(head,start,dataset,sequence,kerns,rlmode,step,i,injection)
- local startchar=getchar(start)
- if step.format=="pair" then
- local dx,dy,w,h=setpair(start,factor,rlmode,sequence.flags[4],kerns,injection)
- if trace_kerns then
- logprocess("%s: shifting single %s by (%p,%p) and correction (%p,%p)",pref(dataset,sequence),gref(startchar),dx,dy,w,h)
- end
- else
- local k=setkern(start,factor,rlmode,kerns,injection)
- if trace_kerns then
- logprocess("%s: shifting single %s by %p",pref(dataset,sequence),gref(startchar),k)
- end
- end
- return head,start,false
-end
-function handlers.gpos_pair(head,start,dataset,sequence,kerns,rlmode,step,i,injection)
- local snext=getnext(start)
- if not snext then
- return head,start,false
- else
- local prev=start
- local done=false
- while snext do
- local nextchar=ischar(snext,currentfont)
- if nextchar then
- local krn=kerns[nextchar]
- if not krn and marks[nextchar] then
- prev=snext
- snext=getnext(snext)
- elseif not krn then
- break
- elseif step.format=="pair" then
- local a,b=krn[1],krn[2]
- if optimizekerns then
- if not b and a[1]==0 and a[2]==0 and a[4]==0 then
- local k=setkern(snext,factor,rlmode,a[3],injection)
- if trace_kerns then
- logprocess("%s: shifting single %s by %p",pref(dataset,sequence),gref(nextchar),k)
- end
- done=true
- break
- end
- end
- if a and #a>0 then
- local x,y,w,h=setpair(start,factor,rlmode,sequence.flags[4],a,injection)
- if trace_kerns then
- local startchar=getchar(start)
- logprocess("%s: shifting first of pair %s and %s by (%p,%p) and correction (%p,%p) as %s",pref(dataset,sequence),gref(startchar),gref(nextchar),x,y,w,h,injection or "injections")
- end
- end
- if b and #b>0 then
- local x,y,w,h=setpair(snext,factor,rlmode,sequence.flags[4],b,injection)
- if trace_kerns then
- local startchar=getchar(snext)
- logprocess("%s: shifting second of pair %s and %s by (%p,%p) and correction (%p,%p) as %s",pref(dataset,sequence),gref(startchar),gref(nextchar),x,y,w,h,injection or "injections")
- end
- end
- done=true
- break
- elseif krn~=0 then
- local k=setkern(snext,factor,rlmode,krn,injection)
- if trace_kerns then
- logprocess("%s: inserting kern %p between %s and %s as %s",pref(dataset,sequence),k,gref(getchar(prev)),gref(nextchar),injection or "injections")
- end
- done=true
- break
- else
- break
- end
- else
- break
- end
- end
- return head,start,done
- end
-end
-function handlers.gpos_mark2base(head,start,dataset,sequence,markanchors,rlmode)
- local markchar=getchar(start)
- if marks[markchar] then
- local base=getprev(start)
- if base then
- local basechar=ischar(base,currentfont)
- if basechar then
- if marks[basechar] then
- while base do
- base=getprev(base)
- if base then
- basechar=ischar(base,currentfont)
- if basechar then
- if not marks[basechar] then
- break
- end
- else
- if trace_bugs then
- logwarning("%s: no base for mark %s, case %i",pref(dataset,sequence),gref(markchar),1)
- end
- return head,start,false
- end
- else
- if trace_bugs then
- logwarning("%s: no base for mark %s, case %i",pref(dataset,sequence),gref(markchar),2)
- end
- return head,start,false
- end
- end
- end
- local ba=markanchors[1][basechar]
- if ba then
- local ma=markanchors[2]
- local dx,dy,bound=setmark(start,base,factor,rlmode,ba,ma,characters[basechar],false,checkmarks)
- if trace_marks then
- logprocess("%s, anchor %s, bound %s: anchoring mark %s to basechar %s => (%p,%p)",
- pref(dataset,sequence),anchor,bound,gref(markchar),gref(basechar),dx,dy)
- end
- return head,start,true
- end
- elseif trace_bugs then
- logwarning("%s: nothing preceding, case %i",pref(dataset,sequence),1)
- end
- elseif trace_bugs then
- logwarning("%s: nothing preceding, case %i",pref(dataset,sequence),2)
- end
- elseif trace_bugs then
- logwarning("%s: mark %s is no mark",pref(dataset,sequence),gref(markchar))
- end
- return head,start,false
-end
-function handlers.gpos_mark2ligature(head,start,dataset,sequence,markanchors,rlmode)
- local markchar=getchar(start)
- if marks[markchar] then
- local base=getprev(start)
- if base then
- local basechar=ischar(base,currentfont)
- if basechar then
- if marks[basechar] then
- while base do
- base=getprev(base)
- if base then
- basechar=ischar(base,currentfont)
- if basechar then
- if not marks[basechar] then
- break
- end
- else
- if trace_bugs then
- logwarning("%s: no base for mark %s, case %i",pref(dataset,sequence),gref(markchar),1)
- end
- return head,start,false
- end
- else
- if trace_bugs then
- logwarning("%s: no base for mark %s, case %i",pref(dataset,sequence),gref(markchar),2)
- end
- return head,start,false
- end
- end
- end
- local ba=markanchors[1][basechar]
- if ba then
- local ma=markanchors[2]
- if ma then
- local index=getligaindex(start)
- ba=ba[index]
- if ba then
- local dx,dy,bound=setmark(start,base,factor,rlmode,ba,ma,characters[basechar],false,checkmarks)
- if trace_marks then
- logprocess("%s, anchor %s, index %s, bound %s: anchoring mark %s to baselig %s at index %s => (%p,%p)",
- pref(dataset,sequence),anchor,index,bound,gref(markchar),gref(basechar),index,dx,dy)
- end
- return head,start,true
- else
- if trace_bugs then
- logwarning("%s: no matching anchors for mark %s and baselig %s with index %a",pref(dataset,sequence),gref(markchar),gref(basechar),index)
- end
- end
- end
- elseif trace_bugs then
- onetimemessage(currentfont,basechar,"no base anchors",report_fonts)
- end
- elseif trace_bugs then
- logwarning("%s: prev node is no char, case %i",pref(dataset,sequence),1)
- end
- elseif trace_bugs then
- logwarning("%s: prev node is no char, case %i",pref(dataset,sequence),2)
- end
- elseif trace_bugs then
- logwarning("%s: mark %s is no mark",pref(dataset,sequence),gref(markchar))
- end
- return head,start,false
-end
-function handlers.gpos_mark2mark(head,start,dataset,sequence,markanchors,rlmode)
- local markchar=getchar(start)
- if marks[markchar] then
- local base=getprev(start)
- local slc=getligaindex(start)
- if slc then
- while base do
- local blc=getligaindex(base)
- if blc and blc~=slc then
- base=getprev(base)
- else
- break
- end
- end
- end
- if base then
- local basechar=ischar(base,currentfont)
- if basechar then
- local ba=markanchors[1][basechar]
- if ba then
- local ma=markanchors[2]
- local dx,dy,bound=setmark(start,base,factor,rlmode,ba,ma,characters[basechar],true,checkmarks)
- if trace_marks then
- logprocess("%s, anchor %s, bound %s: anchoring mark %s to basemark %s => (%p,%p)",
- pref(dataset,sequence),anchor,bound,gref(markchar),gref(basechar),dx,dy)
- end
- return head,start,true
- end
- end
- end
- elseif trace_bugs then
- logwarning("%s: mark %s is no mark",pref(dataset,sequence),gref(markchar))
- end
- return head,start,false
-end
-function handlers.gpos_cursive(head,start,dataset,sequence,exitanchors,rlmode,step,i)
- local done=false
- local startchar=getchar(start)
- if marks[startchar] then
- if trace_cursive then
- logprocess("%s: ignoring cursive for mark %s",pref(dataset,sequence),gref(startchar))
- end
- else
- local nxt=getnext(start)
- while not done and nxt do
- local nextchar=ischar(nxt,currentfont)
- if not nextchar then
- break
- elseif marks[nextchar] then
- nxt=getnext(nxt)
- else
- local exit=exitanchors[3]
- if exit then
- local entry=exitanchors[1][nextchar]
- if entry then
- entry=entry[2]
- if entry then
- local dx,dy,bound=setcursive(start,nxt,factor,rlmode,exit,entry,characters[startchar],characters[nextchar])
- if trace_cursive then
- logprocess("%s: moving %s to %s cursive (%p,%p) using anchor %s and bound %s in %s mode",pref(dataset,sequence),gref(startchar),gref(nextchar),dx,dy,anchor,bound,mref(rlmode))
- end
- done=true
- end
- end
- end
- break
- end
- end
- end
- return head,start,done
-end
-local chainprocs={}
-local function logprocess(...)
- if trace_steps then
- registermessage(...)
- end
- report_subchain(...)
-end
-local logwarning=report_subchain
-local function logprocess(...)
- if trace_steps then
- registermessage(...)
- end
- report_chain(...)
-end
-local logwarning=report_chain
-local function reversesub(head,start,stop,dataset,sequence,replacements,rlmode)
- local char=getchar(start)
- local replacement=replacements[char]
- if replacement then
- if trace_singles then
- logprocess("%s: single reverse replacement of %s by %s",cref(dataset,sequence),gref(char),gref(replacement))
- end
- resetinjection(start)
- setchar(start,replacement)
- return head,start,true
- else
- return head,start,false
- end
-end
-chainprocs.reversesub=reversesub
-local function reportmoresteps(dataset,sequence)
- logwarning("%s: more than 1 step",cref(dataset,sequence))
-end
-function chainprocs.gsub_single(head,start,stop,dataset,sequence,currentlookup,chainindex)
- local steps=currentlookup.steps
- local nofsteps=currentlookup.nofsteps
- if nofsteps>1 then
- reportmoresteps(dataset,sequence)
- end
- local current=start
- while current do
- local currentchar=ischar(current)
- if currentchar then
- local replacement=steps[1].coverage[currentchar]
- if not replacement or replacement=="" then
- if trace_bugs then
- logwarning("%s: no single for %s",cref(dataset,sequence,chainindex),gref(currentchar))
- end
- else
- if trace_singles then
- logprocess("%s: replacing single %s by %s",cref(dataset,sequence,chainindex),gref(currentchar),gref(replacement))
- end
- resetinjection(current)
- setchar(current,replacement)
- end
- return head,start,true
- elseif currentchar==false then
- break
- elseif current==stop then
- break
- else
- current=getnext(current)
- end
- end
- return head,start,false
-end
-function chainprocs.gsub_multiple(head,start,stop,dataset,sequence,currentlookup)
- local steps=currentlookup.steps
- local nofsteps=currentlookup.nofsteps
- if nofsteps>1 then
- reportmoresteps(dataset,sequence)
- end
- local startchar=getchar(start)
- local replacement=steps[1].coverage[startchar]
- if not replacement or replacement=="" then
- if trace_bugs then
- logwarning("%s: no multiple for %s",cref(dataset,sequence),gref(startchar))
- end
- else
- if trace_multiples then
- logprocess("%s: replacing %s by multiple characters %s",cref(dataset,sequence),gref(startchar),gref(replacement))
- end
- return multiple_glyphs(head,start,replacement,sequence.flags[1],dataset[1])
- end
- return head,start,false
-end
-function chainprocs.gsub_alternate(head,start,stop,dataset,sequence,currentlookup)
- local steps=currentlookup.steps
- local nofsteps=currentlookup.nofsteps
- if nofsteps>1 then
- reportmoresteps(dataset,sequence)
- end
- local kind=dataset[4]
- local what=dataset[1]
- local value=what==true and tfmdata.shared.features[kind] or what
- local current=start
- while current do
- local currentchar=ischar(current)
- if currentchar then
- local alternatives=steps[1].coverage[currentchar]
- if alternatives then
- local choice,comment=get_alternative_glyph(current,alternatives,value)
- if choice then
- if trace_alternatives then
- logprocess("%s: replacing %s by alternative %a to %s, %s",cref(dataset,sequence),gref(char),choice,gref(choice),comment)
- end
- resetinjection(start)
- setchar(start,choice)
- else
- if trace_alternatives then
- logwarning("%s: no variant %a for %s, %s",cref(dataset,sequence),value,gref(char),comment)
- end
- end
- end
- return head,start,true
- elseif currentchar==false then
- break
- elseif current==stop then
- break
- else
- current=getnext(current)
- end
- end
- return head,start,false
-end
-function chainprocs.gsub_ligature(head,start,stop,dataset,sequence,currentlookup,chainindex)
- local steps=currentlookup.steps
- local nofsteps=currentlookup.nofsteps
- if nofsteps>1 then
- reportmoresteps(dataset,sequence)
- end
- local startchar=getchar(start)
- local ligatures=steps[1].coverage[startchar]
- if not ligatures then
- if trace_bugs then
- logwarning("%s: no ligatures starting with %s",cref(dataset,sequence,chainindex),gref(startchar))
- end
- else
- local current=getnext(start)
- local discfound=false
- local last=stop
- local nofreplacements=1
- local skipmark=currentlookup.flags[1]
- while current do
- local id=getid(current)
- if id==disc_code then
- if not discfound then
- discfound=current
- end
- if current==stop then
- break
- else
- current=getnext(current)
- end
- else
- local schar=getchar(current)
- if skipmark and marks[schar] then
- current=getnext(current)
- else
- local lg=ligatures[schar]
- if lg then
- ligatures=lg
- last=current
- nofreplacements=nofreplacements+1
- if current==stop then
- break
- else
- current=getnext(current)
- end
- else
- break
- end
- end
- end
- end
- local ligature=ligatures.ligature
- if ligature then
- if chainindex then
- stop=last
- end
- if trace_ligatures then
- if start==stop then
- logprocess("%s: replacing character %s by ligature %s case 3",cref(dataset,sequence,chainindex),gref(startchar),gref(ligature))
- else
- logprocess("%s: replacing character %s upto %s by ligature %s case 4",cref(dataset,sequence,chainindex),gref(startchar),gref(getchar(stop)),gref(ligature))
- end
- end
- head,start=toligature(head,start,stop,ligature,dataset,sequence,skipmark,discfound)
- return head,start,true,nofreplacements,discfound
- elseif trace_bugs then
- if start==stop then
- logwarning("%s: replacing character %s by ligature fails",cref(dataset,sequence,chainindex),gref(startchar))
- else
- logwarning("%s: replacing character %s upto %s by ligature fails",cref(dataset,sequence,chainindex),gref(startchar),gref(getchar(stop)))
- end
- end
- end
- return head,start,false,0,false
-end
-function chainprocs.gpos_single(head,start,stop,dataset,sequence,currentlookup,rlmode,chainindex)
- local steps=currentlookup.steps
- local nofsteps=currentlookup.nofsteps
- if nofsteps>1 then
- reportmoresteps(dataset,sequence)
- end
- local startchar=getchar(start)
- local step=steps[1]
- local kerns=step.coverage[startchar]
- if not kerns then
- elseif step.format=="pair" then
- local dx,dy,w,h=setpair(start,factor,rlmode,sequence.flags[4],kerns)
- if trace_kerns then
- logprocess("%s: shifting single %s by (%p,%p) and correction (%p,%p)",cref(dataset,sequence),gref(startchar),dx,dy,w,h)
- end
- else
- local k=setkern(start,factor,rlmode,kerns,injection)
- if trace_kerns then
- logprocess("%s: shifting single %s by %p",cref(dataset,sequence),gref(startchar),k)
- end
- end
- return head,start,false
-end
-function chainprocs.gpos_pair(head,start,stop,dataset,sequence,currentlookup,rlmode,chainindex)
- local steps=currentlookup.steps
- local nofsteps=currentlookup.nofsteps
- if nofsteps>1 then
- reportmoresteps(dataset,sequence)
- end
- local snext=getnext(start)
- if snext then
- local startchar=getchar(start)
- local step=steps[1]
- local kerns=step.coverage[startchar]
- if kerns then
- local prev=start
- local done=false
- while snext do
- local nextchar=ischar(snext,currentfont)
- if not nextchar then
- break
- end
- local krn=kerns[nextchar]
- if not krn and marks[nextchar] then
- prev=snext
- snext=getnext(snext)
- elseif not krn then
- break
- elseif step.format=="pair" then
- local a,b=krn[1],krn[2]
- if optimizekerns then
- if not b and a[1]==0 and a[2]==0 and a[4]==0 then
- local k=setkern(snext,factor,rlmode,a[3],"injections")
- if trace_kerns then
- logprocess("%s: shifting single %s by %p",cref(dataset,sequence),gref(startchar),k)
- end
- done=true
- break
- end
- end
- if a and #a>0 then
- local startchar=getchar(start)
- local x,y,w,h=setpair(start,factor,rlmode,sequence.flags[4],a,"injections")
- if trace_kerns then
- logprocess("%s: shifting first of pair %s and %s by (%p,%p) and correction (%p,%p)",cref(dataset,sequence),gref(startchar),gref(nextchar),x,y,w,h)
- end
- end
- if b and #b>0 then
- local startchar=getchar(start)
- local x,y,w,h=setpair(snext,factor,rlmode,sequence.flags[4],b,"injections")
- if trace_kerns then
- logprocess("%s: shifting second of pair %s and %s by (%p,%p) and correction (%p,%p)",cref(dataset,sequence),gref(startchar),gref(nextchar),x,y,w,h)
- end
- end
- done=true
- break
- elseif krn~=0 then
- local k=setkern(snext,factor,rlmode,krn)
- if trace_kerns then
- logprocess("%s: inserting kern %s between %s and %s",cref(dataset,sequence),k,gref(getchar(prev)),gref(nextchar))
- end
- done=true
- break
- else
- break
- end
- end
- return head,start,done
- end
- end
- return head,start,false
-end
-function chainprocs.gpos_mark2base(head,start,stop,dataset,sequence,currentlookup,rlmode)
- local steps=currentlookup.steps
- local nofsteps=currentlookup.nofsteps
- if nofsteps>1 then
- reportmoresteps(dataset,sequence)
- end
- local markchar=getchar(start)
- if marks[markchar] then
- local markanchors=steps[1].coverage[markchar]
- if markanchors then
- local base=getprev(start)
- if base then
- local basechar=ischar(base,currentfont)
- if basechar then
- if marks[basechar] then
- while base do
- base=getprev(base)
- if base then
- local basechar=ischar(base,currentfont)
- if basechar then
- if not marks[basechar] then
- break
- end
- else
- if trace_bugs then
- logwarning("%s: no base for mark %s, case %i",pref(dataset,sequence),gref(markchar),1)
- end
- return head,start,false
- end
- else
- if trace_bugs then
- logwarning("%s: no base for mark %s, case %i",pref(dataset,sequence),gref(markchar),2)
- end
- return head,start,false
- end
- end
- end
- local ba=markanchors[1][basechar]
- if ba then
- local ma=markanchors[2]
- if ma then
- local dx,dy,bound=setmark(start,base,factor,rlmode,ba,ma,characters[basechar],false,checkmarks)
- if trace_marks then
- logprocess("%s, anchor %s, bound %s: anchoring mark %s to basechar %s => (%p,%p)",
- cref(dataset,sequence),anchor,bound,gref(markchar),gref(basechar),dx,dy)
- end
- return head,start,true
- end
- end
- elseif trace_bugs then
- logwarning("%s: prev node is no char, case %i",cref(dataset,sequence),1)
- end
- elseif trace_bugs then
- logwarning("%s: prev node is no char, case %i",cref(dataset,sequence),2)
- end
- elseif trace_bugs then
- logwarning("%s: mark %s has no anchors",cref(dataset,sequence),gref(markchar))
- end
- elseif trace_bugs then
- logwarning("%s: mark %s is no mark",cref(dataset,sequence),gref(markchar))
- end
- return head,start,false
-end
-function chainprocs.gpos_mark2ligature(head,start,stop,dataset,sequence,currentlookup,rlmode)
- local steps=currentlookup.steps
- local nofsteps=currentlookup.nofsteps
- if nofsteps>1 then
- reportmoresteps(dataset,sequence)
- end
- local markchar=getchar(start)
- if marks[markchar] then
- local markanchors=steps[1].coverage[markchar]
- if markanchors then
- local base=getprev(start)
- if base then
- local basechar=ischar(base,currentfont)
- if basechar then
- if marks[basechar] then
- while base do
- base=getprev(base)
- if base then
- local basechar=ischar(base,currentfont)
- if basechar then
- if not marks[basechar] then
- break
- end
- else
- if trace_bugs then
- logwarning("%s: no base for mark %s, case %i",cref(dataset,sequence),markchar,1)
- end
- return head,start,false
- end
- else
- if trace_bugs then
- logwarning("%s: no base for mark %s, case %i",cref(dataset,sequence),markchar,2)
- end
- return head,start,false
- end
- end
- end
- local ba=markanchors[1][basechar]
- if ba then
- local ma=markanchors[2]
- if ma then
- local index=getligaindex(start)
- ba=ba[index]
- if ba then
- local dx,dy,bound=setmark(start,base,factor,rlmode,ba,ma,characters[basechar],false,checkmarks)
- if trace_marks then
- logprocess("%s, anchor %s, bound %s: anchoring mark %s to baselig %s at index %s => (%p,%p)",
- cref(dataset,sequence),anchor,a or bound,gref(markchar),gref(basechar),index,dx,dy)
- end
- return head,start,true
- end
- end
- end
- elseif trace_bugs then
- logwarning("%s, prev node is no char, case %i",cref(dataset,sequence),1)
- end
- elseif trace_bugs then
- logwarning("%s, prev node is no char, case %i",cref(dataset,sequence),2)
- end
- elseif trace_bugs then
- logwarning("%s, mark %s has no anchors",cref(dataset,sequence),gref(markchar))
- end
- elseif trace_bugs then
- logwarning("%s, mark %s is no mark",cref(dataset,sequence),gref(markchar))
- end
- return head,start,false
-end
-function chainprocs.gpos_mark2mark(head,start,stop,dataset,sequence,currentlookup,rlmode)
- local steps=currentlookup.steps
- local nofsteps=currentlookup.nofsteps
- if nofsteps>1 then
- reportmoresteps(dataset,sequence)
- end
- local markchar=getchar(start)
- if marks[markchar] then
- local markanchors=steps[1].coverage[markchar]
- if markanchors then
- local base=getprev(start)
- local slc=getligaindex(start)
- if slc then
- while base do
- local blc=getligaindex(base)
- if blc and blc~=slc then
- base=getprev(base)
- else
- break
- end
- end
- end
- if base then
- local basechar=ischar(base,currentfont)
- if basechar then
- local ba=markanchors[1][basechar]
- if ba then
- local ma=markanchors[2]
- if ma then
- local dx,dy,bound=setmark(start,base,factor,rlmode,ba,ma,characters[basechar],true,checkmarks)
- if trace_marks then
- logprocess("%s, anchor %s, bound %s: anchoring mark %s to basemark %s => (%p,%p)",
- cref(dataset,sequence),anchor,bound,gref(markchar),gref(basechar),dx,dy)
- end
- return head,start,true
- end
- end
- elseif trace_bugs then
- logwarning("%s: prev node is no mark, case %i",cref(dataset,sequence),1)
- end
- elseif trace_bugs then
- logwarning("%s: prev node is no mark, case %i",cref(dataset,sequence),2)
- end
- elseif trace_bugs then
- logwarning("%s: mark %s has no anchors",cref(dataset,sequence),gref(markchar))
- end
- elseif trace_bugs then
- logwarning("%s: mark %s is no mark",cref(dataset,sequence),gref(markchar))
- end
- return head,start,false
-end
-function chainprocs.gpos_cursive(head,start,stop,dataset,sequence,currentlookup,rlmode)
- local steps=currentlookup.steps
- local nofsteps=currentlookup.nofsteps
- if nofsteps>1 then
- reportmoresteps(dataset,sequence)
- end
- local startchar=getchar(start)
- local exitanchors=steps[1].coverage[startchar]
- if exitanchors then
- local done=false
- if marks[startchar] then
- if trace_cursive then
- logprocess("%s: ignoring cursive for mark %s",pref(dataset,sequence),gref(startchar))
- end
- else
- local nxt=getnext(start)
- while not done and nxt do
- local nextchar=ischar(nxt,currentfont)
- if not nextchar then
- break
- elseif marks[nextchar] then
- nxt=getnext(nxt)
- else
- local exit=exitanchors[3]
- if exit then
- local entry=exitanchors[1][nextchar]
- if entry then
- entry=entry[2]
- if entry then
- local dx,dy,bound=setcursive(start,nxt,factor,rlmode,exit,entry,characters[startchar],characters[nextchar])
- if trace_cursive then
- logprocess("%s: moving %s to %s cursive (%p,%p) using anchor %s and bound %s in %s mode",pref(dataset,sequence),gref(startchar),gref(nextchar),dx,dy,anchor,bound,mref(rlmode))
- end
- done=true
- break
- end
- end
- elseif trace_bugs then
- onetimemessage(currentfont,startchar,"no entry anchors",report_fonts)
- end
- break
- end
- end
- end
- return head,start,done
- else
- if trace_cursive and trace_details then
- logprocess("%s, cursive %s is already done",pref(dataset,sequence),gref(getchar(start)),alreadydone)
- end
- return head,start,false
- end
-end
-local function show_skip(dataset,sequence,char,ck,class)
- logwarning("%s: skipping char %s, class %a, rule %a, lookuptype %a",cref(dataset,sequence),gref(char),class,ck[1],ck[8] or ck[2])
-end
-local new_kern=nuts.pool.kern
-local function checked(head)
- local current=head
- while current do
- if getid(current)==glue_code then
- local kern=new_kern(getfield(current,"width"))
- if head==current then
- local next=getnext(current)
- if next then
- setlink(kern,next)
- end
- flush_node(current)
- head=kern
- current=next
- else
- local prev,next=getboth(current)
- setlink(prev,kern)
- setlink(kern,next)
- flush_node(current)
- current=next
- end
- else
- current=getnext(current)
- end
- end
- return head
-end
-local function setdiscchecked(d,pre,post,replace)
- if pre then pre=checked(pre) end
- if post then post=checked(post) end
- if replace then replace=checked(replace) end
- setdisc(d,pre,post,replace)
-end
-local function chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,k,ck,chainproc)
- if not start then
- return head,start,false
- end
- local startishead=start==head
- local seq=ck[3]
- local f=ck[4]
- local l=ck[5]
- local s=#seq
- local done=false
- local sweepnode=sweepnode
- local sweeptype=sweeptype
- local sweepoverflow=false
- local checkdisc=getprev(head)
- local keepdisc=not sweepnode
- local lookaheaddisc=nil
- local backtrackdisc=nil
- local current=start
- local last=start
- local prev=getprev(start)
- local hasglue=false
- local i=f
- while i<=l do
- local id=getid(current)
- if id==glyph_code then
- i=i+1
- last=current
- current=getnext(current)
- elseif id==glue_code then
- i=i+1
- last=current
- current=getnext(current)
- hasglue=true
- elseif id==disc_code then
- if keepdisc then
- keepdisc=false
- if notmatchpre[current]~=notmatchreplace[current] then
- lookaheaddisc=current
- end
- local replace=getfield(current,"replace")
- while replace and i<=l do
- if getid(replace)==glyph_code then
- i=i+1
- end
- replace=getnext(replace)
- end
- last=current
- current=getnext(c)
- else
- head,current=flattendisk(head,current)
- end
- else
- last=current
- current=getnext(current)
- end
- if current then
- elseif sweepoverflow then
- break
- elseif sweeptype=="post" or sweeptype=="replace" then
- current=getnext(sweepnode)
- if current then
- sweeptype=nil
- sweepoverflow=true
- else
- break
- end
- else
- break
- end
- end
- if sweepoverflow then
- local prev=current and getprev(current)
- if not current or prev~=sweepnode then
- local head=getnext(sweepnode)
- local tail=nil
- if prev then
- tail=prev
- setprev(current,sweepnode)
- else
- tail=find_node_tail(head)
- end
- setnext(sweepnode,current)
- setprev(head)
- setnext(tail)
- appenddisc(sweepnode,head)
- end
- end
- if l<s then
- local i=l
- local t=sweeptype=="post" or sweeptype=="replace"
- while current and i<s do
- local id=getid(current)
- if id==glyph_code then
- i=i+1
- current=getnext(current)
- elseif id==glue_code then
- i=i+1
- current=getnext(current)
- hasglue=true
- elseif id==disc_code then
- if keepdisc then
- keepdisc=false
- if notmatchpre[current]~=notmatchreplace[current] then
- lookaheaddisc=current
- end
- local replace=getfield(c,"replace")
- while replace and i<s do
- if getid(replace)==glyph_code then
- i=i+1
- end
- replace=getnext(replace)
- end
- current=getnext(current)
- elseif notmatchpre[current]~=notmatchreplace[current] then
- head,current=flattendisk(head,current)
- else
- current=getnext(current)
- end
- else
- current=getnext(current)
- end
- if not current and t then
- current=getnext(sweepnode)
- if current then
- sweeptype=nil
- end
- end
- end
- end
- if f>1 then
- local current=prev
- local i=f
- local t=sweeptype=="pre" or sweeptype=="replace"
- if not current and t and current==checkdisk then
- current=getprev(sweepnode)
- end
- while current and i>1 do
- local id=getid(current)
- if id==glyph_code then
- i=i-1
- elseif id==glue_code then
- i=i-1
- hasglue=true
- elseif id==disc_code then
- if keepdisc then
- keepdisc=false
- if notmatchpost[current]~=notmatchreplace[current] then
- backtrackdisc=current
- end
- local replace=getfield(current,"replace")
- while replace and i>1 do
- if getid(replace)==glyph_code then
- i=i-1
- end
- replace=getnext(replace)
- end
- elseif notmatchpost[current]~=notmatchreplace[current] then
- head,current=flattendisk(head,current)
- end
- end
- current=getprev(current)
- if t and current==checkdisk then
- current=getprev(sweepnode)
- end
- end
- end
- local ok=false
- if lookaheaddisc then
- local cf=start
- local cl=getprev(lookaheaddisc)
- local cprev=getprev(start)
- local insertedmarks=0
- while cprev do
- local char=ischar(cf,currentfont)
- if char and marks[char] then
- insertedmarks=insertedmarks+1
- cf=cprev
- startishead=cf==head
- cprev=getprev(cprev)
- else
- break
- end
- end
- setprev(lookaheaddisc,cprev)
- if cprev then
- setnext(cprev,lookaheaddisc)
- end
- setprev(cf)
- setnext(cl)
- if startishead then
- head=lookaheaddisc
- end
- local pre,post,replace=getdisc(lookaheaddisc)
- local new=copy_node_list(cf)
- local cnew=new
- for i=1,insertedmarks do
- cnew=getnext(cnew)
- end
- local clast=cnew
- for i=f,l do
- clast=getnext(clast)
- end
- if not notmatchpre[lookaheaddisc] then
- cf,start,ok=chainproc(cf,start,last,dataset,sequence,chainlookup,rlmode,k)
- end
- if not notmatchreplace[lookaheaddisc] then
- new,cnew,ok=chainproc(new,cnew,clast,dataset,sequence,chainlookup,rlmode,k)
- end
- if pre then
- setlink(cl,pre)
- end
- if replace then
- local tail=find_node_tail(new)
- setlink(tail,replace)
- end
- if hasglue then
- setdiscchecked(lookaheaddisc,cf,post,new)
- else
- setdisc(lookaheaddisc,cf,post,new)
- end
- start=getprev(lookaheaddisc)
- sweephead[cf]=getnext(clast)
- sweephead[new]=getnext(last)
- elseif backtrackdisc then
- local cf=getnext(backtrackdisc)
- local cl=start
- local cnext=getnext(start)
- local insertedmarks=0
- while cnext do
- local char=ischar(cnext,currentfont)
- if char and marks[char] then
- insertedmarks=insertedmarks+1
- cl=cnext
- cnext=getnext(cnext)
- else
- break
- end
- end
- if cnext then
- setprev(cnext,backtrackdisc)
- end
- setnext(backtrackdisc,cnext)
- setprev(cf)
- setnext(cl)
- local pre,post,replace,pretail,posttail,replacetail=getdisc(backtrackdisc,true)
- local new=copy_node_list(cf)
- local cnew=find_node_tail(new)
- for i=1,insertedmarks do
- cnew=getprev(cnew)
- end
- local clast=cnew
- for i=f,l do
- clast=getnext(clast)
- end
- if not notmatchpost[backtrackdisc] then
- cf,start,ok=chainproc(cf,start,last,dataset,sequence,chainlookup,rlmode,k)
- end
- if not notmatchreplace[backtrackdisc] then
- new,cnew,ok=chainproc(new,cnew,clast,dataset,sequence,chainlookup,rlmode,k)
- end
- if post then
- setlink(posttail,cf)
- else
- post=cf
- end
- if replace then
- setlink(replacetail,new)
- else
- replace=new
- end
- if hasglue then
- setdiscchecked(backtrackdisc,pre,post,replace)
- else
- setdisc(backtrackdisc,pre,post,replace)
- end
- start=getprev(backtrackdisc)
- sweephead[post]=getnext(clast)
- sweephead[replace]=getnext(last)
- else
- head,start,ok=chainproc(head,start,last,dataset,sequence,chainlookup,rlmode,k)
- end
- return head,start,ok
-end
-local noflags={ false,false,false,false }
-local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
- local sweepnode=sweepnode
- local sweeptype=sweeptype
- local currentfont=currentfont
- local diskseen=false
- local checkdisc=getprev(head)
- local flags=sequence.flags or noflags
- local done=false
- local skipmark=flags[1]
- local skipligature=flags[2]
- local skipbase=flags[3]
- local markclass=sequence.markclass
- local skipped=false
- for k=1,#contexts do
- local match=true
- local current=start
- local last=start
- local ck=contexts[k]
- local seq=ck[3]
- local s=#seq
- local size=1
- if s==1 then
- local char=ischar(current,currentfont)
- if char then
- match=seq[1][char]
- end
- else
- local f=ck[4]
- local l=ck[5]
- size=l-f+1
- if size>1 then
- local discfound=nil
- local n=f+1
- last=getnext(last)
- while n<=l do
- if not last and (sweeptype=="post" or sweeptype=="replace") then
- last=getnext(sweepnode)
- sweeptype=nil
- end
- if last then
- local char,id=ischar(last,currentfont)
- if char then
- local ccd=descriptions[char]
- if ccd then
- local class=ccd.class or "base"
- if class==skipmark or class==skipligature or class==skipbase or (markclass and class=="mark" and not markclass[char]) then
- skipped=true
- if trace_skips then
- show_skip(dataset,sequence,char,ck,class)
- end
- last=getnext(last)
- elseif seq[n][char] then
- if n<l then
- last=getnext(last)
- end
- n=n+1
- else
- if discfound then
- notmatchreplace[discfound]=true
- match=not notmatchpre[discfound]
- else
- match=false
- end
- break
- end
- else
- if discfound then
- notmatchreplace[discfound]=true
- match=not notmatchpre[discfound]
- else
- match=false
- end
- break
- end
- elseif char==false then
- if discfound then
- notmatchreplace[discfound]=true
- match=not notmatchpre[discfound]
- else
- match=false
- end
- break
- elseif id==disc_code then
- diskseen=true
- discfound=last
- notmatchpre[last]=nil
- notmatchpost[last]=true
- notmatchreplace[last]=nil
- local pre,post,replace=getdisc(last)
- if pre then
- local n=n
- while pre do
- if seq[n][getchar(pre)] then
- n=n+1
- pre=getnext(pre)
- if n>l then
- break
- end
- else
- notmatchpre[last]=true
- break
- end
- end
- if n<=l then
- notmatchpre[last]=true
- end
- else
- notmatchpre[last]=true
- end
- if replace then
- while replace do
- if seq[n][getchar(replace)] then
- n=n+1
- replace=getnext(replace)
- if n>l then
- break
- end
- else
- notmatchreplace[last]=true
- match=not notmatchpre[last]
- break
- end
- end
- match=not notmatchpre[last]
- end
- last=getnext(last)
- else
- match=false
- break
- end
- else
- match=false
- break
- end
- end
- end
- if match and f>1 then
- local prev=getprev(start)
- if prev then
- if prev==checkdisc and (sweeptype=="pre" or sweeptype=="replace") then
- prev=getprev(sweepnode)
- end
- if prev then
- local discfound=nil
- local n=f-1
- while n>=1 do
- if prev then
- local char,id=ischar(prev,currentfont)
- if char then
- local ccd=descriptions[char]
- if ccd then
- local class=ccd.class
- if class==skipmark or class==skipligature or class==skipbase or (markclass and class=="mark" and not markclass[char]) then
- skipped=true
- if trace_skips then
- show_skip(dataset,sequence,char,ck,class)
- end
- prev=getprev(prev)
- elseif seq[n][char] then
- if n>1 then
- prev=getprev(prev)
- end
- n=n-1
- else
- if discfound then
- notmatchreplace[discfound]=true
- match=not notmatchpost[discfound]
- else
- match=false
- end
- break
- end
- else
- if discfound then
- notmatchreplace[discfound]=true
- match=not notmatchpost[discfound]
- else
- match=false
- end
- break
- end
- elseif char==false then
- if discfound then
- notmatchreplace[discfound]=true
- match=not notmatchpost[discfound]
- else
- match=false
- end
- break
- elseif id==disc_code then
- diskseen=true
- discfound=prev
- notmatchpre[prev]=true
- notmatchpost[prev]=nil
- notmatchreplace[prev]=nil
- local pre,post,replace,pretail,posttail,replacetail=getdisc(prev,true)
- if pre~=start and post~=start and replace~=start then
- if post then
- local n=n
- while posttail do
- if seq[n][getchar(posttail)] then
- n=n-1
- if posttail==post then
- break
- else
- posttail=getprev(posttail)
- if n<1 then
- break
- end
- end
- else
- notmatchpost[prev]=true
- break
- end
- end
- if n>=1 then
- notmatchpost[prev]=true
- end
- else
- notmatchpost[prev]=true
- end
- if replace then
- while replacetail do
- if seq[n][getchar(replacetail)] then
- n=n-1
- if replacetail==replace then
- break
- else
- replacetail=getprev(replacetail)
- if n<1 then
- break
- end
- end
- else
- notmatchreplace[prev]=true
- match=not notmatchpost[prev]
- break
- end
- end
- if not match then
- break
- end
- end
- end
- prev=getprev(prev)
- elseif seq[n][32] and isspace(prev,threshold) then
- n=n-1
- prev=getprev(prev)
- else
- match=false
- break
- end
- else
- match=false
- break
- end
- end
- else
- match=false
- end
- else
- match=false
- end
- end
- if match and s>l then
- local current=last and getnext(last)
- if not current then
- if sweeptype=="post" or sweeptype=="replace" then
- current=getnext(sweepnode)
- end
- end
- if current then
- local discfound=nil
- local n=l+1
- while n<=s do
- if current then
- local char,id=ischar(current,currentfont)
- if char then
- local ccd=descriptions[char]
- if ccd then
- local class=ccd.class
- if class==skipmark or class==skipligature or class==skipbase or (markclass and class=="mark" and not markclass[char]) then
- skipped=true
- if trace_skips then
- show_skip(dataset,sequence,char,ck,class)
- end
- current=getnext(current)
- elseif seq[n][char] then
- if n<s then
- current=getnext(current)
- end
- n=n+1
- else
- if discfound then
- notmatchreplace[discfound]=true
- match=not notmatchpre[discfound]
- else
- match=false
- end
- break
- end
- else
- if discfound then
- notmatchreplace[discfound]=true
- match=not notmatchpre[discfound]
- else
- match=false
- end
- break
- end
- elseif char==false then
- if discfound then
- notmatchreplace[discfound]=true
- match=not notmatchpre[discfound]
- else
- match=false
- end
- break
- elseif id==disc_code then
- diskseen=true
- discfound=current
- notmatchpre[current]=nil
- notmatchpost[current]=true
- notmatchreplace[current]=nil
- local pre,post,replace=getdisc(current)
- if pre then
- local n=n
- while pre do
- if seq[n][getchar(pre)] then
- n=n+1
- pre=getnext(pre)
- if n>s then
- break
- end
- else
- notmatchpre[current]=true
- break
- end
- end
- if n<=s then
- notmatchpre[current]=true
- end
- else
- notmatchpre[current]=true
- end
- if replace then
- while replace do
- if seq[n][getchar(replace)] then
- n=n+1
- replace=getnext(replace)
- if n>s then
- break
- end
- else
- notmatchreplace[current]=true
- match=notmatchpre[current]
- break
- end
- end
- if not match then
- break
- end
- else
- end
- current=getnext(current)
- elseif seq[n][32] and isspace(current,threshold) then
- n=n+1
- current=getnext(current)
- else
- match=false
- break
- end
- else
- match=false
- break
- end
- end
- else
- match=false
- end
- end
- end
- if match then
- local diskchain=diskseen or sweepnode
- if trace_contexts then
- local rule=ck[1]
- local lookuptype=ck[8] or ck[2]
- local first=ck[4]
- local last=ck[5]
- local char=getchar(start)
- logwarning("%s: rule %s matches at char %s for (%s,%s,%s) chars, lookuptype %a",
- cref(dataset,sequence),rule,gref(char),first-1,last-first+1,s-last,lookuptype)
- end
- local chainlookups=ck[6]
- if chainlookups then
- local nofchainlookups=#chainlookups
- if size==1 then
- local chainlookup=chainlookups[1]
- local chainkind=chainlookup.type
- local chainproc=chainprocs[chainkind]
- if chainproc then
- local ok
- if diskchain then
- head,start,ok=chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,1,ck,chainproc)
- else
- head,start,ok=chainproc(head,start,last,dataset,sequence,chainlookup,rlmode,1)
- end
- if ok then
- done=true
- end
- else
- logprocess("%s: %s is not yet supported (1)",cref(dataset,sequence),chainkind)
- end
- else
- local i=1
- while start do
- if skipped then
- while start do
- local char=getchar(start)
- local ccd=descriptions[char]
- if ccd then
- local class=ccd.class or "base"
- if class==skipmark or class==skipligature or class==skipbase or (markclass and class=="mark" and not markclass[char]) then
- start=getnext(start)
- else
- break
- end
- else
- break
- end
- end
- end
- local chainlookup=chainlookups[i]
- if chainlookup then
- local chainkind=chainlookup.type
- local chainproc=chainprocs[chainkind]
- if chainproc then
- local ok,n
- if diskchain then
- head,start,ok=chaindisk(head,start,last,dataset,sequence,chainlookup,rlmode,i,ck,chainproc)
- else
- head,start,ok,n=chainproc(head,start,last,dataset,sequence,chainlookup,rlmode,i)
- end
- if ok then
- done=true
- if n and n>1 and i+n>nofchainlookups then
- break
- end
- end
- else
- logprocess("%s: %s is not yet supported (2)",cref(dataset,sequence),chainkind)
- end
- end
- i=i+1
- if i>size or not start then
- break
- elseif start then
- start=getnext(start)
- end
- end
- end
- else
- local replacements=ck[7]
- if replacements then
- head,start,done=reversesub(head,start,last,dataset,sequence,replacements,rlmode)
- else
- done=true
- if trace_contexts then
- logprocess("%s: skipping match",cref(dataset,sequence))
- end
- end
- end
- if done then
- break
- end
- end
- end
- if diskseen then
- notmatchpre={}
- notmatchpost={}
- notmatchreplace={}
- end
- return head,start,done
-end
-handlers.gsub_context=handle_contextchain
-handlers.gsub_contextchain=handle_contextchain
-handlers.gsub_reversecontextchain=handle_contextchain
-handlers.gpos_contextchain=handle_contextchain
-handlers.gpos_context=handle_contextchain
-local function chained_contextchain(head,start,stop,dataset,sequence,currentlookup,rlmode)
- local steps=currentlookup.steps
- local nofsteps=currentlookup.nofsteps
- if nofsteps>1 then
- reportmoresteps(dataset,sequence)
- end
- return handle_contextchain(head,start,dataset,sequence,currentlookup,rlmode)
-end
-chainprocs.gsub_context=chained_contextchain
-chainprocs.gsub_contextchain=chained_contextchain
-chainprocs.gsub_reversecontextchain=chained_contextchain
-chainprocs.gpos_contextchain=chained_contextchain
-chainprocs.gpos_context=chained_contextchain
-local missing=setmetatableindex("table")
-local function logprocess(...)
- if trace_steps then
- registermessage(...)
- end
- report_process(...)
-end
-local logwarning=report_process
-local function report_missing_coverage(dataset,sequence)
- local t=missing[currentfont]
- if not t[sequence] then
- t[sequence]=true
- logwarning("missing coverage for feature %a, lookup %a, type %a, font %a, name %a",
- dataset[4],sequence.name,sequence.type,currentfont,tfmdata.properties.fullname)
- end
-end
-local resolved={}
-local sequencelists=setmetatableindex(function(t,font)
- local sequences=fontdata[font].resources.sequences
- if not sequences or not next(sequences) then
- sequences=false
- end
- t[font]=sequences
- return sequences
-end)
-local autofeatures=fonts.analyzers.features
-local featuretypes=otf.tables.featuretypes
-local defaultscript=otf.features.checkeddefaultscript
-local defaultlanguage=otf.features.checkeddefaultlanguage
-local function initialize(sequence,script,language,enabled,autoscript,autolanguage)
- local features=sequence.features
- if features then
- local order=sequence.order
- if order then
- local featuretype=featuretypes[sequence.type or "unknown"]
- for i=1,#order do
- local kind=order[i]
- local valid=enabled[kind]
- if valid then
- local scripts=features[kind]
- local languages=scripts and (
- scripts[script] or
- scripts[wildcard] or
- (autoscript and defaultscript(featuretype,autoscript,scripts))
- )
- local enabled=languages and (
- languages[language] or
- languages[wildcard] or
- (autolanguage and defaultlanguage(featuretype,autolanguage,languages))
- )
- if enabled then
- return { valid,autofeatures[kind] or false,sequence,kind }
- end
- end
- end
- else
- end
- end
- return false
-end
-function otf.dataset(tfmdata,font)
- local shared=tfmdata.shared
- local properties=tfmdata.properties
- local language=properties.language or "dflt"
- local script=properties.script or "dflt"
- local enabled=shared.features
- local autoscript=enabled and enabled.autoscript
- local autolanguage=enabled and enabled.autolanguage
- local res=resolved[font]
- if not res then
- res={}
- resolved[font]=res
- end
- local rs=res[script]
- if not rs then
- rs={}
- res[script]=rs
- end
- local rl=rs[language]
- if not rl then
- rl={
- }
- rs[language]=rl
- local sequences=tfmdata.resources.sequences
- if sequences then
- for s=1,#sequences do
- local v=enabled and initialize(sequences[s],script,language,enabled,autoscript,autolanguage)
- if v then
- rl[#rl+1]=v
- end
- end
- end
- end
- return rl
-end
-local function report_disc(what,n)
- report_run("%s: %s > %s",what,n,languages.serializediscretionary(n))
-end
-local function kernrun(disc,k_run,font,attr,...)
- if trace_kernruns then
- report_disc("kern",disc)
- end
- local prev,next=getboth(disc)
- local nextstart=next
- local done=false
- local pre,post,replace,pretail,posttail,replacetail=getdisc(disc,true)
- local prevmarks=prev
- while prevmarks do
- local char=ischar(prevmarks,font)
- if char and marks[char] then
- prevmarks=getprev(prevmarks)
- else
- break
- end
- end
- if prev and not ischar(prev,font) then
- prev=false
- end
- if next and not ischar(next,font) then
- next=false
- end
- if pre then
- if k_run(pre,"injections",nil,font,attr,...) then
- done=true
- end
- if prev then
- local nest=getprev(pre)
- setlink(prev,pre)
- if k_run(prevmarks,"preinjections",pre,font,attr,...) then
- done=true
- end
- setprev(pre,nest)
- setnext(prev,disc)
- end
- end
- if post then
- if k_run(post,"injections",nil,font,attr,...) then
- done=true
- end
- if next then
- setlink(posttail,next)
- if k_run(posttail,"postinjections",next,font,attr,...) then
- done=true
- end
- setnext(posttail)
- setprev(next,disc)
- end
- end
- if replace then
- if k_run(replace,"injections",nil,font,attr,...) then
- done=true
- end
- if prev then
- local nest=getprev(replace)
- setlink(prev,replace)
- if k_run(prevmarks,"replaceinjections",replace,font,attr,...) then
- done=true
- end
- setprev(replace,nest)
- setnext(prev,disc)
- end
- if next then
- setlink(replacetail,next)
- if k_run(replacetail,"replaceinjections",next,font,attr,...) then
- done=true
- end
- setnext(replacetail)
- setprev(next,disc)
- end
- elseif prev and next then
- setlink(prev,next)
- if k_run(prevmarks,"emptyinjections",next,font,attr,...) then
- done=true
- end
- setlink(prev,disc)
- setlink(disc,next)
- end
- return nextstart,done
-end
-local function comprun(disc,c_run,...)
- if trace_compruns then
- report_disc("comp",disc)
- end
- local pre,post,replace=getdisc(disc)
- local renewed=false
- if pre then
- sweepnode=disc
- sweeptype="pre"
- local new,done=c_run(pre,...)
- if done then
- pre=new
- renewed=true
- end
- end
- if post then
- sweepnode=disc
- sweeptype="post"
- local new,done=c_run(post,...)
- if done then
- post=new
- renewed=true
- end
- end
- if replace then
- sweepnode=disc
- sweeptype="replace"
- local new,done=c_run(replace,...)
- if done then
- replace=new
- renewed=true
- end
- end
- sweepnode=nil
- sweeptype=nil
- if renewed then
- setdisc(disc,pre,post,replace)
- end
- return getnext(disc),renewed
-end
-local function testrun(disc,t_run,c_run,...)
- if trace_testruns then
- report_disc("test",disc)
- end
- local prev,next=getboth(disc)
- if not next then
- return
- end
- local pre,post,replace,pretail,posttail,replacetail=getdisc(disc,true)
- local done=false
- if replace and prev then
- setlink(replacetail,next)
- local ok,overflow=t_run(replace,next,...)
- if ok and overflow then
- setfield(disc,"replace")
- setlink(prev,replace)
- setboth(disc)
- flush_node_list(disc)
- return replace,true
- else
- setnext(replacetail)
- setprev(next,disc)
- end
- end
- local renewed=false
- if pre then
- sweepnode=disc
- sweeptype="pre"
- local new,ok=c_run(pre,...)
- if ok then
- pre=new
- renewed=true
- end
- end
- if post then
- sweepnode=disc
- sweeptype="post"
- local new,ok=c_run(post,...)
- if ok then
- post=new
- renewed=true
- end
- end
- if replace then
- sweepnode=disc
- sweeptype="replace"
- local new,ok=c_run(replace,...)
- if ok then
- replace=new
- renewed=true
- end
- end
- sweepnode=nil
- sweeptype=nil
- if renewed then
- setdisc(disc,pre,post,replace)
- return next,true
- else
- return next,done
- end
-end
-local nesting=0
-local function c_run_single(head,font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
- local done=false
- local sweep=sweephead[head]
- if sweep then
- start=sweep
- sweephead[head]=nil
- else
- start=head
- end
- while start do
- local char=ischar(start,font)
- if char then
- local a=attr and getattr(start,0)
- if not a or (a==attr) then
- local lookupmatch=lookupcache[char]
- if lookupmatch then
- local ok
- head,start,ok=handler(head,start,dataset,sequence,lookupmatch,rlmode,step,1)
- if ok then
- done=true
- end
- end
- if start then
- start=getnext(start)
- end
- else
- start=getnext(start)
- end
- elseif char==false then
- return head,done
- elseif sweep then
- return head,done
- else
- start=getnext(start)
- end
- end
- return head,done
-end
-local function t_run_single(start,stop,font,attr,lookupcache)
- while start~=stop do
- local char=ischar(start,font)
- if char then
- local a=attr and getattr(start,0)
- if not a or (a==attr) then
- local lookupmatch=lookupcache[char]
- if lookupmatch then
- local s=getnext(start)
- local l=nil
- local d=0
- while s do
- if s==stop then
- d=1
- elseif d>0 then
- d=d+1
- end
- local lg=lookupmatch[getchar(s)]
- if lg then
- l=lg
- s=getnext(s)
- else
- break
- end
- end
- if l and l.ligature then
- return true,d>1
- end
- end
- else
- end
- start=getnext(start)
- else
- break
- end
- end
-end
-local function k_run_single(sub,injection,last,font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
- local a=attr and getattr(sub,0)
- if not a or (a==attr) then
- for n in traverse_nodes(sub) do
- if n==last then
- break
- end
- local char=ischar(n)
- if char then
- local lookupmatch=lookupcache[char]
- if lookupmatch then
- local h,d,ok=handler(sub,n,dataset,sequence,lookupmatch,rlmode,step,1,injection)
- if ok then
- return true
- end
- end
- end
- end
- end
-end
-local function c_run_multiple(head,font,attr,steps,nofsteps,dataset,sequence,rlmode,handler)
- local done=false
- local sweep=sweephead[head]
- if sweep then
- start=sweep
- sweephead[head]=nil
- else
- start=head
- end
- while start do
- local char=ischar(start,font)
- if char then
- local a=attr and getattr(start,0)
- if not a or (a==attr) then
- for i=1,nofsteps do
- local step=steps[i]
- local lookupcache=step.coverage
- if lookupcache then
- local lookupmatch=lookupcache[char]
- if lookupmatch then
- local ok
- head,start,ok=handler(head,start,dataset,sequence,lookupmatch,rlmode,step,i)
- if ok then
- done=true
- break
- elseif not start then
- break
- end
- end
- else
- report_missing_coverage(dataset,sequence)
- end
- end
- if start then
- start=getnext(start)
- end
- else
- start=getnext(start)
- end
- elseif char==false then
- return head,done
- elseif sweep then
- return head,done
- else
- start=getnext(start)
- end
- end
- return head,done
-end
-local function t_run_multiple(start,stop,font,attr,steps,nofsteps)
- while start~=stop do
- local char=ischar(start,font)
- if char then
- local a=attr and getattr(start,0)
- if not a or (a==attr) then
- for i=1,nofsteps do
- local step=steps[i]
- local lookupcache=step.coverage
- if lookupcache then
- local lookupmatch=lookupcache[char]
- if lookupmatch then
- local s=getnext(start)
- local l=nil
- local d=0
- while s do
- if s==stop then
- d=1
- elseif d>0 then
- d=d+1
- end
- local lg=lookupmatch[getchar(s)]
- if lg then
- l=lg
- s=getnext(s)
- else
- break
- end
- end
- if l and l.ligature then
- return true,d>1
- end
- end
- else
- report_missing_coverage(dataset,sequence)
- end
- end
- else
- end
- start=getnext(start)
- else
- break
- end
- end
-end
-local function k_run_multiple(sub,injection,last,font,attr,steps,nofsteps,dataset,sequence,rlmode,handler)
- local a=attr and getattr(sub,0)
- if not a or (a==attr) then
- for n in traverse_nodes(sub) do
- if n==last then
- break
- end
- local char=ischar(n)
- if char then
- for i=1,nofsteps do
- local step=steps[i]
- local lookupcache=step.coverage
- if lookupcache then
- local lookupmatch=lookupcache[char]
- if lookupmatch then
- local h,d,ok=handler(head,n,dataset,sequence,lookupmatch,step,rlmode,i,injection)
- if ok then
- return true
- end
- end
- else
- report_missing_coverage(dataset,sequence)
- end
- end
- end
- end
- end
-end
-local function txtdirstate(start,stack,top,rlparmode)
- local dir=getfield(start,"dir")
- local new=1
- if dir=="+TRT" then
- top=top+1
- stack[top]=dir
- new=-1
- elseif dir=="+TLT" then
- top=top+1
- stack[top]=dir
- elseif dir=="-TRT" or dir=="-TLT" then
- top=top-1
- if stack[top]=="+TRT" then
- new=-1
- end
- else
- new=rlparmode
- end
- if trace_directions then
- report_process("directions after txtdir %a: parmode %a, txtmode %a, level %a",dir,mref(rlparmode),mref(new),top)
- end
- return getnext(start),top,new
-end
-local function pardirstate(start)
- local dir=getfield(start,"dir")
- local new=0
- if dir=="TLT" then
- new=1
- elseif dir=="TRT" then
- new=-1
- end
- if trace_directions then
- report_process("directions after pardir %a: parmode %a",dir,mref(new))
- end
- return getnext(start),new,new
-end
-otf.helpers=otf.helpers or {}
-otf.helpers.txtdirstate=txtdirstate
-otf.helpers.pardirstate=pardirstate
-local function featuresprocessor(head,font,attr)
- local sequences=sequencelists[font]
- if not sequencelists then
- return head,false
- end
- nesting=nesting+1
- if nesting==1 then
- currentfont=font
- tfmdata=fontdata[font]
- descriptions=tfmdata.descriptions
- characters=tfmdata.characters
- marks=tfmdata.resources.marks
- threshold,
- factor=getthreshold(font)
- checkmarks=tfmdata.properties.checkmarks
- elseif currentfont~=font then
- report_warning("nested call with a different font, level %s, quitting",nesting)
- nesting=nesting-1
- return head,false
- end
- head=tonut(head)
- if trace_steps then
- checkstep(head)
- end
- local rlmode=0
- local done=false
- local datasets=otf.dataset(tfmdata,font,attr)
- local forcedisc=alwaysdisc or not attr
- local dirstack={}
- sweephead={}
- for s=1,#datasets do
- local dataset=datasets[s]
- local attribute=dataset[2]
- local sequence=dataset[3]
- local rlparmode=0
- local topstack=0
- local success=false
- local typ=sequence.type
- local gpossing=typ=="gpos_single" or typ=="gpos_pair"
- local handler=handlers[typ]
- local steps=sequence.steps
- local nofsteps=sequence.nofsteps
- if not steps then
- local h,d,ok=handler(head,head,dataset,sequence,nil,nil,nil,0,font,attr)
- if ok then
- success=true
- if h then
- head=h
- end
- end
- elseif typ=="gsub_reversecontextchain" then
- local start=find_node_tail(head)
- while start do
- local char=ischar(start,font)
- if char then
- local a=attr and getattr(start,0)
- if not a or (a==attr) then
- for i=1,nofsteps do
- local step=steps[i]
- local lookupcache=step.coverage
- if lookupcache then
- local lookupmatch=lookupcache[char]
- if lookupmatch then
- local ok
- head,start,ok=handler(head,start,dataset,sequence,lookupmatch,rlmode,step,i)
- if ok then
- success=true
- break
- end
- end
- else
- report_missing_coverage(dataset,sequence)
- end
- end
- if start then
- start=getprev(start)
- end
- else
- start=getprev(start)
- end
- else
- start=getprev(start)
- end
- end
- else
- local start=head
- rlmode=0
- if nofsteps==1 then
- local step=steps[1]
- local lookupcache=step.coverage
- if not lookupcache then
- report_missing_coverage(dataset,sequence)
- else
- while start do
- local char,id=ischar(start,font)
- if char then
- local a=attr and getattr(start,0)
- if a then
- a=(a==attr) and (not attribute or getprop(start,a_state)==attribute)
- else
- a=not attribute or getprop(start,a_state)==attribute
- end
- if a then
- local lookupmatch=lookupcache[char]
- if lookupmatch then
- local ok
- head,start,ok=handler(head,start,dataset,sequence,lookupmatch,rlmode,step,1)
- if ok then
- success=true
- end
- end
- if start then
- start=getnext(start)
- end
- else
- start=getnext(start)
- end
- elseif char==false then
- start=getnext(start)
- elseif id==disc_code then
- local a=forcedisc or getsubtype(start)==discretionary_code or getattr(start,0)==attr
- if a then
- local ok
- if gpossing then
- start,ok=kernrun(start,k_run_single,font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
- elseif typ=="gsub_ligature" then
- start,ok=testrun(start,t_run_single,c_run_single,font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
- else
- start,ok=comprun(start,c_run_single,font,attr,lookupcache,step,dataset,sequence,rlmode,handler)
- end
- if ok then
- success=true
- end
- else
- start=getnext(start)
- end
- elseif id==math_code then
- start=getnext(end_of_math(start))
- elseif id==dir_code then
- start,topstack,rlmode=txtdirstate(start,dirstack,topstack,rlparmode)
- elseif id==localpar_code then
- start,rlparmode,rlmode=pardirstate(start)
- else
- start=getnext(start)
- end
- end
- end
- else
- while start do
- local char,id=ischar(start,font)
- if char then
- local a=attr and getattr(start,0)
- if a then
- a=(a==attr) and (not attribute or getprop(start,a_state)==attribute)
- else
- a=not attribute or getprop(start,a_state)==attribute
- end
- if a then
- for i=1,nofsteps do
- local step=steps[i]
- local lookupcache=step.coverage
- if lookupcache then
- local lookupmatch=lookupcache[char]
- if lookupmatch then
- local ok
- head,start,ok=handler(head,start,dataset,sequence,lookupmatch,rlmode,step,i)
- if ok then
- success=true
- break
- elseif not start then
- break
- end
- end
- else
- report_missing_coverage(dataset,sequence)
- end
- end
- if start then
- start=getnext(start)
- end
- else
- start=getnext(start)
- end
- elseif char==false then
- start=getnext(start)
- elseif id==disc_code then
- local a=forcedisc or getsubtype(start)==discretionary_code or getattr(start,0)==attr
- if a then
- local ok
- if gpossing then
- start,ok=kernrun(start,k_run_multiple,font,attr,steps,nofsteps,dataset,sequence,rlmode,handler)
- elseif typ=="gsub_ligature" then
- start,ok=testrun(start,t_run_multiple,c_run_multiple,font,attr,steps,nofsteps,dataset,sequence,rlmode,handler)
- else
- start,ok=comprun(start,c_run_multiple,font,attr,steps,nofsteps,dataset,sequence,rlmode,handler)
- end
- if ok then
- success=true
- end
- else
- start=getnext(start)
- end
- elseif id==math_code then
- start=getnext(end_of_math(start))
- elseif id==dir_code then
- start,topstack,rlmode=txtdirstate(start,dirstack,topstack,rlparmode)
- elseif id==localpar_code then
- start,rlparmode,rlmode=pardirstate(start)
- else
- start=getnext(start)
- end
- end
- end
- end
- if success then
- done=true
- end
- if trace_steps then
- registerstep(head)
- end
- end
- nesting=nesting-1
- head=tonode(head)
- return head,done
-end
-local plugins={}
-otf.plugins=plugins
-function otf.registerplugin(name,f)
- if type(name)=="string" and type(f)=="function" then
- plugins[name]={ name,f }
- end
-end
-local function plugininitializer(tfmdata,value)
- if type(value)=="string" then
- tfmdata.shared.plugin=plugins[value]
- end
-end
-local function pluginprocessor(head,font)
- local s=fontdata[font].shared
- local p=s and s.plugin
- if p then
- if trace_plugins then
- report_process("applying plugin %a",p[1])
- end
- return p[2](head,font)
- else
- return head,false
- end
-end
-local function featuresinitializer(tfmdata,value)
-end
-registerotffeature {
- name="features",
- description="features",
- default=true,
- initializers={
- position=1,
- node=featuresinitializer,
- plug=plugininitializer,
- },
- processors={
- node=featuresprocessor,
- plug=pluginprocessor,
- }
-}
-otf.nodemodeinitializer=featuresinitializer
-otf.featuresprocessor=featuresprocessor
-otf.handlers=handlers
-local setspacekerns=nodes.injections.setspacekerns if not setspacekerns then os.exit() end
-if fontfeatures then
- function otf.handlers.trigger_space_kerns(head,start,dataset,sequence,_,_,_,_,font,attr)
- local features=fontfeatures[font]
- local enabled=features and features.spacekern and features.kern
- if enabled then
- setspacekerns(font,sequence)
- end
- return head,start,enabled
- end
-else
- function otf.handlers.trigger_space_kerns(head,start,dataset,sequence,_,_,_,_,font,attr)
- local shared=fontdata[font].shared
- local features=shared and shared.features
- local enabled=features and features.spacekern and features.kern
- if enabled then
- setspacekerns(font,sequence)
- end
- return head,start,enabled
- end
-end
-local function hasspacekerns(data)
- local sequences=data.resources.sequences
- for i=1,#sequences do
- local sequence=sequences[i]
- local steps=sequence.steps
- if steps and sequence.features.kern then
- for i=1,#steps do
- local coverage=steps[i].coverage
- if not coverage then
- elseif coverage[32] then
- return true
- else
- for k,v in next,coverage do
- if v[32] then
- return true
- end
- end
- end
- end
- end
- end
- return false
-end
-otf.readers.registerextender {
- name="spacekerns",
- action=function(data)
- data.properties.hasspacekerns=hasspacekerns(data)
- end
-}
-local function spaceinitializer(tfmdata,value)
- local resources=tfmdata.resources
- local spacekerns=resources and resources.spacekerns
- local properties=tfmdata.properties
- if value and spacekerns==nil then
- if properties and properties.hasspacekerns then
- local sequences=resources.sequences
- local left={}
- local right={}
- local last=0
- local feat=nil
- for i=1,#sequences do
- local sequence=sequences[i]
- local steps=sequence.steps
- if steps then
- local kern=sequence.features.kern
- if kern then
- if feat then
- for script,languages in next,kern do
- local f=feat[script]
- if f then
- for l in next,languages do
- f[l]=true
- end
- else
- feat[script]=languages
- end
- end
- else
- feat=kern
- end
- for i=1,#steps do
- local step=steps[i]
- local coverage=step.coverage
- local rules=step.rules
- local format=step.format
- if rules then
- elseif coverage then
- local single=format==gpos_single
- local kerns=coverage[32]
- if kerns then
- for k,v in next,kerns do
- if type(v)~="table" then
- right[k]=v
- elseif single then
- right[k]=v[3]
- else
- local one=v[1]
- if one then
- right[k]=one[3]
- end
- end
- end
- end
- for k,v in next,coverage do
- local kern=v[32]
- if kern then
- if type(kern)~="table" then
- left[k]=kern
- elseif single then
- left[k]=v[3]
- else
- local one=v[1]
- if one then
- left[k]=one[3]
- end
- end
- end
- end
- end
- end
- last=i
- end
- else
- end
- end
- left=next(left) and left or false
- right=next(right) and right or false
- if left or right then
- spacekerns={
- left=left,
- right=right,
- }
- if last>0 then
- local triggersequence={
- features={ kern=feat or { dflt={ dflt=true,} } },
- flags=noflags,
- name="trigger_space_kerns",
- order={ "kern" },
- type="trigger_space_kerns",
- left=left,
- right=right,
- }
- insert(sequences,last,triggersequence)
- end
- else
- spacekerns=false
- end
- else
- spacekerns=false
- end
- resources.spacekerns=spacekerns
- end
- return spacekerns
-end
-registerotffeature {
- name="spacekern",
- description="space kern injection",
- default=true,
- initializers={
- node=spaceinitializer,
- },
-}
-local function markinitializer(tfmdata,value)
- local properties=tfmdata.properties
- properties.checkmarks=value
-end
-registerotffeature {
- name="checkmarks",
- description="check mark widths",
- default=true,
- initializers={
- node=markinitializer,
- },
-}
-
-end --- [luaotfload, fontloader-2017-02-11.lua scope for “font-ots”] ---
-
-
-do --- [luaotfload, fontloader-2017-02-11.lua scope for “font-osd” 10ecd4b375680b011e7c6a25e5ad74f7] ---
-
-if not modules then modules={} end modules ['font-osd']={
- version=1.001,
- comment="companion to font-ini.mkiv",
- author="Kai Eigner, TAT Zetwerk / Hans Hagen, PRAGMA ADE",
- copyright="TAT Zetwerk / PRAGMA ADE / ConTeXt Development Team",
- license="see context related readme files"
-}
-local insert,imerge,copy=table.insert,table.imerge,table.copy
-local next,type=next,type
-local report_devanagari=logs.reporter("otf","devanagari")
-fonts=fonts or {}
-fonts.analyzers=fonts.analyzers or {}
-fonts.analyzers.methods=fonts.analyzers.methods or { node={ otf={} } }
-local otf=fonts.handlers.otf
-local handlers=otf.handlers
-local methods=fonts.analyzers.methods
-local otffeatures=fonts.constructors.features.otf
-local registerotffeature=otffeatures.register
-local nuts=nodes.nuts
-local tonode=nuts.tonode
-local tonut=nuts.tonut
-local getnext=nuts.getnext
-local getprev=nuts.getprev
-local getboth=nuts.getboth
-local getid=nuts.getid
-local getchar=nuts.getchar
-local getfont=nuts.getfont
-local getsubtype=nuts.getsubtype
-local setlink=nuts.setlink
-local setnext=nuts.setnext
-local setprev=nuts.setprev
-local setchar=nuts.setchar
-local getprop=nuts.getprop
-local setprop=nuts.setprop
-local ischar=nuts.is_char
-local insert_node_after=nuts.insert_after
-local copy_node=nuts.copy
-local remove_node=nuts.remove
-local flush_list=nuts.flush_list
-local flush_node=nuts.flush_node
-local copyinjection=nodes.injections.copy
-local unsetvalue=attributes.unsetvalue
-local fontdata=fonts.hashes.identifiers
-local a_state=attributes.private('state')
-local a_syllabe=attributes.private('syllabe')
-local dotted_circle=0x25CC
-local states=fonts.analyzers.states
-local s_rphf=states.rphf
-local s_half=states.half
-local s_pref=states.pref
-local s_blwf=states.blwf
-local s_pstf=states.pstf
-local replace_all_nbsp=nil
-replace_all_nbsp=function(head)
- replace_all_nbsp=typesetters and typesetters.characters and typesetters.characters.replacenbspaces or function(head)
- return head
- end
- return replace_all_nbsp(head)
-end
-local xprocesscharacters=nil
-if context then
- xprocesscharacters=function(head,font)
- xprocesscharacters=nodes.handlers.characters
- return xprocesscharacters(head,font)
- end
-else
- xprocesscharacters=function(head,font)
- xprocesscharacters=nodes.handlers.nodepass
- return xprocesscharacters(head,font)
- end
-end
-local function processcharacters(head,font)
- return tonut(xprocesscharacters(tonode(head)))
-end
-local consonant={
- [0x0915]=true,[0x0916]=true,[0x0917]=true,[0x0918]=true,
- [0x0919]=true,[0x091A]=true,[0x091B]=true,[0x091C]=true,
- [0x091D]=true,[0x091E]=true,[0x091F]=true,[0x0920]=true,
- [0x0921]=true,[0x0922]=true,[0x0923]=true,[0x0924]=true,
- [0x0925]=true,[0x0926]=true,[0x0927]=true,[0x0928]=true,
- [0x0929]=true,[0x092A]=true,[0x092B]=true,[0x092C]=true,
- [0x092D]=true,[0x092E]=true,[0x092F]=true,[0x0930]=true,
- [0x0931]=true,[0x0932]=true,[0x0933]=true,[0x0934]=true,
- [0x0935]=true,[0x0936]=true,[0x0937]=true,[0x0938]=true,
- [0x0939]=true,[0x0958]=true,[0x0959]=true,[0x095A]=true,
- [0x095B]=true,[0x095C]=true,[0x095D]=true,[0x095E]=true,
- [0x095F]=true,[0x0979]=true,[0x097A]=true,
- [0x0C95]=true,[0x0C96]=true,[0x0C97]=true,[0x0C98]=true,
- [0x0C99]=true,[0x0C9A]=true,[0x0C9B]=true,[0x0C9C]=true,
- [0x0C9D]=true,[0x0C9E]=true,[0x0C9F]=true,[0x0CA0]=true,
- [0x0CA1]=true,[0x0CA2]=true,[0x0CA3]=true,[0x0CA4]=true,
- [0x0CA5]=true,[0x0CA6]=true,[0x0CA7]=true,[0x0CA8]=true,
- [0x0CA9]=true,[0x0CAA]=true,[0x0CAB]=true,[0x0CAC]=true,
- [0x0CAD]=true,[0x0CAE]=true,[0x0CAF]=true,[0x0CB0]=true,
- [0x0CB1]=true,[0x0CB2]=true,[0x0CB3]=true,[0x0CB4]=true,
- [0x0CB5]=true,[0x0CB6]=true,[0x0CB7]=true,[0x0CB8]=true,
- [0x0CB9]=true,
- [0x0CDE]=true,
- [0x0D15]=true,[0x0D16]=true,[0x0D17]=true,[0x0D18]=true,
- [0x0D19]=true,[0x0D1A]=true,[0x0D1B]=true,[0x0D1C]=true,
- [0x0D1D]=true,[0x0D1E]=true,[0x0D1F]=true,[0x0D20]=true,
- [0x0D21]=true,[0x0D22]=true,[0x0D23]=true,[0x0D24]=true,
- [0x0D25]=true,[0x0D26]=true,[0x0D27]=true,[0x0D28]=true,
- [0x0D29]=true,[0x0D2A]=true,[0x0D2B]=true,[0x0D2C]=true,
- [0x0D2D]=true,[0x0D2E]=true,[0x0D2F]=true,[0x0D30]=true,
- [0x0D31]=true,[0x0D32]=true,[0x0D33]=true,[0x0D34]=true,
- [0x0D35]=true,[0x0D36]=true,[0x0D37]=true,[0x0D38]=true,
- [0x0D39]=true,[0x0D3A]=true,
-}
-local independent_vowel={
- [0x0904]=true,[0x0905]=true,[0x0906]=true,[0x0907]=true,
- [0x0908]=true,[0x0909]=true,[0x090A]=true,[0x090B]=true,
- [0x090C]=true,[0x090D]=true,[0x090E]=true,[0x090F]=true,
- [0x0910]=true,[0x0911]=true,[0x0912]=true,[0x0913]=true,
- [0x0914]=true,[0x0960]=true,[0x0961]=true,[0x0972]=true,
- [0x0973]=true,[0x0974]=true,[0x0975]=true,[0x0976]=true,
- [0x0977]=true,
- [0x0C85]=true,[0x0C86]=true,[0x0C87]=true,[0x0C88]=true,
- [0x0C89]=true,[0x0C8A]=true,[0x0C8B]=true,[0x0C8C]=true,
- [0x0C8D]=true,[0x0C8E]=true,[0x0C8F]=true,[0x0C90]=true,
- [0x0C91]=true,[0x0C92]=true,[0x0C93]=true,[0x0C94]=true,
- [0x0D05]=true,[0x0D06]=true,[0x0D07]=true,[0x0D08]=true,
- [0x0D09]=true,[0x0D0A]=true,[0x0D0B]=true,[0x0D0C]=true,
- [0x0D0E]=true,[0x0D0F]=true,[0x0D10]=true,[0x0D12]=true,
- [0x0D13]=true,[0x0D14]=true,
-}
-local dependent_vowel={
- [0x093A]=true,[0x093B]=true,[0x093E]=true,[0x093F]=true,
- [0x0940]=true,[0x0941]=true,[0x0942]=true,[0x0943]=true,
- [0x0944]=true,[0x0945]=true,[0x0946]=true,[0x0947]=true,
- [0x0948]=true,[0x0949]=true,[0x094A]=true,[0x094B]=true,
- [0x094C]=true,[0x094E]=true,[0x094F]=true,[0x0955]=true,
- [0x0956]=true,[0x0957]=true,[0x0962]=true,[0x0963]=true,
- [0x0CBE]=true,[0x0CBF]=true,[0x0CC0]=true,[0x0CC1]=true,
- [0x0CC2]=true,[0x0CC3]=true,[0x0CC4]=true,[0x0CC5]=true,
- [0x0CC6]=true,[0x0CC7]=true,[0x0CC8]=true,[0x0CC9]=true,
- [0x0CCA]=true,[0x0CCB]=true,[0x0CCC]=true,
- [0x0D3E]=true,[0x0D3F]=true,[0x0D40]=true,[0x0D41]=true,
- [0x0D42]=true,[0x0D43]=true,[0x0D44]=true,[0x0D46]=true,
- [0x0D47]=true,[0x0D48]=true,[0x0D4A]=true,[0x0D4B]=true,
- [0x0D4C]=true,[0x0D57]=true,
-}
-local vowel_modifier={
- [0x0900]=true,[0x0901]=true,[0x0902]=true,[0x0903]=true,
- [0xA8E0]=true,[0xA8E1]=true,[0xA8E2]=true,[0xA8E3]=true,
- [0xA8E4]=true,[0xA8E5]=true,[0xA8E6]=true,[0xA8E7]=true,
- [0xA8E8]=true,[0xA8E9]=true,[0xA8EA]=true,[0xA8EB]=true,
- [0xA8EC]=true,[0xA8ED]=true,[0xA8EE]=true,[0xA8EF]=true,
- [0xA8F0]=true,[0xA8F1]=true,
- [0x0D02]=true,[0x0D03]=true,
-}
-local stress_tone_mark={
- [0x0951]=true,[0x0952]=true,[0x0953]=true,[0x0954]=true,
- [0x0CCD]=true,
- [0x0D4D]=true,
-}
-local nukta={
- [0x093C]=true,
- [0x0CBC]=true,
-}
-local halant={
- [0x094D]=true,
- [0x0CCD]=true,
- [0x0D4D]=true,
-}
-local ra={
- [0x0930]=true,
- [0x0CB0]=true,
- [0x0D30]=true,
-}
-local c_anudatta=0x0952
-local c_nbsp=0x00A0
-local c_zwnj=0x200C
-local c_zwj=0x200D
-local zw_char={
- [0x200C]=true,
- [0x200D]=true,
-}
-local pre_mark={
- [0x093F]=true,[0x094E]=true,
- [0x0D46]=true,[0x0D47]=true,[0x0D48]=true,
-}
-local above_mark={
- [0x0900]=true,[0x0901]=true,[0x0902]=true,[0x093A]=true,
- [0x0945]=true,[0x0946]=true,[0x0947]=true,[0x0948]=true,
- [0x0951]=true,[0x0953]=true,[0x0954]=true,[0x0955]=true,
- [0xA8E0]=true,[0xA8E1]=true,[0xA8E2]=true,[0xA8E3]=true,
- [0xA8E4]=true,[0xA8E5]=true,[0xA8E6]=true,[0xA8E7]=true,
- [0xA8E8]=true,[0xA8E9]=true,[0xA8EA]=true,[0xA8EB]=true,
- [0xA8EC]=true,[0xA8ED]=true,[0xA8EE]=true,[0xA8EF]=true,
- [0xA8F0]=true,[0xA8F1]=true,
- [0x0D4E]=true,
-}
-local below_mark={
- [0x093C]=true,[0x0941]=true,[0x0942]=true,[0x0943]=true,
- [0x0944]=true,[0x094D]=true,[0x0952]=true,[0x0956]=true,
- [0x0957]=true,[0x0962]=true,[0x0963]=true,
-}
-local post_mark={
- [0x0903]=true,[0x093B]=true,[0x093E]=true,[0x0940]=true,
- [0x0949]=true,[0x094A]=true,[0x094B]=true,[0x094C]=true,
- [0x094F]=true,
-}
-local twopart_mark={
- [0x0D4A]={ 0x0D46,0x0D3E,},
- [0x0D4B]={ 0x0D47,0x0D3E,},
- [0x0D4C]={ 0x0D46,0x0D57,},
-}
-local mark_four={}
-for k,v in next,pre_mark do mark_four[k]=pre_mark end
-for k,v in next,above_mark do mark_four[k]=above_mark end
-for k,v in next,below_mark do mark_four[k]=below_mark end
-for k,v in next,post_mark do mark_four[k]=post_mark end
-local mark_above_below_post={}
-for k,v in next,above_mark do mark_above_below_post[k]=above_mark end
-for k,v in next,below_mark do mark_above_below_post[k]=below_mark end
-for k,v in next,post_mark do mark_above_below_post[k]=post_mark end
-local reorder_class={
- [0x0930]="before postscript",
- [0x093F]="before half",
- [0x0940]="after subscript",
- [0x0941]="after subscript",
- [0x0942]="after subscript",
- [0x0943]="after subscript",
- [0x0944]="after subscript",
- [0x0945]="after subscript",
- [0x0946]="after subscript",
- [0x0947]="after subscript",
- [0x0948]="after subscript",
- [0x0949]="after subscript",
- [0x094A]="after subscript",
- [0x094B]="after subscript",
- [0x094C]="after subscript",
- [0x0962]="after subscript",
- [0x0963]="after subscript",
- [0x093E]="after subscript",
- [0x0CB0]="after postscript",
- [0x0CBF]="before subscript",
- [0x0CC6]="before subscript",
- [0x0CCC]="before subscript",
- [0x0CBE]="before subscript",
- [0x0CE2]="before subscript",
- [0x0CE3]="before subscript",
- [0x0CC1]="before subscript",
- [0x0CC2]="before subscript",
- [0x0CC3]="after subscript",
- [0x0CC4]="after subscript",
- [0x0CD5]="after subscript",
- [0x0CD6]="after subscript",
-}
-local dflt_true={
- dflt=true
-}
-local dev2_defaults={
- dev2=dflt_true,
-}
-local deva_defaults={
- dev2=dflt_true,
- deva=dflt_true,
-}
-local false_flags={ false,false,false,false }
-local both_joiners_true={
- [0x200C]=true,
- [0x200D]=true,
-}
-local sequence_reorder_matras={
- features={ dv01=dev2_defaults },
- flags=false_flags,
- name="dv01_reorder_matras",
- order={ "dv01" },
- type="devanagari_reorder_matras",
- nofsteps=1,
- steps={
- {
- osdstep=true,
- coverage=pre_mark,
- }
- }
-}
-local sequence_reorder_reph={
- features={ dv02=dev2_defaults },
- flags=false_flags,
- name="dv02_reorder_reph",
- order={ "dv02" },
- type="devanagari_reorder_reph",
- nofsteps=1,
- steps={
- {
- osdstep=true,
- coverage={},
- }
- }
-}
-local sequence_reorder_pre_base_reordering_consonants={
- features={ dv03=dev2_defaults },
- flags=false_flags,
- name="dv03_reorder_pre_base_reordering_consonants",
- order={ "dv03" },
- type="devanagari_reorder_pre_base_reordering_consonants",
- nofsteps=1,
- steps={
- {
- osdstep=true,
- coverage={},
- }
- }
-}
-local sequence_remove_joiners={
- features={ dv04=deva_defaults },
- flags=false_flags,
- name="dv04_remove_joiners",
- order={ "dv04" },
- type="devanagari_remove_joiners",
- nofsteps=1,
- steps={
- { osdstep=true,
- coverage=both_joiners_true,
- },
- }
-}
-local basic_shaping_forms={
- nukt=true,
- akhn=true,
- rphf=true,
- pref=true,
- rkrf=true,
- blwf=true,
- half=true,
- pstf=true,
- vatu=true,
- cjct=true,
-}
-local valid={
- akhn=true,
- rphf=true,
- pref=true,
- half=true,
- blwf=true,
- pstf=true,
- pres=true,
- blws=true,
- psts=true,
-}
-local function initializedevanagi(tfmdata)
- local script,language=otf.scriptandlanguage(tfmdata,attr)
- if script=="deva" or script=="dev2" or script=="mlym" or script=="mlm2" then
- local resources=tfmdata.resources
- local devanagari=resources.devanagari
- if not devanagari then
- report_devanagari("adding devanagari features to font")
- local gsubfeatures=resources.features.gsub
- local sequences=resources.sequences
- local sharedfeatures=tfmdata.shared.features
- local lastmatch=0
- for s=1,#sequences do
- local features=sequences[s].features
- if features then
- for k,v in next,features do
- if basic_shaping_forms[k] then
- lastmatch=s
- end
- end
- end
- end
- local insertindex=lastmatch+1
- gsubfeatures["dv01"]=dev2_defaults
- gsubfeatures["dv02"]=dev2_defaults
- gsubfeatures["dv03"]=dev2_defaults
- gsubfeatures["dv04"]=deva_defaults
- local reorder_pre_base_reordering_consonants=copy(sequence_reorder_pre_base_reordering_consonants)
- local reorder_reph=copy(sequence_reorder_reph)
- local reorder_matras=copy(sequence_reorder_matras)
- local remove_joiners=copy(sequence_remove_joiners)
- insert(sequences,insertindex,reorder_pre_base_reordering_consonants)
- insert(sequences,insertindex,reorder_reph)
- insert(sequences,insertindex,reorder_matras)
- insert(sequences,insertindex,remove_joiners)
- local blwfcache={}
- local seqsubset={}
- local rephstep={
- coverage={}
- }
- local devanagari={
- reph=false,
- vattu=false,
- blwfcache=blwfcache,
- seqsubset=seqsubset,
- reorderreph=rephstep,
- }
- reorder_reph.steps={ rephstep }
- local pre_base_reordering_consonants={}
- reorder_pre_base_reordering_consonants.steps[1].coverage=pre_base_reordering_consonants
- resources.devanagari=devanagari
- for s=1,#sequences do
- local sequence=sequences[s]
- local steps=sequence.steps
- local nofsteps=sequence.nofsteps
- local features=sequence.features
- local has_rphf=features.rphf
- local has_blwf=features.blwf
- if has_rphf and has_rphf.deva then
- devanagari.reph=true
- elseif has_blwf and has_blwf.deva then
- devanagari.vattu=true
- for i=1,nofsteps do
- local step=steps[i]
- local coverage=step.coverage
- if coverage then
- for k,v in next,coverage do
- if not blwfcache[k] then
- blwfcache[k]=v
- end
- end
- end
- end
- end
- for kind,spec in next,features do
- if spec.dev2 and valid[kind] then
- for i=1,nofsteps do
- local step=steps[i]
- local coverage=step.coverage
- if coverage then
- local reph=false
- if kind=="rphf" then
- if true then
- for k,v in next,ra do
- local r=coverage[k]
- if r then
- local h=false
- for k,v in next,halant do
- local h=r[k]
- if h then
- reph=h.ligature or false
- break
- end
- end
- if reph then
- break
- end
- end
- end
- else
- end
- end
- seqsubset[#seqsubset+1]={ kind,coverage,reph }
- end
- end
- end
- if kind=="pref" then
- local steps=sequence.steps
- local nofsteps=sequence.nofsteps
- for i=1,nofsteps do
- local step=steps[i]
- local coverage=step.coverage
- if coverage then
- for k,v in next,halant do
- local h=coverage[k]
- if h then
- local found=false
- for k,v in next,h do
- found=v and v.ligature
- if found then
- pre_base_reordering_consonants[k]=found
- break
- end
- end
- if found then
- break
- end
- end
- end
- end
- end
- end
- end
- end
- if script=="deva" then
- sharedfeatures["dv04"]=true
- elseif script=="dev2" then
- sharedfeatures["dv01"]=true
- sharedfeatures["dv02"]=true
- sharedfeatures["dv03"]=true
- sharedfeatures["dv04"]=true
- elseif script=="mlym" then
- sharedfeatures["pstf"]=true
- elseif script=="mlm2" then
- sharedfeatures["pstf"]=true
- sharedfeatures["pref"]=true
- sharedfeatures["dv03"]=true
- gsubfeatures ["dv03"]=dev2_defaults
- insert(sequences,insertindex,sequence_reorder_pre_base_reordering_consonants)
- end
- end
- end
-end
-registerotffeature {
- name="devanagari",
- description="inject additional features",
- default=true,
- initializers={
- node=initializedevanagi,
- },
-}
-local function deva_initialize(font,attr)
- local tfmdata=fontdata[font]
- local datasets=otf.dataset(tfmdata,font,attr)
- local devanagaridata=datasets.devanagari
- if not devanagaridata then
- devanagaridata={
- reph=false,
- vattu=false,
- blwfcache={},
- }
- datasets.devanagari=devanagaridata
- local resources=tfmdata.resources
- local devanagari=resources.devanagari
- for s=1,#datasets do
- local dataset=datasets[s]
- if dataset and dataset[1] then
- local kind=dataset[4]
- if kind=="rphf" then
- devanagaridata.reph=true
- elseif kind=="blwf" then
- devanagaridata.vattu=true
- devanagaridata.blwfcache=devanagari.blwfcache
- end
- end
- end
- end
- return devanagaridata.reph,devanagaridata.vattu,devanagaridata.blwfcache
-end
-local function deva_reorder(head,start,stop,font,attr,nbspaces)
- local reph,vattu,blwfcache=deva_initialize(font,attr)
- local current=start
- local n=getnext(start)
- local base=nil
- local firstcons=nil
- local lastcons=nil
- local basefound=false
- if reph and ra[getchar(start)] and halant[getchar(n)] then
- if n==stop then
- return head,stop,nbspaces
- end
- if getchar(getnext(n))==c_zwj then
- current=start
- else
- current=getnext(n)
- setprop(start,a_state,s_rphf)
- end
- end
- if getchar(current)==c_nbsp then
- if current==stop then
- stop=getprev(stop)
- head=remove_node(head,current)
- flush_node(current)
- return head,stop,nbspaces
- else
- nbspaces=nbspaces+1
- base=current
- firstcons=current
- lastcons=current
- current=getnext(current)
- if current~=stop then
- if nukta[getchar(current)] then
- current=getnext(current)
- end
- if getchar(current)==c_zwj then
- if current~=stop then
- local next=getnext(current)
- if next~=stop and halant[getchar(next)] then
- current=next
- next=getnext(current)
- local tmp=next and getnext(next) or nil
- local changestop=next==stop
- local tempcurrent=copy_node(next)
- copyinjection(tempcurrent,next)
- local nextcurrent=copy_node(current)
- copyinjection(nextcurrent,current)
- setlink(tempcurrent,nextcurrent)
- setprop(tempcurrent,a_state,s_blwf)
- tempcurrent=processcharacters(tempcurrent,font)
- setprop(tempcurrent,a_state,unsetvalue)
- if getchar(next)==getchar(tempcurrent) then
- flush_list(tempcurrent)
- local n=copy_node(current)
- copyinjection(n,current)
- setchar(current,dotted_circle)
- head=insert_node_after(head,current,n)
- else
- setchar(current,getchar(tempcurrent))
- local freenode=getnext(current)
- setlink(current,tmp)
- flush_node(freenode)
- flush_list(tempcurrent)
- if changestop then
- stop=current
- end
- end
- end
- end
- end
- end
- end
- end
- while not basefound do
- local char=getchar(current)
- if consonant[char] then
- setprop(current,a_state,s_half)
- if not firstcons then
- firstcons=current
- end
- lastcons=current
- if not base then
- base=current
- elseif blwfcache[char] then
- setprop(current,a_state,s_blwf)
- else
- base=current
- end
- end
- basefound=current==stop
- current=getnext(current)
- end
- if base~=lastcons then
- local np=base
- local n=getnext(base)
- local ch=getchar(n)
- if nukta[ch] then
- np=n
- n=getnext(n)
- ch=getchar(n)
- end
- if halant[ch] then
- if lastcons~=stop then
- local ln=getnext(lastcons)
- if nukta[getchar(ln)] then
- lastcons=ln
- end
- end
- local nn=getnext(n)
- local ln=getnext(lastcons)
- setlink(np,nn)
- setnext(lastcons,n)
- if ln then
- setprev(ln,n)
- end
- setnext(n,ln)
- setprev(n,lastcons)
- if lastcons==stop then
- stop=n
- end
- end
- end
- n=getnext(start)
- if n~=stop and ra[getchar(start)] and halant[getchar(n)] and not zw_char[getchar(getnext(n))] then
- local matra=base
- if base~=stop then
- local next=getnext(base)
- if dependent_vowel[getchar(next)] then
- matra=next
- end
- end
- local sp=getprev(start)
- local nn=getnext(n)
- local mn=getnext(matra)
- setlink(sp,nn)
- setlink(matra,start)
- setlink(n,mn)
- if head==start then
- head=nn
- end
- start=nn
- if matra==stop then
- stop=n
- end
- end
- local current=start
- while current~=stop do
- local next=getnext(current)
- if next~=stop and halant[getchar(next)] and getchar(getnext(next))==c_zwnj then
- setprop(current,a_state,unsetvalue)
- end
- current=next
- end
- if base~=stop and getprop(base,a_state) then
- local next=getnext(base)
- if halant[getchar(next)] and not (next~=stop and getchar(getnext(next))==c_zwj) then
- setprop(base,a_state,unsetvalue)
- end
- end
- local current,allreordered,moved=start,false,{ [base]=true }
- local a,b,p,bn=base,base,base,getnext(base)
- if base~=stop and nukta[getchar(bn)] then
- a,b,p=bn,bn,bn
- end
- while not allreordered do
- local c=current
- local n=getnext(current)
- local l=nil
- if c~=stop then
- local ch=getchar(n)
- if nukta[ch] then
- c=n
- n=getnext(n)
- ch=getchar(n)
- end
- if c~=stop then
- if halant[ch] then
- c=n
- n=getnext(n)
- ch=getchar(n)
- end
- while c~=stop and dependent_vowel[ch] do
- c=n
- n=getnext(n)
- ch=getchar(n)
- end
- if c~=stop then
- if vowel_modifier[ch] then
- c=n
- n=getnext(n)
- ch=getchar(n)
- end
- if c~=stop and stress_tone_mark[ch] then
- c=n
- n=getnext(n)
- end
- end
- end
- end
- local bp=getprev(firstcons)
- local cn=getnext(current)
- local last=getnext(c)
- while cn~=last do
- if pre_mark[getchar(cn)] then
- if bp then
- setnext(bp,cn)
- end
- local prev,next=getboth(cn)
- if next then
- setprev(next,prev)
- end
- setnext(prev,next)
- if cn==stop then
- stop=prev
- end
- setprev(cn,bp)
- setlink(cn,firstcons)
- if firstcons==start then
- if head==start then
- head=cn
- end
- start=cn
- end
- break
- end
- cn=getnext(cn)
- end
- allreordered=c==stop
- current=getnext(c)
- end
- if reph or vattu then
- local current,cns=start,nil
- while current~=stop do
- local c=current
- local n=getnext(current)
- if ra[getchar(current)] and halant[getchar(n)] then
- c=n
- n=getnext(n)
- local b,bn=base,base
- while bn~=stop do
- local next=getnext(bn)
- if dependent_vowel[getchar(next)] then
- b=next
- end
- bn=next
- end
- if getprop(current,a_state)==s_rphf then
- if b~=current then
- if current==start then
- if head==start then
- head=n
- end
- start=n
- end
- if b==stop then
- stop=c
- end
- local prev=getprev(current)
- setlink(prev,n)
- local next=getnext(b)
- setlink(c,next)
- setlink(b,current)
- end
- elseif cns and getnext(cns)~=current then
- local cp=getprev(current)
- local cnsn=getnext(cns)
- setlink(cp,n)
- setlink(cns,current)
- setlink(c,cnsn)
- if c==stop then
- stop=cp
- break
- end
- current=getprev(n)
- end
- else
- local char=getchar(current)
- if consonant[char] then
- cns=current
- local next=getnext(cns)
- if halant[getchar(next)] then
- cns=next
- end
- elseif char==c_nbsp then
- nbspaces=nbspaces+1
- cns=current
- local next=getnext(cns)
- if halant[getchar(next)] then
- cns=next
- end
- end
- end
- current=getnext(current)
- end
- end
- if getchar(base)==c_nbsp then
- nbspaces=nbspaces-1
- head=remove_node(head,base)
- flush_node(base)
- end
- return head,stop,nbspaces
-end
-function handlers.devanagari_reorder_matras(head,start)
- local current=start
- local startfont=getfont(start)
- local startattr=getprop(start,a_syllabe)
- while current do
- local char=ischar(current,startfont)
- local next=getnext(current)
- if char and getprop(current,a_syllabe)==startattr then
- if halant[char] and not getprop(current,a_state) then
- if next then
- local char=ischar(next,startfont)
- if char and zw_char[char] and getprop(next,a_syllabe)==startattr then
- current=next
- next=getnext(current)
- end
- end
- local startnext=getnext(start)
- head=remove_node(head,start)
- setlink(start,next)
- setlink(current,start)
- start=startnext
- break
- end
- else
- break
- end
- current=next
- end
- return head,start,true
-end
-function handlers.devanagari_reorder_reph(head,start)
- local current=getnext(start)
- local startnext=nil
- local startprev=nil
- local startfont=getfont(start)
- local startattr=getprop(start,a_syllabe)
- while current do
- local char=ischar(current,startfont)
- if char and getprop(current,a_syllabe)==startattr then
- if halant[char] and not getprop(current,a_state) then
- local next=getnext(current)
- if next then
- local nextchar=ischar(next,startfont)
- if nextchar and zw_char[nextchar] and getprop(next,a_syllabe)==startattr then
- current=next
- next=getnext(current)
- end
- end
- startnext=getnext(start)
- head=remove_node(head,start)
- setlink(start,next)
- setlink(current,start)
- start=startnext
- startattr=getprop(start,a_syllabe)
- break
- end
- current=getnext(current)
- else
- break
- end
- end
- if not startnext then
- current=getnext(start)
- while current do
- local char=ischar(current,startfont)
- if char and getprop(current,a_syllabe)==startattr then
- if getprop(current,a_state)==s_pstf then
- startnext=getnext(start)
- head=remove_node(head,start)
- local prev=getprev(current)
- setlink(prev,start)
- setlink(start,current)
- start=startnext
- startattr=getprop(start,a_syllabe)
- break
- end
- current=getnext(current)
- else
- break
- end
- end
- end
- if not startnext then
- current=getnext(start)
- local c=nil
- while current do
- local char=ischar(current,startfont)
- if char and getprop(current,a_syllabe)==startattr then
- if not c and mark_above_below_post[char] and reorder_class[char]~="after subscript" then
- c=current
- end
- current=getnext(current)
- else
- break
- end
- end
- if c then
- startnext=getnext(start)
- head=remove_node(head,start)
- local prev=getprev(c)
- setlink(prev,start)
- setlink(start,c)
- start=startnext
- startattr=getprop(start,a_syllabe)
- end
- end
- if not startnext then
- current=start
- local next=getnext(current)
- while next do
- local nextchar=ischar(next,startfont)
- if nextchar and getprop(next,a_syllabe)==startattr then
- current=next
- next=getnext(current)
- else
- break
- end
- end
- if start~=current then
- startnext=getnext(start)
- head=remove_node(head,start)
- local next=getnext(current)
- setlink(start,next)
- setlink(current,start)
- start=startnext
- end
- end
- return head,start,true
-end
-function handlers.devanagari_reorder_pre_base_reordering_consonants(head,start)
- local current=start
- local startnext=nil
- local startprev=nil
- local startfont=getfont(start)
- local startattr=getprop(start,a_syllabe)
- while current do
- local char=ischar(current,startfont)
- if char and getprop(current,a_syllabe)==startattr then
- local next=getnext(current)
- if halant[char] and not getprop(current,a_state) then
- if next then
- local nextchar=ischar(next,startfont)
- if nextchar and getprop(next,a_syllabe)==startattr then
- if nextchar==c_zwnj or nextchar==c_zwj then
- current=next
- next=getnext(current)
- end
- end
- end
- startnext=getnext(start)
- removenode(start,start)
- setlink(start,next)
- setlink(current,start)
- start=startnext
- break
- end
- current=next
- else
- break
- end
- end
- if not startnext then
- current=getnext(start)
- startattr=getprop(start,a_syllabe)
- while current do
- local char=ischar(current,startfont)
- if char and getprop(current,a_syllabe)==startattr then
- if not consonant[char] and getprop(current,a_state) then
- startnext=getnext(start)
- removenode(start,start)
- local prev=getprev(current)
- setlink(prev,start)
- setlink(start,current)
- start=startnext
- break
- end
- current=getnext(current)
- else
- break
- end
- end
- end
- return head,start,true
-end
-function handlers.devanagari_remove_joiners(head,start,kind,lookupname,replacement)
- local stop=getnext(start)
- local font=getfont(start)
- local last=start
- while stop do
- local char=ischar(stop,font)
- if char and (char==c_zwnj or char==c_zwj) then
- last=stop
- stop=getnext(stop)
- else
- break
- end
- end
- local prev=getprev(start)
- if stop then
- setnext(last)
- setlink(prev,stop)
- elseif prev then
- setnext(prev)
- end
- if head==start then
- head=stop
- end
- flush_list(start)
- return head,stop,true
-end
-local function dev2_initialize(font,attr)
- local devanagari=fontdata[font].resources.devanagari
- if devanagari then
- return devanagari.seqsubset or {},devanagari.reorderreph or {}
- else
- return {},{}
- end
-end
-local function dev2_reorder(head,start,stop,font,attr,nbspaces)
- local seqsubset,reorderreph=dev2_initialize(font,attr)
- local reph=false
- local halfpos=nil
- local basepos=nil
- local subpos=nil
- local postpos=nil
- local locl={}
- for i=1,#seqsubset do
- local subset=seqsubset[i]
- local kind=subset[1]
- local lookupcache=subset[2]
- if kind=="rphf" then
- reph=subset[3]
- local current=start
- local last=getnext(stop)
- while current~=last do
- if current~=stop then
- local c=locl[current] or getchar(current)
- local found=lookupcache[c]
- if found then
- local next=getnext(current)
- local n=locl[next] or getchar(next)
- if found[n] then
- local afternext=next~=stop and getnext(next)
- if afternext and zw_char[getchar(afternext)] then
- current=next
- current=getnext(current)
- elseif current==start then
- setprop(current,a_state,s_rphf)
- current=next
- else
- current=next
- end
- end
- end
- end
- current=getnext(current)
- end
- elseif kind=="pref" then
- local current=start
- local last=getnext(stop)
- while current~=last do
- if current~=stop then
- local c=locl[current] or getchar(current)
- local found=lookupcache[c]
- if found then
- local next=getnext(current)
- local n=locl[next] or getchar(next)
- if found[n] then
- setprop(current,a_state,s_pref)
- setprop(next,a_state,s_pref)
- current=next
- end
- end
- end
- current=getnext(current)
- end
- elseif kind=="half" then
- local current=start
- local last=getnext(stop)
- while current~=last do
- if current~=stop then
- local c=locl[current] or getchar(current)
- local found=lookupcache[c]
- if found then
- local next=getnext(current)
- local n=locl[next] or getchar(next)
- if found[n] then
- if next~=stop and getchar(getnext(next))==c_zwnj then
- current=next
- else
- setprop(current,a_state,s_half)
- if not halfpos then
- halfpos=current
- end
- end
- current=getnext(current)
- end
- end
- end
- current=getnext(current)
- end
- elseif kind=="blwf" then
- local current=start
- local last=getnext(stop)
- while current~=last do
- if current~=stop then
- local c=locl[current] or getchar(current)
- local found=lookupcache[c]
- if found then
- local next=getnext(current)
- local n=locl[next] or getchar(next)
- if found[n] then
- setprop(current,a_state,s_blwf)
- setprop(next,a_state,s_blwf)
- current=next
- subpos=current
- end
- end
- end
- current=getnext(current)
- end
- elseif kind=="pstf" then
- local current=start
- local last=getnext(stop)
- while current~=last do
- if current~=stop then
- local c=locl[current] or getchar(current)
- local found=lookupcache[c]
- if found then
- local next=getnext(current)
- local n=locl[next] or getchar(next)
- if found[n] then
- setprop(current,a_state,s_pstf)
- setprop(next,a_state,s_pstf)
- current=next
- postpos=current
- end
- end
- end
- current=getnext(current)
- end
- end
- end
- reorderreph.coverage={ [reph]=true }
- local current,base,firstcons=start,nil,nil
- if getprop(start,a_state)==s_rphf then
- current=getnext(getnext(start))
- end
- if current~=getnext(stop) and getchar(current)==c_nbsp then
- if current==stop then
- stop=getprev(stop)
- head=remove_node(head,current)
- flush_node(current)
- return head,stop,nbspaces
- else
- nbspaces=nbspaces+1
- base=current
- current=getnext(current)
- if current~=stop then
- local char=getchar(current)
- if nukta[char] then
- current=getnext(current)
- char=getchar(current)
- end
- if char==c_zwj then
- local next=getnext(current)
- if current~=stop and next~=stop and halant[getchar(next)] then
- current=next
- next=getnext(current)
- local tmp=getnext(next)
- local changestop=next==stop
- setnext(next,nil)
- setprop(current,a_state,s_pref)
- current=processcharacters(current,font)
- setprop(current,a_state,s_blwf)
- current=processcharacters(current,font)
- setprop(current,a_state,s_pstf)
- current=processcharacters(current,font)
- setprop(current,a_state,unsetvalue)
- if halant[getchar(current)] then
- setnext(getnext(current),tmp)
- local nc=copy_node(current)
- copyinjection(nc,current)
- setchar(current,dotted_circle)
- head=insert_node_after(head,current,nc)
- else
- setnext(current,tmp)
- if changestop then
- stop=current
- end
- end
- end
- end
- end
- end
- else
- local last=getnext(stop)
- while current~=last do
- local next=getnext(current)
- if consonant[getchar(current)] then
- if not (current~=stop and next~=stop and halant[getchar(next)] and getchar(getnext(next))==c_zwj) then
- if not firstcons then
- firstcons=current
- end
- local a=getprop(current,a_state)
- if not (a==s_pref or a==s_blwf or a==s_pstf) then
- base=current
- end
- end
- end
- current=next
- end
- if not base then
- base=firstcons
- end
- end
- if not base then
- if getprop(start,a_state)==s_rphf then
- setprop(start,a_state,unsetvalue)
- end
- return head,stop,nbspaces
- else
- if getprop(base,a_state) then
- setprop(base,a_state,unsetvalue)
- end
- basepos=base
- end
- if not halfpos then
- halfpos=base
- end
- if not subpos then
- subpos=base
- end
- if not postpos then
- postpos=subpos or base
- end
- local moved={}
- local current=start
- local last=getnext(stop)
- while current~=last do
- local char,target,cn=locl[current] or getchar(current),nil,getnext(current)
- local tpm=twopart_mark[char]
- if tpm then
- local extra=copy_node(current)
- copyinjection(extra,current)
- char=tpm[1]
- setchar(current,char)
- setchar(extra,tpm[2])
- head=insert_node_after(head,current,extra)
- end
- if not moved[current] and dependent_vowel[char] then
- if pre_mark[char] then
- moved[current]=true
- local prev,next=getboth(current)
- setlink(prev,next)
- if current==stop then
- stop=getprev(current)
- end
- if halfpos==start then
- if head==start then
- head=current
- end
- start=current
- end
- local prev=getprev(halfpos)
- setlink(prev,current)
- setlink(current,halfpos)
- halfpos=current
- elseif above_mark[char] then
- target=basepos
- if subpos==basepos then
- subpos=current
- end
- if postpos==basepos then
- postpos=current
- end
- basepos=current
- elseif below_mark[char] then
- target=subpos
- if postpos==subpos then
- postpos=current
- end
- subpos=current
- elseif post_mark[char] then
- target=postpos
- postpos=current
- end
- if mark_above_below_post[char] then
- local prev=getprev(current)
- if prev~=target then
- local next=getnext(current)
- setlink(prev,next)
- if current==stop then
- stop=prev
- end
- local next=getnext(target)
- setlink(current,next)
- setlink(target,current)
- end
- end
- end
- current=cn
- end
- local current,c=start,nil
- while current~=stop do
- local char=getchar(current)
- if halant[char] or stress_tone_mark[char] then
- if not c then
- c=current
- end
- else
- c=nil
- end
- local next=getnext(current)
- if c and nukta[getchar(next)] then
- if head==c then
- head=next
- end
- if stop==next then
- stop=current
- end
- local prev=getprev(c)
- setlink(prev,next)
- local nextnext=getnext(next)
- setnext(current,nextnext)
- local nextnextnext=getnext(nextnext)
- if nextnextnext then
- setprev(nextnextnext,current)
- end
- setlink(nextnext,c)
- end
- if stop==current then break end
- current=getnext(current)
- end
- if getchar(base)==c_nbsp then
- if base==stop then
- stop=getprev(stop)
- end
- nbspaces=nbspaces-1
- head=remove_node(head,base)
- flush_node(base)
- end
- return head,stop,nbspaces
-end
-local separator={}
-imerge(separator,consonant)
-imerge(separator,independent_vowel)
-imerge(separator,dependent_vowel)
-imerge(separator,vowel_modifier)
-imerge(separator,stress_tone_mark)
-for k,v in next,nukta do separator[k]=true end
-for k,v in next,halant do separator[k]=true end
-local function analyze_next_chars_one(c,font,variant)
- local n=getnext(c)
- if not n then
- return c
- end
- if variant==1 then
- local v=ischar(n,font)
- if v and nukta[v] then
- n=getnext(n)
- if n then
- v=ischar(n,font)
- end
- end
- if n and v then
- local nn=getnext(n)
- if nn then
- local vv=ischar(nn,font)
- if vv then
- local nnn=getnext(nn)
- if nnn then
- local vvv=ischar(nnn,font)
- if vvv then
- if vv==c_zwj and consonant[vvv] then
- c=nnn
- elseif (vv==c_zwnj or vv==c_zwj) and halant[vvv] then
- local nnnn=getnext(nnn)
- if nnnn then
- local vvvv=ischar(nnnn,font)
- if vvvv and consonant[vvvv] then
- c=nnnn
- end
- end
- end
- end
- end
- end
- end
- end
- elseif variant==2 then
- local v=ischar(n,font)
- if v and nukta[v] then
- c=n
- end
- n=getnext(c)
- if n then
- v=ischar(n,font)
- if v then
- local nn=getnext(n)
- if nn then
- local vv=ischar(nn,font)
- if vv and zw_char[v] then
- n=nn
- v=vv
- nn=getnext(nn)
- vv=nn and ischar(nn,font)
- end
- if vv and halant[v] and consonant[vv] then
- c=nn
- end
- end
- end
- end
- end
- local n=getnext(c)
- if not n then
- return c
- end
- local v=ischar(n,font)
- if not v then
- return c
- end
- if dependent_vowel[v] then
- c=getnext(c)
- n=getnext(c)
- if not n then
- return c
- end
- v=ischar(n,font)
- if not v then
- return c
- end
- end
- if nukta[v] then
- c=getnext(c)
- n=getnext(c)
- if not n then
- return c
- end
- v=ischar(n,font)
- if not v then
- return c
- end
- end
- if halant[v] then
- c=getnext(c)
- n=getnext(c)
- if not n then
- return c
- end
- v=ischar(n,font)
- if not v then
- return c
- end
- end
- if vowel_modifier[v] then
- c=getnext(c)
- n=getnext(c)
- if not n then
- return c
- end
- v=ischar(n,font)
- if not v then
- return c
- end
- end
- if stress_tone_mark[v] then
- c=getnext(c)
- n=getnext(c)
- if not n then
- return c
- end
- v=ischar(n,font)
- if not v then
- return c
- end
- end
- if stress_tone_mark[v] then
- return n
- else
- return c
- end
-end
-local function analyze_next_chars_two(c,font)
- local n=getnext(c)
- if not n then
- return c
- end
- local v=ischar(n,font)
- if v and nukta[v] then
- c=n
- end
- n=c
- while true do
- local nn=getnext(n)
- if nn then
- local vv=ischar(nn,font)
- if vv then
- if halant[vv] then
- n=nn
- local nnn=getnext(nn)
- if nnn then
- local vvv=ischar(nnn,font)
- if vvv and zw_char[vvv] then
- n=nnn
- end
- end
- elseif vv==c_zwnj or vv==c_zwj then
- local nnn=getnext(nn)
- if nnn then
- local vvv=ischar(nnn,font)
- if vvv and halant[vvv] then
- n=nnn
- end
- end
- else
- break
- end
- local nn=getnext(n)
- if nn then
- local vv=ischar(nn,font)
- if vv and consonant[vv] then
- n=nn
- local nnn=getnext(nn)
- if nnn then
- local vvv=ischar(nnn,font)
- if vvv and nukta[vvv] then
- n=nnn
- end
- end
- c=n
- else
- break
- end
- else
- break
- end
- else
- break
- end
- else
- break
- end
- end
- if not c then
- return
- end
- local n=getnext(c)
- if not n then
- return c
- end
- local v=ischar(n,font)
- if not v then
- return c
- end
- if v==c_anudatta then
- c=n
- n=getnext(c)
- if not n then
- return c
- end
- v=ischar(n,font)
- if not v then
- return c
- end
- end
- if halant[v] then
- c=n
- n=getnext(c)
- if not n then
- return c
- end
- v=ischar(n,font)
- if not v then
- return c
- end
- if v==c_zwnj or v==c_zwj then
- c=n
- n=getnext(c)
- if not n then
- return c
- end
- v=ischar(n,font)
- if not v then
- return c
- end
- end
- else
- if dependent_vowel[v] then
- c=n
- n=getnext(c)
- if not n then
- return c
- end
- v=ischar(n,font)
- if not v then
- return c
- end
- end
- if nukta[v] then
- c=n
- n=getnext(c)
- if not n then
- return c
- end
- v=ischar(n,font)
- if not v then
- return c
- end
- end
- if halant[v] then
- c=n
- n=getnext(c)
- if not n then
- return c
- end
- v=ischar(n,font)
- if not v then
- return c
- end
- end
- end
- if vowel_modifier[v] then
- c=n
- n=getnext(c)
- if not n then
- return c
- end
- v=ischar(n,font)
- if not v then
- return c
- end
- end
- if stress_tone_mark[v] then
- c=n
- n=getnext(c)
- if not n then
- return c
- end
- v=ischar(n,font)
- if not v then
- return c
- end
- end
- if stress_tone_mark[v] then
- return n
- else
- return c
- end
-end
-local function inject_syntax_error(head,current,mark)
- local signal=copy_node(current)
- copyinjection(signal,current)
- if mark==pre_mark then
- setchar(signal,dotted_circle)
- else
- setchar(current,dotted_circle)
- end
- return insert_node_after(head,current,signal)
-end
-function methods.deva(head,font,attr)
- head=tonut(head)
- local current=head
- local start=true
- local done=false
- local nbspaces=0
- while current do
- local char=ischar(current,font)
- if char then
- done=true
- local syllablestart=current
- local syllableend=nil
- local c=current
- local n=getnext(c)
- local first=char
- if n and ra[first] then
- local second=ischar(n,font)
- if second and halant[second] then
- local n=getnext(n)
- if n then
- local third=ischar(n,font)
- if third then
- c=n
- first=third
- end
- end
- end
- end
- local standalone=first==c_nbsp
- if standalone then
- local prev=getprev(current)
- if prev then
- local prevchar=ischar(prev,font)
- if not prevchar then
- elseif not separator[prevchar] then
- else
- standalone=false
- end
- else
- end
- end
- if standalone then
- local syllableend=analyze_next_chars_one(c,font,2)
- current=getnext(syllableend)
- if syllablestart~=syllableend then
- head,current,nbspaces=deva_reorder(head,syllablestart,syllableend,font,attr,nbspaces)
- current=getnext(current)
- end
- else
- if consonant[char] then
- local prevc=true
- while prevc do
- prevc=false
- local n=getnext(current)
- if not n then
- break
- end
- local v=ischar(n,font)
- if not v then
- break
- end
- if nukta[v] then
- n=getnext(n)
- if not n then
- break
- end
- v=ischar(n,font)
- if not v then
- break
- end
- end
- if halant[v] then
- n=getnext(n)
- if not n then
- break
- end
- v=ischar(n,font)
- if not v then
- break
- end
- if v==c_zwnj or v==c_zwj then
- n=getnext(n)
- if not n then
- break
- end
- v=ischar(n,font)
- if not v then
- break
- end
- end
- if consonant[v] then
- prevc=true
- current=n
- end
- end
- end
- local n=getnext(current)
- if n then
- local v=ischar(n,font)
- if v and nukta[v] then
- current=n
- n=getnext(current)
- end
- end
- syllableend=current
- current=n
- if current then
- local v=ischar(current,font)
- if not v then
- elseif halant[v] then
- local n=getnext(current)
- if n then
- local v=ischar(n,font)
- if v and zw_char[v] then
- syllableend=n
- current=getnext(n)
- else
- syllableend=current
- current=n
- end
- else
- syllableend=current
- current=n
- end
- else
- if dependent_vowel[v] then
- syllableend=current
- current=getnext(current)
- v=ischar(current,font)
- end
- if v and vowel_modifier[v] then
- syllableend=current
- current=getnext(current)
- v=ischar(current,font)
- end
- if v and stress_tone_mark[v] then
- syllableend=current
- current=getnext(current)
- end
- end
- end
- if syllablestart~=syllableend then
- head,current,nbspaces=deva_reorder(head,syllablestart,syllableend,font,attr,nbspaces)
- current=getnext(current)
- end
- elseif independent_vowel[char] then
- syllableend=current
- current=getnext(current)
- if current then
- local v=ischar(current,font)
- if v then
- if vowel_modifier[v] then
- syllableend=current
- current=getnext(current)
- v=ischar(current,font)
- end
- if v and stress_tone_mark[v] then
- syllableend=current
- current=getnext(current)
- end
- end
- end
- else
- local mark=mark_four[char]
- if mark then
- head,current=inject_syntax_error(head,current,mark)
- end
- current=getnext(current)
- end
- end
- else
- current=getnext(current)
- end
- start=false
- end
- if nbspaces>0 then
- head=replace_all_nbsp(head)
- end
- head=tonode(head)
- return head,done
-end
-function methods.dev2(head,font,attr)
- head=tonut(head)
- local current=head
- local start=true
- local done=false
- local syllabe=0
- local nbspaces=0
- while current do
- local syllablestart=nil
- local syllableend=nil
- local char=ischar(current,font)
- if char then
- done=true
- syllablestart=current
- local c=current
- local n=getnext(current)
- if n and ra[char] then
- local nextchar=ischar(n,font)
- if nextchar and halant[nextchar] then
- local n=getnext(n)
- if n then
- local nextnextchar=ischar(n,font)
- if nextnextchar then
- c=n
- char=nextnextchar
- end
- end
- end
- end
- if independent_vowel[char] then
- current=analyze_next_chars_one(c,font,1)
- syllableend=current
- else
- local standalone=char==c_nbsp
- if standalone then
- nbspaces=nbspaces+1
- local p=getprev(current)
- if not p then
- elseif ischar(p,font) then
- elseif not separator[getchar(p)] then
- else
- standalone=false
- end
- end
- if standalone then
- current=analyze_next_chars_one(c,font,2)
- syllableend=current
- elseif consonant[getchar(current)] then
- current=analyze_next_chars_two(current,font)
- syllableend=current
- end
- end
- end
- if syllableend then
- syllabe=syllabe+1
- local c=syllablestart
- local n=getnext(syllableend)
- while c~=n do
- setprop(c,a_syllabe,syllabe)
- c=getnext(c)
- end
- end
- if syllableend and syllablestart~=syllableend then
- head,current,nbspaces=dev2_reorder(head,syllablestart,syllableend,font,attr,nbspaces)
- end
- if not syllableend then
- local char=ischar(current,font)
- if char and not getprop(current,a_state) then
- local mark=mark_four[char]
- if mark then
- head,current=inject_syntax_error(head,current,mark)
- end
- end
- end
- start=false
- current=getnext(current)
- end
- if nbspaces>0 then
- head=replace_all_nbsp(head)
- end
- head=tonode(head)
- return head,done
-end
-methods.mlym=methods.deva
-methods.mlm2=methods.dev2
-
-end --- [luaotfload, fontloader-2017-02-11.lua scope for “font-osd”] ---
-
-
-do --- [luaotfload, fontloader-2017-02-11.lua scope for “font-ocl” fbc00782e4efb24a7569f99cd1574ffb] ---
-
-if not modules then modules={} end modules ['font-ocl']={
- version=1.001,
- comment="companion to font-otf.lua (context)",
- author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright="PRAGMA ADE / ConTeXt Development Team",
- license="see context related readme files"
-}
-local tostring,next,format=tostring,next,string.format
-local round,max=math.round,math.round
-local formatters=string.formatters
-local tounicode=fonts.mappings.tounicode
-local otf=fonts.handlers.otf
-local f_color=formatters["pdf:direct:%f %f %f rg"]
-local f_gray=formatters["pdf:direct:%f g"]
-local s_black="pdf:direct:0 g"
-if context then
- local startactualtext=nil
- local stopactualtext=nil
- function otf.getactualtext(s)
- if not startactualtext then
- startactualtext=backends.codeinjections.startunicodetoactualtextdirect
- stopactualtext=backends.codeinjections.stopunicodetoactualtextdirect
- end
- return startactualtext(s),stopactualtext()
- end
-else
- local tounicode=fonts.mappings.tounicode16
- function otf.getactualtext(s)
- return
- "/Span << /ActualText <feff"..n.."> >> BDC",
- "EMC"
- end
-end
-local sharedpalettes={}
-if context then
- local graytorgb=attributes.colors.graytorgb
- local cmyktorgb=attributes.colors.cmyktorgb
- function otf.registerpalette(name,values)
- sharedpalettes[name]=values
- for i=1,#values do
- local v=values[i]
- local r,g,b
- local s=v.s
- if s then
- r,g,b=graytorgb(s)
- else
- local c,m,y,k=v.c,v.m,v.y,v.k
- if c or m or y or k then
- r,g,b=cmyktorgb(c or 0,m or 0,y or 0,k or 0)
- else
- r,g,b=v.r,v.g,v.b
- end
- end
- values[i]={
- max(r and round(r*255) or 0,255),
- max(g and round(g*255) or 0,255),
- max(b and round(b*255) or 0,255)
- }
- end
- end
-else
- function otf.registerpalette(name,values)
- sharedpalettes[name]=values
- for i=1,#values do
- local v=values[i]
- values[i]={
- max(round((v.r or 0)*255),255),
- max(round((v.g or 0)*255),255),
- max(round((v.b or 0)*255),255)
- }
- end
- end
-end
-local function initializecolr(tfmdata,kind,value)
- if value then
- local palettes=tfmdata.resources.colorpalettes
- if palettes then
- local palette=sharedpalettes[value] or palettes[tonumber(value) or 1] or palettes[1] or {}
- local classes=#palette
- if classes==0 then
- return
- end
- local characters=tfmdata.characters
- local descriptions=tfmdata.descriptions
- local properties=tfmdata.properties
- local colorvalues={}
- properties.virtualized=true
- tfmdata.fonts={
- { id=0 }
- }
- for i=1,classes do
- local p=palette[i]
- local r,g,b=p[1],p[2],p[3]
- if r==g and g==b then
- colorvalues[i]={ "special",f_gray(r/255) }
- else
- colorvalues[i]={ "special",f_color(r/255,g/255,b/255) }
- end
- end
- local getactualtext=otf.getactualtext
- for unicode,character in next,characters do
- local description=descriptions[unicode]
- if description then
- local colorlist=description.colors
- if colorlist then
- local b,e=getactualtext(tounicode(characters[unicode].unicode or 0xFFFD))
- local w=character.width or 0
- local s=#colorlist
- local t={
- { "special","pdf:page:q" },
- { "special","pdf:raw:"..b }
- }
- local n=#t
- for i=1,s do
- local entry=colorlist[i]
- n=n+1 t[n]=colorvalues[entry.class] or s_black
- n=n+1 t[n]={ "char",entry.slot }
- if s>1 and i<s and w~=0 then
- n=n+1 t[n]={ "right",-w }
- end
- end
- n=n+1 t[n]={ "special","pdf:page:"..e }
- n=n+1 t[n]={ "special","pdf:raw:Q" }
- character.commands=t
- end
- end
- end
- end
- end
-end
-fonts.handlers.otf.features.register {
- name="colr",
- description="color glyphs",
- manipulators={
- base=initializecolr,
- node=initializecolr,
- }
-}
-local otfsvg=otf.svg or {}
-otf.svg=otfsvg
-otf.svgenabled=true
-do
- local nofstreams=0
- local f_name=formatters[ [[svg-glyph-%05i]] ]
- local f_used=context and formatters[ [[original:///%s]] ] or formatters[ [[%s]] ]
- local cache={}
- function otfsvg.storepdfdata(pdf)
- nofstreams=nofstreams+1
- local o,n=epdf.openMemStream(pdf,#pdf,f_name(nofstreams))
- cache[n]=o
- return nil,f_used(n),nil
- end
- if context then
- local storepdfdata=otfsvg.storepdfdata
- local initialized=false
- function otfsvg.storepdfdata(pdf)
- if not initialized then
- if resolvers.setmemstream then
- local f_setstream=formatters[ [[resolvers.setmemstream("svg-glyph-%05i",%q,true)]] ]
- local f_getstream=formatters[ [[memstream:///svg-glyph-%05i]] ]
- local f_nilstream=formatters[ [[resolvers.resetmemstream("svg-glyph-%05i",true)]] ]
- storepdfdata=function(pdf)
- nofstreams=nofstreams+1
- return
- f_setstream(nofstreams,pdf),
- f_getstream(nofstreams),
- f_nilstream(nofstreams)
- end
- otfsvg.storepdfdata=storepdfdata
- end
- initialized=true
- end
- return storepdfdata(pdf)
- end
- end
-end
-do
- local report_svg=logs.reporter("fonts","svg conversion")
- local loaddata=io.loaddata
- local savedata=io.savedata
- local remove=os.remove
- if context and xml.convert then
- local xmlconvert=xml.convert
- local xmlfirst=xml.first
- function otfsvg.filterglyph(entry,index)
- local svg=xmlconvert(entry.data)
- local root=svg and xmlfirst(svg,"/svg[@id='glyph"..index.."']")
- local data=root and tostring(root)
- return data
- end
- else
- function otfsvg.filterglyph(entry,index)
- return entry.data
- end
- end
- function otfsvg.topdf(svgshapes)
- local inkscape=io.popen("inkscape --shell > temp-otf-svg-shape.log","w")
- local pdfshapes={}
- local nofshapes=#svgshapes
- local f_svgfile=formatters["temp-otf-svg-shape-%i.svg"]
- local f_pdffile=formatters["temp-otf-svg-shape-%i.pdf"]
- local f_convert=formatters["%s --export-pdf=%s\n"]
- local filterglyph=otfsvg.filterglyph
- report_svg("processing %i svg containers",nofshapes)
- statistics.starttiming()
- for i=1,nofshapes do
- local entry=svgshapes[i]
- for index=entry.first,entry.last do
- local data=filterglyph(entry,index)
- if data and data~="" then
- local svgfile=f_svgfile(index)
- local pdffile=f_pdffile(index)
- savedata(svgfile,data)
- inkscape:write(f_convert(svgfile,pdffile))
- pdfshapes[index]=true
- end
- end
- end
- inkscape:write("quit\n")
- inkscape:close()
- report_svg("processing %i pdf results",nofshapes)
- for index in next,pdfshapes do
- local svgfile=f_svgfile(index)
- local pdffile=f_pdffile(index)
- pdfshapes[index]=loaddata(pdffile)
- remove(svgfile)
- remove(pdffile)
- end
- statistics.stoptiming()
- if statistics.elapsedseconds then
- report_svg("svg conversion time %s",statistics.elapsedseconds())
- end
- return pdfshapes
- end
-end
-local function initializesvg(tfmdata,kind,value)
- if value and otf.svgenabled then
- local characters=tfmdata.characters
- local descriptions=tfmdata.descriptions
- local properties=tfmdata.properties
- local svg=properties.svg
- local hash=svg and svg.hash
- local timestamp=svg and svg.timestamp
- if not hash then
- return
- end
- local pdffile=containers.read(otf.pdfcache,hash)
- local pdfshapes=pdffile and pdffile.pdfshapes
- if not pdfshapes or pdffile.timestamp~=timestamp then
- local svgfile=containers.read(otf.svgcache,hash)
- local svgshapes=svgfile and svgfile.svgshapes
- pdfshapes=svgshapes and otfsvg.topdf(svgshapes) or {}
- containers.write(otf.pdfcache,hash,{
- pdfshapes=pdfshapes,
- timestamp=timestamp,
- })
- end
- if not pdfshapes or not next(pdfshapes) then
- return
- end
- properties.virtualized=true
- tfmdata.fonts={
- { id=0 }
- }
- local getactualtext=otf.getactualtext
- local storepdfdata=otfsvg.storepdfdata
- local nop={ "nop" }
- for unicode,character in next,characters do
- local index=character.index
- if index then
- local pdf=pdfshapes[index]
- if pdf then
- local setcode,name,nilcode=storepdfdata(pdf)
- if name then
- local bt,et=getactualtext(unicode)
- local wd=character.width or 0
- local ht=character.height or 0
- local dp=character.depth or 0
- character.commands={
- { "special","pdf:direct:"..bt },
- { "down",dp },
- setcode and { "lua",setcode } or nop,
- { "image",{ filename=name,width=wd,height=ht,depth=dp } },
- nilcode and { "lua",nilcode } or nop,
- { "special","pdf:direct:"..et },
- }
- character.svg=true
- end
- end
- end
- end
- end
-end
-fonts.handlers.otf.features.register {
- name="svg",
- description="svg glyphs",
- manipulators={
- base=initializesvg,
- node=initializesvg,
- }
-}
-
-end --- [luaotfload, fontloader-2017-02-11.lua scope for “font-ocl”] ---
-
-
-do --- [luaotfload, fontloader-2017-02-11.lua scope for “font-otc” 85d63e257c748c624768aa7c8ec7f0bc] ---
-
-if not modules then modules={} end modules ['font-otc']={
- version=1.001,
- comment="companion to font-otf.lua (context)",
- author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright="PRAGMA ADE / ConTeXt Development Team",
- license="see context related readme files"
-}
-local format,insert,sortedkeys,tohash=string.format,table.insert,table.sortedkeys,table.tohash
-local type,next=type,next
-local lpegmatch=lpeg.match
-local utfbyte,utflen=utf.byte,utf.len
-local trace_loading=false trackers.register("otf.loading",function(v) trace_loading=v end)
-local report_otf=logs.reporter("fonts","otf loading")
-local fonts=fonts
-local otf=fonts.handlers.otf
-local registerotffeature=otf.features.register
-local setmetatableindex=table.setmetatableindex
-local normalized={
- substitution="substitution",
- single="substitution",
- ligature="ligature",
- alternate="alternate",
- multiple="multiple",
- kern="kern",
- pair="pair",
- chainsubstitution="chainsubstitution",
- chainposition="chainposition",
-}
-local types={
- substitution="gsub_single",
- ligature="gsub_ligature",
- alternate="gsub_alternate",
- multiple="gsub_multiple",
- kern="gpos_pair",
- pair="gpos_pair",
- chainsubstitution="gsub_contextchain",
- chainposition="gpos_contextchain",
-}
-local names={
- gsub_single="gsub",
- gsub_multiple="gsub",
- gsub_alternate="gsub",
- gsub_ligature="gsub",
- gsub_context="gsub",
- gsub_contextchain="gsub",
- gsub_reversecontextchain="gsub",
- gpos_single="gpos",
- gpos_pair="gpos",
- gpos_cursive="gpos",
- gpos_mark2base="gpos",
- gpos_mark2ligature="gpos",
- gpos_mark2mark="gpos",
- gpos_context="gpos",
- gpos_contextchain="gpos",
-}
-setmetatableindex(types,function(t,k) t[k]=k return k end)
-local everywhere={ ["*"]={ ["*"]=true } }
-local noflags={ false,false,false,false }
-local function getrange(sequences,category)
- local count=#sequences
- local first=nil
- local last=nil
- for i=1,count do
- local t=sequences[i].type
- if t and names[t]==category then
- if not first then
- first=i
- end
- last=i
- end
- end
- return first or 1,last or count
-end
-local function validspecification(specification,name)
- local dataset=specification.dataset
- if dataset then
- elseif specification[1] then
- dataset=specification
- specification={ dataset=dataset }
- else
- dataset={ { data=specification.data } }
- specification.data=nil
- specification.dataset=dataset
- end
- local first=dataset[1]
- if first then
- first=first.data
- end
- if not first then
- report_otf("invalid feature specification, no dataset")
- return
- end
- if type(name)~="string" then
- name=specification.name or first.name
- end
- if type(name)~="string" then
- report_otf("invalid feature specification, no name")
- return
- end
- local n=#dataset
- if n>0 then
- for i=1,n do
- setmetatableindex(dataset[i],specification)
- end
- return specification,name
- end
-end
-local function addfeature(data,feature,specifications)
- if not specifications then
- report_otf("missing specification")
- return
- end
- local descriptions=data.descriptions
- local resources=data.resources
- local features=resources.features
- local sequences=resources.sequences
- if not features or not sequences then
- report_otf("missing specification")
- return
- end
- local alreadydone=resources.alreadydone
- if not alreadydone then
- alreadydone={}
- resources.alreadydone=alreadydone
- end
- if alreadydone[specifications] then
- return
- else
- alreadydone[specifications]=true
- end
- local fontfeatures=resources.features or everywhere
- local unicodes=resources.unicodes
- local splitter=lpeg.splitter(" ",unicodes)
- local done=0
- local skip=0
- local aglunicodes=false
- local specifications=validspecification(specifications,feature)
- if not specifications then
- return
- end
- local function tounicode(code)
- if not code then
- return
- end
- if type(code)=="number" then
- return code
- end
- local u=unicodes[code]
- if u then
- return u
- end
- if utflen(code)==1 then
- u=utfbyte(code)
- if u then
- return u
- end
- end
- if not aglunicodes then
- aglunicodes=fonts.encodings.agl.unicodes
- end
- return aglunicodes[code]
- end
- local coverup=otf.coverup
- local coveractions=coverup.actions
- local stepkey=coverup.stepkey
- local register=coverup.register
- local function prepare_substitution(list,featuretype)
- local coverage={}
- local cover=coveractions[featuretype]
- for code,replacement in next,list do
- local unicode=tounicode(code)
- local description=descriptions[unicode]
- if description then
- if type(replacement)=="table" then
- replacement=replacement[1]
- end
- replacement=tounicode(replacement)
- if replacement and descriptions[replacement] then
- cover(coverage,unicode,replacement)
- done=done+1
- else
- skip=skip+1
- end
- else
- skip=skip+1
- end
- end
- return coverage
- end
- local function prepare_alternate(list,featuretype)
- local coverage={}
- local cover=coveractions[featuretype]
- for code,replacement in next,list do
- local unicode=tounicode(code)
- local description=descriptions[unicode]
- if not description then
- skip=skip+1
- elseif type(replacement)=="table" then
- local r={}
- for i=1,#replacement do
- local u=tounicode(replacement[i])
- r[i]=descriptions[u] and u or unicode
- end
- cover(coverage,unicode,r)
- done=done+1
- else
- local u=tounicode(replacement)
- if u then
- cover(coverage,unicode,{ u })
- done=done+1
- else
- skip=skip+1
- end
- end
- end
- return coverage
- end
- local function prepare_multiple(list,featuretype)
- local coverage={}
- local cover=coveractions[featuretype]
- for code,replacement in next,list do
- local unicode=tounicode(code)
- local description=descriptions[unicode]
- if not description then
- skip=skip+1
- elseif type(replacement)=="table" then
- local r,n={},0
- for i=1,#replacement do
- local u=tounicode(replacement[i])
- if descriptions[u] then
- n=n+1
- r[n]=u
- end
- end
- if n>0 then
- cover(coverage,unicode,r)
- done=done+1
- else
- skip=skip+1
- end
- else
- local u=tounicode(replacement)
- if u then
- cover(coverage,unicode,{ u })
- done=done+1
- else
- skip=skip+1
- end
- end
- end
- return coverage
- end
- local function prepare_ligature(list,featuretype)
- local coverage={}
- local cover=coveractions[featuretype]
- for code,ligature in next,list do
- local unicode=tounicode(code)
- local description=descriptions[unicode]
- if description then
- if type(ligature)=="string" then
- ligature={ lpegmatch(splitter,ligature) }
- end
- local present=true
- for i=1,#ligature do
- local l=ligature[i]
- local u=tounicode(l)
- if descriptions[u] then
- ligature[i]=u
- else
- present=false
- break
- end
- end
- if present then
- cover(coverage,unicode,ligature)
- done=done+1
- else
- skip=skip+1
- end
- else
- skip=skip+1
- end
- end
- return coverage
- end
- local function prepare_kern(list,featuretype)
- local coverage={}
- local cover=coveractions[featuretype]
- for code,replacement in next,list do
- local unicode=tounicode(code)
- local description=descriptions[unicode]
- if description and type(replacement)=="table" then
- local r={}
- for k,v in next,replacement do
- local u=tounicode(k)
- if u then
- r[u]=v
- end
- end
- if next(r) then
- cover(coverage,unicode,r)
- done=done+1
- else
- skip=skip+1
- end
- else
- skip=skip+1
- end
- end
- return coverage
- end
- local function prepare_pair(list,featuretype)
- local coverage={}
- local cover=coveractions[featuretype]
- if cover then
- for code,replacement in next,list do
- local unicode=tounicode(code)
- local description=descriptions[unicode]
- if description and type(replacement)=="table" then
- local r={}
- for k,v in next,replacement do
- local u=tounicode(k)
- if u then
- r[u]=v
- end
- end
- if next(r) then
- cover(coverage,unicode,r)
- done=done+1
- else
- skip=skip+1
- end
- else
- skip=skip+1
- end
- end
- else
- report_otf("unknown cover type %a",featuretype)
- end
- return coverage
- end
- local function prepare_chain(list,featuretype,sublookups)
- local rules=list.rules
- local coverage={}
- if rules then
- local rulehash={}
- local rulesize=0
- local sequence={}
- local nofsequences=0
- local lookuptype=types[featuretype]
- for nofrules=1,#rules do
- local rule=rules[nofrules]
- local current=rule.current
- local before=rule.before
- local after=rule.after
- local replacements=rule.replacements or false
- local sequence={}
- local nofsequences=0
- if before then
- for n=1,#before do
- nofsequences=nofsequences+1
- sequence[nofsequences]=before[n]
- end
- end
- local start=nofsequences+1
- for n=1,#current do
- nofsequences=nofsequences+1
- sequence[nofsequences]=current[n]
- end
- local stop=nofsequences
- if after then
- for n=1,#after do
- nofsequences=nofsequences+1
- sequence[nofsequences]=after[n]
- end
- end
- local lookups=rule.lookups or false
- local subtype=nil
- if lookups and sublookups then
- for k,v in next,lookups do
- local lookup=sublookups[v]
- if lookup then
- lookups[k]=lookup
- if not subtype then
- subtype=lookup.type
- end
- else
- end
- end
- end
- if nofsequences>0 then
- local hashed={}
- for i=1,nofsequences do
- local t={}
- local s=sequence[i]
- for i=1,#s do
- local u=tounicode(s[i])
- if u then
- t[u]=true
- end
- end
- hashed[i]=t
- end
- sequence=hashed
- rulesize=rulesize+1
- rulehash[rulesize]={
- nofrules,
- lookuptype,
- sequence,
- start,
- stop,
- lookups,
- replacements,
- subtype,
- }
- for unic in next,sequence[start] do
- local cu=coverage[unic]
- if not cu then
- coverage[unic]=rulehash
- end
- end
- end
- end
- end
- return coverage
- end
- local dataset=specifications.dataset
- local function report(name,category,position,first,last,sequences)
- report_otf("injecting name %a of category %a at position %i in [%i,%i] of [%i,%i]",
- name,category,position,first,last,1,#sequences)
- end
- local function inject(specification,sequences,sequence,first,last,category,name)
- local position=specification.position or false
- if not position then
- position=specification.prepend
- if position==true then
- if trace_loading then
- report(name,category,first,first,last,sequences)
- end
- insert(sequences,first,sequence)
- return
- end
- end
- if not position then
- position=specification.append
- if position==true then
- if trace_loading then
- report(name,category,last+1,first,last,sequences)
- end
- insert(sequences,last+1,sequence)
- return
- end
- end
- local kind=type(position)
- if kind=="string" then
- local index=false
- for i=first,last do
- local s=sequences[i]
- local f=s.features
- if f then
- for k in next,f do
- if k==position then
- index=i
- break
- end
- end
- if index then
- break
- end
- end
- end
- if index then
- position=index
- else
- position=last+1
- end
- elseif kind=="number" then
- if position<0 then
- position=last-position+1
- end
- if position>last then
- position=last+1
- elseif position<first then
- position=first
- end
- else
- position=last+1
- end
- if trace_loading then
- report(name,category,position,first,last,sequences)
- end
- insert(sequences,position,sequence)
- end
- for s=1,#dataset do
- local specification=dataset[s]
- local valid=specification.valid
- local feature=specification.name or feature
- if not feature or feature=="" then
- report_otf("no valid name given for extra feature")
- elseif not valid or valid(data,specification,feature) then
- local initialize=specification.initialize
- if initialize then
- specification.initialize=initialize(specification,data) and initialize or nil
- end
- local askedfeatures=specification.features or everywhere
- local askedsteps=specification.steps or specification.subtables or { specification.data } or {}
- local featuretype=normalized[specification.type or "substitution"] or "substitution"
- local featureflags=specification.flags or noflags
- local featureorder=specification.order or { feature }
- local featurechain=(featuretype=="chainsubstitution" or featuretype=="chainposition") and 1 or 0
- local nofsteps=0
- local steps={}
- local sublookups=specification.lookups
- local category=nil
- if sublookups then
- local s={}
- for i=1,#sublookups do
- local specification=sublookups[i]
- local askedsteps=specification.steps or specification.subtables or { specification.data } or {}
- local featuretype=normalized[specification.type or "substitution"] or "substitution"
- local featureflags=specification.flags or noflags
- local nofsteps=0
- local steps={}
- for i=1,#askedsteps do
- local list=askedsteps[i]
- local coverage=nil
- local format=nil
- if featuretype=="substitution" then
- coverage=prepare_substitution(list,featuretype)
- elseif featuretype=="ligature" then
- coverage=prepare_ligature(list,featuretype)
- elseif featuretype=="alternate" then
- coverage=prepare_alternate(list,featuretype)
- elseif featuretype=="multiple" then
- coverage=prepare_multiple(list,featuretype)
- elseif featuretype=="kern" then
- format="kern"
- coverage=prepare_kern(list,featuretype)
- elseif featuretype=="pair" then
- format="pair"
- coverage=prepare_pair(list,featuretype)
- end
- if coverage and next(coverage) then
- nofsteps=nofsteps+1
- steps[nofsteps]=register(coverage,featuretype,format,feature,nofsteps,descriptions,resources)
- end
- end
- s[i]={
- [stepkey]=steps,
- nofsteps=nofsteps,
- type=types[featuretype],
- }
- end
- sublookups=s
- end
- for i=1,#askedsteps do
- local list=askedsteps[i]
- local coverage=nil
- local format=nil
- if featuretype=="substitution" then
- category="gsub"
- coverage=prepare_substitution(list,featuretype)
- elseif featuretype=="ligature" then
- category="gsub"
- coverage=prepare_ligature(list,featuretype)
- elseif featuretype=="alternate" then
- category="gsub"
- coverage=prepare_alternate(list,featuretype)
- elseif featuretype=="multiple" then
- category="gsub"
- coverage=prepare_multiple(list,featuretype)
- elseif featuretype=="kern" then
- category="gpos"
- format="kern"
- coverage=prepare_kern(list,featuretype)
- elseif featuretype=="pair" then
- category="gpos"
- format="pair"
- coverage=prepare_pair(list,featuretype)
- elseif featuretype=="chainsubstitution" then
- category="gsub"
- coverage=prepare_chain(list,featuretype,sublookups)
- elseif featuretype=="chainposition" then
- category="gpos"
- coverage=prepare_chain(list,featuretype,sublookups)
- else
- report_otf("not registering feature %a, unknown category",feature)
- return
- end
- if coverage and next(coverage) then
- nofsteps=nofsteps+1
- steps[nofsteps]=register(coverage,featuretype,format,feature,nofsteps,descriptions,resources)
- end
- end
- if nofsteps>0 then
- for k,v in next,askedfeatures do
- if v[1] then
- askedfeatures[k]=tohash(v)
- end
- end
- if featureflags[1] then featureflags[1]="mark" end
- if featureflags[2] then featureflags[2]="ligature" end
- if featureflags[3] then featureflags[3]="base" end
- local steptype=types[featuretype]
- local sequence={
- chain=featurechain,
- features={ [feature]=askedfeatures },
- flags=featureflags,
- name=feature,
- order=featureorder,
- [stepkey]=steps,
- nofsteps=nofsteps,
- type=steptype,
- }
- local first,last=getrange(sequences,category)
- inject(specification,sequences,sequence,first,last,category,feature)
- local features=fontfeatures[category]
- if not features then
- features={}
- fontfeatures[category]=features
- end
- local k=features[feature]
- if not k then
- k={}
- features[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
-otf.enhancers.addfeature=addfeature
-local extrafeatures={}
-local knownfeatures={}
-function otf.addfeature(name,specification)
- if type(name)=="table" then
- specification=name
- end
- if type(specification)~="table" then
- report_otf("invalid feature specification, no valid table")
- return
- end
- specification,name=validspecification(specification,name)
- if name and specification then
- local slot=knownfeatures[name]
- if slot then
- else
- slot=#extrafeatures+1
- knownfeatures[name]=slot
- end
- specification.name=name
- extrafeatures[slot]=specification
- end
-end
-local function enhance(data,filename,raw)
- for slot=1,#extrafeatures do
- local specification=extrafeatures[slot]
- addfeature(data,specification.name,specification)
- end
-end
-otf.enhancers.enhance=enhance
-otf.enhancers.register("check extra features",enhance)
-local tlig={
- [0x2013]={ 0x002D,0x002D },
- [0x2014]={ 0x002D,0x002D,0x002D },
-}
-local tlig_specification={
- type="ligature",
- features=everywhere,
- data=tlig,
- order={ "tlig" },
- flags=noflags,
- prepend=true,
-}
-otf.addfeature("tlig",tlig_specification)
-registerotffeature {
- name='tlig',
- description='tex ligatures',
-}
-local trep={
- [0x0027]=0x2019,
-}
-local trep_specification={
- type="substitution",
- features=everywhere,
- data=trep,
- order={ "trep" },
- flags=noflags,
- prepend=true,
-}
-otf.addfeature("trep",trep_specification)
-registerotffeature {
- name='trep',
- description='tex replacements',
-}
-local anum_arabic={
- [0x0030]=0x0660,
- [0x0031]=0x0661,
- [0x0032]=0x0662,
- [0x0033]=0x0663,
- [0x0034]=0x0664,
- [0x0035]=0x0665,
- [0x0036]=0x0666,
- [0x0037]=0x0667,
- [0x0038]=0x0668,
- [0x0039]=0x0669,
-}
-local anum_persian={
- [0x0030]=0x06F0,
- [0x0031]=0x06F1,
- [0x0032]=0x06F2,
- [0x0033]=0x06F3,
- [0x0034]=0x06F4,
- [0x0035]=0x06F5,
- [0x0036]=0x06F6,
- [0x0037]=0x06F7,
- [0x0038]=0x06F8,
- [0x0039]=0x06F9,
-}
-local function valid(data)
- local features=data.resources.features
- if features then
- for k,v in next,features do
- for k,v in next,v do
- if v.arab then
- return true
- end
- end
- end
- end
-end
-local anum_specification={
- {
- type="substitution",
- features={ arab={ urd=true,dflt=true } },
- order={ "anum" },
- data=anum_arabic,
- flags=noflags,
- valid=valid,
- },
- {
- type="substitution",
- features={ arab={ urd=true } },
- order={ "anum" },
- data=anum_persian,
- flags=noflags,
- valid=valid,
- },
-}
-otf.addfeature("anum",anum_specification)
-registerotffeature {
- name='anum',
- description='arabic digits',
-}
-
-end --- [luaotfload, fontloader-2017-02-11.lua scope for “font-otc”] ---
-
-
-do --- [luaotfload, fontloader-2017-02-11.lua scope for “font-onr” 205c8bc640715aecf3538a33b842f450] ---
-
-if not modules then modules={} end modules ['font-onr']={
- version=1.001,
- comment="companion to font-ini.mkiv",
- author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright="PRAGMA ADE / ConTeXt Development Team",
- license="see context related readme files"
-}
-local fonts,logs,trackers,resolvers=fonts,logs,trackers,resolvers
-local next,type,tonumber,rawget,rawset=next,type,tonumber,rawget,rawset
-local match,lower,gsub,strip,find=string.match,string.lower,string.gsub,string.strip,string.find
-local char,byte,sub=string.char,string.byte,string.sub
-local abs=math.abs
-local bxor,rshift=bit32.bxor,bit32.rshift
-local P,S,R,Cmt,C,Ct,Cs,Carg,Cf,Cg=lpeg.P,lpeg.S,lpeg.R,lpeg.Cmt,lpeg.C,lpeg.Ct,lpeg.Cs,lpeg.Carg,lpeg.Cf,lpeg.Cg
-local lpegmatch,patterns=lpeg.match,lpeg.patterns
-local trace_indexing=false trackers.register("afm.indexing",function(v) trace_indexing=v end)
-local trace_loading=false trackers.register("afm.loading",function(v) trace_loading=v end)
-local report_afm=logs.reporter("fonts","afm loading")
-local report_pfb=logs.reporter("fonts","pfb loading")
-local handlers=fonts.handlers
-local afm=handlers.afm or {}
-handlers.afm=afm
-local readers=afm.readers or {}
-afm.readers=readers
-afm.version=1.512
-local get_indexes,get_shapes
-do
- local decrypt
- do
- local r,c1,c2,n=0,0,0,0
- local function step(c)
- local cipher=byte(c)
- local plain=bxor(cipher,rshift(r,8))
- r=((cipher+r)*c1+c2)%65536
- return char(plain)
- end
- decrypt=function(binary,initial,seed)
- r,c1,c2,n=initial,52845,22719,seed
- binary=gsub(binary,".",step)
- return sub(binary,n+1)
- end
- end
- local charstrings=P("/CharStrings")
- local subroutines=P("/Subrs")
- local encoding=P("/Encoding")
- local dup=P("dup")
- local put=P("put")
- local array=P("array")
- local name=P("/")*C((R("az")+R("AZ")+R("09")+S("-_."))^1)
- local digits=R("09")^1
- local cardinal=digits/tonumber
- local spaces=P(" ")^1
- local spacing=patterns.whitespace^0
- local routines,vector,chars,n,m
- local initialize=function(str,position,size)
- n=0
- m=size
- return position+1
- end
- local setroutine=function(str,position,index,size)
- local forward=position+tonumber(size)
- local stream=sub(str,position+1,forward)
- routines[index]=decrypt(stream,4330,4)
- return forward
- end
- local setvector=function(str,position,name,size)
- local forward=position+tonumber(size)
- if n>=m then
- return #str
- elseif forward<#str then
- vector[n]=name
- n=n+1
- return forward
- else
- return #str
- end
- end
- local setshapes=function(str,position,name,size)
- local forward=position+tonumber(size)
- local stream=sub(str,position+1,forward)
- if n>m then
- return #str
- elseif forward<#str then
- vector[n]=name
- n=n+1
- chars [n]=decrypt(stream,4330,4)
- return forward
- else
- return #str
- end
- end
- local p_rd=spacing*(P("RD")+P("-|"))
- local p_np=spacing*(P("NP")+P("|"))
- local p_nd=spacing*(P("ND")+P("|"))
- local p_filterroutines=
- (1-subroutines)^0*subroutines*spaces*Cmt(cardinal,initialize)*(Cmt(cardinal*spaces*cardinal*p_rd,setroutine)*p_np+P(1))^1
- local p_filtershapes=
- (1-charstrings)^0*charstrings*spaces*Cmt(cardinal,initialize)*(Cmt(name*spaces*cardinal*p_rd,setshapes)*p_nd+P(1))^1
- local p_filternames=Ct (
- (1-charstrings)^0*charstrings*spaces*Cmt(cardinal,initialize)*(Cmt(name*spaces*cardinal,setvector)+P(1))^1
- )
- local p_filterencoding=(1-encoding)^0*encoding*spaces*digits*spaces*array*(1-dup)^0*Cf(
- Ct("")*Cg(spacing*dup*spaces*cardinal*spaces*name*spaces*put)^1
-,rawset)
- local function loadpfbvector(filename,shapestoo)
- local data=io.loaddata(resolvers.findfile(filename))
- if not data then
- report_pfb("no data in %a",filename)
- return
- end
- if not (find(data,"!PS%-AdobeFont%-") or find(data,"%%!FontType1")) then
- report_pfb("no font in %a",filename)
- return
- end
- local ascii,binary=match(data,"(.*)eexec%s+......(.*)")
- if not binary then
- report_pfb("no binary data in %a",filename)
- return
- end
- binary=decrypt(binary,55665,4)
- local names={}
- local encoding=lpegmatch(p_filterencoding,ascii)
- local glyphs={}
- routines,vector,chars={},{},{}
- if shapestoo then
- lpegmatch(p_filterroutines,binary)
- lpegmatch(p_filtershapes,binary)
- local data={
- dictionaries={
- {
- charstrings=chars,
- charset=vector,
- subroutines=routines,
- }
- },
- }
- fonts.handlers.otf.readers.parsecharstrings(data,glyphs,true,true)
- else
- lpegmatch(p_filternames,binary)
- end
- names=vector
- routines,vector,chars=nil,nil,nil
- return names,encoding,glyphs
- end
- local pfb=handlers.pfb or {}
- handlers.pfb=pfb
- pfb.loadvector=loadpfbvector
- get_indexes=function(data,pfbname)
- local vector=loadpfbvector(pfbname)
- if vector then
- local characters=data.characters
- if trace_loading then
- report_afm("getting index data from %a",pfbname)
- end
- for index=1,#vector do
- local name=vector[index]
- local char=characters[name]
- if char then
- if trace_indexing then
- report_afm("glyph %a has index %a",name,index)
- end
- char.index=index
- end
- end
- end
- end
- get_shapes=function(pfbname)
- local vector,encoding,glyphs=loadpfbvector(pfbname,true)
- return glyphs
- end
-end
-local spacer=patterns.spacer
-local whitespace=patterns.whitespace
-local lineend=patterns.newline
-local spacing=spacer^0
-local number=spacing*S("+-")^-1*(R("09")+S("."))^1/tonumber
-local name=spacing*C((1-whitespace)^1)
-local words=spacing*((1-lineend)^1/strip)
-local rest=(1-lineend)^0
-local fontdata=Carg(1)
-local semicolon=spacing*P(";")
-local plus=spacing*P("plus")*number
-local minus=spacing*P("minus")*number
-local function addkernpair(data,one,two,value)
- local chr=data.characters[one]
- if chr then
- local kerns=chr.kerns
- if kerns then
- kerns[two]=tonumber(value)
- else
- chr.kerns={ [two]=tonumber(value) }
- end
- end
-end
-local p_kernpair=(fontdata*P("KPX")*name*name*number)/addkernpair
-local chr=false
-local ind=0
-local function start(data,version)
- data.metadata.afmversion=version
- ind=0
- chr={}
-end
-local function stop()
- ind=0
- chr=false
-end
-local function setindex(i)
- if i<0 then
- ind=ind+1
- else
- ind=i
- end
- chr={
- index=ind
- }
-end
-local function setwidth(width)
- chr.width=width
-end
-local function setname(data,name)
- data.characters[name]=chr
-end
-local function setboundingbox(boundingbox)
- chr.boundingbox=boundingbox
-end
-local function setligature(plus,becomes)
- local ligatures=chr.ligatures
- if ligatures then
- ligatures[plus]=becomes
- else
- chr.ligatures={ [plus]=becomes }
- end
-end
-local p_charmetric=((
- P("C")*number/setindex+P("WX")*number/setwidth+P("N")*fontdata*name/setname+P("B")*Ct((number)^4)/setboundingbox+P("L")*(name)^2/setligature
- )*semicolon )^1
-local p_charmetrics=P("StartCharMetrics")*number*(p_charmetric+(1-P("EndCharMetrics")))^0*P("EndCharMetrics")
-local p_kernpairs=P("StartKernPairs")*number*(p_kernpair+(1-P("EndKernPairs" )))^0*P("EndKernPairs" )
-local function set_1(data,key,a) data.metadata[lower(key)]=a end
-local function set_2(data,key,a,b) data.metadata[lower(key)]={ a,b } end
-local function set_3(data,key,a,b,c) data.metadata[lower(key)]={ a,b,c } end
-local p_parameters=P(false)+fontdata*((P("FontName")+P("FullName")+P("FamilyName"))/lower)*words/function(data,key,value)
- data.metadata[key]=value
- end+fontdata*((P("Weight")+P("Version"))/lower)*name/function(data,key,value)
- data.metadata[key]=value
- end+fontdata*P("IsFixedPitch")*name/function(data,pitch)
- data.metadata.monospaced=toboolean(pitch,true)
- end+fontdata*P("FontBBox")*Ct(number^4)/function(data,boundingbox)
- data.metadata.boundingbox=boundingbox
- end+fontdata*((P("CharWidth")+P("CapHeight")+P("XHeight")+P("Descender")+P("Ascender")+P("ItalicAngle"))/lower)*number/function(data,key,value)
- data.metadata[key]=value
- end+P("Comment")*spacing*(P(false)+(fontdata*C("DESIGNSIZE")*number*rest)/set_1
-+(fontdata*C("TFM designsize")*number*rest)/set_1+(fontdata*C("DesignSize")*number*rest)/set_1+(fontdata*C("CODINGSCHEME")*words*rest)/set_1
-+(fontdata*C("CHECKSUM")*number*words*rest)/set_1
-+(fontdata*C("SPACE")*number*plus*minus*rest)/set_3
-+(fontdata*C("QUAD")*number*rest)/set_1
-+(fontdata*C("EXTRASPACE")*number*rest)/set_1
-+(fontdata*C("NUM")*number*number*number*rest)/set_3
-+(fontdata*C("DENOM")*number*number*rest)/set_2
-+(fontdata*C("SUP")*number*number*number*rest)/set_3
-+(fontdata*C("SUB")*number*number*rest)/set_2
-+(fontdata*C("SUPDROP")*number*rest)/set_1
-+(fontdata*C("SUBDROP")*number*rest)/set_1
-+(fontdata*C("DELIM")*number*number*rest)/set_2
-+(fontdata*C("AXISHEIGHT")*number*rest)/set_1
- )
-local fullparser=(P("StartFontMetrics")*fontdata*name/start )*(p_charmetrics+p_kernpairs+p_parameters+(1-P("EndFontMetrics")) )^0*(P("EndFontMetrics")/stop )
-local fullparser=(P("StartFontMetrics")*fontdata*name/start )*(p_charmetrics+p_kernpairs+p_parameters+(1-P("EndFontMetrics")) )^0*(P("EndFontMetrics")/stop )
-local infoparser=(P("StartFontMetrics")*fontdata*name/start )*(p_parameters+(1-P("EndFontMetrics")) )^0*(P("EndFontMetrics")/stop )
-local function read(filename,parser)
- local afmblob=io.loaddata(filename)
- if afmblob then
- local data={
- resources={
- filename=resolvers.unresolve(filename),
- version=afm.version,
- creator="context mkiv",
- },
- properties={
- hasitalics=false,
- },
- goodies={},
- metadata={
- filename=file.removesuffix(file.basename(filename))
- },
- characters={
- },
- descriptions={
- },
- }
- if trace_loading then
- report_afm("parsing afm file %a",filename)
- end
- lpegmatch(parser,afmblob,1,data)
- return data
- else
- if trace_loading then
- report_afm("no valid afm file %a",filename)
- end
- return nil
- end
-end
-function readers.loadfont(afmname,pfbname)
- local data=read(resolvers.findfile(afmname),fullparser)
- if data then
- if not pfbname or pfbname=="" then
- pfbname=file.replacesuffix(file.nameonly(afmname),"pfb")
- pfbname=resolvers.findfile(pfbname)
- end
- if pfbname and pfbname~="" then
- data.resources.filename=resolvers.unresolve(pfbname)
- get_indexes(data,pfbname)
- elseif trace_loading then
- report_afm("no pfb file for %a",afmname)
- end
- return data
- end
-end
-function readers.loadshapes(filename)
- local fullname=resolvers.findfile(filename) or ""
- if fullname=="" then
- return {
- filename="not found: "..filename,
- glyphs={}
- }
- else
- return {
- filename=fullname,
- format="opentype",
- glyphs=get_shapes(fullname) or {},
- units=1000,
- }
- end
-end
-function readers.getinfo(filename)
- local data=read(resolvers.findfile(filename),infoparser)
- if data then
- return data.metadata
- end
-end
-
-end --- [luaotfload, fontloader-2017-02-11.lua scope for “font-onr”] ---
-
-
-do --- [luaotfload, fontloader-2017-02-11.lua scope for “font-one” 6fbf6b9e219a944cd1ad5933d77cc488] ---
-
-if not modules then modules={} end modules ['font-one']={
- version=1.001,
- comment="companion to font-ini.mkiv",
- author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright="PRAGMA ADE / ConTeXt Development Team",
- license="see context related readme files"
-}
-local fonts,logs,trackers,containers,resolvers=fonts,logs,trackers,containers,resolvers
-local next,type,tonumber,rawget=next,type,tonumber,rawget
-local match,gmatch,lower,gsub,strip,find=string.match,string.gmatch,string.lower,string.gsub,string.strip,string.find
-local char,byte,sub=string.char,string.byte,string.sub
-local abs=math.abs
-local bxor,rshift=bit32.bxor,bit32.rshift
-local P,S,R,Cmt,C,Ct,Cs,Carg=lpeg.P,lpeg.S,lpeg.R,lpeg.Cmt,lpeg.C,lpeg.Ct,lpeg.Cs,lpeg.Carg
-local lpegmatch,patterns=lpeg.match,lpeg.patterns
-local trace_features=false trackers.register("afm.features",function(v) trace_features=v end)
-local trace_indexing=false trackers.register("afm.indexing",function(v) trace_indexing=v end)
-local trace_loading=false trackers.register("afm.loading",function(v) trace_loading=v end)
-local trace_defining=false trackers.register("fonts.defining",function(v) trace_defining=v end)
-local report_afm=logs.reporter("fonts","afm loading")
-local setmetatableindex=table.setmetatableindex
-local derivetable=table.derive
-local findbinfile=resolvers.findbinfile
-local definers=fonts.definers
-local readers=fonts.readers
-local constructors=fonts.constructors
-local afm=constructors.handlers.afm
-local pfb=constructors.handlers.pfb
-local otf=fonts.handlers.otf
-local otfreaders=otf.readers
-local otfenhancers=otf.enhancers
-local afmfeatures=constructors.features.afm
-local registerafmfeature=afmfeatures.register
-local afmenhancers=constructors.enhancers.afm
-local registerafmenhancer=afmenhancers.register
-afm.version=1.512
-afm.cache=containers.define("fonts","one",afm.version,true)
-afm.autoprefixed=true
-afm.helpdata={}
-afm.syncspace=true
-local overloads=fonts.mappings.overloads
-local applyruntimefixes=fonts.treatments and fonts.treatments.applyfixes
-function afm.load(filename)
- filename=resolvers.findfile(filename,'afm') or ""
- if filename~="" and not fonts.names.ignoredfile(filename) then
- local name=file.removesuffix(file.basename(filename))
- local data=containers.read(afm.cache,name)
- local attr=lfs.attributes(filename)
- local size,time=attr.size or 0,attr.modification or 0
- local pfbfile=file.replacesuffix(name,"pfb")
- local pfbname=resolvers.findfile(pfbfile,"pfb") or ""
- if pfbname=="" then
- pfbname=resolvers.findfile(file.basename(pfbfile),"pfb") or ""
- end
- local pfbsize,pfbtime=0,0
- if pfbname~="" then
- local attr=lfs.attributes(pfbname)
- pfbsize=attr.size or 0
- pfbtime=attr.modification or 0
- end
- if not data or data.size~=size or data.time~=time or data.pfbsize~=pfbsize or data.pfbtime~=pfbtime then
- report_afm("reading %a",filename)
- data=afm.readers.loadfont(filename,pfbname)
- if data then
- afmenhancers.apply(data,filename)
- fonts.mappings.addtounicode(data,filename)
- otfreaders.pack(data)
- data.size=size
- data.time=time
- data.pfbsize=pfbsize
- data.pfbtime=pfbtime
- report_afm("saving %a in cache",name)
- data=containers.write(afm.cache,name,data)
- data=containers.read(afm.cache,name)
- end
- end
- if data then
- otfreaders.unpack(data)
- otfreaders.expand(data)
- otfreaders.addunicodetable(data)
- otfenhancers.apply(data,filename,data)
- if applyruntimefixes then
- applyruntimefixes(filename,data)
- end
- end
- return data
- end
-end
-local uparser=fonts.mappings.makenameparser()
-local function enhance_unify_names(data,filename)
- local unicodevector=fonts.encodings.agl.unicodes
- local unicodes={}
- local names={}
- local private=constructors.privateoffset
- local descriptions=data.descriptions
- for name,blob in next,data.characters do
- local code=unicodevector[name]
- if not code then
- code=lpegmatch(uparser,name)
- if type(code)~="number" then
- code=private
- private=private+1
- report_afm("assigning private slot %U for unknown glyph name %a",code,name)
- end
- end
- local index=blob.index
- unicodes[name]=code
- names[name]=index
- blob.name=name
- descriptions[code]={
- boundingbox=blob.boundingbox,
- width=blob.width,
- kerns=blob.kerns,
- index=index,
- name=name,
- }
- end
- for unicode,description in next,descriptions do
- local kerns=description.kerns
- if kerns then
- local krn={}
- for name,kern in next,kerns do
- local unicode=unicodes[name]
- if unicode then
- krn[unicode]=kern
- else
- end
- end
- description.kerns=krn
- end
- end
- data.characters=nil
- local resources=data.resources
- local filename=resources.filename or file.removesuffix(file.basename(filename))
- resources.filename=resolvers.unresolve(filename)
- resources.unicodes=unicodes
- resources.marks={}
- resources.private=private
-end
-local everywhere={ ["*"]={ ["*"]=true } }
-local noflags={ false,false,false,false }
-local function enhance_normalize_features(data)
- local ligatures=setmetatableindex("table")
- local kerns=setmetatableindex("table")
- local extrakerns=setmetatableindex("table")
- for u,c in next,data.descriptions do
- local l=c.ligatures
- local k=c.kerns
- local e=c.extrakerns
- if l then
- ligatures[u]=l
- for u,v in next,l do
- l[u]={ ligature=v }
- end
- c.ligatures=nil
- end
- if k then
- kerns[u]=k
- for u,v in next,k do
- k[u]=v
- end
- c.kerns=nil
- end
- if e then
- extrakerns[u]=e
- for u,v in next,e do
- e[u]=v
- end
- c.extrakerns=nil
- end
- end
- local features={
- gpos={},
- gsub={},
- }
- local sequences={
- }
- if next(ligatures) then
- features.gsub.liga=everywhere
- data.properties.hasligatures=true
- sequences[#sequences+1]={
- features={
- liga=everywhere,
- },
- flags=noflags,
- name="s_s_0",
- nofsteps=1,
- order={ "liga" },
- type="gsub_ligature",
- steps={
- {
- coverage=ligatures,
- },
- },
- }
- end
- if next(kerns) then
- features.gpos.kern=everywhere
- data.properties.haskerns=true
- sequences[#sequences+1]={
- features={
- kern=everywhere,
- },
- flags=noflags,
- name="p_s_0",
- nofsteps=1,
- order={ "kern" },
- type="gpos_pair",
- steps={
- {
- format="kern",
- coverage=kerns,
- },
- },
- }
- end
- if next(extrakerns) then
- features.gpos.extrakerns=everywhere
- data.properties.haskerns=true
- sequences[#sequences+1]={
- features={
- extrakerns=everywhere,
- },
- flags=noflags,
- name="p_s_1",
- nofsteps=1,
- order={ "extrakerns" },
- type="gpos_pair",
- steps={
- {
- format="kern",
- coverage=extrakerns,
- },
- },
- }
- end
- data.resources.features=features
- data.resources.sequences=sequences
-end
-local function enhance_fix_names(data)
- for k,v in next,data.descriptions do
- local n=v.name
- local r=overloads[n]
- if r then
- local name=r.name
- if trace_indexing then
- report_afm("renaming characters %a to %a",n,name)
- end
- v.name=name
- v.unicode=r.unicode
- end
- end
-end
-local addthem=function(rawdata,ligatures)
- if ligatures then
- local descriptions=rawdata.descriptions
- local resources=rawdata.resources
- local unicodes=resources.unicodes
- for ligname,ligdata in next,ligatures do
- local one=descriptions[unicodes[ligname]]
- if one then
- for _,pair in next,ligdata do
- local two,three=unicodes[pair[1]],unicodes[pair[2]]
- if two and three then
- local ol=one.ligatures
- if ol then
- if not ol[two] then
- ol[two]=three
- end
- else
- one.ligatures={ [two]=three }
- end
- end
- end
- end
- end
- end
-end
-local function enhance_add_ligatures(rawdata)
- addthem(rawdata,afm.helpdata.ligatures)
-end
-local function enhance_add_extra_kerns(rawdata)
- local descriptions=rawdata.descriptions
- local resources=rawdata.resources
- local unicodes=resources.unicodes
- local function do_it_left(what)
- if what then
- for unicode,description in next,descriptions do
- local kerns=description.kerns
- if kerns then
- local extrakerns
- for complex,simple in next,what do
- complex=unicodes[complex]
- simple=unicodes[simple]
- if complex and simple then
- local ks=kerns[simple]
- if ks and not kerns[complex] then
- if extrakerns then
- extrakerns[complex]=ks
- else
- extrakerns={ [complex]=ks }
- end
- end
- end
- end
- if extrakerns then
- description.extrakerns=extrakerns
- end
- end
- end
- end
- end
- local function do_it_copy(what)
- if what then
- for complex,simple in next,what do
- complex=unicodes[complex]
- simple=unicodes[simple]
- if complex and simple then
- local complexdescription=descriptions[complex]
- if complexdescription then
- local simpledescription=descriptions[complex]
- if simpledescription then
- local extrakerns
- local kerns=simpledescription.kerns
- if kerns then
- for unicode,kern in next,kerns do
- if extrakerns then
- extrakerns[unicode]=kern
- else
- extrakerns={ [unicode]=kern }
- end
- end
- end
- local extrakerns=simpledescription.extrakerns
- if extrakerns then
- for unicode,kern in next,extrakerns do
- if extrakerns then
- extrakerns[unicode]=kern
- else
- extrakerns={ [unicode]=kern }
- end
- end
- end
- if extrakerns then
- complexdescription.extrakerns=extrakerns
- end
- end
- end
- end
- end
- end
- end
- do_it_left(afm.helpdata.leftkerned)
- do_it_left(afm.helpdata.bothkerned)
- do_it_copy(afm.helpdata.bothkerned)
- do_it_copy(afm.helpdata.rightkerned)
-end
-local function adddimensions(data)
- if data then
- for unicode,description in next,data.descriptions do
- local bb=description.boundingbox
- if bb then
- local ht,dp=bb[4],-bb[2]
- if ht==0 or ht<0 then
- else
- description.height=ht
- end
- if dp==0 or dp<0 then
- else
- description.depth=dp
- end
- end
- end
- end
-end
-local function copytotfm(data)
- if data and data.descriptions then
- local metadata=data.metadata
- local resources=data.resources
- local properties=derivetable(data.properties)
- local descriptions=derivetable(data.descriptions)
- local goodies=derivetable(data.goodies)
- local characters={}
- local parameters={}
- local unicodes=resources.unicodes
- for unicode,description in next,data.descriptions do
- characters[unicode]={}
- end
- local filename=constructors.checkedfilename(resources)
- local fontname=metadata.fontname or metadata.fullname
- local fullname=metadata.fullname or metadata.fontname
- local endash=0x0020
- local emdash=0x2014
- local spacer="space"
- local spaceunits=500
- local monospaced=metadata.monospaced
- local charwidth=metadata.charwidth
- local italicangle=metadata.italicangle
- local charxheight=metadata.xheight and metadata.xheight>0 and metadata.xheight
- properties.monospaced=monospaced
- parameters.italicangle=italicangle
- parameters.charwidth=charwidth
- parameters.charxheight=charxheight
- if properties.monospaced then
- if descriptions[endash] then
- spaceunits,spacer=descriptions[endash].width,"space"
- end
- if not spaceunits and descriptions[emdash] then
- spaceunits,spacer=descriptions[emdash].width,"emdash"
- end
- if not spaceunits and charwidth then
- spaceunits,spacer=charwidth,"charwidth"
- end
- else
- if descriptions[endash] then
- spaceunits,spacer=descriptions[endash].width,"space"
- end
- if not spaceunits and charwidth then
- spaceunits,spacer=charwidth,"charwidth"
- end
- end
- spaceunits=tonumber(spaceunits)
- if spaceunits<200 then
- end
- parameters.slant=0
- parameters.space=spaceunits
- parameters.space_stretch=500
- parameters.space_shrink=333
- parameters.x_height=400
- parameters.quad=1000
- if italicangle and italicangle~=0 then
- parameters.italicangle=italicangle
- parameters.italicfactor=math.cos(math.rad(90+italicangle))
- parameters.slant=- math.tan(italicangle*math.pi/180)
- end
- if monospaced then
- parameters.space_stretch=0
- parameters.space_shrink=0
- elseif afm.syncspace then
- parameters.space_stretch=spaceunits/2
- parameters.space_shrink=spaceunits/3
- end
- parameters.extra_space=parameters.space_shrink
- if charxheight then
- parameters.x_height=charxheight
- else
- local x=0x0078
- if x then
- local x=descriptions[x]
- if x then
- parameters.x_height=x.height
- end
- end
- end
- if metadata.sup then
- local dummy={ 0,0,0 }
- parameters[ 1]=metadata.designsize or 0
- parameters[ 2]=metadata.checksum or 0
- parameters[ 3],
- parameters[ 4],
- parameters[ 5]=unpack(metadata.space or dummy)
- parameters[ 6]=metadata.quad or 0
- parameters[ 7]=metadata.extraspace or 0
- parameters[ 8],
- parameters[ 9],
- parameters[10]=unpack(metadata.num or dummy)
- parameters[11],
- parameters[12]=unpack(metadata.denom or dummy)
- parameters[13],
- parameters[14],
- parameters[15]=unpack(metadata.sup or dummy)
- parameters[16],
- parameters[17]=unpack(metadata.sub or dummy)
- parameters[18]=metadata.supdrop or 0
- parameters[19]=metadata.subdrop or 0
- parameters[20],
- parameters[21]=unpack(metadata.delim or dummy)
- parameters[22]=metadata.axisheight or 0
- end
- parameters.designsize=(metadata.designsize or 10)*65536
- parameters.ascender=abs(metadata.ascender or 0)
- parameters.descender=abs(metadata.descender or 0)
- parameters.units=1000
- properties.spacer=spacer
- properties.encodingbytes=2
- properties.format=fonts.formats[filename] or "type1"
- properties.filename=filename
- properties.fontname=fontname
- properties.fullname=fullname
- properties.psname=fullname
- properties.name=filename or fullname or fontname
- if next(characters) then
- return {
- characters=characters,
- descriptions=descriptions,
- parameters=parameters,
- resources=resources,
- properties=properties,
- goodies=goodies,
- }
- end
- end
- return nil
-end
-function afm.setfeatures(tfmdata,features)
- local okay=constructors.initializefeatures("afm",tfmdata,features,trace_features,report_afm)
- if okay then
- return constructors.collectprocessors("afm",tfmdata,features,trace_features,report_afm)
- else
- return {}
- end
-end
-local function addtables(data)
- local resources=data.resources
- local lookuptags=resources.lookuptags
- local unicodes=resources.unicodes
- if not lookuptags then
- lookuptags={}
- resources.lookuptags=lookuptags
- end
- setmetatableindex(lookuptags,function(t,k)
- local v=type(k)=="number" and ("lookup "..k) or k
- t[k]=v
- return v
- end)
- if not unicodes then
- unicodes={}
- resources.unicodes=unicodes
- setmetatableindex(unicodes,function(t,k)
- setmetatableindex(unicodes,nil)
- for u,d in next,data.descriptions do
- local n=d.name
- if n then
- t[n]=u
- end
- end
- return rawget(t,k)
- end)
- end
- constructors.addcoreunicodes(unicodes)
-end
-local function afmtotfm(specification)
- local afmname=specification.filename or specification.name
- if specification.forced=="afm" or specification.format=="afm" then
- if trace_loading then
- report_afm("forcing afm format for %a",afmname)
- end
- else
- local tfmname=findbinfile(afmname,"ofm") or ""
- if tfmname~="" then
- if trace_loading then
- report_afm("fallback from afm to tfm for %a",afmname)
- end
- return
- end
- end
- if afmname~="" then
- local features=constructors.checkedfeatures("afm",specification.features.normal)
- specification.features.normal=features
- constructors.hashinstance(specification,true)
- specification=definers.resolve(specification)
- local cache_id=specification.hash
- local tfmdata=containers.read(constructors.cache,cache_id)
- if not tfmdata then
- local rawdata=afm.load(afmname)
- if rawdata and next(rawdata) then
- addtables(rawdata)
- adddimensions(rawdata)
- tfmdata=copytotfm(rawdata)
- if tfmdata and next(tfmdata) then
- local shared=tfmdata.shared
- if not shared then
- shared={}
- tfmdata.shared=shared
- end
- shared.rawdata=rawdata
- shared.dynamics={}
- tfmdata.changed={}
- shared.features=features
- shared.processes=afm.setfeatures(tfmdata,features)
- end
- elseif trace_loading then
- report_afm("no (valid) afm file found with name %a",afmname)
- end
- tfmdata=containers.write(constructors.cache,cache_id,tfmdata)
- end
- return tfmdata
- end
-end
-local function read_from_afm(specification)
- local tfmdata=afmtotfm(specification)
- if tfmdata then
- tfmdata.properties.name=specification.name
- tfmdata=constructors.scale(tfmdata,specification)
- local allfeatures=tfmdata.shared.features or specification.features.normal
- constructors.applymanipulators("afm",tfmdata,allfeatures,trace_features,report_afm)
- fonts.loggers.register(tfmdata,'afm',specification)
- end
- return tfmdata
-end
-registerafmfeature {
- name="mode",
- description="mode",
- initializers={
- base=otf.modeinitializer,
- node=otf.modeinitializer,
- }
-}
-registerafmfeature {
- name="features",
- description="features",
- default=true,
- initializers={
- node=otf.nodemodeinitializer,
- base=otf.basemodeinitializer,
- },
- processors={
- node=otf.featuresprocessor,
- }
-}
-fonts.formats.afm="type1"
-fonts.formats.pfb="type1"
-local function check_afm(specification,fullname)
- local foundname=findbinfile(fullname,'afm') or ""
- if foundname=="" then
- foundname=fonts.names.getfilename(fullname,"afm") or ""
- end
- if foundname=="" and afm.autoprefixed then
- local encoding,shortname=match(fullname,"^(.-)%-(.*)$")
- if encoding and shortname and fonts.encodings.known[encoding] then
- shortname=findbinfile(shortname,'afm') or ""
- if shortname~="" then
- foundname=shortname
- if trace_defining then
- report_afm("stripping encoding prefix from filename %a",afmname)
- end
- end
- end
- end
- if foundname~="" then
- specification.filename=foundname
- specification.format="afm"
- return read_from_afm(specification)
- end
-end
-function readers.afm(specification,method)
- local fullname=specification.filename or ""
- local tfmdata=nil
- if fullname=="" then
- local forced=specification.forced or ""
- if forced~="" then
- tfmdata=check_afm(specification,specification.name.."."..forced)
- end
- if not tfmdata then
- local check_tfm=readers.check_tfm
- method=(check_tfm and (method or definers.method or "afm or tfm")) or "afm"
- if method=="tfm" then
- tfmdata=check_tfm(specification,specification.name)
- elseif method=="afm" then
- tfmdata=check_afm(specification,specification.name)
- elseif method=="tfm or afm" then
- tfmdata=check_tfm(specification,specification.name) or check_afm(specification,specification.name)
- else
- tfmdata=check_afm(specification,specification.name) or check_tfm(specification,specification.name)
- end
- end
- else
- tfmdata=check_afm(specification,fullname)
- end
- return tfmdata
-end
-function readers.pfb(specification,method)
- local original=specification.specification
- if trace_defining then
- report_afm("using afm reader for %a",original)
- end
- specification.forced="afm"
- local function swap(name)
- local value=specification[swap]
- if value then
- specification[swap]=gsub("%.pfb",".afm",1)
- end
- end
- swap("filename")
- swap("fullname")
- swap("forcedname")
- swap("specification")
- return readers.afm(specification,method)
-end
-registerafmenhancer("unify names",enhance_unify_names)
-registerafmenhancer("add ligatures",enhance_add_ligatures)
-registerafmenhancer("add extra kerns",enhance_add_extra_kerns)
-registerafmenhancer("normalize features",enhance_normalize_features)
-registerafmenhancer("check extra features",otfenhancers.enhance)
-registerafmenhancer("fix names",enhance_fix_names)
-
-end --- [luaotfload, fontloader-2017-02-11.lua scope for “font-one”] ---
-
-
-do --- [luaotfload, fontloader-2017-02-11.lua scope for “font-afk” b36a76ceb835f41f8c05b471000ddc14] ---
-
-if not modules then modules={} end modules ['font-afk']={
- version=1.001,
- comment="companion to font-afm.lua",
- author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright="PRAGMA ADE / ConTeXt Development Team",
- license="see context related readme files",
- dataonly=true,
-}
-local allocate=utilities.storage.allocate
-fonts.handlers.afm.helpdata={
- ligatures=allocate {
- ['f']={
- { 'f','ff' },
- { 'i','fi' },
- { 'l','fl' },
- },
- ['ff']={
- { 'i','ffi' }
- },
- ['fi']={
- { 'i','fii' }
- },
- ['fl']={
- { 'i','fli' }
- },
- ['s']={
- { 't','st' }
- },
- ['i']={
- { 'j','ij' }
- },
- },
- texligatures=allocate {
- ['quoteleft']={
- { 'quoteleft','quotedblleft' }
- },
- ['quoteright']={
- { 'quoteright','quotedblright' }
- },
- ['hyphen']={
- { 'hyphen','endash' }
- },
- ['endash']={
- { 'hyphen','emdash' }
- }
- },
- leftkerned=allocate {
- AEligature="A",aeligature="a",
- OEligature="O",oeligature="o",
- IJligature="I",ijligature="i",
- AE="A",ae="a",
- OE="O",oe="o",
- IJ="I",ij="i",
- Ssharp="S",ssharp="s",
- },
- rightkerned=allocate {
- AEligature="E",aeligature="e",
- OEligature="E",oeligature="e",
- IJligature="J",ijligature="j",
- AE="E",ae="e",
- OE="E",oe="e",
- IJ="J",ij="j",
- Ssharp="S",ssharp="s",
- },
- bothkerned=allocate {
- Acircumflex="A",acircumflex="a",
- Ccircumflex="C",ccircumflex="c",
- Ecircumflex="E",ecircumflex="e",
- Gcircumflex="G",gcircumflex="g",
- Hcircumflex="H",hcircumflex="h",
- Icircumflex="I",icircumflex="i",
- Jcircumflex="J",jcircumflex="j",
- Ocircumflex="O",ocircumflex="o",
- Scircumflex="S",scircumflex="s",
- Ucircumflex="U",ucircumflex="u",
- Wcircumflex="W",wcircumflex="w",
- Ycircumflex="Y",ycircumflex="y",
- Agrave="A",agrave="a",
- Egrave="E",egrave="e",
- Igrave="I",igrave="i",
- Ograve="O",ograve="o",
- Ugrave="U",ugrave="u",
- Ygrave="Y",ygrave="y",
- Atilde="A",atilde="a",
- Itilde="I",itilde="i",
- Otilde="O",otilde="o",
- Utilde="U",utilde="u",
- Ntilde="N",ntilde="n",
- Adiaeresis="A",adiaeresis="a",Adieresis="A",adieresis="a",
- Ediaeresis="E",ediaeresis="e",Edieresis="E",edieresis="e",
- Idiaeresis="I",idiaeresis="i",Idieresis="I",idieresis="i",
- Odiaeresis="O",odiaeresis="o",Odieresis="O",odieresis="o",
- Udiaeresis="U",udiaeresis="u",Udieresis="U",udieresis="u",
- Ydiaeresis="Y",ydiaeresis="y",Ydieresis="Y",ydieresis="y",
- Aacute="A",aacute="a",
- Cacute="C",cacute="c",
- Eacute="E",eacute="e",
- Iacute="I",iacute="i",
- Lacute="L",lacute="l",
- Nacute="N",nacute="n",
- Oacute="O",oacute="o",
- Racute="R",racute="r",
- Sacute="S",sacute="s",
- Uacute="U",uacute="u",
- Yacute="Y",yacute="y",
- Zacute="Z",zacute="z",
- Dstroke="D",dstroke="d",
- Hstroke="H",hstroke="h",
- Tstroke="T",tstroke="t",
- Cdotaccent="C",cdotaccent="c",
- Edotaccent="E",edotaccent="e",
- Gdotaccent="G",gdotaccent="g",
- Idotaccent="I",idotaccent="i",
- Zdotaccent="Z",zdotaccent="z",
- Amacron="A",amacron="a",
- Emacron="E",emacron="e",
- Imacron="I",imacron="i",
- Omacron="O",omacron="o",
- Umacron="U",umacron="u",
- Ccedilla="C",ccedilla="c",
- Kcedilla="K",kcedilla="k",
- Lcedilla="L",lcedilla="l",
- Ncedilla="N",ncedilla="n",
- Rcedilla="R",rcedilla="r",
- Scedilla="S",scedilla="s",
- Tcedilla="T",tcedilla="t",
- Ohungarumlaut="O",ohungarumlaut="o",
- Uhungarumlaut="U",uhungarumlaut="u",
- Aogonek="A",aogonek="a",
- Eogonek="E",eogonek="e",
- Iogonek="I",iogonek="i",
- Uogonek="U",uogonek="u",
- Aring="A",aring="a",
- Uring="U",uring="u",
- Abreve="A",abreve="a",
- Ebreve="E",ebreve="e",
- Gbreve="G",gbreve="g",
- Ibreve="I",ibreve="i",
- Obreve="O",obreve="o",
- Ubreve="U",ubreve="u",
- Ccaron="C",ccaron="c",
- Dcaron="D",dcaron="d",
- Ecaron="E",ecaron="e",
- Lcaron="L",lcaron="l",
- Ncaron="N",ncaron="n",
- Rcaron="R",rcaron="r",
- Scaron="S",scaron="s",
- Tcaron="T",tcaron="t",
- Zcaron="Z",zcaron="z",
- dotlessI="I",dotlessi="i",
- dotlessJ="J",dotlessj="j",
- AEligature="AE",aeligature="ae",AE="AE",ae="ae",
- OEligature="OE",oeligature="oe",OE="OE",oe="oe",
- IJligature="IJ",ijligature="ij",IJ="IJ",ij="ij",
- Lstroke="L",lstroke="l",Lslash="L",lslash="l",
- Ostroke="O",ostroke="o",Oslash="O",oslash="o",
- Ssharp="SS",ssharp="ss",
- Aumlaut="A",aumlaut="a",
- Eumlaut="E",eumlaut="e",
- Iumlaut="I",iumlaut="i",
- Oumlaut="O",oumlaut="o",
- Uumlaut="U",uumlaut="u",
- }
-}
-
-end --- [luaotfload, fontloader-2017-02-11.lua scope for “font-afk”] ---
-
-
-do --- [luaotfload, fontloader-2017-02-11.lua scope for “font-tfm” 3d813578dbf6c447e4b859c2bf0618f7] ---
-
-if not modules then modules={} end modules ['font-tfm']={
- version=1.001,
- comment="companion to font-ini.mkiv",
- author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright="PRAGMA ADE / ConTeXt Development Team",
- license="see context related readme files"
-}
-local next,type=next,type
-local match,format=string.match,string.format
-local concat,sortedhash=table.concat,table.sortedhash
-local trace_defining=false trackers.register("fonts.defining",function(v) trace_defining=v end)
-local trace_features=false trackers.register("tfm.features",function(v) trace_features=v end)
-local report_defining=logs.reporter("fonts","defining")
-local report_tfm=logs.reporter("fonts","tfm loading")
-local findbinfile=resolvers.findbinfile
-local setmetatableindex=table.setmetatableindex
-local fonts=fonts
-local handlers=fonts.handlers
-local readers=fonts.readers
-local constructors=fonts.constructors
-local encodings=fonts.encodings
-local tfm=constructors.handlers.tfm
-tfm.version=1.000
-tfm.maxnestingdepth=5
-tfm.maxnestingsize=65536*1024
-local otf=fonts.handlers.otf
-local otfenhancers=otf.enhancers
-local tfmfeatures=constructors.features.tfm
-local registertfmfeature=tfmfeatures.register
-local tfmenhancers=constructors.enhancers.tfm
-local registertfmenhancer=tfmenhancers.register
-constructors.resolvevirtualtoo=false
-fonts.formats.tfm="type1"
-fonts.formats.ofm="type1"
-function tfm.setfeatures(tfmdata,features)
- local okay=constructors.initializefeatures("tfm",tfmdata,features,trace_features,report_tfm)
- if okay then
- return constructors.collectprocessors("tfm",tfmdata,features,trace_features,report_tfm)
- else
- return {}
- end
-end
-local depth={}
-local function read_from_tfm(specification)
- local filename=specification.filename
- local size=specification.size
- depth[filename]=(depth[filename] or 0)+1
- if trace_defining then
- report_defining("loading tfm file %a at size %s",filename,size)
- end
- local tfmdata=font.read_tfm(filename,size)
- if tfmdata then
- local features=specification.features and specification.features.normal or {}
- local features=constructors.checkedfeatures("tfm",features)
- specification.features.normal=features
- local newtfmdata=(depth[filename]==1) and tfm.reencode(tfmdata,specification)
- if newtfmdata then
- tfmdata=newtfmdata
- end
- local resources=tfmdata.resources or {}
- local properties=tfmdata.properties or {}
- local parameters=tfmdata.parameters or {}
- local shared=tfmdata.shared or {}
- shared.features=features
- shared.resources=resources
- properties.name=tfmdata.name
- properties.fontname=tfmdata.fontname
- properties.psname=tfmdata.psname
- properties.fullname=tfmdata.fullname
- properties.filename=specification.filename
- properties.format=fonts.formats.tfm
- tfmdata.properties=properties
- tfmdata.resources=resources
- tfmdata.parameters=parameters
- tfmdata.shared=shared
- shared.rawdata={ resources=resources }
- shared.features=features
- if newtfmdata then
- if not resources.marks then
- resources.marks={}
- end
- if not resources.sequences then
- resources.sequences={}
- end
- if not resources.features then
- resources.features={
- gsub={},
- gpos={},
- }
- end
- if not tfmdata.changed then
- tfmdata.changed={}
- end
- if not tfmdata.descriptions then
- tfmdata.descriptions=tfmdata.characters
- end
- otf.readers.addunicodetable(tfmdata)
- tfmenhancers.apply(tfmdata,filename)
- constructors.applymanipulators("tfm",tfmdata,features,trace_features,report_tfm)
- otf.readers.unifymissing(tfmdata)
- fonts.mappings.addtounicode(tfmdata,filename)
- tfmdata.tounicode=1
- local tounicode=fonts.mappings.tounicode
- for unicode,v in next,tfmdata.characters do
- local u=v.unicode
- if u then
- v.tounicode=tounicode(u)
- end
- end
- if tfmdata.usedbitmap then
- tfm.addtounicode(tfmdata)
- end
- end
- shared.processes=next(features) and tfm.setfeatures(tfmdata,features) or nil
- parameters.factor=1
- parameters.size=size
- parameters.slant=parameters.slant or parameters[1] or 0
- parameters.space=parameters.space or parameters[2] or 0
- parameters.space_stretch=parameters.space_stretch or parameters[3] or 0
- parameters.space_shrink=parameters.space_shrink or parameters[4] or 0
- parameters.x_height=parameters.x_height or parameters[5] or 0
- parameters.quad=parameters.quad or parameters[6] or 0
- parameters.extra_space=parameters.extra_space or parameters[7] or 0
- constructors.enhanceparameters(parameters)
- if newtfmdata then
- elseif constructors.resolvevirtualtoo then
- fonts.loggers.register(tfmdata,file.suffix(filename),specification)
- local vfname=findbinfile(specification.name,'ovf')
- if vfname and vfname~="" then
- local vfdata=font.read_vf(vfname,size)
- if vfdata then
- local chars=tfmdata.characters
- for k,v in next,vfdata.characters do
- chars[k].commands=v.commands
- end
- properties.virtualized=true
- tfmdata.fonts=vfdata.fonts
- tfmdata.type="virtual"
- local fontlist=vfdata.fonts
- local name=file.nameonly(filename)
- for i=1,#fontlist do
- local n=fontlist[i].name
- local s=fontlist[i].size
- local d=depth[filename]
- s=constructors.scaled(s,vfdata.designsize)
- if d>tfm.maxnestingdepth then
- report_defining("too deeply nested virtual font %a with size %a, max nesting depth %s",n,s,tfm.maxnestingdepth)
- fontlist[i]={ id=0 }
- elseif (d>1) and (s>tfm.maxnestingsize) then
- report_defining("virtual font %a exceeds size %s",n,s)
- fontlist[i]={ id=0 }
- else
- local t,id=fonts.constructors.readanddefine(n,s)
- fontlist[i]={ id=id }
- end
- end
- end
- end
- end
- properties.haskerns=true
- properties.hasligatures=true
- resources.unicodes={}
- resources.lookuptags={}
- depth[filename]=depth[filename]-1
- return tfmdata
- else
- depth[filename]=depth[filename]-1
- end
-end
-local function check_tfm(specification,fullname)
- local foundname=findbinfile(fullname,'tfm') or ""
- if foundname=="" then
- foundname=findbinfile(fullname,'ofm') or ""
- end
- if foundname=="" then
- foundname=fonts.names.getfilename(fullname,"tfm") or ""
- end
- if foundname~="" then
- specification.filename=foundname
- specification.format="ofm"
- return read_from_tfm(specification)
- elseif trace_defining then
- report_defining("loading tfm with name %a fails",specification.name)
- end
-end
-readers.check_tfm=check_tfm
-function readers.tfm(specification)
- local fullname=specification.filename or ""
- if fullname=="" then
- local forced=specification.forced or ""
- if forced~="" then
- fullname=specification.name.."."..forced
- else
- fullname=specification.name
- end
- end
- return check_tfm(specification,fullname)
-end
-readers.ofm=readers.tfm
-do
- local outfiles={}
- local tfmcache=table.setmetatableindex(function(t,tfmdata)
- local id=font.define(tfmdata)
- t[tfmdata]=id
- return id
- end)
- local encdone=table.setmetatableindex("table")
- function tfm.reencode(tfmdata,specification)
- local features=specification.features
- if not features then
- return
- end
- local features=features.normal
- if not features then
- return
- end
- local tfmfile=file.basename(tfmdata.name)
- local encfile=features.reencode
- local pfbfile=features.pfbfile
- local bitmap=features.bitmap
- if not encfile then
- return
- end
- local pfbfile=outfiles[tfmfile]
- if pfbfile==nil then
- if bitmap then
- pfbfile=false
- elseif type(pfbfile)~="string" then
- pfbfile=tfmfile
- end
- if type(pfbfile)=="string" then
- pfbfile=file.addsuffix(pfbfile,"pfb")
- report_tfm("using type1 shapes from %a for %a",pfbfile,tfmfile)
- else
- report_tfm("using bitmap shapes for %a",tfmfile)
- pfbfile=false
- end
- outfiles[tfmfile]=pfbfile
- end
- local encoding=false
- local vector=false
- if type(pfbfile)=="string" then
- local pfb=fonts.constructors.handlers.pfb
- if pfb and pfb.loadvector then
- local v,e=pfb.loadvector(pfbfile)
- if v then
- vector=v
- end
- if e then
- encoding=e
- end
- end
- end
- if type(encfile)=="string" and encfile~="auto" then
- encoding=fonts.encodings.load(file.addsuffix(encfile,"enc"))
- if encoding then
- encoding=encoding.vector
- end
- end
- if not encoding then
- report_tfm("bad encoding for %a, quitting",tfmfile)
- return
- end
- local unicoding=fonts.encodings.agl and fonts.encodings.agl.unicodes
- local virtualid=tfmcache[tfmdata]
- local tfmdata=table.copy(tfmdata)
- local characters={}
- local originals=tfmdata.characters
- local indices={}
- local parentfont={ "font",1 }
- local private=fonts.constructors.privateoffset
- local reported=encdone[tfmfile][encfile]
- local backmap=vector and table.swapped(vector)
- local done={}
- for index,name in sortedhash(encoding) do
- local unicode=unicoding[name]
- local original=originals[index]
- if original then
- if unicode then
- original.unicode=unicode
- else
- unicode=private
- private=private+1
- if not reported then
- report_tfm("glyph %a in font %a with encoding %a gets unicode %U",name,tfmfile,encfile,unicode)
- end
- end
- characters[unicode]=original
- indices[index]=unicode
- original.name=name
- if backmap then
- original.index=backmap[name]
- else
- original.commands={ parentfont,{ "char",index } }
- original.oindex=index
- end
- done[name]=true
- elseif not done[name] then
- report_tfm("bad index %a in font %a with name %a",index,tfmfile,name)
- end
- end
- encdone[tfmfile][encfile]=true
- for k,v in next,characters do
- local kerns=v.kerns
- if kerns then
- local t={}
- for k,v in next,kerns do
- local i=indices[k]
- if i then
- t[i]=v
- end
- end
- v.kerns=next(t) and t or nil
- end
- local ligatures=v.ligatures
- if ligatures then
- local t={}
- for k,v in next,ligatures do
- local i=indices[k]
- if i then
- t[i]=v
- v.char=indices[v.char]
- end
- end
- v.ligatures=next(t) and t or nil
- end
- end
- tfmdata.fonts={ { id=virtualid } }
- tfmdata.characters=characters
- tfmdata.fullname=tfmdata.fullname or tfmdata.name
- tfmdata.psname=file.nameonly(pfbfile or tfmdata.name)
- tfmdata.filename=pfbfile
- tfmdata.encodingbytes=2
- tfmdata.format="type1"
- tfmdata.tounicode=1
- tfmdata.embedding="subset"
- tfmdata.usedbitmap=bitmap and virtualid
- return tfmdata
- end
-end
-do
- local template=[[
-/CIDInit /ProcSet findresource begin
- 12 dict begin
- begincmap
- /CIDSystemInfo << /Registry (TeX) /Ordering (bitmap-%s) /Supplement 0 >> def
- /CMapName /TeX-bitmap-%s def
- /CMapType 2 def
- 1 begincodespacerange
- <00> <FF>
- endcodespacerange
- %s beginbfchar
-%s
- endbfchar
- endcmap
-CMapName currentdict /CMap defineresource pop end
-end
-end
-]]
- local flushstreamobject=lpdf and lpdf.flushstreamobject
- local setfontattributes=pdf.setfontattributes
- if not flushstreamobject then
- flushstreamobject=function(data)
- return pdf.obj {
- immediate=true,
- type="stream",
- string=data,
- }
- end
- end
- if not setfontattributes then
- setfontattributes=function(id,data)
- print(format("your luatex is too old so no tounicode bitmap font%i",id))
- end
- end
- function tfm.addtounicode(tfmdata)
- local id=tfmdata.usedbitmap
- local map={}
- local char={}
- for k,v in next,tfmdata.characters do
- local index=v.oindex
- local tounicode=v.tounicode
- if index and tounicode then
- map[index]=tounicode
- end
- end
- for k,v in sortedhash(map) do
- char[#char+1]=format("<%02X> <%s>",k,v)
- end
- char=concat(char,"\n")
- local stream=format(template,id,id,#char,char)
- local reference=flushstreamobject(stream,nil,true)
- setfontattributes(id,format("/ToUnicode %i 0 R",reference))
- end
-end
-do
- local everywhere={ ["*"]={ ["*"]=true } }
- local noflags={ false,false,false,false }
- local function enhance_normalize_features(data)
- local ligatures=setmetatableindex("table")
- local kerns=setmetatableindex("table")
- local characters=data.characters
- for u,c in next,characters do
- local l=c.ligatures
- local k=c.kerns
- if l then
- ligatures[u]=l
- for u,v in next,l do
- l[u]={ ligature=v.char }
- end
- c.ligatures=nil
- end
- if k then
- kerns[u]=k
- for u,v in next,k do
- k[u]=v
- end
- c.kerns=nil
- end
- end
- for u,l in next,ligatures do
- for k,v in next,l do
- local vl=v.ligature
- local dl=ligatures[vl]
- if dl then
- for kk,vv in next,dl do
- v[kk]=vv
- end
- end
- end
- end
- local features={
- gpos={},
- gsub={},
- }
- local sequences={
- }
- if next(ligatures) then
- features.gsub.liga=everywhere
- data.properties.hasligatures=true
- sequences[#sequences+1]={
- features={
- liga=everywhere,
- },
- flags=noflags,
- name="s_s_0",
- nofsteps=1,
- order={ "liga" },
- type="gsub_ligature",
- steps={
- {
- coverage=ligatures,
- },
- },
- }
- end
- if next(kerns) then
- features.gpos.kern=everywhere
- data.properties.haskerns=true
- sequences[#sequences+1]={
- features={
- kern=everywhere,
- },
- flags=noflags,
- name="p_s_0",
- nofsteps=1,
- order={ "kern" },
- type="gpos_pair",
- steps={
- {
- format="kern",
- coverage=kerns,
- },
- },
- }
- end
- data.resources.features=features
- data.resources.sequences=sequences
- data.shared.resources=data.shared.resources or resources
- end
- registertfmenhancer("normalize features",enhance_normalize_features)
- registertfmenhancer("check extra features",otfenhancers.enhance)
-end
-registertfmfeature {
- name="mode",
- description="mode",
- initializers={
- base=otf.modeinitializer,
- node=otf.modeinitializer,
- }
-}
-registertfmfeature {
- name="features",
- description="features",
- default=true,
- initializers={
- base=otf.basemodeinitializer,
- node=otf.nodemodeinitializer,
- },
- processors={
- node=otf.featuresprocessor,
- }
-}
-
-end --- [luaotfload, fontloader-2017-02-11.lua scope for “font-tfm”] ---
-
-
-do --- [luaotfload, fontloader-2017-02-11.lua scope for “font-lua” 1fbfdf7b689b2bdfd0e3bb9bf74ce136] ---
-
-if not modules then modules={} end modules ['font-lua']={
- version=1.001,
- comment="companion to font-ini.mkiv",
- author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright="PRAGMA ADE / ConTeXt Development Team",
- license="see context related readme files"
-}
-local trace_defining=false trackers.register("fonts.defining",function(v) trace_defining=v end)
-local report_lua=logs.reporter("fonts","lua loading")
-local fonts=fonts
-local readers=fonts.readers
-fonts.formats.lua="lua"
-local function check_lua(specification,fullname)
- local fullname=resolvers.findfile(fullname) or ""
- if fullname~="" then
- local loader=loadfile(fullname)
- loader=loader and loader()
- return loader and loader(specification)
- end
-end
-readers.check_lua=check_lua
-function readers.lua(specification)
- local original=specification.specification
- if trace_defining then
- report_lua("using lua reader for %a",original)
- end
- local fullname=specification.filename or ""
- if fullname=="" then
- local forced=specification.forced or ""
- if forced~="" then
- fullname=specification.name.."."..forced
- else
- fullname=specification.name
- end
- end
- return check_lua(specification,fullname)
-end
-
-end --- [luaotfload, fontloader-2017-02-11.lua scope for “font-lua”] ---
-
-
-do --- [luaotfload, fontloader-2017-02-11.lua scope for “font-def” 49fa2b50d8d2a1bb70b08b72f858ecd0] ---
-
-if not modules then modules={} end modules ['font-def']={
- version=1.001,
- comment="companion to font-ini.mkiv",
- author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright="PRAGMA ADE / ConTeXt Development Team",
- license="see context related readme files"
-}
-local lower,gsub=string.lower,string.gsub
-local tostring,next=tostring,next
-local lpegmatch=lpeg.match
-local suffixonly,removesuffix=file.suffix,file.removesuffix
-local formatters=string.formatters
-local allocate=utilities.storage.allocate
-local trace_defining=false trackers .register("fonts.defining",function(v) trace_defining=v end)
-local directive_embedall=false directives.register("fonts.embedall",function(v) directive_embedall=v end)
-trackers.register("fonts.loading","fonts.defining","otf.loading","afm.loading","tfm.loading")
-trackers.register("fonts.all","fonts.*","otf.*","afm.*","tfm.*")
-local report_defining=logs.reporter("fonts","defining")
-local fonts=fonts
-local fontdata=fonts.hashes.identifiers
-local readers=fonts.readers
-local definers=fonts.definers
-local specifiers=fonts.specifiers
-local constructors=fonts.constructors
-local fontgoodies=fonts.goodies
-readers.sequence=allocate { 'otf','ttf','afm','tfm','lua' }
-local variants=allocate()
-specifiers.variants=variants
-definers.methods=definers.methods or {}
-local internalized=allocate()
-local lastdefined=nil
-local loadedfonts=constructors.loadedfonts
-local designsizes=constructors.designsizes
-local resolvefile=fontgoodies and fontgoodies.filenames and fontgoodies.filenames.resolve or function(s) return s end
-local splitter,splitspecifiers=nil,""
-local P,C,S,Cc=lpeg.P,lpeg.C,lpeg.S,lpeg.Cc
-local left=P("(")
-local right=P(")")
-local colon=P(":")
-local space=P(" ")
-definers.defaultlookup="file"
-local prefixpattern=P(false)
-local function addspecifier(symbol)
- splitspecifiers=splitspecifiers..symbol
- local method=S(splitspecifiers)
- local lookup=C(prefixpattern)*colon
- local sub=left*C(P(1-left-right-method)^1)*right
- local specification=C(method)*C(P(1)^1)
- local name=C((1-sub-specification)^1)
- splitter=P((lookup+Cc(""))*name*(sub+Cc(""))*(specification+Cc("")))
-end
-local function addlookup(str,default)
- prefixpattern=prefixpattern+P(str)
-end
-definers.addlookup=addlookup
-addlookup("file")
-addlookup("name")
-addlookup("spec")
-local function getspecification(str)
- return lpegmatch(splitter,str or "")
-end
-definers.getspecification=getspecification
-function definers.registersplit(symbol,action,verbosename)
- addspecifier(symbol)
- variants[symbol]=action
- if verbosename then
- variants[verbosename]=action
- end
-end
-local function makespecification(specification,lookup,name,sub,method,detail,size)
- size=size or 655360
- if not lookup or lookup=="" then
- lookup=definers.defaultlookup
- end
- if trace_defining then
- report_defining("specification %a, lookup %a, name %a, sub %a, method %a, detail %a",
- specification,lookup,name,sub,method,detail)
- end
- local t={
- lookup=lookup,
- specification=specification,
- size=size,
- name=name,
- sub=sub,
- method=method,
- detail=detail,
- resolved="",
- forced="",
- features={},
- }
- return t
-end
-definers.makespecification=makespecification
-function definers.analyze(specification,size)
- local lookup,name,sub,method,detail=getspecification(specification or "")
- return makespecification(specification,lookup,name,sub,method,detail,size)
-end
-definers.resolvers=definers.resolvers or {}
-local resolvers=definers.resolvers
-function resolvers.file(specification)
- local name=resolvefile(specification.name)
- local suffix=lower(suffixonly(name))
- if fonts.formats[suffix] then
- specification.forced=suffix
- specification.forcedname=name
- specification.name=removesuffix(name)
- else
- specification.name=name
- end
-end
-function resolvers.name(specification)
- local resolve=fonts.names.resolve
- if resolve then
- local resolved,sub,subindex=resolve(specification.name,specification.sub,specification)
- if resolved then
- specification.resolved=resolved
- specification.sub=sub
- specification.subindex=subindex
- local suffix=lower(suffixonly(resolved))
- if fonts.formats[suffix] then
- specification.forced=suffix
- specification.forcedname=resolved
- specification.name=removesuffix(resolved)
- else
- specification.name=resolved
- end
- end
- else
- resolvers.file(specification)
- end
-end
-function resolvers.spec(specification)
- local resolvespec=fonts.names.resolvespec
- if resolvespec then
- local resolved,sub,subindex=resolvespec(specification.name,specification.sub,specification)
- if resolved then
- specification.resolved=resolved
- specification.sub=sub
- specification.subindex=subindex
- specification.forced=lower(suffixonly(resolved))
- specification.forcedname=resolved
- specification.name=removesuffix(resolved)
- end
- else
- resolvers.name(specification)
- end
-end
-function definers.resolve(specification)
- if not specification.resolved or specification.resolved=="" then
- local r=resolvers[specification.lookup]
- if r then
- r(specification)
- end
- end
- if specification.forced=="" then
- specification.forced=nil
- specification.forcedname=nil
- end
- specification.hash=lower(specification.name..' @ '..constructors.hashfeatures(specification))
- if specification.sub and specification.sub~="" then
- specification.hash=specification.sub..' @ '..specification.hash
- end
- return specification
-end
-function definers.applypostprocessors(tfmdata)
- local postprocessors=tfmdata.postprocessors
- if postprocessors then
- local properties=tfmdata.properties
- for i=1,#postprocessors do
- local extrahash=postprocessors[i](tfmdata)
- if type(extrahash)=="string" and extrahash~="" then
- extrahash=gsub(lower(extrahash),"[^a-z]","-")
- properties.fullname=formatters["%s-%s"](properties.fullname,extrahash)
- end
- end
- end
- return tfmdata
-end
-local function checkembedding(tfmdata)
- local properties=tfmdata.properties
- local embedding
- if directive_embedall then
- embedding="full"
- elseif properties and properties.filename and constructors.dontembed[properties.filename] then
- embedding="no"
- else
- embedding="subset"
- end
- if properties then
- properties.embedding=embedding
- else
- tfmdata.properties={ embedding=embedding }
- end
- tfmdata.embedding=embedding
-end
-function definers.loadfont(specification)
- local hash=constructors.hashinstance(specification)
- local tfmdata=loadedfonts[hash]
- if not tfmdata then
- local forced=specification.forced or ""
- if forced~="" then
- local reader=readers[lower(forced)]
- tfmdata=reader and reader(specification)
- if not tfmdata then
- report_defining("forced type %a of %a not found",forced,specification.name)
- end
- else
- local sequence=readers.sequence
- for s=1,#sequence do
- local reader=sequence[s]
- if readers[reader] then
- if trace_defining then
- report_defining("trying (reader sequence driven) type %a for %a with file %a",reader,specification.name,specification.filename)
- end
- tfmdata=readers[reader](specification)
- if tfmdata then
- break
- else
- specification.filename=nil
- end
- end
- end
- end
- if tfmdata then
- tfmdata=definers.applypostprocessors(tfmdata)
- checkembedding(tfmdata)
- loadedfonts[hash]=tfmdata
- designsizes[specification.hash]=tfmdata.parameters.designsize
- end
- end
- if not tfmdata then
- report_defining("font with asked name %a is not found using lookup %a",specification.name,specification.lookup)
- end
- return tfmdata
-end
-function constructors.checkvirtualids()
-end
-function constructors.readanddefine(name,size)
- local specification=definers.analyze(name,size)
- local method=specification.method
- if method and variants[method] then
- specification=variants[method](specification)
- end
- specification=definers.resolve(specification)
- local hash=constructors.hashinstance(specification)
- local id=definers.registered(hash)
- if not id then
- local tfmdata=definers.loadfont(specification)
- if tfmdata then
- tfmdata.properties.hash=hash
- constructors.checkvirtualids(tfmdata)
- id=font.define(tfmdata)
- definers.register(tfmdata,id)
- else
- id=0
- end
- end
- return fontdata[id],id
-end
-function definers.current()
- return lastdefined
-end
-function definers.registered(hash)
- local id=internalized[hash]
- return id,id and fontdata[id]
-end
-function definers.register(tfmdata,id)
- if tfmdata and id then
- local hash=tfmdata.properties.hash
- if not hash then
- report_defining("registering font, id %a, name %a, invalid hash",id,tfmdata.properties.filename or "?")
- elseif not internalized[hash] then
- internalized[hash]=id
- if trace_defining then
- report_defining("registering font, id %s, hash %a",id,hash)
- end
- fontdata[id]=tfmdata
- end
- end
-end
-function definers.read(specification,size,id)
- statistics.starttiming(fonts)
- if type(specification)=="string" then
- specification=definers.analyze(specification,size)
- end
- local method=specification.method
- if method and variants[method] then
- specification=variants[method](specification)
- end
- specification=definers.resolve(specification)
- local hash=constructors.hashinstance(specification)
- local tfmdata=definers.registered(hash)
- if tfmdata then
- if trace_defining then
- report_defining("already hashed: %s",hash)
- end
- else
- tfmdata=definers.loadfont(specification)
- if tfmdata then
- if trace_defining then
- report_defining("loaded and hashed: %s",hash)
- end
- tfmdata.properties.hash=hash
- if id then
- definers.register(tfmdata,id)
- end
- else
- if trace_defining then
- report_defining("not loaded and hashed: %s",hash)
- end
- end
- end
- lastdefined=tfmdata or id
- if not tfmdata then
- report_defining("unknown font %a, loading aborted",specification.name)
- elseif trace_defining and type(tfmdata)=="table" then
- local properties=tfmdata.properties or {}
- local parameters=tfmdata.parameters or {}
- report_defining("using %a font with id %a, name %a, size %a, bytes %a, encoding %a, fullname %a, filename %a",
- properties.format or "unknown",id,properties.name,parameters.size,properties.encodingbytes,
- properties.encodingname,properties.fullname,file.basename(properties.filename))
- end
- statistics.stoptiming(fonts)
- return tfmdata
-end
-function font.getfont(id)
- return fontdata[id]
-end
-callbacks.register('define_font',definers.read,"definition of fonts (tfmdata preparation)")
-
-end --- [luaotfload, fontloader-2017-02-11.lua scope for “font-def”] ---
-
-
-do --- [luaotfload, fontloader-2017-02-11.lua scope for “fonts-ext” aff3846f4c1f15de0a9f4fd7081e0c68] ---
-
-if not modules then modules={} end modules ['luatex-fonts-ext']={
- version=1.001,
- comment="companion to luatex-*.tex",
- author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright="PRAGMA ADE / ConTeXt Development Team",
- license="see context related readme files"
-}
-if context then
- texio.write_nl("fatal error: this module is not for context")
- os.exit()
-end
-local fonts=fonts
-local otffeatures=fonts.constructors.features.otf
-local function initializeitlc(tfmdata,value)
- if value then
- local parameters=tfmdata.parameters
- local italicangle=parameters.italicangle
- if italicangle and italicangle~=0 then
- local properties=tfmdata.properties
- local factor=tonumber(value) or 1
- properties.hasitalics=true
- properties.autoitalicamount=factor*(parameters.uwidth or 40)/2
- end
- end
-end
-otffeatures.register {
- name="itlc",
- description="italic correction",
- initializers={
- base=initializeitlc,
- node=initializeitlc,
- }
-}
-local function initializeslant(tfmdata,value)
- value=tonumber(value)
- if not value then
- value=0
- elseif value>1 then
- value=1
- elseif value<-1 then
- value=-1
- end
- tfmdata.parameters.slantfactor=value
-end
-otffeatures.register {
- name="slant",
- description="slant glyphs",
- initializers={
- base=initializeslant,
- node=initializeslant,
- }
-}
-local function initializeextend(tfmdata,value)
- value=tonumber(value)
- if not value then
- value=0
- elseif value>10 then
- value=10
- elseif value<-10 then
- value=-10
- end
- tfmdata.parameters.extendfactor=value
-end
-otffeatures.register {
- name="extend",
- description="scale glyphs horizontally",
- initializers={
- base=initializeextend,
- node=initializeextend,
- }
-}
-fonts.protrusions=fonts.protrusions or {}
-fonts.protrusions.setups=fonts.protrusions.setups or {}
-local setups=fonts.protrusions.setups
-local function initializeprotrusion(tfmdata,value)
- if value then
- local setup=setups[value]
- if setup then
- local factor,left,right=setup.factor or 1,setup.left or 1,setup.right or 1
- local emwidth=tfmdata.parameters.quad
- tfmdata.parameters.protrusion={
- auto=true,
- }
- for i,chr in next,tfmdata.characters do
- local v,pl,pr=setup[i],nil,nil
- if v then
- pl,pr=v[1],v[2]
- end
- if pl and pl~=0 then chr.left_protruding=left*pl*factor end
- if pr and pr~=0 then chr.right_protruding=right*pr*factor end
- end
- end
- end
-end
-otffeatures.register {
- name="protrusion",
- description="shift characters into the left and or right margin",
- initializers={
- base=initializeprotrusion,
- node=initializeprotrusion,
- }
-}
-fonts.expansions=fonts.expansions or {}
-fonts.expansions.setups=fonts.expansions.setups or {}
-local setups=fonts.expansions.setups
-local function initializeexpansion(tfmdata,value)
- if value then
- local setup=setups[value]
- if setup then
- local factor=setup.factor or 1
- tfmdata.parameters.expansion={
- stretch=10*(setup.stretch or 0),
- shrink=10*(setup.shrink or 0),
- step=10*(setup.step or 0),
- auto=true,
- }
- for i,chr in next,tfmdata.characters do
- local v=setup[i]
- if v and v~=0 then
- chr.expansion_factor=v*factor
- else
- chr.expansion_factor=factor
- end
- end
- end
- end
-end
-otffeatures.register {
- name="expansion",
- description="apply hz optimization",
- initializers={
- base=initializeexpansion,
- node=initializeexpansion,
- }
-}
-function fonts.loggers.onetimemessage() end
-local byte=string.byte
-fonts.expansions.setups['default']={
- stretch=2,shrink=2,step=.5,factor=1,
- [byte('A')]=0.5,[byte('B')]=0.7,[byte('C')]=0.7,[byte('D')]=0.5,[byte('E')]=0.7,
- [byte('F')]=0.7,[byte('G')]=0.5,[byte('H')]=0.7,[byte('K')]=0.7,[byte('M')]=0.7,
- [byte('N')]=0.7,[byte('O')]=0.5,[byte('P')]=0.7,[byte('Q')]=0.5,[byte('R')]=0.7,
- [byte('S')]=0.7,[byte('U')]=0.7,[byte('W')]=0.7,[byte('Z')]=0.7,
- [byte('a')]=0.7,[byte('b')]=0.7,[byte('c')]=0.7,[byte('d')]=0.7,[byte('e')]=0.7,
- [byte('g')]=0.7,[byte('h')]=0.7,[byte('k')]=0.7,[byte('m')]=0.7,[byte('n')]=0.7,
- [byte('o')]=0.7,[byte('p')]=0.7,[byte('q')]=0.7,[byte('s')]=0.7,[byte('u')]=0.7,
- [byte('w')]=0.7,[byte('z')]=0.7,
- [byte('2')]=0.7,[byte('3')]=0.7,[byte('6')]=0.7,[byte('8')]=0.7,[byte('9')]=0.7,
-}
-fonts.protrusions.setups['default']={
- factor=1,left=1,right=1,
- [0x002C]={ 0,1 },
- [0x002E]={ 0,1 },
- [0x003A]={ 0,1 },
- [0x003B]={ 0,1 },
- [0x002D]={ 0,1 },
- [0x2013]={ 0,0.50 },
- [0x2014]={ 0,0.33 },
- [0x3001]={ 0,1 },
- [0x3002]={ 0,1 },
- [0x060C]={ 0,1 },
- [0x061B]={ 0,1 },
- [0x06D4]={ 0,1 },
-}
-fonts.handlers.otf.features.normalize=function(t)
- if t.rand then
- t.rand="random"
- end
- return t
-end
-function fonts.helpers.nametoslot(name)
- local t=type(name)
- if t=="string" then
- local tfmdata=fonts.hashes.identifiers[currentfont()]
- local shared=tfmdata and tfmdata.shared
- local fntdata=shared and shared.rawdata
- return fntdata and fntdata.resources.unicodes[name]
- elseif t=="number" then
- return n
- end
-end
-fonts.encodings=fonts.encodings or {}
-local reencodings={}
-fonts.encodings.reencodings=reencodings
-local function specialreencode(tfmdata,value)
- local encoding=value and reencodings[value]
- if encoding then
- local temp={}
- local char=tfmdata.characters
- for k,v in next,encoding do
- temp[k]=char[v]
- end
- for k,v in next,temp do
- char[k]=temp[k]
- end
- return string.format("reencoded:%s",value)
- end
-end
-local function reencode(tfmdata,value)
- tfmdata.postprocessors=tfmdata.postprocessors or {}
- table.insert(tfmdata.postprocessors,
- function(tfmdata)
- return specialreencode(tfmdata,value)
- end
- )
-end
-otffeatures.register {
- name="reencode",
- description="reencode characters",
- manipulators={
- base=reencode,
- node=reencode,
- }
-}
-local function ignore(tfmdata,key,value)
- if value then
- tfmdata.mathparameters=nil
- end
-end
-otffeatures.register {
- name="ignoremathconstants",
- description="ignore math constants table",
- initializers={
- base=ignore,
- node=ignore,
- }
-}
-
-end --- [luaotfload, fontloader-2017-02-11.lua scope for “fonts-ext”] ---
-
-
-do --- [luaotfload, fontloader-2017-02-11.lua scope for “font-gbn” 850f31ba73ff8de96371d0aed2b2b4cb] ---
-
-if not modules then modules={} end modules ['font-gbn']={
- version=1.001,
- comment="companion to luatex-*.tex",
- author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright="PRAGMA ADE / ConTeXt Development Team",
- license="see context related readme files"
-}
-if context then
- texio.write_nl("fatal error: this module is not for context")
- os.exit()
-end
-local fonts=fonts
-local nodes=nodes
-local nuts=nodes.nuts
-local traverse_id=nuts.traverse_id
-local flush_node=nuts.flush_node
-local glyph_code=nodes.nodecodes.glyph
-local disc_code=nodes.nodecodes.disc
-local tonode=nuts.tonode
-local tonut=nuts.tonut
-local getfont=nuts.getfont
-local getchar=nuts.getchar
-local getid=nuts.getid
-local getboth=nuts.getboth
-local getprev=nuts.getprev
-local getnext=nuts.getnext
-local getdisc=nuts.getdisc
-local setchar=nuts.setchar
-local setlink=nuts.setlink
-local setprev=nuts.setprev
-local nodetail=nuts.tail
-local n_ligaturing=node.ligaturing
-local n_kerning=node.kerning
-local ligaturing=nuts.ligaturing
-local kerning=nuts.kerning
-local basemodepass=true
-local function l_warning() texio.write_nl("warning: node.ligaturing called directly") l_warning=nil end
-local function k_warning() texio.write_nl("warning: node.kerning called directly") k_warning=nil end
-function node.ligaturing(...)
- if basemodepass and l_warning then
- l_warning()
- end
- return n_ligaturing(...)
-end
-function node.kerning(...)
- if basemodepass and k_warning then
- k_warning()
- end
- return n_kerning(...)
-end
-function nodes.handlers.setbasemodepass(v)
- basemodepass=v
-end
-function nodes.handlers.nodepass(head)
- local fontdata=fonts.hashes.identifiers
- if fontdata then
- local nuthead=tonut(head)
- local usedfonts={}
- local basefonts={}
- local prevfont=nil
- local basefont=nil
- local variants=nil
- local redundant=nil
- for n in traverse_id(glyph_code,nuthead) do
- local font=getfont(n)
- if font~=prevfont then
- if basefont then
- basefont[2]=getprev(n)
- end
- prevfont=font
- local used=usedfonts[font]
- if not used then
- local tfmdata=fontdata[font]
- if tfmdata then
- local shared=tfmdata.shared
- if shared then
- local processors=shared.processes
- if processors and #processors>0 then
- usedfonts[font]=processors
- elseif basemodepass then
- basefont={ n,nil }
- basefonts[#basefonts+1]=basefont
- end
- end
- local resources=tfmdata.resources
- variants=resources and resources.variants
- variants=variants and next(variants) and variants or false
- end
- else
- local tfmdata=fontdata[prevfont]
- if tfmdata then
- local resources=tfmdata.resources
- variants=resources and resources.variants
- variants=variants and next(variants) and variants or false
- end
- end
- end
- if variants then
- local char=getchar(n)
- if char>=0xFE00 and (char<=0xFE0F or (char>=0xE0100 and char<=0xE01EF)) then
- local hash=variants[char]
- if hash then
- local p=getprev(n)
- if p and getid(p)==glyph_code then
- local variant=hash[getchar(p)]
- if variant then
- setchar(p,variant)
- end
- end
- end
- if not redundant then
- redundant={ n }
- else
- redundant[#redundant+1]=n
- end
- end
- end
- end
- local nofbasefonts=#basefonts
- if redundant then
- for i=1,#redundant do
- local r=redundant[i]
- local p,n=getboth(r)
- if r==nuthead then
- nuthead=n
- setprev(n)
- else
- setlink(p,n)
- end
- if nofbasefonts>0 then
- for i=1,nofbasefonts do
- local bi=basefonts[i]
- if r==bi[1] then
- bi[1]=n
- end
- if r==bi[2] then
- bi[2]=n
- end
- end
- end
- flush_node(r)
- end
- end
- for d in traverse_id(disc_code,nuthead) do
- local _,_,r=getdisc(d)
- if r then
- for n in traverse_id(glyph_code,r) do
- local font=getfont(n)
- if font~=prevfont then
- prevfont=font
- local used=usedfonts[font]
- if not used then
- local tfmdata=fontdata[font]
- if tfmdata then
- local shared=tfmdata.shared
- if shared then
- local processors=shared.processes
- if processors and #processors>0 then
- usedfonts[font]=processors
- end
- end
- end
- end
- end
- end
- end
- end
- if next(usedfonts) then
- for font,processors in next,usedfonts do
- for i=1,#processors do
- head=processors[i](head,font,0) or head
- end
- end
- end
- if basemodepass and nofbasefonts>0 then
- for i=1,nofbasefonts do
- local range=basefonts[i]
- local start=range[1]
- local stop=range[2]
- if start then
- local front=nuthead==start
- if not stop then
- stop=nodetail(start)
- end
- if stop then
- start,stop=ligaturing(start,stop)
- start,stop=kerning(start,stop)
- elseif start then
- start,stop=ligaturing(start,stop)
- start,stop=kerning(start,stop)
- end
- if front and nuthead~=start then
- head=tonode(start)
- end
- end
- end
- end
- return head,true
- else
- return head,false
- end
-end
-function nodes.handlers.basepass(head)
- if not basemodepass then
- head=n_ligaturing(head)
- head=n_kerning(head)
- end
- return head,true
-end
-local nodepass=nodes.handlers.nodepass
-local basepass=nodes.handlers.basepass
-local injectpass=nodes.injections.handler
-local protectpass=nodes.handlers.protectglyphs
-function nodes.simple_font_handler(head)
- if head then
- head=nodepass(head)
- head=injectpass(head)
- if not basemodepass then
- head=basepass(head)
- end
- protectpass(head)
- return head,true
- else
- return head,false
- end
-end
-
-end --- [luaotfload, fontloader-2017-02-11.lua scope for “font-gbn”] ---
-
-
---- vim:ft=lua:sw=2:ts=8:et:tw=79
Added: trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-2018-09-24.lua
===================================================================
--- trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-2018-09-24.lua (rev 0)
+++ trunk/Master/texmf-dist/tex/luatex/luaotfload/fontloader-2018-09-24.lua 2018-09-26 20:50:34 UTC (rev 48771)
@@ -0,0 +1,29266 @@
+--[[info-----------------------------------------------------------------------
+ Luaotfload fontloader package
+ build 2018-09-24 22:51:46 by fischer at troubleshooting-tex.de
+-------------------------------------------------------------------------------
+
+ © 2018 PRAGMA ADE / ConTeXt Development Team
+
+ The code in this file is provided under the GPL v2.0 license. See the
+ file COPYING in the Luaotfload repository for details.
+
+ Report bugs to github.com/lualatex/luaotfload
+
+ This file has been assembled from components taken from Context. See
+ the Luaotfload documentation for details:
+
+ $ texdoc luaotfload
+ $ man 1 luaotfload-tool
+ $ man 5 luaotfload.conf
+
+ Included files:
+
+ · fontloader-data-con.lua
+ · fontloader-basics-nod.lua
+ · fontloader-font-ini.lua
+ · fontloader-fonts-mis.lua
+ · fontloader-font-con.lua
+ · fontloader-fonts-enc.lua
+ · fontloader-font-cid.lua
+ · fontloader-font-map.lua
+ · fontloader-font-vfc.lua
+ · fontloader-font-otr.lua
+ · fontloader-font-oti.lua
+ · fontloader-font-ott.lua
+ · fontloader-font-cff.lua
+ · fontloader-font-ttf.lua
+ · fontloader-font-dsp.lua
+ · fontloader-font-oup.lua
+ · fontloader-font-otl.lua
+ · fontloader-font-oto.lua
+ · fontloader-font-otj.lua
+ · fontloader-font-ota.lua
+ · fontloader-font-ots.lua
+ · fontloader-font-osd.lua
+ · fontloader-font-ocl.lua
+ · fontloader-font-otc.lua
+ · fontloader-font-onr.lua
+ · fontloader-font-one.lua
+ · fontloader-font-afk.lua
+ · fontloader-font-tfm.lua
+ · fontloader-font-lua.lua
+ · fontloader-font-def.lua
+ · fontloader-fonts-def.lua
+ · fontloader-fonts-ext.lua
+ · fontloader-font-imp-tex.lua
+ · fontloader-font-imp-ligatures.lua
+ · fontloader-font-imp-italics.lua
+ · fontloader-font-imp-effects.lua
+ · fontloader-fonts-lig.lua
+ · fontloader-fonts-gbn.lua
+
+--info]]-----------------------------------------------------------------------
+
+
+do --- [luaotfload, fontloader-2018-09-24.lua scope for “data-con” d8982c834ed9acc6193eee23067b9d5d] ---
+
+if not modules then modules={} end modules ['data-con']={
+ version=1.100,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local format,lower,gsub=string.format,string.lower,string.gsub
+local trace_cache=false trackers.register("resolvers.cache",function(v) trace_cache=v end)
+local trace_containers=false trackers.register("resolvers.containers",function(v) trace_containers=v end)
+local trace_storage=false trackers.register("resolvers.storage",function(v) trace_storage=v end)
+containers=containers or {}
+local containers=containers
+containers.usecache=true
+local report_containers=logs.reporter("resolvers","containers")
+local allocated={}
+local mt={
+ __index=function(t,k)
+ if k=="writable" then
+ local writable=caches.getwritablepath(t.category,t.subcategory) or { "." }
+ t.writable=writable
+ return writable
+ elseif k=="readables" then
+ local readables=caches.getreadablepaths(t.category,t.subcategory) or { "." }
+ t.readables=readables
+ return readables
+ end
+ end,
+ __storage__=true
+}
+function containers.define(category,subcategory,version,enabled)
+ if category and subcategory then
+ local c=allocated[category]
+ if not c then
+ c={}
+ allocated[category]=c
+ end
+ local s=c[subcategory]
+ if not s then
+ s={
+ category=category,
+ subcategory=subcategory,
+ storage={},
+ enabled=enabled,
+ version=version or math.pi,
+ trace=false,
+ }
+ setmetatable(s,mt)
+ c[subcategory]=s
+ end
+ return s
+ end
+end
+function containers.is_usable(container,name)
+ return container.enabled and caches and caches.is_writable(container.writable,name)
+end
+function containers.is_valid(container,name)
+ if name and name~="" then
+ local storage=container.storage[name]
+ return storage and storage.cache_version==container.version
+ else
+ return false
+ end
+end
+function containers.read(container,name)
+ local storage=container.storage
+ local stored=storage[name]
+ if not stored and container.enabled and caches and containers.usecache then
+ stored=caches.loaddata(container.readables,name,container.writable)
+ if stored and stored.cache_version==container.version then
+ if trace_cache or trace_containers then
+ report_containers("action %a, category %a, name %a","load",container.subcategory,name)
+ end
+ else
+ stored=nil
+ end
+ storage[name]=stored
+ elseif stored then
+ if trace_cache or trace_containers then
+ report_containers("action %a, category %a, name %a","reuse",container.subcategory,name)
+ end
+ end
+ return stored
+end
+function containers.write(container,name,data)
+ if data then
+ data.cache_version=container.version
+ if container.enabled and caches then
+ local unique,shared=data.unique,data.shared
+ data.unique,data.shared=nil,nil
+ caches.savedata(container.writable,name,data)
+ if trace_cache or trace_containers then
+ report_containers("action %a, category %a, name %a","save",container.subcategory,name)
+ end
+ data.unique,data.shared=unique,shared
+ end
+ if trace_cache or trace_containers then
+ report_containers("action %a, category %a, name %a","store",container.subcategory,name)
+ end
+ container.storage[name]=data
+ end
+ return data
+end
+function containers.content(container,name)
+ return container.storage[name]
+end
+function containers.cleanname(name)
+ return (gsub(lower(name),"[^%w\128-\255]+","-"))
+end
+
+end --- [luaotfload, fontloader-2018-09-24.lua scope for “data-con”] ---
+
+
+do --- [luaotfload, fontloader-2018-09-24.lua scope for “basics-nod” 78f56219685f3145b9393c2b688aad94] ---
+
+if not modules then modules={} end modules ['luatex-fonts-nod']={
+ version=1.001,
+ comment="companion to luatex-fonts.lua",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+if context then
+ os.exit()
+end
+if tex.attribute[0]~=0 then
+ texio.write_nl("log","!")
+ texio.write_nl("log","! Attribute 0 is reserved for ConTeXt's font feature management and has to be")
+ texio.write_nl("log","! set to zero. Also, some attributes in the range 1-255 are used for special")
+ texio.write_nl("log","! purposes so setting them at the TeX end might break the font handler.")
+ texio.write_nl("log","!")
+ tex.attribute[0]=0
+end
+attributes=attributes or {}
+attributes.unsetvalue=-0x7FFFFFFF
+local numbers,last={},127
+attributes.private=attributes.private or function(name)
+ local number=numbers[name]
+ if not number then
+ if last<255 then
+ last=last+1
+ end
+ number=last
+ numbers[name]=number
+ end
+ return number
+end
+nodes={}
+nodes.handlers={}
+local nodecodes={}
+local glyphcodes=node.subtypes("glyph")
+local disccodes=node.subtypes("disc")
+for k,v in next,node.types() do
+ v=string.gsub(v,"_","")
+ nodecodes[k]=v
+ nodecodes[v]=k
+end
+for k,v in next,glyphcodes do
+ glyphcodes[v]=k
+end
+for k,v in next,glyphcodes do
+ disccodes[v]=k
+end
+nodes.nodecodes=nodecodes
+nodes.glyphcodes=glyphcodes
+nodes.disccodes=disccodes
+local flush_node=node.flush_node
+local remove_node=node.remove
+local traverse_id=node.traverse_id
+nodes.handlers.protectglyphs=node.protect_glyphs
+nodes.handlers.unprotectglyphs=node.unprotect_glyphs
+local math_code=nodecodes.math
+local end_of_math=node.end_of_math
+function node.end_of_math(n)
+ if n.id==math_code and n.subtype==1 then
+ return n
+ else
+ return end_of_math(n)
+ end
+end
+function nodes.remove(head,current,free_too)
+ local t=current
+ head,current=remove_node(head,current)
+ if t then
+ if free_too then
+ flush_node(t)
+ t=nil
+ else
+ t.next,t.prev=nil,nil
+ end
+ end
+ return head,current,t
+end
+function nodes.delete(head,current)
+ return nodes.remove(head,current,true)
+end
+local getfield=node.getfield
+local setfield=node.setfield
+nodes.getfield=getfield
+nodes.setfield=setfield
+nodes.getattr=getfield
+nodes.setattr=setfield
+nodes.tostring=node.tostring or tostring
+nodes.copy=node.copy
+nodes.copy_node=node.copy
+nodes.copy_list=node.copy_list
+nodes.delete=node.delete
+nodes.dimensions=node.dimensions
+nodes.end_of_math=node.end_of_math
+nodes.flush_list=node.flush_list
+nodes.flush_node=node.flush_node
+nodes.flush=node.flush_node
+nodes.free=node.free
+nodes.insert_after=node.insert_after
+nodes.insert_before=node.insert_before
+nodes.hpack=node.hpack
+nodes.new=node.new
+nodes.tail=node.tail
+nodes.traverse=node.traverse
+nodes.traverse_id=node.traverse_id
+nodes.slide=node.slide
+nodes.vpack=node.vpack
+nodes.first_glyph=node.first_glyph
+nodes.has_glyph=node.has_glyph or node.first_glyph
+nodes.current_attr=node.current_attr
+nodes.has_field=node.has_field
+nodes.last_node=node.last_node
+nodes.usedlist=node.usedlist
+nodes.protrusion_skippable=node.protrusion_skippable
+nodes.write=node.write
+nodes.has_attribute=node.has_attribute
+nodes.set_attribute=node.set_attribute
+nodes.unset_attribute=node.unset_attribute
+nodes.protect_glyphs=node.protect_glyphs
+nodes.unprotect_glyphs=node.unprotect_glyphs
+nodes.mlist_to_hlist=node.mlist_to_hlist
+local direct=node.direct
+local nuts={}
+nodes.nuts=nuts
+local tonode=direct.tonode
+local tonut=direct.todirect
+nodes.tonode=tonode
+nodes.tonut=tonut
+nuts.tonode=tonode
+nuts.tonut=tonut
+local getfield=direct.getfield
+local setfield=direct.setfield
+nuts.getfield=getfield
+nuts.setfield=setfield
+nuts.getnext=direct.getnext
+nuts.setnext=direct.setnext
+nuts.getprev=direct.getprev
+nuts.setprev=direct.setprev
+nuts.getboth=direct.getboth
+nuts.setboth=direct.setboth
+nuts.getid=direct.getid
+nuts.getattr=direct.get_attribute or direct.has_attribute or getfield
+nuts.setattr=setfield
+nuts.getfont=direct.getfont
+nuts.setfont=direct.setfont
+nuts.getsubtype=direct.getsubtype
+nuts.setsubtype=direct.setsubtype
+nuts.getchar=direct.getchar
+nuts.setchar=direct.setchar
+nuts.getdisc=direct.getdisc
+nuts.setdisc=direct.setdisc
+nuts.setlink=direct.setlink
+nuts.setsplit=direct.setsplit
+nuts.getlist=direct.getlist
+nuts.setlist=direct.setlist
+nuts.getoffsets=direct.getoffsets or
+ function(n)
+ return getfield(n,"xoffset"),getfield(n,"yoffset")
+ end
+nuts.setoffsets=direct.setoffsets or
+ function(n,x,y)
+ if x then setfield(n,"xoffset",x) end
+ if y then setfield(n,"xoffset",y) end
+ end
+nuts.getleader=direct.getleader or function(n) return getfield(n,"leader") end
+nuts.setleader=direct.setleader or function(n,l) setfield(n,"leader",l) end
+nuts.getcomponents=direct.getcomponents or function(n) return getfield(n,"components") end
+nuts.setcomponents=direct.setcomponents or function(n,c) setfield(n,"components",c) end
+nuts.getkern=direct.getkern or function(n) return getfield(n,"kern") end
+nuts.setkern=direct.setkern or function(n,k) setfield(n,"kern",k) end
+nuts.getdir=direct.getdir or function(n) return getfield(n,"dir") end
+nuts.setdir=direct.setdir or function(n,d) setfield(n,"dir",d) end
+nuts.getwidth=direct.getwidth or function(n) return getfield(n,"width") end
+nuts.setwidth=direct.setwidth or function(n,w) return setfield(n,"width",w) end
+nuts.getheight=direct.getheight or function(n) return getfield(n,"height") end
+nuts.setheight=direct.setheight or function(n,h) return setfield(n,"height",h) end
+nuts.getdepth=direct.getdepth or function(n) return getfield(n,"depth") end
+nuts.setdepth=direct.setdepth or function(n,d) return setfield(n,"depth",d) end
+if not direct.is_glyph then
+ local getchar=direct.getchar
+ local getid=direct.getid
+ local getfont=direct.getfont
+ local glyph_code=nodes.nodecodes.glyph
+ function direct.is_glyph(n,f)
+ local id=getid(n)
+ if id==glyph_code then
+ if f and getfont(n)==f then
+ return getchar(n)
+ else
+ return false
+ end
+ else
+ return nil,id
+ end
+ end
+ function direct.is_char(n,f)
+ local id=getid(n)
+ if id==glyph_code then
+ if getsubtype(n)>=256 then
+ return false
+ elseif f and getfont(n)==f then
+ return getchar(n)
+ else
+ return false
+ end
+ else
+ return nil,id
+ end
+ end
+end
+nuts.ischar=direct.is_char
+nuts.is_char=direct.is_char
+nuts.isglyph=direct.is_glyph
+nuts.is_glyph=direct.is_glyph
+nuts.insert_before=direct.insert_before
+nuts.insert_after=direct.insert_after
+nuts.delete=direct.delete
+nuts.copy=direct.copy
+nuts.copy_node=direct.copy
+nuts.copy_list=direct.copy_list
+nuts.tail=direct.tail
+nuts.flush_list=direct.flush_list
+nuts.flush_node=direct.flush_node
+nuts.flush=direct.flush
+nuts.free=direct.free
+nuts.remove=direct.remove
+nuts.is_node=direct.is_node
+nuts.end_of_math=direct.end_of_math
+nuts.traverse=direct.traverse
+nuts.traverse_id=direct.traverse_id
+nuts.traverse_char=direct.traverse_char
+nuts.traverse_glyph=direct.traverse_glyph
+nuts.ligaturing=direct.ligaturing
+nuts.kerning=direct.kerning
+nuts.new=direct.new
+nuts.getprop=nuts.getattr
+nuts.setprop=nuts.setattr
+local propertydata=direct.get_properties_table()
+nodes.properties={ data=propertydata }
+direct.set_properties_mode(true,true)
+function direct.set_properties_mode() end
+nuts.getprop=function(n,k)
+ local p=propertydata[n]
+ if p then
+ return p[k]
+ end
+end
+nuts.setprop=function(n,k,v)
+ if v then
+ local p=propertydata[n]
+ if p then
+ p[k]=v
+ else
+ propertydata[n]={ [k]=v }
+ end
+ end
+end
+nodes.setprop=nodes.setproperty
+nodes.getprop=nodes.getproperty
+local setprev=nuts.setprev
+local setnext=nuts.setnext
+local getnext=nuts.getnext
+local setlink=nuts.setlink
+local getfield=nuts.getfield
+local setfield=nuts.setfield
+local getcomponents=nuts.getcomponents
+local setcomponents=nuts.setcomponents
+local find_tail=nuts.tail
+local flush_list=nuts.flush_list
+local flush_node=nuts.flush_node
+local traverse_id=nuts.traverse_id
+local copy_node=nuts.copy_node
+local glyph_code=nodes.nodecodes.glyph
+function nuts.set_components(target,start,stop)
+ local head=getcomponents(target)
+ if head then
+ flush_list(head)
+ head=nil
+ end
+ if start then
+ setprev(start)
+ else
+ return nil
+ end
+ if stop then
+ setnext(stop)
+ end
+ local tail=nil
+ while start do
+ local c=getcomponents(start)
+ local n=getnext(start)
+ if c then
+ if head then
+ setlink(tail,c)
+ else
+ head=c
+ end
+ tail=find_tail(c)
+ setcomponents(start)
+ flush_node(start)
+ else
+ if head then
+ setlink(tail,start)
+ else
+ head=start
+ end
+ tail=start
+ end
+ start=n
+ end
+ setcomponents(target,head)
+ return head
+end
+nuts.get_components=nuts.getcomponents
+function nuts.take_components(target)
+ local c=getcomponents(target)
+ setcomponents(target)
+ return c
+end
+function nuts.count_components(n,marks)
+ local components=getcomponents(n)
+ if components then
+ if marks then
+ local i=0
+ for g in traverse_id(glyph_code,components) do
+ if not marks[getchar(g)] then
+ i=i+1
+ end
+ end
+ return i
+ else
+ return count(glyph_code,components)
+ end
+ else
+ return 0
+ end
+end
+function nuts.copy_no_components(g,copyinjection)
+ local components=getcomponents(g)
+ if components then
+ setcomponents(g)
+ local n=copy_node(g)
+ if copyinjection then
+ copyinjection(n,g)
+ end
+ setcomponents(g,components)
+ return n
+ else
+ local n=copy_node(g)
+ if copyinjection then
+ copyinjection(n,g)
+ end
+ return n
+ end
+end
+function nuts.copy_only_glyphs(current)
+ local head=nil
+ local previous=nil
+ for n in traverse_id(glyph_code,current) do
+ n=copy_node(n)
+ if head then
+ setlink(previous,n)
+ else
+ head=n
+ end
+ previous=n
+ end
+ return head
+end
+nuts.uses_font=direct.uses_font
+if not nuts.uses_font then
+ local getdisc=nuts.getdisc
+ local getfont=nuts.getfont
+ function nuts.uses_font(n,font)
+ local pre,post,replace=getdisc(n)
+ if pre then
+ for n in traverse_id(glyph_code,pre) do
+ if getfont(n)==font then
+ return true
+ end
+ end
+ end
+ if post then
+ for n in traverse_id(glyph_code,post) do
+ if getfont(n)==font then
+ return true
+ end
+ end
+ end
+ if replace then
+ for n in traverse_id(glyph_code,replace) do
+ if getfont(n)==font then
+ return true
+ end
+ end
+ end
+ return false
+ end
+end
+do
+ local dummy=tonut(node.new("glyph"))
+ nuts.traversers={
+ glyph=nuts.traverse_id(nodecodes.glyph,dummy),
+ glue=nuts.traverse_id(nodecodes.glue,dummy),
+ disc=nuts.traverse_id(nodecodes.disc,dummy),
+ boundary=nuts.traverse_id(nodecodes.boundary,dummy),
+ char=nuts.traverse_char(dummy),
+ node=nuts.traverse(dummy),
+ }
+end
+
+end --- [luaotfload, fontloader-2018-09-24.lua scope for “basics-nod”] ---
+
+
+do --- [luaotfload, fontloader-2018-09-24.lua scope for “font-ini” 6f615d3bc72fb29f409ed2b8f6364c35] ---
+
+if not modules then modules={} end modules ['font-ini']={
+ version=1.001,
+ comment="companion to font-ini.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local allocate=utilities.storage.allocate
+fonts=fonts or {}
+local fonts=fonts
+fonts.hashes=fonts.hashes or { identifiers=allocate() }
+fonts.tables=fonts.tables or {}
+fonts.helpers=fonts.helpers or {}
+fonts.tracers=fonts.tracers or {}
+fonts.specifiers=fonts.specifiers or {}
+fonts.analyzers={}
+fonts.readers={}
+fonts.definers={ methods={} }
+fonts.loggers={ register=function() end }
+if context then
+ fontloader=nil
+end
+
+end --- [luaotfload, fontloader-2018-09-24.lua scope for “font-ini”] ---
+
+
+do --- [luaotfload, fontloader-2018-09-24.lua scope for “fonts-mis” fd0a52acf5180695d2870da654db7272] ---
+
+if not modules then modules={} end modules ['luatex-font-mis']={
+ version=1.001,
+ comment="companion to luatex-*.tex",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+if context then
+ os.exit()
+end
+local currentfont=font.current
+local hashes=fonts.hashes
+local identifiers=hashes.identifiers or {}
+local marks=hashes.marks or {}
+hashes.identifiers=identifiers
+hashes.marks=marks
+table.setmetatableindex(marks,function(t,k)
+ if k==true then
+ return marks[currentfont()]
+ else
+ local resources=identifiers[k].resources or {}
+ local marks=resources.marks or {}
+ t[k]=marks
+ return marks
+ end
+end)
+
+end --- [luaotfload, fontloader-2018-09-24.lua scope for “fonts-mis”] ---
+
+
+do --- [luaotfload, fontloader-2018-09-24.lua scope for “font-con” 3218bd21a24c2abb13b284085da8ced4] ---
+
+if not modules then modules={} end modules ['font-con']={
+ version=1.001,
+ comment="companion to font-ini.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local next,tostring,tonumber,rawget=next,tostring,tonumber,rawget
+local format,match,lower,gsub,find=string.format,string.match,string.lower,string.gsub,string.find
+local sort,insert,concat=table.sort,table.insert,table.concat
+local sortedkeys,sortedhash,serialize,fastcopy=table.sortedkeys,table.sortedhash,table.serialize,table.fastcopy
+local derivetable=table.derive
+local ioflush=io.flush
+local round=math.round
+local setmetatable,getmetatable,rawget,rawset=setmetatable,getmetatable,rawget,rawset
+local trace_defining=false trackers.register("fonts.defining",function(v) trace_defining=v end)
+local trace_scaling=false trackers.register("fonts.scaling",function(v) trace_scaling=v end)
+local report_defining=logs.reporter("fonts","defining")
+local fonts=fonts
+local constructors=fonts.constructors or {}
+fonts.constructors=constructors
+local handlers=fonts.handlers or {}
+fonts.handlers=handlers
+local allocate=utilities.storage.allocate
+local setmetatableindex=table.setmetatableindex
+constructors.dontembed=allocate()
+constructors.autocleanup=true
+constructors.namemode="fullpath"
+constructors.version=1.01
+constructors.cache=containers.define("fonts","constructors",constructors.version,false)
+constructors.privateoffset=0xF0000
+constructors.cacheintex=true
+local designsizes=allocate()
+constructors.designsizes=designsizes
+local loadedfonts=allocate()
+constructors.loadedfonts=loadedfonts
+local factors={
+ pt=65536.0,
+ bp=65781.8,
+}
+function constructors.setfactor(f)
+ constructors.factor=factors[f or 'pt'] or factors.pt
+end
+constructors.setfactor()
+function constructors.scaled(scaledpoints,designsize)
+ if scaledpoints<0 then
+ local factor=constructors.factor
+ if designsize then
+ if designsize>factor then
+ return (- scaledpoints/1000)*designsize
+ else
+ return (- scaledpoints/1000)*designsize*factor
+ end
+ else
+ return (- scaledpoints/1000)*10*factor
+ end
+ else
+ return scaledpoints
+ end
+end
+function constructors.getprivate(tfmdata)
+ local properties=tfmdata.properties
+ local private=properties.private
+ properties.private=private+1
+ return private
+end
+function constructors.setmathparameter(tfmdata,name,value)
+ local m=tfmdata.mathparameters
+ local c=tfmdata.MathConstants
+ if m then
+ m[name]=value
+ end
+ if c and c~=m then
+ c[name]=value
+ end
+end
+function constructors.getmathparameter(tfmdata,name)
+ local p=tfmdata.mathparameters or tfmdata.MathConstants
+ if p then
+ return p[name]
+ end
+end
+function constructors.cleanuptable(tfmdata)
+ if constructors.autocleanup and tfmdata.properties.virtualized then
+ for k,v in next,tfmdata.characters do
+ if v.commands then v.commands=nil end
+ end
+ end
+end
+function constructors.calculatescale(tfmdata,scaledpoints)
+ local parameters=tfmdata.parameters
+ if scaledpoints<0 then
+ scaledpoints=(- scaledpoints/1000)*(tfmdata.designsize or parameters.designsize)
+ end
+ return scaledpoints,scaledpoints/(parameters.units or 1000)
+end
+local unscaled={
+ ScriptPercentScaleDown=true,
+ ScriptScriptPercentScaleDown=true,
+ RadicalDegreeBottomRaisePercent=true,
+ NoLimitSupFactor=true,
+ NoLimitSubFactor=true,
+}
+function constructors.assignmathparameters(target,original)
+ local mathparameters=original.mathparameters
+ if mathparameters and next(mathparameters) then
+ local targetparameters=target.parameters
+ local targetproperties=target.properties
+ local targetmathparameters={}
+ local factor=targetproperties.math_is_scaled and 1 or targetparameters.factor
+ for name,value in next,mathparameters do
+ if unscaled[name] then
+ targetmathparameters[name]=value
+ else
+ targetmathparameters[name]=value*factor
+ end
+ end
+ if not targetmathparameters.FractionDelimiterSize then
+ targetmathparameters.FractionDelimiterSize=1.01*targetparameters.size
+ end
+ if not mathparameters.FractionDelimiterDisplayStyleSize then
+ targetmathparameters.FractionDelimiterDisplayStyleSize=2.40*targetparameters.size
+ end
+ target.mathparameters=targetmathparameters
+ end
+end
+function constructors.beforecopyingcharacters(target,original)
+end
+function constructors.aftercopyingcharacters(target,original)
+end
+constructors.sharefonts=false
+constructors.nofsharedfonts=0
+local sharednames={}
+function constructors.trytosharefont(target,tfmdata)
+ if constructors.sharefonts then
+ local characters=target.characters
+ local n=1
+ local t={ target.psname }
+ local u=sortedkeys(characters)
+ for i=1,#u do
+ local k=u[i]
+ n=n+1;t[n]=k
+ n=n+1;t[n]=characters[k].index or k
+ end
+ local h=md5.HEX(concat(t," "))
+ local s=sharednames[h]
+ if s then
+ if trace_defining then
+ report_defining("font %a uses backend resources of font %a",target.fullname,s)
+ end
+ target.fullname=s
+ constructors.nofsharedfonts=constructors.nofsharedfonts+1
+ target.properties.sharedwith=s
+ else
+ sharednames[h]=target.fullname
+ end
+ end
+end
+local synonyms={
+ exheight="x_height",
+ xheight="x_height",
+ ex="x_height",
+ emwidth="quad",
+ em="quad",
+ spacestretch="space_stretch",
+ stretch="space_stretch",
+ spaceshrink="space_shrink",
+ shrink="space_shrink",
+ extraspace="extra_space",
+ xspace="extra_space",
+ slantperpoint="slant",
+}
+function constructors.enhanceparameters(parameters)
+ local mt=getmetatable(parameters)
+ local getter=function(t,k)
+ if not k then
+ return nil
+ end
+ local s=synonyms[k]
+ if s then
+ return rawget(t,s) or (mt and mt[s]) or nil
+ end
+ if k=="spacing" then
+ return {
+ width=t.space,
+ stretch=t.space_stretch,
+ shrink=t.space_shrink,
+ extra=t.extra_space,
+ }
+ end
+ return mt and mt[k] or nil
+ end
+ local setter=function(t,k,v)
+ if not k then
+ return 0
+ end
+ local s=synonyms[k]
+ if s then
+ rawset(t,s,v)
+ elseif k=="spacing" then
+ if type(v)=="table" then
+ rawset(t,"space",v.width or 0)
+ rawset(t,"space_stretch",v.stretch or 0)
+ rawset(t,"space_shrink",v.shrink or 0)
+ rawset(t,"extra_space",v.extra or 0)
+ end
+ else
+ rawset(t,k,v)
+ end
+ end
+ setmetatable(parameters,{
+ __index=getter,
+ __newindex=setter,
+ })
+end
+local function mathkerns(v,vdelta)
+ local k={}
+ for i=1,#v do
+ local entry=v[i]
+ local height=entry.height
+ local kern=entry.kern
+ k[i]={
+ height=height and vdelta*height or 0,
+ kern=kern and vdelta*kern or 0,
+ }
+ end
+ return k
+end
+local psfake=0
+local function fixedpsname(psname,fallback)
+ local usedname=psname
+ if psname and psname~="" then
+ if find(psname," ",1,true) then
+ usedname=gsub(psname,"[%s]+","-")
+ else
+ end
+ elseif not fallback or fallback=="" then
+ psfake=psfake+1
+ psname="fakename-"..psfake
+ else
+ psname=fallback
+ usedname=gsub(psname,"[^a-zA-Z0-9]+","-")
+ end
+ return usedname,psname~=usedname
+end
+function constructors.scale(tfmdata,specification)
+ local target={}
+ if tonumber(specification) then
+ specification={ size=specification }
+ end
+ target.specification=specification
+ local scaledpoints=specification.size
+ local relativeid=specification.relativeid
+ local properties=tfmdata.properties or {}
+ local goodies=tfmdata.goodies or {}
+ local resources=tfmdata.resources or {}
+ local descriptions=tfmdata.descriptions or {}
+ local characters=tfmdata.characters or {}
+ local changed=tfmdata.changed or {}
+ local shared=tfmdata.shared or {}
+ local parameters=tfmdata.parameters or {}
+ local mathparameters=tfmdata.mathparameters or {}
+ local targetcharacters={}
+ local targetdescriptions=derivetable(descriptions)
+ local targetparameters=derivetable(parameters)
+ local targetproperties=derivetable(properties)
+ local targetgoodies=goodies
+ target.characters=targetcharacters
+ target.descriptions=targetdescriptions
+ target.parameters=targetparameters
+ target.properties=targetproperties
+ target.goodies=targetgoodies
+ target.shared=shared
+ target.resources=resources
+ target.unscaled=tfmdata
+ local mathsize=tonumber(specification.mathsize) or 0
+ local textsize=tonumber(specification.textsize) or scaledpoints
+ local forcedsize=tonumber(parameters.mathsize ) or 0
+ local extrafactor=tonumber(specification.factor ) or 1
+ if (mathsize==2 or forcedsize==2) and parameters.scriptpercentage then
+ scaledpoints=parameters.scriptpercentage*textsize/100
+ elseif (mathsize==3 or forcedsize==3) and parameters.scriptscriptpercentage then
+ scaledpoints=parameters.scriptscriptpercentage*textsize/100
+ elseif forcedsize>1000 then
+ scaledpoints=forcedsize
+ else
+ end
+ targetparameters.mathsize=mathsize
+ targetparameters.textsize=textsize
+ targetparameters.forcedsize=forcedsize
+ targetparameters.extrafactor=extrafactor
+ local tounicode=fonts.mappings.tounicode
+ local defaultwidth=resources.defaultwidth or 0
+ local defaultheight=resources.defaultheight or 0
+ local defaultdepth=resources.defaultdepth or 0
+ local units=parameters.units or 1000
+ targetproperties.language=properties.language or "dflt"
+ targetproperties.script=properties.script or "dflt"
+ targetproperties.mode=properties.mode or "base"
+ local askedscaledpoints=scaledpoints
+ local scaledpoints,delta=constructors.calculatescale(tfmdata,scaledpoints,nil,specification)
+ local hdelta=delta
+ local vdelta=delta
+ target.designsize=parameters.designsize
+ target.units=units
+ target.units_per_em=units
+ local direction=properties.direction or tfmdata.direction or 0
+ target.direction=direction
+ properties.direction=direction
+ target.size=scaledpoints
+ target.encodingbytes=properties.encodingbytes or 1
+ target.embedding=properties.embedding or "subset"
+ target.tounicode=1
+ target.cidinfo=properties.cidinfo
+ target.format=properties.format
+ target.cache=constructors.cacheintex and "yes" or "renew"
+ local fontname=properties.fontname or tfmdata.fontname
+ local fullname=properties.fullname or tfmdata.fullname
+ local filename=properties.filename or tfmdata.filename
+ local psname=properties.psname or tfmdata.psname
+ local name=properties.name or tfmdata.name
+ local psname,psfixed=fixedpsname(psname,fontname or fullname or file.nameonly(filename))
+ target.fontname=fontname
+ target.fullname=fullname
+ target.filename=filename
+ target.psname=psname
+ target.name=name
+ properties.fontname=fontname
+ properties.fullname=fullname
+ properties.filename=filename
+ properties.psname=psname
+ properties.name=name
+ local expansion=parameters.expansion
+ if expansion then
+ target.stretch=expansion.stretch
+ target.shrink=expansion.shrink
+ target.step=expansion.step
+ end
+ local slantfactor=parameters.slantfactor or 0
+ if slantfactor~=0 then
+ target.slant=slantfactor*1000
+ else
+ target.slant=0
+ end
+ local extendfactor=parameters.extendfactor or 0
+ if extendfactor~=0 and extendfactor~=1 then
+ hdelta=hdelta*extendfactor
+ target.extend=extendfactor*1000
+ else
+ target.extend=1000
+ end
+ local squeezefactor=parameters.squeezefactor or 0
+ if squeezefactor~=0 and squeezefactor~=1 then
+ vdelta=vdelta*squeezefactor
+ target.squeeze=squeezefactor*1000
+ else
+ target.squeeze=1000
+ end
+ local mode=parameters.mode or 0
+ if mode~=0 then
+ target.mode=mode
+ end
+ local width=parameters.width or 0
+ if width~=0 then
+ target.width=width*delta*1000/655360
+ end
+ targetparameters.factor=delta
+ targetparameters.hfactor=hdelta
+ targetparameters.vfactor=vdelta
+ targetparameters.size=scaledpoints
+ targetparameters.units=units
+ targetparameters.scaledpoints=askedscaledpoints
+ targetparameters.mode=mode
+ targetparameters.width=width
+ local isvirtual=properties.virtualized or tfmdata.type=="virtual"
+ local hasquality=parameters.expansion or parameters.protrusion
+ local hasitalics=properties.hasitalics
+ local autoitalicamount=properties.autoitalicamount
+ local stackmath=not properties.nostackmath
+ local nonames=properties.noglyphnames
+ local haskerns=properties.haskerns or properties.mode=="base"
+ local hasligatures=properties.hasligatures or properties.mode=="base"
+ local realdimensions=properties.realdimensions
+ local writingmode=properties.writingmode or "horizontal"
+ local identity=properties.identity or "horizontal"
+ local vfonts=target.fonts
+ if vfonts and #vfonts>0 then
+ target.fonts=fastcopy(vfonts)
+ elseif isvirtual then
+ target.fonts={ { id=0 } }
+ end
+ if changed and not next(changed) then
+ changed=false
+ end
+ target.type=isvirtual and "virtual" or "real"
+ target.writingmode=writingmode=="vertical" and "vertical" or "horizontal"
+ target.identity=identity=="vertical" and "vertical" or "horizontal"
+ target.postprocessors=tfmdata.postprocessors
+ local targetslant=(parameters.slant or parameters[1] or 0)*factors.pt
+ local targetspace=(parameters.space or parameters[2] or 0)*hdelta
+ local targetspace_stretch=(parameters.space_stretch or parameters[3] or 0)*hdelta
+ local targetspace_shrink=(parameters.space_shrink or parameters[4] or 0)*hdelta
+ local targetx_height=(parameters.x_height or parameters[5] or 0)*vdelta
+ local targetquad=(parameters.quad or parameters[6] or 0)*hdelta
+ local targetextra_space=(parameters.extra_space or parameters[7] or 0)*hdelta
+ targetparameters.slant=targetslant
+ targetparameters.space=targetspace
+ targetparameters.space_stretch=targetspace_stretch
+ targetparameters.space_shrink=targetspace_shrink
+ targetparameters.x_height=targetx_height
+ targetparameters.quad=targetquad
+ targetparameters.extra_space=targetextra_space
+ local ascender=parameters.ascender
+ if ascender then
+ targetparameters.ascender=delta*ascender
+ end
+ local descender=parameters.descender
+ if descender then
+ targetparameters.descender=delta*descender
+ end
+ constructors.enhanceparameters(targetparameters)
+ local protrusionfactor=(targetquad~=0 and 1000/targetquad) or 0
+ local scaledwidth=defaultwidth*hdelta
+ local scaledheight=defaultheight*vdelta
+ local scaleddepth=defaultdepth*vdelta
+ local hasmath=(properties.hasmath or next(mathparameters)) and true
+ if hasmath then
+ constructors.assignmathparameters(target,tfmdata)
+ properties.hasmath=true
+ target.nomath=false
+ target.MathConstants=target.mathparameters
+ else
+ properties.hasmath=false
+ target.nomath=true
+ target.mathparameters=nil
+ end
+ if hasmath then
+ local mathitalics=properties.mathitalics
+ if mathitalics==false then
+ if trace_defining then
+ report_defining("%s italics %s for font %a, fullname %a, filename %a","math",hasitalics and "ignored" or "disabled",name,fullname,filename)
+ end
+ hasitalics=false
+ autoitalicamount=false
+ end
+ else
+ local textitalics=properties.textitalics
+ if textitalics==false then
+ if trace_defining then
+ report_defining("%s italics %s for font %a, fullname %a, filename %a","text",hasitalics and "ignored" or "disabled",name,fullname,filename)
+ end
+ hasitalics=false
+ autoitalicamount=false
+ end
+ end
+ if trace_defining then
+ report_defining("defining tfm, name %a, fullname %a, filename %a, %spsname %a, hscale %a, vscale %a, math %a, italics %a",
+ name,fullname,filename,psfixed and "(fixed) " or "",psname,hdelta,vdelta,
+ hasmath and "enabled" or "disabled",hasitalics and "enabled" or "disabled")
+ end
+ constructors.beforecopyingcharacters(target,tfmdata)
+ local sharedkerns={}
+ for unicode,character in next,characters do
+ local chr,description,index
+ if changed then
+ local c=changed[unicode]
+ if c and c~=unicode then
+ if c then
+ description=descriptions[c] or descriptions[unicode] or character
+ character=characters[c] or character
+ index=description.index or c
+ else
+ description=descriptions[unicode] or character
+ index=description.index or unicode
+ end
+ else
+ description=descriptions[unicode] or character
+ index=description.index or unicode
+ end
+ else
+ description=descriptions[unicode] or character
+ index=description.index or unicode
+ end
+ local width=description.width
+ local height=description.height
+ local depth=description.depth
+ if realdimensions then
+ if not height or height==0 then
+ local bb=description.boundingbox
+ local ht=bb[4]
+ if ht~=0 then
+ height=ht
+ end
+ if not depth or depth==0 then
+ local dp=-bb[2]
+ if dp~=0 then
+ depth=dp
+ end
+ end
+ elseif not depth or depth==0 then
+ local dp=-description.boundingbox[2]
+ if dp~=0 then
+ depth=dp
+ end
+ end
+ end
+ if width then width=hdelta*width else width=scaledwidth end
+ if height then height=vdelta*height else height=scaledheight end
+ if depth and depth~=0 then
+ depth=delta*depth
+ if nonames then
+ chr={
+ index=index,
+ height=height,
+ depth=depth,
+ width=width,
+ }
+ else
+ chr={
+ name=description.name,
+ index=index,
+ height=height,
+ depth=depth,
+ width=width,
+ }
+ end
+ else
+ if nonames then
+ chr={
+ index=index,
+ height=height,
+ width=width,
+ }
+ else
+ chr={
+ name=description.name,
+ index=index,
+ height=height,
+ width=width,
+ }
+ end
+ end
+ local isunicode=description.unicode
+ if isunicode then
+ chr.unicode=isunicode
+ chr.tounicode=tounicode(isunicode)
+ end
+ if hasquality then
+ local ve=character.expansion_factor
+ if ve then
+ chr.expansion_factor=ve*1000
+ end
+ local vl=character.left_protruding
+ if vl then
+ chr.left_protruding=protrusionfactor*width*vl
+ end
+ local vr=character.right_protruding
+ if vr then
+ chr.right_protruding=protrusionfactor*width*vr
+ end
+ end
+ if hasmath then
+ local vn=character.next
+ if vn then
+ chr.next=vn
+ else
+ local vv=character.vert_variants
+ if vv then
+ local t={}
+ for i=1,#vv do
+ local vvi=vv[i]
+ local s=vvi["start"] or 0
+ local e=vvi["end"] or 0
+ local a=vvi["advance"] or 0
+ t[i]={
+ ["start"]=s==0 and 0 or s*vdelta,
+ ["end"]=e==0 and 0 or e*vdelta,
+ ["advance"]=a==0 and 0 or a*vdelta,
+ ["extender"]=vvi["extender"],
+ ["glyph"]=vvi["glyph"],
+ }
+ end
+ chr.vert_variants=t
+ else
+ local hv=character.horiz_variants
+ if hv then
+ local t={}
+ for i=1,#hv do
+ local hvi=hv[i]
+ local s=hvi["start"] or 0
+ local e=hvi["end"] or 0
+ local a=hvi["advance"] or 0
+ t[i]={
+ ["start"]=s==0 and 0 or s*hdelta,
+ ["end"]=e==0 and 0 or e*hdelta,
+ ["advance"]=a==0 and 0 or a*hdelta,
+ ["extender"]=hvi["extender"],
+ ["glyph"]=hvi["glyph"],
+ }
+ end
+ chr.horiz_variants=t
+ end
+ end
+ end
+ local vi=character.vert_italic
+ if vi and vi~=0 then
+ chr.vert_italic=vi*hdelta
+ end
+ local va=character.accent
+ if va then
+ chr.top_accent=vdelta*va
+ end
+ if stackmath then
+ local mk=character.mathkerns
+ if mk then
+ local tr,tl,br,bl=mk.topright,mk.topleft,mk.bottomright,mk.bottomleft
+ chr.mathkern={
+ top_right=tr and mathkerns(tr,vdelta) or nil,
+ top_left=tl and mathkerns(tl,vdelta) or nil,
+ bottom_right=br and mathkerns(br,vdelta) or nil,
+ bottom_left=bl and mathkerns(bl,vdelta) or nil,
+ }
+ end
+ end
+ if hasitalics then
+ local vi=character.italic
+ if vi and vi~=0 then
+ chr.italic=vi*hdelta
+ end
+ end
+ elseif autoitalicamount then
+ local vi=description.italic
+ if not vi then
+ local bb=description.boundingbox
+ if bb then
+ local vi=bb[3]-description.width+autoitalicamount
+ if vi>0 then
+ chr.italic=vi*hdelta
+ end
+ else
+ end
+ elseif vi~=0 then
+ chr.italic=vi*hdelta
+ end
+ elseif hasitalics then
+ local vi=character.italic
+ if vi and vi~=0 then
+ chr.italic=vi*hdelta
+ end
+ end
+ if haskerns then
+ local vk=character.kerns
+ if vk then
+ local s=sharedkerns[vk]
+ if not s then
+ s={}
+ for k,v in next,vk do s[k]=v*hdelta end
+ sharedkerns[vk]=s
+ end
+ chr.kerns=s
+ end
+ end
+ if hasligatures then
+ local vl=character.ligatures
+ if vl then
+ if true then
+ chr.ligatures=vl
+ else
+ local tt={}
+ for i,l in next,vl do
+ tt[i]=l
+ end
+ chr.ligatures=tt
+ end
+ end
+ end
+ if isvirtual then
+ local vc=character.commands
+ if vc then
+ local ok=false
+ for i=1,#vc do
+ local key=vc[i][1]
+ if key=="right" or key=="down" or key=="rule" then
+ ok=true
+ break
+ end
+ end
+ if ok then
+ local tt={}
+ for i=1,#vc do
+ local ivc=vc[i]
+ local key=ivc[1]
+ if key=="right" then
+ tt[i]={ key,ivc[2]*hdelta }
+ elseif key=="down" then
+ tt[i]={ key,ivc[2]*vdelta }
+ elseif key=="rule" then
+ tt[i]={ key,ivc[2]*vdelta,ivc[3]*hdelta }
+ else
+ tt[i]=ivc
+ end
+ end
+ chr.commands=tt
+ else
+ chr.commands=vc
+ end
+ end
+ end
+ targetcharacters[unicode]=chr
+ end
+ properties.setitalics=hasitalics
+ constructors.aftercopyingcharacters(target,tfmdata)
+ constructors.trytosharefont(target,tfmdata)
+ local vfonts=target.fonts
+if isvirtual or target.type=="virtual" or properties.virtualized then
+ properties.virtualized=true
+target.type="virtual"
+ if not vfonts or #vfonts==0 then
+ target.fonts={ { id=0 } }
+ end
+ elseif vfonts then
+ properties.virtualized=true
+ target.type="virtual"
+ if #vfonts==0 then
+ target.fonts={ { id=0 } }
+ end
+ end
+ return target
+end
+function constructors.finalize(tfmdata)
+ if tfmdata.properties and tfmdata.properties.finalized then
+ return
+ end
+ if not tfmdata.characters then
+ return nil
+ end
+ if not tfmdata.goodies then
+ tfmdata.goodies={}
+ end
+ local parameters=tfmdata.parameters
+ if not parameters then
+ return nil
+ end
+ if not parameters.expansion then
+ parameters.expansion={
+ stretch=tfmdata.stretch or 0,
+ shrink=tfmdata.shrink or 0,
+ step=tfmdata.step or 0,
+ }
+ end
+ if not parameters.size then
+ parameters.size=tfmdata.size
+ end
+ if not parameters.mode then
+ parameters.mode=0
+ end
+ if not parameters.width then
+ parameters.width=0
+ end
+ if not parameters.slantfactor then
+ parameters.slantfactor=tfmdata.slant or 0
+ end
+ if not parameters.extendfactor then
+ parameters.extendfactor=tfmdata.extend or 0
+ end
+ if not parameters.squeezefactor then
+ parameters.squeezefactor=tfmdata.squeeze or 0
+ end
+ local designsize=parameters.designsize
+ if designsize then
+ parameters.minsize=tfmdata.minsize or designsize
+ parameters.maxsize=tfmdata.maxsize or designsize
+ else
+ designsize=factors.pt*10
+ parameters.designsize=designsize
+ parameters.minsize=designsize
+ parameters.maxsize=designsize
+ end
+ parameters.minsize=tfmdata.minsize or parameters.designsize
+ parameters.maxsize=tfmdata.maxsize or parameters.designsize
+ if not parameters.units then
+ parameters.units=tfmdata.units or tfmdata.units_per_em or 1000
+ end
+ if not tfmdata.descriptions then
+ local descriptions={}
+ setmetatableindex(descriptions,function(t,k) local v={} t[k]=v return v end)
+ tfmdata.descriptions=descriptions
+ end
+ local properties=tfmdata.properties
+ if not properties then
+ properties={}
+ tfmdata.properties=properties
+ end
+ if not properties.virtualized then
+ properties.virtualized=tfmdata.type=="virtual"
+ end
+ if not tfmdata.properties then
+ tfmdata.properties={
+ fontname=tfmdata.fontname,
+ filename=tfmdata.filename,
+ fullname=tfmdata.fullname,
+ name=tfmdata.name,
+ psname=tfmdata.psname,
+ encodingbytes=tfmdata.encodingbytes or 1,
+ embedding=tfmdata.embedding or "subset",
+ tounicode=tfmdata.tounicode or 1,
+ cidinfo=tfmdata.cidinfo or nil,
+ format=tfmdata.format or "type1",
+ direction=tfmdata.direction or 0,
+ writingmode=tfmdata.writingmode or "horizontal",
+ identity=tfmdata.identity or "horizontal",
+ }
+ end
+ if not tfmdata.resources then
+ tfmdata.resources={}
+ end
+ if not tfmdata.shared then
+ tfmdata.shared={}
+ end
+ if not properties.hasmath then
+ properties.hasmath=not tfmdata.nomath
+ end
+ tfmdata.MathConstants=nil
+ tfmdata.postprocessors=nil
+ tfmdata.fontname=nil
+ tfmdata.filename=nil
+ tfmdata.fullname=nil
+ tfmdata.name=nil
+ tfmdata.psname=nil
+ tfmdata.encodingbytes=nil
+ tfmdata.embedding=nil
+ tfmdata.tounicode=nil
+ tfmdata.cidinfo=nil
+ tfmdata.format=nil
+ tfmdata.direction=nil
+ tfmdata.type=nil
+ tfmdata.nomath=nil
+ tfmdata.designsize=nil
+ tfmdata.size=nil
+ tfmdata.stretch=nil
+ tfmdata.shrink=nil
+ tfmdata.step=nil
+ tfmdata.slant=nil
+ tfmdata.extend=nil
+ tfmdata.squeeze=nil
+ tfmdata.mode=nil
+ tfmdata.width=nil
+ tfmdata.units=nil
+ tfmdata.units_per_em=nil
+ tfmdata.cache=nil
+ properties.finalized=true
+ return tfmdata
+end
+local hashmethods={}
+constructors.hashmethods=hashmethods
+function constructors.hashfeatures(specification)
+ local features=specification.features
+ if features then
+ local t,n={},0
+ for category,list in sortedhash(features) do
+ if next(list) then
+ local hasher=hashmethods[category]
+ if hasher then
+ local hash=hasher(list)
+ if hash then
+ n=n+1
+ t[n]=category..":"..hash
+ end
+ end
+ end
+ end
+ if n>0 then
+ return concat(t," & ")
+ end
+ end
+ return "unknown"
+end
+hashmethods.normal=function(list)
+ local s={}
+ local n=0
+ for k,v in next,list do
+ if not k then
+ elseif k=="number" or k=="features" then
+ else
+ n=n+1
+ if type(v)=="table" then
+ local t={}
+ local m=0
+ for k,v in next,v do
+ m=m+1
+ t[m]=k..'='..tostring(v)
+ end
+ s[n]=k..'={'..concat(t,",").."}"
+ else
+ s[n]=k..'='..tostring(v)
+ end
+ end
+ end
+ if n>0 then
+ sort(s)
+ return concat(s,"+")
+ end
+end
+function constructors.hashinstance(specification,force)
+ local hash,size,fallbacks=specification.hash,specification.size,specification.fallbacks
+ if force or not hash then
+ hash=constructors.hashfeatures(specification)
+ specification.hash=hash
+ end
+ if size<1000 and designsizes[hash] then
+ size=round(constructors.scaled(size,designsizes[hash]))
+ else
+ size=round(size)
+ end
+ specification.size=size
+ if fallbacks then
+ return hash..' @ '..size..' @ '..fallbacks
+ else
+ return hash..' @ '..size
+ end
+end
+function constructors.setname(tfmdata,specification)
+ if constructors.namemode=="specification" then
+ local specname=specification.specification
+ if specname then
+ tfmdata.properties.name=specname
+ if trace_defining then
+ report_otf("overloaded fontname %a",specname)
+ end
+ end
+ end
+end
+function constructors.checkedfilename(data)
+ local foundfilename=data.foundfilename
+ if not foundfilename then
+ local askedfilename=data.filename or ""
+ if askedfilename~="" then
+ askedfilename=resolvers.resolve(askedfilename)
+ foundfilename=resolvers.findbinfile(askedfilename,"") or ""
+ if foundfilename=="" then
+ report_defining("source file %a is not found",askedfilename)
+ foundfilename=resolvers.findbinfile(file.basename(askedfilename),"") or ""
+ if foundfilename~="" then
+ report_defining("using source file %a due to cache mismatch",foundfilename)
+ end
+ end
+ end
+ data.foundfilename=foundfilename
+ end
+ return foundfilename
+end
+local formats=allocate()
+fonts.formats=formats
+setmetatableindex(formats,function(t,k)
+ local l=lower(k)
+ if rawget(t,k) then
+ t[k]=l
+ return l
+ end
+ return rawget(t,file.suffix(l))
+end)
+do
+ local function setindeed(mode,source,target,group,name,position)
+ local action=source[mode]
+ if not action then
+ return
+ end
+ local t=target[mode]
+ if not t then
+ report_defining("fatal error in setting feature %a, group %a, mode %a",name,group,mode)
+ os.exit()
+ elseif position then
+ insert(t,position,{ name=name,action=action })
+ else
+ for i=1,#t do
+ local ti=t[i]
+ if ti.name==name then
+ ti.action=action
+ return
+ end
+ end
+ insert(t,{ name=name,action=action })
+ end
+ end
+ local function set(group,name,target,source)
+ target=target[group]
+ if not target then
+ report_defining("fatal target error in setting feature %a, group %a",name,group)
+ os.exit()
+ end
+ local source=source[group]
+ if not source then
+ report_defining("fatal source error in setting feature %a, group %a",name,group)
+ os.exit()
+ end
+ local position=source.position
+ setindeed("node",source,target,group,name,position)
+ setindeed("base",source,target,group,name,position)
+ setindeed("plug",source,target,group,name,position)
+ end
+ local function register(where,specification)
+ local name=specification.name
+ if name and name~="" then
+ local default=specification.default
+ local description=specification.description
+ local initializers=specification.initializers
+ local processors=specification.processors
+ local manipulators=specification.manipulators
+ local modechecker=specification.modechecker
+ if default then
+ where.defaults[name]=default
+ end
+ if description and description~="" then
+ where.descriptions[name]=description
+ end
+ if initializers then
+ set('initializers',name,where,specification)
+ end
+ if processors then
+ set('processors',name,where,specification)
+ end
+ if manipulators then
+ set('manipulators',name,where,specification)
+ end
+ if modechecker then
+ where.modechecker=modechecker
+ end
+ end
+ end
+ constructors.registerfeature=register
+ function constructors.getfeatureaction(what,where,mode,name)
+ what=handlers[what].features
+ if what then
+ where=what[where]
+ if where then
+ mode=where[mode]
+ if mode then
+ for i=1,#mode do
+ local m=mode[i]
+ if m.name==name then
+ return m.action
+ end
+ end
+ end
+ end
+ end
+ end
+ local newfeatures={}
+ constructors.newfeatures=newfeatures
+ constructors.features=newfeatures
+ local function setnewfeatures(what)
+ local handler=handlers[what]
+ local features=handler.features
+ if not features then
+ local tables=handler.tables
+ local statistics=handler.statistics
+ features=allocate {
+ defaults={},
+ descriptions=tables and tables.features or {},
+ used=statistics and statistics.usedfeatures or {},
+ initializers={ base={},node={},plug={} },
+ processors={ base={},node={},plug={} },
+ manipulators={ base={},node={},plug={} },
+ }
+ features.register=function(specification) return register(features,specification) end
+ handler.features=features
+ end
+ return features
+ end
+ setmetatable(newfeatures,{
+ __call=function(t,k) local v=t[k] return v end,
+ __index=function(t,k) local v=setnewfeatures(k) t[k]=v return v end,
+ })
+end
+do
+ local newhandler={}
+ constructors.handlers=newhandler
+ constructors.newhandler=newhandler
+ local function setnewhandler(what)
+ local handler=handlers[what]
+ if not handler then
+ handler={}
+ handlers[what]=handler
+ end
+ return handler
+ end
+ setmetatable(newhandler,{
+ __call=function(t,k) local v=t[k] return v end,
+ __index=function(t,k) local v=setnewhandler(k) t[k]=v return v end,
+ })
+end
+do
+ local newenhancer={}
+ constructors.enhancers=newenhancer
+ constructors.newenhancer=newenhancer
+ local function setnewenhancer(format)
+ local handler=handlers[format]
+ local enhancers=handler.enhancers
+ if not enhancers then
+ local actions=allocate()
+ local before=allocate()
+ local after=allocate()
+ local order=allocate()
+ local known={}
+ local nofsteps=0
+ local patches={ before=before,after=after }
+ local trace=false
+ local report=logs.reporter("fonts",format.." enhancing")
+ trackers.register(format..".loading",function(v) trace=v end)
+ local function enhance(name,data,filename,raw)
+ local enhancer=actions[name]
+ if enhancer then
+ if trace then
+ report("apply enhancement %a to file %a",name,filename)
+ ioflush()
+ end
+ enhancer(data,filename,raw)
+ else
+ end
+ end
+ local function apply(data,filename,raw)
+ local basename=file.basename(lower(filename))
+ if trace then
+ report("%s enhancing file %a","start",filename)
+ end
+ ioflush()
+ for e=1,nofsteps do
+ local enhancer=order[e]
+ local b=before[enhancer]
+ if b then
+ for pattern,action in next,b do
+ if find(basename,pattern) then
+ action(data,filename,raw)
+ end
+ end
+ end
+ enhance(enhancer,data,filename,raw)
+ local a=after[enhancer]
+ if a then
+ for pattern,action in next,a do
+ if find(basename,pattern) then
+ action(data,filename,raw)
+ end
+ end
+ end
+ ioflush()
+ end
+ if trace then
+ report("%s enhancing file %a","stop",filename)
+ end
+ ioflush()
+ end
+ local function register(what,action)
+ if action then
+ if actions[what] then
+ else
+ nofsteps=nofsteps+1
+ order[nofsteps]=what
+ known[what]=nofsteps
+ end
+ actions[what]=action
+ else
+ report("bad enhancer %a",what)
+ end
+ end
+ local function patch(what,where,pattern,action)
+ local pw=patches[what]
+ if pw then
+ local ww=pw[where]
+ if ww then
+ ww[pattern]=action
+ else
+ pw[where]={ [pattern]=action }
+ if not known[where] then
+ nofsteps=nofsteps+1
+ order[nofsteps]=where
+ known[where]=nofsteps
+ end
+ end
+ end
+ end
+ enhancers={
+ register=register,
+ apply=apply,
+ patch=patch,
+ report=report,
+ patches={
+ register=patch,
+ report=report,
+ },
+ }
+ handler.enhancers=enhancers
+ end
+ return enhancers
+ end
+ setmetatable(newenhancer,{
+ __call=function(t,k) local v=t[k] return v end,
+ __index=function(t,k) local v=setnewenhancer(k) t[k]=v return v end,
+ })
+end
+function constructors.checkedfeatures(what,features)
+ local defaults=handlers[what].features.defaults
+ if features and next(features) then
+ features=fastcopy(features)
+ for key,value in next,defaults do
+ if features[key]==nil then
+ features[key]=value
+ end
+ end
+ return features
+ else
+ return fastcopy(defaults)
+ end
+end
+function constructors.initializefeatures(what,tfmdata,features,trace,report)
+ if features and next(features) then
+ local properties=tfmdata.properties or {}
+ local whathandler=handlers[what]
+ local whatfeatures=whathandler.features
+ local whatmodechecker=whatfeatures.modechecker
+ local mode=properties.mode or (whatmodechecker and whatmodechecker(tfmdata,features,features.mode)) or features.mode or "base"
+ properties.mode=mode
+ features.mode=mode
+ local done={}
+ while true do
+ local redo=false
+ local initializers=whatfeatures.initializers[mode]
+ if initializers then
+ for i=1,#initializers do
+ local step=initializers[i]
+ local feature=step.name
+ local value=features[feature]
+ if not value then
+ elseif done[feature] then
+ else
+ local action=step.action
+ if trace then
+ report("initializing feature %a to %a for mode %a for font %a",feature,
+ value,mode,tfmdata.properties.fullname)
+ end
+ action(tfmdata,value,features)
+ if mode~=properties.mode or mode~=features.mode then
+ if whatmodechecker then
+ properties.mode=whatmodechecker(tfmdata,features,properties.mode)
+ features.mode=properties.mode
+ end
+ if mode~=properties.mode then
+ mode=properties.mode
+ redo=true
+ end
+ end
+ done[feature]=true
+ end
+ if redo then
+ break
+ end
+ end
+ if not redo then
+ break
+ end
+ else
+ break
+ end
+ end
+ properties.mode=mode
+ return true
+ else
+ return false
+ end
+end
+function constructors.collectprocessors(what,tfmdata,features,trace,report)
+ local processes,nofprocesses={},0
+ if features and next(features) then
+ local properties=tfmdata.properties
+ local whathandler=handlers[what]
+ local whatfeatures=whathandler.features
+ local whatprocessors=whatfeatures.processors
+ local mode=properties.mode
+ local processors=whatprocessors[mode]
+ if processors then
+ for i=1,#processors do
+ local step=processors[i]
+ local feature=step.name
+ if features[feature] then
+ local action=step.action
+ if trace then
+ report("installing feature processor %a for mode %a for font %a",feature,mode,tfmdata.properties.fullname)
+ end
+ if action then
+ nofprocesses=nofprocesses+1
+ processes[nofprocesses]=action
+ end
+ end
+ end
+ elseif trace then
+ report("no feature processors for mode %a for font %a",mode,properties.fullname)
+ end
+ end
+ return processes
+end
+function constructors.applymanipulators(what,tfmdata,features,trace,report)
+ if features and next(features) then
+ local properties=tfmdata.properties
+ local whathandler=handlers[what]
+ local whatfeatures=whathandler.features
+ local whatmanipulators=whatfeatures.manipulators
+ local mode=properties.mode
+ local manipulators=whatmanipulators[mode]
+ if manipulators then
+ for i=1,#manipulators do
+ local step=manipulators[i]
+ local feature=step.name
+ local value=features[feature]
+ if value then
+ local action=step.action
+ if trace then
+ report("applying feature manipulator %a for mode %a for font %a",feature,mode,properties.fullname)
+ end
+ if action then
+ action(tfmdata,feature,value)
+ end
+ end
+ end
+ end
+ end
+end
+function constructors.addcoreunicodes(unicodes)
+ if not unicodes then
+ unicodes={}
+ end
+ unicodes.space=0x0020
+ unicodes.hyphen=0x002D
+ unicodes.zwj=0x200D
+ unicodes.zwnj=0x200C
+ return unicodes
+end
+
+end --- [luaotfload, fontloader-2018-09-24.lua scope for “font-con”] ---
+
+
+do --- [luaotfload, fontloader-2018-09-24.lua scope for “fonts-enc” 5ff4ca50493d7c4ecea0e15c203099f0] ---
+
+if not modules then modules={} end modules ['luatex-font-enc']={
+ version=1.001,
+ comment="companion to luatex-*.tex",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+if context then
+ os.exit()
+end
+local fonts=fonts
+local encodings={}
+fonts.encodings=encodings
+encodings.agl={}
+encodings.known={}
+setmetatable(encodings.agl,{ __index=function(t,k)
+ if k=="unicodes" then
+ logs.report("fonts","loading (extended) adobe glyph list")
+ local unicodes=dofile(resolvers.findfile("font-age.lua"))
+ encodings.agl={ unicodes=unicodes }
+ return unicodes
+ else
+ return nil
+ end
+end })
+encodings.cache=containers.define("fonts","enc",encodings.version,true)
+function encodings.load(filename)
+ local name=file.removesuffix(filename)
+ local data=containers.read(encodings.cache,name)
+ if data then
+ return data
+ end
+ local vector,tag,hash,unicodes={},"",{},{}
+ local foundname=resolvers.findfile(filename,'enc')
+ if foundname and foundname~="" then
+ local ok,encoding,size=resolvers.loadbinfile(foundname)
+ if ok and encoding then
+ encoding=string.gsub(encoding,"%%(.-)\n","")
+ local unicoding=encodings.agl.unicodes
+ local tag,vec=string.match(encoding,"/(%w+)%s*%[(.*)%]%s*def")
+ local i=0
+ for ch in string.gmatch(vec,"/([%a%d%.]+)") do
+ if ch~=".notdef" then
+ vector[i]=ch
+ if not hash[ch] then
+ hash[ch]=i
+ else
+ end
+ local u=unicoding[ch]
+ if u then
+ unicodes[u]=i
+ end
+ end
+ i=i+1
+ end
+ end
+ end
+ local data={
+ name=name,
+ tag=tag,
+ vector=vector,
+ hash=hash,
+ unicodes=unicodes
+ }
+ return containers.write(encodings.cache,name,data)
+end
+
+end --- [luaotfload, fontloader-2018-09-24.lua scope for “fonts-enc”] ---
+
+
+do --- [luaotfload, fontloader-2018-09-24.lua scope for “font-cid” 22b0367742fb253deef84ef7ccf5e8de] ---
+
+if not modules then modules={} end modules ['font-cid']={
+ version=1.001,
+ comment="companion to font-ini.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local format,match,lower=string.format,string.match,string.lower
+local tonumber=tonumber
+local P,S,R,C,V,lpegmatch=lpeg.P,lpeg.S,lpeg.R,lpeg.C,lpeg.V,lpeg.match
+local fonts,logs,trackers=fonts,logs,trackers
+local trace_loading=false trackers.register("otf.loading",function(v) trace_loading=v end)
+local report_otf=logs.reporter("fonts","otf loading")
+local cid={}
+fonts.cid=cid
+local cidmap={}
+local cidmax=10
+local number=C(R("09","af","AF")^1)
+local space=S(" \n\r\t")
+local spaces=space^0
+local period=P(".")
+local periods=period*period
+local name=P("/")*C((1-space)^1)
+local unicodes,names={},{}
+local function do_one(a,b)
+ unicodes[tonumber(a)]=tonumber(b,16)
+end
+local function do_range(a,b,c)
+ c=tonumber(c,16)
+ for i=tonumber(a),tonumber(b) do
+ unicodes[i]=c
+ c=c+1
+ end
+end
+local function do_name(a,b)
+ names[tonumber(a)]=b
+end
+local grammar=P { "start",
+ start=number*spaces*number*V("series"),
+ series=(spaces*(V("one")+V("range")+V("named")))^1,
+ one=(number*spaces*number)/do_one,
+ range=(number*periods*number*spaces*number)/do_range,
+ named=(number*spaces*name)/do_name
+}
+local function loadcidfile(filename)
+ local data=io.loaddata(filename)
+ if data then
+ unicodes,names={},{}
+ lpegmatch(grammar,data)
+ local supplement,registry,ordering=match(filename,"^(.-)%-(.-)%-()%.(.-)$")
+ return {
+ supplement=supplement,
+ registry=registry,
+ ordering=ordering,
+ filename=filename,
+ unicodes=unicodes,
+ names=names,
+ }
+ end
+end
+cid.loadfile=loadcidfile
+local template="%s-%s-%s.cidmap"
+local function locate(registry,ordering,supplement)
+ local filename=format(template,registry,ordering,supplement)
+ local hashname=lower(filename)
+ local found=cidmap[hashname]
+ if not found then
+ if trace_loading then
+ report_otf("checking cidmap, registry %a, ordering %a, supplement %a, filename %a",registry,ordering,supplement,filename)
+ end
+ local fullname=resolvers.findfile(filename,'cid') or ""
+ if fullname~="" then
+ found=loadcidfile(fullname)
+ if found then
+ if trace_loading then
+ report_otf("using cidmap file %a",filename)
+ end
+ cidmap[hashname]=found
+ found.usedname=file.basename(filename)
+ end
+ end
+ end
+ return found
+end
+function cid.getmap(specification)
+ if not specification then
+ report_otf("invalid cidinfo specification, table expected")
+ return
+ end
+ local registry=specification.registry
+ local ordering=specification.ordering
+ local supplement=specification.supplement
+ local filename=format(registry,ordering,supplement)
+ local lowername=lower(filename)
+ local found=cidmap[lowername]
+ if found then
+ return found
+ end
+ if ordering=="Identity" then
+ local found={
+ supplement=supplement,
+ registry=registry,
+ ordering=ordering,
+ filename=filename,
+ unicodes={},
+ names={},
+ }
+ cidmap[lowername]=found
+ return found
+ end
+ if trace_loading then
+ report_otf("cidmap needed, registry %a, ordering %a, supplement %a",registry,ordering,supplement)
+ end
+ found=locate(registry,ordering,supplement)
+ if not found then
+ local supnum=tonumber(supplement)
+ local cidnum=nil
+ if supnum<cidmax then
+ for s=supnum+1,cidmax do
+ local c=locate(registry,ordering,s)
+ if c then
+ found,cidnum=c,s
+ break
+ end
+ end
+ end
+ if not found and supnum>0 then
+ for s=supnum-1,0,-1 do
+ local c=locate(registry,ordering,s)
+ if c then
+ found,cidnum=c,s
+ break
+ end
+ end
+ end
+ registry=lower(registry)
+ ordering=lower(ordering)
+ if found and cidnum>0 then
+ for s=0,cidnum-1 do
+ local filename=format(template,registry,ordering,s)
+ if not cidmap[filename] then
+ cidmap[filename]=found
+ end
+ end
+ end
+ end
+ return found
+end
+
+end --- [luaotfload, fontloader-2018-09-24.lua scope for “font-cid”] ---
+
+
+do --- [luaotfload, fontloader-2018-09-24.lua scope for “font-map” 2c03dc61afabb5887ef18a88e6ec86bd] ---
+
+if not modules then modules={} end modules ['font-map']={
+ version=1.001,
+ comment="companion to font-ini.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local tonumber,next,type=tonumber,next,type
+local match,format,find,concat,gsub,lower=string.match,string.format,string.find,table.concat,string.gsub,string.lower
+local P,R,S,C,Ct,Cc,lpegmatch=lpeg.P,lpeg.R,lpeg.S,lpeg.C,lpeg.Ct,lpeg.Cc,lpeg.match
+local formatters=string.formatters
+local sortedhash,sortedkeys=table.sortedhash,table.sortedkeys
+local rshift=bit32.rshift
+local trace_loading=false trackers.register("fonts.loading",function(v) trace_loading=v end)
+local trace_mapping=false trackers.register("fonts.mapping",function(v) trace_mapping=v end)
+local report_fonts=logs.reporter("fonts","loading")
+local force_ligatures=false directives.register("fonts.mapping.forceligatures",function(v) force_ligatures=v end)
+local fonts=fonts or {}
+local mappings=fonts.mappings or {}
+fonts.mappings=mappings
+local allocate=utilities.storage.allocate
+local hex=R("AF","af","09")
+local hexfour=(hex*hex*hex^-2)/function(s) return tonumber(s,16) end
+local hexsix=(hex*hex*hex^-4)/function(s) return tonumber(s,16) end
+local dec=(R("09")^1)/tonumber
+local period=P(".")
+local unicode=(P("uni")+P("UNI"))*(hexfour*(period+P(-1))*Cc(false)+Ct(hexfour^1)*Cc(true))
+local ucode=(P("u")+P("U") )*(hexsix*(period+P(-1))*Cc(false)+Ct(hexsix^1)*Cc(true))
+local index=P("index")*dec*Cc(false)
+local parser=unicode+ucode+index
+local parsers={}
+local function makenameparser(str)
+ if not str or str=="" then
+ return parser
+ else
+ local p=parsers[str]
+ if not p then
+ p=P(str)*period*dec*Cc(false)
+ parsers[str]=p
+ end
+ return p
+ end
+end
+local f_single=formatters["%04X"]
+local f_double=formatters["%04X%04X"]
+local function tounicode16(unicode)
+ if unicode<0xD7FF or (unicode>0xDFFF and unicode<=0xFFFF) then
+ return f_single(unicode)
+ else
+ unicode=unicode-0x10000
+ return f_double(rshift(unicode,10)+0xD800,unicode%1024+0xDC00)
+ end
+end
+local function tounicode16sequence(unicodes)
+ local t={}
+ for l=1,#unicodes do
+ local u=unicodes[l]
+ if u<0xD7FF or (u>0xDFFF and u<=0xFFFF) then
+ t[l]=f_single(u)
+ else
+ u=u-0x10000
+ t[l]=f_double(rshift(u,10)+0xD800,u%1024+0xDC00)
+ end
+ end
+ return concat(t)
+end
+local unknown=f_single(0xFFFD)
+local hash={}
+local conc={}
+table.setmetatableindex(hash,function(t,k)
+ if type(k)=="table" then
+ local n=#k
+ for l=1,n do
+ conc[l]=hash[k[l]]
+ end
+ return concat(conc,"",1,n)
+ end
+ local v
+ if k>=0x00E000 and k<=0x00F8FF then
+ v=unknown
+ elseif k>=0x0F0000 and k<=0x0FFFFF then
+ v=unknown
+ elseif k>=0x100000 and k<=0x10FFFF then
+ v=unknown
+ elseif k<0xD7FF or (k>0xDFFF and k<=0xFFFF) then
+ v=f_single(k)
+ else
+ k=k-0x10000
+ v=f_double(rshift(k,10)+0xD800,k%1024+0xDC00)
+ end
+ t[k]=v
+ return v
+end)
+local function tounicode(unicode)
+ return hash[unicode]
+end
+local function fromunicode16(str)
+ if #str==4 then
+ return tonumber(str,16)
+ else
+ local l,r=match(str,"(....)(....)")
+ return 0x10000+(tonumber(l,16)-0xD800)*0x400+tonumber(r,16)-0xDC00
+ end
+end
+mappings.makenameparser=makenameparser
+mappings.tounicode=tounicode
+mappings.tounicode16=tounicode16
+mappings.tounicode16sequence=tounicode16sequence
+mappings.fromunicode16=fromunicode16
+local ligseparator=P("_")
+local varseparator=P(".")
+local namesplitter=Ct(C((1-ligseparator-varseparator)^1)*(ligseparator*C((1-ligseparator-varseparator)^1))^0)
+do
+ local overloads={
+ IJ={ name="I_J",unicode={ 0x49,0x4A },mess=0x0132 },
+ ij={ name="i_j",unicode={ 0x69,0x6A },mess=0x0133 },
+ ff={ name="f_f",unicode={ 0x66,0x66 },mess=0xFB00 },
+ fi={ name="f_i",unicode={ 0x66,0x69 },mess=0xFB01 },
+ fl={ name="f_l",unicode={ 0x66,0x6C },mess=0xFB02 },
+ ffi={ name="f_f_i",unicode={ 0x66,0x66,0x69 },mess=0xFB03 },
+ ffl={ name="f_f_l",unicode={ 0x66,0x66,0x6C },mess=0xFB04 },
+ fj={ name="f_j",unicode={ 0x66,0x6A } },
+ fk={ name="f_k",unicode={ 0x66,0x6B } },
+ }
+ local o=allocate {}
+ for k,v in next,overloads do
+ local name=v.name
+ local mess=v.mess
+ if name then
+ o[name]=v
+ end
+ if mess then
+ o[mess]=v
+ end
+ o[k]=v
+ end
+ mappings.overloads=o
+end
+function mappings.addtounicode(data,filename,checklookups,forceligatures)
+ local resources=data.resources
+ local unicodes=resources.unicodes
+ if not unicodes then
+ if trace_mapping then
+ report_fonts("no unicode list, quitting tounicode for %a",filename)
+ end
+ return
+ end
+ local properties=data.properties
+ local descriptions=data.descriptions
+ local overloads=mappings.overloads
+ unicodes['space']=unicodes['space'] or 32
+ unicodes['hyphen']=unicodes['hyphen'] or 45
+ unicodes['zwj']=unicodes['zwj'] or 0x200D
+ unicodes['zwnj']=unicodes['zwnj'] or 0x200C
+ local private=fonts.constructors and fonts.constructors.privateoffset or 0xF0000
+ local unicodevector=fonts.encodings.agl.unicodes or {}
+ local contextvector=fonts.encodings.agl.ctxcodes or {}
+ local missing={}
+ local nofmissing=0
+ local oparser=nil
+ local cidnames=nil
+ local cidcodes=nil
+ local cidinfo=properties.cidinfo
+ local usedmap=cidinfo and fonts.cid.getmap(cidinfo)
+ local uparser=makenameparser()
+ if usedmap then
+ oparser=usedmap and makenameparser(cidinfo.ordering)
+ cidnames=usedmap.names
+ cidcodes=usedmap.unicodes
+ end
+ local ns=0
+ local nl=0
+ local dlist=sortedkeys(descriptions)
+ for i=1,#dlist do
+ local du=dlist[i]
+ local glyph=descriptions[du]
+ local name=glyph.name
+ if name then
+ local overload=overloads[name] or overloads[du]
+ if overload then
+ glyph.unicode=overload.unicode
+ else
+ local gu=glyph.unicode
+ if not gu or gu==-1 or du>=private or (du>=0xE000 and du<=0xF8FF) or du==0xFFFE or du==0xFFFF then
+ local unicode=unicodevector[name] or contextvector[name]
+ if unicode then
+ glyph.unicode=unicode
+ ns=ns+1
+ end
+ if (not unicode) and usedmap then
+ local foundindex=lpegmatch(oparser,name)
+ if foundindex then
+ unicode=cidcodes[foundindex]
+ if unicode then
+ glyph.unicode=unicode
+ ns=ns+1
+ else
+ local reference=cidnames[foundindex]
+ if reference then
+ local foundindex=lpegmatch(oparser,reference)
+ if foundindex then
+ unicode=cidcodes[foundindex]
+ if unicode then
+ glyph.unicode=unicode
+ ns=ns+1
+ end
+ end
+ if not unicode or unicode=="" then
+ local foundcodes,multiple=lpegmatch(uparser,reference)
+ if foundcodes then
+ glyph.unicode=foundcodes
+ if multiple then
+ nl=nl+1
+ unicode=true
+ else
+ ns=ns+1
+ unicode=foundcodes
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ if not unicode or unicode=="" then
+ local split=lpegmatch(namesplitter,name)
+ local nsplit=split and #split or 0
+ if nsplit==0 then
+ elseif nsplit==1 then
+ local base=split[1]
+ local u=unicodes[base] or unicodevector[base] or contextvector[name]
+ if not u then
+ elseif type(u)=="table" then
+ if u[1]<private then
+ unicode=u
+ glyph.unicode=unicode
+ end
+ elseif u<private then
+ unicode=u
+ glyph.unicode=unicode
+ end
+ else
+ local t,n={},0
+ for l=1,nsplit do
+ local base=split[l]
+ local u=unicodes[base] or unicodevector[base] or contextvector[name]
+ if not u then
+ break
+ elseif type(u)=="table" then
+ if u[1]>=private then
+ break
+ end
+ n=n+1
+ t[n]=u[1]
+ else
+ if u>=private then
+ break
+ end
+ n=n+1
+ t[n]=u
+ end
+ end
+ if n>0 then
+ if n==1 then
+ unicode=t[1]
+ else
+ unicode=t
+ end
+ glyph.unicode=unicode
+ end
+ end
+ nl=nl+1
+ end
+ if not unicode or unicode=="" then
+ local foundcodes,multiple=lpegmatch(uparser,name)
+ if foundcodes then
+ glyph.unicode=foundcodes
+ if multiple then
+ nl=nl+1
+ unicode=true
+ else
+ ns=ns+1
+ unicode=foundcodes
+ end
+ end
+ end
+ local r=overloads[unicode]
+ if r then
+ unicode=r.unicode
+ glyph.unicode=unicode
+ end
+ if not unicode then
+ missing[du]=true
+ nofmissing=nofmissing+1
+ end
+ end
+ end
+ else
+ local overload=overloads[du]
+ if overload then
+ glyph.unicode=overload.unicode
+ end
+ end
+ end
+ if type(checklookups)=="function" then
+ checklookups(data,missing,nofmissing)
+ end
+ local unicoded=0
+ local collected=fonts.handlers.otf.readers.getcomponents(data)
+ local function resolve(glyph,u)
+ local n=#u
+ for i=1,n do
+ if u[i]>private then
+ n=0
+ break
+ end
+ end
+ if n>0 then
+ if n>1 then
+ glyph.unicode=u
+ else
+ glyph.unicode=u[1]
+ end
+ unicoded=unicoded+1
+ end
+ end
+ if not collected then
+ elseif forceligatures or force_ligatures then
+ for i=1,#dlist do
+ local du=dlist[i]
+ if du>=private or (du>=0xE000 and du<=0xF8FF) then
+ local u=collected[du]
+ if u then
+ resolve(descriptions[du],u)
+ end
+ end
+ end
+ else
+ for i=1,#dlist do
+ local du=dlist[i]
+ if du>=private or (du>=0xE000 and du<=0xF8FF) then
+ local glyph=descriptions[du]
+ if glyph.class=="ligature" and not glyph.unicode then
+ local u=collected[du]
+ if u then
+ resolve(glyph,u)
+ end
+ end
+ end
+ end
+ end
+ if trace_mapping and unicoded>0 then
+ report_fonts("%n ligature tounicode mappings deduced from gsub ligature features",unicoded)
+ end
+ if trace_mapping then
+ for i=1,#dlist do
+ local du=dlist[i]
+ local glyph=descriptions[du]
+ local name=glyph.name or "-"
+ local index=glyph.index or 0
+ local unicode=glyph.unicode
+ if unicode then
+ if type(unicode)=="table" then
+ local unicodes={}
+ for i=1,#unicode do
+ unicodes[i]=formatters("%U",unicode[i])
+ end
+ report_fonts("internal slot %U, name %a, unicode %U, tounicode % t",index,name,du,unicodes)
+ else
+ report_fonts("internal slot %U, name %a, unicode %U, tounicode %U",index,name,du,unicode)
+ end
+ else
+ report_fonts("internal slot %U, name %a, unicode %U",index,name,du)
+ end
+ end
+ end
+ if trace_loading and (ns>0 or nl>0) then
+ report_fonts("%s tounicode entries added, ligatures %s",nl+ns,ns)
+ end
+end
+
+end --- [luaotfload, fontloader-2018-09-24.lua scope for “font-map”] ---
+
+
+do --- [luaotfload, fontloader-2018-09-24.lua scope for “font-vfc” 237aff1862009b7850653c2098473bd4] ---
+
+if not modules then modules={} end modules ['font-vfc']={
+ version=1.001,
+ comment="companion to font-ini.mkiv and hand-ini.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local select=select
+local insert=table.insert
+local fonts=fonts
+local helpers=fonts.helpers
+local setmetatableindex=table.setmetatableindex
+local makeweak=table.makeweak
+local push={ "push" }
+local pop={ "pop" }
+local dummy={ "comment" }
+function helpers.prependcommands(commands,...)
+ insert(commands,1,push)
+ for i=select("#",...),1,-1 do
+ local s=select(i,...)
+ if s then
+ insert(commands,1,s)
+ end
+ end
+ insert(commands,pop)
+ return commands
+end
+function helpers.appendcommands(commands,...)
+ insert(commands,1,push)
+ insert(commands,pop)
+ for i=1,select("#",...) do
+ local s=select(i,...)
+ if s then
+ insert(commands,s)
+ end
+ end
+ return commands
+end
+local char=setmetatableindex(function(t,k)
+ local v={ "slot",0,k }
+ t[k]=v
+ return v
+end)
+local right=setmetatableindex(function(t,k)
+ local v={ "right",k }
+ t[k]=v
+ return v
+end)
+local left=setmetatableindex(function(t,k)
+ local v={ "right",-k }
+ t[k]=v
+ return v
+end)
+local down=setmetatableindex(function(t,k)
+ local v={ "down",k }
+ t[k]=v
+ return v
+end)
+local up=setmetatableindex(function(t,k)
+ local v={ "down",-k }
+ t[k]=v
+ return v
+end)
+helpers.commands=utilities.storage.allocate {
+ char=char,
+ right=right,
+ left=left,
+ down=down,
+ up=up,
+ push=push,
+ pop=pop,
+ dummy=dummy,
+}
+
+end --- [luaotfload, fontloader-2018-09-24.lua scope for “font-vfc”] ---
+
+
+do --- [luaotfload, fontloader-2018-09-24.lua scope for “font-otr” 4a1dae571a43d7cb8afce7e906df89c6] ---
+
+if not modules then modules={} end modules ['font-otr']={
+ version=1.001,
+ comment="companion to font-ini.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local next,type,tonumber=next,type,tonumber
+local byte,lower,char,gsub=string.byte,string.lower,string.char,string.gsub
+local floor,round=math.floor,math.round
+local P,R,S,C,Cs,Cc,Ct,Carg,Cmt=lpeg.P,lpeg.R,lpeg.S,lpeg.C,lpeg.Cs,lpeg.Cc,lpeg.Ct,lpeg.Carg,lpeg.Cmt
+local lpegmatch=lpeg.match
+local rshift=bit32.rshift
+local setmetatableindex=table.setmetatableindex
+local formatters=string.formatters
+local sortedkeys=table.sortedkeys
+local sortedhash=table.sortedhash
+local stripstring=string.nospaces
+local utf16_to_utf8_be=utf.utf16_to_utf8_be
+local report=logs.reporter("otf reader")
+local trace_cmap=false
+local trace_cmap_detail=false
+fonts=fonts or {}
+local handlers=fonts.handlers or {}
+fonts.handlers=handlers
+local otf=handlers.otf or {}
+handlers.otf=otf
+local readers=otf.readers or {}
+otf.readers=readers
+local streamreader=utilities.files
+local streamwriter=utilities.files
+readers.streamreader=streamreader
+readers.streamwriter=streamwriter
+local openfile=streamreader.open
+local closefile=streamreader.close
+local setposition=streamreader.setposition
+local skipshort=streamreader.skipshort
+local readbytes=streamreader.readbytes
+local readstring=streamreader.readstring
+local readbyte=streamreader.readcardinal1
+local readushort=streamreader.readcardinal2
+local readuint=streamreader.readcardinal3
+local readulong=streamreader.readcardinal4
+local readshort=streamreader.readinteger2
+local readlong=streamreader.readinteger4
+local readfixed=streamreader.readfixed4
+local read2dot14=streamreader.read2dot14
+local readfword=readshort
+local readufword=readushort
+local readoffset=readushort
+local readcardinaltable=streamreader.readcardinaltable
+local readintegertable=streamreader.readintegertable
+function streamreader.readtag(f)
+ return lower(stripstring(readstring(f,4)))
+end
+local short=2
+local ushort=2
+local ulong=4
+directives.register("fonts.streamreader",function()
+ streamreader=utilities.streams
+ openfile=streamreader.open
+ closefile=streamreader.close
+ setposition=streamreader.setposition
+ skipshort=streamreader.skipshort
+ readbytes=streamreader.readbytes
+ readstring=streamreader.readstring
+ readbyte=streamreader.readcardinal1
+ readushort=streamreader.readcardinal2
+ readuint=streamreader.readcardinal3
+ readulong=streamreader.readcardinal4
+ readshort=streamreader.readinteger2
+ readlong=streamreader.readinteger4
+ readfixed=streamreader.readfixed4
+ read2dot14=streamreader.read2dot14
+ readfword=readshort
+ readufword=readushort
+ readoffset=readushort
+ readcardinaltable=streamreader.readcardinaltable
+ readintegertable=streamreader.readintegertable
+ function streamreader.readtag(f)
+ return lower(stripstring(readstring(f,4)))
+ end
+end)
+local function readlongdatetime(f)
+ local a,b,c,d,e,f,g,h=readbytes(f,8)
+ return 0x100000000*d+0x1000000*e+0x10000*f+0x100*g+h
+end
+local tableversion=0.004
+readers.tableversion=tableversion
+local privateoffset=fonts.constructors and fonts.constructors.privateoffset or 0xF0000
+local reservednames={ [0]="copyright",
+ "family",
+ "subfamily",
+ "uniqueid",
+ "fullname",
+ "version",
+ "postscriptname",
+ "trademark",
+ "manufacturer",
+ "designer",
+ "description",
+ "vendorurl",
+ "designerurl",
+ "license",
+ "licenseurl",
+ "reserved",
+ "typographicfamily",
+ "typographicsubfamily",
+ "compatiblefullname",
+ "sampletext",
+ "cidfindfontname",
+ "wwsfamily",
+ "wwssubfamily",
+ "lightbackgroundpalette",
+ "darkbackgroundpalette",
+ "variationspostscriptnameprefix",
+}
+local platforms={ [0]="unicode",
+ "macintosh",
+ "iso",
+ "windows",
+ "custom",
+}
+local encodings={
+ unicode={ [0]="unicode 1.0 semantics",
+ "unicode 1.1 semantics",
+ "iso/iec 10646",
+ "unicode 2.0 bmp",
+ "unicode 2.0 full",
+ "unicode variation sequences",
+ "unicode full repertoire",
+ },
+ macintosh={ [0]="roman","japanese","chinese (traditional)","korean","arabic","hebrew","greek","russian",
+ "rsymbol","devanagari","gurmukhi","gujarati","oriya","bengali","tamil","telugu","kannada",
+ "malayalam","sinhalese","burmese","khmer","thai","laotian","georgian","armenian",
+ "chinese (simplified)","tibetan","mongolian","geez","slavic","vietnamese","sindhi",
+ "uninterpreted",
+ },
+ iso={ [0]="7-bit ascii",
+ "iso 10646",
+ "iso 8859-1",
+ },
+ windows={ [0]="symbol",
+ "unicode bmp",
+ "shiftjis",
+ "prc",
+ "big5",
+ "wansung",
+ "johab",
+ "reserved 7",
+ "reserved 8",
+ "reserved 9",
+ "unicode ucs-4",
+ },
+ custom={
+ }
+}
+local decoders={
+ unicode={},
+ macintosh={},
+ iso={},
+ windows={
+ ["unicode semantics"]=utf16_to_utf8_be,
+ ["unicode bmp"]=utf16_to_utf8_be,
+ ["unicode full"]=utf16_to_utf8_be,
+ ["unicode 1.0 semantics"]=utf16_to_utf8_be,
+ ["unicode 1.1 semantics"]=utf16_to_utf8_be,
+ ["unicode 2.0 bmp"]=utf16_to_utf8_be,
+ ["unicode 2.0 full"]=utf16_to_utf8_be,
+ ["unicode variation sequences"]=utf16_to_utf8_be,
+ ["unicode full repertoire"]=utf16_to_utf8_be,
+ },
+ custom={},
+}
+local languages={
+ unicode={
+ [ 0]="english",
+ },
+ macintosh={
+ [ 0]="english",
+ },
+ iso={},
+ windows={
+ [0x0409]="english - united states",
+ },
+ custom={},
+}
+local standardromanencoding={ [0]=
+ "notdef",".null","nonmarkingreturn","space","exclam","quotedbl",
+ "numbersign","dollar","percent","ampersand","quotesingle","parenleft",
+ "parenright","asterisk","plus","comma","hyphen","period","slash",
+ "zero","one","two","three","four","five","six","seven","eight",
+ "nine","colon","semicolon","less","equal","greater","question","at",
+ "A","B","C","D","E","F","G","H","I","J","K","L","M","N","O",
+ "P","Q","R","S","T","U","V","W","X","Y","Z","bracketleft",
+ "backslash","bracketright","asciicircum","underscore","grave","a","b",
+ "c","d","e","f","g","h","i","j","k","l","m","n","o","p","q",
+ "r","s","t","u","v","w","x","y","z","braceleft","bar",
+ "braceright","asciitilde","Adieresis","Aring","Ccedilla","Eacute",
+ "Ntilde","Odieresis","Udieresis","aacute","agrave","acircumflex",
+ "adieresis","atilde","aring","ccedilla","eacute","egrave",
+ "ecircumflex","edieresis","iacute","igrave","icircumflex","idieresis",
+ "ntilde","oacute","ograve","ocircumflex","odieresis","otilde","uacute",
+ "ugrave","ucircumflex","udieresis","dagger","degree","cent","sterling",
+ "section","bullet","paragraph","germandbls","registered","copyright",
+ "trademark","acute","dieresis","notequal","AE","Oslash","infinity",
+ "plusminus","lessequal","greaterequal","yen","mu","partialdiff",
+ "summation","product","pi","integral","ordfeminine","ordmasculine",
+ "Omega","ae","oslash","questiondown","exclamdown","logicalnot",
+ "radical","florin","approxequal","Delta","guillemotleft",
+ "guillemotright","ellipsis","nonbreakingspace","Agrave","Atilde",
+ "Otilde","OE","oe","endash","emdash","quotedblleft","quotedblright",
+ "quoteleft","quoteright","divide","lozenge","ydieresis","Ydieresis",
+ "fraction","currency","guilsinglleft","guilsinglright","fi","fl",
+ "daggerdbl","periodcentered","quotesinglbase","quotedblbase",
+ "perthousand","Acircumflex","Ecircumflex","Aacute","Edieresis","Egrave",
+ "Iacute","Icircumflex","Idieresis","Igrave","Oacute","Ocircumflex",
+ "apple","Ograve","Uacute","Ucircumflex","Ugrave","dotlessi",
+ "circumflex","tilde","macron","breve","dotaccent","ring","cedilla",
+ "hungarumlaut","ogonek","caron","Lslash","lslash","Scaron","scaron",
+ "Zcaron","zcaron","brokenbar","Eth","eth","Yacute","yacute","Thorn",
+ "thorn","minus","multiply","onesuperior","twosuperior","threesuperior",
+ "onehalf","onequarter","threequarters","franc","Gbreve","gbreve",
+ "Idotaccent","Scedilla","scedilla","Cacute","cacute","Ccaron","ccaron",
+ "dcroat",
+}
+local weights={
+ [100]="thin",
+ [200]="extralight",
+ [300]="light",
+ [400]="normal",
+ [500]="medium",
+ [600]="semibold",
+ [700]="bold",
+ [800]="extrabold",
+ [900]="black",
+}
+local widths={
+ [1]="ultracondensed",
+ [2]="extracondensed",
+ [3]="condensed",
+ [4]="semicondensed",
+ [5]="normal",
+ [6]="semiexpanded",
+ [7]="expanded",
+ [8]="extraexpanded",
+ [9]="ultraexpanded",
+}
+setmetatableindex(weights,function(t,k)
+ local r=floor((k+50)/100)*100
+ local v=(r>900 and "black") or rawget(t,r) or "normal"
+ return v
+end)
+setmetatableindex(widths,function(t,k)
+ return "normal"
+end)
+local panoseweights={
+ [ 0]="normal",
+ [ 1]="normal",
+ [ 2]="verylight",
+ [ 3]="light",
+ [ 4]="thin",
+ [ 5]="book",
+ [ 6]="medium",
+ [ 7]="demi",
+ [ 8]="bold",
+ [ 9]="heavy",
+ [10]="black",
+}
+local panosewidths={
+ [ 0]="normal",
+ [ 1]="normal",
+ [ 2]="normal",
+ [ 3]="normal",
+ [ 4]="normal",
+ [ 5]="expanded",
+ [ 6]="condensed",
+ [ 7]="veryexpanded",
+ [ 8]="verycondensed",
+ [ 9]="monospaced",
+}
+local helpers={}
+readers.helpers=helpers
+local function gotodatatable(f,fontdata,tag,criterium)
+ if criterium and f then
+ local datatable=fontdata.tables[tag]
+ if datatable then
+ local tableoffset=datatable.offset
+ setposition(f,tableoffset)
+ return tableoffset
+ end
+ end
+end
+local function reportskippedtable(f,fontdata,tag,criterium)
+ if criterium and f then
+ local datatable=fontdata.tables[tag]
+ if datatable then
+ report("loading of table %a skipped",tag)
+ end
+ end
+end
+local function setvariabledata(fontdata,tag,data)
+ local variabledata=fontdata.variabledata
+ if variabledata then
+ variabledata[tag]=data
+ else
+ fontdata.variabledata={ [tag]=data }
+ end
+end
+helpers.gotodatatable=gotodatatable
+helpers.setvariabledata=setvariabledata
+helpers.reportskippedtable=reportskippedtable
+local platformnames={
+ postscriptname=true,
+ fullname=true,
+ family=true,
+ subfamily=true,
+ typographicfamily=true,
+ typographicsubfamily=true,
+ compatiblefullname=true,
+}
+function readers.name(f,fontdata,specification)
+ local tableoffset=gotodatatable(f,fontdata,"name",true)
+ if tableoffset then
+ local format=readushort(f)
+ local nofnames=readushort(f)
+ local offset=readushort(f)
+ local start=tableoffset+offset
+ local namelists={
+ unicode={},
+ windows={},
+ macintosh={},
+ }
+ for i=1,nofnames do
+ local platform=platforms[readushort(f)]
+ if platform then
+ local namelist=namelists[platform]
+ if namelist then
+ local encoding=readushort(f)
+ local language=readushort(f)
+ local encodings=encodings[platform]
+ local languages=languages[platform]
+ if encodings and languages then
+ local encoding=encodings[encoding]
+ local language=languages[language]
+ if encoding and language then
+ local index=readushort(f)
+ local name=reservednames[index]
+ namelist[#namelist+1]={
+ platform=platform,
+ encoding=encoding,
+ language=language,
+ name=name,
+ index=index,
+ length=readushort(f),
+ offset=start+readushort(f),
+ }
+ else
+ skipshort(f,3)
+ end
+ else
+ skipshort(f,3)
+ end
+ else
+ skipshort(f,5)
+ end
+ else
+ skipshort(f,5)
+ end
+ end
+ local names={}
+ local done={}
+ local extras={}
+ local function filter(platform,e,l)
+ local namelist=namelists[platform]
+ for i=1,#namelist do
+ local name=namelist[i]
+ local nametag=name.name
+ local index=name.index
+ if not done[nametag or i] then
+ local encoding=name.encoding
+ local language=name.language
+ if (not e or encoding==e) and (not l or language==l) then
+ setposition(f,name.offset)
+ local content=readstring(f,name.length)
+ local decoder=decoders[platform]
+ if decoder then
+ decoder=decoder[encoding]
+ end
+ if decoder then
+ content=decoder(content)
+ end
+ if nametag then
+ names[nametag]={
+ content=content,
+ platform=platform,
+ encoding=encoding,
+ language=language,
+ }
+ end
+ extras[index]=content
+ done[nametag or i]=true
+ end
+ end
+ end
+ end
+ filter("windows","unicode bmp","english - united states")
+ filter("macintosh","roman","english")
+ filter("windows")
+ filter("macintosh")
+ filter("unicode")
+ fontdata.names=names
+ fontdata.extras=extras
+ if specification.platformnames then
+ local collected={}
+ for platform,namelist in next,namelists do
+ local filtered=false
+ for i=1,#namelist do
+ local entry=namelist[i]
+ local name=entry.name
+ if platformnames[name] then
+ setposition(f,entry.offset)
+ local content=readstring(f,entry.length)
+ local encoding=entry.encoding
+ local decoder=decoders[platform]
+ if decoder then
+ decoder=decoder[encoding]
+ end
+ if decoder then
+ content=decoder(content)
+ end
+ if filtered then
+ filtered[name]=content
+ else
+ filtered={ [name]=content }
+ end
+ end
+ end
+ if filtered then
+ collected[platform]=filtered
+ end
+ end
+ fontdata.platformnames=collected
+ end
+ else
+ fontdata.names={}
+ end
+end
+local validutf=lpeg.patterns.validutf8
+local function getname(fontdata,key)
+ local names=fontdata.names
+ if names then
+ local value=names[key]
+ if value then
+ local content=value.content
+ return lpegmatch(validutf,content) and content or nil
+ end
+ end
+end
+readers["os/2"]=function(f,fontdata)
+ local tableoffset=gotodatatable(f,fontdata,"os/2",true)
+ if tableoffset then
+ local version=readushort(f)
+ local windowsmetrics={
+ version=version,
+ averagewidth=readshort(f),
+ weightclass=readushort(f),
+ widthclass=readushort(f),
+ fstype=readushort(f),
+ subscriptxsize=readshort(f),
+ subscriptysize=readshort(f),
+ subscriptxoffset=readshort(f),
+ subscriptyoffset=readshort(f),
+ superscriptxsize=readshort(f),
+ superscriptysize=readshort(f),
+ superscriptxoffset=readshort(f),
+ superscriptyoffset=readshort(f),
+ strikeoutsize=readshort(f),
+ strikeoutpos=readshort(f),
+ familyclass=readshort(f),
+ panose={ readbytes(f,10) },
+ unicoderanges={ readulong(f),readulong(f),readulong(f),readulong(f) },
+ vendor=readstring(f,4),
+ fsselection=readushort(f),
+ firstcharindex=readushort(f),
+ lastcharindex=readushort(f),
+ typoascender=readshort(f),
+ typodescender=readshort(f),
+ typolinegap=readshort(f),
+ winascent=readushort(f),
+ windescent=readushort(f),
+ }
+ if version>=1 then
+ windowsmetrics.codepageranges={ readulong(f),readulong(f) }
+ end
+ if version>=3 then
+ windowsmetrics.xheight=readshort(f)
+ windowsmetrics.capheight=readshort(f)
+ windowsmetrics.defaultchar=readushort(f)
+ windowsmetrics.breakchar=readushort(f)
+ end
+ windowsmetrics.weight=windowsmetrics.weightclass and weights[windowsmetrics.weightclass]
+ windowsmetrics.width=windowsmetrics.widthclass and widths [windowsmetrics.widthclass]
+ windowsmetrics.panoseweight=panoseweights[windowsmetrics.panose[3]]
+ windowsmetrics.panosewidth=panosewidths [windowsmetrics.panose[4]]
+ fontdata.windowsmetrics=windowsmetrics
+ else
+ fontdata.windowsmetrics={}
+ end
+end
+readers.head=function(f,fontdata)
+ local tableoffset=gotodatatable(f,fontdata,"head",true)
+ if tableoffset then
+ local fontheader={
+ version=readfixed(f),
+ revision=readfixed(f),
+ checksum=readulong(f),
+ magic=readulong(f),
+ flags=readushort(f),
+ units=readushort(f),
+ created=readlongdatetime(f),
+ modified=readlongdatetime(f),
+ xmin=readshort(f),
+ ymin=readshort(f),
+ xmax=readshort(f),
+ ymax=readshort(f),
+ macstyle=readushort(f),
+ smallpixels=readushort(f),
+ directionhint=readshort(f),
+ indextolocformat=readshort(f),
+ glyphformat=readshort(f),
+ }
+ fontdata.fontheader=fontheader
+ else
+ fontdata.fontheader={}
+ end
+ fontdata.nofglyphs=0
+end
+readers.hhea=function(f,fontdata,specification)
+ local tableoffset=gotodatatable(f,fontdata,"hhea",specification.details)
+ if tableoffset then
+ fontdata.horizontalheader={
+ version=readfixed(f),
+ ascender=readfword(f),
+ descender=readfword(f),
+ linegap=readfword(f),
+ maxadvancewidth=readufword(f),
+ minleftsidebearing=readfword(f),
+ minrightsidebearing=readfword(f),
+ maxextent=readfword(f),
+ caretsloperise=readshort(f),
+ caretsloperun=readshort(f),
+ caretoffset=readshort(f),
+ reserved_1=readshort(f),
+ reserved_2=readshort(f),
+ reserved_3=readshort(f),
+ reserved_4=readshort(f),
+ metricdataformat=readshort(f),
+ nofmetrics=readushort(f),
+ }
+ else
+ fontdata.horizontalheader={
+ nofmetrics=0,
+ }
+ end
+end
+readers.vhea=function(f,fontdata,specification)
+ local tableoffset=gotodatatable(f,fontdata,"vhea",specification.details)
+ if tableoffset then
+ fontdata.verticalheader={
+ version=readfixed(f),
+ ascender=readfword(f),
+ descender=readfword(f),
+ linegap=readfword(f),
+ maxadvanceheight=readufword(f),
+ mintopsidebearing=readfword(f),
+ minbottomsidebearing=readfword(f),
+ maxextent=readfword(f),
+ caretsloperise=readshort(f),
+ caretsloperun=readshort(f),
+ caretoffset=readshort(f),
+ reserved_1=readshort(f),
+ reserved_2=readshort(f),
+ reserved_3=readshort(f),
+ reserved_4=readshort(f),
+ metricdataformat=readshort(f),
+ nofmetrics=readushort(f),
+ }
+ else
+ fontdata.verticalheader={
+ nofmetrics=0,
+ }
+ end
+end
+readers.maxp=function(f,fontdata,specification)
+ local tableoffset=gotodatatable(f,fontdata,"maxp",specification.details)
+ if tableoffset then
+ local version=readfixed(f)
+ local nofglyphs=readushort(f)
+ fontdata.nofglyphs=nofglyphs
+ if version==0.5 then
+ fontdata.maximumprofile={
+ version=version,
+ nofglyphs=nofglyphs,
+ }
+ elseif version==1.0 then
+ fontdata.maximumprofile={
+ version=version,
+ nofglyphs=nofglyphs,
+ points=readushort(f),
+ contours=readushort(f),
+ compositepoints=readushort(f),
+ compositecontours=readushort(f),
+ zones=readushort(f),
+ twilightpoints=readushort(f),
+ storage=readushort(f),
+ functiondefs=readushort(f),
+ instructiondefs=readushort(f),
+ stackelements=readushort(f),
+ sizeofinstructions=readushort(f),
+ componentelements=readushort(f),
+ componentdepth=readushort(f),
+ }
+ else
+ fontdata.maximumprofile={
+ version=version,
+ nofglyphs=0,
+ }
+ end
+ end
+end
+readers.hmtx=function(f,fontdata,specification)
+ local tableoffset=gotodatatable(f,fontdata,"hmtx",specification.glyphs)
+ if tableoffset then
+ local horizontalheader=fontdata.horizontalheader
+ local nofmetrics=horizontalheader.nofmetrics
+ local glyphs=fontdata.glyphs
+ local nofglyphs=fontdata.nofglyphs
+ local width=0
+ local leftsidebearing=0
+ for i=0,nofmetrics-1 do
+ local glyph=glyphs[i]
+ width=readshort(f)
+ leftsidebearing=readshort(f)
+ if width~=0 then
+ glyph.width=width
+ end
+ end
+ for i=nofmetrics,nofglyphs-1 do
+ local glyph=glyphs[i]
+ if width~=0 then
+ glyph.width=width
+ end
+ end
+ end
+end
+readers.vmtx=function(f,fontdata,specification)
+ local tableoffset=gotodatatable(f,fontdata,"vmtx",specification.glyphs)
+ if tableoffset then
+ local verticalheader=fontdata.verticalheader
+ local nofmetrics=verticalheader.nofmetrics
+ local glyphs=fontdata.glyphs
+ local nofglyphs=fontdata.nofglyphs
+ local vheight=0
+ local vdefault=verticalheader.ascender+verticalheader.descender
+ local topsidebearing=0
+ for i=0,nofmetrics-1 do
+ local glyph=glyphs[i]
+ vheight=readshort(f)
+ topsidebearing=readshort(f)
+ if vheight~=0 and vheight~=vdefault then
+ glyph.vheight=vheight
+ end
+ end
+ for i=nofmetrics,nofglyphs-1 do
+ local glyph=glyphs[i]
+ if vheight~=0 and vheight~=vdefault then
+ glyph.vheight=vheight
+ end
+ end
+ end
+end
+readers.vorg=function(f,fontdata,specification)
+ reportskippedtable(f,fontdata,"vorg",specification.glyphs)
+end
+readers.post=function(f,fontdata,specification)
+ local tableoffset=gotodatatable(f,fontdata,"post",true)
+ if tableoffset then
+ local version=readfixed(f)
+ fontdata.postscript={
+ version=version,
+ italicangle=round(1000*readfixed(f))/1000,
+ underlineposition=readfword(f),
+ underlinethickness=readfword(f),
+ monospaced=readulong(f),
+ minmemtype42=readulong(f),
+ maxmemtype42=readulong(f),
+ minmemtype1=readulong(f),
+ maxmemtype1=readulong(f),
+ }
+ if not specification.glyphs then
+ elseif version==1.0 then
+ for index=0,#standardromanencoding do
+ glyphs[index].name=standardromanencoding[index]
+ end
+ elseif version==2.0 then
+ local glyphs=fontdata.glyphs
+ local nofglyphs=readushort(f)
+ local indices={}
+ local names={}
+ local maxnames=0
+ for i=0,nofglyphs-1 do
+ local nameindex=readushort(f)
+ if nameindex>=258 then
+ maxnames=maxnames+1
+ nameindex=nameindex-257
+ indices[nameindex]=i
+ else
+ glyphs[i].name=standardromanencoding[nameindex]
+ end
+ end
+ for i=1,maxnames do
+ local mapping=indices[i]
+ if not mapping then
+ report("quit post name fetching at %a of %a: %s",i,maxnames,"no index")
+ break
+ else
+ local length=readbyte(f)
+ if length>0 then
+ glyphs[mapping].name=readstring(f,length)
+ else
+ report("quit post name fetching at %a of %a: %s",i,maxnames,"overflow")
+ break
+ end
+ end
+ end
+ elseif version==2.5 then
+ elseif version==3.0 then
+ end
+ else
+ fontdata.postscript={}
+ end
+end
+readers.cff=function(f,fontdata,specification)
+ reportskippedtable(f,fontdata,"cff",specification.glyphs)
+end
+local formatreaders={}
+local duplicatestoo=true
+local sequence={
+ { 3,1,4 },
+ { 3,10,12 },
+ { 0,3,4 },
+ { 0,1,4 },
+ { 0,0,6 },
+ { 3,0,6 },
+ { 0,5,14 },
+{ 0,4,12 },
+ { 3,10,13 },
+}
+local supported={}
+for i=1,#sequence do
+ local si=sequence[i]
+ local sp,se,sf=si[1],si[2],si[3]
+ local p=supported[sp]
+ if not p then
+ p={}
+ supported[sp]=p
+ end
+ local e=p[se]
+ if not e then
+ e={}
+ p[se]=e
+ end
+ e[sf]=true
+end
+formatreaders[4]=function(f,fontdata,offset)
+ setposition(f,offset+2)
+ local length=readushort(f)
+ local language=readushort(f)
+ local nofsegments=readushort(f)/2
+ skipshort(f,3)
+ local mapping=fontdata.mapping
+ local glyphs=fontdata.glyphs
+ local duplicates=fontdata.duplicates
+ local nofdone=0
+ local endchars=readcardinaltable(f,nofsegments,ushort)
+ local reserved=readushort(f)
+ local startchars=readcardinaltable(f,nofsegments,ushort)
+ local deltas=readcardinaltable(f,nofsegments,ushort)
+ local offsets=readcardinaltable(f,nofsegments,ushort)
+ local size=(length-2*2-5*2-4*2*nofsegments)/2
+ local indices=readcardinaltable(f,size-1,ushort)
+ for segment=1,nofsegments do
+ local startchar=startchars[segment]
+ local endchar=endchars[segment]
+ local offset=offsets[segment]
+ local delta=deltas[segment]
+ if startchar==0xFFFF and endchar==0xFFFF then
+ elseif startchar==0xFFFF and offset==0 then
+ elseif offset==0xFFFF then
+ elseif offset==0 then
+ if trace_cmap_detail then
+ report("format 4.%i segment %2i from %C upto %C at index %H",1,segment,startchar,endchar,(startchar+delta)%65536)
+ end
+ for unicode=startchar,endchar do
+ local index=(unicode+delta)%65536
+ if index and index>0 then
+ local glyph=glyphs[index]
+ if glyph then
+ local gu=glyph.unicode
+ if not gu then
+ glyph.unicode=unicode
+ nofdone=nofdone+1
+ elseif gu~=unicode then
+ if duplicatestoo then
+ local d=duplicates[gu]
+ if d then
+ d[unicode]=true
+ else
+ duplicates[gu]={ [unicode]=true }
+ end
+ else
+ report("duplicate case 1: %C %04i %s",unicode,index,glyphs[index].name)
+ end
+ end
+ if not mapping[index] then
+ mapping[index]=unicode
+ end
+ end
+ end
+ end
+ else
+ local shift=(segment-nofsegments+offset/2)-startchar
+ if trace_cmap_detail then
+ report("format 4.%i segment %2i from %C upto %C at index %H",0,segment,startchar,endchar,(startchar+delta)%65536)
+ end
+ for unicode=startchar,endchar do
+ local slot=shift+unicode
+ local index=indices[slot]
+ if index and index>0 then
+ index=(index+delta)%65536
+ local glyph=glyphs[index]
+ if glyph then
+ local gu=glyph.unicode
+ if not gu then
+ glyph.unicode=unicode
+ nofdone=nofdone+1
+ elseif gu~=unicode then
+ if duplicatestoo then
+ local d=duplicates[gu]
+ if d then
+ d[unicode]=true
+ else
+ duplicates[gu]={ [unicode]=true }
+ end
+ else
+ report("duplicate case 2: %C %04i %s",unicode,index,glyphs[index].name)
+ end
+ end
+ if not mapping[index] then
+ mapping[index]=unicode
+ end
+ end
+ end
+ end
+ end
+ end
+ return nofdone
+end
+formatreaders[6]=function(f,fontdata,offset)
+ setposition(f,offset)
+ local format=readushort(f)
+ local length=readushort(f)
+ local language=readushort(f)
+ local mapping=fontdata.mapping
+ local glyphs=fontdata.glyphs
+ local duplicates=fontdata.duplicates
+ local start=readushort(f)
+ local count=readushort(f)
+ local stop=start+count-1
+ local nofdone=0
+ if trace_cmap_detail then
+ report("format 6 from %C to %C",2,start,stop)
+ end
+ for unicode=start,stop do
+ local index=readushort(f)
+ if index>0 then
+ local glyph=glyphs[index]
+ if glyph then
+ local gu=glyph.unicode
+ if not gu then
+ glyph.unicode=unicode
+ nofdone=nofdone+1
+ elseif gu~=unicode then
+ end
+ if not mapping[index] then
+ mapping[index]=unicode
+ end
+ end
+ end
+ end
+ return nofdone
+end
+formatreaders[12]=function(f,fontdata,offset)
+ setposition(f,offset+2+2+4+4)
+ local mapping=fontdata.mapping
+ local glyphs=fontdata.glyphs
+ local duplicates=fontdata.duplicates
+ local nofgroups=readulong(f)
+ local nofdone=0
+ for i=1,nofgroups do
+ local first=readulong(f)
+ local last=readulong(f)
+ local index=readulong(f)
+ if trace_cmap_detail then
+ report("format 12 from %C to %C starts at index %i",first,last,index)
+ end
+ for unicode=first,last do
+ local glyph=glyphs[index]
+ if glyph then
+ local gu=glyph.unicode
+ if not gu then
+ glyph.unicode=unicode
+ nofdone=nofdone+1
+ elseif gu~=unicode then
+ local d=duplicates[gu]
+ if d then
+ d[unicode]=true
+ else
+ duplicates[gu]={ [unicode]=true }
+ end
+ end
+ if not mapping[index] then
+ mapping[index]=unicode
+ end
+ end
+ index=index+1
+ end
+ end
+ return nofdone
+end
+formatreaders[13]=function(f,fontdata,offset)
+ setposition(f,offset+2+2+4+4)
+ local mapping=fontdata.mapping
+ local glyphs=fontdata.glyphs
+ local duplicates=fontdata.duplicates
+ local nofgroups=readulong(f)
+ local nofdone=0
+ for i=1,nofgroups do
+ local first=readulong(f)
+ local last=readulong(f)
+ local index=readulong(f)
+ if first<privateoffset then
+ if trace_cmap_detail then
+ report("format 13 from %C to %C get index %i",first,last,index)
+ end
+ local glyph=glyphs[index]
+ local unicode=glyph.unicode
+ if not unicode then
+ unicode=first
+ glyph.unicode=unicode
+ first=first+1
+ end
+ local list=duplicates[unicode]
+ mapping[index]=unicode
+ if not list then
+ list={}
+ duplicates[unicode]=list
+ end
+ if last>=privateoffset then
+ local limit=privateoffset-1
+ report("format 13 from %C to %C pruned to %C",first,last,limit)
+ last=limit
+ end
+ for unicode=first,last do
+ list[unicode]=true
+ end
+ nofdone=nofdone+last-first+1
+ else
+ report("format 13 from %C to %C ignored",first,last)
+ end
+ end
+ return nofdone
+end
+formatreaders[14]=function(f,fontdata,offset)
+ if offset and offset~=0 then
+ setposition(f,offset)
+ local format=readushort(f)
+ local length=readulong(f)
+ local nofrecords=readulong(f)
+ local records={}
+ local variants={}
+ local nofdone=0
+ fontdata.variants=variants
+ for i=1,nofrecords do
+ records[i]={
+ selector=readuint(f),
+ default=readulong(f),
+ other=readulong(f),
+ }
+ end
+ for i=1,nofrecords do
+ local record=records[i]
+ local selector=record.selector
+ local default=record.default
+ local other=record.other
+ local other=record.other
+ if other~=0 then
+ setposition(f,offset+other)
+ local mapping={}
+ local count=readulong(f)
+ for i=1,count do
+ mapping[readuint(f)]=readushort(f)
+ end
+ nofdone=nofdone+count
+ variants[selector]=mapping
+ end
+ end
+ return nofdone
+ else
+ return 0
+ end
+end
+local function checkcmap(f,fontdata,records,platform,encoding,format)
+ local data=records[platform]
+ if not data then
+ return 0
+ end
+ data=data[encoding]
+ if not data then
+ return 0
+ end
+ data=data[format]
+ if not data then
+ return 0
+ end
+ local reader=formatreaders[format]
+ if not reader then
+ return 0
+ end
+ local p=platforms[platform]
+ local e=encodings[p]
+ local n=reader(f,fontdata,data) or 0
+ if trace_cmap then
+ report("cmap checked: platform %i (%s), encoding %i (%s), format %i, new unicodes %i",platform,p,encoding,e and e[encoding] or "?",format,n)
+ end
+ return n
+end
+function readers.cmap(f,fontdata,specification)
+ local tableoffset=gotodatatable(f,fontdata,"cmap",specification.glyphs)
+ if tableoffset then
+ local version=readushort(f)
+ local noftables=readushort(f)
+ local records={}
+ local unicodecid=false
+ local variantcid=false
+ local variants={}
+ local duplicates=fontdata.duplicates or {}
+ fontdata.duplicates=duplicates
+ for i=1,noftables do
+ local platform=readushort(f)
+ local encoding=readushort(f)
+ local offset=readulong(f)
+ local record=records[platform]
+ if not record then
+ records[platform]={
+ [encoding]={
+ offsets={ offset },
+ formats={},
+ }
+ }
+ else
+ local subtables=record[encoding]
+ if not subtables then
+ record[encoding]={
+ offsets={ offset },
+ formats={},
+ }
+ else
+ local offsets=subtables.offsets
+ offsets[#offsets+1]=offset
+ end
+ end
+ end
+ if trace_cmap then
+ report("found cmaps:")
+ end
+ for platform,record in sortedhash(records) do
+ local p=platforms[platform]
+ local e=encodings[p]
+ local sp=supported[platform]
+ local ps=p or "?"
+ if trace_cmap then
+ if sp then
+ report(" platform %i: %s",platform,ps)
+ else
+ report(" platform %i: %s (unsupported)",platform,ps)
+ end
+ end
+ for encoding,subtables in sortedhash(record) do
+ local se=sp and sp[encoding]
+ local es=e and e[encoding] or "?"
+ if trace_cmap then
+ if se then
+ report(" encoding %i: %s",encoding,es)
+ else
+ report(" encoding %i: %s (unsupported)",encoding,es)
+ end
+ end
+ local offsets=subtables.offsets
+ local formats=subtables.formats
+ for i=1,#offsets do
+ local offset=tableoffset+offsets[i]
+ setposition(f,offset)
+ formats[readushort(f)]=offset
+ end
+ record[encoding]=formats
+ if trace_cmap then
+ local list=sortedkeys(formats)
+ for i=1,#list do
+ if not (se and se[list[i]]) then
+ list[i]=list[i].." (unsupported)"
+ end
+ end
+ report(" formats: % t",list)
+ end
+ end
+ end
+ local ok=false
+ for i=1,#sequence do
+ local si=sequence[i]
+ local sp,se,sf=si[1],si[2],si[3]
+ if checkcmap(f,fontdata,records,sp,se,sf)>0 then
+ ok=true
+ end
+ end
+ if not ok then
+ report("no useable unicode cmap found")
+ end
+ fontdata.cidmaps={
+ version=version,
+ noftables=noftables,
+ records=records,
+ }
+ else
+ fontdata.cidmaps={}
+ end
+end
+function readers.loca(f,fontdata,specification)
+ reportskippedtable(f,fontdata,"loca",specification.glyphs)
+end
+function readers.glyf(f,fontdata,specification)
+ reportskippedtable(f,fontdata,"glyf",specification.glyphs)
+end
+function readers.colr(f,fontdata,specification)
+ reportskippedtable(f,fontdata,"colr",specification.glyphs)
+end
+function readers.cpal(f,fontdata,specification)
+ reportskippedtable(f,fontdata,"cpal",specification.glyphs)
+end
+function readers.svg(f,fontdata,specification)
+ reportskippedtable(f,fontdata,"svg",specification.glyphs)
+end
+function readers.sbix(f,fontdata,specification)
+ reportskippedtable(f,fontdata,"sbix",specification.glyphs)
+end
+function readers.cbdt(f,fontdata,specification)
+ reportskippedtable(f,fontdata,"cbdt",specification.glyphs)
+end
+function readers.cblc(f,fontdata,specification)
+ reportskippedtable(f,fontdata,"cblc",specification.glyphs)
+end
+function readers.ebdt(f,fontdata,specification)
+ reportskippedtable(f,fontdata,"ebdt",specification.glyphs)
+end
+function readers.ebsc(f,fontdata,specification)
+ reportskippedtable(f,fontdata,"ebsc",specification.glyphs)
+end
+function readers.eblc(f,fontdata,specification)
+ reportskippedtable(f,fontdata,"eblc",specification.glyphs)
+end
+function readers.kern(f,fontdata,specification)
+ local tableoffset=gotodatatable(f,fontdata,"kern",specification.kerns)
+ if tableoffset then
+ local version=readushort(f)
+ local noftables=readushort(f)
+ for i=1,noftables do
+ local version=readushort(f)
+ local length=readushort(f)
+ local coverage=readushort(f)
+ local format=rshift(coverage,8)
+ if format==0 then
+ local nofpairs=readushort(f)
+ local searchrange=readushort(f)
+ local entryselector=readushort(f)
+ local rangeshift=readushort(f)
+ local kerns={}
+ local glyphs=fontdata.glyphs
+ for i=1,nofpairs do
+ local left=readushort(f)
+ local right=readushort(f)
+ local kern=readfword(f)
+ local glyph=glyphs[left]
+ local kerns=glyph.kerns
+ if kerns then
+ kerns[right]=kern
+ else
+ glyph.kerns={ [right]=kern }
+ end
+ end
+ elseif format==2 then
+ report("todo: kern classes")
+ else
+ report("todo: kerns")
+ end
+ end
+ end
+end
+function readers.gdef(f,fontdata,specification)
+ reportskippedtable(f,fontdata,"gdef",specification.details)
+end
+function readers.gsub(f,fontdata,specification)
+ reportskippedtable(f,fontdata,"gsub",specification.details)
+end
+function readers.gpos(f,fontdata,specification)
+ reportskippedtable(f,fontdata,"gpos",specification.details)
+end
+function readers.math(f,fontdata,specification)
+ reportskippedtable(f,fontdata,"math",specification.details)
+end
+local function getinfo(maindata,sub,platformnames,rawfamilynames,metricstoo,instancenames)
+ local fontdata=sub and maindata.subfonts and maindata.subfonts[sub] or maindata
+ local names=fontdata.names
+ local info=nil
+ if names then
+ local metrics=fontdata.windowsmetrics or {}
+ local postscript=fontdata.postscript or {}
+ local fontheader=fontdata.fontheader or {}
+ local cffinfo=fontdata.cffinfo or {}
+ local filename=fontdata.filename
+ local weight=getname(fontdata,"weight") or (cffinfo and cffinfo.weight) or (metrics and metrics.weight)
+ local width=getname(fontdata,"width") or (cffinfo and cffinfo.width ) or (metrics and metrics.width )
+ local fontname=getname(fontdata,"postscriptname")
+ local fullname=getname(fontdata,"fullname")
+ local family=getname(fontdata,"family")
+ local subfamily=getname(fontdata,"subfamily")
+ local familyname=getname(fontdata,"typographicfamily")
+ local subfamilyname=getname(fontdata,"typographicsubfamily")
+ local compatiblename=getname(fontdata,"compatiblefullname")
+ if rawfamilynames then
+ else
+ if not familyname then familyname=family end
+ if not subfamilyname then subfamilyname=subfamily end
+ end
+ if platformnames then
+ platformnames=fontdata.platformnames
+ end
+ if instancenames then
+ local variabledata=fontdata.variabledata
+ if variabledata then
+ local instances=variabledata and variabledata.instances
+ if instances then
+ instancenames={}
+ for i=1,#instances do
+ instancenames[i]=lower(stripstring(instances[i].subfamily))
+ end
+ else
+ instancenames=nil
+ end
+ else
+ instancenames=nil
+ end
+ end
+ info={
+ subfontindex=fontdata.subfontindex or sub or 0,
+ version=getname(fontdata,"version"),
+ fontname=fontname,
+ fullname=fullname,
+ family=family,
+ subfamily=subfamily,
+ familyname=familyname,
+ subfamilyname=subfamilyname,
+ compatiblename=compatiblename,
+ weight=weight and lower(weight),
+ width=width and lower(width),
+ pfmweight=metrics.weightclass or 400,
+ pfmwidth=metrics.widthclass or 5,
+ panosewidth=metrics.panosewidth,
+ panoseweight=metrics.panoseweight,
+ italicangle=postscript.italicangle or 0,
+ units=fontheader.units or 0,
+ designsize=fontdata.designsize,
+ minsize=fontdata.minsize,
+ maxsize=fontdata.maxsize,
+ monospaced=(tonumber(postscript.monospaced or 0)>0) or metrics.panosewidth=="monospaced",
+ averagewidth=metrics.averagewidth,
+ xheight=metrics.xheight,
+ capheight=metrics.capheight,
+ ascender=metrics.typoascender,
+ descender=metrics.typodescender,
+ platformnames=platformnames or nil,
+ instancenames=instancenames or nil,
+ }
+ if metricstoo then
+ local keys={
+ "version",
+ "ascender","descender","linegap",
+ "maxadvancewidth","maxadvanceheight","maxextent",
+ "minbottomsidebearing","mintopsidebearing",
+ }
+ local h=fontdata.horizontalheader or {}
+ local v=fontdata.verticalheader or {}
+ if h then
+ local th={}
+ local tv={}
+ for i=1,#keys do
+ local key=keys[i]
+ th[key]=h[key] or 0
+ tv[key]=v[key] or 0
+ end
+ info.horizontalmetrics=th
+ info.verticalmetrics=tv
+ end
+ end
+ elseif n then
+ info={
+ filename=fontdata.filename,
+ comment="there is no info for subfont "..n,
+ }
+ else
+ info={
+ filename=fontdata.filename,
+ comment="there is no info",
+ }
+ end
+ return info
+end
+local function loadtables(f,specification,offset)
+ if offset then
+ setposition(f,offset)
+ end
+ local tables={}
+ local basename=file.basename(specification.filename)
+ local filesize=specification.filesize
+ local filetime=specification.filetime
+ local fontdata={
+ filename=basename,
+ filesize=filesize,
+ filetime=filetime,
+ version=readstring(f,4),
+ noftables=readushort(f),
+ searchrange=readushort(f),
+ entryselector=readushort(f),
+ rangeshift=readushort(f),
+ tables=tables,
+ foundtables=false,
+ }
+ for i=1,fontdata.noftables do
+ local tag=lower(stripstring(readstring(f,4)))
+ local checksum=readulong(f)
+ local offset=readulong(f)
+ local length=readulong(f)
+ if offset+length>filesize then
+ report("bad %a table in file %a",tag,basename)
+ end
+ tables[tag]={
+ checksum=checksum,
+ offset=offset,
+ length=length,
+ }
+ end
+ fontdata.foundtables=sortedkeys(tables)
+ if tables.cff or tables.cff2 then
+ fontdata.format="opentype"
+ else
+ fontdata.format="truetype"
+ end
+ return fontdata
+end
+local function prepareglyps(fontdata)
+ local glyphs=setmetatableindex(function(t,k)
+ local v={
+ index=k,
+ }
+ t[k]=v
+ return v
+ end)
+ fontdata.glyphs=glyphs
+ fontdata.mapping={}
+end
+local function readtable(tag,f,fontdata,specification,...)
+ local reader=readers[tag]
+ if reader then
+ reader(f,fontdata,specification,...)
+ end
+end
+local variablefonts_supported=(context and true) or (logs and logs.application and true) or false
+local function readdata(f,offset,specification)
+ local fontdata=loadtables(f,specification,offset)
+ if specification.glyphs then
+ prepareglyps(fontdata)
+ end
+ if not variablefonts_supported then
+ specification.instance=nil
+ specification.variable=nil
+ specification.factors=nil
+ end
+ fontdata.temporary={}
+ readtable("name",f,fontdata,specification)
+ local askedname=specification.askedname
+ if askedname then
+ local fullname=getname(fontdata,"fullname") or ""
+ local cleanname=gsub(askedname,"[^a-zA-Z0-9]","")
+ local foundname=gsub(fullname,"[^a-zA-Z0-9]","")
+ if lower(cleanname)~=lower(foundname) then
+ return
+ end
+ end
+ readtable("stat",f,fontdata,specification)
+ readtable("avar",f,fontdata,specification)
+ readtable("fvar",f,fontdata,specification)
+ if variablefonts_supported then
+ local variabledata=fontdata.variabledata
+ if variabledata then
+ local instances=variabledata.instances
+ local axis=variabledata.axis
+ if axis and (not instances or #instances==0) then
+ instances={}
+ variabledata.instances=instances
+ local function add(n,subfamily,value)
+ local values={}
+ for i=1,#axis do
+ local a=axis[i]
+ values[i]={
+ axis=a.tag,
+ value=i==n and value or a.default,
+ }
+ end
+ instances[#instances+1]={
+ subfamily=subfamily,
+ values=values,
+ }
+ end
+ for i=1,#axis do
+ local a=axis[i]
+ local tag=a.tag
+ add(i,"default"..tag,a.default)
+ add(i,"minimum"..tag,a.minimum)
+ add(i,"maximum"..tag,a.maximum)
+ end
+ end
+ end
+ if not specification.factors then
+ local instance=specification.instance
+ if type(instance)=="string" then
+ local factors=helpers.getfactors(fontdata,instance)
+ if factors then
+ specification.factors=factors
+ fontdata.factors=factors
+ fontdata.instance=instance
+ report("user instance: %s, factors: % t",instance,factors)
+ else
+ report("user instance: %s, bad factors",instance)
+ end
+ end
+ end
+ if not fontdata.factors then
+ if fontdata.variabledata then
+ local factors=helpers.getfactors(fontdata,true)
+ if factors then
+ specification.factors=factors
+ fontdata.factors=factors
+ end
+ else
+ end
+ end
+ end
+ readtable("os/2",f,fontdata,specification)
+ readtable("head",f,fontdata,specification)
+ readtable("maxp",f,fontdata,specification)
+ readtable("hhea",f,fontdata,specification)
+ readtable("vhea",f,fontdata,specification)
+ readtable("hmtx",f,fontdata,specification)
+ readtable("vmtx",f,fontdata,specification)
+ readtable("vorg",f,fontdata,specification)
+ readtable("post",f,fontdata,specification)
+ readtable("mvar",f,fontdata,specification)
+ readtable("hvar",f,fontdata,specification)
+ readtable("vvar",f,fontdata,specification)
+ readtable("gdef",f,fontdata,specification)
+ readtable("cff",f,fontdata,specification)
+ readtable("cff2",f,fontdata,specification)
+ readtable("cmap",f,fontdata,specification)
+ readtable("loca",f,fontdata,specification)
+ readtable("glyf",f,fontdata,specification)
+ readtable("colr",f,fontdata,specification)
+ readtable("cpal",f,fontdata,specification)
+ readtable("svg",f,fontdata,specification)
+ readtable("sbix",f,fontdata,specification)
+ readtable("cbdt",f,fontdata,specification)
+ readtable("cblc",f,fontdata,specification)
+ readtable("ebdt",f,fontdata,specification)
+ readtable("eblc",f,fontdata,specification)
+ readtable("kern",f,fontdata,specification)
+ readtable("gsub",f,fontdata,specification)
+ readtable("gpos",f,fontdata,specification)
+ readtable("math",f,fontdata,specification)
+ fontdata.locations=nil
+ fontdata.tables=nil
+ fontdata.cidmaps=nil
+ fontdata.dictionaries=nil
+ return fontdata
+end
+local function loadfontdata(specification)
+ local filename=specification.filename
+ local fileattr=lfs.attributes(filename)
+ local filesize=fileattr and fileattr.size or 0
+ local filetime=fileattr and fileattr.modification or 0
+ local f=openfile(filename,true)
+ if not f then
+ report("unable to open %a",filename)
+ elseif filesize==0 then
+ report("empty file %a",filename)
+ closefile(f)
+ else
+ specification.filesize=filesize
+ specification.filetime=filetime
+ local version=readstring(f,4)
+ local fontdata=nil
+ if version=="OTTO" or version=="true" or version=="\0\1\0\0" then
+ fontdata=readdata(f,0,specification)
+ elseif version=="ttcf" then
+ local subfont=tonumber(specification.subfont)
+ local ttcversion=readulong(f)
+ local nofsubfonts=readulong(f)
+ local offsets=readcardinaltable(f,nofsubfonts,ulong)
+ if subfont then
+ if subfont>=1 and subfont<=nofsubfonts then
+ fontdata=readdata(f,offsets[subfont],specification)
+ else
+ report("no subfont %a in file %a",subfont,filename)
+ end
+ else
+ subfont=specification.subfont
+ if type(subfont)=="string" and subfont~="" then
+ specification.askedname=subfont
+ for i=1,nofsubfonts do
+ fontdata=readdata(f,offsets[i],specification)
+ if fontdata then
+ fontdata.subfontindex=i
+ report("subfont named %a has index %a",subfont,i)
+ break
+ end
+ end
+ if not fontdata then
+ report("no subfont named %a",subfont)
+ end
+ else
+ local subfonts={}
+ fontdata={
+ filename=filename,
+ filesize=filesize,
+ filetime=filetime,
+ version=version,
+ subfonts=subfonts,
+ ttcversion=ttcversion,
+ nofsubfonts=nofsubfonts,
+ }
+ for i=1,nofsubfonts do
+ subfonts[i]=readdata(f,offsets[i],specification)
+ end
+ end
+ end
+ else
+ report("unknown version %a in file %a",version,filename)
+ end
+ closefile(f)
+ return fontdata or {}
+ end
+end
+local function loadfont(specification,n,instance)
+ if type(specification)=="string" then
+ specification={
+ filename=specification,
+ info=true,
+ details=true,
+ glyphs=true,
+ shapes=true,
+ kerns=true,
+ variable=true,
+ globalkerns=true,
+ lookups=true,
+ subfont=n or true,
+ tounicode=false,
+ instance=instance
+ }
+ end
+ if specification.shapes or specification.lookups or specification.kerns then
+ specification.glyphs=true
+ end
+ if specification.glyphs then
+ specification.details=true
+ end
+ if specification.details then
+ specification.info=true
+ end
+ if specification.platformnames then
+ specification.platformnames=true
+ end
+ if specification.instance or instance then
+ specification.variable=true
+ specification.instance=specification.instance or instance
+ end
+ local function message(str)
+ report("fatal error in file %a: %s\n%s",specification.filename,str,debug.traceback())
+ end
+ local ok,result=xpcall(loadfontdata,message,specification)
+ if ok then
+ return result
+ end
+end
+function readers.loadshapes(filename,n,instance,streams)
+ local fontdata=loadfont {
+ filename=filename,
+ shapes=true,
+ streams=streams,
+ variable=true,
+ subfont=n,
+ instance=instance,
+ }
+ if fontdata then
+ for k,v in next,fontdata.glyphs do
+ v.class=nil
+ v.index=nil
+ v.math=nil
+ end
+ end
+ return fontdata and {
+ filename=filename,
+ format=fontdata.format,
+ glyphs=fontdata.glyphs,
+ units=fontdata.fontheader.units,
+ } or {
+ filename=filename,
+ format="unknown",
+ glyphs={},
+ units=0,
+ }
+end
+function readers.loadfont(filename,n,instance)
+ local fontdata=loadfont {
+ filename=filename,
+ glyphs=true,
+ shapes=false,
+ lookups=true,
+ variable=true,
+ subfont=n,
+ instance=instance,
+ }
+ if fontdata then
+ return {
+ tableversion=tableversion,
+ creator="context mkiv",
+ size=fontdata.filesize,
+ time=fontdata.filetime,
+ glyphs=fontdata.glyphs,
+ descriptions=fontdata.descriptions,
+ format=fontdata.format,
+ goodies={},
+ metadata=getinfo(fontdata,n,false,false,true,true),
+ properties={
+ hasitalics=fontdata.hasitalics or false,
+ maxcolorclass=fontdata.maxcolorclass,
+ hascolor=fontdata.hascolor or false,
+ instance=fontdata.instance,
+ factors=fontdata.factors,
+ },
+ resources={
+ filename=filename,
+ private=privateoffset,
+ duplicates=fontdata.duplicates or {},
+ features=fontdata.features or {},
+ sublookups=fontdata.sublookups or {},
+ marks=fontdata.marks or {},
+ markclasses=fontdata.markclasses or {},
+ marksets=fontdata.marksets or {},
+ sequences=fontdata.sequences or {},
+ variants=fontdata.variants,
+ version=getname(fontdata,"version"),
+ cidinfo=fontdata.cidinfo,
+ mathconstants=fontdata.mathconstants,
+ colorpalettes=fontdata.colorpalettes,
+ svgshapes=fontdata.svgshapes,
+ sbixshapes=fontdata.sbixshapes,
+ variabledata=fontdata.variabledata,
+ foundtables=fontdata.foundtables,
+ },
+ }
+ end
+end
+function readers.getinfo(filename,specification)
+ local subfont=nil
+ local platformnames=false
+ local rawfamilynames=false
+ local instancenames=true
+ if type(specification)=="table" then
+ subfont=tonumber(specification.subfont)
+ platformnames=specification.platformnames
+ rawfamilynames=specification.rawfamilynames
+ else
+ subfont=tonumber(specification)
+ end
+ local fontdata=loadfont {
+ filename=filename,
+ details=true,
+ platformnames=platformnames,
+ instancenames=true,
+ }
+ if fontdata then
+ local subfonts=fontdata.subfonts
+ if not subfonts then
+ return getinfo(fontdata,nil,platformnames,rawfamilynames,false,instancenames)
+ elseif not subfont then
+ local info={}
+ for i=1,#subfonts do
+ info[i]=getinfo(fontdata,i,platformnames,rawfamilynames,false,instancenames)
+ end
+ return info
+ elseif subfont>=1 and subfont<=#subfonts then
+ return getinfo(fontdata,subfont,platformnames,rawfamilynames,false,instancenames)
+ else
+ return {
+ filename=filename,
+ comment="there is no subfont "..subfont.." in this file"
+ }
+ end
+ else
+ return {
+ filename=filename,
+ comment="the file cannot be opened for reading",
+ }
+ end
+end
+function readers.rehash(fontdata,hashmethod)
+ report("the %a helper is not yet implemented","rehash")
+end
+function readers.checkhash(fontdata)
+ report("the %a helper is not yet implemented","checkhash")
+end
+function readers.pack(fontdata,hashmethod)
+ report("the %a helper is not yet implemented","pack")
+end
+function readers.unpack(fontdata)
+ report("the %a helper is not yet implemented","unpack")
+end
+function readers.expand(fontdata)
+ report("the %a helper is not yet implemented","unpack")
+end
+function readers.compact(fontdata)
+ report("the %a helper is not yet implemented","compact")
+end
+local extenders={}
+function readers.registerextender(extender)
+ extenders[#extenders+1]=extender
+end
+function readers.extend(fontdata)
+ for i=1,#extenders do
+ local extender=extenders[i]
+ local name=extender.name or "unknown"
+ local action=extender.action
+ if action then
+ action(fontdata)
+ end
+ end
+end
+
+end --- [luaotfload, fontloader-2018-09-24.lua scope for “font-otr”] ---
+
+
+do --- [luaotfload, fontloader-2018-09-24.lua scope for “font-oti” 309a75f9c14b77d87e94eba827dc4e71] ---
+
+if not modules then modules={} end modules ['font-oti']={
+ version=1.001,
+ comment="companion to font-ini.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local lower=string.lower
+local fonts=fonts
+local constructors=fonts.constructors
+local otf=constructors.handlers.otf
+local otffeatures=constructors.features.otf
+local registerotffeature=otffeatures.register
+local otftables=otf.tables or {}
+otf.tables=otftables
+local allocate=utilities.storage.allocate
+registerotffeature {
+ name="features",
+ description="initialization of feature handler",
+ default=true,
+}
+local function setmode(tfmdata,value)
+ if value then
+ tfmdata.properties.mode=lower(value)
+ end
+end
+otf.modeinitializer=setmode
+local function setlanguage(tfmdata,value)
+ if value then
+ local cleanvalue=lower(value)
+ local languages=otftables and otftables.languages
+ local properties=tfmdata.properties
+ if not languages then
+ properties.language=cleanvalue
+ elseif languages[value] then
+ properties.language=cleanvalue
+ else
+ properties.language="dflt"
+ end
+ end
+end
+local function setscript(tfmdata,value)
+ if value then
+ local cleanvalue=lower(value)
+ local scripts=otftables and otftables.scripts
+ local properties=tfmdata.properties
+ if not scripts then
+ properties.script=cleanvalue
+ elseif scripts[value] then
+ properties.script=cleanvalue
+ else
+ properties.script="dflt"
+ end
+ end
+end
+registerotffeature {
+ name="mode",
+ description="mode",
+ initializers={
+ base=setmode,
+ node=setmode,
+ plug=setmode,
+ }
+}
+registerotffeature {
+ name="language",
+ description="language",
+ initializers={
+ base=setlanguage,
+ node=setlanguage,
+ plug=setlanguage,
+ }
+}
+registerotffeature {
+ name="script",
+ description="script",
+ initializers={
+ base=setscript,
+ node=setscript,
+ plug=setscript,
+ }
+}
+otftables.featuretypes=allocate {
+ gpos_single="position",
+ gpos_pair="position",
+ gpos_cursive="position",
+ gpos_mark2base="position",
+ gpos_mark2ligature="position",
+ gpos_mark2mark="position",
+ gpos_context="position",
+ gpos_contextchain="position",
+ gsub_single="substitution",
+ gsub_multiple="substitution",
+ gsub_alternate="substitution",
+ gsub_ligature="substitution",
+ gsub_context="substitution",
+ gsub_contextchain="substitution",
+ gsub_reversecontextchain="substitution",
+ gsub_reversesub="substitution",
+}
+function otffeatures.checkeddefaultscript(featuretype,autoscript,scripts)
+ if featuretype=="position" then
+ local default=scripts.dflt
+ if default then
+ if autoscript=="position" or autoscript==true then
+ return default
+ else
+ report_otf("script feature %s not applied, enable default positioning")
+ end
+ else
+ end
+ elseif featuretype=="substitution" then
+ local default=scripts.dflt
+ if default then
+ if autoscript=="substitution" or autoscript==true then
+ return default
+ end
+ end
+ end
+end
+function otffeatures.checkeddefaultlanguage(featuretype,autolanguage,languages)
+ if featuretype=="position" then
+ local default=languages.dflt
+ if default then
+ if autolanguage=="position" or autolanguage==true then
+ return default
+ else
+ report_otf("language feature %s not applied, enable default positioning")
+ end
+ else
+ end
+ elseif featuretype=="substitution" then
+ local default=languages.dflt
+ if default then
+ if autolanguage=="substitution" or autolanguage==true then
+ return default
+ end
+ end
+ end
+end
+
+end --- [luaotfload, fontloader-2018-09-24.lua scope for “font-oti”] ---
+
+
+do --- [luaotfload, fontloader-2018-09-24.lua scope for “font-ott” a4dd9bc516bdb7669ee61d5207f899c6] ---
+
+if not modules then modules={} end modules ["font-ott"]={
+ version=1.001,
+ comment="companion to font-ini.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files",
+}
+local type,next,tonumber,tostring,rawget,rawset=type,next,tonumber,tostring,rawget,rawset
+local gsub,lower,format,match,gmatch,find=string.gsub,string.lower,string.format,string.match,string.gmatch,string.find
+local sequenced=table.sequenced
+local is_boolean=string.is_boolean
+local setmetatableindex=table.setmetatableindex
+local setmetatablenewindex=table.setmetatablenewindex
+local allocate=utilities.storage.allocate
+local fonts=fonts
+local otf=fonts.handlers.otf
+local otffeatures=otf.features
+local tables=otf.tables or {}
+otf.tables=tables
+local statistics=otf.statistics or {}
+otf.statistics=statistics
+local scripts=allocate {
+ ["arab"]="arabic",
+ ["armi"]="imperial aramaic",
+ ["armn"]="armenian",
+ ["avst"]="avestan",
+ ["bali"]="balinese",
+ ["bamu"]="bamum",
+ ["batk"]="batak",
+ ["beng"]="bengali",
+ ["bng2"]="bengali variant 2",
+ ["bopo"]="bopomofo",
+ ["brah"]="brahmi",
+ ["brai"]="braille",
+ ["bugi"]="buginese",
+ ["buhd"]="buhid",
+ ["byzm"]="byzantine music",
+ ["cakm"]="chakma",
+ ["cans"]="canadian syllabics",
+ ["cari"]="carian",
+ ["cham"]="cham",
+ ["cher"]="cherokee",
+ ["copt"]="coptic",
+ ["cprt"]="cypriot syllabary",
+ ["cyrl"]="cyrillic",
+ ["deva"]="devanagari",
+ ["dev2"]="devanagari variant 2",
+ ["dsrt"]="deseret",
+ ["egyp"]="egyptian heiroglyphs",
+ ["ethi"]="ethiopic",
+ ["geor"]="georgian",
+ ["glag"]="glagolitic",
+ ["goth"]="gothic",
+ ["grek"]="greek",
+ ["gujr"]="gujarati",
+ ["gjr2"]="gujarati variant 2",
+ ["guru"]="gurmukhi",
+ ["gur2"]="gurmukhi variant 2",
+ ["hang"]="hangul",
+ ["hani"]="cjk ideographic",
+ ["hano"]="hanunoo",
+ ["hebr"]="hebrew",
+ ["ital"]="old italic",
+ ["jamo"]="hangul jamo",
+ ["java"]="javanese",
+ ["kali"]="kayah li",
+ ["kana"]="hiragana and katakana",
+ ["khar"]="kharosthi",
+ ["khmr"]="khmer",
+ ["knda"]="kannada",
+ ["knd2"]="kannada variant 2",
+ ["kthi"]="kaithi",
+ ["lana"]="tai tham",
+ ["lao" ]="lao",
+ ["latn"]="latin",
+ ["lepc"]="lepcha",
+ ["limb"]="limbu",
+ ["linb"]="linear b",
+ ["lisu"]="lisu",
+ ["lyci"]="lycian",
+ ["lydi"]="lydian",
+ ["mand"]="mandaic and mandaean",
+ ["math"]="mathematical alphanumeric symbols",
+ ["merc"]="meroitic cursive",
+ ["mero"]="meroitic hieroglyphs",
+ ["mlym"]="malayalam",
+ ["mlm2"]="malayalam variant 2",
+ ["mong"]="mongolian",
+ ["mtei"]="meitei Mayek",
+ ["musc"]="musical symbols",
+ ["mym2"]="myanmar variant 2",
+ ["mymr"]="myanmar",
+ ["nko" ]='n"ko',
+ ["ogam"]="ogham",
+ ["olck"]="ol chiki",
+ ["orkh"]="old turkic and orkhon runic",
+ ["orya"]="oriya",
+ ["ory2"]="odia variant 2",
+ ["osma"]="osmanya",
+ ["phag"]="phags-pa",
+ ["phli"]="inscriptional pahlavi",
+ ["phnx"]="phoenician",
+ ["prti"]="inscriptional parthian",
+ ["rjng"]="rejang",
+ ["runr"]="runic",
+ ["samr"]="samaritan",
+ ["sarb"]="old south arabian",
+ ["saur"]="saurashtra",
+ ["shaw"]="shavian",
+ ["shrd"]="sharada",
+ ["sinh"]="sinhala",
+ ["sora"]="sora sompeng",
+ ["sund"]="sundanese",
+ ["sylo"]="syloti nagri",
+ ["syrc"]="syriac",
+ ["tagb"]="tagbanwa",
+ ["takr"]="takri",
+ ["tale"]="tai le",
+ ["talu"]="tai lu",
+ ["taml"]="tamil",
+ ["tavt"]="tai viet",
+ ["telu"]="telugu",
+ ["tel2"]="telugu variant 2",
+ ["tfng"]="tifinagh",
+ ["tglg"]="tagalog",
+ ["thaa"]="thaana",
+ ["thai"]="thai",
+ ["tibt"]="tibetan",
+ ["tml2"]="tamil variant 2",
+ ["ugar"]="ugaritic cuneiform",
+ ["vai" ]="vai",
+ ["xpeo"]="old persian cuneiform",
+ ["xsux"]="sumero-akkadian cuneiform",
+ ["yi" ]="yi",
+}
+local languages=allocate {
+ ["aba" ]="abaza",
+ ["abk" ]="abkhazian",
+ ["ach" ]="acholi",
+ ["acr" ]="achi",
+ ["ady" ]="adyghe",
+ ["afk" ]="afrikaans",
+ ["afr" ]="afar",
+ ["agw" ]="agaw",
+ ["aio" ]="aiton",
+ ["aka" ]="akan",
+ ["als" ]="alsatian",
+ ["alt" ]="altai",
+ ["amh" ]="amharic",
+ ["ang" ]="anglo-saxon",
+ ["apph"]="phonetic transcription—americanist conventions",
+ ["ara" ]="arabic",
+ ["arg" ]="aragonese",
+ ["ari" ]="aari",
+ ["ark" ]="rakhine",
+ ["asm" ]="assamese",
+ ["ast" ]="asturian",
+ ["ath" ]="athapaskan",
+ ["avr" ]="avar",
+ ["awa" ]="awadhi",
+ ["aym" ]="aymara",
+ ["azb" ]="torki",
+ ["aze" ]="azerbaijani",
+ ["bad" ]="badaga",
+ ["bad0"]="banda",
+ ["bag" ]="baghelkhandi",
+ ["bal" ]="balkar",
+ ["ban" ]="balinese",
+ ["bar" ]="bavarian",
+ ["bau" ]="baulé",
+ ["bbc" ]="batak toba",
+ ["bbr" ]="berber",
+ ["bch" ]="bench",
+ ["bcr" ]="bible cree",
+ ["bdy" ]="bandjalang",
+ ["bel" ]="belarussian",
+ ["bem" ]="bemba",
+ ["ben" ]="bengali",
+ ["bgc" ]="haryanvi",
+ ["bgq" ]="bagri",
+ ["bgr" ]="bulgarian",
+ ["bhi" ]="bhili",
+ ["bho" ]="bhojpuri",
+ ["bik" ]="bikol",
+ ["bil" ]="bilen",
+ ["bis" ]="bislama",
+ ["bjj" ]="kanauji",
+ ["bkf" ]="blackfoot",
+ ["bli" ]="baluchi",
+ ["blk" ]="pa'o karen",
+ ["bln" ]="balante",
+ ["blt" ]="balti",
+ ["bmb" ]="bambara (bamanankan)",
+ ["bml" ]="bamileke",
+ ["bos" ]="bosnian",
+ ["bpy" ]="bishnupriya manipuri",
+ ["bre" ]="breton",
+ ["brh" ]="brahui",
+ ["bri" ]="braj bhasha",
+ ["brm" ]="burmese",
+ ["brx" ]="bodo",
+ ["bsh" ]="bashkir",
+ ["bti" ]="beti",
+ ["bts" ]="batak simalungun",
+ ["bug" ]="bugis",
+ ["cak" ]="kaqchikel",
+ ["cat" ]="catalan",
+ ["cbk" ]="zamboanga chavacano",
+ ["ceb" ]="cebuano",
+ ["cgg" ]="chiga",
+ ["cha" ]="chamorro",
+ ["che" ]="chechen",
+ ["chg" ]="chaha gurage",
+ ["chh" ]="chattisgarhi",
+ ["chi" ]="chichewa (chewa, nyanja)",
+ ["chk" ]="chukchi",
+ ["chk0"]="chuukese",
+ ["cho" ]="choctaw",
+ ["chp" ]="chipewyan",
+ ["chr" ]="cherokee",
+ ["chu" ]="chuvash",
+ ["chy" ]="cheyenne",
+ ["cmr" ]="comorian",
+ ["cop" ]="coptic",
+ ["cor" ]="cornish",
+ ["cos" ]="corsican",
+ ["cpp" ]="creoles",
+ ["cre" ]="cree",
+ ["crr" ]="carrier",
+ ["crt" ]="crimean tatar",
+ ["csb" ]="kashubian",
+ ["csl" ]="church slavonic",
+ ["csy" ]="czech",
+ ["ctg" ]="chittagonian",
+ ["cuk" ]="san blas kuna",
+ ["dan" ]="danish",
+ ["dar" ]="dargwa",
+ ["dax" ]="dayi",
+ ["dcr" ]="woods cree",
+ ["deu" ]="german",
+ ["dgo" ]="dogri",
+ ["dgr" ]="dogri",
+ ["dhg" ]="dhangu",
+ ["dhv" ]="divehi (dhivehi, maldivian)",
+ ["diq" ]="dimli",
+ ["div" ]="divehi (dhivehi, maldivian)",
+ ["djr" ]="zarma",
+ ["djr0"]="djambarrpuyngu",
+ ["dng" ]="dangme",
+ ["dnj" ]="dan",
+ ["dnk" ]="dinka",
+ ["dri" ]="dari",
+ ["duj" ]="dhuwal",
+ ["dun" ]="dungan",
+ ["dzn" ]="dzongkha",
+ ["ebi" ]="ebira",
+ ["ecr" ]="eastern cree",
+ ["edo" ]="edo",
+ ["efi" ]="efik",
+ ["ell" ]="greek",
+ ["emk" ]="eastern maninkakan",
+ ["eng" ]="english",
+ ["erz" ]="erzya",
+ ["esp" ]="spanish",
+ ["esu" ]="central yupik",
+ ["eti" ]="estonian",
+ ["euq" ]="basque",
+ ["evk" ]="evenki",
+ ["evn" ]="even",
+ ["ewe" ]="ewe",
+ ["fan" ]="french antillean",
+ ["fan0"]=" fang",
+ ["far" ]="persian",
+ ["fat" ]="fanti",
+ ["fin" ]="finnish",
+ ["fji" ]="fijian",
+ ["fle" ]="dutch (flemish)",
+ ["fne" ]="forest nenets",
+ ["fon" ]="fon",
+ ["fos" ]="faroese",
+ ["fra" ]="french",
+ ["frc" ]="cajun french",
+ ["fri" ]="frisian",
+ ["frl" ]="friulian",
+ ["frp" ]="arpitan",
+ ["fta" ]="futa",
+ ["ful" ]="fulah",
+ ["fuv" ]="nigerian fulfulde",
+ ["gad" ]="ga",
+ ["gae" ]="scottish gaelic (gaelic)",
+ ["gag" ]="gagauz",
+ ["gal" ]="galician",
+ ["gar" ]="garshuni",
+ ["gaw" ]="garhwali",
+ ["gez" ]="ge'ez",
+ ["gih" ]="githabul",
+ ["gil" ]="gilyak",
+ ["gil0"]="kiribati (gilbertese)",
+ ["gkp" ]="kpelle (guinea)",
+ ["glk" ]="gilaki",
+ ["gmz" ]="gumuz",
+ ["gnn" ]="gumatj",
+ ["gog" ]="gogo",
+ ["gon" ]="gondi",
+ ["grn" ]="greenlandic",
+ ["gro" ]="garo",
+ ["gua" ]="guarani",
+ ["guc" ]="wayuu",
+ ["guf" ]="gupapuyngu",
+ ["guj" ]="gujarati",
+ ["guz" ]="gusii",
+ ["hai" ]="haitian (haitian creole)",
+ ["hal" ]="halam",
+ ["har" ]="harauti",
+ ["hau" ]="hausa",
+ ["haw" ]="hawaiian",
+ ["hay" ]="haya",
+ ["haz" ]="hazaragi",
+ ["hbn" ]="hammer-banna",
+ ["her" ]="herero",
+ ["hil" ]="hiligaynon",
+ ["hin" ]="hindi",
+ ["hma" ]="high mari",
+ ["hmn" ]="hmong",
+ ["hmo" ]="hiri motu",
+ ["hnd" ]="hindko",
+ ["ho" ]="ho",
+ ["hri" ]="harari",
+ ["hrv" ]="croatian",
+ ["hun" ]="hungarian",
+ ["hye" ]="armenian",
+ ["hye0"]="armenian east",
+ ["iba" ]="iban",
+ ["ibb" ]="ibibio",
+ ["ibo" ]="igbo",
+ ["ido" ]="ido",
+ ["ijo" ]="ijo languages",
+ ["ile" ]="interlingue",
+ ["ilo" ]="ilokano",
+ ["ina" ]="interlingua",
+ ["ind" ]="indonesian",
+ ["ing" ]="ingush",
+ ["inu" ]="inuktitut",
+ ["ipk" ]="inupiat",
+ ["ipph"]="phonetic transcription—ipa conventions",
+ ["iri" ]="irish",
+ ["irt" ]="irish traditional",
+ ["isl" ]="icelandic",
+ ["ism" ]="inari sami",
+ ["ita" ]="italian",
+ ["iwr" ]="hebrew",
+ ["jam" ]="jamaican creole",
+ ["jan" ]="japanese",
+ ["jav" ]="javanese",
+ ["jbo" ]="lojban",
+ ["jii" ]="yiddish",
+ ["jud" ]="ladino",
+ ["jul" ]="jula",
+ ["kab" ]="kabardian",
+ ["kab0"]="kabyle",
+ ["kac" ]="kachchi",
+ ["kal" ]="kalenjin",
+ ["kan" ]="kannada",
+ ["kar" ]="karachay",
+ ["kat" ]="georgian",
+ ["kaz" ]="kazakh",
+ ["kde" ]="makonde",
+ ["kea" ]="kabuverdianu (crioulo)",
+ ["keb" ]="kebena",
+ ["kek" ]="kekchi",
+ ["kge" ]="khutsuri georgian",
+ ["kha" ]="khakass",
+ ["khk" ]="khanty-kazim",
+ ["khm" ]="khmer",
+ ["khs" ]="khanty-shurishkar",
+ ["kht" ]="khamti shan",
+ ["khv" ]="khanty-vakhi",
+ ["khw" ]="khowar",
+ ["kik" ]="kikuyu (gikuyu)",
+ ["kir" ]="kirghiz (kyrgyz)",
+ ["kis" ]="kisii",
+ ["kiu" ]="kirmanjki",
+ ["kjd" ]="southern kiwai",
+ ["kjp" ]="eastern pwo karen",
+ ["kkn" ]="kokni",
+ ["klm" ]="kalmyk",
+ ["kmb" ]="kamba",
+ ["kmn" ]="kumaoni",
+ ["kmo" ]="komo",
+ ["kms" ]="komso",
+ ["knr" ]="kanuri",
+ ["kod" ]="kodagu",
+ ["koh" ]="korean old hangul",
+ ["kok" ]="konkani",
+ ["kom" ]="komi",
+ ["kon" ]="kikongo",
+ ["kon0"]="kongo",
+ ["kop" ]="komi-permyak",
+ ["kor" ]="korean",
+ ["kos" ]="kosraean",
+ ["koz" ]="komi-zyrian",
+ ["kpl" ]="kpelle",
+ ["kri" ]="krio",
+ ["krk" ]="karakalpak",
+ ["krl" ]="karelian",
+ ["krm" ]="karaim",
+ ["krn" ]="karen",
+ ["krt" ]="koorete",
+ ["ksh" ]="kashmiri",
+ ["ksh0"]="ripuarian",
+ ["ksi" ]="khasi",
+ ["ksm" ]="kildin sami",
+ ["ksw" ]="s’gaw karen",
+ ["kua" ]="kuanyama",
+ ["kui" ]="kui",
+ ["kul" ]="kulvi",
+ ["kum" ]="kumyk",
+ ["kur" ]="kurdish",
+ ["kuu" ]="kurukh",
+ ["kuy" ]="kuy",
+ ["kyk" ]="koryak",
+ ["kyu" ]="western kayah",
+ ["lad" ]="ladin",
+ ["lah" ]="lahuli",
+ ["lak" ]="lak",
+ ["lam" ]="lambani",
+ ["lao" ]="lao",
+ ["lat" ]="latin",
+ ["laz" ]="laz",
+ ["lcr" ]="l-cree",
+ ["ldk" ]="ladakhi",
+ ["lez" ]="lezgi",
+ ["lij" ]="ligurian",
+ ["lim" ]="limburgish",
+ ["lin" ]="lingala",
+ ["lis" ]="lisu",
+ ["ljp" ]="lampung",
+ ["lki" ]="laki",
+ ["lma" ]="low mari",
+ ["lmb" ]="limbu",
+ ["lmo" ]="lombard",
+ ["lmw" ]="lomwe",
+ ["lom" ]="loma",
+ ["lrc" ]="luri",
+ ["lsb" ]="lower sorbian",
+ ["lsm" ]="lule sami",
+ ["lth" ]="lithuanian",
+ ["ltz" ]="luxembourgish",
+ ["lua" ]="luba-lulua",
+ ["lub" ]="luba-katanga",
+ ["lug" ]="ganda",
+ ["luh" ]="luyia",
+ ["luo" ]="luo",
+ ["lvi" ]="latvian",
+ ["mad" ]="madura",
+ ["mag" ]="magahi",
+ ["mah" ]="marshallese",
+ ["maj" ]="majang",
+ ["mak" ]="makhuwa",
+ ["mal" ]="malayalam reformed",
+ ["mam" ]="mam",
+ ["man" ]="mansi",
+ ["map" ]="mapudungun",
+ ["mar" ]="marathi",
+ ["maw" ]="marwari",
+ ["mbn" ]="mbundu",
+ ["mch" ]="manchu",
+ ["mcr" ]="moose cree",
+ ["mde" ]="mende",
+ ["mdr" ]="mandar",
+ ["men" ]="me'en",
+ ["mer" ]="meru",
+ ["mfe" ]="morisyen",
+ ["min" ]="minangkabau",
+ ["miz" ]="mizo",
+ ["mkd" ]="macedonian",
+ ["mkr" ]="makasar",
+ ["mkw" ]="kituba",
+ ["mle" ]="male",
+ ["mlg" ]="malagasy",
+ ["mln" ]="malinke",
+ ["mly" ]="malay",
+ ["mnd" ]="mandinka",
+ ["mng" ]="mongolian",
+ ["mni" ]="manipuri",
+ ["mnk" ]="maninka",
+ ["mnx" ]="manx",
+ ["moh" ]="mohawk",
+ ["mok" ]="moksha",
+ ["mol" ]="moldavian",
+ ["mon" ]="mon",
+ ["mor" ]="moroccan",
+ ["mos" ]="mossi",
+ ["mri" ]="maori",
+ ["mth" ]="maithili",
+ ["mts" ]="maltese",
+ ["mun" ]="mundari",
+ ["mus" ]="muscogee",
+ ["mwl" ]="mirandese",
+ ["mww" ]="hmong daw",
+ ["myn" ]="mayan",
+ ["mzn" ]="mazanderani",
+ ["nag" ]="naga-assamese",
+ ["nah" ]="nahuatl",
+ ["nan" ]="nanai",
+ ["nap" ]="neapolitan",
+ ["nas" ]="naskapi",
+ ["nau" ]="nauruan",
+ ["nav" ]="navajo",
+ ["ncr" ]="n-cree",
+ ["ndb" ]="ndebele",
+ ["ndc" ]="ndau",
+ ["ndg" ]="ndonga",
+ ["nds" ]="low saxon",
+ ["nep" ]="nepali",
+ ["new" ]="newari",
+ ["nga" ]="ngbaka",
+ ["ngr" ]="nagari",
+ ["nhc" ]="norway house cree",
+ ["nis" ]="nisi",
+ ["niu" ]="niuean",
+ ["nkl" ]="nyankole",
+ ["nko" ]="n'ko",
+ ["nld" ]="dutch",
+ ["noe" ]="nimadi",
+ ["nog" ]="nogai",
+ ["nor" ]="norwegian",
+ ["nov" ]="novial",
+ ["nsm" ]="northern sami",
+ ["nso" ]="sotho, northern",
+ ["nta" ]="northern tai",
+ ["nto" ]="esperanto",
+ ["nym" ]="nyamwezi",
+ ["nyn" ]="norwegian nynorsk",
+ ["oci" ]="occitan",
+ ["ocr" ]="oji-cree",
+ ["ojb" ]="ojibway",
+ ["ori" ]="odia",
+ ["oro" ]="oromo",
+ ["oss" ]="ossetian",
+ ["paa" ]="palestinian aramaic",
+ ["pag" ]="pangasinan",
+ ["pal" ]="pali",
+ ["pam" ]="pampangan",
+ ["pan" ]="punjabi",
+ ["pap" ]="palpa",
+ ["pap0"]="papiamentu",
+ ["pas" ]="pashto",
+ ["pau" ]="palauan",
+ ["pcc" ]="bouyei",
+ ["pcd" ]="picard",
+ ["pdc" ]="pennsylvania german",
+ ["pgr" ]="polytonic greek",
+ ["phk" ]="phake",
+ ["pih" ]="norfolk",
+ ["pil" ]="filipino",
+ ["plg" ]="palaung",
+ ["plk" ]="polish",
+ ["pms" ]="piemontese",
+ ["pnb" ]="western panjabi",
+ ["poh" ]="pocomchi",
+ ["pon" ]="pohnpeian",
+ ["pro" ]="provencal",
+ ["ptg" ]="portuguese",
+ ["pwo" ]="western pwo karen",
+ ["qin" ]="chin",
+ ["quc" ]="k’iche’",
+ ["quh" ]="quechua (bolivia)",
+ ["quz" ]="quechua",
+ ["qvi" ]="quechua (ecuador)",
+ ["qwh" ]="quechua (peru)",
+ ["raj" ]="rajasthani",
+ ["rar" ]="rarotongan",
+ ["rbu" ]="russian buriat",
+ ["rcr" ]="r-cree",
+ ["rej" ]="rejang",
+ ["ria" ]="riang",
+ ["rif" ]="tarifit",
+ ["rit" ]="ritarungo",
+ ["rkw" ]="arakwal",
+ ["rms" ]="romansh",
+ ["rmy" ]="vlax romani",
+ ["rom" ]="romanian",
+ ["roy" ]="romany",
+ ["rsy" ]="rusyn",
+ ["rtm" ]="rotuman",
+ ["rua" ]="kinyarwanda",
+ ["run" ]="rundi",
+ ["rup" ]="aromanian",
+ ["rus" ]="russian",
+ ["sad" ]="sadri",
+ ["san" ]="sanskrit",
+ ["sas" ]="sasak",
+ ["sat" ]="santali",
+ ["say" ]="sayisi",
+ ["scn" ]="sicilian",
+ ["sco" ]="scots",
+ ["sek" ]="sekota",
+ ["sel" ]="selkup",
+ ["sga" ]="old irish",
+ ["sgo" ]="sango",
+ ["sgs" ]="samogitian",
+ ["shi" ]="tachelhit",
+ ["shn" ]="shan",
+ ["sib" ]="sibe",
+ ["sid" ]="sidamo",
+ ["sig" ]="silte gurage",
+ ["sks" ]="skolt sami",
+ ["sky" ]="slovak",
+ ["sla" ]="slavey",
+ ["slv" ]="slovenian",
+ ["sml" ]="somali",
+ ["smo" ]="samoan",
+ ["sna" ]="sena",
+ ["sna0"]="shona",
+ ["snd" ]="sindhi",
+ ["snh" ]="sinhala (sinhalese)",
+ ["snk" ]="soninke",
+ ["sog" ]="sodo gurage",
+ ["sop" ]="songe",
+ ["sot" ]="sotho, southern",
+ ["sqi" ]="albanian",
+ ["srb" ]="serbian",
+ ["srd" ]="sardinian",
+ ["srk" ]="saraiki",
+ ["srr" ]="serer",
+ ["ssl" ]="south slavey",
+ ["ssm" ]="southern sami",
+ ["stq" ]="saterland frisian",
+ ["suk" ]="sukuma",
+ ["sun" ]="sundanese",
+ ["sur" ]="suri",
+ ["sva" ]="svan",
+ ["sve" ]="swedish",
+ ["swa" ]="swadaya aramaic",
+ ["swk" ]="swahili",
+ ["swz" ]="swati",
+ ["sxt" ]="sutu",
+ ["sxu" ]="upper saxon",
+ ["syl" ]="sylheti",
+ ["syr" ]="syriac",
+ ["szl" ]="silesian",
+ ["tab" ]="tabasaran",
+ ["taj" ]="tajiki",
+ ["tam" ]="tamil",
+ ["tat" ]="tatar",
+ ["tcr" ]="th-cree",
+ ["tdd" ]="dehong dai",
+ ["tel" ]="telugu",
+ ["tet" ]="tetum",
+ ["tgl" ]="tagalog",
+ ["tgn" ]="tongan",
+ ["tgr" ]="tigre",
+ ["tgy" ]="tigrinya",
+ ["tha" ]="thai",
+ ["tht" ]="tahitian",
+ ["tib" ]="tibetan",
+ ["tiv" ]="tiv",
+ ["tkm" ]="turkmen",
+ ["tmh" ]="tamashek",
+ ["tmn" ]="temne",
+ ["tna" ]="tswana",
+ ["tne" ]="tundra nenets",
+ ["tng" ]="tonga",
+ ["tod" ]="todo",
+ ["tod0"]="toma",
+ ["tpi" ]="tok pisin",
+ ["trk" ]="turkish",
+ ["tsg" ]="tsonga",
+ ["tua" ]="turoyo aramaic",
+ ["tul" ]="tulu",
+ ["tuv" ]="tuvin",
+ ["tvl" ]="tuvalu",
+ ["twi" ]="twi",
+ ["tyz" ]="tày",
+ ["tzm" ]="tamazight",
+ ["tzo" ]="tzotzil",
+ ["udm" ]="udmurt",
+ ["ukr" ]="ukrainian",
+ ["umb" ]="umbundu",
+ ["urd" ]="urdu",
+ ["usb" ]="upper sorbian",
+ ["uyg" ]="uyghur",
+ ["uzb" ]="uzbek",
+ ["vec" ]="venetian",
+ ["ven" ]="venda",
+ ["vit" ]="vietnamese",
+ ["vol" ]="volapük",
+ ["vro" ]="võro",
+ ["wa" ]="wa",
+ ["wag" ]="wagdi",
+ ["war" ]="waray-waray",
+ ["wcr" ]="west-cree",
+ ["wel" ]="welsh",
+ ["wlf" ]="wolof",
+ ["wln" ]="walloon",
+ ["xbd" ]="lü",
+ ["xhs" ]="xhosa",
+ ["xjb" ]="minjangbal",
+ ["xog" ]="soga",
+ ["xpe" ]="kpelle (liberia)",
+ ["yak" ]="sakha",
+ ["yao" ]="yao",
+ ["yap" ]="yapese",
+ ["yba" ]="yoruba",
+ ["ycr" ]="y-cree",
+ ["yic" ]="yi classic",
+ ["yim" ]="yi modern",
+ ["zea" ]="zealandic",
+ ["zgh" ]="standard morrocan tamazigh",
+ ["zha" ]="zhuang",
+ ["zhh" ]="chinese, hong kong sar",
+ ["zhp" ]="chinese phonetic",
+ ["zhs" ]="chinese simplified",
+ ["zht" ]="chinese traditional",
+ ["znd" ]="zande",
+ ["zul" ]="zulu",
+ ["zza" ]="zazaki",
+}
+local features=allocate {
+ ["aalt"]="access all alternates",
+ ["abvf"]="above-base forms",
+ ["abvm"]="above-base mark positioning",
+ ["abvs"]="above-base substitutions",
+ ["afrc"]="alternative fractions",
+ ["akhn"]="akhands",
+ ["blwf"]="below-base forms",
+ ["blwm"]="below-base mark positioning",
+ ["blws"]="below-base substitutions",
+ ["c2pc"]="petite capitals from capitals",
+ ["c2sc"]="small capitals from capitals",
+ ["calt"]="contextual alternates",
+ ["case"]="case-sensitive forms",
+ ["ccmp"]="glyph composition/decomposition",
+ ["cfar"]="conjunct form after ro",
+ ["cjct"]="conjunct forms",
+ ["clig"]="contextual ligatures",
+ ["cpct"]="centered cjk punctuation",
+ ["cpsp"]="capital spacing",
+ ["cswh"]="contextual swash",
+ ["curs"]="cursive positioning",
+ ["dflt"]="default processing",
+ ["dist"]="distances",
+ ["dlig"]="discretionary ligatures",
+ ["dnom"]="denominators",
+ ["dtls"]="dotless forms",
+ ["expt"]="expert forms",
+ ["falt"]="final glyph alternates",
+ ["fin2"]="terminal forms #2",
+ ["fin3"]="terminal forms #3",
+ ["fina"]="terminal forms",
+ ["flac"]="flattened accents over capitals",
+ ["frac"]="fractions",
+ ["fwid"]="full width",
+ ["half"]="half forms",
+ ["haln"]="halant forms",
+ ["halt"]="alternate half width",
+ ["hist"]="historical forms",
+ ["hkna"]="horizontal kana alternates",
+ ["hlig"]="historical ligatures",
+ ["hngl"]="hangul",
+ ["hojo"]="hojo kanji forms",
+ ["hwid"]="half width",
+ ["init"]="initial forms",
+ ["isol"]="isolated forms",
+ ["ital"]="italics",
+ ["jalt"]="justification alternatives",
+ ["jp04"]="jis2004 forms",
+ ["jp78"]="jis78 forms",
+ ["jp83"]="jis83 forms",
+ ["jp90"]="jis90 forms",
+ ["kern"]="kerning",
+ ["lfbd"]="left bounds",
+ ["liga"]="standard ligatures",
+ ["ljmo"]="leading jamo forms",
+ ["lnum"]="lining figures",
+ ["locl"]="localized forms",
+ ["ltra"]="left-to-right alternates",
+ ["ltrm"]="left-to-right mirrored forms",
+ ["mark"]="mark positioning",
+ ["med2"]="medial forms #2",
+ ["medi"]="medial forms",
+ ["mgrk"]="mathematical greek",
+ ["mkmk"]="mark to mark positioning",
+ ["mset"]="mark positioning via substitution",
+ ["nalt"]="alternate annotation forms",
+ ["nlck"]="nlc kanji forms",
+ ["nukt"]="nukta forms",
+ ["numr"]="numerators",
+ ["onum"]="old style figures",
+ ["opbd"]="optical bounds",
+ ["ordn"]="ordinals",
+ ["ornm"]="ornaments",
+ ["palt"]="proportional alternate width",
+ ["pcap"]="petite capitals",
+ ["pkna"]="proportional kana",
+ ["pnum"]="proportional figures",
+ ["pref"]="pre-base forms",
+ ["pres"]="pre-base substitutions",
+ ["pstf"]="post-base forms",
+ ["psts"]="post-base substitutions",
+ ["pwid"]="proportional widths",
+ ["qwid"]="quarter widths",
+ ["rand"]="randomize",
+ ["rclt"]="required contextual alternates",
+ ["rkrf"]="rakar forms",
+ ["rlig"]="required ligatures",
+ ["rphf"]="reph form",
+ ["rtbd"]="right bounds",
+ ["rtla"]="right-to-left alternates",
+ ["rtlm"]="right to left mirrored forms",
+ ["rvrn"]="required variation alternates",
+ ["ruby"]="ruby notation forms",
+ ["salt"]="stylistic alternates",
+ ["sinf"]="scientific inferiors",
+ ["size"]="optical size",
+ ["smcp"]="small capitals",
+ ["smpl"]="simplified forms",
+ ["ssty"]="script style",
+ ["stch"]="stretching glyph decomposition",
+ ["subs"]="subscript",
+ ["sups"]="superscript",
+ ["swsh"]="swash",
+ ["titl"]="titling",
+ ["tjmo"]="trailing jamo forms",
+ ["tnam"]="traditional name forms",
+ ["tnum"]="tabular figures",
+ ["trad"]="traditional forms",
+ ["twid"]="third widths",
+ ["unic"]="unicase",
+ ["valt"]="alternate vertical metrics",
+ ["vatu"]="vattu variants",
+ ["vert"]="vertical writing",
+ ["vhal"]="alternate vertical half metrics",
+ ["vjmo"]="vowel jamo forms",
+ ["vkna"]="vertical kana alternates",
+ ["vkrn"]="vertical kerning",
+ ["vpal"]="proportional alternate vertical metrics",
+ ["vrt2"]="vertical rotation",
+ ["zero"]="slashed zero",
+ ["trep"]="traditional tex replacements",
+ ["tlig"]="traditional tex ligatures",
+ ["ss.."]="stylistic set ..",
+ ["cv.."]="character variant ..",
+ ["js.."]="justification ..",
+ ["dv.."]="devanagari ..",
+ ["ml.."]="malayalam ..",
+}
+local baselines=allocate {
+ ["hang"]="hanging baseline",
+ ["icfb"]="ideographic character face bottom edge baseline",
+ ["icft"]="ideographic character face tope edige baseline",
+ ["ideo"]="ideographic em-box bottom edge baseline",
+ ["idtp"]="ideographic em-box top edge baseline",
+ ["math"]="mathematical centered baseline",
+ ["romn"]="roman baseline"
+}
+tables.scripts=scripts
+tables.languages=languages
+tables.features=features
+tables.baselines=baselines
+local acceptscripts=true directives.register("otf.acceptscripts",function(v) acceptscripts=v end)
+local acceptlanguages=true directives.register("otf.acceptlanguages",function(v) acceptlanguages=v end)
+local report_checks=logs.reporter("fonts","checks")
+if otffeatures.features then
+ for k,v in next,otffeatures.features do
+ features[k]=v
+ end
+ otffeatures.features=features
+end
+local function swapped(h)
+ local r={}
+ for k,v in next,h do
+ r[gsub(v,"[^a-z0-9]","")]=k
+ end
+ return r
+end
+local verbosescripts=allocate(swapped(scripts ))
+local verboselanguages=allocate(swapped(languages))
+local verbosefeatures=allocate(swapped(features ))
+local verbosebaselines=allocate(swapped(baselines))
+local function resolve(t,k)
+ if k then
+ k=gsub(lower(k),"[^a-z0-9]","")
+ local v=rawget(t,k)
+ if v then
+ return v
+ end
+ end
+end
+setmetatableindex(verbosescripts,resolve)
+setmetatableindex(verboselanguages,resolve)
+setmetatableindex(verbosefeatures,resolve)
+setmetatableindex(verbosebaselines,resolve)
+setmetatableindex(scripts,function(t,k)
+ if k then
+ k=lower(k)
+ if k=="dflt" then
+ return k
+ end
+ local v=rawget(t,k)
+ if v then
+ return v
+ end
+ k=gsub(k," ","")
+ v=rawget(t,v)
+ if v then
+ return v
+ elseif acceptscripts then
+ report_checks("registering extra script %a",k)
+ rawset(t,k,k)
+ return k
+ end
+ end
+ return "dflt"
+end)
+setmetatableindex(languages,function(t,k)
+ if k then
+ k=lower(k)
+ if k=="dflt" then
+ return k
+ end
+ local v=rawget(t,k)
+ if v then
+ return v
+ end
+ k=gsub(k," ","")
+ v=rawget(t,v)
+ if v then
+ return v
+ elseif acceptlanguages then
+ report_checks("registering extra language %a",k)
+ rawset(t,k,k)
+ return k
+ end
+ end
+ return "dflt"
+end)
+if setmetatablenewindex then
+ setmetatablenewindex(languages,"ignore")
+ setmetatablenewindex(scripts,"ignore")
+ setmetatablenewindex(baselines,"ignore")
+end
+local function resolve(t,k)
+ if k then
+ k=lower(k)
+ local v=rawget(t,k)
+ if v then
+ return v
+ end
+ k=gsub(k," ","")
+ local v=rawget(t,k)
+ if v then
+ return v
+ end
+ local tag,dd=match(k,"(..)(%d+)")
+ if tag and dd then
+ local v=rawget(t,tag)
+ if v then
+ return v
+ else
+ local v=rawget(t,tag.."..")
+ if v then
+ return (gsub(v,"%.%.",tonumber(dd)))
+ end
+ end
+ end
+ end
+ return k
+end
+setmetatableindex(features,resolve)
+local function assign(t,k,v)
+ if k and v then
+ v=lower(v)
+ rawset(t,k,v)
+ end
+end
+if setmetatablenewindex then
+ setmetatablenewindex(features,assign)
+end
+local checkers={
+ rand=function(v)
+ return v==true and "random" or v
+ end
+}
+if not storage then
+ return
+end
+local usedfeatures=statistics.usedfeatures or {}
+statistics.usedfeatures=usedfeatures
+table.setmetatableindex(usedfeatures,function(t,k) if k then local v={} t[k]=v return v end end)
+storage.register("fonts/otf/usedfeatures",usedfeatures,"fonts.handlers.otf.statistics.usedfeatures" )
+local normalizedaxis=otf.readers.helpers.normalizedaxis or function(s) return s end
+function otffeatures.normalize(features)
+ if features then
+ local h={}
+ for key,value in next,features do
+ local k=lower(key)
+ if k=="language" then
+ local v=gsub(lower(value),"[^a-z0-9]","")
+ h.language=rawget(verboselanguages,v) or (languages[v] and v) or "dflt"
+ elseif k=="script" then
+ local v=gsub(lower(value),"[^a-z0-9]","")
+ h.script=rawget(verbosescripts,v) or (scripts[v] and v) or "dflt"
+ elseif k=="axis" then
+ h[k]=normalizedaxis(value)
+ if not callbacks.supported.glyph_stream_provider then
+ h.variableshapes=true
+ end
+ else
+ local uk=usedfeatures[key]
+ local uv=uk[value]
+ if uv then
+ else
+ uv=tonumber(value)
+ if uv then
+ elseif type(value)=="string" then
+ local b=is_boolean(value)
+ if type(b)=="nil" then
+ uv=lower(value)
+ else
+ uv=b
+ end
+ elseif type(value)=="table" then
+ uv=sequenced(t,",")
+ else
+ uv=value
+ end
+ if not rawget(features,k) then
+ k=rawget(verbosefeatures,k) or k
+ end
+ local c=checkers[k]
+ if c then
+ uv=c(uv) or vc
+ end
+ uk[value]=uv
+ end
+ h[k]=uv
+ end
+ end
+ return h
+ end
+end
+
+end --- [luaotfload, fontloader-2018-09-24.lua scope for “font-ott”] ---
+
+
+do --- [luaotfload, fontloader-2018-09-24.lua scope for “font-cff” eefa156275ba0ac91aa651a944d35978] ---
+
+if not modules then modules={} end modules ['font-cff']={
+ version=1.001,
+ comment="companion to font-ini.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
+}
+local next,type,tonumber=next,type,tonumber
+local byte,char,gmatch=string.byte,string.char,string.gmatch
+local concat,remove=table.concat,table.remove
+local floor,abs,round,ceil,min,max=math.floor,math.abs,math.round,math.ceil,math.min,math.max
+local P,C,R,S,C,Cs,Ct=lpeg.P,lpeg.C,lpeg.R,lpeg.S,lpeg.C,lpeg.Cs,lpeg.Ct
+local lpegmatch=lpeg.match
+local formatters=string.formatters
+local bytetable=string.bytetable
+local readers=fonts.handlers.otf.readers
+local streamreader=readers.streamreader
+local readstring=streamreader.readstring
+local readbyte=streamreader.readcardinal1
+local readushort=streamreader.readcardinal2
+local readuint=streamreader.readcardinal3
+local readulong=streamreader.readcardinal4
+local setposition=streamreader.setposition
+local getposition=streamreader.getposition
+local readbytetable=streamreader.readbytetable
+directives.register("fonts.streamreader",function()
+ streamreader=utilities.streams
+ readstring=streamreader.readstring
+ readbyte=streamreader.readcardinal1
+ readushort=streamreader.readcardinal2
+ readuint=streamreader.readcardinal3
+ readulong=streamreader.readcardinal4
+ setposition=streamreader.setposition
+ getposition=streamreader.getposition
+ readbytetable=streamreader.readbytetable
+end)
+local setmetatableindex=table.setmetatableindex
+local trace_charstrings=false trackers.register("fonts.cff.charstrings",function(v) trace_charstrings=v end)
+local report=logs.reporter("otf reader","cff")
+local parsedictionaries
+local parsecharstring
+local parsecharstrings
+local resetcharstrings
+local parseprivates
+local startparsing
+local stopparsing
+local defaultstrings={ [0]=
+ ".notdef","space","exclam","quotedbl","numbersign","dollar","percent",
+ "ampersand","quoteright","parenleft","parenright","asterisk","plus",
+ "comma","hyphen","period","slash","zero","one","two","three","four",
+ "five","six","seven","eight","nine","colon","semicolon","less",
+ "equal","greater","question","at","A","B","C","D","E","F","G","H",
+ "I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W",
+ "X","Y","Z","bracketleft","backslash","bracketright","asciicircum",
+ "underscore","quoteleft","a","b","c","d","e","f","g","h","i","j",
+ "k","l","m","n","o","p","q","r","s","t","u","v","w","x","y",
+ "z","braceleft","bar","braceright","asciitilde","exclamdown","cent",
+ "sterling","fraction","yen","florin","section","currency",
+ "quotesingle","quotedblleft","guillemotleft","guilsinglleft",
+ "guilsinglright","fi","fl","endash","dagger","daggerdbl",
+ "periodcentered","paragraph","bullet","quotesinglbase","quotedblbase",
+ "quotedblright","guillemotright","ellipsis","perthousand","questiondown",
+ "grave","acute","circumflex","tilde","macron","breve","dotaccent",
+ "dieresis","ring","cedilla","hungarumlaut","ogonek","caron","emdash",
+ "AE","ordfeminine","Lslash","Oslash","OE","ordmasculine","ae",
+ "dotlessi","lslash","oslash","oe","germandbls","onesuperior",
+ "logicalnot","mu","trademark","Eth","onehalf","plusminus","Thorn",
+ "onequarter","divide","brokenbar","degree","thorn","threequarters",
+ "twosuperior","registered","minus","eth","multiply","threesuperior",
+ "copyright","Aacute","Acircumflex","Adieresis","Agrave","Aring",
+ "Atilde","Ccedilla","Eacute","Ecircumflex","Edieresis","Egrave",
+ "Iacute","Icircumflex","Idieresis","Igrave","Ntilde","Oacute",
+ "Ocircumflex","Odieresis","Ograve","Otilde","Scaron","Uacute",
+ "Ucircumflex","Udieresis","Ugrave","Yacute","Ydieresis","Zcaron",
+ "aacute","acircumflex","adieresis","agrave","aring","atilde",
+ "ccedilla","eacute","ecircumflex","edieresis","egrave","iacute",
+ "icircumflex","idieresis","igrave","ntilde","oacute","ocircumflex",
+ "odieresis","ograve","otilde","scaron","uacute","ucircumflex",
+ "udieresis","ugrave","yacute","ydieresis","zcaron","exclamsmall",
+ "Hungarumlautsmall","dollaroldstyle","dollarsuperior","ampersandsmall",
+ "Acutesmall","parenleftsuperior","parenrightsuperior","twodotenleader",
+ "onedotenleader","zerooldstyle","oneoldstyle","twooldstyle",
+ "threeoldstyle","fouroldstyle","fiveoldstyle","sixoldstyle",
+ "sevenoldstyle","eightoldstyle","nineoldstyle","commasuperior",
+ "threequartersemdash","periodsuperior","questionsmall","asuperior",
+ "bsuperior","centsuperior","dsuperior","esuperior","isuperior",
+ "lsuperior","msuperior","nsuperior","osuperior","rsuperior","ssuperior",
+ "tsuperior","ff","ffi","ffl","parenleftinferior","parenrightinferior",
+ "Circumflexsmall","hyphensuperior","Gravesmall","Asmall","Bsmall",
+ "Csmall","Dsmall","Esmall","Fsmall","Gsmall","Hsmall","Ismall",
+ "Jsmall","Ksmall","Lsmall","Msmall","Nsmall","Osmall","Psmall",
+ "Qsmall","Rsmall","Ssmall","Tsmall","Usmall","Vsmall","Wsmall",
+ "Xsmall","Ysmall","Zsmall","colonmonetary","onefitted","rupiah",
+ "Tildesmall","exclamdownsmall","centoldstyle","Lslashsmall",
+ "Scaronsmall","Zcaronsmall","Dieresissmall","Brevesmall","Caronsmall",
+ "Dotaccentsmall","Macronsmall","figuredash","hypheninferior",
+ "Ogoneksmall","Ringsmall","Cedillasmall","questiondownsmall","oneeighth",
+ "threeeighths","fiveeighths","seveneighths","onethird","twothirds",
+ "zerosuperior","foursuperior","fivesuperior","sixsuperior",
+ "sevensuperior","eightsuperior","ninesuperior","zeroinferior",
+ "oneinferior","twoinferior","threeinferior","fourinferior",
+ "fiveinferior","sixinferior","seveninferior","eightinferior",
+ "nineinferior","centinferior","dollarinferior","periodinferior",
+ "commainferior","Agravesmall","Aacutesmall","Acircumflexsmall",
+ "Atildesmall","Adieresissmall","Aringsmall","AEsmall","Ccedillasmall",
+ "Egravesmall","Eacutesmall","Ecircumflexsmall","Edieresissmall",
+ "Igravesmall","Iacutesmall","Icircumflexsmall","Idieresissmall",
+ "Ethsmall","Ntildesmall","Ogravesmall","Oacutesmall","Ocircumflexsmall",
+ "Otildesmall","Odieresissmall","OEsmall","Oslashsmall","Ugravesmall",
+ "Uacutesmall","Ucircumflexsmall","Udieresissmall","Yacutesmall",
+ "Thornsmall","Ydieresissmall","001.000","001.001","001.002","001.003",
+ "Black","Bold","Book","Light","Medium","Regular","Roman","Semibold",
+}
+local cffreaders={
+ readbyte,
+ readushort,
+ readuint,
+ readulong,
+}
+local function readheader(f)
+ local offset=getposition(f)
+ local major=readbyte(f)
+ local header={
+ offset=offset,
+ major=major,
+ minor=readbyte(f),
+ size=readbyte(f),
+ }
+ if major==1 then
+ header.dsize=readbyte(f)
+ elseif major==2 then
+ header.dsize=readushort(f)
+ else
+ end
+ setposition(f,offset+header.size)
+ return header
+end
+local function readlengths(f,longcount)
+ local count=longcount and readulong(f) or readushort(f)
+ if count==0 then
+ return {}
+ end
+ local osize=readbyte(f)
+ local read=cffreaders[osize]
+ if not read then
+ report("bad offset size: %i",osize)
+ return {}
+ end
+ local lengths={}
+ local previous=read(f)
+ for i=1,count do
+ local offset=read(f)
+ local length=offset-previous
+ if length<0 then
+ report("bad offset: %i",length)
+ length=0
+ end
+ lengths[i]=length
+ previous=offset
+ end
+ return lengths
+end
+local function readfontnames(f)
+ local names=readlengths(f)
+ for i=1,#names do
+ names[i]=readstring(f,names[i])
+ end
+ return names
+end
+local function readtopdictionaries(f)
+ local dictionaries=readlengths(f)
+ for i=1,#dictionaries do
+ dictionaries[i]=readstring(f,dictionaries[i])
+ end
+ return dictionaries
+end
+local function readstrings(f)
+ local lengths=readlengths(f)
+ local strings=setmetatableindex({},defaultstrings)
+ local index=#defaultstrings
+ for i=1,#lengths do
+ index=index+1
+ strings[index]=readstring(f,lengths[i])
+ end
+ return strings
+end
+do
+ local stack={}
+ local top=0
+ local result={}
+ local strings={}
+ local p_single=P("\00")/function()
+ result.version=strings[stack[top]] or "unset"
+ top=0
+ end+P("\01")/function()
+ result.notice=strings[stack[top]] or "unset"
+ top=0
+ end+P("\02")/function()
+ result.fullname=strings[stack[top]] or "unset"
+ top=0
+ end+P("\03")/function()
+ result.familyname=strings[stack[top]] or "unset"
+ top=0
+ end+P("\04")/function()
+ result.weight=strings[stack[top]] or "unset"
+ top=0
+ end+P("\05")/function()
+ result.fontbbox={ unpack(stack,1,4) }
+ top=0
+ end
++P("\13")/function()
+ result.uniqueid=stack[top]
+ top=0
+ end+P("\14")/function()
+ result.xuid=concat(stack,"",1,top)
+ top=0
+ end+P("\15")/function()
+ result.charset=stack[top]
+ top=0
+ end+P("\16")/function()
+ result.encoding=stack[top]
+ top=0
+ end+P("\17")/function()
+ result.charstrings=stack[top]
+ top=0
+ end+P("\18")/function()
+ result.private={
+ size=stack[top-1],
+ offset=stack[top],
+ }
+ top=0
+ end+P("\19")/function()
+ result.subroutines=stack[top]
+ top=0
+ end+P("\20")/function()
+ result.defaultwidthx=stack[top]
+ top=0
+ end+P("\21")/function()
+ result.nominalwidthx=stack[top]
+ top=0
+ end
++P("\24")/function()
+ result.vstore=stack[top]
+ top=0
+ end+P("\25")/function()
+ result.maxstack=stack[top]
+ top=0
+ end
+ local p_double=P("\12")*(
+ P("\00")/function()
+ result.copyright=stack[top]
+ top=0
+ end+P("\01")/function()
+ result.monospaced=stack[top]==1 and true or false
+ top=0
+ end+P("\02")/function()
+ result.italicangle=stack[top]
+ top=0
+ end+P("\03")/function()
+ result.underlineposition=stack[top]
+ top=0
+ end+P("\04")/function()
+ result.underlinethickness=stack[top]
+ top=0
+ end+P("\05")/function()
+ result.painttype=stack[top]
+ top=0
+ end+P("\06")/function()
+ result.charstringtype=stack[top]
+ top=0
+ end+P("\07")/function()
+ result.fontmatrix={ unpack(stack,1,6) }
+ top=0
+ end+P("\08")/function()
+ result.strokewidth=stack[top]
+ top=0
+ end+P("\20")/function()
+ result.syntheticbase=stack[top]
+ top=0
+ end+P("\21")/function()
+ result.postscript=strings[stack[top]] or "unset"
+ top=0
+ end+P("\22")/function()
+ result.basefontname=strings[stack[top]] or "unset"
+ top=0
+ end+P("\21")/function()
+ result.basefontblend=stack[top]
+ top=0
+ end+P("\30")/function()
+ result.cid.registry=strings[stack[top-2]] or "unset"
+ result.cid.ordering=strings[stack[top-1]] or "unset"
+ result.cid.supplement=stack[top]
+ top=0
+ end+P("\31")/function()
+ result.cid.fontversion=stack[top]
+ top=0
+ end+P("\32")/function()
+ result.cid.fontrevision=stack[top]
+ top=0
+ end+P("\33")/function()
+ result.cid.fonttype=stack[top]
+ top=0
+ end+P("\34")/function()
+ result.cid.count=stack[top]
+ top=0
+ end+P("\35")/function()
+ result.cid.uidbase=stack[top]
+ top=0
+ end+P("\36")/function()
+ result.cid.fdarray=stack[top]
+ top=0
+ end+P("\37")/function()
+ result.cid.fdselect=stack[top]
+ top=0
+ end+P("\38")/function()
+ result.cid.fontname=strings[stack[top]] or "unset"
+ top=0
+ end
+ )
+ local p_last=P("\x0F")/"0"+P("\x1F")/"1"+P("\x2F")/"2"+P("\x3F")/"3"+P("\x4F")/"4"+P("\x5F")/"5"+P("\x6F")/"6"+P("\x7F")/"7"+P("\x8F")/"8"+P("\x9F")/"9"+P("\xAF")/""+P("\xBF")/""+P("\xCF")/""+P("\xDF")/""+P("\xEF")/""+R("\xF0\xFF")/""
+ local remap={
+ ["\x00"]="00",["\x01"]="01",["\x02"]="02",["\x03"]="03",["\x04"]="04",["\x05"]="05",["\x06"]="06",["\x07"]="07",["\x08"]="08",["\x09"]="09",["\x0A"]="0.",["\x0B"]="0E",["\x0C"]="0E-",["\x0D"]="0",["\x0E"]="0-",["\x0F"]="0",
+ ["\x10"]="10",["\x11"]="11",["\x12"]="12",["\x13"]="13",["\x14"]="14",["\x15"]="15",["\x16"]="16",["\x17"]="17",["\x18"]="18",["\x19"]="19",["\x1A"]="0.",["\x1B"]="0E",["\x1C"]="0E-",["\x1D"]="0",["\x1E"]="0-",["\x1F"]="0",
+ ["\x20"]="20",["\x21"]="21",["\x22"]="22",["\x23"]="23",["\x24"]="24",["\x25"]="25",["\x26"]="26",["\x27"]="27",["\x28"]="28",["\x29"]="29",["\x2A"]="0.",["\x2B"]="0E",["\x2C"]="0E-",["\x2D"]="0",["\x2E"]="0-",["\x2F"]="0",
+ ["\x30"]="30",["\x31"]="31",["\x32"]="32",["\x33"]="33",["\x34"]="34",["\x35"]="35",["\x36"]="36",["\x37"]="37",["\x38"]="38",["\x39"]="39",["\x3A"]="0.",["\x3B"]="0E",["\x3C"]="0E-",["\x3D"]="0",["\x3E"]="0-",["\x3F"]="0",
+ ["\x40"]="40",["\x41"]="41",["\x42"]="42",["\x43"]="43",["\x44"]="44",["\x45"]="45",["\x46"]="46",["\x47"]="47",["\x48"]="48",["\x49"]="49",["\x4A"]="0.",["\x4B"]="0E",["\x4C"]="0E-",["\x4D"]="0",["\x4E"]="0-",["\x4F"]="0",
+ ["\x50"]="50",["\x51"]="51",["\x52"]="52",["\x53"]="53",["\x54"]="54",["\x55"]="55",["\x56"]="56",["\x57"]="57",["\x58"]="58",["\x59"]="59",["\x5A"]="0.",["\x5B"]="0E",["\x5C"]="0E-",["\x5D"]="0",["\x5E"]="0-",["\x5F"]="0",
+ ["\x60"]="60",["\x61"]="61",["\x62"]="62",["\x63"]="63",["\x64"]="64",["\x65"]="65",["\x66"]="66",["\x67"]="67",["\x68"]="68",["\x69"]="69",["\x6A"]="0.",["\x6B"]="0E",["\x6C"]="0E-",["\x6D"]="0",["\x6E"]="0-",["\x6F"]="0",
+ ["\x70"]="70",["\x71"]="71",["\x72"]="72",["\x73"]="73",["\x74"]="74",["\x75"]="75",["\x76"]="76",["\x77"]="77",["\x78"]="78",["\x79"]="79",["\x7A"]="0.",["\x7B"]="0E",["\x7C"]="0E-",["\x7D"]="0",["\x7E"]="0-",["\x7F"]="0",
+ ["\x80"]="80",["\x81"]="81",["\x82"]="82",["\x83"]="83",["\x84"]="84",["\x85"]="85",["\x86"]="86",["\x87"]="87",["\x88"]="88",["\x89"]="89",["\x8A"]="0.",["\x8B"]="0E",["\x8C"]="0E-",["\x8D"]="0",["\x8E"]="0-",["\x8F"]="0",
+ ["\x90"]="90",["\x91"]="91",["\x92"]="92",["\x93"]="93",["\x94"]="94",["\x95"]="95",["\x96"]="96",["\x97"]="97",["\x98"]="98",["\x99"]="99",["\x9A"]="0.",["\x9B"]="0E",["\x9C"]="0E-",["\x9D"]="0",["\x9E"]="0-",["\x9F"]="0",
+ ["\xA0"]=".0",["\xA1"]=".1",["\xA2"]=".2",["\xA3"]=".3",["\xA4"]=".4",["\xA5"]=".5",["\xA6"]=".6",["\xA7"]=".7",["\xA8"]=".8",["\xA9"]=".9",["\xAA"]="..",["\xAB"]=".E",["\xAC"]=".E-",["\xAD"]=".",["\xAE"]=".-",["\xAF"]=".",
+ ["\xB0"]="E0",["\xB1"]="E1",["\xB2"]="E2",["\xB3"]="E3",["\xB4"]="E4",["\xB5"]="E5",["\xB6"]="E6",["\xB7"]="E7",["\xB8"]="E8",["\xB9"]="E9",["\xBA"]="E.",["\xBB"]="EE",["\xBC"]="EE-",["\xBD"]="E",["\xBE"]="E-",["\xBF"]="E",
+ ["\xC0"]="E-0",["\xC1"]="E-1",["\xC2"]="E-2",["\xC3"]="E-3",["\xC4"]="E-4",["\xC5"]="E-5",["\xC6"]="E-6",["\xC7"]="E-7",["\xC8"]="E-8",["\xC9"]="E-9",["\xCA"]="E-.",["\xCB"]="E-E",["\xCC"]="E-E-",["\xCD"]="E-",["\xCE"]="E--",["\xCF"]="E-",
+ ["\xD0"]="-0",["\xD1"]="-1",["\xD2"]="-2",["\xD3"]="-3",["\xD4"]="-4",["\xD5"]="-5",["\xD6"]="-6",["\xD7"]="-7",["\xD8"]="-8",["\xD9"]="-9",["\xDA"]="-.",["\xDB"]="-E",["\xDC"]="-E-",["\xDD"]="-",["\xDE"]="--",["\xDF"]="-",
+ }
+ local p_nibbles=P("\30")*Cs(((1-p_last)/remap)^0+p_last)/function(n)
+ top=top+1
+ stack[top]=tonumber(n) or 0
+ end
+ local p_byte=C(R("\32\246"))/function(b0)
+ top=top+1
+ stack[top]=byte(b0)-139
+ end
+ local p_positive=C(R("\247\250"))*C(1)/function(b0,b1)
+ top=top+1
+ stack[top]=(byte(b0)-247)*256+byte(b1)+108
+ end
+ local p_negative=C(R("\251\254"))*C(1)/function(b0,b1)
+ top=top+1
+ stack[top]=-(byte(b0)-251)*256-byte(b1)-108
+ end
+ local p_short=P("\28")*C(1)*C(1)/function(b1,b2)
+ top=top+1
+ local n=0x100*byte(b1)+byte(b2)
+ if n>=0x8000 then
+ stack[top]=n-0xFFFF-1
+ else
+ stack[top]=n
+ end
+ end
+ local p_long=P("\29")*C(1)*C(1)*C(1)*C(1)/function(b1,b2,b3,b4)
+ top=top+1
+ local n=0x1000000*byte(b1)+0x10000*byte(b2)+0x100*byte(b3)+byte(b4)
+ if n>=0x8000000 then
+ stack[top]=n-0xFFFFFFFF-1
+ else
+ stack[top]=n
+ end
+ end
+ local p_unsupported=P(1)/function(detail)
+ top=0
+ end
+ local p_dictionary=(
+ p_byte+p_positive+p_negative+p_short+p_long+p_nibbles+p_single+p_double+p_unsupported
+ )^1
+ parsedictionaries=function(data,dictionaries,what)
+ stack={}
+ strings=data.strings
+ for i=1,#dictionaries do
+ top=0
+ result=what=="cff" and {
+ monospaced=false,
+ italicangle=0,
+ underlineposition=-100,
+ underlinethickness=50,
+ painttype=0,
+ charstringtype=2,
+ fontmatrix={ 0.001,0,0,0.001,0,0 },
+ fontbbox={ 0,0,0,0 },
+ strokewidth=0,
+ charset=0,
+ encoding=0,
+ cid={
+ fontversion=0,
+ fontrevision=0,
+ fonttype=0,
+ count=8720,
+ }
+ } or {
+ charstringtype=2,
+ charset=0,
+ vstore=0,
+ cid={
+ },
+ }
+ lpegmatch(p_dictionary,dictionaries[i])
+ dictionaries[i]=result
+ end
+ result={}
+ top=0
+ stack={}
+ end
+ parseprivates=function(data,dictionaries)
+ stack={}
+ strings=data.strings
+ for i=1,#dictionaries do
+ local private=dictionaries[i].private
+ if private and private.data then
+ top=0
+ result={
+ forcebold=false,
+ languagegroup=0,
+ expansionfactor=0.06,
+ initialrandomseed=0,
+ subroutines=0,
+ defaultwidthx=0,
+ nominalwidthx=0,
+ cid={
+ },
+ }
+ lpegmatch(p_dictionary,private.data)
+ private.data=result
+ end
+ end
+ result={}
+ top=0
+ stack={}
+ end
+ local x=0
+ local y=0
+ local width=false
+ local r=0
+ local stems=0
+ local globalbias=0
+ local localbias=0
+ local nominalwidth=0
+ local defaultwidth=0
+ local charset=false
+ local globals=false
+ local locals=false
+ local depth=1
+ local xmin=0
+ local xmax=0
+ local ymin=0
+ local ymax=0
+ local checked=false
+ local keepcurve=false
+ local version=2
+ local regions=false
+ local nofregions=0
+ local region=false
+ local factors=false
+ local axis=false
+ local vsindex=0
+ local function showstate(where)
+ report("%w%-10s : [%s] n=%i",depth*2,where,concat(stack," ",1,top),top)
+ end
+ local function showvalue(where,value,showstack)
+ if showstack then
+ report("%w%-10s : %s : [%s] n=%i",depth*2,where,tostring(value),concat(stack," ",1,top),top)
+ else
+ report("%w%-10s : %s",depth*2,where,tostring(value))
+ end
+ end
+ local function xymoveto()
+ if keepcurve then
+ r=r+1
+ result[r]={ x,y,"m" }
+ end
+ if checked then
+ if x>xmax then xmax=x elseif x<xmin then xmin=x end
+ if y>ymax then ymax=y elseif y<ymin then ymin=y end
+ else
+ xmin=x
+ ymin=y
+ xmax=x
+ ymax=y
+ checked=true
+ end
+ end
+ local function xmoveto()
+ if keepcurve then
+ r=r+1
+ result[r]={ x,y,"m" }
+ end
+ if not checked then
+ xmin=x
+ ymin=y
+ xmax=x
+ ymax=y
+ checked=true
+ elseif x>xmax then
+ xmax=x
+ elseif x<xmin then
+ xmin=x
+ end
+ end
+ local function ymoveto()
+ if keepcurve then
+ r=r+1
+ result[r]={ x,y,"m" }
+ end
+ if not checked then
+ xmin=x
+ ymin=y
+ xmax=x
+ ymax=y
+ checked=true
+ elseif y>ymax then
+ ymax=y
+ elseif y<ymin then
+ ymin=y
+ end
+ end
+ local function moveto()
+ if trace_charstrings then
+ showstate("moveto")
+ end
+ top=0
+ xymoveto()
+ end
+ local function xylineto()
+ if keepcurve then
+ r=r+1
+ result[r]={ x,y,"l" }
+ end
+ if checked then
+ if x>xmax then xmax=x elseif x<xmin then xmin=x end
+ if y>ymax then ymax=y elseif y<ymin then ymin=y end
+ else
+ xmin=x
+ ymin=y
+ xmax=x
+ ymax=y
+ checked=true
+ end
+ end
+ local function xlineto()
+ if keepcurve then
+ r=r+1
+ result[r]={ x,y,"l" }
+ end
+ if not checked then
+ xmin=x
+ ymin=y
+ xmax=x
+ ymax=y
+ checked=true
+ elseif x>xmax then
+ xmax=x
+ elseif x<xmin then
+ xmin=x
+ end
+ end
+ local function ylineto()
+ if keepcurve then
+ r=r+1
+ result[r]={ x,y,"l" }
+ end
+ if not checked then
+ xmin=x
+ ymin=y
+ xmax=x
+ ymax=y
+ checked=true
+ elseif y>ymax then
+ ymax=y
+ elseif y<ymin then
+ ymin=y
+ end
+ end
+ local function xycurveto(x1,y1,x2,y2,x3,y3)
+ if trace_charstrings then
+ showstate("curveto")
+ end
+ if keepcurve then
+ r=r+1
+ result[r]={ x1,y1,x2,y2,x3,y3,"c" }
+ end
+ if checked then
+ if x1>xmax then xmax=x1 elseif x1<xmin then xmin=x1 end
+ if y1>ymax then ymax=y1 elseif y1<ymin then ymin=y1 end
+ else
+ xmin=x1
+ ymin=y1
+ xmax=x1
+ ymax=y1
+ checked=true
+ end
+ if x2>xmax then xmax=x2 elseif x2<xmin then xmin=x2 end
+ if y2>ymax then ymax=y2 elseif y2<ymin then ymin=y2 end
+ if x3>xmax then xmax=x3 elseif x3<xmin then xmin=x3 end
+ if y3>ymax then ymax=y3 elseif y3<ymin then ymin=y3 end
+ end
+ local function rmoveto()
+ if not width then
+ if top>2 then
+ width=stack[1]
+ if trace_charstrings then
+ showvalue("backtrack width",width)
+ end
+ else
+ width=true
+ end
+ end
+ if trace_charstrings then
+ showstate("rmoveto")
+ end
+ x=x+stack[top-1]
+ y=y+stack[top]
+ top=0
+ xymoveto()
+ end
+ local function hmoveto()
+ if not width then
+ if top>1 then
+ width=stack[1]
+ if trace_charstrings then
+ showvalue("backtrack width",width)
+ end
+ else
+ width=true
+ end
+ end
+ if trace_charstrings then
+ showstate("hmoveto")
+ end
+ x=x+stack[top]
+ top=0
+ xmoveto()
+ end
+ local function vmoveto()
+ if not width then
+ if top>1 then
+ width=stack[1]
+ if trace_charstrings then
+ showvalue("backtrack width",width)
+ end
+ else
+ width=true
+ end
+ end
+ if trace_charstrings then
+ showstate("vmoveto")
+ end
+ y=y+stack[top]
+ top=0
+ ymoveto()
+ end
+ local function rlineto()
+ if trace_charstrings then
+ showstate("rlineto")
+ end
+ for i=1,top,2 do
+ x=x+stack[i]
+ y=y+stack[i+1]
+ xylineto()
+ end
+ top=0
+ end
+ local function hlineto()
+ if trace_charstrings then
+ showstate("hlineto")
+ end
+ if top==1 then
+ x=x+stack[1]
+ xlineto()
+ else
+ local swap=true
+ for i=1,top do
+ if swap then
+ x=x+stack[i]
+ xlineto()
+ swap=false
+ else
+ y=y+stack[i]
+ ylineto()
+ swap=true
+ end
+ end
+ end
+ top=0
+ end
+ local function vlineto()
+ if trace_charstrings then
+ showstate("vlineto")
+ end
+ if top==1 then
+ y=y+stack[1]
+ ylineto()
+ else
+ local swap=false
+ for i=1,top do
+ if swap then
+ x=x+stack[i]
+ xlineto()
+ swap=false
+ else
+ y=y+stack[i]
+ ylineto()
+ swap=true
+ end
+ end
+ end
+ top=0
+ end
+ local function rrcurveto()
+ if trace_charstrings then
+ showstate("rrcurveto")
+ end
+ for i=1,top,6 do
+ local ax=x+stack[i]
+ local ay=y+stack[i+1]
+ local bx=ax+stack[i+2]
+ local by=ay+stack[i+3]
+ x=bx+stack[i+4]
+ y=by+stack[i+5]
+ xycurveto(ax,ay,bx,by,x,y)
+ end
+ top=0
+ end
+ local function hhcurveto()
+ if trace_charstrings then
+ showstate("hhcurveto")
+ end
+ local s=1
+ if top%2~=0 then
+ y=y+stack[1]
+ s=2
+ end
+ for i=s,top,4 do
+ local ax=x+stack[i]
+ local ay=y
+ local bx=ax+stack[i+1]
+ local by=ay+stack[i+2]
+ x=bx+stack[i+3]
+ y=by
+ xycurveto(ax,ay,bx,by,x,y)
+ end
+ top=0
+ end
+ local function vvcurveto()
+ if trace_charstrings then
+ showstate("vvcurveto")
+ end
+ local s=1
+ local d=0
+ if top%2~=0 then
+ d=stack[1]
+ s=2
+ end
+ for i=s,top,4 do
+ local ax=x+d
+ local ay=y+stack[i]
+ local bx=ax+stack[i+1]
+ local by=ay+stack[i+2]
+ x=bx
+ y=by+stack[i+3]
+ xycurveto(ax,ay,bx,by,x,y)
+ d=0
+ end
+ top=0
+ end
+ local function xxcurveto(swap)
+ local last=top%4~=0 and stack[top]
+ if last then
+ top=top-1
+ end
+ for i=1,top,4 do
+ local ax,ay,bx,by
+ if swap then
+ ax=x+stack[i]
+ ay=y
+ bx=ax+stack[i+1]
+ by=ay+stack[i+2]
+ y=by+stack[i+3]
+ if last and i+3==top then
+ x=bx+last
+ else
+ x=bx
+ end
+ swap=false
+ else
+ ax=x
+ ay=y+stack[i]
+ bx=ax+stack[i+1]
+ by=ay+stack[i+2]
+ x=bx+stack[i+3]
+ if last and i+3==top then
+ y=by+last
+ else
+ y=by
+ end
+ swap=true
+ end
+ xycurveto(ax,ay,bx,by,x,y)
+ end
+ top=0
+ end
+ local function hvcurveto()
+ if trace_charstrings then
+ showstate("hvcurveto")
+ end
+ xxcurveto(true)
+ end
+ local function vhcurveto()
+ if trace_charstrings then
+ showstate("vhcurveto")
+ end
+ xxcurveto(false)
+ end
+ local function rcurveline()
+ if trace_charstrings then
+ showstate("rcurveline")
+ end
+ for i=1,top-2,6 do
+ local ax=x+stack[i]
+ local ay=y+stack[i+1]
+ local bx=ax+stack[i+2]
+ local by=ay+stack[i+3]
+ x=bx+stack[i+4]
+ y=by+stack[i+5]
+ xycurveto(ax,ay,bx,by,x,y)
+ end
+ x=x+stack[top-1]
+ y=y+stack[top]
+ xylineto()
+ top=0
+ end
+ local function rlinecurve()
+ if trace_charstrings then
+ showstate("rlinecurve")
+ end
+ if top>6 then
+ for i=1,top-6,2 do
+ x=x+stack[i]
+ y=y+stack[i+1]
+ xylineto()
+ end
+ end
+ local ax=x+stack[top-5]
+ local ay=y+stack[top-4]
+ local bx=ax+stack[top-3]
+ local by=ay+stack[top-2]
+ x=bx+stack[top-1]
+ y=by+stack[top]
+ xycurveto(ax,ay,bx,by,x,y)
+ top=0
+ end
+ local function flex()
+ if trace_charstrings then
+ showstate("flex")
+ end
+ local ax=x+stack[1]
+ local ay=y+stack[2]
+ local bx=ax+stack[3]
+ local by=ay+stack[4]
+ local cx=bx+stack[5]
+ local cy=by+stack[6]
+ xycurveto(ax,ay,bx,by,cx,cy)
+ local dx=cx+stack[7]
+ local dy=cy+stack[8]
+ local ex=dx+stack[9]
+ local ey=dy+stack[10]
+ x=ex+stack[11]
+ y=ey+stack[12]
+ xycurveto(dx,dy,ex,ey,x,y)
+ top=0
+ end
+ local function hflex()
+ if trace_charstrings then
+ showstate("hflex")
+ end
+ local ax=x+stack[1]
+ local ay=y
+ local bx=ax+stack[2]
+ local by=ay+stack[3]
+ local cx=bx+stack[4]
+ local cy=by
+ xycurveto(ax,ay,bx,by,cx,cy)
+ local dx=cx+stack[5]
+ local dy=by
+ local ex=dx+stack[6]
+ local ey=y
+ x=ex+stack[7]
+ xycurveto(dx,dy,ex,ey,x,y)
+ top=0
+ end
+ local function hflex1()
+ if trace_charstrings then
+ showstate("hflex1")
+ end
+ local ax=x+stack[1]
+ local ay=y+stack[2]
+ local bx=ax+stack[3]
+ local by=ay+stack[4]
+ local cx=bx+stack[5]
+ local cy=by
+ xycurveto(ax,ay,bx,by,cx,cy)
+ local dx=cx+stack[6]
+ local dy=by
+ local ex=dx+stack[7]
+ local ey=dy+stack[8]
+ x=ex+stack[9]
+ xycurveto(dx,dy,ex,ey,x,y)
+ top=0
+ end
+ local function flex1()
+ if trace_charstrings then
+ showstate("flex1")
+ end
+ local ax=x+stack[1]
+ local ay=y+stack[2]
+ local bx=ax+stack[3]
+ local by=ay+stack[4]
+ local cx=bx+stack[5]
+ local cy=by+stack[6]
+ xycurveto(ax,ay,bx,by,cx,cy)
+ local dx=cx+stack[7]
+ local dy=cy+stack[8]
+ local ex=dx+stack[9]
+ local ey=dy+stack[10]
+ if abs(ex-x)>abs(ey-y) then
+ x=ex+stack[11]
+ else
+ y=ey+stack[11]
+ end
+ xycurveto(dx,dy,ex,ey,x,y)
+ top=0
+ end
+ local function getstem()
+ if top==0 then
+ elseif top%2~=0 then
+ if width then
+ remove(stack,1)
+ else
+ width=remove(stack,1)
+ if trace_charstrings then
+ showvalue("width",width)
+ end
+ end
+ top=top-1
+ end
+ if trace_charstrings then
+ showstate("stem")
+ end
+ stems=stems+top/2
+ top=0
+ end
+ local function getmask()
+ if top==0 then
+ elseif top%2~=0 then
+ if width then
+ remove(stack,1)
+ else
+ width=remove(stack,1)
+ if trace_charstrings then
+ showvalue("width",width)
+ end
+ end
+ top=top-1
+ end
+ if trace_charstrings then
+ showstate(operator==19 and "hintmark" or "cntrmask")
+ end
+ stems=stems+top/2
+ top=0
+ if stems==0 then
+ elseif stems<=8 then
+ return 1
+ else
+ return floor((stems+7)/8)
+ end
+ end
+ local function unsupported(t)
+ if trace_charstrings then
+ showstate("unsupported "..t)
+ end
+ top=0
+ end
+ local function unsupportedsub(t)
+ if trace_charstrings then
+ showstate("unsupported sub "..t)
+ end
+ top=0
+ end
+ local function getstem3()
+ if trace_charstrings then
+ showstate("stem3")
+ end
+ top=0
+ end
+ local function divide()
+ if version==1 then
+ local d=stack[top]
+ top=top-1
+ stack[top]=stack[top]/d
+ end
+ end
+ local function closepath()
+ if version==1 then
+ if trace_charstrings then
+ showstate("closepath")
+ end
+ end
+ top=0
+ end
+ local function hsbw()
+ if version==1 then
+ if trace_charstrings then
+ showstate("dotsection")
+ end
+ width=stack[top]
+ end
+ top=0
+ end
+ local function seac()
+ if version==1 then
+ if trace_charstrings then
+ showstate("seac")
+ end
+ end
+ top=0
+ end
+ local function sbw()
+ if version==1 then
+ if trace_charstrings then
+ showstate("sbw")
+ end
+ width=stack[top-1]
+ end
+ top=0
+ end
+ local function callothersubr()
+ if version==1 then
+ if trace_charstrings then
+ showstate("callothersubr (unsupported)")
+ end
+ end
+ top=0
+ end
+ local function pop()
+ if version==1 then
+ if trace_charstrings then
+ showstate("pop (unsupported)")
+ end
+ top=top+1
+ stack[top]=0
+ else
+ top=0
+ end
+ end
+ local function setcurrentpoint()
+ if version==1 then
+ if trace_charstrings then
+ showstate("pop (unsupported)")
+ end
+ x=x+stack[top-1]
+ y=y+stack[top]
+ end
+ top=0
+ end
+ local reginit=false
+ local function updateregions(n)
+ if regions then
+ local current=regions[n] or regions[1]
+ nofregions=#current
+ if axis and n~=reginit then
+ factors={}
+ for i=1,nofregions do
+ local region=current[i]
+ local s=1
+ for j=1,#axis do
+ local f=axis[j]
+ local r=region[j]
+ local start=r.start
+ local peak=r.peak
+ local stop=r.stop
+ if start>peak or peak>stop then
+ elseif start<0 and stop>0 and peak~=0 then
+ elseif peak==0 then
+ elseif f<start or f>stop then
+ s=0
+ break
+ elseif f<peak then
+ s=s*(f-start)/(peak-start)
+ elseif f>peak then
+ s=s*(stop-f)/(stop-peak)
+ else
+ end
+ end
+ factors[i]=s
+ end
+ end
+ end
+ reginit=n
+ end
+ local function setvsindex()
+ local vsindex=stack[top]
+ if trace_charstrings then
+ showstate(formatters["vsindex %i"](vsindex))
+ end
+ updateregions(vsindex)
+ top=top-1
+ end
+ local function blend()
+ local n=stack[top]
+ top=top-1
+ if axis then
+ if trace_charstrings then
+ local t=top-nofregions*n
+ local m=t-n
+ for i=1,n do
+ local k=m+i
+ local d=m+n+(i-1)*nofregions
+ local old=stack[k]
+ local new=old
+ for r=1,nofregions do
+ new=new+stack[d+r]*factors[r]
+ end
+ stack[k]=new
+ showstate(formatters["blend %i of %i: %s -> %s"](i,n,old,new))
+ end
+ top=t
+ elseif n==1 then
+ top=top-nofregions
+ local v=stack[top]
+ for r=1,nofregions do
+ v=v+stack[top+r]*factors[r]
+ end
+ stack[top]=v
+ else
+ top=top-nofregions*n
+ local d=top
+ local k=top-n
+ for i=1,n do
+ k=k+1
+ local v=stack[k]
+ for r=1,nofregions do
+ v=v+stack[d+r]*factors[r]
+ end
+ stack[k]=v
+ d=d+nofregions
+ end
+ end
+ else
+ end
+ end
+ local actions={ [0]=unsupported,
+ getstem,
+ unsupported,
+ getstem,
+ vmoveto,
+ rlineto,
+ hlineto,
+ vlineto,
+ rrcurveto,
+ unsupported,
+ unsupported,
+ unsupported,
+ unsupported,
+ hsbw,
+ unsupported,
+ setvsindex,
+ blend,
+ unsupported,
+ getstem,
+ getmask,
+ getmask,
+ rmoveto,
+ hmoveto,
+ getstem,
+ rcurveline,
+ rlinecurve,
+ vvcurveto,
+ hhcurveto,
+ unsupported,
+ unsupported,
+ vhcurveto,
+ hvcurveto,
+ }
+ local subactions={
+ [000]=dotsection,
+ [001]=getstem3,
+ [002]=getstem3,
+ [006]=seac,
+ [007]=sbw,
+ [012]=divide,
+ [016]=callothersubr,
+ [017]=pop,
+ [033]=setcurrentpoint,
+ [034]=hflex,
+ [035]=flex,
+ [036]=hflex1,
+ [037]=flex1,
+ }
+ local c_endchar=char(14)
+ local passon do
+ local rshift=bit32.rshift
+ local band=bit32.band
+ local round=math.round
+ local encode=table.setmetatableindex(function(t,i)
+ for i=-2048,-1130 do
+ t[i]=char(28,band(rshift(i,8),0xFF),band(i,0xFF))
+ end
+ for i=-1131,-108 do
+ local v=0xFB00-i-108
+ t[i]=char(band(rshift(v,8),0xFF),band(v,0xFF))
+ end
+ for i=-107,107 do
+ t[i]=char(i+139)
+ end
+ for i=108,1131 do
+ local v=0xF700+i-108
+ t[i]=char(band(rshift(v,8),0xFF),band(v,0xFF))
+ end
+ for i=1132,2048 do
+ t[i]=char(28,band(rshift(i,8),0xFF),band(i,0xFF))
+ end
+ return t[i]
+ end)
+ local function setvsindex()
+ local vsindex=stack[top]
+ updateregions(vsindex)
+ top=top-1
+ end
+ local function blend()
+ local n=stack[top]
+ top=top-1
+ if not axis then
+ elseif n==1 then
+ top=top-nofregions
+ local v=stack[top]
+ for r=1,nofregions do
+ v=v+stack[top+r]*factors[r]
+ end
+ stack[top]=round(v)
+ else
+ top=top-nofregions*n
+ local d=top
+ local k=top-n
+ for i=1,n do
+ k=k+1
+ local v=stack[k]
+ for r=1,nofregions do
+ v=v+stack[d+r]*factors[r]
+ end
+ stack[k]=round(v)
+ d=d+nofregions
+ end
+ end
+ end
+ passon=function(operation)
+ if operation==15 then
+ setvsindex()
+ elseif operation==16 then
+ blend()
+ else
+ for i=1,top do
+ r=r+1
+ result[r]=encode[stack[i]]
+ end
+ r=r+1
+ result[r]=char(operation)
+ top=0
+ end
+ end
+ end
+ local process
+ local function call(scope,list,bias)
+ depth=depth+1
+ if top==0 then
+ showstate(formatters["unknown %s call"](scope))
+ top=0
+ else
+ local index=stack[top]+bias
+ top=top-1
+ if trace_charstrings then
+ showvalue(scope,index,true)
+ end
+ local tab=list[index]
+ if tab then
+ process(tab)
+ else
+ showstate(formatters["unknown %s call %i"](scope,index))
+ top=0
+ end
+ end
+ depth=depth-1
+ end
+ local justpass=false
+ process=function(tab)
+ local i=1
+ local n=#tab
+ while i<=n do
+ local t=tab[i]
+ if t>=32 then
+ top=top+1
+ if t<=246 then
+ stack[top]=t-139
+ i=i+1
+ elseif t<=250 then
+ stack[top]=t*256-63124+tab[i+1]
+ i=i+2
+ elseif t<=254 then
+ stack[top]=-t*256+64148-tab[i+1]
+ i=i+2
+ else
+ local n=0x100*tab[i+1]+tab[i+2]
+ if n>=0x8000 then
+ stack[top]=n-0x10000+(0x100*tab[i+3]+tab[i+4])/0xFFFF
+ else
+ stack[top]=n+(0x100*tab[i+3]+tab[i+4])/0xFFFF
+ end
+ i=i+5
+ end
+ elseif t==28 then
+ top=top+1
+ local n=0x100*tab[i+1]+tab[i+2]
+ if n>=0x8000 then
+ stack[top]=n-0x10000
+ else
+ stack[top]=n
+ end
+ i=i+3
+ elseif t==11 then
+ if trace_charstrings then
+ showstate("return")
+ end
+ return
+ elseif t==10 then
+ call("local",locals,localbias)
+ i=i+1
+ elseif t==14 then
+ if width then
+ elseif top>0 then
+ width=stack[1]
+ if trace_charstrings then
+ showvalue("width",width)
+ end
+ else
+ width=true
+ end
+ if trace_charstrings then
+ showstate("endchar")
+ end
+ return
+ elseif t==29 then
+ call("global",globals,globalbias)
+ i=i+1
+ elseif t==12 then
+ i=i+1
+ local t=tab[i]
+ local a=subactions[t]
+ if a then
+ a(t)
+ else
+ if trace_charstrings then
+ showvalue("<subaction>",t)
+ end
+ top=0
+ end
+ i=i+1
+ elseif justpass then
+ passon(t)
+ i=i+1
+ else
+ local a=actions[t]
+ if a then
+ local s=a(t)
+ if s then
+ i=i+s+1
+ else
+ i=i+1
+ end
+ else
+ if trace_charstrings then
+ showvalue("<action>",t)
+ end
+ top=0
+ i=i+1
+ end
+ end
+ end
+ end
+ local function setbias(globals,locals)
+ if version==1 then
+ return
+ false,
+ false
+ else
+ local g,l=#globals,#locals
+ return
+ ((g<1240 and 107) or (g<33900 and 1131) or 32768)+1,
+ ((l<1240 and 107) or (l<33900 and 1131) or 32768)+1
+ end
+ end
+ local function processshape(tab,index)
+ tab=bytetable(tab)
+ x=0
+ y=0
+ width=false
+ r=0
+ top=0
+ stems=0
+ result={}
+ xmin=0
+ xmax=0
+ ymin=0
+ ymax=0
+ checked=false
+ if trace_charstrings then
+ report("glyph: %i",index)
+ report("data : % t",tab)
+ end
+ if regions then
+ updateregions(vsindex)
+ end
+ process(tab)
+ local boundingbox={
+ round(xmin),
+ round(ymin),
+ round(xmax),
+ round(ymax),
+ }
+ if width==true or width==false then
+ width=defaultwidth
+ else
+ width=nominalwidth+width
+ end
+ local glyph=glyphs[index]
+ if justpass then
+ r=r+1
+ result[r]=c_endchar
+ local stream=concat(result)
+ if glyph then
+ glyph.stream=stream
+ else
+ glyphs[index]={ stream=stream }
+ end
+ elseif glyph then
+ glyph.segments=keepcurve~=false and result or nil
+ glyph.boundingbox=boundingbox
+ if not glyph.width then
+ glyph.width=width
+ end
+ if charset and not glyph.name then
+ glyph.name=charset[index]
+ end
+ elseif keepcurve then
+ glyphs[index]={
+ segments=result,
+ boundingbox=boundingbox,
+ width=width,
+ name=charset and charset[index] or nil,
+ }
+ else
+ glyphs[index]={
+ boundingbox=boundingbox,
+ width=width,
+ name=charset and charset[index] or nil,
+ }
+ end
+ if trace_charstrings then
+ report("width : %s",tostring(width))
+ report("boundingbox: % t",boundingbox)
+ end
+ end
+ startparsing=function(fontdata,data,streams)
+ reginit=false
+ axis=false
+ regions=data.regions
+ justpass=streams==true
+ if regions then
+ regions={ regions }
+ axis=data.factors or false
+ end
+ end
+ stopparsing=function(fontdata,data)
+ stack={}
+ glyphs=false
+ result={}
+ top=0
+ locals=false
+ globals=false
+ strings=false
+ end
+ local function setwidths(private)
+ if not private then
+ return 0,0
+ end
+ local privatedata=private.data
+ if not privatedata then
+ return 0,0
+ end
+ return privatedata.nominalwidthx or 0,privatedata.defaultwidthx or 0
+ end
+ parsecharstrings=function(fontdata,data,glphs,doshapes,tversion,streams)
+ local dictionary=data.dictionaries[1]
+ local charstrings=dictionary.charstrings
+ keepcurve=doshapes
+ version=tversion
+ strings=data.strings
+ globals=data.routines or {}
+ locals=dictionary.subroutines or {}
+ charset=dictionary.charset
+ vsindex=dictionary.vsindex or 0
+ glyphs=glphs or {}
+ globalbias,localbias=setbias(globals,locals)
+ nominalwidth,defaultwidth=setwidths(dictionary.private)
+ startparsing(fontdata,data,streams)
+ for index=1,#charstrings do
+ processshape(charstrings[index],index-1)
+ charstrings[index]=nil
+ end
+ stopparsing(fontdata,data)
+ return glyphs
+ end
+ parsecharstring=function(fontdata,data,dictionary,tab,glphs,index,doshapes,tversion)
+ keepcurve=doshapes
+ version=tversion
+ strings=data.strings
+ globals=data.routines or {}
+ locals=dictionary.subroutines or {}
+ charset=false
+ vsindex=dictionary.vsindex or 0
+ glyphs=glphs or {}
+ globalbias,localbias=setbias(globals,locals)
+ nominalwidth,defaultwidth=setwidths(dictionary.private)
+ processshape(tab,index-1)
+ end
+end
+local function readglobals(f,data)
+ local routines=readlengths(f)
+ for i=1,#routines do
+ routines[i]=readbytetable(f,routines[i])
+ end
+ data.routines=routines
+end
+local function readencodings(f,data)
+ data.encodings={}
+end
+local function readcharsets(f,data,dictionary)
+ local header=data.header
+ local strings=data.strings
+ local nofglyphs=data.nofglyphs
+ local charsetoffset=dictionary.charset
+ if charsetoffset and charsetoffset~=0 then
+ setposition(f,header.offset+charsetoffset)
+ local format=readbyte(f)
+ local charset={ [0]=".notdef" }
+ dictionary.charset=charset
+ if format==0 then
+ for i=1,nofglyphs do
+ charset[i]=strings[readushort(f)]
+ end
+ elseif format==1 or format==2 then
+ local readcount=format==1 and readbyte or readushort
+ local i=1
+ while i<=nofglyphs do
+ local sid=readushort(f)
+ local n=readcount(f)
+ for s=sid,sid+n do
+ charset[i]=strings[s]
+ i=i+1
+ if i>nofglyphs then
+ break
+ end
+ end
+ end
+ else
+ report("cff parser: unsupported charset format %a",format)
+ end
+ else
+ dictionary.nocharset=true
+ dictionary.charset=nil
+ end
+end
+local function readprivates(f,data)
+ local header=data.header
+ local dictionaries=data.dictionaries
+ local private=dictionaries[1].private
+ if private then
+ setposition(f,header.offset+private.offset)
+ private.data=readstring(f,private.size)
+ end
+end
+local function readlocals(f,data,dictionary)
+ local header=data.header
+ local private=dictionary.private
+ if private then
+ local subroutineoffset=private.data.subroutines
+ if subroutineoffset~=0 then
+ setposition(f,header.offset+private.offset+subroutineoffset)
+ local subroutines=readlengths(f)
+ for i=1,#subroutines do
+ subroutines[i]=readbytetable(f,subroutines[i])
+ end
+ dictionary.subroutines=subroutines
+ private.data.subroutines=nil
+ else
+ dictionary.subroutines={}
+ end
+ else
+ dictionary.subroutines={}
+ end
+end
+local function readcharstrings(f,data,what)
+ local header=data.header
+ local dictionaries=data.dictionaries
+ local dictionary=dictionaries[1]
+ local stringtype=dictionary.charstringtype
+ local offset=dictionary.charstrings
+ if type(offset)~="number" then
+ elseif stringtype==2 then
+ setposition(f,header.offset+offset)
+ local charstrings=readlengths(f,what=="cff2")
+ local nofglyphs=#charstrings
+ for i=1,nofglyphs do
+ charstrings[i]=readstring(f,charstrings[i])
+ end
+ data.nofglyphs=nofglyphs
+ dictionary.charstrings=charstrings
+ else
+ report("unsupported charstr type %i",stringtype)
+ data.nofglyphs=0
+ dictionary.charstrings={}
+ end
+end
+local function readcidprivates(f,data)
+ local header=data.header
+ local dictionaries=data.dictionaries[1].cid.dictionaries
+ for i=1,#dictionaries do
+ local dictionary=dictionaries[i]
+ local private=dictionary.private
+ if private then
+ setposition(f,header.offset+private.offset)
+ private.data=readstring(f,private.size)
+ end
+ end
+ parseprivates(data,dictionaries)
+end
+readers.parsecharstrings=parsecharstrings
+local function readnoselect(f,fontdata,data,glyphs,doshapes,version,streams)
@@ Diff output truncated at 1234567 characters. @@
More information about the tex-live-commits
mailing list